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 ---------------------------------------------------------*/
870
+ − 118
+ − 119 #ifndef BOOTLOADER_STANDALONE
+ − 120 static uint32_t entryPoint = 0;
+ − 121 static uint32_t LengthLeftSampleRead = 0;
+ − 122 static uint32_t actualPointerDevicedata_Read = DDSTART;
+ − 123 #endif
+ − 124
268
+ − 125 static uint32_t actualAddress = 0;
423
+ − 126 static uint32_t preparedPageAddress = 0;
425
+ − 127 static uint32_t closeSectorAddress = 0;
268
+ − 128 static uint32_t actualPointerHeader = 0;
+ − 129 static uint32_t actualPointerSample = 0;
421
+ − 130 static uint32_t actualPointerDevicedata = DDSTART;
268
+ − 131 static uint32_t actualPointerVPM = 0;
427
+ − 132 static uint32_t actualPointerSettings = SETTINGSSTART;
268
+ − 133 static uint32_t actualPointerFirmware = 0;
+ − 134 static uint32_t actualPointerFirmware2 = 0;
38
+ − 135
+ − 136 /* Private function prototypes -----------------------------------------------*/
268
+ − 137 static void chip_unselect(void);
+ − 138 static void chip_select(void);
870
+ − 139 #ifndef BOOTLOADER_STANDALONE
268
+ − 140 static void error_led_on(void);
+ − 141 static void error_led_off(void);
870
+ − 142 static void ext_flash_decf_address_ring(uint8_t type);
+ − 143 static void ext_flash_disable_protection(void);
+ − 144 static _Bool ext_flash_test_remaining_space_of_page_empty(uint32_t pointer, uint16_t length);
+ − 145 static void ext_flash_set_to_begin_of_next_page(uint32_t *pointer, uint8_t type);
+ − 146 #endif
268
+ − 147 static void write_spi(uint8_t data, uint8_t unselect_CS_afterwards);
+ − 148 static uint8_t read_spi(uint8_t unselect_CS_afterwards);
+ − 149 static void write_address(uint8_t unselect_CS_afterwards);
38
+ − 150 static void Error_Handler_extflash(void);
+ − 151 static void wait_chip_not_busy(void);
268
+ − 152 static void ext_flash_incf_address(uint8_t type);
38
+ − 153 //void ext_flash_incf_address_ring(void);
+ − 154
268
+ − 155 static void ext_flash_erase4kB(void);
+ − 156 static void ext_flash_erase32kB(void);
+ − 157 static void ext_flash_erase64kB(void);
+ − 158 static uint8_t ext_flash_erase_if_on_page_start(void);
38
+ − 159
268
+ − 160 static void ef_write_block(uint8_t * sendByte, uint32_t length, uint8_t type, uint8_t do_not_erase);
38
+ − 161
268
+ − 162 static void ext_flash_read_block(uint8_t *getByte, uint8_t type);
+ − 163 static void ext_flash_read_block_multi(void *getByte, uint32_t size, uint8_t type);
+ − 164 static void ext_flash_read_block_stop(void);
38
+ − 165
+ − 166 static void ef_hw_rough_delay_us(uint32_t delayUs);
+ − 167 static void ef_erase_64K(uint32_t blocks);
+ − 168
870
+ − 169 #ifndef BOOTLOADER_STANDALONE
268
+ − 170 static void ext_flash_overwrite_sample_without_erase(uint8_t *pSample, uint16_t length);
870
+ − 171 static void ext_flash_find_start(void);
+ − 172 #endif
38
+ − 173
+ − 174
+ − 175
+ − 176 /* Exported functions --------------------------------------------------------*/
+ − 177
+ − 178 void ext_flash_write_firmware(uint8_t *pSample1, uint32_t length1)//, uint8_t *pSample2, uint32_t length2)
+ − 179 {
+ − 180 general32to8_Type lengthTransform;
+ − 181
+ − 182 lengthTransform.u32 = length1;
+ − 183
+ − 184 actualPointerFirmware = FWSTART;
+ − 185 ef_write_block(lengthTransform.u8,4, EF_FIRMWARE, 1);
+ − 186 ef_write_block(pSample1,length1, EF_FIRMWARE, 1);
+ − 187
+ − 188 // if(length2)
+ − 189 // ef_write_block(pSample2,length2, EF_FIRMWARE, 1);
+ − 190 }
+ − 191
+ − 192 uint8_t ext_flash_read_firmware_version(char *text)
+ − 193 {
+ − 194 uint32_t backup = actualAddress;
+ − 195 uint8_t buffer[4];
+ − 196
+ − 197 // + 4 for length data, see ext_flash_write_firmware
+ − 198 actualAddress = FWSTART + 4 + 0x10000;
+ − 199 ext_flash_read_block_start();
+ − 200 ext_flash_read_block(&buffer[0], EF_FIRMWARE);
+ − 201 ext_flash_read_block(&buffer[1], EF_FIRMWARE);
+ − 202 ext_flash_read_block(&buffer[2], EF_FIRMWARE);
+ − 203 ext_flash_read_block(&buffer[3], EF_FIRMWARE);
+ − 204
+ − 205 ext_flash_read_block_stop();
+ − 206 actualAddress = backup;
+ − 207
+ − 208 uint8_t ptr = 0;
+ − 209 text[ptr++] = 'V';
+ − 210 ptr += gfx_number_to_string(2,0,&text[ptr],buffer[0] & 0x3F);
+ − 211 text[ptr++] = '.';
+ − 212 ptr += gfx_number_to_string(2,0,&text[ptr],buffer[1] & 0x3F);
+ − 213 text[ptr++] = '.';
+ − 214 ptr += gfx_number_to_string(2,0,&text[ptr],buffer[2] & 0x3F);
+ − 215 text[ptr++] = ' ';
+ − 216 if(buffer[3])
+ − 217 {
+ − 218 text[ptr++] = 'b';
+ − 219 text[ptr++] = 'e';
+ − 220 text[ptr++] = 't';
+ − 221 text[ptr++] = 'a';
+ − 222 text[ptr++] = ' ';
+ − 223 }
+ − 224 return ptr;
+ − 225 }
+ − 226
+ − 227
+ − 228 uint32_t ext_flash_read_firmware(uint8_t *pSample1, uint32_t max_length, uint8_t *magicByte)
+ − 229 {
+ − 230 uint32_t backup = actualAddress;
+ − 231 general32to8_Type lengthTransform;
+ − 232
+ − 233 actualAddress = FWSTART;
+ − 234 ext_flash_read_block_start();
+ − 235
+ − 236 ext_flash_read_block(&lengthTransform.u8[0], EF_FIRMWARE);
+ − 237 ext_flash_read_block(&lengthTransform.u8[1], EF_FIRMWARE);
+ − 238 ext_flash_read_block(&lengthTransform.u8[2], EF_FIRMWARE);
+ − 239 ext_flash_read_block(&lengthTransform.u8[3], EF_FIRMWARE);
+ − 240
+ − 241
+ − 242 if(lengthTransform.u32 == 0xFFFFFFFF)
+ − 243 {
+ − 244 lengthTransform.u32 = 0xFFFFFFFF;
+ − 245 }
+ − 246 else
+ − 247 if(lengthTransform.u32 > max_length)
+ − 248 {
+ − 249 lengthTransform.u32 = 0xFF000000;
+ − 250 }
+ − 251 else
+ − 252 {
+ − 253 for(uint32_t i = 0; i<lengthTransform.u32; i++)
+ − 254 {
+ − 255 ext_flash_read_block(&pSample1[i], EF_FIRMWARE);
+ − 256 }
+ − 257
+ − 258 }
+ − 259
+ − 260 ext_flash_read_block_stop();
+ − 261
+ − 262 if(magicByte)
+ − 263 {
+ − 264 *magicByte = pSample1[0x10000 + 0x3E]; // 0x3E == 62
+ − 265 }
+ − 266
+ − 267 actualAddress = backup;
+ − 268 return lengthTransform.u32;
+ − 269 }
+ − 270
+ − 271
+ − 272 void ext_flash_write_firmware2(uint32_t offset, uint8_t *pSample1, uint32_t length1, uint8_t *pSample2, uint32_t length2)
+ − 273 {
+ − 274 general32to8_Type lengthTransform, offsetTransform;
+ − 275
+ − 276 lengthTransform.u32 = length1 + length2;
+ − 277 offsetTransform.u32 = offset;
+ − 278
+ − 279 actualPointerFirmware2 = FWSTART2;
+ − 280 ef_write_block(lengthTransform.u8,4, EF_FIRMWARE2, 1);
+ − 281 ef_write_block(offsetTransform.u8,4, EF_FIRMWARE2, 1);
+ − 282 ef_write_block(pSample1,length1, EF_FIRMWARE2, 1);
+ − 283 if(length2)
+ − 284 ef_write_block(pSample2,length2, EF_FIRMWARE2, 1);
+ − 285 }
+ − 286
+ − 287
+ − 288 uint32_t ext_flash_read_firmware2(uint32_t *offset, uint8_t *pSample1, uint32_t max_length1, uint8_t *pSample2, uint32_t max_length2)
+ − 289 {
+ − 290 uint32_t backup = actualAddress;
+ − 291 uint32_t length1, length2;
+ − 292 general32to8_Type lengthTransform, offsetTransform;
+ − 293
+ − 294 actualAddress = FWSTART2;
+ − 295 ext_flash_read_block_start();
+ − 296
+ − 297 ext_flash_read_block(&lengthTransform.u8[0], EF_FIRMWARE2);
+ − 298 ext_flash_read_block(&lengthTransform.u8[1], EF_FIRMWARE2);
+ − 299 ext_flash_read_block(&lengthTransform.u8[2], EF_FIRMWARE2);
+ − 300 ext_flash_read_block(&lengthTransform.u8[3], EF_FIRMWARE2);
+ − 301
+ − 302 ext_flash_read_block(&offsetTransform.u8[0], EF_FIRMWARE2);
+ − 303 ext_flash_read_block(&offsetTransform.u8[1], EF_FIRMWARE2);
+ − 304 ext_flash_read_block(&offsetTransform.u8[2], EF_FIRMWARE2);
+ − 305 ext_flash_read_block(&offsetTransform.u8[3], EF_FIRMWARE2);
+ − 306
+ − 307 *offset = offsetTransform.u32;
+ − 308
+ − 309 if(lengthTransform.u32 == 0xFFFFFFFF)
+ − 310 {
+ − 311 lengthTransform.u32 = 0xFFFFFFFF;
+ − 312 }
+ − 313 else
+ − 314 if(lengthTransform.u32 > max_length1 + max_length2)
+ − 315 {
+ − 316 lengthTransform.u32 = 0xFF000000;
+ − 317 }
+ − 318 else
+ − 319 {
+ − 320 if(lengthTransform.u32 < max_length1)
+ − 321 {
+ − 322 length1 = lengthTransform.u32;
+ − 323 length2 = 0;
+ − 324 }
+ − 325 else
+ − 326 {
+ − 327 length1 = max_length1;
+ − 328 length2 = lengthTransform.u32 - max_length1;
+ − 329 }
+ − 330
+ − 331 if(pSample1)
+ − 332 {
+ − 333 for(uint32_t i = 0; i<length1; i++)
+ − 334 {
+ − 335 ext_flash_read_block(&pSample1[i], EF_FIRMWARE2);
+ − 336 }
+ − 337 if(pSample2)
+ − 338 {
+ − 339 for(uint32_t i = 0; i<length2; i++)
+ − 340 {
+ − 341 ext_flash_read_block(&pSample2[i], EF_FIRMWARE2);
+ − 342 }
+ − 343 }
+ − 344 }
+ − 345 else if(pSample2)
+ − 346 {
+ − 347 actualAddress += length1;
+ − 348 for(uint32_t i = 0; i<length2; i++)
+ − 349 {
+ − 350 ext_flash_read_block(&pSample2[i], EF_FIRMWARE2);
+ − 351 }
+ − 352 }
+ − 353 }
+ − 354 ext_flash_read_block_stop();
+ − 355 actualAddress = backup;
+ − 356 return lengthTransform.u32;
+ − 357 }
+ − 358
+ − 359
+ − 360 void ext_flash_read_fixed_16_devicedata_blocks_formated_128byte_total(uint8_t *buffer)
+ − 361 {
+ − 362 SDeviceLine data[16];
+ − 363 uint8_t tempLengthIngnore;
+ − 364 uint16_t count;
+ − 365 uint8_t transfer;
+ − 366
+ − 367 RTC_DateTypeDef Sdate;
+ − 368 RTC_TimeTypeDef Stime;
+ − 369
+ − 370 actualAddress = DDSTART;
+ − 371
+ − 372 ext_flash_read_block_start();
+ − 373 ext_flash_read_block(&tempLengthIngnore, EF_DEVICEDATA);
+ − 374 ext_flash_read_block(&tempLengthIngnore, EF_DEVICEDATA);
+ − 375
+ − 376 ext_flash_read_block_multi((uint8_t *)data,16*3*4, EF_DEVICEDATA);
+ − 377 ext_flash_read_block_stop();
+ − 378
+ − 379 count = 0;
+ − 380 for(int i=0;i<16;i++)
+ − 381 {
+ − 382 transfer = (data[i].value_int32 >> 24) & 0xFF;
+ − 383 buffer[count++] = transfer;
+ − 384 transfer = (data[i].value_int32 >> 16) & 0xFF;
+ − 385 buffer[count++] = transfer;
+ − 386 transfer = (data[i].value_int32 >> 8) & 0xFF;
+ − 387 buffer[count++] = transfer;
+ − 388 transfer = (data[i].value_int32) & 0xFF;
+ − 389 buffer[count++] = transfer;
+ − 390
+ − 391 translateDate(data[i].date_rtc_dr, &Sdate);
+ − 392 translateTime(data[i].time_rtc_tr, &Stime);
+ − 393 buffer[count++] = Sdate.Year;
+ − 394 buffer[count++] = Sdate.Month;
+ − 395 buffer[count++] = Sdate.Date;
+ − 396 buffer[count++] = Stime.Hours;
+ − 397 }
+ − 398 }
+ − 399
+ − 400
+ − 401 #ifndef BOOTLOADER_STANDALONE
+ − 402
421
+ − 403 void ext_flash_write_devicedata(uint8_t resetRing)
38
+ − 404 {
+ − 405 uint8_t *pData;
+ − 406 const uint16_t length = sizeof(SDevice);
+ − 407 uint8_t length_lo, length_hi;
+ − 408 uint8_t dataLength[2] = { 0 };
421
+ − 409 uint32_t tmpBlockStart;
38
+ − 410
+ − 411 ext_flash_disable_protection();
+ − 412
+ − 413 pData = (uint8_t *)stateDeviceGetPointer();
+ − 414
421
+ − 415 /* Reset the Ring to the start address if requested (e.g. because we write the default block during shutdown) */
+ − 416 if((resetRing) || ((actualPointerDevicedata + length) >= DDSTOP))
+ − 417 {
+ − 418 actualPointerDevicedata = DDSTART;
+ − 419 }
+ − 420 tmpBlockStart = actualPointerDevicedata;
38
+ − 421
+ − 422 length_lo = (uint8_t)(length & 0xFF);
+ − 423 length_hi = (uint8_t)(length >> 8);
+ − 424 dataLength[0] = length_lo;
+ − 425 dataLength[1] = length_hi;
+ − 426
+ − 427 ef_write_block(dataLength,2, EF_DEVICEDATA, 0);
+ − 428 ef_write_block(pData,length, EF_DEVICEDATA, 0);
421
+ − 429
+ − 430 actualPointerDevicedata_Read = tmpBlockStart;
+ − 431
38
+ − 432 }
+ − 433
+ − 434
+ − 435 uint16_t ext_flash_read_devicedata(uint8_t *buffer, uint16_t max_length)
+ − 436 {
+ − 437 uint16_t length;
+ − 438 uint8_t length_lo, length_hi;
+ − 439
421
+ − 440 actualAddress = actualPointerDevicedata_Read;
38
+ − 441
421
+ − 442 length = 0;
+ − 443 length_lo = 0;
+ − 444 length_hi = 0;
38
+ − 445 ext_flash_read_block_start();
421
+ − 446
+ − 447
38
+ − 448 ext_flash_read_block(&length_lo, EF_DEVICEDATA);
+ − 449 ext_flash_read_block(&length_hi, EF_DEVICEDATA);
+ − 450
421
+ − 451 while ((length_lo != 0xFF) && (length_hi != 0xFF))
+ − 452 {
+ − 453 length = (length_hi * 256) + length_lo;
+ − 454
+ − 455 if(length > max_length)
+ − 456 return 0;
+ − 457
+ − 458 ext_flash_read_block_multi(buffer,length,EF_DEVICEDATA);
+ − 459
+ − 460 ext_flash_read_block(&length_lo, EF_DEVICEDATA); /* check if another devicedata set is available */
+ − 461 ext_flash_read_block(&length_hi, EF_DEVICEDATA); /* length will be 0xFFFF if a empty memory is read */
+ − 462 }
+ − 463 ext_flash_decf_address_ring(EF_DEVICEDATA); /* set pointer back to empty address */
+ − 464 ext_flash_decf_address_ring(EF_DEVICEDATA);
38
+ − 465 ext_flash_read_block_stop();
421
+ − 466
+ − 467 if(actualAddress > actualPointerDevicedata) /* the write pointer has not yet been set up probably */
+ − 468 {
+ − 469 actualPointerDevicedata = actualAddress;
+ − 470 }
38
+ − 471 return length;
+ − 472 }
+ − 473
+ − 474
+ − 475 void ext_flash_write_vpm(SVpm *vpmInput)
+ − 476 {
+ − 477 uint8_t *pData;
+ − 478 const uint16_t length = sizeof(SVpm);
+ − 479
+ − 480 uint8_t length_lo, length_hi;
+ − 481 uint8_t dataLength[2] = { 0 };
+ − 482
+ − 483 pData = (uint8_t *)vpmInput;
+ − 484
+ − 485 actualPointerVPM = VPMSTART;
+ − 486
+ − 487 length_lo = (uint8_t)(length & 0xFF);
+ − 488 length_hi = (uint8_t)(length >> 8);
+ − 489 dataLength[0] = length_lo;
+ − 490 dataLength[1] = length_hi;
+ − 491
+ − 492 ef_write_block(dataLength,2, EF_VPMDATA, 0);
+ − 493 ef_write_block(pData,length, EF_VPMDATA, 0);
+ − 494 }
+ − 495
+ − 496
+ − 497 int ext_flash_read_vpm(SVpm *vpmOutput)
+ − 498 {
+ − 499 uint8_t *pData;
+ − 500 const uint16_t length = sizeof(SVpm);
+ − 501 uint8_t length_lo, length_hi;
+ − 502 int output;
+ − 503
+ − 504 actualAddress = VPMSTART;
+ − 505
+ − 506 ext_flash_read_block_start();
+ − 507 ext_flash_read_block(&length_lo, EF_VPMDATA);
+ − 508 ext_flash_read_block(&length_hi, EF_VPMDATA);
+ − 509 if((length_lo == (uint8_t)(length & 0xFF))
+ − 510 &&(length_hi == (uint8_t)(length >> 8)))
+ − 511 {
+ − 512 pData = (uint8_t *)vpmOutput;
+ − 513 for(uint16_t i = 0; i < length; i++)
+ − 514 ext_flash_read_block(&pData[i], EF_VPMDATA);
+ − 515 output = length;
+ − 516 }
+ − 517 else
+ − 518 output = 0;
+ − 519
+ − 520 ext_flash_read_block_stop();
+ − 521 return output;
+ − 522 }
+ − 523
+ − 524 #ifdef DEMOMODE
+ − 525 void ext_flash_write_settings(void)
+ − 526 {
+ − 527 return;
+ − 528 }
+ − 529 #else
427
+ − 530 void ext_flash_write_settings(uint8_t resetRing)
38
+ − 531 {
+ − 532 uint8_t *pData;
+ − 533 const uint16_t length = sizeof(SSettings);
+ − 534 uint8_t length_lo, length_hi;
+ − 535 uint8_t dataLength[2] = { 0 };
+ − 536
+ − 537 ext_flash_disable_protection();
+ − 538
+ − 539 if(stateRealGetPointer()->lastKnownBatteryPercentage)
+ − 540 {
+ − 541 settingsGetPointer()->lastKnownBatteryPercentage = stateRealGetPointer()->lastKnownBatteryPercentage;
+ − 542 }
+ − 543 settingsGetPointer()->backup_localtime_rtc_tr = stateRealGetPointer()->lifeData.timeBinaryFormat;
+ − 544 settingsGetPointer()->backup_localtime_rtc_dr = stateRealGetPointer()->lifeData.dateBinaryFormat;
+ − 545
+ − 546 pData = (uint8_t *)settingsGetPointer();
+ − 547
427
+ − 548 /* Reset the Ring to the start address if requested (e.g. because we write the default block during shutdown) */
+ − 549 if((resetRing) || ((actualPointerSettings + length) >= SETTINGSSTOP))
+ − 550 {
+ − 551 actualPointerSettings = SETTINGSSTART;
+ − 552 }
38
+ − 553
+ − 554 length_lo = (uint8_t)(length & 0xFF);
+ − 555 length_hi = (uint8_t)(length >> 8);
+ − 556 dataLength[0] = length_lo;
+ − 557 dataLength[1] = length_hi;
+ − 558
+ − 559 ef_write_block(dataLength,2, EF_SETTINGS, 0);
+ − 560 ef_write_block(pData,length, EF_SETTINGS, 0);
+ − 561 // ext_flash_enable_protection();
+ − 562 }
+ − 563 #endif
+ − 564
+ − 565
+ − 566 /* CHANGES 150929 hw
+ − 567 * this now allows to read old settings too
+ − 568 * but make sure that everything is fixed in
+ − 569 * set_new_settings_missing_in_ext_flash
+ − 570 * new settings should be fine as they are added
+ − 571 * and loaded before calling this function
+ − 572 */
+ − 573 uint8_t ext_flash_read_settings(void)
+ − 574 {
+ − 575 uint8_t returnValue = HAL_BUSY;
538
+ − 576 uint8_t exit = 0;
38
+ − 577 uint8_t *pData;
+ − 578 const uint16_t lengthStandardNow = sizeof(SSettings);
+ − 579 uint8_t length_lo, length_hi;
+ − 580 uint16_t lengthOnEEPROM;
+ − 581 uint32_t header;
+ − 582 SSettings *pSettings = settingsGetPointer();
+ − 583
+ − 584 actualAddress = SETTINGSSTART;
+ − 585
+ − 586 ext_flash_read_block_start();
+ − 587 ext_flash_read_block(&length_lo, EF_SETTINGS);
+ − 588 ext_flash_read_block(&length_hi, EF_SETTINGS);
+ − 589
538
+ − 590 while ((length_lo != 0xFF) && (length_hi != 0xFF) && (exit == 0)) /* get the latest stored setting block */
38
+ − 591 {
427
+ − 592 lengthOnEEPROM = length_hi * 256;
+ − 593 lengthOnEEPROM += length_lo;
538
+ − 594 if(lengthOnEEPROM <= lengthStandardNow) /* EEPROM Header size equal or smaller => settings constant or upgraded */
38
+ − 595 {
427
+ − 596 ext_flash_read_block_multi(&header, 4, EF_SETTINGS);
538
+ − 597 if((header <= pSettings->header) && (header >= pSettings->updateSettingsAllowedFromHeader)) /* check to allow update of header */
427
+ − 598 {
+ − 599 returnValue = HAL_OK;
+ − 600 pSettings->header = header;
+ − 601 pData = (uint8_t *)pSettings + 4; /* header */
+ − 602 for(uint16_t i = 0; i < (lengthOnEEPROM-4); i++)
+ − 603 ext_flash_read_block(&pData[i], EF_SETTINGS);
538
+ − 604 if(header != pSettings->header) /* setting layout changed => no additional setting sets expected */
+ − 605 {
+ − 606 exit = 1;
+ − 607 }
+ − 608 }
+ − 609 else
+ − 610 {
+ − 611 returnValue = HAL_ERROR;
+ − 612 exit = 1;
+ − 613 }
+ − 614 }
+ − 615 else /* size of settings decreased => possible downgrade of firmware */
+ − 616 {
+ − 617 ext_flash_read_block_multi(&header, 4, EF_SETTINGS);
+ − 618
+ − 619 if(header > 0xFFFF0014) /* verify that new (old) header should be compatible (only less bytes, no change in layout) */
+ − 620 {
+ − 621 returnValue = HAL_OK;
+ − 622 pSettings->header = header;
+ − 623 pData = (uint8_t *)pSettings + 4; /* header */
+ − 624 for(uint16_t i = 0; i < (lengthStandardNow-4); i++) /* only read the data fitting into the structure */
+ − 625 ext_flash_read_block(&pData[i], EF_SETTINGS);
427
+ − 626 }
+ − 627 else
+ − 628 {
+ − 629 returnValue = HAL_ERROR;
+ − 630 }
538
+ − 631 exit = 1;
38
+ − 632 }
427
+ − 633 ext_flash_read_block(&length_lo, EF_SETTINGS);
+ − 634 ext_flash_read_block(&length_hi, EF_SETTINGS);
+ − 635 }
+ − 636 ext_flash_decf_address_ring(EF_SETTINGS); /* set pointer back to empty address */
+ − 637 ext_flash_decf_address_ring(EF_SETTINGS);
+ − 638 ext_flash_read_block_stop();
+ − 639
+ − 640 if(actualAddress > actualPointerSettings) /* the write pointer has not yet been set up probably */
+ − 641 {
+ − 642 actualPointerSettings = actualAddress;
38
+ − 643 }
+ − 644 ext_flash_read_block_stop();
+ − 645 return returnValue;
+ − 646 }
+ − 647
+ − 648
+ − 649
+ − 650
+ − 651 /* ext_flash_start_new_dive_log_and_set_actualPointerSample
+ − 652 * prepares the write sample pointer
+ − 653 * to be used by ext_flash_write_sample()
+ − 654 * to be set in the * pHeaderPreDive
+ − 655 * for write with ext_flash_create_new_dive_log() and ext_flash_close_new_dive_log()
+ − 656 */
+ − 657 void ext_flash_start_new_dive_log_and_set_actualPointerSample(uint8_t *pHeaderPreDive)
+ − 658 {
+ − 659 convert_Type data;
+ − 660 SSettings *settings = settingsGetPointer();
+ − 661
+ − 662 /* new 5. Jan. 2015 */
+ − 663 actualPointerSample = settings->logFlashNextSampleStartAddress;
+ − 664
+ − 665 if(!ext_flash_test_remaining_space_of_page_empty(actualPointerSample, 4))
+ − 666 ext_flash_set_to_begin_of_next_page(&actualPointerSample, EF_SAMPLE);
+ − 667
+ − 668 if((actualPointerSample < SAMPLESTART) || (actualPointerSample > SAMPLESTOP))
+ − 669 actualPointerSample = SAMPLESTART;
+ − 670
+ − 671 data.u32bit = actualPointerSample;
+ − 672 pHeaderPreDive[2] = data.u8bit.byteLow;
+ − 673 pHeaderPreDive[3] = data.u8bit.byteMidLow;
+ − 674 pHeaderPreDive[4] = data.u8bit.byteMidHigh;
+ − 675 /* to start sample writing and header etc. pp. */
+ − 676 ext_flash_disable_protection_for_logbook();
+ − 677 }
+ − 678
+ − 679
+ − 680 /* ext_flash_create_new_dive_log
+ − 681 * uses the first header without HEADER2OFFSET
+ − 682 * for the header it is not important to be complete
+ − 683 * and can be reconstructed
+ − 684 * ext_flash_start_new_dive_log_and_set_actualPointerSample()
+ − 685 * has to be called before to set the actualPointerSample
+ − 686 * in the header
+ − 687 * the following func writes to header to the ext_flash
+ − 688 */
+ − 689 void ext_flash_create_new_dive_log(uint8_t *pHeaderPreDive)
+ − 690 {
+ − 691 SSettings *settings;
429
+ − 692 uint8_t id;
38
+ − 693 uint8_t header1, header2;
+ − 694
+ − 695 settings = settingsGetPointer();
+ − 696 id = settings->lastDiveLogId;
+ − 697
+ − 698 actualAddress = HEADERSTART + (0x800 * id);
+ − 699 ext_flash_read_block_start();
429
+ − 700 ext_flash_read_block(&header1, EF_SAMPLE); /* the sample ring is increased instead of header... not sure if that is planned intention */
+ − 701 ext_flash_read_block(&header2, EF_SAMPLE); /* does not matter because actual address is reset in write_block call */
38
+ − 702 ext_flash_read_block_stop();
+ − 703
429
+ − 704 /* TODO Cleanup_Ref_2: The code below should not be necessary in case of a proper shutdown and startup */
+ − 705 /* the implementation fixes an issue which might happen at Cleanup_Ref_1 (in case of more then 254 dives) */
38
+ − 706 if((header1 == 0xFA) && (header2 == 0xFA))
+ − 707 {
+ − 708 id += 1; /* 0-255, auto rollover */
+ − 709 if(id & 1)
+ − 710 {
+ − 711 actualAddress = HEADERSTART + (0x800 * id);
+ − 712 ext_flash_read_block_start();
+ − 713 ext_flash_read_block(&header1, EF_SAMPLE);
+ − 714 ext_flash_read_block(&header2, EF_SAMPLE);
+ − 715 ext_flash_read_block_stop();
+ − 716 if((header1 == 0xFA) && (header2 == 0xFA))
+ − 717 id += 1;
+ − 718 }
+ − 719 }
+ − 720 else
+ − 721 {
+ − 722 id = 0;
+ − 723 }
+ − 724
+ − 725 settings->lastDiveLogId = id;
+ − 726 actualPointerHeader = HEADERSTART + (0x800 * id);
+ − 727
+ − 728 if(pHeaderPreDive != 0)
+ − 729 ef_write_block(pHeaderPreDive,HEADERSIZE, EF_HEADER, 0);
+ − 730 }
+ − 731
+ − 732
+ − 733 void ext_flash_close_new_dive_log(uint8_t *pHeaderPostDive )
+ − 734 {
+ − 735 SSettings * settings = settingsGetPointer();
+ − 736 uint8_t id;
+ − 737 convert_Type startAddress;
+ − 738 convert_Type data;
+ − 739 uint32_t backup;
+ − 740
+ − 741 uint8_t sampleData[3];
+ − 742 actualAddress = actualPointerSample;
+ − 743 sampleData[0] = 0xFD;
+ − 744 sampleData[1] = 0xFD;
+ − 745 ext_flash_write_sample(sampleData, 2);
+ − 746
+ − 747 /* end of sample data, pointing to the last sample 0xFD
+ − 748 */
+ − 749 actualAddress = actualPointerSample; // change hw 17.09.2015
+ − 750 ext_flash_decf_address_ring(EF_SAMPLE); // 17.09.2015: this decf actualAddress only!!
+ − 751 actualPointerSample = actualAddress; // change hw 17.09.2015
+ − 752 data.u32bit = actualPointerSample;
+ − 753
+ − 754 pHeaderPostDive[5] = data.u8bit.byteLow;
+ − 755 pHeaderPostDive[6] = data.u8bit.byteMidLow;
+ − 756 pHeaderPostDive[7] = data.u8bit.byteMidHigh;
+ − 757
+ − 758 /* take data written before, calculate length and write
+ − 759 SLogbookHeader has different order: length (byte# 8,9,10) prior to profile version (byte# 11)
+ − 760 */
+ − 761 startAddress.u8bit.byteLow = pHeaderPostDive[2];
+ − 762 startAddress.u8bit.byteMidLow = pHeaderPostDive[3];
+ − 763 startAddress.u8bit.byteMidHigh = pHeaderPostDive[4];
+ − 764 startAddress.u8bit.byteHigh = 0;
+ − 765
+ − 766 if(startAddress.u32bit < actualPointerSample)
+ − 767 data.u32bit = 1 + actualPointerSample - startAddress.u32bit;
+ − 768 else
+ − 769 data.u32bit = 2 + (actualPointerSample - SAMPLESTART) + (SAMPLESTOP - startAddress.u32bit);
+ − 770
+ − 771 pHeaderPostDive[8] = data.u8bit.byteLow;
+ − 772 pHeaderPostDive[9] = data.u8bit.byteMidLow;
+ − 773 pHeaderPostDive[10] = data.u8bit.byteMidHigh;
+ − 774
+ − 775 /* set id and write post-dive-header
+ − 776 */
+ − 777 id = settings->lastDiveLogId;
+ − 778 actualPointerHeader = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
+ − 779
+ − 780 ef_write_block(pHeaderPostDive,HEADERSIZE, EF_HEADER, 0);
+ − 781
+ − 782 /* write length at beginning of sample
+ − 783 and write proper beginning for next dive to actualPointerSample
+ − 784 */
+ − 785 backup = actualPointerSample;
+ − 786 actualPointerSample = startAddress.u32bit; // is still 0xFF
+ − 787 sampleData[0] = data.u8bit.byteLow;
+ − 788 sampleData[1] = data.u8bit.byteMidLow;
+ − 789 sampleData[2] = data.u8bit.byteMidHigh;
+ − 790 ext_flash_overwrite_sample_without_erase(sampleData, 3);
+ − 791
+ − 792 actualAddress = backup;
+ − 793 ext_flash_incf_address(EF_SAMPLE);
+ − 794 actualPointerSample = actualAddress;
+ − 795 ext_flash_enable_protection();
+ − 796 }
+ − 797
+ − 798
+ − 799 void ext_flash_write_sample(uint8_t *pSample, uint16_t length)
+ − 800 {
423
+ − 801 uint32_t actualAdressBackup = 0;
+ − 802
38
+ − 803 ef_write_block(pSample,length, EF_SAMPLE, 0);
+ − 804
+ − 805 SSettings *settings = settingsGetPointer();
+ − 806 settings->logFlashNextSampleStartAddress = actualPointerSample;
423
+ − 807
+ − 808 if(0xFFFF - (actualAddress & 0x0000FFFF) < 255) /* are we close to a sector border? */
+ − 809 {
+ − 810 if (((actualAddress & 0x0000FFFF) != 0) && (preparedPageAddress == 0)) /* only prepare if not already at start of sector */
+ − 811 {
+ − 812 actualAdressBackup = actualAddress;
+ − 813 actualAddress = (actualAddress & 0xFFFF0000) + 0x00010000; /* Set to start of next 64k sector */
+ − 814 if(actualAddress >= SAMPLESTOP)
+ − 815 {
+ − 816 actualAddress = SAMPLESTART;
+ − 817 }
+ − 818 preparedPageAddress = actualAddress;
+ − 819 ext_flash_erase64kB();
+ − 820 actualAddress = actualAdressBackup;
+ − 821 }
+ − 822 }
38
+ − 823 }
+ − 824
268
+ − 825 static void ext_flash_overwrite_sample_without_erase(uint8_t *pSample, uint16_t length)
38
+ − 826 {
+ − 827 ef_write_block(pSample,length, EF_SAMPLE, 1);
+ − 828 }
+ − 829
+ − 830
+ − 831 uint8_t ext_flash_count_dive_headers(void)
+ − 832 {
+ − 833 uint8_t id = 0;
+ − 834 uint8_t counter = 0;
+ − 835 uint16_t headerStartData = 0x0000;
+ − 836
+ − 837 id = settingsGetPointer()->lastDiveLogId;
+ − 838
+ − 839 do
+ − 840 {
+ − 841 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
+ − 842 ext_flash_read_block_start();
+ − 843 ext_flash_read_block_multi((uint8_t *)&headerStartData, 2, EF_HEADER);
+ − 844 ext_flash_read_block_stop();
+ − 845 counter++;
+ − 846 id -=1;
+ − 847 } while((headerStartData == 0xFAFA) && (counter < 255));
+ − 848 return (counter - 1);
+ − 849 }
+ − 850
+ − 851
+ − 852 void ext_flash_read_dive_header(uint8_t *pHeaderToFill, uint8_t StepBackwards)
+ − 853 {
+ − 854 SSettings *settings;
+ − 855 uint8_t id;
+ − 856 uint16_t i;
+ − 857
+ − 858 settings = settingsGetPointer();
+ − 859 id = settings->lastDiveLogId;
+ − 860 id -= StepBackwards; /* 0-255, auto rollover */
+ − 861
+ − 862 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
+ − 863 ext_flash_read_block_start();
+ − 864 for(i = 0; i < HEADERSIZE; i++)
+ − 865 ext_flash_read_block(&pHeaderToFill[i], EF_HEADER);
+ − 866 ext_flash_read_block_stop();
+ − 867
+ − 868 }
+ − 869
+ − 870 void ext_flash_read_dive_header2(uint8_t *pHeaderToFill, uint8_t id, _Bool bOffset)
+ − 871 {
+ − 872
+ − 873 uint16_t i;
+ − 874 actualAddress = HEADERSTART + (0x800 * id) ;
+ − 875
+ − 876 if(bOffset)
+ − 877 actualAddress += HEADER2OFFSET;
+ − 878 ext_flash_read_block_start();
+ − 879 for(i = 0; i < HEADERSIZE; i++)
+ − 880 ext_flash_read_block(&pHeaderToFill[i], EF_HEADER);
+ − 881 ext_flash_read_block_stop();
+ − 882 }
+ − 883
+ − 884
+ − 885 uint32_t ext_flash_read_dive_raw_with_double_header_1K(uint8_t *data, uint32_t max_size, uint8_t StepBackwards)
+ − 886 {
+ − 887 if(max_size < 0x800)
+ − 888 return 0;
+ − 889
+ − 890 uint8_t id;
+ − 891 convert_Type dataStart, dataEnd;
+ − 892 uint32_t LengthAll = 0;
+ − 893
+ − 894 id = settingsGetPointer()->lastDiveLogId;
+ − 895 id -= StepBackwards; /* 0-255, auto rollover */
+ − 896
+ − 897 // clear data
+ − 898 for(int i=0;i<0x800;i++)
+ − 899 data[i] = 0xFF;
+ − 900
+ − 901 // copy primary/pre-dive
+ − 902 actualAddress = HEADERSTART + (0x800 * id);
+ − 903 ext_flash_read_block_start();
+ − 904 for(int i = 0; i < HEADERSIZE; i++)
+ − 905 ext_flash_read_block(&data[i], EF_HEADER);
+ − 906 ext_flash_read_block_stop();
+ − 907
+ − 908 // copy main/secondary/post-dive
+ − 909 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
+ − 910 ext_flash_read_block_start();
+ − 911 for(int i = 0x400; i < HEADERSIZE+0x400; i++)
+ − 912 ext_flash_read_block(&data[i], EF_HEADER);
+ − 913 ext_flash_read_block_stop();
+ − 914
+ − 915 // data
+ − 916
+ − 917 dataStart.u8bit.byteHigh = 0;
+ − 918 dataStart.u8bit.byteLow = data[0x402];
+ − 919 dataStart.u8bit.byteMidLow = data[0x403];
+ − 920 dataStart.u8bit.byteMidHigh = data[0x404];
+ − 921
+ − 922 dataEnd.u8bit.byteHigh = 0;
+ − 923 dataEnd.u8bit.byteLow = data[0x405];
+ − 924 dataEnd.u8bit.byteMidLow = data[0x406];
+ − 925 dataEnd.u8bit.byteMidHigh = data[0x407];
+ − 926
+ − 927 actualPointerSample = dataStart.u32bit;
+ − 928 if(dataEnd.u32bit >= dataStart.u32bit)
+ − 929 LengthAll = 1 + dataEnd.u32bit - dataStart.u32bit;
+ − 930 else
+ − 931 LengthAll = 2 + (dataStart.u32bit - SAMPLESTART) + (SAMPLESTOP - dataEnd.u32bit);
+ − 932
+ − 933 LengthAll += 0x800;
+ − 934
+ − 935 if(LengthAll > max_size)
+ − 936 return 0x800;
+ − 937
+ − 938 actualAddress = actualPointerSample;
+ − 939 ext_flash_read_block_start();
+ − 940 for(uint32_t i = 0x800; i < LengthAll; i++)
+ − 941 ext_flash_read_block(&data[i], EF_SAMPLE);
+ − 942 ext_flash_read_block_stop();
+ − 943 return LengthAll;
+ − 944 }
+ − 945
+ − 946 void ext_flash_write_dive_raw_with_double_header_1K(uint8_t *data, uint32_t length)
+ − 947 {
+ − 948 convert_Type dataStart, dataEnd;
+ − 949 SLogbookHeader headerTemp;
+ − 950
+ − 951 // set actualPointerSample and get pointer to sample storage and disable flash write protect
+ − 952 ext_flash_start_new_dive_log_and_set_actualPointerSample((uint8_t *)&headerTemp);
+ − 953
+ − 954 dataStart.u8bit.byteHigh = 0;
+ − 955 dataStart.u8bit.byteLow = headerTemp.pBeginProfileData[0];
+ − 956 dataStart.u8bit.byteMidLow = headerTemp.pBeginProfileData[1];
+ − 957 dataStart.u8bit.byteMidHigh = headerTemp.pBeginProfileData[2];
+ − 958
+ − 959 dataEnd.u32bit = dataStart.u32bit + length - 0x801;
+ − 960 if(dataEnd.u32bit > SAMPLESTOP)
+ − 961 dataEnd.u32bit -= SAMPLESTOP + SAMPLESTART - 1;
+ − 962
+ − 963 data[0x002] = data[0x402] = dataStart.u8bit.byteLow;
+ − 964 data[0x003] = data[0x403] = dataStart.u8bit.byteMidLow;
+ − 965 data[0x004] = data[0x404] = dataStart.u8bit.byteMidHigh;
+ − 966 data[0x005] = data[0x405] = dataEnd.u8bit.byteLow;
+ − 967 data[0x006] = data[0x406] = dataEnd.u8bit.byteMidLow;
+ − 968 data[0x007] = data[0x407] = dataEnd.u8bit.byteMidHigh;
+ − 969
+ − 970 // set actualPointerHeader to next free header and update lastDiveLogId
+ − 971 ext_flash_create_new_dive_log(0);
+ − 972
+ − 973 // copy header data
+ − 974 ef_write_block(data,0x800,EF_HEADER, 1);
+ − 975
+ − 976 // copy sample data
+ − 977 ef_write_block(&data[0x800], length-0x800, EF_SAMPLE, 1);
+ − 978
+ − 979 // update logFlashNextSampleStartAddress
+ − 980 settingsGetPointer()->logFlashNextSampleStartAddress = actualPointerSample;
+ − 981 }
+ − 982
+ − 983
+ − 984 // ===============================================================================
+ − 985 // ext_flash_read_header_memory
+ − 986 /// @brief This function returns the entire header space 1:1
+ − 987 /// @date 04-April-2016
+ − 988 ///
+ − 989 /// @param *data 256KB output
+ − 990 // ===============================================================================
+ − 991 void ext_flash_read_header_memory(uint8_t *data)
+ − 992 {
+ − 993 actualAddress = HEADERSTART;
+ − 994 actualPointerHeader = actualAddress;
+ − 995 ext_flash_read_block_start();
+ − 996 for(int i=0;i<8;i++)
+ − 997 ext_flash_read_block_multi(&data[0x8000 * i], 0x8000, EF_HEADER);
+ − 998 ext_flash_read_block_stop();
+ − 999 }
+ − 1000
+ − 1001
+ − 1002 // ===============================================================================
463
+ − 1003 // ext_flash_write_header_memory
38
+ − 1004 /// @brief This function erases and overwrites the entire logbook header block
+ − 1005 /// @date 04-April-2016
+ − 1006 ///
+ − 1007 /// @param *data 256KB input of header memory 1:1
+ − 1008 // ===============================================================================
+ − 1009 void ext_flash_write_header_memory(uint8_t *data)
+ − 1010 {
+ − 1011 actualAddress = HEADERSTART;
+ − 1012 actualPointerHeader = actualAddress;
+ − 1013 ef_write_block(data, 0x40000, EF_HEADER, 0);
+ − 1014 }
+ − 1015
463
+ − 1016 void ext_flash_read_sample_memory(uint8_t *data,uint16_t blockId)
+ − 1017 {
+ − 1018 actualAddress = SAMPLESTART;
+ − 1019 actualAddress += blockId * 0x8000; /* add 32k Block offset */
+ − 1020 actualPointerSample = actualAddress;
+ − 1021 ext_flash_read_block_start();
+ − 1022 ext_flash_read_block_multi(data, 0x8000, EF_SAMPLE);
+ − 1023 ext_flash_read_block_stop();
+ − 1024 }
+ − 1025
+ − 1026 void ext_flash_write_sample_memory(uint8_t *data,uint16_t blockId)
+ − 1027 {
+ − 1028 actualAddress = SAMPLESTART;
+ − 1029 actualAddress += blockId * 0x8000; /* add 32k Block offset */
+ − 1030 actualPointerSample = actualAddress;
+ − 1031 ef_write_block(data, 0x8000, EF_SAMPLE,0);
+ − 1032 }
+ − 1033
38
+ − 1034
+ − 1035 void ext_flash_open_read_sample(uint8_t StepBackwards, uint32_t *totalNumberOfBytes)
+ − 1036 {
+ − 1037 SSettings *settings = settingsGetPointer();
+ − 1038 uint8_t id;
+ − 1039 convert_Type dataStart, dataEnd;
+ − 1040 uint8_t header1, header2;
+ − 1041
+ − 1042 id = settings->lastDiveLogId;
+ − 1043 id -= StepBackwards; /* 0-255, auto rollover */
+ − 1044 #
+ − 1045 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
+ − 1046 actualPointerHeader = actualAddress;
+ − 1047
+ − 1048 ext_flash_read_block_start();
+ − 1049 /* little endian */
+ − 1050 ext_flash_read_block(&header1, EF_HEADER);
+ − 1051 ext_flash_read_block(&header2, EF_HEADER);
+ − 1052 dataStart.u8bit.byteHigh = 0;
+ − 1053 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER);
+ − 1054 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER);
+ − 1055 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER);
+ − 1056 dataEnd.u8bit.byteHigh = 0;
+ − 1057 ext_flash_read_block(&dataEnd.u8bit.byteLow, EF_HEADER);
+ − 1058 ext_flash_read_block(&dataEnd.u8bit.byteMidLow, EF_HEADER);
+ − 1059 ext_flash_read_block(&dataEnd.u8bit.byteMidHigh, EF_HEADER);
+ − 1060 ext_flash_read_block_stop();
+ − 1061
+ − 1062 actualPointerSample = dataStart.u32bit;
+ − 1063 if(dataEnd.u32bit >= dataStart.u32bit)
+ − 1064 LengthLeftSampleRead = 1 + dataEnd.u32bit - dataStart.u32bit;
+ − 1065 else
+ − 1066 LengthLeftSampleRead = 2 + (dataStart.u32bit - SAMPLESTART) + (SAMPLESTOP - dataEnd.u32bit);
+ − 1067 *totalNumberOfBytes = LengthLeftSampleRead;
+ − 1068
+ − 1069 actualAddress = actualPointerSample;
+ − 1070 ext_flash_read_block_start();
+ − 1071 }
+ − 1072
+ − 1073
+ − 1074 void ext_flash_read_next_sample_part(uint8_t *pSample, uint8_t length)
+ − 1075 {
+ − 1076 for(uint16_t i = 0; i < length; i++)
+ − 1077 ext_flash_read_block(&pSample[i], EF_SAMPLE);
+ − 1078 }
+ − 1079
+ − 1080
+ − 1081 void ext_flash_close_read_sample(void)
+ − 1082 {
+ − 1083 actualPointerSample = actualAddress;
+ − 1084 ext_flash_read_block_stop();
+ − 1085 }
+ − 1086
+ − 1087
+ − 1088 void ext_flash_set_entry_point(void)
+ − 1089 {
+ − 1090 entryPoint = actualAddress;
+ − 1091 }
+ − 1092
+ − 1093
+ − 1094 void ext_flash_reopen_read_sample_at_entry_point(void)
+ − 1095 {
+ − 1096 error_led_on();
+ − 1097 chip_unselect();
+ − 1098 wait_chip_not_busy();
+ − 1099
+ − 1100 actualAddress = entryPoint;
+ − 1101 ext_flash_read_block_start();
+ − 1102 error_led_off();
+ − 1103 }
+ − 1104
+ − 1105 /*
+ − 1106 uint8_t ext_flash_point_to_64k_block_in_headerSpace(uint8_t logId)
+ − 1107 {
+ − 1108 uint32_t pointerToData = logId * 0x800;
+ − 1109
+ − 1110 return pointerToData / 0x10000;
+ − 1111 }
+ − 1112 */
+ − 1113
+ − 1114
+ − 1115 // ===============================================================================
+ − 1116 // ext_flash_repair_dive_numbers_starting_count_helper
+ − 1117 /// @brief
+ − 1118 /// @date 22-June-2016
+ − 1119
+ − 1120 // ===============================================================================
268
+ − 1121 static uint16_t ext_flash_repair_dive_numbers_starting_count_helper(uint8_t *data, uint8_t *change64k, uint16_t startNumber, uint8_t lastLogId)
38
+ − 1122 {
+ − 1123 const uint32_t headerStep = 0x800;
+ − 1124 uint8_t actualLogId = 0;
+ − 1125 uint16_t oldNumber = 0;
+ − 1126 uint16_t actualNumber = 0;
+ − 1127 SLogbookHeader *ptrLogbookHeader = 0;
+ − 1128
+ − 1129 if(startNumber == 0)
+ − 1130 return 0;
+ − 1131
+ − 1132 actualNumber = startNumber - 1;
+ − 1133
282
+ − 1134 // where is the oldest dive (Which is now getting startNumber)
38
+ − 1135 // use first header for ease (without HEADER2OFFSET for end of dive header)
+ − 1136 // compare for lastLogId to prevent endless loop
+ − 1137
+ − 1138 if(*(uint16_t*)&data[lastLogId * headerStep] != 0xFAFA)
+ − 1139 return 0;
+ − 1140
+ − 1141 actualLogId = lastLogId - 1;
+ − 1142 while((*(uint16_t*)&data[actualLogId * headerStep] == 0xFAFA) && (actualLogId != lastLogId))
+ − 1143 {
+ − 1144 actualLogId--;
+ − 1145 }
+ − 1146
+ − 1147 // now pointing to one behind the last
+ − 1148 while(actualLogId != lastLogId)
+ − 1149 {
+ − 1150 actualLogId++;
+ − 1151 actualNumber++;
+ − 1152 ptrLogbookHeader = (SLogbookHeader *)&data[actualLogId * headerStep];
+ − 1153
+ − 1154 oldNumber = ptrLogbookHeader->diveNumber;
+ − 1155 if(oldNumber != actualNumber)
+ − 1156 {
+ − 1157 // change64k[ext_flash_point_to_64k_block_in_headerSpace(actualLogId )] = 1;
+ − 1158 change64k[(actualLogId * 0x800)/0x10000] = 1;
+ − 1159 ptrLogbookHeader->diveNumber = actualNumber;
+ − 1160 ptrLogbookHeader = (SLogbookHeader *)(&data[actualLogId * headerStep] + HEADER2OFFSET);
+ − 1161 ptrLogbookHeader->diveNumber = actualNumber;
+ − 1162 }
+ − 1163 }
+ − 1164
+ − 1165 return actualNumber;
+ − 1166 }
+ − 1167
+ − 1168 // ===============================================================================
+ − 1169 // ext_flash_repair_SPECIAL_dive_numbers_starting_count_with
+ − 1170 /// @brief This function
+ − 1171 /// @date 04-April-2016
282
+ − 1172 /// problem (160621): 64K blocks (32 dives) in the new flash memory chip
+ − 1173 /// This block needs to be deleted
+ − 1174 /// these where only 4KB block before
38
+ − 1175 /// @output endCount, last diveNumber
+ − 1176
+ − 1177 // ===============================================================================
+ − 1178 uint16_t ext_flash_repair_SPECIAL_dive_numbers_starting_count_with(uint16_t startCount)
+ − 1179 {
+ − 1180 uint32_t logCopyDataPtr = 0;
+ − 1181 uint8_t *data;
+ − 1182 uint16_t lastCount;
282
+ − 1183 uint8_t listOfChanged64kBlocks[8]; // 32 dives each 64K
38
+ − 1184
+ − 1185 logCopyDataPtr = getFrame(97);
+ − 1186 data = (uint8_t *)logCopyDataPtr;
+ − 1187
+ − 1188 for(int i=0;i<8;i++)
+ − 1189 listOfChanged64kBlocks[i] = 0;
+ − 1190
+ − 1191 actualAddress = HEADERSTART;
+ − 1192 ext_flash_read_block_start();
+ − 1193 ext_flash_read_block_multi(data,0x100000,EF_HEADER);
+ − 1194 ext_flash_read_block_stop();
+ − 1195
+ − 1196 lastCount = ext_flash_repair_dive_numbers_starting_count_helper(data, listOfChanged64kBlocks, startCount, settingsGetPointer()->lastDiveLogId);
+ − 1197
+ − 1198 for(int i=0;i<8;i++)
+ − 1199 {
+ − 1200 if(listOfChanged64kBlocks[i] != 0)
+ − 1201 {
+ − 1202 actualPointerHeader = HEADERSTART + (i * 0x10000);
+ − 1203 ef_write_block(&data[i * 0x10000], 0x10000, EF_HEADER, 0);
+ − 1204 }
+ − 1205 }
+ − 1206
+ − 1207 releaseFrame(97,logCopyDataPtr);
+ − 1208 if(settingsGetPointer()->totalDiveCounter < lastCount)
+ − 1209 {
+ − 1210 settingsGetPointer()->totalDiveCounter = lastCount;
+ − 1211 }
+ − 1212 return lastCount;
+ − 1213 }
+ − 1214
268
+ − 1215 /*
38
+ − 1216 void OLD_ext_flash_repair_SPECIAL_dive_numbers_starting_count_with(uint16_t startCount)
+ − 1217 {
+ − 1218 uint16_t counterStorage[256];
+ − 1219 uint8_t start = 0xFF;
+ − 1220 uint32_t logCopyDataPtr = 0;
+ − 1221 uint8_t *data;
+ − 1222 uint8_t startAbsolute = 0;
+ − 1223 int16_t count = 0;
+ − 1224 _Bool repair = 0;
+ − 1225 uint8_t startBackup = 0;
+ − 1226
+ − 1227 SLogbookHeader tempLogbookHeader;
+ − 1228 SLogbookHeader *ptrHeaderInData1a;
+ − 1229 SLogbookHeader *ptrHeaderInData1b;
+ − 1230 SLogbookHeader *ptrHeaderInData2a;
+ − 1231 SLogbookHeader *ptrHeaderInData2b;
+ − 1232
+ − 1233 logCopyDataPtr = getFrame(97);
+ − 1234 data = (uint8_t *)logCopyDataPtr;
+ − 1235 ptrHeaderInData1a = (SLogbookHeader *)logCopyDataPtr;
+ − 1236 ptrHeaderInData1b = (SLogbookHeader *)(logCopyDataPtr + HEADER2OFFSET);
+ − 1237 ptrHeaderInData2a = (SLogbookHeader *)(logCopyDataPtr + 0x800);
+ − 1238 ptrHeaderInData2b = (SLogbookHeader *)(logCopyDataPtr + 0x800 + HEADER2OFFSET);
+ − 1239
+ − 1240 // get data
+ − 1241 for(int StepBackwards = 0; StepBackwards < 255; StepBackwards++)
+ − 1242 {
+ − 1243 logbook_getHeader(StepBackwards, &tempLogbookHeader);
+ − 1244 counterStorage[StepBackwards+1] = tempLogbookHeader.diveNumber;
+ − 1245 if(tempLogbookHeader.diveHeaderStart == 0xFAFA)
+ − 1246 start = StepBackwards;
+ − 1247 else
+ − 1248 break;
+ − 1249 }
+ − 1250
+ − 1251 if(start == 0xFF)
+ − 1252 return;
+ − 1253
+ − 1254 count = start + 1;
+ − 1255 startAbsolute = settingsGetPointer()->lastDiveLogId;
+ − 1256
+ − 1257
268
+ − 1258
38
+ − 1259 if(start%2)
+ − 1260 {
+ − 1261 if(counterStorage[start] != startCount)
+ − 1262 {
+ − 1263 // clear data
+ − 1264 for(int i=0;i<0x800*2;i++)
+ − 1265 data[i] = 0xFF;
+ − 1266
+ − 1267 uint8_t id = settingsGetPointer()->lastDiveLogId;
+ − 1268 id -= start; // 0-255, auto rollover
+ − 1269
+ − 1270 // copy primary/pre-dive
+ − 1271 actualAddress = HEADERSTART + (0x800 * id);
+ − 1272 ext_flash_read_block_start();
+ − 1273 for(int i = 0; i < HEADERSIZE; i++)
+ − 1274 ext_flash_read_block(&data[i], EF_HEADER);
+ − 1275 ext_flash_read_block_stop();
+ − 1276
+ − 1277 // copy main/secondary/post-dive
+ − 1278 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
+ − 1279 ext_flash_read_block_start();
+ − 1280 for(int i = 0x400; i < HEADERSIZE+0x400; i++)
+ − 1281 ext_flash_read_block(&data[i], EF_HEADER);
+ − 1282 ext_flash_read_block_stop();
+ − 1283
+ − 1284 // repair
+ − 1285 ptrHeaderInData2a->diveNumber = startCount;
+ − 1286 ptrHeaderInData2b->diveNumber = startCount;
+ − 1287 startCount++;
+ − 1288
+ − 1289 // write
+ − 1290 actualAddress = HEADERSTART + (0x800 * (id-1));
+ − 1291 ef_write_block(data,0x800*2,EF_HEADER, 0);
+ − 1292 }
+ − 1293 start--;
+ − 1294 }
268
+ − 1295
38
+ − 1296 // for(int count = start; count > -1; count -= 2)
+ − 1297
+ − 1298 while(count > 0)
+ − 1299 {
+ − 1300 // clear data
+ − 1301 for(int i=0;i<0x1000;i++)
+ − 1302 data[i] = 0xFF;
+ − 1303
+ − 1304 repair = 0;
+ − 1305
+ − 1306 startBackup = startAbsolute;
+ − 1307
+ − 1308 if(startAbsolute%2) // 0x800 to 0x1000
+ − 1309 {
+ − 1310 // copy second pre-dive
+ − 1311 actualAddress = HEADERSTART + (0x800 * startAbsolute);
+ − 1312 ext_flash_read_block_start();
+ − 1313 for(int i = 0x800; i < HEADERSIZE+0x800; i++)
+ − 1314 ext_flash_read_block(&data[i], EF_HEADER);
+ − 1315 ext_flash_read_block_stop();
+ − 1316
+ − 1317 // copy second post-dive
+ − 1318 actualAddress = HEADERSTART + HEADER2OFFSET + (0x800 * startAbsolute);
+ − 1319 ext_flash_read_block_start();
+ − 1320 for(int i = 0xC00; i < HEADERSIZE+0xC00; i++)
+ − 1321 ext_flash_read_block(&data[i], EF_HEADER);
+ − 1322 ext_flash_read_block_stop();
+ − 1323
+ − 1324 if(counterStorage[count] != startCount)
+ − 1325 {
+ − 1326 ptrHeaderInData2a->diveNumber = startCount;
+ − 1327 ptrHeaderInData2b->diveNumber = startCount;
+ − 1328 repair = 1;
+ − 1329 }
+ − 1330 startCount += 1;
+ − 1331
+ − 1332 startAbsolute -= 1;
+ − 1333 count -= 1;
+ − 1334
+ − 1335 if(count > 0)
+ − 1336 {
+ − 1337 // copy first pre-dive
+ − 1338 actualAddress = HEADERSTART + (0x800 * startAbsolute);
+ − 1339 ext_flash_read_block_start();
+ − 1340 for(int i = 0; i < HEADERSIZE; i++)
+ − 1341 ext_flash_read_block(&data[i], EF_HEADER);
+ − 1342 ext_flash_read_block_stop();
+ − 1343
+ − 1344 // copy first post-dive
+ − 1345 actualAddress = HEADERSTART + (0x800 * startAbsolute);
+ − 1346 ext_flash_read_block_start();
+ − 1347 for(int i = 0x400; i < HEADERSIZE+0x400; i++)
+ − 1348 ext_flash_read_block(&data[i], EF_HEADER);
+ − 1349 ext_flash_read_block_stop();
+ − 1350
+ − 1351 if(counterStorage[count] != startCount)
+ − 1352 {
+ − 1353 ptrHeaderInData1a->diveNumber = startCount;
+ − 1354 ptrHeaderInData1b->diveNumber = startCount;
+ − 1355 repair = 1;
+ − 1356 }
+ − 1357 startCount += 1;
+ − 1358
+ − 1359 startAbsolute -= 1;
+ − 1360 count -= 1;
+ − 1361 }
+ − 1362 }
+ − 1363 else
+ − 1364 {
+ − 1365 // copy first pre-dive
+ − 1366 actualAddress = HEADERSTART + (0x800 * startAbsolute);
+ − 1367 ext_flash_read_block_start();
+ − 1368 for(int i = 0; i < HEADERSIZE; i++)
+ − 1369 ext_flash_read_block(&data[i], EF_HEADER);
+ − 1370 ext_flash_read_block_stop();
+ − 1371
+ − 1372 // copy first post-dive
+ − 1373 actualAddress = HEADERSTART + (0x800 * startAbsolute);
+ − 1374 ext_flash_read_block_start();
+ − 1375 for(int i = 0x400; i < HEADERSIZE+0x400; i++)
+ − 1376 ext_flash_read_block(&data[i], EF_HEADER);
+ − 1377 ext_flash_read_block_stop();
+ − 1378
+ − 1379 if(counterStorage[count] != startCount)
+ − 1380 {
+ − 1381 ptrHeaderInData1a->diveNumber = startCount;
+ − 1382 ptrHeaderInData1b->diveNumber = startCount;
+ − 1383 repair = 1;
+ − 1384 }
+ − 1385 startCount += 1;
+ − 1386
+ − 1387 startAbsolute -= 1;
+ − 1388 count -= 1;
+ − 1389 }
+ − 1390
+ − 1391 // write
+ − 1392 if(repair)
+ − 1393 {
+ − 1394 actualPointerHeader = HEADERSTART + (0x1000 * startBackup%2);
+ − 1395 ef_write_block(data,0x1000,EF_HEADER, 0);
+ − 1396 }
+ − 1397 }
+ − 1398 releaseFrame(97,logCopyDataPtr);
+ − 1399 settingsGetPointer()->totalDiveCounter = startCount;
+ − 1400 }
268
+ − 1401 */
38
+ − 1402
452
+ − 1403 uint8_t ext_dive_log_consistent(void)
+ − 1404 {
+ − 1405 uint8_t ret = 0;
+ − 1406 uint8_t header1, header2;
+ − 1407 uint8_t id;
+ − 1408 convert_Type dataStart;
557
+ − 1409 convert_Type dataEnd;
452
+ − 1410
+ − 1411 SSettings *settings = settingsGetPointer();
+ − 1412 id = settings->lastDiveLogId;
+ − 1413
557
+ − 1414 if(settings->lastDiveLogId != 0) /* not trust LogID 0 which might be reset by a settings problem */
+ − 1415 { /* ==> Find function will be called restoring the Id belonging to the latest sample */
+ − 1416 actualAddress = HEADERSTART + (0x800 * id);
+ − 1417 ext_flash_read_block_start();
+ − 1418 ext_flash_read_block(&header1, EF_HEADER);
+ − 1419 ext_flash_read_block(&header2, EF_HEADER);
+ − 1420 ext_flash_read_block_stop();
+ − 1421 if((header1 == 0xFA) && (header2 == 0xFA)) /* Header is indicating the start of a dive */
+ − 1422 {
+ − 1423 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
+ − 1424 ext_flash_read_block_start();
+ − 1425 ext_flash_read_block(&header1, EF_HEADER);
+ − 1426 ext_flash_read_block(&header2, EF_HEADER);
+ − 1427 dataStart.u8bit.byteHigh = 0;
+ − 1428 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER);
+ − 1429 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER);
+ − 1430 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER);
+ − 1431 dataEnd.u8bit.byteHigh = 0;
+ − 1432 ext_flash_read_block(&dataEnd.u8bit.byteLow, EF_HEADER);
+ − 1433 ext_flash_read_block(&dataEnd.u8bit.byteMidLow, EF_HEADER);
+ − 1434 ext_flash_read_block(&dataEnd.u8bit.byteMidHigh, EF_HEADER);
+ − 1435 ext_flash_read_block_stop();
+ − 1436
+ − 1437 if((header1 == 0xFA) && (header2 == 0xFA)) /* Secondary header was written at the end of a dive */
+ − 1438 {
+ − 1439 if(dataStart.u32bit < dataEnd.u32bit)
+ − 1440 {
+ − 1441 ret = 1; /* => lastDiveLogID points to a valid dive entry */
+ − 1442 }
+ − 1443 else /* check if address wrap is valid */
+ − 1444 {
+ − 1445 if(ext_flash_SampleOverrunValid())
+ − 1446 {
+ − 1447 ret = 1;
+ − 1448 }
+ − 1449 }
+ − 1450 }
+ − 1451 }
+ − 1452 }
452
+ − 1453 return ret;
+ − 1454 }
+ − 1455
38
+ − 1456 // ===============================================================================
+ − 1457 // ext_flash_repair_dive_log
+ − 1458 /// @brief This function
+ − 1459 /// does set
+ − 1460 /// logFlashNextSampleStartAddress
+ − 1461 /// and
+ − 1462 /// lastDiveLogId
+ − 1463 ///
452
+ − 1464
38
+ − 1465 void ext_flash_repair_dive_log(void)
+ − 1466 {
+ − 1467 uint8_t header1, header2;
+ − 1468 convert_Type dataStart;
+ − 1469
+ − 1470 for(int id = 0; id < 255;id++)
+ − 1471 {
+ − 1472 actualAddress = HEADERSTART + (0x800 * id);
+ − 1473 ext_flash_read_block_start();
+ − 1474 ext_flash_read_block(&header1, EF_HEADER);
+ − 1475 ext_flash_read_block(&header2, EF_HEADER);
+ − 1476 dataStart.u8bit.byteHigh = 0;
+ − 1477 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER);
+ − 1478 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER);
+ − 1479 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER);
+ − 1480 ext_flash_read_block_stop();
425
+ − 1481 if((header1 == 0xFA) && (header2 == 0xFA)) /* Header is indicating the start of a dive */
38
+ − 1482 {
+ − 1483 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
+ − 1484 ext_flash_read_block_start();
+ − 1485 ext_flash_read_block(&header1, EF_HEADER);
+ − 1486 ext_flash_read_block(&header2, EF_HEADER);
+ − 1487 ext_flash_read_block_stop();
425
+ − 1488 if((header1 != 0xFA) || (header2 != 0xFA)) /* Secondary header was not written at the end of a dive */
38
+ − 1489 {
425
+ − 1490 actualPointerSample = dataStart.u32bit; /* Set datapointer to position stored in header written at beginning of dive */
38
+ − 1491 actualAddress = actualPointerSample;
+ − 1492 logbook_recover_brokenlog(id);
+ − 1493 SSettings *settings = settingsGetPointer();
+ − 1494 settings->logFlashNextSampleStartAddress = actualPointerSample;
+ − 1495 }
+ − 1496 }
+ − 1497 }
+ − 1498 ext_flash_find_start();
+ − 1499 }
+ − 1500
+ − 1501
268
+ − 1502 static void ext_flash_find_start(void)
38
+ − 1503 {
+ − 1504 uint8_t id;
+ − 1505 uint8_t header1, header2;
+ − 1506 convert_Type dataStart, dataEnd;
+ − 1507
429
+ − 1508 /* TODO Cleanup_Ref_1: cleanup logFlashNextSampleStartAddress and lastDiveLogId */
+ − 1509 /* The implementation below would cause problems in case more then 254 dives would be done. */
+ − 1510 /* This is avoided by Cleanup_Ref2 */
441
+ − 1511 for(id = 0; id <= 255;id++)
38
+ − 1512 {
+ − 1513 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
+ − 1514 ext_flash_read_block_start();
+ − 1515 ext_flash_read_block(&header1, EF_HEADER);
+ − 1516 ext_flash_read_block(&header2, EF_HEADER);
+ − 1517 dataStart.u8bit.byteHigh = 0;
+ − 1518 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER);
+ − 1519 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER);
+ − 1520 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER);
+ − 1521 ext_flash_read_block_stop();
+ − 1522 if((header1 == 0xFF) && (header2 == 0xFF))
+ − 1523 {
+ − 1524 break;
+ − 1525 }
+ − 1526 }
+ − 1527 id--;
+ − 1528 SSettings *settings = settingsGetPointer();
+ − 1529 settings->lastDiveLogId = id;
+ − 1530
+ − 1531 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
+ − 1532 actualPointerHeader = actualAddress;
+ − 1533
+ − 1534 ext_flash_read_block_start();
+ − 1535
+ − 1536 ext_flash_read_block(&header1, EF_HEADER);
+ − 1537 ext_flash_read_block(&header2, EF_HEADER);
+ − 1538 dataStart.u8bit.byteHigh = 0;
+ − 1539 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER);
+ − 1540 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER);
+ − 1541 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER);
+ − 1542 dataEnd.u8bit.byteHigh = 0;
+ − 1543 ext_flash_read_block(&dataEnd.u8bit.byteLow, EF_HEADER);
+ − 1544 ext_flash_read_block(&dataEnd.u8bit.byteMidLow, EF_HEADER);
+ − 1545 ext_flash_read_block(&dataEnd.u8bit.byteMidHigh, EF_HEADER);
+ − 1546 ext_flash_read_block_stop();
+ − 1547
+ − 1548 //Find free space
+ − 1549 if((header1 == 0xFA) && (header2 == 0xFA))
+ − 1550 {
+ − 1551 uint8_t uiRead = 0;
+ − 1552 int countFF = 0;
+ − 1553 //End of last complete dive
+ − 1554 actualPointerSample = dataEnd.u32bit ;
+ − 1555 actualAddress = actualPointerSample;
+ − 1556 //Check if there are samples of dives with less than half a minute
+ − 1557 while(true)
+ − 1558 {
+ − 1559 ext_flash_read_block_start();
+ − 1560 ext_flash_read_block(&uiRead, EF_SAMPLE);
+ − 1561 if(uiRead == 0xFF)
+ − 1562 countFF++;
+ − 1563 else
+ − 1564 countFF = 0;
+ − 1565
+ − 1566
+ − 1567
+ − 1568 if(countFF == 10)
+ − 1569 {
+ − 1570 actualAddress -= 10;
+ − 1571 break;
+ − 1572 }
+ − 1573
+ − 1574 //New page: clear
+ − 1575 if(ext_flash_erase_if_on_page_start())
+ − 1576 break;
+ − 1577 }
+ − 1578 // Set new start address
+ − 1579 actualPointerSample = actualAddress;
+ − 1580 settings->logFlashNextSampleStartAddress = actualPointerSample;
+ − 1581 }
+ − 1582 else
+ − 1583 {
+ − 1584 settings->logFlashNextSampleStartAddress = SAMPLESTART;
+ − 1585 }
+ − 1586 }
+ − 1587
+ − 1588
870
+ − 1589
38
+ − 1590
268
+ − 1591 static void ext_flash_disable_protection(void)
38
+ − 1592 {
+ − 1593 /*
+ − 1594 extFlashStatusBit8_Type status;
+ − 1595
+ − 1596 status.uw = 0;
+ − 1597
+ − 1598 wait_chip_not_busy();
+ − 1599 write_spi(0x50,RELEASE); // EWSR
+ − 1600 write_spi(0x01,HOLDCS); // WRSR
+ − 1601 write_spi(status.uw,RELEASE); // new status
+ − 1602 */
+ − 1603 }
870
+ − 1604 #endif
38
+ − 1605
+ − 1606 void ext_flash_disable_protection_for_logbook(void)
+ − 1607 {
+ − 1608 /*
+ − 1609 extFlashStatusBit8_Type status;
+ − 1610
+ − 1611 status.uw = 0;
+ − 1612 status.ub.BlockProtect0 = 1;
+ − 1613 status.ub.BlockProtect1 = 0;
+ − 1614 status.ub.BlockProtect2 = 1;
+ − 1615 status.ub.BlockProtect3 = 0; // not set in OSTC3. Why?
+ − 1616
+ − 1617 wait_chip_not_busy();
+ − 1618 write_spi(0x50,RELEASE); // EWSR
+ − 1619 write_spi(0x01,HOLDCS); // WRSR
+ − 1620 write_spi(status.uw,RELEASE); // new status
+ − 1621 */
+ − 1622 }
+ − 1623
+ − 1624
+ − 1625 void ext_flash_enable_protection(void)
+ − 1626 {
+ − 1627 /*
+ − 1628 extFlashStatusBit8_Type status;
+ − 1629
+ − 1630 status.uw = 0;
+ − 1631 status.ub.BlockProtect0 = 1;
+ − 1632 status.ub.BlockProtect1 = 1;
+ − 1633 status.ub.BlockProtect2 = 1;
+ − 1634 status.ub.BlockProtect3 = 1; // not set in OSTC3. Why?
+ − 1635
+ − 1636 wait_chip_not_busy();
+ − 1637 write_spi(0x50,RELEASE); // EWSR
+ − 1638 write_spi(0x01,HOLDCS); // WRSR
+ − 1639 write_spi(status.uw,RELEASE); // new status
+ − 1640 */
+ − 1641 }
+ − 1642
+ − 1643
268
+ − 1644 /*void ext_flash_erase_chip(void)
38
+ − 1645 {
+ − 1646 wait_chip_not_busy();
+ − 1647 write_spi(0x06,RELEASE);
+ − 1648 write_spi(0x60,RELEASE);
+ − 1649 wait_chip_not_busy();
268
+ − 1650 }*/
38
+ − 1651
+ − 1652 void ext_flash_erase_firmware(void)
+ − 1653 {
+ − 1654 uint32_t size, blocks_64k;
+ − 1655
+ − 1656 actualAddress = FWSTART;
+ − 1657 size = 1 + FWSTOP - FWSTART;
+ − 1658 blocks_64k = size / 0x10000;
+ − 1659 ef_erase_64K(blocks_64k);
+ − 1660 }
+ − 1661
+ − 1662 void ext_flash_erase_firmware2(void)
+ − 1663 {
+ − 1664 uint32_t size, blocks_64k;
+ − 1665
+ − 1666 actualAddress = FWSTART2;
+ − 1667 size = 1 + FWSTOP2 - FWSTART2;
+ − 1668 blocks_64k = size / 0x10000;
+ − 1669 ef_erase_64K(blocks_64k);
+ − 1670 }
+ − 1671
+ − 1672
+ − 1673
+ − 1674 void ext_flash_erase_logbook(void)
+ − 1675 {
+ − 1676 uint32_t size, blocks_64k;
+ − 1677
+ − 1678 ext_flash_disable_protection_for_logbook();
+ − 1679
+ − 1680 actualAddress = SAMPLESTART;
+ − 1681 size = 1 + SAMPLESTOP - SAMPLESTART;
+ − 1682 blocks_64k = size / 0x10000;
+ − 1683 ef_erase_64K(blocks_64k);
+ − 1684
+ − 1685 actualAddress = HEADERSTART;
+ − 1686 size = 1 + HEADERSTOP - HEADERSTART;
+ − 1687 blocks_64k = size / 0x10000;
+ − 1688 ef_erase_64K(blocks_64k);
+ − 1689
+ − 1690 ext_flash_enable_protection();
+ − 1691 }
+ − 1692
+ − 1693
268
+ − 1694 static void ext_flash_erase4kB(void)
38
+ − 1695 {
+ − 1696 wait_chip_not_busy();
+ − 1697 write_spi(0x06,RELEASE);/* WREN */
+ − 1698 write_spi(0x20,HOLDCS);/* sector erase cmd */
+ − 1699 write_address(RELEASE);
+ − 1700 }
+ − 1701
282
+ − 1702 /* be careful - might not work with entire family and other products
38
+ − 1703 * see page 14 of LOGBOOK_V3_S25FS-S_00-271247.pdf
+ − 1704 */
268
+ − 1705 static void ext_flash_erase32kB(void)
38
+ − 1706 {
+ − 1707 uint32_t actualAddress_backup;
+ − 1708
+ − 1709 actualAddress_backup = actualAddress;
+ − 1710 actualAddress = 0;
+ − 1711 wait_chip_not_busy();
+ − 1712 write_spi(0x06,RELEASE);/* WREN */
+ − 1713 write_spi(0xD8,HOLDCS);/* sector erase cmd */
+ − 1714 write_address(RELEASE);
+ − 1715 actualAddress = actualAddress_backup;
+ − 1716 }
+ − 1717
+ − 1718
268
+ − 1719 static void ext_flash_erase64kB(void)
38
+ − 1720 {
+ − 1721 wait_chip_not_busy();
+ − 1722 write_spi(0x06,RELEASE);/* WREN */
+ − 1723 write_spi(0xD8,HOLDCS);/* sector erase cmd */
+ − 1724 write_address(RELEASE);
+ − 1725 }
+ − 1726
+ − 1727
+ − 1728 void ext_flash_read_block_start(void)
+ − 1729 {
+ − 1730 wait_chip_not_busy();
+ − 1731 write_spi(0x03,HOLDCS); /* WREN */
+ − 1732 write_address(HOLDCS);
+ − 1733 }
+ − 1734
+ − 1735 /* 4KB, 32KB, 64 KB, not the upper 16 MB with 4 Byte address at the moment */
268
+ − 1736 static uint8_t ext_flash_erase_if_on_page_start(void)
38
+ − 1737 {
+ − 1738 if(actualAddress < 0x00008000)
+ − 1739 {
+ − 1740 /* 4K Byte is 0x1000 */
+ − 1741 if((actualAddress & 0xFFF) == 0)
+ − 1742 {
+ − 1743 ext_flash_erase4kB();
+ − 1744 return 1;
+ − 1745 }
423
+ − 1746 }
38
+ − 1747 else
+ − 1748 if(actualAddress < 0x00010000)
+ − 1749 {
+ − 1750 /* 32K Byte is only one page */
+ − 1751 if(actualAddress == 0x00010000)
+ − 1752 {
+ − 1753 ext_flash_erase32kB();
+ − 1754 return 1;
+ − 1755 }
423
+ − 1756 }
38
+ − 1757 else
+ − 1758 {
+ − 1759 /* 64K Byte is 0x10000 */
+ − 1760 if((actualAddress & 0xFFFF) == 0)
+ − 1761 {
423
+ − 1762 if(preparedPageAddress == actualAddress) /* has page already been prepared before? (at the moment for samples only) */
+ − 1763 {
+ − 1764 preparedPageAddress = 0;
+ − 1765
+ − 1766 }
+ − 1767 else
+ − 1768 {
+ − 1769 ext_flash_erase64kB();
+ − 1770 }
38
+ − 1771 return 1;
+ − 1772 }
423
+ − 1773 }
+ − 1774
38
+ − 1775 return 0;
+ − 1776 }
+ − 1777
+ − 1778
268
+ − 1779 static void ext_flash_read_block(uint8_t *getByte, uint8_t type)
38
+ − 1780 {
+ − 1781 *getByte = read_spi(HOLDCS);/* read data */
+ − 1782 ext_flash_incf_address(type);
+ − 1783 }
+ − 1784
+ − 1785
268
+ − 1786 static void ext_flash_read_block_multi(void *getByte, uint32_t size, uint8_t type)
38
+ − 1787 {
+ − 1788 uint8_t *data;
+ − 1789 data = getByte;
+ − 1790
+ − 1791 for(uint32_t i=0;i<size;i++)
+ − 1792 {
+ − 1793 data[i] = read_spi(HOLDCS);/* read data */
+ − 1794 ext_flash_incf_address(type);
+ − 1795 }
+ − 1796 }
+ − 1797
+ − 1798
268
+ − 1799 static void ext_flash_read_block_stop(void)
38
+ − 1800 {
+ − 1801 chip_unselect();
+ − 1802 }
+ − 1803
+ − 1804
+ − 1805 /* Private functions ---------------------------------------------------------*/
+ − 1806
268
+ − 1807 static void ef_write_block(uint8_t * sendByte, uint32_t length, uint8_t type, uint8_t do_not_erase)
38
+ − 1808 {
+ − 1809 uint32_t remaining_page_size, remaining_length, remaining_space_to_ring_end;
420
+ − 1810 uint32_t i=0;
+ − 1811
38
+ − 1812 if(!length)
+ − 1813 return;
+ − 1814
+ − 1815 uint32_t ringStart, ringStop;
+ − 1816
+ − 1817 switch(type)
+ − 1818 {
+ − 1819 case EF_HEADER:
+ − 1820 actualAddress = actualPointerHeader;
+ − 1821 ringStart = HEADERSTART;
+ − 1822 ringStop = HEADERSTOP;
+ − 1823 break;
+ − 1824 case EF_SAMPLE:
+ − 1825 actualAddress = actualPointerSample;
+ − 1826 ringStart = SAMPLESTART;
+ − 1827 ringStop = SAMPLESTOP;
+ − 1828 break;
+ − 1829 case EF_DEVICEDATA:
+ − 1830 actualAddress = actualPointerDevicedata;
+ − 1831 ringStart = DDSTART;
+ − 1832 ringStop = DDSTOP;
+ − 1833 break;
+ − 1834 case EF_VPMDATA:
+ − 1835 actualAddress = actualPointerVPM;
+ − 1836 ringStart = VPMSTART;
+ − 1837 ringStop = VPMSTOP;
+ − 1838 break;
+ − 1839 case EF_SETTINGS:
+ − 1840 actualAddress = actualPointerSettings;
+ − 1841 ringStart = SETTINGSSTART;
+ − 1842 ringStop = SETTINGSSTOP;
+ − 1843 break;
+ − 1844 case EF_FIRMWARE:
+ − 1845 actualAddress = actualPointerFirmware;
+ − 1846 ringStart = FWSTART;
+ − 1847 ringStop = FWSTOP;
+ − 1848 break;
+ − 1849 case EF_FIRMWARE2:
+ − 1850 actualAddress = actualPointerFirmware2;
+ − 1851 ringStart = FWSTART2;
+ − 1852 ringStop = FWSTOP2;
+ − 1853 break;
+ − 1854 default:
+ − 1855 ringStart = FLASHSTART;
+ − 1856 ringStop = FLASHSTOP;
+ − 1857 break;
+ − 1858 }
+ − 1859 /* safety */
+ − 1860 if(actualAddress < ringStart)
+ − 1861 actualAddress = ringStart;
+ − 1862
+ − 1863 if(do_not_erase == 0)
459
7ac0e76dbd6a
Activated reset of sample information within header data at time of sector erasing:
ideenmodellierer
diff
changeset
+ − 1864 {
466
+ − 1865 ext_flash_erase_if_on_page_start();
459
7ac0e76dbd6a
Activated reset of sample information within header data at time of sector erasing:
ideenmodellierer
diff
changeset
+ − 1866 }
38
+ − 1867
420
+ − 1868 while( i<length)
38
+ − 1869 {
+ − 1870 ef_hw_rough_delay_us(5);
+ − 1871 wait_chip_not_busy();
+ − 1872 write_spi(0x06,RELEASE); /* WREN */
+ − 1873 write_spi(0x02,HOLDCS); /* write cmd */
+ − 1874 write_address(HOLDCS);
+ − 1875
+ − 1876 remaining_length = length - i;
420
+ − 1877 remaining_page_size = 0xFF - (uint8_t)(actualAddress & 0xFF) +1;
38
+ − 1878 remaining_space_to_ring_end = ringStop - actualAddress;
+ − 1879
420
+ − 1880 if(remaining_length >= 256)
+ − 1881 {
+ − 1882 remaining_length = 255; /* up to 256 bytes may be written in one burst. Last byte is written with release */
+ − 1883 }
+ − 1884 else
38
+ − 1885 {
420
+ − 1886 remaining_length--; /* last byte needed for release */
+ − 1887 }
+ − 1888 if(remaining_length >= (remaining_page_size) ) /* use 256 byte page and calculate number of bytes left */
+ − 1889 {
+ − 1890 remaining_length = remaining_page_size - 1;
+ − 1891 }
+ − 1892 if( (remaining_space_to_ring_end >= 256))
+ − 1893 {
+ − 1894 for(int j=0; j<remaining_length; j++)
38
+ − 1895 {
+ − 1896 write_spi(sendByte[i],HOLDCS);/* write data */
+ − 1897 actualAddress++;
+ − 1898 i++;
+ − 1899 }
+ − 1900 }
+ − 1901 /* byte with RELEASE */
+ − 1902 write_spi(sendByte[i],RELEASE);/* write data */
+ − 1903 actualAddress++;
420
+ − 1904 i++;
+ − 1905
38
+ − 1906 if(actualAddress > ringStop)
+ − 1907 actualAddress = ringStart;
420
+ − 1908
38
+ − 1909 if(do_not_erase == 0)
+ − 1910 ext_flash_erase_if_on_page_start();
+ − 1911 }
+ − 1912 switch(type)
+ − 1913 {
+ − 1914 case EF_HEADER:
+ − 1915 actualPointerHeader = actualAddress;
+ − 1916 break;
+ − 1917 case EF_SAMPLE:
+ − 1918 actualPointerSample = actualAddress;
+ − 1919 break;
+ − 1920 case EF_DEVICEDATA:
+ − 1921 actualPointerDevicedata = actualAddress;
+ − 1922 break;
+ − 1923 case EF_VPMDATA:
+ − 1924 actualPointerVPM = actualAddress;
+ − 1925 break;
+ − 1926 case EF_SETTINGS:
+ − 1927 actualPointerSettings = actualAddress;
+ − 1928 break;
+ − 1929 case EF_FIRMWARE:
+ − 1930 actualPointerFirmware = actualAddress;
+ − 1931 break;
+ − 1932 case EF_FIRMWARE2:
+ − 1933 actualPointerFirmware2 = actualAddress;
+ − 1934 break;
+ − 1935 default:
+ − 1936 break;
+ − 1937 }
+ − 1938 }
+ − 1939
870
+ − 1940 #ifndef BOOTLOADER_STANDALONE
268
+ − 1941 static _Bool ext_flash_test_remaining_space_of_page_empty(uint32_t pointer, uint16_t length)
38
+ − 1942 {
+ − 1943 if((pointer & 0xFFF) == 0)
+ − 1944 return 1;
+ − 1945
+ − 1946 uint32_t backup = actualAddress;
+ − 1947 uint8_t data;
+ − 1948 uint32_t size_to_page_end;
+ − 1949
+ − 1950 size_to_page_end = 0x1000 - (pointer & 0xFFF);
+ − 1951 if(length > size_to_page_end)
+ − 1952 length = size_to_page_end;
+ − 1953
+ − 1954 actualAddress = pointer;
+ − 1955 ext_flash_read_block_start();
+ − 1956
+ − 1957 for(uint16_t i = 0; i<length; i++)
+ − 1958 {
+ − 1959 ext_flash_read_block(&data, 255); // 255 = ENTIRE FLASH
+ − 1960 if(data != 0xFF)
+ − 1961 {
+ − 1962 ext_flash_read_block_stop();
+ − 1963 actualAddress = backup;
+ − 1964 return 0;
+ − 1965 }
+ − 1966 }
+ − 1967 ext_flash_read_block_stop();
+ − 1968 actualAddress = backup;
+ − 1969 return 1;
+ − 1970 }
+ − 1971
+ − 1972
268
+ − 1973 static void ext_flash_set_to_begin_of_next_page(uint32_t *pointer, uint8_t type)
38
+ − 1974 {
+ − 1975 uint32_t ringStart, ringStop;
+ − 1976
+ − 1977 switch(type)
+ − 1978 {
+ − 1979 case EF_HEADER:
+ − 1980 ringStart = HEADERSTART;
+ − 1981 ringStop = HEADERSTOP;
+ − 1982 break;
+ − 1983 case EF_SAMPLE:
+ − 1984 ringStart = SAMPLESTART;
+ − 1985 ringStop = SAMPLESTOP;
+ − 1986 break;
+ − 1987 case EF_DEVICEDATA:
+ − 1988 ringStart = DDSTART;
+ − 1989 ringStop = DDSTOP;
+ − 1990 break;
+ − 1991 case EF_VPMDATA:
+ − 1992 ringStart = VPMSTART;
+ − 1993 ringStop = VPMSTOP;
+ − 1994 break;
+ − 1995 case EF_SETTINGS:
+ − 1996 ringStart = SETTINGSSTART;
+ − 1997 ringStop = SETTINGSSTOP;
+ − 1998 break;
+ − 1999 default:
+ − 2000 ringStart = FLASHSTART;
+ − 2001 ringStop = FLASHSTOP;
+ − 2002 break;
+ − 2003 }
+ − 2004
+ − 2005 *pointer = (*pointer & 0xFFF) + 0x1000;
+ − 2006
+ − 2007 if((*pointer < ringStart) || (*pointer >= ringStop))
+ − 2008 *pointer = ringStart;
+ − 2009 }
870
+ − 2010 #endif
38
+ − 2011
+ − 2012 static void ef_erase_64K(uint32_t blocks)
+ − 2013 {
+ − 2014 for(uint32_t i = 0; i < blocks; i++)
+ − 2015 {
+ − 2016 wait_chip_not_busy();
+ − 2017 write_spi(0x06,RELEASE);/* WREN */
+ − 2018 write_spi(0xD8,HOLDCS);/* 64k erase cmd */
+ − 2019 write_address(RELEASE);
+ − 2020 actualAddress += 0x10000;
+ − 2021 HAL_Delay(25);
+ − 2022 }
+ − 2023 }
+ − 2024
+ − 2025
268
+ − 2026 static void chip_unselect(void)
38
+ − 2027 {
+ − 2028 HAL_GPIO_WritePin(EXTFLASH_CSB_GPIO_PORT,EXTFLASH_CSB_PIN,GPIO_PIN_SET); // chip select
+ − 2029 }
+ − 2030
268
+ − 2031 static void chip_select(void)
38
+ − 2032 {
+ − 2033 HAL_GPIO_WritePin(EXTFLASH_CSB_GPIO_PORT,EXTFLASH_CSB_PIN,GPIO_PIN_RESET); // chip select
+ − 2034 }
870
+ − 2035 #ifndef BOOTLOADER_STANDALONE
268
+ − 2036 static void error_led_on(void)
38
+ − 2037 {
+ − 2038 HAL_GPIO_WritePin(OSCILLOSCOPE_GPIO_PORT,OSCILLOSCOPE_PIN,GPIO_PIN_SET);
+ − 2039 }
+ − 2040
268
+ − 2041 static void error_led_off(void)
38
+ − 2042 {
+ − 2043 HAL_GPIO_WritePin(OSCILLOSCOPE_GPIO_PORT,OSCILLOSCOPE_PIN,GPIO_PIN_RESET);
+ − 2044 }
870
+ − 2045 #endif
38
+ − 2046
268
+ − 2047 static uint8_t read_spi(uint8_t unselect_CS_afterwards)
38
+ − 2048 {
+ − 2049 uint8_t byte;
+ − 2050
+ − 2051 chip_select();
+ − 2052
+ − 2053 if(HAL_SPI_Receive(&hspiDisplay, &byte, 1, 10000) != HAL_OK)
+ − 2054 Error_Handler_extflash();
+ − 2055
+ − 2056 while (HAL_SPI_GetState(&hspiDisplay) != HAL_SPI_STATE_READY)
+ − 2057 {
+ − 2058 }
+ − 2059 if(unselect_CS_afterwards)
+ − 2060 chip_unselect();
+ − 2061
+ − 2062 return byte;
+ − 2063 }
+ − 2064
+ − 2065
268
+ − 2066 static void write_spi(uint8_t data, uint8_t unselect_CS_afterwards)
38
+ − 2067 {
+ − 2068 chip_select();
+ − 2069
+ − 2070 if(HAL_SPI_Transmit(&hspiDisplay, &data, 1, 10000) != HAL_OK)
+ − 2071 Error_Handler_extflash();
+ − 2072
+ − 2073 while (HAL_SPI_GetState(&hspiDisplay) != HAL_SPI_STATE_READY)
+ − 2074 {
+ − 2075 }
+ − 2076 if(unselect_CS_afterwards)
+ − 2077 chip_unselect();
+ − 2078 }
+ − 2079
+ − 2080
268
+ − 2081 static void write_address(uint8_t unselect_CS_afterwards)
38
+ − 2082 {
+ − 2083 uint8_t hi, med ,lo;
+ − 2084
+ − 2085 hi = (actualAddress >> 16) & 0xFF;
+ − 2086 med = (actualAddress >> 8) & 0xFF;
+ − 2087 lo = actualAddress & 0xFF;
+ − 2088
+ − 2089 write_spi(hi, HOLDCS);
+ − 2090 write_spi(med, HOLDCS);
+ − 2091 write_spi(lo, unselect_CS_afterwards);
+ − 2092 }
+ − 2093
+ − 2094
+ − 2095 static void wait_chip_not_busy(void)
+ − 2096 {
+ − 2097 uint8_t status;
+ − 2098
+ − 2099 chip_unselect();
+ − 2100
+ − 2101 write_spi(0x05,HOLDCS); /* RDSR */
+ − 2102 status = read_spi(HOLDCS);/* read status */
+ − 2103 while(status & 0x01)
+ − 2104 {
+ − 2105 HAL_Delay(1);
+ − 2106 status = read_spi(HOLDCS);/* read status */
+ − 2107 }
+ − 2108 chip_unselect();
+ − 2109 }
+ − 2110
+ − 2111
268
+ − 2112 static void ext_flash_incf_address(uint8_t type)
38
+ − 2113 {
+ − 2114 uint32_t ringStart, ringStop;
+ − 2115
+ − 2116 actualAddress += 1;
+ − 2117
+ − 2118 switch(type)
+ − 2119 {
+ − 2120 case EF_HEADER:
+ − 2121 ringStart = HEADERSTART;
+ − 2122 ringStop = HEADERSTOP;
+ − 2123 break;
+ − 2124 case EF_SAMPLE:
+ − 2125 ringStart = SAMPLESTART;
+ − 2126 ringStop = SAMPLESTOP;
+ − 2127 break;
+ − 2128 case EF_DEVICEDATA:
+ − 2129 ringStart = DDSTART;
+ − 2130 ringStop = DDSTOP;
+ − 2131 break;
+ − 2132 case EF_VPMDATA:
+ − 2133 ringStart = VPMSTART;
+ − 2134 ringStop = VPMSTOP;
+ − 2135 break;
+ − 2136 case EF_SETTINGS:
+ − 2137 ringStart = SETTINGSSTART;
+ − 2138 ringStop = SETTINGSSTOP;
+ − 2139 break;
+ − 2140 case EF_FIRMWARE:
+ − 2141 ringStart = FWSTART;
+ − 2142 ringStop = FWSTOP;
+ − 2143 break;
+ − 2144 case EF_FIRMWARE2:
+ − 2145 ringStart = FWSTART2;
+ − 2146 ringStop = FWSTOP2;
+ − 2147 break;
+ − 2148 default:
+ − 2149 ringStart = FLASHSTART;
+ − 2150 ringStop = FLASHSTOP;
+ − 2151 break;
+ − 2152 }
+ − 2153
+ − 2154 if((actualAddress < ringStart) || (actualAddress > ringStop))
+ − 2155 actualAddress = ringStart;
+ − 2156 }
+ − 2157
870
+ − 2158 #ifndef BOOTLOADER_STANDALONE
268
+ − 2159 static void ext_flash_decf_address_ring(uint8_t type)
38
+ − 2160 {
+ − 2161 uint32_t ringStart, ringStop;
+ − 2162
+ − 2163 switch(type)
+ − 2164 {
+ − 2165 case EF_HEADER:
+ − 2166 ringStart = HEADERSTART;
+ − 2167 ringStop = HEADERSTOP;
+ − 2168 break;
+ − 2169 case EF_SAMPLE:
+ − 2170 ringStart = SAMPLESTART;
+ − 2171 ringStop = SAMPLESTOP;
+ − 2172 break;
+ − 2173 case EF_DEVICEDATA:
+ − 2174 ringStart = DDSTART;
+ − 2175 ringStop = DDSTOP;
+ − 2176 break;
+ − 2177 case EF_VPMDATA:
+ − 2178 ringStart = VPMSTART;
+ − 2179 ringStop = VPMSTOP;
+ − 2180 break;
+ − 2181 case EF_SETTINGS:
+ − 2182 ringStart = SETTINGSSTART;
+ − 2183 ringStop = SETTINGSSTOP;
+ − 2184 break;
+ − 2185 case EF_FIRMWARE:
+ − 2186 ringStart = FWSTART;
+ − 2187 ringStop = FWSTOP;
+ − 2188 break;
+ − 2189 case EF_FIRMWARE2:
+ − 2190 ringStart = FWSTART2;
+ − 2191 ringStop = FWSTOP2;
+ − 2192 break;
+ − 2193 default:
+ − 2194 ringStart = FLASHSTART;
+ − 2195 ringStop = FLASHSTOP;
+ − 2196 break;
+ − 2197 }
+ − 2198
+ − 2199 if((actualAddress <= ringStart) || (actualAddress > ringStop))
+ − 2200 actualAddress = ringStop;
+ − 2201 else
+ − 2202 actualAddress -= 1;
+ − 2203 }
870
+ − 2204 #endif
38
+ − 2205
+ − 2206 static void ef_hw_rough_delay_us(uint32_t delayUs)
+ − 2207 {
+ − 2208 if(!delayUs)
+ − 2209 return;
+ − 2210 delayUs*= 12;
+ − 2211 while(delayUs--);
+ − 2212 return;
+ − 2213 }
+ − 2214
+ − 2215 static void Error_Handler_extflash(void)
+ − 2216 {
+ − 2217 while(1)
+ − 2218 {
+ − 2219 }
+ − 2220 }
425
+ − 2221
+ − 2222 void ext_flash_CloseSector(void)
+ − 2223 {
+ − 2224 uint32_t actualAddressBackup = actualAddress;
+ − 2225 int i=0;
+ − 2226
+ − 2227 if(closeSectorAddress != 0)
+ − 2228 {
+ − 2229 /* write some dummy bytes to the sector which is currently used for storing samples. This is done to "hide" problem if function is calles again */
+ − 2230 actualAddress = closeSectorAddress;
+ − 2231
+ − 2232 wait_chip_not_busy();
+ − 2233 write_spi(0x06,RELEASE); /* WREN */
+ − 2234 write_spi(0x02,HOLDCS); /* write cmd */
+ − 2235 write_address(HOLDCS);
+ − 2236 for(i = 0; i<8; i++)
+ − 2237 {
+ − 2238 write_spi(0xA5,HOLDCS);/* write data */
+ − 2239 actualAddress++;
+ − 2240 }
+ − 2241 /* byte with RELEASE */
+ − 2242 write_spi(0xA5,RELEASE);/* write data */
+ − 2243 actualAddress = actualAddressBackup;
+ − 2244 closeSectorAddress = 0;
+ − 2245 }
+ − 2246 }
+ − 2247
466
+ − 2248 /* This function validates a potential jump of sample address by checking the last sector for empty memory cells */
+ − 2249 uint8_t ext_flash_SampleOverrunValid(void)
+ − 2250 {
+ − 2251 uint8_t jumpvalid = 1;
+ − 2252 uint32_t curAddress, actualaddrbackup;
+ − 2253 uint8_t tmpBuffer;
+ − 2254 uint8_t emptyCellCnt = 0;
+ − 2255
+ − 2256 actualaddrbackup = actualAddress;
557
+ − 2257 curAddress = SAMPLESTOP - 20; /* check the last 20 bytes of the last sample sector */
466
+ − 2258 actualAddress = curAddress;
+ − 2259 ext_flash_read_block_start();
+ − 2260 while(actualAddress < SAMPLESTOP)
+ − 2261 {
+ − 2262 tmpBuffer = read_spi(HOLDCS);/* read data */
+ − 2263 if(tmpBuffer == 0xFF)
+ − 2264 {
+ − 2265 emptyCellCnt++;
+ − 2266 }
+ − 2267 actualAddress++;
+ − 2268 }
+ − 2269 ext_flash_read_block_stop();
+ − 2270
+ − 2271 if(emptyCellCnt == 20)
+ − 2272 {
+ − 2273 jumpvalid = 0;
+ − 2274 }
+ − 2275 actualAddress = actualaddrbackup;
+ − 2276 return jumpvalid;
+ − 2277 }
+ − 2278
557
+ − 2279 uint32_t ext_flash_AnalyseSampleBuffer()
425
+ − 2280 {
557
+ − 2281 uint8_t sectorState[192]; /* samples are stored in 192 sector / 64k each */
425
+ − 2282 uint32_t curAddress = SAMPLESTART;
+ − 2283 uint8_t curSector = 0;
+ − 2284 uint8_t samplebuffer[10];
+ − 2285 uint32_t actualAddressBackup = actualAddress;
+ − 2286 uint8_t emptyCellCnt = 0;
+ − 2287 uint32_t i = 0;
+ − 2288 uint8_t startedSectors = 0;
+ − 2289 uint8_t lastSectorInuse = 0;
+ − 2290
+ − 2291 /* check if a sector is used till its end */
557
+ − 2292 for(curSector = 0; curSector < 192; curSector++)
425
+ − 2293 {
+ − 2294 sectorState[curSector] = 0;
+ − 2295 emptyCellCnt = 0;
+ − 2296 curAddress = SAMPLESTART + (curSector * 0x10000); /* set address to begin of sector and check if it is used */
+ − 2297 actualAddress = curAddress;
+ − 2298 ext_flash_read_block_start();
+ − 2299 for(uint32_t i=0;i<10;i++)
+ − 2300 {
+ − 2301 samplebuffer[i] = read_spi(HOLDCS);/* read data */
+ − 2302 if(samplebuffer[i] == 0xFF)
+ − 2303 {
+ − 2304 emptyCellCnt++;
+ − 2305 }
+ − 2306 }
+ − 2307 ext_flash_read_block_stop();
+ − 2308 if(emptyCellCnt == 10)
+ − 2309 {
+ − 2310 sectorState[curSector] = SECTOR_NOTUSED;
+ − 2311 }
+ − 2312 emptyCellCnt = 0;
+ − 2313 curAddress = SAMPLESTART + (curSector * 0x10000) + 0xFFF5; /* set address to end of sector and check if it is used */
+ − 2314 actualAddress = curAddress;
+ − 2315 ext_flash_read_block_start();
+ − 2316 for(i=0;i<10;i++)
+ − 2317 {
+ − 2318 samplebuffer[i] = read_spi(HOLDCS);/* read data */
+ − 2319 if(samplebuffer[i] == 0xFF)
+ − 2320 {
+ − 2321 emptyCellCnt++;
+ − 2322 }
+ − 2323 }
+ − 2324 ext_flash_read_block_stop();
+ − 2325 if(emptyCellCnt == 10)
+ − 2326 {
+ − 2327 sectorState[curSector] |= SECTOR_INUSE; /* will become SECTOR_EMPTY if start is NOTUSED */
+ − 2328 }
+ − 2329 }
+ − 2330
557
+ − 2331 for(i=0;i<192;i++)
425
+ − 2332 {
+ − 2333 if( sectorState[i] == SECTOR_INUSE)
+ − 2334 {
+ − 2335 startedSectors++;
+ − 2336 lastSectorInuse = i;
+ − 2337 }
+ − 2338 }
+ − 2339
+ − 2340 if(startedSectors > 1) /* more than one sector is in used => ring buffer corrupted */
+ − 2341 {
+ − 2342 if(startedSectors == 2) /* only fix issue if only two sectors are in used. Otherwise fixing will cause more worries than help */
+ − 2343 {
+ − 2344 /* the logic behind healing of the problem is that the larger address is the oldest one => restore the largest address */
+ − 2345 curAddress = SAMPLESTART + (lastSectorInuse * 0x10000);
+ − 2346 emptyCellCnt = 0;
+ − 2347 actualAddress = curAddress;
+ − 2348 ext_flash_read_block_start();
+ − 2349 while((emptyCellCnt < 10) && (actualAddress < curAddress + 0x10000))
+ − 2350 {
+ − 2351 samplebuffer[0] = read_spi(HOLDCS);/* read data */
+ − 2352 if(samplebuffer[0] == 0xFF)
+ − 2353 {
+ − 2354 emptyCellCnt++;
+ − 2355 }
+ − 2356 else
+ − 2357 {
+ − 2358 emptyCellCnt = 0;
+ − 2359 }
+ − 2360 actualAddress++;
+ − 2361 }
+ − 2362 ext_flash_read_block_stop();
+ − 2363 actualAddress -= 10; /* step 10 bytes back to the start of free bytes */
+ − 2364 actualPointerSample = actualAddress;
+ − 2365
+ − 2366 closeSectorAddress = settingsGetPointer()->logFlashNextSampleStartAddress & 0xFFFF0000;
+ − 2367 closeSectorAddress += 0xFFF5; /* to be used once next time a dive is logged. Needed because NextSampleID is derived at every startup */
+ − 2368 settingsGetPointer()->logFlashNextSampleStartAddress = actualPointerSample; /* store new position to be used for next dive */
557
+ − 2369 ext_flash_CloseSector();
425
+ − 2370 }
+ − 2371 }
+ − 2372 actualAddress = actualAddressBackup;
+ − 2373 return startedSectors;
+ − 2374 }
+ − 2375
466
+ − 2376 uint32_t ext_flash_read_profilelength_small_header(uint32_t smallHeaderAddr)
452
+ − 2377 {
466
+ − 2378 uint32_t profileLength = 0;
+ − 2379 actualPointerSample = smallHeaderAddr;
+ − 2380 actualAddress = actualPointerSample;
+ − 2381 ext_flash_read_block_start();
+ − 2382 ext_flash_read_next_sample_part((uint8_t*)&profileLength, 3);
+ − 2383 ext_flash_close_read_sample();
+ − 2384 return profileLength;
452
+ − 2385 }
+ − 2386
+ − 2387
870
+ − 2388
38
+ − 2389 uint8_t ext_flash_erase_firmware_if_not_empty(void)
+ − 2390 {
+ − 2391 const uint8_t TESTSIZE_FW = 4;
+ − 2392
+ − 2393 uint8_t data[TESTSIZE_FW];
+ − 2394 uint8_t notEmpty = 0;
+ − 2395
+ − 2396 actualAddress = FWSTART;
+ − 2397 ext_flash_read_block_start();
+ − 2398 for(int i = 0; i < TESTSIZE_FW; i++)
+ − 2399 {
+ − 2400 ext_flash_read_block(&data[i], EF_FIRMWARE);
+ − 2401 if(data[i] != 0xFF)
+ − 2402 notEmpty = 1;
+ − 2403 }
+ − 2404 ext_flash_read_block_stop();
+ − 2405
+ − 2406 if(notEmpty)
+ − 2407 {
+ − 2408 ext_flash_erase_firmware();
+ − 2409 return 1;
+ − 2410 }
+ − 2411 else
+ − 2412 return 0;
+ − 2413 }
+ − 2414
+ − 2415 uint8_t ext_flash_erase_firmware2_if_not_empty(void)
+ − 2416 {
+ − 2417 const uint8_t TESTSIZE_FW = 4;
+ − 2418
+ − 2419 uint8_t data[TESTSIZE_FW];
+ − 2420 uint8_t notEmpty = 0;
+ − 2421
+ − 2422 actualAddress = FWSTART2;
+ − 2423 ext_flash_read_block_start();
+ − 2424 for(int i = 0; i < TESTSIZE_FW; i++)
+ − 2425 {
+ − 2426 ext_flash_read_block(&data[i], EF_FIRMWARE2);
+ − 2427 if(data[i] != 0xFF)
+ − 2428 notEmpty = 1;
+ − 2429 }
+ − 2430 ext_flash_read_block_stop();
+ − 2431
+ − 2432 if(notEmpty)
+ − 2433 {
+ − 2434 ext_flash_erase_firmware2();
+ − 2435 return 1;
+ − 2436 }
+ − 2437 else
+ − 2438 return 0;
870
+ − 2439 }