diff --git a/components/driver/deprecated/adc_dma_legacy.c b/components/driver/deprecated/adc_dma_legacy.c index 72f060341f..84c316e48d 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 954b6fe7ab..736e3e0b25 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -93,6 +93,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 @@ -206,7 +207,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); @@ -293,6 +295,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) { @@ -331,6 +340,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) { @@ -354,11 +364,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 2286c4296a..01d0938dea 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -261,7 +261,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) @@ -332,6 +332,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 8b5cd28860..742d1e178c 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -188,7 +188,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 @@ -199,6 +199,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 *