第一次提交

This commit is contained in:
2026-04-09 10:14:20 +08:00
commit e325a77b42
584 changed files with 279711 additions and 0 deletions

View File

@@ -0,0 +1,172 @@
#include "bsp_fmc_flash.h"
#include <stdio.h>
#include <string.h>
/* 这个文件默认是根据GD32F303 实现的flash 操作接口函数所以移植的时候需要根据项目自行实现芯片平台相关的fmc 外设操作函数,只需要替换实现以下函数的函数体:
bsp_flash_read
bsp_flash_write
bsp_flash_is_erased
bsp_flash_erased
其他不需要动
*/
#include "at32a423.h" // Device header
#define BSP_FLASH_BANK_FLAGS ((fmc_flag_enum)(FMC_FLAG_PGAERR | FMC_FLAG_WPERR | \
FMC_FLAG_END | FMC_FLAG_PGERR ))
#define BSP_FLASH_SN_SIZE 16U
static const bsp_flash_info_t s_bsp_flash_info =
{
BSP_FLASH_PAGE_SIZE,
BSP_FLASH_PROGRAM_UNIT,
BSP_FLASH_ERASE_VALUE,
};
static uint32_t bsp_flash_align_down(uint32_t value, uint32_t align)
{
return value & ~(align - 1U);
}
static uint32_t bsp_flash_align_up(uint32_t value, uint32_t align)
{
return (value + align - 1U) & ~(align - 1U);
}
static void bsp_flash_clear_flags(void)
{
fmc_flag_clear(BSP_FLASH_BANK_FLAGS);
}
static uint8_t bsp_flash_pack_word(const uint8_t *src, uint32_t size, uint32_t *word_out)
{
uint8_t bytes[BSP_FLASH_PROGRAM_UNIT] = { BSP_FLASH_ERASE_VALUE, BSP_FLASH_ERASE_VALUE,
BSP_FLASH_ERASE_VALUE, BSP_FLASH_ERASE_VALUE };
if ((word_out == 0) || ((src == 0) && (size > 0U))) {
return 0;
}
if (size > BSP_FLASH_PROGRAM_UNIT) {
size = BSP_FLASH_PROGRAM_UNIT;
}
if (size > 0U) {
memcpy(bytes, src, size);
}
*word_out = ((uint32_t)bytes[0]) |
((uint32_t)bytes[1] << 8) |
((uint32_t)bytes[2] << 16) |
((uint32_t)bytes[3] << 24);
return 1;
}
const bsp_flash_info_t *bsp_flash_get_info(void)
{
return &s_bsp_flash_info;
}
uint8_t bsp_flash_read(uint32_t addr, void *buffer, uint32_t size)
{
if ((buffer == 0) && (size > 0U)) {
return 0;
}
if (size > 0U) {
memcpy(buffer, (const void *)addr, size);
}
return 1;
}
uint8_t bsp_flash_is_erased(uint32_t addr, uint32_t size)
{
const uint8_t *flash_ptr = (const uint8_t *)addr;
uint32_t i;
for (i = 0U; i < size; i++) {
if (flash_ptr[i] != BSP_FLASH_ERASE_VALUE) {
return 0;
}
}
return 1;
}
uint8_t bsp_flash_erased(uint32_t addr, uint32_t size)
{
uint32_t erase_addr;
uint32_t erase_end;
if (size == 0U) {
return 1;
}
erase_addr = bsp_flash_align_down(addr, BSP_FLASH_PAGE_SIZE);
erase_end = bsp_flash_align_up(addr + size, BSP_FLASH_PAGE_SIZE);
fmc_unlock();
bsp_flash_clear_flags();
while (erase_addr < erase_end) {
if (fmc_page_erase(erase_addr) != FMC_READY) {
fmc_lock();
return 0;
}
erase_addr += BSP_FLASH_PAGE_SIZE;
bsp_flash_clear_flags();
}
fmc_lock();
return 1;
}
uint8_t bsp_flash_write(uint32_t addr, const void *data, uint32_t size)
{
const uint8_t *src = (const uint8_t *)data;
uint32_t offset = 0U;
uint32_t word = 0U;
uint32_t chunk_size;
if ((addr % BSP_FLASH_PROGRAM_UNIT) != 0U) {
return 0;
}
if ((data == 0) && (size > 0U)) {
return 0;
}
if (size == 0U) {
return 1;
}
fmc_unlock();
bsp_flash_clear_flags();
while (offset < size)
{
chunk_size = size - offset;
if (chunk_size > BSP_FLASH_PROGRAM_UNIT) {
chunk_size = BSP_FLASH_PROGRAM_UNIT;
}
if (!bsp_flash_pack_word(src + offset, chunk_size, &word)) {
fmc_lock();
return 0;
}
if (fmc_word_program(addr + offset, word) != FMC_READY) {
fmc_lock();
return 0;
}
offset += BSP_FLASH_PROGRAM_UNIT;
bsp_flash_clear_flags();
}
fmc_lock();
return 1;
}

View File

@@ -0,0 +1,28 @@
#ifndef BSP_FMC_FLASH_H
#define BSP_FMC_FLASH_H
#include <stdbool.h>
#include <stdint.h>
#define BSP_FLASH_PAGE_SIZE ((uint32_t)0x400U) // 1KB per page
#define BSP_FLASH_PROGRAM_UNIT ((uint32_t)4U) // 4 bytes per program unit (word)
#define BSP_FLASH_ERASE_VALUE ((uint8_t)0xFFU) // Value of erased flash bytes
typedef struct
{
uint32_t page_size;
uint32_t program_unit;
uint8_t erased_value;
} bsp_flash_info_t;
const bsp_flash_info_t *bsp_flash_get_info(void);
uint8_t bsp_flash_read(uint32_t addr, void *buffer, uint32_t size);
uint8_t bsp_flash_erased(uint32_t addr, uint32_t size);
uint8_t bsp_flash_write(uint32_t addr, const void *data, uint32_t size);
uint8_t bsp_flash_is_erased(uint32_t addr, uint32_t size);
#endif /* BSP_FMC_FLASH_H */

393
app_cail/port/flash_port.c Normal file
View File

@@ -0,0 +1,393 @@
#include "flash_port.h"
#include <string.h>
#include "mx_log.h"
#undef MX_LOGD
#undef MX_LOGI
#undef MX_LOGW
#undef MX_LOGE
#define MX_LOGD FLASH_PORT_LOGD
#define MX_LOGI FLASH_PORT_LOGI
#define MX_LOGW FLASH_PORT_LOGW
#define MX_LOGE FLASH_PORT_LOGE
#define FLASH_PORT_TAG FLASH_PORT_LOG_TAG
#define FLASH_PORT_ERASE_PROBE_BYTES 8U
#define FLASH_PORT_VERIFY_CHUNK_BYTES 64U
static flash_port_ops_t s_flash_ops = {0};
void flash_port_init(const flash_port_ops_t *ops)
{
if (ops != NULL) {
s_flash_ops = *ops;
}
}
static uint8_t hal_read(uint32_t addr, void *buf, uint32_t len)
{
if (s_flash_ops.read) {
return s_flash_ops.read(addr, buf, len/2);
}
return 0;
}
static uint8_t hal_write(uint32_t addr, const void *buf, uint32_t len)
{
if (s_flash_ops.write) {
return s_flash_ops.write(addr, buf, len);
}
return 0;
}
static uint8_t hal_erase(uint32_t addr, uint32_t len)
{
if (s_flash_ops.erase) {
return s_flash_ops.erase(addr, len);
}
return 0;
}
static uint8_t hal_is_erased(uint32_t addr, uint32_t len)
{
if (s_flash_ops.is_erased) {
return s_flash_ops.is_erased(addr, len);
}
return 0;
}
static uint32_t flash_port_min_u32(uint32_t a, uint32_t b)
{
return (a < b) ? a : b;
}
static uint8_t flash_port_addr_is_erased(uint32_t addr, uint32_t bytes)
{
uint32_t probe_bytes = flash_port_min_u32(bytes, FLASH_PORT_ERASE_PROBE_BYTES);
if (probe_bytes == 0U)
{
probe_bytes = FLASH_PORT_ERASE_PROBE_BYTES;
}
return hal_is_erased(addr, probe_bytes);
}
static uint8_t flash_port_erase_range(uint32_t start_addr, uint32_t bytes)
{
if (!hal_erase(start_addr, bytes))
{
return 0;
}
return flash_port_addr_is_erased(start_addr, bytes);
}
static uint8_t flash_port_verify_bytes(uint32_t addr, const void *expect, uint32_t bytes)
{
uint8_t verify_buf[FLASH_PORT_VERIFY_CHUNK_BYTES];
const uint8_t *expect_bytes = (const uint8_t *)expect;
uint32_t offset = 0U;
if ((expect == NULL) && (bytes > 0U))
{
return 0;
}
while (offset < bytes)
{
uint32_t chunk = flash_port_min_u32(bytes - offset, FLASH_PORT_VERIFY_CHUNK_BYTES);
if (!hal_read(addr + offset, verify_buf, chunk)) {
MX_LOGE(FLASH_PORT_TAG, "verify read failed addr=0x%08X offset=%u",
(unsigned int)addr, (unsigned int)offset);
return 0;
}
if (memcmp(verify_buf, expect_bytes + offset, chunk) != 0) {
MX_LOGE(FLASH_PORT_TAG, "verify failed addr=0x%08X offset=%u",
(unsigned int)addr, (unsigned int)offset);
return 0;
}
offset += chunk;
}
return 1;
}
static uint8_t flash_port_load_cali_raw(app_math_cali_t *params)
{
if (params == NULL) {
MX_LOGE(FLASH_PORT_TAG, "load cali raw null params");
return 0;
}
if (sizeof(app_math_cali_t) > FLASH_PORT_CALI_REGION_SIZE) {
MX_LOGE(FLASH_PORT_TAG, "cali region too small: need=%u size=%u",
(unsigned int)sizeof(app_math_cali_t), (unsigned int)FLASH_PORT_CALI_REGION_SIZE);
return 0;
}
return hal_read(FLASH_PORT_CALI_REGION_ADDR, params, sizeof(app_math_cali_t));
}
static uint8_t flash_port_store_cali_raw(const app_math_cali_t *params)
{
if (params == NULL)
{
MX_LOGE(FLASH_PORT_TAG, "store cali raw null params");
return 0;
}
if (sizeof(app_math_cali_t) > FLASH_PORT_CALI_REGION_SIZE) {
MX_LOGE(FLASH_PORT_TAG, "cali region too small: need=%u size=%u",
(unsigned int)sizeof(app_math_cali_t), (unsigned int)FLASH_PORT_CALI_REGION_SIZE);
return 0;
}
if (!flash_port_erase_range(FLASH_PORT_CALI_REGION_ADDR, FLASH_PORT_CALI_REGION_SIZE)) {
MX_LOGE(FLASH_PORT_TAG, "erase cali region failed");
return 0;
}
if (!hal_write(FLASH_PORT_CALI_REGION_ADDR, params, sizeof(app_math_cali_t))) {
MX_LOGE(FLASH_PORT_TAG, "write cali raw failed");
return 0;
}
return flash_port_verify_bytes(FLASH_PORT_CALI_REGION_ADDR, params, sizeof(app_math_cali_t));
}
uint8_t flash_port_math_load(app_math_cali_t *params)
{
if (!flash_port_load_cali_raw(params))
{
return 0;
}
if ((params->min_trigger_res_value == 0xFFFFU) &&
(params->max_trigger_res_value == 0xFFFFU) &&
(params->div_trigger_res_value == 0xFFFFU) &&
(params->max_display_value == 0xFFFFU)) {
MX_LOGW(FLASH_PORT_TAG, "math area is empty");
return 0;
}
return 1;
}
uint8_t flash_port_math_save(const app_math_cali_t *params)
{
app_math_cali_t merged = {0};
if (params == NULL)
{
MX_LOGE(FLASH_PORT_TAG, "math save null params");
return 0;
}
(void)flash_port_load_cali_raw(&merged);
merged.check_cail = params->check_cail;
merged.min_trigger_res_value = params->min_trigger_res_value;
merged.max_trigger_res_value = params->max_trigger_res_value;
merged.div_trigger_res_value = params->div_trigger_res_value;
merged.max_display_value = params->max_display_value;
merged.sensor_data_type = params->sensor_data_type;
return flash_port_store_cali_raw(&merged);
}
uint8_t flash_port_math_clear(void)
{
if (!flash_port_erase_range(FLASH_PORT_CALI_REGION_ADDR, FLASH_PORT_CALI_REGION_SIZE)) {
MX_LOGE(FLASH_PORT_TAG, "math clear erase failed");
return 0;
}
return 1;
}
uint8_t flash_port_pressure_load(app_math_cali_t *params)
{
if (!flash_port_load_cali_raw(params)) {
return 0;
}
if ((params->num_points == 0xFFFFU) || (params->num_points > MAX_PRESSURE_POINTS)) {
MX_LOGW(FLASH_PORT_TAG, "invalid pressure points=%u", (unsigned int)params->num_points);
return 0;
}
return 1;
}
uint8_t flash_port_pressure_save(const app_math_cali_t *params)
{
app_math_cali_t merged = {0};
if ((params == NULL) || (params->num_points > MAX_PRESSURE_POINTS)) {
MX_LOGE(FLASH_PORT_TAG, "pressure save invalid params, num_points=%u",
(unsigned int)(params ? params->num_points : 0U));
return 0;
}
(void)flash_port_load_cali_raw(&merged);
merged.num_points = params->num_points;
memcpy(merged.pressure_points, params->pressure_points, sizeof(merged.pressure_points));
return flash_port_store_cali_raw(&merged);
}
uint8_t flash_port_pressure_clear(void)
{
app_math_cali_t merged = {0};
(void)flash_port_load_cali_raw(&merged);
merged.num_points = 0U;
memset(merged.pressure_points, 0, sizeof(merged.pressure_points));
return flash_port_store_cali_raw(&merged);
}
uint8_t flash_port_map_load(uint16_t *map_matrix, uint32_t map_words)
{
uint32_t map_bytes = map_words * sizeof(uint16_t);
if ((map_matrix == NULL) || (map_words != FLASH_PORT_MAP_WORDS)) {
MX_LOGE(FLASH_PORT_TAG, "map load bad arg, words=%u", (unsigned int)map_words);
return 0;
}
if (map_bytes > FLASH_PORT_MAP_REGION_SIZE) {
MX_LOGE(FLASH_PORT_TAG, "map region too small: need=%u size=%u",
(unsigned int)map_bytes, (unsigned int)FLASH_PORT_MAP_REGION_SIZE);
return 0;
}
if (flash_port_addr_is_erased(FLASH_PORT_MAP_REGION_ADDR, map_bytes)) {
MX_LOGW(FLASH_PORT_TAG, "map area is empty");
return 0;
}
return hal_read(FLASH_PORT_MAP_REGION_ADDR, map_matrix, map_bytes);
}
uint8_t flash_port_map_save(const uint16_t *map_matrix, uint32_t map_words)
{
uint32_t map_bytes = map_words * sizeof(uint16_t);
if ((map_matrix == NULL) || (map_words != FLASH_PORT_MAP_WORDS)) {
MX_LOGE(FLASH_PORT_TAG, "map save bad arg, words=%u", (unsigned int)map_words);
return 0;
}
if (map_bytes > FLASH_PORT_MAP_REGION_SIZE) {
MX_LOGE(FLASH_PORT_TAG, "map region too small: need=%u size=%u",
(unsigned int)map_bytes, (unsigned int)FLASH_PORT_MAP_REGION_SIZE);
return 0;
}
if (!flash_port_erase_range(FLASH_PORT_MAP_REGION_ADDR, FLASH_PORT_MAP_REGION_SIZE)) {
MX_LOGE(FLASH_PORT_TAG, "map erase failed");
return 0;
}
if (!hal_write(FLASH_PORT_MAP_REGION_ADDR, map_matrix, map_bytes)) {
MX_LOGE(FLASH_PORT_TAG, "map write failed");
return 0;
}
return flash_port_verify_bytes(FLASH_PORT_MAP_REGION_ADDR, map_matrix, map_bytes);
}
uint8_t flash_port_map_clear(void)
{
if (!flash_port_erase_range(FLASH_PORT_MAP_REGION_ADDR, FLASH_PORT_MAP_REGION_SIZE)) {
MX_LOGE(FLASH_PORT_TAG, "map clear erase failed");
return 0;
}
return 1;
}
uint8_t flash_port_creep_load(app_creep_params *params)
{
uint32_t raw_data[2];
if (params == NULL) {
return 0;
}
if (!hal_read(FLASH_PORT_CREEP_REGION_ADDR, raw_data, sizeof(raw_data))) {
return 0;
}
if ((raw_data[0] == 0xFFFFFFFFUL) && (raw_data[1] == 0xFFFFFFFFUL)) {
return 0;
}
params->creep_strength = (uint8_t)raw_data[0];
params->creep_level = (uint8_t)raw_data[1];
return 1;
}
uint8_t flash_port_creep_save(const app_creep_params *params)
{
uint32_t raw_data[2];
if (params == NULL) {
return 0;
}
raw_data[0] = (uint32_t)params->creep_strength;
raw_data[1] = (uint32_t)params->creep_level;
if (!flash_port_erase_range(FLASH_PORT_CREEP_REGION_ADDR, FLASH_PORT_CREEP_REGION_SIZE)) {
return 0;
}
if (!hal_write(FLASH_PORT_CREEP_REGION_ADDR, raw_data, sizeof(raw_data))) {
return 0;
}
return flash_port_verify_bytes(FLASH_PORT_CREEP_REGION_ADDR, raw_data, sizeof(raw_data));
}
uint8_t flash_port_creep_clear(void)
{
if (!flash_port_erase_range(FLASH_PORT_CREEP_REGION_ADDR, FLASH_PORT_CREEP_REGION_SIZE)) {
return 0;
}
return 1;
}
uint8_t flash_port_device_info_load(app_dev_info *info)
{
if (info == NULL) {
return 0;
}
if (flash_port_addr_is_erased(FLASH_PORT_DEVICE_INFO_REGION_ADDR, sizeof(*info))) {
return 0;
}
return hal_read(FLASH_PORT_DEVICE_INFO_REGION_ADDR, info, sizeof(*info));
}
uint8_t flash_port_device_info_save(const app_dev_info *info)
{
if (info == NULL) {
return 0;
}
if (!flash_port_erase_range(FLASH_PORT_DEVICE_INFO_REGION_ADDR, FLASH_PORT_DEVICE_INFO_REGION_SIZE)) {
return 0;
}
if (!hal_write(FLASH_PORT_DEVICE_INFO_REGION_ADDR, info, sizeof(*info))) {
return 0;
}
return flash_port_verify_bytes(FLASH_PORT_DEVICE_INFO_REGION_ADDR, info, sizeof(*info));
}

View File

@@ -0,0 +1,82 @@
#ifndef __FLASH_PORT_H
#define __FLASH_PORT_H
#include <stdint.h>
#include "app_calibration.h"
#ifndef FLASH_PORT_LOG_TAG
#define FLASH_PORT_LOG_TAG "FLASH_PORT"
#endif
/*
* Flash Region Configuration
* Adjust Sector Size and Base Addresses for your specific MCU.
*/
#ifndef PORT_SECTOR_SIZE
#define PORT_SECTOR_SIZE (2048U) // Target MCU Sector Size
#endif
#ifndef FLASH_PORT_CREEP_REGION
#define FLASH_PORT_CREEP_REGION_ADDR (0x08000000 + 1024 * 58)
#define FLASH_PORT_CREEP_REGION_SIZE PORT_SECTOR_SIZE
#endif
#ifndef FLASH_PORT_DEVICE_INFO_REGION
#define FLASH_PORT_DEVICE_INFO_REGION_ADDR (0x08000000 + 1024 * 60)
#define FLASH_PORT_DEVICE_INFO_REGION_SIZE PORT_SECTOR_SIZE
#endif
#ifndef FLASH_PORT_CALI_REGION
#define FLASH_PORT_CALI_REGION_ADDR (0x08000000 + 1024 * 62) // FMC_WRITE_MAP_ADDR in old code
#define FLASH_PORT_CALI_REGION_SIZE PORT_SECTOR_SIZE
#endif
#ifndef FLASH_PORT_MAP_REGION
#define FLASH_PORT_MAP_REGION_ADDR (FLASH_PORT_CALI_REGION_ADDR + PORT_SECTOR_SIZE)
#define FLASH_PORT_MAP_REGION_SIZE APP_MAP_MATRIX_BYTES
#define FLASH_PORT_MAP_WORDS APP_MAP_MATRIX_WORDS
#endif
/* ============================================================================
* HAL Interface (Function pointer injection)
* ============================================================================ */
typedef struct flash_port_ops_t
{
uint8_t (*read)(uint32_t addr, void *buf, uint32_t len);
uint8_t (*write)(uint32_t addr, const void *buf, uint32_t len);
uint8_t (*erase)(uint32_t addr, uint32_t len);
uint8_t (*is_erased)(uint32_t addr, uint32_t len);
} flash_port_ops_t;
/**
* @brief Initialize the flash port layer with hardware specific operations.
* @param ops Pointer to hardware operations structure.
*/
void flash_port_init(const flash_port_ops_t *ops);
/* ============================================================================
* Application APIs
* ============================================================================ */
uint8_t flash_port_math_load(app_math_cali_t *params);
uint8_t flash_port_math_save(const app_math_cali_t *params);
uint8_t flash_port_math_clear(void);
uint8_t flash_port_pressure_load(app_math_cali_t *params);
uint8_t flash_port_pressure_save(const app_math_cali_t *params);
uint8_t flash_port_pressure_clear(void);
uint8_t flash_port_map_load(uint16_t *map_matrix, uint32_t map_words);
uint8_t flash_port_map_save(const uint16_t *map_matrix, uint32_t map_words);
uint8_t flash_port_map_clear(void);
uint8_t flash_port_creep_load(app_creep_params *params);
uint8_t flash_port_creep_save(const app_creep_params *params);
uint8_t flash_port_creep_clear(void);
uint8_t flash_port_device_info_load(app_dev_info *info);
uint8_t flash_port_device_info_save(const app_dev_info *info);
#endif /* __FLASH_PORT_H */