forked from espressif/esp-idf
gdma: correct the iram placement logic
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -26,19 +26,17 @@
|
|||||||
|
|
||||||
static const char *TAG = "gdma";
|
static const char *TAG = "gdma";
|
||||||
|
|
||||||
#if CONFIG_GDMA_ISR_IRAM_SAFE
|
#if CONFIG_GDMA_ISR_IRAM_SAFE || CONFIG_GDMA_CTRL_FUNC_IN_IRAM
|
||||||
#define GDMA_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED)
|
|
||||||
#define GDMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
#define GDMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||||
#else
|
#else
|
||||||
#define GDMA_INTR_ALLOC_FLAGS ESP_INTR_FLAG_INTRDISABLED
|
|
||||||
#define GDMA_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
#define GDMA_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||||
#endif // CONFIG_GDMA_ISR_IRAM_SAFE
|
#endif
|
||||||
|
|
||||||
#if CONFIG_GDMA_CTRL_FUNC_IN_IRAM
|
#if CONFIG_GDMA_ISR_IRAM_SAFE
|
||||||
#define GDMA_CTRL_FUNC_ATTR IRAM_ATTR
|
#define GDMA_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED)
|
||||||
#else
|
#else
|
||||||
#define GDMA_CTRL_FUNC_ATTR
|
#define GDMA_INTR_ALLOC_FLAGS ESP_INTR_FLAG_INTRDISABLED
|
||||||
#endif // CONFIG_GDMA_CTRL_FUNC_IN_IRAM
|
#endif
|
||||||
|
|
||||||
#define GDMA_INVALID_PERIPH_TRIG (0x3F)
|
#define GDMA_INVALID_PERIPH_TRIG (0x3F)
|
||||||
#define SEARCH_REQUEST_RX_CHANNEL (1 << 0)
|
#define SEARCH_REQUEST_RX_CHANNEL (1 << 0)
|
||||||
@@ -109,11 +107,9 @@ struct gdma_rx_channel_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static gdma_group_t *gdma_acquire_group_handle(int group_id);
|
static gdma_group_t *gdma_acquire_group_handle(int group_id);
|
||||||
static void gdma_release_group_handle(gdma_group_t *group);
|
|
||||||
static gdma_pair_t *gdma_acquire_pair_handle(gdma_group_t *group, int pair_id);
|
static gdma_pair_t *gdma_acquire_pair_handle(gdma_group_t *group, int pair_id);
|
||||||
|
static void gdma_release_group_handle(gdma_group_t *group);
|
||||||
static void gdma_release_pair_handle(gdma_pair_t *pair);
|
static void gdma_release_pair_handle(gdma_pair_t *pair);
|
||||||
static void gdma_uninstall_group(gdma_group_t *group);
|
|
||||||
static void gdma_uninstall_pair(gdma_pair_t *pair);
|
|
||||||
static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel);
|
static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel);
|
||||||
static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel);
|
static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel);
|
||||||
static esp_err_t gdma_install_rx_interrupt(gdma_rx_channel_t *rx_chan);
|
static esp_err_t gdma_install_rx_interrupt(gdma_rx_channel_t *rx_chan);
|
||||||
@@ -161,27 +157,28 @@ esp_err_t gdma_new_channel(const gdma_channel_alloc_config_t *config, gdma_chann
|
|||||||
|
|
||||||
for (int i = 0; i < SOC_GDMA_GROUPS && search_code; i++) { // loop to search group
|
for (int i = 0; i < SOC_GDMA_GROUPS && search_code; i++) { // loop to search group
|
||||||
group = gdma_acquire_group_handle(i);
|
group = gdma_acquire_group_handle(i);
|
||||||
for (int j = 0; j < SOC_GDMA_PAIRS_PER_GROUP && search_code && group; j++) { // loop to search pair
|
ESP_GOTO_ON_FALSE(group, ESP_ERR_NO_MEM, err, TAG, "no mem for group(%d)", i);
|
||||||
|
for (int j = 0; j < SOC_GDMA_PAIRS_PER_GROUP && search_code; j++) { // loop to search pair
|
||||||
pair = gdma_acquire_pair_handle(group, j);
|
pair = gdma_acquire_pair_handle(group, j);
|
||||||
if (pair) {
|
ESP_GOTO_ON_FALSE(pair, ESP_ERR_NO_MEM, err, TAG, "no mem for pair(%d,%d)", i, j);
|
||||||
portENTER_CRITICAL(&pair->spinlock);
|
portENTER_CRITICAL(&pair->spinlock);
|
||||||
if (!(search_code & pair->occupy_code)) { // pair has suitable position for acquired channel(s)
|
if (!(search_code & pair->occupy_code)) { // pair has suitable position for acquired channel(s)
|
||||||
pair->occupy_code |= search_code;
|
pair->occupy_code |= search_code;
|
||||||
search_code = 0; // exit search loop
|
search_code = 0; // exit search loop
|
||||||
}
|
}
|
||||||
portEXIT_CRITICAL(&pair->spinlock);
|
portEXIT_CRITICAL(&pair->spinlock);
|
||||||
if (!search_code) {
|
if (search_code) {
|
||||||
portENTER_CRITICAL(&group->spinlock);
|
gdma_release_pair_handle(pair);
|
||||||
group->pair_ref_counts[j]++; // channel obtains a reference to pair
|
pair = NULL;
|
||||||
portEXIT_CRITICAL(&group->spinlock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
gdma_release_pair_handle(pair);
|
|
||||||
} // loop used to search pair
|
} // loop used to search pair
|
||||||
gdma_release_group_handle(group);
|
if (search_code) {
|
||||||
|
gdma_release_group_handle(group);
|
||||||
|
group = NULL;
|
||||||
|
}
|
||||||
} // loop used to search group
|
} // loop used to search group
|
||||||
ESP_GOTO_ON_FALSE(search_code == 0, ESP_ERR_NOT_FOUND, err, TAG, "no free gdma channel, search code=%d", search_code);
|
ESP_GOTO_ON_FALSE(search_code == 0, ESP_ERR_NOT_FOUND, err, TAG, "no free gdma channel, search code=%d", search_code);
|
||||||
|
assert(pair && group); // pair and group handle shouldn't be NULL
|
||||||
search_done:
|
search_done:
|
||||||
// register TX channel
|
// register TX channel
|
||||||
if (alloc_tx_channel) {
|
if (alloc_tx_channel) {
|
||||||
@@ -214,6 +211,12 @@ err:
|
|||||||
if (alloc_rx_channel) {
|
if (alloc_rx_channel) {
|
||||||
free(alloc_rx_channel);
|
free(alloc_rx_channel);
|
||||||
}
|
}
|
||||||
|
if (pair) {
|
||||||
|
gdma_release_pair_handle(pair);
|
||||||
|
}
|
||||||
|
if (group) {
|
||||||
|
gdma_release_group_handle(group);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,9 +389,7 @@ esp_err_t gdma_register_tx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_
|
|||||||
ESP_GOTO_ON_FALSE(esp_ptr_in_iram(cbs->on_trans_eof), ESP_ERR_INVALID_ARG, err, TAG, "on_trans_eof not in IRAM");
|
ESP_GOTO_ON_FALSE(esp_ptr_in_iram(cbs->on_trans_eof), ESP_ERR_INVALID_ARG, err, TAG, "on_trans_eof not in IRAM");
|
||||||
}
|
}
|
||||||
if (user_data) {
|
if (user_data) {
|
||||||
ESP_GOTO_ON_FALSE(esp_ptr_in_dram(user_data) ||
|
ESP_GOTO_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, err, TAG, "user context not in internal RAM");
|
||||||
esp_ptr_in_diram_dram(user_data) ||
|
|
||||||
esp_ptr_in_rtc_dram_fast(user_data), ESP_ERR_INVALID_ARG, err, TAG, "user context not in DRAM");
|
|
||||||
}
|
}
|
||||||
#endif // CONFIG_GDMA_ISR_IRAM_SAFE
|
#endif // CONFIG_GDMA_ISR_IRAM_SAFE
|
||||||
|
|
||||||
@@ -424,9 +425,7 @@ esp_err_t gdma_register_rx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_
|
|||||||
ESP_GOTO_ON_FALSE(esp_ptr_in_iram(cbs->on_recv_eof), ESP_ERR_INVALID_ARG, err, TAG, "on_recv_eof not in IRAM");
|
ESP_GOTO_ON_FALSE(esp_ptr_in_iram(cbs->on_recv_eof), ESP_ERR_INVALID_ARG, err, TAG, "on_recv_eof not in IRAM");
|
||||||
}
|
}
|
||||||
if (user_data) {
|
if (user_data) {
|
||||||
ESP_GOTO_ON_FALSE(esp_ptr_in_dram(user_data) ||
|
ESP_GOTO_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, err, TAG, "user context not in internal RAM");
|
||||||
esp_ptr_in_diram_dram(user_data) ||
|
|
||||||
esp_ptr_in_rtc_dram_fast(user_data), ESP_ERR_INVALID_ARG, err, TAG, "user context not in DRAM");
|
|
||||||
}
|
}
|
||||||
#endif // CONFIG_GDMA_ISR_IRAM_SAFE
|
#endif // CONFIG_GDMA_ISR_IRAM_SAFE
|
||||||
|
|
||||||
@@ -447,7 +446,7 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
GDMA_CTRL_FUNC_ATTR esp_err_t gdma_start(gdma_channel_handle_t dma_chan, intptr_t desc_base_addr)
|
esp_err_t gdma_start(gdma_channel_handle_t dma_chan, intptr_t desc_base_addr)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
gdma_pair_t *pair = NULL;
|
gdma_pair_t *pair = NULL;
|
||||||
@@ -468,7 +467,7 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
GDMA_CTRL_FUNC_ATTR esp_err_t gdma_stop(gdma_channel_handle_t dma_chan)
|
esp_err_t gdma_stop(gdma_channel_handle_t dma_chan)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
gdma_pair_t *pair = NULL;
|
gdma_pair_t *pair = NULL;
|
||||||
@@ -487,7 +486,7 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
GDMA_CTRL_FUNC_ATTR esp_err_t gdma_append(gdma_channel_handle_t dma_chan)
|
esp_err_t gdma_append(gdma_channel_handle_t dma_chan)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
gdma_pair_t *pair = NULL;
|
gdma_pair_t *pair = NULL;
|
||||||
@@ -506,7 +505,7 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
GDMA_CTRL_FUNC_ATTR esp_err_t gdma_reset(gdma_channel_handle_t dma_chan)
|
esp_err_t gdma_reset(gdma_channel_handle_t dma_chan)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
gdma_pair_t *pair = NULL;
|
gdma_pair_t *pair = NULL;
|
||||||
@@ -525,7 +524,7 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gdma_uninstall_group(gdma_group_t *group)
|
static void gdma_release_group_handle(gdma_group_t *group)
|
||||||
{
|
{
|
||||||
int group_id = group->group_id;
|
int group_id = group->group_id;
|
||||||
bool do_deinitialize = false;
|
bool do_deinitialize = false;
|
||||||
@@ -581,14 +580,7 @@ out:
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gdma_release_group_handle(gdma_group_t *group)
|
static void gdma_release_pair_handle(gdma_pair_t *pair)
|
||||||
{
|
|
||||||
if (group) {
|
|
||||||
gdma_uninstall_group(group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gdma_uninstall_pair(gdma_pair_t *pair)
|
|
||||||
{
|
{
|
||||||
gdma_group_t *group = pair->group;
|
gdma_group_t *group = pair->group;
|
||||||
int pair_id = pair->pair_id;
|
int pair_id = pair->pair_id;
|
||||||
@@ -606,8 +598,7 @@ static void gdma_uninstall_pair(gdma_pair_t *pair)
|
|||||||
if (do_deinitialize) {
|
if (do_deinitialize) {
|
||||||
free(pair);
|
free(pair);
|
||||||
ESP_LOGD(TAG, "del pair (%d,%d)", group->group_id, pair_id);
|
ESP_LOGD(TAG, "del pair (%d,%d)", group->group_id, pair_id);
|
||||||
|
gdma_release_group_handle(group);
|
||||||
gdma_uninstall_group(group);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,17 +637,12 @@ out:
|
|||||||
return pair;
|
return pair;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gdma_release_pair_handle(gdma_pair_t *pair)
|
|
||||||
{
|
|
||||||
if (pair) {
|
|
||||||
gdma_uninstall_pair(pair);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel)
|
static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel)
|
||||||
{
|
{
|
||||||
gdma_pair_t *pair = dma_channel->pair;
|
gdma_pair_t *pair = dma_channel->pair;
|
||||||
gdma_group_t *group = pair->group;
|
gdma_group_t *group = pair->group;
|
||||||
|
int pair_id = pair->pair_id;
|
||||||
|
int group_id = group->group_id;
|
||||||
gdma_tx_channel_t *tx_chan = __containerof(dma_channel, gdma_tx_channel_t, base);
|
gdma_tx_channel_t *tx_chan = __containerof(dma_channel, gdma_tx_channel_t, base);
|
||||||
portENTER_CRITICAL(&pair->spinlock);
|
portENTER_CRITICAL(&pair->spinlock);
|
||||||
pair->tx_chan = NULL;
|
pair->tx_chan = NULL;
|
||||||
@@ -666,15 +652,16 @@ static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel)
|
|||||||
if (dma_channel->intr) {
|
if (dma_channel->intr) {
|
||||||
esp_intr_free(dma_channel->intr);
|
esp_intr_free(dma_channel->intr);
|
||||||
portENTER_CRITICAL(&pair->spinlock);
|
portENTER_CRITICAL(&pair->spinlock);
|
||||||
gdma_ll_tx_enable_interrupt(group->hal.dev, pair->pair_id, UINT32_MAX, false); // disable all interupt events
|
gdma_ll_tx_enable_interrupt(group->hal.dev, pair_id, UINT32_MAX, false); // disable all interupt events
|
||||||
gdma_ll_tx_clear_interrupt_status(group->hal.dev, pair->pair_id, UINT32_MAX); // clear all pending events
|
gdma_ll_tx_clear_interrupt_status(group->hal.dev, pair_id, UINT32_MAX); // clear all pending events
|
||||||
portEXIT_CRITICAL(&pair->spinlock);
|
portEXIT_CRITICAL(&pair->spinlock);
|
||||||
ESP_LOGD(TAG, "uninstall interrupt service for tx channel (%d,%d)", group->group_id, pair->pair_id);
|
ESP_LOGD(TAG, "uninstall interrupt service for tx channel (%d,%d)", group_id, pair_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, "del tx channel (%d,%d)", group->group_id, pair->pair_id);
|
|
||||||
free(tx_chan);
|
free(tx_chan);
|
||||||
gdma_uninstall_pair(pair);
|
ESP_LOGD(TAG, "del tx channel (%d,%d)", group_id, pair_id);
|
||||||
|
// channel has a reference on pair, release it now
|
||||||
|
gdma_release_pair_handle(pair);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,6 +669,8 @@ static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel)
|
|||||||
{
|
{
|
||||||
gdma_pair_t *pair = dma_channel->pair;
|
gdma_pair_t *pair = dma_channel->pair;
|
||||||
gdma_group_t *group = pair->group;
|
gdma_group_t *group = pair->group;
|
||||||
|
int pair_id = pair->pair_id;
|
||||||
|
int group_id = group->group_id;
|
||||||
gdma_rx_channel_t *rx_chan = __containerof(dma_channel, gdma_rx_channel_t, base);
|
gdma_rx_channel_t *rx_chan = __containerof(dma_channel, gdma_rx_channel_t, base);
|
||||||
portENTER_CRITICAL(&pair->spinlock);
|
portENTER_CRITICAL(&pair->spinlock);
|
||||||
pair->rx_chan = NULL;
|
pair->rx_chan = NULL;
|
||||||
@@ -691,15 +680,15 @@ static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel)
|
|||||||
if (dma_channel->intr) {
|
if (dma_channel->intr) {
|
||||||
esp_intr_free(dma_channel->intr);
|
esp_intr_free(dma_channel->intr);
|
||||||
portENTER_CRITICAL(&pair->spinlock);
|
portENTER_CRITICAL(&pair->spinlock);
|
||||||
gdma_ll_rx_enable_interrupt(group->hal.dev, pair->pair_id, UINT32_MAX, false); // disable all interupt events
|
gdma_ll_rx_enable_interrupt(group->hal.dev, pair_id, UINT32_MAX, false); // disable all interupt events
|
||||||
gdma_ll_rx_clear_interrupt_status(group->hal.dev, pair->pair_id, UINT32_MAX); // clear all pending events
|
gdma_ll_rx_clear_interrupt_status(group->hal.dev, pair_id, UINT32_MAX); // clear all pending events
|
||||||
portEXIT_CRITICAL(&pair->spinlock);
|
portEXIT_CRITICAL(&pair->spinlock);
|
||||||
ESP_LOGD(TAG, "uninstall interrupt service for rx channel (%d,%d)", group->group_id, pair->pair_id);
|
ESP_LOGD(TAG, "uninstall interrupt service for rx channel (%d,%d)", group_id, pair_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, "del rx channel (%d,%d)", group->group_id, pair->pair_id);
|
|
||||||
free(rx_chan);
|
free(rx_chan);
|
||||||
gdma_uninstall_pair(pair);
|
ESP_LOGD(TAG, "del rx channel (%d,%d)", group_id, pair_id);
|
||||||
|
gdma_release_pair_handle(pair);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[mapping:driver]
|
[mapping:driver]
|
||||||
archive: libdriver.a
|
archive: libdriver.a
|
||||||
entries:
|
entries:
|
||||||
@@ -7,3 +6,8 @@ entries:
|
|||||||
# placed in flash.
|
# placed in flash.
|
||||||
if TWAI_ISR_IN_IRAM = y && (TWAI_ERRATA_FIX_RX_FRAME_INVALID = y || TWAI_ERRATA_FIX_RX_FIFO_CORRUPT = y):
|
if TWAI_ISR_IN_IRAM = y && (TWAI_ERRATA_FIX_RX_FRAME_INVALID = y || TWAI_ERRATA_FIX_RX_FIFO_CORRUPT = y):
|
||||||
periph_ctrl: periph_module_reset (noflash)
|
periph_ctrl: periph_module_reset (noflash)
|
||||||
|
if GDMA_CTRL_FUNC_IN_IRAM = y:
|
||||||
|
gdma: gdma_start (noflash)
|
||||||
|
gdma: gdma_stop (noflash)
|
||||||
|
gdma: gdma_append (noflash)
|
||||||
|
gdma: gdma_reset (noflash)
|
||||||
|
Reference in New Issue
Block a user