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.