From f76f3dc83fb55615d4e9d41e0177946d3181157e Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 16 May 2023 14:23:19 +0800 Subject: [PATCH 1/3] adc: fix adc continuous driver conv_frame_size not bigger than 4092 issue Closes https://github.com/espressif/esp-idf/issues/11385 --- components/driver/deprecated/adc_dma_legacy.c | 14 ++-- components/esp_adc/adc_continuous.c | 18 +++-- components/hal/adc_hal.c | 65 ++++++++++++++----- components/hal/include/hal/adc_hal.h | 11 ++-- components/hal/include/hal/dma_types.h | 2 + 5 files changed, 76 insertions(+), 34 deletions(-) diff --git a/components/driver/deprecated/adc_dma_legacy.c b/components/driver/deprecated/adc_dma_legacy.c index 57556f4627..4870a734e5 100644 --- a/components/driver/deprecated/adc_dma_legacy.c +++ b/components/driver/deprecated/adc_dma_legacy.c @@ -207,7 +207,9 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) } //malloc dma descriptor - s_adc_digi_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA); + uint32_t dma_desc_num_per_frame = (init_config->conv_num_each_intr + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; + uint32_t dma_desc_max_num = dma_desc_num_per_frame * INTERNAL_BUF_NUM; + s_adc_digi_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * dma_desc_max_num, MALLOC_CAP_DMA); if (!s_adc_digi_ctx->hal.rx_desc) { ret = ESP_ERR_NO_MEM; goto cleanup; @@ -310,7 +312,8 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) #elif CONFIG_IDF_TARGET_ESP32 .dev = (void *)I2S_LL_GET_HW(s_adc_digi_ctx->i2s_host), #endif - .desc_max_num = INTERNAL_BUF_NUM, + .eof_desc_num = INTERNAL_BUF_NUM, + .eof_step = dma_desc_num_per_frame, .dma_chan = dma_chan, .eof_num = init_config->conv_num_each_intr / SOC_ADC_DIGI_DATA_BYTES_PER_CONV }; @@ -367,15 +370,16 @@ static IRAM_ATTR bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx) portBASE_TYPE taskAwoken = 0; BaseType_t ret; adc_hal_dma_desc_status_t status = false; - dma_descriptor_t *current_desc = NULL; + uint8_t *finished_buffer = NULL; + uint32_t finished_size = 0; while (1) { - status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, ¤t_desc); + status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, &finished_buffer, &finished_size); if (status != ADC_HAL_DMA_DESC_VALID) { break; } - ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken); + ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); if (ret == pdFALSE) { //ringbuffer overflow adc_digi_ctx->ringbuf_overflow_flag = 1; diff --git a/components/esp_adc/adc_continuous.c b/components/esp_adc/adc_continuous.c index 90d5c78c47..6b08be7eae 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -134,7 +134,9 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi } //malloc dma descriptor - adc_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + uint32_t dma_desc_num_per_frame = (hdl_config->conv_frame_size + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; + uint32_t dma_desc_max_num = dma_desc_num_per_frame * INTERNAL_BUF_NUM; + adc_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * dma_desc_max_num, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); if (!adc_ctx->hal.rx_desc) { ret = ESP_ERR_NO_MEM; goto cleanup; @@ -224,7 +226,8 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi #elif CONFIG_IDF_TARGET_ESP32 .dev = (void *)I2S_LL_GET_HW(adc_ctx->i2s_host), #endif - .desc_max_num = INTERNAL_BUF_NUM, + .eof_desc_num = INTERNAL_BUF_NUM, + .eof_step = dma_desc_num_per_frame, .dma_chan = dma_chan, .eof_num = hdl_config->conv_frame_size / SOC_ADC_DIGI_DATA_BYTES_PER_CONV }; @@ -286,21 +289,22 @@ static IRAM_ATTR bool s_adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx) bool need_yield = false; BaseType_t ret; adc_hal_dma_desc_status_t status = false; - dma_descriptor_t *current_desc = NULL; + uint8_t *finished_buffer = NULL; + uint32_t finished_size = 0; while (1) { - status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, ¤t_desc); + status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, &finished_buffer, &finished_size); if (status != ADC_HAL_DMA_DESC_VALID) { break; } - ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken); + ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); need_yield |= (taskAwoken == pdTRUE); if (adc_digi_ctx->cbs.on_conv_done) { adc_continuous_evt_data_t edata = { - .conv_frame_buffer = current_desc->buffer, - .size = current_desc->dw0.length, + .conv_frame_buffer = finished_buffer, + .size = finished_size, }; if (adc_digi_ctx->cbs.on_conv_done(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) { need_yield |= true; diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index 4aa198c6df..96fe8be039 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -96,7 +96,8 @@ void adc_hal_dma_ctx_config(adc_hal_dma_ctx_t *hal, const adc_hal_dma_config_t * { hal->desc_dummy_head.next = hal->rx_desc; hal->dev = config->dev; - hal->desc_max_num = config->desc_max_num; + hal->eof_desc_num = config->eof_desc_num; + hal->eof_step = config->eof_step; hal->dma_chan = config->dma_chan; hal->eof_num = config->eof_num; } @@ -229,23 +230,33 @@ void adc_hal_digi_controller_config(adc_hal_dma_ctx_t *hal, const adc_hal_digi_c adc_hal_digi_sample_freq_config(hal, cfg->clk_src, cfg->clk_src_freq_hz, cfg->sample_freq_hz); } -static void adc_hal_digi_dma_link_descriptors(dma_descriptor_t *desc, uint8_t *data_buf, uint32_t size, uint32_t num) +static void adc_hal_digi_dma_link_descriptors(dma_descriptor_t *desc, uint8_t *data_buf, uint32_t per_eof_size, uint32_t eof_step, uint32_t eof_num) { HAL_ASSERT(((uint32_t)data_buf % 4) == 0); - HAL_ASSERT((size % 4) == 0); + HAL_ASSERT((per_eof_size % 4) == 0); uint32_t n = 0; - while (num--) { - desc[n] = (dma_descriptor_t) { - .dw0.size = size, - .dw0.length = 0, - .dw0.suc_eof = 0, - .dw0.owner = 1, - .buffer = data_buf, - .next = &desc[n+1] - }; - data_buf += size; - n++; + while (eof_num--) { + uint32_t eof_size = per_eof_size; + + for (int i = 0; i < eof_step; i++) { + uint32_t this_len = eof_size; + if (this_len > DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED) { + this_len = DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED; + } + + desc[n] = (dma_descriptor_t) { + .dw0.size = this_len, + .dw0.length = 0, + .dw0.suc_eof = 0, + .dw0.owner = 1, + .buffer = data_buf, + .next = &desc[n+1] + }; + eof_size -= this_len; + data_buf += this_len; + n++; + } } desc[n-1].next = NULL; } @@ -262,7 +273,7 @@ void adc_hal_digi_start(adc_hal_dma_ctx_t *hal, uint8_t *data_buf) //reset the current descriptor address hal->cur_desc_ptr = &hal->desc_dummy_head; - adc_hal_digi_dma_link_descriptors(hal->rx_desc, data_buf, hal->eof_num * SOC_ADC_DIGI_DATA_BYTES_PER_CONV, hal->desc_max_num); + adc_hal_digi_dma_link_descriptors(hal->rx_desc, data_buf, hal->eof_num * SOC_ADC_DIGI_DATA_BYTES_PER_CONV, hal->eof_step, hal->eof_desc_num); //start DMA adc_dma_ll_rx_start(hal->dev, hal->dma_chan, (lldesc_t *)hal->rx_desc); @@ -284,18 +295,36 @@ bool adc_hal_check_event(adc_hal_dma_ctx_t *hal, uint32_t mask) } #endif //#if !SOC_GDMA_SUPPORTED -adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, const intptr_t eof_desc_addr, dma_descriptor_t **cur_desc) +adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, const intptr_t eof_desc_addr, uint8_t **buffer, uint32_t *len) { HAL_ASSERT(hal->cur_desc_ptr); + if (!hal->cur_desc_ptr->next) { return ADC_HAL_DMA_DESC_NULL; } + if ((intptr_t)hal->cur_desc_ptr == eof_desc_addr) { return ADC_HAL_DMA_DESC_WAITING; } - hal->cur_desc_ptr = hal->cur_desc_ptr->next; - *cur_desc = hal->cur_desc_ptr; + uint8_t *buffer_start = NULL; + uint32_t eof_len = 0; + dma_descriptor_t *eof_desc = hal->cur_desc_ptr; + + //Find the eof list start + eof_desc = eof_desc->next; + buffer_start = eof_desc->buffer; + eof_len += eof_desc->dw0.length; + + //Find the eof list end + for (int i = 1; i < hal->eof_step; i++) { + eof_desc = eof_desc->next; + eof_len += eof_desc->dw0.length; + } + + hal->cur_desc_ptr = eof_desc; + *buffer = buffer_start; + *len = eof_len; return ADC_HAL_DMA_DESC_VALID; } diff --git a/components/hal/include/hal/adc_hal.h b/components/hal/include/hal/adc_hal.h index 5bbb0c81bd..d023ff7dd6 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -55,7 +55,8 @@ typedef enum adc_hal_dma_desc_status_t { */ typedef struct adc_hal_dma_config_t { void *dev; ///< DMA peripheral address - uint32_t desc_max_num; ///< Number of the descriptors linked once + uint32_t eof_desc_num; ///< Number of dma descriptors that is eof + uint32_t eof_step; ///< Number of linked descriptors that is one eof uint32_t dma_chan; ///< DMA channel to be used uint32_t eof_num; ///< Bytes between 2 in_suc_eof interrupts } adc_hal_dma_config_t; @@ -73,7 +74,8 @@ typedef struct adc_hal_dma_ctx_t { /**< these need to be configured by `adc_hal_dma_config_t` via driver layer*/ void *dev; ///< DMA address - uint32_t desc_max_num; ///< Number of the descriptors linked once + uint32_t eof_desc_num; ///< Number of dma descriptors that is eof + uint32_t eof_step; ///< Number of linked descriptors that is one eof uint32_t dma_chan; ///< DMA channel to be used uint32_t eof_num; ///< Words between 2 in_suc_eof interrupts } adc_hal_dma_ctx_t; @@ -175,11 +177,12 @@ bool adc_hal_check_event(adc_hal_dma_ctx_t *hal, uint32_t mask); * * @param hal Context of the HAL * @param eof_desc_addr The last descriptor that is finished by HW. Should be got from DMA - * @param[out] cur_desc The descriptor with ADC reading result (from the 1st one to the last one (``eof_desc_addr``)) + * @param[out] buffer ADC reading result buffer + * @param[out] len ADC reading result len * * @return See ``adc_hal_dma_desc_status_t`` */ -adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, const intptr_t eof_desc_addr, dma_descriptor_t **cur_desc); +adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, const intptr_t eof_desc_addr, uint8_t **buffer, uint32_t *len); /** * @brief Clear interrupt diff --git a/components/hal/include/hal/dma_types.h b/components/hal/include/hal/dma_types.h index ad323deb00..dead785c2c 100644 --- a/components/hal/include/hal/dma_types.h +++ b/components/hal/include/hal/dma_types.h @@ -36,6 +36,8 @@ ESP_STATIC_ASSERT(sizeof(dma_descriptor_t) == 12, "dma_descriptor_t should occup #define DMA_DESCRIPTOR_BUFFER_OWNER_CPU (0) /*!< DMA buffer is allowed to be accessed by CPU */ #define DMA_DESCRIPTOR_BUFFER_OWNER_DMA (1) /*!< DMA buffer is allowed to be accessed by DMA engine */ #define DMA_DESCRIPTOR_BUFFER_MAX_SIZE (4095) /*!< Maximum size of the buffer that can be attached to descriptor */ +#define DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED (4095-3) /*!< Maximum size of the buffer that can be attached to descriptor, and aligned to 4B */ + #ifdef __cplusplus } From 5da5e1801b65ac88a34f31132e88f24db91eff25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20G=C3=BCrtler?= Date: Thu, 25 May 2023 10:11:22 +0200 Subject: [PATCH 2/3] Fix #10804 by running continuous ADC DMA in endless loop instead of restarting after each run (descriptor chain) to avoid losing samples. Use descriptor error callback for GDMA to check for DMA buffer overrun. Signed-off-by: Armando --- components/driver/deprecated/adc_dma_legacy.c | 6 +----- components/esp_adc/adc_continuous.c | 17 +++++++++++------ components/hal/adc_hal.c | 7 ++++++- components/hal/include/hal/adc_hal.h | 10 +++++++++- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/components/driver/deprecated/adc_dma_legacy.c b/components/driver/deprecated/adc_dma_legacy.c index 4870a734e5..4e5616c7c1 100644 --- a/components/driver/deprecated/adc_dma_legacy.c +++ b/components/driver/deprecated/adc_dma_legacy.c @@ -380,17 +380,13 @@ static IRAM_ATTR bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx) } ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); + adc_hal_read_desc_finish (&adc_digi_ctx->hal); if (ret == pdFALSE) { //ringbuffer overflow adc_digi_ctx->ringbuf_overflow_flag = 1; } } - if (status == ADC_HAL_DMA_DESC_NULL) { - //start next turns of dma operation - adc_hal_digi_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf); - } - return (taskAwoken == pdTRUE); } diff --git a/components/esp_adc/adc_continuous.c b/components/esp_adc/adc_continuous.c index 6b08be7eae..3d31f83369 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -61,6 +61,7 @@ static bool s_adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx); #if SOC_GDMA_SUPPORTED static bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data); +static bool adc_dma_descr_err_callback(gdma_channel_handle_t dma_chan, void *user_data); #else static void adc_dma_intr_handler(void *arg); #endif @@ -174,7 +175,8 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi gdma_apply_strategy(adc_ctx->rx_dma_channel, &strategy_config); gdma_rx_event_callbacks_t cbs = { - .on_recv_eof = adc_dma_in_suc_eof_callback + .on_recv_eof = adc_dma_in_suc_eof_callback, + .on_descr_err = adc_dma_descr_err_callback }; gdma_register_rx_event_callbacks(adc_ctx->rx_dma_channel, &cbs, adc_ctx); @@ -261,6 +263,13 @@ static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr; return s_adc_dma_intr(user_data); } + +static bool adc_dma_descr_err_callback(gdma_channel_handle_t dma_chan, void *user_data) +{ + ESP_EARLY_LOGE(ADC_TAG, "GDMA descriptor error occurred, probable ADC data loss, CPU load too high?"); + return false; +} + #else static IRAM_ATTR void adc_dma_intr_handler(void *arg) { @@ -299,6 +308,7 @@ static IRAM_ATTR bool s_adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx) } ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); + adc_hal_read_desc_finish (&adc_digi_ctx->hal); need_yield |= (taskAwoken == pdTRUE); if (adc_digi_ctx->cbs.on_conv_done) { @@ -322,11 +332,6 @@ static IRAM_ATTR bool s_adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx) } } - if (status == ADC_HAL_DMA_DESC_NULL) { - //start next turns of dma operation - adc_hal_digi_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf); - } - return need_yield; } diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index 96fe8be039..6a2f1c2118 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -258,7 +258,7 @@ static void adc_hal_digi_dma_link_descriptors(dma_descriptor_t *desc, uint8_t *d n++; } } - desc[n-1].next = NULL; + desc[n-1].next = desc; } void adc_hal_digi_start(adc_hal_dma_ctx_t *hal, uint8_t *data_buf) @@ -329,6 +329,11 @@ adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, con return ADC_HAL_DMA_DESC_VALID; } +void adc_hal_read_desc_finish(adc_hal_dma_ctx_t *hal) { + // Allow DMA to re-use descriptor. + hal->cur_desc_ptr->dw0.owner = 1; +} + void adc_hal_digi_clr_intr(adc_hal_dma_ctx_t *hal, uint32_t mask) { adc_dma_ll_rx_clear_intr(hal->dev, hal->dma_chan, mask); diff --git a/components/hal/include/hal/adc_hal.h b/components/hal/include/hal/adc_hal.h index d023ff7dd6..daf96a1abc 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -173,7 +173,7 @@ bool adc_hal_check_event(adc_hal_dma_ctx_t *hal, uint32_t mask); #endif /** - * @brief Get the ADC reading result + * @brief Get the ADC reading result. Call adc_hal_read_desc_finish after using the descriptor. * * @param hal Context of the HAL * @param eof_desc_addr The last descriptor that is finished by HW. Should be got from DMA @@ -184,6 +184,14 @@ bool adc_hal_check_event(adc_hal_dma_ctx_t *hal, uint32_t mask); */ adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, const intptr_t eof_desc_addr, uint8_t **buffer, uint32_t *len); +/** + * @brief Finishes reading the current descriptor and frees it for repeated usage by DMA. + * + * @param hal Context of the HAL + */ +void adc_hal_read_desc_finish(adc_hal_dma_ctx_t *hal); + + /** * @brief Clear interrupt * From d8ee45ce081954d27241fc6648793d67f36da20a Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 5 Jun 2023 12:27:14 +0800 Subject: [PATCH 3/3] adc: port gh pr to current adc continuous mode driver DMA EOF may happens per multiple dma descriptors, instead of only one. Closes https://github.com/espressif/esp-idf/pull/11500 --- components/driver/deprecated/adc_dma_legacy.c | 1 - components/esp_adc/adc_continuous.c | 11 +---------- components/hal/adc_hal.c | 17 +++++++++++------ components/hal/include/hal/adc_hal.h | 10 +--------- 4 files changed, 13 insertions(+), 26 deletions(-) diff --git a/components/driver/deprecated/adc_dma_legacy.c b/components/driver/deprecated/adc_dma_legacy.c index 4e5616c7c1..26076bc32c 100644 --- a/components/driver/deprecated/adc_dma_legacy.c +++ b/components/driver/deprecated/adc_dma_legacy.c @@ -380,7 +380,6 @@ static IRAM_ATTR bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx) } ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); - adc_hal_read_desc_finish (&adc_digi_ctx->hal); if (ret == pdFALSE) { //ringbuffer overflow adc_digi_ctx->ringbuf_overflow_flag = 1; diff --git a/components/esp_adc/adc_continuous.c b/components/esp_adc/adc_continuous.c index 3d31f83369..0638cd53ee 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -61,7 +61,6 @@ static bool s_adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx); #if SOC_GDMA_SUPPORTED static bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data); -static bool adc_dma_descr_err_callback(gdma_channel_handle_t dma_chan, void *user_data); #else static void adc_dma_intr_handler(void *arg); #endif @@ -175,8 +174,7 @@ esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_confi gdma_apply_strategy(adc_ctx->rx_dma_channel, &strategy_config); gdma_rx_event_callbacks_t cbs = { - .on_recv_eof = adc_dma_in_suc_eof_callback, - .on_descr_err = adc_dma_descr_err_callback + .on_recv_eof = adc_dma_in_suc_eof_callback }; gdma_register_rx_event_callbacks(adc_ctx->rx_dma_channel, &cbs, adc_ctx); @@ -264,12 +262,6 @@ static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan return s_adc_dma_intr(user_data); } -static bool adc_dma_descr_err_callback(gdma_channel_handle_t dma_chan, void *user_data) -{ - ESP_EARLY_LOGE(ADC_TAG, "GDMA descriptor error occurred, probable ADC data loss, CPU load too high?"); - return false; -} - #else static IRAM_ATTR void adc_dma_intr_handler(void *arg) { @@ -308,7 +300,6 @@ static IRAM_ATTR bool s_adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx) } ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken); - adc_hal_read_desc_finish (&adc_digi_ctx->hal); need_yield |= (taskAwoken == pdTRUE); if (adc_digi_ctx->cbs.on_conv_done) { diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index 6a2f1c2118..053cc5f712 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -235,6 +235,7 @@ static void adc_hal_digi_dma_link_descriptors(dma_descriptor_t *desc, uint8_t *d HAL_ASSERT(((uint32_t)data_buf % 4) == 0); HAL_ASSERT((per_eof_size % 4) == 0); uint32_t n = 0; + dma_descriptor_t *desc_head = desc; while (eof_num--) { uint32_t eof_size = per_eof_size; @@ -258,7 +259,7 @@ static void adc_hal_digi_dma_link_descriptors(dma_descriptor_t *desc, uint8_t *d n++; } } - desc[n-1].next = desc; + desc[n-1].next = desc_head; } void adc_hal_digi_start(adc_hal_dma_ctx_t *hal, uint8_t *data_buf) @@ -313,15 +314,24 @@ adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, con //Find the eof list start eof_desc = eof_desc->next; + eof_desc->dw0.owner = 1; buffer_start = eof_desc->buffer; eof_len += eof_desc->dw0.length; + if ((intptr_t)eof_desc == eof_desc_addr) { + goto valid; + } //Find the eof list end for (int i = 1; i < hal->eof_step; i++) { eof_desc = eof_desc->next; + eof_desc->dw0.owner = 1; eof_len += eof_desc->dw0.length; + if ((intptr_t)eof_desc == eof_desc_addr) { + goto valid; + } } +valid: hal->cur_desc_ptr = eof_desc; *buffer = buffer_start; *len = eof_len; @@ -329,11 +339,6 @@ adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, con return ADC_HAL_DMA_DESC_VALID; } -void adc_hal_read_desc_finish(adc_hal_dma_ctx_t *hal) { - // Allow DMA to re-use descriptor. - hal->cur_desc_ptr->dw0.owner = 1; -} - void adc_hal_digi_clr_intr(adc_hal_dma_ctx_t *hal, uint32_t mask) { adc_dma_ll_rx_clear_intr(hal->dev, hal->dma_chan, mask); diff --git a/components/hal/include/hal/adc_hal.h b/components/hal/include/hal/adc_hal.h index daf96a1abc..d023ff7dd6 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -173,7 +173,7 @@ bool adc_hal_check_event(adc_hal_dma_ctx_t *hal, uint32_t mask); #endif /** - * @brief Get the ADC reading result. Call adc_hal_read_desc_finish after using the descriptor. + * @brief Get the ADC reading result * * @param hal Context of the HAL * @param eof_desc_addr The last descriptor that is finished by HW. Should be got from DMA @@ -184,14 +184,6 @@ bool adc_hal_check_event(adc_hal_dma_ctx_t *hal, uint32_t mask); */ adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_dma_ctx_t *hal, const intptr_t eof_desc_addr, uint8_t **buffer, uint32_t *len); -/** - * @brief Finishes reading the current descriptor and frees it for repeated usage by DMA. - * - * @param hal Context of the HAL - */ -void adc_hal_read_desc_finish(adc_hal_dma_ctx_t *hal); - - /** * @brief Clear interrupt *