From 6aa7091199b7a5f30414f5496f6b6ef15c0566e1 Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 28 Nov 2022 20:48:50 +0800 Subject: [PATCH 1/3] adc: added a soc macro indicating digital controller supported unit --- components/soc/esp32/include/soc/soc_caps.h | 1 + components/soc/esp32c2/include/soc/soc_caps.h | 1 + components/soc/esp32c3/include/soc/soc_caps.h | 1 + components/soc/esp32h4/include/soc/soc_caps.h | 1 + components/soc/esp32s2/include/soc/soc_caps.h | 3 ++- components/soc/esp32s3/include/soc/soc_caps.h | 1 + 6 files changed, 7 insertions(+), 1 deletion(-) diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 7b72bf6dd8..84234e014e 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -107,6 +107,7 @@ #define SOC_ADC_RTC_CTRL_SUPPORTED 1 #define SOC_ADC_DIG_CTRL_SUPPORTED 1 #define SOC_ADC_DMA_SUPPORTED 1 +#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) ((UNIT == 0) ? 1 : 0) #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) diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 47a0d42bac..edc25c1c69 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -52,6 +52,7 @@ #define SOC_ADC_DIG_CTRL_SUPPORTED 1 #define SOC_ADC_FILTER_SUPPORTED 1 #define SOC_ADC_MONITOR_SUPPORTED 1 +#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) 1 //Digital controller supported ADC unit #define SOC_ADC_PERIPH_NUM (1U) #define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (5) #define SOC_ADC_MAX_CHANNEL_NUM (5) diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 604ced866c..c91f707d08 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -78,6 +78,7 @@ #define SOC_ADC_FILTER_SUPPORTED 1 #define SOC_ADC_MONITOR_SUPPORTED 1 #define SOC_ADC_DMA_SUPPORTED 1 +#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) ((UNIT == 0) ? 1 : 0) //Digital controller supported ADC unit #define SOC_ADC_PERIPH_NUM (2) #define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 5 : 1) #define SOC_ADC_MAX_CHANNEL_NUM (5) diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index c209d12f58..be32908b2a 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -79,6 +79,7 @@ #define SOC_ADC_FILTER_SUPPORTED 1 #define SOC_ADC_MONITOR_SUPPORTED 1 #define SOC_ADC_DMA_SUPPORTED 1 +#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) ((UNIT == 0) ? 1 : 0) //Digital controller supported ADC unit #define SOC_ADC_PERIPH_NUM (1U) #define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (5) #define SOC_ADC_MAX_CHANNEL_NUM (5) diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 683e6f681e..40649f2a2b 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -88,8 +88,9 @@ #define SOC_ADC_FILTER_SUPPORTED 1 #define SOC_ADC_MONITOR_SUPPORTED 1 #define SOC_ADC_DMA_SUPPORTED 1 +#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) 1 //Digital controller supported ADC unit #define SOC_ADC_PERIPH_NUM (2) -#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10) +#define SOC_ADC_CHANNEL_NUM(UNIT) (10) #define SOC_ADC_MAX_CHANNEL_NUM (10) #define SOC_ADC_ATTEN_NUM (4) diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index d7864fa6e2..c96703d5a8 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -81,6 +81,7 @@ #define SOC_ADC_FILTER_SUPPORTED 1 #define SOC_ADC_MONITOR_SUPPORTED 1 #define SOC_ADC_DMA_SUPPORTED 1 +#define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) ((UNIT == 0) ? 1 : 0) //Digital controller supported ADC unit #define SOC_ADC_PERIPH_NUM (2) #define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10) #define SOC_ADC_MAX_CHANNEL_NUM (10) From b4c90c44d21cf34f16f54856c671b5d39497f4e7 Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 12 Dec 2022 11:00:47 +0800 Subject: [PATCH 2/3] adc: no longer support adc2 continuous mode on esp32c3 and esp32s3 Due to HW limitation, we don't support this anymore. On s3 and c3, ADC2 under continuous mode is not stable. However, you can enable CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 to force use ADC2. Refer to errata to know more details: https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_en.pdf https://www.espressif.com/sites/default/files/documentation/esp32-c3_errata_en.pdf --- components/esp_adc/Kconfig | 10 +++ components/esp_adc/adc_continuous.c | 21 +++-- .../peripherals/adc_continuous.rst | 12 ++- .../main/continuous_read_main.c | 76 ++++++++----------- 4 files changed, 66 insertions(+), 53 deletions(-) diff --git a/components/esp_adc/Kconfig b/components/esp_adc/Kconfig index 4d8e4205e8..805549c5eb 100644 --- a/components/esp_adc/Kconfig +++ b/components/esp_adc/Kconfig @@ -55,5 +55,15 @@ menu "ADC and ADC Calibration" Disable this option so as to measure the output of DAC by internal ADC, for test usage. + config ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 + depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 + bool "Force use ADC2 continumous mode on ESP32S3 or ESP32C3" + default n + help + On ESP32C3 and ESP32S3, ADC2 Digital Controller is not stable. Therefore, + ADC2 continuous mode is not suggested on ESP32S3 and ESP32C3 + + If you stick to this, you can enable this option to force use ADC2 under above conditions. + For more details, you can search for errata on espressif website. endmenu diff --git a/components/esp_adc/adc_continuous.c b/components/esp_adc/adc_continuous.c index 73c00e6cf9..efd42cc7ec 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -530,16 +530,27 @@ esp_err_t adc_continuous_config(adc_continuous_handle_t handle, const adc_contin //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"); +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + //we add this error log to hint users what happened + if (SOC_ADC_DIG_SUPPORTED_UNIT(config->adc_pattern[i].unit) == 0) { + ESP_LOGE(ADC_TAG, "ADC2 continuous mode is no longer supported, please use ADC1. Search for errata on espressif website for more details. You can enable CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 to force use ADC2"); + } +#endif //CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + +#if !CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 + /** + * On all continuous mode supported chips, we will always check the unit to see if it's a continuous mode supported unit. + * However, on ESP32C3 and ESP32S3, we will jump this check, if `CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` is enabled. + */ + ESP_RETURN_ON_FALSE(SOC_ADC_DIG_SUPPORTED_UNIT(config->adc_pattern[i].unit), ESP_ERR_INVALID_ARG, ADC_TAG, "Only support using ADC1 DMA mode"); +#endif //#if !CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 } -#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 diff --git a/docs/en/api-reference/peripherals/adc_continuous.rst b/docs/en/api-reference/peripherals/adc_continuous.rst index 125237d43e..5f7d8fc182 100644 --- a/docs/en/api-reference/peripherals/adc_continuous.rst +++ b/docs/en/api-reference/peripherals/adc_continuous.rst @@ -209,7 +209,7 @@ Hardware Limitations - Random Number Generator uses ADC as an input source. When ADC continuous mode driver works, the random number generated from RNG will be less random. -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 +.. only:: esp32 or esp32s2 - ADC2 is also used by the Wi-Fi. :cpp:func:`adc_continuous_start` has provided the protection between Wi-Fi driver and ADC continuous mode driver. @@ -225,6 +225,14 @@ Hardware Limitations - ADC continuous mode driver uses SPI3 peripheral as hardware DMA fifo. Therefore, if SPI3 is in use already, the :cpp:func:`adc_continuous_new_handle` will return :c:macro:`ESP_ERR_NOT_FOUND`. +.. only:: esp32c3 + + - ADC2 continuous mode is no longer supported, due to hardware limitation. The results are not stable. This issue can be found in `ESP32C3 Errata `. For compatibility, you can enable :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` to force use ADC2. + +.. only:: esp32s3 + + - ADC2 continuous mode is no longer supported, due to hardware limitation. The results are not stable. This issue can be found in `ESP32S3 Errata `. For compatibility, you can enable :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` to force use ADC2. + Power Management ^^^^^^^^^^^^^^^^ @@ -255,4 +263,4 @@ Application Examples API Reference ------------- -.. include-build-file:: inc/adc_continuous.inc \ No newline at end of file +.. include-build-file:: inc/adc_continuous.inc diff --git a/examples/peripherals/adc/continuous_read/main/continuous_read_main.c b/examples/peripherals/adc/continuous_read/main/continuous_read_main.c index 27b94216a3..1f2c1ad15f 100644 --- a/examples/peripherals/adc/continuous_read/main/continuous_read_main.c +++ b/examples/peripherals/adc/continuous_read/main/continuous_read_main.c @@ -14,30 +14,19 @@ #include "esp_adc/adc_continuous.h" #define EXAMPLE_READ_LEN 256 -#define GET_UNIT(x) ((x>>3) & 0x1) +#define EXAMPLE_ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1 + +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 +#define EXAMPLE_ADC_USE_OUTPUT_TYPE1 1 +#define EXAMPLE_ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1 +#else +#define EXAMPLE_ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 +#endif #if CONFIG_IDF_TARGET_ESP32 -#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_CONV_MODE ADC_CONV_BOTH_UNIT -#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H4 || CONFIG_IDF_TARGET_ESP32C2 -#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_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_ESP32H4 || CONFIG_IDF_TARGET_ESP32C2 -static adc_channel_t channel[3] = {ADC_CHANNEL_2, ADC_CHANNEL_3, (ADC_CHANNEL_0 | 1 << 3)}; -#endif -#if CONFIG_IDF_TARGET_ESP32S2 -static adc_channel_t channel[3] = {ADC_CHANNEL_2, ADC_CHANNEL_3, (ADC_CHANNEL_0 | 1 << 3)}; -#endif -#if CONFIG_IDF_TARGET_ESP32 -static adc_channel_t channel[1] = {ADC_CHANNEL_7}; +static adc_channel_t channel[2] = {ADC_CHANNEL_6, ADC_CHANNEL_7}; +#else +static adc_channel_t channel[2] = {ADC_CHANNEL_2, ADC_CHANNEL_3}; #endif static TaskHandle_t s_task_handle; @@ -65,14 +54,14 @@ static void continuous_adc_init(adc_channel_t *channel, uint8_t channel_num, adc adc_continuous_config_t dig_cfg = { .sample_freq_hz = 20 * 1000, - .conv_mode = ADC_CONV_MODE, - .format = ADC_OUTPUT_TYPE, + .conv_mode = EXAMPLE_ADC_CONV_MODE, + .format = EXAMPLE_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 unit = ADC_UNIT_1; uint8_t ch = channel[i] & 0x7; adc_pattern[i].atten = ADC_ATTEN_DB_0; adc_pattern[i].channel = ch; @@ -89,16 +78,20 @@ static void continuous_adc_init(adc_channel_t *channel, uint8_t channel_num, adc *out_handle = handle; } -#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; +#if EXAMPLE_ADC_USE_OUTPUT_TYPE1 + if (data->type1.channel >= SOC_ADC_CHANNEL_NUM(ADC_UNIT_1)) { + return false; + } +#else + if (data->type2.channel >= SOC_ADC_CHANNEL_NUM(ADC_UNIT_1)) { + return false; + } +#endif return true; } -#endif void app_main(void) { @@ -136,24 +129,15 @@ void app_main(void) ESP_LOGI("TASK", "ret is %x, ret_num is %"PRIu32, ret, ret_num); for (int i = 0; i < ret_num; i += SOC_ADC_DIGI_RESULT_BYTES) { 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 { - 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) { + if (check_valid_data(p)) { + #if EXAMPLE_ADC_USE_OUTPUT_TYPE1 ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 1, p->type1.channel, p->type1.data); + #else + ESP_LOGI(TAG, "Unit: %d,_Channel: %d, Value: %x", 1, p->type2.channel, p->type2.data); + #endif + } else { + ESP_LOGI(TAG, "Invalid data"); } - #endif //#if CONFIG_IDF_TARGET_ESP32S2 - #endif } /** * Because printing is slow, so every time you call `ulTaskNotifyTake`, it will immediately return. From ded528e1883fc8ad04ea1af52037b43a36ead6ac Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 12 Dec 2022 11:01:22 +0800 Subject: [PATCH 3/3] adc: no longer support adc2 oneshot mode on esp32c3 Due to HW limitation, we don't support this anymore. On c3, ADC2 under oneshot mode is not stable. However, you can enable CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3 to force use ADC2. Refer to errata to know more details: https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_en.pdf https://www.espressif.com/sites/default/files/documentation/esp32-c3_errata_en.pdf --- .../legacy_adc_driver/main/test_legacy_adc.c | 7 +++-- components/esp_adc/Kconfig | 10 +++++++ components/esp_adc/adc_oneshot.c | 7 +++++ .../esp_adc/test_apps/adc/main/test_adc.c | 28 +++++++++++-------- .../test_apps/adc/main/test_adc2_wifi.c | 5 +++- .../test_apps/adc/main/test_adc_performance.c | 5 ++-- .../api-reference/peripherals/adc_oneshot.rst | 6 +++- .../adc/oneshot_read/main/oneshot_read_main.c | 24 ++++++++++------ 8 files changed, 66 insertions(+), 26 deletions(-) diff --git a/components/driver/test_apps/legacy_adc_driver/main/test_legacy_adc.c b/components/driver/test_apps/legacy_adc_driver/main/test_legacy_adc.c index 0039001bcf..c76a0a8e53 100644 --- a/components/driver/test_apps/legacy_adc_driver/main/test_legacy_adc.c +++ b/components/driver/test_apps/legacy_adc_driver/main/test_legacy_adc.c @@ -66,6 +66,9 @@ #define ADC1_TEST_CHAN0 ADC1_CHANNEL_2 #endif +//ESP32C3 ADC2 oneshot mode is not supported anymore +#define ADC_TEST_ADC2 ((SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3) + const __attribute__((unused)) static char *TAG = "TEST_ADC_LEGACY"; @@ -94,7 +97,7 @@ TEST_CASE("Legacy ADC oneshot high/low test", "[legacy_adc_oneshot]") //ADC1 config TEST_ESP_OK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT)); TEST_ESP_OK(adc1_config_channel_atten(ADC1_TEST_CHAN0, ADC_ATTEN_DB_11)); -#if (SOC_ADC_PERIPH_NUM >= 2) +#if ADC_TEST_ADC2 //ADC2 config TEST_ESP_OK(adc2_config_channel_atten(ADC2_TEST_CHAN0, ADC_ATTEN_DB_11)); #endif @@ -109,7 +112,7 @@ TEST_CASE("Legacy ADC oneshot high/low test", "[legacy_adc_oneshot]") ESP_LOGI(TAG, "ADC%d Channel %d raw: %d\n", ADC_UNIT_1, ADC1_TEST_CHAN0, adc_raw); TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, adc_raw); -#if (SOC_ADC_PERIPH_NUM >= 2) +#if ADC_TEST_ADC2 test_adc_set_io_level(ADC_UNIT_2, (adc2_channel_t)ADC2_TEST_CHAN0, 0); TEST_ESP_OK(adc2_get_raw(ADC2_TEST_CHAN0, ADC_WIDTH_BIT_DEFAULT, &adc_raw)); ESP_LOGI(TAG, "ADC%d Channel %d raw: %d\n", ADC_UNIT_2, ADC2_TEST_CHAN0, adc_raw); diff --git a/components/esp_adc/Kconfig b/components/esp_adc/Kconfig index 805549c5eb..16ca097037 100644 --- a/components/esp_adc/Kconfig +++ b/components/esp_adc/Kconfig @@ -66,4 +66,14 @@ menu "ADC and ADC Calibration" If you stick to this, you can enable this option to force use ADC2 under above conditions. For more details, you can search for errata on espressif website. + config ADC_ONESHOT_FORCE_USE_ADC2_ON_C3 + depends on IDF_TARGET_ESP32C3 + bool "Force use ADC2 oneshot mode on ESP32C3" + default n + help + On ESP32C3, ADC2 Digital Controller is not stable. Therefore, + ADC2 oneshot mode is not suggested on ESP32C3 + + If you stick to this, you can enable this option to force use ADC2 under above conditions. + For more details, you can search for errata on espressif website. endmenu diff --git a/components/esp_adc/adc_oneshot.c b/components/esp_adc/adc_oneshot.c index f88e5a1bf7..743b76cec9 100644 --- a/components/esp_adc/adc_oneshot.c +++ b/components/esp_adc/adc_oneshot.c @@ -77,6 +77,13 @@ esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, a adc_oneshot_unit_ctx_t *unit = NULL; ESP_GOTO_ON_FALSE(init_config && ret_unit, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument: null pointer"); ESP_GOTO_ON_FALSE(init_config->unit_id < SOC_ADC_PERIPH_NUM, ESP_ERR_INVALID_ARG, err, TAG, "invalid unit"); +#if CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3 + /** + * We only check this on ESP32C3, because other adc units are no longer supported on later chips + * If CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3 is enabled, we jump this check + */ + ESP_GOTO_ON_FALSE(SOC_ADC_DIG_SUPPORTED_UNIT(init_config->unit_id), ESP_ERR_INVALID_ARG, err, TAG, "adc unit not supported"); +#endif unit = heap_caps_calloc(1, sizeof(adc_oneshot_unit_ctx_t), ADC_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, TAG, "no mem for unit"); diff --git a/components/esp_adc/test_apps/adc/main/test_adc.c b/components/esp_adc/test_apps/adc/main/test_adc.c index e49715fa8f..d4fc8409db 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc.c +++ b/components/esp_adc/test_apps/adc/main/test_adc.c @@ -35,6 +35,9 @@ static const char *TAG_CH[2][10] = {{"ADC1_CH2", "ADC1_CH3"}, {"ADC2_CH0"}}; /*--------------------------------------------------------------- ADC Oneshot High / Low test ---------------------------------------------------------------*/ +//ESP32C3 ADC2 oneshot mode is not supported anymore +#define ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 ((SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3) + TEST_CASE("ADC oneshot high/low test", "[adc_oneshot]") { static int adc_raw[2][10]; @@ -47,7 +50,7 @@ TEST_CASE("ADC oneshot high/low test", "[adc_oneshot]") }; TEST_ESP_OK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); -#if (SOC_ADC_PERIPH_NUM >= 2) +#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 //-------------ADC2 Init---------------// adc_oneshot_unit_handle_t adc2_handle; adc_oneshot_unit_init_cfg_t init_config2 = { @@ -55,7 +58,7 @@ TEST_CASE("ADC oneshot high/low test", "[adc_oneshot]") .ulp_mode = ADC_ULP_MODE_DISABLE, }; TEST_ESP_OK(adc_oneshot_new_unit(&init_config2, &adc2_handle)); -#endif //#if (SOC_ADC_PERIPH_NUM >= 2) +#endif //#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 //-------------ADC1 TEST Channel 0 Config---------------// adc_oneshot_chan_cfg_t config = { @@ -67,10 +70,10 @@ TEST_CASE("ADC oneshot high/low test", "[adc_oneshot]") //-------------ADC1 TEST Channel 1 Config---------------// TEST_ESP_OK(adc_oneshot_config_channel(adc1_handle, ADC1_TEST_CHAN1, &config)); -#if (SOC_ADC_PERIPH_NUM >= 2) +#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 //-------------ADC2 TEST Channel 0 Config---------------// TEST_ESP_OK(adc_oneshot_config_channel(adc2_handle, ADC2_TEST_CHAN0, &config)); -#endif //#if (SOC_ADC_PERIPH_NUM >= 2) +#endif //#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 0); TEST_ESP_OK(adc_oneshot_read(adc1_handle, ADC1_TEST_CHAN0, &adc_raw[0][0])); @@ -82,12 +85,12 @@ TEST_CASE("ADC oneshot high/low test", "[adc_oneshot]") ESP_LOGI(TAG_CH[0][1], "raw data: %d", adc_raw[0][1]); TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, adc_raw[0][1]); -#if (SOC_ADC_PERIPH_NUM >= 2) +#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 test_adc_set_io_level(ADC_UNIT_2, ADC2_TEST_CHAN0, 0); TEST_ESP_OK(adc_oneshot_read(adc2_handle, ADC2_TEST_CHAN0, &adc_raw[1][0])); ESP_LOGI(TAG_CH[1][0], "raw data: %d", adc_raw[1][0]); TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, adc_raw[1][0]); -#endif //#if (SOC_ADC_PERIPH_NUM >= 2) +#endif //#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 1); @@ -100,18 +103,18 @@ TEST_CASE("ADC oneshot high/low test", "[adc_oneshot]") ESP_LOGI(TAG_CH[0][1], "raw data: %d", adc_raw[0][1]); TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, adc_raw[0][1]); -#if (SOC_ADC_PERIPH_NUM >= 2) +#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 test_adc_set_io_level(ADC_UNIT_2, ADC2_TEST_CHAN0, 1); TEST_ESP_OK(adc_oneshot_read(adc2_handle, ADC2_TEST_CHAN0, &adc_raw[1][0])); ESP_LOGI(TAG_CH[1][0], "raw data: %d", adc_raw[1][0]); TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, adc_raw[1][0]); -#endif //#if (SOC_ADC_PERIPH_NUM >= 2) +#endif //#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 TEST_ESP_OK(adc_oneshot_del_unit(adc1_handle)); -#if (SOC_ADC_PERIPH_NUM >= 2) +#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 TEST_ESP_OK(adc_oneshot_del_unit(adc2_handle)); -#endif //#if (SOC_ADC_PERIPH_NUM >= 2) +#endif //#if ADC_TEST_ONESHOT_HIGH_LOW_TEST_ADC2 } @@ -251,11 +254,12 @@ TEST_CASE("test ADC1 Single Read with Light Sleep", "[adc][manul][ignore]") s_adc_oneshot_with_sleep(ADC_UNIT_1, ADC1_SLEEP_TEST_CHAN); } -#if (SOC_ADC_PERIPH_NUM >= 2) +#if (SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3 +//ESP32C3 ADC2 oneshot mode is not supported anymore TEST_CASE("test ADC2 Single Read with Light Sleep", "[adc][manul][ignore]") { s_adc_oneshot_with_sleep(ADC_UNIT_2, ADC2_SLEEP_TEST_CHAN); } -#endif //#if (SOC_ADC_PERIPH_NUM >= 2) +#endif //#if (SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3 #endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED diff --git a/components/esp_adc/test_apps/adc/main/test_adc2_wifi.c b/components/esp_adc/test_apps/adc/main/test_adc2_wifi.c index ae1fa35f82..8a25812526 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc2_wifi.c +++ b/components/esp_adc/test_apps/adc/main/test_adc2_wifi.c @@ -18,7 +18,10 @@ #include "test_common_adc.h" #include "test_utils.h" -#if (SOC_ADC_PERIPH_NUM > 1) +/** + * On ESP32C3, ADC2 is no longer supported, due to its HW limitation. + */ +#if (SOC_ADC_PERIPH_NUM > 1) && !CONFIG_IDF_TARGET_ESP32C3 static const char* TAG = "test_adc2"; diff --git a/components/esp_adc/test_apps/adc/main/test_adc_performance.c b/components/esp_adc/test_apps/adc/main/test_adc_performance.c index 1eccc0c8b8..314b59aef9 100644 --- a/components/esp_adc/test_apps/adc/main/test_adc_performance.c +++ b/components/esp_adc/test_apps/adc/main/test_adc_performance.c @@ -282,11 +282,12 @@ TEST_CASE("ADC1 Calibration Speed", "[adc][ignore][manual]") s_adc_cali_speed(ADC_UNIT_1, ADC1_CALI_SPEED_TEST_CHAN0); } -#if (SOC_ADC_PERIPH_NUM >= 2) +#if (SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3 +//ESP32C3 ADC2 oneshot mode is not supported anymore TEST_CASE("ADC2 Calibration Speed", "[adc][ignore][manual]") { s_adc_cali_speed(ADC_UNIT_2, ADC2_CALI_SPEED_TEST_CHAN0); } -#endif //#if (SOC_ADC_PERIPH_NUM >= 2) +#endif //#if (SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3 #endif //#if CONFIG_IDF_TARGET_ESP32 || SOC_ADC_CALIBRATION_V1_SUPPORTED diff --git a/docs/en/api-reference/peripherals/adc_oneshot.rst b/docs/en/api-reference/peripherals/adc_oneshot.rst index c6800b801b..8a8bdf2d24 100644 --- a/docs/en/api-reference/peripherals/adc_oneshot.rst +++ b/docs/en/api-reference/peripherals/adc_oneshot.rst @@ -154,10 +154,14 @@ Hardware Limitations - A specific ADC unit can only work under one operating mode at any one time, either continuous mode or oneshot mode. :cpp:func:`adc_oneshot_read` has provided the protection. -.. only:: esp32 or esp32s2 or esp32c3 or esp32s3 +.. only:: esp32 or esp32s2 or esp32s3 - ADC2 is also used by the Wi-Fi. :cpp:func:`adc_oneshot_read` has provided the protection between Wi-Fi driver and ADC oneshot mode driver. +.. only:: esp32c3 + + - ADC2 oneshot mode is no longer supported, due to hardware limitation. The results are not stable. This issue can be found in `ESP32C3 Errata `. For compatibility, you can enable :ref:`CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3` to force use ADC2. + .. only:: esp32 - ESP32 DevKitC: GPIO 0 cannot be used due to external auto program circuits. diff --git a/examples/peripherals/adc/oneshot_read/main/oneshot_read_main.c b/examples/peripherals/adc/oneshot_read/main/oneshot_read_main.c index 2ff69f4f5b..dd831b1f89 100644 --- a/examples/peripherals/adc/oneshot_read/main/oneshot_read_main.c +++ b/examples/peripherals/adc/oneshot_read/main/oneshot_read_main.c @@ -28,14 +28,22 @@ const static char *TAG = "EXAMPLE"; #define EXAMPLE_ADC1_CHAN1 ADC_CHANNEL_3 #endif -#if (SOC_ADC_PERIPH_NUM >= 2) +#if (SOC_ADC_PERIPH_NUM >= 2) && !CONFIG_IDF_TARGET_ESP32C3 +/** + * On ESP32C3, ADC2 is no longer supported, due to its HW limitation. + * Search for errata on espressif website for more details. + */ +#define EXAMPLE_USE_ADC2 1 +#endif + +#if EXAMPLE_USE_ADC2 //ADC2 Channels #if CONFIG_IDF_TARGET_ESP32 #define EXAMPLE_ADC2_CHAN0 ADC_CHANNEL_0 #else #define EXAMPLE_ADC2_CHAN0 ADC_CHANNEL_0 #endif -#endif +#endif //#if EXAMPLE_USE_ADC2 #define EXAMPLE_ADC_ATTEN ADC_ATTEN_DB_11 @@ -67,7 +75,7 @@ void app_main(void) bool do_calibration1 = example_adc_calibration_init(ADC_UNIT_1, EXAMPLE_ADC_ATTEN, &adc1_cali_handle); -#if (SOC_ADC_PERIPH_NUM >= 2) +#if EXAMPLE_USE_ADC2 //-------------ADC2 Init---------------// adc_oneshot_unit_handle_t adc2_handle; adc_oneshot_unit_init_cfg_t init_config2 = { @@ -82,7 +90,7 @@ void app_main(void) //-------------ADC2 Config---------------// ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, EXAMPLE_ADC2_CHAN0, &config)); -#endif //#if (SOC_ADC_PERIPH_NUM >= 2) +#endif //#if EXAMPLE_USE_ADC2 while (1) { ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, EXAMPLE_ADC1_CHAN0, &adc_raw[0][0])); @@ -101,7 +109,7 @@ void app_main(void) } vTaskDelay(pdMS_TO_TICKS(1000)); -#if (SOC_ADC_PERIPH_NUM >= 2) +#if EXAMPLE_USE_ADC2 ESP_ERROR_CHECK(adc_oneshot_read(adc2_handle, EXAMPLE_ADC2_CHAN0, &adc_raw[1][0])); ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_2 + 1, EXAMPLE_ADC2_CHAN0, adc_raw[1][0]); if (do_calibration2) { @@ -109,7 +117,7 @@ void app_main(void) ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_2 + 1, EXAMPLE_ADC2_CHAN0, voltage[1][0]); } vTaskDelay(pdMS_TO_TICKS(1000)); -#endif //#if (SOC_ADC_PERIPH_NUM >= 2) +#endif //#if EXAMPLE_USE_ADC2 } //Tear Down @@ -118,12 +126,12 @@ void app_main(void) example_adc_calibration_deinit(adc1_cali_handle); } -#if (SOC_ADC_PERIPH_NUM >= 2) +#if EXAMPLE_USE_ADC2 ESP_ERROR_CHECK(adc_oneshot_del_unit(adc2_handle)); if (do_calibration2) { example_adc_calibration_deinit(adc2_cali_handle); } -#endif //#if (SOC_ADC_PERIPH_NUM >= 2) +#endif //#if EXAMPLE_USE_ADC2 }