diff --git a/components/driver/esp32c3/adc.c b/components/driver/esp32c3/adc.c index df8c520484..5dc01e0583 100644 --- a/components/driver/esp32c3/adc.c +++ b/components/driver/esp32c3/adc.c @@ -32,6 +32,7 @@ #include "hal/adc_hal.h" #include "hal/dma_types.h" #include "esp32c3/esp_efuse_rtc_calib.h" +#include "esp_private/gdma.h" #define ADC_CHECK_RET(fun_ret) ({ \ if (fun_ret != ESP_OK) { \ @@ -87,6 +88,7 @@ typedef struct adc_digi_context_t { 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) + gdma_channel_handle_t rx_dma_channel; //dma rx channel handle RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler bool ringbuf_overflow_flag; //1: ringbuffer overflow bool driver_start_flag; //1: driver is started; 0: driver is stoped @@ -104,7 +106,7 @@ static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t cha /*--------------------------------------------------------------- ADC Continuous Read Mode (via DMA) ---------------------------------------------------------------*/ -static void adc_dma_intr(void* arg); +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 int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel) { @@ -149,11 +151,6 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) goto cleanup; } - ret = esp_intr_alloc(SOC_GDMA_ADC_INTR_SOURCE, 0, adc_dma_intr, (void *)s_adc_digi_ctx, &s_adc_digi_ctx->dma_intr_hdl); - if (ret != ESP_OK) { - goto cleanup; - } - //ringbuffer s_adc_digi_ctx->ringbuf_hdl = xRingbufferCreate(init_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF); if (!s_adc_digi_ctx->ringbuf_hdl) { @@ -161,7 +158,7 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) goto cleanup; } - //malloc internal buffer + //malloc internal buffer used by DMA s_adc_digi_ctx->bytes_between_intr = init_config->conv_num_each_intr; s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, s_adc_digi_ctx->bytes_between_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL); if (!s_adc_digi_ctx->rx_dma_buf) { @@ -176,7 +173,6 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) goto cleanup; } s_adc_digi_ctx->hal_dma_config.desc_max_num = INTERNAL_BUF_NUM; - s_adc_digi_ctx->hal_dma_config.dma_chan = init_config->dma_chan; //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)); @@ -185,6 +181,7 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) goto cleanup; } + //init gpio pins if (init_config->adc1_chan_mask) { ret = adc_digi_gpio_init(ADC_NUM_1, init_config->adc1_chan_mask); if (ret != ESP_OK) { @@ -198,8 +195,33 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) } } + //alloc rx gdma channel + gdma_channel_alloc_config_t rx_alloc_config = { + .direction = GDMA_CHANNEL_DIRECTION_RX, + }; + ret = gdma_new_channel(&rx_alloc_config, &s_adc_digi_ctx->rx_dma_channel); + if (ret != ESP_OK) { + goto cleanup; + } + gdma_connect(s_adc_digi_ctx->rx_dma_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0)); + + gdma_strategy_config_t strategy_config = { + .auto_update_desc = true, + .owner_check = true + }; + 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 + }; + gdma_register_rx_event_callbacks(s_adc_digi_ctx->rx_dma_channel, &cbs, s_adc_digi_ctx); + + 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; + + //enable SARADC module clock periph_module_enable(PERIPH_SARADC_MODULE); - periph_module_enable(PERIPH_GDMA_MODULE); adc_hal_calibration_init(ADC_NUM_1); adc_hal_calibration_init(ADC_NUM_2); @@ -212,45 +234,51 @@ cleanup: } -static IRAM_ATTR void adc_dma_intr(void *arg) +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; + return adc_dma_intr(adc_digi_ctx); +} + +static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx) { portBASE_TYPE taskAwoken = 0; BaseType_t ret; - //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); - - while (s_adc_digi_ctx->hal_dma_config.cur_desc_ptr->dw0.owner == 0) { - - dma_descriptor_t *current_desc = s_adc_digi_ctx->hal_dma_config.cur_desc_ptr; - ret = xRingbufferSendFromISR(s_adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken); + 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 - s_adc_digi_ctx->ringbuf_overflow_flag = 1; + adc_digi_ctx->ringbuf_overflow_flag = 1; } - s_adc_digi_ctx->hal_dma_config.desc_cnt += 1; + adc_digi_ctx->hal_dma_config.desc_cnt += 1; //cycle the dma descriptor and buffers - s_adc_digi_ctx->hal_dma_config.cur_desc_ptr = s_adc_digi_ctx->hal_dma_config.cur_desc_ptr->next; - if (!s_adc_digi_ctx->hal_dma_config.cur_desc_ptr) { + 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 (!s_adc_digi_ctx->hal_dma_config.cur_desc_ptr) { + if (!adc_digi_ctx->hal_dma_config.cur_desc_ptr) { - assert(s_adc_digi_ctx->hal_dma_config.desc_cnt == s_adc_digi_ctx->hal_dma_config.desc_max_num); + assert(adc_digi_ctx->hal_dma_config.desc_cnt == adc_digi_ctx->hal_dma_config.desc_max_num); //reset the current descriptor status - 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; + 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; //start next turns of dma operation - 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_rxdma_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config); + 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); } if(taskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); + return true; + } else { + return false; } } @@ -387,11 +415,13 @@ esp_err_t adc_digi_deinitialize(void) free(s_adc_digi_ctx->rx_dma_buf); free(s_adc_digi_ctx->hal_dma_config.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); + free(s_adc_digi_ctx); s_adc_digi_ctx = NULL; periph_module_disable(PERIPH_SARADC_MODULE); - periph_module_disable(PERIPH_GDMA_MODULE); return ESP_OK; } diff --git a/components/driver/include/driver/adc_common.h b/components/driver/include/driver/adc_common.h index 52b7d60c38..66b34a47b7 100644 --- a/components/driver/include/driver/adc_common.h +++ b/components/driver/include/driver/adc_common.h @@ -137,9 +137,8 @@ typedef enum { typedef struct adc_digi_init_config_s { uint32_t max_store_buf_size; ///< Max length of the converted data that driver can store before they are processed. When this length is reached, driver will dump out all the old data and start to store them again. uint32_t conv_num_each_intr; ///< Bytes of data that can be converted in 1 interrupt. - uint32_t dma_chan; ///< DMA channel. - uint16_t adc1_chan_mask; ///< Channel list of ADC1 to be initialized. - uint16_t adc2_chan_mask; ///< Channel list of ADC2 to be initialized. + uint32_t adc1_chan_mask; ///< Channel list of ADC1 to be initialized. + uint32_t adc2_chan_mask; ///< Channel list of ADC2 to be initialized. } adc_digi_init_config_t; #endif diff --git a/components/driver/test/test_adc_dma.c b/components/driver/test/test_adc_dma.c index 9122509c6c..5946c092ef 100644 --- a/components/driver/test/test_adc_dma.c +++ b/components/driver/test/test_adc_dma.c @@ -122,7 +122,6 @@ static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask adc_digi_init_config_t adc_dma_config = { .max_store_buf_size = TEST_COUNT*2, .conv_num_each_intr = 128, - .dma_chan = SOC_GDMA_ADC_DMA_CHANNEL, .adc1_chan_mask = adc1_chan_mask, .adc2_chan_mask = adc2_chan_mask, }; diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index ba2a42c833..7ff8f984bd 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -281,10 +281,7 @@ void adc_hal_digi_stop(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t 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_enable_clock(adc_dma_ctx->dev, true); gdma_ll_clear_interrupt_status(adc_dma_ctx->dev, dma_config->dma_chan, UINT32_MAX); - gdma_ll_rx_connect_to_periph(adc_dma_ctx->dev, dma_config->dma_chan, SOC_GDMA_TRIG_PERIPH_ADC0); - adc_ll_adc1_onetime_sample_enable(false); adc_ll_adc2_onetime_sample_enable(false); } diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index c63a0c3867..7d75ce4a18 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -14,14 +14,12 @@ // Attention: These fixed DMA channels are temporarily workaround before we have a centralized DMA controller API to help alloc the channel dynamically // Remove them when GDMA driver API is ready #define SOC_GDMA_SPI2_DMA_CHANNEL (2) -#define SOC_GDMA_ADC_DMA_CHANNEL (0) //NOTE: The CHx number should be consistent with the selected DMA channel above #define SOC_GDMA_SPI2_INTR_SOURCE ETS_DMA_CH2_INTR_SOURCE //On C3, there is only 1 GPSPI controller (GPSPI2) #define SOC_GDMA_SPI3_DMA_CHANNEL SOC_GDMA_SPI2_DMA_CHANNEL -#define SOC_GDMA_ADC_INTR_SOURCE ETS_DMA_CH0_INTR_SOURCE #include "rmt_caps.h" diff --git a/examples/peripherals/adc/adc_dma/main/adc_dma_example_main.c b/examples/peripherals/adc/adc_dma/main/adc_dma_example_main.c index bac3dece22..774a1eaf06 100644 --- a/examples/peripherals/adc/adc_dma/main/adc_dma_example_main.c +++ b/examples/peripherals/adc/adc_dma/main/adc_dma_example_main.c @@ -7,7 +7,6 @@ #include "driver/adc.h" #define TIMES 256 -#define DMA_CHANNEL 0 static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num) { @@ -17,7 +16,6 @@ static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask adc_digi_init_config_t adc_dma_config = { .max_store_buf_size = 1024, .conv_num_each_intr = 256, - .dma_chan = SOC_GDMA_ADC_DMA_CHANNEL, .adc1_chan_mask = adc1_chan_mask, .adc2_chan_mask = adc2_chan_mask, };