From bb074904b469550f4e53878b2ec93f0a6b05b1d7 Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 12 Dec 2022 11:01:22 +0800 Subject: [PATCH] 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 d877a1d66190..41dc6fffc80c 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 805549c5ebda..16ca09703739 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 f88e5a1bf7fe..743b76cec930 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 04a4e610df83..340965d5adda 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 ae1fa35f82a7..8a25812526ce 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 8b4b1cebf5e3..d3cf9f462bc4 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 c73198e429f8..60b41ac22a79 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 c71c50259bd9..0e55942b419a 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 }