#include "EEPROM_24Cxx_Remap.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; //0�б�����ʹ�� 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++) //д��˳��ΪCol1 -> Col3, Col1�н����п��������µ�����(����д������жϵ�����) { wdt_reset(); 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; //�������3�� NVMAbsentCnt = 0; //����洢��δ���Ӽ��� PhyAddr = (EEPPROM_TOTAL_ROW_NUM * Col + Row) * EEPROM_PAGE_SIZE; while (RetryCnt) { RetryCnt--; ReadCnt = 255; //���Զ�ȡ�������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 //255�����Զ�δ�ܴӴ洢���ж������� NVMAbsentCnt++; } if (NVMAbsentCnt >= 3) //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) //3��ȫ��д�� { EEPROMDataWrCtrl.Busy = 0; //д����� if (EEPROMDataWrCtrl.WrCnt == 3) //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) //����3����Ȼδ�ܳɹ�д�� { EEPROMDataWrCtrl.Col++; //����д��һ�� EEPROMDataWrCtrl.Retry = 3; //ÿҳ�������д������ if (EEPROMDataWrCtrl.Col > 3) //3��ȫ��д�� { EEPROMDataWrCtrl.Busy = 0; //д����� if (EEPROMDataWrCtrl.WrCnt == 0) //3ҳȫ��д��ʧ��,��������д��ʧ�� 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; } } /****************************************************************************** ExtLife�������ݶ�д ******************************************************************************/ /****************************************************************************** Normal�������ݶ�д ******************************************************************************/ 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; //ÿ��Page������Զ�ȡ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) //3�ζ�δ�ܳɹ��Ӵ洢���ж������� return EEPROM_DATA_RW_FAIL; Offset = 0; //Offsetֻ���ڵ�����ҳƫ���� 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; //Offsetֻ���ڵ�����ҳƫ���� 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) //����3����Ȼδ�ܳɹ�д�� { 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; }