Skip to main content
This topic has been closed for replies.

12 replies

Tesla DeLorean
Guru
July 29, 2014
Posted on July 29, 2014 at 15:19

http://www.st.com/web/en/catalog/tools/PF257902

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
July 30, 2014
Posted on July 30, 2014 at 02:22

No idea, if you understand the issues/limitations of the STM32 Flash memory you'd be better off not using an abstraction to make it function like an awkward EEPROM

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
harinath
harinathAuthor
Associate III
July 30, 2014
Posted on July 30, 2014 at 07:56

I have created a new IAR project & writing 3 variables with virtual addresses 0x5555, 0x6666 and 0x7777 respectively. The sample code uses 2 pages (page0, page1) in sectors 2 & 3 of FLASH memory ( STM32F4-Discovery board with STM32F407VG mcu).

Here is simple code which writesfirst variable 10 timesat 0x5555, second variable 20 timesat 0x6666 and the third variable 40 times at 0x77


/* Virtual address defined by the user: 0xFFFF value is prohibited */

uint16_t VirtAddVarTab[NB_OF_VAR] = {0x5555, 0x6666, 0x7777};

uint16_t VarDataTab[NB_OF_VAR] = {0, 0, 0};

uint16_t VarValue = 0;


int

main(

void

)

{

/*!< At this stage the microcontroller clock setting is already configured,

this is done through SystemInit() function which is called from startup

file (startup_stm32f4xx.s) before to branch to application main.

To reconfigure the default setting of SystemInit() function, refer to

system_stm32f4xx.c file

*/

/* Unlock the Flash Program Erase controller */

FLASH_Unlock();

/* EEPROM Init */

EE_Init();


/* --- Store successively many values of the three variables in the EEPROM ---*/

/* Store 10 values of Variable1 in EEPROM */

for

(VarValue = 1; VarValue <= 10; VarValue++)

{

EE_WriteVariable(VirtAddVarTab[0], VarValue);

}

/* read the last stored variables data*/

EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);


/* Store 20 values of Variable2 in EEPROM */

for

(VarValue = 1; VarValue <= 20; VarValue++)

{

EE_WriteVariable(VirtAddVarTab[1], VarValue);

}

/* read the last stored variables data*/

EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);

EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);


/* Store 40 values of Variable3 in EEPROM */

for

(VarValue = 1; VarValue <= 40; VarValue++)

{

EE_WriteVariable(VirtAddVarTab[2], VarValue);

}

/* read the last stored variables data*/

EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);

EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);

EE_ReadVariable(VirtAddVarTab[2], &VarDataTab[2]);

while

(1);

}

With this code, I was trying to test reliability & correctness when there is overflow from page0 to page1 and page1 to page0. page size is 16kb or 0x4000. page0 start address is 0x08008000& page1 start address is 0x0800C000. Case 1:page0 to page1 Case 2:page1 to page0 I use ST-Link Utility tool to see the FLASH memory contents. I found Case 1 is working fine. But not Case 2. Here is properly written elements for verification. 0690X0000060597QAA.png Case 1: 0690X00000604OWQAY.png The following image shows the contents of page1 ( page0 now erased). The latest values of 0x5555 & 0x6666 are retained properly from page0. We can see the continuation of variables in page1 of virtual address 0x77 0690X0000060592QAA.png Case 2: 0690X000006053yQAA.png The following image shows the contents of page0 ( page 1 now erased). The latest values of 0x5555 & 0x6666 are retained properly from page1.We can see 2 retained variables 555000A and 66660014, 39th written variable 77770 After them, we should have 40th variable 77770 But it has not been written. I guess there is some coding issue. 0690X000006056JQAQ.png I tested Case 1 and Case 2 again once more, I found Case 2 exhibits the same problem described here.Where is it going wrong ? @clive1: I understand the problems with this emulation stuff, but I desperately need it in my project.
harinath
harinathAuthor
Associate III
July 31, 2014
Posted on July 31, 2014 at 08:01

I have observed several times, the for loop is getting terminated in Case 2.

For example, lets say, now we are in third for loop, found that page1 is full when trying to write 38th variable, The page transfer should happen.

During this page transfer, first page0 header is written with REVEIVE_DATA, then 38th variable is written to page0. And finally copies the updated values of variables from page1. 

Then erase the page1, set the page status VALID_PAGE.

At this point we will return back to for loop, and we should still be in the for loop to write the rest of variables ( 39th and 40th), but its getting terminated due to some reason, Don't know why ?

harinath
harinathAuthor
Associate III
July 31, 2014
Posted on July 31, 2014 at 09:13

Replying for myself.

I did step by step debug in IAR, watched flash memory for Case 2. There was no problem, everything works ok. 

0690X000006059CQAQ.png

0690X000006059MQAQ.png

But WHY there is problem when running stand alone ?

Do we need any delay after the sector erase ? too confused !
harinath
harinathAuthor
Associate III
July 31, 2014
Posted on July 31, 2014 at 12:39

I cleared the SER, MER and MER, PG bits in FLASH_ProgramHalfWord and FLASH_EraseSector function respectively as proposed

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a//my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Interrupt%20generation%20on%20flash%20writes&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=50

.

But I started getting a new problem.

The remaining data values of for loop are being written in the old page, i.e. page1 after erase.

harinath
harinathAuthor
Associate III
August 1, 2014
Posted on August 01, 2014 at 04:48

Did little more debugging, actually the loop is not getting terminated. But the values are being written to the erased page ( page1) though the page0 marked as VALID_PAGE and page1 ERASED.

Here is FLASH memory contents of Case 2;

See page0

0690X000006059HQAQ.png

See page1

0690X00000604ilQAA.png

I found this behavior is repeatable. As we can see the page1 has ERASED page status, when application runs next time, the page will be erased by EE_Init(); functional call at start.

I'm updating this forum post with care & hoping that someone will reply and suggest any fix.

I'm waiting for EEPROM Emulation application based on STM32Cube package library. Hope that may fix this bug.

Please help, our project has tight schedule.
Tesla DeLorean
Guru
August 1, 2014
Posted on August 01, 2014 at 17:01

I'm updating this forum post with care & hoping that someone will reply and suggest any fix. I'm waiting for EEPROM Emulation application based on STM32Cube package library. Hope that may fix this bug. Please help, our project has tight schedule.

While your presentation is thorough I think you're talking to the wrong audience. I would suggest you push your support concerns through your local ST reps or FAE.

You have all the source to the driver code, you'd perhaps want to dig into that. As I suggested much earlier, it would be more effective for you to manage the Flash yourself, rather than rely on something coded by an intern.

If you need technical staffing to meet

http://www.catb.org/esr/faqs/smart-questions.html#urgent

you might want to seek support from the

http://www.st.com/web/en/support/mcu_design_consultants.html

ST catalogues?
Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
harinath
harinathAuthor
Associate III
August 2, 2014
Posted on August 02, 2014 at 09:55

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 into

EE_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).