comparison Discovery/Src/externLogbookFlash.c @ 38:5f11787b4f42

include in ostc4 repository
author heinrichsweikamp
date Sat, 28 Apr 2018 11:52:34 +0200
parents
children 2bb1db22b5f5
comparison
equal deleted inserted replaced
37:ccc45c0e1ea2 38:5f11787b4f42
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>&copy; 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 }
2028
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;
2079 }