فهرست منبع

gdma: avoid manually start/stop when channel is controled by ETM

morris 2 سال پیش
والد
کامیت
6c19e7b8a7

+ 3 - 2
components/bootloader_support/test_apps/bootloader_support/main/test_app_main.c

@@ -9,8 +9,9 @@
 #include "esp_heap_caps.h"
 
 
-// Some resources are lazy allocated (newlib locks) in the bootloader support code, the threshold is left for that case
-#define TEST_MEMORY_LEAK_THRESHOLD (-650)
+// Some resources are lazy allocated, e.g. newlib locks, GDMA channel lazy installed by crypto driver
+// the threshold is left for those cases
+#define TEST_MEMORY_LEAK_THRESHOLD (-700)
 
 static size_t before_free_8bit;
 static size_t before_free_32bit;

+ 6 - 8
components/esp_hw_support/dma/gdma.c

@@ -451,10 +451,10 @@ err:
 
 esp_err_t gdma_start(gdma_channel_handle_t dma_chan, intptr_t desc_base_addr)
 {
-    esp_err_t ret = ESP_OK;
     gdma_pair_t *pair = NULL;
     gdma_group_t *group = NULL;
-    ESP_GOTO_ON_FALSE_ISR(dma_chan, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
+    ESP_RETURN_ON_FALSE_ISR(dma_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    ESP_RETURN_ON_FALSE_ISR(dma_chan->flags.start_stop_by_etm == false, ESP_ERR_INVALID_STATE, TAG, "channel is controlled by ETM");
     pair = dma_chan->pair;
     group = pair->group;
 
@@ -468,16 +468,15 @@ esp_err_t gdma_start(gdma_channel_handle_t dma_chan, intptr_t desc_base_addr)
     }
     portEXIT_CRITICAL_SAFE(&dma_chan->spinlock);
 
-err:
-    return ret;
+    return ESP_OK;
 }
 
 esp_err_t gdma_stop(gdma_channel_handle_t dma_chan)
 {
-    esp_err_t ret = ESP_OK;
     gdma_pair_t *pair = NULL;
     gdma_group_t *group = NULL;
-    ESP_GOTO_ON_FALSE_ISR(dma_chan, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
+    ESP_RETURN_ON_FALSE_ISR(dma_chan, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
+    ESP_RETURN_ON_FALSE_ISR(dma_chan->flags.start_stop_by_etm == false, ESP_ERR_INVALID_STATE, TAG, "channel is controlled by ETM");
     pair = dma_chan->pair;
     group = pair->group;
 
@@ -489,8 +488,7 @@ esp_err_t gdma_stop(gdma_channel_handle_t dma_chan)
     }
     portEXIT_CRITICAL_SAFE(&dma_chan->spinlock);
 
-err:
-    return ret;
+    return ESP_OK;
 }
 
 esp_err_t gdma_append(gdma_channel_handle_t dma_chan)

+ 3 - 0
components/esp_hw_support/dma/gdma_etm.c

@@ -46,6 +46,7 @@ static esp_err_t gdma_del_etm_task(esp_etm_task_t *task)
         gdma_ll_tx_enable_etm_task(group->hal.dev, pair->pair_id, false);
     }
     free(gdma_task);
+    dma_chan->flags.start_stop_by_etm = false;
     return ESP_OK;
 }
 
@@ -105,6 +106,8 @@ esp_err_t gdma_new_etm_task(gdma_channel_handle_t dma_chan, const gdma_etm_task_
     }
     ESP_GOTO_ON_FALSE(task_id != 0, ESP_ERR_NOT_SUPPORTED, err, TAG, "not supported task type");
 
+    // set a flag, now the GDMA channel is start/stop by ETM subsystem
+    dma_chan->flags.start_stop_by_etm = true;
     // fill the ETM task object
     task->chan = dma_chan;
     task->base.task_id = task_id;

+ 3 - 0
components/esp_hw_support/dma/gdma_priv.h

@@ -67,6 +67,9 @@ struct gdma_channel_t {
     size_t sram_alignment;  // alignment for memory in SRAM
     size_t psram_alignment; // alignment for memory in PSRAM
     esp_err_t (*del)(gdma_channel_t *channel); // channel deletion function, it's polymorphic, see `gdma_del_tx_channel` or `gdma_del_rx_channel`
+    struct {
+        uint32_t start_stop_by_etm: 1; // whether the channel is started/stopped by ETM
+    } flags;
 };
 
 struct gdma_tx_channel_t {

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

@@ -265,6 +265,7 @@ esp_err_t gdma_register_rx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_
  * @return
  *      - ESP_OK: Start DMA engine successfully
  *      - ESP_ERR_INVALID_ARG: Start DMA engine failed because of invalid argument
+ *      - ESP_ERR_INVALID_STATE: Start DMA engine failed because of invalid state, e.g. the channel is controlled by ETM, so can't start it manually
  *      - ESP_FAIL: Start DMA engine failed because of other error
  */
 esp_err_t gdma_start(gdma_channel_handle_t dma_chan, intptr_t desc_base_addr);
@@ -279,6 +280,7 @@ esp_err_t gdma_start(gdma_channel_handle_t dma_chan, intptr_t desc_base_addr);
  * @return
  *      - ESP_OK: Stop DMA engine successfully
  *      - ESP_ERR_INVALID_ARG: Stop DMA engine failed because of invalid argument
+ *      - ESP_ERR_INVALID_STATE: Stop DMA engine failed because of invalid state, e.g. the channel is controlled by ETM, so can't stop it manually
  *      - ESP_FAIL: Stop DMA engine failed because of other error
  */
 esp_err_t gdma_stop(gdma_channel_handle_t dma_chan);
@@ -347,6 +349,7 @@ typedef struct {
  * @brief Get the ETM task for GDMA channel
  *
  * @note The created ETM task object can be deleted later by calling `esp_etm_del_task`
+ * @note If the GDMA task (e.g. start/stop) is controlled by ETM, then you can't use `gdma_start`/`gdma_stop` to control it.
  *
  * @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
  * @param[in] config GDMA ETM task configuration