Merge branch 'feature/set_gdma_priority' into 'master'

gdma: support override default channel priority

See merge request espressif/esp-idf!22676
This commit is contained in:
morris
2023-04-06 14:52:35 +08:00
11 changed files with 68 additions and 12 deletions

View File

@@ -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;

View File

@@ -359,6 +359,24 @@ err:
return ret;
}
esp_err_t gdma_set_priority(gdma_channel_handle_t dma_chan, uint32_t priority)
{
gdma_pair_t *pair = NULL;
gdma_group_t *group = NULL;
ESP_RETURN_ON_FALSE(dma_chan && priority <= GDMA_LL_CHANNEL_MAX_PRIORITY, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
pair = dma_chan->pair;
group = pair->group;
if (dma_chan->direction == GDMA_CHANNEL_DIRECTION_TX) {
gdma_ll_tx_set_priority(group->hal.dev, pair->pair_id, priority);
} else {
gdma_ll_rx_set_priority(group->hal.dev, pair->pair_id, priority);
}
return ESP_OK;
}
esp_err_t gdma_register_tx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_tx_event_callbacks_t *cbs, void *user_data)
{
esp_err_t ret = ESP_OK;
@@ -433,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;
@@ -450,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;
@@ -471,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)
@@ -651,6 +667,8 @@ static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel)
ESP_LOGD(TAG, "uninstall interrupt service for tx channel (%d,%d)", group_id, pair_id);
}
gdma_ll_tx_set_priority(group->hal.dev, pair_id, 0); // reset the priority to 0 (lowest)
free(tx_chan);
ESP_LOGD(TAG, "del tx channel (%d,%d)", group_id, pair_id);
// channel has a reference on pair, release it now
@@ -679,6 +697,8 @@ static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel)
ESP_LOGD(TAG, "uninstall interrupt service for rx channel (%d,%d)", group_id, pair_id);
}
gdma_ll_rx_set_priority(group->hal.dev, pair_id, 0); // reset the priority to 0 (lowest)
free(rx_chan);
ESP_LOGD(TAG, "del rx channel (%d,%d)", group_id, pair_id);
gdma_release_pair_handle(pair);

View File

@@ -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;

View File

@@ -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 {

View File

@@ -177,14 +177,28 @@ esp_err_t gdma_set_transfer_ability(gdma_channel_handle_t dma_chan, const gdma_t
/**
* @brief Apply channel strategy for GDMA channel
*
* @param dma_chan GDMA channel handle, allocated by `gdma_new_channel`
* @param config Configuration of GDMA channel strategy
* @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
* @param[in] config Configuration of GDMA channel strategy
* - ESP_OK: Apply channel strategy successfully
* - ESP_ERR_INVALID_ARG: Apply channel strategy failed because of invalid argument
* - ESP_FAIL: Apply channel strategy failed because of other error
*/
esp_err_t gdma_apply_strategy(gdma_channel_handle_t dma_chan, const gdma_strategy_config_t *config);
/**
* @brief Set GDMA channel priority
*
* @note By default, all GDMA channels are with the same priority: 0. Channels with the same priority are served in round-robin manner.
*
* @param[in] dma_chan GDMA channel handle, allocated by `gdma_new_channel`
* @param[in] priority Priority of GDMA channel, higher value means higher priority
* @return
* - ESP_OK: Set GDMA channel priority successfully
* - ESP_ERR_INVALID_ARG: Set GDMA channel priority failed because of invalid argument, e.g. priority out of range [0,GDMA_LL_CHANNEL_MAX_PRIORITY]
* - ESP_FAIL: Set GDMA channel priority failed because of other error
*/
esp_err_t gdma_set_priority(gdma_channel_handle_t dma_chan, uint32_t priority);
/**
* @brief Delete GDMA channel
* @note If you call `gdma_new_channel` several times for a same peripheral, make sure you call this API the same times.
@@ -251,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);
@@ -265,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);
@@ -333,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

View File

@@ -18,6 +18,8 @@ extern "C" {
#define GDMA_LL_GET_HW(id) (((id) == 0) ? (&GDMA) : NULL)
#define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5]
#define GDMA_LL_RX_EVENT_MASK (0x06A7)
#define GDMA_LL_TX_EVENT_MASK (0x1958)

View File

@@ -18,6 +18,8 @@ extern "C" {
#define GDMA_LL_GET_HW(id) (((id) == 0) ? (&GDMA) : NULL)
#define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5]
#define GDMA_LL_RX_EVENT_MASK (0x06A7)
#define GDMA_LL_TX_EVENT_MASK (0x1958)

View File

@@ -19,6 +19,8 @@ extern "C" {
#define GDMA_LL_GET_HW(id) (((id) == 0) ? (&GDMA) : NULL)
#define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5]
#define GDMA_LL_RX_EVENT_MASK (0x7F)
#define GDMA_LL_TX_EVENT_MASK (0x3F)

View File

@@ -19,6 +19,8 @@ extern "C" {
#define GDMA_LL_GET_HW(id) (((id) == 0) ? (&GDMA) : NULL)
#define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5]
#define GDMA_LL_RX_EVENT_MASK (0x7F)
#define GDMA_LL_TX_EVENT_MASK (0x3F)

View File

@@ -18,6 +18,8 @@ extern "C" {
#define GDMA_LL_GET_HW(id) (((id) == 0) ? (&GDMA) : NULL)
#define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5]
#define GDMA_LL_RX_EVENT_MASK (0x06A7)
#define GDMA_LL_TX_EVENT_MASK (0x1958)

View File

@@ -18,6 +18,8 @@ extern "C" {
#define GDMA_LL_GET_HW(id) (((id) == 0) ? (&GDMA) : NULL)
#define GDMA_LL_CHANNEL_MAX_PRIORITY 5 // supported priority levels: [0,5]
#define GDMA_LL_RX_EVENT_MASK (0x3FF)
#define GDMA_LL_TX_EVENT_MASK (0xFF)