Mercurial > public > ostc4
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 |