Mercurial > public > ostc4
comparison Discovery/Src/tMenuEditSystem.c @ 1067:a7ed4eb3142b Icon_Integration
Exit to Correct Menu when Exiting from 'Reset Menu' Submenus.
Write Progress and Success Messages when Flashing the Bootloader.
Only Show 'Flash Bootloader' if the Available Bootloader is Different from the Existing One.
(mikeller)
| author | heinrichsweikamp |
|---|---|
| date | Tue, 17 Feb 2026 09:49:37 +0100 |
| parents | 8fe6676f28c9 |
| children |
comparison
equal
deleted
inserted
replaced
| 1066:eceb5cb2a8e3 | 1067:a7ed4eb3142b |
|---|---|
| 40 #include "tMenuSystem.h" | 40 #include "tMenuSystem.h" |
| 41 #include "tMenuEditCustom.h" | 41 #include "tMenuEditCustom.h" |
| 42 #include "motion.h" | 42 #include "motion.h" |
| 43 #include "t7.h" | 43 #include "t7.h" |
| 44 #include "math.h" | 44 #include "math.h" |
| 45 #include "firmwareEraseProgram.h" | |
| 45 | 46 |
| 46 | 47 |
| 47 /*#define HAVE_DEBUG_VIEW */ | 48 /*#define HAVE_DEBUG_VIEW */ |
| 48 static uint8_t infoPage = 0; | 49 static uint8_t infoPage = 0; |
| 49 #ifdef ENABLE_SETTING_PROFILES | 50 #ifdef ENABLE_SETTING_PROFILES |
| 1505 | 1506 |
| 1506 void openEdit_Reset(void) | 1507 void openEdit_Reset(void) |
| 1507 { | 1508 { |
| 1508 char text[32]; | 1509 char text[32]; |
| 1509 | 1510 |
| 1511 resetMenuEdit(CLUT_MenuPageSystem); | |
| 1512 setBackMenu((uint32_t)openEdit_System, 0, 5); | |
| 1513 | |
| 1510 text[0] = '\001'; | 1514 text[0] = '\001'; |
| 1511 text[1] = TXT_2BYTE; | 1515 text[1] = TXT_2BYTE; |
| 1512 text[2] = TXT2BYTE_ResetMenu; | 1516 text[2] = TXT2BYTE_ResetMenu; |
| 1513 text[3] = 0; | 1517 text[3] = 0; |
| 1514 write_topline(text); | 1518 write_topline(text); |
| 1547 char text[32]; | 1551 char text[32]; |
| 1548 SIconHeader* pIconHeader = (SIconHeader*) ICON_HEADER_ADDR; | 1552 SIconHeader* pIconHeader = (SIconHeader*) ICON_HEADER_ADDR; |
| 1549 | 1553 |
| 1550 | 1554 |
| 1551 resetMenuEdit(CLUT_MenuPageSystem); | 1555 resetMenuEdit(CLUT_MenuPageSystem); |
| 1556 setBackMenu((uint32_t)openEdit_Reset, 0, 0); | |
| 1552 | 1557 |
| 1553 text[0] = '\001'; | 1558 text[0] = '\001'; |
| 1554 text[1] = TXT_2BYTE; | 1559 text[1] = TXT_2BYTE; |
| 1555 text[2] = TXT2BYTE_AreYouSure; | 1560 text[2] = TXT2BYTE_AreYouSure; |
| 1556 text[3] = 0; | 1561 text[3] = 0; |
| 1612 } | 1617 } |
| 1613 | 1618 |
| 1614 write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); | 1619 write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext); |
| 1615 } | 1620 } |
| 1616 | 1621 |
| 1622 | |
| 1623 static bool isValidBootloaderBlock(const customBlockInfo_t *info, uint32_t checksum) | |
| 1624 { | |
| 1625 if (info == NULL) { | |
| 1626 return false; | |
| 1627 } | |
| 1628 | |
| 1629 return (info->Type & 0x0000FF00) == 0x0100 && checksum == info->fletcher; | |
| 1630 } | |
| 1631 | |
| 1617 customBlockInfo_t blockInfo; | 1632 customBlockInfo_t blockInfo; |
| 1633 | |
| 1634 static bool isBootloaderEqualToSource(const customBlockInfo_t *info) | |
| 1635 { | |
| 1636 if (info == NULL) { | |
| 1637 return false; | |
| 1638 } | |
| 1639 | |
| 1640 const uint8_t *pSource = (const uint8_t *)0x08100000; | |
| 1641 | |
| 1642 /* We only compare the bootloader bytes actually present in the source | |
| 1643 * image (info->length). Hardware data is device-specific and must be | |
| 1644 * skipped in both flash and source when overlapping. */ | |
| 1645 | |
| 1646 const uint32_t boot_start = FLASH_BOOT_START_ADDR; | |
| 1647 const uint32_t hw_off = HARDWAREDATA_ADDRESS - FLASH_BOOT_START_ADDR; | |
| 1648 const uint32_t total_boot_capacity = (FLASH_BOOT_END_ADDR - FLASH_BOOT_START_ADDR) + 1; | |
| 1649 | |
| 1650 /* Bound total to compare by the source-provided length and boot capacity */ | |
| 1651 uint32_t total = info->length; | |
| 1652 if (total > total_boot_capacity) { | |
| 1653 total = total_boot_capacity; | |
| 1654 } | |
| 1655 | |
| 1656 /* Region 1: from start to just before hardware data (if covered) */ | |
| 1657 uint32_t r1_len = (total > hw_off) ? hw_off : total; | |
| 1658 if (r1_len) { | |
| 1659 if (memcmp((void *)boot_start, pSource, r1_len) != 0) { | |
| 1660 return false; | |
| 1661 } | |
| 1662 } | |
| 1663 | |
| 1664 /* If total is within the hardware block, there's nothing more to compare */ | |
| 1665 if (total <= hw_off) { | |
| 1666 return true; | |
| 1667 } | |
| 1668 | |
| 1669 /* Skip hardware block overlap in both flash and source */ | |
| 1670 uint32_t after_hw_in_source = hw_off + sizeof(SHardwareData); | |
| 1671 uint32_t bytes_past_hw = 0; | |
| 1672 if (total > after_hw_in_source) { | |
| 1673 bytes_past_hw = total - after_hw_in_source; | |
| 1674 } else { | |
| 1675 /* Source length ends within or at the end of the hardware block */ | |
| 1676 return true; | |
| 1677 } | |
| 1678 | |
| 1679 /* Region 2: bytes after hardware data */ | |
| 1680 uint32_t r2_flash = HARDWAREDATA_ADDRESS + sizeof(SHardwareData); | |
| 1681 uint32_t r2_src = after_hw_in_source; | |
| 1682 | |
| 1683 if (memcmp((void *)r2_flash, pSource + r2_src, bytes_past_hw) != 0) { | |
| 1684 return false; | |
| 1685 } | |
| 1686 | |
| 1687 return true; | |
| 1688 } | |
| 1618 | 1689 |
| 1619 void openEdit_Maintenance(void) | 1690 void openEdit_Maintenance(void) |
| 1620 { | 1691 { |
| 1621 char text[32]; | 1692 char text[32]; |
| 1622 unsigned char index = 0; | 1693 unsigned char index = 0; |
| 1694 unsigned char nextLine = ME_Y_LINE3; | |
| 1623 SSettings *pSettings = settingsGetPointer(); | 1695 SSettings *pSettings = settingsGetPointer(); |
| 1624 SSensorDataDiveO2* pDiveO2Data = NULL; | 1696 SSensorDataDiveO2* pDiveO2Data = NULL; |
| 1625 | 1697 |
| 1626 customBlockInfo_t* pCustumBlockInfo = (customBlockInfo_t *) CUSTOM_BLOCK_INFO_ADDR; | 1698 customBlockInfo_t* pCustumBlockInfo = (customBlockInfo_t *) CUSTOM_BLOCK_INFO_ADDR; |
| 1627 | 1699 |
| 1628 blockInfo.Type = swapBytes(pCustumBlockInfo->Type); | 1700 blockInfo.Type = swapBytes(pCustumBlockInfo->Type); |
| 1629 blockInfo.fletcher = swapBytes(pCustumBlockInfo->fletcher); | 1701 blockInfo.fletcher = swapBytes(pCustumBlockInfo->fletcher); |
| 1630 blockInfo.length = swapBytes(pCustumBlockInfo->length); | 1702 blockInfo.length = swapBytes(pCustumBlockInfo->length); |
| 1631 | 1703 |
| 1704 uint32_t checksum = CalcFletcher32(0x08100000,0x0811FFEF); /* last nibble contains block info => exclude */ | |
| 1705 | |
| 1632 resetMenuEdit(CLUT_MenuPageSystem); | 1706 resetMenuEdit(CLUT_MenuPageSystem); |
| 1707 setBackMenu((uint32_t)openEdit_Reset, 0, 5); | |
| 1633 | 1708 |
| 1634 text[0] = '\001'; | 1709 text[0] = '\001'; |
| 1635 text[1] = TXT_2BYTE; | 1710 text[1] = TXT_2BYTE; |
| 1636 text[2] = TXT2BYTE_Maintenance; | 1711 text[2] = TXT2BYTE_Maintenance; |
| 1637 text[3] = 0; | 1712 text[3] = 0; |
| 1649 text[1] = TXT2BYTE_SetBatteryCharge; | 1724 text[1] = TXT2BYTE_SetBatteryCharge; |
| 1650 text[2] = 0; | 1725 text[2] = 0; |
| 1651 snprintf(&text[2],10,": %u%%",pSettings->lastKnownBatteryPercentage); | 1726 snprintf(&text[2],10,": %u%%",pSettings->lastKnownBatteryPercentage); |
| 1652 write_field_button(StMSYS5_SetBattCharge, 30, 800, ME_Y_LINE2, &FontT48, text); | 1727 write_field_button(StMSYS5_SetBattCharge, 30, 800, ME_Y_LINE2, &FontT48, text); |
| 1653 } | 1728 } |
| 1729 | |
| 1730 /* No need to remember line; we'll update the field text directly */ | |
| 1731 | |
| 1732 #ifdef ENABLE_ANALYSE_SAMPLES | |
| 1733 text[0] = TXT_2BYTE; | |
| 1734 text[1] = TXT2BYTE_SetSampleIndex; | |
| 1735 text[2] = 0; | |
| 1736 write_field_button(StMSYS5_SetSampleIndx, 30, 800, nextLine, &FontT48, text); | |
| 1737 nextLine += ME_Y_LINE_STEP; | |
| 1738 #endif | |
| 1654 | 1739 |
| 1655 if((pSettings->ppo2sensors_source == O2_SENSOR_SOURCE_ANADIG) || (pSettings->ppo2sensors_source == O2_SENSOR_SOURCE_DIGITAL)) | 1740 if((pSettings->ppo2sensors_source == O2_SENSOR_SOURCE_ANADIG) || (pSettings->ppo2sensors_source == O2_SENSOR_SOURCE_DIGITAL)) |
| 1656 { | 1741 { |
| 1657 for (index = 0; index < 3; index++) | 1742 for (index = 0; index < 3; index++) |
| 1658 { | 1743 { |
| 1662 if(pDiveO2Data->pressure != 0) | 1747 if(pDiveO2Data->pressure != 0) |
| 1663 { | 1748 { |
| 1664 snprintf(text,32,"%c%c (%1.3lf => %1.3f)\016\016Bar",TXT_2BYTE,TXT2BYTE_AdjustAmbPressure,(float)(pDiveO2Data->pressure/1000000.0), | 1749 snprintf(text,32,"%c%c (%1.3lf => %1.3f)\016\016Bar",TXT_2BYTE,TXT2BYTE_AdjustAmbPressure,(float)(pDiveO2Data->pressure/1000000.0), |
| 1665 stateRealGetPointer()->lifeData.pressure_surface_bar); | 1750 stateRealGetPointer()->lifeData.pressure_surface_bar); |
| 1666 | 1751 |
| 1667 write_field_button(StMSYS5_AdjustSurfPres, 30, 800, ME_Y_LINE4, &FontT48, text); | 1752 write_field_button(StMSYS5_AdjustSurfPres, 30, 800, nextLine, &FontT48, text); |
| 1753 nextLine += ME_Y_LINE_STEP; | |
| 1668 } | 1754 } |
| 1669 break; | 1755 break; |
| 1670 } | 1756 } |
| 1671 } | 1757 } |
| 1672 } | 1758 } |
| 1673 | 1759 |
| 1674 if((blockInfo.Type & 0x0000FF00)== 0x0100) | 1760 if (isValidBootloaderBlock(&blockInfo, checksum)) { |
| 1675 { | 1761 if (!isBootloaderEqualToSource(&blockInfo)) { |
| 1676 snprintf(text,32,"Flash Bootloader"); | 1762 snprintf(text,32,"Flash Bootloader"); |
| 1677 write_field_button(StMSYS5_FlashBoot, 30, 800, ME_Y_LINE4, &FontT48, text); | 1763 if (nextLine < ME_Y_LINE5) { |
| 1678 } | 1764 write_field_button(StMSYS5_FlashBoot, 30, 800, nextLine, &FontT48, text); |
| 1679 | 1765 nextLine += ME_Y_LINE_STEP; |
| 1680 #ifdef ENABLE_ANALYSE_SAMPLES | 1766 } |
| 1681 text[0] = TXT_2BYTE; | 1767 } |
| 1682 text[1] = TXT2BYTE_SetSampleIndex; | 1768 } |
| 1683 text[2] = 0; | |
| 1684 write_field_button(StMSYS5_SetSampleIndx, 30, 800, ME_Y_LINE4, &FontT48, text); | |
| 1685 #endif | |
| 1686 | 1769 |
| 1687 setEvent(StMSYS5_SetFactoryBC, (uint32_t)OnAction_SetFactoryDefaults); | 1770 setEvent(StMSYS5_SetFactoryBC, (uint32_t)OnAction_SetFactoryDefaults); |
| 1688 if(stateRealGetPointer()->lifeData.battery_charge <= 0) | 1771 if(stateRealGetPointer()->lifeData.battery_charge <= 0) |
| 1689 { | 1772 { |
| 1690 setEvent(StMSYS5_SetBattCharge, (uint32_t)OnAction_SetBatteryCharge); | 1773 setEvent(StMSYS5_SetBattCharge, (uint32_t)OnAction_SetBatteryCharge); |
| 1698 } | 1781 } |
| 1699 #ifdef ENABLE_ANALYSE_SAMPLES | 1782 #ifdef ENABLE_ANALYSE_SAMPLES |
| 1700 setEvent(StMSYS5_SetSampleIndx, (uint32_t)OnAction_RecoverSampleIdx); | 1783 setEvent(StMSYS5_SetSampleIndx, (uint32_t)OnAction_RecoverSampleIdx); |
| 1701 #endif | 1784 #endif |
| 1702 | 1785 |
| 1703 if((blockInfo.Type & 0x0000FF00)== 0x0100) | 1786 if (isValidBootloaderBlock(&blockInfo, checksum) && !isBootloaderEqualToSource(&blockInfo)) { |
| 1704 { | 1787 setEvent(StMSYS5_FlashBoot, (uint32_t)OnAction_FlashBootloader); |
| 1705 setEvent(StMSYS5_FlashBoot, (uint32_t)OnAction_FlashBootloader); | 1788 } |
| 1706 } | |
| 1707 | |
| 1708 | |
| 1709 | 1789 |
| 1710 text[0] = TXT_2BYTE; | 1790 text[0] = TXT_2BYTE; |
| 1711 text[1] = TXT2BYTE_WarnBatteryLow; | 1791 text[1] = TXT2BYTE_WarnBatteryLow; |
| 1712 text[2] = 0; | 1792 text[2] = 0; |
| 1713 snprintf(&text[2],10,": %01.2fV",stateRealGetPointer()->lifeData.battery_voltage); | 1793 snprintf(&text[2],10,": %01.2fV",stateRealGetPointer()->lifeData.battery_voltage); |
| 1825 settingsGetPointer()->showDebugInfo = 0; | 1905 settingsGetPointer()->showDebugInfo = 0; |
| 1826 extern uint8_t bootToBootloader; | 1906 extern uint8_t bootToBootloader; |
| 1827 bootToBootloader = 1; | 1907 bootToBootloader = 1; |
| 1828 return UNSPECIFIC_RETURN; | 1908 return UNSPECIFIC_RETURN; |
| 1829 } | 1909 } |
| 1910 | |
| 1830 | 1911 |
| 1831 | 1912 |
| 1832 uint8_t OnAction_SetFactoryDefaults(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) | 1913 uint8_t OnAction_SetFactoryDefaults(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) |
| 1833 { | 1914 { |
| 1834 settingsWriteFactoryDefaults(settingsGetPointer()->ButtonResponsiveness[3], settingsGetPointer()->buttonBalance); | 1915 settingsWriteFactoryDefaults(settingsGetPointer()->ButtonResponsiveness[3], settingsGetPointer()->buttonBalance); |
| 1939 SHardwareData HwInfo; | 2020 SHardwareData HwInfo; |
| 1940 customBlockInfo_t* pCustumBlockInfo = (customBlockInfo_t *) CUSTOM_BLOCK_INFO_ADDR; | 2021 customBlockInfo_t* pCustumBlockInfo = (customBlockInfo_t *) CUSTOM_BLOCK_INFO_ADDR; |
| 1941 customBlockInfo_t blockInfo; | 2022 customBlockInfo_t blockInfo; |
| 1942 uint32_t checksum; | 2023 uint32_t checksum; |
| 1943 uint8_t* pSource = (uint8_t *) 0x08100000; | 2024 uint8_t* pSource = (uint8_t *) 0x08100000; |
| 2025 uint8_t eraseResult; | |
| 2026 uint8_t progResult; | |
| 2027 | |
| 2028 // Update the button's text directly to show progress | |
| 2029 tMenuEdit_newButtonText(editId, "Flashing, please wait"); | |
| 1944 | 2030 |
| 1945 checksum = CalcFletcher32(0x08100000,0x0811FFEF); /* last nibble contains block info => exclude */ | 2031 checksum = CalcFletcher32(0x08100000,0x0811FFEF); /* last nibble contains block info => exclude */ |
| 1946 | 2032 |
| 1947 blockInfo.Type = swapBytes(pCustumBlockInfo->Type); | 2033 blockInfo.Type = swapBytes(pCustumBlockInfo->Type); |
| 1948 blockInfo.fletcher = swapBytes(pCustumBlockInfo->fletcher); | 2034 blockInfo.fletcher = swapBytes(pCustumBlockInfo->fletcher); |
| 1949 blockInfo.length = swapBytes(pCustumBlockInfo->length); | 2035 blockInfo.length = swapBytes(pCustumBlockInfo->length); |
| 1950 | 2036 |
| 1951 if(checksum == blockInfo.fletcher) | 2037 if (isValidBootloaderBlock(&blockInfo, checksum)) { |
| 1952 { | |
| 1953 memcpy (&HwInfo, hardwareDataGetPointer(), sizeof(SHardwareData)); /* create backup copy because data will be overwritten during flash erase */ | 2038 memcpy (&HwInfo, hardwareDataGetPointer(), sizeof(SHardwareData)); /* create backup copy because data will be overwritten during flash erase */ |
| 1954 | 2039 |
| 1955 bootloader_eraseFlashMemory(); | 2040 eraseResult = bootloader_eraseFlashMemory(); |
| 1956 bootloader_programFlashMemory(pSource, blockInfo.length, &HwInfo); | 2041 if (eraseResult != 0) { |
| 2042 // Lock flash before returning on error | |
| 2043 HAL_FLASH_Lock(); | |
| 2044 // Show error on the button itself | |
| 2045 tMenuEdit_newButtonText(editId, "Erase failed!"); | |
| 2046 return UNSPECIFIC_RETURN; | |
| 2047 } | |
| 2048 | |
| 2049 progResult = bootloader_programFlashMemory(pSource, blockInfo.length, &HwInfo); | |
| 2050 if (progResult != 0) { | |
| 2051 // Lock flash before returning on error (in case program failed before locking) | |
| 2052 HAL_FLASH_Lock(); | |
| 2053 // Show error on the button itself | |
| 2054 tMenuEdit_newButtonText(editId, "Program failed!"); | |
| 2055 return UNSPECIFIC_RETURN; | |
| 2056 } | |
| 2057 | |
| 2058 // Show success on the button itself | |
| 2059 tMenuEdit_newButtonText(editId, "Flash complete"); | |
| 2060 | |
| 2061 // Give user time to see the message, then return to the previous menu | |
| 2062 // which will cause a refresh and hide the "Flash Bootloader" button | |
| 2063 HAL_Delay(1500); | |
| 2064 | |
| 2065 return EXIT_TO_MENU; | |
| 1957 } | 2066 } |
| 1958 return UNSPECIFIC_RETURN; | 2067 return UNSPECIFIC_RETURN; |
| 1959 } | 2068 } |
| 1960 | 2069 |
| 1961 /* | 2070 /* |
