comparison spiflash.c @ 83:05ba84c7da97

Add a flash layer for compatibility (in future). Fix SPI flash block writing. White space fixes.
author Daniel O'Connor <darius@dons.net.au>
date Mon, 02 Mar 2015 14:32:08 +1030
parents 1a4573062b37
children
comparison
equal deleted inserted replaced
82:c0ff52b8e80c 83:05ba84c7da97
25 #define RW_IDLE 0 25 #define RW_IDLE 0
26 #define RW_RUNNING 1 26 #define RW_RUNNING 1
27 27
28 static int writestate = RW_IDLE; 28 static int writestate = RW_IDLE;
29 static int readstate = RW_IDLE; 29 static int readstate = RW_IDLE;
30 #if 0 30
31 void
32 spiflashcmd(int argc, char **argv) {
33 uint8_t status, tmp, len;
34 uint32_t addr;
35
36 if (argc == 0) {
37 fputs("No command specified\n", stdout);
38 return;
39 }
40
41 if (!strcmp(argv[0], "str")) {
42 status = spiflashreadstatus();
43 fputs("Status = ", stdout);
44 for (unsigned int i = 0; i < sizeof(flstattbl) / sizeof(flstattbl[0]); i++)
45 if (status & 1 << i) {
46 fputs(flstattbl[i], stdout);
47 fputs(" ", stdout);
48 }
49 printf("(0x%02x)\n", status);
50 } else if (!strcmp(argv[0], "stw")) {
51 if (argc != 2) {
52 fputs("Incorrect number of arguments\n", stdout);
53 return;
54 }
55 tmp = atoi(argv[1]);
56 spiflashwritestatus(tmp);
57 status = spiflashreadstatus();
58 printf("Wrote 0x%02x to status, now 0x%02x\n", tmp, status);
59 } else if (!strcmp(argv[0], "er")) {
60 if (argc != 2) {
61 fputs("Incorrect number of arguments\n", stdout);
62 return;
63 }
64 addr = atoi(argv[1]);
65 spiflash4kerase(addr);
66 printf("Erased 0x%x\n", (unsigned int)addr);
67 } else if (!strcmp(argv[0], "rd")) {
68 if (argc < 2) {
69 fputs("Incorrect number of arguments\n", stdout);
70 return;
71 }
72
73 addr = atoi(argv[1]);
74
75 if (argc > 2)
76 len = atoi(argv[2]);
77 else
78 len = 16;
79
80 spiflashstartread(addr);
81
82 for (uint32_t i = 0; i < len; i++)
83 printf("Read 0x%02x from 0x%06x\n", spiflashreadbyte(), (unsigned int)(addr + i));
84 spiflashstopread();
85
86 fputs("\n", stdout);
87 } else if (!strcmp(argv[0], "wr")) {
88 if (argc < 2) {
89 fputs("Incorrect number of arguments\n", stdout);
90 return;
91 }
92
93 addr = atoi(argv[1]);
94
95 if (argc > 2)
96 len = atoi(argv[2]);
97 else
98 len = 16;
99
100 for (int i = 0; i < 16; i += 2) {
101 uint16_t data;
102 data = ((i + 1) << 8) | i;
103 printf("Writing 0x%04x to 0x%06x\n", data, (unsigned int)(addr + i));
104
105 if (i == 0)
106 spiflashstartwrite(addr, data);
107 else
108 spiflashwriteword(data);
109 }
110 spiflashstopwrite();
111 } else if (!strcmp(argv[0], "id")) {
112 printf("Flash ID = 0x%04hx (expect 0xbf41)\n", spiflashreadid());
113 } else {
114 fputs("Unknown sub command\n", stdout);
115 return;
116 }
117 }
118 #endif
119 void 31 void
120 spiflash4kerase(uint32_t addr) { 32 spiflash4kerase(uint32_t addr) {
121 spiflashenablewrite(); /* Enable writing */ 33 spiflashenablewrite(); /* Enable writing */
122 34
123 FL_SELECT(); /* Select device */ 35 FL_SELECT(); /* Select device */
124 36
125 SPI_WriteByte(FL_4KERASE); /* Send command */ 37 SPI_WriteByte(FL_4KERASE); /* Send command */
126 SPI_WriteByte(addr >> 16); /* Send address */ 38 SPI_WriteByte(addr >> 16); /* Send address */
127 SPI_WriteByte(addr >> 8); 39 SPI_WriteByte(addr >> 8);
128 SPI_WriteByte(addr); 40 SPI_WriteByte(addr);
129 41
130 FL_DESELECT(); 42 FL_DESELECT();
131 43
132 //fputs("4k erase ", stdout); 44 //fputs("4k erase ", stdout);
133 spiflashwait(); 45 spiflashwait();
134 } 46 }
135 47
136 void 48 void
137 spiflashwait(void) { 49 spiflashwait(void) {
138 uint8_t cnt; 50 uint8_t cnt;
139 51
140 /* Wait for not BUSY */ 52 /* Wait for not BUSY */
141 for (cnt = 0; (spiflashreadstatus() & FL_BUSY) != 0; cnt++) 53 for (cnt = 0; (spiflashreadstatus() & FL_BUSY) != 0; cnt++)
142 ; 54 ;
143 55
144 //printf("cnt = %d\n", cnt); 56 //printf("cnt = %d\n", cnt);
145 } 57 }
146 58
147 uint16_t 59 uint16_t
148 spiflashreadid(void) { 60 spiflashreadid(void) {
149 uint8_t fac, dev; 61 uint8_t fac, dev;
150 62
151 FL_SELECT(); /* Select device */ 63 FL_SELECT(); /* Select device */
152 64
153 SPI_WriteByte(FL_RDID); /* Send command */ 65 SPI_WriteByte(FL_RDID); /* Send command */
154 SPI_WriteByte(0x00); /* Send address cycles (ID data starts at 0) */ 66 SPI_WriteByte(0x00); /* Send address cycles (ID data starts at 0) */
155 SPI_WriteByte(0x00); 67 SPI_WriteByte(0x00);
156 SPI_WriteByte(0x00); 68 SPI_WriteByte(0x00);
157 fac = SPI_WriteByte(0x00); /* Read ID */ 69 fac = SPI_WriteByte(0x00); /* Read ID */
158 dev = SPI_WriteByte(0x00); 70 dev = SPI_WriteByte(0x00);
159 71
160 FL_DESELECT(); /* De-select device */ 72 FL_DESELECT(); /* De-select device */
161 73
162 return fac << 8 | dev; 74 return fac << 8 | dev;
163 } 75 }
164 76
165 void 77 void
166 spiflashenablewrite(void) { 78 spiflashenablewrite(void) {
167 FL_SELECT(); /* Select device */ 79 FL_SELECT(); /* Select device */
168 80
169 SPI_WriteByte(FL_WREN); /* Send command */ 81 SPI_WriteByte(FL_WREN); /* Send command */
170 82
171 FL_DESELECT(); /* De-select device */ 83 FL_DESELECT(); /* De-select device */
172 } 84 }
173 85
174 uint8_t 86 uint8_t
175 spiflashreadstatus(void) { 87 spiflashreadstatus(void) {
176 uint8_t status; 88 uint8_t status;
177 89
178 FL_SELECT(); /* Select device */ 90 FL_SELECT(); /* Select device */
179 91
180 SPI_WriteByte(FL_RDSR); /* Send command */ 92 SPI_WriteByte(FL_RDSR); /* Send command */
181 SPI_WriteByte(0x00); /* Send dummy byte for address cycle */ 93 SPI_WriteByte(0x00); /* Send dummy byte for address cycle */
182 status = SPI_WriteByte(0x00); /* Read status */ 94 status = SPI_WriteByte(0x00); /* Read status */
183 95
184 FL_DESELECT(); /* De-select device */ 96 FL_DESELECT(); /* De-select device */
185 97
186 return status; 98 return status;
187 } 99 }
188 100
193 SPI_WriteByte(FL_EWSR); /* Send command */ 105 SPI_WriteByte(FL_EWSR); /* Send command */
194 SPI_WriteByte(0x00); /* Send data byte */ 106 SPI_WriteByte(0x00); /* Send data byte */
195 FL_DESELECT(); 107 FL_DESELECT();
196 108
197 /* Actually write status */ 109 /* Actually write status */
198 FL_SELECT(); /* Re-select device for new command */ 110 FL_SELECT(); /* Re-select device for new command */
199 SPI_WriteByte(FL_WRSR); /* Send command */ 111 SPI_WriteByte(FL_WRSR); /* Send command */
200 SPI_WriteByte(status); /* Send data byte */ 112 SPI_WriteByte(status); /* Send data byte */
201 FL_DESELECT(); /* De-select device */ 113 FL_DESELECT(); /* De-select device */
202 } 114 }
203 115
204 uint8_t 116 uint8_t
205 spiflashread(uint32_t addr) { 117 spiflashread(uint32_t addr) {
206 uint8_t data; 118 uint8_t data;
207 119
208 FL_SELECT(); /* Select device */ 120 FL_SELECT(); /* Select device */
209 121
210 SPI_WriteByte(FL_READ); /* Send command */ 122 SPI_WriteByte(FL_READ); /* Send command */
211 SPI_WriteByte(addr >> 16); /* Send address */ 123 SPI_WriteByte(addr >> 16); /* Send address */
212 SPI_WriteByte(addr >> 8); 124 SPI_WriteByte(addr >> 8);
213 SPI_WriteByte(addr); 125 SPI_WriteByte(addr);
214 data = SPI_WriteByte(0x00); /* Read data */ 126 data = SPI_WriteByte(0x00); /* Read data */
215 127
216 FL_DESELECT(); /* De-select device */ 128 FL_DESELECT(); /* De-select device */
217 129
218 return data; 130 return data;
219 } 131 }
220 132
228 SPI_WriteByte(FL_BYTEPROG); /* Send command */ 140 SPI_WriteByte(FL_BYTEPROG); /* Send command */
229 SPI_WriteByte(addr >> 16); /* Send address */ 141 SPI_WriteByte(addr >> 16); /* Send address */
230 SPI_WriteByte(addr >> 8); 142 SPI_WriteByte(addr >> 8);
231 SPI_WriteByte(addr); 143 SPI_WriteByte(addr);
232 SPI_WriteByte(data); /* Write data */ 144 SPI_WriteByte(data); /* Write data */
233 145
234 FL_DESELECT(); /* De-select device */ 146 FL_DESELECT(); /* De-select device */
235 147
236 } 148 }
237 149
238 /* 150 /*
241 */ 153 */
242 154
243 void 155 void
244 spiflashstartread(uint32_t addr) { 156 spiflashstartread(uint32_t addr) {
245 assert(readstate == RW_IDLE); 157 assert(readstate == RW_IDLE);
246 158
247 FL_SELECT(); /* Select device */ 159 FL_SELECT(); /* Select device */
248 160
249 SPI_WriteByte(FL_READ); /* Send command */ 161 SPI_WriteByte(FL_READ); /* Send command */
250 SPI_WriteByte(addr >> 16); /* Send address */ 162 SPI_WriteByte(addr >> 16); /* Send address */
251 SPI_WriteByte(addr >> 8); 163 SPI_WriteByte(addr >> 8);
267 FL_DESELECT(); 179 FL_DESELECT();
268 180
269 readstate = RW_IDLE; 181 readstate = RW_IDLE;
270 } 182 }
271 183
272 /* 184 /*
273 * Auto increment writing looks like so 185 * Auto increment writing looks like so
274 * 186 *
275 * Enable writing CS, WREN, nCS 187 * Enable writing CS, WREN, nCS
276 * Send start address & first data word CS, AAI + addr + data, nCS 188 * Send start address & first data word CS, AAI + addr + data, nCS
277 * Send subsequent words wait for nBUSY, CS, AAI + data, nCS 189 * Send subsequent words wait for nBUSY, CS, AAI + data, nCS
282 * STM32 could sample it without switching out of SPI mode. 194 * STM32 could sample it without switching out of SPI mode.
283 */ 195 */
284 void 196 void
285 spiflashstartwrite(uint32_t addr, uint16_t data) { 197 spiflashstartwrite(uint32_t addr, uint16_t data) {
286 assert(writestate == RW_IDLE); 198 assert(writestate == RW_IDLE);
287 199
288 spiflashenablewrite(); /* Enable writes */ 200 spiflashenablewrite(); /* Enable writes */
289 201
290 FL_SELECT(); /* Select device */ 202 FL_SELECT(); /* Select device */
291 203
292 SPI_WriteByte(FL_AAIWP); /* Send command */ 204 SPI_WriteByte(FL_AAIWP); /* Send command */
293 SPI_WriteByte(addr >> 16); 205 SPI_WriteByte(addr >> 16);
303 } 215 }
304 216
305 void 217 void
306 spiflashwriteword(uint16_t data) { 218 spiflashwriteword(uint16_t data) {
307 assert(writestate == RW_RUNNING); 219 assert(writestate == RW_RUNNING);
308 220
309 //fputs("write word ", stdout); 221 //fputs("write word ", stdout);
310 spiflashwait(); /* Wait until not busy */ 222 spiflashwait(); /* Wait until not busy */
311 223
312 FL_SELECT(); /* Select device */ 224 FL_SELECT(); /* Select device */
313 225
337 writestate = RW_IDLE; 249 writestate = RW_IDLE;
338 } 250 }
339 251
340 int 252 int
341 spiflashreadblock(uint32_t addr, uint32_t len, void *_data) { 253 spiflashreadblock(uint32_t addr, uint32_t len, void *_data) {
342 uint8_t *data = _data; 254 uint32_t *data = _data;
343 uint32_t flashcrc, ramcrc; 255 uint32_t flashcrc, ramcrc, tmp;
344 256
345 /* Must be a multiple of 4 due to CRC check */ 257 /* Must be a multiple of 4 due to CRC check */
346 assert(len % 4 == 0); 258 assert(len % 4 == 0);
347 259
348 spiflashstartread(addr); 260 spiflashstartread(addr);
349 CRC_ResetDR(); 261 CRC_ResetDR();
350 for (int i = len; i > 0; i--) { 262 for (int i = len; i > 0; i -= 4) {
351 *data = spiflashreadbyte(); 263 tmp = spiflashreadbyte() |
352 CRC_CalcCRC(*data); 264 spiflashreadbyte() << 8 |
265 spiflashreadbyte() << 16 |
266 spiflashreadbyte() << 24;
267
268 *data = tmp;
269 CRC_CalcCRC(tmp);
353 data++; 270 data++;
354 } 271 }
355 272
356 flashcrc = spiflashreadbyte(); 273 flashcrc = spiflashreadbyte();
357 flashcrc |= spiflashreadbyte() << 8; 274 flashcrc |= spiflashreadbyte() << 8;
359 flashcrc |= spiflashreadbyte() << 24; 276 flashcrc |= spiflashreadbyte() << 24;
360 277
361 spiflashstopread(); 278 spiflashstopread();
362 279
363 ramcrc = CRC_GetCRC(); 280 ramcrc = CRC_GetCRC();
364 281
365 /* printf("RAM CRC 0x%08x Flash CRC 0x%08x\n", (uint)ramcrc, (uint)flashcrc); */ 282 //printf("RAM CRC 0x%08x Flash CRC 0x%08x\n", (uint)ramcrc, (uint)flashcrc);
366 if (ramcrc == flashcrc) 283 if (ramcrc == flashcrc)
367 return 1; 284 return 1;
368 else 285 else
369 return 0; 286 return 0;
370 } 287 }
371 288
372 uint32_t 289 uint32_t
373 spiflashcrcblock(uint32_t addr, uint32_t len) { 290 spiflashcrcblock(uint32_t addr, uint32_t len) {
291 uint32_t tmp;
292
374 assert(len % 4 == 0); 293 assert(len % 4 == 0);
375 294
376 CRC_ResetDR(); 295 CRC_ResetDR();
377 296
378 spiflashstartread(addr); 297 spiflashstartread(addr);
379 for (int i = len; i > 0; i--) 298 for (; len > 0; len -= 4) {
380 CRC_CalcCRC(spiflashreadbyte()); 299 tmp = spiflashreadbyte() |
381 300 spiflashreadbyte() << 8 |
301 spiflashreadbyte() << 16 |
302 spiflashreadbyte() << 24;
303 CRC_CalcCRC(tmp);
304 }
382 spiflashstopread(); 305 spiflashstopread();
383 306
384 return CRC_GetCRC(); 307 return CRC_GetCRC();
385 } 308 }
386 309
387 int 310 int
388 spiflashwriteblock(uint32_t addr, uint32_t len, void *_data) { 311 spiflashwriteblock(uint32_t addr, uint32_t len, void *_data) {
389 uint16_t *data = _data; 312 uint16_t *data = _data;
390 uint32_t crc, vcrc; 313 uint32_t crc, vcrc, tmp;
391 314
392 //printf("Writing %u bytes to 0x%06x\n", (uint)len, (uint)addr); 315 //printf("Writing %u bytes to 0x%06x\n", (uint)len, (uint)addr);
393 316
394 /* Ensure data is 317 /* Ensure data is
395 * - 16 bit aligned 318 * - 16 bit aligned
396 * - a multiple of 32 bits in length (for CRCs, the flash only need 16 bits) 319 * - a multiple of 32 bits in length (for CRCs, the flash only need 16 bits)
397 * - not longer than a sector 320 * - not longer than a sector
398 */ 321 */
399 assert(addr % 2 == 0); 322 assert(addr % 2 == 0);
400 assert(len % 4 == 0); 323 assert(len % 4 == 0);
401 assert(len <= 4096); 324 assert(len <= 4096);
402 325
403 /* Disable write protect */ 326 /* Disable write protect */
404 spiflashwritestatus(0x00); 327 spiflashwritestatus(0x00);
405 328
406 /* Erase sector */ 329 /* Erase sector */
407 spiflash4kerase(addr); 330 spiflash4kerase(addr);
408
409 CRC_ResetDR();
410 331
411 /* Write data */ 332 /* Write data */
412 for (uint i = 0; i < len / 2; i++) { 333 CRC_ResetDR();
334 for (uint i = 0; i < len / 2; i++) {
335 //printf("0x%04x: %04x\n", i, *data);
413 if (i == 0) 336 if (i == 0)
414 spiflashstartwrite(addr, *data); 337 spiflashstartwrite(addr, *data);
415 else 338 else
416 spiflashwriteword(*data); 339 spiflashwriteword(*data);
417 CRC_CalcCRC(*data); 340
341 if (i % 2 == 0)
342 tmp = *data;
343 else {
344 tmp |= *data << 16;
345 CRC_CalcCRC(tmp);
346 }
418 data++; 347 data++;
419 } 348 }
420 349
421 /* Calculate CRC */ 350 /* Calculate CRC */
422 crc = CRC_GetCRC(); 351 crc = CRC_GetCRC();
423 352 //printf("CRC is 0x%08x\n", (uint)crc);
424 //printf("CRC is 0x%08x\n", (uint)crc); 353
425 354 /* Write CRC */
426 /* Write CRC */ 355 spiflashwriteword(crc);
427 spiflashwriteword(crc); 356 spiflashwriteword(crc >> 16);
428 spiflashwriteword(crc >> 16); 357
429 358 spiflashstopwrite();
430 spiflashstopwrite(); 359
431 360 /* Read back and check CRC */
432 /* Read back and check CRC */ 361 vcrc = spiflashcrcblock(addr, len);
433 vcrc = spiflashcrcblock(addr, len); 362 //printf("CRC read back as 0x%08x\n", (uint)vcrc);
434 if (vcrc != crc) 363 if (vcrc != crc)
435 return 1; 364 return 1;
436 else 365 else
437 return 0; 366 return 0;
438 } 367 }
439 368
440 void 369 void
441 spiflashprintstatus(uint8_t status, FILE *out) { 370 spiflashprintstatus(uint8_t status, FILE *out) {
442 for (unsigned int i = 0; i < sizeof(flstattbl) / sizeof(flstattbl[0]); i++) 371 for (unsigned int i = 0; i < sizeof(flstattbl) / sizeof(flstattbl[0]); i++)