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

utzig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


The following commit(s) were added to refs/heads/master by this push:
     new b257c71  mcu: kinetis: fix QSPI HW reset race
b257c71 is described below

commit b257c715193c14ff92b279208ffca15eec9476a0
Author: Fabio Utzig <ut...@apache.org>
AuthorDate: Wed Sep 22 18:26:16 2021 -0300

    mcu: kinetis: fix QSPI HW reset race
    
    Lock the OS when calling `QSPI_SoftwareReset`; this API sets bits that
    result in a QSPI HW reset, loops for a while, and manually resets the
    same bits. If a context switch happens while those bits are set, and
    the next task reads the QSPI flash through the AHB mapping, this read
    results in zeroes being returned instead of the expected data.
    
    Also removed a non-required busy wait after the HW reset.
    
    Signed-off-by: Fabio Utzig <ut...@apache.org>
---
 hw/mcu/nxp/kinetis/src/hal_qspi.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/hw/mcu/nxp/kinetis/src/hal_qspi.c 
b/hw/mcu/nxp/kinetis/src/hal_qspi.c
index a9eff8a..66d5ad1 100644
--- a/hw/mcu/nxp/kinetis/src/hal_qspi.c
+++ b/hw/mcu/nxp/kinetis/src/hal_qspi.c
@@ -196,6 +196,7 @@ nxp_qspi_write(const struct hal_flash *dev,
     int32_t remaining;
     uint32_t *src32;
     int i;
+    os_sr_t sr;
 
     align = dev->hf_align;
     if (address % align) {
@@ -263,8 +264,9 @@ nxp_qspi_write(const struct hal_flash *dev,
     }
 
     while (qspi_in_use(QuadSPI0));
+    OS_ENTER_CRITICAL(sr);
     QSPI_SoftwareReset(QuadSPI0);
-    while (qspi_in_use(QuadSPI0));
+    OS_EXIT_CRITICAL(sr);
 
     os_mutex_release(&g_mtx);
 
@@ -274,6 +276,8 @@ nxp_qspi_write(const struct hal_flash *dev,
 static int
 nxp_qspi_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 {
+    os_sr_t sr;
+
     while (qspi_is_busy(QuadSPI0));
 
     os_mutex_pend(&g_mtx, OS_TIMEOUT_NEVER);
@@ -289,7 +293,9 @@ nxp_qspi_erase_sector(const struct hal_flash *dev, uint32_t 
sector_address)
     QSPI_ClearCache(QuadSPI0);
 #endif
 
+    OS_ENTER_CRITICAL(sr);
     QSPI_SoftwareReset(QuadSPI0);
+    OS_EXIT_CRITICAL(sr);
 
     os_mutex_release(&g_mtx);
 
@@ -299,6 +305,8 @@ nxp_qspi_erase_sector(const struct hal_flash *dev, uint32_t 
sector_address)
 void
 nxp_qspi_erase_chip(void)
 {
+    os_sr_t sr;
+
     int chips = (MYNEWT_VAL(QSPIA_ENABLE) ? 1 : 0) +
                 (MYNEWT_VAL(QSPIB_ENABLE) ? 1 : 0);
     uint32_t address;
@@ -320,7 +328,9 @@ nxp_qspi_erase_chip(void)
         QSPI_ClearCache(QuadSPI0);
 #endif
 
+        OS_ENTER_CRITICAL(sr);
         QSPI_SoftwareReset(QuadSPI0);
+        OS_EXIT_CRITICAL(sr);
 
         address += MYNEWT_VAL(QSPI_FLASH_SECTOR_SIZE) *
                    MYNEWT_VAL(QSPI_FLASH_SECTOR_COUNT);
@@ -336,6 +346,7 @@ nxp_qspi_erase(const struct hal_flash *dev,
                uint32_t size)
 {
     uint32_t erased_size;
+    os_sr_t sr;
 
     if (address % MYNEWT_VAL(QSPI_FLASH_SECTOR_SIZE) ||
         size % MYNEWT_VAL(QSPI_FLASH_SECTOR_SIZE)) {
@@ -370,7 +381,9 @@ nxp_qspi_erase(const struct hal_flash *dev,
         size -= erased_size;
     }
 
+    OS_ENTER_CRITICAL(sr);
     QSPI_SoftwareReset(QuadSPI0);
+    OS_EXIT_CRITICAL(sr);
 
     os_mutex_release(&g_mtx);
 

Reply via email to