]> granicus.if.org Git - esp-idf/commitdiff
spi: fix a possible concurrency issue
authorMichael (XIAO Xufeng) <xiaoxufeng@espressif.com>
Fri, 31 May 2019 07:23:10 +0000 (15:23 +0800)
committerMichael (XIAO Xufeng) <xiaoxufeng@espressif.com>
Tue, 11 Jun 2019 05:02:21 +0000 (13:02 +0800)
components/driver/spi_master.c
components/driver/spi_slave.c

index 800d65ef3969bb9d6903d128f5c01c695f93e384..6bfce0b3caa4046493edeb8208e8d25bf10e8ef2 100644 (file)
@@ -539,6 +539,9 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
 
     /*------------ new transaction starts here ------------------*/
     //ToDo: This is a stupidly simple low-cs-first priority scheme. Make this configurable somehow. - JD
+    //Disable interrupt before checking to avoid concurrency issue.
+    esp_intr_disable(host->intr);
+
     for (i=0; i<NO_CS; i++) {
         if (host->device[i]) {
             r=xQueueReceiveFromISR(host->device[i]->trans_queue, &host->cur_trans_buf, &do_yield);
@@ -548,13 +551,14 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
         }
     }
     if (i==NO_CS) {
-        //No packet waiting. Disable interrupt.
-        esp_intr_disable(host->intr);
 #ifdef CONFIG_PM_ENABLE
         //Release APB frequency lock
         esp_pm_lock_release(host->pm_lock);
 #endif
     } else {
+        //enable the interrupt again if there is packet to send
+        esp_intr_enable(host->intr);
+
         host->hw->slave.trans_done=0; //clear int bit
         //We have a transaction. Send it.
         spi_device_t *dev=host->device[i];
index 332977377e271a52c1e13261d69f50a6c52d6f27..a752a1af5007a2dd9cf15717de403d1046775000 100644 (file)
@@ -415,12 +415,14 @@ static void IRAM_ATTR spi_intr(void *arg)
         }
     }
 
+    //Disable interrupt before checking to avoid concurrency issue.
+    esp_intr_disable(host->intr);
     //Grab next transaction
     r = xQueueReceiveFromISR(host->trans_queue, &trans, &do_yield);
-    if (!r) {
-        //No packet waiting. Disable interrupt.
-        esp_intr_disable(host->intr);
-    } else {
+    if (r) {
+        //enable the interrupt again if there is packet to send
+        esp_intr_enable(host->intr);
+
         //We have a transaction. Send it.
         host->hw->slave.trans_done = 0; //clear int bit
         host->cur_trans = trans;