Open NikLeberg opened 1 year ago
I did some debugging and compared the HW registers before and after the call to esp_wifi_stop()
. The main difference observed was, that the ADC peripheral gets powered down, i.e. in the register SENS_SAR_MEAS_WAIT2_REG
the field SENS_FORCE_XPD_SAR
is set to a value SENS_FORCE_XPD_SAR_PD
. To operate with the ULP this needs to be set to SENS_FORCE_XPD_SAR_FSM
or at least that is what ulp_adc_init()
does.
Setting the register manually to SENS_FORCE_XPD_SAR_FSM
solves the issue for me.
I then debugged with GDB to see what piece of code changes this register. I found the set of functions adc_power_acquire()
and adc_power_release()
that seem to manage the power to the ADC peripheral. They manage a reference count of the ADC usages and power it down if no code uses it any more. PD is done differently for the ESP32 than for the other ESP modules:
static void adc_power_off_internal(void)
{
#if CONFIG_IDF_TARGET_ESP32
adc_hal_set_power_manage(ADC_POWER_SW_OFF);
#else
adc_hal_set_power_manage(ADC_POWER_BY_FSM);
#endif
}
The ADC_POWER_BY_FSM
would be equivalent to the required SENS_FORCE_XPD_SAR_FSM
to solve the issue in my case.
This precompiler switch was added in commit cc6bfcd
but I sadly could not find a reason for the special handling of ESP32.
If I remove the ESP32 special case and always let it set ADC_POWER_BY_FSM
then the ADC usage with ULP works.
I'm assuming, that initially that reference count is incremented with the use of ulp_adc_init()
. But then after the deep sleep the count is obviously lost and the HAL no longer knows that the ULP is using it. As such after the last module (the wifi stack in this case) stops to use the ADC, the ADC is powered down.
Am I supposed to use the ADC API in a different way? What is the specific reason for the special handling of original ESP32 module?
hi @NikLeberg sorry for late reply, thanks for your feedback, we will take a test
Answers checklist.
IDF version.
v5.1-dev-2658-g0025915dc4
Operating System used.
Linux
How did you build your project?
VS Code IDE
If you are using Windows, please specify command line type.
None
Development Kit.
ESP32-WROOM-32
Power Supply used.
USB
What is the expected behavior?
The ULP is configured to put ADC measurement into shared global variable. I'd expect that after correct configuration the ULP will continue to put ADC data into variable. This should also work after deep sleep and wifi start/stop.
What is the actual behavior?
The ULP outputs the ADC values happily before the wifi stack is stopped. But after a deep sleep and a wifi stop the values are frozen in time and won't update anymore. It does not happen if there is no deep sleep in-between.
Steps to reproduce.
At every step ADC values are written to output. After call to
esp_wifi_stop()
and before second call toulp_adc_init()
the ADC value is frozen and will not update.Debug Logs.
More Information.
As seen in the example code, if the ADC is initialized again with a call to
ulp_adc_init()
, then the ULP starts spitting out fresh and correct values again.I noticed this bug after the ULP could no longer wake the SoC in one of my project. I'm assuming it got stuck on the
adc
instruction while reading the ADC that was miss configured (or erroneously de initialized by the wifi library?) and could never continue from that instruction.I have read that Wifi can influence ADC operation. But that should only be the case for ADC2, or isn't it? I'm also not sure if I'm not supposed to initialize the ADC after every deep sleep anyway. So if I'm using the API wrong I'm happy to be corrected.