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
This commit is contained in:
Armando 2022-12-12 11:01:22 +08:00 committed by morris
parent b4c90c44d2
commit ded528e188
8 changed files with 66 additions and 26 deletions

View File

@ -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);

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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";

View File

@ -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

View File

@ -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 <https://www.espressif.com/sites/default/files/documentation/esp32-c3_errata_en.pdf>`. 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.

View File

@ -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
}