diff --git a/platform/avr-raven/cfs-coffee-arch.c b/platform/avr-raven/cfs-coffee-arch.c new file mode 100644 index 000000000..da5ecde8f --- /dev/null +++ b/platform/avr-raven/cfs-coffee-arch.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2009, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Coffee architecture-dependent functionality for the AVR-Raven 1284p platform. + * \author + * Nicolas Tsiftes + * Frederic Thepaut + * David Kopf + */ + +#include +#include +#include + +#include "cfs-coffee-arch.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTF(...) +#endif + +#define TESTCOFFEE 1 +#if TESTCOFFEE + +#include "cfs/cfs.h" +#include "cfs/cfs-coffee.h" +#include "lib/crc16.h" +#include "lib/random.h" +#include +#include + +#define FAIL(x) error = (x); goto end; + +#define FILE_SIZE 512 + +int +coffee_file_test(void) +{ + int error; + int wfd, rfd, afd; + unsigned char buf[256], buf2[11]; + int r, i, j, total_read; + unsigned offset; + + cfs_remove("T1"); + cfs_remove("T2"); + cfs_remove("T3"); + + wfd = rfd = afd = -1; + + for(r = 0; r < sizeof(buf); r++) { + buf[r] = r; + } + + /* Test 1: Open for writing. */ + wfd = cfs_open("T1", CFS_WRITE); + if(wfd < 0) { + FAIL(-1); + } + + /* Test 2: Write buffer. */ + r = cfs_write(wfd, buf, sizeof(buf)); + if(r < 0) { + FAIL(-2); + } else if(r < sizeof(buf)) { + FAIL(-3); + } + + /* Test 3: Deny reading. */ + r = cfs_read(wfd, buf, sizeof(buf)); + if(r >= 0) { + FAIL(-4); + } + + /* Test 4: Open for reading. */ + rfd = cfs_open("T1", CFS_READ); + if(rfd < 0) { + FAIL(-5); + } + + /* Test 5: Write to read-only file. */ + r = cfs_write(rfd, buf, sizeof(buf)); + if(r >= 0) { + FAIL(-6); + } + + /* Test 7: Read the buffer written in Test 2. */ + memset(buf, 0, sizeof(buf)); + r = cfs_read(rfd, buf, sizeof(buf)); + if(r < 0) { + FAIL(-8); + } else if(r < sizeof(buf)) { + printf("r=%d\n", r); + FAIL(-9); + } + + /* Test 8: Verify that the buffer is correct. */ + for(r = 0; r < sizeof(buf); r++) { + if(buf[r] != r) { + printf("r=%d. buf[r]=%d\n", r, buf[r]); + FAIL(-10); + } + } + + /* Test 9: Seek to beginning. */ + if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) { + FAIL(-11); + } + + /* Test 10: Write to the log. */ + r = cfs_write(wfd, buf, sizeof(buf)); + if(r < 0) { + FAIL(-12); + } else if(r < sizeof(buf)) { + FAIL(-13); + } + + /* Test 11: Read the data from the log. */ + cfs_seek(rfd, 0, CFS_SEEK_SET); + memset(buf, 0, sizeof(buf)); + r = cfs_read(rfd, buf, sizeof(buf)); + if(r < 0) { + FAIL(-14); + } else if(r < sizeof(buf)) { + FAIL(-15); + } + + /* Test 12: Verify that the data is correct. */ + for(r = 0; r < sizeof(buf); r++) { + if(buf[r] != r) { + FAIL(-16); + } + } + + /* Test 13: Write a reversed buffer to the file. */ + for(r = 0; r < sizeof(buf); r++) { + buf[r] = sizeof(buf) - r - 1; + } + if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) { + FAIL(-17); + } + r = cfs_write(wfd, buf, sizeof(buf)); + if(r < 0) { + FAIL(-18); + } else if(r < sizeof(buf)) { + FAIL(-19); + } + if(cfs_seek(rfd, 0, CFS_SEEK_SET) != 0) { + FAIL(-20); + } + + /* Test 14: Read the reversed buffer. */ + cfs_seek(rfd, 0, CFS_SEEK_SET); + memset(buf, 0, sizeof(buf)); + r = cfs_read(rfd, buf, sizeof(buf)); + if(r < 0) { + FAIL(-21); + } else if(r < sizeof(buf)) { + printf("r = %d\n", r); + FAIL(-22); + } + + /* Test 15: Verify that the data is correct. */ + for(r = 0; r < sizeof(buf); r++) { + if(buf[r] != sizeof(buf) - r - 1) { + FAIL(-23); + } + } + + cfs_close(rfd); + cfs_close(wfd); + + if(cfs_coffee_reserve("T2", FILE_SIZE) < 0) { + FAIL(-24); + } + + /* Test 16: Test multiple writes at random offset. */ + for(r = 0; r < 100; r++) { + wfd = cfs_open("T2", CFS_WRITE | CFS_READ); + if(wfd < 0) { + FAIL(-25); + } + + offset = random_rand() % FILE_SIZE; + + for(r = 0; r < sizeof(buf); r++) { + buf[r] = r; + } + + if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) { + FAIL(-26); + } + + if(cfs_write(wfd, buf, sizeof(buf)) != sizeof(buf)) { + FAIL(-27); + } + + if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) { + FAIL(-28); + } + + memset(buf, 0, sizeof(buf)); + if(cfs_read(wfd, buf, sizeof(buf)) != sizeof(buf)) { + FAIL(-29); + } + + for(i = 0; i < sizeof(buf); i++) { + if(buf[i] != i) { + printf("buf[%d] != %d\n", i, buf[i]); + FAIL(-30); + } + } + } + + /* Test 17: Append data to the same file many times. */ +#define APPEND_BYTES 1000 +#define BULK_SIZE 10 + for(i = 0; i < APPEND_BYTES; i += BULK_SIZE) { + afd = cfs_open("T3", CFS_WRITE | CFS_APPEND); + if(afd < 0) { + FAIL(-31); + } + for(j = 0; j < BULK_SIZE; j++) { + buf[j] = 1 + ((i + j) & 0x7f); + } + if((r = cfs_write(afd, buf, BULK_SIZE)) != BULK_SIZE) { + printf("r=%d\n", r); + FAIL(-32); + } + cfs_close(afd); + } + + /* Test 18: Read back the data written in Test 17 and verify that it + is correct. */ + afd = cfs_open("T3", CFS_READ); + if(afd < 0) { + FAIL(-33); + } + total_read = 0; + while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) { + for(j = 0; j < r; j++) { + if(buf2[j] != 1 + ((total_read + j) & 0x7f)) { + FAIL(-34); + } + } + total_read += r; + } + if(r < 0) { + FAIL(-35); + } + if(total_read != APPEND_BYTES) { + FAIL(-35); + } + cfs_close(afd); + + error = 0; +end: + cfs_close(wfd); cfs_close(rfd); cfs_close(afd); + return error; +} +#endif /* TESTCOFFEE */ + +/*---------------------------------------------------------------------------*/ +/*---------------------------EEPROM ROUTINES---------------------------------*/ +/*---------------------------------------------------------------------------*/ +#ifdef COFFEE_AVR_EEPROM + +/* Letting .bss initialize nullb to zero saves COFFEE_SECTOR_SIZE of flash */ +//static const unsigned char nullb[COFFEE_SECTOR_SIZE] = {0}; +static const unsigned char nullb[COFFEE_SECTOR_SIZE]; + +/*---------------------------------------------------------------------------*/ +/* Erase EEPROM sector + */ +void +avr_eeprom_erase(uint16_t sector) +{ + eeprom_write(COFFEE_START + sector * COFFEE_SECTOR_SIZE, + (unsigned char *)nullb, sizeof(nullb)); +} +#endif /* COFFEE_AVR_EEPROM */ + +#ifdef COFFEE_AVR_FLASH +/*---------------------------------------------------------------------------*/ +/*---------------------------FLASH ROUTINES----------------------------------*/ +/*---------------------------------------------------------------------------*/ +/* + * Read from flash info buf. addr contains starting flash byte address + */ +void +avr_flash_read(CFS_CONF_OFFSET_TYPE addr, uint8_t *buf, CFS_CONF_OFFSET_TYPE size) +{ + uint32_t addr32=COFFEE_START+addr; +#if DEBUG + unsigned char *bufo=(unsigned char *)buf; + uint8_t i; + uint16_t w=addr32>>1; //Show progmem word address for debug + PRINTF("r0x%04x(%u) ",w,size); +#endif +#ifndef FLASH_WORD_READS + for (;size>0;size--) { + *buf++=(uint8_t)pgm_read_byte_far(addr32++); + } +#else +/* 130 bytes more PROGMEM, but faster */ + if (size&0x01) { //handle first odd byte + *buf++=(uint8_t)pgm_read_byte_far(addr32++); + size--; + } + for (;size>1;size-=2) {//read words from flash + *(uint16_t *)buf=(uint16_t)pgm_read_word_far(addr32); + buf+=2; + addr32+=2; + } + if (size) { //handle last odd byte + *buf++=(uint8_t)pgm_read_byte_far(addr32); + } +#endif /* FLASH_WORD_READS */ + +#if DEBUG>1 + PRINTF("\nbuf="); + for (i=0;i<16;i++) PRINTF("%2x ",*bufo++); +#endif +} +/*---------------------------------------------------------------------------*/ +/* + Erase the flash page(s) corresponding to the coffee sector. + This is done by calling the write routine with a null buffer and any address + within each page of the sector (we choose the first byte). + */ +void +avr_flash_erase(coffee_page_t sector) +{ + coffee_page_t i; + for (i=0;i>1,k=(COFFEE_START+COFFEE_SIZE)>>1,l=COFFEE_SIZE/1024UL; + printf_P(PSTR("\nTesting coffee filesystem [0x%08x -> 0x%08x (%uKb)] ..."),j,k,l); + int r= coffee_file_test(); + if (r<0) { + printf_P(PSTR("\nFailed with return %d! :-(\n"),r); + } else { + printf_P(PSTR("Passed! :-)\n")); + } + } +#endif +} +/*---------------------------------------------------------------------------*/ +/* + * Transfer buf[size] from RAM to flash, starting at addr. + * If buf is null, just erase the flash page + * Note this routine has to be in the bootloader NRWW part of program memory, + * and that writing to NRWW (last 32 pages on the 1284p) will halt the CPU. + */ +BOOTLOADER_SECTION +void +avr_flash_write(CFS_CONF_OFFSET_TYPE addr, uint8_t *buf, CFS_CONF_OFFSET_TYPE size) +{ + uint32_t addr32; + uint16_t i,w,startpage; + uint8_t bb,ba,sreg; + + /* Disable interrupts, make sure no eeprom write in progress */ + sreg = SREG; + cli(); + eeprom_busy_wait(); + + /* Calculate the starting address of the first flash page being + modified (will be on a page boundary) and the number of + unaltered bytes before and after the data to be written. */ + + startpage=addr/COFFEE_PAGE_SIZE; + addr32=COFFEE_START+startpage*COFFEE_PAGE_SIZE; + bb=addr&0xff; + ba=2*SPM_PAGESIZE-((addr+size)&0xff); + +#if DEBUG + w=addr32>>1; //Show progmem word address for debug + if (buf) { + PRINTF("w0x%04x %u %u %u",w,size,bb,ba); + } else { + PRINTF("e0x%04x %u ",w,thepage); + } +#endif + + /* If buf not null, modfy the page(s) */ + if (buf) { + if (size==0) return; //nothing to write + /*Copy the first part of the existing page into the write buffer */ + while (bb>1) { + w=pgm_read_word_far(addr32); + boot_page_fill(addr32,w); + addr32+=2; + bb-=2; + } + /* Transfer the bytes to be modified */ + while (size>1) { + if (bb) { //handle odd byte boundary + w=pgm_read_word_far(addr32); + w &= 0xff; + bb=0; + size++; + } else { + w = *buf++; + } + w += (*buf++) << 8; + boot_page_fill(addr32, w); + size-=2; +/* Below ought to work but writing to 0xnnnnnnfe modifies the NEXT flash page + for some reason, at least in the AVR Studio simulator. + if ((addr32&0x000000ff)==0x000000fe) { //handle page boundary + if (size) { + boot_page_erase(addr32); + boot_spm_busy_wait(); + boot_page_write(addr32); + boot_spm_busy_wait(); + } + } + addr32+=2; +*/ + +/* This works...*/ + addr32+=2; + if ((addr32&0x000000ff)==0) { //handle page boundary + if (size) { + addr32-=0x42; //get an address within the page + boot_page_erase(addr32); + boot_spm_busy_wait(); + boot_page_write(addr32); + boot_spm_busy_wait(); + addr32+=0x42; + } + } + } + /* Copy the remainder of the existing page */ + while (ba>1) { + w=pgm_read_word_far(addr32); + if (size) { //handle odd byte boundary + w &= 0xff00; + w +=*buf; + size=0; + } + boot_page_fill(addr32,w); + addr32+=2; + ba-=2; + } + /* If buf is null, erase the page to zero */ + } else { + for (i=0;i + * David Kopf + */ + +#ifndef CFS_COFFEE_ARCH_H +#define CFS_COFFEE_ARCH_H + +#include "contiki-conf.h" + +//Currently you may choose just one for the coffee file sytem +//#define COFFEE_AVR_EEPROM //use eeprom for file system +#define COFFEE_AVR_FLASH //use flash for file system + +#ifdef COFFEE_AVR_EEPROM +#include "dev/eeprom.h" +//1284p EEPROM has 512 pages of 8 bytes each = 4KB + +#define COFFEE_SECTOR_SIZE 64UL +#define COFFEE_PAGE_SIZE 16UL +#define COFFEE_START CFS_EEPROM_CONF_OFFSET +#define COFFEE_SIZE ((3 * 1024U) - COFFEE_START) +#define COFFEE_NAME_LENGTH 16 +#define COFFEE_MAX_OPEN_FILES 4 +#define COFFEE_FD_SET_SIZE 8 +#define COFFEE_LOG_TABLE_LIMIT 16 +#define COFFEE_DIR_CACHE_ENTRIES 1 +#define COFFEE_DYN_SIZE (COFFEE_PAGE_SIZE * 4) +#define COFFEE_LOG_SIZE 128 + +typedef int16_t coffee_page_t; +typedef uint16_t coffee_offset_t; + +#define COFFEE_ERASE(sector) avr_eeprom_erase(sector) +void avr_eeprom_erase(uint16_t sector); + +#define COFFEE_WRITE(buf, size, offset) \ + eeprom_write(COFFEE_START + (offset), (unsigned char *)(buf), (size)) + +#define COFFEE_READ(buf, size, offset) \ + eeprom_read (COFFEE_START + (offset), (unsigned char *)(buf), (size)) + +#endif /* COFFEE_AVR_EEPROM */ + +#ifdef COFFEE_AVR_FLASH +/* 1284p PROGMEM has 512 pages of 256 bytes each = 128KB + * Writing to the last 32 NRRW pages will halt the CPU. + * Take care not to overwrite the .bootloader section... */ +#define COFFEE_PAGE_SIZE 256UL //Byte per program flash page (256 for 1284p +#define COFFEE_PAGE_START 65536UL/COFFEE_PAGE_SIZE //Starting page at 64KB for webserver +#define COFFEE_PAGES 512UL-COFFEE_PAGE_START-32UL //Number of pages to use (reserve NWWR pages) +#define COFFEE_START (COFFEE_PAGE_START)*COFFEE_PAGE_SIZE //Starting address of the file system, on a page boundary +#define FLASH_WORD_READS 1 //Faster but takes 130 bytes more PROGMEM + +#define COFFEE_SIZE (COFFEE_PAGES)*COFFEE_PAGE_SIZE //Bytes in filesystem +#define COFFEE_SECTOR_SIZE (COFFEE_PAGE_SIZE*1) //Each page a sector? +#define COFFEE_NAME_LENGTH 16 +#define COFFEE_MAX_OPEN_FILES 4 +#define COFFEE_FD_SET_SIZE 8 //Size of file descriptor +#define COFFEE_LOG_TABLE_LIMIT 16 +#define COFFEE_DIR_CACHE_ENTRIES 1 +#define COFFEE_DYN_SIZE (COFFEE_PAGE_SIZE*1) //Allocation block size +#define COFFEE_MICRO_LOGS 0 //1 to enable, 0 best for single page sectors +#define COFFEE_LOG_SIZE 128 //Microlog size, when used + +/* coffee_page_t is used for page and sector numbering + * uint8_t can handle 511 pages. + * cfs_offset_t is used for full byte addresses + * If CFS_CONF_OFFSET_TYPE is not defined it defaults to int. + * uint16_t can handle up to a 65535 byte file system. */ +#define coffee_page_t uint8_t +#define CFS_CONF_OFFSET_TYPE uint16_t + + +#define COFFEE_WRITE(buf, size, offset) \ + avr_flash_write(offset, (uint8_t *) buf, size) + +#define COFFEE_READ(buf, size, offset) \ + avr_flash_read(offset, (uint8_t *) buf, size) + +#define COFFEE_ERASE(sector) avr_flash_erase(sector) + +void avr_flash_erase(coffee_page_t sector); +void avr_flash_read (CFS_CONF_OFFSET_TYPE addr, uint8_t *buf, CFS_CONF_OFFSET_TYPE size); +void avr_flash_write(CFS_CONF_OFFSET_TYPE addr, uint8_t *buf, CFS_CONF_OFFSET_TYPE size); + +#endif /* COFFEE_AVR_FLASH */ + +#endif /* !COFFEE_ARCH_H */ diff --git a/platform/avr-raven/watchdog.c b/platform/avr-raven/watchdog.c new file mode 100644 index 000000000..6882a9571 --- /dev/null +++ b/platform/avr-raven/watchdog.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2005, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * @(#)$Id: watchdog.c,v 1.1 2009/07/14 19:23:22 dak664 Exp $ + */ + + /* Dummy watchdog routines for the Raven 1284p */ +#include "dev/watchdog.h" + +/*---------------------------------------------------------------------------*/ +void +watchdog_init(void) +{ +} +/*---------------------------------------------------------------------------*/ +void +watchdog_start(void) +{ +} +/*---------------------------------------------------------------------------*/ +void +watchdog_periodic(void) +{ +} +/*---------------------------------------------------------------------------*/ +void +watchdog_stop(void) +{ +} +/*---------------------------------------------------------------------------*/ +void +watchdog_reboot(void) +{ +} +/*---------------------------------------------------------------------------*/