comparison Discovery/Src/externLogbookFlash.c @ 430:30580cf5ee77

Merged in Ideenmodellierer/ostc4/ImprovmentNVM_2 (pull request #39) ImprovmentNVM 2
author heinrichsweikamp <bitbucket@heinrichsweikamp.com>
date Tue, 18 Feb 2020 07:20:29 +0000
parents 7f351c25608a
children 9a9e4908ce2e b90ddf57f7f1
comparison
equal deleted inserted replaced
419:c2264ce139cb 430:30580cf5ee77
114 114
115 /* Exported variables --------------------------------------------------------*/ 115 /* Exported variables --------------------------------------------------------*/
116 116
117 /* Private variables ---------------------------------------------------------*/ 117 /* Private variables ---------------------------------------------------------*/
118 static uint32_t actualAddress = 0; 118 static uint32_t actualAddress = 0;
119 static uint32_t preparedPageAddress = 0;
120 static uint32_t closeSectorAddress = 0;
119 static uint32_t entryPoint = 0; 121 static uint32_t entryPoint = 0;
120 122
121 static uint32_t actualPointerHeader = 0; 123 static uint32_t actualPointerHeader = 0;
122 static uint32_t actualPointerSample = 0; 124 static uint32_t actualPointerSample = 0;
123 static uint32_t LengthLeftSampleRead = 0; 125 static uint32_t LengthLeftSampleRead = 0;
124 static uint32_t actualPointerDevicedata = 0; 126 static uint32_t actualPointerDevicedata = DDSTART;
127 static uint32_t actualPointerDevicedata_Read = DDSTART;
125 static uint32_t actualPointerVPM = 0; 128 static uint32_t actualPointerVPM = 0;
126 static uint32_t actualPointerSettings = 0; 129 static uint32_t actualPointerSettings = SETTINGSSTART;
127 static uint32_t actualPointerFirmware = 0; 130 static uint32_t actualPointerFirmware = 0;
128 static uint32_t actualPointerFirmware2 = 0; 131 static uint32_t actualPointerFirmware2 = 0;
129 132
130 /* Private function prototypes -----------------------------------------------*/ 133 /* Private function prototypes -----------------------------------------------*/
131 static void chip_unselect(void); 134 static void chip_unselect(void);
390 } 393 }
391 394
392 395
393 #ifndef BOOTLOADER_STANDALONE 396 #ifndef BOOTLOADER_STANDALONE
394 397
395 void ext_flash_write_devicedata(void) 398 void ext_flash_write_devicedata(uint8_t resetRing)
396 { 399 {
397 uint8_t *pData; 400 uint8_t *pData;
398 const uint16_t length = sizeof(SDevice); 401 const uint16_t length = sizeof(SDevice);
399 uint8_t length_lo, length_hi; 402 uint8_t length_lo, length_hi;
400 uint8_t dataLength[2] = { 0 }; 403 uint8_t dataLength[2] = { 0 };
404 uint32_t tmpBlockStart;
401 405
402 ext_flash_disable_protection(); 406 ext_flash_disable_protection();
403 407
404 pData = (uint8_t *)stateDeviceGetPointer(); 408 pData = (uint8_t *)stateDeviceGetPointer();
405 409
406 actualPointerDevicedata = DDSTART; 410 /* Reset the Ring to the start address if requested (e.g. because we write the default block during shutdown) */
411 if((resetRing) || ((actualPointerDevicedata + length) >= DDSTOP))
412 {
413 actualPointerDevicedata = DDSTART;
414 }
415 tmpBlockStart = actualPointerDevicedata;
407 416
408 length_lo = (uint8_t)(length & 0xFF); 417 length_lo = (uint8_t)(length & 0xFF);
409 length_hi = (uint8_t)(length >> 8); 418 length_hi = (uint8_t)(length >> 8);
410 dataLength[0] = length_lo; 419 dataLength[0] = length_lo;
411 dataLength[1] = length_hi; 420 dataLength[1] = length_hi;
412 421
413 ef_write_block(dataLength,2, EF_DEVICEDATA, 0); 422 ef_write_block(dataLength,2, EF_DEVICEDATA, 0);
414 ef_write_block(pData,length, EF_DEVICEDATA, 0); 423 ef_write_block(pData,length, EF_DEVICEDATA, 0);
424
425 actualPointerDevicedata_Read = tmpBlockStart;
426
415 } 427 }
416 428
417 429
418 uint16_t ext_flash_read_devicedata(uint8_t *buffer, uint16_t max_length) 430 uint16_t ext_flash_read_devicedata(uint8_t *buffer, uint16_t max_length)
419 { 431 {
420 uint16_t length; 432 uint16_t length;
421 uint8_t length_lo, length_hi; 433 uint8_t length_lo, length_hi;
422 434
423 actualAddress = DDSTART; 435 actualAddress = actualPointerDevicedata_Read;
424 436
437 length = 0;
438 length_lo = 0;
439 length_hi = 0;
425 ext_flash_read_block_start(); 440 ext_flash_read_block_start();
441
442
426 ext_flash_read_block(&length_lo, EF_DEVICEDATA); 443 ext_flash_read_block(&length_lo, EF_DEVICEDATA);
427 ext_flash_read_block(&length_hi, EF_DEVICEDATA); 444 ext_flash_read_block(&length_hi, EF_DEVICEDATA);
428 445
429 length = (length_hi * 256) + length_lo; 446 while ((length_lo != 0xFF) && (length_hi != 0xFF))
430 447 {
431 if(length > max_length) 448 length = (length_hi * 256) + length_lo;
432 return 0; 449
433 450 if(length > max_length)
434 ext_flash_read_block_multi(buffer,length,EF_DEVICEDATA); 451 return 0;
452
453 ext_flash_read_block_multi(buffer,length,EF_DEVICEDATA);
454
455 ext_flash_read_block(&length_lo, EF_DEVICEDATA); /* check if another devicedata set is available */
456 ext_flash_read_block(&length_hi, EF_DEVICEDATA); /* length will be 0xFFFF if a empty memory is read */
457 }
458 ext_flash_decf_address_ring(EF_DEVICEDATA); /* set pointer back to empty address */
459 ext_flash_decf_address_ring(EF_DEVICEDATA);
435 ext_flash_read_block_stop(); 460 ext_flash_read_block_stop();
436 461
462 if(actualAddress > actualPointerDevicedata) /* the write pointer has not yet been set up probably */
463 {
464 actualPointerDevicedata = actualAddress;
465 }
437 return length; 466 return length;
438 } 467 }
439 468
440 469
441 void ext_flash_write_vpm(SVpm *vpmInput) 470 void ext_flash_write_vpm(SVpm *vpmInput)
491 void ext_flash_write_settings(void) 520 void ext_flash_write_settings(void)
492 { 521 {
493 return; 522 return;
494 } 523 }
495 #else 524 #else
496 void ext_flash_write_settings(void) 525 void ext_flash_write_settings(uint8_t resetRing)
497 { 526 {
498 uint8_t *pData; 527 uint8_t *pData;
499 const uint16_t length = sizeof(SSettings); 528 const uint16_t length = sizeof(SSettings);
500 uint8_t length_lo, length_hi; 529 uint8_t length_lo, length_hi;
501 uint8_t dataLength[2] = { 0 }; 530 uint8_t dataLength[2] = { 0 };
509 settingsGetPointer()->backup_localtime_rtc_tr = stateRealGetPointer()->lifeData.timeBinaryFormat; 538 settingsGetPointer()->backup_localtime_rtc_tr = stateRealGetPointer()->lifeData.timeBinaryFormat;
510 settingsGetPointer()->backup_localtime_rtc_dr = stateRealGetPointer()->lifeData.dateBinaryFormat; 539 settingsGetPointer()->backup_localtime_rtc_dr = stateRealGetPointer()->lifeData.dateBinaryFormat;
511 540
512 pData = (uint8_t *)settingsGetPointer(); 541 pData = (uint8_t *)settingsGetPointer();
513 542
514 actualPointerSettings = SETTINGSSTART; 543 /* Reset the Ring to the start address if requested (e.g. because we write the default block during shutdown) */
544 if((resetRing) || ((actualPointerSettings + length) >= SETTINGSSTOP))
545 {
546 actualPointerSettings = SETTINGSSTART;
547 }
515 548
516 length_lo = (uint8_t)(length & 0xFF); 549 length_lo = (uint8_t)(length & 0xFF);
517 length_hi = (uint8_t)(length >> 8); 550 length_hi = (uint8_t)(length >> 8);
518 dataLength[0] = length_lo; 551 dataLength[0] = length_lo;
519 dataLength[1] = length_hi; 552 dataLength[1] = length_hi;
546 579
547 ext_flash_read_block_start(); 580 ext_flash_read_block_start();
548 ext_flash_read_block(&length_lo, EF_SETTINGS); 581 ext_flash_read_block(&length_lo, EF_SETTINGS);
549 ext_flash_read_block(&length_hi, EF_SETTINGS); 582 ext_flash_read_block(&length_hi, EF_SETTINGS);
550 583
551 lengthOnEEPROM = length_hi * 256; 584 while ((length_lo != 0xFF) && (length_hi != 0xFF)) /* get the latest stored setting block */
552 lengthOnEEPROM += length_lo; 585 {
553 if(lengthOnEEPROM <= lengthStandardNow) 586 lengthOnEEPROM = length_hi * 256;
554 { 587 lengthOnEEPROM += length_lo;
555 ext_flash_read_block_multi(&header, 4, EF_SETTINGS); 588 if(lengthOnEEPROM <= lengthStandardNow)
556 if((header <= pSettings->header) && (header >= pSettings->updateSettingsAllowedFromHeader)) 589 {
557 { 590 ext_flash_read_block_multi(&header, 4, EF_SETTINGS);
558 returnValue = HAL_OK; 591 if((header <= pSettings->header) && (header >= pSettings->updateSettingsAllowedFromHeader))
559 pSettings->header = header; 592 {
560 pData = (uint8_t *)pSettings + 4; /* header */ 593 returnValue = HAL_OK;
561 for(uint16_t i = 0; i < (lengthOnEEPROM-4); i++) 594 pSettings->header = header;
562 ext_flash_read_block(&pData[i], EF_SETTINGS); 595 pData = (uint8_t *)pSettings + 4; /* header */
563 } 596 for(uint16_t i = 0; i < (lengthOnEEPROM-4); i++)
564 else 597 ext_flash_read_block(&pData[i], EF_SETTINGS);
565 { 598 }
566 returnValue = HAL_ERROR; 599 else
567 } 600 {
601 returnValue = HAL_ERROR;
602 }
603 }
604 ext_flash_read_block(&length_lo, EF_SETTINGS);
605 ext_flash_read_block(&length_hi, EF_SETTINGS);
606 }
607 ext_flash_decf_address_ring(EF_SETTINGS); /* set pointer back to empty address */
608 ext_flash_decf_address_ring(EF_SETTINGS);
609 ext_flash_read_block_stop();
610
611 if(actualAddress > actualPointerSettings) /* the write pointer has not yet been set up probably */
612 {
613 actualPointerSettings = actualAddress;
568 } 614 }
569 ext_flash_read_block_stop(); 615 ext_flash_read_block_stop();
570 return returnValue; 616 return returnValue;
571 } 617 }
572 618
612 * the following func writes to header to the ext_flash 658 * the following func writes to header to the ext_flash
613 */ 659 */
614 void ext_flash_create_new_dive_log(uint8_t *pHeaderPreDive) 660 void ext_flash_create_new_dive_log(uint8_t *pHeaderPreDive)
615 { 661 {
616 SSettings *settings; 662 SSettings *settings;
617 uint8_t id, id_next; 663 uint8_t id;
618 uint8_t header1, header2; 664 uint8_t header1, header2;
619 665
620 settings = settingsGetPointer(); 666 settings = settingsGetPointer();
621 id = settings->lastDiveLogId; 667 id = settings->lastDiveLogId;
622 668
623 actualAddress = HEADERSTART + (0x800 * id); 669 actualAddress = HEADERSTART + (0x800 * id);
624 ext_flash_read_block_start(); 670 ext_flash_read_block_start();
625 ext_flash_read_block(&header1, EF_SAMPLE); 671 ext_flash_read_block(&header1, EF_SAMPLE); /* the sample ring is increased instead of header... not sure if that is planned intention */
626 ext_flash_read_block(&header2, EF_SAMPLE); 672 ext_flash_read_block(&header2, EF_SAMPLE); /* does not matter because actual address is reset in write_block call */
627 ext_flash_read_block_stop(); 673 ext_flash_read_block_stop();
628 674
675 /* TODO Cleanup_Ref_2: The code below should not be necessary in case of a proper shutdown and startup */
676 /* the implementation fixes an issue which might happen at Cleanup_Ref_1 (in case of more then 254 dives) */
629 if((header1 == 0xFA) && (header2 == 0xFA)) 677 if((header1 == 0xFA) && (header2 == 0xFA))
630 { 678 {
631 id += 1; /* 0-255, auto rollover */ 679 id += 1; /* 0-255, auto rollover */
632 if(id & 1) 680 if(id & 1)
633 { 681 {
642 } 690 }
643 else 691 else
644 { 692 {
645 id = 0; 693 id = 0;
646 } 694 }
647
648 /* delete next header */
649 id_next = id + 1;
650 actualPointerHeader = HEADERSTART + (0x800 * id_next);
651 ef_write_block(0,0, EF_HEADER, 0);
652 695
653 settings->lastDiveLogId = id; 696 settings->lastDiveLogId = id;
654 actualPointerHeader = HEADERSTART + (0x800 * id); 697 actualPointerHeader = HEADERSTART + (0x800 * id);
655 698
656 if(pHeaderPreDive != 0) 699 if(pHeaderPreDive != 0)
724 } 767 }
725 768
726 769
727 void ext_flash_write_sample(uint8_t *pSample, uint16_t length) 770 void ext_flash_write_sample(uint8_t *pSample, uint16_t length)
728 { 771 {
772 uint32_t actualAdressBackup = 0;
773
729 ef_write_block(pSample,length, EF_SAMPLE, 0); 774 ef_write_block(pSample,length, EF_SAMPLE, 0);
730 775
731 SSettings *settings = settingsGetPointer(); 776 SSettings *settings = settingsGetPointer();
732 settings->logFlashNextSampleStartAddress = actualPointerSample; 777 settings->logFlashNextSampleStartAddress = actualPointerSample;
778
779 if(0xFFFF - (actualAddress & 0x0000FFFF) < 255) /* are we close to a sector border? */
780 {
781 if (((actualAddress & 0x0000FFFF) != 0) && (preparedPageAddress == 0)) /* only prepare if not already at start of sector */
782 {
783 actualAdressBackup = actualAddress;
784 actualAddress = (actualAddress & 0xFFFF0000) + 0x00010000; /* Set to start of next 64k sector */
785 if(actualAddress >= SAMPLESTOP)
786 {
787 actualAddress = SAMPLESTART;
788 }
789 preparedPageAddress = actualAddress;
790 ext_flash_erase64kB();
791 actualAddress = actualAdressBackup;
792 }
793 }
733 } 794 }
734 795
735 static void ext_flash_overwrite_sample_without_erase(uint8_t *pSample, uint16_t length) 796 static void ext_flash_overwrite_sample_without_erase(uint8_t *pSample, uint16_t length)
736 { 797 {
737 ef_write_block(pSample,length, EF_SAMPLE, 1); 798 ef_write_block(pSample,length, EF_SAMPLE, 1);
1314 dataStart.u8bit.byteHigh = 0; 1375 dataStart.u8bit.byteHigh = 0;
1315 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER); 1376 ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER);
1316 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER); 1377 ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER);
1317 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER); 1378 ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER);
1318 ext_flash_read_block_stop(); 1379 ext_flash_read_block_stop();
1319 if((header1 == 0xFA) && (header2 == 0xFA)) 1380 if((header1 == 0xFA) && (header2 == 0xFA)) /* Header is indicating the start of a dive */
1320 { 1381 {
1321 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; 1382 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
1322 ext_flash_read_block_start(); 1383 ext_flash_read_block_start();
1323 ext_flash_read_block(&header1, EF_HEADER); 1384 ext_flash_read_block(&header1, EF_HEADER);
1324 ext_flash_read_block(&header2, EF_HEADER); 1385 ext_flash_read_block(&header2, EF_HEADER);
1325 ext_flash_read_block_stop(); 1386 ext_flash_read_block_stop();
1326 if((header1 != 0xFA) || (header2 != 0xFA)) 1387 if((header1 != 0xFA) || (header2 != 0xFA)) /* Secondary header was not written at the end of a dive */
1327 { 1388 {
1328 actualPointerSample = dataStart.u32bit; 1389 actualPointerSample = dataStart.u32bit; /* Set datapointer to position stored in header written at beginning of dive */
1329 actualAddress = actualPointerSample; 1390 actualAddress = actualPointerSample;
1330 logbook_recover_brokenlog(id); 1391 logbook_recover_brokenlog(id);
1331 SSettings *settings = settingsGetPointer(); 1392 SSettings *settings = settingsGetPointer();
1332 settings->logFlashNextSampleStartAddress = actualPointerSample; 1393 settings->logFlashNextSampleStartAddress = actualPointerSample;
1333 } 1394 }
1341 { 1402 {
1342 uint8_t id; 1403 uint8_t id;
1343 uint8_t header1, header2; 1404 uint8_t header1, header2;
1344 convert_Type dataStart, dataEnd; 1405 convert_Type dataStart, dataEnd;
1345 1406
1407 /* TODO Cleanup_Ref_1: cleanup logFlashNextSampleStartAddress and lastDiveLogId */
1408 /* The implementation below would cause problems in case more then 254 dives would be done. */
1409 /* This is avoided by Cleanup_Ref2 */
1346 for(id = 0; id < 255;id++) 1410 for(id = 0; id < 255;id++)
1347 { 1411 {
1348 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET; 1412 actualAddress = HEADERSTART + (0x800 * id) + HEADER2OFFSET;
1349 ext_flash_read_block_start(); 1413 ext_flash_read_block_start();
1350 ext_flash_read_block(&header1, EF_HEADER); 1414 ext_flash_read_block(&header1, EF_HEADER);
1576 if((actualAddress & 0xFFF) == 0) 1640 if((actualAddress & 0xFFF) == 0)
1577 { 1641 {
1578 ext_flash_erase4kB(); 1642 ext_flash_erase4kB();
1579 return 1; 1643 return 1;
1580 } 1644 }
1581 } 1645 }
1582 else 1646 else
1583 if(actualAddress < 0x00010000) 1647 if(actualAddress < 0x00010000)
1584 { 1648 {
1585 /* 32K Byte is only one page */ 1649 /* 32K Byte is only one page */
1586 if(actualAddress == 0x00010000) 1650 if(actualAddress == 0x00010000)
1587 { 1651 {
1588 ext_flash_erase32kB(); 1652 ext_flash_erase32kB();
1589 return 1; 1653 return 1;
1590 } 1654 }
1591 } 1655 }
1592 else 1656 else
1593 { 1657 {
1594 /* 64K Byte is 0x10000 */ 1658 /* 64K Byte is 0x10000 */
1595 if((actualAddress & 0xFFFF) == 0) 1659 if((actualAddress & 0xFFFF) == 0)
1596 { 1660 {
1597 ext_flash_erase64kB(); 1661 if(preparedPageAddress == actualAddress) /* has page already been prepared before? (at the moment for samples only) */
1662 {
1663 preparedPageAddress = 0;
1664
1665 }
1666 else
1667 {
1668 ext_flash_erase64kB();
1669 }
1598 return 1; 1670 return 1;
1599 } 1671 }
1600 } 1672 }
1673
1601 return 0; 1674 return 0;
1602 } 1675 }
1603 1676
1604 1677
1605 static void ext_flash_read_block(uint8_t *getByte, uint8_t type) 1678 static void ext_flash_read_block(uint8_t *getByte, uint8_t type)
1631 /* Private functions ---------------------------------------------------------*/ 1704 /* Private functions ---------------------------------------------------------*/
1632 1705
1633 static void ef_write_block(uint8_t * sendByte, uint32_t length, uint8_t type, uint8_t do_not_erase) 1706 static void ef_write_block(uint8_t * sendByte, uint32_t length, uint8_t type, uint8_t do_not_erase)
1634 { 1707 {
1635 uint32_t remaining_page_size, remaining_length, remaining_space_to_ring_end; 1708 uint32_t remaining_page_size, remaining_length, remaining_space_to_ring_end;
1636 1709 uint32_t i=0;
1710
1637 if(!length) 1711 if(!length)
1638 return; 1712 return;
1639 1713
1640 uint32_t ringStart, ringStop; 1714 uint32_t ringStart, ringStop;
1641 1715
1686 actualAddress = ringStart; 1760 actualAddress = ringStart;
1687 1761
1688 if(do_not_erase == 0) 1762 if(do_not_erase == 0)
1689 ext_flash_erase_if_on_page_start(); 1763 ext_flash_erase_if_on_page_start();
1690 1764
1691 for(uint32_t i=0;i<length;i++) 1765 while( i<length)
1692 { 1766 {
1693 ef_hw_rough_delay_us(5); 1767 ef_hw_rough_delay_us(5);
1694 wait_chip_not_busy(); 1768 wait_chip_not_busy();
1695 write_spi(0x06,RELEASE); /* WREN */ 1769 write_spi(0x06,RELEASE); /* WREN */
1696 write_spi(0x02,HOLDCS); /* write cmd */ 1770 write_spi(0x02,HOLDCS); /* write cmd */
1697 write_address(HOLDCS); 1771 write_address(HOLDCS);
1698 1772
1699 remaining_length = length - i; 1773 remaining_length = length - i;
1700 remaining_page_size = actualAddress & 0xFF; 1774 remaining_page_size = 0xFF - (uint8_t)(actualAddress & 0xFF) +1;
1701 remaining_space_to_ring_end = ringStop - actualAddress; 1775 remaining_space_to_ring_end = ringStop - actualAddress;
1702 1776
1703 if((remaining_page_size == 0) && (remaining_length >= 256) && (remaining_space_to_ring_end >= 256)) 1777 if(remaining_length >= 256)
1704 { 1778 {
1705 for(int j=0; j<255; j++) 1779 remaining_length = 255; /* up to 256 bytes may be written in one burst. Last byte is written with release */
1780 }
1781 else
1782 {
1783 remaining_length--; /* last byte needed for release */
1784 }
1785 if(remaining_length >= (remaining_page_size) ) /* use 256 byte page and calculate number of bytes left */
1786 {
1787 remaining_length = remaining_page_size - 1;
1788 }
1789 if( (remaining_space_to_ring_end >= 256))
1790 {
1791 for(int j=0; j<remaining_length; j++)
1706 { 1792 {
1707 write_spi(sendByte[i],HOLDCS);/* write data */ 1793 write_spi(sendByte[i],HOLDCS);/* write data */
1708 actualAddress++; 1794 actualAddress++;
1709 i++; 1795 i++;
1710 } 1796 }
1711 } 1797 }
1712 /* byte with RELEASE */ 1798 /* byte with RELEASE */
1713 write_spi(sendByte[i],RELEASE);/* write data */ 1799 write_spi(sendByte[i],RELEASE);/* write data */
1714 actualAddress++; 1800 actualAddress++;
1801 i++;
1802
1715 if(actualAddress > ringStop) 1803 if(actualAddress > ringStop)
1716 actualAddress = ringStart; 1804 actualAddress = ringStart;
1805
1717 if(do_not_erase == 0) 1806 if(do_not_erase == 0)
1718 ext_flash_erase_if_on_page_start(); 1807 ext_flash_erase_if_on_page_start();
1719 } 1808 }
1720 switch(type) 1809 switch(type)
1721 { 1810 {
2024 { 2113 {
2025 while(1) 2114 while(1)
2026 { 2115 {
2027 } 2116 }
2028 } 2117 }
2118
2119 void ext_flash_CloseSector(void)
2120 {
2121 uint32_t actualAddressBackup = actualAddress;
2122 int i=0;
2123
2124 if(closeSectorAddress != 0)
2125 {
2126 /* 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 */
2127 actualAddress = closeSectorAddress;
2128
2129 wait_chip_not_busy();
2130 write_spi(0x06,RELEASE); /* WREN */
2131 write_spi(0x02,HOLDCS); /* write cmd */
2132 write_address(HOLDCS);
2133 for(i = 0; i<8; i++)
2134 {
2135 write_spi(0xA5,HOLDCS);/* write data */
2136 actualAddress++;
2137 }
2138 /* byte with RELEASE */
2139 write_spi(0xA5,RELEASE);/* write data */
2140 actualAddress = actualAddressBackup;
2141 closeSectorAddress = 0;
2142 }
2143 }
2144
2145 uint32_t ext_flash_AnalyseSampleBuffer(char *pstrResult)
2146 {
2147 uint8_t sectorState[16]; /* samples are stored in 16 sector / 64k each */
2148 uint32_t curAddress = SAMPLESTART;
2149 uint8_t curSector = 0;
2150 uint8_t samplebuffer[10];
2151 uint32_t actualAddressBackup = actualAddress;
2152 uint8_t emptyCellCnt = 0;
2153 uint32_t i = 0;
2154 uint8_t startedSectors = 0;
2155 uint8_t lastSectorInuse = 0;
2156
2157 /* check if a sector is used till its end */
2158 for(curSector = 0; curSector < 16; curSector++)
2159 {
2160 sectorState[curSector] = 0;
2161 emptyCellCnt = 0;
2162 curAddress = SAMPLESTART + (curSector * 0x10000); /* set address to begin of sector and check if it is used */
2163 actualAddress = curAddress;
2164 ext_flash_read_block_start();
2165 for(uint32_t i=0;i<10;i++)
2166 {
2167 samplebuffer[i] = read_spi(HOLDCS);/* read data */
2168 if(samplebuffer[i] == 0xFF)
2169 {
2170 emptyCellCnt++;
2171 }
2172 }
2173 ext_flash_read_block_stop();
2174 if(emptyCellCnt == 10)
2175 {
2176 sectorState[curSector] = SECTOR_NOTUSED;
2177 }
2178 emptyCellCnt = 0;
2179 curAddress = SAMPLESTART + (curSector * 0x10000) + 0xFFF5; /* set address to end of sector and check if it is used */
2180 actualAddress = curAddress;
2181 ext_flash_read_block_start();
2182 for(i=0;i<10;i++)
2183 {
2184 samplebuffer[i] = read_spi(HOLDCS);/* read data */
2185 if(samplebuffer[i] == 0xFF)
2186 {
2187 emptyCellCnt++;
2188 }
2189 }
2190 ext_flash_read_block_stop();
2191 if(emptyCellCnt == 10)
2192 {
2193 sectorState[curSector] |= SECTOR_INUSE; /* will become SECTOR_EMPTY if start is NOTUSED */
2194 }
2195 }
2196
2197 for(i=0;i<16;i++)
2198 {
2199 if( sectorState[i] == SECTOR_INUSE)
2200 {
2201 startedSectors++;
2202 lastSectorInuse = i;
2203 }
2204 *(pstrResult+i) = sectorState[i] + 48;
2205 }
2206
2207 if(startedSectors > 1) /* more than one sector is in used => ring buffer corrupted */
2208 {
2209 if(startedSectors == 2) /* only fix issue if only two sectors are in used. Otherwise fixing will cause more worries than help */
2210 {
2211 /* the logic behind healing of the problem is that the larger address is the oldest one => restore the largest address */
2212 curAddress = SAMPLESTART + (lastSectorInuse * 0x10000);
2213 emptyCellCnt = 0;
2214 actualAddress = curAddress;
2215 ext_flash_read_block_start();
2216 while((emptyCellCnt < 10) && (actualAddress < curAddress + 0x10000))
2217 {
2218 samplebuffer[0] = read_spi(HOLDCS);/* read data */
2219 if(samplebuffer[0] == 0xFF)
2220 {
2221 emptyCellCnt++;
2222 }
2223 else
2224 {
2225 emptyCellCnt = 0;
2226 }
2227 actualAddress++;
2228 }
2229 ext_flash_read_block_stop();
2230 actualAddress -= 10; /* step 10 bytes back to the start of free bytes */
2231 actualPointerSample = actualAddress;
2232
2233 closeSectorAddress = settingsGetPointer()->logFlashNextSampleStartAddress & 0xFFFF0000;
2234 closeSectorAddress += 0xFFF5; /* to be used once next time a dive is logged. Needed because NextSampleID is derived at every startup */
2235 settingsGetPointer()->logFlashNextSampleStartAddress = actualPointerSample; /* store new position to be used for next dive */
2236 }
2237 }
2238 actualAddress = actualAddressBackup;
2239 *(pstrResult+i) = 0;
2240 return startedSectors;
2241 }
2242
2029 /* 2243 /*
2030 uint8_t ext_flash_erase_firmware_if_not_empty(void) 2244 uint8_t ext_flash_erase_firmware_if_not_empty(void)
2031 { 2245 {
2032 const uint8_t TESTSIZE_FW = 4; 2246 const uint8_t TESTSIZE_FW = 4;
2033 2247