diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index c608893847..32ffd67b48 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -20,6 +20,12 @@ set(srcs set(includes "include" "${target}/include" "deprecated") +if(CONFIG_SOC_ADC_SUPPORTED) + list(APPEND srcs + "adc_common.c" + "adc.c") +endif() + if(CONFIG_SOC_MCPWM_SUPPORTED) list(APPEND srcs "mcpwm.c") endif() @@ -30,8 +36,7 @@ endif() if(${target} STREQUAL "esp32") # SDMMC and MCPWM are in ESP32 only. - list(APPEND srcs "adc_common.c" - "dac_common.c" + list(APPEND srcs "dac_common.c" "sdio_slave.c" "sdmmc_host.c" "i2s.c" @@ -41,13 +46,13 @@ if(${target} STREQUAL "esp32") "touch_sensor_common.c" "esp32/touch_sensor.c" "esp32/adc.c" + "adc_deprecated.c" "esp32/dac.c" "twai.c") endif() if(IDF_TARGET STREQUAL "esp32s2") - list(APPEND srcs "adc_common.c" - "dac_common.c" + list(APPEND srcs "dac_common.c" "dedic_gpio.c" "spi_slave_hd.c" "touch_sensor_common.c" @@ -58,13 +63,13 @@ if(IDF_TARGET STREQUAL "esp32s2") "esp32s2/rtc_tempsensor.c" "esp32s2/touch_sensor.c" "esp32s2/adc.c" + "adc_deprecated.c" "esp32s2/adc2_init_cal.c" "esp32s2/dac.c") endif() if(${target} STREQUAL "esp32s3") - list(APPEND srcs "adc_common.c" - "dedic_gpio.c" + list(APPEND srcs "dedic_gpio.c" "sdmmc_host.c" "sdmmc_transaction.c" "rmt.c" @@ -79,13 +84,11 @@ endif() if(IDF_TARGET STREQUAL "esp32c3") list(APPEND srcs "spi_slave_hd.c" - "adc_common.c" "dedic_gpio.c" "usb_serial_jtag.c" "i2s.c" "rmt.c" "sigmadelta.c" - "esp32c3/adc.c" "esp32c3/adc2_init_cal.c" "esp32c3/rtc_tempsensor.c" "twai.c") @@ -93,12 +96,10 @@ endif() if(IDF_TARGET STREQUAL "esp32h2") list(APPEND srcs "spi_slave_hd.c" - "adc_common.c" "dedic_gpio.c" "i2s.c" "rmt.c" "sigmadelta.c" - "esp32h2/adc.c" "esp32h2/rtc_tempsensor.c" "twai.c") endif() diff --git a/components/driver/esp32c3/adc.c b/components/driver/adc.c similarity index 50% rename from components/driver/esp32c3/adc.c rename to components/driver/adc.c index dd8d3c1247..0e2dc19d9b 100644 --- a/components/driver/esp32c3/adc.c +++ b/components/driver/adc.c @@ -12,49 +12,48 @@ #include "esp_intr_alloc.h" #include "esp_log.h" #include "esp_pm.h" +#include "esp_check.h" #include "sys/lock.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/timers.h" #include "freertos/ringbuf.h" -#include "esp32c3/rom/ets_sys.h" #include "esp_private/periph_ctrl.h" #include "driver/gpio.h" #include "driver/adc.h" #include "hal/adc_types.h" #include "hal/adc_hal.h" #include "hal/dma_types.h" +//For calibration +#if CONFIG_IDF_TARGET_ESP32S2 +#include "esp_efuse_rtc_table.h" +#elif SOC_ADC_CALIBRATION_V1_SUPPORTED #include "esp_efuse_rtc_calib.h" +#endif +//For DMA +#if SOC_GDMA_SUPPORTED #include "esp_private/gdma.h" - -#define ADC_CHECK_RET(fun_ret) ({ \ - if (fun_ret != ESP_OK) { \ - ESP_LOGE(ADC_TAG,"%s(%d)",__FUNCTION__,__LINE__); \ - return ESP_FAIL; \ - } \ -}) +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "hal/spi_types.h" +#include "driver/spi_common_internal.h" +#elif CONFIG_IDF_TARGET_ESP32 +#include "driver/i2s.h" +#include "hal/i2s_types.h" +#include "soc/i2s_periph.h" +#include "esp_private/i2s_platform.h" +#endif static const char *ADC_TAG = "ADC"; -#define ADC_CHECK(a, str, ret_val) ({ \ - if (!(a)) { \ - ESP_LOGE(ADC_TAG,"%s(%d) :%s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } \ -}) - #define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel]) -#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG) - extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. #define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) #define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) /** * 1. sar_adc1_lock: this mutex lock is to protect the SARADC1 module. - * 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module. On C3, it is controlled by the digital controller - * and PWDET controller. + * 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module. * 3. adc_reg_lock: this spin lock is to protect the shared registers used by ADC1 / ADC2 single read mode. */ static _lock_t sar_adc1_lock; @@ -68,35 +67,55 @@ portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED; #define ADC_REG_LOCK_EXIT() portEXIT_CRITICAL(&adc_reg_lock) #define INTERNAL_BUF_NUM 5 -#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF /*--------------------------------------------------------------- Digital Controller Context ---------------------------------------------------------------*/ typedef struct adc_digi_context_t { - uint8_t *rx_dma_buf; //dma buffer - 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. - bool use_adc2; //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not. - adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation. - adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation. - adc_digi_config_t digi_controller_config; //Digital Controller Configuration - esp_pm_lock_handle_t pm_lock; //For power management + uint8_t *rx_dma_buf; //dma buffer + adc_hal_context_t hal; //hal context +#if SOC_GDMA_SUPPORTED + gdma_channel_handle_t rx_dma_channel; //dma rx channel handle +#elif CONFIG_IDF_TARGET_ESP32S2 + spi_host_device_t spi_host; //ADC uses this SPI DMA + intr_handle_t intr_hdl; //Interrupt handler +#elif CONFIG_IDF_TARGET_ESP32 + i2s_port_t i2s_host; //ADC uses this I2S DMA + intr_handle_t intr_hdl; //Interrupt handler +#endif + 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. + bool use_adc2; //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not. + adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation. + adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation. + adc_hal_digi_ctrlr_cfg_t hal_digi_ctrlr_cfg; //Hal digital controller configuration + esp_pm_lock_handle_t pm_lock; //For power management } adc_digi_context_t; static adc_digi_context_t *s_adc_digi_ctx = NULL; +#ifdef CONFIG_PM_ENABLE +//Only for deprecated API +extern esp_pm_lock_handle_t adc_digi_arbiter_lock; +#endif //CONFIG_PM_ENABLE -static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan, adc_atten_t atten); +#if SOC_ADC_CALIBRATION_V1_SUPPORTED +uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan, adc_atten_t atten); +#endif /*--------------------------------------------------------------- ADC Continuous Read Mode (via DMA) ---------------------------------------------------------------*/ +//Function to address transaction +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); +#else +static IRAM_ATTR void adc_dma_intr_handler(void *arg); +#endif static int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel) { @@ -149,7 +168,7 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) } //malloc internal buffer used by DMA - s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL); + s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); if (!s_adc_digi_ctx->rx_dma_buf) { ret = ESP_ERR_NO_MEM; goto cleanup; @@ -163,8 +182,8 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) } //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)); - if (!s_adc_digi_ctx->digi_controller_config.adc_pattern) { + s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_config_t)); + if (!s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern) { ret = ESP_ERR_NO_MEM; goto cleanup; } @@ -190,6 +209,7 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) } } +#if SOC_GDMA_SUPPORTED //alloc rx gdma channel gdma_channel_alloc_config_t rx_alloc_config = { .direction = GDMA_CHANNEL_DIRECTION_RX, @@ -214,7 +234,50 @@ 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); +#elif CONFIG_IDF_TARGET_ESP32S2 + //ADC utilises SPI3 DMA on ESP32S2 + bool spi_success = false; + uint32_t dma_chan = 0; + + spi_success = spicommon_periph_claim(SPI3_HOST, "adc"); + ret = spicommon_dma_chan_alloc(SPI3_HOST, SPI_DMA_CH_AUTO, &dma_chan, &dma_chan); + if (ret == ESP_OK) { + s_adc_digi_ctx->spi_host = SPI3_HOST; + } + if (!spi_success || (s_adc_digi_ctx->spi_host != SPI3_HOST)) { + goto cleanup; + } + + ret = esp_intr_alloc(spicommon_irqdma_source_for_host(s_adc_digi_ctx->spi_host), 0, adc_dma_intr_handler, + (void *)s_adc_digi_ctx, &s_adc_digi_ctx->intr_hdl); + if (ret != ESP_OK) { + goto cleanup; + } + +#elif CONFIG_IDF_TARGET_ESP32 + //ADC utilises I2S0 DMA on ESP32 + uint32_t dma_chan = 0; + ret = i2s_priv_register_object(&s_adc_digi_ctx, I2S_NUM_0); + if (ret != ESP_OK) { + goto cleanup; + } + + s_adc_digi_ctx->i2s_host = I2S_NUM_0; + ret = esp_intr_alloc(i2s_periph_signal[s_adc_digi_ctx->i2s_host].irq, 0, adc_dma_intr_handler, + (void *)s_adc_digi_ctx, &s_adc_digi_ctx->intr_hdl); + if (ret != ESP_OK) { + goto cleanup; + } +#endif + adc_hal_config_t config = { +#if SOC_GDMA_SUPPORTED + .dev = (void *)GDMA_LL_GET_HW(0), +#elif CONFIG_IDF_TARGET_ESP32S2 + .dev = (void *)SPI_LL_GET_HW(s_adc_digi_ctx->spi_host), +#elif CONFIG_IDF_TARGET_ESP32 + .dev = (void *)I2S_LL_GET_HW(s_adc_digi_ctx->i2s_host), +#endif .desc_max_num = INTERNAL_BUF_NUM, .dma_chan = dma_chan, .eof_num = init_config->conv_num_each_intr / ADC_HAL_DATA_LEN_PER_CONV @@ -224,28 +287,48 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) //enable SARADC module clock periph_module_enable(PERIPH_SARADC_MODULE); +#if SOC_ADC_CALIBRATION_V1_SUPPORTED adc_hal_calibration_init(ADC_NUM_1); adc_hal_calibration_init(ADC_NUM_2); +#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED return ret; cleanup: adc_digi_deinitialize(); return ret; - } -static IRAM_ATTR bool 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) { assert(event_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); + s_adc_digi_ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr; + return s_adc_dma_intr(user_data); } +#else +static IRAM_ATTR void adc_dma_intr_handler(void *arg) +{ + adc_digi_context_t *ctx = (adc_digi_context_t *)arg; + bool need_yield = false; -static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx) + bool conversion_finish = adc_hal_check_event(&ctx->hal, ADC_HAL_DMA_INTR_MASK); + if (conversion_finish) { + adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK); + + intptr_t desc_addr = adc_hal_get_desc_addr(&ctx->hal); + + ctx->rx_eof_desc_addr = desc_addr; + need_yield = s_adc_dma_intr(ctx); + } + + if (need_yield) { + portYIELD_FROM_ISR(); + } +} +#endif + +static IRAM_ATTR bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx) { portBASE_TYPE taskAwoken = 0; BaseType_t ret; @@ -267,7 +350,7 @@ static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx) if (status == ADC_HAL_DMA_DESC_NULL) { //start next turns of dma operation - adc_hal_digi_rxdma_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf); + adc_hal_digi_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf); } return (taskAwoken == pdTRUE); @@ -275,82 +358,117 @@ static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx) esp_err_t adc_digi_start(void) { - if (s_adc_digi_ctx->driver_start_flag != 0) { - ESP_LOGE(ADC_TAG, "The driver is already started"); - return ESP_ERR_INVALID_STATE; - } - adc_power_acquire(); - //reset flags - s_adc_digi_ctx->ringbuf_overflow_flag = 0; - s_adc_digi_ctx->driver_start_flag = 1; - if (s_adc_digi_ctx->use_adc1) { - SAR_ADC1_LOCK_ACQUIRE(); - } - if (s_adc_digi_ctx->use_adc2) { - SAR_ADC2_LOCK_ACQUIRE(); - } + if (s_adc_digi_ctx) { + if (s_adc_digi_ctx->driver_start_flag != 0) { + ESP_LOGE(ADC_TAG, "The driver is already started"); + return ESP_ERR_INVALID_STATE; + } + adc_power_acquire(); + //reset flags + s_adc_digi_ctx->ringbuf_overflow_flag = 0; + s_adc_digi_ctx->driver_start_flag = 1; + if (s_adc_digi_ctx->use_adc1) { + SAR_ADC1_LOCK_ACQUIRE(); + } + if (s_adc_digi_ctx->use_adc2) { + SAR_ADC2_LOCK_ACQUIRE(); + } #if CONFIG_PM_ENABLE - // Lock APB frequency while ADC driver is in use - esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock); + // Lock APB frequency while ADC driver is in use + esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock); #endif - adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); - if (s_adc_digi_ctx->use_adc1) { - uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc1_atten); - adc_hal_set_calibration_param(ADC_NUM_1, cal_val); +#if SOC_ADC_CALIBRATION_V1_SUPPORTED + if (s_adc_digi_ctx->use_adc1) { + uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc1_atten); + adc_hal_set_calibration_param(ADC_NUM_1, cal_val); + } + if (s_adc_digi_ctx->use_adc2) { + uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc2_atten); + adc_hal_set_calibration_param(ADC_NUM_2, cal_val); + } +#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED + + adc_hal_init(); +#if SOC_ADC_ARBITER_SUPPORTED + adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); + adc_hal_arbiter_config(&config); +#endif //#if SOC_ADC_ARBITER_SUPPORTED + + adc_hal_set_controller(ADC_NUM_1, ADC_HAL_CONTINUOUS_READ_MODE); + adc_hal_set_controller(ADC_NUM_2, ADC_HAL_CONTINUOUS_READ_MODE); + + adc_hal_digi_init(&s_adc_digi_ctx->hal); + adc_hal_digi_controller_config(&s_adc_digi_ctx->hal, &s_adc_digi_ctx->hal_digi_ctrlr_cfg); + + //start conversion + adc_hal_digi_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf); + } - if (s_adc_digi_ctx->use_adc2) { - uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc2_atten); - adc_hal_set_calibration_param(ADC_NUM_2, cal_val); +#if CONFIG_IDF_TARGET_ESP32S2 + //For being compatible with the deprecated behaviour + else { + ESP_LOGE(ADC_TAG, "API used without driver initialization before. The following behaviour is deprecated!!"); +#ifdef CONFIG_PM_ENABLE + ESP_RETURN_ON_FALSE((adc_digi_arbiter_lock), ESP_FAIL, ADC_TAG, "Should start after call `adc_digi_controller_config`"); + esp_pm_lock_acquire(adc_digi_arbiter_lock); +#endif + ADC_ENTER_CRITICAL(); + adc_ll_digi_dma_enable(); + adc_ll_digi_trigger_enable(); + ADC_EXIT_CRITICAL(); } - - adc_hal_init(); - adc_hal_arbiter_config(&config); - adc_hal_digi_init(&s_adc_digi_ctx->hal); - adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_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, s_adc_digi_ctx->rx_dma_buf); - //start ADC - adc_hal_digi_start(&s_adc_digi_ctx->hal); - +#endif //#if CONFIG_IDF_TARGET_ESP32S2 return ESP_OK; } esp_err_t adc_digi_stop(void) { - if (s_adc_digi_ctx->driver_start_flag != 1) { - ESP_LOGE(ADC_TAG, "The driver is already stopped"); - return ESP_ERR_INVALID_STATE; - } - s_adc_digi_ctx->driver_start_flag = 0; + if (s_adc_digi_ctx) { + if (s_adc_digi_ctx->driver_start_flag != 1) { + ESP_LOGE(ADC_TAG, "The driver is already stopped"); + return ESP_ERR_INVALID_STATE; + } + s_adc_digi_ctx->driver_start_flag = 0; - //disable the in suc eof intrrupt - 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, IN_SUC_EOF_BIT); - //stop ADC - 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(); + //disable the in suc eof intrrupt + adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK); + //clear the in suc eof interrupt + adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK); + //stop ADC + adc_hal_digi_stop(&s_adc_digi_ctx->hal); + + adc_hal_digi_deinit(&s_adc_digi_ctx->hal); #if CONFIG_PM_ENABLE - if (s_adc_digi_ctx->pm_lock) { - esp_pm_lock_release(s_adc_digi_ctx->pm_lock); - } + if (s_adc_digi_ctx->pm_lock) { + esp_pm_lock_release(s_adc_digi_ctx->pm_lock); + } #endif //CONFIG_PM_ENABLE - if (s_adc_digi_ctx->use_adc1) { - SAR_ADC1_LOCK_RELEASE(); + if (s_adc_digi_ctx->use_adc1) { + SAR_ADC1_LOCK_RELEASE(); + } + if (s_adc_digi_ctx->use_adc2) { + SAR_ADC2_LOCK_RELEASE(); + } + adc_power_release(); } - if (s_adc_digi_ctx->use_adc2) { - SAR_ADC2_LOCK_RELEASE(); +#if CONFIG_IDF_TARGET_ESP32S2 + else { + //For being compatible with the deprecated behaviour + ESP_LOGE(ADC_TAG, "API used without driver initialization before. The following behaviour is deprecated!!"); +#ifdef CONFIG_PM_ENABLE + if (adc_digi_arbiter_lock) { + esp_pm_lock_release(adc_digi_arbiter_lock); + } +#endif + ADC_ENTER_CRITICAL(); + adc_ll_digi_trigger_disable(); + adc_ll_digi_dma_disable(); + ADC_EXIT_CRITICAL(); } - adc_power_release(); - +#endif //#if CONFIG_IDF_TARGET_ESP32S2 return ESP_OK; } @@ -410,10 +528,18 @@ esp_err_t adc_digi_deinitialize(void) free(s_adc_digi_ctx->rx_dma_buf); free(s_adc_digi_ctx->hal.rx_desc); - free(s_adc_digi_ctx->digi_controller_config.adc_pattern); + free(s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern); +#if SOC_GDMA_SUPPORTED gdma_disconnect(s_adc_digi_ctx->rx_dma_channel); gdma_del_channel(s_adc_digi_ctx->rx_dma_channel); - +#elif CONFIG_IDF_TARGET_ESP32S2 + esp_intr_free(s_adc_digi_ctx->intr_hdl); + spicommon_dma_chan_free(s_adc_digi_ctx->spi_host); + spicommon_periph_free(s_adc_digi_ctx->spi_host); +#elif CONFIG_IDF_TARGET_ESP32 + esp_intr_free(s_adc_digi_ctx->intr_hdl); + i2s_priv_deregister_object(s_adc_digi_ctx->i2s_host); +#endif free(s_adc_digi_ctx); s_adc_digi_ctx = NULL; @@ -422,6 +548,83 @@ esp_err_t adc_digi_deinitialize(void) return ESP_OK; } +/*--------------------------------------------------------------- + Digital controller setting +---------------------------------------------------------------*/ +esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config) +{ + if (!s_adc_digi_ctx) { + return ESP_ERR_INVALID_STATE; + } + + //Pattern related check + ESP_RETURN_ON_FALSE(config->pattern_num <= SOC_ADC_PATT_LEN_MAX, ESP_ERR_INVALID_ARG, ADC_TAG, "Max pattern num is %d", SOC_ADC_PATT_LEN_MAX); +#if CONFIG_IDF_TARGET_ESP32 + for (int i = 0; i < config->pattern_num; i++) { + ESP_RETURN_ON_FALSE((config->adc_pattern[i].bit_width >= SOC_ADC_DIGI_MIN_BITWIDTH && config->adc_pattern->bit_width <= SOC_ADC_DIGI_MAX_BITWIDTH), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC bitwidth not supported"); + ESP_RETURN_ON_FALSE(config->adc_pattern[i].unit == 0, ESP_ERR_INVALID_ARG, ADC_TAG, "Only support using ADC1 DMA mode"); + } +#else + for (int i = 0; i < config->pattern_num; i++) { + ESP_RETURN_ON_FALSE((config->adc_pattern[i].bit_width == SOC_ADC_DIGI_MAX_BITWIDTH), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC bitwidth not supported"); + } +#endif + ESP_RETURN_ON_FALSE(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, ESP_ERR_INVALID_ARG, ADC_TAG, "ADC sampling frequency out of range"); +#if CONFIG_IDF_TARGET_ESP32 + ESP_RETURN_ON_FALSE(config->conv_limit_en == 1, ESP_ERR_INVALID_ARG, ADC_TAG, "`conv_limit_en` should be set to 1"); +#endif + +#if CONFIG_IDF_TARGET_ESP32 + ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1"); +#elif CONFIG_IDF_TARGET_ESP32S2 + if (config->conv_mode == ADC_CONV_BOTH_UNIT || config->conv_mode == ADC_CONV_ALTER_UNIT) { + ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2"); + } else if (config->conv_mode == ADC_CONV_SINGLE_UNIT_1 || config->conv_mode == ADC_CONV_SINGLE_UNIT_2) { + ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1"); + } +#else + ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2"); +#endif + + s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_en = config->conv_limit_en; + s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_num = config->conv_limit_num; + s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern_len = config->pattern_num; + s_adc_digi_ctx->hal_digi_ctrlr_cfg.sample_freq_hz = config->sample_freq_hz; + s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_mode = config->conv_mode; + memcpy(s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern, config->adc_pattern, config->pattern_num * sizeof(adc_digi_pattern_config_t)); + + const int atten_uninitialized = 999; + s_adc_digi_ctx->adc1_atten = atten_uninitialized; + s_adc_digi_ctx->adc2_atten = atten_uninitialized; + s_adc_digi_ctx->use_adc1 = 0; + s_adc_digi_ctx->use_adc2 = 0; + for (int i = 0; i < config->pattern_num; i++) { + const adc_digi_pattern_config_t *pat = &config->adc_pattern[i]; + if (pat->unit == ADC_NUM_1) { + s_adc_digi_ctx->use_adc1 = 1; + + if (s_adc_digi_ctx->adc1_atten == atten_uninitialized) { + s_adc_digi_ctx->adc1_atten = pat->atten; + } else if (s_adc_digi_ctx->adc1_atten != pat->atten) { + return ESP_ERR_INVALID_ARG; + } + } else if (pat->unit == ADC_NUM_2) { + //See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver + s_adc_digi_ctx->use_adc2 = 1; + + if (s_adc_digi_ctx->adc2_atten == atten_uninitialized) { + s_adc_digi_ctx->adc2_atten = pat->atten; + } else if (s_adc_digi_ctx->adc2_atten != pat->atten) { + return ESP_ERR_INVALID_ARG; + } + } + } + + return ESP_OK; +} + + +#if CONFIG_IDF_TARGET_ESP32C3 /*--------------------------------------------------------------- ADC Single Read Mode ---------------------------------------------------------------*/ @@ -472,8 +675,8 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit) esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten) { - ADC_CHANNEL_CHECK(ADC_NUM_1, channel); - ADC_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_NUM_1), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC1 channel error"); + ESP_RETURN_ON_FALSE((atten < ADC_ATTEN_MAX), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC Atten Err"); esp_err_t ret = ESP_OK; s_atten1_single[channel] = atten; @@ -512,8 +715,8 @@ int adc1_get_raw(adc1_channel_t channel) esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten) { - ADC_CHANNEL_CHECK(ADC_NUM_2, channel); - ADC_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_NUM_2), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 channel error"); + ESP_RETURN_ON_FALSE((atten <= ADC_ATTEN_11db), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 Atten Err"); esp_err_t ret = ESP_OK; s_atten2_single[channel] = atten; @@ -558,53 +761,6 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int * return ret; } - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ -esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) -{ - if (!s_adc_digi_ctx) { - return ESP_ERR_INVALID_STATE; - } - ADC_CHECK(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, "ADC sampling frequency out of range", ESP_ERR_INVALID_ARG); - - s_adc_digi_ctx->digi_controller_config.conv_limit_en = config->conv_limit_en; - s_adc_digi_ctx->digi_controller_config.conv_limit_num = config->conv_limit_num; - s_adc_digi_ctx->digi_controller_config.adc_pattern_len = config->adc_pattern_len; - s_adc_digi_ctx->digi_controller_config.sample_freq_hz = config->sample_freq_hz; - memcpy(s_adc_digi_ctx->digi_controller_config.adc_pattern, config->adc_pattern, config->adc_pattern_len * sizeof(adc_digi_pattern_table_t)); - - const int atten_uninitialised = 999; - s_adc_digi_ctx->adc1_atten = atten_uninitialised; - s_adc_digi_ctx->adc2_atten = atten_uninitialised; - s_adc_digi_ctx->use_adc1 = 0; - s_adc_digi_ctx->use_adc2 = 0; - for (int i = 0; i < config->adc_pattern_len; i++) { - const adc_digi_pattern_table_t *pat = &config->adc_pattern[i]; - if (pat->unit == ADC_NUM_1) { - s_adc_digi_ctx->use_adc1 = 1; - - if (s_adc_digi_ctx->adc1_atten == atten_uninitialised) { - s_adc_digi_ctx->adc1_atten = pat->atten; - } else if (s_adc_digi_ctx->adc1_atten != pat->atten) { - return ESP_ERR_INVALID_ARG; - } - } else if (pat->unit == ADC_NUM_2) { - //See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver - s_adc_digi_ctx->use_adc2 = 1; - - if (s_adc_digi_ctx->adc2_atten == atten_uninitialised) { - s_adc_digi_ctx->adc2_atten = pat->atten; - } else if (s_adc_digi_ctx->adc2_atten != pat->atten) { - return ESP_ERR_INVALID_ARG; - } - } - } - - return ESP_OK; -} - /*************************************/ /* Digital controller filter setting */ /*************************************/ @@ -661,10 +817,22 @@ esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable) ADC_EXIT_CRITICAL(); return ESP_OK; } +#endif //#if CONFIG_IDF_TARGET_ESP32C3 + +#if SOC_ADC_CALIBRATION_V1_SUPPORTED /*--------------------------------------------------------------- - RTC controller setting + Hardware Calibration Setting ---------------------------------------------------------------*/ +#if CONFIG_IDF_TARGET_ESP32S2 +#define esp_efuse_rtc_calib_get_ver() esp_efuse_rtc_table_read_calib_version() + +static inline uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten) +{ + int tag = esp_efuse_rtc_table_get_tag(version, adc_unit + 1, atten, RTCCALIB_V2_PARAM_VINIT); + return esp_efuse_rtc_table_get_parsed_efuse_value(tag, false); +} +#endif static uint16_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][ADC_ATTEN_MAX] = {}; @@ -672,39 +840,34 @@ static uint16_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][ADC_ATTEN_MAX] = {}; // 1. Semaphore when reading efuse // 2. Lock (Spinlock, or Mutex) if we actually do ADC calibration in the future //This function shoudn't be called inside critical section or ISR -static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) +uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) { - const bool no_cal = false; if (s_adc_cali_param[adc_n][atten]) { + ESP_LOGV(ADC_TAG, "Use calibrated val ADC%d atten=%d: %04X", adc_n, atten, s_adc_cali_param[adc_n][atten]); return (uint32_t)s_adc_cali_param[adc_n][atten]; } - if (no_cal) { - return 0; //indicating failure - } - // check if we can fetch the values from eFuse. int version = esp_efuse_rtc_calib_get_ver(); uint32_t init_code = 0; - if (version == 1) { - //for calibration v1, both ADC units use the same init code (calibrated by ADC1) - init_code = esp_efuse_rtc_calib_get_init_code(version, atten); - ESP_LOGD(ADC_TAG, "Calib(V%d) ADC0, 1 atten=%d: %04X", version, atten, init_code); - s_adc_cali_param[0][atten] = init_code; - s_adc_cali_param[1][atten] = init_code; + + if (version == ESP_EFUSE_ADC_CALIB_VER) { + init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten); + } else { + ESP_LOGD(ADC_TAG, "Calibration eFuse is not configured, use self-calibration for ICode"); adc_power_acquire(); ADC_ENTER_CRITICAL(); const bool internal_gnd = true; init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd); ADC_EXIT_CRITICAL(); adc_power_release(); - - ESP_LOGD(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code); - s_adc_cali_param[adc_n][atten] = init_code; } + s_adc_cali_param[adc_n][atten] = init_code; + ESP_LOGV(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code); + return init_code; } @@ -718,3 +881,61 @@ esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t ADC_EXIT_CRITICAL(); return ESP_OK; } +#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED + +/*--------------------------------------------------------------- + Deprecated API +---------------------------------------------------------------*/ +#if CONFIG_IDF_TARGET_ESP32C3 +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#include "deprecated/driver/adc_deprecated.h" +#include "deprecated/driver/adc_types_deprecated.h" +esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) +{ + if (!s_adc_digi_ctx) { + return ESP_ERR_INVALID_STATE; + } + ESP_RETURN_ON_FALSE((config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW), ESP_ERR_INVALID_ARG, ADC_TAG, "DC sampling frequency out of range"); + + s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_en = config->conv_limit_en; + s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_num = config->conv_limit_num; + s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern_len = config->adc_pattern_len; + s_adc_digi_ctx->hal_digi_ctrlr_cfg.sample_freq_hz = config->sample_freq_hz; + + for (int i = 0; i < config->adc_pattern_len; i++) { + s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i].atten = config->adc_pattern[i].atten; + s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i].channel = config->adc_pattern[i].channel; + s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i].unit = config->adc_pattern[i].unit; + } + + + const int atten_uninitialized = 999; + s_adc_digi_ctx->adc1_atten = atten_uninitialized; + s_adc_digi_ctx->adc2_atten = atten_uninitialized; + s_adc_digi_ctx->use_adc1 = 0; + s_adc_digi_ctx->use_adc2 = 0; + for (int i = 0; i < config->adc_pattern_len; i++) { + const adc_digi_pattern_config_t *pat = &s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i]; + if (pat->unit == ADC_NUM_1) { + s_adc_digi_ctx->use_adc1 = 1; + + if (s_adc_digi_ctx->adc1_atten == atten_uninitialized) { + s_adc_digi_ctx->adc1_atten = pat->atten; + } else if (s_adc_digi_ctx->adc1_atten != pat->atten) { + return ESP_ERR_INVALID_ARG; + } + } else if (pat->unit == ADC_NUM_2) { + //See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver + s_adc_digi_ctx->use_adc2 = 1; + + if (s_adc_digi_ctx->adc2_atten == atten_uninitialized) { + s_adc_digi_ctx->adc2_atten = pat->atten; + } else if (s_adc_digi_ctx->adc2_atten != pat->atten) { + return ESP_ERR_INVALID_ARG; + } + } + } + + return ESP_OK; +} +#endif //#if CONFIG_IDF_TARGET_ESP32C3 diff --git a/components/driver/adc_common.c b/components/driver/adc_common.c index 2be9768533..3cd949aa4b 100644 --- a/components/driver/adc_common.c +++ b/components/driver/adc_common.c @@ -78,6 +78,7 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi #define FSM_ENTER() RTC_ENTER_CRITICAL() #define FSM_EXIT() RTC_EXIT_CRITICAL() +//TODO: IDF-3610 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 //prevent ADC1 being used by I2S dma and other tasks at the same time. static _lock_t adc1_dma_lock; @@ -85,6 +86,7 @@ static _lock_t adc1_dma_lock; #define SARADC1_RELEASE() _lock_release( &adc1_dma_lock ) #endif + /* In ADC2, there're two locks used for different cases: 1. lock shared with app and Wi-Fi: @@ -218,65 +220,23 @@ esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num) return ESP_OK; } - //------------------------------------------------------------RTC Single Read----------------------------------------------// #if SOC_ADC_RTC_CTRL_SUPPORTED -/*--------------------------------------------------------------- - ADC Calibration ----------------------------------------------------------------*/ -#if CONFIG_IDF_TARGET_ESP32S3 -/** - * Temporarily put this function here. These are about ADC calibration and will be moved driver/adc.c in !14278. - * Reason for putting calibration functions in driver/adc.c: - * adc_common.c is far too confusing. Before a refactor is applied to adc_common.c, will put definite code in driver/adc.c - */ - -static uint16_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][ADC_ATTEN_MAX] = {}; - -uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) -{ - if (s_adc_cali_param[adc_n][atten]) { - //These value won't exceed UINT16_MAX - return s_adc_cali_param[adc_n][atten]; - } - - //Get the calibration version - int version = esp_efuse_rtc_calib_get_ver(); - - uint32_t init_code = 0; - if (version == 1) { - init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten); - } else { - ESP_LOGV(ADC_TAG, "Calibration eFuse is not configured, use self-calibration for ICode"); - adc_power_acquire(); - RTC_ENTER_CRITICAL(); - const bool internal_gnd = true; - init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd); - RTC_EXIT_CRITICAL(); - adc_power_release(); - } - s_adc_cali_param[adc_n][atten] = init_code; - return s_adc_cali_param[adc_n][atten]; -} -#elif CONFIG_IDF_TARGET_ESP32S2 -//Temporarily extern this from s2/adc.c. Will be modified in !14278. -extern uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten); -#endif //CONFIG_IDF_TARGET_ESP32S3 - #if SOC_ADC_CALIBRATION_V1_SUPPORTED static uint32_t get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan) { - adc_atten_t atten = adc_hal_get_atten(adc_n, chan); + adc_atten_t atten = adc_ll_get_atten(adc_n, chan); + extern uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten); return adc_get_calibration_offset(adc_n, chan, atten); } -#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED +#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED esp_err_t adc_set_clk_div(uint8_t clk_div) { DIGI_CONTROLLER_ENTER(); - adc_hal_digi_set_clk_div(clk_div); + adc_ll_digi_set_clk_div(clk_div); DIGI_CONTROLLER_EXIT(); return ESP_OK; } @@ -290,20 +250,25 @@ static void adc_rtc_chan_init(adc_unit_t adc_unit) dac_hal_rtc_sync_by_adc(false); #endif adc_hal_rtc_output_invert(ADC_NUM_1, SOC_ADC1_DATA_INVERT_DEFAULT); - adc_hal_set_sar_clk_div(ADC_NUM_1, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_1)); + adc_ll_set_sar_clk_div(ADC_NUM_1, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_1)); #ifdef CONFIG_IDF_TARGET_ESP32 - adc_hal_hall_disable(); //Disable other peripherals. - adc_hal_amp_disable(); //Currently the LNA is not open, close it by default. + adc_ll_hall_disable(); //Disable other peripherals. + adc_ll_amp_disable(); //Currently the LNA is not open, close it by default. #endif } if (adc_unit & ADC_UNIT_2) { adc_hal_pwdet_set_cct(SOC_ADC_PWDET_CCT_DEFAULT); adc_hal_rtc_output_invert(ADC_NUM_2, SOC_ADC2_DATA_INVERT_DEFAULT); - adc_hal_set_sar_clk_div(ADC_NUM_2, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_2)); + adc_ll_set_sar_clk_div(ADC_NUM_2, SOC_ADC_SAR_CLK_DIV_DEFAULT(ADC_NUM_2)); } } -esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel) +/** + * This function is NOT an API. + * Now some to-be-deprecated APIs are using this function, so don't make it static for now. + * Will make this static on v5.0 + */ +esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel) { gpio_num_t gpio_num = 0; //If called with `ADC_UNIT_BOTH (ADC_UNIT_1 | ADC_UNIT_2)`, both if blocks will be run @@ -343,22 +308,22 @@ esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en) return ESP_OK; } -esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits) +esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit) { #if CONFIG_IDF_TARGET_ESP32 - ADC_CHECK(bits < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG); + ADC_CHECK(width_bit < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG); #else - ADC_CHECK(bits == ADC_WIDTH_MAX - 1, "WIDTH ERR: see `adc_bits_width_t` for supported bit width", ESP_ERR_INVALID_ARG); + ADC_CHECK(width_bit == ADC_WIDTH_MAX - 1, "WIDTH ERR: see `adc_bits_width_t` for supported bit width", ESP_ERR_INVALID_ARG); #endif if (adc_unit & ADC_UNIT_1) { SARADC1_ENTER(); - adc_hal_rtc_set_output_format(ADC_NUM_1, bits); + adc_hal_rtc_set_output_format(ADC_NUM_1, width_bit); SARADC1_EXIT(); } if (adc_unit & ADC_UNIT_2) { SARADC2_ENTER(); - adc_hal_rtc_set_output_format(ADC_NUM_2, bits); + adc_hal_rtc_set_output_format(ADC_NUM_2, width_bit); SARADC2_EXIT(); } @@ -389,7 +354,7 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten) ADC_CHANNEL_CHECK(ADC_NUM_1, channel); ADC_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG); - adc_gpio_init(ADC_UNIT_1, channel); + adc_common_gpio_init(ADC_UNIT_1, channel); SARADC1_ENTER(); adc_rtc_chan_init(ADC_UNIT_1); adc_hal_set_atten(ADC_NUM_1, channel, atten); @@ -428,11 +393,7 @@ esp_err_t adc1_dma_mode_acquire(void) SARADC1_ENTER(); /* switch SARADC into DIG channel */ -#if CONFIG_IDF_TARGET_ESP32S3 // remove this macro. TODO: IDF-1776 - adc_hal_set_controller(ADC_NUM_1, ADC_LL_CTRL_DIG); -#else - adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_DIG); -#endif + adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_DIG); SARADC1_EXIT(); return ESP_OK; @@ -447,11 +408,7 @@ esp_err_t adc1_rtc_mode_acquire(void) SARADC1_ENTER(); /* switch SARADC into RTC channel. */ -#if CONFIG_IDF_TARGET_ESP32S3 // remove this macro. TODO: IDF-1776 - adc_hal_set_controller(ADC_NUM_1, ADC_LL_CTRL_RTC); -#else - adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_RTC); -#endif + adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_RTC); SARADC1_EXIT(); return ESP_OK; @@ -481,14 +438,10 @@ int adc1_get_raw(adc1_channel_t channel) SARADC1_ENTER(); #ifdef CONFIG_IDF_TARGET_ESP32 - adc_hal_hall_disable(); //Disable other peripherals. - adc_hal_amp_disable(); //Currently the LNA is not open, close it by default. -#endif -#if CONFIG_IDF_TARGET_ESP32S3 // remove this macro. TODO: IDF-1776 - adc_hal_set_controller(ADC_NUM_1, ADC_LL_CTRL_RTC); //Set controller -#else - adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_RTC); //Set controller + adc_ll_hall_disable(); //Disable other peripherals. + adc_ll_amp_disable(); //Currently the LNA is not open, close it by default. #endif + adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_RTC); //Set controller adc_hal_convert(ADC_NUM_1, channel, &adc_value); //Start conversion, For ADC1, the data always valid. #if !CONFIG_IDF_TARGET_ESP32 adc_ll_rtc_reset(); //Reset FSM of rtc controller @@ -510,17 +463,13 @@ void adc1_ulp_enable(void) adc_power_acquire(); SARADC1_ENTER(); -#if CONFIG_IDF_TARGET_ESP32S3 // remove this macro. TODO: IDF-1776 - adc_hal_set_controller(ADC_NUM_1, ADC_LL_CTRL_ULP); -#else - adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_ULP); //Set controller -#endif + adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_ULP); /* since most users do not need LNA and HALL with uLP, we disable them here open them in the uLP if needed. */ #ifdef CONFIG_IDF_TARGET_ESP32 /* disable other peripherals. */ - adc_hal_hall_disable(); - adc_hal_amp_disable(); + adc_ll_hall_disable(); + adc_ll_amp_disable(); #endif SARADC1_EXIT(); } @@ -552,7 +501,7 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten) ADC_CHANNEL_CHECK(ADC_NUM_2, channel); ADC_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG); - adc_gpio_init(ADC_UNIT_2, channel); + adc_common_gpio_init(ADC_UNIT_2, channel); if ( SARADC2_TRY_ACQUIRE() == -1 ) { //try the lock, return if failed (wifi using). @@ -649,10 +598,11 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int * adc2_dac_disable(channel); //disable other peripherals #endif adc_hal_rtc_set_output_format(ADC_NUM_2, width_bit); -#if CONFIG_IDF_TARGET_ESP32S3 // remove this macro. TODO: IDF-1776 - adc_hal_set_controller(ADC_NUM_2, ADC_LL_CTRL_ARB);// set controller + +#if CONFIG_IDF_TARGET_ESP32 + adc_ll_set_controller(ADC_NUM_2, ADC_LL_CTRL_RTC);// set controller #else - adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC); + adc_ll_set_controller(ADC_NUM_2, ADC_LL_CTRL_ARB);// set controller #endif #if CONFIG_IDF_TARGET_ESP32S2 @@ -721,7 +671,7 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio) } //Configure RTC gpio, Only ADC2's channels IO are supported to output reference voltage. - adc_gpio_init(ADC_UNIT_2, ch); + adc_common_gpio_init(ADC_UNIT_2, ch); return ESP_OK; } diff --git a/components/driver/adc_deprecated.c b/components/driver/adc_deprecated.c new file mode 100644 index 0000000000..c891b24aa7 --- /dev/null +++ b/components/driver/adc_deprecated.c @@ -0,0 +1,626 @@ +/* + * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/*---------------------------------------------------------------------------------- + This file contains ESP32 and ESP32S2 Depricated ADC APIs and functions +-----------------------------------------------------------------------------------*/ + +#include "sdkconfig.h" +#include "esp_types.h" +#include "esp_log.h" +#include "esp_intr_alloc.h" +#include "driver/rtc_io.h" +#include "hal/adc_ll.h" +#include "hal/adc_types.h" +#ifdef CONFIG_PM_ENABLE +#include "esp_pm.h" +#endif +#include "adc.h" +#include "esp_private/adc_cali.h" +#include "freertos/FreeRTOS.h" + +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#include "deprecated/driver/adc_types_deprecated.h" + +static const char *ADC_TAG = "ADC"; + +#define ADC_CHECK_RET(fun_ret) ({ \ + if (fun_ret != ESP_OK) { \ + ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__); \ + return ESP_FAIL; \ + } \ +}) + +#define ADC_CHECK(a, str, ret_val) ({ \ + if (!(a)) { \ + ESP_LOGE(ADC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } \ +}) + +#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG) +#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel]) + +extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. +#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) +#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) + +#ifdef CONFIG_PM_ENABLE +esp_pm_lock_handle_t adc_digi_arbiter_lock = NULL; +#endif //CONFIG_PM_ENABLE + + +#if CONFIG_IDF_TARGET_ESP32 +/*--------------------------------------------------------------- + ESP32 Depricated ADC APIs and functions +---------------------------------------------------------------*/ +#define ADC_MEAS_NUM_LIM_DEFAULT (1) +#define ADC_MAX_MEAS_NUM_DEFAULT (255) +#define DIG_ADC_OUTPUT_FORMAT_DEFUALT (ADC_DIGI_FORMAT_12BIT) +#define DIG_ADC_ATTEN_DEFUALT (ADC_ATTEN_DB_11) +#define DIG_ADC_BIT_WIDTH_DEFUALT (ADC_WIDTH_BIT_12) + +esp_err_t adc_digi_init(void) +{ + ADC_ENTER_CRITICAL(); + adc_hal_init(); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t adc_digi_deinit(void) +{ + adc_power_release(); + ADC_ENTER_CRITICAL(); + adc_hal_digi_deinit(NULL); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +/** + * Set adc output 16-bit-data format from digital controller. + * + * @param data_sel 1: [15] unit, [14:11] channel, [10:0] data, 11-bit-width at most. Only work under `ADC_LL_DIGI_CONV_BOTH_UNIT` or `ADC_LL_DIGI_CONV_ALTER_UNIT` mode. + * 0: [15:12] channel, [11:0] data, 12-bit-width at most. Only work under `ADC_LL_DIGI_CONV_ONLY_ADC1` or `ADC_LL_DIGI_CONV_ONLY_ADC2` mode + * @note see `adc_ll_digi_pattern_table_t` for more detail of data bit width + */ +static inline void adc_ll_digi_set_output_format(bool data_sel) +{ + SYSCON.saradc_ctrl.data_sar_sel = data_sel; +} + +static inline void adc_ll_digi_prepare_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern) +{ + uint32_t tab; + uint8_t index = pattern_index / 4; + uint8_t offset = (pattern_index % 4) * 8; + if (adc_n == ADC_NUM_1) { + tab = SYSCON.saradc_sar1_patt_tab[index]; // Read old register value + tab &= (~(0xFF000000 >> offset)); // clear old data + tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data + SYSCON.saradc_sar1_patt_tab[index] = tab; // Write back + } else { // adc_n == ADC_NUM_2 + tab = SYSCON.saradc_sar2_patt_tab[index]; // Read old register value + tab &= (~(0xFF000000 >> offset)); // clear old data + tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data + SYSCON.saradc_sar2_patt_tab[index] = tab; // Write back + } +} + +void adc_digi_controller_reg_set(const adc_digi_config_t *cfg) +{ + /* On ESP32, only support ADC1 */ + switch (cfg->conv_mode) { + case ADC_CONV_SINGLE_UNIT_1: + adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC1); + break; + case ADC_CONV_SINGLE_UNIT_2: + adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC2); + break; + case ADC_CONV_BOTH_UNIT: + adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT); + break; + case ADC_CONV_ALTER_UNIT: + adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ALTER_UNIT); + break; + default: + abort(); + } + + if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) { + adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_DIG); + if (cfg->adc1_pattern_len) { + adc_ll_digi_clear_pattern_table(ADC_NUM_1); + adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len); + for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) { + adc_ll_digi_prepare_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]); + } + } + } + if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) { + adc_ll_set_controller(ADC_NUM_2, ADC_LL_CTRL_DIG); + if (cfg->adc2_pattern_len) { + adc_ll_digi_clear_pattern_table(ADC_NUM_2); + adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len); + for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) { + adc_ll_digi_prepare_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]); + } + } + } + adc_ll_digi_set_output_format(cfg->format); + if (cfg->conv_limit_en) { + adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num); + adc_ll_digi_convert_limit_enable(); + } else { + adc_ll_digi_convert_limit_disable(); + } + adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_ADC); +} + +esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) +{ + adc_power_acquire(); + ADC_ENTER_CRITICAL(); + adc_digi_controller_reg_set(config); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src) +{ + ADC_CHECK(src < ADC_I2S_DATA_SRC_MAX, "ADC i2s data source error", ESP_ERR_INVALID_ARG); + ADC_ENTER_CRITICAL(); + adc_ll_digi_set_data_source(src); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +extern esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel); +esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) +{ + if (adc_unit & ADC_UNIT_1) { + ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_NUM_1)), "ADC1 not support DMA for now.", ESP_ERR_INVALID_ARG); + ADC_CHANNEL_CHECK(ADC_NUM_1, channel); + } + if (adc_unit & ADC_UNIT_2) { + ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_NUM_2)), "ADC2 not support DMA for now.", ESP_ERR_INVALID_ARG); + ADC_CHANNEL_CHECK(ADC_NUM_2, channel); + } + + adc_digi_pattern_table_t adc1_pattern[1]; + adc_digi_pattern_table_t adc2_pattern[1]; + adc_digi_config_t dig_cfg = { + .conv_limit_en = ADC_MEAS_NUM_LIM_DEFAULT, + .conv_limit_num = ADC_MAX_MEAS_NUM_DEFAULT, + .format = DIG_ADC_OUTPUT_FORMAT_DEFUALT, + .conv_mode = (adc_digi_convert_mode_t)adc_unit, + }; + + if (adc_unit & ADC_UNIT_1) { + adc1_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT; + adc1_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT; + adc1_pattern[0].channel = channel; + dig_cfg.adc1_pattern_len = 1; + dig_cfg.adc1_pattern = adc1_pattern; + } + if (adc_unit & ADC_UNIT_2) { + adc2_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT; + adc2_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT; + adc2_pattern[0].channel = channel; + dig_cfg.adc2_pattern_len = 1; + dig_cfg.adc2_pattern = adc2_pattern; + } + adc_common_gpio_init(adc_unit, channel); + ADC_ENTER_CRITICAL(); + adc_hal_init(); + adc_digi_controller_reg_set(&dig_cfg); + ADC_EXIT_CRITICAL(); + + return ESP_OK; +} + +#endif //#if CONFIG_IDF_TARGET_ESP32 + +#if CONFIG_IDF_TARGET_ESP32S2 +/*--------------------------------------------------------------- + ESP32S2 Depricated ADC functions and APIs +---------------------------------------------------------------*/ +esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config) +{ + if (adc_unit & ADC_UNIT_1) { + return ESP_ERR_NOT_SUPPORTED; + } + ADC_ENTER_CRITICAL(); + adc_hal_arbiter_config(config); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +/** + * Enable interrupt of adc digital controller by bitmask. + * + * @param adc_n ADC unit. + * @param intr Interrupt bitmask. + */ +static inline void adc_ll_digi_intr_enable(adc_ll_num_t adc_n, adc_digi_intr_t intr) +{ + if (adc_n == ADC_NUM_1) { + if (intr & ADC_DIGI_INTR_MASK_MONITOR) { + APB_SARADC.int_ena.adc1_thres = 1; + } + if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { + APB_SARADC.int_ena.adc1_done = 1; + } + } else { // adc_n == ADC_NUM_2 + if (intr & ADC_DIGI_INTR_MASK_MONITOR) { + APB_SARADC.int_ena.adc2_thres = 1; + } + if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { + APB_SARADC.int_ena.adc2_done = 1; + } + } +} + +esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) +{ + ADC_ENTER_CRITICAL(); + if (adc_unit & ADC_UNIT_1) { + adc_ll_digi_intr_enable(ADC_NUM_1, intr_mask); + } + if (adc_unit & ADC_UNIT_2) { + adc_ll_digi_intr_enable(ADC_NUM_2, intr_mask); + } + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +/** + * Disable interrupt of adc digital controller by bitmask. + * + * @param adc_n ADC unit. + * @param intr Interrupt bitmask. + */ +static inline void adc_ll_digi_intr_disable(adc_ll_num_t adc_n, adc_digi_intr_t intr) +{ + if (adc_n == ADC_NUM_1) { + if (intr & ADC_DIGI_INTR_MASK_MONITOR) { + APB_SARADC.int_ena.adc1_thres = 0; + } + if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { + APB_SARADC.int_ena.adc1_done = 0; + } + } else { // adc_n == ADC_NUM_2 + if (intr & ADC_DIGI_INTR_MASK_MONITOR) { + APB_SARADC.int_ena.adc2_thres = 0; + } + if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { + APB_SARADC.int_ena.adc2_done = 0; + } + } +} + +esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) +{ + ADC_ENTER_CRITICAL(); + if (adc_unit & ADC_UNIT_1) { + adc_ll_digi_intr_disable(ADC_NUM_1, intr_mask); + } + if (adc_unit & ADC_UNIT_2) { + adc_ll_digi_intr_disable(ADC_NUM_2, intr_mask); + } + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +/** + * Clear interrupt of adc digital controller by bitmask. + * + * @param adc_n ADC unit. + * @param intr Interrupt bitmask. + */ +static inline void adc_ll_digi_intr_clear(adc_ll_num_t adc_n, adc_digi_intr_t intr) +{ + if (adc_n == ADC_NUM_1) { + if (intr & ADC_DIGI_INTR_MASK_MONITOR) { + APB_SARADC.int_clr.adc1_thres = 1; + } + if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { + APB_SARADC.int_clr.adc1_done = 1; + } + } else { // adc_n == ADC_NUM_2 + if (intr & ADC_DIGI_INTR_MASK_MONITOR) { + APB_SARADC.int_clr.adc2_thres = 1; + } + if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { + APB_SARADC.int_clr.adc2_done = 1; + } + } +} + +esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) +{ + ADC_ENTER_CRITICAL(); + if (adc_unit & ADC_UNIT_1) { + adc_ll_digi_intr_clear(ADC_NUM_1, intr_mask); + } + if (adc_unit & ADC_UNIT_2) { + adc_ll_digi_intr_clear(ADC_NUM_2, intr_mask); + } + ADC_EXIT_CRITICAL(); + + return ESP_OK; +} + +/** + * Get interrupt status mask of adc digital controller. + * + * @param adc_n ADC unit. + * @return + * - intr Interrupt bitmask. + */ +static inline uint32_t adc_ll_digi_get_intr_status(adc_ll_num_t adc_n) +{ + uint32_t int_st = APB_SARADC.int_st.val; + uint32_t ret_msk = 0; + + if (adc_n == ADC_NUM_1) { + if (int_st & APB_SARADC_ADC1_DONE_INT_ST_M) { + ret_msk |= ADC_DIGI_INTR_MASK_MEAS_DONE; + } + if (int_st & APB_SARADC_ADC1_THRES_INT_ST) { + ret_msk |= ADC_DIGI_INTR_MASK_MONITOR; + } + } else { // adc_n == ADC_NUM_2 + if (int_st & APB_SARADC_ADC2_DONE_INT_ST_M) { + ret_msk |= ADC_DIGI_INTR_MASK_MEAS_DONE; + } + if (int_st & APB_SARADC_ADC2_THRES_INT_ST_M) { + ret_msk |= ADC_DIGI_INTR_MASK_MONITOR; + } + } + + return ret_msk; +} + +uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit) +{ + uint32_t ret = 0; + ADC_ENTER_CRITICAL(); + if (adc_unit & ADC_UNIT_1) { + ret = adc_ll_digi_get_intr_status(ADC_NUM_1); + } + if (adc_unit & ADC_UNIT_2) { + ret = adc_ll_digi_get_intr_status(ADC_NUM_2); + } + ADC_EXIT_CRITICAL(); + return ret; +} + +static uint8_t s_isr_registered = 0; +static intr_handle_t s_adc_isr_handle = NULL; + +esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags) +{ + ADC_CHECK((fn != NULL), "Parameter error", ESP_ERR_INVALID_ARG); + ADC_CHECK(s_isr_registered == 0, "ADC ISR have installed, can not install again", ESP_FAIL); + + esp_err_t ret = esp_intr_alloc(ETS_APB_ADC_INTR_SOURCE, intr_alloc_flags, fn, arg, &s_adc_isr_handle); + if (ret == ESP_OK) { + s_isr_registered = 1; + } + return ret; +} + +esp_err_t adc_digi_isr_deregister(void) +{ + esp_err_t ret = ESP_FAIL; + if (s_isr_registered) { + ret = esp_intr_free(s_adc_isr_handle); + if (ret == ESP_OK) { + s_isr_registered = 0; + } + } + return ret; +} + +esp_err_t adc_digi_init(void) +{ + adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); + ADC_ENTER_CRITICAL(); + adc_hal_init(); + adc_hal_arbiter_config(&config); + ADC_EXIT_CRITICAL(); + + adc_hal_calibration_init(ADC_NUM_1); + adc_hal_calibration_init(ADC_NUM_2); + + return ESP_OK; +} + +esp_err_t adc_digi_deinit(void) +{ +#ifdef CONFIG_PM_ENABLE + if (adc_digi_arbiter_lock) { + esp_pm_lock_delete(adc_digi_arbiter_lock); + adc_digi_arbiter_lock = NULL; + } +#endif + adc_power_release(); + ADC_ENTER_CRITICAL(); + adc_hal_digi_deinit(NULL); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +/** + * @brief Reset FSM of adc digital controller. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_reset(void) +{ + ADC_ENTER_CRITICAL(); + adc_ll_digi_reset(); + adc_ll_digi_clear_pattern_table(ADC_NUM_1); + adc_ll_digi_clear_pattern_table(ADC_NUM_2); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} + +/** + * Set adc output data format for digital controller. + * + * @param format Output data format. + */ +static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format) +{ + APB_SARADC.ctrl.data_sar_sel = format; +} + +static inline void adc_ll_digi_prepare_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern) +{ + uint32_t tab; + uint8_t index = pattern_index / 4; + uint8_t offset = (pattern_index % 4) * 8; + if (adc_n == ADC_NUM_1) { + tab = APB_SARADC.sar1_patt_tab[index]; // Read old register value + tab &= (~(0xFF000000 >> offset)); // clear old data + tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data + APB_SARADC.sar1_patt_tab[index] = tab; // Write back + } else { // adc_n == ADC_NUM_2 + tab = APB_SARADC.sar2_patt_tab[index]; // Read old register value + tab &= (~(0xFF000000 >> offset)); // clear old data + tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data + APB_SARADC.sar2_patt_tab[index] = tab; // Write back + } +} + +static void adc_digi_controller_reg_set(const adc_digi_config_t *cfg) +{ + /* Single channel mode or multi channel mode. */ + switch (cfg->conv_mode) { + case ADC_CONV_SINGLE_UNIT_1: + adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC1); + break; + case ADC_CONV_SINGLE_UNIT_2: + adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC2); + break; + case ADC_CONV_BOTH_UNIT: + adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT); + break; + case ADC_CONV_ALTER_UNIT: + adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ALTER_UNIT); + break; + default: + abort(); + } + + if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) { + if (cfg->adc1_pattern_len) { + adc_ll_digi_clear_pattern_table(ADC_NUM_1); + adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len); + for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) { + adc_ll_digi_prepare_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]); + } + } + } + if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) { + if (cfg->adc2_pattern_len) { + adc_ll_digi_clear_pattern_table(ADC_NUM_2); + adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len); + for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) { + adc_ll_digi_prepare_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]); + } + } + } + if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) { + adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_DIG); + } + if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) { + adc_ll_set_controller(ADC_NUM_2, ADC_LL_CTRL_ARB); + } + adc_ll_digi_set_output_format(cfg->format); + if (cfg->conv_limit_en) { + adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num); + adc_ll_digi_convert_limit_enable(); + } else { + adc_ll_digi_convert_limit_disable(); + } + + adc_ll_digi_set_trigger_interval(cfg->interval); + adc_ll_digi_controller_clk_div(cfg->dig_clk.div_num, cfg->dig_clk.div_b, cfg->dig_clk.div_a); + adc_ll_digi_clk_sel(cfg->dig_clk.use_apll); + adc_ll_digi_dma_set_eof_num(cfg->dma_eof_num); +} + +esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) +{ +#ifdef CONFIG_PM_ENABLE + esp_err_t err; + if (adc_digi_arbiter_lock == NULL) { + if (config->dig_clk.use_apll) { + err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "adc_dma", &adc_digi_arbiter_lock); + } else { + err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &adc_digi_arbiter_lock); + } + if (err != ESP_OK) { + adc_digi_arbiter_lock = NULL; + ESP_LOGE(ADC_TAG, "ADC-DMA pm lock error"); + return err; + } + } +#endif //CONFIG_PM_ENABLE + + if (config->conv_mode & ADC_CONV_SINGLE_UNIT_1) { + for (int i = 0; i < config->adc1_pattern_len; i++) { + adc_cal_offset(ADC_NUM_1, config->adc1_pattern[i].channel, config->adc1_pattern[i].atten); + } + } + if (config->conv_mode & ADC_CONV_SINGLE_UNIT_2) { + for (int i = 0; i < config->adc2_pattern_len; i++) { + adc_cal_offset(ADC_NUM_2, config->adc2_pattern[i].channel, config->adc2_pattern[i].atten); + } + } + + /* If enable digtal controller, adc xpd should always on. */ + adc_power_acquire(); + ADC_ENTER_CRITICAL(); + adc_digi_controller_reg_set(config); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} +#endif // #if CONFIG_IDF_TARGET_ESP32S2 + + +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 +/*--------------------------------------------------------------- + ESP32S2 Depricated ADC functions and APIs +---------------------------------------------------------------*/ +esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel) +{ + gpio_num_t gpio_num = 0; + //If called with `ADC_UNIT_BOTH (ADC_UNIT_1 | ADC_UNIT_2)`, both if blocks will be run + if (adc_unit & ADC_UNIT_1) { + ADC_CHANNEL_CHECK(ADC_NUM_1, channel); + gpio_num = ADC_GET_IO_NUM(ADC_NUM_1, channel); + ADC_CHECK_RET(rtc_gpio_init(gpio_num)); + ADC_CHECK_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED)); + ADC_CHECK_RET(rtc_gpio_pulldown_dis(gpio_num)); + ADC_CHECK_RET(rtc_gpio_pullup_dis(gpio_num)); + } + if (adc_unit & ADC_UNIT_2) { + ADC_CHANNEL_CHECK(ADC_NUM_2, channel); + gpio_num = ADC_GET_IO_NUM(ADC_NUM_2, channel); + ADC_CHECK_RET(rtc_gpio_init(gpio_num)); + ADC_CHECK_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED)); + ADC_CHECK_RET(rtc_gpio_pulldown_dis(gpio_num)); + ADC_CHECK_RET(rtc_gpio_pullup_dis(gpio_num)); + } + + return ESP_OK; +} +#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 diff --git a/components/driver/deprecated/driver/adc_deprecated.h b/components/driver/deprecated/driver/adc_deprecated.h new file mode 100644 index 0000000000..bdd0547c06 --- /dev/null +++ b/components/driver/deprecated/driver/adc_deprecated.h @@ -0,0 +1,163 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/*---------------------------------------------------------------------------------- + This file contains Deprecated ADC APIs +-----------------------------------------------------------------------------------*/ + +#pragma once +#include "esp_err.h" +#include "hal/adc_types.h" +#include "driver/adc_types_deprecated.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if CONFIG_IDF_TARGET_ESP32S2 +/*--------------------------------------------------------------- + ESP32S2 Deprecated ADC APIs +---------------------------------------------------------------*/ +/** + * @brief Config ADC module arbiter. + * The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority, + * the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data. + * + * @note Only ADC2 support arbiter. + * @note Default priority: Wi-Fi > RTC > Digital; + * @note In normal use, there is no need to call this interface to config arbiter. + * + * @param adc_unit ADC unit. + * @param config Refer to `adc_arbiter_t`. + * + * @return + * - ESP_OK Success + * - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter. + */ +esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config) __attribute__((deprecated)); + +/** + * @brief Enable interrupt of adc digital controller by bitmask. + * + * @param adc_unit ADC unit. + * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) __attribute__((deprecated)); + +/** + * @brief Disable interrupt of adc digital controller by bitmask. + * + * @param adc_unit ADC unit. + * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) __attribute__((deprecated)); + +/** + * @brief Clear interrupt of adc digital controller by bitmask. + * + * @param adc_unit ADC unit. + * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) __attribute__((deprecated)); + +/** + * @brief Get interrupt status mask of adc digital controller. + * + * @param adc_unit ADC unit. + * @return + * - intr Interrupt bitmask, See ``adc_digi_intr_t``. + */ +uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit) __attribute__((deprecated)); + +/** + * @brief Register ADC interrupt handler, the handler is an ISR. + * The handler will be attached to the same CPU core that this function is running on. + * + * @param fn Interrupt handler function. + * @param arg Parameter for handler function + * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred) + * ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. + * + * @return + * - ESP_OK Success + * - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags. + * - ESP_ERR_INVALID_ARG Function pointer error. + */ +esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags) __attribute__((deprecated)); + +/** + * @brief Deregister ADC interrupt handler, the handler is an ISR. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG hander error. + * - ESP_FAIL ISR not be registered. + */ +esp_err_t adc_digi_isr_deregister(void) __attribute__((deprecated)); +#endif // #if CONFIG_IDF_TARGET_ESP32S2 + + +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 +/*--------------------------------------------------------------- + ESP32, ESP32S2 Deprecated ADC APIs +---------------------------------------------------------------*/ +/** + * @brief ADC digital controller initialization. + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_init(void) __attribute__((deprecated)); + +/** + * @brief ADC digital controller deinitialization. + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_deinit(void) __attribute__((deprecated)); +#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 + + +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 +/*--------------------------------------------------------------- + ESP32, ESP32S2, ESP32C3 Deprecated ADC APIs +---------------------------------------------------------------*/ +/** + * @brief Setting the digital controller. + * + * @param config Pointer to digital controller paramter. Refer to ``adc_digi_config_t``. + * + * @return + * - ESP_ERR_INVALID_STATE Driver state is invalid. + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. + * - ESP_OK On success + */ +esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) __attribute__((deprecated)); + +/** + * @brief Initialize ADC pad + * @param adc_unit ADC unit index + * @param channel ADC channel index + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel) __attribute__((deprecated));; +#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 + + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/deprecated/driver/adc_types_deprecated.h b/components/driver/deprecated/driver/adc_types_deprecated.h new file mode 100644 index 0000000000..5d0e0dc232 --- /dev/null +++ b/components/driver/deprecated/driver/adc_types_deprecated.h @@ -0,0 +1,203 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include "esp_err.h" +#include "hal/adc_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_IDF_TARGET_ESP32 +/*--------------------------------------------------------------- + ESP32 Deprecated Types +---------------------------------------------------------------*/ +/** + * @brief ADC digital controller (DMA mode) conversion rules setting. + */ +typedef struct { + union { + struct { + uint8_t atten: 2; /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements. + 0: measurement range 0 - 800mV, + 1: measurement range 0 - 1100mV, + 2: measurement range 0 - 1350mV, + 3: measurement range 0 - 2600mV. */ + uint8_t bit_width: 2; /*!< ADC resolution. +- 0: 9 bit; +- 1: 10 bit; +- 2: 11 bit; +- 3: 12 bit. */ + int8_t channel: 4; /*!< ADC channel index. */ + }; + uint8_t val; /*! -#include -#include -#include -#include "sdkconfig.h" -#include "esp_intr_alloc.h" -#include "esp_log.h" -#include "esp_pm.h" -#include "sys/lock.h" -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "freertos/timers.h" -#include "freertos/ringbuf.h" -#include "esp32h2/rom/ets_sys.h" -#include "esp_private/periph_ctrl.h" -#include "driver/gpio.h" -#include "driver/adc.h" -#include "hal/adc_types.h" -#include "hal/adc_hal.h" -#include "hal/dma_types.h" -#include "esp_efuse_rtc_calib.h" -#include "esp_private/gdma.h" - -#define ADC_CHECK_RET(fun_ret) ({ \ - if (fun_ret != ESP_OK) { \ - ESP_LOGE(ADC_TAG,"%s(%d)",__FUNCTION__,__LINE__); \ - return ESP_FAIL; \ - } \ -}) - -static const char *ADC_TAG = "ADC"; - -#define ADC_CHECK(a, str, ret_val) ({ \ - if (!(a)) { \ - ESP_LOGE(ADC_TAG,"%s(%d) :%s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } \ -}) - -#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel]) - -#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG) - -extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. -#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) -#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) - -/** - * 1. sar_adc1_lock: this mutex lock is to protect the SARADC1 module. - * 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module. On H2, it is controlled by the digital controller - * and PWDET controller. - * 3. adc_reg_lock: this spin lock is to protect the shared registers used by ADC1 / ADC2 single read mode. - */ -static _lock_t sar_adc1_lock; -#define SAR_ADC1_LOCK_ACQUIRE() _lock_acquire(&sar_adc1_lock) -#define SAR_ADC1_LOCK_RELEASE() _lock_release(&sar_adc1_lock) -static _lock_t sar_adc2_lock; -#define SAR_ADC2_LOCK_ACQUIRE() _lock_acquire(&sar_adc2_lock) -#define SAR_ADC2_LOCK_RELEASE() _lock_release(&sar_adc2_lock) -portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED; -#define ADC_REG_LOCK_ENTER() portENTER_CRITICAL(&adc_reg_lock) -#define ADC_REG_LOCK_EXIT() portEXIT_CRITICAL(&adc_reg_lock) - -#define INTERNAL_BUF_NUM 5 -#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF - -/*--------------------------------------------------------------- - Digital Controller Context ----------------------------------------------------------------*/ -typedef struct adc_digi_context_t { - uint8_t *rx_dma_buf; //dma buffer - 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. - bool use_adc2; //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not. - adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation. - adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation. - adc_digi_config_t digi_controller_config; //Digital Controller Configuration - esp_pm_lock_handle_t pm_lock; //For power management -} adc_digi_context_t; - -static adc_digi_context_t *s_adc_digi_ctx = NULL; - -static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan, adc_atten_t atten); - -/*--------------------------------------------------------------- - ADC Continuous Read Mode (via DMA) ----------------------------------------------------------------*/ -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) -{ - return adc_channel_io_map[adc_unit][adc_channel]; -} - -static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask) -{ - esp_err_t ret = ESP_OK; - uint64_t gpio_mask = 0; - uint32_t n = 0; - int8_t io = 0; - - while (channel_mask) { - if (channel_mask & 0x1) { - io = adc_digi_get_io_num(adc_unit, n); - if (io < 0) { - return ESP_ERR_INVALID_ARG; - } - gpio_mask |= BIT64(io); - } - channel_mask = channel_mask >> 1; - n++; - } - - gpio_config_t cfg = { - .pin_bit_mask = gpio_mask, - .mode = GPIO_MODE_DISABLE, - }; - ret = gpio_config(&cfg); - - return ret; -} - -esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config) -{ - esp_err_t ret = ESP_OK; - - s_adc_digi_ctx = calloc(1, sizeof(adc_digi_context_t)); - if (s_adc_digi_ctx == NULL) { - ret = ESP_ERR_NO_MEM; - 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) { - ret = ESP_ERR_NO_MEM; - goto cleanup; - } - - //malloc internal buffer used by DMA - s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL); - if (!s_adc_digi_ctx->rx_dma_buf) { - ret = ESP_ERR_NO_MEM; - goto cleanup; - } - - //malloc dma descriptor - 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; - } - - //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)); - if (!s_adc_digi_ctx->digi_controller_config.adc_pattern) { - ret = ESP_ERR_NO_MEM; - goto cleanup; - } - -#if CONFIG_PM_ENABLE - ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &s_adc_digi_ctx->pm_lock); - if (ret != ESP_OK) { - goto cleanup; - } -#endif //CONFIG_PM_ENABLE - - //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) { - goto cleanup; - } - } - if (init_config->adc2_chan_mask) { - ret = adc_digi_gpio_init(ADC_NUM_2, init_config->adc2_chan_mask); - if (ret != ESP_OK) { - goto cleanup; - } - } - - //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); - - adc_hal_config_t config = { - .desc_max_num = INTERNAL_BUF_NUM, - .dma_chan = dma_chan, - .eof_num = init_config->conv_num_each_intr / ADC_HAL_DATA_LEN_PER_CONV - }; - adc_hal_context_config(&s_adc_digi_ctx->hal, &config); - - //enable SARADC module clock - periph_module_enable(PERIPH_SARADC_MODULE); - - adc_hal_calibration_init(ADC_NUM_1); - adc_hal_calibration_init(ADC_NUM_2); - - return ret; - -cleanup: - adc_digi_deinitialize(); - return ret; - -} - -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) -{ - assert(event_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); -} - -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_HAL_DMA_DESC_VALID) { - break; - } - - 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; - } - } - - if (status == ADC_HAL_DMA_DESC_NULL) { - //start next turns of dma operation - adc_hal_digi_rxdma_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf); - } - - return (taskAwoken == pdTRUE); -} - -esp_err_t adc_digi_start(void) -{ - if (s_adc_digi_ctx->driver_start_flag != 0) { - ESP_LOGE(ADC_TAG, "The driver is already started"); - return ESP_ERR_INVALID_STATE; - } - adc_power_acquire(); - //reset flags - s_adc_digi_ctx->ringbuf_overflow_flag = 0; - s_adc_digi_ctx->driver_start_flag = 1; - if (s_adc_digi_ctx->use_adc1) { - SAR_ADC1_LOCK_ACQUIRE(); - } - if (s_adc_digi_ctx->use_adc2) { - SAR_ADC2_LOCK_ACQUIRE(); - } - -#if CONFIG_PM_ENABLE - // Lock APB frequency while ADC driver is in use - esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock); -#endif - - adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); - if (s_adc_digi_ctx->use_adc1) { - uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc1_atten); - adc_hal_set_calibration_param(ADC_NUM_1, cal_val); - } - if (s_adc_digi_ctx->use_adc2) { - uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc2_atten); - adc_hal_set_calibration_param(ADC_NUM_2, cal_val); - } - - adc_hal_init(); - adc_hal_arbiter_config(&config); - adc_hal_digi_init(&s_adc_digi_ctx->hal); - adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_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, s_adc_digi_ctx->rx_dma_buf); - //start ADC - adc_hal_digi_start(&s_adc_digi_ctx->hal); - - return ESP_OK; -} - -esp_err_t adc_digi_stop(void) -{ - if (s_adc_digi_ctx->driver_start_flag != 1) { - ESP_LOGE(ADC_TAG, "The driver is already stopped"); - return ESP_ERR_INVALID_STATE; - } - s_adc_digi_ctx->driver_start_flag = 0; - - //disable the in suc eof intrrupt - 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, IN_SUC_EOF_BIT); - //stop ADC - 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(); -#if CONFIG_PM_ENABLE - if (s_adc_digi_ctx->pm_lock) { - esp_pm_lock_release(s_adc_digi_ctx->pm_lock); - } -#endif //CONFIG_PM_ENABLE - - if (s_adc_digi_ctx->use_adc1) { - SAR_ADC1_LOCK_RELEASE(); - } - if (s_adc_digi_ctx->use_adc2) { - SAR_ADC2_LOCK_RELEASE(); - } - adc_power_release(); - - return ESP_OK; -} - -esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms) -{ - TickType_t ticks_to_wait; - esp_err_t ret = ESP_OK; - uint8_t *data = NULL; - size_t size = 0; - - ticks_to_wait = timeout_ms / portTICK_RATE_MS; - if (timeout_ms == ADC_MAX_DELAY) { - ticks_to_wait = portMAX_DELAY; - } - - data = xRingbufferReceiveUpTo(s_adc_digi_ctx->ringbuf_hdl, &size, ticks_to_wait, length_max); - if (!data) { - ESP_LOGV(ADC_TAG, "No data, increase timeout or reduce conv_num_each_intr"); - ret = ESP_ERR_TIMEOUT; - *out_length = 0; - return ret; - } - - memcpy(buf, data, size); - vRingbufferReturnItem(s_adc_digi_ctx->ringbuf_hdl, data); - assert((size % 4) == 0); - *out_length = size; - - if (s_adc_digi_ctx->ringbuf_overflow_flag) { - ret = ESP_ERR_INVALID_STATE; - } - - return ret; -} - -esp_err_t adc_digi_deinitialize(void) -{ - if (!s_adc_digi_ctx) { - return ESP_ERR_INVALID_STATE; - } - - if (s_adc_digi_ctx->driver_start_flag != 0) { - ESP_LOGE(ADC_TAG, "The driver is not stopped"); - return ESP_ERR_INVALID_STATE; - } - - if (s_adc_digi_ctx->ringbuf_hdl) { - vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl); - s_adc_digi_ctx->ringbuf_hdl = NULL; - } - -#if CONFIG_PM_ENABLE - if (s_adc_digi_ctx->pm_lock) { - esp_pm_lock_delete(s_adc_digi_ctx->pm_lock); - } -#endif //CONFIG_PM_ENABLE - - free(s_adc_digi_ctx->rx_dma_buf); - 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); - - free(s_adc_digi_ctx); - s_adc_digi_ctx = NULL; - - periph_module_disable(PERIPH_SARADC_MODULE); - - return ESP_OK; -} - -/*--------------------------------------------------------------- - ADC Single Read Mode ----------------------------------------------------------------*/ -static adc_atten_t s_atten1_single[ADC1_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC1, used by single read API -static adc_atten_t s_atten2_single[ADC2_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC2, used by single read API - -esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio) -{ - esp_err_t ret; - uint32_t channel = ADC2_CHANNEL_MAX; - if (adc_unit == ADC_UNIT_2) { - for (int i = 0; i < ADC2_CHANNEL_MAX; i++) { - if (gpio == ADC_GET_IO_NUM(ADC_NUM_2, i)) { - channel = i; - break; - } - } - if (channel == ADC2_CHANNEL_MAX) { - return ESP_ERR_INVALID_ARG; - } - } - - adc_power_acquire(); - if (adc_unit & ADC_UNIT_1) { - ADC_ENTER_CRITICAL(); - adc_hal_vref_output(ADC_NUM_1, channel, true); - ADC_EXIT_CRITICAL() - } else if (adc_unit & ADC_UNIT_2) { - ADC_ENTER_CRITICAL(); - adc_hal_vref_output(ADC_NUM_2, channel, true); - ADC_EXIT_CRITICAL() - } - - ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel)); - - return ret; -} - -esp_err_t adc1_config_width(adc_bits_width_t width_bit) -{ - //On ESP32H2, the data width is always 12-bits. - if (width_bit != ADC_WIDTH_BIT_12) { - return ESP_ERR_INVALID_ARG; - } - - return ESP_OK; -} - -esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten) -{ - ADC_CHANNEL_CHECK(ADC_NUM_1, channel); - ADC_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG); - - esp_err_t ret = ESP_OK; - s_atten1_single[channel] = atten; - ret = adc_digi_gpio_init(ADC_NUM_1, BIT(channel)); - - adc_hal_calibration_init(ADC_NUM_1); - - return ret; -} - -int adc1_get_raw(adc1_channel_t channel) -{ - int raw_out = 0; - - periph_module_enable(PERIPH_SARADC_MODULE); - adc_power_acquire(); - - SAR_ADC1_LOCK_ACQUIRE(); - - adc_atten_t atten = s_atten1_single[channel]; - uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, channel, atten); - adc_hal_set_calibration_param(ADC_NUM_1, cal_val); - - ADC_REG_LOCK_ENTER(); - adc_hal_set_atten(ADC_NUM_2, channel, atten); - adc_hal_convert(ADC_NUM_1, channel, &raw_out); - ADC_REG_LOCK_EXIT(); - - SAR_ADC1_LOCK_RELEASE(); - - adc_power_release(); - periph_module_disable(PERIPH_SARADC_MODULE); - - return raw_out; -} - -esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten) -{ - ADC_CHANNEL_CHECK(ADC_NUM_2, channel); - ADC_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG); - - esp_err_t ret = ESP_OK; - s_atten2_single[channel] = atten; - ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel)); - - adc_hal_calibration_init(ADC_NUM_2); - - return ret; -} - -esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out) -{ - //On ESP32H2, the data width is always 12-bits. - if (width_bit != ADC_WIDTH_BIT_12) { - return ESP_ERR_INVALID_ARG; - } - - esp_err_t ret = ESP_OK; - - periph_module_enable(PERIPH_SARADC_MODULE); - adc_power_acquire(); - - SAR_ADC2_LOCK_ACQUIRE(); - - adc_atten_t atten = s_atten2_single[channel]; - uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, channel, atten); - adc_hal_set_calibration_param(ADC_NUM_2, cal_val); - - ADC_REG_LOCK_ENTER(); - adc_hal_set_atten(ADC_NUM_2, channel, atten); - ret = adc_hal_convert(ADC_NUM_2, channel, raw_out); - ADC_REG_LOCK_EXIT(); - - SAR_ADC2_LOCK_RELEASE(); - - adc_power_release(); - periph_module_disable(PERIPH_SARADC_MODULE); - - return ret; -} - - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ -esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) -{ - if (!s_adc_digi_ctx) { - return ESP_ERR_INVALID_STATE; - } - ADC_CHECK(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, "ADC sampling frequency out of range", ESP_ERR_INVALID_ARG); - - s_adc_digi_ctx->digi_controller_config.conv_limit_en = config->conv_limit_en; - s_adc_digi_ctx->digi_controller_config.conv_limit_num = config->conv_limit_num; - s_adc_digi_ctx->digi_controller_config.adc_pattern_len = config->adc_pattern_len; - s_adc_digi_ctx->digi_controller_config.sample_freq_hz = config->sample_freq_hz; - memcpy(s_adc_digi_ctx->digi_controller_config.adc_pattern, config->adc_pattern, config->adc_pattern_len * sizeof(adc_digi_pattern_table_t)); - - const int atten_uninitialised = 999; - s_adc_digi_ctx->adc1_atten = atten_uninitialised; - s_adc_digi_ctx->adc2_atten = atten_uninitialised; - s_adc_digi_ctx->use_adc1 = 0; - s_adc_digi_ctx->use_adc2 = 0; - for (int i = 0; i < config->adc_pattern_len; i++) { - const adc_digi_pattern_table_t *pat = &config->adc_pattern[i]; - if (pat->unit == ADC_NUM_1) { - s_adc_digi_ctx->use_adc1 = 1; - - if (s_adc_digi_ctx->adc1_atten == atten_uninitialised) { - s_adc_digi_ctx->adc1_atten = pat->atten; - } else if (s_adc_digi_ctx->adc1_atten != pat->atten) { - return ESP_ERR_INVALID_ARG; - } - } else if (pat->unit == ADC_NUM_2) { - //See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver - s_adc_digi_ctx->use_adc2 = 1; - - if (s_adc_digi_ctx->adc2_atten == atten_uninitialised) { - s_adc_digi_ctx->adc2_atten = pat->atten; - } else if (s_adc_digi_ctx->adc2_atten != pat->atten) { - return ESP_ERR_INVALID_ARG; - } - } - } - - return ESP_OK; -} - -/*************************************/ -/* Digital controller filter setting */ -/*************************************/ - -esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx) -{ - ADC_ENTER_CRITICAL(); - adc_hal_digi_filter_reset(idx); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config) -{ - ADC_ENTER_CRITICAL(); - adc_hal_digi_filter_set_factor(idx, config); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config) -{ - ADC_ENTER_CRITICAL(); - adc_hal_digi_filter_get_factor(idx, config); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable) -{ - ADC_ENTER_CRITICAL(); - adc_hal_digi_filter_enable(idx, enable); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -/**************************************/ -/* Digital controller monitor setting */ -/**************************************/ - -esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config) -{ - ADC_ENTER_CRITICAL(); - adc_hal_digi_monitor_config(idx, config); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable) -{ - - ADC_ENTER_CRITICAL(); - adc_hal_digi_monitor_enable(idx, enable); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -/*--------------------------------------------------------------- - RTC controller setting ----------------------------------------------------------------*/ - -static uint16_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][ADC_ATTEN_MAX] = {}; - -//NOTE: according to calibration version, different types of lock may be taken during the process: -// 1. Semaphore when reading efuse -// 2. Lock (Spinlock, or Mutex) if we actually do ADC calibration in the future -//This function shoudn't be called inside critical section or ISR -static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) -{ - const bool no_cal = false; - if (s_adc_cali_param[adc_n][atten]) { - return (uint32_t)s_adc_cali_param[adc_n][atten]; - } - - if (no_cal) { - return 0; //indicating failure - } - - // check if we can fetch the values from eFuse. - int version = esp_efuse_rtc_calib_get_ver(); - - uint32_t init_code = 0; - if (version == 1) { - //for calibration v1, both ADC units use the same init code (calibrated by ADC1) - init_code = esp_efuse_rtc_calib_get_init_code(version, atten); - ESP_LOGD(ADC_TAG, "Calib(V%d) ADC0, 1 atten=%d: %04X", version, atten, init_code); - s_adc_cali_param[0][atten] = init_code; - s_adc_cali_param[1][atten] = init_code; - } else { - adc_power_acquire(); - ADC_ENTER_CRITICAL(); - const bool internal_gnd = true; - init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd); - ADC_EXIT_CRITICAL(); - adc_power_release(); - - ESP_LOGD(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code); - s_adc_cali_param[adc_n][atten] = init_code; - } - - return init_code; -} - -// Internal function to calibrate PWDET for WiFi -esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) -{ - adc_hal_calibration_init(adc_n); - uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten); - ADC_ENTER_CRITICAL(); - adc_hal_set_calibration_param(adc_n, cal_val); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} diff --git a/components/driver/esp32h2/adc2_init_cal.c b/components/driver/esp32h2/adc2_init_cal.c deleted file mode 100644 index 351e795024..0000000000 --- a/components/driver/esp32h2/adc2_init_cal.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* This file is used to get `adc2_init_code_calibration` executed before the APP when the ADC2 is used by Wi-Fi or other drivers. -The linker will link constructor (adc2_init_code_calibration) only when any sections inside the same file (adc2_cal_include) is used. -Don't put any other code into this file. */ - -#include "adc2_wifi_private.h" -#include "hal/adc_hal.h" -#include "esp_private/adc_cali.h" - -/** - * @brief Set initial code to ADC2 after calibration. ADC2 RTC and ADC2 PWDET controller share the initial code. - * This API be called in before `app_main()`. - */ -static __attribute__((constructor)) void adc2_init_code_calibration(void) -{ - const adc_ll_num_t adc_n = ADC_NUM_2; - const adc_atten_t atten = ADC_ATTEN_DB_11; - const adc_channel_t channel = 0; - adc_cal_offset(adc_n, channel, atten); -} - -/** Don't call `adc2_cal_include` in user code. */ -void adc2_cal_include(void) -{ - /* When this empty function is called, the `adc2_init_code_calibration` constructor will be linked and executed before the app.*/ -} diff --git a/components/driver/esp32h2/include/driver/adc.h b/components/driver/esp32h2/include/driver/adc.h deleted file mode 100644 index 7567c7b2a1..0000000000 --- a/components/driver/esp32h2/include/driver/adc.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "driver/adc_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*--------------------------------------------------------------- - Common setting ----------------------------------------------------------------*/ -/*************************************/ -/* Digital controller filter setting */ -/*************************************/ -/** - * @brief Reset adc digital controller filter. - * - * @param idx Filter index. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx); - -/** - * @brief Set adc digital controller filter configuration. - * - * @param idx Filter index. - * @param config See ``adc_digi_filter_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config); - -/** - * @brief Get adc digital controller filter configuration. - * - * @param idx Filter index. - * @param config See ``adc_digi_filter_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config); - -/** - * @brief Enable/disable adc digital controller filter. - * Filtering the ADC data to obtain smooth data at higher sampling rates. - * - * @param idx Filter index. - * @param enable Enable/Disable filter. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable); - -/**************************************/ -/* Digital controller monitor setting */ -/**************************************/ - -/** - * @brief Config monitor of adc digital controller. - * - * @param idx Monitor index. - * @param config See ``adc_digi_monitor_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config); - -/** - * @brief Enable/disable monitor of adc digital controller. - * - * @param idx Monitor index. - * @param enable True or false enable monitor. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable); - -#ifdef __cplusplus -} -#endif diff --git a/components/driver/esp32s2/adc.c b/components/driver/esp32s2/adc.c index 2b73bd2f72..2c032a732a 100644 --- a/components/driver/esp32s2/adc.c +++ b/components/driver/esp32s2/adc.c @@ -11,229 +11,24 @@ #include "esp_log.h" #include "sys/lock.h" #include "freertos/FreeRTOS.h" -#include "freertos/xtensa_api.h" -#include "freertos/semphr.h" -#include "freertos/timers.h" -#include "esp_pm.h" -#include "esp_intr_alloc.h" -#include "esp_private/periph_ctrl.h" -#include "driver/rtc_io.h" -#include "driver/rtc_cntl.h" -#include "driver/gpio.h" -#include "driver/adc.h" -#include "esp_efuse_rtc_table.h" - #include "hal/adc_types.h" -#include "hal/adc_hal.h" - -#define ADC_CHECK_RET(fun_ret) ({ \ - if (fun_ret != ESP_OK) { \ - ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__); \ - return ESP_FAIL; \ - } \ -}) - -static const char *ADC_TAG = "ADC"; - -#define ADC_CHECK(a, str, ret_val) ({ \ - if (!(a)) { \ - ESP_LOGE(ADC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } \ -}) - -#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel]) - -#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG) +#include "hal/adc_ll.h" extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. #define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) #define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) -#ifdef CONFIG_PM_ENABLE -static esp_pm_lock_handle_t s_adc_digi_arbiter_lock = NULL; -#endif //CONFIG_PM_ENABLE - -esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten); - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ -esp_err_t adc_digi_init(void) -{ - adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); - ADC_ENTER_CRITICAL(); - adc_hal_init(); - adc_hal_arbiter_config(&config); - ADC_EXIT_CRITICAL(); - - adc_hal_calibration_init(ADC_NUM_1); - adc_hal_calibration_init(ADC_NUM_2); - - return ESP_OK; -} - -esp_err_t adc_digi_deinit(void) -{ -#ifdef CONFIG_PM_ENABLE - if (s_adc_digi_arbiter_lock) { - esp_pm_lock_delete(s_adc_digi_arbiter_lock); - s_adc_digi_arbiter_lock = NULL; - } -#endif - adc_power_release(); - ADC_ENTER_CRITICAL(); - adc_hal_digi_deinit(); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) -{ -#ifdef CONFIG_PM_ENABLE - esp_err_t err; - if (s_adc_digi_arbiter_lock == NULL) { - if (config->dig_clk.use_apll) { - err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "adc_dma", &s_adc_digi_arbiter_lock); - } else { - err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &s_adc_digi_arbiter_lock); - } - if (err != ESP_OK) { - s_adc_digi_arbiter_lock = NULL; - ESP_LOGE(ADC_TAG, "ADC-DMA pm lock error"); - return err; - } - } -#endif //CONFIG_PM_ENABLE - - if (config->conv_mode & ADC_CONV_SINGLE_UNIT_1) { - for (int i = 0; i < config->adc1_pattern_len; i++) { - adc_cal_offset(ADC_NUM_1, config->adc1_pattern[i].channel, config->adc1_pattern[i].atten); - } - } - if (config->conv_mode & ADC_CONV_SINGLE_UNIT_2) { - for (int i = 0; i < config->adc2_pattern_len; i++) { - adc_cal_offset(ADC_NUM_2, config->adc2_pattern[i].channel, config->adc2_pattern[i].atten); - } - } - - /* If enable digtal controller, adc xpd should always on. */ - adc_power_acquire(); - ADC_ENTER_CRITICAL(); - adc_hal_digi_controller_config(config); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config) -{ - if (adc_unit & ADC_UNIT_1) { - return ESP_ERR_NOT_SUPPORTED; - } - ADC_ENTER_CRITICAL(); - adc_hal_arbiter_config(config); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - /** - * @brief Set ADC module controller. - * There are five SAR ADC controllers: - * Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes; - * Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep; - * the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2. + * Config monitor of adc digital controller. * - * @note Only ADC2 support arbiter to switch controllers automatically. Access to the ADC is based on the priority of the controller. - * @note For ADC1, Controller access is mutually exclusive. - * - * @param adc_unit ADC unit. - * @param ctrl ADC controller, Refer to `adc_ll_controller_t`. - * - * @return - * - ESP_OK Success + * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time. + * @param adc_n ADC unit. + * @param config Refer to ``adc_digi_monitor_t``. */ -esp_err_t adc_set_controller(adc_unit_t adc_unit, adc_ll_controller_t ctrl) +static void adc_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config) { - adc_arbiter_t config = {0}; - adc_arbiter_t cfg = ADC_ARBITER_CONFIG_DEFAULT(); - - if (adc_unit & ADC_UNIT_1) { - adc_hal_set_controller(ADC_NUM_1, ctrl); - } - if (adc_unit & ADC_UNIT_2) { - adc_hal_set_controller(ADC_NUM_2, ctrl); - switch (ctrl) { - case ADC2_CTRL_FORCE_PWDET: - config.pwdet_pri = 2; - config.mode = ADC_ARB_MODE_SHIELD; - adc_hal_arbiter_config(&config); - adc_hal_set_controller(ADC_NUM_2, ADC2_CTRL_PWDET); - break; - case ADC2_CTRL_FORCE_RTC: - config.rtc_pri = 2; - config.mode = ADC_ARB_MODE_SHIELD; - adc_hal_arbiter_config(&config); - adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC); - break; - case ADC2_CTRL_FORCE_ULP: - config.rtc_pri = 2; - config.mode = ADC_ARB_MODE_SHIELD; - adc_hal_arbiter_config(&config); - adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_ULP); - break; - case ADC2_CTRL_FORCE_DIG: - config.dig_pri = 2; - config.mode = ADC_ARB_MODE_SHIELD; - adc_hal_arbiter_config(&config); - adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_DIG); - break; - default: - adc_hal_arbiter_config(&cfg); - break; - } - } - return ESP_OK; -} - -esp_err_t adc_digi_start(void) -{ -#ifdef CONFIG_PM_ENABLE - ADC_CHECK((s_adc_digi_arbiter_lock), "Should start after call `adc_digi_controller_config`", ESP_FAIL); - esp_pm_lock_acquire(s_adc_digi_arbiter_lock); -#endif - ADC_ENTER_CRITICAL(); - adc_hal_digi_enable(); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -esp_err_t adc_digi_stop(void) -{ -#ifdef CONFIG_PM_ENABLE - if (s_adc_digi_arbiter_lock) { - esp_pm_lock_release(s_adc_digi_arbiter_lock); - } -#endif - ADC_ENTER_CRITICAL(); - adc_hal_digi_disable(); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -/** - * @brief Reset FSM of adc digital controller. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_reset(void) -{ - ADC_ENTER_CRITICAL(); - adc_hal_digi_reset(); - adc_hal_digi_clear_pattern_table(ADC_NUM_1); - adc_hal_digi_clear_pattern_table(ADC_NUM_2); - ADC_EXIT_CRITICAL(); - return ESP_OK; + adc_ll_digi_monitor_set_mode(adc_n, config->mode); + adc_ll_digi_monitor_set_thres(adc_n, config->threshold); } /*************************************/ @@ -244,9 +39,9 @@ esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx) { ADC_ENTER_CRITICAL(); if (idx == ADC_DIGI_FILTER_IDX0) { - adc_hal_digi_filter_reset(ADC_NUM_1); + adc_ll_digi_filter_reset(ADC_NUM_1); } else if (idx == ADC_DIGI_FILTER_IDX1) { - adc_hal_digi_filter_reset(ADC_NUM_2); + adc_ll_digi_filter_reset(ADC_NUM_2); } ADC_EXIT_CRITICAL(); return ESP_OK; @@ -256,9 +51,9 @@ esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_ { ADC_ENTER_CRITICAL(); if (idx == ADC_DIGI_FILTER_IDX0) { - adc_hal_digi_filter_set_factor(ADC_NUM_1, config->mode); + adc_ll_digi_filter_set_factor(ADC_NUM_1, config->mode); } else if (idx == ADC_DIGI_FILTER_IDX1) { - adc_hal_digi_filter_set_factor(ADC_NUM_2, config->mode); + adc_ll_digi_filter_set_factor(ADC_NUM_2, config->mode); } ADC_EXIT_CRITICAL(); return ESP_OK; @@ -270,11 +65,11 @@ esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_ if (idx == ADC_DIGI_FILTER_IDX0) { config->adc_unit = ADC_UNIT_1; config->channel = ADC_CHANNEL_MAX; - adc_hal_digi_filter_get_factor(ADC_NUM_1, &config->mode); + adc_ll_digi_filter_get_factor(ADC_NUM_1, &config->mode); } else if (idx == ADC_DIGI_FILTER_IDX1) { config->adc_unit = ADC_UNIT_2; config->channel = ADC_CHANNEL_MAX; - adc_hal_digi_filter_get_factor(ADC_NUM_2, &config->mode); + adc_ll_digi_filter_get_factor(ADC_NUM_2, &config->mode); } ADC_EXIT_CRITICAL(); return ESP_OK; @@ -284,9 +79,9 @@ esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable) { ADC_ENTER_CRITICAL(); if (idx == ADC_DIGI_FILTER_IDX0) { - adc_hal_digi_filter_enable(ADC_NUM_1, enable); + adc_ll_digi_filter_enable(ADC_NUM_1, enable); } else if (idx == ADC_DIGI_FILTER_IDX1) { - adc_hal_digi_filter_enable(ADC_NUM_2, enable); + adc_ll_digi_filter_enable(ADC_NUM_2, enable); } ADC_EXIT_CRITICAL(); return ESP_OK; @@ -303,9 +98,9 @@ esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable) int adc_digi_filter_read_data(adc_digi_filter_idx_t idx) { if (idx == ADC_DIGI_FILTER_IDX0) { - return adc_hal_digi_filter_read_data(ADC_NUM_1); + return adc_ll_digi_filter_read_data(ADC_NUM_1); } else if (idx == ADC_DIGI_FILTER_IDX1) { - return adc_hal_digi_filter_read_data(ADC_NUM_2); + return adc_ll_digi_filter_read_data(ADC_NUM_2); } else { return -1; } @@ -319,9 +114,9 @@ esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monit { ADC_ENTER_CRITICAL(); if (idx == ADC_DIGI_MONITOR_IDX0) { - adc_hal_digi_monitor_config(ADC_NUM_1, config); + adc_digi_monitor_config(ADC_NUM_1, config); } else if (idx == ADC_DIGI_MONITOR_IDX1) { - adc_hal_digi_monitor_config(ADC_NUM_2, config); + adc_digi_monitor_config(ADC_NUM_2, config); } ADC_EXIT_CRITICAL(); return ESP_OK; @@ -331,148 +126,10 @@ esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable) { ADC_ENTER_CRITICAL(); if (idx == ADC_DIGI_MONITOR_IDX0) { - adc_hal_digi_monitor_enable(ADC_NUM_1, enable); + adc_ll_digi_monitor_enable(ADC_NUM_1, enable); } else if (idx == ADC_DIGI_MONITOR_IDX1) { - adc_hal_digi_monitor_enable(ADC_NUM_2, enable); + adc_ll_digi_monitor_enable(ADC_NUM_2, enable); } ADC_EXIT_CRITICAL(); return ESP_OK; } - -/**************************************/ -/* Digital controller intr setting */ -/**************************************/ - -esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) -{ - ADC_ENTER_CRITICAL(); - if (adc_unit & ADC_UNIT_1) { - adc_hal_digi_intr_enable(ADC_NUM_1, intr_mask); - } - if (adc_unit & ADC_UNIT_2) { - adc_hal_digi_intr_enable(ADC_NUM_2, intr_mask); - } - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) -{ - ADC_ENTER_CRITICAL(); - if (adc_unit & ADC_UNIT_1) { - adc_hal_digi_intr_disable(ADC_NUM_1, intr_mask); - } - if (adc_unit & ADC_UNIT_2) { - adc_hal_digi_intr_disable(ADC_NUM_2, intr_mask); - } - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) -{ - ADC_ENTER_CRITICAL(); - if (adc_unit & ADC_UNIT_1) { - adc_hal_digi_intr_clear(ADC_NUM_1, intr_mask); - } - if (adc_unit & ADC_UNIT_2) { - adc_hal_digi_intr_clear(ADC_NUM_2, intr_mask); - } - ADC_EXIT_CRITICAL(); - return ESP_OK; -} - -uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit) -{ - uint32_t ret = 0; - ADC_ENTER_CRITICAL(); - if (adc_unit & ADC_UNIT_1) { - ret = adc_hal_digi_get_intr_status(ADC_NUM_1); - } - if (adc_unit & ADC_UNIT_2) { - ret = adc_hal_digi_get_intr_status(ADC_NUM_2); - } - ADC_EXIT_CRITICAL(); - return ret; -} - -static uint8_t s_isr_registered = 0; -static intr_handle_t s_adc_isr_handle = NULL; - -esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags) -{ - ADC_CHECK((fn != NULL), "Parameter error", ESP_ERR_INVALID_ARG); - ADC_CHECK(s_isr_registered == 0, "ADC ISR have installed, can not install again", ESP_FAIL); - - esp_err_t ret = esp_intr_alloc(ETS_APB_ADC_INTR_SOURCE, intr_alloc_flags, fn, arg, &s_adc_isr_handle); - if (ret == ESP_OK) { - s_isr_registered = 1; - } - return ret; -} - -esp_err_t adc_digi_isr_deregister(void) -{ - esp_err_t ret = ESP_FAIL; - if (s_isr_registered) { - ret = esp_intr_free(s_adc_isr_handle); - if (ret == ESP_OK) { - s_isr_registered = 0; - } - } - return ret; -} - -/*--------------------------------------------------------------- - RTC controller setting ----------------------------------------------------------------*/ - -/*--------------------------------------------------------------- - Calibration ----------------------------------------------------------------*/ - -static uint16_t s_adc_cali_param[ADC_NUM_MAX][ADC_ATTEN_MAX] = { {0}, {0} }; - -//NOTE: according to calibration version, different types of lock may be taken during the process: -// 1. Semaphore when reading efuse -// 2. Spinlock when actually doing ADC calibration -//This function shoudn't be called inside critical section or ISR -uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) -{ -#ifdef CONFIG_IDF_ENV_FPGA - return 0; -#endif - - if (s_adc_cali_param[adc_n][atten]) { - ESP_LOGV(ADC_TAG, "Use calibrated val ADC%d atten=%d: %04X", adc_n, atten, s_adc_cali_param[adc_n][atten]); - return (uint32_t)s_adc_cali_param[adc_n][atten]; - } - - uint32_t dout = 0; - // check if we can fetch the values from eFuse. - int version = esp_efuse_rtc_table_read_calib_version(); - if (version == 2) { - int tag = esp_efuse_rtc_table_get_tag(version, adc_n + 1, atten, RTCCALIB_V2_PARAM_VINIT); - dout = esp_efuse_rtc_table_get_parsed_efuse_value(tag, false); - } else { - adc_power_acquire(); - ADC_ENTER_CRITICAL(); - const bool internal_gnd = true; - dout = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd); - ADC_EXIT_CRITICAL(); - adc_power_release(); - } - ESP_LOGD(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, dout); - s_adc_cali_param[adc_n][atten] = (uint16_t)dout; - return dout; -} - -esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) -{ - adc_hal_calibration_init(adc_n); - uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten); - ADC_ENTER_CRITICAL(); - adc_hal_set_calibration_param(adc_n, cal_val); - ADC_EXIT_CRITICAL(); - return ESP_OK; -} diff --git a/components/driver/esp32s2/include/driver/adc.h b/components/driver/esp32s2/include/driver/adc.h deleted file mode 100644 index 000fa73bb2..0000000000 --- a/components/driver/esp32s2/include/driver/adc.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "driver/adc_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*--------------------------------------------------------------- - Common setting ----------------------------------------------------------------*/ - -/** - * @brief Config ADC module arbiter. - * The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority, - * the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data. - * - * @note Only ADC2 support arbiter. - * @note Default priority: Wi-Fi > RTC > Digital; - * @note In normal use, there is no need to call this interface to config arbiter. - * - * @param adc_unit ADC unit. - * @param config Refer to `adc_arbiter_t`. - * - * @return - * - ESP_OK Success - * - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter. - */ -esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config); - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ - -/** - * @brief Enable digital controller to trigger the measurement. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_start(void); - -/** - * @brief Disable digital controller to trigger the measurement. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_stop(void); - -/*************************************/ -/* Digital controller filter setting */ -/*************************************/ -/** - * @brief Reset adc digital controller filter. - * - * @param idx Filter index. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx); - -/** - * @brief Set adc digital controller filter configuration. - * - * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. - * - * @param idx Filter index. - * @param config See ``adc_digi_filter_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config); - -/** - * @brief Get adc digital controller filter configuration. - * - * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. - * - * @param idx Filter index. - * @param config See ``adc_digi_filter_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config); - -/** - * @brief Enable/disable adc digital controller filter. - * Filtering the ADC data to obtain smooth data at higher sampling rates. - * - * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. - * - * @param idx Filter index. - * @param enable Enable/Disable filter. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable); - -/**************************************/ -/* Digital controller monitor setting */ -/**************************************/ - -/** - * @brief Config monitor of adc digital controller. - * - * @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time. - * - * @param idx Monitor index. - * @param config See ``adc_digi_monitor_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config); - -/** - * @brief Enable/disable monitor of adc digital controller. - * - * @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time. - * - * @param idx Monitor index. - * @param enable True or false enable monitor. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable); - -/**************************************/ -/* Digital controller intr setting */ -/**************************************/ - -/** - * @brief Enable interrupt of adc digital controller by bitmask. - * - * @param adc_unit ADC unit. - * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask); - -/** - * @brief Disable interrupt of adc digital controller by bitmask. - * - * @param adc_unit ADC unit. - * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask); - -/** - * @brief Clear interrupt of adc digital controller by bitmask. - * - * @param adc_unit ADC unit. - * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask); - -/** - * @brief Get interrupt status mask of adc digital controller. - * - * @param adc_unit ADC unit. - * @return - * - intr Interrupt bitmask, See ``adc_digi_intr_t``. - */ -uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit); - -/** - * @brief Register ADC interrupt handler, the handler is an ISR. - * The handler will be attached to the same CPU core that this function is running on. - * - * @param fn Interrupt handler function. - * @param arg Parameter for handler function - * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred) - * ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. - * - * @return - * - ESP_OK Success - * - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags. - * - ESP_ERR_INVALID_ARG Function pointer error. - */ -esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags); - -/** - * @brief Deregister ADC interrupt handler, the handler is an ISR. - * - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG hander error. - * - ESP_FAIL ISR not be registered. - */ -esp_err_t adc_digi_isr_deregister(void); - -/*--------------------------------------------------------------- - RTC controller setting ----------------------------------------------------------------*/ - -/*--------------------------------------------------------------- - Deprecated API ----------------------------------------------------------------*/ -/** - * @brief Set I2S data source - * - * @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC. - * - * @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead. - * - * @return - * - ESP_OK success - */ -esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src) __attribute__((deprecated)); - -/** - * @brief Initialize I2S ADC mode - * - * @param adc_unit ADC unit index - * @param channel ADC channel index - * - * @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead. - * - * @return - * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error - */ -esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) __attribute__((deprecated)); - -#ifdef __cplusplus -} -#endif diff --git a/components/driver/esp32s3/include/driver/adc.h b/components/driver/esp32s3/include/driver/adc.h deleted file mode 100644 index 8bade108db..0000000000 --- a/components/driver/esp32s3/include/driver/adc.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "driver/adc_common.h" -// This file will be removed. TODO: IDF-1776 diff --git a/components/driver/esp8684/include/driver/adc.h b/components/driver/esp8684/include/driver/adc.h deleted file mode 100644 index 7567c7b2a1..0000000000 --- a/components/driver/esp8684/include/driver/adc.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "driver/adc_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*--------------------------------------------------------------- - Common setting ----------------------------------------------------------------*/ -/*************************************/ -/* Digital controller filter setting */ -/*************************************/ -/** - * @brief Reset adc digital controller filter. - * - * @param idx Filter index. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx); - -/** - * @brief Set adc digital controller filter configuration. - * - * @param idx Filter index. - * @param config See ``adc_digi_filter_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config); - -/** - * @brief Get adc digital controller filter configuration. - * - * @param idx Filter index. - * @param config See ``adc_digi_filter_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config); - -/** - * @brief Enable/disable adc digital controller filter. - * Filtering the ADC data to obtain smooth data at higher sampling rates. - * - * @param idx Filter index. - * @param enable Enable/Disable filter. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable); - -/**************************************/ -/* Digital controller monitor setting */ -/**************************************/ - -/** - * @brief Config monitor of adc digital controller. - * - * @param idx Monitor index. - * @param config See ``adc_digi_monitor_t``. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config); - -/** - * @brief Enable/disable monitor of adc digital controller. - * - * @param idx Monitor index. - * @param enable True or false enable monitor. - * - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable); - -#ifdef __cplusplus -} -#endif diff --git a/components/driver/i2s.c b/components/driver/i2s.c index f8856708de..7b2dcb9216 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -8,7 +8,6 @@ #include #include #include - #include "freertos/FreeRTOS.h" #include "freertos/queue.h" #include "freertos/semphr.h" diff --git a/components/driver/include/driver/adc.h b/components/driver/include/driver/adc.h new file mode 100644 index 0000000000..24d964c512 --- /dev/null +++ b/components/driver/include/driver/adc.h @@ -0,0 +1,646 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "esp_err.h" +#include "sdkconfig.h" +#include "driver/gpio.h" +#include "hal/adc_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_IDF_TARGET_ESP32 +/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ +typedef enum { + ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */ + ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 */ + ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO38 */ + ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO39 */ + ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO32 */ + ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO33 */ + ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO34 */ + ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO35 */ + ADC1_CHANNEL_MAX, +} adc1_channel_t; +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776 +/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ +typedef enum { + ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO1 */ + ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO2 */ + ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO3 */ + ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO4 */ + ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO5 */ + ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO6 */ + ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO7 */ + ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO8 */ + ADC1_CHANNEL_8, /*!< ADC1 channel 8 is GPIO9 */ + ADC1_CHANNEL_9, /*!< ADC1 channel 9 is GPIO10 */ + ADC1_CHANNEL_MAX, +} adc1_channel_t; +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 +/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ +typedef enum { + ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */ + ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO1 */ + ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO2 */ + ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO3 */ + ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO4 */ + ADC1_CHANNEL_MAX, +} adc1_channel_t; +#endif // CONFIG_IDF_TARGET_* + +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776 +/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ +typedef enum { + ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO4 (ESP32), GPIO11 (ESP32-S2) */ + ADC2_CHANNEL_1, /*!< ADC2 channel 1 is GPIO0 (ESP32), GPIO12 (ESP32-S2) */ + ADC2_CHANNEL_2, /*!< ADC2 channel 2 is GPIO2 (ESP32), GPIO13 (ESP32-S2) */ + ADC2_CHANNEL_3, /*!< ADC2 channel 3 is GPIO15 (ESP32), GPIO14 (ESP32-S2) */ + ADC2_CHANNEL_4, /*!< ADC2 channel 4 is GPIO13 (ESP32), GPIO15 (ESP32-S2) */ + ADC2_CHANNEL_5, /*!< ADC2 channel 5 is GPIO12 (ESP32), GPIO16 (ESP32-S2) */ + ADC2_CHANNEL_6, /*!< ADC2 channel 6 is GPIO14 (ESP32), GPIO17 (ESP32-S2) */ + ADC2_CHANNEL_7, /*!< ADC2 channel 7 is GPIO27 (ESP32), GPIO18 (ESP32-S2) */ + ADC2_CHANNEL_8, /*!< ADC2 channel 8 is GPIO25 (ESP32), GPIO19 (ESP32-S2) */ + ADC2_CHANNEL_9, /*!< ADC2 channel 9 is GPIO26 (ESP32), GPIO20 (ESP32-S2) */ + ADC2_CHANNEL_MAX, +} adc2_channel_t; +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 +/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ +typedef enum { + ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */ + ADC2_CHANNEL_MAX, +} adc2_channel_t; +#endif + + +/** + * @brief ADC rtc controller attenuation option. + * + * @note This definitions are only for being back-compatible + */ +#define ADC_ATTEN_0db ADC_ATTEN_DB_0 +#define ADC_ATTEN_2_5db ADC_ATTEN_DB_2_5 +#define ADC_ATTEN_6db ADC_ATTEN_DB_6 +#define ADC_ATTEN_11db ADC_ATTEN_DB_11 + +/** + * The default (max) bit width of the ADC of current version. You can also get the maximum bitwidth + * by `SOC_ADC_MAX_BITWIDTH` defined in soc_caps.h. + */ +#define ADC_WIDTH_BIT_DEFAULT (ADC_WIDTH_MAX-1) + +//this definitions are only for being back-compatible +#define ADC_WIDTH_9Bit ADC_WIDTH_BIT_9 +#define ADC_WIDTH_10Bit ADC_WIDTH_BIT_10 +#define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11 +#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12 + +/** + * @brief ADC digital controller encode option. + * + * @deprecated The ESP32-S2 doesn't use I2S DMA. Call ``adc_digi_output_format_t`` instead. + */ +typedef enum { + ADC_ENCODE_12BIT, /*!< ADC to DMA data format, , [15:12]-channel [11:0]-12 bits ADC data */ + ADC_ENCODE_11BIT, /*!< ADC to DMA data format, [15]-unit, [14:11]-channel [10:0]-11 bits ADC data */ + ADC_ENCODE_MAX, +} adc_i2s_encode_t; + +/*--------------------------------------------------------------- + Common setting +---------------------------------------------------------------*/ + +/** + * @brief Enable ADC power + * @deprecated Use adc_power_acquire and adc_power_release instead. + */ +void adc_power_on(void) __attribute__((deprecated)); + +/** + * @brief Power off SAR ADC + * @deprecated Use adc_power_acquire and adc_power_release instead. + * This function will force power down for ADC. + * This function is deprecated because forcing power ADC power off may + * disrupt operation of other components which may be using the ADC. + */ +void adc_power_off(void) __attribute__((deprecated)); + +/** + * @brief Increment the usage counter for ADC module. + * ADC will stay powered on while the counter is greater than 0. + * Call adc_power_release when done using the ADC. + */ +void adc_power_acquire(void); + +/** + * @brief Decrement the usage counter for ADC module. + * ADC will stay powered on while the counter is greater than 0. + * Call this function when done using the ADC. + */ +void adc_power_release(void); + +/*--------------------------------------------------------------- + ADC Single Read Setting +---------------------------------------------------------------*/ +/** + * @brief Get the GPIO number of a specific ADC1 channel. + * + * @param channel Channel to get the GPIO number + * @param gpio_num output buffer to hold the GPIO number + * + * @return + * - ESP_OK if success + * - ESP_ERR_INVALID_ARG if channel not valid + */ +esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num); + +/** + * @brief Set the attenuation of a particular channel on ADC1, and configure its associated GPIO pin mux. + * + * The default ADC voltage is for attenuation 0 dB and listed in the table below. + * By setting higher attenuation it is possible to read higher voltages. + * + * Due to ADC characteristics, most accurate results are obtained within the "suggested range" + * shown in the following table. + * + * +----------+-------------+-----------------+ + * | | attenuation | suggested range | + * | SoC | (dB) | (mV) | + * +==========+=============+=================+ + * | | 0 | 100 ~ 950 | + * | +-------------+-----------------+ + * | | 2.5 | 100 ~ 1250 | + * | ESP32 +-------------+-----------------+ + * | | 6 | 150 ~ 1750 | + * | +-------------+-----------------+ + * | | 11 | 150 ~ 2450 | + * +----------+-------------+-----------------+ + * | | 0 | 0 ~ 750 | + * | +-------------+-----------------+ + * | | 2.5 | 0 ~ 1050 | + * | ESP32-S2 +-------------+-----------------+ + * | | 6 | 0 ~ 1300 | + * | +-------------+-----------------+ + * | | 11 | 0 ~ 2500 | + * +----------+-------------+-----------------+ + * + * For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges. + * + * @note For any given channel, this function must be called before the first time ``adc1_get_raw()`` is called for that channel. + * + * @note This function can be called multiple times to configure multiple + * ADC channels simultaneously. You may call ``adc1_get_raw()`` only after configuring a channel. + * + * @param channel ADC1 channel to configure + * @param atten Attenuation level + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten); + +/** + * @brief Configure ADC1 capture width, meanwhile enable output invert for ADC1. + * The configuration is for all channels of ADC1 + * @param width_bit Bit capture width for ADC1 + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t adc1_config_width(adc_bits_width_t width_bit); + +/** + * @brief Take an ADC1 reading from a single channel. + * @note ESP32: + * When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on, + * the input of GPIO36 and GPIO39 will be pulled down for about 80ns. + * When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39. + * Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue. + * As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA), + * but will remove the glitches on GPIO36 and GPIO39. + * + * @note Call ``adc1_config_width()`` before the first time this + * function is called. + * + * @note For any given channel, adc1_config_channel_atten(channel) + * must be called before the first time this function is called. Configuring + * a new channel does not prevent a previously configured channel from being read. + * + * @param channel ADC1 channel to read + * + * @return + * - -1: Parameter error + * - Other: ADC1 channel reading. + */ +int adc1_get_raw(adc1_channel_t channel); + +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +//TODO IDF-3610, replace these with proper caps +/** + * @brief Set ADC data invert + * @param adc_unit ADC unit index + * @param inv_en whether enable data invert + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en); + +/** + * @brief Set ADC source clock + * @param clk_div ADC clock divider, ADC clock is divided from APB clock + * @return + * - ESP_OK success + */ +esp_err_t adc_set_clk_div(uint8_t clk_div); + +/** + * @brief Configure ADC capture width. + * + * @param adc_unit ADC unit index + * @param width_bit Bit capture width for ADC unit. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit); + +/** + * @brief Configure ADC1 to be usable by the ULP + * + * This function reconfigures ADC1 to be controlled by the ULP. + * Effect of this function can be reverted using ``adc1_get_raw()`` function. + * + * Note that adc1_config_channel_atten, ``adc1_config_width()`` functions need + * to be called to configure ADC1 channels, before ADC1 is used by the ULP. + */ +void adc1_ulp_enable(void); +#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + +/** + * @brief Get the GPIO number of a specific ADC2 channel. + * + * @param channel Channel to get the GPIO number + * + * @param gpio_num output buffer to hold the GPIO number + * + * @return + * - ESP_OK if success + * - ESP_ERR_INVALID_ARG if channel not valid + */ +esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num); + +/** + * @brief Configure the ADC2 channel, including setting attenuation. + * + * The default ADC voltage is for attenuation 0 dB and listed in the table below. + * By setting higher attenuation it is possible to read higher voltages. + * + * Due to ADC characteristics, most accurate results are obtained within the "suggested range" + * shown in the following table. + * + * +----------+-------------+-----------------+ + * | | attenuation | suggested range | + * | SoC | (dB) | (mV) | + * +==========+=============+=================+ + * | | 0 | 100 ~ 950 | + * | +-------------+-----------------+ + * | | 2.5 | 100 ~ 1250 | + * | ESP32 +-------------+-----------------+ + * | | 6 | 150 ~ 1750 | + * | +-------------+-----------------+ + * | | 11 | 150 ~ 2450 | + * +----------+-------------+-----------------+ + * | | 0 | 0 ~ 750 | + * | +-------------+-----------------+ + * | | 2.5 | 0 ~ 1050 | + * | ESP32-S2 +-------------+-----------------+ + * | | 6 | 0 ~ 1300 | + * | +-------------+-----------------+ + * | | 11 | 0 ~ 2500 | + * +----------+-------------+-----------------+ + * + * For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges. + * + * @note This function also configures the input GPIO pin mux to + * connect it to the ADC2 channel. It must be called before calling + * ``adc2_get_raw()`` for this channel. + * + * @note For any given channel, this function must be called before the first time ``adc2_get_raw()`` is called for that channel. + * + * @param channel ADC2 channel to configure + * @param atten Attenuation level + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten); + +/** + * @brief Take an ADC2 reading on a single channel + * + * @note ESP32: + * When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on, + * the input of GPIO36 and GPIO39 will be pulled down for about 80ns. + * When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39. + * Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue. + * As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA), + * but will remove the glitches on GPIO36 and GPIO39. + * + * + * @note ESP32: + * For a given channel, ``adc2_config_channel_atten()`` + * must be called before the first time this function is called. If Wi-Fi is started via ``esp_wifi_start()``, this + * function will always fail with ``ESP_ERR_TIMEOUT``. + * + * @note ESP32-S2: + * ADC2 support hardware arbiter. The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority, + * the low priority controller will read the invalid ADC2 data. Default priority: Wi-Fi > RTC > Digital; + * + * @param channel ADC2 channel to read + * @param width_bit Bit capture width for ADC2 + * @param raw_out the variable to hold the output data. + * + * @return + * - ESP_OK if success + * - ESP_ERR_TIMEOUT ADC2 is being used by other controller and the request timed out. + * - ESP_ERR_INVALID_STATE The controller status is invalid. Please try again. + */ +esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out); + +/** + * @brief Output ADC1 or ADC2's reference voltage to ``adc2_channe_t``'s IO. + * + * This function routes the internal reference voltage of ADCn to one of + * ADC2's channels. This reference voltage can then be manually measured + * for calibration purposes. + * + * @note ESP32 only supports output of ADC2's internal reference voltage. + * @param[in] adc_unit ADC unit index + * @param[in] gpio GPIO number (Only ADC2's channels IO are supported) + * + * @return + * - ESP_OK: v_ref successfully routed to selected GPIO + * - ESP_ERR_INVALID_ARG: Unsupported GPIO + */ +esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio); + +/** + * @brief Output ADC2 reference voltage to ``adc2_channe_t``'s IO. + * + * This function routes the internal reference voltage of ADCn to one of + * ADC2's channels. This reference voltage can then be manually measured + * for calibration purposes. + * + * @deprecated Use ``adc_vref_to_gpio`` instead. + * + * @param[in] gpio GPIO number (ADC2's channels are supported) + * + * @return + * - ESP_OK: v_ref successfully routed to selected GPIO + * - ESP_ERR_INVALID_ARG: Unsupported GPIO + */ +esp_err_t adc2_vref_to_gpio(gpio_num_t gpio) __attribute__((deprecated)); + +/*--------------------------------------------------------------- + DMA setting +---------------------------------------------------------------*/ +/** + * @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports + */ +#define ADC_MAX_DELAY UINT32_MAX + +/** + * @brief ADC DMA driver configuration + */ +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. + uint32_t conv_num_each_intr; ///< Bytes of data that can be converted in 1 interrupt. + 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; + +/** + * @brief ADC digital controller settings + */ +typedef struct { + bool conv_limit_en; ///< To limit ADC conversion times. Conversion stops after finishing `conv_limit_num` times conversion + uint32_t conv_limit_num; ///< Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. + uint32_t pattern_num; ///< Number of ADC channels that will be used + adc_digi_pattern_config_t *adc_pattern; ///< List of configs for each ADC channel that will be used + uint32_t sample_freq_hz; /*!< The expected ADC sampling frequency in Hz. Range: 611Hz ~ 83333Hz + Fs = Fd / interval / 2 + Fs: sampling frequency; + Fd: digital controller frequency, no larger than 5M for better performance + interval: interval between 2 measurement trigger signal, the smallest interval should not be smaller than the ADC measurement period, the largest interval should not be larger than 4095 */ + adc_digi_convert_mode_t conv_mode; ///< ADC DMA conversion mode, see `adc_digi_convert_mode_t`. + adc_digi_output_format_t format; ///< ADC DMA conversion output format, see `adc_digi_output_format_t`. +} adc_digi_configuration_t; + +/** + * @brief Initialize the Digital ADC. + * + * @param init_config Pointer to Digital ADC initilization config. Refer to ``adc_digi_init_config_t``. + * + * @return + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. + * - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags + * - ESP_ERR_NO_MEM If out of memory + * - ESP_OK On success + */ +esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config); + +/** + * @brief Read bytes from Digital ADC through DMA. + * + * @param[out] buf Buffer to read from ADC. + * @param[in] length_max Expected length of data read from the ADC. + * @param[out] out_length Real length of data read from the ADC via this API. + * @param[in] timeout_ms Time to wait for data via this API, in millisecond. + * + * @return + * - ESP_ERR_INVALID_STATE Driver state is invalid. Usually it means the ADC sampling rate is faster than the task processing rate. + * - ESP_ERR_TIMEOUT Operation timed out + * - ESP_OK On success + */ +esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms); + +/** + * @brief Start the Digital ADC and DMA peripherals. After this, the hardware starts working. + * + * @return + * - ESP_ERR_INVALID_STATE Driver state is invalid. + * - ESP_OK On success + */ +esp_err_t adc_digi_start(void); + +/** + * @brief Stop the Digital ADC and DMA peripherals. After this, the hardware stops working. + * + * @return + * - ESP_ERR_INVALID_STATE Driver state is invalid. + * - ESP_OK On success + */ +esp_err_t adc_digi_stop(void); + +/** + * @brief Deinitialize the Digital ADC. + * + * @return + * - ESP_ERR_INVALID_STATE Driver state is invalid. + * - ESP_OK On success + */ +esp_err_t adc_digi_deinitialize(void); + +/** + * @brief Setting the digital controller. + * + * @param config Pointer to digital controller paramter. Refer to ``adc_digi_config_t``. + * + * @return + * - ESP_ERR_INVALID_STATE Driver state is invalid. + * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. + * - ESP_OK On success + */ +esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config); + + +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 +//TODO IDF-3610 +/** + * @brief Reset adc digital controller filter. + * + * @param idx Filter index. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx); + +/** + * @brief Set adc digital controller filter configuration. + * + * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. + * + * @param idx Filter index. + * @param config See ``adc_digi_filter_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config); + +/** + * @brief Get adc digital controller filter configuration. + * + * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. + * + * @param idx Filter index. + * @param config See ``adc_digi_filter_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config); + +/** + * @brief Enable/disable adc digital controller filter. + * Filtering the ADC data to obtain smooth data at higher sampling rates. + * + * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time. + * + * @param idx Filter index. + * @param enable Enable/Disable filter. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable); + +/** + * @brief Config monitor of adc digital controller. + * + * @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time. + * + * @param idx Monitor index. + * @param config See ``adc_digi_monitor_t``. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config); + +/** + * @brief Enable/disable monitor of adc digital controller. + * + * @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time. + * + * @param idx Monitor index. + * @param enable True or false enable monitor. + * + * @return + * - ESP_OK Success + */ +esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable); +#endif //#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 + +#if CONFIG_IDF_TARGET_ESP32 +//TODO IDF-3610 +/** + * @brief Read Hall Sensor + * + * @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on, + * the input of GPIO36 and GPIO39 will be pulled down for about 80ns. + * When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39. + * Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue. + * + * @note The Hall Sensor uses channels 0 and 3 of ADC1. Do not configure + * these channels for use as ADC channels. + * + * @note The ADC1 module must be enabled by calling + * adc1_config_width() before calling hall_sensor_read(). ADC1 + * should be configured for 12 bit readings, as the hall sensor + * readings are low values and do not cover the full range of the + * ADC. + * + * @return The hall sensor reading. + */ +int hall_sensor_read(void); + +/*--------------------------------------------------------------- + To Be Deprecated TODO: IDF-3610 +---------------------------------------------------------------*/ +/** + * @brief Set I2S data source + * @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC. + * @return + * - ESP_OK success + */ +esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src); + +/** + * @brief Initialize I2S ADC mode + * @param adc_unit ADC unit index + * @param channel ADC channel index + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/include/driver/adc_common.h b/components/driver/include/driver/adc_common.h index b6961b6006..e081f28d15 100644 --- a/components/driver/include/driver/adc_common.h +++ b/components/driver/include/driver/adc_common.h @@ -1,544 +1,11 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -#pragma once - -#include -#include -#include "esp_err.h" -#include "sdkconfig.h" -#include "driver/gpio.h" -#include "hal/adc_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if CONFIG_IDF_TARGET_ESP32 -/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ -typedef enum { - ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */ - ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 */ - ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO38 */ - ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO39 */ - ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO32 */ - ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO33 */ - ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO34 */ - ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO35 */ - ADC1_CHANNEL_MAX, -} adc1_channel_t; -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776 -/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ -typedef enum { - ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO1 */ - ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO2 */ - ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO3 */ - ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO4 */ - ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO5 */ - ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO6 */ - ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO7 */ - ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO8 */ - ADC1_CHANNEL_8, /*!< ADC1 channel 8 is GPIO9 */ - ADC1_CHANNEL_9, /*!< ADC1 channel 9 is GPIO10 */ - ADC1_CHANNEL_MAX, -} adc1_channel_t; -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 -/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ -typedef enum { - ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */ - ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO1 */ - ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO2 */ - ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO3 */ - ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO4 */ - ADC1_CHANNEL_MAX, -} adc1_channel_t; -#endif // CONFIG_IDF_TARGET_* - -#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776 -/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ -typedef enum { - ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO4 (ESP32), GPIO11 (ESP32-S2) */ - ADC2_CHANNEL_1, /*!< ADC2 channel 1 is GPIO0 (ESP32), GPIO12 (ESP32-S2) */ - ADC2_CHANNEL_2, /*!< ADC2 channel 2 is GPIO2 (ESP32), GPIO13 (ESP32-S2) */ - ADC2_CHANNEL_3, /*!< ADC2 channel 3 is GPIO15 (ESP32), GPIO14 (ESP32-S2) */ - ADC2_CHANNEL_4, /*!< ADC2 channel 4 is GPIO13 (ESP32), GPIO15 (ESP32-S2) */ - ADC2_CHANNEL_5, /*!< ADC2 channel 5 is GPIO12 (ESP32), GPIO16 (ESP32-S2) */ - ADC2_CHANNEL_6, /*!< ADC2 channel 6 is GPIO14 (ESP32), GPIO17 (ESP32-S2) */ - ADC2_CHANNEL_7, /*!< ADC2 channel 7 is GPIO27 (ESP32), GPIO18 (ESP32-S2) */ - ADC2_CHANNEL_8, /*!< ADC2 channel 8 is GPIO25 (ESP32), GPIO19 (ESP32-S2) */ - ADC2_CHANNEL_9, /*!< ADC2 channel 9 is GPIO26 (ESP32), GPIO20 (ESP32-S2) */ - ADC2_CHANNEL_MAX, -} adc2_channel_t; -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 -/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/ -typedef enum { - ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */ - ADC2_CHANNEL_MAX, -} adc2_channel_t; -#endif - - /** - * @brief ADC rtc controller attenuation option. - * - * @note This definitions are only for being back-compatible + * This file is only a wrapper for `driver/adc.h` for back-compatability. */ -#define ADC_ATTEN_0db ADC_ATTEN_DB_0 -#define ADC_ATTEN_2_5db ADC_ATTEN_DB_2_5 -#define ADC_ATTEN_6db ADC_ATTEN_DB_6 -#define ADC_ATTEN_11db ADC_ATTEN_DB_11 -/** - * The default (max) bit width of the ADC of current version. You can also get the maximum bitwidth - * by `SOC_ADC_MAX_BITWIDTH` defined in soc_caps.h. - */ -#define ADC_WIDTH_BIT_DEFAULT (ADC_WIDTH_MAX-1) - -//this definitions are only for being back-compatible -#define ADC_WIDTH_9Bit ADC_WIDTH_BIT_9 -#define ADC_WIDTH_10Bit ADC_WIDTH_BIT_10 -#define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11 -#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12 - -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 -/** - * @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports - */ -#define ADC_MAX_DELAY UINT32_MAX -#endif - -/** - * @brief ADC digital controller encode option. - * - * @deprecated The ESP32-S2 doesn't use I2S DMA. Call ``adc_digi_output_format_t`` instead. - */ -typedef enum { - ADC_ENCODE_12BIT, /*!< ADC to DMA data format, , [15:12]-channel [11:0]-12 bits ADC data */ - ADC_ENCODE_11BIT, /*!< ADC to DMA data format, [15]-unit, [14:11]-channel [10:0]-11 bits ADC data */ - ADC_ENCODE_MAX, -} adc_i2s_encode_t; - -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 -//This feature is currently supported on ESP32C3, will be supported on other chips soon -/** - * @brief Digital ADC DMA configuration - */ -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. - uint32_t conv_num_each_intr; ///< Bytes of data that can be converted in 1 interrupt. - 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 - -/*--------------------------------------------------------------- - Common setting ----------------------------------------------------------------*/ - -/** - * @brief Enable ADC power - * @deprecated Use adc_power_acquire and adc_power_release instead. - */ -void adc_power_on(void) __attribute__((deprecated)); - -/** - * @brief Power off SAR ADC - * @deprecated Use adc_power_acquire and adc_power_release instead. - * This function will force power down for ADC. - * This function is deprecated because forcing power ADC power off may - * disrupt operation of other components which may be using the ADC. - */ -void adc_power_off(void) __attribute__((deprecated)); - -/** - * @brief Increment the usage counter for ADC module. - * ADC will stay powered on while the counter is greater than 0. - * Call adc_power_release when done using the ADC. - */ -void adc_power_acquire(void); - -/** - * @brief Decrement the usage counter for ADC module. - * ADC will stay powered on while the counter is greater than 0. - * Call this function when done using the ADC. - */ -void adc_power_release(void); - -#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684 -/** - * @brief Initialize ADC pad - * @param adc_unit ADC unit index - * @param channel ADC channel index - * @return - * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error - */ -esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel); -#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684 - -/*--------------------------------------------------------------- - ADC Single Read Setting ----------------------------------------------------------------*/ -/** - * @brief Get the GPIO number of a specific ADC1 channel. - * - * @param channel Channel to get the GPIO number - * @param gpio_num output buffer to hold the GPIO number - * - * @return - * - ESP_OK if success - * - ESP_ERR_INVALID_ARG if channel not valid - */ -esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num); - -/** - * @brief Set the attenuation of a particular channel on ADC1, and configure its associated GPIO pin mux. - * - * The default ADC voltage is for attenuation 0 dB and listed in the table below. - * By setting higher attenuation it is possible to read higher voltages. - * - * Due to ADC characteristics, most accurate results are obtained within the "suggested range" - * shown in the following table. - * - * +----------+-------------+-----------------+ - * | | attenuation | suggested range | - * | SoC | (dB) | (mV) | - * +==========+=============+=================+ - * | | 0 | 100 ~ 950 | - * | +-------------+-----------------+ - * | | 2.5 | 100 ~ 1250 | - * | ESP32 +-------------+-----------------+ - * | | 6 | 150 ~ 1750 | - * | +-------------+-----------------+ - * | | 11 | 150 ~ 2450 | - * +----------+-------------+-----------------+ - * | | 0 | 0 ~ 750 | - * | +-------------+-----------------+ - * | | 2.5 | 0 ~ 1050 | - * | ESP32-S2 +-------------+-----------------+ - * | | 6 | 0 ~ 1300 | - * | +-------------+-----------------+ - * | | 11 | 0 ~ 2500 | - * +----------+-------------+-----------------+ - * - * For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges. - * - * @note For any given channel, this function must be called before the first time ``adc1_get_raw()`` is called for that channel. - * - * @note This function can be called multiple times to configure multiple - * ADC channels simultaneously. You may call ``adc1_get_raw()`` only after configuring a channel. - * - * @param channel ADC1 channel to configure - * @param atten Attenuation level - * - * @return - * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error - */ -esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten); - -/** - * @brief Configure ADC1 capture width, meanwhile enable output invert for ADC1. - * The configuration is for all channels of ADC1 - * @param width_bit Bit capture width for ADC1 - * - * @return - * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error - */ -esp_err_t adc1_config_width(adc_bits_width_t width_bit); - -/** - * @brief Take an ADC1 reading from a single channel. - * @note ESP32: - * When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on, - * the input of GPIO36 and GPIO39 will be pulled down for about 80ns. - * When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39. - * Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue. - * As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA), - * but will remove the glitches on GPIO36 and GPIO39. - * - * @note Call ``adc1_config_width()`` before the first time this - * function is called. - * - * @note For any given channel, adc1_config_channel_atten(channel) - * must be called before the first time this function is called. Configuring - * a new channel does not prevent a previously configured channel from being read. - * - * @param channel ADC1 channel to read - * - * @return - * - -1: Parameter error - * - Other: ADC1 channel reading. - */ -int adc1_get_raw(adc1_channel_t channel); - -#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684 -/** - * @brief Set ADC data invert - * @param adc_unit ADC unit index - * @param inv_en whether enable data invert - * @return - * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error - */ -esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en); - -/** - * @brief Set ADC source clock - * @param clk_div ADC clock divider, ADC clock is divided from APB clock - * @return - * - ESP_OK success - */ -esp_err_t adc_set_clk_div(uint8_t clk_div); - -/** - * @brief Configure ADC capture width. - * - * @param adc_unit ADC unit index - * @param width_bit Bit capture width for ADC unit. - * - * @return - * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error - */ -esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit); - -/** - * @brief Configure ADC1 to be usable by the ULP - * - * This function reconfigures ADC1 to be controlled by the ULP. - * Effect of this function can be reverted using ``adc1_get_raw()`` function. - * - * Note that adc1_config_channel_atten, ``adc1_config_width()`` functions need - * to be called to configure ADC1 channels, before ADC1 is used by the ULP. - */ -void adc1_ulp_enable(void); -#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684 - -/** - * @brief Get the GPIO number of a specific ADC2 channel. - * - * @param channel Channel to get the GPIO number - * - * @param gpio_num output buffer to hold the GPIO number - * - * @return - * - ESP_OK if success - * - ESP_ERR_INVALID_ARG if channel not valid - */ -esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num); - -/** - * @brief Configure the ADC2 channel, including setting attenuation. - * - * The default ADC voltage is for attenuation 0 dB and listed in the table below. - * By setting higher attenuation it is possible to read higher voltages. - * - * Due to ADC characteristics, most accurate results are obtained within the "suggested range" - * shown in the following table. - * - * +----------+-------------+-----------------+ - * | | attenuation | suggested range | - * | SoC | (dB) | (mV) | - * +==========+=============+=================+ - * | | 0 | 100 ~ 950 | - * | +-------------+-----------------+ - * | | 2.5 | 100 ~ 1250 | - * | ESP32 +-------------+-----------------+ - * | | 6 | 150 ~ 1750 | - * | +-------------+-----------------+ - * | | 11 | 150 ~ 2450 | - * +----------+-------------+-----------------+ - * | | 0 | 0 ~ 750 | - * | +-------------+-----------------+ - * | | 2.5 | 0 ~ 1050 | - * | ESP32-S2 +-------------+-----------------+ - * | | 6 | 0 ~ 1300 | - * | +-------------+-----------------+ - * | | 11 | 0 ~ 2500 | - * +----------+-------------+-----------------+ - * - * For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges. - * - * @note This function also configures the input GPIO pin mux to - * connect it to the ADC2 channel. It must be called before calling - * ``adc2_get_raw()`` for this channel. - * - * @note For any given channel, this function must be called before the first time ``adc2_get_raw()`` is called for that channel. - * - * @param channel ADC2 channel to configure - * @param atten Attenuation level - * - * @return - * - ESP_OK success - * - ESP_ERR_INVALID_ARG Parameter error - */ -esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten); - -/** - * @brief Take an ADC2 reading on a single channel - * - * @note ESP32: - * When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on, - * the input of GPIO36 and GPIO39 will be pulled down for about 80ns. - * When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39. - * Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue. - * As a workaround, call adc_power_acquire() in the app. This will result in higher power consumption (by ~1mA), - * but will remove the glitches on GPIO36 and GPIO39. - * - * - * @note ESP32: - * For a given channel, ``adc2_config_channel_atten()`` - * must be called before the first time this function is called. If Wi-Fi is started via ``esp_wifi_start()``, this - * function will always fail with ``ESP_ERR_TIMEOUT``. - * - * @note ESP32-S2: - * ADC2 support hardware arbiter. The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority, - * the low priority controller will read the invalid ADC2 data. Default priority: Wi-Fi > RTC > Digital; - * - * @param channel ADC2 channel to read - * @param width_bit Bit capture width for ADC2 - * @param raw_out the variable to hold the output data. - * - * @return - * - ESP_OK if success - * - ESP_ERR_TIMEOUT ADC2 is being used by other controller and the request timed out. - * - ESP_ERR_INVALID_STATE The controller status is invalid. Please try again. - */ -esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out); - -/** - * @brief Output ADC1 or ADC2's reference voltage to ``adc2_channe_t``'s IO. - * - * This function routes the internal reference voltage of ADCn to one of - * ADC2's channels. This reference voltage can then be manually measured - * for calibration purposes. - * - * @note ESP32 only supports output of ADC2's internal reference voltage. - * @param[in] adc_unit ADC unit index - * @param[in] gpio GPIO number (Only ADC2's channels IO are supported) - * - * @return - * - ESP_OK: v_ref successfully routed to selected GPIO - * - ESP_ERR_INVALID_ARG: Unsupported GPIO - */ -esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio); - -/** - * @brief Output ADC2 reference voltage to ``adc2_channe_t``'s IO. - * - * This function routes the internal reference voltage of ADCn to one of - * ADC2's channels. This reference voltage can then be manually measured - * for calibration purposes. - * - * @deprecated Use ``adc_vref_to_gpio`` instead. - * - * @param[in] gpio GPIO number (ADC2's channels are supported) - * - * @return - * - ESP_OK: v_ref successfully routed to selected GPIO - * - ESP_ERR_INVALID_ARG: Unsupported GPIO - */ -esp_err_t adc2_vref_to_gpio(gpio_num_t gpio) __attribute__((deprecated)); - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ -#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 -//These APIs are only supported on ESP32 and ESP32-S2. On ESP32-C3 and later chips, please use ``adc_digi_initialize`` and ``adc_digi_deinitialize`` -/** - * @brief ADC digital controller initialization. - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_init(void); - -/** - * @brief ADC digital controller deinitialization. - * @return - * - ESP_OK Success - */ -esp_err_t adc_digi_deinit(void); -#endif - -/** - * @brief Setting the digital controller. - * - * @param config Pointer to digital controller paramter. Refer to ``adc_digi_config_t``. - * - * @return - * - ESP_ERR_INVALID_STATE Driver state is invalid. - * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. - * - ESP_OK On success - */ -esp_err_t adc_digi_controller_config(const adc_digi_config_t *config); - -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 -//This feature is currently supported on ESP32C3, will be supported on other chips soon -/*--------------------------------------------------------------- - DMA setting ----------------------------------------------------------------*/ -/** - * @brief Initialize the Digital ADC. - * - * @param init_config Pointer to Digital ADC initilization config. Refer to ``adc_digi_init_config_t``. - * - * @return - * - ESP_ERR_INVALID_ARG If the combination of arguments is invalid. - * - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags - * - ESP_ERR_NO_MEM If out of memory - * - ESP_OK On success - */ -esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config); - -/** - * @brief Start the Digital ADC and DMA peripherals. After this, the hardware starts working. - * - * @return - * - ESP_ERR_INVALID_STATE Driver state is invalid. - * - ESP_OK On success - */ -esp_err_t adc_digi_start(void); - -/** - * @brief Stop the Digital ADC and DMA peripherals. After this, the hardware stops working. - * - * @return - * - ESP_ERR_INVALID_STATE Driver state is invalid. - * - ESP_OK On success - */ -esp_err_t adc_digi_stop(void); - -/** - * @brief Read bytes from Digital ADC through DMA. - * - * @param[out] buf Buffer to read from ADC. - * @param[in] length_max Expected length of data read from the ADC. - * @param[out] out_length Real length of data read from the ADC via this API. - * @param[in] timeout_ms Time to wait for data via this API, in millisecond. - * - * @return - * - ESP_ERR_INVALID_STATE Driver state is invalid. Usually it means the ADC sampling rate is faster than the task processing rate. - * - ESP_ERR_TIMEOUT Operation timed out - * - ESP_OK On success - */ -esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms); - -/** - * @brief Deinitialize the Digital ADC. - * - * @return - * - ESP_ERR_INVALID_STATE Driver state is invalid. - * - ESP_OK On success - */ -esp_err_t adc_digi_deinitialize(void); - -#endif //#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 - -#ifdef __cplusplus -} -#endif +#include "adc.h" diff --git a/components/driver/include/driver/spi_common_internal.h b/components/driver/include/driver/spi_common_internal.h index 90826c0a8e..0704c7ddd8 100644 --- a/components/driver/include/driver/spi_common_internal.h +++ b/components/driver/include/driver/spi_common_internal.h @@ -110,7 +110,7 @@ bool spicommon_periph_in_use(spi_host_device_t host); bool spicommon_periph_free(spi_host_device_t host); /** - * @brief Alloc DMA for SPI Slave + * @brief Alloc DMA for SPI * * @param host_id SPI host ID * @param dma_chan DMA channel to be used @@ -122,17 +122,17 @@ bool spicommon_periph_free(spi_host_device_t host); * - ESP_ERR_NO_MEM: No enough memory * - ESP_ERR_NOT_FOUND: There is no available DMA channel */ -esp_err_t spicommon_slave_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan); +esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan); /** - * @brief Free DMA for SPI Slave + * @brief Free DMA for SPI * * @param host_id SPI host ID * * @return * - ESP_OK: On success */ -esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id); +esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id); /** * @brief Connect a SPI peripheral to GPIO pins diff --git a/components/driver/spi_common.c b/components/driver/spi_common.c index 6af2b6fa31..c81f8d173e 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -158,7 +158,7 @@ static inline periph_module_t get_dma_periph(int dma_chan) #endif } -static bool spicommon_dma_chan_claim(int dma_chan, uint32_t *out_actual_dma_chan) +static bool claim_dma_chan(int dma_chan, uint32_t *out_actual_dma_chan) { bool ret = false; @@ -175,7 +175,7 @@ static bool spicommon_dma_chan_claim(int dma_chan, uint32_t *out_actual_dma_chan return ret; } -static void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan) +static void connect_spi_and_dma(spi_host_device_t host, int dma_chan) { #if CONFIG_IDF_TARGET_ESP32 DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2)); @@ -184,7 +184,7 @@ static void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan) #endif } -static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan) +static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan) { assert(is_valid_host(host_id)); #if CONFIG_IDF_TARGET_ESP32 @@ -200,17 +200,17 @@ static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_cha if (dma_chan == SPI_DMA_CH_AUTO) { #if CONFIG_IDF_TARGET_ESP32 for (int i = 1; i < SOC_SPI_DMA_CHAN_NUM+1; i++) { - success = spicommon_dma_chan_claim(i, &actual_dma_chan); + success = claim_dma_chan(i, &actual_dma_chan); if (success) { break; } } #elif CONFIG_IDF_TARGET_ESP32S2 //On ESP32S2, each SPI controller has its own DMA channel - success = spicommon_dma_chan_claim(host_id, &actual_dma_chan); + success = claim_dma_chan(host_id, &actual_dma_chan); #endif //#if CONFIG_IDF_TARGET_XXX } else { - success = spicommon_dma_chan_claim((int)dma_chan, &actual_dma_chan); + success = claim_dma_chan((int)dma_chan, &actual_dma_chan); } //On ESP32 and ESP32S2, actual_tx_dma_chan and actual_rx_dma_chan are always same @@ -221,13 +221,13 @@ static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_cha SPI_CHECK(false, "no available dma channel", ESP_ERR_NOT_FOUND); } - spicommon_connect_spi_and_dma(host_id, *out_actual_tx_dma_chan); + connect_spi_and_dma(host_id, *out_actual_tx_dma_chan); return ret; } #else //SOC_GDMA_SUPPORTED -static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan) +static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan) { assert(is_valid_host(host_id)); assert(dma_chan == SPI_DMA_CH_AUTO); @@ -272,7 +272,7 @@ static esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_cha } #endif //#if !SOC_GDMA_SUPPORTED -esp_err_t spicommon_slave_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan) +esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan) { assert(is_valid_host(host_id)); #if CONFIG_IDF_TARGET_ESP32 @@ -292,7 +292,7 @@ esp_err_t spicommon_slave_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan bus_ctx[host_id] = ctx; ctx->host_id = host_id; - ret = spicommon_dma_chan_alloc(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan); + ret = alloc_dma_chan(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan); if (ret != ESP_OK) { goto cleanup; } @@ -310,7 +310,7 @@ cleanup: } //----------------------------------------------------------free dma periph-------------------------------------------------------// -static esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id) +static esp_err_t dma_chan_free(spi_host_device_t host_id) { assert(is_valid_host(host_id)); @@ -339,11 +339,11 @@ static esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id) return ESP_OK; } -esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id) +esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id) { assert(is_valid_host(host_id)); - esp_err_t ret = spicommon_dma_chan_free(host_id); + esp_err_t ret = dma_chan_free(host_id); free(bus_ctx[host_id]); bus_ctx[host_id] = NULL; @@ -783,7 +783,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t * if (dma_chan != SPI_DMA_DISABLED) { bus_attr->dma_enabled = 1; - err = spicommon_dma_chan_alloc(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan); + err = alloc_dma_chan(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan); if (err != ESP_OK) { goto cleanup; } @@ -844,7 +844,7 @@ cleanup: bus_attr->dmadesc_tx = NULL; bus_attr->dmadesc_rx = NULL; if (bus_attr->dma_enabled) { - spicommon_dma_chan_free(host_id); + dma_chan_free(host_id); } } spicommon_periph_free(host_id); @@ -881,7 +881,7 @@ esp_err_t spi_bus_free(spi_host_device_t host_id) bus_attr->dmadesc_tx = NULL; bus_attr->dmadesc_rx = NULL; if (bus_attr->dma_enabled > 0) { - spicommon_dma_chan_free(host_id); + dma_chan_free(host_id); } spicommon_periph_free(host_id); free(ctx); diff --git a/components/driver/spi_slave.c b/components/driver/spi_slave.c index f09fd4ccc7..e404715e5e 100644 --- a/components/driver/spi_slave.c +++ b/components/driver/spi_slave.c @@ -140,7 +140,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b bool use_dma = (dma_chan != SPI_DMA_DISABLED); spihost[host]->dma_enabled = use_dma; if (use_dma) { - ret = spicommon_slave_dma_chan_alloc(host, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan); + ret = spicommon_dma_chan_alloc(host, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan); if (ret != ESP_OK) { goto cleanup; } @@ -240,7 +240,7 @@ cleanup: } spi_slave_hal_deinit(&spihost[host]->hal); if (spihost[host]->dma_enabled) { - spicommon_slave_free_dma(host); + spicommon_dma_chan_free(host); } free(spihost[host]); @@ -257,7 +257,7 @@ esp_err_t spi_slave_free(spi_host_device_t host) if (spihost[host]->trans_queue) vQueueDelete(spihost[host]->trans_queue); if (spihost[host]->ret_queue) vQueueDelete(spihost[host]->ret_queue); if (spihost[host]->dma_enabled) { - spicommon_slave_free_dma(host); + spicommon_dma_chan_free(host); } free(spihost[host]->hal.dmadesc_tx); free(spihost[host]->hal.dmadesc_rx); diff --git a/components/driver/spi_slave_hd.c b/components/driver/spi_slave_hd.c index 125153e089..dda2e5297d 100644 --- a/components/driver/spi_slave_hd.c +++ b/components/driver/spi_slave_hd.c @@ -89,7 +89,7 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b host->dma_enabled = (config->dma_chan != SPI_DMA_DISABLED); if (host->dma_enabled) { - ret = spicommon_slave_dma_chan_alloc(host_id, config->dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan); + ret = spicommon_dma_chan_alloc(host_id, config->dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan); if (ret != ESP_OK) { goto cleanup; } @@ -241,7 +241,7 @@ esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id) spicommon_periph_free(host_id); if (host->dma_enabled) { - spicommon_slave_free_dma(host_id); + spicommon_dma_chan_free(host_id); } free(host); spihost[host_id] = NULL; diff --git a/components/driver/test/adc_dma_test/test_esp32s2.c b/components/driver/test/adc_dma_test/test_esp32s2.c index 2a41f4ff69..7985aeb976 100644 --- a/components/driver/test/adc_dma_test/test_esp32s2.c +++ b/components/driver/test/adc_dma_test/test_esp32s2.c @@ -8,6 +8,10 @@ Tests for the adc device driver on ESP32-S2 only */ #include "sdkconfig.h" +#include "unity.h" +#include "test_utils.h" + +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2) //TODO: IDF-3160 #if CONFIG_IDF_TARGET_ESP32S2 @@ -37,6 +41,10 @@ #include "soc/lldesc.h" #include "test/test_adc_dac_dma.h" +#include "driver/adc_deprecated.h" +#include "hal/adc_ll.h" +#include "esp_pm.h" + static const char *TAG = "test_adc"; #define PLATFORM_SELECT (1) //0: pxp; 1: chip @@ -83,7 +91,6 @@ static adc_channel_t adc_list[SOC_ADC_PATT_LEN_MAX] = { /* For ESP32S2, it should use same atten, or, it will have error. */ #define TEST_ADC_ATTEN_DEFAULT (ADC_ATTEN_11db) -extern esp_err_t adc_digi_reset(void); /* Work mode. * single: eof_num; @@ -109,6 +116,20 @@ static lldesc_t dma2 = {0}; static QueueHandle_t que_adc = NULL; static adc_dma_event_t adc_evt; +/** + * @brief Reset FSM of adc digital controller. + * + * @return + * - ESP_OK Success + */ +static esp_err_t adc_digi_reset(void) +{ + adc_ll_digi_reset(); + adc_ll_digi_clear_pattern_table(ADC_NUM_1); + adc_ll_digi_clear_pattern_table(ADC_NUM_2); + return ESP_OK; +} + /** ADC-DMA ISR handler. */ static IRAM_ATTR void adc_dma_isr(void *arg) { @@ -630,3 +651,4 @@ TEST_CASE("test_adc_digi_slope_debug", "[adc_dma][ignore]") } #endif // CONFIG_IDF_TARGET_ESP32S2 +#endif //#if !DISABLED_FOR_TARGETS(ESP32S2) diff --git a/components/driver/test/test_adc.c b/components/driver/test/test_adc.c index ac735fde99..58f0eb17f8 100644 --- a/components/driver/test/test_adc.c +++ b/components/driver/test/test_adc.c @@ -12,14 +12,15 @@ #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP8684) // TODO: Support ADC IDF-3908 #include "esp_adc_cal.h" -#include "driver/adc_common.h" +#include "driver/adc.h" static const char *TAG = "ADC"; -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3) + +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3, ESP32C3) //TODO: IDF-3160 //API only supported for C3 now. -#include "driver/adc.h" +#include "esp_adc_cal.h" #include "esp_log.h" #define TEST_COUNT 4096 diff --git a/components/driver/test/test_adc2_with_wifi.c b/components/driver/test/test_adc2_with_wifi.c index 6c72609274..395c1af479 100644 --- a/components/driver/test/test_adc2_with_wifi.c +++ b/components/driver/test/test_adc2_with_wifi.c @@ -7,7 +7,6 @@ Tests for the adc2 device driver */ #include "esp_system.h" -#include "driver/adc.h" #include "unity.h" #include "esp_system.h" #include "esp_event.h" @@ -16,6 +15,7 @@ #include "nvs_flash.h" #include "test_utils.h" #include "driver/gpio.h" +#include "driver/adc.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" diff --git a/components/efuse/esp32c3/esp_efuse_rtc_calib.c b/components/efuse/esp32c3/esp_efuse_rtc_calib.c index 52e4167363..dc02072e4e 100644 --- a/components/efuse/esp32c3/esp_efuse_rtc_calib.c +++ b/components/efuse/esp32c3/esp_efuse_rtc_calib.c @@ -15,9 +15,10 @@ int esp_efuse_rtc_calib_get_ver(void) return result; } -uint16_t esp_efuse_rtc_calib_get_init_code(int version, int atten) +uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten) { assert(version == 1); + (void) adc_unit; const esp_efuse_desc_t** init_code_efuse; assert(atten < 4); if (atten == 0) { diff --git a/components/efuse/esp32c3/include/esp_efuse_rtc_calib.h b/components/efuse/esp32c3/include/esp_efuse_rtc_calib.h index 0e059c4f3f..d7bb47f644 100644 --- a/components/efuse/esp32c3/include/esp_efuse_rtc_calib.h +++ b/components/efuse/esp32c3/include/esp_efuse_rtc_calib.h @@ -11,6 +11,9 @@ extern "C" { #endif +//This is the ADC calibration value version burnt in efuse +#define ESP_EFUSE_ADC_CALIB_VER 1 + /** * @brief Get the RTC calibration efuse version * @@ -21,11 +24,12 @@ int esp_efuse_rtc_calib_get_ver(void); /** * @brief Get the init code in the efuse, for the corresponding attenuation. * - * @param version Version of the stored efuse - * @param atten Attenuation of the init code + * @param version Version of the stored efuse + * @param adc_unit ADC unit. Not used, for compatibility. On esp32c3, for calibration v1, both ADC units use the same init code (calibrated by ADC1) + * @param atten Attenuation of the init code * @return The init code stored in efuse */ -uint16_t esp_efuse_rtc_calib_get_init_code(int version, int atten); +uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten); /** * @brief Get the calibration digits stored in the efuse, and the corresponding voltage. diff --git a/components/efuse/esp32s2/include/esp_efuse_rtc_table.h b/components/efuse/esp32s2/include/esp_efuse_rtc_table.h index 3cc54e2035..f6f5d16845 100644 --- a/components/efuse/esp32s2/include/esp_efuse_rtc_table.h +++ b/components/efuse/esp32s2/include/esp_efuse_rtc_table.h @@ -15,6 +15,9 @@ extern "C" { #include "esp_err.h" #include "sdkconfig.h" +//This is the ADC calibration value version burnt in efuse +#define ESP_EFUSE_ADC_CALIB_VER 2 + #define RTCCALIB_ESP32S2_ADCCOUNT 2 #define RTCCALIB_ESP32S2_ATTENCOUNT 4 diff --git a/components/efuse/esp32s3/esp_efuse_rtc_calib.c b/components/efuse/esp32s3/esp_efuse_rtc_calib.c index b2c3041101..272549986b 100644 --- a/components/efuse/esp32s3/esp_efuse_rtc_calib.c +++ b/components/efuse/esp32s3/esp_efuse_rtc_calib.c @@ -30,7 +30,7 @@ int esp_efuse_rtc_calib_get_ver(void) return cali_version_v1; } -uint16_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten) +uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten) { assert(version == 1); assert(atten < 4); diff --git a/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h b/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h index b0ba57669d..e2f5b54329 100644 --- a/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h +++ b/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h @@ -11,6 +11,9 @@ extern "C" { #endif +//This is the ADC calibration value version burnt in efuse +#define ESP_EFUSE_ADC_CALIB_VER 1 + /** * @brief Get the RTC calibration efuse version * @@ -26,7 +29,7 @@ int esp_efuse_rtc_calib_get_ver(void); * @param atten Attenuation of the init code * @return The init code stored in efuse */ -uint16_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten); +uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten); /** * @brief Get the calibration digits stored in the efuse, and the corresponding voltage. diff --git a/components/esp_adc_cal/esp_adc_cal_esp32h2.c b/components/esp_adc_cal/esp_adc_cal_esp32h2.c deleted file mode 100644 index 265a88782b..0000000000 --- a/components/esp_adc_cal/esp_adc_cal_esp32h2.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include "esp_types.h" -#include "esp_err.h" -#include "esp_log.h" -#include "esp_check.h" -#include "driver/adc.h" -#include "hal/adc_ll.h" -#include "esp_efuse_rtc_calib.h" -#include "esp_adc_cal.h" - -const static char LOG_TAG[] = "adc_calib"; - - -/* ------------------------ Characterization Constants ---------------------- */ - -// coeff_a and coeff_b are actually floats -// they are scaled to put them into uint32_t so that the headers do not have to be changed -static const int coeff_a_scaling = 65536; -static const int coeff_b_scaling = 1024; -/* -------------------- Characterization Helper Data Types ------------------ */ -typedef struct { - uint32_t voltage; - uint32_t digi; -} adc_calib_data_ver1; - -typedef struct { - char version_num; - adc_unit_t adc_num; - adc_atten_t atten_level; - union { - adc_calib_data_ver1 ver1; - } efuse_data; -} adc_calib_parsed_info; - -static esp_err_t prepare_calib_data_for(int version_num, adc_unit_t adc_num, adc_atten_t atten, adc_calib_parsed_info *parsed_data_storage) -{ - assert(version_num == 1); - esp_err_t ret; - - parsed_data_storage->version_num = version_num; - parsed_data_storage->adc_num = adc_num; - parsed_data_storage->atten_level = atten; - // V1 we don't have calibration data for ADC2, using the efuse data of ADC1 - uint32_t voltage, digi; - ret = esp_efuse_rtc_calib_get_cal_voltage(version_num, atten, &digi, &voltage); - if (ret != ESP_OK) { - return ret; - } - parsed_data_storage->efuse_data.ver1.voltage = voltage; - parsed_data_storage->efuse_data.ver1.digi = digi; - return ret; -} - -/* ----------------------- Characterization Functions ----------------------- */ -/* - * Estimate the (assumed) linear relationship btwn the measured raw value and the voltage - * with the previously done measurement when the chip was manufactured. - */ -static void calculate_characterization_coefficients(const adc_calib_parsed_info *parsed_data, esp_adc_cal_characteristics_t *chars) -{ - ESP_LOGD(LOG_TAG, "Calib V1, Cal Voltage = %d, Digi out = %d\n", parsed_data->efuse_data.ver1.voltage, parsed_data->efuse_data.ver1.digi); - - chars->coeff_a = coeff_a_scaling * parsed_data->efuse_data.ver1.voltage / parsed_data->efuse_data.ver1.digi; - chars->coeff_b = 0; -} - -/* ------------------------- Public API ------------------------------------- */ -esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source) -{ - if (source != ESP_ADC_CAL_VAL_EFUSE_TP) { - return ESP_ERR_NOT_SUPPORTED; - } - uint8_t adc_encoding_version = esp_efuse_rtc_calib_get_ver(); - if (adc_encoding_version != 1) { - // current version only accepts encoding ver 1. - return ESP_ERR_INVALID_VERSION; - } - return ESP_OK; -} - -esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num, - adc_atten_t atten, - adc_bits_width_t bit_width, - uint32_t default_vref, - esp_adc_cal_characteristics_t *chars) -{ - esp_err_t ret; - adc_calib_parsed_info efuse_parsed_data = {0}; - // Check parameters - ESP_RETURN_ON_FALSE(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid unit num"); - ESP_RETURN_ON_FALSE(chars != NULL, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Ivalid characteristic"); - ESP_RETURN_ON_FALSE(bit_width == ADC_WIDTH_BIT_12, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid bit_width"); - ESP_RETURN_ON_FALSE(atten < 4, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid attenuation"); - - int version_num = esp_efuse_rtc_calib_get_ver(); - ESP_RETURN_ON_FALSE(version_num == 1, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "No calibration efuse burnt"); - - memset(chars, 0, sizeof(esp_adc_cal_characteristics_t)); - - // make sure adc is calibrated. - ret = prepare_calib_data_for(version_num, adc_num, atten, &efuse_parsed_data); - if (ret != ESP_OK) { - abort(); - } - - calculate_characterization_coefficients(&efuse_parsed_data, chars); - ESP_LOGD(LOG_TAG, "adc%d (atten leven %d) calibration done: A:%d B:%d\n", adc_num, atten, chars->coeff_a, chars->coeff_b); - - // Initialize remaining fields - chars->adc_num = adc_num; - chars->atten = atten; - chars->bit_width = bit_width; - - // in esp32h2 we only use the two point method to calibrate the adc. - return ESP_ADC_CAL_VAL_EFUSE_TP; -} - -uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars) -{ - assert(chars != NULL); - return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling; -} diff --git a/components/esp_serial_slave_link/include/essl_spi/esp32h2_defs.h b/components/esp_serial_slave_link/include/essl_spi/esp32h2_defs.h index 3dfd4a14b7..e69de29bb2 100644 --- a/components/esp_serial_slave_link/include/essl_spi/esp32h2_defs.h +++ b/components/esp_serial_slave_link/include/essl_spi/esp32h2_defs.h @@ -1,38 +0,0 @@ -// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -#pragma once - -// NOTE: From the view of master -#define CMD_HD_WRBUF_REG 0x01 -#define CMD_HD_RDBUF_REG 0x02 -#define CMD_HD_WRDMA_REG 0x03 -#define CMD_HD_RDDMA_REG 0x04 - -#define CMD_HD_ONEBIT_MODE 0x00 -#define CMD_HD_DOUT_MODE 0x10 -#define CMD_HD_QOUT_MODE 0x20 -#define CMD_HD_DIO_MODE 0x50 -#define CMD_HD_QIO_MODE 0xA0 - -#define CMD_HD_SEG_END_REG 0x05 -#define CMD_HD_EN_QPI_REG 0x06 -#define CMD_HD_WR_END_REG 0x07 -#define CMD_HD_INT0_REG 0x08 -#define CMD_HD_INT1_REG 0x09 -#define CMD_HD_INT2_REG 0x0A -#define CMD_HD_EX_QPI_REG 0xDD - -#define SPI_SLAVE_HD_BUFFER_SIZE 64 diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 00ea9f2149..cba0a93167 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -139,7 +139,6 @@ if(NOT BOOTLOADER_BUILD) "twai_hal.c" "twai_hal_iram.c" "aes_hal.c" - "esp32h2/adc_hal.c" "esp32h2/brownout_hal.c" "esp32h2/hmac_hal.c" "esp32h2/rtc_cntl_hal.c") @@ -151,7 +150,6 @@ if(NOT BOOTLOADER_BUILD) "spi_flash_hal_gpspi.c" "spi_slave_hd_hal.c" "systimer_hal.c" - "esp8684/adc_hal.c" "esp8684/brownout_hal.c" "esp8684/rtc_cntl_hal.c") endif() diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index 0a0ef3f45a..14e04b99d7 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -5,25 +5,108 @@ */ #include -#include "soc/soc_caps.h" +#include "sdkconfig.h" #include "hal/adc_hal.h" #include "hal/adc_hal_conf.h" #include "hal/assert.h" -#include "sdkconfig.h" +#include "soc/lldesc.h" +#include "soc/soc_caps.h" +#if CONFIG_IDF_TARGET_ESP32 +//ADC utilises I2S0 DMA on ESP32 +#include "hal/i2s_ll.h" +#include "hal/i2s_types.h" +#include "soc/i2s_struct.h" +#endif -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 -#include "soc/gdma_channel.h" -#include "soc/soc.h" +#if CONFIG_IDF_TARGET_ESP32S2 +//ADC utilises SPI3 DMA on ESP32S2 +#include "hal/spi_ll.h" +#include "soc/spi_struct.h" +#endif + +#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED +/*--------------------------------------------------------------- + Single Read +---------------------------------------------------------------*/ +/** + * For chips without RTC controller, Digital controller is used to trigger an ADC single read. + */ #include "esp_rom_sys.h" typedef enum { ADC_EVENT_ADC1_DONE = BIT(0), ADC_EVENT_ADC2_DONE = BIT(1), } adc_hal_event_t; +#endif //SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED + +/*--------------------------------------------------------------- + Define all ADC DMA required operations here +---------------------------------------------------------------*/ +#if SOC_GDMA_SUPPORTED +#define adc_dma_ll_rx_clear_intr(dev, chan, mask) gdma_ll_rx_clear_interrupt_status(dev, chan, mask) +#define adc_dma_ll_rx_enable_intr(dev, chan, mask) gdma_ll_rx_enable_interrupt(dev, chan, mask, true) +#define adc_dma_ll_rx_disable_intr(dev, chan, mask) gdma_ll_rx_enable_interrupt(dev, chan, mask, false) +#define adc_dma_ll_rx_reset_channel(dev, chan) gdma_ll_rx_reset_channel(dev, chan) +#define adc_dma_ll_rx_stop(dev, chan) gdma_ll_rx_stop(dev, chan) +#define adc_dma_ll_rx_start(dev, chan, addr) do { \ + gdma_ll_rx_set_desc_addr(dev, chan, (uint32_t)addr); \ + gdma_ll_rx_start(dev, chan); \ + } while (0) +#define adc_ll_digi_dma_set_eof_num(dev, num) adc_ll_digi_dma_set_eof_num(num) +#define adc_ll_digi_reset(dev) adc_ll_digi_reset() +#define adc_ll_digi_trigger_enable(dev) adc_ll_digi_trigger_enable() +#define adc_ll_digi_trigger_disable(dev) adc_ll_digi_trigger_disable() + +//ADC utilises SPI3 DMA on ESP32S2 +#elif CONFIG_IDF_TARGET_ESP32S2 +#define adc_dma_ll_rx_get_intr(dev, mask) spi_ll_get_intr(dev, mask) +#define adc_dma_ll_rx_clear_intr(dev, chan, mask) spi_ll_clear_intr(dev, mask) +#define adc_dma_ll_rx_enable_intr(dev, chan, mask) spi_ll_enable_intr(dev, mask) +#define adc_dma_ll_rx_disable_intr(dev, chan, mask) spi_ll_disable_intr(dev, mask) +#define adc_dma_ll_rx_reset_channel(dev, chan) spi_dma_ll_rx_reset(dev, chan) +#define adc_dma_ll_rx_stop(dev, chan) spi_dma_ll_rx_stop(dev, chan) +#define adc_dma_ll_rx_start(dev, chan, addr) spi_dma_ll_rx_start(dev, chan, addr) +#define adc_dma_ll_get_in_suc_eof_desc_addr(dev, chan) spi_dma_ll_get_in_suc_eof_desc_addr(dev, chan) +#define adc_ll_digi_dma_set_eof_num(dev, num) adc_ll_digi_dma_set_eof_num(num) +#define adc_ll_digi_reset(dev) adc_ll_digi_reset() +#define adc_ll_digi_trigger_enable(dev) adc_ll_digi_trigger_enable() +#define adc_ll_digi_trigger_disable(dev) adc_ll_digi_trigger_disable() + +//ADC utilises I2S0 DMA on ESP32 +#else //CONFIG_IDF_TARGET_ESP32 +#define adc_dma_ll_rx_get_intr(dev, mask) ({i2s_ll_get_intr_status(dev) & mask;}) +#define adc_dma_ll_rx_clear_intr(dev, chan, mask) i2s_ll_clear_intr_status(dev, mask) +#define adc_dma_ll_rx_enable_intr(dev, chan, mask) do {((i2s_dev_t *)(dev))->int_ena.val |= mask;} while (0) +#define adc_dma_ll_rx_disable_intr(dev, chan, mask) do {((i2s_dev_t *)(dev))->int_ena.val &= ~mask;} while (0) +#define adc_dma_ll_rx_reset_channel(dev, chan) i2s_ll_rx_reset_dma(dev) +#define adc_dma_ll_rx_stop(dev, chan) i2s_ll_rx_stop_link(dev) +#define adc_dma_ll_rx_start(dev, chan, address) do { \ + ((i2s_dev_t *)(dev))->in_link.addr = (uint32_t)(address); \ + i2s_ll_enable_dma(dev, 1); \ + ((i2s_dev_t *)(dev))->in_link.start = 1; \ + } while (0) +#define adc_dma_ll_get_in_suc_eof_desc_addr(dev, chan) ({uint32_t addr; i2s_ll_rx_get_eof_des_addr(dev, &addr); addr;}) +#define adc_ll_digi_dma_set_eof_num(dev, num) do {((i2s_dev_t *)(dev))->rx_eof_num = num;} while (0) +#define adc_ll_digi_reset(dev) do { \ + i2s_ll_rx_reset(dev); \ + i2s_ll_rx_reset_fifo(dev); \ + } while (0) +#define adc_ll_digi_trigger_enable(dev) i2s_ll_rx_start(dev) +#define adc_ll_digi_trigger_disable(dev) i2s_ll_rx_stop(dev) +#define adc_ll_digi_dma_enable() adc_ll_digi_set_data_source(1) //Will this influence I2S0 +#define adc_ll_digi_dma_disable() adc_ll_digi_set_data_source(0) + +//ESP32 ADC uses the DMA through I2S. The I2S needs to be configured. +#define I2S_BASE_CLK (2*APB_CLK_FREQ) +#define SAMPLE_BITS 16 +#define ADC_LL_CLKM_DIV_NUM_DEFAULT 2 +#define ADC_LL_CLKM_DIV_B_DEFAULT 0 +#define ADC_LL_CLKM_DIV_A_DEFAULT 1 #endif + void adc_hal_init(void) { // Set internal FSM wait time, fixed value. @@ -42,7 +125,405 @@ void adc_hal_arbiter_config(adc_arbiter_t *config) adc_ll_set_arbiter_work_mode(config->mode); adc_ll_set_arbiter_priority(config->rtc_pri, config->dig_pri, config->pwdet_pri); } +#endif // #if SOC_ADC_ARBITER_SUPPORTED + +void adc_hal_digi_deinit(adc_hal_context_t *hal) +{ + adc_ll_digi_trigger_disable(hal->dev); + adc_ll_digi_dma_disable(); + adc_ll_digi_clear_pattern_table(ADC_NUM_1); + adc_ll_digi_clear_pattern_table(ADC_NUM_2); + adc_ll_digi_reset(hal->dev); + adc_ll_digi_controller_clk_disable(); +} + +/*--------------------------------------------------------------- + Controller Setting +---------------------------------------------------------------*/ +static adc_ll_controller_t get_controller(adc_ll_num_t unit, adc_hal_work_mode_t work_mode) +{ + if (unit == ADC_NUM_1) { + switch (work_mode) { +#if SOC_ULP_SUPPORTED + case ADC_HAL_ULP_MODE: + return ADC_LL_CTRL_ULP; #endif + case ADC_HAL_SINGLE_READ_MODE: +#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED + return ADC_LL_CTRL_DIG; +#elif SOC_ADC_RTC_CTRL_SUPPORTED + return ADC_LL_CTRL_RTC; +#endif + case ADC_HAL_CONTINUOUS_READ_MODE: + return ADC_LL_CTRL_DIG; + default: + abort(); + } + } else { + switch (work_mode) { +#if SOC_ULP_SUPPORTED + case ADC_HAL_ULP_MODE: + return ADC_LL_CTRL_ULP; +#endif +#if !SOC_ADC_ARBITER_SUPPORTED //No ADC2 arbiter on ESP32 + case ADC_HAL_SINGLE_READ_MODE: + return ADC_LL_CTRL_RTC; + case ADC_HAL_CONTINUOUS_READ_MODE: + return ADC_LL_CTRL_DIG; + case ADC_HAL_PWDET_MODE: + return ADC_LL_CTRL_PWDET; + default: + abort(); +#else + default: + return ADC_LL_CTRL_ARB; +#endif + } + } +} + +void adc_hal_set_controller(adc_ll_num_t unit, adc_hal_work_mode_t work_mode) +{ + adc_ll_controller_t ctrlr = get_controller(unit, work_mode); + adc_ll_set_controller(unit, ctrlr); +} + +/*--------------------------------------------------------------- + DMA read +---------------------------------------------------------------*/ +static adc_ll_digi_convert_mode_t get_convert_mode(adc_digi_convert_mode_t convert_mode) +{ +#if CONFIG_IDF_TARGET_ESP32 + return ADC_LL_DIGI_CONV_ONLY_ADC1; +#endif +#if (SOC_ADC_DIGI_CONTROLLER_NUM == 1) + return ADC_LL_DIGI_CONV_ALTER_UNIT; +#elif (SOC_ADC_DIGI_CONTROLLER_NUM >= 2) + switch (convert_mode) { + case ADC_CONV_SINGLE_UNIT_1: + return ADC_LL_DIGI_CONV_ONLY_ADC1; + case ADC_CONV_SINGLE_UNIT_2: + return ADC_LL_DIGI_CONV_ONLY_ADC2; + case ADC_CONV_BOTH_UNIT: + return ADC_LL_DIGI_CONV_BOTH_UNIT; + case ADC_CONV_ALTER_UNIT: + return ADC_LL_DIGI_CONV_ALTER_UNIT; + default: + abort(); + } +#endif +} + +/** + * For esp32s2 and later chips + * - Set ADC digital controller clock division factor. The clock is divided from `APLL` or `APB` clock. + * Expression: controller_clk = APLL/APB * (div_num + div_a / div_b + 1). + * - Enable clock and select clock source for ADC digital controller. + * For esp32, use I2S clock + */ +static void adc_hal_digi_sample_freq_config(adc_hal_context_t *hal, uint32_t freq) +{ +#if !CONFIG_IDF_TARGET_ESP32 + uint32_t interval = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / freq; + //set sample interval + adc_ll_digi_set_trigger_interval(interval); + //Here we set the clock divider factor to make the digital clock to 5M Hz + adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT); + adc_ll_digi_clk_sel(0); //use APB +#else + i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); /*!< Clock from PLL_D2_CLK(160M)*/ + uint32_t bck = I2S_BASE_CLK / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_B_DEFAULT / ADC_LL_CLKM_DIV_A_DEFAULT) / 2 / freq; + i2s_ll_mclk_div_t clk = { + .mclk_div = ADC_LL_CLKM_DIV_NUM_DEFAULT, + .a = ADC_LL_CLKM_DIV_A_DEFAULT, + .b = ADC_LL_CLKM_DIV_B_DEFAULT, + }; + i2s_ll_rx_set_clk(hal->dev, &clk); + i2s_ll_rx_set_bck_div_num(hal->dev, bck); +#endif +} + +void adc_hal_digi_controller_config(adc_hal_context_t *hal, const adc_hal_digi_ctrlr_cfg_t *cfg) +{ +#if (SOC_ADC_DIGI_CONTROLLER_NUM == 1) + //Only one pattern table, this variable is for readability + const int pattern_both = 0; + + adc_ll_digi_clear_pattern_table(pattern_both); + adc_ll_digi_set_pattern_table_len(pattern_both, cfg->adc_pattern_len); + for (int i = 0; i < cfg->adc_pattern_len; i++) { + adc_ll_digi_set_pattern_table(pattern_both, i, cfg->adc_pattern[i]); + } + +#elif (SOC_ADC_DIGI_CONTROLLER_NUM >= 2) + uint32_t adc1_pattern_idx = 0; + uint32_t adc2_pattern_idx = 0; + + adc_ll_digi_clear_pattern_table(ADC_NUM_1); + adc_ll_digi_clear_pattern_table(ADC_NUM_2); + + for (int i = 0; i < cfg->adc_pattern_len; i++) { + if (cfg->adc_pattern[i].unit == ADC_NUM_1) { + adc_ll_digi_set_pattern_table(ADC_NUM_1, adc1_pattern_idx, cfg->adc_pattern[i]); + adc1_pattern_idx++; + } else if (cfg->adc_pattern[i].unit == ADC_NUM_2) { + adc_ll_digi_set_pattern_table(ADC_NUM_2, adc2_pattern_idx, cfg->adc_pattern[i]); + adc2_pattern_idx++; + } else { + abort(); + } + } + adc_ll_digi_set_pattern_table_len(ADC_NUM_1, adc1_pattern_idx); + adc_ll_digi_set_pattern_table_len(ADC_NUM_2, adc2_pattern_idx); + +#endif + + if (cfg->conv_limit_en) { + adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num); + adc_ll_digi_convert_limit_enable(); + } else { + adc_ll_digi_convert_limit_disable(); + } + + adc_ll_digi_set_convert_mode(get_convert_mode(cfg->conv_mode)); + + //clock and sample frequency + adc_hal_digi_sample_freq_config(hal, cfg->sample_freq_hz); +} + +void adc_hal_context_config(adc_hal_context_t *hal, const adc_hal_config_t *config) +{ + hal->desc_dummy_head.next = hal->rx_desc; + hal->dev = config->dev; + 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) +{ + adc_dma_ll_rx_clear_intr(hal->dev, hal->dma_chan, ADC_HAL_DMA_INTR_MASK); + adc_dma_ll_rx_enable_intr(hal->dev, hal->dma_chan, ADC_HAL_DMA_INTR_MASK); + adc_ll_digi_dma_set_eof_num(hal->dev, hal->eof_num); +#if CONFIG_IDF_TARGET_ESP32 + i2s_ll_rx_set_sample_bit(hal->dev, SAMPLE_BITS, SAMPLE_BITS); + i2s_ll_rx_enable_mono_mode(hal->dev, 1); + i2s_ll_rx_force_enable_fifo_mod(hal->dev, 1); + i2s_ll_enable_builtin_adc(hal->dev, 1); +#endif +#if CONFIG_IDF_TARGET_ESP32C3 + adc_ll_onetime_sample_enable(ADC_NUM_1, false); + adc_ll_onetime_sample_enable(ADC_NUM_2, false); +#endif +} + +static void adc_hal_digi_dma_link_descriptors(dma_descriptor_t *desc, uint8_t *data_buf, uint32_t size, uint32_t num) +{ + HAL_ASSERT(((uint32_t)data_buf % 4) == 0); + HAL_ASSERT((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++; + } + desc[n-1].next = NULL; +} + +void adc_hal_digi_start(adc_hal_context_t *hal, uint8_t *data_buf) +{ + //stop peripheral and DMA + adc_hal_digi_stop(hal); + + //reset DMA + adc_dma_ll_rx_reset_channel(hal->dev, hal->dma_chan); + //reset peripheral + adc_ll_digi_reset(hal->dev); + + //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 * ADC_HAL_DATA_LEN_PER_CONV, hal->desc_max_num); + + //start DMA + adc_dma_ll_rx_start(hal->dev, hal->dma_chan, (lldesc_t *)hal->rx_desc); + //connect DMA and peripheral + adc_ll_digi_dma_enable(); + //start ADC + adc_ll_digi_trigger_enable(hal->dev); +} + +#if !SOC_GDMA_SUPPORTED +intptr_t adc_hal_get_desc_addr(adc_hal_context_t *hal) +{ + return adc_dma_ll_get_in_suc_eof_desc_addr(hal->dev, hal->dma_chan); +} + +bool adc_hal_check_event(adc_hal_context_t *hal, uint32_t mask) +{ + return adc_dma_ll_rx_get_intr(hal->dev, mask); +} +#endif //#if !SOC_GDMA_SUPPORTED + +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) +{ + 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; + + return ADC_HAL_DMA_DESC_VALID; +} + +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); +} + +void adc_hal_digi_dis_intr(adc_hal_context_t *hal, uint32_t mask) +{ + adc_dma_ll_rx_disable_intr(hal->dev, hal->dma_chan, mask); +} + +void adc_hal_digi_stop(adc_hal_context_t *hal) +{ + //stop ADC + adc_ll_digi_trigger_disable(hal->dev); + //stop DMA + adc_dma_ll_rx_stop(hal->dev, hal->dma_chan); + //disconnect DMA and peripheral + adc_ll_digi_dma_disable(); +} + +#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED +/*--------------------------------------------------------------- + Single Read +---------------------------------------------------------------*/ +/** + * For chips without RTC controller, Digital controller is used to trigger an ADC single read. + */ + +//--------------------INTR-------------------------------// +static adc_ll_intr_t get_event_intr(adc_hal_event_t event) +{ + adc_ll_intr_t intr_mask = 0; + if (event & ADC_EVENT_ADC1_DONE) { + intr_mask |= ADC_LL_INTR_ADC1_DONE; + } + if (event & ADC_EVENT_ADC2_DONE) { + intr_mask |= ADC_LL_INTR_ADC2_DONE; + } + return intr_mask; +} + +static void adc_hal_intr_clear(adc_hal_event_t event) +{ + adc_ll_intr_clear(get_event_intr(event)); +} + +static bool adc_hal_intr_get_raw(adc_hal_event_t event) +{ + return adc_ll_intr_get_raw(get_event_intr(event)); +} + + +//--------------------Single Read-------------------------------// +static void adc_hal_onetime_start(void) +{ + /** + * There is a hardware limitation. If the APB clock frequency is high, the step of this reg signal: ``onetime_start`` may not be captured by the + * ADC digital controller (when its clock frequency is too slow). A rough estimate for this step should be at least 3 ADC digital controller + * clock cycle. + * + * This limitation will be removed in hardware future versions. + * + */ + uint32_t digi_clk = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1); + //Convert frequency to time (us). Since decimals are removed by this division operation. Add 1 here in case of the fact that delay is not enough. + uint32_t delay = (1000 * 1000) / digi_clk + 1; + //3 ADC digital controller clock cycle + delay = delay * 3; + //This coefficient (8) is got from test. When digi_clk is not smaller than ``APB_CLK_FREQ/8``, no delay is needed. + if (digi_clk >= APB_CLK_FREQ/8) { + delay = 0; + } + + adc_ll_onetime_start(false); + esp_rom_delay_us(delay); + adc_ll_onetime_start(true); + + //No need to delay here. Becuase if the start signal is not seen, there won't be a done intr. +} + +static esp_err_t adc_hal_single_read(adc_ll_num_t adc_n, int *out_raw) +{ + if (adc_n == ADC_NUM_1) { + *out_raw = adc_ll_adc1_read(); + } else if (adc_n == ADC_NUM_2) { + *out_raw = adc_ll_adc2_read(); + if (adc_ll_analysis_raw_data(adc_n, *out_raw)) { + return ESP_ERR_INVALID_STATE; + } + } + return ESP_OK; +} + +esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw) +{ + esp_err_t ret; + adc_hal_event_t event; + + if (adc_n == ADC_NUM_1) { + event = ADC_EVENT_ADC1_DONE; + } else { + event = ADC_EVENT_ADC2_DONE; + } + + adc_hal_intr_clear(event); + adc_ll_onetime_sample_enable(ADC_NUM_1, false); + adc_ll_onetime_sample_enable(ADC_NUM_2, false); + adc_ll_onetime_sample_enable(adc_n, true); + adc_ll_onetime_set_channel(adc_n, channel); + + //Trigger single read. + adc_hal_onetime_start(); + while (!adc_hal_intr_get_raw(event)); + ret = adc_hal_single_read(adc_n, out_raw); + //HW workaround: when enabling periph clock, this should be false + adc_ll_onetime_sample_enable(adc_n, false); + + return ret; +} + +#else // #if SOC_ADC_RTC_CTRL_SUPPORTED +esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw) +{ + adc_ll_rtc_enable_channel(adc_n, channel); + adc_ll_rtc_start_convert(adc_n, channel); + while (adc_ll_rtc_convert_is_done(adc_n) != true); + *out_raw = adc_ll_rtc_get_convert_value(adc_n); + + if ((int)adc_ll_rtc_analysis_raw_data(adc_n, (uint16_t)(*out_raw))) { + return ESP_ERR_INVALID_STATE; + } + + return ESP_OK; +} +#endif //#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED + /*--------------------------------------------------------------- ADC calibration setting @@ -63,14 +544,10 @@ void adc_hal_set_calibration_param(adc_ll_num_t adc_n, uint32_t param) } } -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#if SOC_ADC_RTC_CTRL_SUPPORTED static void cal_setup(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd) { -#if CONFIG_IDF_TARGET_ESP32S2 - adc_hal_set_controller(adc_n, ADC_CTRL_RTC); //Set controller -#else - adc_hal_set_controller(adc_n, ADC_LL_CTRL_ARB); //Set controller -#endif + adc_hal_set_controller(adc_n, ADC_HAL_SINGLE_READ_MODE); //Set controller /* Enable/disable internal connect GND (for calibration). */ if (internal_gnd) { @@ -89,14 +566,15 @@ static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel) return (uint32_t)adc_ll_rtc_get_convert_value(adc_n); } -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 +#elif SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED +//For those RTC controller not supported chips, they use digital controller to do the single read. e.g.: esp32c3 static void cal_setup(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd) { adc_ll_onetime_sample_enable(ADC_NUM_1, false); adc_ll_onetime_sample_enable(ADC_NUM_2, false); /* Enable/disable internal connect GND (for calibration). */ if (internal_gnd) { - const int esp32c3_invalid_chan = (adc_n == ADC_NUM_1) ? 0xF : 0x1; + const int esp32c3_invalid_chan = (adc_n == ADC_NUM_1)? 0xF: 0x1; adc_ll_onetime_set_channel(adc_n, esp32c3_invalid_chan); } else { adc_ll_onetime_set_channel(adc_n, channel); @@ -112,7 +590,7 @@ static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel) esp_rom_delay_us(5); adc_ll_onetime_start(true); - while (!adc_ll_intr_get_raw(ADC_LL_INTR_ADC1_DONE | ADC_LL_INTR_ADC2_DONE)); + while(!adc_ll_intr_get_raw(ADC_LL_INTR_ADC1_DONE | ADC_LL_INTR_ADC2_DONE)); uint32_t read_val = -1; if (adc_n == ADC_NUM_1) { @@ -125,7 +603,7 @@ static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel) } return read_val; } -#endif //CONFIG_IDF_TARGET_* +#endif //Do single read via DIGI controller or RTC controller #define ADC_HAL_CAL_TIMES (10) #define ADC_HAL_CAL_OFFSET_RANGE (4096) @@ -181,224 +659,10 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc chk_code = code_h + code_l; uint32_t ret = ((code_sum - chk_code) % (ADC_HAL_CAL_TIMES - 2) < 4) - ? (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) - : (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1; + ? (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + : (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1; adc_ll_calibration_finish(adc_n); - return ret; } #endif //SOC_ADC_CALIBRATION_V1_SUPPORTED - -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 -//This feature is currently supported on ESP32C3, will be supported on other chips soon -/*--------------------------------------------------------------- - DMA setting ----------------------------------------------------------------*/ -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_rx_clear_interrupt_status(hal->dev, hal->dma_chan, UINT32_MAX); - gdma_ll_rx_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_onetime_sample_enable(ADC_NUM_1, false); - adc_ll_onetime_sample_enable(ADC_NUM_2, 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_link_descriptors(dma_descriptor_t *desc, uint8_t *data_buf, uint32_t size, uint32_t num) -{ - HAL_ASSERT(((uint32_t)data_buf % 4) == 0); - HAL_ASSERT((size % 4) == 0); - uint32_t n = 0; - - while (num--) { - desc[n].dw0.size = size; - desc[n].dw0.suc_eof = 0; - desc[n].dw0.owner = 1; - desc[n].buffer = data_buf; - desc[n].next = &desc[n + 1]; - data_buf += size; - n++; - } - desc[n - 1].next = NULL; -} - -void adc_hal_digi_rxdma_start(adc_hal_context_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 * ADC_HAL_DATA_LEN_PER_CONV, 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_start(adc_hal_context_t *hal) -{ - //the ADC data will be sent to the DMA - adc_ll_digi_dma_enable(); - //enable sar adc timer - adc_ll_digi_trigger_enable(); -} - -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) -{ - 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; - - return ADC_HAL_DMA_DESC_VALID; -} - -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_rx_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_rx_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(); - //disable sar adc timer - adc_ll_digi_trigger_disable(); -} - -/*--------------------------------------------------------------- - Single Read ----------------------------------------------------------------*/ - -//--------------------INTR-------------------------------// -static adc_ll_intr_t get_event_intr(adc_hal_event_t event) -{ - adc_ll_intr_t intr_mask = 0; - if (event & ADC_EVENT_ADC1_DONE) { - intr_mask |= ADC_LL_INTR_ADC1_DONE; - } - if (event & ADC_EVENT_ADC2_DONE) { - intr_mask |= ADC_LL_INTR_ADC2_DONE; - } - return intr_mask; -} - -static void adc_hal_intr_clear(adc_hal_event_t event) -{ - adc_ll_intr_clear(get_event_intr(event)); -} - -static bool adc_hal_intr_get_raw(adc_hal_event_t event) -{ - return adc_ll_intr_get_raw(get_event_intr(event)); -} - -//--------------------Single Read-------------------------------// -static void adc_hal_onetime_start(void) -{ - /** - * There is a hardware limitation. If the APB clock frequency is high, the step of this reg signal: ``onetime_start`` may not be captured by the - * ADC digital controller (when its clock frequency is too slow). A rough estimate for this step should be at least 3 ADC digital controller - * clock cycle. - * - * This limitation will be removed in hardware future versions. - * - */ - uint32_t digi_clk = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1); - //Convert frequency to time (us). Since decimals are removed by this division operation. Add 1 here in case of the fact that delay is not enough. - uint32_t delay = (1000 * 1000) / digi_clk + 1; - //3 ADC digital controller clock cycle - delay = delay * 3; - //This coefficient (8) is got from test. When digi_clk is not smaller than ``APB_CLK_FREQ/8``, no delay is needed. - if (digi_clk >= APB_CLK_FREQ / 8) { - delay = 0; - } - - adc_ll_onetime_start(false); - esp_rom_delay_us(delay); - adc_ll_onetime_start(true); - - //No need to delay here. Becuase if the start signal is not seen, there won't be a done intr. -} - -static esp_err_t adc_hal_single_read(adc_ll_num_t adc_n, int *out_raw) -{ - if (adc_n == ADC_NUM_1) { - *out_raw = adc_ll_adc1_read(); - } else if (adc_n == ADC_NUM_2) { - *out_raw = adc_ll_adc2_read(); - if (adc_ll_analysis_raw_data(adc_n, *out_raw)) { - return ESP_ERR_INVALID_STATE; - } - } - return ESP_OK; -} - -esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw) -{ - esp_err_t ret; - adc_hal_event_t event; - - if (adc_n == ADC_NUM_1) { - event = ADC_EVENT_ADC1_DONE; - } else { - event = ADC_EVENT_ADC2_DONE; - } - - adc_hal_intr_clear(event); - adc_ll_onetime_sample_enable(ADC_NUM_1, false); - adc_ll_onetime_sample_enable(ADC_NUM_2, false); - adc_ll_onetime_sample_enable(adc_n, true); - adc_ll_onetime_set_channel(adc_n, channel); - - //Trigger single read. - adc_hal_onetime_start(); - while (!adc_hal_intr_get_raw(event)); - ret = adc_hal_single_read(adc_n, out_raw); - //HW workaround: when enabling periph clock, this should be false - adc_ll_onetime_sample_enable(adc_n, false); - - return ret; -} -#else // !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 -esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw) -{ - adc_ll_rtc_enable_channel(adc_n, channel); - adc_ll_rtc_start_convert(adc_n, channel); - while (adc_ll_rtc_convert_is_done(adc_n) != true); - *out_raw = adc_ll_rtc_get_convert_value(adc_n); - - if ((int)adc_ll_rtc_analysis_raw_data(adc_n, (uint16_t)(*out_raw))) { - return ESP_ERR_INVALID_STATE; - } - - return ESP_OK; -} -#endif //#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP8684 diff --git a/components/hal/esp32/adc_hal.c b/components/hal/esp32/adc_hal.c index 867daa47ce..cffbbef9c1 100644 --- a/components/hal/esp32/adc_hal.c +++ b/components/hal/esp32/adc_hal.c @@ -1,16 +1,8 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ // The HAL layer for ADC (common part) @@ -18,45 +10,6 @@ #include "hal/adc_hal_conf.h" #include "hal/adc_types.h" -void adc_hal_digi_deinit(void) -{ - adc_ll_digi_clear_pattern_table(ADC_NUM_1); - adc_ll_digi_clear_pattern_table(ADC_NUM_2); -} - -void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) -{ - /* Single channel mode or multi channel mode. */ - adc_ll_digi_set_convert_mode(cfg->conv_mode); - if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) { - adc_ll_set_controller(ADC_NUM_1, ADC_CTRL_DIG); - if (cfg->adc1_pattern_len) { - adc_ll_digi_clear_pattern_table(ADC_NUM_1); - adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len); - for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) { - adc_ll_digi_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]); - } - } - } - if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) { - adc_ll_set_controller(ADC_NUM_2, ADC_CTRL_DIG); - if (cfg->adc2_pattern_len) { - adc_ll_digi_clear_pattern_table(ADC_NUM_2); - adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len); - for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) { - adc_ll_digi_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]); - } - } - } - adc_ll_digi_set_output_format(cfg->format); - if (cfg->conv_limit_en) { - adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num); - adc_ll_digi_convert_limit_enable(); - } else { - adc_ll_digi_convert_limit_disable(); - } - adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_ADC); -} int adc_hal_hall_convert(void) { diff --git a/components/hal/esp32/include/hal/adc_hal.h b/components/hal/esp32/include/hal/adc_hal.h index 50e3c9138c..53da0e034b 100644 --- a/components/hal/esp32/include/hal/adc_hal.h +++ b/components/hal/esp32/include/hal/adc_hal.h @@ -1,16 +1,8 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /******************************************************************************* * NOTICE @@ -31,35 +23,9 @@ extern "C" { #endif -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ - -/** - * Set I2S DMA data source for digital controller. - * - * @param src i2s data source. - */ -#define adc_hal_digi_set_data_source(src) adc_ll_digi_set_data_source(src) - -/*--------------------------------------------------------------- - Common setting ----------------------------------------------------------------*/ - /*--------------------------------------------------------------- Hall sensor setting ---------------------------------------------------------------*/ - -/** - * Enable hall sensor. - */ -#define adc_hal_hall_enable() adc_ll_hall_enable() - -/** - * Disable hall sensor. - */ -#define adc_hal_hall_disable() adc_ll_hall_disable() - /** * Start hall convert and return the hall value. * diff --git a/components/hal/esp32/include/hal/adc_ll.h b/components/hal/esp32/include/hal/adc_ll.h index 1b5969ac43..6e648733be 100644 --- a/components/hal/esp32/include/hal/adc_ll.h +++ b/components/hal/esp32/include/hal/adc_ll.h @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + #pragma once #include "soc/adc_periph.h" @@ -26,22 +32,50 @@ typedef enum { ADC_POWER_MAX, /*!< For parameter check. */ } adc_ll_power_t; +typedef enum { + ADC_RTC_DATA_OK = 0, +} adc_ll_rtc_raw_data_t; + +typedef enum { + ADC_LL_CTRL_RTC = 0, ///< For ADC1 and ADC2. Select RTC controller. + ADC_LL_CTRL_ULP = 1, ///< For ADC1 and ADC2. Select ULP controller. + ADC_LL_CTRL_DIG = 2, ///< For ADC1 and ADC2. Select DIG controller. + ADC_LL_CTRL_PWDET = 3, ///< For ADC2. Select PWDET controller. +} adc_ll_controller_t; + +/** + * @brief ADC digital controller (DMA mode) work mode. + * + * @note The conversion mode affects the sampling frequency: + * SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once. + * SINGLE_UNIT_2: When the measurement is triggered, only ADC2 is sampled once. + * BOTH_UNIT : When the measurement is triggered, ADC1 and ADC2 are sampled at the same time. + * ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately. + */ +typedef enum { + ADC_LL_DIGI_CONV_ONLY_ADC1 = 0, // Only use ADC1 for conversion + ADC_LL_DIGI_CONV_ONLY_ADC2 = 1, // Only use ADC2 for conversion + ADC_LL_DIGI_CONV_BOTH_UNIT = 2, // Use Both ADC1 and ADC2 for conversion simultaneously + ADC_LL_DIGI_CONV_ALTER_UNIT = 3 // Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 ..... +} adc_ll_digi_convert_mode_t; + +//Need a unit test for bit_width +typedef struct { + union { + struct { + uint8_t atten: 2; + uint8_t bit_width: 2; //ADC resolution. 0: 9 bit; 1: 10 bit; 2: 11 bit; 3: 12 bit + uint8_t channel: 4; + }; + uint8_t val; + }; +} __attribute__((packed)) adc_ll_digi_pattern_table_t; + typedef enum { ADC_HALL_CTRL_ULP = 0x0,/*!< Hall sensor controlled by ULP */ ADC_HALL_CTRL_RTC = 0x1 /*!< Hall sensor controlled by RTC */ } adc_ll_hall_controller_t ; -typedef enum { - ADC_CTRL_RTC = 0, - ADC_CTRL_ULP = 1, - ADC_CTRL_DIG = 2, - ADC2_CTRL_PWDET = 3, -} adc_hal_controller_t ; - -typedef enum { - ADC_RTC_DATA_OK = 0, -} adc_ll_rtc_raw_data_t; - /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ @@ -85,16 +119,6 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div) HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_ctrl, sar_clk_div, div); } -/** - * Set adc output data format for digital controller. - * - * @param format Output data format, see ``adc_digi_output_format_t``. - */ -static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format) -{ - SYSCON.saradc_ctrl.data_sar_sel = format; -} - /** * Set adc max conversion number for digital controller. * If the number of ADC conversion is equal to the maximum, the conversion is stopped. @@ -128,21 +152,28 @@ static inline void adc_ll_digi_convert_limit_disable(void) * Set adc conversion mode for digital controller. * * @note ESP32 only support ADC1 single mode. + * @note For `data_sar_sel` register: + * 1: [15] unit, [14:11] channel, [10:0] data, 11-bit-width at most. Only work under `ADC_LL_DIGI_CONV_BOTH_UNIT` or `ADC_LL_DIGI_CONV_ALTER_UNIT` mode. + * 0: [15:12] channel, [11:0] data, 12-bit-width at most. Only work under `ADC_LL_DIGI_CONV_ONLY_ADC1` or `ADC_LL_DIGI_CONV_ONLY_ADC2` mode * - * @param mode Conversion mode select, see ``adc_digi_convert_mode_t``. + * @param mode Conversion mode select. */ -static inline void adc_ll_digi_set_convert_mode(adc_digi_convert_mode_t mode) +static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode) { - if (mode == ADC_CONV_SINGLE_UNIT_1) { + if (mode == ADC_LL_DIGI_CONV_ONLY_ADC1) { SYSCON.saradc_ctrl.work_mode = 0; SYSCON.saradc_ctrl.sar_sel = 0; - } else if (mode == ADC_CONV_SINGLE_UNIT_2) { + SYSCON.saradc_ctrl.data_sar_sel = 0; + } else if (mode == ADC_LL_DIGI_CONV_ONLY_ADC2) { SYSCON.saradc_ctrl.work_mode = 0; SYSCON.saradc_ctrl.sar_sel = 1; - } else if (mode == ADC_CONV_BOTH_UNIT) { + SYSCON.saradc_ctrl.data_sar_sel = 0; + } else if (mode == ADC_LL_DIGI_CONV_BOTH_UNIT) { SYSCON.saradc_ctrl.work_mode = 1; - } else if (mode == ADC_CONV_ALTER_UNIT) { + SYSCON.saradc_ctrl.data_sar_sel = 1; + } else if (mode == ADC_LL_DIGI_CONV_ALTER_UNIT) { SYSCON.saradc_ctrl.work_mode = 2; + SYSCON.saradc_ctrl.data_sar_sel = 1; } } @@ -163,11 +194,10 @@ static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en) /** * Set I2S DMA data source for digital controller. * - * @param src i2s data source, see ``adc_i2s_source_t``. + * @param src 1: I2S input data is from SAR ADC (for DMA) 0: I2S input data is from GPIO matrix */ -static inline void adc_ll_digi_set_data_source(adc_i2s_source_t src) +static inline void adc_ll_digi_set_data_source(bool src) { - /* 1: I2S input data is from SAR ADC (for DMA) 0: I2S input data is from GPIO matrix */ SYSCON.saradc_ctrl.data_to_i2s = src; } @@ -199,12 +229,33 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_ * @param pattern_index Items index. Range: 0 ~ 15. * @param pattern Stored conversion rules, see ``adc_digi_pattern_table_t``. */ -static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern) +static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_config_t table) { uint32_t tab; uint8_t index = pattern_index / 4; uint8_t offset = (pattern_index % 4) * 8; - if (adc_n == ADC_NUM_1) { + adc_ll_digi_pattern_table_t pattern = {0}; + uint8_t bit_width; + + switch (table.bit_width) { + case 9: + bit_width = 0x0; + break; + case 10: + bit_width = 0x1; + break; + case 11: + bit_width = 0x2; + break; + case 12: + bit_width = 0x3; + break; + default: + bit_width = 0x3; + } + pattern.val = (table.atten & 0x3) | ((bit_width) << 2) | ((table.channel & 0xF) << 4); + + if (table.unit == ADC_NUM_1) { tab = SYSCON.saradc_sar1_patt_tab[index]; // Read old register value tab &= (~(0xFF000000 >> offset)); // clear old data tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data @@ -233,6 +284,15 @@ static inline void adc_ll_digi_clear_pattern_table(adc_ll_num_t adc_n) } } +/** + * Disable clock for ADC digital controller. + * @note Not used for esp32 + */ +static inline void adc_ll_digi_controller_clk_disable(void) +{ + //Leave here for compatibility +} + /*--------------------------------------------------------------- PWDET(Power detect) controller setting ---------------------------------------------------------------*/ @@ -263,6 +323,20 @@ static inline uint32_t adc_ll_pwdet_get_cct(void) /*--------------------------------------------------------------- RTC controller setting ---------------------------------------------------------------*/ +/** + * ADC SAR clock division factor setting. ADC SAR clock divided from `RTC_FAST_CLK`. + * + * @param div Division factor. + */ +static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) +{ + if (adc_n == ADC_NUM_1) { + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl, sar1_clk_div, div); + } else { // adc_n == ADC_NUM_2 + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl2, sar2_clk_div, div); + } +} + /** * Set adc output data format for RTC controller. * @@ -398,62 +472,6 @@ static inline adc_ll_rtc_raw_data_t adc_ll_rtc_analysis_raw_data(adc_ll_num_t ad return ADC_RTC_DATA_OK; } -/*--------------------------------------------------------------- - Common setting ----------------------------------------------------------------*/ -/** - * Set ADC module power management. - * - * @param manage Set ADC power status. - */ -static inline void adc_ll_set_power_manage(adc_ll_power_t manage) -{ - /* Bit1 0:Fsm 1: SW mode - Bit0 0:SW mode power down 1: SW mode power on */ - if (manage == ADC_POWER_SW_ON) { - SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU; - } else if (manage == ADC_POWER_BY_FSM) { - SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM; - } else if (manage == ADC_POWER_SW_OFF) { - SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PD; - } -} - -/** - * Get ADC module power management. - * - * @return - * - ADC power status. - */ -static inline adc_ll_power_t adc_ll_get_power_manage(void) -{ - /* Bit1 0:Fsm 1: SW mode - Bit0 0:SW mode power down 1: SW mode power on */ - adc_ll_power_t manage; - if (SENS.sar_meas_wait2.force_xpd_sar == SENS_FORCE_XPD_SAR_PU) { - manage = ADC_POWER_SW_ON; - } else if (SENS.sar_meas_wait2.force_xpd_sar == SENS_FORCE_XPD_SAR_PD) { - manage = ADC_POWER_SW_OFF; - } else { - manage = ADC_POWER_BY_FSM; - } - return manage; -} - -/** - * ADC SAR clock division factor setting. ADC SAR clock divided from `RTC_FAST_CLK`. - * - * @param div Division factor. - */ -static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) -{ - if (adc_n == ADC_NUM_1) { - HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl, sar1_clk_div, div); - } else { // adc_n == ADC_NUM_2 - HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl2, sar2_clk_div, div); - } -} - /** * Set the attenuation of a particular channel on ADCn. */ @@ -482,6 +500,27 @@ static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t cha } } +/*--------------------------------------------------------------- + Common setting +---------------------------------------------------------------*/ +/** + * Set ADC module power management. + * + * @param manage Set ADC power status. + */ +static inline void adc_ll_set_power_manage(adc_ll_power_t manage) +{ + /* Bit1 0:Fsm 1: SW mode + Bit0 0:SW mode power down 1: SW mode power on */ + if (manage == ADC_POWER_SW_ON) { + SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU; + } else if (manage == ADC_POWER_BY_FSM) { + SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM; + } else if (manage == ADC_POWER_SW_OFF) { + SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PD; + } +} + /** * Set ADC module controller. * There are five SAR ADC controllers: @@ -492,25 +531,25 @@ static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t cha * @param adc_n ADC unit. * @param ctrl ADC controller. */ -static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_hal_controller_t ctrl) +static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl) { if (adc_n == ADC_NUM_1) { switch ( ctrl ) { - case ADC_CTRL_RTC: + case ADC_LL_CTRL_RTC: SENS.sar_read_ctrl.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control. SENS.sar_meas_start1.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas_start1.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; SENS.sar_touch_ctrl1.xpd_hall_force = 1; // 1: SW control HALL power; 0: ULP FSM control HALL power. SENS.sar_touch_ctrl1.hall_phase_force = 1; // 1: SW control HALL phase; 0: ULP FSM control HALL phase. break; - case ADC_CTRL_ULP: + case ADC_LL_CTRL_ULP: SENS.sar_read_ctrl.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control. SENS.sar_meas_start1.meas1_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas_start1.sar1_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; SENS.sar_touch_ctrl1.xpd_hall_force = 0; // 1: SW control HALL power; 0: ULP FSM control HALL power. SENS.sar_touch_ctrl1.hall_phase_force = 0; // 1: SW control HALL phase; 0: ULP FSM control HALL phase. break; - case ADC_CTRL_DIG: + case ADC_LL_CTRL_DIG: SENS.sar_read_ctrl.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control. SENS.sar_meas_start1.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas_start1.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; @@ -522,28 +561,28 @@ static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_hal_controller_ } } else { // adc_n == ADC_NUM_2 switch ( ctrl ) { - case ADC_CTRL_RTC: + case ADC_LL_CTRL_RTC: SENS.sar_meas_start2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas_start2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; SENS.sar_read_ctrl2.sar2_dig_force = 0; // 1: Select digital control; 0: Select RTC control. SENS.sar_read_ctrl2.sar2_pwdet_force = 0; // 1: Select power detect control; 0: Select RTC control. SYSCON.saradc_ctrl.sar2_mux = 1; // 1: Select digital control; 0: Select power detect control. break; - case ADC_CTRL_ULP: + case ADC_LL_CTRL_ULP: SENS.sar_meas_start2.meas2_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas_start2.sar2_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; SENS.sar_read_ctrl2.sar2_dig_force = 0; // 1: Select digital control; 0: Select RTC control. SENS.sar_read_ctrl2.sar2_pwdet_force = 0; // 1: Select power detect control; 0: Select RTC control. SYSCON.saradc_ctrl.sar2_mux = 1; // 1: Select digital control; 0: Select power detect control. break; - case ADC_CTRL_DIG: + case ADC_LL_CTRL_DIG: SENS.sar_meas_start2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas_start2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; SENS.sar_read_ctrl2.sar2_dig_force = 1; // 1: Select digital control; 0: Select RTC control. SENS.sar_read_ctrl2.sar2_pwdet_force = 0; // 1: Select power detect control; 0: Select RTC control. SYSCON.saradc_ctrl.sar2_mux = 1; // 1: Select digital control; 0: Select power detect control. break; - case ADC2_CTRL_PWDET: // currently only used by Wi-Fi + case ADC_LL_CTRL_PWDET: // currently only used by Wi-Fi SENS.sar_meas_start2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas_start2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; SENS.sar_read_ctrl2.sar2_dig_force = 0; // 1: Select digital control; 0: Select RTC control. diff --git a/components/hal/esp32c3/adc_hal.c b/components/hal/esp32c3/adc_hal.c index c2fcaab27e..7b21a48d11 100644 --- a/components/hal/esp32c3/adc_hal.c +++ b/components/hal/esp32c3/adc_hal.c @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ // The HAL layer for ADC (ESP32-C3 specific part) @@ -32,56 +24,6 @@ static adc_digi_monitor_t s_monitor_config[SOC_ADC_DIGI_MONITOR_NUM] = {}; /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ -void adc_hal_digi_deinit(void) -{ - adc_ll_digi_trigger_disable(); // boss - adc_ll_digi_dma_disable(); - adc_ll_digi_clear_pattern_table(ADC_NUM_1); - adc_ll_digi_clear_pattern_table(ADC_NUM_2); - adc_ll_digi_filter_reset(ADC_NUM_1); - adc_ll_digi_filter_reset(ADC_NUM_2); - adc_ll_digi_reset(); - adc_ll_digi_controller_clk_disable(); -} - -/** - * - Set ADC digital controller clock division factor. The clock is divided from `APLL` or `APB` clock. - * Expression: controller_clk = APLL/APB * (div_num + div_a / div_b + 1). - * - Enable clock and select clock source for ADC digital controller. - */ -static void adc_hal_digi_clk_config(void) -{ - //Here we set the clock divider factor to make the digital clock to 5M Hz - adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT); - adc_ll_digi_controller_clk_enable(0); -} - -void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) -{ - //only one pattern table is supported on C3, but LL still needs one argument. - const int pattern_both = 0; - - if (cfg->adc_pattern_len) { - adc_ll_digi_clear_pattern_table(pattern_both); - adc_ll_digi_set_pattern_table_len(pattern_both, cfg->adc_pattern_len); - for (uint32_t i = 0; i < cfg->adc_pattern_len; i++) { - adc_ll_digi_set_pattern_table(pattern_both, i, cfg->adc_pattern[i]); - } - } - - if (cfg->conv_limit_en) { - adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num); - adc_ll_digi_convert_limit_enable(); - } else { - adc_ll_digi_convert_limit_disable(); - } - - //clock - uint32_t interval = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / cfg->sample_freq_hz; - adc_ll_digi_set_trigger_interval(interval); - adc_hal_digi_clk_config(); -} - static void filter_update(adc_digi_filter_idx_t idx) { //ESP32-C3 has no enable bit, the filter will be enabled when the filter channel is configured diff --git a/components/hal/esp32c3/include/hal/adc_hal.h b/components/hal/esp32c3/include/hal/adc_hal.h index 1425acf0e1..bf4794377a 100644 --- a/components/hal/esp32c3/include/hal/adc_hal.h +++ b/components/hal/esp32c3/include/hal/adc_hal.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /******************************************************************************* * NOTICE @@ -34,18 +26,6 @@ extern "C" { /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ -/** - * Digital controller deinitialization. - */ -void adc_hal_digi_deinit(void); - -/** - * Setting the digital controller. - * - * @param cfg Pointer to digital controller paramter. - */ -void adc_hal_digi_controller_config(const adc_digi_config_t *cfg); - /** * Reset adc digital controller filter. * diff --git a/components/hal/esp32c3/include/hal/adc_ll.h b/components/hal/esp32c3/include/hal/adc_ll.h index 49ff4a23f4..38bdae9fe9 100644 --- a/components/hal/esp32c3/include/hal/adc_ll.h +++ b/components/hal/esp32c3/include/hal/adc_ll.h @@ -1,30 +1,22 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include #include -#include "hal/misc.h" #include "regi2c_ctrl.h" #include "esp_attr.h" #include "soc/adc_periph.h" -#include "hal/adc_types.h" #include "soc/apb_saradc_struct.h" #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" +#include "hal/misc.h" +#include "hal/adc_types.h" #ifdef __cplusplus extern "C" { @@ -54,6 +46,22 @@ typedef enum { ADC_RTC_DATA_FAIL = -1, } adc_ll_rtc_raw_data_t; +typedef enum { + ADC_LL_CTRL_DIG = 0, ///< For ADC1. Select DIG controller. + ADC_LL_CTRL_ARB = 1, ///< For ADC2. The controller is selected by the arbiter. +} adc_ll_controller_t; + +/** + * @brief ADC digital controller (DMA mode) work mode. + * + * @note The conversion mode affects the sampling frequency: + * ESP32C3 only support ALTER_UNIT mode + * ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately. + */ +typedef enum { + ADC_LL_DIGI_CONV_ALTER_UNIT = 0, // Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 ..... +} adc_ll_digi_convert_mode_t; + //These values should be set according to the HW typedef enum { ADC_LL_INTR_THRES1_LOW = BIT(26), @@ -65,21 +73,17 @@ typedef enum { } adc_ll_intr_t; FLAG_ATTR(adc_ll_intr_t) -/** - * @brief ADC controller type selection. - * - * @note For ADC2, use the force option with care. The system power consumption detection will use ADC2. - * If it is forced to switch to another controller, it may cause the system to obtain incorrect values. - * @note Normally, there is no need to switch the controller manually. - */ -typedef enum { - ADC_CTRL_RTC = 0, /*!> offset)); // Clear old data - tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data - APB_SARADC.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back + pattern.val = (table.atten & 0x3) | ((table.channel & 0x7) << 2) | ((table.unit & 0x1) << 5); + tab = APB_SARADC.sar_patt_tab[index].sar_patt_tab1; // Read old register value + tab &= (~(0xFC0000 >> offset)); // Clear old data + tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data + APB_SARADC.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back } /** @@ -260,9 +278,9 @@ static inline void adc_ll_digi_trigger_disable(void) /** * Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock. - * Expression: controller_clk = APLL/APB * (div_num + div_b / div_a). + * Expression: controller_clk = (APLL or APB) / (div_num + div_a / div_b + 1). * - * @param div_num Division factor. Range: 1 ~ 255. + * @param div_num Division factor. Range: 0 ~ 255. * @param div_b Division factor. Range: 1 ~ 63. * @param div_a Division factor. Range: 0 ~ 63. */ @@ -278,7 +296,7 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div * * @param use_apll true: use APLL clock; false: use APB clock. */ -static inline void adc_ll_digi_controller_clk_enable(bool use_apll) +static inline void adc_ll_digi_clk_sel(bool use_apll) { if (use_apll) { APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock @@ -494,8 +512,8 @@ static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n, */ static inline void adc_ll_set_power_manage(adc_ll_power_t manage) { - // /* Bit1 0:Fsm 1: SW mode - // Bit0 0:SW mode power down 1: SW mode power on */ + /* Bit1 0:Fsm 1: SW mode + Bit0 0:SW mode power down 1: SW mode power on */ if (manage == ADC_POWER_SW_ON) { APB_SARADC.ctrl.sar_clk_gated = 1; APB_SARADC.ctrl.xpd_sar_force = 3; @@ -503,30 +521,14 @@ static inline void adc_ll_set_power_manage(adc_ll_power_t manage) APB_SARADC.ctrl.sar_clk_gated = 1; APB_SARADC.ctrl.xpd_sar_force = 0; } else if (manage == ADC_POWER_SW_OFF) { - APB_SARADC.ctrl.xpd_sar_force = 2; APB_SARADC.ctrl.sar_clk_gated = 0; + APB_SARADC.ctrl.xpd_sar_force = 2; } } -/** - * Get ADC module power management. - * - * @return - * - ADC power status. - */ -static inline adc_ll_power_t adc_ll_get_power_manage(void) +static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl) { - /* Bit1 0:Fsm 1: SW mode - Bit0 0:SW mode power down 1: SW mode power on */ - adc_ll_power_t manage; - if (APB_SARADC.ctrl.xpd_sar_force == 3) { - manage = ADC_POWER_SW_ON; - } else if (APB_SARADC.ctrl.xpd_sar_force == 2) { - manage = ADC_POWER_SW_OFF; - } else { - manage = ADC_POWER_BY_FSM; - } - return manage; + //Not used on ESP32C3 } /** diff --git a/components/hal/esp32h2/adc_hal.c b/components/hal/esp32h2/adc_hal.c deleted file mode 100644 index 4490db606f..0000000000 --- a/components/hal/esp32h2/adc_hal.c +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// The HAL layer for ADC (ESP32-H2 specific part) - -#include -#include "soc/soc_caps.h" -#include "hal/adc_hal.h" -#include "hal/adc_types.h" -#include "soc/soc.h" - -//Currently we don't have context for the ADC HAL. So HAL variables are temporarily put here. But -//please don't follow this code. Create a context for your own HAL! - -static bool s_filter_enabled[SOC_ADC_DIGI_FILTER_NUM] = {}; -static adc_digi_filter_t s_filter[SOC_ADC_DIGI_FILTER_NUM] = {}; - -static bool s_monitor_enabled[SOC_ADC_DIGI_MONITOR_NUM] = {}; -static adc_digi_monitor_t s_monitor_config[SOC_ADC_DIGI_MONITOR_NUM] = {}; - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ -void adc_hal_digi_deinit(void) -{ - adc_ll_digi_trigger_disable(); // boss - adc_ll_digi_dma_disable(); - adc_ll_digi_clear_pattern_table(ADC_NUM_1); - adc_ll_digi_clear_pattern_table(ADC_NUM_2); - adc_ll_digi_filter_reset(ADC_NUM_1); - adc_ll_digi_filter_reset(ADC_NUM_2); - adc_ll_digi_reset(); - adc_ll_digi_controller_clk_disable(); -} - -/** - * - Set ADC digital controller clock division factor. The clock is divided from `APLL` or `APB` clock. - * Expression: controller_clk = APLL/APB * (div_num + div_a / div_b + 1). - * - Enable clock and select clock source for ADC digital controller. - */ -static void adc_hal_digi_clk_config(void) -{ - //Here we set the clock divider factor to make the digital clock to 5M Hz - adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT); - adc_ll_digi_controller_clk_enable(0); -} - -void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) -{ - //only one pattern table is supported on H2, but LL still needs one argument. - const int pattern_both = 0; - - if (cfg->adc_pattern_len) { - adc_ll_digi_clear_pattern_table(pattern_both); - adc_ll_digi_set_pattern_table_len(pattern_both, cfg->adc_pattern_len); - for (uint32_t i = 0; i < cfg->adc_pattern_len; i++) { - adc_ll_digi_set_pattern_table(pattern_both, i, cfg->adc_pattern[i]); - } - } - - if (cfg->conv_limit_en) { - adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num); - adc_ll_digi_convert_limit_enable(); - } else { - adc_ll_digi_convert_limit_disable(); - } - - //clock - uint32_t interval = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / cfg->sample_freq_hz; - adc_ll_digi_set_trigger_interval(interval); - adc_hal_digi_clk_config(); -} - -static void filter_update(adc_digi_filter_idx_t idx) -{ - //ESP32-H2 has no enable bit, the filter will be enabled when the filter channel is configured - if (s_filter_enabled[idx]) { - adc_ll_digi_filter_set_factor(idx, &s_filter[idx]); - } else { - adc_ll_digi_filter_disable(idx); - } -} - -/** - * Set adc digital controller filter factor. - * - * @param idx ADC filter unit. - * @param filter Filter config. Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). - */ -void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter) -{ - s_filter[idx] = *filter; - filter_update(idx); -} - -/** - * Get adc digital controller filter factor. - * - * @param adc_n ADC unit. - * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). - */ -void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter) -{ - *filter = s_filter[idx]; -} - -void adc_hal_digi_filter_enable(adc_digi_filter_idx_t filter_idx, bool enable) -{ - s_filter_enabled[filter_idx] = enable; - filter_update(filter_idx); -} - -static void update_monitor(adc_digi_monitor_idx_t idx) -{ - //ESP32-H2 has no enable bit, the monitor will be enabled when the monitor channel is configured - if (s_monitor_enabled[idx]) { - adc_ll_digi_monitor_set_mode(idx, &s_monitor_config[idx]); - } else { - adc_ll_digi_monitor_disable(idx); - } -} - -void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config) -{ - s_monitor_config[idx] = *config; - update_monitor(idx); -} - -void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable) -{ - s_monitor_enabled[mon_idx] = enable; - update_monitor(mon_idx); -} - -/*--------------------------------------------------------------- - Common setting ----------------------------------------------------------------*/ - -/** - * Config ADC2 module arbiter. - * The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority, - * the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data. - * - * @note Only ADC2 support arbiter. - * @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode. - * @note Default priority: Wi-Fi > RTC > Digital; - * - * @param config Refer to `adc_arbiter_t`. - */ -void adc_hal_arbiter_config(adc_arbiter_t *config) -{ - adc_ll_set_arbiter_work_mode(config->mode); - adc_ll_set_arbiter_priority(config->rtc_pri, config->dig_pri, config->pwdet_pri); -} diff --git a/components/hal/esp32h2/include/hal/adc_hal.h b/components/hal/esp32h2/include/hal/adc_hal.h deleted file mode 100644 index 9993f9e8d9..0000000000 --- a/components/hal/esp32h2/include/hal/adc_hal.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/******************************************************************************* - * NOTICE - * The hal is not public api, don't use in application code. - * See readme.md in soc/include/hal/readme.md - ******************************************************************************/ - -// The HAL layer for ADC (esp32s2 specific part) - -#pragma once - -#include "hal/adc_ll.h" -#include "hal/adc_types.h" - -#include_next "hal/adc_hal.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ -/** - * Digital controller deinitialization. - */ -void adc_hal_digi_deinit(void); - -/** - * Setting the digital controller. - * - * @param cfg Pointer to digital controller paramter. - */ -void adc_hal_digi_controller_config(const adc_digi_config_t *cfg); - -/** - * Reset adc digital controller filter. - * - * @param filter_idx ADC filter unit. - */ -#define adc_hal_digi_filter_reset(filter_idx) adc_ll_digi_filter_reset(filter_idx) - -/** - * Set adc digital controller filter factor. - * - * @param filter_idx ADC filter unit. - * @param filter Filter config. Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). - */ -void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t filter_idx, adc_digi_filter_t *filter); - -/** - * Get adc digital controller filter factor. - * - * @param filter_idx ADC filter unit. - * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). - */ -void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t filter_idx, adc_digi_filter_t *filter); - -/** - * Enable/disable adc digital controller filter. - * Filtering the ADC data to obtain smooth data at higher sampling rates. - * - * @note The filter will filter all the enabled channel data of the each ADC unit at the same time. - * @param filter_idx ADC filter unit. - * @param enable True to enable the filter, otherwise disable. - */ -void adc_hal_digi_filter_enable(adc_digi_filter_idx_t filter_idx, bool enable); - -/** - * Config monitor of adc digital controller. - * - * @note If the channel info is not supported, the monitor function will not be enabled. - * @param mon_idx ADC monitor index. - * @param config Refer to `adc_digi_monitor_t`. - */ -void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t mon_idx, adc_digi_monitor_t *config); - -/** - * Enable/disable monitor of adc digital controller. - * - * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time. - * @param mon_idx ADC monitor index. - * @param enable True to enable the monitor, otherwise disable. - */ -void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable); - -/*--------------------------------------------------------------- - Common setting ----------------------------------------------------------------*/ - -/** - * Config ADC2 module arbiter. - * The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority, - * the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data. - * - * @note Only ADC2 support arbiter. - * @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode. - * @note Default priority: Wi-Fi > RTC > Digital; - * - * @param config Refer to `adc_arbiter_t`. - */ -void adc_hal_arbiter_config(adc_arbiter_t *config); - -#ifdef __cplusplus -} -#endif diff --git a/components/hal/esp32h2/include/hal/adc_ll.h b/components/hal/esp32h2/include/hal/adc_ll.h index 7806465258..2221f441f3 100644 --- a/components/hal/esp32h2/include/hal/adc_ll.h +++ b/components/hal/esp32h2/include/hal/adc_ll.h @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include @@ -54,6 +46,22 @@ typedef enum { ADC_RTC_DATA_FAIL = -1, } adc_ll_rtc_raw_data_t; +typedef enum { + ADC_LL_CTRL_DIG = 0, ///< For ADC1. Select DIG controller. + ADC_LL_CTRL_ARB = 1, ///< For ADC2. The controller is selected by the arbiter. +} adc_ll_controller_t; + +/** + * @brief ADC digital controller (DMA mode) work mode. + * + * @note The conversion mode affects the sampling frequency: + * ESP32H2 only support ALTER_UNIT mode + * ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately. + */ +typedef enum { + ADC_LL_DIGI_CONV_ALTER_UNIT = 0, // Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 ..... +} adc_ll_digi_convert_mode_t; + //These values should be set according to the HW typedef enum { ADC_LL_INTR_THRES1_LOW = BIT(26), @@ -65,21 +73,17 @@ typedef enum { } adc_ll_intr_t; FLAG_ATTR(adc_ll_intr_t) -/** - * @brief ADC controller type selection. - * - * @note For ADC2, use the force option with care. The system power consumption detection will use ADC2. - * If it is forced to switch to another controller, it may cause the system to obtain incorrect values. - * @note Normally, there is no need to switch the controller manually. - */ -typedef enum { - ADC_CTRL_RTC = 0, /*!> offset)); // Clear old data - tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data - APB_SARADC.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back + pattern.val = (table.atten & 0x3) | ((table.channel & 0x7) << 2) | ((table.unit & 0x1) << 5); + tab = APB_SARADC.sar_patt_tab[index].sar_patt_tab1; // Read old register value + tab &= (~(0xFC0000 >> offset)); // Clear old data + tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data + APB_SARADC.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back } /** @@ -260,9 +278,9 @@ static inline void adc_ll_digi_trigger_disable(void) /** * Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock. - * Expression: controller_clk = APLL/APB * (div_num + div_b / div_a). + * Expression: controller_clk = (APLL or APB) / (div_num + div_a / div_b + 1). * - * @param div_num Division factor. Range: 1 ~ 255. + * @param div_num Division factor. Range: 0 ~ 255. * @param div_b Division factor. Range: 1 ~ 63. * @param div_a Division factor. Range: 0 ~ 63. */ @@ -278,7 +296,7 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div * * @param use_apll true: use APLL clock; false: use APB clock. */ -static inline void adc_ll_digi_controller_clk_enable(bool use_apll) +static inline void adc_ll_digi_clk_sel(bool use_apll) { if (use_apll) { APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock @@ -445,8 +463,7 @@ static inline void adc_ll_digi_reset(void) static inline void adc_ll_pwdet_set_cct(uint32_t cct) { /* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */ - // RTCCNTL.sensor_ctrl.sar2_pwdet_cct = cct; - abort(); // ESP32H2-TODO: IDF-3389 + abort(); } /** @@ -458,9 +475,7 @@ static inline void adc_ll_pwdet_set_cct(uint32_t cct) static inline uint32_t adc_ll_pwdet_get_cct(void) { /* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */ - // return RTCCNTL.sensor_ctrl.sar2_pwdet_cct; - abort(); // ESP32H2-TODO: IDF-3389 - return 0; + abort(); } /** @@ -497,8 +512,8 @@ static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n, */ static inline void adc_ll_set_power_manage(adc_ll_power_t manage) { - // /* Bit1 0:Fsm 1: SW mode - // Bit0 0:SW mode power down 1: SW mode power on */ + /* Bit1 0:Fsm 1: SW mode + Bit0 0:SW mode power down 1: SW mode power on */ if (manage == ADC_POWER_SW_ON) { APB_SARADC.ctrl.sar_clk_gated = 1; APB_SARADC.ctrl.xpd_sar_force = 3; @@ -506,30 +521,14 @@ static inline void adc_ll_set_power_manage(adc_ll_power_t manage) APB_SARADC.ctrl.sar_clk_gated = 1; APB_SARADC.ctrl.xpd_sar_force = 0; } else if (manage == ADC_POWER_SW_OFF) { - APB_SARADC.ctrl.xpd_sar_force = 2; APB_SARADC.ctrl.sar_clk_gated = 0; + APB_SARADC.ctrl.xpd_sar_force = 2; } } -/** - * Get ADC module power management. - * - * @return - * - ADC power status. - */ -static inline adc_ll_power_t adc_ll_get_power_manage(void) +static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl) { - /* Bit1 0:Fsm 1: SW mode - Bit0 0:SW mode power down 1: SW mode power on */ - adc_ll_power_t manage; - if (APB_SARADC.ctrl.xpd_sar_force == 3) { - manage = ADC_POWER_SW_ON; - } else if (APB_SARADC.ctrl.xpd_sar_force == 2) { - manage = ADC_POWER_SW_OFF; - } else { - manage = ADC_POWER_BY_FSM; - } - return manage; + //Not used on ESP32H2 } /** @@ -688,7 +687,7 @@ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t par */ static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, bool en) { - // ESP32H2-TODO: IDF-3389 + abort(); } /*--------------------------------------------------------------- diff --git a/components/hal/esp32s2/adc_hal.c b/components/hal/esp32s2/adc_hal.c index d1196c61e3..e69de29bb2 100644 --- a/components/hal/esp32s2/adc_hal.c +++ b/components/hal/esp32s2/adc_hal.c @@ -1,123 +0,0 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// The HAL layer for ADC (ESP32-S2 specific part) - -#include "sdkconfig.h" -#include "hal/adc_hal.h" -#include "hal/adc_types.h" -#include "hal/adc_hal_conf.h" - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ -void adc_hal_digi_deinit(void) -{ - adc_ll_digi_trigger_disable(); // boss - adc_ll_digi_dma_disable(); - adc_ll_digi_clear_pattern_table(ADC_NUM_1); - adc_ll_digi_clear_pattern_table(ADC_NUM_2); - adc_ll_digi_filter_reset(ADC_NUM_1); - adc_ll_digi_filter_reset(ADC_NUM_2); - adc_ll_digi_reset(); - adc_ll_digi_controller_clk_disable(); -} - -void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) -{ - /* Single channel mode or multi channel mode. */ - adc_ll_digi_set_convert_mode(cfg->conv_mode); - if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) { - if (cfg->adc1_pattern_len) { - adc_ll_digi_clear_pattern_table(ADC_NUM_1); - adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len); - for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) { - adc_ll_digi_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]); - } - } - } - if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) { - if (cfg->adc2_pattern_len) { - adc_ll_digi_clear_pattern_table(ADC_NUM_2); - adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len); - for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) { - adc_ll_digi_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]); - } - } - } - if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) { - adc_ll_set_controller(ADC_NUM_1, ADC_CTRL_DIG); - } - if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) { - adc_ll_set_controller(ADC_NUM_2, ADC_CTRL_DIG); - } - adc_ll_digi_set_output_format(cfg->format); - if (cfg->conv_limit_en) { - adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num); - adc_ll_digi_convert_limit_enable(); - } else { - adc_ll_digi_convert_limit_disable(); - } - - adc_ll_digi_set_trigger_interval(cfg->interval); - adc_hal_digi_clk_config(&cfg->dig_clk); - adc_ll_digi_dma_set_eof_num(cfg->dma_eof_num); -} - -/** - * Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock. - * Enable clock and select clock source for ADC digital controller. - * Expression: controller_clk = (`APLL` or `APB`) / (div_num + div_a / div_b + 1). - * - * @note ADC and DAC digital controller share the same frequency divider. - * Please set a reasonable frequency division factor to meet the sampling frequency of the ADC and the output frequency of the DAC. - * - * @param clk Refer to ``adc_digi_clk_t``. - */ -void adc_hal_digi_clk_config(const adc_digi_clk_t *clk) -{ - adc_ll_digi_controller_clk_div(clk->div_num, clk->div_b, clk->div_a); - adc_ll_digi_controller_clk_enable(clk->use_apll); -} - -/** - * Enable digital controller to trigger the measurement. - */ -void adc_hal_digi_enable(void) -{ - adc_ll_digi_dma_enable(); - adc_ll_digi_trigger_enable(); -} - -/** - * Disable digital controller to trigger the measurement. - */ -void adc_hal_digi_disable(void) -{ - adc_ll_digi_trigger_disable(); - adc_ll_digi_dma_disable(); -} - -/** - * Config monitor of adc digital controller. - * - * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time. - * @param adc_n ADC unit. - * @param config Refer to ``adc_digi_monitor_t``. - */ -void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config) -{ - adc_ll_digi_monitor_set_mode(adc_n, config->mode); - adc_ll_digi_monitor_set_thres(adc_n, config->threshold); -} diff --git a/components/hal/esp32s2/dac_hal.c b/components/hal/esp32s2/dac_hal.c index 1e35b29ef6..473fd7f8ac 100644 --- a/components/hal/esp32s2/dac_hal.c +++ b/components/hal/esp32s2/dac_hal.c @@ -1,21 +1,13 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ // The HAL layer for ADC (esp32s2 specific part) #include "hal/dac_hal.h" -#include "hal/adc_hal.h" +#include "hal/adc_ll.h" #include "hal/dac_types.h" /*--------------------------------------------------------------- @@ -39,7 +31,8 @@ void dac_hal_digi_controller_config(const dac_digi_config_t *cfg) { dac_ll_digi_set_convert_mode(cfg->mode); dac_ll_digi_set_trigger_interval(cfg->interval); - adc_hal_digi_clk_config(&cfg->dig_clk); + adc_ll_digi_controller_clk_div(cfg->dig_clk.div_num, cfg->dig_clk.div_b, cfg->dig_clk.div_a); + adc_ll_digi_clk_sel(cfg->dig_clk.use_apll); } void dac_hal_digi_start(void) diff --git a/components/hal/esp32s2/include/hal/adc_hal.h b/components/hal/esp32s2/include/hal/adc_hal.h deleted file mode 100644 index a49618f07c..0000000000 --- a/components/hal/esp32s2/include/hal/adc_hal.h +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/******************************************************************************* - * NOTICE - * The hal is not public api, don't use in application code. - * See readme.md in hal/include/hal/readme.md - ******************************************************************************/ - -// The HAL layer for ADC (esp32s2 specific part) - -#pragma once - -#include "hal/adc_ll.h" -#include "hal/adc_types.h" - -#include_next "hal/adc_hal.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ -/** - * ADC Digital controller output data invert or not. - * - * @param adc_n ADC unit. - * @param inv_en data invert or not. - */ -#define adc_hal_digi_output_invert(adc_n, inv_en) adc_ll_digi_output_invert(adc_n, inv_en) - -/** - * Sets the number of interval clock cycles for the digital controller to trigger the measurement. - * Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``. - * - * @note The trigger interval should not be less than the sampling time of the SAR ADC. - * @param cycle The number of clock cycles for the trigger interval. The unit is the divided clock. Range: 40 ~ 4095. - */ -#define adc_hal_digi_set_trigger_interval(cycle) adc_ll_digi_set_trigger_interval(cycle) - -/** - * Enable digital controller to trigger the measurement. - */ -void adc_hal_digi_enable(void); - -/** - * Disable digital controller to trigger the measurement. - */ -void adc_hal_digi_disable(void); - -/** - * Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock. - * Enable clock and select clock source for ADC digital controller. - * Expression: controller_clk = (`APLL` or `APB`) / (div_num + div_a / div_b + 1). - * - * @note ADC and DAC digital controller share the same frequency divider. - * Please set a reasonable frequency division factor to meet the sampling frequency of the ADC and the output frequency of the DAC. - * - * @param clk Refer to ``adc_digi_clk_t``. - */ -void adc_hal_digi_clk_config(const adc_digi_clk_t *clk); - -/** - * Reset adc digital controller filter. - * - * @param adc_n ADC unit. - */ -#define adc_hal_digi_filter_reset(adc_n) adc_ll_digi_filter_reset(adc_n) - -/** - * Set adc digital controller filter factor. - * - * @param adc_n ADC unit. - * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). - */ -#define adc_hal_digi_filter_set_factor(adc_n, factor) adc_ll_digi_filter_set_factor(adc_n, factor) - -/** - * Get adc digital controller filter factor. - * - * @param adc_n ADC unit. - * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). - */ -#define adc_hal_digi_filter_get_factor(adc_n, factor) adc_ll_digi_filter_get_factor(adc_n, factor) - -/** - * Enable/disable adc digital controller filter. - * Filtering the ADC data to obtain smooth data at higher sampling rates. - * - * @note The filter will filter all the enabled channel data of the each ADC unit at the same time. - * @param adc_n ADC unit. - */ -#define adc_hal_digi_filter_enable(adc_n, enable) adc_ll_digi_filter_enable(adc_n, enable) - -/** - * Get the filtered data of adc digital controller filter. - * The data after each measurement and filtering is updated to the DMA by the digital controller. But it can also be obtained manually through this API. - * - * @note The filter will filter all the enabled channel data of the each ADC unit at the same time. - * @param adc_n ADC unit. - * @return Filtered data. - */ -#define adc_hal_digi_filter_read_data(adc_n) adc_ll_digi_filter_read_data(adc_n) - -/** - * Config monitor of adc digital controller. - * - * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time. - * @param adc_n ADC unit. - * @param config Refer to ``adc_digi_monitor_t``. - */ -void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config); - -/** - * Enable/disable monitor of adc digital controller. - * - * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time. - * @param adc_n ADC unit. - */ -#define adc_hal_digi_monitor_enable(adc_n, enable) adc_ll_digi_monitor_enable(adc_n, enable) - -/** - * Enable interrupt of adc digital controller by bitmask. - * - * @param adc_n ADC unit. - * @param intr Interrupt bitmask. - */ -#define adc_hal_digi_intr_enable(adc_n, intr) adc_ll_digi_intr_enable(adc_n, intr) - -/** - * Disable interrupt of adc digital controller by bitmask. - * - * @param adc_n ADC unit. - * @param intr Interrupt bitmask. - */ -#define adc_hal_digi_intr_disable(adc_n, intr) adc_ll_digi_intr_disable(adc_n, intr) - -/** - * Clear interrupt of adc digital controller by bitmask. - * - * @param adc_n ADC unit. - * @param intr Interrupt bitmask. - */ -#define adc_hal_digi_intr_clear(adc_n, intr) adc_ll_digi_intr_clear(adc_n, intr) - -/** - * Get interrupt status mask of adc digital controller. - * - * @param adc_n ADC unit. - * @return - * - intr Interrupt bitmask. - */ -#define adc_hal_digi_get_intr_status(adc_n) adc_ll_digi_get_intr_status(adc_n) - - -/** - * Set DMA eof num of adc digital controller. - * If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated. - * - * @param num eof num of DMA. - */ -#define adc_hal_digi_dma_set_eof_num(num) adc_ll_digi_dma_set_eof_num(num) - -/** - * Enable output data to DMA from adc digital controller. - */ -#define adc_hal_digi_dma_enable() adc_ll_digi_dma_enable() - -/** - * Disable output data to DMA from adc digital controller. - */ -#define adc_hal_digi_dma_disable() adc_ll_digi_dma_disable() - -/** - * Reset adc digital controller. - */ -#define adc_hal_digi_reset() adc_ll_digi_reset() - -/*--------------------------------------------------------------- - RTC controller setting ----------------------------------------------------------------*/ -/** - * Reset RTC controller FSM. - */ -#define adc_hal_rtc_reset() adc_ll_rtc_reset() - -#ifdef __cplusplus -} -#endif diff --git a/components/hal/esp32s2/include/hal/adc_ll.h b/components/hal/esp32s2/include/hal/adc_ll.h index a44f50915f..5e53ab2191 100644 --- a/components/hal/esp32s2/include/hal/adc_ll.h +++ b/components/hal/esp32s2/include/hal/adc_ll.h @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + #pragma once #include @@ -15,6 +21,11 @@ extern "C" { #endif +//To be checked if ESP32S2 has the 5M freq limit +#define ADC_LL_CLKM_DIV_NUM_DEFAULT 15 +#define ADC_LL_CLKM_DIV_B_DEFAULT 1 +#define ADC_LL_CLKM_DIV_A_DEFAULT 0 + typedef enum { ADC_NUM_1 = 0, /*!< SAR ADC 1 */ ADC_NUM_2 = 1, /*!< SAR ADC 2 */ @@ -35,6 +46,40 @@ typedef enum { ADC_RTC_DATA_FAIL = -1, } adc_ll_rtc_raw_data_t; +typedef enum { + ADC_LL_CTRL_RTC = 0, ///< For ADC1. Select RTC controller. + ADC_LL_CTRL_ULP = 1, ///< For ADC1 and ADC2. Select ULP controller. + ADC_LL_CTRL_DIG = 2, ///< For ADC1. Select DIG controller. + ADC_LL_CTRL_ARB = 3, ///< For ADC2. The controller is selected by the arbiter. +} adc_ll_controller_t; + +/** + * @brief ADC digital controller (DMA mode) work mode. + * + * @note The conversion mode affects the sampling frequency: + * SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once. + * SINGLE_UNIT_2: When the measurement is triggered, only ADC2 is sampled once. + * BOTH_UNIT : When the measurement is triggered, ADC1 and ADC2 are sampled at the same time. + * ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately. + */ +typedef enum { + ADC_LL_DIGI_CONV_ONLY_ADC1 = 0, // Only use ADC1 for conversion + ADC_LL_DIGI_CONV_ONLY_ADC2 = 1, // Only use ADC2 for conversion + ADC_LL_DIGI_CONV_BOTH_UNIT = 2, // Use Both ADC1 and ADC2 for conversion simultaneously + ADC_LL_DIGI_CONV_ALTER_UNIT = 3 // Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 ..... +} adc_ll_digi_convert_mode_t; + +typedef struct { + union { + struct { + uint8_t atten: 2; + uint8_t reserved: 2; + uint8_t channel: 4; + }; + uint8_t val; + }; +} __attribute__((packed)) adc_ll_digi_pattern_table_t; + /** * @brief Analyze whether the obtained raw data is correct. * ADC2 use arbiter by default. The arbitration result can be judged by the flag bit in the original data. @@ -53,24 +98,6 @@ typedef struct { }; } adc_ll_rtc_output_data_t; -/** - * @brief ADC controller type selection. - * - * @note For ADC2, use the force option with care. The system power consumption detection will use ADC2. - * If it is forced to switch to another controller, it may cause the system to obtain incorrect values. - * @note Normally, there is no need to switch the controller manually. - */ -typedef enum { - ADC_CTRL_RTC = 0, /*!> offset)); // clear old data tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data @@ -319,7 +342,7 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div * * @param use_apll true: use APLL clock; false: use APB clock. */ -static inline void adc_ll_digi_controller_clk_enable(bool use_apll) +static inline void adc_ll_digi_clk_sel(bool use_apll) { if (use_apll) { APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock @@ -483,112 +506,6 @@ static inline void adc_ll_digi_monitor_enable(adc_ll_num_t adc_n, bool enable) } } -/** - * Enable interrupt of adc digital controller by bitmask. - * - * @param adc_n ADC unit. - * @param intr Interrupt bitmask. - */ -static inline void adc_ll_digi_intr_enable(adc_ll_num_t adc_n, adc_digi_intr_t intr) -{ - if (adc_n == ADC_NUM_1) { - if (intr & ADC_DIGI_INTR_MASK_MONITOR) { - APB_SARADC.int_ena.adc1_thres = 1; - } - if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { - APB_SARADC.int_ena.adc1_done = 1; - } - } else { // adc_n == ADC_NUM_2 - if (intr & ADC_DIGI_INTR_MASK_MONITOR) { - APB_SARADC.int_ena.adc2_thres = 1; - } - if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { - APB_SARADC.int_ena.adc2_done = 1; - } - } -} - -/** - * Disable interrupt of adc digital controller by bitmask. - * - * @param adc_n ADC unit. - * @param intr Interrupt bitmask. - */ -static inline void adc_ll_digi_intr_disable(adc_ll_num_t adc_n, adc_digi_intr_t intr) -{ - if (adc_n == ADC_NUM_1) { - if (intr & ADC_DIGI_INTR_MASK_MONITOR) { - APB_SARADC.int_ena.adc1_thres = 0; - } - if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { - APB_SARADC.int_ena.adc1_done = 0; - } - } else { // adc_n == ADC_NUM_2 - if (intr & ADC_DIGI_INTR_MASK_MONITOR) { - APB_SARADC.int_ena.adc2_thres = 0; - } - if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { - APB_SARADC.int_ena.adc2_done = 0; - } - } -} - -/** - * Clear interrupt of adc digital controller by bitmask. - * - * @param adc_n ADC unit. - * @param intr Interrupt bitmask. - */ -static inline void adc_ll_digi_intr_clear(adc_ll_num_t adc_n, adc_digi_intr_t intr) -{ - if (adc_n == ADC_NUM_1) { - if (intr & ADC_DIGI_INTR_MASK_MONITOR) { - APB_SARADC.int_clr.adc1_thres = 1; - } - if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { - APB_SARADC.int_clr.adc1_done = 1; - } - } else { // adc_n == ADC_NUM_2 - if (intr & ADC_DIGI_INTR_MASK_MONITOR) { - APB_SARADC.int_clr.adc2_thres = 1; - } - if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) { - APB_SARADC.int_clr.adc2_done = 1; - } - } -} - -/** - * Get interrupt status mask of adc digital controller. - * - * @param adc_n ADC unit. - * @return - * - intr Interrupt bitmask. - */ -static inline uint32_t adc_ll_digi_get_intr_status(adc_ll_num_t adc_n) -{ - uint32_t int_st = APB_SARADC.int_st.val; - uint32_t ret_msk = 0; - - if (adc_n == ADC_NUM_1) { - if (int_st & APB_SARADC_ADC1_DONE_INT_ST_M) { - ret_msk |= ADC_DIGI_INTR_MASK_MEAS_DONE; - } - if (int_st & APB_SARADC_ADC1_THRES_INT_ST) { - ret_msk |= ADC_DIGI_INTR_MASK_MONITOR; - } - } else { // adc_n == ADC_NUM_2 - if (int_st & APB_SARADC_ADC2_DONE_INT_ST_M) { - ret_msk |= ADC_DIGI_INTR_MASK_MEAS_DONE; - } - if (int_st & APB_SARADC_ADC2_THRES_INT_ST_M) { - ret_msk |= ADC_DIGI_INTR_MASK_MONITOR; - } - } - - return ret_msk; -} - /** * Set DMA eof num of adc digital controller. * If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated. @@ -655,6 +572,20 @@ static inline uint32_t adc_ll_pwdet_get_cct(void) /*--------------------------------------------------------------- RTC controller setting ---------------------------------------------------------------*/ +/** + * ADC SAR clock division factor setting. ADC SAR clock devided from `RTC_FAST_CLK`. + * + * @param div Division factor. + */ +static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) +{ + if (adc_n == ADC_NUM_1) { + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader1_ctrl, sar1_clk_div, div); + } else { // adc_n == ADC_NUM_2 + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader2_ctrl, sar2_clk_div, div); + } +} + /** * Set adc output data format for RTC controller. * @@ -855,65 +786,6 @@ static inline adc_ll_rtc_raw_data_t adc_ll_rtc_analysis_raw_data(adc_ll_num_t ad } } -/*--------------------------------------------------------------- - Common setting ----------------------------------------------------------------*/ -/** - * Set ADC module power management. - * - * @param manage Set ADC power status. - */ -static inline void adc_ll_set_power_manage(adc_ll_power_t manage) -{ - /* Bit1 0:Fsm 1: SW mode - Bit0 0:SW mode power down 1: SW mode power on */ - if (manage == ADC_POWER_SW_ON) { - SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 1; - SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU; - } else if (manage == ADC_POWER_BY_FSM) { - SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 1; - SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM; - } else if (manage == ADC_POWER_SW_OFF) { - SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PD; - SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 0; - } -} - -/** - * Get ADC module power management. - * - * @return - * - ADC power status. - */ -static inline adc_ll_power_t adc_ll_get_power_manage(void) -{ - /* Bit1 0:Fsm 1: SW mode - Bit0 0:SW mode power down 1: SW mode power on */ - adc_ll_power_t manage; - if (SENS.sar_power_xpd_sar.force_xpd_sar == SENS_FORCE_XPD_SAR_PU) { - manage = ADC_POWER_SW_ON; - } else if (SENS.sar_power_xpd_sar.force_xpd_sar == SENS_FORCE_XPD_SAR_PD) { - manage = ADC_POWER_SW_OFF; - } else { - manage = ADC_POWER_BY_FSM; - } - return manage; -} - -/** - * ADC SAR clock division factor setting. ADC SAR clock devided from `RTC_FAST_CLK`. - * - * @param div Division factor. - */ -static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) -{ - if (adc_n == ADC_NUM_1) { - HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader1_ctrl, sar1_clk_div, div); - } else { // adc_n == ADC_NUM_2 - HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader2_ctrl, sar2_clk_div, div); - } -} - /** * Set the attenuation of a particular channel on ADCn. * @@ -972,6 +844,30 @@ static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t cha } } +/*--------------------------------------------------------------- + Common setting +---------------------------------------------------------------*/ +/** + * Set ADC module power management. + * + * @param manage Set ADC power status. + */ +static inline void adc_ll_set_power_manage(adc_ll_power_t manage) +{ + /* Bit1 0:Fsm 1: SW mode + Bit0 0:SW mode power down 1: SW mode power on */ + if (manage == ADC_POWER_SW_ON) { + SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 1; + SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU; + } else if (manage == ADC_POWER_BY_FSM) { + SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 1; + SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM; + } else if (manage == ADC_POWER_SW_OFF) { + SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PD; + SENS.sar_meas1_ctrl1.rtc_saradc_clkgate_en = 0; + } +} + /** * Set ADC module controller. * There are five SAR ADC controllers: @@ -985,18 +881,18 @@ static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t cha static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl) { if (adc_n == ADC_NUM_1) { - switch ( ctrl ) { - case ADC_CTRL_RTC: + switch (ctrl) { + case ADC_LL_CTRL_RTC: SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control. SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; break; - case ADC_CTRL_ULP: + case ADC_LL_CTRL_ULP: SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control. SENS.sar_meas1_ctrl2.meas1_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas1_ctrl2.sar1_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; break; - case ADC_CTRL_DIG: + case ADC_LL_CTRL_DIG: SENS.sar_meas1_mux.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control. SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; @@ -1005,23 +901,16 @@ static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t break; } } else { // adc_n == ADC_NUM_2 - switch ( ctrl ) { - case ADC_CTRL_RTC: + switch (ctrl) { + //If ADC2 is not controlled by ULP, the arbiter will decide which controller to use ADC2. + case ADC_LL_CTRL_ARB: SENS.sar_meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; break; - case ADC_CTRL_ULP: + case ADC_LL_CTRL_ULP: SENS.sar_meas2_ctrl2.meas2_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. SENS.sar_meas2_ctrl2.sar2_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; break; - case ADC_CTRL_DIG: - SENS.sar_meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. - SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; - break; - case ADC2_CTRL_PWDET: // currently only used by Wi-Fi - SENS.sar_meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. - SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; - break; default: break; } diff --git a/components/hal/esp32s2/include/hal/spi_ll.h b/components/hal/esp32s2/include/hal/spi_ll.h index b81b36c53b..d7ca9ea0ef 100644 --- a/components/hal/esp32s2/include/hal/spi_ll.h +++ b/components/hal/esp32s2/include/hal/spi_ll.h @@ -1,16 +1,8 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /******************************************************************************* * NOTICE @@ -1089,10 +1081,6 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) */ static inline void spi_dma_ll_rx_reset(spi_dma_dev_t *dma_in, uint32_t channel) { - //Reset RX DMA peripheral - dma_in->dma_in_link.dma_rx_ena = 0; - HAL_ASSERT(dma_in->dma_in_link.dma_rx_ena == 0); - dma_in->dma_conf.in_rst = 1; dma_in->dma_conf.in_rst = 0; } @@ -1110,6 +1098,17 @@ static inline void spi_dma_ll_rx_start(spi_dma_dev_t *dma_in, uint32_t channel, dma_in->dma_in_link.start = 1; } +/** + * Stop RX DMA. + * + * @param dma_in Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM. + * @param channel DMA channel, for chip version compatibility, not used. + */ +static inline void spi_dma_ll_rx_stop(spi_dma_dev_t *dma_in, uint32_t channel) +{ + dma_in->dma_in_link.stop = 1; +} + /** * Enable DMA RX channel burst for data * @@ -1173,6 +1172,17 @@ static inline void spi_dma_ll_tx_start(spi_dma_dev_t *dma_out, uint32_t channel, dma_out->dma_out_link.start = 1; } +/** + * Stop TX DMA. + * + * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral. + * @param channel DMA channel, for chip version compatibility, not used. + */ +static inline void spi_dma_ll_tx_stop(spi_dma_dev_t *dma_out, uint32_t channel) +{ + dma_out->dma_out_link.stop = 1; +} + /** * Enable DMA TX channel burst for data * @@ -1251,7 +1261,6 @@ static inline void spi_dma_ll_rx_disable(spi_dma_dev_t *dma_in) static inline void spi_dma_ll_tx_disable(spi_dma_dev_t *dma_out) { dma_out->dma_out_link.dma_tx_ena = 0; - dma_out->dma_out_link.stop = 1; } static inline bool spi_ll_tx_get_empty_err(spi_dev_t *hw) diff --git a/components/hal/esp32s3/include/hal/adc_ll.h b/components/hal/esp32s3/include/hal/adc_ll.h index 778e9d8d78..15e0b15de6 100644 --- a/components/hal/esp32s3/include/hal/adc_ll.h +++ b/components/hal/esp32s3/include/hal/adc_ll.h @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include @@ -55,12 +47,28 @@ typedef enum { } adc_ll_rtc_raw_data_t; typedef enum { - ADC_LL_CTRL_RTC = 0, ///< For ADC1. Select RTC controller. - ADC_LL_CTRL_ULP = 1, ///< For ADC1 and ADC2. Select ULP controller. - ADC_LL_CTRL_DIG = 2, ///< For ADC1. Select DIG controller. - ADC_LL_CTRL_ARB = 4, ///< For ADC2. The controller is selected by the arbiter. + ADC_LL_CTRL_RTC = 0, ///< For ADC1. Select RTC controller. + ADC_LL_CTRL_ULP = 1, ///< For ADC1 and ADC2. Select ULP controller. + ADC_LL_CTRL_DIG = 2, ///< For ADC1. Select DIG controller. + ADC_LL_CTRL_ARB = 3, ///< For ADC2. The controller is selected by the arbiter. } adc_ll_controller_t; +/** + * @brief ADC digital controller (DMA mode) work mode. + * + * @note The conversion mode affects the sampling frequency: + * SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once. + * SINGLE_UNIT_2: When the measurement is triggered, only ADC2 is sampled once. + * BOTH_UNIT : When the measurement is triggered, ADC1 and ADC2 are sampled at the same time. + * ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately. + */ +typedef enum { + ADC_LL_DIGI_CONV_ONLY_ADC1 = 0, // Only use ADC1 for conversion + ADC_LL_DIGI_CONV_ONLY_ADC2 = 1, // Only use ADC2 for conversion + ADC_LL_DIGI_CONV_BOTH_UNIT = 2, // Use Both ADC1 and ADC2 for conversion simultaneously + ADC_LL_DIGI_CONV_ALTER_UNIT = 3 // Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 ..... +} adc_ll_digi_convert_mode_t; + typedef struct { union { struct { @@ -84,8 +92,8 @@ typedef struct { typedef struct { union { struct { - uint16_t data: 12; /*! 0), The data is invalid. */ @@ -181,21 +189,19 @@ static inline void adc_ll_digi_convert_limit_disable(void) /** * Set adc conversion mode for digital controller. * - * @note ESP32 only support ADC1 single mode. - * * @param mode Conversion mode select. */ -static inline void adc_ll_digi_set_convert_mode(adc_digi_convert_mode_t mode) +static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode) { - if (mode == ADC_CONV_SINGLE_UNIT_1) { + if (mode == ADC_LL_DIGI_CONV_ONLY_ADC1) { APB_SARADC.ctrl.work_mode = 0; APB_SARADC.ctrl.sar_sel = 0; - } else if (mode == ADC_CONV_SINGLE_UNIT_2) { + } else if (mode == ADC_LL_DIGI_CONV_ONLY_ADC2) { APB_SARADC.ctrl.work_mode = 0; APB_SARADC.ctrl.sar_sel = 1; - } else if (mode == ADC_CONV_BOTH_UNIT) { + } else if (mode == ADC_LL_DIGI_CONV_BOTH_UNIT) { APB_SARADC.ctrl.work_mode = 1; - } else if (mode == ADC_CONV_ALTER_UNIT) { + } else if (mode == ADC_LL_DIGI_CONV_ALTER_UNIT) { APB_SARADC.ctrl.work_mode = 2; } APB_SARADC.ctrl.data_sar_sel = 1; @@ -229,9 +235,25 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_ * @param pattern_index Items index. Range: 0 ~ 11. * @param pattern Stored conversion rules. */ -static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t table) +static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pattern_index, adc_digi_pattern_config_t table) { - abort(); + uint32_t tab; + uint8_t index = pattern_index / 4; + uint8_t offset = (pattern_index % 4) * 6; + adc_ll_digi_pattern_table_t pattern = {0}; + + pattern.val = (table.atten & 0x3) | ((table.channel & 0xF) << 2); + if (table.unit == ADC_NUM_1){ + tab = APB_SARADC.sar1_patt_tab[index].sar1_patt_tab; //Read old register value + tab &= (~(0xFC0000 >> offset)); //Clear old data + tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; //Fill in the new data + APB_SARADC.sar1_patt_tab[index].sar1_patt_tab = tab; //Write back + } else { + tab = APB_SARADC.sar2_patt_tab[index].sar2_patt_tab; //Read old register value + tab &= (~(0xFC0000 >> offset)); //clear old data + tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; //Fill in the new data + APB_SARADC.sar2_patt_tab[index].sar2_patt_tab = tab; //Write back + } } /** @@ -325,7 +347,7 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div * * @param use_apll true: use APLL clock; false: use APB clock. */ -static inline void adc_ll_digi_controller_clk_enable(bool use_apll) +static inline void adc_ll_digi_clk_sel(bool use_apll) { if (use_apll) { APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock @@ -354,26 +376,13 @@ static inline void adc_ll_digi_filter_reset(adc_ll_num_t adc_n) abort(); } -/** - * Disable adc digital controller filter. - * Filtering the ADC data to obtain smooth data at higher sampling rates. - * - * @note If the channel info is not supported, the filter function will not be enabled. - * @param adc_n ADC unit. - */ -static inline void adc_ll_digi_filter_disable(adc_digi_filter_idx_t idx) -{ - abort(); -} - /** * Set adc digital controller filter factor. * - * @note If the channel info is not supported, the filter function will not be enabled. - * @param idx ADC filter unit. - * @param filter Filter config. Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). + * @param adc_n ADC unit. + * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). */ -static inline void adc_ll_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter) +static inline void adc_ll_digi_filter_set_factor(adc_ll_num_t adc_n, adc_digi_filter_mode_t factor) { abort(); } @@ -384,7 +393,19 @@ static inline void adc_ll_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_ * @param adc_n ADC unit. * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). */ -static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter) +static inline void adc_ll_digi_filter_get_factor(adc_ll_num_t adc_n, adc_digi_filter_mode_t *factor) +{ + abort(); +} + +/** + * Enable/disable adc digital controller filter. + * Filtering the ADC data to obtain smooth data at higher sampling rates. + * + * @note The filter will filter all the enabled channel data of the each ADC unit at the same time. + * @param adc_n ADC unit. + */ +static inline void adc_ll_digi_filter_enable(adc_ll_num_t adc_n, bool enable) { abort(); } @@ -410,23 +431,11 @@ static inline uint32_t adc_ll_digi_filter_read_data(adc_ll_num_t adc_n) * @param is_larger true: If ADC_OUT > threshold, Generates monitor interrupt. * false: If ADC_OUT < threshold, Generates monitor interrupt. */ -static inline void adc_ll_digi_monitor_set_mode(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *cfg) +static inline void adc_ll_digi_monitor_set_mode(adc_ll_num_t adc_n, bool is_larger) { abort(); } -/** - * Enable/disable monitor of adc digital controller. - * - * @note If the channel info is not supported, the monitor function will not be enabled. - * @param adc_n ADC unit. - */ -static inline void adc_ll_digi_monitor_disable(adc_digi_monitor_idx_t idx) -{ - abort(); -} - - /** * Set monitor threshold of adc digital controller. * @@ -513,30 +522,6 @@ static inline uint32_t adc_ll_pwdet_get_cct(void) return SENS.sar_meas2_mux.sar2_pwdet_cct; } -/** - * Analyze whether the obtained raw data is correct. - * ADC2 can use arbiter. The arbitration result is stored in the channel information of the returned data. - * - * @param adc_n ADC unit. - * @param raw_data ADC raw data input (convert value). - * @return - * - 0: The data is correct to use. - * - -1: The data is invalid. - */ -static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n, int raw_data) -{ - if (adc_n == ADC_NUM_1) { - return ADC_RTC_DATA_OK; - } - - //The raw data API returns value without channel information. Read value directly from the register - if (((APB_SARADC.apb_saradc2_data_status.adc2_data >> 12) & 0xF) > 9) { - return ADC_RTC_DATA_FAIL; - } - - return ADC_RTC_DATA_OK; -} - /*--------------------------------------------------------------- Common setting ---------------------------------------------------------------*/ @@ -547,21 +532,17 @@ static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n, */ static inline void adc_ll_set_power_manage(adc_ll_power_t manage) { + /* Bit1 0:Fsm 1: SW mode + Bit0 0:SW mode power down 1: SW mode power on */ if (manage == ADC_POWER_SW_ON) { SENS.sar_peri_clk_gate_conf.saradc_clk_en = 1; SENS.sar_power_xpd_sar.force_xpd_sar = 3; //SENS_FORCE_XPD_SAR_PU; - APB_SARADC.ctrl.sar_clk_gated = 1; - APB_SARADC.ctrl.xpd_sar_force = 3; } else if (manage == ADC_POWER_BY_FSM) { SENS.sar_peri_clk_gate_conf.saradc_clk_en = 1; SENS.sar_power_xpd_sar.force_xpd_sar = 0; //SENS_FORCE_XPD_SAR_FSM; - APB_SARADC.ctrl.sar_clk_gated = 1; - APB_SARADC.ctrl.xpd_sar_force = 0; } else if (manage == ADC_POWER_SW_OFF) { SENS.sar_power_xpd_sar.force_xpd_sar = 2; //SENS_FORCE_XPD_SAR_PD; SENS.sar_peri_clk_gate_conf.saradc_clk_en = 0; - APB_SARADC.ctrl.sar_clk_gated = 0; - APB_SARADC.ctrl.xpd_sar_force = 2; } } @@ -579,37 +560,37 @@ static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t { if (adc_n == ADC_NUM_1) { switch (ctrl) { - case ADC_LL_CTRL_RTC: - SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control. - SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. - SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; - break; - case ADC_LL_CTRL_ULP: - SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control. - SENS.sar_meas1_ctrl2.meas1_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. - SENS.sar_meas1_ctrl2.sar1_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; - break; - case ADC_LL_CTRL_DIG: - SENS.sar_meas1_mux.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control. - SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. - SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; - break; - default: - break; + case ADC_LL_CTRL_RTC: + SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control. + SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. + SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; + break; + case ADC_LL_CTRL_ULP: + SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control. + SENS.sar_meas1_ctrl2.meas1_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. + SENS.sar_meas1_ctrl2.sar1_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; + break; + case ADC_LL_CTRL_DIG: + SENS.sar_meas1_mux.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control. + SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. + SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; + break; + default: + break; } } else { // adc_n == ADC_NUM_2 //If ADC2 is not controlled by ULP, the arbiter will decide which controller to use ADC2. switch (ctrl) { - case ADC_LL_CTRL_ARB: - SENS.sar_meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. - SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; - break; - case ADC_LL_CTRL_ULP: - SENS.sar_meas2_ctrl2.meas2_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. - SENS.sar_meas2_ctrl2.sar2_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; - break; - default: - break; + case ADC_LL_CTRL_ARB: + SENS.sar_meas2_ctrl2.meas2_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. + SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; + break; + case ADC_LL_CTRL_ULP: + SENS.sar_meas2_ctrl2.meas2_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start. + SENS.sar_meas2_ctrl2.sar2_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map; + break; + default: + break; } } } @@ -725,7 +706,7 @@ static inline void adc_ll_calibration_init(adc_ll_num_t adc_n) * Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration. * * @param adc_n ADC index number. - * @param channel Not used + * @param channel Not used. * @param internal_gnd true: Disconnect from the IO port and use the internal GND as the calibration voltage. * false: Use IO external voltage as calibration voltage. */ diff --git a/components/hal/esp8684/adc_hal.c b/components/hal/esp8684/adc_hal.c deleted file mode 100644 index 2dc896bd81..0000000000 --- a/components/hal/esp8684/adc_hal.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -// The HAL layer for ADC (ESP-8684 specific part) - -#include -#include "soc/soc_caps.h" -#include "hal/adc_hal.h" -#include "hal/adc_types.h" -#include "soc/soc.h" - -//Currently we don't have context for the ADC HAL. So HAL variables are temporarily put here. But -//please don't follow this code. Create a context for your own HAL! - -static bool s_filter_enabled[SOC_ADC_DIGI_FILTER_NUM] = {}; -static adc_digi_filter_t s_filter[SOC_ADC_DIGI_FILTER_NUM] = {}; - -static bool s_monitor_enabled[SOC_ADC_DIGI_MONITOR_NUM] = {}; -static adc_digi_monitor_t s_monitor_config[SOC_ADC_DIGI_MONITOR_NUM] = {}; - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ -void adc_hal_digi_deinit(void) -{ - adc_ll_digi_trigger_disable(); // boss - adc_ll_digi_dma_disable(); - adc_ll_digi_clear_pattern_table(ADC_NUM_1); - adc_ll_digi_clear_pattern_table(ADC_NUM_2); - adc_ll_digi_filter_reset(ADC_NUM_1); - adc_ll_digi_filter_reset(ADC_NUM_2); - adc_ll_digi_reset(); - adc_ll_digi_controller_clk_disable(); -} - -/** - * - Set ADC digital controller clock division factor. The clock is divided from `APLL` or `APB` clock. - * Expression: controller_clk = APLL/APB * (div_num + div_a / div_b + 1). - * - Enable clock and select clock source for ADC digital controller. - */ -static void adc_hal_digi_clk_config(void) -{ - //Here we set the clock divider factor to make the digital clock to 5M Hz - adc_ll_digi_controller_clk_div(ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT); - adc_ll_digi_controller_clk_enable(0); -} - -void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) -{ - //only one pattern table is supported on C3, but LL still needs one argument. - const int pattern_both = 0; - - if (cfg->adc_pattern_len) { - adc_ll_digi_clear_pattern_table(pattern_both); - adc_ll_digi_set_pattern_table_len(pattern_both, cfg->adc_pattern_len); - for (uint32_t i = 0; i < cfg->adc_pattern_len; i++) { - adc_ll_digi_set_pattern_table(pattern_both, i, cfg->adc_pattern[i]); - } - } - - if (cfg->conv_limit_en) { - adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num); - adc_ll_digi_convert_limit_enable(); - } else { - adc_ll_digi_convert_limit_disable(); - } - - //clock - uint32_t interval = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1) / 2 / cfg->sample_freq_hz; - adc_ll_digi_set_trigger_interval(interval); - adc_hal_digi_clk_config(); -} - -static void filter_update(adc_digi_filter_idx_t idx) -{ - //ESP8684 has no enable bit, the filter will be enabled when the filter channel is configured - if (s_filter_enabled[idx]) { - adc_ll_digi_filter_set_factor(idx, &s_filter[idx]); - } else { - adc_ll_digi_filter_disable(idx); - } -} - -/** - * Set adc digital controller filter factor. - * - * @param idx ADC filter unit. - * @param filter Filter config. Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). - */ -void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter) -{ - s_filter[idx] = *filter; - filter_update(idx); -} - -/** - * Get adc digital controller filter factor. - * - * @param adc_n ADC unit. - * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). - */ -void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter) -{ - *filter = s_filter[idx]; -} - -void adc_hal_digi_filter_enable(adc_digi_filter_idx_t filter_idx, bool enable) -{ - s_filter_enabled[filter_idx] = enable; - filter_update(filter_idx); -} - -static void update_monitor(adc_digi_monitor_idx_t idx) -{ - //ESP8684 has no enable bit, the monitor will be enabled when the monitor channel is configured - if (s_monitor_enabled[idx]) { - adc_ll_digi_monitor_set_mode(idx, &s_monitor_config[idx]); - } else { - adc_ll_digi_monitor_disable(idx); - } -} - -void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config) -{ - s_monitor_config[idx] = *config; - update_monitor(idx); -} - -void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable) -{ - s_monitor_enabled[mon_idx] = enable; - update_monitor(mon_idx); -} diff --git a/components/hal/esp8684/include/hal/adc_hal.h b/components/hal/esp8684/include/hal/adc_hal.h deleted file mode 100644 index 02952c1e8e..0000000000 --- a/components/hal/esp8684/include/hal/adc_hal.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/******************************************************************************* - * NOTICE - * The hal is not public api, don't use in application code. - * See readme.md in soc/include/hal/readme.md - ******************************************************************************/ - -// The HAL layer for ADC (esp32s2 specific part) - -#pragma once - -#include "hal/adc_ll.h" -#include "hal/adc_types.h" - -#include_next "hal/adc_hal.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*--------------------------------------------------------------- - Digital controller setting ----------------------------------------------------------------*/ -/** - * Digital controller deinitialization. - */ -void adc_hal_digi_deinit(void); - -/** - * Setting the digital controller. - * - * @param cfg Pointer to digital controller paramter. - */ -void adc_hal_digi_controller_config(const adc_digi_config_t *cfg); - -/** - * Reset adc digital controller filter. - * - * @param filter_idx ADC filter unit. - */ -#define adc_hal_digi_filter_reset(filter_idx) adc_ll_digi_filter_reset(filter_idx) - -/** - * Set adc digital controller filter factor. - * - * @param filter_idx ADC filter unit. - * @param filter Filter config. Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). - */ -void adc_hal_digi_filter_set_factor(adc_digi_filter_idx_t filter_idx, adc_digi_filter_t *filter); - -/** - * Get adc digital controller filter factor. - * - * @param filter_idx ADC filter unit. - * @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64). - */ -void adc_hal_digi_filter_get_factor(adc_digi_filter_idx_t filter_idx, adc_digi_filter_t *filter); - -/** - * Enable/disable adc digital controller filter. - * Filtering the ADC data to obtain smooth data at higher sampling rates. - * - * @note The filter will filter all the enabled channel data of the each ADC unit at the same time. - * @param filter_idx ADC filter unit. - * @param enable True to enable the filter, otherwise disable. - */ -void adc_hal_digi_filter_enable(adc_digi_filter_idx_t filter_idx, bool enable); - -/** - * Config monitor of adc digital controller. - * - * @note If the channel info is not supported, the monitor function will not be enabled. - * @param mon_idx ADC monitor index. - * @param config Refer to `adc_digi_monitor_t`. - */ -void adc_hal_digi_monitor_config(adc_digi_monitor_idx_t mon_idx, adc_digi_monitor_t *config); - -/** - * Enable/disable monitor of adc digital controller. - * - * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time. - * @param mon_idx ADC monitor index. - * @param enable True to enable the monitor, otherwise disable. - */ -void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable); - -/*--------------------------------------------------------------- - Common setting ----------------------------------------------------------------*/ - -/** - * Config ADC2 module arbiter. - * The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority, - * the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data. - * - * @note Only ADC2 support arbiter. - * @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode. - * @note Default priority: Wi-Fi > RTC > Digital; - * - * @param config Refer to `adc_arbiter_t`. - */ -void adc_hal_arbiter_config(adc_arbiter_t *config); - -#ifdef __cplusplus -} -#endif diff --git a/components/hal/esp8684/include/hal/adc_ll.h b/components/hal/esp8684/include/hal/adc_ll.h index f624fe83ee..7421ec7a7b 100644 --- a/components/hal/esp8684/include/hal/adc_ll.h +++ b/components/hal/esp8684/include/hal/adc_ll.h @@ -11,11 +11,12 @@ #include "esp_attr.h" #include "soc/adc_periph.h" -#include "hal/adc_types.h" #include "soc/apb_saradc_struct.h" #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" +#include "hal/misc.h" +#include "hal/adc_types.h" #ifdef __cplusplus extern "C" { @@ -45,6 +46,22 @@ typedef enum { ADC_RTC_DATA_FAIL = -1, } adc_ll_rtc_raw_data_t; +typedef enum { + ADC_LL_CTRL_DIG = 0, ///< For ADC1. Select DIG controller. + ADC_LL_CTRL_ARB = 1, ///< For ADC2. The controller is selected by the arbiter. +} adc_ll_controller_t; + +/** + * @brief ADC digital controller (DMA mode) work mode. + * + * @note The conversion mode affects the sampling frequency: + * ESP8684 only support ALTER_UNIT mode + * ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately. + */ +typedef enum { + ADC_LL_DIGI_CONV_ALTER_UNIT = 0, // Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 ..... +} adc_ll_digi_convert_mode_t; + //These values should be set according to the HW typedef enum { ADC_LL_INTR_THRES1_LOW = BIT(26), @@ -56,21 +73,17 @@ typedef enum { } adc_ll_intr_t; FLAG_ATTR(adc_ll_intr_t) -/** - * @brief ADC controller type selection. - * - * @note For ADC2, use the force option with care. The system power consumption detection will use ADC2. - * If it is forced to switch to another controller, it may cause the system to obtain incorrect values. - * @note Normally, there is no need to switch the controller manually. - */ -typedef enum { - ADC_CTRL_RTC = 0, /*!> offset)); // Clear old data + // tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data + // APB_SARADC.sar_patt_tab[index].sar_patt_tab1 = tab; // Write back } /** @@ -176,7 +226,9 @@ static inline void adc_ll_digi_set_pattern_table(adc_ll_num_t adc_n, uint32_t pa */ static inline void adc_ll_digi_clear_pattern_table(adc_ll_num_t adc_n) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.ctrl.sar_patt_p_clear = 1; + // APB_SARADC.ctrl.sar_patt_p_clear = 0; } /** @@ -187,7 +239,8 @@ static inline void adc_ll_digi_clear_pattern_table(adc_ll_num_t adc_n) */ static inline void adc_ll_digi_set_arbiter_stable_cycle(uint32_t cycle) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.ctrl.wait_arb_cycle = cycle; } /** @@ -198,7 +251,12 @@ static inline void adc_ll_digi_set_arbiter_stable_cycle(uint32_t cycle) */ static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (adc_n == ADC_NUM_1) { + // APB_SARADC.ctrl2.sar1_inv = inv_en; // Enable / Disable ADC data invert + // } else { // adc_n == ADC_NUM_2 + // APB_SARADC.ctrl2.sar2_inv = inv_en; // Enable / Disable ADC data invert + // } } /** @@ -210,7 +268,8 @@ static inline void adc_ll_digi_output_invert(adc_ll_num_t adc_n, bool inv_en) */ static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.ctrl2.timer_target = cycle; } /** @@ -218,7 +277,8 @@ static inline void adc_ll_digi_set_trigger_interval(uint32_t cycle) */ static inline void adc_ll_digi_trigger_enable(void) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.ctrl2.timer_en = 1; } /** @@ -226,20 +286,24 @@ static inline void adc_ll_digi_trigger_enable(void) */ static inline void adc_ll_digi_trigger_disable(void) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.ctrl2.timer_en = 0; } /** * Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock. - * Expression: controller_clk = APLL/APB * (div_num + div_b / div_a). + * Expression: controller_clk = (APLL or APB) / (div_num + div_a / div_b + 1). * - * @param div_num Division factor. Range: 1 ~ 255. + * @param div_num Division factor. Range: 0 ~ 255. * @param div_b Division factor. Range: 1 ~ 63. * @param div_a Division factor. Range: 0 ~ 63. */ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.apb_adc_clkm_conf, clkm_div_num, div_num); + // APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b; + // APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a; } /** @@ -247,9 +311,15 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div * * @param use_apll true: use APLL clock; false: use APB clock. */ -static inline void adc_ll_digi_controller_clk_enable(bool use_apll) +static inline void adc_ll_digi_clk_sel(bool use_apll) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (use_apll) { + // APB_SARADC.apb_adc_clkm_conf.clk_sel = 1; // APLL clock + // } else { + // APB_SARADC.apb_adc_clkm_conf.clk_sel = 2; // APB clock + // } + // APB_SARADC.ctrl.sar_clk_gated = 1; } /** @@ -257,7 +327,8 @@ static inline void adc_ll_digi_controller_clk_enable(bool use_apll) */ static inline void adc_ll_digi_controller_clk_disable(void) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.ctrl.sar_clk_gated = 0; } /** @@ -267,7 +338,8 @@ static inline void adc_ll_digi_controller_clk_disable(void) */ static inline void adc_ll_digi_filter_reset(adc_ll_num_t adc_n) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.filter_ctrl0.filter_reset = 1; } /** @@ -279,7 +351,14 @@ static inline void adc_ll_digi_filter_reset(adc_ll_num_t adc_n) */ static inline void adc_ll_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (idx == ADC_DIGI_FILTER_IDX0) { + // APB_SARADC.filter_ctrl0.filter_channel0 = (filter->adc_unit << 3) | (filter->channel & 0x7); + // APB_SARADC.filter_ctrl1.filter_factor0 = filter->mode; + // } else if (idx == ADC_DIGI_FILTER_IDX1) { + // APB_SARADC.filter_ctrl0.filter_channel1 = (filter->adc_unit << 3) | (filter->channel & 0x7); + // APB_SARADC.filter_ctrl1.filter_factor1 = filter->mode; + // } } /** @@ -290,7 +369,16 @@ static inline void adc_ll_digi_filter_set_factor(adc_digi_filter_idx_t idx, adc_ */ static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_digi_filter_t *filter) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (idx == ADC_DIGI_FILTER_IDX0) { + // filter->adc_unit = (APB_SARADC.filter_ctrl0.filter_channel0 >> 3) & 0x1; + // filter->channel = APB_SARADC.filter_ctrl0.filter_channel0 & 0x7; + // filter->mode = APB_SARADC.filter_ctrl1.filter_factor0; + // } else if (idx == ADC_DIGI_FILTER_IDX1) { + // filter->adc_unit = (APB_SARADC.filter_ctrl0.filter_channel1 >> 3) & 0x1; + // filter->channel = APB_SARADC.filter_ctrl0.filter_channel1 & 0x7; + // filter->mode = APB_SARADC.filter_ctrl1.filter_factor1; + // } } /** @@ -302,7 +390,14 @@ static inline void adc_ll_digi_filter_get_factor(adc_digi_filter_idx_t idx, adc_ */ static inline void adc_ll_digi_filter_disable(adc_digi_filter_idx_t idx) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (idx == ADC_DIGI_FILTER_IDX0) { + // APB_SARADC.filter_ctrl0.filter_channel0 = 0xF; + // APB_SARADC.filter_ctrl1.filter_factor0 = 0; + // } else if (idx == ADC_DIGI_FILTER_IDX1) { + // APB_SARADC.filter_ctrl0.filter_channel1 = 0xF; + // APB_SARADC.filter_ctrl1.filter_factor1 = 0; + // } } /** @@ -315,7 +410,16 @@ static inline void adc_ll_digi_filter_disable(adc_digi_filter_idx_t idx) */ static inline void adc_ll_digi_monitor_set_mode(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *cfg) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (idx == ADC_DIGI_MONITOR_IDX0) { + // APB_SARADC.thres0_ctrl.thres0_channel = (cfg->adc_unit << 3) | (cfg->channel & 0x7); + // APB_SARADC.thres0_ctrl.thres0_high = cfg->h_threshold; + // APB_SARADC.thres0_ctrl.thres0_low = cfg->l_threshold; + // } else { // ADC_DIGI_MONITOR_IDX1 + // APB_SARADC.thres1_ctrl.thres1_channel = (cfg->adc_unit << 3) | (cfg->channel & 0x7); + // APB_SARADC.thres1_ctrl.thres1_high = cfg->h_threshold; + // APB_SARADC.thres1_ctrl.thres1_low = cfg->l_threshold; + // } } /** @@ -326,7 +430,12 @@ static inline void adc_ll_digi_monitor_set_mode(adc_digi_monitor_idx_t idx, adc_ */ static inline void adc_ll_digi_monitor_disable(adc_digi_monitor_idx_t idx) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (idx == ADC_DIGI_MONITOR_IDX0) { + // APB_SARADC.thres0_ctrl.thres0_channel = 0xF; + // } else { // ADC_DIGI_MONITOR_IDX1 + // APB_SARADC.thres1_ctrl.thres1_channel = 0xF; + // } } /** @@ -337,7 +446,8 @@ static inline void adc_ll_digi_monitor_disable(adc_digi_monitor_idx_t idx) */ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num); } /** @@ -345,7 +455,8 @@ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) */ static inline void adc_ll_digi_dma_enable(void) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.dma_conf.apb_adc_trans = 1; } /** @@ -353,7 +464,8 @@ static inline void adc_ll_digi_dma_enable(void) */ static inline void adc_ll_digi_dma_disable(void) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.dma_conf.apb_adc_trans = 0; } /** @@ -361,7 +473,9 @@ static inline void adc_ll_digi_dma_disable(void) */ static inline void adc_ll_digi_reset(void) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.dma_conf.apb_adc_reset_fsm = 1; + // APB_SARADC.dma_conf.apb_adc_reset_fsm = 0; } /*--------------------------------------------------------------- @@ -375,7 +489,9 @@ static inline void adc_ll_digi_reset(void) */ static inline void adc_ll_pwdet_set_cct(uint32_t cct) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // /* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */ + // RTCCNTL.sensor_ctrl.sar2_pwdet_cct = cct; } /** @@ -386,8 +502,9 @@ static inline void adc_ll_pwdet_set_cct(uint32_t cct) */ static inline uint32_t adc_ll_pwdet_get_cct(void) { - // TODO: IDF-3901. - abort(); + abort(); //TODO IDF-3908 + // /* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */ + // return RTCCNTL.sensor_ctrl.sar2_pwdet_cct; } /** @@ -402,8 +519,17 @@ static inline uint32_t adc_ll_pwdet_get_cct(void) */ static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n, int raw_data) { - // TODO: IDF-3901. - abort(); + abort(); //TODO IDF-3908 + // if (adc_n == ADC_NUM_1) { + // return ADC_RTC_DATA_OK; + // } + + // //The raw data API returns value without channel information. Read value directly from the register + // if (((APB_SARADC.apb_saradc2_data_status.adc2_data >> 13) & 0xF) > 9) { + // return ADC_RTC_DATA_FAIL; + // } + + // return ADC_RTC_DATA_OK; } /*--------------------------------------------------------------- @@ -416,18 +542,24 @@ static inline adc_ll_rtc_raw_data_t adc_ll_analysis_raw_data(adc_ll_num_t adc_n, */ static inline void adc_ll_set_power_manage(adc_ll_power_t manage) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // /* Bit1 0:Fsm 1: SW mode + // Bit0 0:SW mode power down 1: SW mode power on */ + // if (manage == ADC_POWER_SW_ON) { + // APB_SARADC.ctrl.sar_clk_gated = 1; + // APB_SARADC.ctrl.xpd_sar_force = 3; + // } else if (manage == ADC_POWER_BY_FSM) { + // APB_SARADC.ctrl.sar_clk_gated = 1; + // APB_SARADC.ctrl.xpd_sar_force = 0; + // } else if (manage == ADC_POWER_SW_OFF) { + // APB_SARADC.ctrl.sar_clk_gated = 0; + // APB_SARADC.ctrl.xpd_sar_force = 2; + // } } -/** - * Get ADC module power management. - * - * @return - * - ADC power status. - */ -static inline adc_ll_power_t adc_ll_get_power_manage(void) +static inline void adc_ll_set_controller(adc_ll_num_t adc_n, adc_ll_controller_t ctrl) { - abort();// TODO: IDF-3901. + //Not used on ESP8684 } /** @@ -442,7 +574,16 @@ static inline adc_ll_power_t adc_ll_get_power_manage(void) */ static inline void adc_ll_set_arbiter_work_mode(adc_arbiter_mode_t mode) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (mode == ADC_ARB_MODE_FIX) { + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_grant_force = 0; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_fix_priority = 1; + // } else if (mode == ADC_ARB_MODE_LOOP) { + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_grant_force = 0; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_fix_priority = 0; + // } else { + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_grant_force = 1; // Shield arbiter. + // } } /** @@ -460,7 +601,34 @@ static inline void adc_ll_set_arbiter_work_mode(adc_arbiter_mode_t mode) */ static inline void adc_ll_set_arbiter_priority(uint8_t pri_rtc, uint8_t pri_dig, uint8_t pri_pwdet) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (pri_rtc != pri_dig && pri_rtc != pri_pwdet && pri_dig != pri_pwdet) { + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_priority = pri_rtc; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_priority = pri_dig; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_priority = pri_pwdet; + // } + // /* Should select highest priority controller. */ + // if (pri_rtc > pri_dig) { + // if (pri_rtc > pri_pwdet) { + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 0; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 1; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 0; + // } else { + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 0; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 0; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 1; + // } + // } else { + // if (pri_dig > pri_pwdet) { + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 1; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 0; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 0; + // } else { + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_apb_force = 0; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_rtc_force = 0; + // APB_SARADC.apb_adc_arb_ctrl.adc_arb_wifi_force = 1; + // } + // } } /* ADC calibration code. */ @@ -469,7 +637,12 @@ static inline void adc_ll_set_arbiter_priority(uint8_t pri_rtc, uint8_t pri_dig, */ static inline void adc_ll_calibration_init(adc_ll_num_t adc_n) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (adc_n == ADC_NUM_1) { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 1); + // } else { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 1); + // } } /** @@ -484,7 +657,21 @@ static inline void adc_ll_calibration_init(adc_ll_num_t adc_n) */ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t channel, bool internal_gnd) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // /* Enable/disable internal connect GND (for calibration). */ + // if (adc_n == ADC_NUM_1) { + // if (internal_gnd) { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 1); + // } else { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0); + // } + // } else { + // if (internal_gnd) { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 1); + // } else { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 0); + // } + // } } /** @@ -494,7 +681,12 @@ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t */ static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (adc_n == ADC_NUM_1) { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0); + // } else { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 0); + // } } /** @@ -506,7 +698,16 @@ static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n) */ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t param) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // uint8_t msb = param >> 8; + // uint8_t lsb = param & 0xFF; + // if (adc_n == ADC_NUM_1) { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, msb); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, lsb); + // } else { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, msb); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, lsb); + // } } /* Temp code end. */ @@ -523,7 +724,46 @@ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t par */ static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, bool en) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (en) { + // REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 3); + // SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); + + // REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_SEL, 2); + // SET_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN); + // SET_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_GRANT_FORCE); + // SET_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_APB_FORCE); + // APB_SARADC.sar_patt_tab[0].sar_patt_tab1 = 0xFFFFFF; + // APB_SARADC.sar_patt_tab[1].sar_patt_tab1 = 0xFFFFFF; + // APB_SARADC.onetime_sample.adc1_onetime_sample = 1; + // APB_SARADC.onetime_sample.onetime_channel = channel; + // SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU); + // if (adc == ADC_NUM_1) { + // /* Config test mux to route v_ref to ADC1 Channels */ + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 1); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 1); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 0); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 1); + // } else { + // /* Config test mux to route v_ref to ADC2 Channels */ + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 1); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_TSENS_ADDR, 0); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0); + // } + // } else { + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 0); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0); + // REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0); + // APB_SARADC.onetime_sample.adc1_onetime_sample = 0; + // APB_SARADC.onetime_sample.onetime_channel = 0xf; + // REG_SET_FIELD(RTC_CNTL_SENSOR_CTRL_REG, RTC_CNTL_FORCE_XPD_SAR, 0); + // REG_SET_FIELD(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_SEL, 0); + // CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_CLKM_CONF_REG, APB_SARADC_CLK_EN); + // CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_GRANT_FORCE); + // CLEAR_PERI_REG_MASK(APB_SARADC_APB_ADC_ARB_CTRL_REG, APB_SARADC_ADC_ARB_APB_FORCE); + // } } /*--------------------------------------------------------------- @@ -538,57 +778,74 @@ static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, b */ static inline void adc_ll_onetime_start(bool val) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.onetime_sample.onetime_start = val; } static inline void adc_ll_onetime_set_channel(adc_ll_num_t unit, adc_channel_t channel) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.onetime_sample.onetime_channel = ((unit << 3) | channel); } static inline void adc_ll_onetime_set_atten(adc_atten_t atten) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.onetime_sample.onetime_atten = atten; } static inline void adc_ll_intr_enable(adc_ll_intr_t mask) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.int_ena.val |= mask; } static inline void adc_ll_intr_disable(adc_ll_intr_t mask) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.int_ena.val &= ~mask; } static inline void adc_ll_intr_clear(adc_ll_intr_t mask) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // APB_SARADC.int_clr.val |= mask; } static inline bool adc_ll_intr_get_raw(adc_ll_intr_t mask) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // return (APB_SARADC.int_raw.val & mask); } static inline bool adc_ll_intr_get_status(adc_ll_intr_t mask) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // return (APB_SARADC.int_st.val & mask); } static inline void adc_ll_onetime_sample_enable(adc_ll_num_t adc_n, bool enable) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // if (adc_n == ADC_NUM_1) { + // APB_SARADC.onetime_sample.adc1_onetime_sample = enable; + // } else { + // APB_SARADC.onetime_sample.adc2_onetime_sample = enable; + // } } static inline uint32_t adc_ll_adc1_read(void) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // //On ESP8684, valid data width is 12-bit + // return (APB_SARADC.apb_saradc1_data_status.adc1_data & 0xfff); } static inline uint32_t adc_ll_adc2_read(void) { - abort();// TODO: IDF-3901. + abort(); //TODO IDF-3908 + // //On ESP8684, valid data width is 12-bit + // return (APB_SARADC.apb_saradc2_data_status.adc2_data & 0xfff); } #ifdef __cplusplus diff --git a/components/hal/include/hal/adc_hal.h b/components/hal/include/hal/adc_hal.h index 175ea91263..b8455e27ec 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -1,21 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + #pragma once +#include "esp_err.h" #include "soc/soc_caps.h" +#include "hal/dma_types.h" #include "hal/adc_types.h" #include "hal/adc_ll.h" #include "esp_err.h" -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 +#if SOC_GDMA_SUPPORTED #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" +#endif + +#if CONFIG_IDF_TARGET_ESP32S2 +//ADC utilises SPI3 DMA on ESP32S2 +#include "hal/spi_ll.h" +#endif + +#if CONFIG_IDF_TARGET_ESP32 +//ADC utilises I2S0 DMA on ESP32 +#include "hal/i2s_ll.h" +#endif + +#if SOC_GDMA_SUPPORTED +#define ADC_HAL_DMA_INTR_MASK GDMA_LL_EVENT_RX_SUC_EOF +#elif CONFIG_IDF_TARGET_ESP32S2 +#define ADC_HAL_DMA_INTR_MASK SPI_LL_INTR_IN_SUC_EOF +#else //CONFIG_IDF_TARGET_ESP32 +#define ADC_HAL_DMA_INTR_MASK BIT(9) +#endif //For ADC module, each conversion contains 4 bytes #define ADC_HAL_DATA_LEN_PER_CONV 4 +typedef enum adc_hal_work_mode_t { + ADC_HAL_ULP_MODE, + ADC_HAL_SINGLE_READ_MODE, + ADC_HAL_CONTINUOUS_READ_MODE, + ADC_HAL_PWDET_MODE +} adc_hal_work_mode_t; + /** * @brief Enum for DMA descriptor status */ @@ -29,6 +59,7 @@ typedef enum adc_hal_dma_desc_status_t { * @brief Configuration of the HAL */ typedef struct adc_hal_config_t { + void *dev; ///< DMA peripheral address 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 @@ -42,25 +73,30 @@ typedef struct adc_hal_context_t { 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*/ + void *dev; ///< DMA address uint32_t desc_max_num; ///< Number of the descriptors linked once uint32_t dma_chan; ///< DMA channel to be used uint32_t eof_num; ///< Words between 2 in_suc_eof interrupts } adc_hal_context_t; -#endif + +typedef struct adc_hal_digi_ctrlr_cfg_t { + bool conv_limit_en; //1: adc conversion will stop when `conv_limit_num` reaches. 0: won't stop. NOTE: esp32 should always be set to 1. + uint32_t conv_limit_num; //see `conv_limit_en` + uint32_t adc_pattern_len; //total pattern item number, including ADC1 and ADC2 + adc_digi_pattern_config_t *adc_pattern; //pattern item + uint32_t sample_freq_hz; //ADC sample frequency + adc_digi_convert_mode_t conv_mode; //controller work mode + uint32_t bit_width; //output data width +} adc_hal_digi_ctrlr_cfg_t; + /*--------------------------------------------------------------- Common setting ---------------------------------------------------------------*/ -/** - * ADC module initialization. - */ -void adc_hal_init(void); - /** * Set ADC module power management. * @@ -68,51 +104,7 @@ void adc_hal_init(void); */ #define adc_hal_set_power_manage(manage) adc_ll_set_power_manage(manage) -/** - * ADC module clock division factor setting. ADC clock devided from APB clock. - * - * @prarm div Division factor. - */ -#define adc_hal_digi_set_clk_div(div) adc_ll_digi_set_clk_div(div) - -#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684 -/** - * ADC SAR clock division factor setting. ADC SAR clock devided from `RTC_FAST_CLK`. - * - * @prarm div Division factor. - */ -#define adc_hal_set_sar_clk_div(adc_n, div) adc_ll_set_sar_clk_div(adc_n, div) - -/** - * Set ADC module controller. - * There are five SAR ADC controllers: - * Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes; - * Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep; - * the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2. - * - * @prarm adc_n ADC unit. - * @prarm ctrl ADC controller. - */ -#define adc_hal_set_controller(adc_n, ctrl) adc_ll_set_controller(adc_n, ctrl) -#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684 - -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 -/** - * Get the attenuation of a particular channel on ADCn. - * - * @param adc_n ADC unit. - * @param channel ADCn channel number. - * @return atten The attenuation option. - */ -#define adc_hal_get_atten(adc_n, channel) adc_ll_get_atten(adc_n, channel) -#endif - -#if CONFIG_IDF_TARGET_ESP32 -/** - * Close ADC AMP module if don't use it for power save. - */ -#define adc_hal_amp_disable() adc_ll_amp_disable() -#endif +void adc_hal_set_controller(adc_ll_num_t unit, adc_hal_work_mode_t work_mode); #if SOC_ADC_ARBITER_SUPPORTED //No ADC2 controller arbiter on ESP32 @@ -133,7 +125,6 @@ void adc_hal_arbiter_config(adc_arbiter_t *config); /*--------------------------------------------------------------- PWDET(Power detect) controller setting ---------------------------------------------------------------*/ - /** * Set adc cct for PWDET controller. * @@ -150,26 +141,6 @@ void adc_hal_arbiter_config(adc_arbiter_t *config); */ #define adc_hal_pwdet_get_cct() adc_ll_pwdet_get_cct() -/*--------------------------------------------------------------- - RTC controller setting ----------------------------------------------------------------*/ -#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684 -/** - * Set adc output data format for RTC controller. - * - * @prarm adc_n ADC unit. - * @prarm bits Output data bits width option. - */ -#define adc_hal_rtc_set_output_format(adc_n, bits) adc_ll_rtc_set_output_format(adc_n, bits) - -/** - * ADC module output data invert or not. - * - * @prarm adc_n ADC unit. - */ -#define adc_hal_rtc_output_invert(adc_n, inv_en) adc_ll_rtc_output_invert(adc_n, inv_en) -#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684 - /** * Enable/disable the output of ADCn's internal reference voltage to one of ADC2's channels. * @@ -188,28 +159,108 @@ void adc_hal_arbiter_config(adc_arbiter_t *config); Digital controller setting ---------------------------------------------------------------*/ /** - * Digital controller deinitialization. + * ADC module initialization. */ -void adc_hal_digi_deinit(void); +void adc_hal_init(void); + +/** + * Digital controller deinitialization. + * + * @param hal Context of the HAL + */ +void adc_hal_digi_deinit(adc_hal_context_t *hal); + +/** + * @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); + +/** + * @brief Initialize the HW + * + * @param hal Context of the HAL + */ +void adc_hal_digi_init(adc_hal_context_t *hal); /** * Setting the digital controller. * - * @param cfg Pointer to digital controller paramter. + * @param hal Context of the HAL + * @param cfg Pointer to digital controller paramter. */ -void adc_hal_digi_controller_config(const adc_digi_config_t *cfg); +void adc_hal_digi_controller_config(adc_hal_context_t *hal, const adc_hal_digi_ctrlr_cfg_t *cfg); /** - * Reset the pattern table pointer, then take the measurement rule from table header in next measurement. + * @brief Start Conversion * - * @param adc_n ADC unit. + * @param hal Context of the HAL + * @param data_buf Pointer to the data buffer, the length should be multiple of ``desc_max_num`` and ``eof_num`` in ``adc_hal_context_t`` */ -#define adc_hal_digi_clear_pattern_table(adc_n) adc_ll_digi_clear_pattern_table(adc_n) +void adc_hal_digi_start(adc_hal_context_t *hal, uint8_t *data_buf); + +#if !SOC_GDMA_SUPPORTED +/** + * @brief Get the DMA descriptor that Hardware has finished processing. + * + * @param hal Context of the HAL + * + * @return DMA descriptor address + */ +intptr_t adc_hal_get_desc_addr(adc_hal_context_t *hal); + +/** + * @brief Check the hardware interrupt event + * + * @param hal Context of the HAL + * @param mask Event mask + * + * @return True: the event is triggered. False: the event is not triggered yet. + */ +bool adc_hal_check_event(adc_hal_context_t *hal, uint32_t mask); +#endif + +/** + * @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); + +/** + * @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); + +/** + * @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); + +/** + * @brief Stop conversion + * + * @param hal Context of the HAL + */ +void adc_hal_digi_stop(adc_hal_context_t *hal); + /*--------------------------------------------------------------- ADC Single Read ---------------------------------------------------------------*/ -#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP8684 +#if SOC_ADC_RTC_CTRL_SUPPORTED /** * Set the attenuation of a particular channel on ADCn. * @@ -245,7 +296,7 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg); */ #define adc_hal_set_atten(adc_n, channel, atten) adc_ll_set_atten(adc_n, channel, atten) -#else // CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 +#else // #if !SOC_ADC_RTC_CTRL_SUPPORTED /** * Set the attenuation for ADC to single read * @@ -256,7 +307,7 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg); * @param atten ADC attenuation. See ``adc_atten_t`` */ #define adc_hal_set_atten(adc_n, channel, atten) adc_ll_onetime_set_atten(atten) -#endif +#endif //#if SOC_ADC_RTC_CTRL_SUPPORTED /** * Start an ADC conversion and get the converted value. @@ -277,7 +328,6 @@ esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw); ADC calibration setting ---------------------------------------------------------------*/ #if SOC_ADC_CALIBRATION_V1_SUPPORTED -// ESP32-S2, C3 and H2 support HW offset calibration. /** * @brief Initialize default parameter for the calibration block. @@ -314,86 +364,21 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc #endif //SOC_ADC_CALIBRATION_V1_SUPPORTED -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 + /*--------------------------------------------------------------- - DMA setting + RTC controller setting ---------------------------------------------------------------*/ /** - * @brief Initialize the hal context + * Set adc output data format for RTC controller. * - * @param hal Context of the HAL - * @param config Configuration of the HAL + * @prarm adc_n ADC unit. + * @prarm bits Output data bits width option. */ -void adc_hal_context_config(adc_hal_context_t *hal, const adc_hal_config_t *config); +#define adc_hal_rtc_set_output_format(adc_n, bits) adc_ll_rtc_set_output_format(adc_n, bits) /** - * @brief Initialize the HW + * ADC module output data invert or not. * - * @param hal Context of the HAL + * @prarm adc_n ADC unit. */ -void adc_hal_digi_init(adc_hal_context_t *hal); - -/** - * @brief Reset ADC / DMA fifo - * - * @param hal Context of the HAL - */ -void adc_hal_fifo_reset(adc_hal_context_t *hal); - -/** - * @brief Start DMA - * - * @param hal Context of the HAL - * @param data_buf Pointer to the data buffer, the length should be multiple of ``desc_max_num`` and ``eof_num`` in ``adc_hal_context_t`` - */ -void adc_hal_digi_rxdma_start(adc_hal_context_t *hal, uint8_t *data_buf); - -/** - * @brief Start ADC - * - * @param hal Context of the HAL - */ -void adc_hal_digi_start(adc_hal_context_t *hal); - -/** - * @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); - -/** - * @brief Stop DMA - * - * @param hal Context of the HAL - */ -void adc_hal_digi_rxdma_stop(adc_hal_context_t *hal); - -/** - * @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); - -/** - * @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); - -/** - * @brief Stop ADC - * - * @param hal Context of the HAL - */ -void adc_hal_digi_stop(adc_hal_context_t *hal); - -#endif //#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 +#define adc_hal_rtc_output_invert(adc_n, inv_en) adc_ll_rtc_output_invert(adc_n, inv_en) diff --git a/components/hal/include/hal/adc_types.h b/components/hal/include/hal/adc_types.h index 10155852ed..d2779f0354 100644 --- a/components/hal/include/hal/adc_types.h +++ b/components/hal/include/hal/adc_types.h @@ -54,26 +54,9 @@ typedef enum { ADC_ATTEN_MAX, } adc_atten_t; -#ifdef CONFIG_IDF_TARGET_ESP32 -/** - * @brief ESP32 ADC DMA source selection. - */ -#else -/** - * @brief ESP32 ADC DMA source selection. - * - * @deprecated Not applicable on ESP32-S2 because ESP32-S2 doesn't use I2S DMA. - */ -#endif -typedef enum { - ADC_I2S_DATA_SRC_IO_SIG = 0, /*!< I2S data from GPIO matrix signal */ - ADC_I2S_DATA_SRC_ADC = 1, /*!< I2S data from ADC */ - ADC_I2S_DATA_SRC_MAX, -} adc_i2s_source_t; - /** * @brief ADC resolution setting option. - * + * @note Only used in single read mode */ typedef enum { #if CONFIG_IDF_TARGET_ESP32 @@ -89,82 +72,56 @@ typedef enum { ADC_WIDTH_MAX, } adc_bits_width_t; - /** * @brief ADC digital controller (DMA mode) work mode. - * - * @note The conversion mode affects the sampling frequency: - * SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once. - * SINGLE_UNIT_2: When the measurement is triggered, only ADC2 is sampled once. - * BOTH_UNIT : When the measurement is triggered, ADC1 and ADC2 are sampled at the same time. - * ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately. */ typedef enum { - ADC_CONV_SINGLE_UNIT_1 = 1, /*!< SAR ADC 1. */ - ADC_CONV_SINGLE_UNIT_2 = 2, /*!< SAR ADC 2. */ - ADC_CONV_BOTH_UNIT = 3, /*!< SAR ADC 1 and 2. */ - ADC_CONV_ALTER_UNIT = 7, /*!< SAR ADC 1 and 2 alternative mode. */ + ADC_CONV_SINGLE_UNIT_1 = 1, ///< Only use ADC1 for conversion + ADC_CONV_SINGLE_UNIT_2 = 2, ///< Only use ADC2 for conversion + ADC_CONV_BOTH_UNIT = 3, ///< Use Both ADC1 and ADC2 for conversion simultaneously + ADC_CONV_ALTER_UNIT = 7, ///< Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 ..... ADC_CONV_UNIT_MAX, } adc_digi_convert_mode_t; -/** - * @brief ADC digital controller (DMA mode) conversion rules setting. - */ -typedef struct { - union { - struct { - uint8_t atten: 2; /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements. - 0: measurement range 0 - 800mV, - 1: measurement range 0 - 1100mV, - 2: measurement range 0 - 1350mV, - 3: measurement range 0 - 2600mV. */ -#if CONFIG_IDF_TARGET_ESP32 - uint8_t bit_width: 2; /*!< ADC resolution. -- 0: 9 bit; -- 1: 10 bit; -- 2: 11 bit; -- 3: 12 bit. */ - int8_t channel: 4; /*!< ADC channel index. */ -#elif CONFIG_IDF_TARGET_ESP32S2 - uint8_t reserved: 2; /*!< reserved0 */ - uint8_t channel: 4; /*!< ADC channel index. */ -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 - uint8_t channel: 3; /*!< ADC channel index. */ - uint8_t unit: 1; /*!< ADC unit index. */ - uint8_t reserved: 2; /*!< reserved0 */ -#endif - }; - uint8_t val; /*! ADC_CHANNEL_MAX), The data is invalid. */ - } type1; /*! ADC_CHANNEL_MAX), The data is invalid. */ + uint32_t unit: 1; /*! +#include +#include "sdkconfig.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "driver/adc.h" + +#define TIMES 256 +#define GET_UNIT(x) ((x>>3) & 0x1) + +#if CONFIG_IDF_TARGET_ESP32 +#define ADC_RESULT_BYTE 2 +#define ADC_CONV_LIMIT_EN 1 //For ESP32, this should always be set to 1 +#define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1 //ESP32 only supports ADC1 DMA mode +#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1 +#elif CONFIG_IDF_TARGET_ESP32S2 +#define ADC_RESULT_BYTE 2 +#define ADC_CONV_LIMIT_EN 0 +#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT +#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 +#define ADC_RESULT_BYTE 4 +#define ADC_CONV_LIMIT_EN 0 +#define ADC_CONV_MODE ADC_CONV_ALTER_UNIT //ESP32C3 only supports alter mode +#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 +#elif CONFIG_IDF_TARGET_ESP32S3 +#define ADC_RESULT_BYTE 4 +#define ADC_CONV_LIMIT_EN 0 +#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT +#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 +#endif + +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684 +static uint16_t adc1_chan_mask = BIT(2) | BIT(3); +static uint16_t adc2_chan_mask = BIT(0); +static adc_channel_t channel[3] = {ADC1_CHANNEL_2, ADC1_CHANNEL_3, (ADC2_CHANNEL_0 | 1 << 3)}; +#endif +#if CONFIG_IDF_TARGET_ESP32S2 +static uint16_t adc1_chan_mask = BIT(2) | BIT(3); +static uint16_t adc2_chan_mask = BIT(0); +static adc_channel_t channel[3] = {ADC1_CHANNEL_2, ADC1_CHANNEL_3, (ADC2_CHANNEL_0 | 1 << 3)}; +#endif +#if CONFIG_IDF_TARGET_ESP32 +static uint16_t adc1_chan_mask = BIT(7); +static uint16_t adc2_chan_mask = 0; +static adc_channel_t channel[1] = {ADC1_CHANNEL_7}; +#endif + +static const char *TAG = "ADC DMA"; + +static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num) +{ + adc_digi_init_config_t adc_dma_config = { + .max_store_buf_size = 1024, + .conv_num_each_intr = TIMES, + .adc1_chan_mask = adc1_chan_mask, + .adc2_chan_mask = adc2_chan_mask, + }; + ESP_ERROR_CHECK(adc_digi_initialize(&adc_dma_config)); + + adc_digi_configuration_t dig_cfg = { + .conv_limit_en = ADC_CONV_LIMIT_EN, + .conv_limit_num = 250, + .sample_freq_hz = 10 * 1000, + .conv_mode = ADC_CONV_MODE, + .format = ADC_OUTPUT_TYPE, + }; + + adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0}; + dig_cfg.pattern_num = channel_num; + for (int i = 0; i < channel_num; i++) { + uint8_t unit = GET_UNIT(channel[i]); + uint8_t ch = channel[i] & 0x7; + adc_pattern[i].atten = ADC_ATTEN_DB_0; + adc_pattern[i].channel = ch; + adc_pattern[i].unit = unit; + adc_pattern[i].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH; + + ESP_LOGI(TAG, "adc_pattern[%d].atten is :%x", i, adc_pattern[i].atten); + ESP_LOGI(TAG, "adc_pattern[%d].channel is :%x", i, adc_pattern[i].channel); + ESP_LOGI(TAG, "adc_pattern[%d].unit is :%x", i, adc_pattern[i].unit); + } + dig_cfg.adc_pattern = adc_pattern; + ESP_ERROR_CHECK(adc_digi_controller_configure(&dig_cfg)); +} + +#if !CONFIG_IDF_TARGET_ESP32 +static bool check_valid_data(const adc_digi_output_data_t *data) +{ + const unsigned int unit = data->type2.unit; + if (unit > 2) return false; + if (data->type2.channel >= SOC_ADC_CHANNEL_NUM(unit)) return false; + + return true; +} +#endif + +void app_main(void) +{ + esp_err_t ret; + uint32_t ret_num = 0; + uint8_t result[TIMES] = {0}; + memset(result, 0xcc, TIMES); + + continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t)); + adc_digi_start(); + + while(1) { + ret = adc_digi_read_bytes(result, TIMES, &ret_num, ADC_MAX_DELAY); + if (ret == ESP_OK || ret == ESP_ERR_INVALID_STATE) { + if (ret == ESP_ERR_INVALID_STATE) { + /** + * @note 1 + * Issue: + * As an example, we simply print the result out, which is super slow. Therefore the conversion is too + * fast for the task to handle. In this condition, some conversion results lost. + * + * Reason: + * When this error occurs, you will usually see the task watchdog timeout issue also. + * Because the conversion is too fast, whereas the task calling `adc_digi_read_bytes` is slow. + * So `adc_digi_read_bytes` will hardly block. Therefore Idle Task hardly has chance to run. In this + * example, we add a `vTaskDelay(1)` below, to prevent the task watchdog timeout. + * + * Solution: + * Either decrease the conversion speed, or increase the frequency you call `adc_digi_read_bytes` + */ + } + + ESP_LOGI("TASK:", "ret is %x, ret_num is %d", ret, ret_num); + for (int i = 0; i < ret_num; i += ADC_RESULT_BYTE) { + adc_digi_output_data_t *p = (void*)&result[i]; + #if CONFIG_IDF_TARGET_ESP32 + ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 1, p->type1.channel, p->type1.data); + #else + if (ADC_CONV_MODE == ADC_CONV_BOTH_UNIT || ADC_CONV_MODE == ADC_CONV_ALTER_UNIT) { + if (check_valid_data(p)) { + ESP_LOGI(TAG, "Unit: %d,_Channel: %d, Value: %x", p->type2.unit+1, p->type2.channel, p->type2.data); + } else { + // abort(); + ESP_LOGI(TAG, "Invalid data [%d_%d_%x]", p->type2.unit+1, p->type2.channel, p->type2.data); + } + } + #if CONFIG_IDF_TARGET_ESP32S2 + else if (ADC_CONV_MODE == ADC_CONV_SINGLE_UNIT_2) { + ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 2, p->type1.channel, p->type1.data); + } else if (ADC_CONV_MODE == ADC_CONV_SINGLE_UNIT_1) { + ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 1, p->type1.channel, p->type1.data); + } + #endif //#if CONFIG_IDF_TARGET_ESP32S2 + #endif + } + //See `note 1` + vTaskDelay(1); + } else if (ret == ESP_ERR_TIMEOUT) { + /** + * ``ESP_ERR_TIMEOUT``: If ADC conversion is not finished until Timeout, you'll get this return error. + * Here we set Timeout ``portMAX_DELAY``, so you'll never reach this branch. + */ + ESP_LOGW(TAG, "No data, increase timeout or reduce conv_num_each_intr"); + vTaskDelay(1000); + } + + } + + adc_digi_stop(); + ret = adc_digi_deinitialize(); + assert(ret == ESP_OK); +} diff --git a/examples/peripherals/adc/esp32c3/adc/README.md b/examples/peripherals/adc/esp32c3/adc/README.md deleted file mode 100644 index 8d349d76f3..0000000000 --- a/examples/peripherals/adc/esp32c3/adc/README.md +++ /dev/null @@ -1,63 +0,0 @@ -| Supported Targets | ESP32-C3 | -| ----------------- | -------- | - -# ADC DMA Example - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -This example shows how to use DMA-Read-APIs and Single-Read-APIs to read voltage from GPIO pins via ADC controller. - -## How to use example - -### Hardware Required - -* A development board with ESP32C3 SoC -* A USB cable for power supply and programming - -For `single_read` (Single-Read-APIs example), we use `ADC1_CHANNEL_2`, `ADC1_CHANNEL_3`, `ADC1_CHANNEL_4`, `ADC2_CHANNEL_0`. Hence we need to connect voltage sources (0 ~ 3.3V) to GPIO2, GPIO3, GPIO4, GPIO5 respectively. - -For `continuous_read` (DMA-Read-APIs example), we use `ADC1_CHANNEL_0`, `ADC1_CHANNEL_1` and `ADC2_CHANNEL_0`. Therefore, GPIO0, GPIO1 and GPIO5 should be connected to voltage sources (0 ~ 3.3V). - -If other ADC units/channels are selected in your application, you need to change the GPIO pin (please refer to the `ESP32C3 Technical Reference Manual`). - -### Configure the project - -``` -idf.py menuconfig -``` - -### Build and Flash - -Build the project and flash it to the board, then run monitor tool to view serial output: - -``` -idf.py -p PORT flash monitor -``` - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -Running this example, you will see the following log output on the serial monitor: -``` -I (322) ADC1_CH2: 7c8 -I (322) ADC1_CH3: 278 -I (322) ADC1_CH4: d4b -I (322) ADC2_CH0: 48 -``` -``` -ADC1_CH0: 61b -ADC1_CH1: 39b -ADC2_CH0: 4b -``` - -## Troubleshooting - -* program upload failure - - * Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs. - * The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again. - -For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/peripherals/adc/esp32c3/adc/main/adc_dma_example_main.c b/examples/peripherals/adc/esp32c3/adc/main/adc_dma_example_main.c deleted file mode 100644 index 774a1eaf06..0000000000 --- a/examples/peripherals/adc/esp32c3/adc/main/adc_dma_example_main.c +++ /dev/null @@ -1,124 +0,0 @@ -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "esp_log.h" -#include "driver/adc.h" - -#define TIMES 256 - -static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num) -{ - esp_err_t ret = ESP_OK; - assert(ret == ESP_OK); - - adc_digi_init_config_t adc_dma_config = { - .max_store_buf_size = 1024, - .conv_num_each_intr = 256, - .adc1_chan_mask = adc1_chan_mask, - .adc2_chan_mask = adc2_chan_mask, - }; - ret = adc_digi_initialize(&adc_dma_config); - assert(ret == ESP_OK); - - adc_digi_pattern_table_t adc_pattern[10] = {0}; - - //Do not set the sampling frequency out of the range between `SOC_ADC_SAMPLE_FREQ_THRES_LOW` and `SOC_ADC_SAMPLE_FREQ_THRES_HIGH` - adc_digi_config_t dig_cfg = { - .conv_limit_en = 0, - .conv_limit_num = 250, - .sample_freq_hz = 620, - }; - - dig_cfg.adc_pattern_len = channel_num; - for (int i = 0; i < channel_num; i++) { - uint8_t unit = ((channel[i] >> 3) & 0x1); - uint8_t ch = channel[i] & 0x7; - adc_pattern[i].atten = ADC_ATTEN_DB_0; - adc_pattern[i].channel = ch; - adc_pattern[i].unit = unit; - } - dig_cfg.adc_pattern = adc_pattern; - ret = adc_digi_controller_config(&dig_cfg); - assert(ret == ESP_OK); -} - -static bool check_valid_data(const adc_digi_output_data_t *data) -{ - const unsigned int unit = data->type2.unit; - if (unit > 2) return false; - if (data->type2.channel >= SOC_ADC_CHANNEL_NUM(unit)) return false; - - return true; -} - -static void continuous_read(void *arg) -{ - esp_err_t ret; - uint32_t ret_num = 0; - uint8_t result[TIMES] = {0}; - memset(result, 0xcc, TIMES); - - uint16_t adc1_chan_mask = BIT(0) | BIT(1); - uint16_t adc2_chan_mask = BIT(0); - adc_channel_t channel[3] = {ADC1_CHANNEL_0, ADC1_CHANNEL_1, (ADC2_CHANNEL_0 | 1 << 3)}; - - continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t)); - adc_digi_start(); - - int n = 20; - while(n--) { - ret = adc_digi_read_bytes(result, TIMES, &ret_num, ADC_MAX_DELAY); - for (int i = 0; i < ret_num; i+=4) { - adc_digi_output_data_t *p = (void*)&result[i]; - if (check_valid_data(p)) { - printf("ADC%d_CH%d: %x\n", p->type2.unit+1, p->type2.channel, p->type2.data); - } else { - printf("Invalid data [%d_%d_%x]\n", p->type2.unit+1, p->type2.channel, p->type2.data); - } - } - // If you see task WDT in this task, it means the conversion is too fast for the task to handle - } - - adc_digi_stop(); - ret = adc_digi_deinitialize(); - assert(ret == ESP_OK); -} - -static void single_read(void *arg) -{ - esp_err_t ret; - int adc1_reading[3] = {0xcc}; - int adc2_reading[1] = {0xcc}; - - const char TAG_CH[][10] = {"ADC1_CH2", "ADC1_CH3","ADC1_CH4", "ADC2_CH0"}; - - adc1_config_width(ADC_WIDTH_BIT_DEFAULT); - adc1_config_channel_atten(ADC1_CHANNEL_2, ADC_ATTEN_DB_0); - adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_6); - adc1_config_channel_atten(ADC1_CHANNEL_4, ADC_ATTEN_DB_0); - adc2_config_channel_atten(ADC2_CHANNEL_0, ADC_ATTEN_DB_0); - - int n = 20; - while (n--) { - - adc1_reading[0] = adc1_get_raw(ADC1_CHANNEL_2); - adc1_reading[1] = adc1_get_raw(ADC1_CHANNEL_3); - adc1_reading[2] = adc1_get_raw(ADC1_CHANNEL_4); - - for (int i = 0; i < 3; i++) { - ESP_LOGI(TAG_CH[i], "%x", adc1_reading[i]); - } - - ret = adc2_get_raw(ADC2_CHANNEL_0, ADC_WIDTH_BIT_12, &adc2_reading[0]); - assert(ret == ESP_OK); - ESP_LOGI(TAG_CH[3], "%x", adc2_reading[0]); - } -} - -void app_main(void) -{ - single_read(NULL); - continuous_read(NULL); -} diff --git a/examples/peripherals/adc/single_read/single_read/main/single_read.c b/examples/peripherals/adc/single_read/single_read/main/single_read.c index 2a567d0682..a40821e849 100644 --- a/examples/peripherals/adc/single_read/single_read/main/single_read.c +++ b/examples/peripherals/adc/single_read/single_read/main/single_read.c @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /* ADC1 Example This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -11,7 +17,7 @@ #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "driver/adc_common.h" +#include "driver/adc.h" #include "esp_adc_cal.h" diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index aa51567792..f15b79a7ea 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -759,7 +759,6 @@ components/esp_serial_slave_link/include/esp_serial_slave_link/essl.h components/esp_serial_slave_link/include/esp_serial_slave_link/essl_sdio.h components/esp_serial_slave_link/include/esp_serial_slave_link/essl_spi.h components/esp_serial_slave_link/include/essl_spi/esp32c3_defs.h -components/esp_serial_slave_link/include/essl_spi/esp32h2_defs.h components/esp_serial_slave_link/include/essl_spi/esp32s2_defs.h components/esp_serial_slave_link/include/essl_spi/esp32s3_defs.h components/esp_system/eh_frame_parser.c @@ -973,12 +972,9 @@ components/hal/aes_hal.c components/hal/cpu_hal.c components/hal/dac_hal.c components/hal/ds_hal.c -components/hal/esp32/adc_hal.c components/hal/esp32/brownout_hal.c components/hal/esp32/gpio_hal_workaround.c -components/hal/esp32/include/hal/adc_hal.h components/hal/esp32/include/hal/adc_hal_conf.h -components/hal/esp32/include/hal/adc_ll.h components/hal/esp32/include/hal/aes_ll.h components/hal/esp32/include/hal/can_hal.h components/hal/esp32/include/hal/can_ll.h @@ -1009,12 +1005,9 @@ components/hal/esp32/include/hal/twai_ll.h components/hal/esp32/include/hal/uart_ll.h components/hal/esp32/interrupt_descriptor_table.c components/hal/esp32/touch_sensor_hal.c -components/hal/esp32c3/adc_hal.c components/hal/esp32c3/brownout_hal.c components/hal/esp32c3/hmac_hal.c -components/hal/esp32c3/include/hal/adc_hal.h components/hal/esp32c3/include/hal/adc_hal_conf.h -components/hal/esp32c3/include/hal/adc_ll.h components/hal/esp32c3/include/hal/aes_ll.h components/hal/esp32c3/include/hal/clk_gate_ll.h components/hal/esp32c3/include/hal/ds_ll.h @@ -1040,12 +1033,9 @@ components/hal/esp32c3/include/hal/uart_ll.h components/hal/esp32c3/include/hal/uhci_ll.h components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h components/hal/esp32c3/rtc_cntl_hal.c -components/hal/esp32h2/adc_hal.c components/hal/esp32h2/brownout_hal.c components/hal/esp32h2/hmac_hal.c -components/hal/esp32h2/include/hal/adc_hal.h components/hal/esp32h2/include/hal/adc_hal_conf.h -components/hal/esp32h2/include/hal/adc_ll.h components/hal/esp32h2/include/hal/aes_ll.h components/hal/esp32h2/include/hal/clk_gate_ll.h components/hal/esp32h2/include/hal/ds_ll.h @@ -1068,13 +1058,9 @@ components/hal/esp32h2/include/hal/uhci_ll.h components/hal/esp32h2/include/hal/uhci_types.h components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h components/hal/esp32h2/rtc_cntl_hal.c -components/hal/esp32s2/adc_hal.c components/hal/esp32s2/brownout_hal.c components/hal/esp32s2/cp_dma_hal.c -components/hal/esp32s2/dac_hal.c -components/hal/esp32s2/include/hal/adc_hal.h components/hal/esp32s2/include/hal/adc_hal_conf.h -components/hal/esp32s2/include/hal/adc_ll.h components/hal/esp32s2/include/hal/aes_ll.h components/hal/esp32s2/include/hal/clk_gate_ll.h components/hal/esp32s2/include/hal/cp_dma_hal.h @@ -1100,7 +1086,6 @@ components/hal/esp32s2/include/hal/sigmadelta_ll.h components/hal/esp32s2/include/hal/soc_ll.h components/hal/esp32s2/include/hal/spi_flash_encrypted_ll.h components/hal/esp32s2/include/hal/spi_flash_ll.h -components/hal/esp32s2/include/hal/spi_ll.h components/hal/esp32s2/include/hal/spimem_flash_ll.h components/hal/esp32s2/include/hal/systimer_ll.h components/hal/esp32s2/include/hal/touch_sensor_hal.h @@ -1113,7 +1098,6 @@ components/hal/esp32s2/interrupt_descriptor_table.c components/hal/esp32s2/touch_sensor_hal.c components/hal/esp32s3/brownout_hal.c components/hal/esp32s3/include/hal/adc_hal_conf.h -components/hal/esp32s3/include/hal/adc_ll.h components/hal/esp32s3/include/hal/aes_ll.h components/hal/esp32s3/include/hal/cpu_ll.h components/hal/esp32s3/include/hal/gpspi_flash_ll.h @@ -1141,7 +1125,6 @@ components/hal/esp32s3/interrupt_descriptor_table.c components/hal/gpio_hal.c components/hal/i2c_hal.c components/hal/i2c_hal_iram.c -components/hal/include/hal/adc_hal.h components/hal/include/hal/aes_hal.h components/hal/include/hal/aes_types.h components/hal/include/hal/brownout_hal.h @@ -1649,7 +1632,6 @@ components/soc/esp32/include/soc/mmu.h components/soc/esp32/include/soc/nrx_reg.h components/soc/esp32/include/soc/pcnt_reg.h components/soc/esp32/include/soc/pcnt_struct.h -components/soc/esp32/include/soc/periph_defs.h components/soc/esp32/include/soc/pid.h components/soc/esp32/include/soc/reset_reasons.h components/soc/esp32/include/soc/rmt_reg.h @@ -1744,7 +1726,6 @@ components/soc/esp32c3/include/soc/rtc_i2c_reg.h components/soc/esp32c3/include/soc/rtc_i2c_struct.h components/soc/esp32c3/include/soc/sensitive_reg.h components/soc/esp32c3/include/soc/sensitive_struct.h -components/soc/esp32c3/include/soc/soc_caps.h components/soc/esp32c3/include/soc/soc_pins.h components/soc/esp32c3/include/soc/spi_mem_reg.h components/soc/esp32c3/include/soc/spi_mem_struct.h @@ -1875,7 +1856,6 @@ components/soc/esp32s2/include/soc/mmu.h components/soc/esp32s2/include/soc/nrx_reg.h components/soc/esp32s2/include/soc/pcnt_reg.h components/soc/esp32s2/include/soc/pcnt_struct.h -components/soc/esp32s2/include/soc/periph_defs.h components/soc/esp32s2/include/soc/reset_reasons.h components/soc/esp32s2/include/soc/rmt_reg.h components/soc/esp32s2/include/soc/rmt_struct.h @@ -1940,7 +1920,6 @@ components/soc/esp32s3/include/soc/adc_channel.h components/soc/esp32s3/include/soc/apb_ctrl_reg.h components/soc/esp32s3/include/soc/apb_ctrl_struct.h components/soc/esp32s3/include/soc/apb_saradc_reg.h -components/soc/esp32s3/include/soc/apb_saradc_struct.h components/soc/esp32s3/include/soc/assist_debug_reg.h components/soc/esp32s3/include/soc/assist_debug_struct.h components/soc/esp32s3/include/soc/bb_reg.h @@ -1986,7 +1965,6 @@ components/soc/esp32s3/include/soc/pcnt_reg.h components/soc/esp32s3/include/soc/pcnt_struct.h components/soc/esp32s3/include/soc/peri_backup_reg.h components/soc/esp32s3/include/soc/peri_backup_struct.h -components/soc/esp32s3/include/soc/periph_defs.h components/soc/esp32s3/include/soc/reset_reasons.h components/soc/esp32s3/include/soc/rmt_reg.h components/soc/esp32s3/include/soc/rmt_struct.h @@ -2721,10 +2699,8 @@ examples/network/simple_sniffer/components/pcap/pcap.h examples/network/simple_sniffer/main/cmd_sniffer.c examples/network/simple_sniffer/main/cmd_sniffer.h examples/network/simple_sniffer/main/simple_sniffer_example_main.c -examples/peripherals/adc/esp32c3/adc/main/adc_dma_example_main.c examples/peripherals/adc/single_read/adc/main/adc1_example_main.c examples/peripherals/adc/single_read/adc2/main/adc2_example_main.c -examples/peripherals/adc/single_read/single_read/main/single_read.c examples/peripherals/gpio/generic_gpio/example_test.py examples/peripherals/gpio/generic_gpio/main/gpio_example_main.c examples/peripherals/gpio/matrix_keyboard/components/matrix_keyboard/include/matrix_keyboard.h