CIU32_L051_M307R/bsp/src/bsp_flash.c

975 lines
33 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-20 10:39:08
* @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"
#define LOG_TAG "bsp_flash" // 该模块对应的标签。不定义时默认NO_TAG
#define LOG_LVL LOG_LVL_DBG // 该模块对应的日志输出级别。不定义时,默认:调试级别
#include <ulog.h> // 必须在 LOG_TAG 与 LOG_LVL 下面
#define FSTPG_WORD_COUNT (0x40U)
// #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_down_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_down_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_down_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_down_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,
};
rt_ubase_t level = 0;
static void BSP_Flash_UnLock(void)
{
std_flash_unlock();
}
static void BSP_Flash_Lock(void)
{
std_flash_lock();
// rt_hw_interrupt_enable(interrupt_value);
}
static void Flash_Interrupt_Disable(void)
{
level = rt_hw_interrupt_disable();
}
static void Flash_Interrupt_Enable(void)
{
rt_hw_interrupt_enable(level);
}
// 计算校验和的函数
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++, read_len++)
{
buf[i] = ((uint32_t *)addr)[i]; //
if (buf[i] != ((uint32_t *)addr)[i])
{
RTT_LOG_E("Flash_Read Data Mismatch at addr %#X, expected %d got %d", addr, *(uint32_t *)buf, *(uint32_t *)addr);
return ERROR;
}
}
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)
{
/* 进入编程模式 */
// std_flash_program_enable();
Flash_Interrupt_Disable();
if (std_flash_word_program(addr, write_data) != SUCCESS) // 写入操作 字节写入
{
Flash_Interrupt_Enable();
LOG_D("addr = %#X, read %d", addr, *(uint32_t *)addr);
// std_flash_program_disable();
BSP_Flash_Lock();
return ERROR;
}
Flash_Interrupt_Enable();
// std_flash_program_disable();
BSP_Flash_Lock();
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);
/* 退出编程模式 */
return ERROR;
}
rt_thread_mdelay(2);
}
return SUCCESS;
}
#if 0
#if defined(__CC_ARM)
#pragma arm section code = "FAST_PROGRAM"
#elif defined(__ICCARM__)
__ramfunc
#elif defined(__GNUC__)
__attribute__ ((section (".RamFunc")))
#endif
/**
* @brief Flash快速编程往目标地址快速编程半页数据
* @param address 编程地址
* @param data_buf 编程数据
* @retval std_status_t 本函数执行结果
*/
std_status_t BSP_Flash_Fast_Write(uint32_t address, uint32_t *data_buf)
{
std_status_t status = STD_OK;
uint32_t prog_count = 0;
/* 启动快速编程模式 */
std_flash_fast_program_enable();
/* 向目标地址写入数据 */
for (prog_count=0; prog_count < FSTPG_WORD_COUNT; prog_count++)
{
((uint32_t *)address)[prog_count] = data_buf[prog_count];
/* 查询等待BSY标志被清除 */
while ((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY);
/* 若出现错误,则退出编程循环 */
if (FLASH->SR & FLASH_FLAG_ALL_ERR)
{
RTT_LOG_E("FLASH_SR = %#X", FLASH->SR);
RTT_LOG_E("Flash_Write Error at addr %#X, expected %X got %X", address, data_buf[prog_count], ((uint32_t *)address)[prog_count]);
status = STD_ERR;
break;
}
}
/* 查询等待FSTPG_MODE状态被自动清零 */
while ((FLASH->CR & FLASH_CR_FSTPG_MODE) == FLASH_CR_FSTPG_MODE);
/* 清除Flash标志 */
FLASH->SR = (FLASH_FLAG_ALL_ERR | FLASH_SR_EOP);
return (status);
}
#if defined(__CC_ARM)
#pragma arm section
#endif
/**
* @brief Flash快速编程流程
* @param address 编程地址
* @param data_buf 编程数据
* @retval std_status_t 本函数执行结果
*/
ErrorStatus BSP_Flash_Fast_Program(uint32_t address, uint32_t *data_buf)
{
std_status_t status = STD_OK;
uint32_t prog_count;
/* 检查Flash上一次操作忙状态、错误状态 */
// status = std_flash_wait_for_last_operation(FLASH_WAIT_PROGRAM);
// if(status == STD_OK)
// {
/* 进入编程模式 */
std_flash_program_enable();
/* 短时间屏蔽中断 */
Flash_Interrupt_Disable();
/* 执行快速编程 */
if(BSP_Flash_Fast_Write(address, data_buf) != STD_OK)
{
status = STD_ERR;
RTT_LOG_E("Flash_Fast_Write status ERROR %d", status);
}
/* 恢复中断 */
Flash_Interrupt_Enable();
/* 退出编程模式 */
std_flash_program_disable();
rt_thread_mdelay(2);
/* 快速编程中无法对Flash执行读操作需在编程结束后统一校验数据 */
if (status == STD_OK)
{
for (prog_count = 0; prog_count < FSTPG_WORD_COUNT; prog_count++)
{
if (((__IO uint32_t *)address)[prog_count] != data_buf[prog_count])
{
RTT_LOG_E("Flash_Fast_Write Data Mismatch at addr %#X, expected %d got %d", address + prog_count * 4, data_buf[prog_count], ((__IO uint32_t *)address)[prog_count]);
status = STD_ERR;
break;
}
else
{
RTT_LOG_D("Flash_Fast_Write Data Match at addr %#X, expected %d got %d", address + prog_count * 4, data_buf[prog_count], ((__IO uint32_t *)address)[prog_count]);
}
}
}
// }
return (status);
}
ErrorStatus BSP_Flash_Program_Page(uint32_t address, uint32_t *data_buf)
{
std_status_t status;
/* 清除错误标志 */
std_flash_clear_flag(FLASH_FLAG_ALL_ERR);
/* Flash控制寄存器解锁 */
BSP_Flash_UnLock();
if (std_flash_get_lock_status() == false)
{
/* 页擦第48页 */
status = std_flash_page_erase(FLASH_HR_INFO_PAGE);
/* 擦除异常,加入自定义处理代码 */
while(status != STD_OK)
{
RTT_LOG_E("Flash_Erase Page %d", FLASH_HR_INFO_PAGE);
return STD_ERR;
}
/* 快速编程64个字前半页 */
status = BSP_Flash_Fast_Program(address, data_buf);
/* 快速编程异常,加入自定义处理代码 */
while(status != STD_OK)
{
RTT_LOG_E("Flash_Fast_Write Page %d", FLASH_HR_INFO_PAGE);
return STD_ERR;
}
/* 快速编程64个字后半页 */
status = BSP_Flash_Fast_Program((address + (FSTPG_WORD_COUNT << 2)), data_buf);
/* 快速编程异常,加入自定义处理代码 */
while(status != STD_OK)
{
RTT_LOG_E("Flash_Fast_Write Page %d", FLASH_HR_INFO_PAGE);
return STD_ERR;
}
/* Flash控制寄存器加锁 */
BSP_Flash_Lock();
}
return STD_OK;
}
#endif
#if 0
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 * sizeof(uint32_t))); // 注意地址增加应按uint32_t大小增加
if (status != SUCCESS)
{
return status; // 返回错误状态
}
}
return status; // 如果所有写入成功返回SUCCESS
}
#endif
std_status_t Flash_ErasePage(uint32_t index)
{
std_flash_unlock();
RTT_LOG_D("ErasePage %d", index);
Flash_Interrupt_Disable();
std_status_t status = std_flash_erase(FLASH_ERASE_PAGE, index);
Flash_Interrupt_Enable();
std_flash_lock();
return status;
}
/**
* @description: 擦除产品信息页
* @return {*}
*/
void Flash_ErasePage_ConfigInfo(void)
{
if (Flash_ErasePage(FLASH_HR_INFO_PAGE) != SUCCESS)
{
RTT_LOG_E("error_page = %#x\r\n");
}
}
ErrorStatus BSP_Flash_Program_InfoPage(uint32_t address, uint32_t *data_buf)
{
ErrorStatus ret = ERROR;
for (uint32_t i = 0; i < FLASH_PAGE_RECORD_WORD_NUM; i++)
{
ret = Flash_WriteWord(address + i * 4, data_buf[i]);
if (ret != SUCCESS)
{
LOG_E("BSP_Flash_Program_InfoPage failed");
return ERROR;
}
}
return ret;
}
/**
* @description: 写产品信息页(最后一页)
* @param {uint8_t*} frame
* @return {*}
*/
ErrorStatus Flash_Write_ConfigInfo(uint32_t *buf)
{
return BSP_Flash_Program_InfoPage(FLASH_CONFIG_INFO_START_ADDR, buf);
}
/*获取当前页号*/
uint32_t Flash_Get_Current_Page(uint32_t addr)
{
return (addr - FLASH_START_ADDR) / FLASH_PAGE_BYTE_SIZE;
}
/**
* @description: 擦除历史记录区的页
* @param {TeRecord} addr 需要擦除的页相对于其项目起始页的偏移量
* @return {*}
*/
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(hr_record_start_page_num[record] + i) != SUCCESS)
{
RTT_LOG_E("Flash_ErasePage_Records failed\r\n");
return ERROR;
}
}
}
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("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("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);
// page_buf[kFlashInitFlag] = FLASH_FIRST_INIT_VALUE;
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;
}
// RTT_LOG_D("Flash_SetProductTimeLimit((%d)):%04d-%02d-%02d,%02d:%02d ", id, year, mon, day, hour, min);
Flash_Write_ConfigInfo(&page_buf[0]);
Flash_GetProductTimeLimit(&ReadLimitTime, id);
}
#endif
uint32_t ProductTimeLimit(uint16_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min)
{
TuFlashHrRecordFrame LimitTime;
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);
return (uint32_t)LimitTime.hr_data;
}
/**
* @description: 产品信息初始化,
* @return {*}
*/
int 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};
// TODO: 此处需要完善,比如写入初始化标志位,写入产品信息,写入出厂时间,写入到期时间
info_page_buf[kFlashInitFlag] = FLASH_FIRST_INIT_VALUE;
info_page_buf[kFlashFactoryTime] = ProductTimeLimit(2024, 1, 2, 3, 4);
info_page_buf[kFlashExpirationTime] = ProductTimeLimit(2024 + 10, 1, 2, 3, 4);
info_page_buf[kFlashLowAlarmValue] = 0x0A; // 10%LEL
info_page_buf[kFlashHighAlarmValue] = 0x32; // 50%LEL
// info_page_buf[kFlashSoftwareVersion] = XXX;
// info_page_buf[kFlashHardwareVersion] = XXX;
// info_page_buf[kFlashCompanyName] = XXX;
// info_page_buf[kFlashUpdateTime] = XXX;
BSP_Flash_EraseRecodrs(); // 擦除历史数据区
Flash_ErasePage_ConfigInfo(); // 擦除配置信息
if (Flash_Write_ConfigInfo(info_page_buf) != STD_OK)
{
RTT_LOG_E("Flash_Write_ConfigInfo failed");
return RT_ERROR;
}
}
return RT_EOK;
}
INIT_ENV_EXPORT(BSP_Flash_Init);
#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)
{
{
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)
{
pHrRecord->hr_data = RecoderFrame.hr_data; // 赋值后读出,看对不对
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, pHrRecord->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, 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(200); // 1min
// }
// }
// 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");
/*获取当前项目记录数*/
uint16_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) >= 256 ? 255 : Flash_GetNum_Records(kRecordAlarm);
pTotalRecords->alarm_rcy = Flash_GetNum_Records(kRecordAlarmRcy) >= 256 ? 255 : Flash_GetNum_Records(kRecordAlarmRcy);
pTotalRecords->fault = Flash_GetNum_Records(kRecordFault);
pTotalRecords->fault_rcy = Flash_GetNum_Records(kRecordFaultRcy);
pTotalRecords->power_down = Flash_GetNum_Records(kRecordPowerDown);
pTotalRecords->power_on = Flash_GetNum_Records(kRecordPowerOn);
pTotalRecords->sensor_failure = Flash_GetNum_Records(kRecordSensorFailure);
LOG_I("alarm:%d, alarm_rcy:%d, fault:%d, fault_rcy:%d, power_down:%d, power_on:%d, sensor_failure:%d",
pTotalRecords->alarm, pTotalRecords->alarm_rcy, pTotalRecords->fault, pTotalRecords->fault_rcy,
pTotalRecords->power_down, pTotalRecords->power_on, pTotalRecords->sensor_failure);
flag = SUCCESS;
return flag;
}
/**
* @brief 获取记录时间
* @param record_type
* @param index
* @param pRecordsTime
* @return ErrorStatus
*/
ErrorStatus Flash_GetRecord(TeFrameC2 record_type, uint16_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;
}