Bladeren bron

feat(gdma): supported rx err_eof interrupt

laokaiyao 2 jaren geleden
bovenliggende
commit
3c2233d48b
2 gewijzigde bestanden met toevoegingen van 28 en 11 verwijderingen
  1. 20 11
      components/esp_hw_support/dma/gdma.c
  2. 8 0
      components/esp_hw_support/include/esp_private/gdma.h

+ 20 - 11
components/esp_hw_support/dma/gdma.c

@@ -739,16 +739,7 @@ void gdma_default_rx_isr(void *args)
     uint32_t intr_status = gdma_hal_read_intr_status(hal, pair_id, GDMA_CHANNEL_DIRECTION_RX);
     gdma_hal_clear_intr(hal, pair_id, GDMA_CHANNEL_DIRECTION_RX, intr_status);
 
-    if ((intr_status & GDMA_LL_EVENT_RX_SUC_EOF) && rx_chan->cbs.on_recv_eof) {
-        uint32_t eof_addr = gdma_hal_get_eof_desc_addr(hal, pair_id, GDMA_CHANNEL_DIRECTION_RX);
-        gdma_event_data_t edata = {
-            .rx_eof_desc_addr = eof_addr
-        };
-        need_yield |= rx_chan->cbs.on_recv_eof(&rx_chan->base, &edata, rx_chan->user_data);
-    }
-    if ((intr_status & GDMA_LL_EVENT_RX_DESC_ERROR) && rx_chan->cbs.on_descr_err) {
-        need_yield |= rx_chan->cbs.on_descr_err(&rx_chan->base, NULL, rx_chan->user_data);
-    }
+    /* Call on_recv_done before eof callbacks to ensure a correct sequence */
     if ((intr_status & GDMA_LL_EVENT_RX_DONE) && rx_chan->cbs.on_recv_done) {
         /* Here we don't return an event data in this callback.
          * Because we can't get a determinant descriptor address
@@ -760,6 +751,24 @@ void gdma_default_rx_isr(void *args)
          */
         need_yield |= rx_chan->cbs.on_recv_done(&rx_chan->base, NULL, rx_chan->user_data);
     }
+    if ((intr_status & GDMA_LL_EVENT_RX_DESC_ERROR) && rx_chan->cbs.on_descr_err) {
+        need_yield |= rx_chan->cbs.on_descr_err(&rx_chan->base, NULL, rx_chan->user_data);
+    }
+    if ((intr_status & GDMA_LL_EVENT_RX_SUC_EOF) && rx_chan->cbs.on_recv_eof) {
+        uint32_t eof_addr = gdma_ll_rx_get_success_eof_desc_addr(group->hal.dev, pair->pair_id);
+        gdma_event_data_t suc_eof_data = {
+            .rx_eof_desc_addr = eof_addr,
+        };
+        need_yield |= rx_chan->cbs.on_recv_eof(&rx_chan->base, &suc_eof_data, rx_chan->user_data);
+    }
+    if ((intr_status & GDMA_LL_EVENT_RX_ERR_EOF) && rx_chan->cbs.on_recv_eof) {
+        uint32_t eof_addr = gdma_ll_rx_get_error_eof_desc_addr(group->hal.dev, pair->pair_id);
+        gdma_event_data_t err_eof_data = {
+            .rx_eof_desc_addr = eof_addr,
+            .flags.abnormal_eof = true,
+        };
+        need_yield |= rx_chan->cbs.on_recv_eof(&rx_chan->base, &err_eof_data, rx_chan->user_data);
+    }
 
     if (need_yield) {
         portYIELD_FROM_ISR();
@@ -781,7 +790,7 @@ void gdma_default_tx_isr(void *args)
     if ((intr_status & GDMA_LL_EVENT_TX_EOF) && tx_chan->cbs.on_trans_eof) {
         uint32_t eof_addr = gdma_hal_get_eof_desc_addr(hal, pair_id, GDMA_CHANNEL_DIRECTION_TX);
         gdma_event_data_t edata = {
-            .tx_eof_desc_addr = eof_addr
+            .tx_eof_desc_addr = eof_addr,
         };
         need_yield |= tx_chan->cbs.on_trans_eof(&tx_chan->base, &edata, tx_chan->user_data);
     }

+ 8 - 0
components/esp_hw_support/include/esp_private/gdma.h

@@ -58,6 +58,14 @@ typedef struct {
         intptr_t rx_eof_desc_addr; /*!< EOF descriptor address of RX channel */
         intptr_t tx_eof_desc_addr; /*!< EOF descriptor address of TX channel */
     };
+    struct {
+        uint32_t abnormal_eof: 1;     /*!< 0: normal/success EOF;
+                                       *   1: abnormal/error EOF,
+                                       *      it doesn't mean GDMA goes into an error condition,
+                                       *      but the other peripheral goes into an abnormal state.
+                                       *      For GDMA, it's still a valid EOF
+                                       */
+    } flags;
 } gdma_event_data_t;
 
 /**