Mercurial > public > ostc4
annotate Discovery/Src/externLogbookFlash.c @ 240:625d20070261 div-fixes-5
Improvement SPI stability/recoverability
The core part of this commit comes from careful code reading. The core is the
swap of Scheduler_Request_sync_with_SPI(SPI_SYNC_METHOD_SOFT) and
SPI_Start_single_TxRx_with_Master(). This code is sitting in an if-clause
that is triggered on SPI comms failure. Instead of blindly trying to
communicate again (which will very likely fail again), first try to reset
the comms link, and then try to communicate again. That simply makes
more sense in this case.
This is heavily tested, on 2 simple dives, and 5 very long deco schedules
from the simulator (10+ hour deco's), and a lot of small simulated dives
(upto 2h runtime). Of all these tests, only one long session failed after
9 out of 11h runtime. Analyzing that one failure, suggests that the
RTE is looping in some error handler, which (obviously) results in
a SPI comms failure as a result. I consider this not part of this change.
Additionally, some more cleanup is done in this code.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
author | Jan Mulder <jlmulder@xs4all.nl> |
---|---|
date | Mon, 08 Apr 2019 11:49:13 +0200 |
parents | 2bb1db22b5f5 |
children | 1b9847d40e81 |
rev | line source |
---|---|
38 | 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 #ifndef BOOTLOADER_STANDALONE | |
74 #include "logbook.h" | |
75 #endif | |
76 | |
77 /* Private types -------------------------------------------------------------*/ | |
78 #define FLASHSTART 0x000000 | |
79 //#define FLASHSTOP 0x01FFFFFF all 32 MB with 4byte addressing | |
80 #define FLASHSTOP 0x00FFFFFF | |
81 //#define FLASHSTOP 0x3FFFFF | |
82 #define RELEASE 1 | |
83 #define HOLDCS 0 | |
84 | |
85 #define HEADER2OFFSET 0x400 | |
86 | |
87 typedef enum{ | |
88 EF_HEADER, | |
89 EF_SAMPLE, | |
90 EF_DEVICEDATA, | |
91 EF_VPMDATA, | |
92 EF_SETTINGS, | |
93 EF_FIRMWARE, | |
94 EF_FIRMWARE2, | |
95 }which_ring_enum; | |
96 | |
97 | |
98 typedef struct{ | |
99 uint8_t IsBusy:1; | |
100 uint8_t IsWriteEnabled:1; | |
101 uint8_t BlockProtect0:1; | |
102 uint8_t BlockProtect1:1; | |
103 uint8_t BlockProtect2:1; | |
104 uint8_t BlockProtect3:1; | |
105 uint8_t IsAutoAddressIncMode:1; | |
106 uint8_t BlockProtectL:1; | |
107 } extFlashStatusUbit8_t; | |
108 | |
109 typedef union{ | |
110 extFlashStatusUbit8_t ub; | |
111 uint8_t uw; | |
112 } extFlashStatusBit8_Type; | |
113 | |
114 | |
115 /* Exported variables --------------------------------------------------------*/ | |
116 | |
117 /* Private variables ---------------------------------------------------------*/ | |
118 uint32_t actualAddress = 0; | |
119 uint32_t entryPoint = 0; | |
120 | |
121 uint32_t actualPointerHeader = 0; | |
122 uint32_t actualPointerSample = 0; | |
123 uint32_t LengthLeftSampleRead = 0; | |
124 uint32_t actualPointerDevicedata = 0; | |
125 uint32_t actualPointerVPM = 0; | |
126 uint32_t actualPointerSettings = 0; | |
127 uint32_t actualPointerFirmware = 0; | |
128 uint32_t actualPointerFirmware2 = 0; | |
129 | |
130 /* Private function prototypes -----------------------------------------------*/ | |
131 void chip_unselect(void); | |
132 void chip_select(void); | |
133 void error_led_on(void); | |
134 void error_led_off(void); | |
135 | |
136 void write_spi(uint8_t data, uint8_t unselect_CS_afterwards); | |
137 uint8_t read_spi(uint8_t unselect_CS_afterwards); | |
138 void write_address(uint8_t unselect_CS_afterwards); | |
139 static void Error_Handler_extflash(void); | |
140 static void wait_chip_not_busy(void); | |
141 void ext_flash_incf_address(uint8_t type); | |
142 //void ext_flash_incf_address_ring(void); | |
143 void ext_flash_decf_address_ring(uint8_t type); | |
144 | |
145 void ext_flash_erase4kB(void); | |
146 void ext_flash_erase32kB(void); | |
147 void ext_flash_erase64kB(void); | |
148 uint8_t ext_flash_erase_if_on_page_start(void); | |
149 | |
150 void ef_write_block(uint8_t * sendByte, uint32_t length, uint8_t type, uint8_t do_not_erase); | |
151 | |
152 void ext_flash_read_block(uint8_t *getByte, uint8_t type); | |
153 void ext_flash_read_block_multi(void *getByte, uint32_t size, uint8_t type); | |
154 void ext_flash_read_block_stop(void); | |
155 | |
156 static void ef_hw_rough_delay_us(uint32_t delayUs); | |
157 static void ef_erase_64K(uint32_t blocks); | |
158 | |
159 void ext_flash_overwrite_sample_without_erase(uint8_t *pSample, uint16_t length); | |
160 | |
161 void ext_flash_disable_protection(void); | |
162 | |
163 _Bool ext_flash_test_remaining_space_of_page_empty(uint32_t pointer, uint16_t length); | |
164 void ext_flash_set_to_begin_of_next_page(uint32_t *pointer, uint8_t type); | |
165 | |
166 | |
167 /* Exported functions --------------------------------------------------------*/ | |
168 | |
169 void ext_flash_write_firmware(uint8_t *pSample1, uint32_t length1)//, uint8_t *pSample2, uint32_t length2) | |
170 { | |
171 general32to8_Type lengthTransform; | |
172 | |
173 lengthTransform.u32 = length1; | |
174 | |
175 actualPointerFirmware = FWSTART; | |
176 ef_write_block(lengthTransform.u8,4, EF_FIRMWARE, 1); | |
177 ef_write_block(pSample1,length1, EF_FIRMWARE, 1); | |
178 | |
179 // if(length2) | |
180 // ef_write_block(pSample2,length2, EF_FIRMWARE, 1); | |
181 } | |
182 | |
183 uint8_t ext_flash_read_firmware_version(char *text) | |
184 { | |
185 uint32_t backup = actualAddress; | |
186 uint8_t buffer[4]; | |
187 | |
188 // + 4 for length data, see ext_flash_write_firmware | |
189 actualAddress = FWSTART + 4 + 0x10000; | |
190 ext_flash_read_block_start(); | |
191 ext_flash_read_block(&buffer[0], EF_FIRMWARE); | |
192 ext_flash_read_block(&buffer[1], EF_FIRMWARE); | |
193 ext_flash_read_block(&buffer[2], EF_FIRMWARE); | |
194 ext_flash_read_block(&buffer[3], EF_FIRMWARE); | |
195 | |
196 ext_flash_read_block_stop(); | |
197 actualAddress = backup; | |
198 | |
199 uint8_t ptr = 0; | |
200 text[ptr++] = 'V'; | |
201 ptr += gfx_number_to_string(2,0,&text[ptr],buffer[0] & 0x3F); | |
202 text[ptr++] = '.'; | |
203 ptr += gfx_number_to_string(2,0,&text[ptr],buffer[1] & 0x3F); | |
204 text[ptr++] = '.'; | |
205 ptr += gfx_number_to_string(2,0,&text[ptr],buffer[2] & 0x3F); | |
206 text[ptr++] = ' '; | |
207 if(buffer[3]) | |
208 { | |
209 text[ptr++] = 'b'; | |
210 text[ptr++] = 'e'; | |
211 text[ptr++] = 't'; | |
212 text[ptr++] = 'a'; | |
213 text[ptr++] = ' '; | |
214 } | |
215 return ptr; | |
216 } | |
217 | |
218 | |
219 uint32_t ext_flash_read_firmware(uint8_t *pSample1, uint32_t max_length, uint8_t *magicByte) | |
220 { | |
221 uint32_t backup = actualAddress; | |
222 general32to8_Type lengthTransform; | |
223 | |
224 actualAddress = FWSTART; | |
225 ext_flash_read_block_start(); | |
226 | |
227 ext_flash_read_block(&lengthTransform.u8[0], EF_FIRMWARE); | |
228 ext_flash_read_block(&lengthTransform.u8[1], EF_FIRMWARE); | |
229 ext_flash_read_block(&lengthTransform.u8[2], EF_FIRMWARE); | |
230 ext_flash_read_block(&lengthTransform.u8[3], EF_FIRMWARE); | |
231 | |
232 | |
233 if(lengthTransform.u32 == 0xFFFFFFFF) | |
234 { | |
235 lengthTransform.u32 = 0xFFFFFFFF; | |
236 } | |
237 else | |
238 if(lengthTransform.u32 > max_length) | |
239 { | |
240 lengthTransform.u32 = 0xFF000000; | |
241 } | |
242 else | |
243 { | |
244 for(uint32_t i = 0; i<lengthTransform.u32; i++) | |
245 { | |
246 ext_flash_read_block(&pSample1[i], EF_FIRMWARE); | |
247 } | |
248 | |
249 } | |
250 | |
251 ext_flash_read_block_stop(); | |
252 | |
253 if(magicByte) | |
254 { | |
255 *magicByte = pSample1[0x10000 + 0x3E]; // 0x3E == 62 | |
256 } | |
257 | |
258 actualAddress = backup; | |
259 return lengthTransform.u32; | |
260 } | |
261 | |
262 | |
263 void ext_flash_write_firmware2(uint32_t offset, uint8_t *pSample1, uint32_t length1, uint8_t *pSample2, uint32_t length2) | |
264 { | |
265 general32to8_Type lengthTransform, offsetTransform; | |
266 | |
267 lengthTransform.u32 = length1 + length2; | |
268 offsetTransform.u32 = offset; | |
269 | |
270 actualPointerFirmware2 = FWSTART2; | |
271 ef_write_block(lengthTransform.u8,4, EF_FIRMWARE2, 1); | |
272 ef_write_block(offsetTransform.u8,4, EF_FIRMWARE2, 1); | |
273 ef_write_block(pSample1,length1, EF_FIRMWARE2, 1); | |
274 if(length2) | |
275 ef_write_block(pSample2,length2, EF_FIRMWARE2, 1); | |
276 } | |
277 | |
278 | |
279 uint32_t ext_flash_read_firmware2(uint32_t *offset, uint8_t *pSample1, uint32_t max_length1, uint8_t *pSample2, uint32_t max_length2) | |
280 { | |
281 uint32_t backup = actualAddress; | |
282 uint32_t length1, length2; | |
283 general32to8_Type lengthTransform, offsetTransform; | |
284 | |
285 actualAddress = FWSTART2; | |
286 ext_flash_read_block_start(); | |
287 | |
288 ext_flash_read_block(&lengthTransform.u8[0], EF_FIRMWARE2); | |
289 ext_flash_read_block(&lengthTransform.u8[1], EF_FIRMWARE2); | |
290 ext_flash_read_block(&lengthTransform.u8[2], EF_FIRMWARE2); | |
291 ext_flash_read_block(&lengthTransform.u8[3], EF_FIRMWARE2); | |
292 | |
293 ext_flash_read_block(&offsetTransform.u8[0], EF_FIRMWARE2); | |
294 ext_flash_read_block(&offsetTransform.u8[1], EF_FIRMWARE2); | |
295 ext_flash_read_block(&offsetTransform.u8[2], EF_FIRMWARE2); | |
296 ext_flash_read_block(&offsetTransform.u8[3], EF_FIRMWARE2); | |
297 | |
298 *offset = offsetTransform.u32; | |
299 | |
300 if(lengthTransform.u32 == 0xFFFFFFFF) | |
301 { | |
302 lengthTransform.u32 = 0xFFFFFFFF; | |
303 } | |
304 else | |
305 if(lengthTransform.u32 > max_length1 + max_length2) | |
306 { | |
307 lengthTransform.u32 = 0xFF000000; | |
308 } | |
309 else | |
310 { | |
311 if(lengthTransform.u32 < max_length1) | |
312 { | |
313 length1 = lengthTransform.u32; | |
314 length2 = 0; | |
315 } | |
316 else | |
317 { | |
318 length1 = max_length1; | |
319 length2 = lengthTransform.u32 - max_length1; | |
320 } | |
321 | |
322 if(pSample1) | |
323 { | |
324 for(uint32_t i = 0; i<length1; i++) | |
325 { | |
326 ext_flash_read_block(&pSample1[i], EF_FIRMWARE2); | |
327 } | |
328 if(pSample2) | |
329 { | |
330 for(uint32_t i = 0; i<length2; i++) | |
331 { | |
332 ext_flash_read_block(&pSample2[i], EF_FIRMWARE2); | |
333 } | |
334 } | |
335 } | |
336 else if(pSample2) | |
337 { | |
338 actualAddress += length1; | |
339 for(uint32_t i = 0; i<length2; i++) | |
340 { | |
341 ext_flash_read_block(&pSample2[i], EF_FIRMWARE2); | |
342 } | |
343 } | |
344 } | |
345 ext_flash_read_block_stop(); | |
346 actualAddress = backup; | |
347 return lengthTransform.u32; | |
348 } | |
349 | |
350 | |
351 void ext_flash_read_fixed_16_devicedata_blocks_formated_128byte_total(uint8_t *buffer) | |
352 { | |
353 SDeviceLine data[16]; | |
354 uint8_t tempLengthIngnore; | |
355 uint16_t count; | |
356 uint8_t transfer; | |
357 | |
358 RTC_DateTypeDef Sdate; | |
359 RTC_TimeTypeDef Stime; | |
360 | |
361 actualAddress = DDSTART; | |
362 | |
363 ext_flash_read_block_start(); | |
364 ext_flash_read_block(&tempLengthIngnore, EF_DEVICEDATA); | |
365 ext_flash_read_block(&tempLengthIngnore, EF_DEVICEDATA); | |
366 | |
367 ext_flash_read_block_multi((uint8_t *)data,16*3*4, EF_DEVICEDATA); | |
368 ext_flash_read_block_stop(); | |
369 | |
370 count = 0; | |
371 for(int i=0;i<16;i++) | |
372 { | |
373 transfer = (data[i].value_int32 >> 24) & 0xFF; | |
374 buffer[count++] = transfer; | |
375 transfer = (data[i].value_int32 >> 16) & 0xFF; | |
376 buffer[count++] = transfer; | |
377 transfer = (data[i].value_int32 >> 8) & 0xFF; | |
378 buffer[count++] = transfer; | |
379 transfer = (data[i].value_int32) & 0xFF; | |
380 buffer[count++] = transfer; | |
381 | |
382 translateDate(data[i].date_rtc_dr, &Sdate); | |
383 translateTime(data[i].time_rtc_tr, &Stime); | |
384 buffer[count++] = Sdate.Year; | |
385 buffer[count++] = Sdate.Month; | |
386 buffer[count++] = Sdate.Date; | |
387 buffer[count++] = Stime.Hours; | |
388 } | |
389 } | |
390 | |
391 | |
392 #ifndef BOOTLOADER_STANDALONE | |
393 | |
394 void ext_flash_write_devicedata(void) | |
395 { | |
396 uint8_t *pData; | |
397 const uint16_t length = sizeof(SDevice); | |
398 uint8_t length_lo, length_hi; | |
399 uint8_t dataLength[2] = { 0 }; | |
400 | |
401 ext_flash_disable_protection(); | |
402 | |
403 pData = (uint8_t *)stateDeviceGetPointer(); | |
404 | |
405 actualPointerDevicedata = DDSTART; | |
406 | |
407 length_lo = (uint8_t)(length & 0xFF); | |
408 length_hi = (uint8_t)(length >> 8); | |
409 dataLength[0] = length_lo; | |
410 dataLength[1] = length_hi; | |
411 | |
412 ef_write_block(dataLength,2, EF_DEVICEDATA, 0); | |
413 ef_write_block(pData,length, EF_DEVICEDATA, 0); | |
414 } | |
415 | |
416 | |
417 uint16_t ext_flash_read_devicedata(uint8_t *buffer, uint16_t max_length) | |
418 { | |
419 uint16_t length; | |
420 uint8_t length_lo, length_hi; | |
421 | |
422 actualAddress = DDSTART; | |
423 | |
424 ext_flash_read_block_start(); | |
425 ext_flash_read_block(&length_lo, EF_DEVICEDATA); | |
426 ext_flash_read_block(&length_hi, EF_DEVICEDATA); | |
427 | |
428 length = (length_hi * 256) + length_lo; | |
429 | |
430 if(length > max_length) | |
431 return 0; | |
432 | |
433 ext_flash_read_block_multi(buffer,length,EF_DEVICEDATA); | |
434 ext_flash_read_block_stop(); | |
435 | |
436 return length; | |
437 } | |
438 | |
439 | |
440 void ext_flash_write_vpm(SVpm *vpmInput) | |
441 { | |
442 uint8_t *pData; | |
443 const uint16_t length = sizeof(SVpm); | |
444 | |
445 uint8_t length_lo, length_hi; | |
446 uint8_t dataLength[2] = { 0 }; | |
447 | |
448 pData = (uint8_t *)vpmInput; | |
449 | |
450 actualPointerVPM = VPMSTART; | |
451 | |
452 length_lo = (uint8_t)(length & 0xFF); | |
453 length_hi = (uint8_t)(length >> 8); | |
454 dataLength[0] = length_lo; | |
455 dataLength[1] = length_hi; | |
456 | |
457 ef_write_block(dataLength,2, EF_VPMDATA, 0); | |
458 ef_write_block(pData,length, EF_VPMDATA, 0); | |
459 } | |
460 | |
461 | |
462 int ext_flash_read_vpm(SVpm *vpmOutput) | |
463 { | |
464 uint8_t *pData; | |
465 const uint16_t length = sizeof(SVpm); | |
466 uint8_t length_lo, length_hi; | |
467 int output; | |
468 | |
469 actualAddress = VPMSTART; | |
470 | |
471 ext_flash_read_block_start(); | |
472 ext_flash_read_block(&length_lo, EF_VPMDATA); | |
473 ext_flash_read_block(&length_hi, EF_VPMDATA); | |
474 if((length_lo == (uint8_t)(length & 0xFF)) | |
475 &&(length_hi == (uint8_t)(length >> 8))) | |
476 { | |
477 pData = (uint8_t *)vpmOutput; | |
478 for(uint16_t i = 0; i < length; i++) | |
479 ext_flash_read_block(&pData[i], EF_VPMDATA); | |
480 output = length; | |
481 } | |
482 else | |
483 output = 0; | |
484 | |
485 ext_flash_read_block_stop(); | |
486 return output; | |
487 } | |
488 | |
489 #ifdef DEMOMODE | |
490 void ext_flash_write_settings(void) | |
491 { | |
492 return; | |
493 } | |
494 #else | |
495 void ext_flash_write_settings(void) | |
496 { | |
497 uint8_t *pData; | |
498 const uint16_t length = sizeof(SSettings); | |
499 uint8_t length_lo, length_hi; | |
500 uint8_t dataLength[2] = { 0 }; | |
501 | |
502 ext_flash_disable_protection(); | |
503 | |
504 if(stateRealGetPointer()->lastKnownBatteryPercentage) | |
505 { | |
506 settingsGetPointer()->lastKnownBatteryPercentage = stateRealGetPointer()->lastKnownBatteryPercentage; | |
507 } | |
508 settingsGetPointer()->backup_localtime_rtc_tr = stateRealGetPointer()->lifeData.timeBinaryFormat; | |
509 settingsGetPointer()->backup_localtime_rtc_dr = stateRealGetPointer()->lifeData.dateBinaryFormat; | |
510 | |
511 pData = (uint8_t *)settingsGetPointer(); | |
512 | |
513 actualPointerSettings = SETTINGSSTART; | |
514 | |
515 length_lo = (uint8_t)(length & 0xFF); | |
516 length_hi = (uint8_t)(length >> 8); | |
517 dataLength[0] = length_lo; | |
518 dataLength[1] = length_hi; | |
519 | |
520 ef_write_block(dataLength,2, EF_SETTINGS, 0); | |
521 ef_write_block(pData,length, EF_SETTINGS, 0); | |
522 // ext_flash_enable_protection(); | |
523 } | |
524 #endif | |
525 | |
526 | |
527 /* CHANGES 150929 hw | |
528 * this now allows to read old settings too | |
529 * but make sure that everything is fixed in | |
530 * set_new_settings_missing_in_ext_flash | |
531 * new settings should be fine as they are added | |
532 * and loaded before calling this function | |
533 */ | |
534 uint8_t ext_flash_read_settings(void) | |
535 { | |
536 uint8_t returnValue = HAL_BUSY; | |
537 uint8_t *pData; | |
538 const uint16_t lengthStandardNow = sizeof(SSettings); | |
539 uint8_t length_lo, length_hi; | |
540 uint16_t lengthOnEEPROM; | |
541 uint32_t header; | |
542 SSettings *pSettings = settingsGetPointer(); | |
543 | |
544 actualAddress = SETTINGSSTART; | |
545 | |
546 ext_flash_read_block_start(); | |
547 ext_flash_read_block(&length_lo, EF_SETTINGS); | |
548 ext_flash_read_block(&length_hi, EF_SETTINGS); | |
549 | |
550 lengthOnEEPROM = length_hi * 256; | |
551 lengthOnEEPROM += length_lo; | |
552 if(lengthOnEEPROM <= lengthStandardNow) | |
553 { | |
554 ext_flash_read_block_multi(&header, 4, EF_SETTINGS); | |
555 if((header <= pSettings->header) && (header >= pSettings->updateSettingsAllowedFromHeader)) | |
556 { | |
557 returnValue = HAL_OK; | |
558 pSettings->header = header; | |
559 pData = (uint8_t *)pSettings + 4; /* header */ | |
560 for(uint16_t i = 0; i < (lengthOnEEPROM-4); i++) | |
561 ext_flash_read_block(&pData[i], EF_SETTINGS); | |
562 } | |
563 else | |
564 { | |
565 returnValue = HAL_ERROR; | |
566 } | |
567 } | |
568 ext_flash_read_block_stop(); | |
569 return returnValue; | |
570 } | |
571 | |
572 | |
573 | |
574 | |
575 /* ext_flash_start_new_dive_log_and_set_actualPointerSample | |
576 * prepares the write sample pointer | |
577 * to be used by ext_flash_write_sample() | |
578 * to be set in the * pHeaderPreDive | |
579 * for write with ext_flash_create_new_dive_log() and ext_flash_close_new_dive_log() | |
580 */ | |
581 void ext_flash_start_new_dive_log_and_set_actualPointerSample(uint8_t *pHeaderPreDive) | |
582 { | |
583 convert_Type data; | |
584 SSettings *settings = settingsGetPointer(); | |
585 | |
586 /* new 5. Jan. 2015 */ | |
587 actualPointerSample = settings->logFlashNextSampleStartAddress; | |
588 | |
589 if(!ext_flash_test_remaining_space_of_page_empty(actualPointerSample, 4)) | |
590 ext_flash_set_to_begin_of_next_page(&actualPointerSample, EF_SAMPLE); | |
591 | |
592 if((actualPointerSample < SAMPLESTART) || (actualPointerSample > SAMPLESTOP)) | |
593 actualPointerSample = SAMPLESTART; | |
594 | |
595 data.u32bit = actualPointerSample; | |
596 pHeaderPreDive[2] = data.u8bit.byteLow; | |
597 pHeaderPreDive[3] = data.u8bit.byteMidLow; | |
598 pHeaderPreDive[4] = data.u8bit.byteMidHigh; | |
599 /* to start sample writing and header etc. pp. */ | |
600 ext_flash_disable_protection_for_logbook(); | |
601 } | |
602 | |
603 | |
604 /* ext_flash_create_new_dive_log | |
605 * uses the first header without HEADER2OFFSET | |
606 * for the header it is not important to be complete | |
607 * and can be reconstructed | |
608 * ext_flash_start_new_dive_log_and_set_actualPointerSample() | |
609 * has to be called before to set the actualPointerSample | |
610 * in the header | |
611 * the following func writes to header to the ext_flash | |
612 */ | |
613 void ext_flash_create_new_dive_log(uint8_t *pHeaderPreDive) | |
614 { | |
615 SSettings *settings; | |
616 uint8_t id, id_next; | |
617 uint8_t header1, header2; | |
618 | |
619 settings = settingsGetPointer(); | |
620 id = settings->lastDiveLogId; | |
621 | |
622 actualAddress = HEADERSTART + (0x800 * id); | |
623 ext_flash_read_block_start(); | |
624 ext_flash_read_block(&header1, EF_SAMPLE); | |
625 ext_flash_read_block(&header2, EF_SAMPLE); | |
626 ext_flash_read_block_stop(); | |
627 | |
628 if((header1 == 0xFA) && (header2 == 0xFA)) | |
629 { | |
630 id += 1; /* 0-255, auto rollover */ | |
631 if(id & 1) | |
632 { | |
633 actualAddress = HEADERSTART + (0x800 * id); | |
634 ext_flash_read_block_start(); | |
635 ext_flash_read_block(&header1, EF_SAMPLE); | |
636 ext_flash_read_block(&header2, EF_SAMPLE); | |
637 ext_flash_read_block_stop(); | |
638 if((header1 == 0xFA) && (header2 == 0xFA)) | |
639 id += 1; | |
640 } | |
641 } | |
642 else | |
643 { | |
644 id = 0; | |
645 } | |
646 | |
647 /* delete next header */ | |
648 id_next = id + 1; | |
649 actualPointerHeader = HEADERSTART + (0x800 * id_next); | |
650 ef_write_block(0,0, EF_HEADER, 0); | |
651 | |
652 settings->lastDiveLogId = id; | |
653 actualPointerHeader = HEADERSTART + (0x800 * id); | |
654 | |
655 if(pHeaderPreDive != 0) | |
656 ef_write_block(pHeaderPreDive,HEADERSIZE, EF_HEADER, 0); | |
657 } | |
658 | |
659 | |
660 void ext_flash_close_new_dive_log(uint8_t *pHeaderPostDive ) | |
661 { | |
662 SSettings * settings = settingsGetPointer(); | |
663 uint8_t id; | |
664 convert_Type startAddress; | |
665 convert_Type data; | |
666 uint32_t backup; | |
667 | |
668 uint8_t sampleData[3]; | |
669 actualAddress = actualPointerSample; | |
670 sampleData[0] = 0xFD; | |
671 sampleData[1] = 0xFD; | |
672 ext_flash_write_sample(sampleData, 2); | |
673 | |
674 /* end of sample data, pointing to the last sample 0xFD | |
675 */ | |
676 actualAddress = actualPointerSample; // change hw 17.09.2015 | |
677 ext_flash_decf_address_ring(EF_SAMPLE); // 17.09.2015: this decf actualAddress only!! | |
678 actualPointerSample = actualAddress; // change hw 17.09.2015 | |
679 data.u32bit = actualPointerSample; | |
680 | |
681 pHeaderPostDive[5] = data.u8bit.byteLow; | |
682 pHeaderPostDive[6] = data.u8bit.byteMidLow; | |
683 pHeaderPostDive[7] = data.u8bit.byteMidHigh; | |
684 | |
685 /* take data written before, calculate length and write | |
686 SLogbookHeader has different order: length (byte# 8,9,10) prior to profile version (byte# 11) | |
687 */ | |
688 startAddress.u8bit.byteLow = pHeaderPostDive[2]; | |
689 startAddress.u8bit.byteMidLow = pHeaderPostDive[3]; | |
690 startAddress.u8bit.byteMidHigh = pHeaderPostDive[4]; | |
691 startAddress.u8bit.byteHigh = 0; | |
692 | |
693 if(startAddress.u32bit < actualPointerSample) | |
694 data.u32bit = 1 + actualPointerSample - startAddress.u32bit; | |
695 else | |
696 data.u32bit = 2 + (actualPointerSample - SAMPLESTART) + (SAMPLESTOP - startAddress.u32bit); | |
697 | |
698 pHeaderPostDive[8] = data.u8bit.byteLow; | |
699 pHeaderPostDive[9] = data.u8bit.byteMidLow; | |
700 pHeaderPostDive[10] = data.u8bit.byteMidHigh; | |
701 | |
702 /* set id and write post-dive-header | |
703 */ | |
704 id = settings->lastDiveLogId; | |
705 actualPointerHeader = HEADERSTART + (0x800 * id) + HEADER2OFFSET; | |
706 | |
707 ef_write_block(pHeaderPostDive,HEADERSIZE, EF_HEADER, 0); | |
708 | |
709 /* write length at beginning of sample | |
710 and write proper beginning for next dive to actualPointerSample | |
711 */ | |
712 backup = actualPointerSample; | |
713 actualPointerSample = startAddress.u32bit; // is still 0xFF | |
714 sampleData[0] = data.u8bit.byteLow; | |
715 sampleData[1] = data.u8bit.byteMidLow; | |
716 sampleData[2] = data.u8bit.byteMidHigh; | |
717 ext_flash_overwrite_sample_without_erase(sampleData, 3); | |
718 | |
719 actualAddress = backup; | |
720 ext_flash_incf_address(EF_SAMPLE); | |
721 actualPointerSample = actualAddress; | |
722 ext_flash_enable_protection(); | |
723 } | |
724 | |
725 | |
726 void ext_flash_write_sample(uint8_t *pSample, uint16_t length) | |
727 { | |
728 ef_write_block(pSample,length, EF_SAMPLE, 0); | |
729 | |
730 SSettings *settings = settingsGetPointer(); | |
731 settings->logFlashNextSampleStartAddress = actualPointerSample; | |
732 } | |
733 | |
734 void ext_flash_overwrite_sample_without_erase(uint8_t *pSample, uint16_t length) | |
735 { | |
736 ef_write_block(pSample,length, EF_SAMPLE, 1); | |
737 } | |
738 | |
739 | |
740 uint8_t ext_flash_count_dive_headers(void) | |
741 { | |
742 uint8_t id = 0; | |
743 uint8_t counter = 0; | |
744 uint16_t headerStartData = 0x0000; | |
745 | |
746 id = settingsGetPointer()->lastDiveLogId; | |
747 | |
748 do | |
749 { | |
750 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; | |
751 ext_flash_read_block_start(); | |
752 ext_flash_read_block_multi((uint8_t *)&headerStartData, 2, EF_HEADER); | |
753 ext_flash_read_block_stop(); | |
754 counter++; | |
755 id -=1; | |
756 } while((headerStartData == 0xFAFA) && (counter < 255)); | |
757 return (counter - 1); | |
758 } | |
759 | |
760 | |
761 void ext_flash_read_dive_header(uint8_t *pHeaderToFill, uint8_t StepBackwards) | |
762 { | |
763 SSettings *settings; | |
764 uint8_t id; | |
765 uint16_t i; | |
766 | |
767 settings = settingsGetPointer(); | |
768 id = settings->lastDiveLogId; | |
769 id -= StepBackwards; /* 0-255, auto rollover */ | |
770 | |
771 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; | |
772 ext_flash_read_block_start(); | |
773 for(i = 0; i < HEADERSIZE; i++) | |
774 ext_flash_read_block(&pHeaderToFill[i], EF_HEADER); | |
775 ext_flash_read_block_stop(); | |
776 | |
777 } | |
778 | |
779 void ext_flash_read_dive_header2(uint8_t *pHeaderToFill, uint8_t id, _Bool bOffset) | |
780 { | |
781 | |
782 uint16_t i; | |
783 actualAddress = HEADERSTART + (0x800 * id) ; | |
784 | |
785 if(bOffset) | |
786 actualAddress += HEADER2OFFSET; | |
787 ext_flash_read_block_start(); | |
788 for(i = 0; i < HEADERSIZE; i++) | |
789 ext_flash_read_block(&pHeaderToFill[i], EF_HEADER); | |
790 ext_flash_read_block_stop(); | |
791 } | |
792 | |
793 | |
794 uint32_t ext_flash_read_dive_raw_with_double_header_1K(uint8_t *data, uint32_t max_size, uint8_t StepBackwards) | |
795 { | |
796 if(max_size < 0x800) | |
797 return 0; | |
798 | |
799 uint8_t id; | |
800 convert_Type dataStart, dataEnd; | |
801 uint32_t LengthAll = 0; | |
802 | |
803 id = settingsGetPointer()->lastDiveLogId; | |
804 id -= StepBackwards; /* 0-255, auto rollover */ | |
805 | |
806 // clear data | |
807 for(int i=0;i<0x800;i++) | |
808 data[i] = 0xFF; | |
809 | |
810 // copy primary/pre-dive | |
811 actualAddress = HEADERSTART + (0x800 * id); | |
812 ext_flash_read_block_start(); | |
813 for(int i = 0; i < HEADERSIZE; i++) | |
814 ext_flash_read_block(&data[i], EF_HEADER); | |
815 ext_flash_read_block_stop(); | |
816 | |
817 // copy main/secondary/post-dive | |
818 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; | |
819 ext_flash_read_block_start(); | |
820 for(int i = 0x400; i < HEADERSIZE+0x400; i++) | |
821 ext_flash_read_block(&data[i], EF_HEADER); | |
822 ext_flash_read_block_stop(); | |
823 | |
824 // data | |
825 | |
826 dataStart.u8bit.byteHigh = 0; | |
827 dataStart.u8bit.byteLow = data[0x402]; | |
828 dataStart.u8bit.byteMidLow = data[0x403]; | |
829 dataStart.u8bit.byteMidHigh = data[0x404]; | |
830 | |
831 dataEnd.u8bit.byteHigh = 0; | |
832 dataEnd.u8bit.byteLow = data[0x405]; | |
833 dataEnd.u8bit.byteMidLow = data[0x406]; | |
834 dataEnd.u8bit.byteMidHigh = data[0x407]; | |
835 | |
836 actualPointerSample = dataStart.u32bit; | |
837 if(dataEnd.u32bit >= dataStart.u32bit) | |
838 LengthAll = 1 + dataEnd.u32bit - dataStart.u32bit; | |
839 else | |
840 LengthAll = 2 + (dataStart.u32bit - SAMPLESTART) + (SAMPLESTOP - dataEnd.u32bit); | |
841 | |
842 LengthAll += 0x800; | |
843 | |
844 if(LengthAll > max_size) | |
845 return 0x800; | |
846 | |
847 actualAddress = actualPointerSample; | |
848 ext_flash_read_block_start(); | |
849 for(uint32_t i = 0x800; i < LengthAll; i++) | |
850 ext_flash_read_block(&data[i], EF_SAMPLE); | |
851 ext_flash_read_block_stop(); | |
852 return LengthAll; | |
853 } | |
854 | |
855 void ext_flash_write_dive_raw_with_double_header_1K(uint8_t *data, uint32_t length) | |
856 { | |
857 convert_Type dataStart, dataEnd; | |
858 SLogbookHeader headerTemp; | |
859 | |
860 // set actualPointerSample and get pointer to sample storage and disable flash write protect | |
861 ext_flash_start_new_dive_log_and_set_actualPointerSample((uint8_t *)&headerTemp); | |
862 | |
863 dataStart.u8bit.byteHigh = 0; | |
864 dataStart.u8bit.byteLow = headerTemp.pBeginProfileData[0]; | |
865 dataStart.u8bit.byteMidLow = headerTemp.pBeginProfileData[1]; | |
866 dataStart.u8bit.byteMidHigh = headerTemp.pBeginProfileData[2]; | |
867 | |
868 dataEnd.u32bit = dataStart.u32bit + length - 0x801; | |
869 if(dataEnd.u32bit > SAMPLESTOP) | |
870 dataEnd.u32bit -= SAMPLESTOP + SAMPLESTART - 1; | |
871 | |
872 data[0x002] = data[0x402] = dataStart.u8bit.byteLow; | |
873 data[0x003] = data[0x403] = dataStart.u8bit.byteMidLow; | |
874 data[0x004] = data[0x404] = dataStart.u8bit.byteMidHigh; | |
875 data[0x005] = data[0x405] = dataEnd.u8bit.byteLow; | |
876 data[0x006] = data[0x406] = dataEnd.u8bit.byteMidLow; | |
877 data[0x007] = data[0x407] = dataEnd.u8bit.byteMidHigh; | |
878 | |
879 // set actualPointerHeader to next free header and update lastDiveLogId | |
880 ext_flash_create_new_dive_log(0); | |
881 | |
882 // copy header data | |
883 ef_write_block(data,0x800,EF_HEADER, 1); | |
884 | |
885 // copy sample data | |
886 ef_write_block(&data[0x800], length-0x800, EF_SAMPLE, 1); | |
887 | |
888 // update logFlashNextSampleStartAddress | |
889 settingsGetPointer()->logFlashNextSampleStartAddress = actualPointerSample; | |
890 } | |
891 | |
892 | |
893 // =============================================================================== | |
894 // ext_flash_read_header_memory | |
895 /// @brief This function returns the entire header space 1:1 | |
896 /// @date 04-April-2016 | |
897 /// | |
898 /// @param *data 256KB output | |
899 // =============================================================================== | |
900 void ext_flash_read_header_memory(uint8_t *data) | |
901 { | |
902 actualAddress = HEADERSTART; | |
903 actualPointerHeader = actualAddress; | |
904 ext_flash_read_block_start(); | |
905 for(int i=0;i<8;i++) | |
906 ext_flash_read_block_multi(&data[0x8000 * i], 0x8000, EF_HEADER); | |
907 ext_flash_read_block_stop(); | |
908 } | |
909 | |
910 | |
911 // =============================================================================== | |
912 // ext_flash_read_header_memory | |
913 /// @brief This function erases and overwrites the entire logbook header block | |
914 /// @date 04-April-2016 | |
915 /// | |
916 /// @param *data 256KB input of header memory 1:1 | |
917 // =============================================================================== | |
918 void ext_flash_write_header_memory(uint8_t *data) | |
919 { | |
920 actualAddress = HEADERSTART; | |
921 actualPointerHeader = actualAddress; | |
922 ef_write_block(data, 0x40000, EF_HEADER, 0); | |
923 } | |
924 | |
925 | |
926 void ext_flash_open_read_sample(uint8_t StepBackwards, uint32_t *totalNumberOfBytes) | |
927 { | |
928 SSettings *settings = settingsGetPointer(); | |
929 uint8_t id; | |
930 convert_Type dataStart, dataEnd; | |
931 uint8_t header1, header2; | |
932 | |
933 id = settings->lastDiveLogId; | |
934 id -= StepBackwards; /* 0-255, auto rollover */ | |
935 # | |
936 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; | |
937 actualPointerHeader = actualAddress; | |
938 | |
939 ext_flash_read_block_start(); | |
940 /* little endian */ | |
941 ext_flash_read_block(&header1, EF_HEADER); | |
942 ext_flash_read_block(&header2, EF_HEADER); | |
943 dataStart.u8bit.byteHigh = 0; | |
944 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER); | |
945 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER); | |
946 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER); | |
947 dataEnd.u8bit.byteHigh = 0; | |
948 ext_flash_read_block(&dataEnd.u8bit.byteLow, EF_HEADER); | |
949 ext_flash_read_block(&dataEnd.u8bit.byteMidLow, EF_HEADER); | |
950 ext_flash_read_block(&dataEnd.u8bit.byteMidHigh, EF_HEADER); | |
951 ext_flash_read_block_stop(); | |
952 | |
953 actualPointerSample = dataStart.u32bit; | |
954 if(dataEnd.u32bit >= dataStart.u32bit) | |
955 LengthLeftSampleRead = 1 + dataEnd.u32bit - dataStart.u32bit; | |
956 else | |
957 LengthLeftSampleRead = 2 + (dataStart.u32bit - SAMPLESTART) + (SAMPLESTOP - dataEnd.u32bit); | |
958 *totalNumberOfBytes = LengthLeftSampleRead; | |
959 | |
960 actualAddress = actualPointerSample; | |
961 ext_flash_read_block_start(); | |
962 } | |
963 | |
964 | |
965 void ext_flash_read_next_sample_part(uint8_t *pSample, uint8_t length) | |
966 { | |
967 for(uint16_t i = 0; i < length; i++) | |
968 ext_flash_read_block(&pSample[i], EF_SAMPLE); | |
969 } | |
970 | |
971 | |
972 void ext_flash_close_read_sample(void) | |
973 { | |
974 actualPointerSample = actualAddress; | |
975 ext_flash_read_block_stop(); | |
976 } | |
977 | |
978 | |
979 void ext_flash_set_entry_point(void) | |
980 { | |
981 entryPoint = actualAddress; | |
982 } | |
983 | |
984 | |
985 void ext_flash_reopen_read_sample_at_entry_point(void) | |
986 { | |
987 error_led_on(); | |
988 chip_unselect(); | |
989 wait_chip_not_busy(); | |
990 | |
991 actualAddress = entryPoint; | |
992 ext_flash_read_block_start(); | |
993 error_led_off(); | |
994 } | |
995 | |
996 /* | |
997 uint8_t ext_flash_point_to_64k_block_in_headerSpace(uint8_t logId) | |
998 { | |
999 uint32_t pointerToData = logId * 0x800; | |
1000 | |
1001 return pointerToData / 0x10000; | |
1002 } | |
1003 */ | |
1004 | |
1005 | |
1006 // =============================================================================== | |
1007 // ext_flash_repair_dive_numbers_starting_count_helper | |
1008 /// @brief | |
1009 /// @date 22-June-2016 | |
1010 | |
1011 // =============================================================================== | |
1012 uint16_t ext_flash_repair_dive_numbers_starting_count_helper(uint8_t *data, uint8_t *change64k, uint16_t startNumber, uint8_t lastLogId) | |
1013 { | |
1014 const uint32_t headerStep = 0x800; | |
1015 uint8_t actualLogId = 0; | |
1016 uint16_t oldNumber = 0; | |
1017 uint16_t actualNumber = 0; | |
1018 SLogbookHeader *ptrLogbookHeader = 0; | |
1019 | |
1020 if(startNumber == 0) | |
1021 return 0; | |
1022 | |
1023 actualNumber = startNumber - 1; | |
1024 | |
1025 // wo ist der �lteste Tauchgang (der, der startNumber bekommt) | |
1026 // use first header for ease (without HEADER2OFFSET for end of dive header) | |
1027 // compare for lastLogId to prevent endless loop | |
1028 | |
1029 if(*(uint16_t*)&data[lastLogId * headerStep] != 0xFAFA) | |
1030 return 0; | |
1031 | |
1032 actualLogId = lastLogId - 1; | |
1033 while((*(uint16_t*)&data[actualLogId * headerStep] == 0xFAFA) && (actualLogId != lastLogId)) | |
1034 { | |
1035 actualLogId--; | |
1036 } | |
1037 | |
1038 // now pointing to one behind the last | |
1039 while(actualLogId != lastLogId) | |
1040 { | |
1041 actualLogId++; | |
1042 actualNumber++; | |
1043 ptrLogbookHeader = (SLogbookHeader *)&data[actualLogId * headerStep]; | |
1044 | |
1045 oldNumber = ptrLogbookHeader->diveNumber; | |
1046 if(oldNumber != actualNumber) | |
1047 { | |
1048 // change64k[ext_flash_point_to_64k_block_in_headerSpace(actualLogId )] = 1; | |
1049 change64k[(actualLogId * 0x800)/0x10000] = 1; | |
1050 ptrLogbookHeader->diveNumber = actualNumber; | |
1051 ptrLogbookHeader = (SLogbookHeader *)(&data[actualLogId * headerStep] + HEADER2OFFSET); | |
1052 ptrLogbookHeader->diveNumber = actualNumber; | |
1053 } | |
1054 } | |
1055 | |
1056 return actualNumber; | |
1057 } | |
1058 | |
1059 // =============================================================================== | |
1060 // ext_flash_repair_SPECIAL_dive_numbers_starting_count_with | |
1061 /// @brief This function | |
1062 /// @date 04-April-2016 | |
1063 /// problem (160621): 64K Bl�cke (32 Tauchg�nge) weil neuer Flash Chip. | |
1064 /// Dieser Bereich muss auf einmal gel�scht werden. | |
1065 /// Vorher waren es 4K Bl�cke. | |
1066 /// @output endCount, last diveNumber | |
1067 | |
1068 // =============================================================================== | |
1069 uint16_t ext_flash_repair_SPECIAL_dive_numbers_starting_count_with(uint16_t startCount) | |
1070 { | |
1071 uint32_t logCopyDataPtr = 0; | |
1072 uint8_t *data; | |
1073 uint16_t lastCount; | |
1074 uint8_t listOfChanged64kBlocks[8]; // 32 Tauchg�nge pro 64K | |
1075 | |
1076 logCopyDataPtr = getFrame(97); | |
1077 data = (uint8_t *)logCopyDataPtr; | |
1078 | |
1079 for(int i=0;i<8;i++) | |
1080 listOfChanged64kBlocks[i] = 0; | |
1081 | |
1082 actualAddress = HEADERSTART; | |
1083 ext_flash_read_block_start(); | |
1084 ext_flash_read_block_multi(data,0x100000,EF_HEADER); | |
1085 ext_flash_read_block_stop(); | |
1086 | |
1087 lastCount = ext_flash_repair_dive_numbers_starting_count_helper(data, listOfChanged64kBlocks, startCount, settingsGetPointer()->lastDiveLogId); | |
1088 | |
1089 for(int i=0;i<8;i++) | |
1090 { | |
1091 if(listOfChanged64kBlocks[i] != 0) | |
1092 { | |
1093 actualPointerHeader = HEADERSTART + (i * 0x10000); | |
1094 ef_write_block(&data[i * 0x10000], 0x10000, EF_HEADER, 0); | |
1095 } | |
1096 } | |
1097 | |
1098 releaseFrame(97,logCopyDataPtr); | |
1099 if(settingsGetPointer()->totalDiveCounter < lastCount) | |
1100 { | |
1101 settingsGetPointer()->totalDiveCounter = lastCount; | |
1102 } | |
1103 return lastCount; | |
1104 } | |
1105 | |
1106 | |
1107 void OLD_ext_flash_repair_SPECIAL_dive_numbers_starting_count_with(uint16_t startCount) | |
1108 { | |
1109 uint16_t counterStorage[256]; | |
1110 uint8_t start = 0xFF; | |
1111 uint32_t logCopyDataPtr = 0; | |
1112 uint8_t *data; | |
1113 uint8_t startAbsolute = 0; | |
1114 int16_t count = 0; | |
1115 _Bool repair = 0; | |
1116 uint8_t startBackup = 0; | |
1117 | |
1118 SLogbookHeader tempLogbookHeader; | |
1119 SLogbookHeader *ptrHeaderInData1a; | |
1120 SLogbookHeader *ptrHeaderInData1b; | |
1121 SLogbookHeader *ptrHeaderInData2a; | |
1122 SLogbookHeader *ptrHeaderInData2b; | |
1123 | |
1124 logCopyDataPtr = getFrame(97); | |
1125 data = (uint8_t *)logCopyDataPtr; | |
1126 ptrHeaderInData1a = (SLogbookHeader *)logCopyDataPtr; | |
1127 ptrHeaderInData1b = (SLogbookHeader *)(logCopyDataPtr + HEADER2OFFSET); | |
1128 ptrHeaderInData2a = (SLogbookHeader *)(logCopyDataPtr + 0x800); | |
1129 ptrHeaderInData2b = (SLogbookHeader *)(logCopyDataPtr + 0x800 + HEADER2OFFSET); | |
1130 | |
1131 // get data | |
1132 for(int StepBackwards = 0; StepBackwards < 255; StepBackwards++) | |
1133 { | |
1134 logbook_getHeader(StepBackwards, &tempLogbookHeader); | |
1135 counterStorage[StepBackwards+1] = tempLogbookHeader.diveNumber; | |
1136 if(tempLogbookHeader.diveHeaderStart == 0xFAFA) | |
1137 start = StepBackwards; | |
1138 else | |
1139 break; | |
1140 } | |
1141 | |
1142 if(start == 0xFF) | |
1143 return; | |
1144 | |
1145 count = start + 1; | |
1146 startAbsolute = settingsGetPointer()->lastDiveLogId; | |
1147 | |
1148 | |
1149 /* | |
1150 if(start%2) | |
1151 { | |
1152 if(counterStorage[start] != startCount) | |
1153 { | |
1154 // clear data | |
1155 for(int i=0;i<0x800*2;i++) | |
1156 data[i] = 0xFF; | |
1157 | |
1158 uint8_t id = settingsGetPointer()->lastDiveLogId; | |
1159 id -= start; // 0-255, auto rollover | |
1160 | |
1161 // copy primary/pre-dive | |
1162 actualAddress = HEADERSTART + (0x800 * id); | |
1163 ext_flash_read_block_start(); | |
1164 for(int i = 0; i < HEADERSIZE; i++) | |
1165 ext_flash_read_block(&data[i], EF_HEADER); | |
1166 ext_flash_read_block_stop(); | |
1167 | |
1168 // copy main/secondary/post-dive | |
1169 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; | |
1170 ext_flash_read_block_start(); | |
1171 for(int i = 0x400; i < HEADERSIZE+0x400; i++) | |
1172 ext_flash_read_block(&data[i], EF_HEADER); | |
1173 ext_flash_read_block_stop(); | |
1174 | |
1175 // repair | |
1176 ptrHeaderInData2a->diveNumber = startCount; | |
1177 ptrHeaderInData2b->diveNumber = startCount; | |
1178 startCount++; | |
1179 | |
1180 // write | |
1181 actualAddress = HEADERSTART + (0x800 * (id-1)); | |
1182 ef_write_block(data,0x800*2,EF_HEADER, 0); | |
1183 } | |
1184 start--; | |
1185 } | |
1186 */ | |
1187 // for(int count = start; count > -1; count -= 2) | |
1188 | |
1189 while(count > 0) | |
1190 { | |
1191 // clear data | |
1192 for(int i=0;i<0x1000;i++) | |
1193 data[i] = 0xFF; | |
1194 | |
1195 repair = 0; | |
1196 | |
1197 startBackup = startAbsolute; | |
1198 | |
1199 if(startAbsolute%2) // 0x800 to 0x1000 | |
1200 { | |
1201 // copy second pre-dive | |
1202 actualAddress = HEADERSTART + (0x800 * startAbsolute); | |
1203 ext_flash_read_block_start(); | |
1204 for(int i = 0x800; i < HEADERSIZE+0x800; i++) | |
1205 ext_flash_read_block(&data[i], EF_HEADER); | |
1206 ext_flash_read_block_stop(); | |
1207 | |
1208 // copy second post-dive | |
1209 actualAddress = HEADERSTART + HEADER2OFFSET + (0x800 * startAbsolute); | |
1210 ext_flash_read_block_start(); | |
1211 for(int i = 0xC00; i < HEADERSIZE+0xC00; i++) | |
1212 ext_flash_read_block(&data[i], EF_HEADER); | |
1213 ext_flash_read_block_stop(); | |
1214 | |
1215 if(counterStorage[count] != startCount) | |
1216 { | |
1217 ptrHeaderInData2a->diveNumber = startCount; | |
1218 ptrHeaderInData2b->diveNumber = startCount; | |
1219 repair = 1; | |
1220 } | |
1221 startCount += 1; | |
1222 | |
1223 startAbsolute -= 1; | |
1224 count -= 1; | |
1225 | |
1226 if(count > 0) | |
1227 { | |
1228 // copy first pre-dive | |
1229 actualAddress = HEADERSTART + (0x800 * startAbsolute); | |
1230 ext_flash_read_block_start(); | |
1231 for(int i = 0; i < HEADERSIZE; i++) | |
1232 ext_flash_read_block(&data[i], EF_HEADER); | |
1233 ext_flash_read_block_stop(); | |
1234 | |
1235 // copy first post-dive | |
1236 actualAddress = HEADERSTART + (0x800 * startAbsolute); | |
1237 ext_flash_read_block_start(); | |
1238 for(int i = 0x400; i < HEADERSIZE+0x400; i++) | |
1239 ext_flash_read_block(&data[i], EF_HEADER); | |
1240 ext_flash_read_block_stop(); | |
1241 | |
1242 if(counterStorage[count] != startCount) | |
1243 { | |
1244 ptrHeaderInData1a->diveNumber = startCount; | |
1245 ptrHeaderInData1b->diveNumber = startCount; | |
1246 repair = 1; | |
1247 } | |
1248 startCount += 1; | |
1249 | |
1250 startAbsolute -= 1; | |
1251 count -= 1; | |
1252 } | |
1253 } | |
1254 else | |
1255 { | |
1256 // copy first pre-dive | |
1257 actualAddress = HEADERSTART + (0x800 * startAbsolute); | |
1258 ext_flash_read_block_start(); | |
1259 for(int i = 0; i < HEADERSIZE; i++) | |
1260 ext_flash_read_block(&data[i], EF_HEADER); | |
1261 ext_flash_read_block_stop(); | |
1262 | |
1263 // copy first post-dive | |
1264 actualAddress = HEADERSTART + (0x800 * startAbsolute); | |
1265 ext_flash_read_block_start(); | |
1266 for(int i = 0x400; i < HEADERSIZE+0x400; i++) | |
1267 ext_flash_read_block(&data[i], EF_HEADER); | |
1268 ext_flash_read_block_stop(); | |
1269 | |
1270 if(counterStorage[count] != startCount) | |
1271 { | |
1272 ptrHeaderInData1a->diveNumber = startCount; | |
1273 ptrHeaderInData1b->diveNumber = startCount; | |
1274 repair = 1; | |
1275 } | |
1276 startCount += 1; | |
1277 | |
1278 startAbsolute -= 1; | |
1279 count -= 1; | |
1280 } | |
1281 | |
1282 // write | |
1283 if(repair) | |
1284 { | |
1285 actualPointerHeader = HEADERSTART + (0x1000 * startBackup%2); | |
1286 ef_write_block(data,0x1000,EF_HEADER, 0); | |
1287 } | |
1288 } | |
1289 releaseFrame(97,logCopyDataPtr); | |
1290 settingsGetPointer()->totalDiveCounter = startCount; | |
1291 } | |
1292 | |
1293 | |
1294 // =============================================================================== | |
1295 // ext_flash_repair_dive_log | |
1296 /// @brief This function | |
1297 /// does set | |
1298 /// logFlashNextSampleStartAddress | |
1299 /// and | |
1300 /// lastDiveLogId | |
1301 /// | |
1302 void ext_flash_repair_dive_log(void) | |
1303 { | |
1304 uint8_t header1, header2; | |
1305 convert_Type dataStart; | |
1306 | |
1307 for(int id = 0; id < 255;id++) | |
1308 { | |
1309 actualAddress = HEADERSTART + (0x800 * id); | |
1310 ext_flash_read_block_start(); | |
1311 ext_flash_read_block(&header1, EF_HEADER); | |
1312 ext_flash_read_block(&header2, EF_HEADER); | |
1313 dataStart.u8bit.byteHigh = 0; | |
1314 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER); | |
1315 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER); | |
1316 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER); | |
1317 ext_flash_read_block_stop(); | |
1318 if((header1 == 0xFA) && (header2 == 0xFA)) | |
1319 { | |
1320 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; | |
1321 ext_flash_read_block_start(); | |
1322 ext_flash_read_block(&header1, EF_HEADER); | |
1323 ext_flash_read_block(&header2, EF_HEADER); | |
1324 ext_flash_read_block_stop(); | |
1325 if((header1 != 0xFA) || (header2 != 0xFA)) | |
1326 { | |
1327 actualPointerSample = dataStart.u32bit; | |
1328 actualAddress = actualPointerSample; | |
1329 logbook_recover_brokenlog(id); | |
1330 SSettings *settings = settingsGetPointer(); | |
1331 settings->logFlashNextSampleStartAddress = actualPointerSample; | |
1332 } | |
1333 } | |
1334 } | |
1335 ext_flash_find_start(); | |
1336 } | |
1337 | |
1338 | |
1339 void ext_flash_find_start(void) | |
1340 { | |
1341 uint8_t id; | |
1342 uint8_t header1, header2; | |
1343 convert_Type dataStart, dataEnd; | |
1344 | |
1345 for(id = 0; id < 255;id++) | |
1346 { | |
1347 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; | |
1348 ext_flash_read_block_start(); | |
1349 ext_flash_read_block(&header1, EF_HEADER); | |
1350 ext_flash_read_block(&header2, EF_HEADER); | |
1351 dataStart.u8bit.byteHigh = 0; | |
1352 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER); | |
1353 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER); | |
1354 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER); | |
1355 ext_flash_read_block_stop(); | |
1356 if((header1 == 0xFF) && (header2 == 0xFF)) | |
1357 { | |
1358 break; | |
1359 } | |
1360 } | |
1361 id--; | |
1362 SSettings *settings = settingsGetPointer(); | |
1363 settings->lastDiveLogId = id; | |
1364 | |
1365 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; | |
1366 actualPointerHeader = actualAddress; | |
1367 | |
1368 ext_flash_read_block_start(); | |
1369 | |
1370 ext_flash_read_block(&header1, EF_HEADER); | |
1371 ext_flash_read_block(&header2, EF_HEADER); | |
1372 dataStart.u8bit.byteHigh = 0; | |
1373 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER); | |
1374 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER); | |
1375 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER); | |
1376 dataEnd.u8bit.byteHigh = 0; | |
1377 ext_flash_read_block(&dataEnd.u8bit.byteLow, EF_HEADER); | |
1378 ext_flash_read_block(&dataEnd.u8bit.byteMidLow, EF_HEADER); | |
1379 ext_flash_read_block(&dataEnd.u8bit.byteMidHigh, EF_HEADER); | |
1380 ext_flash_read_block_stop(); | |
1381 | |
1382 //Find free space | |
1383 if((header1 == 0xFA) && (header2 == 0xFA)) | |
1384 { | |
1385 uint8_t uiRead = 0; | |
1386 int countFF = 0; | |
1387 //End of last complete dive | |
1388 actualPointerSample = dataEnd.u32bit ; | |
1389 actualAddress = actualPointerSample; | |
1390 //Check if there are samples of dives with less than half a minute | |
1391 while(true) | |
1392 { | |
1393 ext_flash_read_block_start(); | |
1394 ext_flash_read_block(&uiRead, EF_SAMPLE); | |
1395 if(uiRead == 0xFF) | |
1396 countFF++; | |
1397 else | |
1398 countFF = 0; | |
1399 | |
1400 | |
1401 | |
1402 if(countFF == 10) | |
1403 { | |
1404 actualAddress -= 10; | |
1405 break; | |
1406 } | |
1407 | |
1408 //New page: clear | |
1409 if(ext_flash_erase_if_on_page_start()) | |
1410 break; | |
1411 } | |
1412 // Set new start address | |
1413 actualPointerSample = actualAddress; | |
1414 settings->logFlashNextSampleStartAddress = actualPointerSample; | |
1415 } | |
1416 else | |
1417 { | |
1418 settings->logFlashNextSampleStartAddress = SAMPLESTART; | |
1419 } | |
1420 } | |
1421 | |
1422 | |
1423 #endif | |
1424 | |
1425 void ext_flash_disable_protection(void) | |
1426 { | |
1427 /* | |
1428 extFlashStatusBit8_Type status; | |
1429 | |
1430 status.uw = 0; | |
1431 | |
1432 wait_chip_not_busy(); | |
1433 write_spi(0x50,RELEASE); // EWSR | |
1434 write_spi(0x01,HOLDCS); // WRSR | |
1435 write_spi(status.uw,RELEASE); // new status | |
1436 */ | |
1437 } | |
1438 | |
1439 | |
1440 void ext_flash_disable_protection_for_logbook(void) | |
1441 { | |
1442 /* | |
1443 extFlashStatusBit8_Type status; | |
1444 | |
1445 status.uw = 0; | |
1446 status.ub.BlockProtect0 = 1; | |
1447 status.ub.BlockProtect1 = 0; | |
1448 status.ub.BlockProtect2 = 1; | |
1449 status.ub.BlockProtect3 = 0; // not set in OSTC3. Why? | |
1450 | |
1451 wait_chip_not_busy(); | |
1452 write_spi(0x50,RELEASE); // EWSR | |
1453 write_spi(0x01,HOLDCS); // WRSR | |
1454 write_spi(status.uw,RELEASE); // new status | |
1455 */ | |
1456 } | |
1457 | |
1458 | |
1459 void ext_flash_enable_protection(void) | |
1460 { | |
1461 /* | |
1462 extFlashStatusBit8_Type status; | |
1463 | |
1464 status.uw = 0; | |
1465 status.ub.BlockProtect0 = 1; | |
1466 status.ub.BlockProtect1 = 1; | |
1467 status.ub.BlockProtect2 = 1; | |
1468 status.ub.BlockProtect3 = 1; // not set in OSTC3. Why? | |
1469 | |
1470 wait_chip_not_busy(); | |
1471 write_spi(0x50,RELEASE); // EWSR | |
1472 write_spi(0x01,HOLDCS); // WRSR | |
1473 write_spi(status.uw,RELEASE); // new status | |
1474 */ | |
1475 } | |
1476 | |
1477 | |
1478 void ext_flash_erase_chip(void) | |
1479 { | |
1480 wait_chip_not_busy(); | |
1481 write_spi(0x06,RELEASE); | |
1482 write_spi(0x60,RELEASE); | |
1483 wait_chip_not_busy(); | |
1484 } | |
1485 | |
1486 void ext_flash_erase_firmware(void) | |
1487 { | |
1488 uint32_t size, blocks_64k; | |
1489 | |
1490 actualAddress = FWSTART; | |
1491 size = 1 + FWSTOP - FWSTART; | |
1492 blocks_64k = size / 0x10000; | |
1493 ef_erase_64K(blocks_64k); | |
1494 } | |
1495 | |
1496 void ext_flash_erase_firmware2(void) | |
1497 { | |
1498 uint32_t size, blocks_64k; | |
1499 | |
1500 actualAddress = FWSTART2; | |
1501 size = 1 + FWSTOP2 - FWSTART2; | |
1502 blocks_64k = size / 0x10000; | |
1503 ef_erase_64K(blocks_64k); | |
1504 } | |
1505 | |
1506 | |
1507 | |
1508 void ext_flash_erase_logbook(void) | |
1509 { | |
1510 uint32_t size, blocks_64k; | |
1511 | |
1512 ext_flash_disable_protection_for_logbook(); | |
1513 | |
1514 actualAddress = SAMPLESTART; | |
1515 size = 1 + SAMPLESTOP - SAMPLESTART; | |
1516 blocks_64k = size / 0x10000; | |
1517 ef_erase_64K(blocks_64k); | |
1518 | |
1519 actualAddress = HEADERSTART; | |
1520 size = 1 + HEADERSTOP - HEADERSTART; | |
1521 blocks_64k = size / 0x10000; | |
1522 ef_erase_64K(blocks_64k); | |
1523 | |
1524 ext_flash_enable_protection(); | |
1525 } | |
1526 | |
1527 | |
1528 void ext_flash_erase4kB(void) | |
1529 { | |
1530 wait_chip_not_busy(); | |
1531 write_spi(0x06,RELEASE);/* WREN */ | |
1532 write_spi(0x20,HOLDCS);/* sector erase cmd */ | |
1533 write_address(RELEASE); | |
1534 } | |
1535 | |
1536 /* be carefull - might not work with entire family and other products | |
1537 * see page 14 of LOGBOOK_V3_S25FS-S_00-271247.pdf | |
1538 */ | |
1539 void ext_flash_erase32kB(void) | |
1540 { | |
1541 uint32_t actualAddress_backup; | |
1542 | |
1543 actualAddress_backup = actualAddress; | |
1544 actualAddress = 0; | |
1545 wait_chip_not_busy(); | |
1546 write_spi(0x06,RELEASE);/* WREN */ | |
1547 write_spi(0xD8,HOLDCS);/* sector erase cmd */ | |
1548 write_address(RELEASE); | |
1549 actualAddress = actualAddress_backup; | |
1550 } | |
1551 | |
1552 | |
1553 void ext_flash_erase64kB(void) | |
1554 { | |
1555 wait_chip_not_busy(); | |
1556 write_spi(0x06,RELEASE);/* WREN */ | |
1557 write_spi(0xD8,HOLDCS);/* sector erase cmd */ | |
1558 write_address(RELEASE); | |
1559 } | |
1560 | |
1561 | |
1562 void ext_flash_read_block_start(void) | |
1563 { | |
1564 wait_chip_not_busy(); | |
1565 write_spi(0x03,HOLDCS); /* WREN */ | |
1566 write_address(HOLDCS); | |
1567 } | |
1568 | |
1569 /* 4KB, 32KB, 64 KB, not the upper 16 MB with 4 Byte address at the moment */ | |
1570 uint8_t ext_flash_erase_if_on_page_start(void) | |
1571 { | |
1572 if(actualAddress < 0x00008000) | |
1573 { | |
1574 /* 4K Byte is 0x1000 */ | |
1575 if((actualAddress & 0xFFF) == 0) | |
1576 { | |
1577 ext_flash_erase4kB(); | |
1578 return 1; | |
1579 } | |
1580 } | |
1581 else | |
1582 if(actualAddress < 0x00010000) | |
1583 { | |
1584 /* 32K Byte is only one page */ | |
1585 if(actualAddress == 0x00010000) | |
1586 { | |
1587 ext_flash_erase32kB(); | |
1588 return 1; | |
1589 } | |
1590 } | |
1591 else | |
1592 { | |
1593 /* 64K Byte is 0x10000 */ | |
1594 if((actualAddress & 0xFFFF) == 0) | |
1595 { | |
1596 ext_flash_erase64kB(); | |
1597 return 1; | |
1598 } | |
1599 } | |
1600 return 0; | |
1601 } | |
1602 | |
1603 | |
1604 void ext_flash_read_block(uint8_t *getByte, uint8_t type) | |
1605 { | |
1606 *getByte = read_spi(HOLDCS);/* read data */ | |
1607 ext_flash_incf_address(type); | |
1608 } | |
1609 | |
1610 | |
1611 void ext_flash_read_block_multi(void *getByte, uint32_t size, uint8_t type) | |
1612 { | |
1613 uint8_t *data; | |
1614 data = getByte; | |
1615 | |
1616 for(uint32_t i=0;i<size;i++) | |
1617 { | |
1618 data[i] = read_spi(HOLDCS);/* read data */ | |
1619 ext_flash_incf_address(type); | |
1620 } | |
1621 } | |
1622 | |
1623 | |
1624 void ext_flash_read_block_stop(void) | |
1625 { | |
1626 chip_unselect(); | |
1627 } | |
1628 | |
1629 | |
1630 /* Private functions ---------------------------------------------------------*/ | |
1631 | |
1632 void ef_write_block(uint8_t * sendByte, uint32_t length, uint8_t type, uint8_t do_not_erase) | |
1633 { | |
1634 uint32_t remaining_page_size, remaining_length, remaining_space_to_ring_end; | |
1635 | |
1636 if(!length) | |
1637 return; | |
1638 | |
1639 uint32_t ringStart, ringStop; | |
1640 | |
1641 switch(type) | |
1642 { | |
1643 case EF_HEADER: | |
1644 actualAddress = actualPointerHeader; | |
1645 ringStart = HEADERSTART; | |
1646 ringStop = HEADERSTOP; | |
1647 break; | |
1648 case EF_SAMPLE: | |
1649 actualAddress = actualPointerSample; | |
1650 ringStart = SAMPLESTART; | |
1651 ringStop = SAMPLESTOP; | |
1652 break; | |
1653 case EF_DEVICEDATA: | |
1654 actualAddress = actualPointerDevicedata; | |
1655 ringStart = DDSTART; | |
1656 ringStop = DDSTOP; | |
1657 break; | |
1658 case EF_VPMDATA: | |
1659 actualAddress = actualPointerVPM; | |
1660 ringStart = VPMSTART; | |
1661 ringStop = VPMSTOP; | |
1662 break; | |
1663 case EF_SETTINGS: | |
1664 actualAddress = actualPointerSettings; | |
1665 ringStart = SETTINGSSTART; | |
1666 ringStop = SETTINGSSTOP; | |
1667 break; | |
1668 case EF_FIRMWARE: | |
1669 actualAddress = actualPointerFirmware; | |
1670 ringStart = FWSTART; | |
1671 ringStop = FWSTOP; | |
1672 break; | |
1673 case EF_FIRMWARE2: | |
1674 actualAddress = actualPointerFirmware2; | |
1675 ringStart = FWSTART2; | |
1676 ringStop = FWSTOP2; | |
1677 break; | |
1678 default: | |
1679 ringStart = FLASHSTART; | |
1680 ringStop = FLASHSTOP; | |
1681 break; | |
1682 } | |
1683 /* safety */ | |
1684 if(actualAddress < ringStart) | |
1685 actualAddress = ringStart; | |
1686 | |
1687 if(do_not_erase == 0) | |
1688 ext_flash_erase_if_on_page_start(); | |
1689 | |
1690 for(uint32_t i=0;i<length;i++) | |
1691 { | |
1692 ef_hw_rough_delay_us(5); | |
1693 wait_chip_not_busy(); | |
1694 write_spi(0x06,RELEASE); /* WREN */ | |
1695 write_spi(0x02,HOLDCS); /* write cmd */ | |
1696 write_address(HOLDCS); | |
1697 | |
1698 remaining_length = length - i; | |
1699 remaining_page_size = actualAddress & 0xFF; | |
1700 remaining_space_to_ring_end = ringStop - actualAddress; | |
1701 | |
1702 if((remaining_page_size == 0) && (remaining_length >= 256) && (remaining_space_to_ring_end >= 256)) | |
1703 { | |
1704 for(int j=0; j<255; j++) | |
1705 { | |
1706 write_spi(sendByte[i],HOLDCS);/* write data */ | |
1707 actualAddress++; | |
1708 i++; | |
1709 } | |
1710 } | |
1711 /* byte with RELEASE */ | |
1712 write_spi(sendByte[i],RELEASE);/* write data */ | |
1713 actualAddress++; | |
1714 if(actualAddress > ringStop) | |
1715 actualAddress = ringStart; | |
1716 if(do_not_erase == 0) | |
1717 ext_flash_erase_if_on_page_start(); | |
1718 } | |
1719 switch(type) | |
1720 { | |
1721 case EF_HEADER: | |
1722 actualPointerHeader = actualAddress; | |
1723 break; | |
1724 case EF_SAMPLE: | |
1725 actualPointerSample = actualAddress; | |
1726 break; | |
1727 case EF_DEVICEDATA: | |
1728 actualPointerDevicedata = actualAddress; | |
1729 break; | |
1730 case EF_VPMDATA: | |
1731 actualPointerVPM = actualAddress; | |
1732 break; | |
1733 case EF_SETTINGS: | |
1734 actualPointerSettings = actualAddress; | |
1735 break; | |
1736 case EF_FIRMWARE: | |
1737 actualPointerFirmware = actualAddress; | |
1738 break; | |
1739 case EF_FIRMWARE2: | |
1740 actualPointerFirmware2 = actualAddress; | |
1741 break; | |
1742 default: | |
1743 break; | |
1744 } | |
1745 } | |
1746 | |
1747 | |
1748 _Bool ext_flash_test_remaining_space_of_page_empty(uint32_t pointer, uint16_t length) | |
1749 { | |
1750 if((pointer & 0xFFF) == 0) | |
1751 return 1; | |
1752 | |
1753 uint32_t backup = actualAddress; | |
1754 uint8_t data; | |
1755 uint32_t size_to_page_end; | |
1756 | |
1757 size_to_page_end = 0x1000 - (pointer & 0xFFF); | |
1758 if(length > size_to_page_end) | |
1759 length = size_to_page_end; | |
1760 | |
1761 actualAddress = pointer; | |
1762 ext_flash_read_block_start(); | |
1763 | |
1764 for(uint16_t i = 0; i<length; i++) | |
1765 { | |
1766 ext_flash_read_block(&data, 255); // 255 = ENTIRE FLASH | |
1767 if(data != 0xFF) | |
1768 { | |
1769 ext_flash_read_block_stop(); | |
1770 actualAddress = backup; | |
1771 return 0; | |
1772 } | |
1773 } | |
1774 ext_flash_read_block_stop(); | |
1775 actualAddress = backup; | |
1776 return 1; | |
1777 } | |
1778 | |
1779 | |
1780 void ext_flash_set_to_begin_of_next_page(uint32_t *pointer, uint8_t type) | |
1781 { | |
1782 uint32_t ringStart, ringStop; | |
1783 | |
1784 switch(type) | |
1785 { | |
1786 case EF_HEADER: | |
1787 ringStart = HEADERSTART; | |
1788 ringStop = HEADERSTOP; | |
1789 break; | |
1790 case EF_SAMPLE: | |
1791 ringStart = SAMPLESTART; | |
1792 ringStop = SAMPLESTOP; | |
1793 break; | |
1794 case EF_DEVICEDATA: | |
1795 ringStart = DDSTART; | |
1796 ringStop = DDSTOP; | |
1797 break; | |
1798 case EF_VPMDATA: | |
1799 ringStart = VPMSTART; | |
1800 ringStop = VPMSTOP; | |
1801 break; | |
1802 case EF_SETTINGS: | |
1803 ringStart = SETTINGSSTART; | |
1804 ringStop = SETTINGSSTOP; | |
1805 break; | |
1806 default: | |
1807 ringStart = FLASHSTART; | |
1808 ringStop = FLASHSTOP; | |
1809 break; | |
1810 } | |
1811 | |
1812 *pointer = (*pointer & 0xFFF) + 0x1000; | |
1813 | |
1814 if((*pointer < ringStart) || (*pointer >= ringStop)) | |
1815 *pointer = ringStart; | |
1816 } | |
1817 | |
1818 | |
1819 static void ef_erase_64K(uint32_t blocks) | |
1820 { | |
1821 for(uint32_t i = 0; i < blocks; i++) | |
1822 { | |
1823 wait_chip_not_busy(); | |
1824 write_spi(0x06,RELEASE);/* WREN */ | |
1825 write_spi(0xD8,HOLDCS);/* 64k erase cmd */ | |
1826 write_address(RELEASE); | |
1827 actualAddress += 0x10000; | |
1828 HAL_Delay(25); | |
1829 } | |
1830 } | |
1831 | |
1832 | |
1833 void chip_unselect(void) | |
1834 { | |
1835 HAL_GPIO_WritePin(EXTFLASH_CSB_GPIO_PORT,EXTFLASH_CSB_PIN,GPIO_PIN_SET); // chip select | |
1836 } | |
1837 | |
1838 void chip_select(void) | |
1839 { | |
1840 HAL_GPIO_WritePin(EXTFLASH_CSB_GPIO_PORT,EXTFLASH_CSB_PIN,GPIO_PIN_RESET); // chip select | |
1841 } | |
1842 | |
1843 void error_led_on(void) | |
1844 { | |
1845 HAL_GPIO_WritePin(OSCILLOSCOPE_GPIO_PORT,OSCILLOSCOPE_PIN,GPIO_PIN_SET); | |
1846 } | |
1847 | |
1848 void error_led_off(void) | |
1849 { | |
1850 HAL_GPIO_WritePin(OSCILLOSCOPE_GPIO_PORT,OSCILLOSCOPE_PIN,GPIO_PIN_RESET); | |
1851 } | |
1852 | |
1853 | |
1854 uint8_t read_spi(uint8_t unselect_CS_afterwards) | |
1855 { | |
1856 uint8_t byte; | |
1857 | |
1858 chip_select(); | |
1859 | |
1860 if(HAL_SPI_Receive(&hspiDisplay, &byte, 1, 10000) != HAL_OK) | |
1861 Error_Handler_extflash(); | |
1862 | |
1863 while (HAL_SPI_GetState(&hspiDisplay) != HAL_SPI_STATE_READY) | |
1864 { | |
1865 } | |
1866 if(unselect_CS_afterwards) | |
1867 chip_unselect(); | |
1868 | |
1869 return byte; | |
1870 } | |
1871 | |
1872 | |
1873 void write_spi(uint8_t data, uint8_t unselect_CS_afterwards) | |
1874 { | |
1875 chip_select(); | |
1876 | |
1877 if(HAL_SPI_Transmit(&hspiDisplay, &data, 1, 10000) != HAL_OK) | |
1878 Error_Handler_extflash(); | |
1879 | |
1880 while (HAL_SPI_GetState(&hspiDisplay) != HAL_SPI_STATE_READY) | |
1881 { | |
1882 } | |
1883 if(unselect_CS_afterwards) | |
1884 chip_unselect(); | |
1885 } | |
1886 | |
1887 | |
1888 void write_address(uint8_t unselect_CS_afterwards) | |
1889 { | |
1890 uint8_t hi, med ,lo; | |
1891 | |
1892 hi = (actualAddress >> 16) & 0xFF; | |
1893 med = (actualAddress >> 8) & 0xFF; | |
1894 lo = actualAddress & 0xFF; | |
1895 | |
1896 write_spi(hi, HOLDCS); | |
1897 write_spi(med, HOLDCS); | |
1898 write_spi(lo, unselect_CS_afterwards); | |
1899 } | |
1900 | |
1901 | |
1902 static void wait_chip_not_busy(void) | |
1903 { | |
1904 uint8_t status; | |
1905 | |
1906 chip_unselect(); | |
1907 | |
1908 write_spi(0x05,HOLDCS); /* RDSR */ | |
1909 status = read_spi(HOLDCS);/* read status */ | |
1910 while(status & 0x01) | |
1911 { | |
1912 HAL_Delay(1); | |
1913 status = read_spi(HOLDCS);/* read status */ | |
1914 } | |
1915 chip_unselect(); | |
1916 } | |
1917 | |
1918 | |
1919 void ext_flash_incf_address(uint8_t type) | |
1920 { | |
1921 uint32_t ringStart, ringStop; | |
1922 | |
1923 actualAddress += 1; | |
1924 | |
1925 switch(type) | |
1926 { | |
1927 case EF_HEADER: | |
1928 ringStart = HEADERSTART; | |
1929 ringStop = HEADERSTOP; | |
1930 break; | |
1931 case EF_SAMPLE: | |
1932 ringStart = SAMPLESTART; | |
1933 ringStop = SAMPLESTOP; | |
1934 break; | |
1935 case EF_DEVICEDATA: | |
1936 ringStart = DDSTART; | |
1937 ringStop = DDSTOP; | |
1938 break; | |
1939 case EF_VPMDATA: | |
1940 ringStart = VPMSTART; | |
1941 ringStop = VPMSTOP; | |
1942 break; | |
1943 case EF_SETTINGS: | |
1944 ringStart = SETTINGSSTART; | |
1945 ringStop = SETTINGSSTOP; | |
1946 break; | |
1947 case EF_FIRMWARE: | |
1948 ringStart = FWSTART; | |
1949 ringStop = FWSTOP; | |
1950 break; | |
1951 case EF_FIRMWARE2: | |
1952 ringStart = FWSTART2; | |
1953 ringStop = FWSTOP2; | |
1954 break; | |
1955 default: | |
1956 ringStart = FLASHSTART; | |
1957 ringStop = FLASHSTOP; | |
1958 break; | |
1959 } | |
1960 | |
1961 if((actualAddress < ringStart) || (actualAddress > ringStop)) | |
1962 actualAddress = ringStart; | |
1963 } | |
1964 | |
1965 | |
1966 void ext_flash_decf_address_ring(uint8_t type) | |
1967 { | |
1968 uint32_t ringStart, ringStop; | |
1969 | |
1970 switch(type) | |
1971 { | |
1972 case EF_HEADER: | |
1973 ringStart = HEADERSTART; | |
1974 ringStop = HEADERSTOP; | |
1975 break; | |
1976 case EF_SAMPLE: | |
1977 ringStart = SAMPLESTART; | |
1978 ringStop = SAMPLESTOP; | |
1979 break; | |
1980 case EF_DEVICEDATA: | |
1981 ringStart = DDSTART; | |
1982 ringStop = DDSTOP; | |
1983 break; | |
1984 case EF_VPMDATA: | |
1985 ringStart = VPMSTART; | |
1986 ringStop = VPMSTOP; | |
1987 break; | |
1988 case EF_SETTINGS: | |
1989 ringStart = SETTINGSSTART; | |
1990 ringStop = SETTINGSSTOP; | |
1991 break; | |
1992 case EF_FIRMWARE: | |
1993 ringStart = FWSTART; | |
1994 ringStop = FWSTOP; | |
1995 break; | |
1996 case EF_FIRMWARE2: | |
1997 ringStart = FWSTART2; | |
1998 ringStop = FWSTOP2; | |
1999 break; | |
2000 default: | |
2001 ringStart = FLASHSTART; | |
2002 ringStop = FLASHSTOP; | |
2003 break; | |
2004 } | |
2005 | |
2006 if((actualAddress <= ringStart) || (actualAddress > ringStop)) | |
2007 actualAddress = ringStop; | |
2008 else | |
2009 actualAddress -= 1; | |
2010 } | |
2011 | |
2012 | |
2013 static void ef_hw_rough_delay_us(uint32_t delayUs) | |
2014 { | |
2015 if(!delayUs) | |
2016 return; | |
2017 delayUs*= 12; | |
2018 while(delayUs--); | |
2019 return; | |
2020 } | |
2021 | |
2022 static void Error_Handler_extflash(void) | |
2023 { | |
2024 while(1) | |
2025 { | |
2026 } | |
2027 } | |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
38
diff
changeset
|
2028 /* |
38 | 2029 uint8_t ext_flash_erase_firmware_if_not_empty(void) |
2030 { | |
2031 const uint8_t TESTSIZE_FW = 4; | |
2032 | |
2033 uint8_t data[TESTSIZE_FW]; | |
2034 uint8_t notEmpty = 0; | |
2035 | |
2036 actualAddress = FWSTART; | |
2037 ext_flash_read_block_start(); | |
2038 for(int i = 0; i < TESTSIZE_FW; i++) | |
2039 { | |
2040 ext_flash_read_block(&data[i], EF_FIRMWARE); | |
2041 if(data[i] != 0xFF) | |
2042 notEmpty = 1; | |
2043 } | |
2044 ext_flash_read_block_stop(); | |
2045 | |
2046 if(notEmpty) | |
2047 { | |
2048 ext_flash_erase_firmware(); | |
2049 return 1; | |
2050 } | |
2051 else | |
2052 return 0; | |
2053 } | |
2054 | |
2055 uint8_t ext_flash_erase_firmware2_if_not_empty(void) | |
2056 { | |
2057 const uint8_t TESTSIZE_FW = 4; | |
2058 | |
2059 uint8_t data[TESTSIZE_FW]; | |
2060 uint8_t notEmpty = 0; | |
2061 | |
2062 actualAddress = FWSTART2; | |
2063 ext_flash_read_block_start(); | |
2064 for(int i = 0; i < TESTSIZE_FW; i++) | |
2065 { | |
2066 ext_flash_read_block(&data[i], EF_FIRMWARE2); | |
2067 if(data[i] != 0xFF) | |
2068 notEmpty = 1; | |
2069 } | |
2070 ext_flash_read_block_stop(); | |
2071 | |
2072 if(notEmpty) | |
2073 { | |
2074 ext_flash_erase_firmware2(); | |
2075 return 1; | |
2076 } | |
2077 else | |
2078 return 0; | |
225
2bb1db22b5f5
cleanup: random set of cleanups
Jan Mulder <jlmulder@xs4all.nl>
parents:
38
diff
changeset
|
2079 }*/ |