Mercurial > ~darius > hgwebdir.cgi > stm32temp
comparison flash.c @ 27:5c9d2e3d6591
Add flashread/writeblock commands which read/write a block of data to
flash with a CRC.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Tue, 20 Nov 2012 21:54:06 +1030 |
parents | 74efdb21ae5d |
children | 03592ca4d37e |
comparison
equal
deleted
inserted
replaced
26:74efdb21ae5d | 27:5c9d2e3d6591 |
---|---|
22 "BPL" | 22 "BPL" |
23 }; | 23 }; |
24 | 24 |
25 #define RW_IDLE 0 | 25 #define RW_IDLE 0 |
26 #define RW_RUNNING 1 | 26 #define RW_RUNNING 1 |
27 #define RW_IDLE 0 | 27 |
28 | 28 /* Holds all the settings needed */ |
29 typedef struct { | |
30 uint8_t fermenter_ROM[8]; | |
31 uint8_t fridge_ROM[8]; | |
32 uint8_t ambient_ROM[8]; | |
33 int16_t target_temp; | |
34 uint16_t hysteresis; | |
35 /* How much to under/overshoot on heating/cooling */ | |
36 int16_t minheatovershoot; | |
37 int16_t mincoolovershoot; | |
38 | |
39 /* Minimum time the cooler can be on/off */ | |
40 int16_t mincoolontime; | |
41 int16_t mincoolofftime; | |
42 | |
43 /* Minimum time the heater can be on/off */ | |
44 int16_t minheatontime; | |
45 int16_t minheatofftime; | |
46 | |
47 #define TC_MODE_AUTO 'a' /* Automatic control */ | |
48 #define TC_MODE_HEAT 'h' /* Force heating */ | |
49 #define TC_MODE_COOL 'c' /* Force cooling */ | |
50 #define TC_MODE_IDLE 'i' /* Force idle */ | |
51 #define TC_MODE_NOTHING 'n' /* Do nothing (like idle but log nothing) */ | |
52 char mode; | |
53 | |
54 /* Bit patterns for various modes */ | |
55 uint8_t coolbits; | |
56 uint8_t heatbits; | |
57 uint8_t idlebits; | |
58 | |
59 /* Check/stale times */ | |
60 int16_t check_interval; | |
61 int16_t stale_factor; | |
62 | |
63 /* Beep if stale */ | |
64 int8_t dobeep; | |
65 | |
66 /* Pad to 4 bytes */ | |
67 uint8_t pad[1]; | |
68 | |
69 } __attribute__((packed, aligned(4))) settings_t; | |
70 | |
71 const settings_t default_settings = { | |
72 .fermenter_ROM = { 0x10, 0x4c, 0x7d, 0x53, 0x01, 0x08, 0x00, 0xff }, | |
73 .fridge_ROM = { 0x10, 0x6f, 0x40, 0x53, 0x01, 0x08, 0x00, 0x16 }, | |
74 .ambient_ROM = { 0x10, 0x76, 0x05, 0x53, 0x01, 0x08, 0x00, 0x8c }, | |
75 .target_temp = 1000, | |
76 .hysteresis = 100, | |
77 .minheatovershoot = 50, | |
78 .mincoolovershoot = -50, | |
79 .mincoolontime = 300, | |
80 .mincoolofftime = 600, | |
81 .minheatontime = 60, | |
82 .minheatofftime = 60, | |
83 .mode = TC_MODE_AUTO, | |
84 .coolbits = 1 << 6, | |
85 .heatbits = 1<< 7, | |
86 .idlebits = 0x00, | |
87 .check_interval = 10, | |
88 .stale_factor = 3, | |
89 .dobeep = 0 | |
90 }; | |
91 | |
92 /* RAM copy of setting */ | |
93 static settings_t ram_settings; | |
94 | |
29 static int writestate = RW_IDLE; | 95 static int writestate = RW_IDLE; |
30 static int readstate = RW_IDLE; | 96 static int readstate = RW_IDLE; |
31 | 97 |
32 void | 98 void |
33 flashcmd(char **argv, int argc) { | 99 flashcmd(char **argv, int argc) { |
34 uint8_t status, tmp; | 100 uint8_t status, tmp, len; |
35 uint32_t addr; | 101 uint32_t addr; |
36 | 102 |
37 if (argc == 0) { | 103 if (argc == 0) { |
38 fputs("No command specified\r\n", stdout); | 104 fputs("No command specified\r\n", stdout); |
39 return; | 105 return; |
64 } | 130 } |
65 addr = atoi(argv[1]); | 131 addr = atoi(argv[1]); |
66 flash4kerase(addr); | 132 flash4kerase(addr); |
67 printf("Erased 0x%x\r\n", (unsigned int)addr); | 133 printf("Erased 0x%x\r\n", (unsigned int)addr); |
68 } else if (!strcmp(argv[0], "rd")) { | 134 } else if (!strcmp(argv[0], "rd")) { |
69 if (argc != 2) { | 135 if (argc < 2) { |
70 fputs("Incorrect number of arguments\r\n", stdout); | 136 fputs("Incorrect number of arguments\r\n", stdout); |
71 return; | 137 return; |
72 } | 138 } |
73 | 139 |
74 addr = atoi(argv[1]); | 140 addr = atoi(argv[1]); |
75 | 141 |
142 if (argc > 2) | |
143 len = atoi(argv[2]); | |
144 else | |
145 len = 16; | |
146 | |
76 flashstartread(addr); | 147 flashstartread(addr); |
77 | 148 |
78 for (int i = 0; i < 16; i++) | 149 for (uint32_t i = 0; i < len; i++) |
79 printf("Read 0x%02x from 0x%06x\r\n", flashreadbyte(), (unsigned int)(addr + i)); | 150 printf("Read 0x%02x from 0x%06x\r\n", flashreadbyte(), (unsigned int)(addr + i)); |
80 flashstopread(); | 151 flashstopread(); |
81 | 152 |
82 fputs("\r\n", stdout); | 153 fputs("\r\n", stdout); |
83 } else if (!strcmp(argv[0], "wr")) { | 154 } else if (!strcmp(argv[0], "wr")) { |
84 if (argc != 2) { | 155 if (argc < 2) { |
85 fputs("Incorrect number of arguments\r\n", stdout); | 156 fputs("Incorrect number of arguments\r\n", stdout); |
86 return; | 157 return; |
87 } | 158 } |
88 | 159 |
89 addr = atoi(argv[1]); | 160 addr = atoi(argv[1]); |
161 | |
162 if (argc > 2) | |
163 len = atoi(argv[2]); | |
164 else | |
165 len = 16; | |
90 | 166 |
91 for (int i = 0; i < 16; i += 2) { | 167 for (int i = 0; i < 16; i += 2) { |
92 uint16_t data; | 168 uint16_t data; |
93 data = ((i + 1) << 8) | i; | 169 data = ((i + 1) << 8) | i; |
94 printf("Writing 0x%04x to 0x%06x\r\n", data, (unsigned int)(addr + i)); | 170 printf("Writing 0x%04x to 0x%06x\r\n", data, (unsigned int)(addr + i)); |
97 flashstartwrite(addr, data); | 173 flashstartwrite(addr, data); |
98 else | 174 else |
99 flashwriteword(data); | 175 flashwriteword(data); |
100 } | 176 } |
101 flashstopwrite(); | 177 flashstopwrite(); |
178 } else if (!strcmp(argv[0], "tw")) { | |
179 /* Copy default to RAM */ | |
180 bcopy(&default_settings, &ram_settings, sizeof(default_settings)); | |
181 | |
182 /* Write RAM copy into flash */ | |
183 flashwriteblock(0, sizeof(ram_settings), &ram_settings); | |
184 } else if (!strcmp(argv[0], "tr")) { | |
185 int crcok; | |
186 | |
187 /* Read flash copy to RAM */ | |
188 crcok = flashreadblock(0, sizeof(ram_settings), &ram_settings); | |
189 | |
190 printf("CRC is %s\r\n", crcok ? "OK" : "bad"); | |
102 } else if (!strcmp(argv[0], "id")) { | 191 } else if (!strcmp(argv[0], "id")) { |
103 printf("Flash ID = 0x%04hx (expect 0xbf41)\r\n", flashreadid()); | 192 printf("Flash ID = 0x%04hx (expect 0xbf41)\r\n", flashreadid()); |
104 } else { | 193 } else { |
105 fputs("Unknown sub command\r\n", stdout); | 194 fputs("Unknown sub command\r\n", stdout); |
106 return; | 195 return; |
118 SPI_WriteByte(addr >> 8); | 207 SPI_WriteByte(addr >> 8); |
119 SPI_WriteByte(addr); | 208 SPI_WriteByte(addr); |
120 | 209 |
121 FL_DESELECT(); | 210 FL_DESELECT(); |
122 | 211 |
212 //fputs("4k erase ", stdout); | |
123 flashwait(); | 213 flashwait(); |
124 } | 214 } |
125 | 215 |
126 void | 216 void |
127 flashwait(void) { | 217 flashwait(void) { |
208 return data; | 298 return data; |
209 } | 299 } |
210 | 300 |
211 void | 301 void |
212 flashwrite(uint32_t addr, uint8_t data) { | 302 flashwrite(uint32_t addr, uint8_t data) { |
303 flashwait(); | |
213 flashenablewrite(); /* Enable writes */ | 304 flashenablewrite(); /* Enable writes */ |
214 | 305 |
215 FL_SELECT(); /* Select device */ | 306 FL_SELECT(); /* Select device */ |
216 | 307 |
217 SPI_WriteByte(FL_BYTEPROG); /* Send command */ | 308 SPI_WriteByte(FL_BYTEPROG); /* Send command */ |
293 | 384 |
294 void | 385 void |
295 flashwriteword(uint16_t data) { | 386 flashwriteword(uint16_t data) { |
296 assert(writestate == RW_RUNNING); | 387 assert(writestate == RW_RUNNING); |
297 | 388 |
389 //fputs("write word ", stdout); | |
298 flashwait(); /* Wait until not busy */ | 390 flashwait(); /* Wait until not busy */ |
299 | 391 |
300 FL_SELECT(); /* Select device */ | 392 FL_SELECT(); /* Select device */ |
301 | 393 |
302 SPI_WriteByte(FL_AAIWP); /* Send command */ | 394 SPI_WriteByte(FL_AAIWP); /* Send command */ |
308 | 400 |
309 void | 401 void |
310 flashstopwrite(void) { | 402 flashstopwrite(void) { |
311 assert(writestate == RW_RUNNING); | 403 assert(writestate == RW_RUNNING); |
312 | 404 |
405 //fputs("flash stop write start ", stdout); | |
313 flashwait(); /* Wait until not busy */ | 406 flashwait(); /* Wait until not busy */ |
314 | 407 |
315 FL_SELECT(); /* Select device */ | 408 FL_SELECT(); /* Select device */ |
316 | 409 |
317 SPI_WriteByte(FL_WRDI); /* Send command */ | 410 SPI_WriteByte(FL_WRDI); /* Send command */ |
318 | 411 |
319 FL_DESELECT(); /* Deselect device */ | 412 FL_DESELECT(); /* Deselect device */ |
320 | 413 |
414 //fputs("flash stop write end ", stdout); | |
321 flashwait(); /* Wait until not busy */ | 415 flashwait(); /* Wait until not busy */ |
322 | 416 |
323 writestate = RW_IDLE; | 417 writestate = RW_IDLE; |
324 } | 418 } |
325 | 419 |
420 int | |
421 flashreadblock(uint32_t addr, uint32_t len, void *_data) { | |
422 uint8_t *data = _data; | |
423 uint32_t flashcrc, ramcrc; | |
424 | |
425 /* Must be a multiple of 4 due to CRC check */ | |
426 assert(len % 4 == 0); | |
427 | |
428 flashstartread(addr); | |
429 for (int i = len; i > 0; i--) { | |
430 *data = flashreadbyte(); | |
431 data++; | |
432 } | |
433 | |
434 flashcrc = flashreadbyte(); | |
435 flashcrc |= flashreadbyte() << 8; | |
436 flashcrc |= flashreadbyte() << 16; | |
437 flashcrc |= flashreadbyte() << 24; | |
438 | |
439 flashstopread(); | |
440 | |
441 /* Calculate CRC */ | |
442 CRC_ResetDR(); | |
443 ramcrc = CRC_CalcBlockCRC((uint32_t *)_data, len / 4); | |
444 | |
445 printf("RAM CRC 0x%08x Flash CRC 0x%08x\r\n", (uint)ramcrc, (uint)flashcrc); | |
446 | |
447 if (ramcrc == flashcrc) | |
448 return 1; | |
449 else | |
450 return 0; | |
451 } | |
452 | |
453 void | |
454 flashwriteblock(uint32_t addr, uint32_t len, void *_data) { | |
455 uint16_t *data = _data; | |
456 uint32_t crc; | |
457 | |
458 printf("Writing %u bytes to 0x%06x\r\n", (uint)len, (uint)addr); | |
459 | |
460 /* Ensure data is | |
461 * - 16 bit aligned | |
462 * - a multiple of 32 bits in length (for CRCs, the flash only need 16 bits) | |
463 * - not longer than a sector | |
464 */ | |
465 assert(addr % 2 == 0); | |
466 assert(len % 4 == 0); | |
467 assert(len <= 4096); | |
468 | |
469 /* Disable write protect */ | |
470 flashwritestatus(0x00); | |
471 | |
472 /* Erase sector */ | |
473 flash4kerase(addr); | |
474 | |
475 /* Write data */ | |
476 for (uint i = 0; i < len / 2; i++) { | |
477 if (i == 0) | |
478 flashstartwrite(addr, *data); | |
479 else | |
480 flashwriteword(*data); | |
481 data++; | |
482 } | |
483 | |
484 /* Calculate CRC */ | |
485 CRC_ResetDR(); | |
486 crc = CRC_CalcBlockCRC((uint32_t *)_data, len / 4); | |
487 | |
488 printf("CRC is 0x%08x\r\n", (uint)crc); | |
489 | |
490 /* Write CRC */ | |
491 flashwriteword(crc); | |
492 flashwriteword(crc >> 16); | |
493 | |
494 flashstopwrite(); | |
495 } |