adc: support adc dma driver on all chips

This commit is contained in:
Armando 2021-12-15 14:15:32 +08:00 committed by Armando (Dou Yiwen)
parent 5ddce053ea
commit 4dc0d6b2fe
81 changed files with 4156 additions and 5420 deletions

View File

@ -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()

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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; /*!<Raw data value */
};
} adc_digi_pattern_table_t __attribute__((deprecated));
/**
* Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
*
* +---------------------+--------+--------+--------+
* | conv_mode | single | both | alter |
* +---------------------+--------+--------+--------+
* | trigger meas times | 1 | 1 | 1 |
* +---------------------+--------+--------+--------+
* | conv_limit_num | +1 | +1 | +1 |
* | dma_eof_num | +1 | +2 | +1 |
* | dma output (byte) | +2 | +4 | +2 |
* +---------------------+--------+--------+--------+
*/
typedef struct {
bool conv_limit_en; /*!<Enable the function of limiting ADC conversion times.
If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
uint32_t conv_limit_num; /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
uint32_t adc2_pattern_len; /*!<Refer to ``adc1_pattern_len`` */
adc_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. See ``adc_digi_output_format_t``. */
} adc_digi_config_t __attribute__((deprecated));
#endif //#if CONFIG_IDF_TARGET_ESP32
#if CONFIG_IDF_TARGET_ESP32S2
/*---------------------------------------------------------------
ESP32S2 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 reserved: 2; /*!< reserved0 */
uint8_t channel: 4; /*!< ADC channel index. */
};
uint8_t val; /*!<Raw data value */
};
} adc_digi_pattern_table_t __attribute__((deprecated));
/**
* @brief ADC digital controller (DMA mode) configuration parameters.
*
* Example setting: When using ADC1 channel0 to measure voltage, the sampling rate is required to be 1 kHz:
*
* +---------------------+--------+--------+--------+
* | sample rate | 1 kHz | 1 kHz | 1 kHz |
* +---------------------+--------+--------+--------+
* | conv_mode | single | both | alter |
* | adc1_pattern_len | 1 | 1 | 1 |
* | dig_clk.use_apll | 0 | 0 | 0 |
* | dig_clk.div_num | 99 | 99 | 99 |
* | dig_clk.div_b | 0 | 0 | 0 |
* | dig_clk.div_a | 0 | 0 | 0 |
* | interval | 400 | 400 | 200 |
* +---------------------+--------+--------+--------+
* | `trigger_meas_freq` | 1 kHz | 1 kHz | 2 kHz |
* +---------------------+--------+--------+--------+
*
* Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
*
* +---------------------+--------+--------+--------+
* | conv_mode | single | both | alter |
* +---------------------+--------+--------+--------+
* | trigger meas times | 1 | 1 | 1 |
* +---------------------+--------+--------+--------+
* | conv_limit_num | +1 | +1 | +1 |
* | dma_eof_num | +1 | +2 | +1 |
* | dma output (byte) | +2 | +4 | +2 |
* +---------------------+--------+--------+--------+
*/
typedef struct {
bool conv_limit_en; /*!<Enable the function of limiting ADC conversion times.
If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
uint32_t conv_limit_num; /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
uint32_t adc2_pattern_len; /*!<Refer to ``adc1_pattern_len`` */
adc_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. See ``adc_digi_output_format_t``. */
uint32_t interval; /*!<The number of interval clock cycles for the digital controller to trigger the measurement.
The unit is the divided clock. Range: 40 ~ 4095.
Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``.
Note: The sampling rate of each channel is also related to the conversion mode (See ``adc_digi_convert_mode_t``) and pattern table settings. */
adc_digi_clk_t dig_clk; /*!<ADC digital controller clock divider settings. Refer to ``adc_digi_clk_t``.
Note: The clocks of the DAC digital controller use the ADC digital controller clock divider. */
uint32_t dma_eof_num; /*!<DMA eof num of adc digital controller.
If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated in DMA.
Note: The converted data in the DMA in link buffer will be multiple of two bytes. */
} adc_digi_config_t __attribute__((deprecated));
/**
* @brief ADC digital controller (DMA mode) interrupt type options.
*/
typedef enum {
ADC_DIGI_INTR_MASK_MONITOR = 0x1,
ADC_DIGI_INTR_MASK_MEAS_DONE = 0x2,
ADC_DIGI_INTR_MASK_ALL = 0x3,
} adc_digi_intr_t __attribute__((deprecated));
FLAG_ATTR(adc_digi_intr_t)
#endif //#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32C3
/*---------------------------------------------------------------
ESP32C3 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 channel: 3; /*!< ADC channel index. */
uint8_t unit: 1; /*!< ADC unit index. */
uint8_t reserved: 2; /*!< reserved0 */
};
uint8_t val; /*!<Raw data value */
};
} adc_digi_pattern_table_t __attribute__((deprecated));
typedef struct {
bool conv_limit_en; /*!<Enable the function of limiting ADC conversion times.
If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
uint32_t conv_limit_num; /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
uint32_t adc_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 7 (0: Don't change the pattern table setting).
The pattern table that defines the conversion rules for each SAR ADC. Each table has 7 items, in which channel selection,
resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
adc_digi_pattern_table_t *adc_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc_pattern_len`. */
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_config_t __attribute__((deprecated));
#endif //#if CONFIG_IDF_TARGET_ESP32C3
#ifdef __cplusplus
}
#endif

View File

@ -30,123 +30,14 @@
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#define ADC_MAX_MEAS_NUM_DEFAULT (255)
#define ADC_MEAS_NUM_LIM_DEFAULT (1)
#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)
#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)
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)
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
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_hal_digi_set_data_source(src);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
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_gpio_init(adc_unit, channel);
ADC_ENTER_CRITICAL();
adc_hal_init();
adc_hal_digi_controller_config(&dig_cfg);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
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();
ADC_EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
{
/* If enable digital controller, adc xpd should always on. */
adc_power_acquire();
ADC_ENTER_CRITICAL();
adc_hal_digi_controller_config(config);
ADC_EXIT_CRITICAL();
return ESP_OK;
}
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/
/*---------------------------------------------------------------
HALL SENSOR
@ -160,22 +51,26 @@ static int hall_sensor_get_value(void) //hall sensor without LNA
ADC_ENTER_CRITICAL();
/* disable other peripherals. */
adc_hal_amp_disable();
adc_hal_hall_enable();
adc_ll_amp_disable();
adc_ll_hall_enable();
// set controller
adc_hal_set_controller( ADC_NUM_1, ADC_CTRL_RTC );
adc_ll_set_controller( ADC_NUM_1, ADC_LL_CTRL_RTC );
hall_value = adc_hal_hall_convert();
adc_hal_hall_disable();
adc_ll_hall_disable();
ADC_EXIT_CRITICAL();
adc_power_release();
return hall_value;
}
/**
* To Be Deprecated
*/
extern esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
int hall_sensor_read(void)
{
adc_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_0);
adc_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_3);
adc_common_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_0);
adc_common_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_3);
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_0);
adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_0);
return hall_sensor_get_value();

View File

@ -1,64 +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
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
/**
* @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);
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/
/**
* @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);
#ifdef __cplusplus
}
#endif

View File

@ -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

View File

@ -1,717 +0,0 @@
/*
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <esp_types.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#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, &current_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;
}

View File

@ -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.*/
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -8,7 +8,6 @@
#include <stdbool.h>
#include <math.h>
#include <esp_types.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"

View File

@ -0,0 +1,646 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#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

View File

@ -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 <stdint.h>
#include <stdbool.h>
#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"

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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"

View File

@ -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) {

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -1,130 +0,0 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#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;
}

View File

@ -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

View File

@ -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()

View File

@ -5,25 +5,108 @@
*/
#include <sys/param.h>
#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

View File

@ -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)
{

View File

@ -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.
*

View File

@ -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.

View File

@ -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

View File

@ -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.
*

View File

@ -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 <stdbool.h>
#include <stdlib.h>
#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, /*!<For ADC1. Select RTC controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC_CTRL_DIG = 2, /*!<For ADC1. Select DIG controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC2_CTRL_PWDET = 3,/*!<For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC2_CTRL_FORCE_PWDET = 3, /*!<For ADC2. Arbiter in shield mode. Force select Wi-Fi controller work. */
ADC2_CTRL_FORCE_RTC = 4, /*!<For ADC2. Arbiter in shield mode. Force select RTC controller work. */
ADC2_CTRL_FORCE_DIG = 6, /*!<For ADC2. Arbiter in shield mode. Force select digital controller work. */
} adc_ll_controller_t;
typedef struct {
union {
struct {
uint8_t atten: 2;
uint8_t channel: 3;
uint8_t unit: 1;
uint8_t reserved: 2;
};
uint8_t val;
};
} __attribute__((packed)) adc_ll_digi_pattern_table_t;
/*---------------------------------------------------------------
Digital controller setting
@ -157,6 +161,18 @@ static inline void adc_ll_digi_convert_limit_disable(void)
APB_SARADC.ctrl2.meas_num_limit = 0;
}
/**
* Set adc conversion mode for digital controller.
*
* @note ESP32C3 only support ADC1 single mode.
*
* @param mode Conversion mode select.
*/
static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode)
{
//ESP32C3 only supports ADC_CONV_ALTER_UNIT mode
}
/**
* Set pattern table length for digital controller.
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 8 items, in which channel selection,
@ -181,16 +197,18 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_
* @param pattern_index Items index. Range: 0 ~ 7.
* @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 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) * 6;
adc_ll_digi_pattern_table_t pattern = {0};
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
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
}
/**

View File

@ -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 <string.h>
#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);
}

View File

@ -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

View File

@ -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 <stdbool.h>
@ -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, /*!<For ADC1. Select RTC controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC_CTRL_DIG = 2, /*!<For ADC1. Select DIG controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC2_CTRL_PWDET = 3,/*!<For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC2_CTRL_FORCE_PWDET = 3, /*!<For ADC2. Arbiter in shield mode. Force select Wi-Fi controller work. */
ADC2_CTRL_FORCE_RTC = 4, /*!<For ADC2. Arbiter in shield mode. Force select RTC controller work. */
ADC2_CTRL_FORCE_DIG = 6, /*!<For ADC2. Arbiter in shield mode. Force select digital controller work. */
} adc_ll_controller_t;
typedef struct {
union {
struct {
uint8_t atten: 2;
uint8_t channel: 3;
uint8_t unit: 1;
uint8_t reserved: 2;
};
uint8_t val;
};
} __attribute__((packed)) adc_ll_digi_pattern_table_t;
/*---------------------------------------------------------------
Digital controller setting
@ -157,6 +161,18 @@ static inline void adc_ll_digi_convert_limit_disable(void)
APB_SARADC.ctrl2.meas_num_limit = 0;
}
/**
* Set adc conversion mode for digital controller.
*
* @note ESP32H2 only support ADC1 single mode.
*
* @param mode Conversion mode select.
*/
static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode)
{
//ESP32H2 only supports ADC_CONV_ALTER_UNIT mode
}
/**
* Set pattern table length for digital controller.
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 8 items, in which channel selection,
@ -181,16 +197,18 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_
* @param pattern_index Items index. Range: 0 ~ 7.
* @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 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) * 6;
adc_ll_digi_pattern_table_t pattern = {0};
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
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();
}
/*---------------------------------------------------------------

View File

@ -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);
}

View File

@ -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)

View File

@ -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

View File

@ -1,3 +1,9 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
@ -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, /*!<For ADC1. Select RTC controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC_CTRL_ULP = 1, /*!<For ADC1. Select ULP controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC_CTRL_DIG = 2, /*!<For ADC1. Select DIG controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC2_CTRL_PWDET = 3,/*!<For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC2_CTRL_FORCE_PWDET = 3, /*!<For ADC2. Arbiter in shield mode. Force select Wi-Fi controller work. */
ADC2_CTRL_FORCE_RTC = 4, /*!<For ADC2. Arbiter in shield mode. Force select RTC controller work. */
ADC2_CTRL_FORCE_ULP = 5, /*!<For ADC2. Arbiter in shield mode. Force select RTC controller work. */
ADC2_CTRL_FORCE_DIG = 6, /*!<For ADC2. Arbiter in shield mode. Force select digital controller work. */
} adc_ll_controller_t;
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
@ -120,16 +147,6 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div)
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div);
}
/**
* 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;
}
/**
* Set adc max conversion number for digital controller.
* If the number of ADC conversion is equal to the maximum, the conversion is stopped.
@ -162,22 +179,25 @@ 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.
* TODO IDF-3610
*/
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) {
APB_SARADC.ctrl.data_sar_sel = 0;
} 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) {
APB_SARADC.ctrl.data_sar_sel = 0;
} else if (mode == ADC_LL_DIGI_CONV_BOTH_UNIT) {
APB_SARADC.ctrl.work_mode = 1;
} else if (mode == ADC_CONV_ALTER_UNIT) {
APB_SARADC.ctrl.data_sar_sel = 1;
} else if (mode == ADC_LL_DIGI_CONV_ALTER_UNIT) {
APB_SARADC.ctrl.work_mode = 2;
APB_SARADC.ctrl.data_sar_sel = 1;
}
}
@ -209,12 +229,15 @@ 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.
*/
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};
pattern.val = (table.atten & 0x3) | ((table.channel & 0xF) << 4);
if (table.unit == 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
@ -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;
}

View File

@ -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)

View File

@ -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 <stdio.h>
@ -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; /*!<ADC real output data info. Resolution: 13 bit. */
uint16_t reserved: 2; /*!<reserved */
uint16_t data: 13; /*!<ADC real output data info. Resolution: 13 bit. */
uint16_t reserved: 1; /*!<reserved */
uint16_t flag: 2; /*!<ADC data flag info.
If (flag == 0), The data is valid.
If (flag > 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.
*/

View File

@ -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 <string.h>
#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);
}

View File

@ -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

View File

@ -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, /*!<For ADC1. Select RTC controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC_CTRL_DIG = 2, /*!<For ADC1. Select DIG controller. For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC2_CTRL_PWDET = 3,/*!<For ADC2. The controller is selected by the arbiter. Arbiter in default mode. */
ADC2_CTRL_FORCE_PWDET = 3, /*!<For ADC2. Arbiter in shield mode. Force select Wi-Fi controller work. */
ADC2_CTRL_FORCE_RTC = 4, /*!<For ADC2. Arbiter in shield mode. Force select RTC controller work. */
ADC2_CTRL_FORCE_DIG = 6, /*!<For ADC2. Arbiter in shield mode. Force select digital controller work. */
} adc_ll_controller_t;
typedef struct {
union {
struct {
uint8_t atten: 2;
uint8_t channel: 3;
uint8_t unit: 1;
uint8_t reserved: 2;
};
uint8_t val;
};
} __attribute__((packed)) adc_ll_digi_pattern_table_t;
/*---------------------------------------------------------------
Digital controller setting
@ -85,7 +98,12 @@ typedef enum {
*/
static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait)
{
abort();// TODO: IDF-3901.
// Internal FSM reset wait time
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, rstb_wait, rst_wait);
// Internal FSM start wait time
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, xpd_wait, start_wait);
// Internal FSM standby wait time
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, standby_wait, standby_wait);
}
/**
@ -97,7 +115,9 @@ static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wa
*/
static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
{
abort();// TODO: IDF-3901.
/* Should be called before writing I2C registers. */
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_SAMPLE_CYCLE_ADDR, sample_cycle);
}
/**
@ -108,7 +128,8 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
*/
static inline void adc_ll_digi_set_clk_div(uint32_t div)
{
abort();// TODO: IDF-3901.
/* ADC clock devided from digital controller clock clk */
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div);
}
/**
@ -119,7 +140,7 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div)
*/
static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num)
{
abort();// TODO: IDF-3901.
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl2, max_meas_num, meas_num);
}
/**
@ -128,7 +149,7 @@ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num)
*/
static inline void adc_ll_digi_convert_limit_enable(void)
{
abort();// TODO: IDF-3901.
APB_SARADC.ctrl2.meas_num_limit = 1;
}
/**
@ -137,7 +158,19 @@ static inline void adc_ll_digi_convert_limit_enable(void)
*/
static inline void adc_ll_digi_convert_limit_disable(void)
{
abort();// TODO: IDF-3901.
APB_SARADC.ctrl2.meas_num_limit = 0;
}
/**
* Set adc conversion mode for digital controller.
*
* @note ESP8684 only support ADC1 single mode.
*
* @param mode Conversion mode select.
*/
static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode)
{
//ESP8684 only supports ADC_CONV_ALTER_UNIT mode
}
/**
@ -151,7 +184,7 @@ static inline void adc_ll_digi_convert_limit_disable(void)
*/
static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_t patt_len)
{
abort();// TODO: IDF-3901.
APB_SARADC.ctrl.sar_patt_len = patt_len - 1;
}
/**
@ -164,9 +197,18 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_ll_num_t adc_n, uint32_
* @param pattern_index Items index. Range: 0 ~ 7.
* @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 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)
{
abort();// TODO: IDF-3901.
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 & 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
}
/**
@ -176,7 +218,8 @@ 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.
APB_SARADC.ctrl.sar_patt_p_clear = 1;
APB_SARADC.ctrl.sar_patt_p_clear = 0;
}
/**
@ -187,7 +230,7 @@ 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.
APB_SARADC.ctrl.wait_arb_cycle = cycle;
}
/**
@ -198,7 +241,11 @@ 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.
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 +257,7 @@ 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.
APB_SARADC.ctrl2.timer_target = cycle;
}
/**
@ -218,7 +265,7 @@ 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.
APB_SARADC.ctrl2.timer_en = 1;
}
/**
@ -226,20 +273,22 @@ static inline void adc_ll_digi_trigger_enable(void)
*/
static inline void adc_ll_digi_trigger_disable(void)
{
abort();// TODO: IDF-3901.
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.
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 +296,14 @@ 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.
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 +311,7 @@ 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.
APB_SARADC.ctrl.sar_clk_gated = 0;
}
/**
@ -267,7 +321,7 @@ 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.
APB_SARADC.filter_ctrl0.filter_reset = 1;
}
/**
@ -279,7 +333,13 @@ 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.
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 +350,15 @@ 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.
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 +370,13 @@ 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.
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 +389,15 @@ 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.
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 +408,11 @@ 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.
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 +423,7 @@ 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.
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num);
}
/**
@ -345,7 +431,7 @@ 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.
APB_SARADC.dma_conf.apb_adc_trans = 1;
}
/**
@ -353,7 +439,7 @@ static inline void adc_ll_digi_dma_enable(void)
*/
static inline void adc_ll_digi_dma_disable(void)
{
abort();// TODO: IDF-3901.
APB_SARADC.dma_conf.apb_adc_trans = 0;
}
/**
@ -361,7 +447,8 @@ static inline void adc_ll_digi_dma_disable(void)
*/
static inline void adc_ll_digi_reset(void)
{
abort();// TODO: IDF-3901.
APB_SARADC.dma_conf.apb_adc_reset_fsm = 1;
APB_SARADC.dma_conf.apb_adc_reset_fsm = 0;
}
/*---------------------------------------------------------------
@ -375,7 +462,8 @@ static inline void adc_ll_digi_reset(void)
*/
static inline void adc_ll_pwdet_set_cct(uint32_t cct)
{
abort();// TODO: IDF-3901.
/* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */
RTCCNTL.sensor_ctrl.sar2_pwdet_cct = cct;
}
/**
@ -386,8 +474,8 @@ 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();
/* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */
return RTCCNTL.sensor_ctrl.sar2_pwdet_cct;
}
/**
@ -402,8 +490,16 @@ 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();
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 +512,23 @@ 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.
/* 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 +543,15 @@ 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.
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 +569,33 @@ 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.
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 +604,11 @@ 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.
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 +623,20 @@ 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.
/* 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 +646,11 @@ 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.
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 +662,15 @@ 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.
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 +687,45 @@ 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.
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 +740,63 @@ 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.
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.
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.
APB_SARADC.onetime_sample.onetime_atten = atten;
}
static inline void adc_ll_intr_enable(adc_ll_intr_t mask)
{
abort();// TODO: IDF-3901.
APB_SARADC.int_ena.val |= mask;
}
static inline void adc_ll_intr_disable(adc_ll_intr_t mask)
{
abort();// TODO: IDF-3901.
APB_SARADC.int_ena.val &= ~mask;
}
static inline void adc_ll_intr_clear(adc_ll_intr_t mask)
{
abort();// TODO: IDF-3901.
APB_SARADC.int_clr.val |= mask;
}
static inline bool adc_ll_intr_get_raw(adc_ll_intr_t mask)
{
abort();// TODO: IDF-3901.
return (APB_SARADC.int_raw.val & mask);
}
static inline bool adc_ll_intr_get_status(adc_ll_intr_t mask)
{
abort();// TODO: IDF-3901.
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.
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.
//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.
//On ESP8684, valid data width is 12-bit
return (APB_SARADC.apb_saradc2_data_status.adc2_data & 0xfff);
}
#ifdef __cplusplus

View File

@ -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)

View File

@ -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; /*!<Raw data value */
};
} adc_digi_pattern_table_t;
/**
* @brief ADC digital controller (DMA mode) output data format option.
*/
typedef enum {
ADC_DIGI_FORMAT_12BIT, /*!<ADC to DMA data format, [15:12]-channel, [11: 0]-12 bits ADC data (`adc_digi_output_data_t`).
Note: For single convert mode. */
ADC_DIGI_FORMAT_11BIT, /*!<ADC to DMA data format, [15]-adc unit, [14:11]-channel, [10: 0]-11 bits ADC data (`adc_digi_output_data_t`).
Note: For multi or alter convert mode. */
ADC_DIGI_FORMAT_MAX,
ADC_DIGI_FORMAT_12BIT __attribute__((deprecated)), /*!<ADC to DMA data format, [15:12]-channel, [11: 0]-12 bits ADC data (`adc_digi_output_data_t`). Note: For single convert mode. */
ADC_DIGI_FORMAT_11BIT __attribute__((deprecated)), /*!<ADC to DMA data format, [15]-adc unit, [14:11]-channel, [10: 0]-11 bits ADC data (`adc_digi_output_data_t`). Note: For multi or alter convert mode. */
ADC_DIGI_FORMAT_MAX __attribute__((deprecated)),
ADC_DIGI_OUTPUT_FORMAT_TYPE1, ///< See `adc_digi_output_data_t.type1`
ADC_DIGI_OUTPUT_FORMAT_TYPE2, ///< See `adc_digi_output_data_t.type2`
} adc_digi_output_format_t;
/**
* @brief ADC digital controller pattern configuration
*/
typedef struct {
uint8_t atten; ///< Attenuation of this ADC channel
uint8_t channel; ///< ADC channel
uint8_t unit; ///< ADC unit
uint8_t bit_width; ///< ADC output bit width
} adc_digi_pattern_config_t;
/*---------------------------------------------------------------
Output Format
---------------------------------------------------------------*/
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
/**
* @brief ADC digital controller (DMA mode) output data format.
* Used to analyze the acquired ADC (DMA) data.
*
* @note ESP32-S2:
* Member `channel` can be used to judge the validity of the ADC data, because the role of the arbiter may get invalid ADC data.
* @note ESP32: Only `type1` is valid. ADC2 does not support DMA mode.
* @note ESP32-S2: Member `channel` can be used to judge the validity of the ADC data,
* because the role of the arbiter may get invalid ADC data.
*/
typedef struct {
union {
struct {
uint16_t data: 12; /*!<ADC real output data info. Resolution: 12 bit. */
uint16_t channel: 4; /*!<ADC channel index info. For ESP32-S2:
If (channel < ADC_CHANNEL_MAX), The data is valid.
If (channel > ADC_CHANNEL_MAX), The data is invalid. */
} type1; /*!<When the configured output format is 12bit. `ADC_DIGI_FORMAT_12BIT` */
uint16_t channel: 4; /*!<ADC channel index info. */
} type1;
struct {
uint16_t data: 11; /*!<ADC real output data info. Resolution: 11 bit. */
uint16_t channel: 4; /*!<ADC channel index info. For ESP32-S2:
@ -175,8 +132,8 @@ typedef struct {
uint16_t val; /*!<Raw data value */
};
} adc_digi_output_data_t;
#endif
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
/**
* @brief ADC digital controller (DMA mode) output data format.
* Used to analyze the acquired ADC (DMA) data.
@ -195,112 +152,32 @@ typedef struct {
uint32_t val; /*!<Raw data value */
};
} adc_digi_output_data_t;
#endif
#if !CONFIG_IDF_TARGET_ESP32
#elif CONFIG_IDF_TARGET_ESP32S3
/**
* @brief ADC digital controller (DMA mode) clock system setting.
* Calculation formula: controller_clk = (`APLL` or `APB`) / (div_num + div_a / div_b + 1).
*
* @note: The clocks of the DAC digital controller use the ADC digital controller clock divider.
* @brief ADC digital controller (DMA mode) output data format.
* Used to analyze the acquired ADC (DMA) data.
*/
typedef struct {
bool use_apll; /*!<true: use APLL clock; false: use APB clock. */
uint32_t div_num; /*!<Division factor. Range: 0 ~ 255.
Note: When a higher frequency clock is used (the division factor is less than 9),
the ADC reading value will be slightly offset. */
uint32_t div_b; /*!<Division factor. Range: 1 ~ 63. */
uint32_t div_a; /*!<Division factor. Range: 0 ~ 63. */
} adc_digi_clk_t;
#endif //!CONFIG_IDF_TARGET_ESP32
/**
* @brief ADC digital controller (DMA mode) configuration parameters.
*
* Example setting: When using ADC1 channel0 to measure voltage, the sampling rate is required to be 1 kHz:
*
* +---------------------+--------+--------+--------+
* | sample rate | 1 kHz | 1 kHz | 1 kHz |
* +---------------------+--------+--------+--------+
* | conv_mode | single | both | alter |
* | adc1_pattern_len | 1 | 1 | 1 |
* | dig_clk.use_apll | 0 | 0 | 0 |
* | dig_clk.div_num | 99 | 99 | 99 |
* | dig_clk.div_b | 0 | 0 | 0 |
* | dig_clk.div_a | 0 | 0 | 0 |
* | interval | 400 | 400 | 200 |
* +---------------------+--------+--------+--------+
* | `trigger_meas_freq` | 1 kHz | 1 kHz | 2 kHz |
* +---------------------+--------+--------+--------+
*
* Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
*
* +---------------------+--------+--------+--------+
* | conv_mode | single | both | alter |
* +---------------------+--------+--------+--------+
* | trigger meas times | 1 | 1 | 1 |
* +---------------------+--------+--------+--------+
* | conv_limit_num | +1 | +1 | +1 |
* | dma_eof_num | +1 | +2 | +1 |
* | dma output (byte) | +2 | +4 | +2 |
* +---------------------+--------+--------+--------+
*/
typedef struct {
bool conv_limit_en; /*!<Enable the function of limiting ADC conversion times.
If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
uint32_t conv_limit_num; /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
uint32_t adc2_pattern_len; /*!<Refer to ``adc1_pattern_len`` */
adc_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. See ``adc_digi_output_format_t``. */
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
uint32_t adc_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 7 (0: Don't change the pattern table setting).
The pattern table that defines the conversion rules for each SAR ADC. Each table has 7 items, in which channel selection,
resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
adc_digi_pattern_table_t *adc_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc_pattern_len`. */
#endif
#if CONFIG_IDF_TARGET_ESP32S2
uint32_t interval; /*!<The number of interval clock cycles for the digital controller to trigger the measurement.
The unit is the divided clock. Range: 40 ~ 4095.
Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``.
Note: The sampling rate of each channel is also related to the conversion mode (See ``adc_digi_convert_mode_t``) and pattern table settings. */
adc_digi_clk_t dig_clk; /*!<ADC digital controller clock divider settings. Refer to ``adc_digi_clk_t``.
Note: The clocks of the DAC digital controller use the ADC digital controller clock divider. */
uint32_t dma_eof_num; /*!<DMA eof num of adc digital controller.
If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated in DMA.
Note: The converted data in the DMA in link buffer will be multiple of two bytes. */
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP8684
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 */
#endif
} adc_digi_config_t;
#if CONFIG_IDF_TARGET_ESP32S2
/**
* @brief ADC digital controller (DMA mode) interrupt type options.
*/
typedef enum {
ADC_DIGI_INTR_MASK_MONITOR = 0x1,
ADC_DIGI_INTR_MASK_MEAS_DONE = 0x2,
ADC_DIGI_INTR_MASK_ALL = 0x3,
} adc_digi_intr_t;
FLAG_ATTR(adc_digi_intr_t)
union {
struct {
uint32_t data: 13; /*!<ADC real output data info. Resolution: 13 bit. */
uint32_t channel: 4; /*!<ADC channel index info.
If (channel < ADC_CHANNEL_MAX), The data is valid.
If (channel > ADC_CHANNEL_MAX), The data is invalid. */
uint32_t unit: 1; /*!<ADC unit index info. 0: ADC1; 1: ADC2. */
uint32_t reserved17_31: 14; /*!<Reserved17. */
} type2; /*!<When the configured output format is 12bit. `ADC_DIGI_FORMAT_11BIT` */
uint32_t val; /*!<Raw data value */
};
} adc_digi_output_data_t;
#endif
#if !CONFIG_IDF_TARGET_ESP32
#if SOC_ADC_ARBITER_SUPPORTED
/*---------------------------------------------------------------
Arbiter
---------------------------------------------------------------*/
/**
* @brief ADC arbiter work mode option.
*
@ -336,7 +213,12 @@ typedef struct {
.dig_pri = 0, \
.pwdet_pri = 2, \
}
#endif //#if SOC_ADC_ARBITER_SUPPORTED
#if SOC_ADC_FILTER_SUPPORTED
/*---------------------------------------------------------------
Filter
---------------------------------------------------------------*/
/**
* @brief ADC digital controller (DMA mode) filter index options.
*
@ -379,7 +261,12 @@ typedef struct {
For ESP32-S2, it's always `ADC_CHANNEL_MAX` */
adc_digi_filter_mode_t mode;/*!<Set adc filter mode for filter. See ``adc_digi_filter_mode_t``. */
} adc_digi_filter_t;
#endif // #if SOC_ADC_FILTER_SUPPORTED
#if SOC_ADC_MONITOR_SUPPORTED
/*---------------------------------------------------------------
Monitor
---------------------------------------------------------------*/
/**
* @brief ADC digital controller (DMA mode) monitor index options.
*
@ -429,5 +316,41 @@ typedef struct {
uint32_t threshold; /*!<Set monitor threshold of adc digital controller. */
#endif
} adc_digi_monitor_t;
#endif //#if SOC_ADC_MONITOR_SUPPORTED
#endif // CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
/*---------------------------------------------------------------
To Be Deprecated TODO: IDF-3610
---------------------------------------------------------------*/
#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;
#if CONFIG_IDF_TARGET_ESP32S2
/**
* @brief ADC digital controller (DMA mode) clock system setting.
* Calculation formula: controller_clk = (`APLL` or `APB`) / (div_num + div_a / div_b + 1).
*
* @note: The clocks of the DAC digital controller use the ADC digital controller clock divider.
*/
typedef struct {
bool use_apll; /*!<true: use APLL clock; false: use APB clock. */
uint32_t div_num; /*!<Division factor. Range: 0 ~ 255.
Note: When a higher frequency clock is used (the division factor is less than 9),
the ADC reading value will be slightly offset. */
uint32_t div_b; /*!<Division factor. Range: 1 ~ 63. */
uint32_t div_a; /*!<Division factor. Range: 0 ~ 63. */
} adc_digi_clk_t;
#endif

View File

@ -15,6 +15,10 @@ config SOC_CAPS_ECO_VER_MAX
int
default 3
config SOC_ADC_SUPPORTED
bool
default y
config SOC_DAC_SUPPORTED
bool
default y
@ -91,6 +95,10 @@ config SOC_ADC_RTC_CTRL_SUPPORTED
bool
default y
config SOC_ADC_DIG_CTRL_SUPPORTED
bool
default y
config SOC_ADC_PERIPH_NUM
int
default 2
@ -117,11 +125,11 @@ config SOC_ADC_DIGI_MAX_BITWIDTH
config SOC_ADC_SAMPLE_FREQ_THRES_HIGH
int
default 83333
default 2
config SOC_ADC_SAMPLE_FREQ_THRES_LOW
int
default 611
default 2000
config SOC_ADC_MAX_BITWIDTH
int

View File

@ -1,16 +1,8 @@
// Copyright 2015-2018 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
*/
#ifndef _SOC_PERIPH_DEFS_H_
#define _SOC_PERIPH_DEFS_H_
@ -54,6 +46,7 @@ typedef enum {
PERIPH_AES_MODULE,
PERIPH_SHA_MODULE,
PERIPH_RSA_MODULE,
PERIPH_SARADC_MODULE,
PERIPH_MODULE_MAX
} periph_module_t;

View File

@ -63,6 +63,7 @@
/*-------------------------- COMMON CAPS ---------------------------------------*/
#define SOC_CAPS_ECO_VER_MAX 3
#define SOC_ADC_SUPPORTED 1
#define SOC_DAC_SUPPORTED 1
#define SOC_MCPWM_SUPPORTED 1
#define SOC_SDMMC_HOST_SUPPORTED 1
@ -85,7 +86,7 @@
/*-------------------------- ADC CAPS ----------------------------------------*/
/**
* TO BE REMOVED in !14278
* TO BE REMOVED
* Check if adc support digital controller (DMA) mode.
* @value
* - 1 : support;
@ -95,6 +96,7 @@
/*!< SAR ADC Module*/
#define SOC_ADC_RTC_CTRL_SUPPORTED 1
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 8: 10)
#define SOC_ADC_MAX_CHANNEL_NUM (10)
@ -105,8 +107,8 @@
#define SOC_ADC_DIGI_MIN_BITWIDTH (9)
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH (2*1000*1000)
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW (2000)
/*!< RTC */
#define SOC_ADC_MAX_BITWIDTH (12)

View File

@ -7,6 +7,10 @@ config SOC_CPU_CORES_NUM
bool
default y
config SOC_ADC_SUPPORTED
bool
default y
config SOC_DEDICATED_GPIO_SUPPORTED
bool
default y
@ -107,6 +111,10 @@ config SOC_AES_SUPPORT_AES_256
bool
default y
config SOC_ADC_DIG_CTRL_SUPPORTED
bool
default y
config SOC_ADC_ARBITER_SUPPORTED
bool
default y
@ -128,8 +136,8 @@ config SOC_ADC_MAX_CHANNEL_NUM
default 5
config SOC_ADC_DIGI_CONTROLLER_NUM
bool
default y
int
default 1
config SOC_ADC_PATT_LEN_MAX
int

View File

@ -1,3 +1,9 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The long term plan is to have a single soc_caps.h for each peripheral.
// During the refactoring and multichip support development process, we
// seperate these information into periph_caps.h for each peripheral and
@ -20,6 +26,7 @@
/*-------------------------- COMMON CAPS ---------------------------------------*/
#define SOC_CPU_CORES_NUM 1
#define SOC_ADC_SUPPORTED 1
#define SOC_DEDICATED_GPIO_SUPPORTED 1
#define SOC_GDMA_SUPPORTED 1
#define SOC_TWAI_SUPPORTED 1
@ -53,6 +60,7 @@
/*-------------------------- ADC CAPS -------------------------------*/
/*!< SAR ADC Module*/
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
#define SOC_ADC_ARBITER_SUPPORTED 1
#define SOC_ADC_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
@ -61,7 +69,7 @@
#define SOC_ADC_MAX_CHANNEL_NUM (5)
/*!< Digital */
#define SOC_ADC_DIGI_CONTROLLER_NUM (1)
#define SOC_ADC_DIGI_CONTROLLER_NUM (1U)
#define SOC_ADC_PATT_LEN_MAX (8) /*!< One pattern table, each contains 8 items. Each item takes 1 byte */
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_FILTER_NUM (2)
@ -76,7 +84,6 @@
/*!< Calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
#define SOC_APB_BACKUP_DMA (1)

View File

@ -7,6 +7,10 @@ config SOC_CPU_CORES_NUM
bool
default y
config SOC_ADC_SUPPORTED
bool
default y
config SOC_DEDICATED_GPIO_SUPPORTED
bool
default y
@ -95,19 +99,39 @@ config SOC_AES_SUPPORT_AES_256
bool
default y
config SOC_ADC_DIG_CTRL_SUPPORTED
bool
default y
config SOC_ADC_ARBITER_SUPPORTED
bool
default y
config SOC_ADC_FILTER_SUPPORTED
bool
default y
config SOC_ADC_MONITOR_SUPPORTED
bool
default y
config SOC_ADC_PERIPH_NUM
int
default 2
config SOC_ADC_PATT_LEN_MAX
int
default 16
config SOC_ADC_MAX_CHANNEL_NUM
int
default 5
config SOC_ADC_MAX_BITWIDTH
config SOC_ADC_DIGI_CONTROLLER_NUM
int
default 1
config SOC_ADC_PATT_LEN_MAX
int
default 8
config SOC_ADC_DIGI_MAX_BITWIDTH
int
default 12
@ -119,10 +143,6 @@ config SOC_ADC_DIGI_MONITOR_NUM
int
default 2
config SOC_ADC_CALIBRATION_V1_SUPPORTED
bool
default y
config SOC_ADC_SAMPLE_FREQ_THRES_HIGH
int
default 83333
@ -131,6 +151,10 @@ config SOC_ADC_SAMPLE_FREQ_THRES_LOW
int
default 611
config SOC_ADC_MAX_BITWIDTH
int
default 12
config SOC_APB_BACKUP_DMA
bool
default y

View File

@ -25,6 +25,7 @@
/*-------------------------- COMMON CAPS ---------------------------------------*/
#define SOC_CPU_CORES_NUM 1
#define SOC_ADC_SUPPORTED 1
#define SOC_DEDICATED_GPIO_SUPPORTED 1
#define SOC_GDMA_SUPPORTED 1
#define SOC_TWAI_SUPPORTED 1
@ -55,19 +56,29 @@
#define SOC_AES_SUPPORT_AES_256 (1)
/*-------------------------- ADC CAPS -------------------------------*/
/*!< SAR ADC Module*/
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
#define SOC_ADC_ARBITER_SUPPORTED 1
#define SOC_ADC_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_PATT_LEN_MAX (16)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 5 : 1)
#define SOC_ADC_MAX_CHANNEL_NUM (5)
#define SOC_ADC_MAX_BITWIDTH (12)
/*!< Digital */
#define SOC_ADC_DIGI_CONTROLLER_NUM (1U)
#define SOC_ADC_PATT_LEN_MAX (8) /*!< One pattern table, each contains 8 items. Each item takes 1 byte */
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_FILTER_NUM (2)
#define SOC_ADC_DIGI_MONITOR_NUM (2)
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) 1
//F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611
/*!< RTC */
#define SOC_ADC_MAX_BITWIDTH (12)
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
#define SOC_APB_BACKUP_DMA (1)
@ -283,6 +294,7 @@
#define SOC_MAC_BB_PD_MEM_SIZE (192*4)
/*-------------------------- Power Management CAPS ----------------------------*/
#define SOC_PM_SUPPORT_BT_WAKEUP (1)
#define SOC_PM_SUPPORT_CPU_PD (1)

View File

@ -3,6 +3,10 @@
# using gen_soc_caps_kconfig.py, do not edit manually
#####################################################
config SOC_ADC_SUPPORTED
bool
default y
config SOC_DAC_SUPPORTED
bool
default y
@ -123,6 +127,10 @@ config SOC_ADC_RTC_CTRL_SUPPORTED
bool
default y
config SOC_ADC_DIG_CTRL_SUPPORTED
bool
default y
config SOC_ADC_ARBITER_SUPPORTED
bool
default y

View File

@ -1,16 +1,8 @@
// Copyright 2015-2018 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
*/
#ifndef _SOC_PERIPH_DEFS_H_
#define _SOC_PERIPH_DEFS_H_
@ -50,6 +42,7 @@ typedef enum {
PERIPH_AES_DMA_MODULE,
PERIPH_SHA_DMA_MODULE,
PERIPH_DEDIC_GPIO_MODULE,
PERIPH_SARADC_MODULE,
PERIPH_MODULE_MAX
} periph_module_t;

View File

@ -39,6 +39,7 @@
#pragma once
/*-------------------------- COMMON CAPS ---------------------------------------*/
#define SOC_ADC_SUPPORTED 1
#define SOC_DAC_SUPPORTED 1
#define SOC_TWAI_SUPPORTED 1
#define SOC_CP_DMA_SUPPORTED 1
@ -73,6 +74,7 @@
/*-------------------------- ADC CAPS ----------------------------------------*/
/*!< SAR ADC Module*/
#define SOC_ADC_RTC_CTRL_SUPPORTED 1
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
#define SOC_ADC_ARBITER_SUPPORTED 1
#define SOC_ADC_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
@ -94,7 +96,6 @@
/*!< Calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
/*-------------------------- BROWNOUT CAPS -----------------------------------*/
#define SOC_BROWNOUT_RESET_SUPPORTED 1

View File

@ -135,6 +135,10 @@ config SOC_RTCIO_WAKE_SUPPORTED
bool
default y
config SOC_ADC_SUPPORTED
bool
default y
config SOC_PCNT_SUPPORTED
bool
default y
@ -263,6 +267,10 @@ config SOC_ADC_RTC_CTRL_SUPPORTED
bool
default y
config SOC_ADC_DIG_CTRL_SUPPORTED
bool
default y
config SOC_ADC_ARBITER_SUPPORTED
bool
default y

View File

@ -1,16 +1,8 @@
// Copyright 2017-2021 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: 2017-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _SOC_APB_SARADC_STRUCT_H_
#define _SOC_APB_SARADC_STRUCT_H_

View File

@ -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
@ -58,6 +50,7 @@ typedef enum {
PERIPH_SYSTIMER_MODULE,
PERIPH_GDMA_MODULE,
PERIPH_DEDIC_GPIO_MODULE,
PERIPH_SARADC_MODULE,
PERIPH_MODULE_MAX
} periph_module_t;

View File

@ -25,6 +25,7 @@
#pragma once
/*-------------------------- COMMON CAPS ---------------------------------------*/
#define SOC_ADC_SUPPORTED 1
#define SOC_PCNT_SUPPORTED 1
#define SOC_TWAI_SUPPORTED 1
#define SOC_GDMA_SUPPORTED 1
@ -62,6 +63,7 @@
/*-------------------------- ADC CAPS ----------------------------------------*/
/*!< SAR ADC Module*/
#define SOC_ADC_RTC_CTRL_SUPPORTED 1
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
#define SOC_ADC_ARBITER_SUPPORTED 1
#define SOC_ADC_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1

View File

@ -7,6 +7,10 @@ config SOC_CPU_CORES_NUM
bool
default y
config SOC_ADC_SUPPORTED
bool
default y
config SOC_GDMA_SUPPORTED
bool
default y
@ -63,26 +67,42 @@ config SOC_AES_GDMA
bool
default y
config SOC_ADC_DIG_CTRL_SUPPORTED
bool
default y
config SOC_ADC_ARBITER_SUPPORTED
bool
default y
config SOC_ADC_FILTER_SUPPORTED
bool
default y
config SOC_ADC_MONITOR_SUPPORTED
bool
default y
config SOC_ADC_PERIPH_NUM
int
default 2
config SOC_ADC_PATT_LEN_MAX
int
default 16
config SOC_ADC_MAX_CHANNEL_NUM
int
default 5
config SOC_ADC_MAX_BITWIDTH
config SOC_ADC_DIGI_CONTROLLER_NUM
int
default 1
config SOC_ADC_PATT_LEN_MAX
int
default 8
config SOC_ADC_DIGI_MAX_BITWIDTH
int
default 12
config SOC_ADC_CALIBRATION_V1_SUPPORTED
bool
default y
config SOC_ADC_DIGI_FILTER_NUM
int
default 2
@ -91,10 +111,6 @@ config SOC_ADC_DIGI_MONITOR_NUM
int
default 2
config SOC_ADC_HW_CALIBRATION_V1
bool
default y
config SOC_ADC_SAMPLE_FREQ_THRES_HIGH
int
default 83333
@ -103,6 +119,10 @@ config SOC_ADC_SAMPLE_FREQ_THRES_LOW
int
default 611
config SOC_ADC_MAX_BITWIDTH
int
default 12
config SOC_APB_BACKUP_DMA
bool
default y

View File

@ -11,6 +11,7 @@
#pragma once
#define SOC_CPU_CORES_NUM 1
#define SOC_ADC_SUPPORTED 1
#define SOC_GDMA_SUPPORTED 1
#define SOC_BT_SUPPORTED 1
#define SOC_DIG_SIGN_SUPPORTED 1
@ -33,20 +34,28 @@
#define SOC_AES_GDMA (1)
/*-------------------------- ADC CAPS -------------------------------*/
/*!< SAR ADC Module*/
#define SOC_ADC_DIG_CTRL_SUPPORTED 1
#define SOC_ADC_ARBITER_SUPPORTED 1
#define SOC_ADC_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_PATT_LEN_MAX (16)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 5 : 1)
#define SOC_ADC_MAX_CHANNEL_NUM (5)
#define SOC_ADC_MAX_BITWIDTH (12)
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
/*!< Digital */
#define SOC_ADC_DIGI_CONTROLLER_NUM (1U)
#define SOC_ADC_PATT_LEN_MAX (8) /*!< One pattern table, each contains 8 items. Each item takes 1 byte */
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_FILTER_NUM (2)
#define SOC_ADC_DIGI_MONITOR_NUM (2)
#define SOC_ADC_HW_CALIBRATION_V1 (1) /*!< support HW offset calibration */
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) 1
//F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611
/*!< RTC */
#define SOC_ADC_MAX_BITWIDTH (12)
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
#define SOC_APB_BACKUP_DMA (1)

View File

@ -81,8 +81,7 @@ INPUT = \
$(PROJECT_PATH)/components/hal/include/hal/lcd_types.h \
$(PROJECT_PATH)/components/hal/include/hal/adc_types.h \
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/adc_channel.h \
$(PROJECT_PATH)/components/driver/include/driver/adc_common.h \
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/adc.h \
$(PROJECT_PATH)/components/driver/include/driver/adc.h \
$(PROJECT_PATH)/components/esp_adc_cal/include/esp_adc_cal.h \
$(PROJECT_PATH)/components/hal/include/hal/dac_types.h \
$(PROJECT_PATH)/components/driver/include/driver/dac_common.h \

View File

@ -161,7 +161,7 @@ Driver Usage
.. only:: esp32c3
The code example for using ADC continuous (DMA) read mode can be found in the :example:`peripherals/adc/esp32c3/adc` directory of ESP-IDF examples.
The code example for using ADC continuous (DMA) read mode can be found in the :example:`peripherals/adc/dma_read` directory of ESP-IDF examples.
.. note:: See :ref:`adc_limitations` for the limitation of using ADC continuous (DMA) read mode.
@ -448,8 +448,6 @@ ADC driver
.. include-build-file:: inc/adc_types.inc
.. include-build-file:: inc/adc_common.inc
.. _adc-api-reference-adc-calibration:
ADC Calibration

View File

@ -0,0 +1,67 @@
# 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 ADC Continuous Read Mode (DMA Mode) to read from GPIO pins via on-chip ADC module(s).
## How to use example
### Hardware Required
* A development board with ESP32, ESP32-S and ESP32-C SoC
* A USB cable for power supply and programming
Please refer to the `channel` array defined in `adc_dma_example_main.c`. These GPIOs should be connected to voltage sources (0 ~ 3.3V). If other ADC unit(s) / channel(s) are selected in your application,
feel free to modify these definitions.
### 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 (338) ADC DMA: adc_pattern[0].atten is :0
I (348) ADC DMA: adc_pattern[0].channel is :2
I (348) ADC DMA: adc_pattern[0].unit is :0
I (358) ADC DMA: adc_pattern[1].atten is :0
I (358) ADC DMA: adc_pattern[1].channel is :3
I (368) ADC DMA: adc_pattern[1].unit is :0
I (368) ADC DMA: adc_pattern[2].atten is :0
I (378) ADC DMA: adc_pattern[2].channel is :0
I (378) ADC DMA: adc_pattern[2].unit is :1
I (388) TASK:: ret is 0, ret_num is 256
I (388) ADC DMA: Unit: 1,_Channel: 2, Value: bec
I (398) ADC DMA: Unit: 2,_Channel: 0, Value: 9cb
I (398) ADC DMA: Unit: 1,_Channel: 3, Value: acb
I (408) ADC DMA: Unit: 2,_Channel: 0, Value: 966
I (408) ADC DMA: Unit: 1,_Channel: 2, Value: b63
I (418) ADC DMA: Unit: 2,_Channel: 0, Value: 8ff
I (418) ADC DMA: Unit: 1,_Channel: 3, Value: a6b
I (428) ADC DMA: Unit: 2,_Channel: 0, Value: 8a2
...
```
## 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.

View File

@ -0,0 +1,176 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdio.h>
#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);
}

View File

@ -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.

View File

@ -1,124 +0,0 @@
#include <string.h>
#include <stdio.h>
#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);
}

View File

@ -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"

View File

@ -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