Lora-net / LoRaMac-node

Reference implementation and documentation of a LoRa network node.
Other
1.88k stars 1.09k forks source link

EEPROM emulation library problems with STM32L4xx single-bank flash configuration #1557

Closed dalbert2 closed 1 year ago

dalbert2 commented 1 year ago

When used on STM32L4xx platforms (and possibly others), with flash configured for single-bank mode, the EEPROM emulation library miscalculates flash sectors which causes silent erase failures.

The stack uses the ST EEPROM emulation library for persistence on ST targets; this uses flash on the target to emulate EEPROM. When porting the stack to a new ST target, the emulated EEPROM must be given a place in the flash memory map; this is done by setting START_PAGE_ADDRESS in boards/myBoard/eeprom_emul_conf.h. In my case, I am using a 512K flash processor (STM32L471) with the flash memory configured as a single contiguous bank so I set the emulated EEPROM start page address to to 0x0806E000 (flash page 220).

This results in a subtle, silent failure. I think this is a bug in the ST EEPROM emulation library that first manifests when the emulated EEPROM is initialized (EEPROM_Emul/Core/eeprom_emul.c: EE_Init(). This calls EEPROM_Emul/Porting/STM32L4/flash_interface.c: Page_Erase() which calls GetBankNumber(). That function should consider whether flash is configured in single or dual bank mode, but simply assumes dual-bank mode resulting in the wrong sector(s) being erased.

The EEPROM emulation library: src/boards/mcu/stm32/EEPROM_Emul/Core/eeprom_emul.h defines:

The real issue (at least for the EEPROM emulation library) is that BANK_SIZE (which evaluates to FLASH_BANK_SIZE defined in HAL) needs to evaluate to the size of flash when in single-bank mode and half of flash when in dual-bank mode. I think the fix is to:

  1. Modify the definition of BANK_SIZE in src/boards/mcu/stm32/EEPROM_Emul/Porting/STM32L4/flash_interface.h to: #define BANK_SIZE ((FLASH->OPTR & FLASH_OPTR_DUALBANK)?FLASH_BANK_SIZE:FLASH_SIZE)
  2. Modify function GetBankNumber() in src/boards/mcu/stm32/EEPROM_Emul/Porting/STM32L4/flash_interface.c to use BANK_SIZE instead of FLASH_BANK_SIZE

I realize this is really a bug in the ST EEPROM emulation library, but because it is included in this code base, I thought it important to report the issue here so others are aware. This may affect more dual-bank-capable ST processors than the one mentioned here.

Why the erase works (but on the wrong sector): ST has a huge number of processor variants and almost certainly doesn't produce that many different types of wafer. So the STM32L471 is likely an STM32L476 with some fuses burnt to identify it as the smaller flash variant and packaging marked accordingly. The STM32L471 parts correctly report their flash size as 512K, but seem to contain 1MB of flash: when you write data to the upper 512K, it will be there after a power cycle and hasn't overwritten anything in the lower 512K. Erasing pages in the upper 512K also seems to work and returns an OK status. However, you can't count on a free 512K...ST may later make wafers that really only have 512K flash or otherwise disable access so you have to code assuming flash matches what is reported by the FLASH_SIZE register.

dalbert2 commented 1 year ago

Another issue is that NvmDataMgmtStore() doesn't handle failures of NvmmWrite(). NvmmWrite() calls EepromMcuWriteBuffer(); if an error such as no active page occurs, returns LMN_STATUS_ERROR which effectively is not handled.

pieterdemil commented 1 year ago

Thanks for reporting it here (we use real EEPROM chips), helpful for the LoRaWAN community.

mluis1 commented 1 year ago

In this project we just use the libraries provided by ST with a specific version. The currently used version of the ST library functionality is enough for this project supported platforms.

Maybe in the mean time ST has produced newer versions of the library which is able to support newer MCU variants. I would recommend to approach ST support.

In our examples we use the EEPROM emulation just as an example. The reason being that the produced firmware binary will work out of the box for the given evaluation kit. No need to have external components.

As @pieterdemil pointed out one should use external real NVM devices (EEPROM, FRAM, etc). The biggest advantage being the maximum number of MCU FLASH erase/write cycles which is much lower than for a real NVM memory.

In the future it would be nice if you could post this kind of questions on the project Discussions tab. It is a better place to engage discussions and then we can agree if it is an issue or not. If you don't mind I move this issue to the Discussions tab.