cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_QSPI_Abort Race Condition

jjurack
Associate

When calling HAL_QSPI_Abort() to disable memory mapped mode, with the memmap timeout active, I find that there is a race condition that can cause the abort to fail when it should not. If the memmap timeout happens after the abort function's check of the busy flag, but before it can write to the abort bit, the TC flag will never be set and the abort function will wait for the configured qspi timeout, then return an error.

I am testing this on a STM32F769I-DISCO board.

I have found that the following patch will fix the issue:

 

diff --git a/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c b/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c
index 8404466..01a06ca 100644
--- a/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c
+++ b/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c
@@ -2381,19 +2381,19 @@ HAL_StatusTypeDef HAL_QSPI_Abort(QSPI_HandleTypeDef *hqspi)
       /* Configure QSPI: CR register with Abort request */
       SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT);
       
-      /* Wait until TC flag is set to go back in idle state */
-      status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, hqspi->Timeout);
+      /* Race Condition: If BUSY becomes reset before ABORT, TC will not be set. So don't wait for it here, just clear it later if it was set. */
       
-      if (status == HAL_OK)
-      {
-        __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
-        
-        /* Wait until BUSY flag is reset */
-        status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout);
-      }
+      /* Wait until BUSY flag is reset */
+      status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout);
 
       if (status == HAL_OK)
       {
+        /* Clear TC flag if it got set during the abort */
+        if (__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_TC) != RESET)
+        {
+          __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+        }
+        
         /* Reset functional mode configuration to indirect write mode by default */
         CLEAR_BIT(hqspi->Instance->CCR, QUADSPI_CCR_FMODE);
         

 

0 REPLIES 0