Mercurial > ~darius > hgwebdir.cgi > stm32temp
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++) |