xmem.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <stdio.h>
00043 #include <string.h>
00044
00045 #include <io.h>
00046 #include <signal.h>
00047
00048 #include "contiki.h"
00049
00050 #include "dev/spi.h"
00051 #include "dev/xmem.h"
00052 #include "dev/watchdog.h"
00053
00054 #if 0
00055 #define PRINTF(...) printf(__VA_ARGS__)
00056 #else
00057 #define PRINTF(...) do {} while (0)
00058 #endif
00059
00060 #define SPI_FLASH_INS_WREN 0x06
00061 #define SPI_FLASH_INS_WRDI 0x04
00062 #define SPI_FLASH_INS_RDSR 0x05
00063 #define SPI_FLASH_INS_WRSR 0x01
00064 #define SPI_FLASH_INS_READ 0x03
00065 #define SPI_FLASH_INS_FAST_READ 0x0b
00066 #define SPI_FLASH_INS_PP 0x02
00067 #define SPI_FLASH_INS_SE 0xd8
00068 #define SPI_FLASH_INS_BE 0xc7
00069 #define SPI_FLASH_INS_DP 0xb9
00070 #define SPI_FLASH_INS_RES 0xab
00071
00072 static void
00073 write_enable(void)
00074 {
00075 int s;
00076
00077 s = splhigh();
00078 SPI_FLASH_ENABLE();
00079
00080 SPI_WRITE(SPI_FLASH_INS_WREN);
00081
00082 SPI_FLASH_DISABLE();
00083 splx(s);
00084 }
00085
00086 static unsigned
00087 read_status_register(void)
00088 {
00089 unsigned char u;
00090
00091 int s;
00092
00093 s = splhigh();
00094 SPI_FLASH_ENABLE();
00095
00096 SPI_WRITE(SPI_FLASH_INS_RDSR);
00097
00098 SPI_FLUSH();
00099 SPI_READ(u);
00100
00101 SPI_FLASH_DISABLE();
00102 splx(s);
00103
00104 return u;
00105 }
00106
00107
00108
00109
00110 static unsigned
00111 wait_ready(void)
00112 {
00113 unsigned u;
00114 do {
00115 u = read_status_register();
00116 watchdog_periodic();
00117 } while(u & 0x01);
00118 return u;
00119 }
00120
00121
00122
00123
00124 static void
00125 erase_sector(unsigned long offset)
00126 {
00127 int s;
00128
00129 wait_ready();
00130 write_enable();
00131
00132 s = splhigh();
00133 SPI_FLASH_ENABLE();
00134
00135 SPI_WRITE_FAST(SPI_FLASH_INS_SE);
00136 SPI_WRITE_FAST(offset >> 16);
00137 SPI_WRITE_FAST(offset >> 8);
00138 SPI_WRITE_FAST(offset >> 0);
00139 SPI_WAITFORTx_ENDED();
00140
00141 SPI_FLASH_DISABLE();
00142 splx(s);
00143 }
00144
00145
00146
00147
00148 void
00149 xmem_init(void)
00150 {
00151 int s;
00152 spi_init();
00153
00154 P4DIR |= BV(FLASH_CS) | BV(FLASH_HOLD) | BV(FLASH_PWR);
00155 P4OUT |= BV(FLASH_PWR);
00156
00157
00158 s = splhigh();
00159 SPI_FLASH_ENABLE();
00160 SPI_WRITE_FAST(SPI_FLASH_INS_RES);
00161 SPI_WAITFORTx_ENDED();
00162 SPI_FLASH_DISABLE();
00163 splx(s);
00164
00165 SPI_FLASH_UNHOLD();
00166 }
00167
00168 int
00169 xmem_pread(void *_p, int size, unsigned long offset)
00170 {
00171 unsigned char *p = _p;
00172 const unsigned char *end = p + size;
00173 int s;
00174
00175 wait_ready();
00176
00177 ENERGEST_ON(ENERGEST_TYPE_FLASH_READ);
00178
00179 s = splhigh();
00180 SPI_FLASH_ENABLE();
00181
00182 SPI_WRITE_FAST(SPI_FLASH_INS_READ);
00183 SPI_WRITE_FAST(offset >> 16);
00184 SPI_WRITE_FAST(offset >> 8);
00185 SPI_WRITE_FAST(offset >> 0);
00186 SPI_WAITFORTx_ENDED();
00187
00188 SPI_FLUSH();
00189 for(; p < end; p++) {
00190 unsigned char u;
00191 SPI_READ(u);
00192 *p = ~u;
00193 }
00194
00195 SPI_FLASH_DISABLE();
00196 splx(s);
00197
00198 ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ);
00199
00200 return size;
00201 }
00202
00203 static const unsigned char *
00204 program_page(unsigned long offset, const unsigned char *p, int nbytes)
00205 {
00206 const unsigned char *end = p + nbytes;
00207 int s;
00208
00209 wait_ready();
00210 write_enable();
00211
00212 s = splhigh();
00213 SPI_FLASH_ENABLE();
00214
00215 SPI_WRITE_FAST(SPI_FLASH_INS_PP);
00216 SPI_WRITE_FAST(offset >> 16);
00217 SPI_WRITE_FAST(offset >> 8);
00218 SPI_WRITE_FAST(offset >> 0);
00219
00220 for(; p < end; p++) {
00221 SPI_WRITE_FAST(~*p);
00222 }
00223 SPI_WAITFORTx_ENDED();
00224
00225 SPI_FLASH_DISABLE();
00226 splx(s);
00227
00228 return p;
00229 }
00230
00231 int
00232 xmem_pwrite(const void *_buf, int size, unsigned long addr)
00233 {
00234 const unsigned char *p = _buf;
00235 const unsigned long end = addr + size;
00236 unsigned long i, next_page;
00237
00238 ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE);
00239
00240 for(i = addr; i < end;) {
00241 next_page = (i | 0xff) + 1;
00242 if(next_page > end) {
00243 next_page = end;
00244 }
00245 p = program_page(i, p, next_page - i);
00246 i = next_page;
00247 }
00248
00249 ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE);
00250
00251 return size;
00252 }
00253
00254 int
00255 xmem_erase(long size, unsigned long addr)
00256 {
00257 unsigned long end = addr + size;
00258
00259 if(size % XMEM_ERASE_UNIT_SIZE != 0) {
00260 PRINTF("xmem_erase: bad size\n");
00261 return -1;
00262 }
00263
00264 if(addr % XMEM_ERASE_UNIT_SIZE != 0) {
00265 PRINTF("xmem_erase: bad offset\n");
00266 return -1;
00267 }
00268
00269 for (; addr < end; addr += XMEM_ERASE_UNIT_SIZE) {
00270 erase_sector(addr);
00271 }
00272
00273 return size;
00274 }
00275