diff --git a/components/driver/esp32c3/adc.c b/components/driver/esp32c3/adc.c index 3c0932564e..cf967a8057 100644 --- a/components/driver/esp32c3/adc.c +++ b/components/driver/esp32c3/adc.c @@ -83,13 +83,12 @@ static _lock_t sar_adc2_mutex; #define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF typedef struct adc_digi_context_t { - intr_handle_t dma_intr_hdl; //MD interrupt handle uint32_t bytes_between_intr; //bytes between in suc eof intr uint8_t *rx_dma_buf; //dma buffer - adc_dma_hal_context_t hal_dma; //dma context (hal) - adc_dma_hal_config_t hal_dma_config; //dma config (hal) + adc_hal_context_t hal; //hal context gdma_channel_handle_t rx_dma_channel; //dma rx channel handle RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler + intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel bool ringbuf_overflow_flag; //1: ringbuffer overflow bool driver_start_flag; //1: driver is started; 0: driver is stoped bool use_adc1; //1: ADC unit1 will be used; 0: ADC unit1 won't be used. @@ -167,12 +166,11 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) } //malloc dma descriptor - s_adc_digi_ctx->hal_dma_config.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA); - if (!s_adc_digi_ctx->hal_dma_config.rx_desc) { + s_adc_digi_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA); + if (!s_adc_digi_ctx->hal.rx_desc) { ret = ESP_ERR_NO_MEM; goto cleanup; } - s_adc_digi_ctx->hal_dma_config.desc_max_num = INTERNAL_BUF_NUM; //malloc pattern table s_adc_digi_ctx->digi_controller_config.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_table_t)); @@ -218,7 +216,13 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) int dma_chan; gdma_get_channel_id(s_adc_digi_ctx->rx_dma_channel, &dma_chan); - s_adc_digi_ctx->hal_dma_config.dma_chan = dma_chan; + + adc_hal_config_t config = { + .desc_max_num = INTERNAL_BUF_NUM, + .dma_chan = dma_chan, + .eof_num = s_adc_digi_ctx->bytes_between_intr / 4 + }; + adc_hal_context_config(&s_adc_digi_ctx->hal, &config); //enable SARADC module clock periph_module_enable(PERIPH_SARADC_MODULE); @@ -239,6 +243,7 @@ static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx); 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) { adc_digi_context_t *adc_digi_ctx = (adc_digi_context_t *)user_data; + adc_digi_ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr; return adc_dma_intr(adc_digi_ctx); } @@ -246,33 +251,25 @@ static IRAM_ATTR bool 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; + + while (1) { + status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, ¤t_desc); + if (status != ADC_DMA_DESC_FINISH) { + break; + } - while (adc_digi_ctx->hal_dma_config.cur_desc_ptr->dw0.owner == 0) { - dma_descriptor_t *current_desc = adc_digi_ctx->hal_dma_config.cur_desc_ptr; ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken); if (ret == pdFALSE) { //ringbuffer overflow adc_digi_ctx->ringbuf_overflow_flag = 1; } - - adc_digi_ctx->hal_dma_config.desc_cnt += 1; - //cycle the dma descriptor and buffers - adc_digi_ctx->hal_dma_config.cur_desc_ptr = adc_digi_ctx->hal_dma_config.cur_desc_ptr->next; - if (!adc_digi_ctx->hal_dma_config.cur_desc_ptr) { - break; - } } - if (!adc_digi_ctx->hal_dma_config.cur_desc_ptr) { - - assert(adc_digi_ctx->hal_dma_config.desc_cnt == adc_digi_ctx->hal_dma_config.desc_max_num); - //reset the current descriptor status - adc_digi_ctx->hal_dma_config.cur_desc_ptr = adc_digi_ctx->hal_dma_config.rx_desc; - adc_digi_ctx->hal_dma_config.desc_cnt = 0; - + if (status == ADC_DMA_DESC_NULL) { //start next turns of dma operation - adc_hal_digi_dma_multi_descriptor(&adc_digi_ctx->hal_dma_config, adc_digi_ctx->rx_dma_buf, adc_digi_ctx->bytes_between_intr, adc_digi_ctx->hal_dma_config.desc_max_num); - adc_hal_digi_rxdma_start(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config); + adc_hal_digi_rxdma_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf, adc_digi_ctx->bytes_between_intr); } if(taskAwoken == pdTRUE) { @@ -309,26 +306,16 @@ esp_err_t adc_digi_start(void) } adc_hal_init(); - adc_hal_arbiter_config(&config); - adc_hal_digi_init(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + adc_hal_digi_init(&s_adc_digi_ctx->hal); adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_config); - //create dma descriptors - adc_hal_digi_dma_multi_descriptor(&s_adc_digi_ctx->hal_dma_config, s_adc_digi_ctx->rx_dma_buf, s_adc_digi_ctx->bytes_between_intr, s_adc_digi_ctx->hal_dma_config.desc_max_num); - adc_hal_digi_set_eof_num(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, (s_adc_digi_ctx->bytes_between_intr)/4); - //set the current descriptor pointer - s_adc_digi_ctx->hal_dma_config.cur_desc_ptr = s_adc_digi_ctx->hal_dma_config.rx_desc; - s_adc_digi_ctx->hal_dma_config.desc_cnt = 0; - - //enable in suc eof intr - adc_hal_digi_ena_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); - - //start ADC - adc_hal_digi_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); - + //reset ADC and DMA + adc_hal_fifo_reset(&s_adc_digi_ctx->hal); //start DMA - adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf, s_adc_digi_ctx->bytes_between_intr); + //start ADC + adc_hal_digi_start(&s_adc_digi_ctx->hal); return ESP_OK; } @@ -342,13 +329,13 @@ esp_err_t adc_digi_stop(void) s_adc_digi_ctx->driver_start_flag = 0; //disable the in suc eof intrrupt - adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); + adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT); //clear the in suc eof interrupt - adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT); - //stop DMA - adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT); //stop ADC - adc_hal_digi_stop(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + adc_hal_digi_stop(&s_adc_digi_ctx->hal); + //stop DMA + adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal); adc_hal_digi_deinit(); ADC_DIGI_LOCK_RELEASE(); @@ -403,17 +390,13 @@ esp_err_t adc_digi_deinitialize(void) return ESP_ERR_INVALID_STATE; } - if (s_adc_digi_ctx->dma_intr_hdl) { - esp_intr_free(s_adc_digi_ctx->dma_intr_hdl); - } - if(s_adc_digi_ctx->ringbuf_hdl) { vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl); s_adc_digi_ctx->ringbuf_hdl = NULL; } free(s_adc_digi_ctx->rx_dma_buf); - free(s_adc_digi_ctx->hal_dma_config.rx_desc); + free(s_adc_digi_ctx->hal.rx_desc); free(s_adc_digi_ctx->digi_controller_config.adc_pattern); gdma_disconnect(s_adc_digi_ctx->rx_dma_channel); gdma_del_channel(s_adc_digi_ctx->rx_dma_channel); diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index 7ff8f984bd..7456911115 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -209,11 +209,34 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc /*--------------------------------------------------------------- DMA setting ---------------------------------------------------------------*/ -void adc_hal_digi_dma_multi_descriptor(adc_dma_hal_config_t *dma_config, uint8_t *data_buf, uint32_t size, uint32_t num) +void adc_hal_context_config(adc_hal_context_t *hal, const adc_hal_config_t *config) +{ + hal->dev = &GDMA; + hal->desc_dummy_head.next = hal->rx_desc; + hal->desc_max_num = config->desc_max_num; + hal->dma_chan = config->dma_chan; + hal->eof_num = config->eof_num; +} + +void adc_hal_digi_init(adc_hal_context_t *hal) +{ + gdma_ll_clear_interrupt_status(hal->dev, hal->dma_chan, UINT32_MAX); + gdma_ll_enable_interrupt(hal->dev, hal->dma_chan, GDMA_LL_EVENT_RX_SUC_EOF, true); + adc_ll_digi_dma_set_eof_num(hal->eof_num); + adc_ll_adc1_onetime_sample_enable(false); + adc_ll_adc2_onetime_sample_enable(false); +} + +void adc_hal_fifo_reset(adc_hal_context_t *hal) +{ + adc_ll_digi_reset(); + gdma_ll_rx_reset_channel(hal->dev, hal->dma_chan); +} + +static void adc_hal_digi_dma_multi_descriptor(dma_descriptor_t *desc, uint8_t *data_buf, uint32_t size, uint32_t num) { assert(((uint32_t)data_buf % 4) == 0); assert((size % 4) == 0); - dma_descriptor_t *desc = dma_config->rx_desc; uint32_t n = 0; while (num--) { @@ -228,49 +251,54 @@ void adc_hal_digi_dma_multi_descriptor(adc_dma_hal_config_t *dma_config, uint8_t desc[n-1].next = NULL; } -void adc_hal_digi_rxdma_start(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config) +void adc_hal_digi_rxdma_start(adc_hal_context_t *hal, uint8_t *data_buf, uint32_t size) { - gdma_ll_rx_reset_channel(adc_dma_ctx->dev, dma_config->dma_chan); - gdma_ll_rx_set_desc_addr(adc_dma_ctx->dev, dma_config->dma_chan, (uint32_t)dma_config->rx_desc); - gdma_ll_rx_start(adc_dma_ctx->dev, dma_config->dma_chan); + //reset the current descriptor address + hal->cur_desc_ptr = &hal->desc_dummy_head; + adc_hal_digi_dma_multi_descriptor(hal->rx_desc, data_buf, size, hal->desc_max_num); + gdma_ll_rx_set_desc_addr(hal->dev, hal->dma_chan, (uint32_t)hal->rx_desc); + gdma_ll_rx_start(hal->dev, hal->dma_chan); } -void adc_hal_digi_rxdma_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config) -{ - gdma_ll_rx_stop(adc_dma_ctx->dev, dma_config->dma_chan); -} - -void adc_hal_digi_ena_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask) -{ - gdma_ll_enable_interrupt(adc_dma_ctx->dev, dma_config->dma_chan, mask, true); -} - -void adc_hal_digi_clr_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask) -{ - gdma_ll_clear_interrupt_status(adc_dma_ctx->dev, dma_config->dma_chan, mask); -} - -void adc_hal_digi_dis_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask) -{ - gdma_ll_enable_interrupt(adc_dma_ctx->dev, dma_config->dma_chan, mask, false); -} - -void adc_hal_digi_set_eof_num(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t num) -{ - adc_ll_digi_dma_set_eof_num(num); -} - -void adc_hal_digi_start(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config) +void adc_hal_digi_start(adc_hal_context_t *hal) { //Set to 1: the ADC data will be sent to the DMA adc_ll_digi_dma_enable(); //enable sar adc timer adc_ll_digi_trigger_enable(); - //reset the adc state - adc_ll_digi_reset(); } -void adc_hal_digi_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config) +adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_context_t *hal, const intptr_t eof_desc_addr, dma_descriptor_t **cur_desc) +{ + if (!hal->cur_desc_ptr->next) { + return ADC_DMA_DESC_NULL; + } + if ((intptr_t)hal->cur_desc_ptr == eof_desc_addr) { + return ADC_DMA_DESC_NOT_FINISH; + } + + hal->cur_desc_ptr = hal->cur_desc_ptr->next; + *cur_desc = hal->cur_desc_ptr; + + return ADC_DMA_DESC_FINISH; +} + +void adc_hal_digi_rxdma_stop(adc_hal_context_t *hal) +{ + gdma_ll_rx_stop(hal->dev, hal->dma_chan); +} + +void adc_hal_digi_clr_intr(adc_hal_context_t *hal, uint32_t mask) +{ + gdma_ll_clear_interrupt_status(hal->dev, hal->dma_chan, mask); +} + +void adc_hal_digi_dis_intr(adc_hal_context_t *hal, uint32_t mask) +{ + gdma_ll_enable_interrupt(hal->dev, hal->dma_chan, mask, false); +} + +void adc_hal_digi_stop(adc_hal_context_t *hal) { //Set to 0: the ADC data won't be sent to the DMA adc_ll_digi_dma_disable(); @@ -278,14 +306,6 @@ void adc_hal_digi_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t adc_ll_digi_trigger_disable(); } -void adc_hal_digi_init(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config) -{ - adc_dma_ctx->dev = &GDMA; - gdma_ll_clear_interrupt_status(adc_dma_ctx->dev, dma_config->dma_chan, UINT32_MAX); - adc_ll_adc1_onetime_sample_enable(false); - adc_ll_adc2_onetime_sample_enable(false); -} - /*--------------------------------------------------------------- Single Read ---------------------------------------------------------------*/ diff --git a/components/hal/include/hal/adc_hal.h b/components/hal/include/hal/adc_hal.h index db7a1e3aa2..4754074154 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -4,6 +4,51 @@ #include "hal/adc_types.h" #include "hal/adc_ll.h" +#if CONFIG_IDF_TARGET_ESP32C3 +#include "soc/gdma_struct.h" +#include "hal/gdma_ll.h" +#include "hal/dma_types.h" +#include "hal/adc_ll.h" +#include "hal/dma_types.h" +#include "esp_err.h" + +/** + * @brief Enum for DMA descriptor status + */ +typedef enum adc_hal_dma_desc_status_t{ + ADC_DMA_DESC_FINISH = 0, ///< This DMA descriptor is written by HW already + ADC_DMA_DESC_NOT_FINISH = 1, ///< This DMA descriptor is not written by HW yet + ADC_DMA_DESC_NULL = 2 ///< This DMA descriptor is NULL +} adc_hal_dma_desc_status_t; + +/** + * @brief Configuration of the HAL + */ +typedef struct adc_hal_config_t { + uint32_t desc_max_num; ///< Number of the descriptors linked once + uint32_t dma_chan; ///< DMA channel to be used + uint32_t eof_num; ///< Bytes between 2 in_suc_eof interrupts +} adc_hal_config_t; + +/** + * @brief Context of the HAL + */ +typedef struct adc_hal_context_t { + /**< this needs to be malloced by the driver layer first */ + dma_descriptor_t *rx_desc; ///< DMA descriptors + + /**< these will be assigned by hal layer itself */ + gdma_dev_t *dev; ///< GDMA address + dma_descriptor_t desc_dummy_head; ///< Dummy DMA descriptor for ``cur_desc_ptr`` to start + dma_descriptor_t *cur_desc_ptr; ///< Pointer to the current descriptor + + /**< these need to be configured by `adc_hal_config_t` via driver layer*/ + uint32_t desc_max_num; ///< Number of the descriptors linked once + uint32_t dma_chan; ///< DMA channel to be used + uint32_t eof_num; ///< Bytes between 2 in_suc_eof interrupts +} adc_hal_context_t; +#endif + /*--------------------------------------------------------------- Common setting ---------------------------------------------------------------*/ @@ -252,44 +297,85 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc /*--------------------------------------------------------------- DMA setting ---------------------------------------------------------------*/ -#include "soc/gdma_struct.h" -#include "hal/gdma_ll.h" -#include "hal/dma_types.h" -#include "hal/adc_ll.h" -#include "hal/dma_types.h" -#include "esp_err.h" +/** + * @brief Initialize the hal context + * + * @param hal Context of the HAL + * @param config Configuration of the HAL + */ +void adc_hal_context_config(adc_hal_context_t *hal, const adc_hal_config_t *config); -typedef struct adc_dma_hal_context_t { - gdma_dev_t *dev; //address of the general DMA -} adc_dma_hal_context_t; +/** + * @brief Initialize the HW + * + * @param hal Context of the HAL + */ +void adc_hal_digi_init(adc_hal_context_t *hal); -typedef struct adc_dma_hal_config_t { - dma_descriptor_t *rx_desc; //dma descriptor - dma_descriptor_t *cur_desc_ptr; //pointer to the current descriptor - uint32_t desc_max_num; //number of the descriptors linked once - uint32_t desc_cnt; - uint32_t dma_chan; -} adc_dma_hal_config_t; +/** + * @brief Reset ADC / DMA fifo + * + * @param hal Context of the HAL + */ +void adc_hal_fifo_reset(adc_hal_context_t *hal); -void adc_hal_digi_dma_multi_descriptor(adc_dma_hal_config_t *dma_config, uint8_t *data_buf, uint32_t size, uint32_t num); +/** + * @brief Start DMA + * + * @param hal Context of the HAL + * @param data_buf Pointer to the data buffer + * @param size Size of the buffer + */ +void adc_hal_digi_rxdma_start(adc_hal_context_t *hal, uint8_t *data_buf, uint32_t size); -void adc_hal_digi_rxdma_start(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); +/** + * @brief Start ADC + * + * @param hal Context of the HAL + */ +void adc_hal_digi_start(adc_hal_context_t *hal); -void adc_hal_digi_rxdma_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); +/** + * @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 + * @param[out] cur_desc The descriptor with ADC reading result (from the 1st one to the last one (``eof_desc_addr``)) + * + * @return See ``adc_hal_dma_desc_status_t`` + */ +adc_hal_dma_desc_status_t adc_hal_get_reading_result(adc_hal_context_t *hal, const intptr_t eof_desc_addr, dma_descriptor_t **cur_desc); -void adc_hal_digi_ena_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask); +/** + * @brief Stop DMA + * + * @param hal Context of the HAL + */ +void adc_hal_digi_rxdma_stop(adc_hal_context_t *hal); -void adc_hal_digi_clr_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask); +/** + * @brief Clear interrupt + * + * @param hal Context of the HAL + * @param mask mask of the interrupt + */ +void adc_hal_digi_clr_intr(adc_hal_context_t *hal, uint32_t mask); -void adc_hal_digi_dis_intr(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t mask); +/** + * @brief Enable interrupt + * + * @param hal Context of the HAL + * @param mask mask of the interrupt + */ +void adc_hal_digi_dis_intr(adc_hal_context_t *hal, uint32_t mask); -void adc_hal_digi_set_eof_num(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config, uint32_t num); +/** + * @brief Stop ADC + * + * @param hal Context of the HAL + */ +void adc_hal_digi_stop(adc_hal_context_t *hal); -void adc_hal_digi_start(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); - -void adc_hal_digi_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); - -void adc_hal_digi_init(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t *dma_config); /*--------------------------------------------------------------- Single Read