/** * @file flash_param.c * @brief Flash parameter storage module implementation */ #include "flash_param.h" #include "stm32f1xx_hal.h" #include /*--------------------------------------------------------------------------- * Private Definitions *---------------------------------------------------------------------------*/ /* CRC32 polynomial (IEEE 802.3) */ #define CRC32_POLYNOMIAL 0xEDB88320 /*--------------------------------------------------------------------------- * Private Variables *---------------------------------------------------------------------------*/ /* CRC32 lookup table */ static uint32_t g_crc_table[256]; static bool g_crc_table_initialized = false; /*--------------------------------------------------------------------------- * Private Functions *---------------------------------------------------------------------------*/ /** * @brief Initialize CRC32 lookup table */ static void crc32_init_table(void) { uint32_t i, j, crc; for (i = 0; i < 256; i++) { crc = i; for (j = 0; j < 8; j++) { if (crc & 1) { crc = (crc >> 1) ^ CRC32_POLYNOMIAL; } else { crc >>= 1; } } g_crc_table[i] = crc; } g_crc_table_initialized = true; } /** * @brief Unlock Flash for writing */ static HAL_StatusTypeDef flash_unlock(void) { return HAL_FLASH_Unlock(); } /** * @brief Lock Flash after writing */ static void flash_lock(void) { HAL_FLASH_Lock(); } /** * @brief Erase Flash page */ static HAL_StatusTypeDef flash_erase_page(uint32_t page_addr) { FLASH_EraseInitTypeDef erase_init; uint32_t page_error; HAL_StatusTypeDef status; erase_init.TypeErase = FLASH_TYPEERASE_PAGES; erase_init.PageAddress = page_addr; erase_init.NbPages = 1; status = HAL_FLASHEx_Erase(&erase_init, &page_error); return status; } /** * @brief Program Flash half-word (16-bit) */ static HAL_StatusTypeDef flash_program_halfword(uint32_t addr, uint16_t data) { return HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr, data); } /*--------------------------------------------------------------------------- * Public Functions *---------------------------------------------------------------------------*/ /** * @brief Initialize Flash parameter storage */ int flash_param_init(void) { /* Initialize CRC table */ if (!g_crc_table_initialized) { crc32_init_table(); } return 0; } /** * @brief Read parameters from Flash */ int flash_param_read(void *data, uint32_t len) { if (data == NULL || len == 0) { return -1; } /* Check if length exceeds available space */ if (len > FLASH_PARAM_PAGE_SIZE) { return -1; } /* Direct memory read from Flash */ memcpy(data, (const void *)FLASH_PARAM_START_ADDR, len); return 0; } /** * @brief Write parameters to Flash */ int flash_param_write(const void *data, uint32_t len) { HAL_StatusTypeDef status; uint32_t addr; const uint8_t *src; uint16_t halfword; uint32_t i; if (data == NULL || len == 0) { return -1; } /* Check if length exceeds available space */ if (len > FLASH_PARAM_PAGE_SIZE) { return -1; } /* Unlock Flash */ status = flash_unlock(); if (status != HAL_OK) { return -1; } /* Erase the page */ status = flash_erase_page(FLASH_PARAM_START_ADDR); if (status != HAL_OK) { flash_lock(); return -1; } /* Program Flash (half-word at a time for STM32F1) */ addr = FLASH_PARAM_START_ADDR; src = (const uint8_t *)data; for (i = 0; i < len; i += 2) { /* Build half-word (little-endian) */ halfword = src[i]; if (i + 1 < len) { halfword |= ((uint16_t)src[i + 1]) << 8; } else { halfword |= 0xFF00; /* Pad with 0xFF */ } status = flash_program_halfword(addr, halfword); if (status != HAL_OK) { flash_lock(); return -1; } addr += 2; } /* Lock Flash */ flash_lock(); /* Verify write */ if (memcmp((const void *)FLASH_PARAM_START_ADDR, data, len) != 0) { return -1; } return 0; } /** * @brief Erase parameter storage area */ int flash_param_erase(void) { HAL_StatusTypeDef status; /* Unlock Flash */ status = flash_unlock(); if (status != HAL_OK) { return -1; } /* Erase the page */ status = flash_erase_page(FLASH_PARAM_START_ADDR); /* Lock Flash */ flash_lock(); return (status == HAL_OK) ? 0 : -1; } /** * @brief Calculate CRC32 */ uint32_t flash_param_crc32(const void *data, uint32_t len) { const uint8_t *p = (const uint8_t *)data; uint32_t crc = 0xFFFFFFFF; uint32_t i; /* Initialize table if needed */ if (!g_crc_table_initialized) { crc32_init_table(); } for (i = 0; i < len; i++) { crc = g_crc_table[(crc ^ p[i]) & 0xFF] ^ (crc >> 8); } return crc ^ 0xFFFFFFFF; } /** * @brief Verify parameter storage integrity */ int flash_param_verify(void) { uint32_t magic; /* Read magic number */ memcpy(&magic, (const void *)FLASH_PARAM_START_ADDR, sizeof(magic)); /* Check if Flash is erased (all 0xFF) */ if (magic == 0xFFFFFFFF) { return -1; /* Empty/erased */ } return 0; }