Skip to content

Commit

Permalink
adc: no longer support adc2 oneshot mode on esp32c3
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Icarus113 committed Dec 16, 2022
1 parent 1c373cf commit bb07490
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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";


Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions components/esp_adc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 7 additions & 0 deletions components/esp_adc/adc_oneshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
27 changes: 17 additions & 10 deletions components/esp_adc/test_apps/adc/main/test_adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -47,15 +50,15 @@ 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 = {
.unit_id = ADC_UNIT_2,
.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 = {
Expand All @@ -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]));
Expand All @@ -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);
Expand All @@ -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
}


Expand Down Expand Up @@ -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
5 changes: 4 additions & 1 deletion components/esp_adc/test_apps/adc/main/test_adc2_wifi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down
4 changes: 4 additions & 0 deletions components/esp_adc/test_apps/adc/main/test_adc_performance.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 6 additions & 2 deletions docs/en/api-reference/peripherals/adc_oneshot.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <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.
Expand Down Expand Up @@ -207,4 +211,4 @@ API Reference
-------------

.. include-build-file:: inc/adc_types.inc
.. include-build-file:: inc/adc_oneshot.inc
.. include-build-file:: inc/adc_oneshot.inc
24 changes: 16 additions & 8 deletions examples/peripherals/adc/oneshot_read/main/oneshot_read_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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 = {
Expand All @@ -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]));
Expand All @@ -99,15 +107,15 @@ 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) {
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc2_cali_handle, adc_raw[1][0], &voltage[1][0]));
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
Expand All @@ -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
}


Expand Down

0 comments on commit bb07490

Please sign in to comment.