mirror of https://github.com/rusefi/bldc.git
Merge pull request #87 from paltatech/flash-memory-crc-integrity-check
Flash memory CRC integrity check
This commit is contained in:
commit
b2816ef596
|
@ -65,6 +65,7 @@ void conf_general_init(void) {
|
|||
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
|
||||
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
||||
EE_Init();
|
||||
FLASH_Lock();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,6 +114,7 @@ bool conf_general_store_app_configuration(app_configuration *conf) {
|
|||
uint8_t *conf_addr = (uint8_t*)conf;
|
||||
uint16_t var;
|
||||
|
||||
FLASH_Unlock();
|
||||
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
|
||||
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
||||
|
||||
|
@ -125,6 +127,7 @@ bool conf_general_store_app_configuration(app_configuration *conf) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
FLASH_Lock();
|
||||
|
||||
timeout_configure_IWDT();
|
||||
|
||||
|
@ -179,6 +182,7 @@ bool conf_general_store_mc_configuration(mc_configuration *conf) {
|
|||
bool is_ok = true;
|
||||
uint8_t *conf_addr = (uint8_t*)conf;
|
||||
|
||||
FLASH_Unlock();
|
||||
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
|
||||
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
||||
|
||||
|
@ -191,6 +195,7 @@ bool conf_general_store_mc_configuration(mc_configuration *conf) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
FLASH_Lock();
|
||||
|
||||
timeout_configure_IWDT();
|
||||
|
||||
|
|
27
crc.c
27
crc.c
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "crc.h"
|
||||
#include "stm32f4xx.h"
|
||||
|
||||
// CRC Table
|
||||
const unsigned short crc16_tab[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084,
|
||||
|
@ -58,3 +59,29 @@ unsigned short crc16(unsigned char *buf, unsigned int len) {
|
|||
}
|
||||
return cksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Computes the 32-bit CRC of a given buffer of data word(32-bit) using
|
||||
* Hardware Acceleration.
|
||||
* @param pBuffer: pointer to the buffer containing the data to be computed
|
||||
* @param BufferLength: length of the buffer to be computed
|
||||
* @retval 32-bit CRC
|
||||
*/
|
||||
uint32_t crc32(uint32_t *pBuffer, uint32_t BufferLength) {
|
||||
uint32_t index = 0;
|
||||
|
||||
for(index = 0; index < BufferLength; index++) {
|
||||
CRC->DR = pBuffer[index];
|
||||
}
|
||||
return (CRC->DR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the CRC Data register (DR).
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void crc32_reset(void) {
|
||||
/* Reset CRC generator */
|
||||
CRC->CR = CRC_CR_RESET;
|
||||
}
|
||||
|
|
4
crc.h
4
crc.h
|
@ -20,9 +20,13 @@
|
|||
#ifndef CRC_H_
|
||||
#define CRC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
unsigned short crc16(unsigned char *buf, unsigned int len);
|
||||
uint32_t crc32(uint32_t *buf, uint32_t len);
|
||||
void crc32_reset(void);
|
||||
|
||||
#endif /* CRC_H_ */
|
||||
|
|
|
@ -92,7 +92,8 @@ typedef enum {
|
|||
FAULT_CODE_BOOTING_FROM_WATCHDOG_RESET,
|
||||
FAULT_CODE_ENCODER_SPI,
|
||||
FAULT_CODE_ENCODER_SINCOS_BELOW_MIN_AMPLITUDE,
|
||||
FAULT_CODE_ENCODER_SINCOS_ABOVE_MAX_AMPLITUDE
|
||||
FAULT_CODE_ENCODER_SINCOS_ABOVE_MAX_AMPLITUDE,
|
||||
FAULT_CODE_FLASH_CORRUPTION
|
||||
} mc_fault_code;
|
||||
|
||||
typedef enum {
|
||||
|
|
120
flash_helper.c
120
flash_helper.c
|
@ -25,6 +25,7 @@
|
|||
#include "mc_interface.h"
|
||||
#include "timeout.h"
|
||||
#include "hw.h"
|
||||
#include "crc.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
|
@ -35,6 +36,8 @@
|
|||
#define APP_BASE 0
|
||||
#define NEW_APP_BASE 8
|
||||
#define NEW_APP_SECTORS 3
|
||||
#define APP_MAX_SIZE (3 * (1 << 17))
|
||||
#define EEPROM_EMULATION_SIZE 0x8000
|
||||
|
||||
// Base address of the Flash sectors
|
||||
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) // Base @ of Sector 0, 16 Kbytes
|
||||
|
@ -50,6 +53,23 @@
|
|||
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) // Base @ of Sector 10, 128 Kbytes
|
||||
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) // Base @ of Sector 11, 128 Kbytes
|
||||
|
||||
#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 ((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 ((uint32_t)(APP_MAX_SIZE - VECTOR_TABLE_SIZE - EEPROM_EMULATION_SIZE))
|
||||
|
||||
typedef struct {
|
||||
uint32_t crc_flag;
|
||||
uint32_t crc;
|
||||
}crc_info_t;
|
||||
|
||||
//Make sure the app image has the CRC bits set to '1' to later write the flag and CRC.
|
||||
const crc_info_t __attribute__((section (".crcinfo"))) crc_info = {0xFFFFFFFF, 0xFFFFFFFF};
|
||||
|
||||
// Private constants
|
||||
static const uint32_t flash_addr[FLASH_SECTORS] = {
|
||||
ADDR_FLASH_SECTOR_0,
|
||||
|
@ -96,12 +116,14 @@ uint16_t flash_helper_erase_new_app(uint32_t new_app_size) {
|
|||
if (new_app_size > flash_addr[NEW_APP_BASE + i]) {
|
||||
uint16_t res = FLASH_EraseSector(flash_sector[NEW_APP_BASE + i], VoltageRange_3);
|
||||
if (res != FLASH_COMPLETE) {
|
||||
FLASH_Lock();
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
FLASH_Lock();
|
||||
|
||||
timeout_configure_IWDT();
|
||||
utils_sys_unlock_cnt();
|
||||
|
@ -110,6 +132,7 @@ uint16_t flash_helper_erase_new_app(uint32_t new_app_size) {
|
|||
}
|
||||
|
||||
uint16_t flash_helper_write_new_app_data(uint32_t offset, uint8_t *data, uint32_t len) {
|
||||
FLASH_Unlock();
|
||||
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
|
||||
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
||||
|
||||
|
@ -121,9 +144,11 @@ uint16_t flash_helper_write_new_app_data(uint32_t offset, uint8_t *data, uint32_
|
|||
for (uint32_t i = 0;i < len;i++) {
|
||||
uint16_t res = FLASH_ProgramByte(flash_addr[NEW_APP_BASE] + offset + i, data[i]);
|
||||
if (res != FLASH_COMPLETE) {
|
||||
FLASH_Lock();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
FLASH_Lock();
|
||||
|
||||
timeout_configure_IWDT();
|
||||
|
||||
|
@ -191,3 +216,98 @@ uint8_t* flash_helper_get_sector_address(uint32_t fsector) {
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute the CRC of the application code to verify its integrity
|
||||
* @retval FAULT_CODE_NONE or FAULT_CODE_FLASH_CORRUPTION
|
||||
*/
|
||||
uint32_t flash_helper_verify_flash_memory(void) {
|
||||
uint32_t crc;
|
||||
// Look for a flag indicating that the CRC was previously computed.
|
||||
// If it is blank (0xFFFFFFFF), calculate and store the CRC.
|
||||
if( (APP_CRC_WAS_CALCULATED_FLAG_ADDRESS)[0] == APP_CRC_WAS_CALCULATED_FLAG )
|
||||
{
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);
|
||||
crc32_reset();
|
||||
|
||||
// compute vector table (sector 0)
|
||||
crc32((VECTOR_TABLE_ADDRESS), (VECTOR_TABLE_SIZE)/4);
|
||||
|
||||
// skip emulated EEPROM (sector 1 and 2)
|
||||
|
||||
// compute application code
|
||||
crc = crc32(APP_START_ADDRESS, (APP_SIZE)/4);
|
||||
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, DISABLE);
|
||||
|
||||
// A CRC over the full image should return zero.
|
||||
return (crc == 0)? FAULT_CODE_NONE : FAULT_CODE_FLASH_CORRUPTION;
|
||||
}
|
||||
else {
|
||||
FLASH_Unlock();
|
||||
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
|
||||
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
||||
|
||||
//Write the flag to indicate CRC has been computed.
|
||||
uint16_t res = FLASH_ProgramWord((uint32_t)APP_CRC_WAS_CALCULATED_FLAG_ADDRESS, APP_CRC_WAS_CALCULATED_FLAG);
|
||||
if (res != FLASH_COMPLETE) {
|
||||
FLASH_Lock();
|
||||
return FAULT_CODE_FLASH_CORRUPTION;
|
||||
}
|
||||
|
||||
// Compute flash crc including the new flag
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);
|
||||
crc32_reset();
|
||||
|
||||
// compute vector table (sector 0)
|
||||
crc32(VECTOR_TABLE_ADDRESS, (VECTOR_TABLE_SIZE)/4);
|
||||
|
||||
// skip emulated EEPROM (sector 1 and 2)
|
||||
|
||||
// compute application code
|
||||
crc = crc32(APP_START_ADDRESS, (APP_SIZE - 4)/4);
|
||||
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, DISABLE);
|
||||
|
||||
//Store CRC
|
||||
res = FLASH_ProgramWord(APP_MAX_SIZE - 4, crc);
|
||||
if (res != FLASH_COMPLETE) {
|
||||
FLASH_Lock();
|
||||
return FAULT_CODE_FLASH_CORRUPTION;
|
||||
}
|
||||
FLASH_Lock();
|
||||
|
||||
// reboot
|
||||
NVIC_SystemReset();
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,5 +27,7 @@ uint16_t flash_helper_erase_new_app(uint32_t new_app_size);
|
|||
uint16_t flash_helper_write_new_app_data(uint32_t offset, uint8_t *data, uint32_t len);
|
||||
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_ */
|
||||
|
|
|
@ -20,11 +20,14 @@
|
|||
/*
|
||||
* STM32F407xG memory setup.
|
||||
* Note: Use of ram1 and ram2 is mutually exclusive with use of ram0.
|
||||
* Note: flash2 length decreased by 8 bytes to use it as hardcoded CRC
|
||||
* flags.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
flash : org = 0x08000000, len = 16k
|
||||
flash2 : org = 0x0800C000, len = 480k
|
||||
flash2 : org = 0x0800C000, len = 393216 - 8 /* NEW_APP_MAX_SIZE - CRC_INFO */
|
||||
crcinfo : org = 0x0805FFF8, len = 8 /* CRC info*/
|
||||
ram0 : org = 0x20000000, len = 128k /* SRAM1 + SRAM2 */
|
||||
ram1 : org = 0x20000000, len = 112k /* SRAM1 */
|
||||
ram2 : org = 0x2001C000, len = 16k /* SRAM2 */
|
||||
|
@ -142,6 +145,13 @@ SECTIONS
|
|||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
_textdata = _etext;
|
||||
|
||||
_crcinfo_start_address = 0x0805FFF8;
|
||||
|
||||
.crcinfo _crcinfo_start_address :
|
||||
{
|
||||
KEEP(*(.crcinfo))
|
||||
} > crcinfo
|
||||
|
||||
.mstack :
|
||||
{
|
||||
|
|
29
main.c
29
main.c
|
@ -49,6 +49,7 @@
|
|||
#include "spi_sw.h"
|
||||
#include "timer.h"
|
||||
#include "imu.h"
|
||||
#include "flash_helper.h"
|
||||
#if HAS_BLACKMAGIC
|
||||
#include "bm_if.h"
|
||||
#endif
|
||||
|
@ -74,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;
|
||||
|
@ -183,6 +200,17 @@ int main(void) {
|
|||
|
||||
timer_init();
|
||||
conf_general_init();
|
||||
|
||||
if( flash_helper_verify_flash_memory() == FAULT_CODE_FLASH_CORRUPTION ) {
|
||||
// Loop here, it is not safe to run any code
|
||||
while (1) {
|
||||
chThdSleepMilliseconds(100);
|
||||
LED_RED_ON();
|
||||
chThdSleepMilliseconds(75);
|
||||
LED_RED_OFF();
|
||||
}
|
||||
}
|
||||
|
||||
ledpwm_init();
|
||||
|
||||
mc_configuration mcconf;
|
||||
|
@ -233,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;
|
||||
|
|
Loading…
Reference in New Issue