/********************************************************************************* *Function : uint16_t EEPROM_WriteVariable(uint16_t EepromAddress, uint16_t EepromData) *Description : Writes/upadtes variable data in EEPROM. *Input : EepromAddress: Variable virtual address EepromData: 16 bit data to be written *Output : none *Return : Success or error status: * - FLASH_COMPLETE: on success * - PAGE_FULL: if valid page is full * - NO_VALID_PAGE: if no valid page was found * - Flash error code: on write Flash error *author : lz *date : 2015-2-1 *Others : none **********************************************************************************/ uint16_t EEPROM_WriteVariable(uint16_t EepromAddress, uint16_t EepromData) { uint16_t Status = 0; /* Unlock the Flash Program Erase controller */ FLASH_Unlock(); /* Write the variable virtual address and value in the EEPROM */ Status = EEPROM_VerifyPageFullWriteVariable(EepromAddress, EepromData); /* In case the EEPROM active page is full */ if (Status == PAGE_FULL) { /* Perform Page transfer */ Status = EEPROM_PageTransfer(EepromAddress, EepromData); } /* Return last operation status */ return Status; }
/********************************************************************************* *Function : static uint16_t EEPROM_PageTransfer(uint16_t EepromAddress, uint16_t EepromData) *Description : Transfers last updated variables data from the full Page to an empty one. *Input : EepromAddress: 16 bit virtual address of the variable EepromData: 16 bit data to be written as variable value *Output : none *Return : Success or error status: * - FLASH_COMPLETE: on success * - PAGE_FULL: if valid page is full * - NO_VALID_PAGE: if no valid page was found * - Flash error code: on write Flash error *author : lz *date : 2015-2-1 *Others : none **********************************************************************************/ static uint16_t EEPROM_PageTransfer(uint16_t EepromAddress, uint16_t EepromData) { FLASH_Status FlashStatus = FLASH_COMPLETE; uint32_t OldPageAddress = PAGE0_BASE_ADDRESS, NewPageAddress = PAGE1_BASE_ADDRESS; uint16_t ValidPage = PAGE0, EepromAddressIdx = 0; uint16_t EepromStatus = 0, ReadStatus = 0; /* Get active Page for read operation */ ValidPage = EEPROM_FindValidPage(READ_FROM_VALID_PAGE); if (ValidPage == PAGE1) /* Page1 valid */ { /* New page address where variable will be moved to */ NewPageAddress = PAGE0_BASE_ADDRESS; /* Old page address where variable will be taken from */ OldPageAddress = PAGE1_BASE_ADDRESS; } else if (ValidPage == PAGE0) /* Page0 valid */ { /* New page address where variable will be moved to */ NewPageAddress = PAGE1_BASE_ADDRESS; /* Old page address where variable will be taken from */ OldPageAddress = PAGE0_BASE_ADDRESS; } else { return NO_VALID_PAGE; /* No valid Page */ } /* Set the new Page status to RECEIVE_DATA status */ FlashStatus = FLASH_ProgramHalfWord(NewPageAddress, RECEIVE_DATA); /* If program operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Write the variable passed as parameter in the new active page */ EepromStatus = EEPROM_VerifyPageFullWriteVariable(EepromAddress, EepromData); /* If program operation was failed, a Flash error code is returned */ if (EepromStatus != FLASH_COMPLETE) { return EepromStatus; } /* Transfer process: transfer variables from old to the new active page */ for (EepromAddressIdx = 0; EepromAddressIdx < EEPROM_SIZE; EepromAddressIdx++) { if (EepromAddressTab[EepromAddressIdx] != EepromAddress) /* Check each variable except the one passed as parameter */ { /* Read the other last variable updates */ ReadStatus = EEPROM_ReadVariable(EepromAddressTab[EepromAddressIdx], &EepromDataVar); /* In case variable corresponding to the virtual address was found */ if (ReadStatus != 0x1) { /* Transfer the variable to the new active page */ EepromStatus = EEPROM_VerifyPageFullWriteVariable(EepromAddressTab[EepromAddressIdx], EepromDataVar); /* If program operation was failed, a Flash error code is returned */ if (EepromStatus != FLASH_COMPLETE) { return EepromStatus; } } } } /* Erase the old Page: Set old Page status to ERASED status */ FlashStatus = FLASH_ErasePage(OldPageAddress); /* If erase operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Set new Page status to VALID_PAGE status */ FlashStatus = FLASH_ProgramHalfWord(NewPageAddress, VALID_PAGE); /* If program operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Return last operation flash status */ return FlashStatus; }
/********************************************************************************* *Function : uint16_t EEPROM_Init(void) *Description : Restore the pages to a known good state in case of page's status corruption after a power loss. *Input : none *Output : none *Return : none *author : lz *date : 2015-2-1 *Others : none **********************************************************************************/ uint16_t EEPROM_Init(void) { uint16_t PageStatus0 = 6, PageStatus1 = 6; uint16_t EepromAddressIdx = 0; uint16_t EepromStatus = 0, ReadStatus = 0; int16_t x = -1; uint16_t FlashStatus; /* Unlock the Flash Program Erase controller */ FLASH_Unlock(); /* Get Page0 status */ PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS); /* Get Page1 status */ PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS); /* Check for invalid header states and repair if necessary */ switch (PageStatus0) { case ERASED: if (PageStatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */ { /* Erase Page0 */ FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS); /* 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 */ FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS); /* If erase operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Mark Page1 as valid */ FlashStatus = FLASH_ProgramHalfWord(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 = EEPROM_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 */ for (EepromAddressIdx = 0; EepromAddressIdx < EEPROM_SIZE; EepromAddressIdx++) { if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == EepromAddressTab[EepromAddressIdx]) { x = EepromAddressIdx; } if (EepromAddressIdx != x) { /* Read the last variables' updates */ ReadStatus = EEPROM_ReadVariable(EepromAddressTab[EepromAddressIdx], &EepromDataVar); /* In case variable corresponding to the virtual address was found */ if (ReadStatus != 0x1) { /* Transfer the variable to the Page0 */ EepromStatus = EEPROM_VerifyPageFullWriteVariable(EepromAddressTab[EepromAddressIdx], EepromDataVar); /* If program operation was failed, a Flash error code is returned */ if (EepromStatus != FLASH_COMPLETE) { return EepromStatus; } } } } /* Mark Page0 as valid */ FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE); /* If program operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Erase Page1 */ FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS); /* 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 */ { /* Erase Page1 */ FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS); /* If erase operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Mark Page0 as valid */ FlashStatus = FLASH_ProgramHalfWord(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 = EEPROM_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 eeprom */ { /* Erase both Page0 and Page1 and set Page0 as valid page */ FlashStatus = EEPROM_Format(); /* If erase/program operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } } else if (PageStatus1 == ERASED) /* Page0 valid, Page1 erased */ { /* Erase Page1 */ FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS); /* If erase operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } } else /* Page0 valid, Page1 receive */ { /* Transfer data from Page0 to Page1 */ for (EepromAddressIdx = 0; EepromAddressIdx < EEPROM_SIZE; EepromAddressIdx++) { if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == EepromAddressTab[EepromAddressIdx]) { x = EepromAddressIdx; } if (EepromAddressIdx != x) { /* Read the last variables' updates */ ReadStatus = EEPROM_ReadVariable(EepromAddressTab[EepromAddressIdx], &EepromDataVar); /* In case variable corresponding to the virtual address was found */ if (ReadStatus != 0x1) { /* Transfer the variable to the Page1 */ EepromStatus = EEPROM_VerifyPageFullWriteVariable(EepromAddressTab[EepromAddressIdx], EepromDataVar); /* If program operation was failed, a Flash error code is returned */ if (EepromStatus != FLASH_COMPLETE) { return EepromStatus; } } } } /* Mark Page1 as valid */ FlashStatus = FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, VALID_PAGE); /* If program operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Erase Page0 */ FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS); /* If erase operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } } break; default: /* Any other state -> format eeprom */ /* Erase both Page0 and Page1 and set Page0 as valid page */ FlashStatus = EEPROM_Format(); /* If erase/program operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } break; } return FLASH_COMPLETE; }
/** * @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 */ static uint16_t EEPROM_Init(void) { uint16_t PageStatus0 = 6, PageStatus1 = 6; uint16_t virtualAddress = 0; uint16_t EepromStatus = 0, ReadStatus = 0; int16_t x = -1; uint16_t FlashStatus; uint16_t EepromDataVar = 0; /* Calling this is here is critical on STM32F2 Devices Else Flash Operation Fails */ FLASH_ClearFlags(); /* Get Page0 status */ PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS); /* Get Page1 status */ PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS); /* Check for invalid header states and repair if necessary */ switch (PageStatus0) { case ERASED: if (PageStatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */ { /* Normal valid state -> nothing to do */ } else if (PageStatus1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */ { /* Erase Page0 */ FlashStatus = FLASH_EraseSector(PAGE0_ID, VOLTAGE_RANGE); /* If erase operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Mark Page1 as valid */ FlashStatus = FLASH_ProgramHalfWord(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 = EEPROM_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 */ for (virtualAddress = 0; virtualAddress < EEPROM_SIZE; virtualAddress++) { if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == virtualAddress) { x = virtualAddress; } if (virtualAddress != x) { /* Read the last variables' updates */ ReadStatus = EEPROM_ReadVariable(virtualAddress, &EepromDataVar); /* In case variable corresponding to the virtual address was found */ if (ReadStatus != 0x1) { /* Transfer the variable to the Page0 */ EepromStatus = EEPROM_VerifyPageFullWriteVariable(virtualAddress, EepromDataVar); /* If program operation was failed, a Flash error code is returned */ if (EepromStatus != FLASH_COMPLETE) { return EepromStatus; } } } } /* Mark Page0 as valid */ FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE); /* If program operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Erase Page1 */ FlashStatus = FLASH_EraseSector(PAGE1_ID, VOLTAGE_RANGE); /* 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 */ { /* Erase Page1 */ FlashStatus = FLASH_EraseSector(PAGE1_ID, VOLTAGE_RANGE); /* If erase operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Mark Page0 as valid */ FlashStatus = FLASH_ProgramHalfWord(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 = EEPROM_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) /* Harmless invalid state -> pick one page and format the other */ { /* Erase Page0 */ FlashStatus = FLASH_EraseSector(PAGE0_ID, VOLTAGE_RANGE); /* If erase/program operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } } else if (PageStatus1 == ERASED) /* Page0 valid, Page1 erased */ { /* Normal valid state -> nothing to do */ } else /* Page0 valid, Page1 receive */ { /* Transfer data from Page0 to Page1 */ for (virtualAddress = 0; virtualAddress < EEPROM_SIZE; virtualAddress++) { if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == virtualAddress) { x = virtualAddress; } if (virtualAddress != x) { /* Read the last variables' updates */ ReadStatus = EEPROM_ReadVariable(virtualAddress, &EepromDataVar); /* In case variable corresponding to the virtual address was found */ if (ReadStatus != 0x1) { /* Transfer the variable to the Page1 */ EepromStatus = EEPROM_VerifyPageFullWriteVariable(virtualAddress, EepromDataVar); /* If program operation was failed, a Flash error code is returned */ if (EepromStatus != FLASH_COMPLETE) { return EepromStatus; } } } } /* Mark Page1 as valid */ FlashStatus = FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, VALID_PAGE); /* If program operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } /* Erase Page0 */ FlashStatus = FLASH_EraseSector(PAGE0_ID, VOLTAGE_RANGE); /* If erase operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } } break; default: /* Any other state -> format eeprom */ /* Erase both Page0 and Page1 and set Page0 as valid page */ FlashStatus = EEPROM_Format(); /* If erase/program operation was failed, a Flash error code is returned */ if (FlashStatus != FLASH_COMPLETE) { return FlashStatus; } break; } return FLASH_COMPLETE; }