diff --git a/platform/z1/Makefile.z1 b/platform/z1/Makefile.z1 index 996e71e8b..17e40e971 100644 --- a/platform/z1/Makefile.z1 +++ b/platform/z1/Makefile.z1 @@ -1,8 +1,8 @@ -# $Id: Makefile.z1,v 1.1 2010/08/24 16:26:38 joxe Exp $ +# $Id: Makefile.z1,v 1.2 2010/08/25 17:28:15 joxe Exp $ CFLAGS+=-Os -g -ARCH=msp430.c leds.c watchdog.c \ +ARCH=msp430.c leds.c watchdog.c xmem.c \ spix.c cc2420.c cc2420-aes.c cc2420-arch.c cc2420-arch-sfd.c\ node-id.c sensors.c button-sensor.c cfs-coffee.c \ radio-sensor.c uart0x.c uart0-putchar.c uip-ipchksum.c \ diff --git a/platform/z1/cfs-coffee-arch.h b/platform/z1/cfs-coffee-arch.h index 1381ac66e..fe28c26ba 100644 --- a/platform/z1/cfs-coffee-arch.h +++ b/platform/z1/cfs-coffee-arch.h @@ -32,9 +32,10 @@ /** * \file - * Coffee architecture-dependent header for the Tmote Sky platform. + * Coffee architecture-dependent header for the Zolertia Z1 platform. * \author * Nicolas Tsiftes + * Enric M. Calvo */ #ifndef CFS_COFFEE_ARCH_H @@ -44,11 +45,21 @@ #include "dev/xmem.h" #include "dev/watchdog.h" +/*** M25P16 Memory Organization +The memory is organized as: +16Mbit = 2 097 152 bytes (8 bits each) +32 sectors (512 Kbits, 65536 bytes each) +8192 pages (256 bytes each). +Each page can be individually programmed (bits are programmed from 1 to 0). The device is +sector or bulk erasable (bits are erased from 0 to 1) but not page erasable +*/ +#define COFFEE_XMEM_TOTAL_SIZE_KB 2048UL //Total size of the External Flash Memory in the Z1 + /* Coffee configuration parameters. */ -#define COFFEE_SECTOR_SIZE 65536UL +#define COFFEE_SECTOR_SIZE 65536UL #define COFFEE_PAGE_SIZE 256UL #define COFFEE_START COFFEE_SECTOR_SIZE -#define COFFEE_SIZE (1024UL * 1024UL - COFFEE_START) +#define COFFEE_SIZE (COFFEE_XMEM_TOTAL_SIZE_KB * 1024UL - COFFEE_START) #define COFFEE_NAME_LENGTH 16 #define COFFEE_MAX_OPEN_FILES 6 #define COFFEE_FD_SET_SIZE 8 diff --git a/platform/z1/dev/xmem.c b/platform/z1/dev/xmem.c new file mode 100644 index 000000000..4e126464f --- /dev/null +++ b/platform/z1/dev/xmem.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2006, 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. + * + * @(#)$Id: xmem.c,v 1.1 2010/08/25 17:28:16 joxe Exp $ + */ + +/** + * \file + * Device driver for the ST M25P16 40MHz 1Mbyte external memory. + * \author + * Björn Grönvall + * Enric M. Calvo + * + * Data is written bit inverted (~-operator) to flash so that + * unwritten data will read as zeros (UNIX style). + */ + +#include +#include + +#include +#include + +#include "contiki.h" + +#include "dev/spi.h" +#include "dev/xmem.h" +#include "dev/watchdog.h" + +#if 1 +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) do {} while (0) +#endif + +#define SPI_FLASH_INS_WREN 0x06 +#define SPI_FLASH_INS_WRDI 0x04 +#define SPI_FLASH_INS_RDSR 0x05 +#define SPI_FLASH_INS_WRSR 0x01 +#define SPI_FLASH_INS_READ 0x03 +#define SPI_FLASH_INS_FAST_READ 0x0b +#define SPI_FLASH_INS_PP 0x02 +#define SPI_FLASH_INS_SE 0xd8 +#define SPI_FLASH_INS_BE 0xc7 +#define SPI_FLASH_INS_DP 0xb9 +#define SPI_FLASH_INS_RES 0xab +/*---------------------------------------------------------------------------*/ +static void +write_enable(void) +{ + int s; + + s = splhigh(); + SPI_FLASH_ENABLE(); + + SPI_WRITE(SPI_FLASH_INS_WREN); + + SPI_FLASH_DISABLE(); + splx(s); +} +/*---------------------------------------------------------------------------*/ +static unsigned +read_status_register(void) +{ + unsigned char u; + + int s; + + s = splhigh(); + SPI_FLASH_ENABLE(); + + + SPI_WRITE(SPI_FLASH_INS_RDSR); + + SPI_FLUSH(); + SPI_READ(u); + + SPI_FLASH_DISABLE(); + splx(s); + + return u; +} +/*---------------------------------------------------------------------------*/ +/* + * Wait for a write/erase operation to finish. + */ +static unsigned +wait_ready(void) +{ + unsigned u; + do { + u = read_status_register(); + } while(u & 0x01); /* WIP=1, write in progress */ + return u; +} +/*---------------------------------------------------------------------------*/ +/* + * Erase 64k bytes of data. It takes about 1s before WIP goes low! + */ +static void +erase_sector(unsigned long offset) +{ + int s; + wait_ready(); + + write_enable(); + + s = splhigh(); + SPI_FLASH_ENABLE(); + + SPI_WRITE_FAST(SPI_FLASH_INS_SE); + SPI_WRITE_FAST(offset >> 16); /* MSB */ + SPI_WRITE_FAST(offset >> 8); + SPI_WRITE_FAST(offset >> 0); /* LSB */ + SPI_WAITFORTx_ENDED(); + + SPI_FLASH_DISABLE(); + splx(s); +} +/*---------------------------------------------------------------------------*/ +/* + * Initialize external flash *and* SPI bus! + */ +void +xmem_init(void) +{ + spi_init(); + + P4DIR |= BV(FLASH_CS); // Unnecessary for Zolertia Z1 | BV(FLASH_PWR); + P5DIR |= BV(FLASH_HOLD); // In P5 for Z1 + + SPI_FLASH_DISABLE(); /* Unselect flash. */ + SPI_FLASH_UNHOLD(); +} +/*---------------------------------------------------------------------------*/ +int +xmem_pread(void *_p, int size, unsigned long offset) +{ + unsigned char *p = _p; + const unsigned char *end = p + size; + int s; + wait_ready(); + + ENERGEST_ON(ENERGEST_TYPE_FLASH_READ); + + s = splhigh(); + SPI_FLASH_ENABLE(); + + SPI_WRITE_FAST(SPI_FLASH_INS_READ); + SPI_WRITE_FAST(offset >> 16); /* MSB */ + SPI_WRITE_FAST(offset >> 8); + SPI_WRITE_FAST(offset >> 0); /* LSB */ + SPI_WAITFORTx_ENDED(); + + SPI_FLUSH(); + for(; p < end; p++) { + unsigned char u; + SPI_READ(u); + *p = ~u; + } + + SPI_FLASH_DISABLE(); + splx(s); + + ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ); + + return size; +} +/*---------------------------------------------------------------------------*/ +static const char * +program_page(unsigned long offset, const unsigned char *p, int nbytes) +{ + const unsigned char *end = p + nbytes; + int s; + + wait_ready(); + + write_enable(); + + s = splhigh(); + SPI_FLASH_ENABLE(); + + SPI_WRITE_FAST(SPI_FLASH_INS_PP); + SPI_WRITE_FAST(offset >> 16); /* MSB */ + SPI_WRITE_FAST(offset >> 8); + SPI_WRITE_FAST(offset >> 0); /* LSB */ + + for(; p < end; p++) { + SPI_WRITE_FAST(~*p); + } + SPI_WAITFORTx_ENDED(); + + SPI_FLASH_DISABLE(); + splx(s); + + return p; +} +/*---------------------------------------------------------------------------*/ +int +xmem_pwrite(const void *_buf, int size, unsigned long addr) +{ + const unsigned char *p = _buf; + const unsigned long end = addr + size; + unsigned long i, next_page; + + ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE); + + for(i = addr; i < end;) { + next_page = (i | 0xff) + 1; + if(next_page > end) { + next_page = end; + } + p = program_page(i, p, next_page - i); + i = next_page; + } + + ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE); + + return size; +} +/*---------------------------------------------------------------------------*/ +int +xmem_erase(long size, unsigned long addr) +{ + unsigned long end = addr + size; + + if(size % XMEM_ERASE_UNIT_SIZE != 0) { + PRINTF("xmem_erase: bad size\n"); + return -1; + } + + if(addr % XMEM_ERASE_UNIT_SIZE != 0) { + PRINTF("xmem_erase: bad offset\n"); + return -1; + } + + watchdog_stop(); + + for (; addr < end; addr += XMEM_ERASE_UNIT_SIZE) { + erase_sector(addr); + } + + watchdog_start(); + + return size; +} +/*---------------------------------------------------------------------------*/