# Asynchronous write to EEPROM

There is Stm32l052 with built-in EEPROM (2k). 4 ADC channels are used, data is collected by the trigger every 40 microseconds. Data from the ADC is processed in the interrupt (determined by the output of values beyond the boundaries). So, using the standard Hal libraries during recording in EEPROM points are lost (3 milliseconds standard write speed in EEPROM data), even if you write one byte from the ring buffer. Is there any way to get the controller to write to the EEPROM asynchronously without blocking the ADC interrupts?

• What are you actually trying to accomplish here? EEPROM (regardless if internal or external) is unlikely to be a fit for your actual need, unless it is a fairly infrequent usage. You may just want to capture the data to RAM - either and then write it to EEPROM, or keep it in RAM alone if it is short lived. You should generally think of the internal EEPROM as a notepad to keep small amounts of information, not really an overflow memory or place to store dynamic data like you would get from an ADC. – Chris Stratton Nov 13 '18 at 13:42
• @ChrisStratton A ring buffer in RAM is implied in the question. As I understand it, only out-of bounds data should make it to permanent storage, i.e. the eeprom is used as an error log, to store more or less infrequent events. – berendi - protesting Nov 13 '18 at 14:01
• Looks like the EEPROM is just a partitioned part of FLASH, so the whole memory stalls for 4mS while you are writing. I imagine this is the issue you are talking about. Not easy to fix. You'll probably have to relocate the ISR table and handler to RAM (making sure you don't call library routines in FLASH - including things like floating point math). The better solution would be an external EEPROM. – Jon Nov 13 '18 at 14:31

STM32L052 appears to have a single bank NVM controller, therefore a write access to any EEPROM address would block data reads and fetches from flash.

It would work only if you can relocate all relevant code, except initialization, but including the vector table, to RAM. It would be quite a challenge to do in 8 kbytes, but it might work. Forget about HAL, it has too much overhead and complexity.

I'd recommend doing it this way:

• Relocate NVIC to RAM
• ADC interrupt handler in RAM, puts data in the ring buffer, invokes PendSV (SCB->ICSR=SCB_ICSR_PENDSVSET).
• PendSV fault handler in RAM, as long as there is data to be written, puts a single 32 bit word† in EEPROM, and waits until the write completes. Do not return while NVM is still busy.
• ADC handler should have higher priority as PendSV.
• The rest of the code can be left in flash as long as the delay is acceptable. Interrupt handlers in flash should have lower priorities than PendSV.

This arrangement would prevent any code in flash from running as long as an EEPROM write is in progress, but lets higher priority handlers run as long as they do not touch nonvolatile memory.

To relocate a function to RAM

With gcc, use __attribute__((section(".data"))) in the function declaration. Do it recursively to each function it calls. Use -ffreestanding to prevent gcc from generating calls to library functions unexpectedly. The .data section will be copied from flash to RAM after reset, along with initialized variables, by the startup code.

To relocate the vector table

The vector table of the STM32L052 is 192 bytes long (Reference manual 12.3 Interrupt and exception vectors). I'd just move the beginning of RAM up by 192 bytes in the linker script

RAM (xrw) : ORIGIN = 0x200000C0, LENGTH = 8000 /* 8192 - 192 */


copy the vector table there, and set the vector table pointer

memcpy((void*)0x20000000, (void*)0x08000000, 192);
SCB->VTOR = 0x20000000;


before any interrupt is enabled.

Using STM32L072 instead, it would be possible to let the program run from Bank 1, and placing EEPROM data in Bank 2, they would not interfere with each other. Of course it would still take 3 ms (or 6 ms if it's not empty) to write a 32 bit word† into EEPROM, attempting to write more data before the first write is completed would still block program execution until the first one completes. Check the Reference manual for the bank layout (3.3.1 NVM Organization)

† AFAIK EEPROM data is written in 32 bit units, writing 1 or 2 bytes at a time takes just as much time as writing a full 4-byte word.