You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/01/26 14:58:12 UTC

[incubator-nuttx] branch master updated: STM32L4: Add workaround of data cache corruption on RWW.

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 705ac84  STM32L4: Add workaround of data cache corruption on RWW.
705ac84 is described below

commit 705ac844320de70b61a3fe54687877c12a391b53
Author: Satoshi Togawa <to...@develcb210.centurysys.co.jp>
AuthorDate: Sun Jan 26 08:57:12 2020 -0600

    STM32L4: Add workaround of data cache corruption on RWW.
    
    Author: Gregory Nutt <gn...@nuttx.org>
    
        Run .c modified by the PR through tools/nxstyle and correct all reporting coding style problems noted in the file.
    
    Author: Satoshi Togawa <to...@develcb210.centurysys.co.jp>
    
        STM32L4: Add workaround of data cache corruption on RWW.
    
        Some STM32L4 chips has eratta "Data cache might be corrupted during Flash Read While Write operation". This is also in STM32, and arch/arm/src/stm32/stm32f20xxf40xx_flash.c has workaround.
    
        To enable this workaround, define CONFIG_STM32L4_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW.
---
 arch/arm/src/stm32l4/Kconfig         |  9 ++++
 arch/arm/src/stm32l4/stm32l4_flash.c | 79 ++++++++++++++++++++++++++----------
 2 files changed, 67 insertions(+), 21 deletions(-)

diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig
index d5e5bda..3b02a97 100644
--- a/arch/arm/src/stm32l4/Kconfig
+++ b/arch/arm/src/stm32l4/Kconfig
@@ -1657,6 +1657,15 @@ config STM32L4_FLASH_PREFETCH
 	---help---
 	Enable FLASH prefetch
 
+config STM32L4_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW
+	bool "Workaround for FLASH data cache corruption"
+	default n
+	depends on STM32L4_STM32L475XX || STM32L4_STM32L476XX || STM32L4_STM32L486XX || STM32L4_STM32L496XX || STM32L4_STM32L4A6XX
+	---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.
+
 config STM32L4_DISABLE_IDLE_SLEEP_DURING_DEBUG
 	bool "Disable IDLE Sleep (WFI) in debug mode"
 	default n
diff --git a/arch/arm/src/stm32l4/stm32l4_flash.c b/arch/arm/src/stm32l4/stm32l4_flash.c
index 170ec89..633d79f 100644
--- a/arch/arm/src/stm32l4/stm32l4_flash.c
+++ b/arch/arm/src/stm32l4/stm32l4_flash.c
@@ -1,4 +1,4 @@
-/************************************************************************************
+/****************************************************************************
  * arch/arm/src/stm32l4/stm32l4_flash.c
  *
  *   Copyright (C) 2011 Uros Platise. All rights reserved.
@@ -33,10 +33,10 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
-/* Provides standard flash access functions, to be used by the flash mtd driver.
- * The interface is defined in the include/nuttx/progmem.h
+/* Provides standard flash access functions, to be used by the flash mtd
+ * driver.  The interface is defined in the include/nuttx/progmem.h
  *
  * Notes about this implementation:
  *  - HSI16 is automatically turned ON by MCU, if not enabled beforehand
@@ -44,9 +44,9 @@
  *  - Low Power Modes are not permitted during write/erase
  */
 
-/************************************************************************************
+/****************************************************************************
  * Included Files
- ************************************************************************************/
+ ****************************************************************************/
 
 #include <nuttx/config.h>
 #include <nuttx/arch.h>
@@ -72,9 +72,9 @@
 #  warning "Flash Configuration has been overridden - make sure it is correct"
 #endif
 
-/************************************************************************************
+/****************************************************************************
  * Pre-processor Definitions
- ************************************************************************************/
+ ****************************************************************************/
 
 #define FLASH_KEY1         0x45670123
 #define FLASH_KEY2         0xCDEF89AB
@@ -107,16 +107,16 @@
 #  define MIN(a, b)        ((a) < (b) ? (a) : (b))
 #endif
 
-/************************************************************************************
+/****************************************************************************
  * Private Data
- ************************************************************************************/
+ ****************************************************************************/
 
 static sem_t g_sem = SEM_INITIALIZER(1);
 static uint32_t g_page_buffer[FLASH_PAGE_WORDS];
 
-/************************************************************************************
+/****************************************************************************
  * Private Functions
- ************************************************************************************/
+ ****************************************************************************/
 
 static inline void sem_lock(void)
 {
@@ -187,9 +187,27 @@ static inline void flash_erase(size_t page)
   modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PAGE_ERASE, 0);
 }
 
-/************************************************************************************
+#if defined(CONFIG_STM32L4_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW)
+static void data_cache_disable(void)
+{
+  modifyreg32(STM32L4_FLASH_ACR, FLASH_ACR_DCEN, 0);
+}
+
+static void data_cache_enable(void)
+{
+  /* Reset data cache */
+
+  modifyreg32(STM32L4_FLASH_ACR, 0, FLASH_ACR_DCRST);
+
+  /* Enable data cache */
+
+  modifyreg32(STM32L4_FLASH_ACR, 0, FLASH_ACR_DCEN);
+}
+#endif /* defined(CONFIG_STM32L4_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW) */
+
+/****************************************************************************
  * Public Functions
- ************************************************************************************/
+ ****************************************************************************/
 
 void stm32l4_flash_unlock(void)
 {
@@ -370,6 +388,7 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
   size_t xfrsize;
   size_t offset;
   size_t page;
+  bool set_pg_bit = false;
   int i;
   int ret = OK;
 
@@ -447,7 +466,12 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
 
       /* Write the page. Must be with double-words. */
 
+#if defined(CONFIG_STM32L4_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW)
+      data_cache_disable();
+#endif
+
       modifyreg32(STM32L4_FLASH_CR, 0, FLASH_CR_PG);
+      set_pg_bit = true;
 
       for (i = 0; i < FLASH_PAGE_WORDS; i += 2)
         {
@@ -463,20 +487,24 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
 
           if (getreg32(STM32L4_FLASH_SR) & FLASH_SR_WRITE_PROTECTION_ERROR)
             {
-              modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PG, 0);
               ret = -EROFS;
               goto out;
             }
 
-          if (getreg32(dest-1) != *(src-1) || getreg32(dest-2) != *(src-2))
+          if (getreg32(dest -1) != *(src - 1) ||
+              getreg32(dest - 2) != *(src - 2))
             {
-              modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PG, 0);
               ret = -EIO;
               goto out;
             }
         }
 
       modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PG, 0);
+      set_pg_bit = false;
+
+#if defined(CONFIG_STM32L4_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW)
+      data_cache_enable();
+#endif
 
       /* Adjust pointers and counts for the next time through the loop */
 
@@ -489,14 +517,23 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen)
     }
 
 out:
-  /* If there was an error, clear all error flags in status
-   * register (rc_w1 register so do this by writing the
-   * error bits).
+  if (set_pg_bit)
+    {
+      modifyreg32(STM32L4_FLASH_CR, FLASH_CR_PG, 0);
+#if defined(CONFIG_STM32L4_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW)
+      data_cache_enable();
+#endif
+    }
+
+  /* If there was an error, clear all error flags in status register (rc_w1
+   * register so do this by writing the error bits).
    */
 
   if (ret != OK)
     {
-      ferr("flash write error: %d, status: 0x%x\n", ret, getreg32(STM32L4_FLASH_SR));
+      ferr("flash write error: %d, status: 0x%x\n",
+           ret, getreg32(STM32L4_FLASH_SR));
+
       modifyreg32(STM32L4_FLASH_SR, 0, FLASH_SR_ALLERRS);
     }