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