diff --git a/components/bms_boss/HW/HW_flash.c b/components/bms_boss/HW/HW_flash.c new file mode 100644 index 00000000..1568279c --- /dev/null +++ b/components/bms_boss/HW/HW_flash.c @@ -0,0 +1,255 @@ +/* + * HW_FLASH.c + * This file describes low-level, mostly hardware-specific Flash behaviour + * https://www.st.com/resource/en/programming_manual/pm0075-stm32f10xxx-flash-memory-microcontrollers-stmicroelectronics.pdf + */ + +/****************************************************************************** + * I N C L U D E S + ******************************************************************************/ + +// module include +#include "HW_flash.h" +#include "LIB_utility.h" + +#include "string.h" +#include "stdbool.h" + +#define FLASH_BASE (0x40022000UL) // base address of flash registers + +#define FLASH_ACR (FLASH_BASE + 0x00UL) // flash access control register +#define FLASH_KEYR (FLASH_BASE + 0x04UL) // flash key register for unlocking flash +#define FLASH_OPTKEYR (FLASH_BASE + 0x08UL) // flash key register for unlocking option bytes +#define FLASH_SR (FLASH_BASE + 0x0CUL) // flash status register +#define FLASH_CR (FLASH_BASE + 0x10UL) // flash control register +#define FLASH_AR (FLASH_BASE + 0x14UL) // flash access register +#define FLASH_OBR (FLASH_BASE + 0x1CUL) // flash option byte register +#define FLASH_WRPR (FLASH_BASE + 0x20UL) // flash write protection register + +#define FLASH_KEY1 (0x45670123UL) // first key to be written to unlock flash +#define FLASH_KEY2 (0xCDEF89ABUL) // second key to be written to unlock flash +#define FLASH_RDPRT (0x000000A5UL) // flash read protection key +#define FLASH_SR_BSY (0x00000001UL) // flash busy bit +#define FLASH_CR_PG (0x00000001UL) // flash program enable bit +#define FLASH_CR_PER (0x00000002UL) // flash page erase enable bit +#define FLASH_CR_START (0x00000040UL) // flash page erase start bit +#define FLASH_CR_LOCK (0x00000080UL) // flash page erase start bit + +#define FLASH_PAGE_LAST (0x08007C00UL) // address of the last flash page +#define FLASH_SIZE_REG (0x1FFFF7E0UL) // register whose 4 least significant bits + // contains the size of the flash for this chip + +#define FLASH_BUSY() ((bool)(GET_REG(FLASH_SR) &FLASH_SR_BSY)) // returns true if flash is busy + +/****************************************************************************** + * P R I V A T E V A R S + ******************************************************************************/ +typedef struct +{ + const uint16_t pageSize; +} flash_S; + +flash_S flash; + +/****************************************************************************** + * P U B L I C F U N C T I O N S + ******************************************************************************/ + +void FLASH_init(void) +{ + const uint16_t pageSize = FLASH_getPageSize(); + flash_S fl = { + .pageSize = pageSize, + }; + + memcpy(&flash, &fl, sizeof(flash_S)); +} + +/* + * FLASH_lock + * @brief Lock the Flash Programming and Erase Controller (FPEC) once + * we're done interacting with the flash + */ +void FLASH_lock(void) +{ + // should we take down the HSI as well? + SET_REG(FLASH_CR, FLASH_CR_LOCK); +} + + +/* + * FLASH_unlock + * @brief Unlock the Flash Programming and Erase Controller (FPEC) so we can perform + * operations on the flash + */ +void FLASH_unlock(void) +{ + if (READ_BIT(FLASH_CR, FLASH_CR_LOCK)) return; + SET_REG(FLASH_KEYR, FLASH_KEY1); + SET_REG(FLASH_KEYR, FLASH_KEY2); + while (READ_BIT(FLASH_CR, FLASH_CR_LOCK)); +} + +/* + * FLASH_erasePages + * @brief Erase the given number of pages of flash, starting from the given page address + * @param startPageAddr uint32_t the address of the first page to erase + * @param pages uint16_t the number of pages to erase + */ +bool FLASH_erasePages(uint32_t startPageAddr, uint16_t pages) +{ + FLASH_unlock(); + bool ret = true; + + // set the page erase bit + SET_REG(FLASH_CR, GET_REG(FLASH_CR) | FLASH_CR_PER); + + for (uint16_t page = 0U; page < pages; page++) + { + uint32_t currPageAddr = startPageAddr + (page * flash.pageSize); + uint32_t currPageEnd = currPageAddr + flash.pageSize; + while (FLASH_BUSY()) + {} + + // set the page address to erase + SET_REG(FLASH_AR, currPageAddr); + // start the erase process + SET_REG(FLASH_CR, GET_REG(FLASH_CR) | FLASH_CR_START); + + while (FLASH_BUSY()) + {} + + // verify page has been erased + // verify 64 bits at a time + for (uint32_t flashWordAddr = currPageAddr; flashWordAddr < currPageEnd; flashWordAddr += 8) + { + if ((*(volatile uint64_t *)flashWordAddr) != 0xFFFFFFFFFFFFFFFFULL) + { + ret = false; + } + } + } + + // clear the page erase bit + SET_REG(FLASH_CR, GET_REG(FLASH_CR) & ~FLASH_CR_PER); + + while (FLASH_BUSY()) + {} + + FLASH_lock(); + return ret; +} + +/* + * FLASH_writeWords + * @brief write the given words of data starting at the given address in flash + * @param addr uint32_t the address of the first word to write + * @param data uint32_t* the words to write + * @param dataLen uint16_t the number of words to write + */ +bool FLASH_writeWords(uint32_t addr, uint32_t *data, uint16_t dataLen) +{ + volatile uint16_t *addr_16; + volatile uint16_t *data_16; + bool ret = true; + + FLASH_unlock(); + // Set the PG bit in FLASH_CR which enables writing + SET_REG(FLASH_CR, GET_REG(FLASH_CR) | FLASH_CR_PG); + + // write all the data + for (uint16_t dataOffset = 0U; dataOffset < dataLen; dataOffset++) + { + // get pointer to the word in flash, access as two half words. + // word is 4 bytes, thus (offset * 4) + addr_16 = (volatile uint16_t*)(addr + (dataOffset * 4U)); + + // uint32_t cast to uint16_t array + // so increment by 2 when we want to get to the next word + data_16 = &(((volatile uint16_t*)data)[dataOffset * 2U]); + + while (FLASH_BUSY()) + {} + addr_16[0] = data_16[0]; + + while (FLASH_BUSY()) + {} + addr_16[1] = data_16[1]; + + while (FLASH_BUSY()) + {} + + // verify the data in flash, + // compare as words + if (*(volatile uint32_t *)(addr + (dataOffset * 4U)) != data[dataOffset]) + { + ret = false; + break; + } + } + + // Clear the PG bit in FLASH_CR + SET_REG(FLASH_CR, GET_REG(FLASH_CR) & ~FLASH_CR_PG); + FLASH_lock(); + + return ret; +} + +/* + * FLASH_writeHalfwords + * @brief write the given halfwords of data starting at the given address in flash + * @param addr uint32_t the address of the first halfword to write + * @param data uint16_t* the halfwords to write + * @param dataLen uint16_t the number of halfwords to write + */ +bool FLASH_writeHalfwords(uint32_t addr, uint16_t *data, uint16_t dataLen) +{ + bool ret = true; + + FLASH_unlock(); + // Set the PG bit in FLASH_CR which enables writing + SET_REG(FLASH_CR, GET_REG(FLASH_CR) | FLASH_CR_PG); + + // write all the data + for (uint16_t dataIdx = 0U; dataIdx < dataLen; dataIdx++) + { + while (FLASH_BUSY()) + {} + volatile uint16_t* addr_16 = (volatile uint16_t*)(addr + dataIdx * sizeof(uint16_t)); + *addr_16 = data[dataIdx]; + + while (FLASH_BUSY()) + {} + + // verify the data in flash, + // compare as halfwords + if (*addr_16 != data[dataIdx]) + { + ret = false; + break; + } + } + + // Clear the PG bit in FLASH_CR + SET_REG(FLASH_CR, GET_REG(FLASH_CR) & ~FLASH_CR_PG); + FLASH_lock(); + + return ret; +} + +uint32_t FLASH_getPageSize(void) +{ + uint16_t *flashSize = (uint16_t *)(FLASH_SIZE_REG); + + // chips with more than 128 pages of flash have pages of size 2k + // otherwise, pages are of size 1k + if ((*flashSize & 0xFFFF) > 128U) + { + return 2048U; + } + else + { + return 1024U; + } +} + diff --git a/components/bms_boss/HW/include/BuildDefines.h b/components/bms_boss/HW/include/BuildDefines.h index b6e2d7c5..d5359162 100644 --- a/components/bms_boss/HW/include/BuildDefines.h +++ b/components/bms_boss/HW/include/BuildDefines.h @@ -8,6 +8,10 @@ #include "FeatureDefines_generated.h" #include "BuildDefines_generated.h" +#define NVM_LIB_ENABLED FEATURE_ENABLED +#define NVM_FLASH_BACKED FEATURE_ENABLED +#define NVM_BLOCK_SIZE 2048 // Multiple of page size + #if MCU_STM32_PN == FDEFS_STM32_PN_STM32F103XB #define STM32F1 #define STM32F103xB diff --git a/components/bms_boss/HW/include/HW_flash.h b/components/bms_boss/HW/include/HW_flash.h new file mode 100644 index 00000000..0ed0ecde --- /dev/null +++ b/components/bms_boss/HW/include/HW_flash.h @@ -0,0 +1,26 @@ +/* + * HW_FLASH.h + * This file describes low-level, mostly hardware-specific Flash peripheral values + */ + +#pragma once + +/****************************************************************************** + * I N C L U D E S + ******************************************************************************/ + +#include "Types.h" + +/****************************************************************************** + * P U B L I C F U N C T I O N P R O T O T Y P E S + ******************************************************************************/ + +void FLASH_init(void); + +void FLASH_lock(void); +void FLASH_unlock(void); + +uint32_t FLASH_getPageSize(void); +bool FLASH_erasePages(uint32_t pageAddr, uint16_t pages); +bool FLASH_writeHalfwords(uint32_t addr, uint16_t *data, uint16_t dataLen); +bool FLASH_writeWords(uint32_t addr, uint32_t *data, uint16_t dataLen); diff --git a/components/bms_boss/SConscript b/components/bms_boss/SConscript index a52386d5..38b95361 100644 --- a/components/bms_boss/SConscript +++ b/components/bms_boss/SConscript @@ -149,6 +149,9 @@ project_source_files = [ SRC_DIR.File("Utility.c"), SRC_DIR.File("UDS.c"), SHARED_LIBS.File("LIB_app.c"), + SHARED_LIBS.File("LIB_nvm.c"), + SHARED_LIBS.File("libcrc.c"), + SRC_DIR.File("NVM.c"), ] project_hw_files = [ @@ -162,6 +165,7 @@ project_hw_files = [ HW_DIR.File("HW_msp.c"), HW_DIR.File("HW_tim.c"), HW_DIR.File("HW_HIH.c"), + HW_DIR.File("HW_flash.c"), ] project_source_files += project_hw_files diff --git a/components/bms_boss/include/BuildDefines_config.h b/components/bms_boss/include/BuildDefines_config.h deleted file mode 100644 index 1e7ca079..00000000 --- a/components/bms_boss/include/BuildDefines_config.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * BuildDefines.h - * - */ - -#pragma once - -#include "FeatureDefines_generated.h" - -#if (MCU_STM32_PN == FDEFS_STM32_PN_STM32F103XB) -#define STM32F1 -#define STM32F103xB -#if FEATURE_IS_ENABLED(MCU_STM32_USE_HAL) -#define USE_HAL_DRIVER -#endif // stm32f103xb diff --git a/components/bms_boss/include/LIB_nvm_config.h b/components/bms_boss/include/LIB_nvm_config.h new file mode 100644 index 00000000..748bf1a5 --- /dev/null +++ b/components/bms_boss/include/LIB_nvm_config.h @@ -0,0 +1,24 @@ +/** + * LIB_nvm_config.h + * LIB_nvm Component Specific file + */ + +#pragma once + +#include "HW.h" +#include "HW_flash.h" +#include "LIB_nvm.h" + +/****************************************************************************** + * T Y P E D E F S + ******************************************************************************/ + +#define LIB_NVM_GET_TIME_MS HW_getTick +#define LIB_NVM_GET_FLASH_PAGE_SIZE FLASH_getPageSize +#define LIB_NVM_CLEAR_FLASH_PAGES FLASH_erasePages +#define LIB_NVM_WRITE_TO_FLASH(addr, data, bytes) FLASH_writeHalfwords(addr, data, bytes / sizeof(storage_t)) + +typedef enum +{ + NVM_ENTRYID_COUNT = 0U, +} lib_nvm_entryId_E; diff --git a/components/bms_boss/include/libcrc_componentSpecific.h b/components/bms_boss/include/libcrc_componentSpecific.h new file mode 100644 index 00000000..aba03401 --- /dev/null +++ b/components/bms_boss/include/libcrc_componentSpecific.h @@ -0,0 +1,7 @@ +/* + * libcrc_componentSpecific.h + * + * Configuration for the libcrc module + */ + +#define LIBCRC_CRC8_FAST diff --git a/components/bms_boss/src/CAN/CANIO-tx.c b/components/bms_boss/src/CAN/CANIO-tx.c index 98a542fc..33c4f20c 100644 --- a/components/bms_boss/src/CAN/CANIO-tx.c +++ b/components/bms_boss/src/CAN/CANIO-tx.c @@ -23,6 +23,7 @@ #include "Sys.h" #include "IMD.h" #include "ENV.h" +#include "LIB_nvm.h" #include "SigTx.c" #include "MessageUnpack_generated.h" @@ -38,11 +39,13 @@ typedef struct { uint8_t tx_100Hz_msg; + uint8_t tx_1Hz_msg; } cantx_S; typedef struct { uint8_t counter_100Hz; + uint8_t counter_1Hz; } cantx_counter_S; /****************************************************************************** @@ -78,6 +81,11 @@ static cantx_counter_S cantx_counter; #define set_nlg513MaxMainsCurrent(m,b,n,s) set(m,b,n,s, 16.0f) #define set_nlg513MaxChargeVoltage(m,b,n,s) set(m,b,n,s, BMS_CONFIGURED_PACK_MAX_VOLTAGE) #define set_nlg513MaxChargeCurrent(m,b,n,s) set(m,b,n,s, BMS.pack_charge_limit) +#define set_nvmBootCycles(m,b,n,s) set(m,b,n,s, lib_nvm_getTotalCycles()) +#define set_nvmRecordWrites(m,b,n,s) set(m,b,n,s, lib_nvm_getTotalRecordWrites()) +#define set_nvmBlockErases(m,b,n,s) set(m,b,n,s, lib_nvm_getTotalBlockErases()) +#define set_nvmFailedCrc(m,b,n,s) set(m,b,n,s, lib_nvm_getTotalFailedCrc()) + #define transmit_BMSB_brusaChargeCommand (SYS_SFT_checkChargerTimeout()) #include "TemporaryStubbing.h" @@ -124,6 +132,38 @@ void CANTX_BUS_A_SWI(void) } cantx.tx_100Hz_msg++; } + + if (cantx.tx_1Hz_msg < VEH_packTable_1000ms_length) + { + CAN_data_T message_1Hz = {0}; + + const packTable_S* entry_1Hz = packNextMessage((const packTable_S*)&VEH_packTable_1000ms, + VEH_packTable_1000ms_length, + &cantx.tx_1Hz_msg, + &message_1Hz, + &cantx_counter.counter_1Hz); + + if (entry_1Hz != NULL) + { + if (CAN_sendMsgBus0(CAN_TX_PRIO_10HZ, message_1Hz, entry_1Hz->id, entry_1Hz->len)) + { + cantx.tx_1Hz_msg++; + } + memset(&message_1Hz, 0, sizeof(message_1Hz)); + } + } + if (cantx.tx_1Hz_msg == VEH_packTable_1000ms_length) + { + if (cantx_counter.counter_1Hz != 255U) + { + cantx_counter.counter_1Hz++; + } + else + { + cantx_counter.counter_1Hz = 0U; + } + cantx.tx_1Hz_msg++; + } } @@ -221,6 +261,18 @@ static void CANIO_tx_100Hz_PRD(void) cantx.tx_100Hz_msg = 0U; } +/** + * CANIO_tx_1Hz_PRD + * module 1Hz periodic function + */ +static void CANIO_tx_1Hz_PRD(void) +{ + if (cantx.tx_1Hz_msg < VEH_packTable_1000ms_length) { + // all the message weren't sent. TO-DO: error handling + } + cantx.tx_1Hz_msg = 0U; +} + /** * CANIO_tx_init * initialize module @@ -237,5 +289,6 @@ const ModuleDesc_S CANIO_tx = { .moduleInit = &CANIO_tx_init, .periodic1kHz_CLK = &CANIO_tx_1kHz_PRD, .periodic100Hz_CLK = &CANIO_tx_100Hz_PRD, + .periodic1Hz_CLK = &CANIO_tx_1Hz_PRD, }; diff --git a/components/bms_boss/src/Module.c b/components/bms_boss/src/Module.c index 6c593008..1e57b922 100644 --- a/components/bms_boss/src/Module.c +++ b/components/bms_boss/src/Module.c @@ -22,6 +22,7 @@ /**< Other Includes */ #include "Utility.h" #include "FeatureDefines_generated.h" +#include "LIB_nvm.h" /****************************************************************************** * P R I V A T E V A R S @@ -57,6 +58,7 @@ static uint64_t rtos_start; */ void Module_Init(void) { + lib_nvm_init(); /**< Run each of the modules Init function in order */ for (uint8_t i = 0U; i < COUNTOF(modules); i++) { @@ -109,6 +111,7 @@ void Module_100Hz_TSK(void) (*modules[i]->periodic100Hz_CLK)(); } } + lib_nvm_run(); vTaskGetInfo(NULL, &finish, pdFALSE, 0); stats[MODULE_100Hz_TASK].total_runtime += finish.ulRunTimeCounter - start.ulRunTimeCounter; diff --git a/components/bms_boss/src/NVM.c b/components/bms_boss/src/NVM.c new file mode 100644 index 00000000..9ad959b1 --- /dev/null +++ b/components/bms_boss/src/NVM.c @@ -0,0 +1,16 @@ +/** + * @file NVM.c + * @brief Source code for Non Volatile Memory Manager + */ + +/****************************************************************************** + * I N C L U D E S + ******************************************************************************/ + +#include "LIB_nvm.h" + +/****************************************************************************** + * P U B L I C V A R S + ******************************************************************************/ + +const lib_nvm_entry_S lib_nvm_entries[NVM_ENTRYID_COUNT]; diff --git a/components/bms_boss/src/SystemManager.c b/components/bms_boss/src/SystemManager.c index c699b117..cc735205 100644 --- a/components/bms_boss/src/SystemManager.c +++ b/components/bms_boss/src/SystemManager.c @@ -19,6 +19,7 @@ #include "HW_gpio.h" #include "HW_i2c.h" #include "HW_tim.h" +#include "HW_flash.h" /**< FreeRTOS Includes */ #include "FreeRTOS.h" @@ -83,6 +84,7 @@ int main(void) HW_CAN_init(); HW_DMA_init(); HW_ADC_init(); + FLASH_init(); ///**< Create RTOS Tasks, Timers, etc... */ RTOS_SWI_Init(); diff --git a/components/bootloaders/STM/stm32f103/SConscript b/components/bootloaders/STM/stm32f103/SConscript index 7e85b14a..df969f85 100644 --- a/components/bootloaders/STM/stm32f103/SConscript +++ b/components/bootloaders/STM/stm32f103/SConscript @@ -116,12 +116,12 @@ src_files = [ SRC_DIR.File("c_only_startup.S"), SRC_DIR.File("cortexm3_macro.S"), SHARED_LIBS.File("LIB_app.c"), + SHARED_LIBS.File("libcrc.c"), ] uds_srcs = [ ISOTP_DIR.File("isotp.c"), UDS_DIR.File("src/udsServer.c"), - LIBS_DIR.File("libcrc/libcrc.c"), ] env.Append( diff --git a/components/bootloaders/STM/stm32f103/include/HW/HW_FLASH.h b/components/bootloaders/STM/stm32f103/include/HW/HW_FLASH.h index 10548e8b..e7f9eb47 100644 --- a/components/bootloaders/STM/stm32f103/include/HW/HW_FLASH.h +++ b/components/bootloaders/STM/stm32f103/include/HW/HW_FLASH.h @@ -35,6 +35,7 @@ #define FLASH_CR_PG (0x00000001UL) // flash program enable bit #define FLASH_CR_PER (0x00000002UL) // flash page erase enable bit #define FLASH_CR_START (0x00000040UL) // flash page erase start bit +#define FLASH_CR_LOCK (0x00000080UL) // flash page erase start bit #define FLASH_PAGE_LAST (0x08007C00UL) // address of the last flash page #define FLASH_SIZE_REG (0x1FFFF7E0UL) // register whose 4 least significant bits diff --git a/components/bootloaders/STM/stm32f103/src/HW/HW_FLASH.c b/components/bootloaders/STM/stm32f103/src/HW/HW_FLASH.c index 7e12ca8c..ce380e6c 100644 --- a/components/bootloaders/STM/stm32f103/src/HW/HW_FLASH.c +++ b/components/bootloaders/STM/stm32f103/src/HW/HW_FLASH.c @@ -91,6 +91,7 @@ void FLASH_lock(void) */ void FLASH_unlock(void) { + if (READ_BIT(FLASH_CR, FLASH_CR_LOCK)) return; SET_REG(FLASH_KEYR, FLASH_KEY1); SET_REG(FLASH_KEYR, FLASH_KEY2); } diff --git a/components/shared/code/libs/LIB_nvm.c b/components/shared/code/libs/LIB_nvm.c new file mode 100644 index 00000000..fd014687 --- /dev/null +++ b/components/shared/code/libs/LIB_nvm.c @@ -0,0 +1,474 @@ +/** LIB_nvm.c + * Source code for the NVM Manager + */ + +/****************************************************************************** + * I N C L U D E S + ******************************************************************************/ + +#include "LIB_nvm.h" +#include +#if FEATURE_IS_ENABLED(NVM_LIB_ENABLED) +#include "LIB_utility.h" +#include "libcrc.h" +#include "string.h" + +/****************************************************************************** + * D E F I N E S + ******************************************************************************/ + +#define LIB_NVM_VERSION 1U +#define NVM_TOTAL_ENTRYID_COUNT (NVM_ENTRYID_INTERNAL_COUNT + COUNTOF(lib_nvm_entries)) + +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) +#define SET_STATE 0x00 +#else +#error "Only flash backed nvm supported presently." +#endif + +/****************************************************************************** + * E X T E R N S + ******************************************************************************/ + +extern const lib_nvm_entry_S lib_nvm_entries[NVM_ENTRYID_COUNT]; + +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) +extern storage_t __FLASH_NVM_ORIGIN; +extern storage_t __FLASH_NVM_END; +storage_t * const nvm_origin = &__FLASH_NVM_ORIGIN; +storage_t * const nvm_end = &__FLASH_NVM_END; +#endif + +/****************************************************************************** + * T Y P E D E F S + ******************************************************************************/ + +typedef uint8_t lib_nvm_crc_t; + +typedef enum +{ + NVM_ENTRYID_INTERNAL_LOG = 0U, + NVM_ENTRYID_INTERNAL_CYCLE, // Anytime an entry is added, a spare should be removed + NVM_ENTRYID_INTERNAL_SPARE_1, + NVM_ENTRYID_INTERNAL_SPARE_2, + NVM_ENTRYID_INTERNAL_SPARE_3, + NVM_ENTRYID_INTERNAL_COUNT, +} lib_nvm_entryIdInternal_E; +#define NVM_LAST_USED_INTERNAL_ENTRYID NVM_ENTRYID_INTERNAL_CYCLE + +typedef struct +{ + lib_nvm_entry_t entryId; + storage_t entry_version; + lib_nvm_crc_t crc; + storage_t initialized; + storage_t discarded; +} LIB_NVM_STORAGE(lib_nvm_recordHeader_S); + +typedef struct +{ + lib_nvm_recordHeader_S* currentNonVolatileAddress_Ptr; + uint32_t lastWrittenTime; + uint8_t observedDifferences; + bool writeRequired; +} lib_nvm_recordData_S; + +typedef struct +{ + uint32_t totalRecordWrites; + uint32_t totalFailedCrc; + uint32_t totalBlockClears; + uint32_t spare[4]; +} LIB_NVM_STORAGE(lib_nvm_nvmRecordLog_S); + +typedef struct +{ + uint32_t totalCycles; + uint32_t spare[2]; +} LIB_NVM_STORAGE(lib_nvm_nvmCycleLog_S); + +typedef struct +{ +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) + uint32_t pageSize; + storage_t* currentPtr; +#endif +} lib_nvm_data_S; + +typedef struct +{ + uint16_t nvm_version; + storage_t initialized; + storage_t discarded; +} LIB_NVM_STORAGE(lib_nvm_blockHeader_S); + +/****************************************************************************** + * P R I V A T E V A R S + ******************************************************************************/ + +lib_nvm_recordData_S records[NVM_TOTAL_ENTRYID_COUNT] = {0U}; +lib_nvm_data_S data = { 0U }; + +const lib_nvm_nvmRecordLog_S recordLogDefault = { + .totalRecordWrites = 0U, + .totalFailedCrc = 0U, + .spare = { 0U }, +}; + +const lib_nvm_nvmCycleLog_S cycleLogDefault = { + .totalCycles = 0U, + .spare = { 0U }, +}; + +LIB_NVM_MEMORY_REGION_ARRAY(lib_nvm_recordHeader_S recordHeaders, NVM_TOTAL_ENTRYID_COUNT) = { 0U }; +LIB_NVM_MEMORY_REGION(lib_nvm_blockHeader_S blockHeader) = { 0U }; +LIB_NVM_MEMORY_REGION(lib_nvm_nvmRecordLog_S recordLog) = { 0U }; +LIB_NVM_MEMORY_REGION(lib_nvm_nvmCycleLog_S cycleLog) = { 0U }; + +const lib_nvm_entry_S lib_nvm_private_entries[] = { + [NVM_ENTRYID_INTERNAL_LOG] = { + .entryId = NVM_ENTRYID_INTERNAL_LOG, + .entrySize = sizeof(lib_nvm_nvmRecordLog_S), + .entryDefault_Ptr = &recordLogDefault, + .entryRam_Ptr = &recordLog, + }, + [NVM_ENTRYID_INTERNAL_CYCLE] = { + .entryId = NVM_ENTRYID_INTERNAL_LOG, + .entrySize = sizeof(lib_nvm_nvmCycleLog_S), + .entryDefault_Ptr = &cycleLogDefault, + .entryRam_Ptr = &cycleLog, + }, +}; +_Static_assert(COUNTOF(lib_nvm_private_entries) <= NVM_ENTRYID_INTERNAL_COUNT, "Too many private NVM entries."); + +/****************************************************************************** + * P R I V A T E F U N C T I O N P R O T O T Y P E S + ******************************************************************************/ + +void initializeEmptyRecords(void); +void evaluateWriteRequiredPrivate(lib_nvm_entry_t entryId); +void requestWritePrivate(lib_nvm_entry_t entryId); +void recordWrite(lib_nvm_entry_t entryId); +void recordPopulateDefault(lib_nvm_entry_t entryId); + +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) +void initializeNVMBlock(uint32_t addr); +uint32_t getBlockBaseAddress(uint32_t addr); +uint32_t getNextBlockStart(uint32_t addr); +#endif + +/****************************************************************************** + * P U B L I C F U N C T I O N S + ******************************************************************************/ + +void lib_nvm_init(void) +{ +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) + data.currentPtr = nvm_origin; + data.pageSize = LIB_NVM_GET_FLASH_PAGE_SIZE(); + + while((((lib_nvm_blockHeader_S*)data.currentPtr)->initialized != (storage_t)SET_STATE) || + (((lib_nvm_blockHeader_S*)data.currentPtr)->discarded == (storage_t)SET_STATE)) + { + data.currentPtr = (storage_t*)getNextBlockStart((uint32_t)data.currentPtr); + if (data.currentPtr == (nvm_end - NVM_BLOCK_SIZE / sizeof(storage_t))) + { + break; + } + } + + if ((((lib_nvm_blockHeader_S*)data.currentPtr)->initialized != (storage_t)SET_STATE) || + (((lib_nvm_blockHeader_S*)data.currentPtr)->discarded == (storage_t)SET_STATE)) + { + initializeNVMBlock((uint32_t)data.currentPtr); + } + else + { + data.currentPtr += sizeof(lib_nvm_blockHeader_S) / sizeof(storage_t); + + while ((((lib_nvm_recordHeader_S*)data.currentPtr)->initialized == SET_STATE) && + (getBlockBaseAddress((uint32_t)data.currentPtr) == getBlockBaseAddress((uint32_t)data.currentPtr + sizeof(lib_nvm_recordHeader_S)))) + { + storage_t* record = data.currentPtr + sizeof(lib_nvm_recordHeader_S) / sizeof(storage_t); + lib_nvm_entry_t id = (((lib_nvm_recordHeader_S*)data.currentPtr)->entryId <= NVM_LAST_USED_INTERNAL_ENTRYID) ? + ((lib_nvm_recordHeader_S*)data.currentPtr)->entryId : + ((lib_nvm_recordHeader_S*)data.currentPtr)->entryId - NVM_ENTRYID_INTERNAL_COUNT; + if (((lib_nvm_recordHeader_S*)data.currentPtr)->discarded != SET_STATE) + { + lib_nvm_crc_t crc = 0xff; + if (((lib_nvm_recordHeader_S*)data.currentPtr)->entryId <= NVM_LAST_USED_INTERNAL_ENTRYID) + { + crc = crc8_calculate(crc, (uint8_t*)record, lib_nvm_private_entries[id].entrySize); + } + else if (((lib_nvm_recordHeader_S*)data.currentPtr)->entryId >= NVM_ENTRYID_INTERNAL_COUNT) + { + crc = crc8_calculate(crc, (uint8_t*)record, lib_nvm_entries[id].entrySize); + } + + if (crc == ((lib_nvm_recordHeader_S*)data.currentPtr)->crc) + { + records[((lib_nvm_recordHeader_S*)data.currentPtr)->entryId].currentNonVolatileAddress_Ptr = (lib_nvm_recordHeader_S*)data.currentPtr; + if (((lib_nvm_recordHeader_S*)data.currentPtr)->entryId <= NVM_LAST_USED_INTERNAL_ENTRYID) + { + memcpy(lib_nvm_private_entries[id].entryRam_Ptr, (uint8_t*)record, lib_nvm_private_entries[id].entrySize); + } + else if (((lib_nvm_recordHeader_S*)data.currentPtr)->entryId >= NVM_ENTRYID_INTERNAL_COUNT) + { + memcpy(lib_nvm_entries[id].entryRam_Ptr, (uint8_t*)record, lib_nvm_entries[id].entrySize); + } + } + else + { + storage_t disc = SET_STATE; + LIB_NVM_WRITE_TO_FLASH((uint32_t)&(((lib_nvm_recordHeader_S*)data.currentPtr)->discarded), + &disc, + sizeof(storage_t)); + recordLog.totalFailedCrc++; + } + } + + if (((lib_nvm_recordHeader_S*)data.currentPtr)->entryId <= NVM_LAST_USED_INTERNAL_ENTRYID) + { + data.currentPtr += lib_nvm_private_entries[id].entrySize / sizeof(storage_t); + } + else if (((lib_nvm_recordHeader_S*)data.currentPtr)->entryId >= NVM_ENTRYID_INTERNAL_COUNT) + { + data.currentPtr += lib_nvm_entries[id].entrySize / sizeof(storage_t); + } + + data.currentPtr += sizeof(lib_nvm_recordHeader_S) / sizeof(storage_t); + } + } +#endif + + initializeEmptyRecords(); + cycleLog.totalCycles++; + requestWritePrivate(NVM_ENTRYID_INTERNAL_CYCLE); +} + +void lib_nvm_run(void) +{ + for (uint8_t index = NVM_ENTRYID_INTERNAL_COUNT; index < NVM_TOTAL_ENTRYID_COUNT; index++) + { + if (records[index].writeRequired) + { + recordWrite(index); + } + } + + for (int8_t index = NVM_ENTRYID_INTERNAL_COUNT; index >= 0; index--) + { + evaluateWriteRequiredPrivate(index); + if (records[index].writeRequired) + { + recordWrite(index); + } + } +} + +void lib_nvm_requestWrite(lib_nvm_entryId_E entryId) +{ + requestWritePrivate(entryId + NVM_ENTRYID_INTERNAL_COUNT); +} + +uint32_t lib_nvm_getTotalRecordWrites(void) +{ + return recordLog.totalRecordWrites; +} + +uint32_t lib_nvm_getTotalFailedCrc(void) +{ + return recordLog.totalFailedCrc; +} + +uint32_t lib_nvm_getTotalBlockErases(void) +{ + return recordLog.totalBlockClears; +} + +uint32_t lib_nvm_getTotalCycles(void) +{ + return cycleLog.totalCycles; +} + +/****************************************************************************** + * P R I V A T E F U N C T I O N S + ******************************************************************************/ + +void initializeEmptyRecords(void) +{ + for (lib_nvm_entry_t entry = 0U; entry <= NVM_LAST_USED_INTERNAL_ENTRYID; entry++) + { + if (records[entry].currentNonVolatileAddress_Ptr == NULL) + { + recordPopulateDefault(entry); + } + + requestWritePrivate(entry); + } + + for (lib_nvm_entry_t entry = 0U; entry < NVM_ENTRYID_COUNT; entry++) + { + if (records[entry + NVM_ENTRYID_INTERNAL_COUNT].currentNonVolatileAddress_Ptr == NULL) + { + recordPopulateDefault(entry + NVM_ENTRYID_INTERNAL_COUNT); + } + + lib_nvm_requestWrite(entry); + } +} + +void evaluateWriteRequiredPrivate(lib_nvm_entry_t entryId) +{ + switch (entryId) + { + case NVM_ENTRYID_INTERNAL_LOG: + { + if (records[NVM_ENTRYID_INTERNAL_LOG].currentNonVolatileAddress_Ptr == NULL) + { + records[NVM_ENTRYID_INTERNAL_LOG].writeRequired = true; + break; + } + + lib_nvm_nvmRecordLog_S recordLog_tmp = *((lib_nvm_nvmRecordLog_S*)(((storage_t*)(records[NVM_ENTRYID_INTERNAL_LOG].currentNonVolatileAddress_Ptr)) + sizeof(lib_nvm_recordHeader_S) / sizeof(storage_t))); + if ((recordLog_tmp.totalBlockClears != recordLog.totalBlockClears) || + (recordLog_tmp.totalRecordWrites != recordLog.totalRecordWrites) || + (recordLog_tmp.totalFailedCrc != recordLog.totalFailedCrc)) + { + records[NVM_ENTRYID_INTERNAL_LOG].writeRequired = true; + } + } + break; + + default: + break; + } +} + +void requestWritePrivate(lib_nvm_entry_t entryId) +{ + records[entryId].writeRequired = true; +} + +void recordWrite(lib_nvm_entry_t entryId) +{ + lib_nvm_recordHeader_S recordHeader = { 0U }; + + lib_nvm_recordHeader_S * const currentRecord = records[entryId].currentNonVolatileAddress_Ptr; + lib_nvm_blockHeader_S * const blockHeaderCurrent = (lib_nvm_blockHeader_S * const)getBlockBaseAddress((uint32_t)data.currentPtr); + uint8_t entrySize = (entryId <= NVM_LAST_USED_INTERNAL_ENTRYID) ? + lib_nvm_private_entries[entryId].entrySize : + lib_nvm_entries[entryId - NVM_ENTRYID_INTERNAL_COUNT].entrySize; + + if (blockHeaderCurrent != (lib_nvm_blockHeader_S * const)getBlockBaseAddress((uint32_t)data.currentPtr + sizeof(lib_nvm_recordHeader_S) + entrySize)) + { + storage_t disc = SET_STATE; + initializeNVMBlock(getNextBlockStart((uint32_t)data.currentPtr)); + lib_nvm_run(); + LIB_NVM_WRITE_TO_FLASH((uint32_t)&blockHeaderCurrent->discarded, &disc, sizeof(storage_t)); + return; + } + + records[entryId].currentNonVolatileAddress_Ptr = (lib_nvm_recordHeader_S*)data.currentPtr; + recordHeader.entryId = entryId; + recordHeader.initialized = SET_STATE; + recordHeader.discarded = ~SET_STATE; + data.currentPtr += sizeof(lib_nvm_recordHeader_S) / sizeof(storage_t); + + recordLog.totalRecordWrites++; + + if (entryId <= NVM_LAST_USED_INTERNAL_ENTRYID) + { +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) + LIB_NVM_WRITE_TO_FLASH((uint32_t)data.currentPtr, + lib_nvm_private_entries[entryId].entryRam_Ptr, + lib_nvm_private_entries[entryId].entrySize); + recordHeader.entry_version = lib_nvm_private_entries[entryId].version; + recordHeader.crc = (storage_t)crc8_calculate(0xff, + (uint8_t*)data.currentPtr, + lib_nvm_private_entries[entryId].entrySize); + data.currentPtr += lib_nvm_private_entries[entryId].entrySize / sizeof(storage_t); +#endif // NVM_FLASH_BACKED + } + else if (entryId >= NVM_ENTRYID_INTERNAL_COUNT) + { +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) + uint8_t relative_entry = entryId - NVM_ENTRYID_INTERNAL_COUNT; + LIB_NVM_WRITE_TO_FLASH((uint32_t)data.currentPtr, + lib_nvm_entries[relative_entry].entryRam_Ptr, + lib_nvm_entries[relative_entry].entrySize); + recordHeader.entry_version = lib_nvm_entries[relative_entry].version; + recordHeader.crc = (storage_t)crc8_calculate(0xff, + (uint8_t*)data.currentPtr, + lib_nvm_entries[relative_entry].entrySize); + data.currentPtr += lib_nvm_entries[relative_entry].entrySize / sizeof(storage_t); +#endif // NVM_FLASH_BACKED + } + +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) + LIB_NVM_WRITE_TO_FLASH((uint32_t)records[entryId].currentNonVolatileAddress_Ptr, + (storage_t*)&recordHeader, + sizeof(lib_nvm_recordHeader_S)); + if (currentRecord != NULL) + { + storage_t disc = SET_STATE; + LIB_NVM_WRITE_TO_FLASH((uint32_t)¤tRecord->discarded, + &disc, + sizeof(storage_t)); + } +#endif // NVM_FLASH_BACKED + records[entryId].writeRequired = false; + records[entryId].lastWrittenTime = LIB_NVM_GET_TIME_MS(); +} + +void recordPopulateDefault(lib_nvm_entry_t entryId) +{ +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) + if (entryId <= NVM_LAST_USED_INTERNAL_ENTRYID) + { + memcpy((uint32_t*)lib_nvm_private_entries[entryId].entryRam_Ptr, lib_nvm_private_entries[entryId].entryDefault_Ptr, lib_nvm_private_entries[entryId].entrySize); + } + else if (entryId >= NVM_ENTRYID_INTERNAL_COUNT) + { + uint8_t relative_entry = entryId - NVM_ENTRYID_INTERNAL_COUNT; + memcpy((uint32_t*)lib_nvm_entries[relative_entry].entryRam_Ptr, lib_nvm_entries[relative_entry].entryDefault_Ptr, lib_nvm_entries[relative_entry].entrySize); + } +#endif // NVM_FLASH_BACKED +} + +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) +void initializeNVMBlock(uint32_t addr) +{ + lib_nvm_blockHeader_S blockHeader_tmp = { 0U }; + blockHeader_tmp.discarded = ~SET_STATE; + blockHeader_tmp.initialized = SET_STATE; + blockHeader_tmp.nvm_version = LIB_NVM_VERSION; + + data.currentPtr = (storage_t*)getBlockBaseAddress(addr); + LIB_NVM_CLEAR_FLASH_PAGES((uint32_t)data.currentPtr, NVM_BLOCK_SIZE / data.pageSize); + + data.currentPtr += sizeof(lib_nvm_blockHeader_S) / sizeof(storage_t); + + initializeEmptyRecords(); + + LIB_NVM_WRITE_TO_FLASH(getBlockBaseAddress((uint32_t)data.currentPtr), + (storage_t*)&blockHeader_tmp, + sizeof(lib_nvm_blockHeader_S)); + + recordLog.totalBlockClears++; +} + +uint32_t getBlockBaseAddress(uint32_t addr) +{ + return (uint32_t)nvm_origin + (((addr - (uint32_t)nvm_origin) / NVM_BLOCK_SIZE) * NVM_BLOCK_SIZE); +} + +uint32_t getNextBlockStart(uint32_t addr) +{ + return ((getBlockBaseAddress(addr + NVM_BLOCK_SIZE) < (uint32_t)nvm_end) ? + (uint32_t)((addr + NVM_BLOCK_SIZE) - (addr % NVM_BLOCK_SIZE)) : + (uint32_t)nvm_origin); +} +#endif + +#endif // NVM_LIB_ENABLED diff --git a/components/shared/code/libs/LIB_nvm.h b/components/shared/code/libs/LIB_nvm.h new file mode 100644 index 00000000..0b1e7efa --- /dev/null +++ b/components/shared/code/libs/LIB_nvm.h @@ -0,0 +1,64 @@ +/** + * LIB_nvm.h + * Header file for the NVM Manager + */ + +#pragma once + +/****************************************************************************** + * I N C L U D E S + ******************************************************************************/ + +#include "BuildDefines.h" + +#if FEATURE_IS_ENABLED(NVM_LIB_ENABLED) +#include "stdbool.h" +#include "stdint.h" + +/****************************************************************************** + * D E F I N E S + ******************************************************************************/ + +#define LIB_NVM_STORAGE(x) (x) __attribute__((aligned(sizeof(storage_t)))) +#define LIB_NVM_MEMORY_REGION(x) __attribute__((section(".nvm"))) x##_nvm = { 0U }; \ + x +#define LIB_NVM_MEMORY_REGION_ARRAY(x, size) __attribute__((section(".nvm"))) x##_nvm[size] = { 0U }; \ + x[size] + +/****************************************************************************** + * T Y P E D E F S + ******************************************************************************/ + +#if FEATURE_IS_ENABLED(NVM_FLASH_BACKED) +#if MCU_STM32_PN == FDEFS_STM32_PN_STM32F103XB +typedef uint16_t storage_t; +#endif +#endif + +typedef uint8_t lib_nvm_entry_t; + +typedef struct +{ + const lib_nvm_entry_t entryId; + const uint16_t version; + const uint8_t entrySize; + const void * const entryDefault_Ptr; + void * const entryRam_Ptr; +} lib_nvm_entry_S; +#include "LIB_nvm_config.h" + +/****************************************************************************** + * P U B L I C F U N C T I O N P R O T O T Y P E S + ******************************************************************************/ + +void lib_nvm_init(void); +void lib_nvm_run(void); + +void lib_nvm_requestWrite(lib_nvm_entryId_E entryId); + +uint32_t lib_nvm_getTotalRecordWrites(void); +uint32_t lib_nvm_getTotalFailedCrc(void); +uint32_t lib_nvm_getTotalBlockErases(void); +uint32_t lib_nvm_getTotalCycles(void); + +#endif // NVM_LIB_ENABLED diff --git a/components/shared/code/libs/LIB_utility.h b/components/shared/code/libs/LIB_utility.h new file mode 100644 index 00000000..775c59c5 --- /dev/null +++ b/components/shared/code/libs/LIB_utility.h @@ -0,0 +1,30 @@ +/** LIB_utility.h + * Header file for utility functions + * Hardware and component a-specific + */ + +#pragma once + + +/****************************************************************************** + * I N C L U D E S + ******************************************************************************/ + +/****************************************************************************** + * D E F I N E S + ******************************************************************************/ + +#define COUNTOF(x) (sizeof(x)/sizeof(x[0U])) + +// taken from rogerclark +#define SET_REG(addr, val) do { *(volatile uint32_t*)(addr) = val; } while (0) +#define GET_REG(addr) (*(volatile uint32_t*)(addr)) + +// taken from stm32 hal +#define SET_BIT(REG, BIT) ((REG) |= (BIT)) +#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) +#define READ_BIT(REG, BIT) ((REG)&(BIT)) +#define CLEAR_REG(REG) ((REG) = (0x0)) +#define WRITE_REG(REG, VAL) ((REG) = (VAL)) +#define READ_REG(REG) ((REG)) +#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) diff --git a/embedded/libs/libcrc/libcrc.c b/components/shared/code/libs/libcrc.c similarity index 100% rename from embedded/libs/libcrc/libcrc.c rename to components/shared/code/libs/libcrc.c diff --git a/embedded/libs/libcrc/libcrc.h b/components/shared/code/libs/libcrc.h similarity index 100% rename from embedded/libs/libcrc/libcrc.h rename to components/shared/code/libs/libcrc.h diff --git a/embedded/platforms/stm32/f1/f103/STM32F103C8.ld b/embedded/platforms/stm32/f1/f103/STM32F103C8.ld index 5fd6517f..d07945b5 100644 --- a/embedded/platforms/stm32/f1/f103/STM32F103C8.ld +++ b/embedded/platforms/stm32/f1/f103/STM32F103C8.ld @@ -29,12 +29,25 @@ __HEAP_SIZE = 0x200; #endif +#ifndef NVM_LIB_ENABLED +#define NVM_LIB_ENABLED 0U +#endif +#if NVM_LIB_ENABLED +# ifndef NVM_BLOCK_SIZE +# define NVM_BLOCK_SIZE 1k +# endif +#define NVM_SIZE (2*NVM_BLOCK_SIZE) +__FLASH_NVM_ORIGIN = FLASH_ORIGIN + FLASH_SIZE - NVM_SIZE; +__FLASH_NVM_END = __FLASH_NVM_ORIGIN + NVM_SIZE; +#else +#define NVM_SIZE 0k +#endif /* determine app start address and size */ #if defined(APP_START_ADDR) # if APP_START_ADDR < FLASH_ORIGIN # error "App flash cannot start earlier than the flash origin address" # endif -__APP_SIZE = FLASH_SIZE - (APP_START_ADDR - FLASH_ORIGIN); +__APP_SIZE = FLASH_SIZE - (APP_START_ADDR - FLASH_ORIGIN) - NVM_SIZE; #else __APP_SIZE = FLASH_SIZE; #define APP_START_ADDR FLASH_ORIGIN @@ -43,8 +56,11 @@ __APP_SIZE = FLASH_SIZE; /* Memory definition */ MEMORY { - RAM (rwx) : ORIGIN = RAM_ORIGIN, LENGTH = RAM_SIZE - FLASH (rx) : ORIGIN = APP_START_ADDR, LENGTH = __APP_SIZE + RAM (rwx) : ORIGIN = RAM_ORIGIN, LENGTH = RAM_SIZE + FLASH (rx) : ORIGIN = APP_START_ADDR, LENGTH = __APP_SIZE +#if FEATURE_IS_ENABLED(NVM_LIB_ENABLED) + NVM_BLOCK (rw) : ORIGIN = __FLASH_NVM_ORIGIN, LENGTH = NVM_BLOCK_SIZE +#endif } SECTIONS @@ -154,6 +170,15 @@ SECTIONS /* *(.ARM.attributes) */ /* } */ +#if FEATURE_IS_ENABLED(NVM_LIB_ENABLED) + .nvm(NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.nvm)) + . = ALIGN(4); + } > NVM_BLOCK + ASSERT(SIZEOF(".nvm") < NVM_BLOCK_SIZE / 2, "NVM size should be more than twice the size of all members.") +#endif /* Initialized data sections into "RAM" Ram type memory */ .relocate : { @@ -177,11 +202,12 @@ SECTIONS /* CRC goes at the very end of the app */ .crc __app_end_addr : { + . = ALIGN(4); __app_crc_addr = .; KEEP(*(.appCrc)) + . = ALIGN(4); } > FLASH - /* Uninitialized data section into "RAM" Ram type memory */ .bss(NOLOAD) : { @@ -226,6 +252,7 @@ SECTIONS ASSERT(__HeapTop < __StackLimit, "RAM overflowed stack") #endif + /* Remove information from the compiler libraries */ /DISCARD/ : { diff --git a/network/definition/data/components/bmsb/bmsb-message.yaml b/network/definition/data/components/bmsb/bmsb-message.yaml index e0479967..baa65557 100644 --- a/network/definition/data/components/bmsb/bmsb-message.yaml +++ b/network/definition/data/components/bmsb/bmsb-message.yaml @@ -34,3 +34,13 @@ messages: lengthBytes: 8 signals: udsPayload: + + nvmInformation: + description: Information relating to the NVM manager + id: 0x7f9 + lengthBytes: 8 + signals: + nvmBootCycles: + nvmRecordWrites: + nvmBlockErases: + nvmFailedCrc: diff --git a/network/definition/data/components/bmsb/bmsb-signals.yaml b/network/definition/data/components/bmsb/bmsb-signals.yaml index e8793c87..eaebb292 100644 --- a/network/definition/data/components/bmsb/bmsb-signals.yaml +++ b/network/definition/data/components/bmsb/bmsb-signals.yaml @@ -113,3 +113,47 @@ signals: range: min: 0 max: 18446744073709551615 + + nvmBootCycles: + cycleTimeMs: 1000 + unit: '' + description: Count of NVM lifetime boot cycles + nativeRepresentation: + bitWidth: 16 + resolution: 1 + range: + min: 0 + max: 65535 + + nvmRecordWrites: + cycleTimeMs: 1000 + unit: '' + description: Count of NVM lifetime record writes + nativeRepresentation: + bitWidth: 16 + resolution: 1 + range: + min: 0 + max: 65535 + + nvmBlockErases: + cycleTimeMs: 1000 + unit: '' + description: Count of NVM lifetime block erases + nativeRepresentation: + bitWidth: 16 + resolution: 1 + range: + min: 0 + max: 65535 + + nvmFailedCrc: + cycleTimeMs: 1000 + unit: '' + description: Count of NVM failed CRC's + nativeRepresentation: + bitWidth: 16 + resolution: 1 + range: + min: 0 + max: 65535 diff --git a/shared/templates/c_file_structure.txt b/shared/templates/c_file_structure.txt index 5e9ee16a..9f967ad1 100644 --- a/shared/templates/c_file_structure.txt +++ b/shared/templates/c_file_structure.txt @@ -1,54 +1,43 @@ -include /****************************************************************************** * I N C L U D E S ******************************************************************************/ -define /****************************************************************************** * D E F I N E S ******************************************************************************/ -externs /****************************************************************************** * E X T E R N S ******************************************************************************/ -typedefs /****************************************************************************** * T Y P E D E F S ******************************************************************************/ -macros /****************************************************************************** * M A C R O S ******************************************************************************/ -public vars /****************************************************************************** * P U B L I C V A R S ******************************************************************************/ -private vars /****************************************************************************** * P R I V A T E V A R S ******************************************************************************/ -public function prototypes /****************************************************************************** * P U B L I C F U N C T I O N P R O T O T Y P E S ******************************************************************************/ -private function prototypes /****************************************************************************** * P R I V A T E F U N C T I O N P R O T O T Y P E S ******************************************************************************/ -public functions /****************************************************************************** * P U B L I C F U N C T I O N S ******************************************************************************/ -private functions /****************************************************************************** * P R I V A T E F U N C T I O N S ******************************************************************************/