Files
CCU621M/BSP/flash_file_mgr/fault_flash_impl.c
T

242 lines
7.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file fault_flash_impl.c
* @brief 历史故障记录:EEPROM 索引 + 外部 Flash 数据区实现。
*
* 迁移说明(参考 CCU601E_D):
* - EEPROMfm24cl16)仅存储 S_HIS_FAULT_MNG 索引信息,减少擦写与上电恢复成本。
* - 外部 Flashexternalflash)按扇区保存 HIS_FAULT_DATA_T 记录内容。
* - 每条记录格式:1字节 RECORD_HEADER + 数据 + 1字节CRC(低8位)。
*/
#include "flash_file_mgr/fault_flash_impl.h"
#include <string.h>
#include "publicdata/publicdata.h"
#include "publicdata/public_define.h"
#include "eeprom/fm24cl16.h"
#include "externalflash/flash_external_data.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
#define HIS_FAULT_MNG_HEADER (0x5AA5u)
#define FAULT_MNG_EEPROM_ADDR ((U16_T)EEPROM_ADDR_HISALARM_MNG)
#define FAULT_RECORD_RETRY (3u)
/* 来自故障任务:全局管理索引 */
extern S_HIS_FAULT_MNG s_hisFaultMng;
void v_fault_flash_init(void)
{
/* 上电恢复 EEPROM 中的历史故障管理索引。 */
v_read_eeprom_hisFaultMng(&s_hisFaultMng);
/* 管理信息异常时回退到安全默认值。 */
if ((s_hisFaultMng.u16_head != HIS_FAULT_MNG_HEADER) ||
(s_hisFaultMng.u16_hisFaultCnt > HIS_FAULT_MAX_CNT) ||
(s_hisFaultMng.u16_currIndex > HIS_FAULT_MAX_CNT)) {
v_fault_clear_his_fault();
}
}
static U16_T fault_sector_record_count(void)
{
return (U16_T)(SPI_SECTOR_SIZE / (sizeof(HIS_FAULT_DATA_T) + 2u));
}
void v_write_eeprom_hisFaultMng(S_HIS_FAULT_MNG *hisFaultMng)
{
S_HIS_FAULT_MNG tmp;
if (hisFaultMng == NULL) {
return;
}
tmp.u16_head = HIS_FAULT_MNG_HEADER;
tmp.u16_hisFaultCnt = hisFaultMng->u16_hisFaultCnt;
tmp.u16_currIndex = hisFaultMng->u16_currIndex;
eeprom_buffer_write((U8_T *)&tmp, FAULT_MNG_EEPROM_ADDR, (U16_T)sizeof(S_HIS_FAULT_MNG));
}
void v_read_eeprom_hisFaultMng(S_HIS_FAULT_MNG *hisFaultMng)
{
S_HIS_FAULT_MNG tmp;
U8_T i;
if (hisFaultMng == NULL) {
return;
}
memset(&tmp, 0, sizeof(tmp));
for (i = 0u; i < FAULT_RECORD_RETRY; i++) {
eeprom_buffer_read((U8_T *)&tmp, FAULT_MNG_EEPROM_ADDR, (U16_T)sizeof(S_HIS_FAULT_MNG));
if ((eeprom_get_last_error() == 0u) && (tmp.u16_head == HIS_FAULT_MNG_HEADER)) {
hisFaultMng->u16_head = HIS_FAULT_MNG_HEADER;
hisFaultMng->u16_hisFaultCnt = tmp.u16_hisFaultCnt;
hisFaultMng->u16_currIndex = tmp.u16_currIndex;
return;
}
}
/* 失败时给出安全默认值,避免野数据参与索引计算。 */
hisFaultMng->u16_head = 0u;
hisFaultMng->u16_hisFaultCnt = 0u;
hisFaultMng->u16_currIndex = RECORD_ZERO_SAVE;
}
void v_fault_clear_his_fault(void)
{
s_hisFaultMng.u16_head = HIS_FAULT_MNG_HEADER;
s_hisFaultMng.u16_hisFaultCnt = 0u;
s_hisFaultMng.u16_currIndex = RECORD_ZERO_SAVE;
v_write_eeprom_hisFaultMng(&s_hisFaultMng);
}
U16_T u16_fault_get_his_count(void)
{
S_HIS_FAULT_MNG mng;
memset(&mng, 0, sizeof(mng));
v_read_eeprom_hisFaultMng(&mng);
if (mng.u16_head != HIS_FAULT_MNG_HEADER) {
return 0u;
}
if (mng.u16_hisFaultCnt > HIS_FAULT_MAX_CNT) {
return HIS_FAULT_MAX_CNT;
}
return mng.u16_hisFaultCnt;
}
U8_T u8_fault_read_his_by_newest(U16_T newest_pos, HIS_FAULT_DATA_T *pt_hisFault)
{
S_HIS_FAULT_MNG mng;
U16_T total;
U16_T slot;
if (pt_hisFault == NULL) {
return 0u;
}
memset(pt_hisFault, 0, sizeof(*pt_hisFault));
total = u16_fault_get_his_count();
if ((total == 0u) || (newest_pos >= total)) {
return 0u;
}
memset(&mng, 0, sizeof(mng));
v_read_eeprom_hisFaultMng(&mng);
if ((mng.u16_head != HIS_FAULT_MNG_HEADER) || (mng.u16_currIndex == RECORD_ZERO_SAVE)) {
return 0u;
}
slot = (U16_T)((mng.u16_currIndex + HIS_FAULT_MAX_CNT - newest_pos) % HIS_FAULT_MAX_CNT);
v_read_hisFault_record(pt_hisFault, slot);
return (pt_hisFault->e_fault_info == E_FAULT_NULL) ? 0u : 1u;
}
void v_read_hisFault_record(HIS_FAULT_DATA_T *pt_hisFault, U16_T u16_index)
{
U16_T rec_size = (U16_T)sizeof(HIS_FAULT_DATA_T);
U16_T one_sector_cnt = fault_sector_record_count();
U32_T addr;
U16_T sector_idx;
U16_T sector_rec_idx;
U8_T retry;
U8_T *buf;
if ((pt_hisFault == NULL) || (one_sector_cnt == 0u)) {
return;
}
buf = (U8_T *)FLASH_MGR_MALLOC((size_t)rec_size + 2u);
if (buf == NULL) {
return;
}
memset(pt_hisFault, 0, sizeof(*pt_hisFault));
for (retry = 0u; retry < FAULT_RECORD_RETRY; retry++) {
sector_idx = (U16_T)(u16_index / one_sector_cnt);
sector_rec_idx = (U16_T)(u16_index % one_sector_cnt);
addr = (U32_T)(DATAFLASH_FAULT_ADDR +
(U32_T)sector_idx * SPI_SECTOR_SIZE +
(U32_T)sector_rec_idx * (rec_size + 2u));
if (s32_flash_dataflash_read(addr, buf, (U32_T)(rec_size + 2u)) != 0u) {
continue;
}
if ((buf[0] == RECORD_HEADER) &&
(buf[rec_size + 1u] == (U8_T)u16_crc_checksum(buf + 1u, rec_size))) {
memcpy(pt_hisFault, buf + 1u, rec_size);
break;
}
}
FLASH_MGR_FREE(buf);
}
static void v_write_hisFault_record(HIS_FAULT_DATA_T *pt_hisFault, U16_T u16_index)
{
U16_T rec_size = (U16_T)sizeof(HIS_FAULT_DATA_T);
U16_T one_sector_cnt = fault_sector_record_count();
U16_T sector_idx;
U16_T sector_rec_idx;
U32_T sector_addr;
U32_T addr;
U8_T *buf;
if ((pt_hisFault == NULL) || (one_sector_cnt == 0u)) {
return;
}
buf = (U8_T *)FLASH_MGR_MALLOC((size_t)rec_size + 2u);
if (buf == NULL) {
return;
}
buf[0] = RECORD_HEADER;
memcpy(buf + 1u, pt_hisFault, rec_size);
buf[rec_size + 1u] = (U8_T)u16_crc_checksum((U8_T *)pt_hisFault, rec_size);
sector_idx = (U16_T)(u16_index / one_sector_cnt);
sector_rec_idx = (U16_T)(u16_index % one_sector_cnt);
sector_addr = (U32_T)(DATAFLASH_FAULT_ADDR + (U32_T)sector_idx * SPI_SECTOR_SIZE);
addr = (U32_T)(sector_addr + (U32_T)sector_rec_idx * (rec_size + 2u));
/* 扇区首条记录写入前先擦除,避免旧数据残留影响 CRC。 */
if (sector_rec_idx == 0u) {
(void)s32_flash_dataflash_erase_sector(sector_addr);
}
(void)s32_flash_dataflash_write(addr, buf, (U32_T)(rec_size + 2u));
FLASH_MGR_FREE(buf);
}
void v_hisFault_save_record(HIS_FAULT_DATA_T *pt_hisFault_data)
{
if (pt_hisFault_data == NULL) {
return;
}
if (s_hisFaultMng.u16_currIndex == RECORD_ZERO_SAVE) {
s_hisFaultMng.u16_currIndex = 0u;
} else {
s_hisFaultMng.u16_currIndex =
(U16_T)((s_hisFaultMng.u16_currIndex + 1u) % HIS_FAULT_MAX_CNT);
}
if (s_hisFaultMng.u16_hisFaultCnt < HIS_FAULT_MAX_CNT) {
s_hisFaultMng.u16_hisFaultCnt++;
}
v_write_hisFault_record(pt_hisFault_data, s_hisFaultMng.u16_currIndex);
v_write_eeprom_hisFaultMng(&s_hisFaultMng);
}