#include "stddef.h" #include "stdint.h" #include "Emulated_EEPROM_Access.h" typedef union { uint32_t u32Word[1U]; struct { uint16_t u16Index; uint16_t u16IndexInv; }stField; }EEPROM_Ctrl_Data_un_t; typedef struct { uint8_t u8State; uint16_t u16BlockNum; uint16_t u16ProgLen; uint32_t u32ProgAddr; uint32_t* pu32ProgData; }EEPROM_Access_Ctrl_st_t; #define EEPROM_BLANK_CHECK_RECORD_NUM (3U) #define EEPROM_OVER_SEARCH_RECORD_NUM (3U) #define EEPROM_WR_STATE_IDLE (0U) #define EEPROM_WR_STATE_ERASE (1U) #define EEPROM_WR_STATE_PROG (2U) // -------------------------------------------------------------- // CRC16计算方法1:使用2个256长度的校验表 // -------------------------------------------------------------- static const uint8_t g_u8EEPROMCRCTableH[] = { 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x01U, 0xC0U, 0x80U, 0x41U, 0x00U, 0xC1U, 0x81U, 0x40U, }; static const uint8_t g_u8EEPROMCRCTableL[] = { 0x00U, 0xC0U, 0xC1U, 0x01U, 0xC3U, 0x03U, 0x02U, 0xC2U, 0xC6U, 0x06U, 0x07U, 0xC7U, 0x05U, 0xC5U, 0xC4U, 0x04U, 0xCCU, 0x0CU, 0x0DU, 0xCDU, 0x0FU, 0xCFU, 0xCEU, 0x0EU, 0x0AU, 0xCAU, 0xCBU, 0x0BU, 0xC9U, 0x09U, 0x08U, 0xC8U, 0xD8U, 0x18U, 0x19U, 0xD9U, 0x1BU, 0xDBU, 0xDAU, 0x1AU, 0x1EU, 0xDEU, 0xDFU, 0x1FU, 0xDDU, 0x1DU, 0x1CU, 0xDCU, 0x14U, 0xD4U, 0xD5U, 0x15U, 0xD7U, 0x17U, 0x16U, 0xD6U, 0xD2U, 0x12U, 0x13U, 0xD3U, 0x11U, 0xD1U, 0xD0U, 0x10U, 0xF0U, 0x30U, 0x31U, 0xF1U, 0x33U, 0xF3U, 0xF2U, 0x32U, 0x36U, 0xF6U, 0xF7U, 0x37U, 0xF5U, 0x35U, 0x34U, 0xF4U, 0x3CU, 0xFCU, 0xFDU, 0x3DU, 0xFFU, 0x3FU, 0x3EU, 0xFEU, 0xFAU, 0x3AU, 0x3BU, 0xFBU, 0x39U, 0xF9U, 0xF8U, 0x38U, 0x28U, 0xE8U, 0xE9U, 0x29U, 0xEBU, 0x2BU, 0x2AU, 0xEAU, 0xEEU, 0x2EU, 0x2FU, 0xEFU, 0x2DU, 0xEDU, 0xECU, 0x2CU, 0xE4U, 0x24U, 0x25U, 0xE5U, 0x27U, 0xE7U, 0xE6U, 0x26U, 0x22U, 0xE2U, 0xE3U, 0x23U, 0xE1U, 0x21U, 0x20U, 0xE0U, 0xA0U, 0x60U, 0x61U, 0xA1U, 0x63U, 0xA3U, 0xA2U, 0x62U, 0x66U, 0xA6U, 0xA7U, 0x67U, 0xA5U, 0x65U, 0x64U, 0xA4U, 0x6CU, 0xACU, 0xADU, 0x6DU, 0xAFU, 0x6FU, 0x6EU, 0xAEU, 0xAAU, 0x6AU, 0x6BU, 0xABU, 0x69U, 0xA9U, 0xA8U, 0x68U, 0x78U, 0xB8U, 0xB9U, 0x79U, 0xBBU, 0x7BU, 0x7AU, 0xBAU, 0xBEU, 0x7EU, 0x7FU, 0xBFU, 0x7DU, 0xBDU, 0xBCU, 0x7CU, 0xB4U, 0x74U, 0x75U, 0xB5U, 0x77U, 0xB7U, 0xB6U, 0x76U, 0x72U, 0xB2U, 0xB3U, 0x73U, 0xB1U, 0x71U, 0x70U, 0xB0U, 0x50U, 0x90U, 0x91U, 0x51U, 0x93U, 0x53U, 0x52U, 0x92U, 0x96U, 0x56U, 0x57U, 0x97U, 0x55U, 0x95U, 0x94U, 0x54U, 0x9CU, 0x5CU, 0x5DU, 0x9DU, 0x5FU, 0x9FU, 0x9EU, 0x5EU, 0x5AU, 0x9AU, 0x9BU, 0x5BU, 0x99U, 0x59U, 0x58U, 0x98U, 0x88U, 0x48U, 0x49U, 0x89U, 0x4BU, 0x8BU, 0x8AU, 0x4AU, 0x4EU, 0x8EU, 0x8FU, 0x4FU, 0x8DU, 0x4DU, 0x4CU, 0x8CU, 0x44U, 0x84U, 0x85U, 0x45U, 0x87U, 0x47U, 0x46U, 0x86U, 0x82U, 0x42U, 0x43U, 0x83U, 0x41U, 0x81U, 0x80U, 0x40U, }; /*static const uint8_t g_u8EEPROMCRCTableH[] = { 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, }; static const uint8_t g_u8EEPROMCRCTableL[] = { 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, 0x55U, };*/ static uint16_t EEPROM_CRC_Calc(uint32_t * pu32Data, uint16_t u16Len); EEPROM_Access_Ctrl_st_t g_stEEPROMAccess; EEPROM_Block_Access_st_t * g_pstEEPROMBlock; EEPROM_Mem_Erase_Func_ptr_t g_pfnEEPROMMemErase; EEPROM_Mem_Blank_Chk_Func_ptr_t g_pfnEEPROMMemBlankCheck; EEPROM_Mem_Read_Func_ptr_t g_pfnEEPROMMemRead; EEPROM_Mem_Write_Func_ptr_t g_pfnEEPROMMemWrite; void EEPROM_Access_Init(const EEPROM_Block_st_t * pstBlockTable, EEPROM_Block_Access_st_t * pstBlockAccess, EEPROM_Media_Access_st_t * pstMediaAccess, uint16_t u16BlockNum) { uint16_t i; uint8_t u8Loop; uint8_t u8Ready; uint16_t u16Index; uint16_t u16IndexBkup; uint16_t u16RecordNum; uint16_t u16MaxRecordNum[2U]; uint16_t u16WordNum; uint16_t u16Result; uint32_t u32DataAddr; uint32_t u32DataAddrBase; uint32_t u32DataAddrEnd; EEPROM_Ctrl_Data_un_t unCtrlData; if ((pstBlockTable != NULL) && (pstBlockAccess != NULL) &&\ (pstMediaAccess != NULL) && (u16BlockNum != 0U)) { /*** Step 1 : Setup media(data flash) access functions ***/ g_pfnEEPROMMemErase = pstMediaAccess->pfnMemErase; g_pfnEEPROMMemBlankCheck = pstMediaAccess->pfnMemBlankChk; g_pfnEEPROMMemRead = pstMediaAccess->pfnMemRead; g_pfnEEPROMMemWrite = pstMediaAccess->pfnMemWrite; /*** Step 2 : Generate flash read / write control data ***/ g_stEEPROMAccess.u8State = EEPROM_WR_STATE_IDLE; g_stEEPROMAccess.u16BlockNum = u16BlockNum; g_pstEEPROMBlock = pstBlockAccess; for (i = 0U; i < g_stEEPROMAccess.u16BlockNum; i++) { u32DataAddr = pstBlockTable[i].u32EndAddr - pstBlockTable[i].u32StartAddr + 1UL; g_pstEEPROMBlock[i].u8Status = EEPROM_BLOCK_BLANK; g_pstEEPROMBlock[i].u32BaseAddr = pstBlockTable[i].u32StartAddr; g_pstEEPROMBlock[i].u16SectorSize = (uint16_t)(u32DataAddr / 2UL); g_pstEEPROMBlock[i].u8SectorOffset = 0U; g_pstEEPROMBlock[i].u16Index = 0U; g_pstEEPROMBlock[i].u16BlockSize = (uint16_t)(pstBlockTable[i].u32DataSize); g_pstEEPROMBlock[i].u16MaxRecordNum = g_pstEEPROMBlock[i].u16SectorSize / g_pstEEPROMBlock[i].u16BlockSize; g_pstEEPROMBlock[i].u16RecordNum = 0U; g_pstEEPROMBlock[i].pu32Data = pstBlockTable[i].pu32DataBuffer; } /*** Step 3 : Blank check and find start record ***/ for (i = 0U; i < g_stEEPROMAccess.u16BlockNum; i++) { /*** Step 3.1 Blank check and find start record - Check if the logic data block related memory is blank. - Then find out which logic sector contains the most recent record. - The found sector will define the starting search point of step 3.2. ***/ /* Search sector +0 */ u32DataAddrBase = g_pstEEPROMBlock[i].u32BaseAddr; u32DataAddrEnd = u32DataAddrBase + (uint32_t)(g_pstEEPROMBlock[i].u16SectorSize) - 1UL; u32DataAddr = g_pfnEEPROMMemBlankCheck(u32DataAddrBase, u32DataAddrEnd); if (u32DataAddr == 0x00000000UL) { u8Loop = 0U; u16MaxRecordNum[0U] = 0U; } else if (u32DataAddr == 0xFFFFFFFFUL) { u8Loop = 1U; u16MaxRecordNum[0U] = g_pstEEPROMBlock[i].u16MaxRecordNum; } else { u8Loop = 1U; u16MaxRecordNum[0U] = (uint16_t)u32DataAddr / g_pstEEPROMBlock[i].u16BlockSize; } u16RecordNum = 0U; u8Ready = 0U; while (u8Loop) { /* Fetch block control data */ u32DataAddr = u32DataAddrBase + (uint32_t)u16RecordNum * (uint32_t)g_pstEEPROMBlock[i].u16BlockSize; g_pfnEEPROMMemRead(u32DataAddr, unCtrlData.u32Word, 1UL); if (unCtrlData.stField.u16Index + unCtrlData.stField.u16IndexInv == 0xFFFFU) { u8Loop = 0U; u8Ready = 1U; g_pstEEPROMBlock[i].u8Status = EEPROM_BLOCK_ACTIVE; g_pstEEPROMBlock[i].u8SectorOffset = 0U; g_pstEEPROMBlock[i].u16RecordNum = u16RecordNum; g_pstEEPROMBlock[i].u16Index = unCtrlData.stField.u16Index; u16IndexBkup = unCtrlData.stField.u16Index; } else { u16RecordNum++; if ((u16RecordNum >= u16MaxRecordNum[0U]) || \ (u16RecordNum >= EEPROM_BLANK_CHECK_RECORD_NUM)) { u8Loop = 0U; } } } /* Search sector +1 */ u32DataAddrBase += (uint32_t)(g_pstEEPROMBlock[i].u16SectorSize); u32DataAddrEnd += (uint32_t)(g_pstEEPROMBlock[i].u16SectorSize); u32DataAddr = g_pfnEEPROMMemBlankCheck(u32DataAddrBase, u32DataAddrEnd); if (u32DataAddr == 0x00000000UL) { u8Loop = 0U; u16MaxRecordNum[1U] = 0U; } else if (u32DataAddr == 0xFFFFFFFFUL) { u8Loop = 1U; u16MaxRecordNum[1U] = g_pstEEPROMBlock[i].u16MaxRecordNum; } else { u8Loop = 1U; u16MaxRecordNum[1U] = (uint16_t)u32DataAddr / g_pstEEPROMBlock[i].u16BlockSize; } u16RecordNum = 0U; while (u8Loop) { /* Fetch block control data */ u32DataAddr = u32DataAddrBase + (uint32_t)u16RecordNum * (uint32_t)g_pstEEPROMBlock[i].u16BlockSize; g_pfnEEPROMMemRead(u32DataAddr, unCtrlData.u32Word, 1UL); if (unCtrlData.stField.u16Index + unCtrlData.stField.u16IndexInv == 0xFFFFU) { u8Loop = 0U; if (u8Ready == 0U) { u8Ready = 1U; g_pstEEPROMBlock[i].u8Status = EEPROM_BLOCK_ACTIVE; g_pstEEPROMBlock[i].u8SectorOffset = 1U; g_pstEEPROMBlock[i].u16RecordNum = u16RecordNum; g_pstEEPROMBlock[i].u16Index = unCtrlData.stField.u16Index; u16IndexBkup = unCtrlData.stField.u16Index; } else { if (unCtrlData.stField.u16Index >= u16IndexBkup) { u16Index = unCtrlData.stField.u16Index - u16IndexBkup; } else { u16Index = unCtrlData.stField.u16Index + (0xFFFFU - u16IndexBkup) + 1U; } if (u16Index < g_pstEEPROMBlock[i].u16MaxRecordNum + EEPROM_BLANK_CHECK_RECORD_NUM) { g_pstEEPROMBlock[i].u8SectorOffset = 1U; g_pstEEPROMBlock[i].u16RecordNum = u16RecordNum; g_pstEEPROMBlock[i].u16Index = unCtrlData.stField.u16Index; } } } else { u16RecordNum++; if ((u16RecordNum >= u16MaxRecordNum[1U]) || \ (u16RecordNum >= EEPROM_BLANK_CHECK_RECORD_NUM)) { u8Loop = 0U; } } } /*** Step 3.2 Search for the most recent record and load data - Find the last record's address - Load data form the address ***/ if (g_pstEEPROMBlock[i].u8Status == EEPROM_BLOCK_ACTIVE) { /* Find the last record by index */ u32DataAddrBase = g_pstEEPROMBlock[i].u32BaseAddr; u32DataAddrBase += (uint32_t)(g_pstEEPROMBlock[i].u16SectorSize * (uint16_t)g_pstEEPROMBlock[i].u8SectorOffset); u16Index = g_pstEEPROMBlock[i].u16Index; u16RecordNum = g_pstEEPROMBlock[i].u16RecordNum; u8Loop = 1U; while (u8Loop) { u16RecordNum++; u16Index++; if ((u16RecordNum >= u16MaxRecordNum[g_pstEEPROMBlock[i].u8SectorOffset]) || \ (u16RecordNum - g_pstEEPROMBlock[i].u16RecordNum >= EEPROM_OVER_SEARCH_RECORD_NUM)) { u8Loop = 0U; } else { /* Fetch block control data */ u32DataAddr = u32DataAddrBase + (uint32_t)u16RecordNum * (uint32_t)g_pstEEPROMBlock[i].u16BlockSize; g_pfnEEPROMMemRead(u32DataAddr, unCtrlData.u32Word, 1UL); if (unCtrlData.stField.u16Index + unCtrlData.stField.u16IndexInv == 0xFFFFU) { if (unCtrlData.stField.u16Index == u16Index) { g_pstEEPROMBlock[i].u16RecordNum = u16RecordNum; g_pstEEPROMBlock[i].u16Index = unCtrlData.stField.u16Index; } } } } /* Load data */ u16RecordNum = g_pstEEPROMBlock[i].u16RecordNum; u16Index = g_pstEEPROMBlock[i].u16Index; u16IndexBkup = u16Index; u8Loop = 1U; do { u32DataAddr = u32DataAddrBase + (uint32_t)u16RecordNum * (uint32_t)g_pstEEPROMBlock[i].u16BlockSize; g_pfnEEPROMMemRead(u32DataAddr, unCtrlData.u32Word, 1UL); if (unCtrlData.stField.u16Index + unCtrlData.stField.u16IndexInv == 0xFFFFU) { if (u16Index == unCtrlData.stField.u16Index) { u16IndexBkup = u16Index; u16WordNum = g_pstEEPROMBlock[i].u16BlockSize / 4U; /* Load data */ g_pfnEEPROMMemRead(u32DataAddr, g_pstEEPROMBlock[i].pu32Data, (uint32_t)u16WordNum); u16Result = EEPROM_CRC_Calc(g_pstEEPROMBlock[i].pu32Data, u16WordNum - 1U); if ((uint16_t)(g_pstEEPROMBlock[i].pu32Data[u16WordNum - 1U]) == u16Result) { u8Loop = 0U; } } } if (u8Loop) /* CRC check fail */ { u16Index--; /* Go to previous record */ if (u16IndexBkup >= u16Index) { u16Result = u16IndexBkup - u16Index; } else { u16Result = u16IndexBkup + (0xFFFFU - u16Index) + 1U; } if ((u16Result <= u16MaxRecordNum[0U] + u16MaxRecordNum[1U]) &&\ (u16Result <= EEPROM_OVER_SEARCH_RECORD_NUM)) { if (u16RecordNum == 0U) /* Cross sector access */ { if (g_pstEEPROMBlock[i].u8SectorOffset) { u32DataAddrBase -= (uint32_t)g_pstEEPROMBlock[i].u16BlockSize; u16RecordNum = u16MaxRecordNum[0U]; if (u16RecordNum == 0U) { u8Loop = 0U; g_pstEEPROMBlock[i].u8Status = EEPROM_BLOCK_ERROR; } else { u16RecordNum -= 1U; } } else { u32DataAddrBase += g_pstEEPROMBlock[i].u16BlockSize; u16RecordNum = u16MaxRecordNum[1U]; if (u16RecordNum == 0U) { u8Loop = 0U; g_pstEEPROMBlock[i].u8Status = EEPROM_BLOCK_ERROR; } else { u16RecordNum -= 1U; } } } else { u16RecordNum--; } } else { /* No correct data found, set error flag */ u8Loop = 0U; g_pstEEPROMBlock[i].u8Status = EEPROM_BLOCK_ERROR; } } }while(u8Loop); } } } } uint8_t EEPROM_Access_Busy(void) { return g_stEEPROMAccess.u8State; } uint8_t EEPROM_Block_Access_Status(uint16_t u16BlockID) { uint8_t u8Status; u8Status = EEPROM_BLOCK_ERROR; if (u16BlockID < g_stEEPROMAccess.u16BlockNum) { u8Status = g_pstEEPROMBlock[u16BlockID].u8Status; } return u8Status; } /* u16Len : DWord(32-bit) number to be read */ /* Retval 0 - OK 1 - Error */ uint8_t EEPROM_Read_Block_Data(uint16_t u16BlockID, uint32_t u32Data[], uint16_t u16Len) { uint16_t i; uint8_t u8Error; u8Error = 1U; if ((u16BlockID < g_stEEPROMAccess.u16BlockNum) && (u32Data != NULL) && (u16Len != 0U)) { if ((g_pstEEPROMBlock[u16BlockID].u8Status == EEPROM_BLOCK_ACTIVE) && \ (u16Len <= (g_pstEEPROMBlock[u16BlockID].u16BlockSize - EEPROM_BLOCK_CTRL_BYTE_SIZE) / 4U)) { for (i = 0U; i < u16Len; i++) { u32Data[i] = g_pstEEPROMBlock[u16BlockID].pu32Data[i + 1U]; } u8Error = 0U; } } return u8Error; } /* u16Len : DWord(32-bit) number to be written */ /* Retval 0 - OK 1 - Error */ uint8_t EEPROM_Write_Block_Data(uint16_t u16BlockID, uint32_t u32Data[], uint16_t u16Len) { uint16_t i; uint8_t u8Error; uint16_t u16WordNum; uint16_t u16Result; uint32_t u32EndAddr; EEPROM_Ctrl_Data_un_t unCtrlData; u8Error = 1U; if ((g_stEEPROMAccess.u8State == EEPROM_WR_STATE_IDLE) && \ (g_stEEPROMAccess.u16BlockNum > u16BlockID) && (u32Data != NULL) && (u16Len != 0U)) { if (u16Len <= (g_pstEEPROMBlock[u16BlockID].u16BlockSize - EEPROM_BLOCK_CTRL_BYTE_SIZE) / 4U) { g_stEEPROMAccess.u8State = EEPROM_WR_STATE_PROG; u16WordNum = g_pstEEPROMBlock[u16BlockID].u16BlockSize / 4U - 1U; /* CRC checksum is ignored */ if (g_pstEEPROMBlock[u16BlockID].u8Status == EEPROM_BLOCK_ACTIVE) { g_pstEEPROMBlock[u16BlockID].u16RecordNum++; if (g_pstEEPROMBlock[u16BlockID].u16RecordNum >= g_pstEEPROMBlock[u16BlockID].u16MaxRecordNum) { g_stEEPROMAccess.u8State = EEPROM_WR_STATE_ERASE; g_pstEEPROMBlock[u16BlockID].u16RecordNum = 0U; if (g_pstEEPROMBlock[u16BlockID].u8SectorOffset == 0U) { g_pstEEPROMBlock[u16BlockID].u8SectorOffset = 1U; } else { g_pstEEPROMBlock[u16BlockID].u8SectorOffset = 0U; } } g_pstEEPROMBlock[u16BlockID].u16Index++; unCtrlData.stField.u16Index = g_pstEEPROMBlock[u16BlockID].u16Index; unCtrlData.stField.u16IndexInv = 0xFFFFU - unCtrlData.stField.u16Index; g_pstEEPROMBlock[u16BlockID].pu32Data[0U] = unCtrlData.u32Word[0U]; } else { g_stEEPROMAccess.u8State = EEPROM_WR_STATE_ERASE; g_pstEEPROMBlock[u16BlockID].u16RecordNum = 0U; g_pstEEPROMBlock[u16BlockID].u8SectorOffset = 0U; g_pstEEPROMBlock[u16BlockID].u16Index = 0U; g_pstEEPROMBlock[u16BlockID].pu32Data[0U] = 0xFFFF0000UL; for (i = 1U; i < u16WordNum; i++) { g_pstEEPROMBlock[u16BlockID].pu32Data[i] = 0x00000000UL; } g_pstEEPROMBlock[u16BlockID].u8Status = EEPROM_BLOCK_ACTIVE; } u16Len += 1U; for (i = 1U; i < u16Len; i++) { g_pstEEPROMBlock[u16BlockID].pu32Data[i] = u32Data[i - 1U]; } u16Result = EEPROM_CRC_Calc(g_pstEEPROMBlock[u16BlockID].pu32Data, u16WordNum); g_pstEEPROMBlock[u16BlockID].pu32Data[u16WordNum] = (uint32_t)u16Result; g_stEEPROMAccess.u32ProgAddr = g_pstEEPROMBlock[u16BlockID].u32BaseAddr; g_stEEPROMAccess.u32ProgAddr += (uint32_t)g_pstEEPROMBlock[u16BlockID].u16SectorSize * (uint32_t)g_pstEEPROMBlock[u16BlockID].u8SectorOffset; g_stEEPROMAccess.u32ProgAddr += (uint32_t)g_pstEEPROMBlock[u16BlockID].u16BlockSize * (uint32_t)g_pstEEPROMBlock[u16BlockID].u16RecordNum; g_stEEPROMAccess.u16ProgLen = g_pstEEPROMBlock[u16BlockID].u16BlockSize / 4U; g_stEEPROMAccess.pu32ProgData = g_pstEEPROMBlock[u16BlockID].pu32Data; if (g_stEEPROMAccess.u8State == EEPROM_WR_STATE_ERASE) { u32EndAddr = g_stEEPROMAccess.u32ProgAddr + (uint32_t)g_pstEEPROMBlock[u16BlockID].u16SectorSize - 1UL; g_pfnEEPROMMemErase(g_stEEPROMAccess.u32ProgAddr, u32EndAddr); } else { g_pfnEEPROMMemWrite(g_stEEPROMAccess.u32ProgAddr, g_stEEPROMAccess.pu32ProgData, (uint32_t)g_stEEPROMAccess.u16ProgLen); } u8Error = 0U; } } return u8Error; } void EEPROM_Mem_Access_Complete_Callback(void) { if (g_stEEPROMAccess.u8State == EEPROM_WR_STATE_ERASE) { g_stEEPROMAccess.u8State = EEPROM_WR_STATE_PROG; g_pfnEEPROMMemWrite(g_stEEPROMAccess.u32ProgAddr, g_stEEPROMAccess.pu32ProgData, (uint32_t)g_stEEPROMAccess.u16ProgLen); } else { g_stEEPROMAccess.u8State = EEPROM_WR_STATE_IDLE; } } static uint16_t EEPROM_CRC_Calc(uint32_t * pu32Data, uint16_t u16Len) { uint16_t i; uint8_t u8CRCHi; uint8_t u8CRCLo; uint8_t u8Index; uint8_t *pu8DataByte; uint16_t u16CRCResult; u16CRCResult = 0xFFFFU; if (pu32Data != NULL) { u8CRCHi = 0xFFU; u8CRCLo = 0xFFU; u16Len <<= 2U; /* u16Len = u16Len * 4U */ pu8DataByte = (uint8_t *)pu32Data; for (i = 0; i < u16Len; i++) { u8Index = u8CRCLo ^ pu8DataByte[i]; u8CRCLo = u8CRCHi ^ g_u8EEPROMCRCTableH[u8Index]; u8CRCHi = g_u8EEPROMCRCTableL[u8Index]; } u16CRCResult = (uint16_t)u8CRCHi; u16CRCResult <<= 8U; u16CRCResult |= (uint16_t)u8CRCLo; } return u16CRCResult; }