Initial commit: CCU621_M firmware project with BLE debug link support.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,526 @@
|
||||
/**
|
||||
* @file meter_calculate_flash_impl.c
|
||||
* @brief 充电订单与临时订单的 EEPROM + 外部 SPI Flash 持久化实现
|
||||
*
|
||||
* 功能说明:
|
||||
* - 订单管理块 `S_CHG_ORDER_MNG` 存于 EEPROM(`EEPROM_ADDR_CHGRCD_MNG`):头标志、已存条数、
|
||||
* 环形槽当前位置、单调递增的 `u32_lastIndex`(对外唯一订单号)。
|
||||
* - 订单正文 `S_LOG_DATA` 存于 Flash 区 `DATAFLASH_HIS_RECORD_ADDR` 起;单条布局为
|
||||
* 1 字节 `RECORD_HEADER` + 数据 + 1 字节 CRC(`u16_crc_checksum` 低 8 位),按扇区擦除后顺序写入。
|
||||
* - `u32_chg_order_save_record`:分配新 `u32_lastIndex`,按 `(lastIndex-1)%CHG_ORDER_MAX_CNT` 映射槽位并写 Flash。
|
||||
* - `v_read_chg_order_record(index)`:用 `(index-1)%CHG_ORDER_MAX_CNT` 定位槽,并校验记录内 `u32_index` 与请求一致,防止覆盖残留。
|
||||
* - `v_read_chg_order_by_position`:在未满/已满环形缓冲下,按“第几条历史”语义换算槽位。
|
||||
* - 双枪临时订单:标志字节 + `S_LOG_DATA` 存于 EEPROM(`EEPROM_ADDR_A_LOG_DATA` / `B`),用于断电续传;清除时仅写无效标志以省擦写。
|
||||
*
|
||||
* 注意:`v_chg_order_clear_all` 仅复位管理元数据,不整片擦除 Flash(由后续写入覆盖)。
|
||||
*/
|
||||
|
||||
#include "meter_calculate_flash_impl.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "mylog/mylog.h"
|
||||
|
||||
/* 动态内存抽象:默认使用 FreeRTOS 堆接口,可按需覆盖 */
|
||||
#ifndef FLASH_MGR_MALLOC
|
||||
#define FLASH_MGR_MALLOC(sz) pvPortMalloc((sz))
|
||||
#endif
|
||||
#ifndef FLASH_MGR_FREE
|
||||
#define FLASH_MGR_FREE(ptr) vPortFree((ptr))
|
||||
#endif
|
||||
|
||||
/* 模块内部全局变量 */
|
||||
S_CHG_ORDER_MNG s_chgOrderMng;
|
||||
|
||||
/* 内部函数声明 */
|
||||
static void v_write_chg_order_record(S_LOG_DATA *order_data, U16_T position);
|
||||
static U8_T v_read_chg_order_record_internal(S_LOG_DATA *order_data, U16_T position);
|
||||
|
||||
/***************************************************************
|
||||
* EEPROM管理函数
|
||||
***************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 写入充电订单管理信息到EEPROM
|
||||
*/
|
||||
void v_write_eeprom_chgOrderMng(S_CHG_ORDER_MNG *chgOrderMng)
|
||||
{
|
||||
S_CHG_ORDER_MNG tempMng;
|
||||
|
||||
// 设置头标志
|
||||
tempMng.u16_head = 0x5AA5;
|
||||
tempMng.u16_chgOrderCnt = chgOrderMng->u16_chgOrderCnt;
|
||||
tempMng.u16_currIndex = chgOrderMng->u16_currIndex;
|
||||
tempMng.u32_lastIndex = chgOrderMng->u32_lastIndex;
|
||||
|
||||
// 写入EEPROM
|
||||
eeprom_write(EEPROM_ADDR_CHGRCD_MNG, (U8_T *)&tempMng, sizeof(S_CHG_ORDER_MNG));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从EEPROM读取充电订单管理信息
|
||||
*/
|
||||
void v_read_eeprom_chgOrderMng(S_CHG_ORDER_MNG *chgOrderMng)
|
||||
{
|
||||
S_CHG_ORDER_MNG tempMng;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
// eeprom_read返回HAL_OK(0)表示成功,非0表示失败
|
||||
if (eeprom_read(EEPROM_ADDR_CHGRCD_MNG, (U8_T *)&tempMng, sizeof(S_CHG_ORDER_MNG)) == HAL_OK) {
|
||||
// 验证头标志
|
||||
if (tempMng.u16_head == 0x5AA5) {
|
||||
chgOrderMng->u16_head = 0x5AA5;
|
||||
chgOrderMng->u16_chgOrderCnt = tempMng.u16_chgOrderCnt;
|
||||
chgOrderMng->u16_currIndex = tempMng.u16_currIndex;
|
||||
chgOrderMng->u32_lastIndex = tempMng.u32_lastIndex;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 读取失败或数据无效,初始化默认值
|
||||
chgOrderMng->u16_head = 0x5AA5;
|
||||
chgOrderMng->u16_chgOrderCnt = 0;
|
||||
chgOrderMng->u16_currIndex = RECORD_ZERO_SAVE;
|
||||
chgOrderMng->u32_lastIndex = 0;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* Flash记录读写函数(内部)
|
||||
***************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 向Flash写充电订单记录(内部函数)
|
||||
*
|
||||
* @param order_data 充电订单数据指针
|
||||
* @param position 循环缓冲区中的位置(1-N范围)
|
||||
*/
|
||||
static void v_write_chg_order_record(S_LOG_DATA *order_data, U16_T position)
|
||||
{
|
||||
U16_T u16_oneRcdSize = CHG_ORDER_RECORD_SIZE; // 一条记录大小(可能大于255)
|
||||
U32_T u32_addr; // 存储地址
|
||||
U16_T SectorIndex = 0; // 扇区偏移索引
|
||||
U16_T SectorRcdIndex = 0; // 扇区内记录索引号
|
||||
U16_T OneSectorRcdCnt = CHG_ORDER_PER_SECTOR_CNT; // 一个扇区内最多存储记录数
|
||||
U32_T SectorAddr = 0; // 扇区地址
|
||||
U16_T CurSectorRcdCnt = 0; // 当前扇区内应存放最大数目
|
||||
|
||||
// position参数范围是1-N,转换为0-N范围用于内部计算
|
||||
U16_T internal_position = position - 1;
|
||||
|
||||
U8_T *tmpbuf = (U8_T *)FLASH_MGR_MALLOC(CHG_ORDER_FULL_RECORD_SIZE);
|
||||
if (tmpbuf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 填充待存储数据缓存
|
||||
tmpbuf[0] = RECORD_HEADER;
|
||||
memcpy(tmpbuf + 1, order_data, u16_oneRcdSize); // 充电订单记录
|
||||
|
||||
// 计算并存储CRC
|
||||
U16_T calculated_crc = u16_crc_checksum((U8_T *)order_data, u16_oneRcdSize);
|
||||
tmpbuf[u16_oneRcdSize + 1] = (U8_T)calculated_crc; // 存储CRC低字节
|
||||
|
||||
#ifdef DEBUG_FLASH_WRITE
|
||||
MYLOG_MSG(TASK_ID_Meterfee, "[DEBUG] Write to addr 0x%08X (position %u, internal %u):", u32_addr, position, internal_position);
|
||||
MYLOG_MSG(TASK_ID_Meterfee, " Header: 0x%02X", tmpbuf[0]);
|
||||
MYLOG_MSG(TASK_ID_Meterfee, " Calculated CRC: 0x%04X -> stored low byte: 0x%02X", calculated_crc, tmpbuf[u16_oneRcdSize + 1]);
|
||||
#endif
|
||||
|
||||
// 确定存储位置(使用internal_position,范围0-N)
|
||||
SectorIndex = internal_position / OneSectorRcdCnt;
|
||||
SectorRcdIndex = internal_position % OneSectorRcdCnt;
|
||||
SectorAddr = DATAFLASH_HIS_RECORD_ADDR + SectorIndex * SPI_SECTOR_SIZE;
|
||||
|
||||
// 如果是扇区内第一条记录,需要擦除整个扇区
|
||||
if (SectorRcdIndex == 0) {
|
||||
s32_flash_dataflash_erase_sector(SectorAddr);
|
||||
|
||||
// 如果记录数超过最大限制,需要调整计数
|
||||
if (s_chgOrderMng.u16_chgOrderCnt > CHG_ORDER_MAX_CNT) {
|
||||
// 如果待存储扇区为最后一个扇区
|
||||
U16_T totalSectors = (CHG_ORDER_MAX_CNT + OneSectorRcdCnt - 1) / OneSectorRcdCnt;
|
||||
if ((SectorIndex + 1) == totalSectors) {
|
||||
CurSectorRcdCnt = CHG_ORDER_MAX_CNT % OneSectorRcdCnt;
|
||||
if (CurSectorRcdCnt == 0) {
|
||||
CurSectorRcdCnt = OneSectorRcdCnt;
|
||||
}
|
||||
} else {
|
||||
CurSectorRcdCnt = OneSectorRcdCnt;
|
||||
}
|
||||
|
||||
s_chgOrderMng.u16_chgOrderCnt = CHG_ORDER_MAX_CNT - CurSectorRcdCnt + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 计算具体地址并写入
|
||||
u32_addr = SectorAddr + SectorRcdIndex * CHG_ORDER_FULL_RECORD_SIZE;
|
||||
s32_flash_dataflash_write(u32_addr, tmpbuf, CHG_ORDER_FULL_RECORD_SIZE);
|
||||
|
||||
FLASH_MGR_FREE(tmpbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从Flash读充电订单记录(内部函数)
|
||||
*
|
||||
* @param order_data 充电订单数据指针(用于存储读取到的数据)
|
||||
* @param position 循环缓冲区中的位置(1-N范围)
|
||||
* @return U8_T 读取结果:0-成功,1-失败
|
||||
*/
|
||||
static U8_T v_read_chg_order_record_internal(S_LOG_DATA *order_data, U16_T position)
|
||||
{
|
||||
U16_T u16_oneRcdSize = CHG_ORDER_RECORD_SIZE; // 一条记录大小(可能大于255)
|
||||
U32_T u32_addr; // 读取地址
|
||||
U16_T SectorIndex = 0; // 扇区偏移索引
|
||||
U16_T SectorRcdIndex = 0; // 扇区内记录索引号
|
||||
U16_T OneSectorRcdCnt = CHG_ORDER_PER_SECTOR_CNT; // 一个扇区内最多存储记录数
|
||||
|
||||
// position参数范围是1-N,转换为0-N范围用于内部计算
|
||||
U16_T internal_position = position - 1;
|
||||
|
||||
U8_T *tmpbuf = (U8_T *)FLASH_MGR_MALLOC(CHG_ORDER_FULL_RECORD_SIZE);
|
||||
if (tmpbuf == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 确定读取位置(使用internal_position,范围0-N)
|
||||
SectorIndex = internal_position / OneSectorRcdCnt;
|
||||
SectorRcdIndex = internal_position % OneSectorRcdCnt;
|
||||
u32_addr = DATAFLASH_HIS_RECORD_ADDR + SectorIndex * SPI_SECTOR_SIZE +
|
||||
SectorRcdIndex * CHG_ORDER_FULL_RECORD_SIZE;
|
||||
|
||||
// 读取数据
|
||||
s32_flash_dataflash_read(u32_addr, tmpbuf, CHG_ORDER_FULL_RECORD_SIZE);
|
||||
|
||||
// 调试信息:打印读取到的数据
|
||||
#ifdef DEBUG_FLASH_READ
|
||||
MYLOG_MSG(TASK_ID_Meterfee, "[DEBUG] Read from addr 0x%08X (position %u, internal %u):", u32_addr, position, internal_position);
|
||||
MYLOG_MSG(TASK_ID_Meterfee, " Header: 0x%02X (expected: 0x%02X)", tmpbuf[0], RECORD_HEADER);
|
||||
|
||||
// 计算CRC
|
||||
U16_T calculated_crc = u16_crc_checksum(tmpbuf + 1, u16_oneRcdSize);
|
||||
U8_T stored_crc = tmpbuf[u16_oneRcdSize + 1];
|
||||
MYLOG_MSG(TASK_ID_Meterfee, " Stored CRC: 0x%02X", stored_crc);
|
||||
MYLOG_MSG(TASK_ID_Meterfee, " Calculated CRC: 0x%04X -> low byte: 0x%02X", calculated_crc, (U8_T)calculated_crc);
|
||||
#endif
|
||||
|
||||
// 验证数据完整性
|
||||
if ((tmpbuf[0] == RECORD_HEADER) &&
|
||||
(tmpbuf[u16_oneRcdSize + 1] == (U8_T)u16_crc_checksum(tmpbuf + 1, u16_oneRcdSize))) {
|
||||
#ifdef DEBUG_FLASH_READ
|
||||
MYLOG_MSG(TASK_ID_Meterfee, "[DEBUG] v_read_chg_order_record_internal: data ok, memcpy dst=0x%08X, size=%u",
|
||||
(U32_T)order_data, u16_oneRcdSize);
|
||||
#endif
|
||||
memcpy(order_data, tmpbuf + 1, u16_oneRcdSize);
|
||||
FLASH_MGR_FREE(tmpbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FLASH_READ
|
||||
MYLOG_MSG(TASK_ID_Meterfee, "[DEBUG] CRC check failed!");
|
||||
MYLOG_MSG(TASK_ID_Meterfee, " Header match: %s", (tmpbuf[0] == RECORD_HEADER) ? "YES" : "NO");
|
||||
MYLOG_MSG(TASK_ID_Meterfee, " CRC match: %s", (tmpbuf[u16_oneRcdSize + 1] == (U8_T)u16_crc_checksum(tmpbuf + 1, u16_oneRcdSize)) ? "YES" : "NO");
|
||||
#endif
|
||||
|
||||
FLASH_MGR_FREE(tmpbuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* 公共接口函数实现
|
||||
***************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 初始化充电订单Flash存储模块
|
||||
*/
|
||||
void v_chg_order_flash_init(void)
|
||||
{
|
||||
// 从EEPROM读取管理信息
|
||||
v_read_eeprom_chgOrderMng(&s_chgOrderMng);
|
||||
|
||||
// 如果头标志无效,初始化默认值
|
||||
if (s_chgOrderMng.u16_head != 0x5AA5)
|
||||
{
|
||||
s_chgOrderMng.u16_head = 0x5AA5;
|
||||
s_chgOrderMng.u16_chgOrderCnt = 0;
|
||||
s_chgOrderMng.u16_currIndex = RECORD_ZERO_SAVE;
|
||||
s_chgOrderMng.u32_lastIndex = 0;
|
||||
|
||||
// 写入EEPROM
|
||||
v_write_eeprom_chgOrderMng(&s_chgOrderMng);
|
||||
}
|
||||
|
||||
// MYLOG_MSG(TASK_ID_Meterfee, "OrderMng: init ok, cnt=%u",
|
||||
// s_chgOrderMng.u16_chgOrderCnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 清除所有充电订单记录
|
||||
*/
|
||||
void v_chg_order_clear_all(void)
|
||||
{
|
||||
// 重置管理信息
|
||||
s_chgOrderMng.u16_head = 0x5AA5;
|
||||
s_chgOrderMng.u16_chgOrderCnt = 0;
|
||||
s_chgOrderMng.u16_currIndex = RECORD_ZERO_SAVE;
|
||||
s_chgOrderMng.u32_lastIndex = 0;
|
||||
|
||||
// 写入EEPROM
|
||||
v_write_eeprom_chgOrderMng(&s_chgOrderMng);
|
||||
|
||||
// 注意:这里不清除Flash中的实际数据,因为Flash擦除成本高
|
||||
// 实际数据会在后续写入时被覆盖
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 保存充电订单记录到Flash
|
||||
*
|
||||
* 新设计:索引号直接对应Flash物理位置
|
||||
* 索引号 = u32_lastIndex + 1
|
||||
* 存储位置 = (u32_lastIndex % CHG_ORDER_MAX_CNT)
|
||||
* 注意:此函数会修改order_data中的u32_index字段
|
||||
*/
|
||||
U32_T u32_chg_order_save_record(S_LOG_DATA *order_data)
|
||||
{
|
||||
U32_T assignedIndex;
|
||||
|
||||
// 分配唯一递增索引
|
||||
s_chgOrderMng.u32_lastIndex++;
|
||||
assignedIndex = s_chgOrderMng.u32_lastIndex;
|
||||
|
||||
// 计算存储位置(基于索引号的循环缓冲区)
|
||||
U16_T storagePosition = (s_chgOrderMng.u32_lastIndex - 1) % CHG_ORDER_MAX_CNT;
|
||||
|
||||
// 更新当前索引位置(存储0-N范围)
|
||||
s_chgOrderMng.u16_currIndex = storagePosition;
|
||||
|
||||
// 记录条数递增(不超过最大限制)
|
||||
if (s_chgOrderMng.u16_chgOrderCnt < CHG_ORDER_MAX_CNT) {
|
||||
s_chgOrderMng.u16_chgOrderCnt++;
|
||||
}
|
||||
|
||||
// 直接修改传入的订单数据,设置索引
|
||||
order_data->u32_index = assignedIndex;
|
||||
|
||||
// 写入Flash记录,传递1-N范围的position
|
||||
v_write_chg_order_record(order_data, storagePosition + 1);
|
||||
|
||||
// 更新管理信息到EEPROM
|
||||
v_write_eeprom_chgOrderMng(&s_chgOrderMng);
|
||||
|
||||
return assignedIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从Flash读取指定索引的充电订单记录
|
||||
*
|
||||
* 新设计:根据索引号直接计算存储位置,无需遍历查找
|
||||
* 存储位置 = (index - 1) % CHG_ORDER_MAX_CNT
|
||||
*/
|
||||
U8_T v_read_chg_order_record(S_LOG_DATA *order_data, U32_T index)
|
||||
{
|
||||
// 检查索引号有效性
|
||||
if (index == 0 || index > s_chgOrderMng.u32_lastIndex) {
|
||||
return 1; // 索引号无效
|
||||
}
|
||||
|
||||
// 如果没有记录,直接返回失败
|
||||
if (s_chgOrderMng.u16_chgOrderCnt == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// 计算存储位置(基于索引号的循环缓冲区)
|
||||
U16_T storagePosition = (index - 1) % CHG_ORDER_MAX_CNT;
|
||||
|
||||
// 直接读取到传入的缓冲区,传递1-N范围的position
|
||||
if (v_read_chg_order_record_internal(order_data, storagePosition + 1) == 0) {
|
||||
// 检查索引是否匹配(防止数据被覆盖)
|
||||
if (order_data->u32_index == index) {
|
||||
return 0; // 成功
|
||||
}
|
||||
}
|
||||
|
||||
return 1; // 读取失败或索引不匹配
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 读取指定位置的充电订单记录(基于循环缓冲区位置)
|
||||
*/
|
||||
U8_T v_read_chg_order_by_position(S_LOG_DATA *order_data, U16_T position)
|
||||
{
|
||||
// 检查位置是否有效
|
||||
if (position >= s_chgOrderMng.u16_chgOrderCnt) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 计算实际Flash位置(考虑循环缓冲区)
|
||||
U16_T actual_position;
|
||||
if (s_chgOrderMng.u16_chgOrderCnt < CHG_ORDER_MAX_CNT) {
|
||||
// 缓冲区未满,直接按顺序读取
|
||||
actual_position = position;
|
||||
} else {
|
||||
// 缓冲区已满,需要计算循环位置
|
||||
actual_position = (s_chgOrderMng.u16_currIndex + 1 + position) % CHG_ORDER_MAX_CNT;
|
||||
}
|
||||
|
||||
// 传递1-N范围的position给内部函数
|
||||
return v_read_chg_order_record_internal(order_data, actual_position + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取充电订单记录总数
|
||||
*/
|
||||
U16_T v_get_chg_order_count(void)
|
||||
{
|
||||
return s_chgOrderMng.u16_chgOrderCnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前索引位置
|
||||
*/
|
||||
U16_T v_get_chg_order_curr_index(void)
|
||||
{
|
||||
return s_chgOrderMng.u16_currIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取最后分配的索引值
|
||||
*/
|
||||
U32_T v_get_chg_order_last_index(void)
|
||||
{
|
||||
return s_chgOrderMng.u32_lastIndex;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* EEPROM临时充电记录存储函数
|
||||
***************************************************************/
|
||||
|
||||
/**
|
||||
* @brief 获取指定枪号的EEPROM地址
|
||||
*/
|
||||
static U32_T v_get_eeprom_addr_for_gun(U8_T gunNo)
|
||||
{
|
||||
if (gunNo == 0) {
|
||||
return EEPROM_ADDR_A_LOG_DATA;
|
||||
} else {
|
||||
return EEPROM_ADDR_B_LOG_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 保存临时充电记录到EEPROM(用于断电续传)
|
||||
*/
|
||||
U8_T v_save_temp_chg_record_to_eeprom(U8_T gunNo, const S_LOG_DATA *order_data, E_TEMP_CHG_FLAG flag)
|
||||
{
|
||||
U32_T eeprom_addr = v_get_eeprom_addr_for_gun(gunNo);
|
||||
U8_T *buffer = NULL;
|
||||
U8_T ret = 1;
|
||||
|
||||
// 检查参数有效性
|
||||
if (order_data == NULL || flag >= TEMP_CHG_FLAG_INVALID) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 动态分配内存
|
||||
buffer = (U8_T *)FLASH_MGR_MALLOC(TEMP_CHG_RECORD_SIZE + 1);
|
||||
if (buffer == NULL) {
|
||||
return 1; // 内存分配失败
|
||||
}
|
||||
|
||||
// 构建缓冲区:标志位 + 订单数据
|
||||
buffer[0] = (U8_T)flag;
|
||||
memcpy(buffer + 1, order_data, TEMP_CHG_RECORD_SIZE);
|
||||
|
||||
// 写入EEPROM,eeprom_write返回HAL_OK(0)表示成功
|
||||
if (eeprom_write(eeprom_addr, buffer, TEMP_CHG_RECORD_SIZE + 1) == HAL_OK) {
|
||||
ret = 0; // 成功
|
||||
}
|
||||
|
||||
// 释放内存
|
||||
FLASH_MGR_FREE(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从EEPROM读取临时充电记录(用于断电续传恢复)
|
||||
*/
|
||||
U8_T v_read_temp_chg_record_from_eeprom(U8_T gunNo, S_LOG_DATA *order_data, E_TEMP_CHG_FLAG *flag)
|
||||
{
|
||||
U32_T eeprom_addr = v_get_eeprom_addr_for_gun(gunNo);
|
||||
U8_T *buffer = NULL;
|
||||
|
||||
// 检查参数有效性
|
||||
if (order_data == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 动态分配内存
|
||||
buffer = (U8_T *)FLASH_MGR_MALLOC(TEMP_CHG_RECORD_SIZE + 1);
|
||||
if (buffer == NULL) {
|
||||
return 1; // 内存分配失败
|
||||
}
|
||||
|
||||
// 从EEPROM读取,eeprom_read返回HAL_OK(0)表示成功
|
||||
if (eeprom_read(eeprom_addr, buffer, TEMP_CHG_RECORD_SIZE + 1) != HAL_OK) {
|
||||
FLASH_MGR_FREE(buffer);
|
||||
return 1; // 读取失败
|
||||
}
|
||||
|
||||
// 检查标志位有效性
|
||||
U8_T read_flag = buffer[0];
|
||||
if (read_flag >= TEMP_CHG_FLAG_INVALID) {
|
||||
FLASH_MGR_FREE(buffer);
|
||||
return 1; // 无效标志位
|
||||
}
|
||||
|
||||
// 返回标志位(如果提供了指针)
|
||||
if (flag != NULL) {
|
||||
*flag = (E_TEMP_CHG_FLAG)read_flag;
|
||||
}
|
||||
|
||||
// 复制订单数据
|
||||
memcpy(order_data, buffer + 1, TEMP_CHG_RECORD_SIZE);
|
||||
|
||||
// 释放内存
|
||||
FLASH_MGR_FREE(buffer);
|
||||
return 0; // 成功
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 清除EEPROM中的临时充电记录
|
||||
*/
|
||||
U8_T v_clear_temp_chg_record_in_eeprom(U8_T gunNo)
|
||||
{
|
||||
U32_T eeprom_addr = v_get_eeprom_addr_for_gun(gunNo);
|
||||
U8_T invalid_flag = TEMP_CHG_FLAG_INVALID;
|
||||
|
||||
// 只写入无效标志位,不清除整个区域(节省EEPROM写寿命)
|
||||
// eeprom_write返回HAL_OK(0)表示成功
|
||||
if (eeprom_write(eeprom_addr, &invalid_flag, 1) == HAL_OK) {
|
||||
return 0; // 成功
|
||||
}
|
||||
|
||||
return 1; // 失败
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查EEPROM中是否有有效的临时充电记录
|
||||
*/
|
||||
U8_T v_check_temp_chg_record_valid(U8_T gunNo)
|
||||
{
|
||||
U32_T eeprom_addr = v_get_eeprom_addr_for_gun(gunNo);
|
||||
U8_T flag_byte;
|
||||
|
||||
// 读取标志位,eeprom_read返回HAL_OK(0)表示成功
|
||||
if (eeprom_read(eeprom_addr, &flag_byte, 1) != HAL_OK) {
|
||||
return 0; // 读取失败,视为无效
|
||||
}
|
||||
|
||||
// 检查标志位是否有效
|
||||
if (flag_byte == TEMP_CHG_FLAG_UNSETTLED || flag_byte == TEMP_CHG_FLAG_SETTLED) {
|
||||
return 1; // 有有效记录
|
||||
}
|
||||
|
||||
return 0; // 无效记录
|
||||
}
|
||||
Reference in New Issue
Block a user