You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
6.3 KiB
217 lines
6.3 KiB
diff --git NuttX/nuttx/arch/arm/src/stm32/Kconfig NuttX/nuttx/arch/arm/src/stm32/Kconfig |
|
index b6c0458..8ebf8df 100644 |
|
--- NuttX/nuttx/arch/arm/src/stm32/Kconfig |
|
+++ NuttX/nuttx/arch/arm/src/stm32/Kconfig |
|
@@ -2514,6 +2514,14 @@ 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 "Workaround for FLASH data cache corruption" |
|
+ default n |
|
+ ---help--- |
|
+ Enable the workaround to fix flash data cache corruption when reading |
|
+ from one flash bank while writing on other flash bank. See your STM32 |
|
+ errata to check if your STM32 is affected by this problem. |
|
+ |
|
choice |
|
prompt "JTAG Configuration" |
|
default STM32_JTAG_DISABLE |
|
diff --git NuttX/nuttx/arch/arm/src/stm32/chip/stm32_flash.h NuttX/nuttx/arch/arm/src/stm32/chip/stm32_flash.h |
|
index 70e6d62..82d8f09 100644 |
|
--- NuttX/nuttx/arch/arm/src/stm32/chip/stm32_flash.h |
|
+++ NuttX/nuttx/arch/arm/src/stm32/chip/stm32_flash.h |
|
@@ -322,10 +322,11 @@ |
|
# define FLASH_CR_SER (1 << 1) /* Bit 1: Sector Erase */ |
|
# define FLASH_CR_MER (1 << 2) /* Bit 2: Mass Erase sectors 0..11 */ |
|
# define FLASH_CR_SNB_SHIFT (3) /* Bits 3-6: Sector number */ |
|
-# define FLASH_CR_SNB_MASK (15 << FLASH_CR_SNB_SHIFT) |
|
#if defined(CONFIG_STM32_STM32F427) || defined(CONFIG_STM32_STM32F429) |
|
+# define FLASH_CR_SNB_MASK (31 << FLASH_CR_SNB_SHIFT) |
|
# define FLASH_CR_SNB(n) (((n % 12) << FLASH_CR_SNB_SHIFT) | ((n / 12) << 7)) /* Sector n, n=0..23 */ |
|
#else |
|
+# define FLASH_CR_SNB_MASK (15 << FLASH_CR_SNB_SHIFT) |
|
# define FLASH_CR_SNB(n) ((n) << FLASH_CR_SNB_SHIFT) /* Sector n, n=0..11 */ |
|
#endif |
|
# define FLASH_CR_PSIZE_SHIFT (8) /* Bits 8-9: Program size */ |
|
diff --git NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c |
|
index 73f1419..fb1e1ca 100644 |
|
--- NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c |
|
+++ NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c |
|
@@ -47,6 +47,10 @@ |
|
|
|
#include <nuttx/config.h> |
|
#include <nuttx/arch.h> |
|
+ |
|
+#include <stdbool.h> |
|
+#include <semaphore.h> |
|
+#include <assert.h> |
|
#include <errno.h> |
|
|
|
#include "stm32_flash.h" |
|
@@ -81,13 +85,29 @@ |
|
#endif |
|
|
|
/************************************************************************************ |
|
- * Private Functions |
|
+ * Private Data |
|
************************************************************************************/ |
|
|
|
+static sem_t g_sem = SEM_INITIALIZER(1); |
|
+ |
|
/************************************************************************************ |
|
- * Public Functions |
|
+ * Private Functions |
|
************************************************************************************/ |
|
-void stm32_flash_unlock(void) |
|
+ |
|
+static void sem_lock(void) |
|
+{ |
|
+ while (sem_wait(&g_sem) < 0) |
|
+ { |
|
+ DEBUGASSERT(errno == EINTR); |
|
+ } |
|
+} |
|
+ |
|
+static inline void sem_unlock(void) |
|
+{ |
|
+ sem_post(&g_sem); |
|
+} |
|
+ |
|
+static void flash_unlock(void) |
|
{ |
|
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) |
|
{ |
|
@@ -103,14 +123,48 @@ void stm32_flash_unlock(void) |
|
} |
|
} |
|
|
|
-void stm32_flash_lock(void) |
|
+static void flash_lock(void) |
|
{ |
|
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_LOCK); |
|
} |
|
|
|
+#if defined(CONFIG_STM32_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW) |
|
+static void data_cache_disable(void) |
|
+{ |
|
+ modifyreg32(STM32_FLASH_ACR, FLASH_ACR_DCEN, 0); |
|
+} |
|
|
|
-#if defined(CONFIG_STM32_STM32F10XX) || defined(CONFIG_STM32_STM32F30XX) |
|
+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); |
|
+} |
|
+#endif /* defined(CONFIG_STM32_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW) */ |
|
+ |
|
+/************************************************************************************ |
|
+ * Public Functions |
|
+ ************************************************************************************/ |
|
+ |
|
+void stm32_flash_unlock(void) |
|
+{ |
|
+ sem_lock(); |
|
+ flash_unlock(); |
|
+ sem_unlock(); |
|
+} |
|
|
|
+void stm32_flash_lock(void) |
|
+{ |
|
+ sem_lock(); |
|
+ flash_lock(); |
|
+ sem_unlock(); |
|
+} |
|
+ |
|
+#if defined(CONFIG_STM32_STM32F10XX) || defined(CONFIG_STM32_STM32F30XX) |
|
size_t up_progmem_pagesize(size_t page) |
|
{ |
|
return STM32_FLASH_PAGESIZE; |
|
@@ -231,14 +285,19 @@ ssize_t up_progmem_erasepage(size_t page) |
|
return -EFAULT; |
|
} |
|
|
|
- /* Get flash ready and begin erasing single page */ |
|
+ sem_lock(); |
|
|
|
+#if !defined(CONFIG_STM32_STM32F40XX) |
|
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION)) |
|
{ |
|
+ sem_unlock(); |
|
return -EPERM; |
|
} |
|
+#endif |
|
+ |
|
+ /* Get flash ready and begin erasing single page */ |
|
|
|
- stm32_flash_unlock(); |
|
+ flash_unlock(); |
|
|
|
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PAGE_ERASE); |
|
|
|
@@ -257,6 +316,7 @@ ssize_t up_progmem_erasepage(size_t page) |
|
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY) up_waste(); |
|
|
|
modifyreg32(STM32_FLASH_CR, FLASH_CR_PAGE_ERASE, 0); |
|
+ sem_unlock(); |
|
|
|
/* Verify */ |
|
if (up_progmem_ispageerased(page) == 0) |
|
@@ -318,14 +378,23 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count) |
|
return -EFAULT; |
|
} |
|
|
|
- /* Get flash ready and begin flashing */ |
|
+ sem_lock(); |
|
|
|
+#if !defined(CONFIG_STM32_STM32F40XX) |
|
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION)) |
|
{ |
|
+ sem_unlock(); |
|
return -EPERM; |
|
} |
|
+#endif |
|
+ |
|
+ /* Get flash ready and begin flashing */ |
|
+ |
|
+ flash_unlock(); |
|
|
|
- stm32_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); |
|
|
|
@@ -347,17 +416,25 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count) |
|
if (getreg32(STM32_FLASH_SR) & FLASH_SR_WRITE_PROTECTION_ERROR) |
|
{ |
|
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0); |
|
+ sem_unlock(); |
|
return -EROFS; |
|
} |
|
|
|
if (getreg16(addr) != *hword) |
|
{ |
|
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0); |
|
+ sem_unlock(); |
|
return -EIO; |
|
} |
|
} |
|
|
|
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; |
|
} |
|
|
|
|