diff --git a/components/driver/Kconfig b/components/driver/Kconfig index 127c09350a..281c85e9cb 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -19,6 +19,17 @@ menu "Driver configurations" For testing, disable this option so that we can measure the output of DAC by internal ADC. + 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 # ADC Configuration menu "MCPWM configuration" diff --git a/components/driver/adc.c b/components/driver/adc.c index b28b9d919a..b32df63e0d 100644 --- a/components/driver/adc.c +++ b/components/driver/adc.c @@ -569,8 +569,21 @@ esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config) #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 +#endif //#if CONFIG_IDF_TARGET_ESP32 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 ESP_RETURN_ON_FALSE(config->conv_limit_en == 1, ESP_ERR_INVALID_ARG, ADC_TAG, "`conv_limit_en` should be set to 1"); diff --git a/docs/en/api-reference/peripherals/adc.rst b/docs/en/api-reference/peripherals/adc.rst index 8ff7d834ec..6f3b98ccb4 100644 --- a/docs/en/api-reference/peripherals/adc.rst +++ b/docs/en/api-reference/peripherals/adc.rst @@ -126,9 +126,16 @@ ADC Limitations .. only:: esp32c3 - A specific ADC module can only work under one operating mode at any one time, either Continuous Read Mode or Single Read Mode. - - ADC1 and ADC2 can not work under Singel Read Mode simultaneously. One of them will get blocked until another one finishes. - For continuous (DMA) read mode, the ADC sampling frequency (the ``sample_freq_hz`` member of :cpp:type:`adc_digi_config_t`) should be within ``SOC_ADC_SAMPLE_FREQ_THRES_LOW`` and ``SOC_ADC_SAMPLE_FREQ_THRES_HIGH``. + .. only:: esp32c3 + + - ADC2 continuous (DMA) 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. + Driver Usage ------------ diff --git a/examples/peripherals/adc/dma_read/main/adc_dma_example_main.c b/examples/peripherals/adc/dma_read/main/adc_dma_example_main.c index f73095ff1e..2d9360adf0 100644 --- a/examples/peripherals/adc/dma_read/main/adc_dma_example_main.c +++ b/examples/peripherals/adc/dma_read/main/adc_dma_example_main.c @@ -17,41 +17,37 @@ #define GET_UNIT(x) ((x>>3) & 0x1) #if CONFIG_IDF_TARGET_ESP32 -#define ADC_RESULT_BYTE 2 -#define ADC_CONV_LIMIT_EN 1 //For ESP32, this should always be set to 1 -#define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1 //ESP32 only supports ADC1 DMA mode -#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1 +#define ADC_RESULT_BYTE 2 +#define ADC_CONV_LIMIT_EN 1 //For ESP32, this should always be set to 1 +#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1 +#define EXAMPLE_ADC_USE_OUTPUT_TYPE1 1 +#define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1 #elif CONFIG_IDF_TARGET_ESP32S2 -#define ADC_RESULT_BYTE 2 -#define ADC_CONV_LIMIT_EN 0 -#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 -#define ADC_RESULT_BYTE 4 -#define ADC_CONV_LIMIT_EN 0 -#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_RESULT_BYTE 4 -#define ADC_CONV_LIMIT_EN 0 -#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT -#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 +#define ADC_RESULT_BYTE 2 +#define ADC_CONV_LIMIT_EN 0 +#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 +#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32S3 +#define ADC_RESULT_BYTE 4 +#define ADC_CONV_LIMIT_EN 0 +#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 +#define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1 #endif -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 -static uint16_t adc1_chan_mask = BIT(2) | BIT(3); -static uint16_t adc2_chan_mask = BIT(0); -static adc_channel_t channel[3] = {ADC1_CHANNEL_2, ADC1_CHANNEL_3, (ADC2_CHANNEL_0 | 1 << 3)}; -#endif -#if CONFIG_IDF_TARGET_ESP32S2 -static uint16_t adc1_chan_mask = BIT(2) | BIT(3); -static uint16_t adc2_chan_mask = BIT(0); -static adc_channel_t channel[3] = {ADC1_CHANNEL_2, ADC1_CHANNEL_3, (ADC2_CHANNEL_0 | 1 << 3)}; -#endif #if CONFIG_IDF_TARGET_ESP32 static uint16_t adc1_chan_mask = BIT(7); static uint16_t adc2_chan_mask = 0; static adc_channel_t channel[1] = {ADC1_CHANNEL_7}; + +#elif CONFIG_IDF_TARGET_ESP32S2 +static uint16_t adc1_chan_mask = BIT(2) | BIT(3); +static uint16_t adc2_chan_mask = BIT(0); +static adc_channel_t channel[3] = {ADC1_CHANNEL_2, ADC1_CHANNEL_3, (ADC2_CHANNEL_0 | 1 << 3)}; + +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 +static uint16_t adc1_chan_mask = BIT(2) | BIT(3); +static uint16_t adc2_chan_mask = 0; +static adc_channel_t channel[2] = {ADC1_CHANNEL_2, ADC1_CHANNEL_3}; #endif static const char *TAG = "ADC DMA"; @@ -92,16 +88,24 @@ static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask ESP_ERROR_CHECK(adc_digi_controller_configure(&dig_cfg)); } -#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 + int unit = data->type2.unit; + if (unit >= ADC_UNIT_2) { + return false; + } + if (data->type2.channel >= SOC_ADC_CHANNEL_NUM(unit)) { + return false; + } +#endif return true; } -#endif void app_main(void) { @@ -137,25 +141,15 @@ void app_main(void) ESP_LOGI("TASK:", "ret is %x, ret_num is %d", ret, ret_num); for (int i = 0; i < ret_num; i += ADC_RESULT_BYTE) { 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 { - // abort(); - 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", p->type2.unit + 1, p->type2.channel, p->type2.data); + #endif + } else { + ESP_LOGI(TAG, "Invalid data"); } - #endif //#if CONFIG_IDF_TARGET_ESP32S2 - #endif } //See `note 1` vTaskDelay(1);