Page 1 of 1

ADC1 incorrectly returns 4095 from ULP coproc during TIMER-triggered wake up

Posted: Sat Nov 28, 2020 7:34 pm
by davidtaille
Hi,

I noticed that ADC1 sometimes erroneously returns 0xFFF during wake up from deep sleep, when the cause is a timeout.
To demonstrate the problem, I downloaded the latest esp-idf, and slightly modified example ulp_adc.
See diff to main .c and to .S files below.

Basically, the mods consist in :
- have the ULP coproc keep track of the highest ADC reading in a variable
- in main.c, printf the last value read along with the highest value seen since last wakeup
- using deepsleep along with a timeout (whereas in the sample only the ULP coproc wakes up the CPU)
- resetting highest value to 0 just before going to sleep.

On the test circuit, pin 34 is hooked on a pot's wiper to keep it at a constant tension of my choosing.
I set the pot so pin 34 is just under the low threshold set in the code.
At this stage, the console shows that the CPU gets woken up after a few coproc runs.
I then increase voltage to just above low threshold.
This causes the coproc to stop waking up the CPU, and lets it get out of deep sleep due to the timeout.
And then, even if the pin never really got above ~1750, the max value read from ADC shows 4095.
Note that it seems to happen on the *first* WAKEUP_TIMER after a WAKEUP_ULP, not on following timeouts.
See console output below.

This is consistent with what is reported on viewtopic.php?f=2&t=7105

In short, it seems that the wake up process itself (== some step inside of it) causes ADC1 to incorrectly return 4095 when read from ULP coproc.

Could you advise on how to fix this ?
Or maybe how to tell, from ULP coprocessor, whether a wake up is in progress ?

Thanks
David

Below the modifications I made on the ESP-IDF example.
  1. $ diff main/ulp/adc.S ../../examples/system/ulp_adc/main/ulp/adc.S
  2. 58,63d57
  3. < /*===mod*/
  4. <   .global highest_result
  5. < highest_result:
  6. <   .long 0
  7. < /*===mod*/
  8. <
  9. 93,102d86
  10. <
  11. < /*===mod*/
  12. <   move r3, highest_result
  13. <   ld r2, r3, 0
  14. <   sub r2, r0, r2
  15. <   jump thr_test, ov
  16. <   st r0, r3, 0
  17. <
  18. < thr_test:
  19. < /*===mod*/
  20. $ diff main/ulp_adc_example_main.c ../../examples/system/ulp_adc/main/ulp_adc_example_main.c
  21. 42,46d41
  22. <   /*===mod*/
  23. <         printf("ULP did %d measurements since last reset\n", ulp_sample_counter & UINT16_MAX);
  24. <         printf("Last result=%d\n", (ulp_last_result & 0xfff));
  25. <         printf("High result=%d\n", (ulp_highest_result & 0xfff));
  26. <   /*===mod*/
  27. 55,57d49
  28. <   /*===mod*/
  29. <         printf("High result=%d\n", (ulp_highest_result & 0xfff));
  30. <   /*===mod*/
  31. 62,65c54
  32. <     /*===mod*/
  33. <     /*esp_deep_sleep_start();*/
  34. <     esp_deep_sleep(5 * 1000000);
  35. <     /*===mod*/
  36. ---
  37. >     esp_deep_sleep_start();
  38. 107,110d95
  39. <
  40. <     /*===mod*/
  41. <     ulp_highest_result = 0;
  42. <     /*===mod*/

Below a excerpt of the console
  1. ... board running with pot set so that value remains within the limits ...
  2.  
  3. Not ULP wakeup
  4. ULP did 252 measurements since last reset
  5. Last result=1613
  6. High result=1647
  7. Entering deep sleep
  8.  
  9.     >>> turning the pot to go below low threshold
  10.  
  11. Deep sleep wakeup
  12. ULP did 24 measurements since last reset
  13. Thresholds:  low=1500  high=2000
  14. Value=1488 was below threshold
  15. High result=1645
  16. Entering deep sleep
  17.  
  18. Deep sleep wakeup
  19. ULP did 2 measurements since last reset
  20. Thresholds:  low=1500  high=2000
  21. Value=1413 was below threshold
  22. High result=1428
  23. Entering deep sleep
  24.  
  25. ... more output like these ...
  26.  
  27. Deep sleep wakeup
  28. ULP did 2 measurements since last reset
  29. Thresholds:  low=1500  high=2000
  30. Value=1497 was below threshold
  31. High result=1497
  32. Entering deep sleep
  33.  
  34.     >>> get the pot back to a spot where tension is back in range
  35.     >>> but taking care not to go above the high threshold
  36.  
  37. Not ULP wakeup
  38. ULP did 252 measurements since last reset
  39. Last result=1706
  40. High result=4095       <<<< 4095 was returned incorrectly at least once
  41. Entering deep sleep
  42.  
  43. Not ULP wakeup
  44. ULP did 252 measurements since last reset
  45. Last result=1705
  46. High result=1719       <<< following WAKEUP_TIMER don't exhibit the problem
  47. Entering deep sleep
  48.  
  49. ...