Skip to main content
Marco S
Associate III
September 4, 2017
Question

How to save a variable in non-volatile memory?

  • September 4, 2017
  • 7 replies
  • 19490 views
Posted on September 04, 2017 at 09:49

Hello,

I'm using a STM32F091VBTx microcontroller and for the application I'm implementing I need a variable to be constantly updated and it must be stored in a non-volatile memory in order to keep its value even if the microcontroller resets. I've found AN2594 about EEPROM emulation, but the functions described there are not available for the microcontroller I'm using. Should I use the functions provided in the stm32f0xx_hal_flash.c file? If yes, I would like to know if there is a demo software for this or if there is any other method to update values in a non-volatile memory.

Thanks.

#stm32f091vb #variable #non-volatile #memory #eeprom-emulation

Note: this post was migrated and contained many threaded conversations, some content may be missing.
This topic has been closed for replies.

7 replies

Jeroen3
Senior
September 4, 2017
Posted on September 04, 2017 at 10:25

Often changing variables are not recommended to be stored in FLASH.

Writing on-chip FLASH has a significant performance penalty*, and it will wear out relatively quickly.

I limit my use cases for using on-chip flash to configurations and bootloaders only. Both are use cases when the chip is not performing it's critical task.

If you have a variable that you need to keep, I recommend using the backup registers or external EEPROM or FRAM.

Depending on the frequency you want to update the variable with you can decide if the durability of EEPROM is sufficient, else you can use FRAM which will last forever. (10 trillion writes)

*up to 40 millisecond halt for erase, endurance of 'only' 10 kcycles.

Marco S
Marco SAuthor
Associate III
September 4, 2017
Posted on September 04, 2017 at 11:26

Thanks for your answer Jeroen3, I will keep your recommendation in mind for future developments of the project I'm working on. Unfortunately, by the moment I'm limited to use the on-chip Flash, so I'm trying to find a way to save there the variable which value I need to keep even if the MCU is powered off.

AvaTar
Senior III
September 4, 2017
Posted on September 04, 2017 at 12:38

Agreeing with Jeroen3, I see three options.

  •  backup registers, + a battery
  •  proper external non-volatile memory (FRAM, EEPROM)
  •  magic

Albeit bean-counting project managers and sales people love option 3, it never worked up to now ...

Danish1
Lead III
September 4, 2017
Posted on September 04, 2017 at 14:22

You can have a variable keep its value if the microcontroller resets. All you need do is convince the start-up code put in by the compiler not to put a default value in there.

With Rowley Crossworks I put load = 'No' into the section placement file. So I'd declare my variable e.g.

int preservedVariable __attribute__((section('.persistent')));

and have this line in the section-placement file:

<ProgramSection alignment='4' load='No' name='.persistent'/>

I'm not sufficiently-familiar with other development environments to say how you'd do it with them.

Of course the variable is volatile and at power-on-reset or other severe crash the value is junk. You can tell if you're at a power-on-reset by looking at RCC->CSR

Hope this helps,

Danish

Marco S
Marco SAuthor
Associate III
September 4, 2017
Posted on September 04, 2017 at 16:46

Hello Danish, thanks for your answer. About this line:

<ProgramSection alignment='4' load='No' name='.persistent'/>

Is this to be added in the block SECTIONS of the *.ld file?

Danish1
Lead III
September 5, 2017
Posted on September 05, 2017 at 10:19

I only know what I have to do to tell my Integrated Debugging Environment (IDE) not to load the variable. I think this translates to (NOLOAD) in the *.ld file. Inside SECTIONS I see:

  __persistent_load_start__ = ALIGN(__DATA_SRAM_segment_start__ , 4);

  .persistent ALIGN(__DATA_SRAM_segment_start__ , 4) (NOLOAD) : AT(ALIGN(__DATA_SRAM_segment_start__ , 4))

  {

    __persistent_start__ = .;

    *(.persistent .persistent.*)

  }

  __persistent_end__ = __persistent_start__ + SIZEOF(.persistent);

  __persistent_size__ = SIZEOF(.persistent);

  __persistent_load_end__ = __persistent_end__;

  . = ASSERT(__persistent_start__ == __persistent_end__ || (__persistent_end__ >= __DATA_SRAM_segment_start__ && __persistent_end__ <= __DATA_SRAM_segment_end__) , 'error: .persistent is too large to fit in DATA_SRAM memory segment');

 - Danish

Brian TIDAL
Technical Moderator
September 4, 2017
Posted on September 04, 2017 at 19:37

Hi Marco,

you may find some interesting things in

http://www.st.com/content/ccc/resource/technical/document/application_note/2e/d4/65/6b/87/dd/40/25/DM00049914.pdf/files/DM00049914.pdf/jcr:content/translations/en.DM00049914.pdf

EEPROM emulation in STM32F0xx microcontrollers.

Regards

Bruno

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Marco S
Marco SAuthor
Associate III
September 5, 2017
Posted on September 05, 2017 at 10:07

Hello Bruno. Thanks, I had already read this document before. In my HAL library there are not files

`

eeprom.h

`

or

`

eeprom.c

`

; what I have as headers are

`

stm32f0xx_hal_flash.h

`

and `stm32f0xx_hal_flash_ex.h

` with their respective `*.c` files. Could you please show me where to download the programs described in the example of AN4061 and if de `eeprom.h` and `eeprom.c` files have any equivalence with `

stm32f0xx_hal_flash.h

`

and `

stm32f0xx_hal_flash_ex.h

`

?

Thanks.

Jeroen3
Senior
September 5, 2017
Posted on September 05, 2017 at 10:18

You need to login to your ST account, then at the bottom of the page for AN4061 (STSW-STM32117) there is a 'get software' button.

https://my.st.com/content/my_st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32-standard-peripheral-libraries-expansions/stsw-stm32117.html

But here is a non-login mirror:

https://dl.dropbox.com/s/405gtzqb9ppe9ae/en.stm32f0_eeprom_emulation.zip

Eugene Solo
Associate III
September 7, 2017
Posted on September 07, 2017 at 10:28

thats why i dont undedrstand ST's idea about not implementing embedded EEPROM array into stm32 chips - it may be not everyones need, but really useful feature when you need to configure your device somehow, or store some data in persisent storage..

and thats why im forced to use external EEPROM or Flash chips. Serial flash/eeproms are really cheap these days, but they consume some pins and, in some cases, occupied area can be critical issue too. Anyway, embedded or not, dedicated hardware helps to avoid software quirks.

Jeroen3
Senior
September 7, 2017
Posted on September 07, 2017 at 11:29

EEPROM is the same as flash, it has the same disadvantages, except smaller erase blocks. 

You can use two flash pages for simple non volatile storage, eeprom isn't much better for that purpose.

Eugene Solo
Associate III
September 7, 2017
Posted on September 07, 2017 at 11:36

EEPROM generally have more endurance, 100k+ erase cycles or more.

And I know embedded MCUs with byte-wide EEPROM blocks, you dont need to erase *block* to write new value, all you need is to write value. Dedicated storage is more flexible solution anyway.

Lorne Vaasjo
Associate II
September 7, 2017
Posted on September 07, 2017 at 14:59

I suggest writing the value(s) at successive locations in a sector.  When you startup scan through to the last one.  That way you should not need to erase very often.  You can adjust the maximum size of flash used so that you stay well below the endurance limit.  If you want to use 'ping-pong' sectors then put a sequence number at the start of the log so you know which one is the newest if you detect both of them active at startup.

Tesla DeLorean
Guru
September 8, 2017
Posted on September 08, 2017 at 21:54

Basically journalling.

I'd strongly advise against using EEPROM emulation, better to understand the medium you're writing too and adapt to that, than apply a paradigm that isn't appropriate and be surprised when it combines the flaws of both.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Dan Mackie
Associate III
September 7, 2017
Posted on September 07, 2017 at 16:01

Marco - did you get your issue resolved?  I did a file compare with the AN4061 version for the F091,  against what I am using for our Nucleo-F429- found in projects>stm32f429zi-nucleo>applications>eeprom etc, and the files are different, but the principal entry points for reading and writing your own data seem to be the same.  I just implemented ST's eeprom.c in our applications for the F429 this week.  A comment from Clive One was useful in terms of a modification to the .LD file.  I am not using his comment yet, as the application does not seem to load into the target area used by eeprom.c to date.  In any case, read and write, and read at boot time are working so far to implement a 'non-volatile ram' concept.  I deliberately do not preserve all of my data tables, just items that are critical, and since these items are user setpoints, they will rarely change, but I want them preserved across power fails.  Trying to duplicate the full memory of 128K SRAM being preserved with data being changed at machine speeds which we had on Intel/Innovasic architecture before moving to the Nucleo-F429 is not likely until we implement our own board, or ST improves the Nucleo significantly.

mailto:Dan.Mackie@DrSCADA.com

Marco S
Marco SAuthor
Associate III
September 7, 2017
Posted on September 07, 2017 at 17:35

Dan, I haven't solved the issue yet. I used the `eeprom.c` example shown in `en.stm32cubef0\STM32Cube_FW_F0_V1.8.0\Projects\STM32F091RC-Nucleo\Applications\EEPROM\EEPROM_Emulation` which uses HAL library. I'm trying to keep just one variable by using the `eeprom.h` functions to write the value and I lose the information after a reset or after a power off of the board. I'm checking if maybe I'm using wrong addresses. I have not modified the *.ld file.

Dan Mackie
Associate III
September 7, 2017
Posted on September 07, 2017 at 18:32

I am using eeprom.c/.h almost unmodified – I had to add an entry point to load my own address tags for data that I wanted to save. Their idea of three only values, with address tags of 5555, 6666, and 7777 was not quite what suited my interest. Ensure that the target address is within the flash address space, and not occupied by your own code, and see what you get. What are you using for a development system? I am using Raisonance. I wrote a wrapper module to do the calls to EE_WriteVariable and EE_ReadVariable, so I would use the read on boot, and the write otherwise, and keep all the HAL type calls within an interface layer that can be replaced or re-written as porting may require. Note that ReadVariable needs a pointer, and WriteVariable does not. If I can help, let me know.

Dan

jim23
Visitor II
September 7, 2017
Posted on September 07, 2017 at 17:09

If you do implement saving a critical variable to non-volatile memory, you should also use a checksum,crc or write ones compliment. This way after a power off/on cycle you can detect if the power off occurred during the data write cycle. Small chance of this but I assure you that it will happen sometimes.

AvaTar
Senior III
September 11, 2017
Posted on September 11, 2017 at 14:07

Small chance of this but I assure you that it will happen sometimes.

This matches with my experiences. And, assuming a commercial project, those will be field returns from angered customers...

You might contemplate you requirements and project suppositions again.

I have been through a design that detected mains-off events, and performed a full parameter save from the remaining charge of it's power supply main cap (an electrolytic cap).

It worked - most of the times ...

You need to find the proper costs/safety tradeoff for your project.

Dan Mackie
Associate III
September 11, 2017
Posted on September 11, 2017 at 14:39

Most of the time?? I'd hope we can do better than that. Seems to me that in a battery/solar system, allowing saves of critical parameters to happen only when voltage is above a safety level measured by the a/d should guarantee operations except for human intervention cases, and it should be easy to manage that with on board leds to indicate 'power off allowed' or not, and suitable 'pending save/power off not allowed' warning light patterns. Unfriendly human intervention is enough to kill most any system, depending on the level of animosity and education, so there is usually not much point planning for that. Comments??

Sent from my Samsung device