From 4fceb73db9308ba40888e378d18951a9537b1db3 Mon Sep 17 00:00:00 2001 From: Marcos Chaparro Date: Wed, 17 Apr 2019 20:54:08 -0300 Subject: [PATCH] Continuous flash memory integrity check running on background Create a new, low priority thread that checks that the CRC of the flash memory matches the CRC stored in flash. 8kB chunks are computed every 50 milliseconds. A reset is invoked if CRC does not match. Signed-off-by: Marcos Chaparro --- flash_helper.c | 37 +++++++++++++++++++++++++++++++++---- flash_helper.h | 1 + main.c | 17 +++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/flash_helper.c b/flash_helper.c index a60f6792..5ddfbfe1 100644 --- a/flash_helper.c +++ b/flash_helper.c @@ -56,11 +56,11 @@ #define APP_CRC_WAS_CALCULATED_FLAG ((uint32_t)0xAAAAAAAA) #define APP_CRC_WAS_CALCULATED_FLAG_ADDRESS (uint32_t*)(APP_MAX_SIZE - 8) -#define VECTOR_TABLE_ADDRESS (uint32_t *)ADDR_FLASH_SECTOR_0 -#define VECTOR_TABLE_SIZE (ADDR_FLASH_SECTOR_1 - ADDR_FLASH_SECTOR_0) +#define VECTOR_TABLE_ADDRESS ((uint32_t *)ADDR_FLASH_SECTOR_0) +#define VECTOR_TABLE_SIZE ((uint32_t)(ADDR_FLASH_SECTOR_1 - ADDR_FLASH_SECTOR_0)) -#define APP_START_ADDRESS (uint32_t *)(ADDR_FLASH_SECTOR_1 + EEPROM_EMULATION_SIZE) -#define APP_SIZE (APP_MAX_SIZE - VECTOR_TABLE_SIZE - EEPROM_EMULATION_SIZE) +#define APP_START_ADDRESS ((uint32_t *)(ADDR_FLASH_SECTOR_1 + EEPROM_EMULATION_SIZE)) +#define APP_SIZE ((uint32_t)(APP_MAX_SIZE - VECTOR_TABLE_SIZE - EEPROM_EMULATION_SIZE)) // Private constants static const uint32_t flash_addr[FLASH_SECTORS] = { @@ -274,3 +274,32 @@ uint32_t flash_helper_verify_flash_memory(void) { return FAULT_CODE_NONE; } } + +uint32_t flash_helper_verify_flash_memory_chunk(void) { + static uint32_t index = 0; + const uint32_t chunk_size = 8192; + uint32_t res = FAULT_CODE_NONE; + uint32_t crc = 0; + + // Make sure RCC_AHB1Periph_CRC is enabled + if (index == 0) { + crc32_reset(); + } + + if (index < VECTOR_TABLE_SIZE) { + crc32((VECTOR_TABLE_ADDRESS + index), chunk_size/4); + } + else { + crc = crc32((uint32_t*)((uint32_t)APP_START_ADDRESS + index - VECTOR_TABLE_SIZE), chunk_size/4); + } + + index += chunk_size; + if (index >= (VECTOR_TABLE_SIZE + APP_SIZE)) { + index = 0; + if (crc != 0) { + res = FAULT_CODE_FLASH_CORRUPTION; + } + } + return res; +} + diff --git a/flash_helper.h b/flash_helper.h index 085078b7..053f1231 100644 --- a/flash_helper.h +++ b/flash_helper.h @@ -28,5 +28,6 @@ uint16_t flash_helper_write_new_app_data(uint32_t offset, uint8_t *data, uint32_ void flash_helper_jump_to_bootloader(void); uint8_t* flash_helper_get_sector_address(uint32_t fsector); uint32_t flash_helper_verify_flash_memory(void); +uint32_t flash_helper_verify_flash_memory_chunk(void); #endif /* FLASH_HELPER_H_ */ diff --git a/main.c b/main.c index a8fd8e5d..f96d2f30 100644 --- a/main.c +++ b/main.c @@ -75,6 +75,22 @@ // Private variables static THD_WORKING_AREA(periodic_thread_wa, 1024); static THD_WORKING_AREA(timer_thread_wa, 128); +static THD_WORKING_AREA(flash_integrity_check_thread_wa, 1024); + +static THD_FUNCTION(flash_integrity_check_thread, arg) { + (void)arg; + + chRegSetThreadName("Flash integrity check"); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE); + + for(;;) { + if (flash_helper_verify_flash_memory_chunk() == FAULT_CODE_FLASH_CORRUPTION) { + NVIC_SystemReset(); + } + + chThdSleepMilliseconds(50); + } +} static THD_FUNCTION(periodic_thread, arg) { (void)arg; @@ -245,6 +261,7 @@ int main(void) { // Threads chThdCreateStatic(periodic_thread_wa, sizeof(periodic_thread_wa), NORMALPRIO, periodic_thread, NULL); chThdCreateStatic(timer_thread_wa, sizeof(timer_thread_wa), NORMALPRIO, timer_thread, NULL); + chThdCreateStatic(flash_integrity_check_thread_wa, sizeof(flash_integrity_check_thread_wa), LOWPRIO, flash_integrity_check_thread, NULL); #if WS2811_TEST unsigned int color_ind = 0;