From 1c373cf2935a04b3ddc06012b88a8c7263d6d422 Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 12 Dec 2022 11:00:47 +0800 Subject: [PATCH] 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.