Skip to content

Fix EEPROM Emulation caching issue on Cortex-M4#186

Open
OrlandoEduardo101 wants to merge 1 commit into
Ultrawipf:masterfrom
OrlandoEduardo101:fix/eeprom-cache
Open

Fix EEPROM Emulation caching issue on Cortex-M4#186
OrlandoEduardo101 wants to merge 1 commit into
Ultrawipf:masterfrom
OrlandoEduardo101:fix/eeprom-cache

Conversation

@OrlandoEduardo101

Copy link
Copy Markdown

Description of the Issue:
Users compiling with newer toolchains (e.g. GCC 13/15) or running on certain STM32F407 hardware were experiencing an issue where saving configurations failed silently. The Configurator/UI reported "Save in flash: OK", but after a reboot, the settings reverted to their defaults.

Root Cause:
The STMicroelectronics EEPROM Emulation library (eeprom.c) uses consecutive flash reads during EE_VerifyPageFullWriteVariable to find an empty slot (0xFFFFFFFF) in the active flash page.
However, on processors with an ART Data Cache (like Cortex-M4/M7), these reads can get cached. If the flash sector was recently erased (or formatted), the memory reads inside the EE_ReadVariable loop result in the CPU aggressively caching empty or stale data values.
When EE_VerifyPageFullWriteVariable attempts to write later, the cached (stale) data is read back instead of the actual physical flash data. Because it doesn't see 0xFFFFFFFF, the library incorrectly assumes the page is completely full (PAGE_FULL error). The write is silently skipped and dropped.

The Solution:
To resolve this desynchronization between the physical flash and the CPU Data Cache during In-Application Programming (IAP), we explicitly flush/invalidate the data cache right before calling EE_WriteVariable().

  • Flash_InvalidateDataCache() now correctly wraps the write operation (before and after).
  • This ensures the CPU fetches the actual flash transistor state when scanning for empty slots.
  • This aligns with STMicroelectronics recommendations in AN3969 for EEPROM Emulation on STM32F4.
    Safety and Regressions:
  • For processors without a Data Cache (e.g. Cortex-M0/M0+), the __HAL_FLASH_DATA_CACHE_DISABLE macro is naturally undefined by the ST HAL, so the cache clearing function compiles to an empty, harmless operation.
  • The performance impact on high-end MCUs is negligible, as EEPROM writes are extremely rare (only triggered on manual save) and flash programming delays natively dwarf any cache-miss penalty.
  • The original code already invoked Flash_InvalidateDataCache() immediately after the write operation; adding it before simply guarantees a clean slate for the pre-write reads.

@Ultrawipf

Copy link
Copy Markdown
Owner

Hm interesting theory.
Please rebase it on master as it seems like there are some conflicts and changes in lines that shouldn't be affected by this change.

But to my knowledge this issue only happens in new chips from specific factories and never occurs again after a few erase cycles indicating to me that it may have something to do with the physical flash itself possibly not erasing/initializing properly. If it was just the cache i would expect it to happen randomly instead.
It is pretty much always only in new and unused chips.

But it shouldn't hurt to invalidate the cache for writing if it is a cache critical operation then.

__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGAERR);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGPERR);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);
Flash_InvalidateDataCache(); // Invalidate before writing because EE_ReadVariable just cached the flash page

@Ultrawipf Ultrawipf Jun 13, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of invalidating both before and after the write only disable before writing and reset and reenable after writing. Or does it make sense to keep the cache active during the access?

The most likely cause is probably the init section if it occurs with fresh chips that have not been erased properly yet.

@OrlandoEduardo101

Copy link
Copy Markdown
Author

Thanks! I have rebased the PR on master and removed the unrelated changes as requested. The commit message was also updated to provide a more detailed technical explanation of the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants