2014-07-28 11:32 PM
I have come across the following ST application note and sample.
I guess this works for STM32F4x family too, am I correct ? #eeprom-emulation2014-08-02 12:55 AM
Read the STM32F40xxx and STM32F41xxxFlash programming manual (PM0081)
Page 13 helped me to do the following modifications. It works now :). Hope this helps others. Flush the caches ( Instruction, Data ) by setting DCRST and ICRST bits in FLASH_CR register. Again, restore the old settings. Introduced code intoEE_PageTransfer
function is/* Flush the caches by setting the DCRST and ICRST bits in the FLASH_CR register.
Note: The I/D cache should be flushed only when it is disabled (I/DCEN = 0).*/
FLASH->ACR &= ~(FLASH_ACR_ICEN |FLASH_ACR_DCEN);
FLASH->ACR = (FLASH_ACR_ICRST |FLASH_ACR_DCRST);
/* Now restore ( Enable I/D caches, clear the DCRST and ICRST bits */
FLASH->ACR = (FLASH_ACR_ICEN |FLASH_ACR_DCEN);
FLASH->ACR = ~(FLASH_ACR_ICRST |FLASH_ACR_DCRST);
static
uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
{
FLASH_Status FlashStatus = FLASH_COMPLETE;
uint32_t NewPageAddress = EEPROM_START_ADDRESS;
uint16_t OldPageId=0;
uint16_t ValidPage = PAGE0, VarIdx = 0;
uint16_t EepromStatus = 0, ReadStatus = 0;
/* Get active Page for read operation */
ValidPage = EE_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 ID where variable will be taken from */
OldPageId = PAGE1_ID;
}
else
if
(ValidPage == PAGE0)
/* Page0 valid */
{
/* New page address where variable will be moved to */
NewPageAddress = PAGE1_BASE_ADDRESS;
/* Old page ID where variable will be taken from */
OldPageId = PAGE0_ID;
}
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 = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
/* 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
(VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++)
{
if
(VirtAddVarTab[VarIdx] != VirtAddress)
/* Check each variable except the one passed as parameter */
{
/* Read the other last variable updates */
ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
/* In case variable corresponding to the virtual address was found */
if
(ReadStatus != 0x1)
{
/* Transfer the variable to the new active page */
EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
/* 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_EraseSector(OldPageId, VOLTAGE_RANGE);
/* 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;
}
/* Flush the caches by setting the DCRST and ICRST bits in the FLASH_CR register.
Note: The I/D cache should be flushed only when it is disabled (I/DCEN = 0).*/
FLASH->ACR &= ~(FLASH_ACR_ICEN |FLASH_ACR_DCEN);
FLASH->ACR = (FLASH_ACR_ICRST |FLASH_ACR_DCRST);
/* Now restore ( Enable I/D caches, clear the DCRST and ICRST bits */
FLASH->ACR = (FLASH_ACR_ICEN |FLASH_ACR_DCEN);
FLASH->ACR = ~(FLASH_ACR_ICRST |FLASH_ACR_DCRST);
/* Return last operation flash status */
return
FlashStatus;
}
clive1, thanks for watching my thread constantly ( I always expected something from you).
people here have a great respect for you. Good day.
Now, I will try to code the same using STM32cube library package( hope to see ST sample).
2014-08-02 10:00 PM
Just finished porting this sample for STM32cube library package. It works without the fix proposed above.
2016-02-10 02:47 PM
Hi guys,
thanks for the great information you were sharing in this post!So, I just also want to share some maybe useful informations regarding the ST EEPROM-emulation:
1. some hints to the old version (''standalone'' solution, based on STSW-STM32066):
Here I encountered the problem that every time my code was calling the EE_INIT() function on startup this function was completely erasing the page which was already marked as ERASED. This erase process takes more than 1 second for my 128k page (I used sectors 10 and 11). But besides that timing issue, I encountered that when loosing power while the erase process was ongoing, the next time I started the code and invoked EE_INIT(), this routineformats both pages because the erase process seems to set all bits to 0 and then backwards to 1 for the whole page which can leave the page in the state VALID. So when interrupted the erased page had a lot of 0s at the beginning and 1s at the end! In this way this page was marked as VALID (0000) and so EE_INIT() get confused with two valid pages and formatted the whole EEPROM memory...2. some hints on an error on the new version from the STM32Cube:
Here they implemented a new funtionality called ''EE_VerifyPageFullyErased'' to overcome the problem described before, so that is great. But anyway - it seems to me that this function just seems to work for Page0, but not for Page1: So I think you should keep that in mind and correct the code when using this functionality... best regards, Markus See attachments for some more details... ________________ Attachments : STM32-EEPROM-Case1.pdf : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I1GM&d=%2Fa%2F0X0000000bkS%2FOndQ7lUtS1loCIvxYEu2fsLExik.Q9CfpUqrbyHOSac&asPdf=falseSTM32-EEPROM-Case2.pdf : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I1GH&d=%2Fa%2F0X0000000bkR%2F1F7KaV35U9alHduvSbp7pzd3AHTVYAXmqrCEMpf7308&asPdf=false