diff --git a/components/driver/adc.c b/components/driver/adc.c index b533f3c22d..3311d1c799 100644 --- a/components/driver/adc.c +++ b/components/driver/adc.c @@ -114,6 +114,7 @@ static IRAM_ATTR bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx); #if SOC_GDMA_SUPPORTED static IRAM_ATTR 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 IRAM_ATTR void adc_dma_intr_handler(void *arg); #endif @@ -230,7 +231,8 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) gdma_apply_strategy(s_adc_digi_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(s_adc_digi_ctx->rx_dma_channel, &cbs, s_adc_digi_ctx); @@ -312,6 +314,13 @@ static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan s_adc_digi_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) { @@ -349,17 +358,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/hal/adc_hal.c b/components/hal/adc_hal.c index b5d2fa8b57..a9ea744f5d 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -354,7 +354,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_context_t *hal, uint8_t *data_buf) @@ -428,6 +428,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_context_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 3973c40489..4708c52754 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -215,7 +215,7 @@ bool adc_hal_check_event(adc_hal_context_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 @@ -375,3 +375,10 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc * @prarm adc_n ADC unit. */ #define adc_hal_rtc_output_invert(adc_n, inv_en) adc_ll_rtc_output_invert(adc_n, inv_en) + +/** + * @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);