/* * @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 // 必须在 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; }