ESP32-S2 : ADC unit can not be controlled by the ULP RISCV (ADC_ULP_MODE_RISCV)
Posted: Fri May 09, 2025 8:58 am
Hi all,
I encountered an issue on the ESP32-S2-MINI2 (ESP-IDF Release v5.4.1) that the ULP is not able to read any ADC value unless I configure it as ADC_ULP_MODE_DISABLE.
ADC unit (GPIO9-ADC1_CHN8)
ULP RISCV - ADC_ULP_MODE_DISABLE - returns new and fresh values
ULP RISCV - ADC_ULP_MODE_RISCV - returns always 8191
The main issue is that the ADC_ULP_MODE_DISABLE configuration does not work in light sleep. It will always return the last ADC value, then it is stale. This is already known and highlighted in several tickets.
I have tried all ESP IDF ULP RISCV examples, all workarounds from different tickets regarding compiler options, power modes/domains, etc., and also the ADC Legacy code.
The ADC configuration comes down to this function:
This shows that the ULP is unable to control the RTC ADC, or there is a missing configuration that needs to be added.
Can someone confirm that the ULP RISCV can read new and fresh ADC data when the ulp_adc_init is used? What could cause this issue?
Bug ticket created https://github.com/espressif/esp-idf/issues/15927
Thank you
I encountered an issue on the ESP32-S2-MINI2 (ESP-IDF Release v5.4.1) that the ULP is not able to read any ADC value unless I configure it as ADC_ULP_MODE_DISABLE.
ADC unit (GPIO9-ADC1_CHN8)
ULP RISCV - ADC_ULP_MODE_DISABLE - returns new and fresh values
ULP RISCV - ADC_ULP_MODE_RISCV - returns always 8191
The main issue is that the ADC_ULP_MODE_DISABLE configuration does not work in light sleep. It will always return the last ADC value, then it is stale. This is already known and highlighted in several tickets.
I have tried all ESP IDF ULP RISCV examples, all workarounds from different tickets regarding compiler options, power modes/domains, etc., and also the ADC Legacy code.
The ADC configuration comes down to this function:
Code: Select all
__attribute__((always_inline))
static inline void adc_ll_set_controller(adc_unit_t adc_n, adc_ll_controller_t ctrl)
{
if (adc_n == ADC_UNIT_1) {
switch (ctrl) {
case ADC_LL_CTRL_RTC:
SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
break;
case ADC_LL_CTRL_ULP:
SENS.sar_meas1_mux.sar1_dig_force = 0; // 1: Select digital control; 0: Select RTC control.
SENS.sar_meas1_ctrl2.meas1_start_force = 0; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 0; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
break;
case ADC_LL_CTRL_DIG:
SENS.sar_meas1_mux.sar1_dig_force = 1; // 1: Select digital control; 0: Select RTC control.
SENS.sar_meas1_ctrl2.meas1_start_force = 1; // 1: SW control RTC ADC start; 0: ULP control RTC ADC start.
SENS.sar_meas1_ctrl2.sar1_en_pad_force = 1; // 1: SW control RTC ADC bit map; 0: ULP control RTC ADC bit map;
break;
default:
break;
}
} else { // adc_n == ADC_UNIT_2Can someone confirm that the ULP RISCV can read new and fresh ADC data when the ulp_adc_init is used? What could cause this issue?
Bug ticket created https://github.com/espressif/esp-idf/issues/15927
Thank you