Initial commit: CCU621_M firmware project with BLE debug link support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-08 17:28:36 +08:00
commit 9ceb218f80
1597 changed files with 724159 additions and 0 deletions
+241
View File
@@ -0,0 +1,241 @@
/**
* @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);
}