#include "stm32f4xx_eeprom.h"
#include "delay.h"
#include "k7_timer.h"
/**
* @file : stm32f4xx_eeprom.c
* @brief: stm32 flash 模拟 EEPROM
* @process : (1) FLASH_Unlock(); //解除flash限制
* (2) EE_Init() //初始化flash
* (3) EE_WriteVariable(uint16_t VirtAddress, void *Data, uint16_t len) //写操作
* EE_ReadVariable(uint16_t VirtAddress, void *Data, uint16_t len) //读操作
* (4) FLASH_Lock(); //记得锁住,以免flash随意改动
*/
/* Global variable used to store variable value in read sequence */
static uint8_t DatWorkBuf[EEPROM_CELL_DATA_LEN];//data work buffer
/* Variable used for Erase sectors under interruption */
static uint16_t EE_FindValidPage(uint8_t Operation);
static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, void *data, uint16_t len);
static uint16_t EE_PageTransfer(uint16_t VirtAddress, void *data, uint16_t Len);
static uint16_t EE_VerifyPageFullyErased(uint32_t Address);
/**
* @brief Restore the pages to a known good state in case of page's status
* corruption after a power loss.
* @param None.
* @retval - Flash error code: on write Flash error
* - FLASH_COMPLETE: on success
*/
uint16_t EE_Init(void)
{
uint16_t PageStatus0 = 6, PageStatus1 = 6;
uint16_t VarIdx = 0;
uint16_t EepromStatus = 0, ReadStatus = 0;
int16_t x0 = -1;
FLASH_Status FlashStatus;
uint32_t SectorError = 0;
FLASH_EraseInitTypeDef pEraseInit;
/* Get Page0 status */
PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
/* Get Page1 status */
PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
pEraseInit.TypeErase = TYPEERASE_SECTORS;
pEraseInit.Sector = PAGE0_ID;
pEraseInit.NbSectors = 1;
pEraseInit.VoltageRange = VOLTAGE_RANGE;
/* Check for invalid header states and repair if necessary */
switch (PageStatus0)
{
case ERASED:
if (PageStatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */
{
/* Erase Page0 */
if (!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
{
FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
}
else if (PageStatus1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */
{
/* Erase Page0 */
if (!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
{
FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
/* Mark Page1 as valid */
FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE1_BASE_ADDRESS, VALID_PAGE);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
else /* First EEPROM access (Page0&1 are erased) or invalid state -> format EEPROM */
{
/* Erase both Page0 and Page1 and set Page0 as valid page */
FlashStatus = EE_Format();
/* If erase/program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
break;
case RECEIVE_DATA:
if (PageStatus1 == VALID_PAGE) /* Page0 receive, Page1 valid */
{
/* Transfer data from Page1 to Page0 */
//only data in 2nd cell of page0 is neweset
x0 = (*(__IO uint16_t*)(PAGE0_BASE_ADDRESS + EEPROM_CELL_SZ * 2 - EEPROM_CELL_ADDR_LEN));
for (VarIdx = 0; VarIdx < NUM_OF_VAL_CELL; VarIdx++)
{
if (VarIdx != x0)
{
/* Read the last variables' updates */
ReadStatus = EE_ReadVariable(VarIdx, DatWorkBuf, EEPROM_CELL_DATA_LEN);
/* In case variable corresponding to the virtual address was found */
if (ReadStatus != 0x1)
{
/* Transfer the variable to the Page0 */
EepromStatus = EE_VerifyPageFullWriteVariable(VarIdx, DatWorkBuf, EEPROM_CELL_DATA_LEN);
/* If program operation was failed, a Flash error code is returned */
if (EepromStatus != FLASH_COMPLETE)
{
return EepromStatus;
}
}
}
}
/* Mark Page0 as valid */
FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
pEraseInit.Sector = PAGE1_ID;
pEraseInit.NbSectors = 1;
pEraseInit.VoltageRange = VOLTAGE_RANGE;
/* Erase Page1 */
if (!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
{
FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
}
else if (PageStatus1 == ERASED) /* Page0 receive, Page1 erased */
{
pEraseInit.Sector = PAGE1_ID;
pEraseInit.NbSectors = 1;
pEraseInit.VoltageRange = VOLTAGE_RANGE;
/* Erase Page1 */
if (!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
{
FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
/* Mark Page0 as valid */
FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
else /* Invalid state -> format eeprom */
{
/* Erase both Page0 and Page1 and set Page0 as valid page */
FlashStatus = EE_Format();
/* If erase/program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
break;
case VALID_PAGE:
if (PageStatus1 == VALID_PAGE) /* Invalid state -> format ee