Trouble Waking from Ligh Sleep using ULP

mortanius
Posts: 3
Joined: Fri Jan 10, 2020 8:16 am

Trouble Waking from Ligh Sleep using ULP

Postby mortanius » Fri Jan 10, 2020 8:25 am

I'm trying to figure out how to wake the ESP32 form a light sleep using the ULP. To this end I've put together some simple code that counts up in 2s. This works as expected for deep sleep (uncomment line 57, and comment line 56 of the c code), but not for light sleep. In light sleep, the program just hangs. Does anyone have any idea on how I could get this to work?
  1. /* idf.py menuconfig weas used to adjust
  2.  * Component config -> ESP32 specific -> select 'Enable Ultra Low Power Coprocessor'
  3.  * to 4096 top get this to work
  4.  */
  5.  
  6. /* ULP assembly files are passed through C preprocessor first, so include directives
  7.    and C macros may be used in these files
  8.  */
  9. #include "soc/rtc_cntl_reg.h"
  10. #include "soc/rtc_io_reg.h"
  11. #include "soc/soc_ulp.h"
  12.    
  13.     /* Define variables, which go into .bss section (zero-initialized data) */
  14.     .bss
  15.  
  16.     .global testval
  17. testval:     .long 0
  18.  
  19.  
  20.     /* Code goes into .text section */
  21.     .text
  22.     .global entry
  23. entry:
  24.     move r0, testval
  25.     ld r1, r0, 0
  26.     add r1, r1, 2
  27.     st r1, r0, 0
  28.     STAGE_RST
  29. wait100ms:
  30.     wait 8000
  31.     STAGE_INC 1
  32.     jumps wake_up, 100, GE
  33.     jump wait100ms
  34.    
  35.    
  36.    
  37. // wake up at the end
  38. wake_up:
  39.     // Check if the system can be woken up
  40.     READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
  41.     and r0, r0, 1
  42.     jump wake_up, eq
  43.     // Wake up the SoC, end program
  44.     wake
  45.     REG_WR 0x006, 24, 24, 0      // Stop ULP timer (clear RTC_CNTL_ULP_CP_SLP_TIMER_EN)
  46.     halt
  1. #include <stdio.h>
  2. #include "esp_sleep.h"
  3. #include "soc/rtc_cntl_reg.h"
  4. #include "soc/rtc_io_reg.h"
  5. #include "soc/sens_reg.h"
  6. #include "soc/rtc_periph.h"
  7. #include "soc/soc.h"
  8. #include "driver/gpio.h"
  9. #include "driver/rtc_io.h"
  10. //#include "sdkconfig.h"
  11. #include "esp32/ulp.h"
  12. #include "ulp_main.h"
  13.  
  14.  
  15. extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
  16. extern const uint8_t ulp_main_bin_end[]   asm("_binary_ulp_main_bin_end");
  17.  
  18. static void init_ulp_program();
  19.  
  20. static void init_ulp_program()
  21. {
  22.     esp_err_t err = ulp_load_binary(0, ulp_main_bin_start,
  23.             (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
  24.     ESP_ERROR_CHECK(err);
  25.    
  26.     // Init Values
  27.     ulp_testval     = 0;
  28.    
  29.     //esp_deep_sleep_disable_rom_logging(); // suppress boot messages
  30.    
  31.     /* Set ULP wake up period to 20ms */
  32.     ulp_set_wakeup_period(0, 20000);
  33.     ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM)  / sizeof(uint32_t)));
  34. }
  35.  
  36. void app_main()
  37. {
  38.     //testNoSleep();
  39.     printf("start\n");
  40.     esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
  41.     if (cause != ESP_SLEEP_WAKEUP_ULP)
  42.     {
  43.         printf("Not ULP wakeup, initializing ULP\n");
  44.         init_ulp_program();
  45.        
  46.     }
  47.     else
  48.     {
  49.         printf("ULP Wakeup\n");
  50.         ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM)  / sizeof(uint32_t)));
  51.         printf("%u\n", ulp_testval& 0x0000FFFF);
  52.         printf("\n");
  53.     }
  54.    
  55.     ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
  56.     esp_light_sleep_start();
  57.     //esp_deep_sleep_start();  
  58. }

boarchuz
Posts: 178
Joined: Tue Aug 21, 2018 5:28 am

Re: Trouble Waking from Ligh Sleep using ULP

Postby boarchuz » Fri Jan 10, 2020 10:55 am

Light sleep behaviour is very different to deep sleep. Execution will continue from where it had a nap, rather than a 'reset' as with deep sleep.

Try this:

Code: Select all

for(;;) {
  printf("Entering light sleep...\n");
  vTaskDelay(500 / portTICK_PERIOD_MS);
  esp_light_sleep_start();
  printf("Woke from light sleep!\n");
}

mortanius
Posts: 3
Joined: Fri Jan 10, 2020 8:16 am

Re: Trouble Waking from Ligh Sleep using ULP

Postby mortanius » Fri Jan 10, 2020 5:40 pm

Thank you! Definitely made forward progress. I now see the first output:
  1. rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
  2. configsip: 0, SPIWP:0xee
  3. clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
  4. mode:DIO, clock div:2
  5. load:0x3fff0018,len:4
  6. load:0x3fff001c,len:5108
  7. load:0x40078000,len:9780
  8. ho 0 tail 12 room 4
  9. load:0x40080400,len:6288
  10. entry 0x4008070c
  11. start
  12. Entering light sleep...
  13. 2
  14. Woke from light sleep!
  15. Entering light sleep...
However, it stalls after going to sleep the second time. Because I was having issues with vTaskDelay(), I am using a for loop as a delay element. I tried moving the esp_sleep_enable_ulp_wakeup() function into the for loop but that also made no change.
  1. /* idf.py menuconfig was used to adjust
  2.  * Component config -> ESP32 specific -> select 'Enable Ultra Low Power Coprocessor'
  3.  * to 4096 top get this to work
  4.  */
  5.  
  6. /* ULP assembly files are passed through C preprocessor first, so include directives
  7.    and C macros may be used in these files
  8.  */
  9. #include "soc/rtc_cntl_reg.h"
  10. #include "soc/rtc_io_reg.h"
  11. #include "soc/soc_ulp.h"
  12.    
  13.     /* Define variables, which go into .bss section (zero-initialized data) */
  14.     .bss
  15.  
  16.     .global testval
  17. testval:     .long 0
  18.  
  19.     /* Code goes into .text section */
  20.     .text
  21.     .global entry
  22. entry:
  23.     move r0, testval
  24.     ld r1, r0, 0
  25.     add r1, r1, 2
  26.     st r1, r0, 0
  27.     STAGE_RST
  28. wait100ms:
  29.     wait 8000
  30.     STAGE_INC 1
  31.     jumps wake_up, 100, GE
  32.     jump wait100ms
  33.    
  34. // wake up at the end
  35. wake_up:
  36.     // Check if the system can be woken up
  37.     READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
  38.     and r0, r0, 1
  39.     jump wake_up, eq
  40.     // Wake up the SoC, end program
  41.     wake
  42.     REG_WR 0x006, 24, 24, 0      // Stop ULP timer (clear RTC_CNTL_ULP_CP_SLP_TIMER_EN)
  43.     halt

  1. #include <stdio.h>
  2. #include "esp_sleep.h"
  3. #include "soc/rtc_cntl_reg.h"
  4. #include "soc/rtc_io_reg.h"
  5. #include "soc/sens_reg.h"
  6. #include "soc/rtc_periph.h"
  7. #include "soc/soc.h"
  8. #include "driver/gpio.h"
  9. #include "driver/rtc_io.h"
  10. //#include "sdkconfig.h"
  11. #include "esp32/ulp.h"
  12. #include "ulp_main.h"
  13. //#include "freertos/FreeRTOS.h"
  14.  
  15.  
  16. extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
  17. extern const uint8_t ulp_main_bin_end[]   asm("_binary_ulp_main_bin_end");
  18.  
  19. static void init_ulp_program();
  20.  
  21. static void init_ulp_program()
  22. {
  23.     esp_err_t err = ulp_load_binary(0, ulp_main_bin_start,
  24.             (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
  25.     ESP_ERROR_CHECK(err);
  26.    
  27.     // Init Values
  28.     ulp_testval     = 0;
  29.    
  30.     //esp_deep_sleep_disable_rom_logging(); // suppress boot messages
  31.    
  32.     /* Set ULP wake up period to 20ms */
  33.     ulp_set_wakeup_period(0, 20000);
  34.     ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM)  / sizeof(uint32_t)));
  35. }
  36.  
  37. void app_main()
  38. {
  39.     //testNoSleep();
  40.     printf("start\n");
  41.     //esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
  42.     init_ulp_program();
  43.     /*if (cause != ESP_SLEEP_WAKEUP_ULP)
  44.     {
  45.         printf("Not ULP wakeup, initializing ULP\n");
  46.         init_ulp_program();
  47.        
  48.     }
  49.     else
  50.     {
  51.         printf("ULP Wakeup\n");
  52.         ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM)  / sizeof(uint32_t)));
  53.         printf("%u\n", ulp_testval& 0x0000FFFF);
  54.         printf("\n");
  55.     }*/
  56.    
  57.     ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
  58.     //esp_light_sleep_start();
  59.     //esp_deep_sleep_start();  
  60.    
  61.     for(;;)
  62.     {
  63.         printf("Entering light sleep...\n");
  64.         //vTaskDelay(500 / portTICK_PERIOD_MS);
  65.         int k  = 0;
  66.         for(int i = 0; i < 1000; i++)
  67.         {
  68.             for(int j = 0; j < 100; j++)
  69.             {
  70.                 k+=i+j;
  71.             }
  72.         }
  73.         esp_light_sleep_start();
  74.         printf("%u\n", ulp_testval& 0x0000FFFF);
  75.         printf("Woke from light sleep!\n");
  76.     }
  77. }
Thank you!

mortanius
Posts: 3
Joined: Fri Jan 10, 2020 8:16 am

Re: Trouble Waking from Ligh Sleep using ULP

Postby mortanius » Fri Jan 10, 2020 5:57 pm

Thank you! This is a step forward. It now wakes from sleep once, but fails to do so on subsequent sleeps. This is the output:
  1. ets Jun  8 2016 00:22:57
  2.  
  3. rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
  4. configsip: 0, SPIWP:0xee
  5. clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
  6. mode:DIO, clock div:2
  7. load:0x3fff0018,len:4
  8. load:0x3fff001c,len:5108
  9. load:0x40078000,len:9780
  10. ho 0 tail 12 room 4
  11. load:0x40080400,len:6288
  12. entry 0x4008070c
  13. start
  14. Entering light sleep...
  15. 2
  16. Woke from light sleep!
  17. Entering light sleep...
I used provided for loop but I replaced the vTaskDelay(), which was giving me errors (even with freeRTOS included) with a for loop delay. I attempted to move esp_sleep_enable_ulp_wakeup() into the loop, but it made no difference.
  1. #include <stdio.h>
  2. #include "esp_sleep.h"
  3. #include "soc/rtc_cntl_reg.h"
  4. #include "soc/rtc_io_reg.h"
  5. #include "soc/sens_reg.h"
  6. #include "soc/rtc_periph.h"
  7. #include "soc/soc.h"
  8. #include "driver/gpio.h"
  9. #include "driver/rtc_io.h"
  10. //#include "sdkconfig.h"
  11. #include "esp32/ulp.h"
  12. #include "ulp_main.h"
  13. //#include "freertos/FreeRTOS.h"
  14.  
  15.  
  16. extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
  17. extern const uint8_t ulp_main_bin_end[]   asm("_binary_ulp_main_bin_end");
  18.  
  19. static void init_ulp_program();
  20.  
  21. static void init_ulp_program()
  22. {
  23.     esp_err_t err = ulp_load_binary(0, ulp_main_bin_start,
  24.             (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
  25.     ESP_ERROR_CHECK(err);
  26.    
  27.     // Init Values
  28.     ulp_testval     = 0;
  29.    
  30.     //esp_deep_sleep_disable_rom_logging(); // suppress boot messages
  31.    
  32.     /* Set ULP wake up period to 20ms */
  33.     ulp_set_wakeup_period(0, 20000);
  34.     ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM)  / sizeof(uint32_t)));
  35. }
  36.  
  37. void app_main()
  38. {
  39.     //testNoSleep();
  40.     printf("start\n");
  41.     //esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
  42.     init_ulp_program();
  43.     /*if (cause != ESP_SLEEP_WAKEUP_ULP)
  44.     {
  45.         printf("Not ULP wakeup, initializing ULP\n");
  46.         init_ulp_program();
  47.        
  48.     }
  49.     else
  50.     {
  51.         printf("ULP Wakeup\n");
  52.         ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM)  / sizeof(uint32_t)));
  53.         printf("%u\n", ulp_testval& 0x0000FFFF);
  54.         printf("\n");
  55.     }*/
  56.    
  57.     //ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
  58.     //esp_light_sleep_start();
  59.     //esp_deep_sleep_start();  
  60.    
  61.     for(;;)
  62.     {
  63.         ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
  64.         printf("Entering light sleep...\n");
  65.         //vTaskDelay(500 / portTICK_PERIOD_MS);
  66.         int k  = 0;
  67.         for(int i = 0; i < 1000; i++)
  68.         {
  69.             for(int j = 0; j < 100; j++)
  70.             {
  71.                 k+=i+j;
  72.             }
  73.         }
  74.         esp_light_sleep_start();
  75.         printf("%u\n", ulp_testval& 0x0000FFFF);
  76.         printf("Woke from light sleep!\n");
  77.     }  
  78. }
  1. /* idf.py menuconfig was used to adjust
  2.  * Component config -> ESP32 specific -> select 'Enable Ultra Low Power Coprocessor'
  3.  * to 4096 to get this to work
  4.  */
  5.  
  6. /* ULP assembly files are passed through C preprocessor first, so include directives
  7.    and C macros may be used in these files
  8.  */
  9. #include "soc/rtc_cntl_reg.h"
  10. #include "soc/rtc_io_reg.h"
  11. #include "soc/soc_ulp.h"
  12.    
  13.     /* Define variables, which go into .bss section (zero-initialized data) */
  14.     .bss
  15.  
  16.     .global testval
  17. testval:     .long 0
  18.  
  19.     /* Code goes into .text section */
  20.     .text
  21.     .global entry
  22. entry:
  23.     move r0, testval
  24.     ld r1, r0, 0
  25.     add r1, r1, 2
  26.     st r1, r0, 0
  27.     STAGE_RST
  28. wait100ms:
  29.     wait 8000
  30.     STAGE_INC 1
  31.     jumps wake_up, 2000, GE
  32.     jump wait100ms
  33. // wake up at the end
  34. wake_up:
  35.     // Check if the system can be woken up
  36.     READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
  37.     and r0, r0, 1
  38.     jump wake_up, eq
  39.     // Wake up the SoC, end program
  40.     wake
  41.     REG_WR 0x006, 24, 24, 0      // Stop ULP timer (clear RTC_CNTL_ULP_CP_SLP_TIMER_EN)
  42.     halt
Thank you!

Who is online

Users browsing this forum: No registered users and 18 guests