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 4d8e4205e8..16ca097037 100644 --- a/components/esp_adc/Kconfig +++ b/components/esp_adc/Kconfig @@ -55,5 +55,25 @@ 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. + + 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_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/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/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) 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/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/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. 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 }