Files
TCP2UART/App/flash_param.c
T

248 lines
5.0 KiB
C

/**
* @file flash_param.c
* @brief Flash parameter storage module implementation
*/
#include "flash_param.h"
#include "stm32f1xx_hal.h"
#include <string.h>
/*---------------------------------------------------------------------------
* Private Definitions
*---------------------------------------------------------------------------*/
/* CRC32 polynomial (IEEE 802.3) */
#define CRC32_POLYNOMIAL 0xEDB88320
/*---------------------------------------------------------------------------
* Private Variables
*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
* Private Functions
*---------------------------------------------------------------------------*/
/**
* @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)
{
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;
uint32_t j;
for (i = 0; i < len; i++)
{
crc ^= p[i];
for (j = 0; j < 8u; ++j)
{
if ((crc & 1u) != 0u)
{
crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
}
else
{
crc >>= 1;
}
}
}
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;
}