2018-03-20 12:55 AM
Hello,
I've encountered a systematic problem with the STM32L151 which I'm finding hard to debug.
We write a bootloader and main image to the flash memory using the ST-Link CLI, and at the same time write some individual configuration data to the internal EEPROM memory. The command usually looks something like this :
C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ST-LINK_CLI.exe -c
-w32 0x8080000 0xaf000c -w32 0x8080004 0x18 -w32 0x8080498 0x0 -w32 0x80804a0 0x0 -P firmwares\bootloader-v1.3.hex -P firmwares\firmware-v0.8.12.hex -V after_programming -Q 1>&2All four operations complete successfully, and after a reset, everything performs as expected (this is what we've been doing on thousands of devices). In some cases though, the MCU gets reprogrammed in-system and it doesn't get powered down before use. It then remains powered on 24/7. The problem here is that in this state, the MCU is unable to write to its own internal EEPROM unless we force a reset. (after that, it works fine).
Obviously, the simple solution is 'do a reset after programming them', but I'd like to know what's actually causing this, since I'm pretty sure some systems are getting stuck in this state on their own, regardless of how they were programmed initially. Is there something in the MCU registers that indicates that the EEPROM is badly initialized, or something like that? Or should I do a test read-modify-check on boot and reset the MCU if that fails?
I'm using the StdPeriph library, v1.3.1 and calling DATA_EEPROM_Unlock() before every write, and DATA_EEPROM_Lock() when finished.
#stm32l1 #st-link #stm32l1-eeprom-nvm2018-03-20 01:59 AM
Update with more information: I can't replicate the bug with the debugger attached, since the bug appears during programming, but I dumped the contents of the FLASH SFRs to UART in both cases.
The difference when the writes fail is that the WRPERR bit is set in the FLASH->SR register even before I attempt to write to the EEPROM. Is it possible that my ST-Link command above is causing a Write Protection error by writing to a wrong address? (as far as I can tell, all the writes succeed, and the addresses are 32-bit aligned)
2018-03-20 05:01 AM
Second update:
The problem seems to be occurring within a loop where we do something like this: (simplified a little by replacing some constants and structs)
// EEPROMTableStart refers to an array in a struct, it starts at 0x8080114 uint32_t zeroes = 0;
uint8_t i, j, status;for (j = 0; j < 68; j++) { for (i = 0; i < 3; i++) { status = DATA_EEPROM_ProgramWord((uint32_t) (&EEPROMTableStart[j])+(i*4), zeroes); if (status != FLASH_COMPLETE) { return ERROR; // <<< Problem here, status == FLASH_ERROR_WRP with j = 4 } } }The strange part (to me) is that this loop fails, not on the first iteration, but on the fourth, writing to 0x8080144.
But this ONLY happens when I've just erased the EEPROM using the ST-Link :
ST-LINK_CLI.exe -c -SE ed1 -Q
When I do this, the program will return an ERROR, on the first boot. All subsequent boots are fine. Call the EEPROM erase command above, error. Reset MCU, no error.
If I have the debugger connected, it doesn't always fail, but if not, it fails systematically on the first boot after an EEPROM erase.
2018-03-20 05:16 AM
And another update:
In the code I posted above, I had DATA_EEPROM_Unlock and DATA_EEPROM_Lock surrounding the outer loop.
I moved those calls to between the two loops, and the bug no longer appears.
As far as I can tell, I'm not calling EEPROM_Lock from anywhere with an interrupt. What could be causing this? I couldn't see any mention in the manual (RM0038) of a timeout for DATA_EEPROM_Unlock or a max number of writes before having to unlock again... what could I be missing?
2018-03-22 03:37 AM
I ended up fixing the problem : during the long loop of writing to the EEPROM, we had an interrupt that was performing a write to EEPROM, and locking it after it was done.