|
|
@@ -19,11 +19,15 @@
|
|
|
#include "freertos/timers.h"
|
|
|
#include "freertos/ringbuf.h"
|
|
|
#include "esp_private/periph_ctrl.h"
|
|
|
-#include "driver/gpio.h"
|
|
|
-#include "driver/adc.h"
|
|
|
+#include "esp_private/adc_private.h"
|
|
|
+#include "esp_private/adc_lock.h"
|
|
|
#include "hal/adc_types.h"
|
|
|
#include "hal/adc_hal.h"
|
|
|
#include "hal/dma_types.h"
|
|
|
+
|
|
|
+#include "driver/gpio.h"
|
|
|
+#include "driver/adc_types_legacy.h"
|
|
|
+
|
|
|
//For calibration
|
|
|
#if CONFIG_IDF_TARGET_ESP32S2
|
|
|
#include "esp_efuse_rtc_table.h"
|
|
|
@@ -37,7 +41,6 @@
|
|
|
#include "hal/spi_types.h"
|
|
|
#include "esp_private/spi_common_internal.h"
|
|
|
#elif CONFIG_IDF_TARGET_ESP32
|
|
|
-#include "hal/i2s_types.h"
|
|
|
#include "driver/i2s_types.h"
|
|
|
#include "soc/i2s_periph.h"
|
|
|
#include "esp_private/i2s_platform.h"
|
|
|
@@ -51,21 +54,6 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
|
|
|
#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.
|
|
|
- * 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
|
|
|
|
|
|
/*---------------------------------------------------------------
|
|
|
@@ -101,10 +89,6 @@ static adc_digi_context_t *s_adc_digi_ctx = NULL;
|
|
|
extern esp_pm_lock_handle_t adc_digi_arbiter_lock;
|
|
|
#endif //CONFIG_PM_ENABLE
|
|
|
|
|
|
-#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
|
|
-uint32_t adc_get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten);
|
|
|
-#endif
|
|
|
-
|
|
|
/*---------------------------------------------------------------
|
|
|
ADC Continuous Read Mode (via DMA)
|
|
|
---------------------------------------------------------------*/
|
|
|
@@ -152,9 +136,54 @@ static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask)
|
|
|
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->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_platform_release_occupation(s_adc_digi_ctx->i2s_host);
|
|
|
+#endif
|
|
|
+ free(s_adc_digi_ctx);
|
|
|
+ s_adc_digi_ctx = NULL;
|
|
|
+
|
|
|
+ periph_module_disable(PERIPH_SARADC_MODULE);
|
|
|
+
|
|
|
+ return ESP_OK;
|
|
|
+}
|
|
|
+
|
|
|
esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
|
|
{
|
|
|
esp_err_t ret = ESP_OK;
|
|
|
+ ESP_RETURN_ON_FALSE((init_config->conv_num_each_intr % SOC_ADC_DIGI_DATA_BYTES_PER_CONV == 0), ESP_ERR_INVALID_ARG, ADC_TAG, "conv_frame_size should be in multiples of `SOC_ADC_DIGI_DATA_BYTES_PER_CONV`");
|
|
|
|
|
|
s_adc_digi_ctx = calloc(1, sizeof(adc_digi_context_t));
|
|
|
if (s_adc_digi_ctx == NULL) {
|
|
|
@@ -282,7 +311,7 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
|
|
#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
|
|
|
+ .eof_num = init_config->conv_num_each_intr / SOC_ADC_DIGI_DATA_BYTES_PER_CONV
|
|
|
};
|
|
|
adc_hal_dma_ctx_config(&s_adc_digi_ctx->hal, &config);
|
|
|
|
|
|
@@ -362,116 +391,83 @@ static IRAM_ATTR bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
|
|
|
|
|
|
esp_err_t adc_digi_start(void)
|
|
|
{
|
|
|
- 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 (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) {
|
|
|
+ adc_lock_acquire(ADC_UNIT_1);
|
|
|
+ }
|
|
|
+ if (s_adc_digi_ctx->use_adc2) {
|
|
|
+ adc_lock_acquire(ADC_UNIT_2);
|
|
|
+ }
|
|
|
|
|
|
#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
|
|
|
|
|
|
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
|
|
- if (s_adc_digi_ctx->use_adc1) {
|
|
|
- uint32_t cal_val = adc_get_calibration_offset(ADC_UNIT_1, s_adc_digi_ctx->adc1_atten);
|
|
|
- adc_hal_set_calibration_param(ADC_UNIT_1, cal_val);
|
|
|
- }
|
|
|
- if (s_adc_digi_ctx->use_adc2) {
|
|
|
- uint32_t cal_val = adc_get_calibration_offset(ADC_UNIT_2, s_adc_digi_ctx->adc2_atten);
|
|
|
- adc_hal_set_calibration_param(ADC_UNIT_2, cal_val);
|
|
|
- }
|
|
|
+ if (s_adc_digi_ctx->use_adc1) {
|
|
|
+ adc_set_hw_calibration_code(ADC_UNIT_1, s_adc_digi_ctx->adc1_atten);
|
|
|
+ }
|
|
|
+ if (s_adc_digi_ctx->use_adc2) {
|
|
|
+ adc_set_hw_calibration_code(ADC_UNIT_2, s_adc_digi_ctx->adc2_atten);
|
|
|
+ }
|
|
|
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
|
|
|
|
|
#if SOC_ADC_ARBITER_SUPPORTED
|
|
|
- adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
|
|
- adc_hal_arbiter_config(&config);
|
|
|
+ adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
|
|
+ adc_hal_arbiter_config(&config);
|
|
|
#endif //#if SOC_ADC_ARBITER_SUPPORTED
|
|
|
|
|
|
- adc_hal_set_controller(ADC_UNIT_1, ADC_HAL_CONTINUOUS_READ_MODE);
|
|
|
- adc_hal_set_controller(ADC_UNIT_2, ADC_HAL_CONTINUOUS_READ_MODE);
|
|
|
+ adc_hal_set_controller(ADC_UNIT_1, ADC_HAL_CONTINUOUS_READ_MODE);
|
|
|
+ adc_hal_set_controller(ADC_UNIT_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);
|
|
|
+ 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);
|
|
|
+ //start conversion
|
|
|
+ adc_hal_digi_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
|
|
|
|
|
|
- }
|
|
|
-#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();
|
|
|
- }
|
|
|
-#endif //#if CONFIG_IDF_TARGET_ESP32S2
|
|
|
return ESP_OK;
|
|
|
}
|
|
|
|
|
|
esp_err_t adc_digi_stop(void)
|
|
|
{
|
|
|
- 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;
|
|
|
+ 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, 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);
|
|
|
+ //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);
|
|
|
+ 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_adc2) {
|
|
|
- SAR_ADC2_LOCK_RELEASE();
|
|
|
- }
|
|
|
- adc_power_release();
|
|
|
+ if (s_adc_digi_ctx->use_adc2) {
|
|
|
+ adc_lock_release(ADC_UNIT_2);
|
|
|
}
|
|
|
-#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();
|
|
|
+ if (s_adc_digi_ctx->use_adc1) {
|
|
|
+ adc_lock_release(ADC_UNIT_1);
|
|
|
}
|
|
|
-#endif //#if CONFIG_IDF_TARGET_ESP32S2
|
|
|
+ adc_power_release();
|
|
|
+
|
|
|
return ESP_OK;
|
|
|
}
|
|
|
|
|
|
@@ -507,50 +503,6 @@ esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_l
|
|
|
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->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_platform_release_occupation(s_adc_digi_ctx->i2s_host);
|
|
|
-#endif
|
|
|
- free(s_adc_digi_ctx);
|
|
|
- s_adc_digi_ctx = NULL;
|
|
|
-
|
|
|
- periph_module_disable(PERIPH_SARADC_MODULE);
|
|
|
-
|
|
|
- return ESP_OK;
|
|
|
-}
|
|
|
-
|
|
|
/*---------------------------------------------------------------
|
|
|
Digital controller setting
|
|
|
---------------------------------------------------------------*/
|
|
|
@@ -573,9 +525,6 @@ esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config)
|
|
|
}
|
|
|
#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");
|
|
|
@@ -589,8 +538,6 @@ esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config)
|
|
|
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;
|
|
|
@@ -626,319 +573,18 @@ esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config)
|
|
|
return ESP_OK;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-#if CONFIG_IDF_TARGET_ESP32C3
|
|
|
-/*---------------------------------------------------------------
|
|
|
- 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_UNIT_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_UNIT_1, channel, true);
|
|
|
- ADC_EXIT_CRITICAL();
|
|
|
- } else { //ADC_UNIT_2
|
|
|
- ADC_ENTER_CRITICAL();
|
|
|
- adc_hal_vref_output(ADC_UNIT_2, channel, true);
|
|
|
- ADC_EXIT_CRITICAL();
|
|
|
- }
|
|
|
-
|
|
|
- ret = adc_digi_gpio_init(ADC_UNIT_2, BIT(channel));
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
|
|
-{
|
|
|
- //On ESP32C3, 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)
|
|
|
-{
|
|
|
- ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_1), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC1 channel error");
|
|
|
- ESP_RETURN_ON_FALSE((atten < SOC_ADC_ATTEN_NUM), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC Atten Err");
|
|
|
-
|
|
|
- esp_err_t ret = ESP_OK;
|
|
|
- s_atten1_single[channel] = atten;
|
|
|
- ret = adc_digi_gpio_init(ADC_UNIT_1, BIT(channel));
|
|
|
-
|
|
|
- adc_hal_calibration_init(ADC_UNIT_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_UNIT_1, atten);
|
|
|
- adc_hal_set_calibration_param(ADC_UNIT_1, cal_val);
|
|
|
-
|
|
|
- ADC_REG_LOCK_ENTER();
|
|
|
- adc_oneshot_ll_set_atten(ADC_UNIT_2, channel, atten);
|
|
|
- adc_hal_convert(ADC_UNIT_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)
|
|
|
-{
|
|
|
- ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_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;
|
|
|
- ret = adc_digi_gpio_init(ADC_UNIT_2, BIT(channel));
|
|
|
-
|
|
|
- adc_hal_calibration_init(ADC_UNIT_2);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
|
|
|
-{
|
|
|
- //On ESP32C3, 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_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
|
|
- adc_hal_arbiter_config(&config);
|
|
|
-
|
|
|
- adc_atten_t atten = s_atten2_single[channel];
|
|
|
- uint32_t cal_val = adc_get_calibration_offset(ADC_UNIT_2, atten);
|
|
|
- adc_hal_set_calibration_param(ADC_UNIT_2, cal_val);
|
|
|
-
|
|
|
- ADC_REG_LOCK_ENTER();
|
|
|
- adc_oneshot_ll_set_atten(ADC_UNIT_2, channel, atten);
|
|
|
- ret = adc_hal_convert(ADC_UNIT_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 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;
|
|
|
-}
|
|
|
-#endif //#if CONFIG_IDF_TARGET_ESP32C3
|
|
|
-
|
|
|
-
|
|
|
-#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
|
|
-/*---------------------------------------------------------------
|
|
|
- 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][SOC_ADC_ATTEN_NUM] = {};
|
|
|
-
|
|
|
-//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
|
|
|
-uint32_t adc_get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten)
|
|
|
-{
|
|
|
- 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];
|
|
|
- }
|
|
|
-
|
|
|
- // check if we can fetch the values from eFuse.
|
|
|
- int version = esp_efuse_rtc_calib_get_ver();
|
|
|
-
|
|
|
- uint32_t init_code = 0;
|
|
|
-
|
|
|
- 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, atten, internal_gnd);
|
|
|
- ADC_EXIT_CRITICAL();
|
|
|
- adc_power_release();
|
|
|
- }
|
|
|
-
|
|
|
- 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;
|
|
|
-}
|
|
|
-
|
|
|
-// Internal function to calibrate PWDET for WiFi
|
|
|
-esp_err_t adc_cal_offset(adc_unit_t adc_n, adc_atten_t atten)
|
|
|
-{
|
|
|
- adc_hal_calibration_init(adc_n);
|
|
|
- uint32_t cal_val = adc_get_calibration_offset(adc_n, atten);
|
|
|
- ADC_ENTER_CRITICAL();
|
|
|
- adc_hal_set_calibration_param(adc_n, cal_val);
|
|
|
- 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)
|
|
|
+/**
|
|
|
+ * @brief This function will be called during start up, to check that adc_continuous driver is not running along with the legacy adc_continuous driver
|
|
|
+ */
|
|
|
+__attribute__((constructor))
|
|
|
+static void check_adc_continuous_driver_conflict(void)
|
|
|
{
|
|
|
- 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_UNIT_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_UNIT_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;
|
|
|
+ // This function was declared as weak here. adc_continuous driver has one implementation.
|
|
|
+ // So if adc_continuous driver is not linked in, then `adc_continuous_new_handle` should be NULL at runtime.
|
|
|
+ extern __attribute__((weak)) esp_err_t adc_continuous_new_handle(const void *init_config, void **ret_handle);
|
|
|
+ if ((void *)adc_continuous_new_handle != NULL) {
|
|
|
+ ESP_EARLY_LOGE(ADC_TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
|
|
|
+ abort();
|
|
|
+ }
|
|
|
+ ESP_EARLY_LOGW(ADC_TAG, "legacy driver is deprecated, please migrate to `esp_adc/adc_continuous.h`");
|
|
|
}
|
|
|
-#endif //#if CONFIG_IDF_TARGET_ESP32C3
|