diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig index de2c8fe23be..72f8a17fbb6 100644 --- a/arch/arm/src/stm32/Kconfig +++ b/arch/arm/src/stm32/Kconfig @@ -2633,6 +2633,12 @@ config STM32_FLASH_PREFETCH on F1 parts). Some early revisions of F4 parts do not support FLASH pre-fetch properly and enabling this option may interfere with ADC accuracy. +config STM32_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW + bool "Enable the workaround to fix flash data cache corruption when reading from one flash bank while writing on other flash bank" + default n + ---help--- + See your STM32 errata to check if your STM32 is affected by this problem. + choice prompt "JTAG Configuration" default STM32_JTAG_DISABLE diff --git a/arch/arm/src/stm32/stm32_flash.c b/arch/arm/src/stm32/stm32_flash.c index 7f0b53ee607..4907aa9f0af 100644 --- a/arch/arm/src/stm32/stm32_flash.c +++ b/arch/arm/src/stm32/stm32_flash.c @@ -130,6 +130,20 @@ static void flash_lock(void) modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_LOCK); } +static void data_cache_disable(void) +{ + modifyreg32(STM32_FLASH_ACR, FLASH_ACR_DCEN, 0); +} + +static void data_cache_enable(void) +{ + /* reset data cache */ + modifyreg32(STM32_FLASH_ACR, 0, FLASH_ACR_DCRST); + + /* enable data cache */ + modifyreg32(STM32_FLASH_ACR, 0, FLASH_ACR_DCEN); +} + /************************************************************************************ * Public Functions ************************************************************************************/ @@ -384,6 +398,10 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count) flash_unlock(); +#if defined(CONFIG_STM32_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW) + data_cache_disable(); +#endif + modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG); #if defined(CONFIG_STM32_STM32F40XX) @@ -417,6 +435,11 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count) } modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0); + +#if defined(CONFIG_STM32_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW) + data_cache_enable(); +#endif + sem_unlock(); return written; }