generated from hulk/gd32e23x_template_cmake_vscode
feat(VL53L4CD): 支持透过玻璃串扰补偿、串口校准命令与校准数据Flash存储
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @file calib_store.c
|
||||
* @brief VL53L4CD 校准数据 Flash 持久化存储实现
|
||||
* @details 校准记录保存在主 Flash 的最后一页(1KB)。页地址根据上电检测到的
|
||||
* Flash 容量(16K/32K/64K)动态计算,同一份固件可适配不同容量器件:
|
||||
* 16K: 0x0800 3C00 32K: 0x0800 7C00 64K: 0x0800 FC00
|
||||
* 记录为 16 字节(2 个双字),带魔数、版本与累加和校验;
|
||||
* 空白 Flash 全 0xFF,不会误判为有效记录。
|
||||
* GD32E230 页擦除为 1KB,编程以 64 位双字为单位。
|
||||
*/
|
||||
#include "gd32e23x.h"
|
||||
#include "calib_store.h"
|
||||
#include "board_config.h"
|
||||
#include "gd32e23x_fmc.h"
|
||||
#include "uart.h"
|
||||
#include <string.h>
|
||||
|
||||
/** 校准记录魔数,"CVL4" 的 ASCII 小端编码 */
|
||||
#define CALIB_RECORD_MAGIC 0x344C5643U
|
||||
#define CALIB_RECORD_VERSION 1U
|
||||
#define CALIB_RECORD_SIZE 16U
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic; /**< 魔数,用于识别有效记录 */
|
||||
uint16_t version; /**< 记录格式版本 */
|
||||
uint16_t flags; /**< 保留标志位 */
|
||||
int16_t offset_mm; /**< 偏移校准值,单位 mm */
|
||||
uint16_t xtalk_kcps; /**< 串扰校准值,单位 kcps */
|
||||
uint16_t checksum; /**< 前 12 字节累加和 */
|
||||
uint16_t pad; /**< 填充到 16 字节 */
|
||||
} calib_record_t;
|
||||
|
||||
/**
|
||||
* @brief 计算校准记录所在页的起始地址(Flash 最后一页)
|
||||
* @retval uint32_t 页起始地址
|
||||
*/
|
||||
static uint32_t calib_page_address(void)
|
||||
{
|
||||
uint32_t size_kb = get_flash_size();
|
||||
|
||||
if (size_kb == 0U) {
|
||||
size_kb = 16U; /* 读取异常时按最小容量处理 */
|
||||
}
|
||||
return 0x08000000U + (size_kb * 1024U) - 1024U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算记录前 12 字节的 16 位累加和
|
||||
* @param[in] rec: 校准记录指针
|
||||
* @retval uint16_t 累加和
|
||||
*/
|
||||
static uint16_t calib_checksum(const calib_record_t *rec)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)rec;
|
||||
uint16_t sum = 0U;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0U; i < 12U; i++) {
|
||||
sum += p[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
bool calib_store_load(int16_t *offset_mm, uint16_t *xtalk_kcps)
|
||||
{
|
||||
const calib_record_t *rec = (const calib_record_t *)(uintptr_t)calib_page_address();
|
||||
|
||||
if (offset_mm == NULL || xtalk_kcps == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (rec->magic != CALIB_RECORD_MAGIC || rec->version != CALIB_RECORD_VERSION) {
|
||||
return false;
|
||||
}
|
||||
if (rec->checksum != calib_checksum(rec)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*offset_mm = rec->offset_mm;
|
||||
*xtalk_kcps = rec->xtalk_kcps;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool calib_store_save(int16_t offset_mm, uint16_t xtalk_kcps)
|
||||
{
|
||||
calib_record_t rec;
|
||||
uint64_t data[2];
|
||||
uint32_t page_addr;
|
||||
fmc_state_enum fmc_state;
|
||||
|
||||
rec.magic = CALIB_RECORD_MAGIC;
|
||||
rec.version = CALIB_RECORD_VERSION;
|
||||
rec.flags = 0U;
|
||||
rec.offset_mm = offset_mm;
|
||||
rec.xtalk_kcps = xtalk_kcps;
|
||||
rec.checksum = 0U;
|
||||
rec.pad = 0U;
|
||||
rec.checksum = calib_checksum(&rec);
|
||||
|
||||
/* GD32E230 按双字(64 位)编程,直接按内存布局拆成两个 64 位 */
|
||||
memcpy(&data[0], &rec, 8U);
|
||||
memcpy(&data[1], (const uint8_t *)&rec + 8U, 8U);
|
||||
|
||||
page_addr = calib_page_address();
|
||||
|
||||
/* Flash 操作期间总线停顿,暂停串口接收避免丢字节 */
|
||||
uart_rx_irq_pause();
|
||||
fmc_unlock();
|
||||
|
||||
fmc_state = fmc_page_erase(page_addr);
|
||||
if (fmc_state == FMC_READY) {
|
||||
fmc_state = fmc_doubleword_program(page_addr, data[0]);
|
||||
if (fmc_state == FMC_READY) {
|
||||
fmc_state = fmc_doubleword_program(page_addr + 8U, data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
fmc_lock();
|
||||
uart_rx_irq_resume();
|
||||
|
||||
return (fmc_state == FMC_READY);
|
||||
}
|
||||
|
||||
bool calib_store_erase(void)
|
||||
{
|
||||
uint32_t page_addr = calib_page_address();
|
||||
fmc_state_enum fmc_state;
|
||||
|
||||
uart_rx_irq_pause();
|
||||
fmc_unlock();
|
||||
|
||||
fmc_state = fmc_page_erase(page_addr);
|
||||
|
||||
fmc_lock();
|
||||
uart_rx_irq_resume();
|
||||
|
||||
return (fmc_state == FMC_READY);
|
||||
}
|
||||
Reference in New Issue
Block a user