mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-06-08 18:52:46 +08:00
Backport:stm32_flash changes from upsteam
PX4 contrib from <jose.souza@intel.com> 1) stm32: Fix erase sector number for microcontrolers with more than 11 sectors Erase a sector from the second bank cause the bit 4 of SNB being set but never unsed, so trying to erase a sector from the first bank was acually eraseing a sector from the second bank. 2) stm32: Make up_progmem thread safe Writing to a flash sector while starting the erase of other sector have a undefined behavior so lets add a [staticaly initalized] semaphore and syncronize access to Flash registers. 3) Add workaround for flash data cache corruption on read-while-write This is a know hardware issue on some STM32 see the errata of your model and if you make use of both memory banks you should enable it. 4) Greg's cleanup 5) PX4 clean up stm32_flash:Need conditional on non F4 targets
This commit is contained in:
committed by
Julian Oes
parent
8810f70fdc
commit
5c6264ae35
@@ -0,0 +1,216 @@
|
||||
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..3b4ebd8 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
|
||||
+
|
||||
+/************************************************************************************
|
||||
+ * 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,18 @@ 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))
|
||||
{
|
||||
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 +315,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 +377,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 +415,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;
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
diff --git NuttX/nuttx/arch/arm/src/stm32/Kconfig NuttX/nuttx/arch/arm/src/stm32/Kconfig
|
||||
index b6c0458649..d9fb0aeaa2 100644
|
||||
--- NuttX/nuttx/arch/arm/src/stm32/Kconfig
|
||||
+++ NuttX/nuttx/arch/arm/src/stm32/Kconfig
|
||||
@@ -2514,6 +2514,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 NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c
|
||||
index 73f1419506..fd0b05d624 100644
|
||||
--- NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c
|
||||
+++ NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c
|
||||
@@ -294,6 +294,37 @@ ssize_t up_progmem_ispageerased(size_t page)
|
||||
return bwritten;
|
||||
}
|
||||
|
||||
+#if defined(CONFIG_STM32_FLASH_WORKAROUND_DATA_CACHE_CORRUPTION_ON_RWW)
|
||||
+static void data_cache_disable(void)
|
||||
+{
|
||||
+ uint32_t value = getreg32(STM32_FLASH_ACR);
|
||||
+
|
||||
+ if (value & FLASH_ACR_DCEN)
|
||||
+ {
|
||||
+ value &= ~FLASH_ACR_DCEN;
|
||||
+ putreg32(value, STM32_FLASH_ACR);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void data_cache_enable(void)
|
||||
+{
|
||||
+ uint32_t value = getreg32(STM32_FLASH_ACR);
|
||||
+ if (value & FLASH_ACR_DCEN)
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* reset data cache */
|
||||
+ value |= FLASH_ACR_DCRST;
|
||||
+ putreg32(value, STM32_FLASH_ACR);
|
||||
+
|
||||
+ /* enable data cache */
|
||||
+ value = getreg32(STM32_FLASH_ACR);
|
||||
+ value |= FLASH_ACR_DCEN;
|
||||
+ putreg32(value, STM32_FLASH_ACR);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
|
||||
{
|
||||
uint16_t *hword = (uint16_t *)buf;
|
||||
@@ -327,6 +358,10 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
|
||||
|
||||
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);
|
||||
|
||||
#if defined(CONFIG_STM32_STM32F40XX)
|
||||
@@ -358,6 +393,10 @@ 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
|
||||
return written;
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
diff --git NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c
|
||||
index 73f1419..9ac38a1 100644
|
||||
--- NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c
|
||||
+++ NuttX/nuttx/arch/arm/src/stm32/stm32_flash.c
|
||||
@@ -231,12 +231,14 @@ ssize_t up_progmem_erasepage(size_t page)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
- /* Get flash ready and begin erasing single page */
|
||||
-
|
||||
+#if !defined(CONFIG_STM32_STM32F40XX)
|
||||
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
+#endif
|
||||
+
|
||||
+ /* Get flash ready and begin erasing single page */
|
||||
|
||||
stm32_flash_unlock();
|
||||
|
||||
@@ -318,12 +320,14 @@ ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
- /* Get flash ready and begin flashing */
|
||||
-
|
||||
+#if !defined(CONFIG_STM32_STM32F40XX)
|
||||
if (!(getreg32(STM32_RCC_CR) & RCC_CR_HSION))
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
+#endif
|
||||
+
|
||||
+ /* Get flash ready and begin flashing */
|
||||
|
||||
stm32_flash_unlock();
|
||||
|
||||
Reference in New Issue
Block a user