#include "EEPROM_24Cxx_Remap.h"
#include "Simulated_IIC_Master.h"
#include "Watchdog.h"
EEPROMDataWrCtrlStruct EEPROMDataWrCtrl;
EEPROMAccessStatusEnum EEPROM_Data_Write(uint8_t Type, uint16_t Addr, uint8_t *pData, uint8_t Len)
{
if (EEPROMDataWrCtrl.Busy)
return EEPROM_DATA_RW_FAIL;
switch (Type)
{
case EEPROM_HIREL_DATA_TYPE : return EEPROM_HiRel_Data_Write(Addr, pData, Len);
break;
case EEPROM_EXTLIFE_DATA_TYPE : return EEPROM_DATA_RW_FAIL;
break;
case EEPROM_NORMAL_DATA_TYPE : return EEPROM_Normal_Data_Write(Addr, pData, Len);
break;
default : return EEPROM_DATA_RW_FAIL;
break;
}
}
EEPROMAccessStatusEnum EEPROM_Get_Data_Write_Status(void)
{
return EEPROMDataWrCtrl.Result;
}
EEPROMAccessStatusEnum EEPROM_Startup_Data_Read(uint8_t Type, uint16_t Addr, uint8_t *pData, uint8_t Len)
{
switch (Type)
{
case EEPROM_HIREL_DATA_TYPE : return EEPROM_Startup_HiRel_Data_Read(Addr, pData, Len);
break;
case EEPROM_EXTLIFE_DATA_TYPE : return EEPROM_DATA_RW_FAIL;
break;
case EEPROM_NORMAL_DATA_TYPE : return EEPROM_Startup_Normal_Data_Read(Addr, pData, Len);
break;
default : return EEPROM_DATA_RW_FAIL;
break;
}
}
void EEPROM_Access_Service(void)
{
if (EEPROMDataWrCtrl.Busy)
{
switch (EEPROMDataWrCtrl.Type)
{
case EEPROM_HIREL_DATA_TYPE : EEPROM_HiRel_Data_Write_Service();
break;
case EEPROM_EXTLIFE_DATA_TYPE :
break;
case EEPROM_NORMAL_DATA_TYPE : EEPROM_Normal_Data_Write_Service();
break;
default : break;
}
}
}
/******************************************************************************
HiRel�������ݶ�д
******************************************************************************/
EEPROMAccessStatusEnum EEPROM_HiRel_Data_Write(uint16_t Addr, uint8_t *pData, uint8_t Len)
{
uint8_t i;
if (Addr >= EEPPROM_HIREL_DATA_NUM)
return EEPROM_DATA_ADDR_ERR;
if ((Len == 0) || (Len > EEPPROM_HIREL_DATA_MAX_LEN))
return EEPROM_DATA_LEN_ERR;
EEPROMDataWrCtrl.Type = EEPROM_HIREL_DATA_TYPE;
for (i = 0; i < Len; i++)
{
EEPROMDataWrCtrl.Data[i] = pData[i];
EEPROMDataWrCtrl.Data[Len + i] = ~pData[i];
}
EEPROMDataWrCtrl.DataLen = Len * 2;
EEPROMDataWrCtrl.Row = (uint8_t)Addr;
EEPROMDataWrCtrl.Col = 1;
EEPROMDataWrCtrl.Offset = 0;
EEPROMDataWrCtrl.Retry = 3;
EEPROMDataWrCtrl.WrLen = 0;
EEPROMDataWrCtrl.WrCnt = 0;
EEPROMDataWrCtrl.Busy = 1;
EEPROMDataWrCtrl.Result = EEPROM_MEMORY_BUSY;
return EEPROM_DATA_OK;
}
EEPROMAccessStatusEnum EEPROM_Startup_HiRel_Data_Read(uint16_t Addr, uint8_t *pData, uint8_t Len)
{
uint8_t Row;
uint8_t Col;
uint8_t ValidDataCnt;
uint8_t Data[EEPPROM_HIREL_DATA_MAX_LEN];
EEPROMAccessStatusEnum Result;
if (Addr >= EEPPROM_HIREL_DATA_NUM)
return EEPROM_DATA_ADDR_ERR;
if ((Len == 0) || (Len > EEPPROM_HIREL_DATA_MAX_LEN))
return EEPROM_DATA_LEN_ERR;
Row = (uint8_t)Addr;
ValidDataCnt = 0;
for (Col = 1; Col <= 3; Col++)
{
WDT_Clear( );
Result = EEPROM_Startup_HiRel_Page_Read(Row, Col, Data, Len);
if (Result == EEPROM_DATA_OK)
{
if (ValidDataCnt == 0)
{
EEPROM_Copy_Data(pData, Data, Len);
ValidDataCnt++;
}
else
{
if (EEPROM_Compare_Data(Data, pData, Len) == 0)
ValidDataCnt++;
}
}
else if ((Result == EEPROM_MEMORY_ABSENT) || (Result == EEPROM_DATA_ADDR_ERR) || (Result == EEPROM_DATA_LEN_ERR))
return Result;
}
if (ValidDataCnt == 3)
return EEPROM_DATA_OK;
else if ((ValidDataCnt == 2) || (ValidDataCnt == 1))
return EEPROM_DATA_PARTIAL_LOST;
else
return EEPROM_DATA_LOST;
}
EEPROMAccessStatusEnum EEPROM_Startup_HiRel_Page_Read(uint8_t Row, uint8_t Col, uint8_t *pData, uint8_t Len)
{
uint8_t ReadCnt;
uint8_t RetryCnt;
uint8_t NVMAbsentCnt;
uint8_t PageData[EEPROM_PAGE_SIZE];
uint16_t PhyAddr;
EEPROMErrEnum ReadResult;
RetryCnt = 3;
NVMAbsentCnt = 0;
PhyAddr = (EEPPROM_TOTAL_ROW_NUM * Col + Row) * EEPROM_PAGE_SIZE;
while (RetryCnt)
{
RetryCnt--;
ReadCnt = 255;
while (ReadCnt)
{
ReadResult = EEPROM_Instant_Sequential_Read(EEPPROM_DEVICE_ADDR, PhyAddr, PageData, Len * 2);
if (ReadResult == EEPROM_OK)
break;
else if ((ReadResult == EEPROM_INVALID_DEVICE_ADDR) || (ReadResult == EEPROM_INVALID_DATA_ADDR))
return EEPROM_DATA_ADDR_ERR;
else if (ReadResult == EEPROM_DATA_LENGTH_ERR)
return EEPROM_DATA_LEN_ERR;
ReadCnt--;
}
if (ReadResult == EEPROM_OK)
{
if (EEPROM_HiRel_Data_Check(PageData, Len) == 0)
{
EEPROM_Copy_Data(pData, PageData, Len);
return EEPROM_DATA_OK;
}
}
else
NVMAbsentCnt++;
}
if (NVMAbsentCnt >= 3)
return EEPROM_MEMORY_ABSENT;
else
return EEPROM_DATA_RW_FAIL;
}
uint8_t EEPROM_HiRel_Data_Check(uint8_t *pData, uint8_t Len)
{
uint8_t i;
for (i = 0; i < Len; i++)
{
if (pData[i] + pData[Len + i] != 0xFF)
return 1;
}
return 0;
}
void EEPROM_HiRel_Data_Write_Service(void)
{
uint16_t PhyAddr;
EEPROMErrEnum WriteErr;
EEPROMRWResultEnum WriteResult;
if (EEPROMDataWrCtrl.Busy > 1)
{
WriteResult = EEPROM_Get_Write_Result();
switch (WriteResult)
{
case EEPROM_RW_NONE :
EEPROMDataWrCtrl.Busy = 0;
EEPROMDataWrCtrl.Result = EEPROM_DATA_RW_FAIL;
return;
break;
case EEPROM_RW_DONE :
EEPROMDataWrCtrl.WrCnt++;
EEPROMDataWrCtrl.Col++;
EEPROMDataWrCtrl.Retry = 3;
if (EEPROMDataWrCtrl.Col > 3)
{
EEPROMDataWrCtrl.Busy = 0;
if (EEPROMDataWrCtrl.WrCnt == 3)
EEPROMDataWrCtrl.Result = EEPROM_DATA_OK;
else
EEPROMDataWrCtrl.Result = EEPROM_DATA_PARTIAL_LOST;
return;
}
break;
case EEPROM_RW_FAIL :
EEPROMDataWrCtrl.Retry--;
if (EEPROMDataWrCtrl.Retry == 0)
{
EEPROMDataWrCtrl.Col++;
EEPROMDataWrCtrl.Retry = 3;
if (EEPROMDataWrCtrl.Col > 3)
{
EEPROMDataWrCtrl.Busy = 0;
if (EEPROMDataWrCtrl.WrCnt == 0)
EEPROMDataWrCtrl.Result = EEPROM_DATA_RW_FAIL;
else
EEPROMDataWrCtrl.Result = EEPROM_DATA_PARTIAL_LOST;
return;
}
}
break;
case EEPROM_RW_IN_PROGRESS :
return;
break;
default : EEPROMDataWrCtrl.Busy = 0;
EEPROMDataWrCtrl.Result = EEPROM_DATA_RW_FAIL;
return;
break;
}
}
PhyAddr = (EEPPROM_TOTAL_ROW_NUM * EEPROMDataWrCtrl.Col + EEPROMDataWrCtrl.Row) * EEPROM_PAGE_SIZE;
WriteErr = EEPROM_Page_Write(EEPPROM_DEVICE_ADDR, PhyAddr, EEPROMDataWrCtrl.Data, (uint8_t)(EEPROMDataWrCtrl.DataLen));
EEPROMDataWrCtrl.Busy = 2;
if (WriteErr != EEPROM_OK)
{
EEPROMDataWrCtrl.Busy = 0;
if ((WriteErr == EEPROM_INVALID_DEVICE_ADDR) || (WriteErr == EEPROM_INVALID_DATA_ADDR))
EEPROMDataWrCtrl.Result = EEPROM_DATA_ADDR_ERR;
else if (WriteErr == EEPROM_DATA_LENGTH_ERR)
EEPROMDataWrCtrl.Result = EEPROM_DATA_LEN_ERR;
else
EEPROMDataWrCtrl.Result = EEPROM_DATA_RW_FAIL;
}
}
EEPROMAccessStatusEnum EEPROM_Normal_Data_Write(uint16_t Addr, uint8_t *pData, uint16_t Len)
{
uint8_t i;
uint16_t PageNum;
if (Addr > EEPPROM_DATA_MAX_ADDR)
return EEPROM_DATA_ADDR_ERR;
if ((Len == 0) || (Len > EEPPROM_DATA_MAX_ADDR - Addr + 1))
return EEPROM_DATA_LEN_ERR;
EEPROMDataWrCtrl.Type = EEPROM_NORMAL_DATA_TYPE;
for (i = 0; i < Len; i++)
{
EEPROMDataWrCtrl.Data[i] = pData[i];
}
EEPROMDataWrCtrl.DataLen = Len;
PageNum = Addr / EEPROM_PAGE_SIZE;
EEPROMDataWrCtrl.Row = (uint8_t)(PageNum / 4) + EEPPROM_DATA_ROW_OFFSEET;
EEPROMDataWrCtrl.Col = (uint8_t)(PageNum % 4);
EEPROMDataWrCtrl.Offset = (uint8_t)(Addr % EEPROM_PAGE_SIZE);
EEPROMDataWrCtrl.Retry = 3;
EEPROMDataWrCtrl.WrLen = 0;
EEPROMDataWrCtrl.WrCnt = 0;
EEPROMDataWrCtrl.Busy = 1;
EEPROMDataWrCtrl.Result = EEPROM_MEMORY_BUSY;
return EEPROM_DATA_OK;
}
EEPROMAccessStatusEnum EEPROM_Startup_Normal_Data_Read(uint16_t Addr, uint8_t *pData, uint8_t Len)
{
uint8_t Row;
uint8_t Col;
uint8_t Offset;
uint16_t PageNum;
uint16_t RemLen;
uint8_t RetryCnt;
uint16_t PhyAddr;
uint8_t CurrentLen;
EEPROMErrEnum ReadResult;
if (Addr > EEPPROM_DATA_MAX_ADDR)
return EEPROM_DATA_ADDR_ERR;
if ((Len == 0) || (Len > EEPPROM_DATA_MAX_ADDR - Addr + 1))
return EEPROM_DATA_LEN_ERR;
RemLen = Len;
PageNum = Addr / EEPROM_PAGE_SIZE;
Row = (uint8_t)(PageNum / 4) + EEPPROM_DATA_ROW_OFFSEET;
Col = (uint8_t)(PageNum % 4);
Offset = (uint8_t)(Addr % EEPROM_PAGE_SIZE);
while (RemLen)
{
PhyAddr = (EEPPROM_TOTAL_ROW_NUM * Col + Row) * EEPROM_PAGE_SIZE + Offset;
CurrentLen = EEPROM_PAGE_SIZE - Offset;
RetryCnt = 3;
if (CurrentLen > RemLen)
CurrentLen = (uint8_t)RemLen;
while (RetryCnt)
{
ReadResult = EEPROM_Instant_Sequential_Read(EEPPROM_DEVICE_ADDR, PhyAddr, &pData[Len - RemLen], CurrentLen);
if (ReadResult == EEPROM_OK)
break;
else if ((ReadResult == EEPROM_INVALID_DEVICE_ADDR) || (ReadResult == EEPROM_INVALID_DATA_ADDR))
return EEPROM_DATA_ADDR_ERR;
else if (ReadResult == EEPROM_DATA_LENGTH_ERR)
return EEPROM_DATA_LEN_ERR;
RetryCnt--;
}
if (ReadResult != EEPROM_OK)
return EEPROM_DATA_RW_FAIL;
Offset = 0;
Col++;
if (Col > 3)
{
Col = 0;
Row++;
}
RemLen -= CurrentLen;
}
return EEPROM_DATA_OK;
}
void EEPROM_Normal_Data_Write_Service(void)
{
uint16_t PhyAddr;
EEPROMErrEnum WriteErr;
EEPROMRWResultEnum WriteResult;
if (EEPROMDataWrCtrl.Busy > 1)
{
WriteResult = EEPROM_Get_Write_Result();
switch (WriteResult)
{
case EEPROM_RW_NONE :
EEPROMDataWrCtrl.Busy = 0;
EEPROMDataWrCtrl.Result = EEPROM_DATA_RW_FAIL;
return;
break;
case EEPROM_RW_DONE :
EEPROMDataWrCtrl.Offset = 0;
EEPROMDataWrCtrl.Col++;
if (EEPROMDataWrCtrl.Col > 3)
{
EEPROMDataWrCtrl.Col = 0;
EEPROMDataWrCtrl.Row++;
}
EEPROMDataWrCtrl.WrCnt += EEPROMDataWrCtrl.WrLen;
EEPROMDataWrCtrl.Retry = 3;
if (EEPROMDataWrCtrl.WrCnt >= EEPROMDataWrCtrl.DataLen)
{
EEPROMDataWrCtrl.Busy = 0;
EEPROMDataWrCtrl.Result = EEPROM_DATA_OK;
return;
}
break;
case EEPROM_RW_FAIL :
EEPROMDataWrCtrl.Retry--;
if (EEPROMDataWrCtrl.Retry == 0)
{
EEPROMDataWrCtrl.Busy = 0;
EEPROMDataWrCtrl.Result = EEPROM_DATA_RW_FAIL;
return;
}
break;
case EEPROM_RW_IN_PROGRESS :
return;
break;
default : EEPROMDataWrCtrl.Busy = 0;
EEPROMDataWrCtrl.Result = EEPROM_DATA_RW_FAIL;
return;
break;
}
}
PhyAddr = (EEPPROM_TOTAL_ROW_NUM * EEPROMDataWrCtrl.Col + EEPROMDataWrCtrl.Row) * EEPROM_PAGE_SIZE + EEPROMDataWrCtrl.Offset;
EEPROMDataWrCtrl.WrLen = EEPROM_PAGE_SIZE - EEPROMDataWrCtrl.Offset;
if (EEPROMDataWrCtrl.WrLen > EEPROMDataWrCtrl.DataLen - EEPROMDataWrCtrl.WrCnt)
EEPROMDataWrCtrl.WrLen = EEPROMDataWrCtrl.DataLen - EEPROMDataWrCtrl.WrCnt;
WriteErr = EEPROM_Page_Write(EEPPROM_DEVICE_ADDR, PhyAddr, &EEPROMDataWrCtrl.Data[EEPROMDataWrCtrl.WrCnt], EEPROMDataWrCtrl.WrLen);
EEPROMDataWrCtrl.Busy = 2;
if (WriteErr != EEPROM_OK)
{
EEPROMDataWrCtrl.Busy = 0;
if ((WriteErr == EEPROM_INVALID_DEVICE_ADDR) || (WriteErr == EEPROM_INVALID_DATA_ADDR))
EEPROMDataWrCtrl.Result = EEPROM_DATA_ADDR_ERR;
else if (WriteErr == EEPROM_DATA_LENGTH_ERR)
EEPROMDataWrCtrl.Result = EEPROM_DATA_LEN_ERR;
else
EEPROMDataWrCtrl.Result = EEPROM_DATA_RW_FAIL;
}
}
void EEPROM_Copy_Data(uint8_t *pDstData, uint8_t *pSrcData, uint8_t Len)
{
uint8_t i;
for (i = 0; i < Len; i++)
pDstData[i] = pSrcData[i];
}
uint8_t EEPROM_Compare_Data(uint8_t *pDstData, uint8_t *pSrcData, uint8_t Len)
{
uint8_t i;
for (i = 0; i < Len; i++)
{
if (pDstData[i] - pSrcData[i])
return 1;
}
return 0;
}