0
\$\begingroup\$

I want to reserve a space in the internal flash memory of my microcontroller (STM32L4) to store the latest 100 measured values by a sensor (in a circular FIFO Fashion) and be able to load them again when I restart the device.

My logic looks like this:

typedef struct
{
   uint16_t   measuredValue;
   DateTime_t timestamp;
}MeasuredValue_t;
// ..
// ..    
MeasuredValue_t measuredValue;
// ..
// ..
while(1)
{
   GetValue(&measuredValue); // Read values (Sensor value + timestamp from the RTC)
   Flash_Fifo_Push(measuredValue);         // Push to buffer
   Sleep();                               // Sleep until the next cycle
}

My questions are:

  1. How to reserve this space in the linker file of my microcontroller (ARM Cortex-M4 2MB flash)?
  2. How to implement the circular FIFO fashion?
\$\endgroup\$
10
  • \$\begingroup\$ How often do you measure? \$\endgroup\$
    – Jeroen3
    May 23, 2019 at 11:50
  • \$\begingroup\$ Every 15 minutes the whole day \$\endgroup\$
    – Pryda
    May 23, 2019 at 11:51
  • 3
    \$\begingroup\$ You can start by reading this application note: EEPROM emulation techniques and software for STM32L4 and STM32L4+ Series microcontrollers \$\endgroup\$
    – Bora
    May 23, 2019 at 11:51
  • 1
    \$\begingroup\$ @Jeroen3 The write block size is 8 bytes. Assuming 16 bytes/record, a 2 kByte block would be filled in 32 hours. Using two erase blocks, each one would be erased once in 64 hours. That's actually a lifetime of 73 years. \$\endgroup\$ May 24, 2019 at 3:58
  • 1
    \$\begingroup\$ @Jeroen3 That's what the reference manual says. "The Flash memory is programmed 72 bits at a time (64 bits + 8 bits ECC). [...] When the flash interface has received a good sequence (a double word), programming is automatically launched" (ECC is calculated by HW) \$\endgroup\$ May 24, 2019 at 5:51

1 Answer 1

5
\$\begingroup\$

How to reserve this space in the linker file of my microcontroller (ARM Cortex-M4 2MB flash)?

As each linker brand uses it's own linker file format, it's impossible to answer without knowing which toolchain are you using. Generally, look into the linker file, find the flash size (usually at the top), and subtract the size of a few erase blocks.

How to implement the circular FIFO fashion?

The internal flash can be programmed in 8 byte blocks, and erased in 2 kByte blocks. When erased, the contents are set to 0xFF.

Arrange your data in 8 or 16 byte structs, and just start filling the reserved space, and erase the next block. Simply wrap around at the end of the flash. Ensure that a struct with all 0xFF bytes doesn't represent valid data (should be no problem if your timestamp structure can cover at least a few centuries). At powerup, just look for the first invalid record following a valid one to find the head.

Keep in mind that the internal flash is rated only for 10000 erase operations, although it shouldn't be a problem at one sample every 15 minutes.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Note that 10000 erase operations and 15 mins, means just over 100 days. \$\endgroup\$ May 23, 2019 at 12:52
  • 1
    \$\begingroup\$ @MichelKeijzers At 16 bytes/sample, a single flash erase block can hold 128 records, that's more than a day's worth of data. \$\endgroup\$ May 23, 2019 at 13:03
  • \$\begingroup\$ He wants to be able to read the last 100 also after a reset, so you have to store it every time new values are read (every 15 minutes). If that requirement is left out, than indeed you can wait until there is a full buffer to be written. \$\endgroup\$ May 23, 2019 at 13:56
  • 2
    \$\begingroup\$ @MichelKeijzers The full buffer for the purpose of writing is 8 bytes. \$\endgroup\$ May 24, 2019 at 3:31
  • \$\begingroup\$ It seems viable. You would only be doing an erase every ~1.2 days and swapping between blocks. So ~2.4 days between each erase on a block? That would give you something like ~65 years of endurance at 10,000 erase ops. Which is higher than the operating life of the flash memory... \$\endgroup\$
    – hekete
    May 24, 2019 at 4:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.