Mercurial > public > ostc4
comparison BootLoader/Src/externLogbookFlash_mini.c @ 985:aeafa631147d BootloaderOstc5
Exchange shared files with Bootloader specific mini version
author | Ideenmodellierer |
---|---|
date | Sun, 30 Mar 2025 21:32:37 +0200 (3 weeks ago) |
parents | |
children |
comparison
equal
deleted
inserted
replaced
984:41136649b90d | 985:aeafa631147d |
---|---|
1 /** | |
2 ****************************************************************************** | |
3 * @copyright heinrichs weikamp | |
4 * @file externLogbookFlash.c | |
5 * @author heinrichs weikamp gmbh | |
6 * @date 07-Aug-2014 | |
7 * @version V0.0.4 | |
8 * @since 29-Sept-2015 | |
9 * @brief Main File to access the new 1.8 Volt Spansion S25FS256S 256 Mbit (32 Mbyte) | |
10 * @bug | |
11 * @warning | |
12 * | |
13 @verbatim | |
14 ============================================================================== | |
15 ##### Logbook Header (TOC) ##### | |
16 ============================================================================== | |
17 [..] Memory useage: | |
18 NEW: Spansion S25FS-S256S | |
19 | |
20 only 8x 4KB and 1x 32KB, remaining is 64KB or 256KB | |
21 Sector Size (kbyte) Sector Count Sector Range Address Range (Byte Address) Notes | |
22 4 8 SA00 00000000h-00000FFFh | |
23 : : | |
24 SA07 00007000h-00007FFFh | |
25 | |
26 32 1 SA08 00008000h-0000FFFFh | |
27 | |
28 64 511 SA09 00010000h-0001FFFFh | |
29 : : | |
30 SA519 01FF0000h-01FFFFFFh | |
31 OLD: | |
32 1kB each header | |
33 with predive header at beginning | |
34 and postdive header with 0x400 HEADER2OFFSET | |
35 4kB (one erase) has two dives with 4 headers total | |
36 total of 512 kB (with 256 header ids (8 bit)) | |
37 Size is 280 Byte (as of 25.Nov. 2014) | |
38 | |
39 [..] Output to PC / UART is postdive header | |
40 | |
41 [..] Block Protection Lock-Down is to erase logbook only | |
42 | |
43 [..] Timing (see page 137 of LOGBOOK_V3_S25FS-S_00-271247.pdf | |
44 bulk erase is 2 minutes typ., 6 minutes max. | |
45 | |
46 ============================================================================== | |
47 ##### DEMOMODE ##### | |
48 ============================================================================== | |
49 151215: ext_flash_write_settings() is DISABLED! | |
50 | |
51 ============================================================================== | |
52 ##### bug fixes ##### | |
53 ============================================================================== | |
54 150917: end in header and length of sample was one byte too long | |
55 as stated by Jef Driesen email 15.09.2015 | |
56 | |
57 @endverbatim | |
58 ****************************************************************************** | |
59 * @attention | |
60 * | |
61 * <h2><center>© COPYRIGHT(c) 2015 heinrichs weikamp</center></h2> | |
62 * | |
63 ****************************************************************************** | |
64 */ | |
65 | |
66 /* Includes ------------------------------------------------------------------*/ | |
67 #include "stm32f4xx_hal.h" | |
68 #include "externLogbookFlash.h" | |
69 #include "ostc.h" | |
70 #include "settings.h" | |
71 #include "gfx_engine.h" | |
72 | |
73 /* Private types -------------------------------------------------------------*/ | |
74 #define FLASHSTART 0x000000 | |
75 //#define FLASHSTOP 0x01FFFFFF all 32 MB with 4byte addressing | |
76 #define FLASHSTOP 0x00FFFFFF | |
77 //#define FLASHSTOP 0x3FFFFF | |
78 #define RELEASE 1 | |
79 #define HOLDCS 0 | |
80 | |
81 #define HEADER2OFFSET 0x400 | |
82 | |
83 typedef enum{ | |
84 EF_HEADER, | |
85 EF_SAMPLE, | |
86 EF_DEVICEDATA, | |
87 EF_VPMDATA, | |
88 EF_SETTINGS, | |
89 EF_FIRMWARE, | |
90 EF_FIRMWARE2, | |
91 }which_ring_enum; | |
92 | |
93 | |
94 typedef struct{ | |
95 uint8_t IsBusy:1; | |
96 uint8_t IsWriteEnabled:1; | |
97 uint8_t BlockProtect0:1; | |
98 uint8_t BlockProtect1:1; | |
99 uint8_t BlockProtect2:1; | |
100 uint8_t BlockProtect3:1; | |
101 uint8_t IsAutoAddressIncMode:1; | |
102 uint8_t BlockProtectL:1; | |
103 } extFlashStatusUbit8_t; | |
104 | |
105 typedef union{ | |
106 extFlashStatusUbit8_t ub; | |
107 uint8_t uw; | |
108 } extFlashStatusBit8_Type; | |
109 | |
110 | |
111 /* Exported variables --------------------------------------------------------*/ | |
112 | |
113 /* Private variables ---------------------------------------------------------*/ | |
114 | |
115 static uint32_t actualAddress = 0; | |
116 static uint32_t preparedPageAddress = 0; | |
117 static uint32_t closeSectorAddress = 0; | |
118 static uint32_t actualPointerHeader = 0; | |
119 static uint32_t actualPointerSample = 0; | |
120 static uint32_t actualPointerDevicedata = DDSTART; | |
121 static uint32_t actualPointerVPM = 0; | |
122 static uint32_t actualPointerSettings = SETTINGSSTART; | |
123 static uint32_t actualPointerFirmware = 0; | |
124 static uint32_t actualPointerFirmware2 = 0; | |
125 | |
126 /* Private function prototypes -----------------------------------------------*/ | |
127 static void chip_unselect(void); | |
128 static void chip_select(void); | |
129 static void write_spi(uint8_t data, uint8_t unselect_CS_afterwards); | |
130 static uint8_t read_spi(uint8_t unselect_CS_afterwards); | |
131 static void write_address(uint8_t unselect_CS_afterwards); | |
132 static void Error_Handler_extflash(void); | |
133 static void wait_chip_not_busy(void); | |
134 static void ext_flash_incf_address(uint8_t type); | |
135 //void ext_flash_incf_address_ring(void); | |
136 | |
137 static void ext_flash_erase4kB(void); | |
138 static void ext_flash_erase32kB(void); | |
139 static void ext_flash_erase64kB(void); | |
140 static uint8_t ext_flash_erase_if_on_page_start(void); | |
141 | |
142 static void ef_write_block(uint8_t * sendByte, uint32_t length, uint8_t type, uint8_t do_not_erase); | |
143 | |
144 static void ext_flash_read_block(uint8_t *getByte, uint8_t type); | |
145 static void ext_flash_read_block_multi(void *getByte, uint32_t size, uint8_t type); | |
146 static void ext_flash_read_block_stop(void); | |
147 | |
148 static void ef_hw_rough_delay_us(uint32_t delayUs); | |
149 static void ef_erase_64K(uint32_t blocks); | |
150 | |
151 | |
152 /* Exported functions --------------------------------------------------------*/ | |
153 | |
154 void ext_flash_write_firmware(uint8_t *pSample1, uint32_t length1)//, uint8_t *pSample2, uint32_t length2) | |
155 { | |
156 general32to8_Type lengthTransform; | |
157 | |
158 lengthTransform.u32 = length1; | |
159 | |
160 actualPointerFirmware = FWSTART; | |
161 ef_write_block(lengthTransform.u8,4, EF_FIRMWARE, 1); | |
162 ef_write_block(pSample1,length1, EF_FIRMWARE, 1); | |
163 | |
164 // if(length2) | |
165 // ef_write_block(pSample2,length2, EF_FIRMWARE, 1); | |
166 } | |
167 | |
168 uint8_t ext_flash_read_firmware_version(char *text) | |
169 { | |
170 uint32_t backup = actualAddress; | |
171 uint8_t buffer[4]; | |
172 | |
173 // + 4 for length data, see ext_flash_write_firmware | |
174 actualAddress = FWSTART + 4 + 0x10000; | |
175 ext_flash_read_block_start(); | |
176 ext_flash_read_block(&buffer[0], EF_FIRMWARE); | |
177 ext_flash_read_block(&buffer[1], EF_FIRMWARE); | |
178 ext_flash_read_block(&buffer[2], EF_FIRMWARE); | |
179 ext_flash_read_block(&buffer[3], EF_FIRMWARE); | |
180 | |
181 ext_flash_read_block_stop(); | |
182 actualAddress = backup; | |
183 | |
184 uint8_t ptr = 0; | |
185 text[ptr++] = 'V'; | |
186 ptr += gfx_number_to_string(2,0,&text[ptr],buffer[0] & 0x3F); | |
187 text[ptr++] = '.'; | |
188 ptr += gfx_number_to_string(2,0,&text[ptr],buffer[1] & 0x3F); | |
189 text[ptr++] = '.'; | |
190 ptr += gfx_number_to_string(2,0,&text[ptr],buffer[2] & 0x3F); | |
191 text[ptr++] = ' '; | |
192 if(buffer[3]) | |
193 { | |
194 text[ptr++] = 'b'; | |
195 text[ptr++] = 'e'; | |
196 text[ptr++] = 't'; | |
197 text[ptr++] = 'a'; | |
198 text[ptr++] = ' '; | |
199 } | |
200 return ptr; | |
201 } | |
202 | |
203 | |
204 uint32_t ext_flash_read_firmware(uint8_t *pSample1, uint32_t max_length, uint8_t *magicByte) | |
205 { | |
206 uint32_t backup = actualAddress; | |
207 general32to8_Type lengthTransform; | |
208 | |
209 actualAddress = FWSTART; | |
210 ext_flash_read_block_start(); | |
211 | |
212 ext_flash_read_block(&lengthTransform.u8[0], EF_FIRMWARE); | |
213 ext_flash_read_block(&lengthTransform.u8[1], EF_FIRMWARE); | |
214 ext_flash_read_block(&lengthTransform.u8[2], EF_FIRMWARE); | |
215 ext_flash_read_block(&lengthTransform.u8[3], EF_FIRMWARE); | |
216 | |
217 | |
218 if(lengthTransform.u32 == 0xFFFFFFFF) | |
219 { | |
220 lengthTransform.u32 = 0xFFFFFFFF; | |
221 } | |
222 else | |
223 if(lengthTransform.u32 > max_length) | |
224 { | |
225 lengthTransform.u32 = 0xFF000000; | |
226 } | |
227 else | |
228 { | |
229 for(uint32_t i = 0; i<lengthTransform.u32; i++) | |
230 { | |
231 ext_flash_read_block(&pSample1[i], EF_FIRMWARE); | |
232 } | |
233 | |
234 } | |
235 | |
236 ext_flash_read_block_stop(); | |
237 | |
238 if(magicByte) | |
239 { | |
240 *magicByte = pSample1[0x10000 + 0x3E]; // 0x3E == 62 | |
241 } | |
242 | |
243 actualAddress = backup; | |
244 return lengthTransform.u32; | |
245 } | |
246 | |
247 | |
248 void ext_flash_write_firmware2(uint32_t offset, uint8_t *pSample1, uint32_t length1, uint8_t *pSample2, uint32_t length2) | |
249 { | |
250 general32to8_Type lengthTransform, offsetTransform; | |
251 | |
252 lengthTransform.u32 = length1 + length2; | |
253 offsetTransform.u32 = offset; | |
254 | |
255 actualPointerFirmware2 = FWSTART2; | |
256 ef_write_block(lengthTransform.u8,4, EF_FIRMWARE2, 1); | |
257 ef_write_block(offsetTransform.u8,4, EF_FIRMWARE2, 1); | |
258 ef_write_block(pSample1,length1, EF_FIRMWARE2, 1); | |
259 if(length2) | |
260 ef_write_block(pSample2,length2, EF_FIRMWARE2, 1); | |
261 } | |
262 | |
263 | |
264 uint32_t ext_flash_read_firmware2(uint32_t *offset, uint8_t *pSample1, uint32_t max_length1, uint8_t *pSample2, uint32_t max_length2) | |
265 { | |
266 uint32_t backup = actualAddress; | |
267 uint32_t length1, length2; | |
268 general32to8_Type lengthTransform, offsetTransform; | |
269 | |
270 actualAddress = FWSTART2; | |
271 ext_flash_read_block_start(); | |
272 | |
273 ext_flash_read_block(&lengthTransform.u8[0], EF_FIRMWARE2); | |
274 ext_flash_read_block(&lengthTransform.u8[1], EF_FIRMWARE2); | |
275 ext_flash_read_block(&lengthTransform.u8[2], EF_FIRMWARE2); | |
276 ext_flash_read_block(&lengthTransform.u8[3], EF_FIRMWARE2); | |
277 | |
278 ext_flash_read_block(&offsetTransform.u8[0], EF_FIRMWARE2); | |
279 ext_flash_read_block(&offsetTransform.u8[1], EF_FIRMWARE2); | |
280 ext_flash_read_block(&offsetTransform.u8[2], EF_FIRMWARE2); | |
281 ext_flash_read_block(&offsetTransform.u8[3], EF_FIRMWARE2); | |
282 | |
283 *offset = offsetTransform.u32; | |
284 | |
285 if(lengthTransform.u32 == 0xFFFFFFFF) | |
286 { | |
287 lengthTransform.u32 = 0xFFFFFFFF; | |
288 } | |
289 else | |
290 if(lengthTransform.u32 > max_length1 + max_length2) | |
291 { | |
292 lengthTransform.u32 = 0xFF000000; | |
293 } | |
294 else | |
295 { | |
296 if(lengthTransform.u32 < max_length1) | |
297 { | |
298 length1 = lengthTransform.u32; | |
299 length2 = 0; | |
300 } | |
301 else | |
302 { | |
303 length1 = max_length1; | |
304 length2 = lengthTransform.u32 - max_length1; | |
305 } | |
306 | |
307 if(pSample1) | |
308 { | |
309 for(uint32_t i = 0; i<length1; i++) | |
310 { | |
311 ext_flash_read_block(&pSample1[i], EF_FIRMWARE2); | |
312 } | |
313 if(pSample2) | |
314 { | |
315 for(uint32_t i = 0; i<length2; i++) | |
316 { | |
317 ext_flash_read_block(&pSample2[i], EF_FIRMWARE2); | |
318 } | |
319 } | |
320 } | |
321 else if(pSample2) | |
322 { | |
323 actualAddress += length1; | |
324 for(uint32_t i = 0; i<length2; i++) | |
325 { | |
326 ext_flash_read_block(&pSample2[i], EF_FIRMWARE2); | |
327 } | |
328 } | |
329 } | |
330 ext_flash_read_block_stop(); | |
331 actualAddress = backup; | |
332 return lengthTransform.u32; | |
333 } | |
334 | |
335 | |
336 void ext_flash_read_fixed_16_devicedata_blocks_formated_128byte_total(uint8_t *buffer) | |
337 { | |
338 SDeviceLine data[16]; | |
339 uint8_t tempLengthIngnore; | |
340 uint16_t count; | |
341 uint8_t transfer; | |
342 | |
343 RTC_DateTypeDef Sdate; | |
344 RTC_TimeTypeDef Stime; | |
345 | |
346 actualAddress = DDSTART; | |
347 | |
348 ext_flash_read_block_start(); | |
349 ext_flash_read_block(&tempLengthIngnore, EF_DEVICEDATA); | |
350 ext_flash_read_block(&tempLengthIngnore, EF_DEVICEDATA); | |
351 | |
352 ext_flash_read_block_multi((uint8_t *)data,16*3*4, EF_DEVICEDATA); | |
353 ext_flash_read_block_stop(); | |
354 | |
355 count = 0; | |
356 for(int i=0;i<16;i++) | |
357 { | |
358 transfer = (data[i].value_int32 >> 24) & 0xFF; | |
359 buffer[count++] = transfer; | |
360 transfer = (data[i].value_int32 >> 16) & 0xFF; | |
361 buffer[count++] = transfer; | |
362 transfer = (data[i].value_int32 >> 8) & 0xFF; | |
363 buffer[count++] = transfer; | |
364 transfer = (data[i].value_int32) & 0xFF; | |
365 buffer[count++] = transfer; | |
366 | |
367 translateDate(data[i].date_rtc_dr, &Sdate); | |
368 translateTime(data[i].time_rtc_tr, &Stime); | |
369 buffer[count++] = Sdate.Year; | |
370 buffer[count++] = Sdate.Month; | |
371 buffer[count++] = Sdate.Date; | |
372 buffer[count++] = Stime.Hours; | |
373 } | |
374 } | |
375 | |
376 void ext_flash_erase_firmware(void) | |
377 { | |
378 uint32_t size, blocks_64k; | |
379 | |
380 actualAddress = FWSTART; | |
381 size = 1 + FWSTOP - FWSTART; | |
382 blocks_64k = size / 0x10000; | |
383 ef_erase_64K(blocks_64k); | |
384 } | |
385 | |
386 void ext_flash_erase_firmware2(void) | |
387 { | |
388 uint32_t size, blocks_64k; | |
389 | |
390 actualAddress = FWSTART2; | |
391 size = 1 + FWSTOP2 - FWSTART2; | |
392 blocks_64k = size / 0x10000; | |
393 ef_erase_64K(blocks_64k); | |
394 } | |
395 | |
396 | |
397 | |
398 static void ext_flash_erase4kB(void) | |
399 { | |
400 wait_chip_not_busy(); | |
401 write_spi(0x06,RELEASE);/* WREN */ | |
402 write_spi(0x20,HOLDCS);/* sector erase cmd */ | |
403 write_address(RELEASE); | |
404 } | |
405 | |
406 /* be careful - might not work with entire family and other products | |
407 * see page 14 of LOGBOOK_V3_S25FS-S_00-271247.pdf | |
408 */ | |
409 static void ext_flash_erase32kB(void) | |
410 { | |
411 uint32_t actualAddress_backup; | |
412 | |
413 actualAddress_backup = actualAddress; | |
414 actualAddress = 0; | |
415 wait_chip_not_busy(); | |
416 write_spi(0x06,RELEASE);/* WREN */ | |
417 write_spi(0xD8,HOLDCS);/* sector erase cmd */ | |
418 write_address(RELEASE); | |
419 actualAddress = actualAddress_backup; | |
420 } | |
421 | |
422 | |
423 static void ext_flash_erase64kB(void) | |
424 { | |
425 wait_chip_not_busy(); | |
426 write_spi(0x06,RELEASE);/* WREN */ | |
427 write_spi(0xD8,HOLDCS);/* sector erase cmd */ | |
428 write_address(RELEASE); | |
429 } | |
430 | |
431 | |
432 void ext_flash_read_block_start(void) | |
433 { | |
434 wait_chip_not_busy(); | |
435 write_spi(0x03,HOLDCS); /* WREN */ | |
436 write_address(HOLDCS); | |
437 } | |
438 | |
439 /* 4KB, 32KB, 64 KB, not the upper 16 MB with 4 Byte address at the moment */ | |
440 static uint8_t ext_flash_erase_if_on_page_start(void) | |
441 { | |
442 if(actualAddress < 0x00008000) | |
443 { | |
444 /* 4K Byte is 0x1000 */ | |
445 if((actualAddress & 0xFFF) == 0) | |
446 { | |
447 ext_flash_erase4kB(); | |
448 return 1; | |
449 } | |
450 } | |
451 else | |
452 if(actualAddress < 0x00010000) | |
453 { | |
454 /* 32K Byte is only one page */ | |
455 if(actualAddress == 0x00010000) | |
456 { | |
457 ext_flash_erase32kB(); | |
458 return 1; | |
459 } | |
460 } | |
461 else | |
462 { | |
463 /* 64K Byte is 0x10000 */ | |
464 if((actualAddress & 0xFFFF) == 0) | |
465 { | |
466 if(preparedPageAddress == actualAddress) /* has page already been prepared before? (at the moment for samples only) */ | |
467 { | |
468 preparedPageAddress = 0; | |
469 | |
470 } | |
471 else | |
472 { | |
473 ext_flash_erase64kB(); | |
474 } | |
475 return 1; | |
476 } | |
477 } | |
478 | |
479 return 0; | |
480 } | |
481 | |
482 | |
483 static void ext_flash_read_block(uint8_t *getByte, uint8_t type) | |
484 { | |
485 *getByte = read_spi(HOLDCS);/* read data */ | |
486 ext_flash_incf_address(type); | |
487 } | |
488 | |
489 | |
490 static void ext_flash_read_block_multi(void *getByte, uint32_t size, uint8_t type) | |
491 { | |
492 uint8_t *data; | |
493 data = getByte; | |
494 | |
495 for(uint32_t i=0;i<size;i++) | |
496 { | |
497 data[i] = read_spi(HOLDCS);/* read data */ | |
498 ext_flash_incf_address(type); | |
499 } | |
500 } | |
501 | |
502 | |
503 static void ext_flash_read_block_stop(void) | |
504 { | |
505 chip_unselect(); | |
506 } | |
507 | |
508 | |
509 /* Private functions ---------------------------------------------------------*/ | |
510 | |
511 static void ef_write_block(uint8_t * sendByte, uint32_t length, uint8_t type, uint8_t do_not_erase) | |
512 { | |
513 uint32_t remaining_page_size, remaining_length, remaining_space_to_ring_end; | |
514 uint32_t i=0; | |
515 | |
516 if(!length) | |
517 return; | |
518 | |
519 uint32_t ringStart, ringStop; | |
520 | |
521 switch(type) | |
522 { | |
523 case EF_HEADER: | |
524 actualAddress = actualPointerHeader; | |
525 ringStart = HEADERSTART; | |
526 ringStop = HEADERSTOP; | |
527 break; | |
528 case EF_SAMPLE: | |
529 actualAddress = actualPointerSample; | |
530 ringStart = SAMPLESTART; | |
531 ringStop = SAMPLESTOP; | |
532 break; | |
533 case EF_DEVICEDATA: | |
534 actualAddress = actualPointerDevicedata; | |
535 ringStart = DDSTART; | |
536 ringStop = DDSTOP; | |
537 break; | |
538 case EF_VPMDATA: | |
539 actualAddress = actualPointerVPM; | |
540 ringStart = VPMSTART; | |
541 ringStop = VPMSTOP; | |
542 break; | |
543 case EF_SETTINGS: | |
544 actualAddress = actualPointerSettings; | |
545 ringStart = SETTINGSSTART; | |
546 ringStop = SETTINGSSTOP; | |
547 break; | |
548 case EF_FIRMWARE: | |
549 actualAddress = actualPointerFirmware; | |
550 ringStart = FWSTART; | |
551 ringStop = FWSTOP; | |
552 break; | |
553 case EF_FIRMWARE2: | |
554 actualAddress = actualPointerFirmware2; | |
555 ringStart = FWSTART2; | |
556 ringStop = FWSTOP2; | |
557 break; | |
558 default: | |
559 ringStart = FLASHSTART; | |
560 ringStop = FLASHSTOP; | |
561 break; | |
562 } | |
563 /* safety */ | |
564 if(actualAddress < ringStart) | |
565 actualAddress = ringStart; | |
566 | |
567 if(do_not_erase == 0) | |
568 { | |
569 ext_flash_erase_if_on_page_start(); | |
570 } | |
571 | |
572 while( i<length) | |
573 { | |
574 ef_hw_rough_delay_us(5); | |
575 wait_chip_not_busy(); | |
576 write_spi(0x06,RELEASE); /* WREN */ | |
577 write_spi(0x02,HOLDCS); /* write cmd */ | |
578 write_address(HOLDCS); | |
579 | |
580 remaining_length = length - i; | |
581 remaining_page_size = 0xFF - (uint8_t)(actualAddress & 0xFF) +1; | |
582 remaining_space_to_ring_end = ringStop - actualAddress; | |
583 | |
584 if(remaining_length >= 256) | |
585 { | |
586 remaining_length = 255; /* up to 256 bytes may be written in one burst. Last byte is written with release */ | |
587 } | |
588 else | |
589 { | |
590 remaining_length--; /* last byte needed for release */ | |
591 } | |
592 if(remaining_length >= (remaining_page_size) ) /* use 256 byte page and calculate number of bytes left */ | |
593 { | |
594 remaining_length = remaining_page_size - 1; | |
595 } | |
596 if( (remaining_space_to_ring_end >= 256)) | |
597 { | |
598 for(int j=0; j<remaining_length; j++) | |
599 { | |
600 write_spi(sendByte[i],HOLDCS);/* write data */ | |
601 actualAddress++; | |
602 i++; | |
603 } | |
604 } | |
605 /* byte with RELEASE */ | |
606 write_spi(sendByte[i],RELEASE);/* write data */ | |
607 actualAddress++; | |
608 i++; | |
609 | |
610 if(actualAddress > ringStop) | |
611 actualAddress = ringStart; | |
612 | |
613 if(do_not_erase == 0) | |
614 ext_flash_erase_if_on_page_start(); | |
615 } | |
616 switch(type) | |
617 { | |
618 case EF_HEADER: | |
619 actualPointerHeader = actualAddress; | |
620 break; | |
621 case EF_SAMPLE: | |
622 actualPointerSample = actualAddress; | |
623 break; | |
624 case EF_DEVICEDATA: | |
625 actualPointerDevicedata = actualAddress; | |
626 break; | |
627 case EF_VPMDATA: | |
628 actualPointerVPM = actualAddress; | |
629 break; | |
630 case EF_SETTINGS: | |
631 actualPointerSettings = actualAddress; | |
632 break; | |
633 case EF_FIRMWARE: | |
634 actualPointerFirmware = actualAddress; | |
635 break; | |
636 case EF_FIRMWARE2: | |
637 actualPointerFirmware2 = actualAddress; | |
638 break; | |
639 default: | |
640 break; | |
641 } | |
642 } | |
643 | |
644 | |
645 static void ef_erase_64K(uint32_t blocks) | |
646 { | |
647 for(uint32_t i = 0; i < blocks; i++) | |
648 { | |
649 wait_chip_not_busy(); | |
650 write_spi(0x06,RELEASE);/* WREN */ | |
651 write_spi(0xD8,HOLDCS);/* 64k erase cmd */ | |
652 write_address(RELEASE); | |
653 actualAddress += 0x10000; | |
654 HAL_Delay(25); | |
655 } | |
656 } | |
657 | |
658 static void chip_unselect(void) | |
659 { | |
660 HAL_GPIO_WritePin(EXTFLASH_CSB_GPIO_PORT,EXTFLASH_CSB_PIN,GPIO_PIN_SET); // chip select | |
661 } | |
662 | |
663 static void chip_select(void) | |
664 { | |
665 HAL_GPIO_WritePin(EXTFLASH_CSB_GPIO_PORT,EXTFLASH_CSB_PIN,GPIO_PIN_RESET); // chip select | |
666 } | |
667 | |
668 static uint8_t read_spi(uint8_t unselect_CS_afterwards) | |
669 { | |
670 uint8_t byte; | |
671 | |
672 chip_select(); | |
673 | |
674 if(HAL_SPI_Receive(&hspiDisplay, &byte, 1, 10000) != HAL_OK) | |
675 Error_Handler_extflash(); | |
676 | |
677 while (HAL_SPI_GetState(&hspiDisplay) != HAL_SPI_STATE_READY) | |
678 { | |
679 } | |
680 if(unselect_CS_afterwards) | |
681 chip_unselect(); | |
682 | |
683 return byte; | |
684 } | |
685 | |
686 | |
687 static void write_spi(uint8_t data, uint8_t unselect_CS_afterwards) | |
688 { | |
689 chip_select(); | |
690 | |
691 if(HAL_SPI_Transmit(&hspiDisplay, &data, 1, 10000) != HAL_OK) | |
692 Error_Handler_extflash(); | |
693 | |
694 while (HAL_SPI_GetState(&hspiDisplay) != HAL_SPI_STATE_READY) | |
695 { | |
696 } | |
697 if(unselect_CS_afterwards) | |
698 chip_unselect(); | |
699 } | |
700 | |
701 | |
702 static void write_address(uint8_t unselect_CS_afterwards) | |
703 { | |
704 uint8_t hi, med ,lo; | |
705 | |
706 hi = (actualAddress >> 16) & 0xFF; | |
707 med = (actualAddress >> 8) & 0xFF; | |
708 lo = actualAddress & 0xFF; | |
709 | |
710 write_spi(hi, HOLDCS); | |
711 write_spi(med, HOLDCS); | |
712 write_spi(lo, unselect_CS_afterwards); | |
713 } | |
714 | |
715 | |
716 static void wait_chip_not_busy(void) | |
717 { | |
718 uint8_t status; | |
719 | |
720 chip_unselect(); | |
721 | |
722 write_spi(0x05,HOLDCS); /* RDSR */ | |
723 status = read_spi(HOLDCS);/* read status */ | |
724 while(status & 0x01) | |
725 { | |
726 HAL_Delay(1); | |
727 status = read_spi(HOLDCS);/* read status */ | |
728 } | |
729 chip_unselect(); | |
730 } | |
731 | |
732 | |
733 static void ext_flash_incf_address(uint8_t type) | |
734 { | |
735 uint32_t ringStart, ringStop; | |
736 | |
737 actualAddress += 1; | |
738 | |
739 switch(type) | |
740 { | |
741 case EF_HEADER: | |
742 ringStart = HEADERSTART; | |
743 ringStop = HEADERSTOP; | |
744 break; | |
745 case EF_SAMPLE: | |
746 ringStart = SAMPLESTART; | |
747 ringStop = SAMPLESTOP; | |
748 break; | |
749 case EF_DEVICEDATA: | |
750 ringStart = DDSTART; | |
751 ringStop = DDSTOP; | |
752 break; | |
753 case EF_VPMDATA: | |
754 ringStart = VPMSTART; | |
755 ringStop = VPMSTOP; | |
756 break; | |
757 case EF_SETTINGS: | |
758 ringStart = SETTINGSSTART; | |
759 ringStop = SETTINGSSTOP; | |
760 break; | |
761 case EF_FIRMWARE: | |
762 ringStart = FWSTART; | |
763 ringStop = FWSTOP; | |
764 break; | |
765 case EF_FIRMWARE2: | |
766 ringStart = FWSTART2; | |
767 ringStop = FWSTOP2; | |
768 break; | |
769 default: | |
770 ringStart = FLASHSTART; | |
771 ringStop = FLASHSTOP; | |
772 break; | |
773 } | |
774 | |
775 if((actualAddress < ringStart) || (actualAddress > ringStop)) | |
776 actualAddress = ringStart; | |
777 } | |
778 | |
779 static void ef_hw_rough_delay_us(uint32_t delayUs) | |
780 { | |
781 if(!delayUs) | |
782 return; | |
783 delayUs*= 12; | |
784 while(delayUs--); | |
785 return; | |
786 } | |
787 | |
788 static void Error_Handler_extflash(void) | |
789 { | |
790 while(1) | |
791 { | |
792 } | |
793 } | |
794 | |
795 void ext_flash_CloseSector(void) | |
796 { | |
797 uint32_t actualAddressBackup = actualAddress; | |
798 int i=0; | |
799 | |
800 if(closeSectorAddress != 0) | |
801 { | |
802 /* write some dummy bytes to the sector which is currently used for storing samples. This is done to "hide" problem if function is calles again */ | |
803 actualAddress = closeSectorAddress; | |
804 | |
805 wait_chip_not_busy(); | |
806 write_spi(0x06,RELEASE); /* WREN */ | |
807 write_spi(0x02,HOLDCS); /* write cmd */ | |
808 write_address(HOLDCS); | |
809 for(i = 0; i<8; i++) | |
810 { | |
811 write_spi(0xA5,HOLDCS);/* write data */ | |
812 actualAddress++; | |
813 } | |
814 /* byte with RELEASE */ | |
815 write_spi(0xA5,RELEASE);/* write data */ | |
816 actualAddress = actualAddressBackup; | |
817 closeSectorAddress = 0; | |
818 } | |
819 } | |
820 | |
821 | |
822 uint8_t ext_flash_erase_firmware_if_not_empty(void) | |
823 { | |
824 const uint8_t TESTSIZE_FW = 4; | |
825 | |
826 uint8_t data[TESTSIZE_FW]; | |
827 uint8_t notEmpty = 0; | |
828 | |
829 actualAddress = FWSTART; | |
830 ext_flash_read_block_start(); | |
831 for(int i = 0; i < TESTSIZE_FW; i++) | |
832 { | |
833 ext_flash_read_block(&data[i], EF_FIRMWARE); | |
834 if(data[i] != 0xFF) | |
835 notEmpty = 1; | |
836 } | |
837 ext_flash_read_block_stop(); | |
838 | |
839 if(notEmpty) | |
840 { | |
841 ext_flash_erase_firmware(); | |
842 return 1; | |
843 } | |
844 else | |
845 return 0; | |
846 } | |
847 | |
848 uint8_t ext_flash_erase_firmware2_if_not_empty(void) | |
849 { | |
850 const uint8_t TESTSIZE_FW = 4; | |
851 | |
852 uint8_t data[TESTSIZE_FW]; | |
853 uint8_t notEmpty = 0; | |
854 | |
855 actualAddress = FWSTART2; | |
856 ext_flash_read_block_start(); | |
857 for(int i = 0; i < TESTSIZE_FW; i++) | |
858 { | |
859 ext_flash_read_block(&data[i], EF_FIRMWARE2); | |
860 if(data[i] != 0xFF) | |
861 notEmpty = 1; | |
862 } | |
863 ext_flash_read_block_stop(); | |
864 | |
865 if(notEmpty) | |
866 { | |
867 ext_flash_erase_firmware2(); | |
868 return 1; | |
869 } | |
870 else | |
871 return 0; | |
872 } |