From 6fd80903de43515143e7c5c193cd690ee11b95c9 Mon Sep 17 00:00:00 2001 From: Armando Date: Fri, 16 Dec 2022 10:51:22 +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/esp32h2/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 1fd46bf5c2..8f276f697f 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -105,6 +105,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 2b7665fcd6..f28f545ad8 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -50,6 +50,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 4587b1e9f8..4c8bbaf5a9 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -76,6 +76,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/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 2cca44f594..bb88bf0243 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -77,6 +77,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 a9d046b8b4..b1f17f2430 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -86,8 +86,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 4ccca1c6d5..a1d9ca6658 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/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 (2) #define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10) #define SOC_ADC_MAX_CHANNEL_NUM (10) From 1c373cf2935a04b3ddc06012b88a8c7263d6d422 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 6f30edafbe..076acba89e 100644 --- a/docs/en/api-reference/peripherals/adc_continuous.rst +++ b/docs/en/api-reference/peripherals/adc_continuous.rst @@ -207,7 +207,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:: 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. @@ -223,6 +223,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 ^^^^^^^^^^^^^^^^ @@ -253,4 +261,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 bdfbf8965d..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_ESP32H2 || 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_ESP32H2 || 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 bb074904b469550f4e53878b2ec93f0a6b05b1d7 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 | 27 ++++++++++++------- .../test_apps/adc/main/test_adc2_wifi.c | 5 +++- .../test_apps/adc/main/test_adc_performance.c | 4 +++ .../api-reference/peripherals/adc_oneshot.rst | 8 ++++-- .../adc/oneshot_read/main/oneshot_read_main.c | 24 +++++++++++------ 8 files changed, 69 insertions(+), 23 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 d877a1d661..41dc6fffc8 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 04a4e610df..340965d5ad 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 } @@ -252,8 +255,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) && !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) && !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 8b4b1cebf5..d3cf9f462b 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 @@ -292,8 +292,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) && !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) && !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 c73198e429..60b41ac22a 100644 --- a/docs/en/api-reference/peripherals/adc_oneshot.rst +++ b/docs/en/api-reference/peripherals/adc_oneshot.rst @@ -156,10 +156,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:: 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 continuous 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. @@ -207,4 +211,4 @@ API Reference ------------- .. include-build-file:: inc/adc_types.inc -.. include-build-file:: inc/adc_oneshot.inc \ No newline at end of file +.. include-build-file:: inc/adc_oneshot.inc 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 c71c50259b..0e55942b41 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 static int adc_raw[2][10]; static int voltage[2][10]; @@ -65,7 +73,7 @@ void app_main(void) bool do_calibration1 = example_adc_calibration_init(ADC_UNIT_1, ADC_ATTEN_DB_11, &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 = { @@ -80,7 +88,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])); @@ -99,7 +107,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) { @@ -107,7 +115,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 @@ -116,12 +124,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 }