CIU32_L051_M307R/bsp/src/bsp_flash.c

758 lines
26 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.

/*
* @Author: mbw
* @Date: 2024-08-22 16:15:08
* @LastEditors: mbw && 1600520629@qq.com
* @LastEditTime: 2024-09-02 16:07:00
* @FilePath: \USART1_Interrupt - RT-Thread\bsp\src\bsp_flash.c
* @Description:
*
* Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
*/
#include "bsp_flash.h"
#include "bsp_rtc.h"
#include "rthw.h"
#include "stdlib.h"
#include "user_rtt.h"
#include "perf_counter.h"
#define LOG_TAG "bsp_flash" // 该模块对应的标签。不定义时默认NO_TAG
#define LOG_LVL LOG_LVL_DBG // 该模块对应的日志输出级别。不定义时,默认:调试级别
#include <ulog.h> // 必须在 LOG_TAG 与 LOG_LVL 下面
// #define TEST 512
#define MAX(a, b) ((a) > (b)) ? (a) : (b)
ErrorStatus Flash_Write_Record(TeRecord record);
const uint32_t hr_start_addr[7] = {FLASH_HR_ALARM_START_ADDR, FLASH_HR_ALARM_RCY_START_ADDR,
FLASH_HR_FAULT_START_ADDR, FLASH_HR_FAULT_RCY_START_ADDR,
FLASH_HR_POWER_FAILURE_START_ADDR, FLASH_HR_POWER_ON_START_ADDR,
FLASH_HR_SENSOR_FAILURE_START_ADDR};
/*各历史数据的条数*/
const uint16_t hr_record_max_num[7] = {HR_ALARM_MAX_NUM, HR_ALARM_RCY_MAX_NUM,
HR_FAULT_MAX_NUM, HR_FAULT_RCY_MAX_NUM,
HR_POWER_FAILURE_MAX_NUM, HR_POWER_ON_MAX_NUM,
HR_SENSOR_FAILURE_MAX_NUM};
const uint8_t hr_record_pages[7] = {HR_ALARM_PAGES, HR_ALARM_RCY_PAGES,
HR_FAULT_PAGES, HR_FAULT_RCY_PAGES,
HR_POWER_FAILURE_PAGES, HR_POWER_ON_PAGES,
HR_SENSOR_FAILURE_PAGES};
/*定义历史数据所在的真实起始页*/
const uint8_t hr_record_start_page_num[7] = {FLASH_HR_ALARM_PAGE, FLASH_HR_ALARM_RCY_PAGE,
FLASH_HR_FAULT_PAGE, FLASH_HR_FAULT_RCY_PAGE,
FLASH_HR_POWER_FAILURE_PAGE, FLASH_HR_POWER_ON_PAGE,
FLASH_HR_SENSOR_FAILIRE_START_PAGE};
/*定义信息页的数据地址*/
const uint32_t hr_record_info_start_addr[9] = {
FLASH_CONFIG_INFO_INIT_FLAG_ADDR,
FLASH_FACTORY_TIME_ADDR,
FLASH_EXPIRATION_TIME_ADDR,
FLASH_LOW_ALARM_VALUE_ADDR,
FLASH_HIGH_ALARM_VALUE_ADDR,
FLASH_SOFTWARE_VERSION_ADDR,
FLASH_HARDWARE_VERSION_ADDR,
FLASH_COMPANY_NAME_ADDR,
FLASH_UPDATE_TIME_ADDR,
};
static rt_base_t interrupt_value;
static void BSP_Flash_UnLock(void)
{
interrupt_value = rt_hw_interrupt_disable();
/* Flash控制寄存器解锁 */
std_flash_unlock();
}
static void BSP_Flash_Lock(void)
{
/* Flash控制寄存器加锁 */
std_flash_lock();
rt_hw_interrupt_enable(interrupt_value);
}
// 计算校验和的函数
uint8_t Sum_Check(TuFlashHrRecordFrame frame)
{
return (frame.time.year + frame.time.month + frame.time.day + frame.time.hour + frame.time.minute) & CHECKSUM_MASK;
}
#if 0
static size_t Flash_Read(uint32_t addr, uint8_t *buf, size_t len)
{
size_t read_len = 0;
for (size_t i = 0; i < len; i++, buf++, addr++, read_len++)
{
*buf = *(uint8_t *)addr;
}
return read_len;
}
#endif
static size_t Flash_ReadWord(uint32_t addr, uint32_t *buf, size_t len)
{
size_t read_len = 0;
if ((addr & 0x03) != 0) // 地址4字节对齐
{
RTT_LOG_E("addr %#X is not aligned\r\n", addr);
return ERROR;
}
for (size_t i = 0; i < len; i++, buf++, addr++, read_len++)
{
*buf = *(uint32_t *)addr;
}
return read_len;
}
/**
* @description: 向Flash中写入数据
* @param {uint32_t} addr
* @param {uint8_t} *buf
* @param {size_t} len
* @return {*}
*/
static std_status_t Flash_WriteWord(uint32_t addr, uint32_t write_data)
{
if ((addr & 0x03) != 0) // 地址4字节对齐
{
LOG_E("addr %#X is not aligned\r\n", addr);
return ERROR;
}
/* 清除错误标志 */
std_flash_clear_flag(FLASH_FLAG_ALL_ERR);
BSP_Flash_UnLock();
if (std_flash_get_lock_status() == false)
{
if (std_flash_word_program(addr, write_data) != SUCCESS) // 写入操作 字节写入
{
LOG_D("addr = %#X, read %d", addr, *(uint32_t *)addr);
BSP_Flash_Lock();
return ERROR;
}
if (*(uint32_t *)addr != write_data)
{
LOG_D("Flash_Write Data Mismatch at addr %#X, expected %d got %d", addr, write_data, *(uint32_t *)addr);
BSP_Flash_Lock();
return ERROR;
}
rt_thread_mdelay(2);
}
BSP_Flash_Lock();
return SUCCESS;
}
static std_status_t Flash_WritePage(uint32_t addr, uint32_t *buf, size_t len)
{
std_status_t status = SUCCESS;
if ((addr & 0x03) != 0) // 地址4字节对齐
{
LOG_E("addr %#X is not aligned\r\n", addr);
return ERROR;
}
for (int i = 0; i < len; i++) // 页写入的WORD数
{
status = Flash_WriteWord((addr + i * sizeof(uint32_t)), *(buf + i)); // 注意地址增加应按uint32_t大小增加
if (status != SUCCESS)
{
return status; // 返回错误状态
}
}
return status; // 如果所有写入成功返回SUCCESS
}
/**
* @description: 擦除产品信息页
* @return {*}
*/
void Flash_ErasePage_ConfigInfo(void)
{
if (std_flash_page_erase(127) != SUCCESS)
{
LOG_D("error_page = %#x\r\n");
}
}
/**
* @description: 写产品信息页(最后一页)
* @param {uint8_t*} frame
* @return {*}
*/
void Flash_Write_ConfigInfo(uint32_t *frame, size_t len)
{
Flash_WritePage(FLASH_CONFIG_INFO_START_ADDR, frame, len);
}
/*获取当前页号*/
uint32_t Flash_Get_Current_Page(uint32_t addr)
{
return (addr - FLASH_START_ADDR) / FLASH_PAGE_BYTE_SIZE;
}
std_status_t Flash_ErasePage(uint32_t index)
{
BSP_Flash_UnLock();
RTT_LOG_D("ErasePage %d", index);
std_status_t status = std_flash_erase(FLASH_ERASE_PAGE, index);
BSP_Flash_Lock();
return status;
}
/**
* @description: 擦除历史记录区的页
* @param {TeRecord} addr 需要擦除的页相对于其项目起始页的偏移量
* @return {*}
*/
static ErrorStatus Flash_ErasePage_Records(TeRecord record, uint8_t page_offset)
{
ErrorStatus flag = SUCCESS;
uint8_t erase_page = Flash_Get_Current_Page(hr_start_addr[record] + page_offset * FLASH_PAGE_BYTE_SIZE);
if (erase_page != hr_record_start_page_num[record] + page_offset)
{
RTT_LOG_E("Flash_ErasePage_Records failed erase_page: %#X != %#X",
erase_page, hr_record_start_page_num[record] + page_offset);
return ERROR;
}
if (Flash_ErasePage(erase_page) != SUCCESS)
{
RTT_LOG_E("Flash_ErasePage failed\r\n");
return ERROR;
}
for (uint16_t i = 0; i < FLASH_PAGE_BYTE_SIZE; i++) // 检查擦除是否完整
{
if (*(uint32_t *)((hr_start_addr[record] + FLASH_PAGE_BYTE_SIZE * erase_page) + i) != FLASH_DEFAULT_VALUE)
{
RTT_LOG_E("Flash_ErasePage failed\r\n");
return ERROR;
}
}
return flag;
}
/**
* @description: 擦除数据记录区
* @return {*}
*/
ErrorStatus BSP_Flash_EraseRecodrs(void)
{
/*擦除所有的历史记录区*/
for (TeRecord record = kRecordAlarm; record < kRecordSensorFailure; record++)
{
for (uint8_t i = 0; i < hr_record_pages[record]; i++)
{
if (Flash_ErasePage_Records(record, i) != SUCCESS)
{
RTT_LOG_E("Flash_ErasePage_Records failed\r\n");
return ERROR;
}
}
}
/*擦除初始信息区*/
Flash_ErasePage_ConfigInfo();
return SUCCESS;
}
/**
* @description: 先读再擦,以确保原有数据不会被擦除
* @param {uint8_t} *page_buf
* @return {*}
*/
void Flash_ErasePage_ReadConfigInfo(uint32_t *page_buf)
{
Flash_ReadWord(FLASH_CONFIG_INFO_START_ADDR, page_buf, FLASH_PAGE_RECORD_WORD_NUM);
Flash_ErasePage_ConfigInfo();
}
#if 1
/**
* @description: 获取产品的出厂或到期时间
* @return {*}
*/
ErrorStatus Flash_GetProductTimeLimit(TuFlashHrRecordFrame *pLimitTime, TeFlashProductTimeLimitId id)
{
if (id == kFactoryTimeId)
{
pLimitTime->hr_data = *(uint32_t *)FLASH_FACTORY_TIME_ADDR;
if (pLimitTime->hr_data == FLASH_DEFAULT_VALUE)
{
RTT_LOG_E("FactoryTime is not set\r\n");
return ERROR;
}
if (pLimitTime->time.check_sum != Sum_Check(*pLimitTime))
{
RTT_LOG_E("FactoryTime check_sum error\r\n");
return ERROR;
}
RTT_LOG_D("FactoryTime: %#X", pLimitTime->hr_data);
RTT_LOG_D("Flash_Read_FactoryTime:%04d-%02d-%02d,%02d:%02d",
BASE_YEAR + pLimitTime->time.year, pLimitTime->time.month, pLimitTime->time.day,
pLimitTime->time.hour, pLimitTime->time.minute);
return SUCCESS;
}
else if (id == kExpirationTimeId)
{
pLimitTime->hr_data = *(uint32_t *)FLASH_EXPIRATION_TIME_ADDR;
if (pLimitTime->hr_data == FLASH_DEFAULT_VALUE)
{
RTT_LOG_E("ExpirationTime is not set\r\n");
return ERROR;
}
if (pLimitTime->time.check_sum != Sum_Check(*pLimitTime))
{
RTT_LOG_E("ExpirationTime check_sum error\r\n");
return ERROR;
}
RTT_LOG_D("kExpirationTimeId: %#X", pLimitTime->hr_data);
RTT_LOG_D("Flash_Read_ExpirationTime:%04d-%02d-%02d,%02d:%02d",
BASE_YEAR + pLimitTime->time.year, pLimitTime->time.month, pLimitTime->time.day,
pLimitTime->time.hour, pLimitTime->time.minute);
return SUCCESS;
}
return ERROR;
}
/**
* @description: 设置产品的出厂或到期时间
* @param {uint16_t} year
* @param {uint8_t} mon
* @param {uint8_t} day
* @param {uint8_t} hour
* @param {uint8_t} min
* @param {TeFlashProductTimeLimitId} id
* @return {*}
*/
void Flash_SetProductTimeLimit(uint16_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min, TeFlashProductTimeLimitId id)
{
TuFlashHrRecordFrame LimitTime;
TuFlashHrRecordFrame ReadLimitTime;
uint32_t page_buf[FLASH_PAGE_RECORD_WORD_NUM] = {0}; // 暂存最后一页的值
Flash_ErasePage_ReadConfigInfo(page_buf);
LimitTime.time.year = year - BASE_YEAR;
LimitTime.time.month = mon;
LimitTime.time.day = day;
LimitTime.time.hour = hour;
LimitTime.time.minute = min;
LimitTime.time.check_sum = Sum_Check(LimitTime);
if (id == kFactoryTimeId)
{
page_buf[kFlashFactoryTime] = LimitTime.hr_data;
}
else if (id == kExpirationTimeId)
{
page_buf[kFlashExpirationTime] = LimitTime.hr_data;
}
Flash_Write_ConfigInfo(&page_buf[0], FLASH_PAGE_RECORD_WORD_NUM);
Flash_GetProductTimeLimit(&ReadLimitTime, id);
}
#endif
/**
* @description: 产品信息初始化,
* @return {*}
*/
void BSP_Flash_Init(void)
{
if (*(uint32_t *)FLASH_CONFIG_INFO_START_ADDR != FLASH_FIRST_INIT_VALUE)
{
uint32_t info_page_buf[FLASH_PAGE_RECORD_WORD_NUM] = {0};
BSP_Flash_EraseRecodrs(); // 擦除历史数据区
// TODO: 此处需要完善,比如写入初始化标志位,写入产品信息,写入出厂时间,写入到期时间
info_page_buf[kFlashInitFlag] = FLASH_FIRST_INIT_VALUE;
Flash_WritePage(FLASH_CONFIG_INFO_START_ADDR, info_page_buf, FLASH_PAGE_RECORD_WORD_NUM);
Flash_SetProductTimeLimit(2024, 1, 1, 0, 0, kFactoryTimeId);
Flash_SetProductTimeLimit(2024 + 10, 1, 1, 0, 0, kExpirationTimeId);
}
}
#if 1
/**
* @description: 获取索引信息
* @param {TeRecord} record
* @return {*}
*/
TsRecordIndex Flash_GetIndex_Pos(TeRecord record)
{
uint32_t index_addr = RT_NULL;
TsRecordIndex Index_Frame = {0};
uint32_t start_addr_default = hr_start_addr[record];
uint32_t hr_record_pages_default = hr_record_pages[record];
for (uint8_t page = 1; page <= hr_record_pages_default; page++) // 遍历对应项的历史数据扇区
{
for (uint8_t i = 0; i < FLASH_HR_PAGE_RECORD_NUM; i++) // 获取扇区偏移量
{
index_addr = (start_addr_default + FLASH_PAGE_BYTE_SIZE * (page - 1) + HR_RECORD_FRAME_LEN * i);
if (*(uint32_t *)index_addr == FLASH_DEFAULT_VALUE)
{
/*获取最新的数据所在位置如果值为0xFFFFFFFF则表示该页有空位是最新的页*/
if (page < hr_record_pages_default) // 当前页不是最后一页
{
if (*(uint32_t *)(index_addr + FLASH_PAGE_BYTE_SIZE) == FLASH_DEFAULT_VALUE)
{
/* 没进行循环写入*/
Index_Frame.hr_start_addr = start_addr_default;
Index_Frame.hr_index_addr = index_addr;
Index_Frame.hr_num = (index_addr - start_addr_default) / HR_RECORD_FRAME_LEN;
Index_Frame.hr_page = page;
return Index_Frame;
}
else // 已经开始循环了
{
Index_Frame.hr_start_addr = (index_addr + FLASH_PAGE_BYTE_SIZE);
Index_Frame.hr_index_addr = index_addr;
Index_Frame.hr_num = hr_record_max_num[record];
Index_Frame.hr_page = page;
return Index_Frame;
}
}
else // 当前页是最后一页,那么首地址应该在第一页,其偏移量是最后一页的偏移量
{
Index_Frame.hr_start_addr = (start_addr_default + HR_RECORD_FRAME_LEN * i);
Index_Frame.hr_index_addr = index_addr;
Index_Frame.hr_num = hr_record_max_num[record];
Index_Frame.hr_page = page;
if (page == 1) // 只有一条数据,则索引地址应该在第一页
{
Index_Frame.hr_start_addr = start_addr_default;
Index_Frame.hr_index_addr = Index_Frame.hr_start_addr;
if (*(uint32_t *)(start_addr_default) == FLASH_DEFAULT_VALUE)
{
Index_Frame.hr_num = 0;
}
}
return Index_Frame;
}
}
}
}
RTT_LOG_E("Flash_GetIndex_Pos Error!");
return Index_Frame;
}
#endif
/**
* @description:
* @param {TuFlashHrRecordFrame} *pHrRecord
* @param {TeRecord} record
* @param {uint8_t} index
* @return {*}
*/
ErrorStatus Flash_Read_Record(TuFlashHrRecordFrame *pHrRecord, TeRecord record, size_t index)
{
uint32_t index_addr = 0;
TuFlashHrRecordFrame RecoderFrame = {0};
TsRecordIndex Index_Frame = Flash_GetIndex_Pos(record); // 已存储的数量
uint32_t start_addr_default = hr_start_addr[record];
uint32_t hr_record_pages_default = hr_record_pages[record];
uint8_t sum_check = 0;
if ((index <= hr_record_max_num[record]) && (index > 0))
{
if ((index <= Index_Frame.hr_num) && (index > 0))
{
{
if (Index_Frame.hr_start_addr == start_addr_default) // 是默认的起始地址,则读取数据就是对应的偏移量
{
index_addr = start_addr_default + (index - 1) * HR_RECORD_FRAME_LEN;
}
else
{
if ((Index_Frame.hr_start_addr + index * HR_RECORD_FRAME_LEN) <=
hr_record_pages_default * FLASH_PAGE_BYTE_SIZE + start_addr_default) // 没超过所在项目的页最大地址,正常读取,此时应该在缓存页
{
RTT_LOG_D("read :hr_start_addr1 = %#x", Index_Frame.hr_start_addr);
index_addr = Index_Frame.hr_start_addr + (index - 1) * HR_RECORD_FRAME_LEN;
}
else // 超过了所在项目的最大地址
{
RTT_LOG_D("read :hr_start_addr2 = %#x", Index_Frame.hr_start_addr);
index_addr = (Index_Frame.hr_start_addr + (index - 1) * HR_RECORD_FRAME_LEN - hr_record_pages[record] * FLASH_PAGE_BYTE_SIZE);
}
}
}
{
RecoderFrame.hr_data = (*(uint32_t *)index_addr);
sum_check = Sum_Check(RecoderFrame);
if (RecoderFrame.time.check_sum == sum_check)
{
RTT_LOG_D("Flash_Read_(%d)Record(%d):%04d-%02d-%02d,%02d:%02d", record, index,
BASE_YEAR + pHrRecord->time.year, pHrRecord->time.month, pHrRecord->time.day,
pHrRecord->time.hour, pHrRecord->time.minute);
RTT_LOG_D("read :hr_start_addr = %#x, index_addr: %#x, hr_num: %d, hr_page:%d, read_data : %#X\r\n",
Index_Frame.hr_start_addr, index_addr, Index_Frame.hr_num, Index_Frame.hr_page, RecoderFrame.hr_data);
pHrRecord->hr_data = RecoderFrame.hr_data;
return SUCCESS;
}
else
{
RTT_LOG_E("read :hr_start_addr = %#x, index_addr: %#x, hr_num: %d, hr_page:%d, read_data : %#X",
Index_Frame.hr_start_addr, index_addr, Index_Frame.hr_num, Index_Frame.hr_page, RecoderFrame.hr_data);
RTT_LOG_E("Flash_GetMaxNum((%d)_Records(%d) Sum_Check(%#X) != check_sum(%#X),index_addr :%#X\r\n",
Index_Frame.hr_num, record, sum_check, RecoderFrame.time.check_sum, index_addr);
pHrRecord->hr_data = 0;
return ERROR;
}
}
}
else
{
RTT_LOG_E("index num (%d) > Actual storage num %d && index > 0", index, Index_Frame.hr_num);
pHrRecord->hr_data = 0;
return ERROR;
}
}
else
{
RTT_LOG_E("index num (%d) > hr record max num %d && index > 0", index, hr_record_max_num[record]);
pHrRecord->hr_data = 0;
return ERROR;
}
}
/**
* @description: 向对应的历史数据存储区写入一次数据
* @param {TeRecord} record
* @return {*}
*/
ErrorStatus Flash_Write_Record(TeRecord record)
{
TsRecordIndex Index_Frame;
TuFlashHrRecordFrame RecoderFrame = {0};
uint8_t rtctime[3] = {0}, rtcdate[3] = {0};
if (record == kRecordSensorFailure && *(uint32_t *)hr_start_addr[record] != FLASH_DEFAULT_VALUE) // 传感器故障记录,且已经写入过数据,则不再写入
{
RecoderFrame.hr_data = *(uint32_t *)hr_start_addr[record];
RTT_LOG_E("Flash_Write_(%d)Record(%d) num >= recorded Max num(%d)", record, Index_Frame.hr_num, hr_record_max_num[record]);
Flash_Read_Record(&RecoderFrame, record, Index_Frame.hr_num); // 读取刚才写入数据
return ERROR;
}
// __cycleof__("my algorithm")
// {
BSP_Rtc_Get_Calendar(rtcdate, rtctime);
// }
Index_Frame = Flash_GetIndex_Pos(record);
/*这里可以使用RTC闹钟每分钟更新一次数据这样只需要从缓存读取数据就行降低了访问的时间*/
RecoderFrame.time.hour = std_rtc_convert_bcd2bin(rtctime[0]);//h
RecoderFrame.time.minute = std_rtc_convert_bcd2bin(rtctime[1]);//m
RecoderFrame.time.year = (std_rtc_convert_bcd2bin(rtcdate[0]) - 24);//y
RecoderFrame.time.month = std_rtc_convert_bcd2bin(rtcdate[1]);// m
RecoderFrame.time.day = std_rtc_convert_bcd2bin(rtcdate[2]);//d
RecoderFrame.time.check_sum = Sum_Check(RecoderFrame);
// RTT_LOG_D("sizof TuFlashHrRecordFrame(%d)", sizeof(TuFlashHrRecordFrame));
RTT_LOG_D("write:hr_start_addr = %#x, index_addr: %#x, hr_num: %d, hr_page:%d, write_data : %#X",
Index_Frame.hr_start_addr, Index_Frame.hr_index_addr, Index_Frame.hr_num, Index_Frame.hr_page, RecoderFrame.hr_data);
RTT_LOG_D("Flash_Write_(%d)Record:%04d-%02d-%02d %02d:%02d, check_sum : %#X",
record, RecoderFrame.time.year + BASE_YEAR, RecoderFrame.time.month, RecoderFrame.time.day,
RecoderFrame.time.hour, RecoderFrame.time.minute, RecoderFrame.time.check_sum);
{
/*写入数据*/
if (Flash_WriteWord(Index_Frame.hr_index_addr, RecoderFrame.hr_data) != SUCCESS)
{
RTT_LOG_E("hr_write_data_error");
RTT_LOG_E("hr_start_addr = %#x, index_addr: %#x, hr_num: %d, hr_page:%d, write_data : %#X",
Index_Frame.hr_start_addr, Index_Frame.hr_index_addr, Index_Frame.hr_num, Index_Frame.hr_page, RecoderFrame.hr_data);
return ERROR;
}
}
{
/*如果把当前页写完了,要把下一页擦了,这样索引才不会出错,否则会导致索引出错*/
if (Index_Frame.hr_index_addr == hr_start_addr[record] + (Index_Frame.hr_page) * FLASH_PAGE_BYTE_SIZE - HR_RECORD_FRAME_LEN)
{
RTT_LOG_I("Index_Frame.hr_index_addr = hr_start_addr[record] + i * FLASH_PAGE_BYTE_SIZE - HR_RECORD_FRAME_LEN = %#X", Index_Frame.hr_index_addr);
if (hr_record_pages[record] - Index_Frame.hr_page > 0) // 当前页不是最后一页,还不需要返回擦
{
if (Flash_ErasePage(Index_Frame.hr_page + hr_record_start_page_num[record]) != SUCCESS)
{
RTT_LOG_I("Erase Page %d", Index_Frame.hr_page + hr_record_start_page_num[record]);
return ERROR;
}
}
else // 当前页是最后一页 此时需要将第一页擦除掉
{
if (Flash_ErasePage(hr_record_start_page_num[record]) != SUCCESS) // 擦除第一页
{
RTT_LOG_I("Erase Page %d", hr_record_start_page_num[record]);
return ERROR;
}
}
}
}
{
if (Index_Frame.hr_num < hr_record_max_num[record])
{
Flash_Read_Record(&RecoderFrame, record, Index_Frame.hr_num + 1); // 读取刚才写入数据,此时这个hr_num实际上是会+1的当到达最大计数之前hr_num会+1到了以后就默认是最大数量条数据所以不用加
}
else // 超了最大数后,每次读出来的数据都是最大数
{
Flash_Read_Record(&RecoderFrame, record, Index_Frame.hr_num); // 读取刚才写入数据
}
}
return SUCCESS;
}
static void TEST_Flash_Write_Record(int argc, char **argv)
{
if (argc == 3)
{
TeRecord record = (TeRecord)atoi(argv[1]);
int num = atoi(argv[2]);
for (int i = 1; i <= num; i++)
{
RTT_LOG_I("Flash_Write_(%d)Record:%d", record, i);
Flash_Write_Record(record);
rt_thread_mdelay(500);
}
}
else
{
LOG_E("TEST_Flash_Write_Record --use _cmd_ [record(0~6)] [num]");
}
}
MSH_CMD_EXPORT(TEST_Flash_Write_Record, "TEST_Flash_Write_Record");
static void TEST_Flash_Read_Record(int argc, char **argv)
{
TuFlashHrRecordFrame RecoderFrame = {0};
if (argc == 3)
{
TeRecord record = (TeRecord)atoi(argv[1]);
int num = atoi(argv[2]);
Flash_Read_Record(&RecoderFrame, record, num);
}
else
{
LOG_E("TEST_Flash_Read_Record --use _cmd_ [record(0~6)] [num]");
}
}
MSH_CMD_EXPORT(TEST_Flash_Read_Record, "TEST_Flash_Read_Record");
/*获取当前项目记录数*/
uint8_t Flash_GetNum_Records(TeRecord record)
{
TsRecordIndex Index_Frame = Flash_GetIndex_Pos(record);
return Index_Frame.hr_num;
}
/**
* @description: 获取总记录数
* @param {TsTotalRecords} *pTotalRecords
* @return {*}
* @note:
*/
ErrorStatus Flash_GetTotalRecord(TsTotalRecords *pTotalRecords)
{
ErrorStatus flag = ERROR;
pTotalRecords->alarm = Flash_GetNum_Records(kRecordAlarm);
pTotalRecords->alarm_rcy = Flash_GetNum_Records(kRecordAlarmRcy);
pTotalRecords->fault = Flash_GetNum_Records(kRecordFault);
pTotalRecords->fault_rcy = Flash_GetNum_Records(kRecordFaultRcy);
pTotalRecords->power_failure = Flash_GetNum_Records(kRecordPowerFailure);
pTotalRecords->power_on = Flash_GetNum_Records(kRecordPowerOn);
pTotalRecords->sensor_failure = Flash_GetNum_Records(kRecordSensorFailure);
flag = SUCCESS;
return flag;
}
/**
* @brief 获取记录时间
* @param record_type
* @param index
* @param pRecordsTime
* @return ErrorStatus
*/
ErrorStatus Flash_GetRecord(TeFrameC2 record_type, uint8_t index, TsRecordsTime *pRecordsTime)
{
ErrorStatus flag = ERROR;
uint16_t years = 0;
if (kNumOfRecords < record_type && record_type < kGetCurrentTime)
{
TuFlashHrRecordFrame pHrReadRecord;
/*这里存在多种情况,其中最常见的就是没有记录,,所有情况的结果就是此基数年不存在*/
if (Flash_Read_Record(&pHrReadRecord, (TeRecord)(record_type - 1), index) != SUCCESS)
{
years = pHrReadRecord.time.year;
}
else
{
years = BASE_YEAR + pHrReadRecord.time.year;
}
LOG_D("(%d)Flash_GetRecord[%d]:%04d-%02d-%02d,%02d:%02d",
record_type - 1, index,
years, pHrReadRecord.time.month, pHrReadRecord.time.day,
pHrReadRecord.time.hour, pHrReadRecord.time.minute);
pRecordsTime->year_h = years / 256;
pRecordsTime->year_l = years % 256;
pRecordsTime->month = pHrReadRecord.time.month;
pRecordsTime->day = pHrReadRecord.time.day;
pRecordsTime->hour = pHrReadRecord.time.hour;
pRecordsTime->minute = pHrReadRecord.time.minute;
flag = SUCCESS;
}
return flag;
}