Page 1 of 1

Deep Sleep Stub function? Sleep mode optimization TG0WDT_SYS_RESET

Posted: Fri Apr 17, 2020 2:56 am
by brolly759
Anyone able to get the deep sleep wake stubs working for Arduino?
https://docs.espressif.com/projects/esp ... -stub.html

I am trying to reduce the wake up time of ESP32. Right now with no code and setting up sleep I am at 200ms. I would like to wake up from sleep run simple code and go back to sleep without going through a full reboot. I think I am getting a WDT reset after the RTC_IRAM_ATTR function for some reason. Any help would be great! Thanks

I have this function:

void RTC_IRAM_ATTR esp_wake_deep_sleep(void) {
esp_default_wake_deep_sleep();
esp_set_deep_sleep_wake_stub(&esp_wake_deep_sleep);
esp_sleep_enable_timer_wakeup(5 * 1000000);
// esp_task_wdt_reset();
esp_deep_sleep_start();
}

end of my setup code:

esp_set_deep_sleep_wake_stub(&esp_wake_deep_sleep);
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
esp_deep_sleep_start();


Output:

rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
ets Jun 8 2016 00:22:57

rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8

Re: Deep Sleep Stub function? Sleep mode optimization TG0WDT_SYS_RESET

Posted: Fri Apr 17, 2020 3:34 am
by brolly759
I was able to get it to work using this code. Current code takes 25ms and sleeps. I will try to optimize and check current measurements. If I have to write the code below, may as well just use RTOS or ESP-IDE than Arduino IDE

Here is the link that answered my question:
https://gist.github.com/igrr/54f7fbe051 ... d7fbecfeab

Code: Select all

#include "driver/rtc_io.h"
#include "rom/ets_sys.h"
#include "rom/rtc.h"
#include "esp_attr.h"
#include "esp_sleep.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/timer_group_reg.h"
#include "soc/uart_reg.h"
#include <stdio.h>
#include <string.h>

RTC_IRAM_ATTR void deepsleep_for_us(uint64_t duration_us);

#define BLINK_GPIO GPIO_NUM_25
#define S_TO_NS 1000000ULL
// Boot counter value, stored in RTC_SLOW_MEM
static size_t RTC_DATA_ATTR boots;
static size_t RTC_DATA_ATTR max_boots;

// Function which runs after exit from deep sleep
static void RTC_IRAM_ATTR wake_stub();
void setup(){
  
}
void loop(void) {
  if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) {
    printf("I'm back! Wake up from (extended) deep sleep. Should be 60s elapsed.\n");
    printf("Boot count=%d\n", boots);
    while (1) {
      ;
    }
  } else {
    printf("Not a deep sleep wake up\n");
  }

  printf("Going to deep sleep for 5x12=60s second\n");
  boots = 0;
  max_boots = 12;
  // hold high during deep sleep
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);

  // Set the wake stub function
  esp_set_deep_sleep_wake_stub(&wake_stub);

  esp_sleep_enable_timer_wakeup(5 * S_TO_NS);
  esp_deep_sleep_start();
}

static const char RTC_RODATA_ATTR wake_fmt_str[] = "count=%d\n";
static const char RTC_RODATA_ATTR sleep_fmt_str[] = "sleeping\n";

static void RTC_IRAM_ATTR wake_stub() {
  // Increment the Boot counter
  boots++;
  // and print the Boot counter value:
  ets_printf(wake_fmt_str, boots);

  if (boots >= max_boots) {
    // On revision 0 of ESP32, this function must be called:
    esp_default_wake_deep_sleep();
    // Return from the wake stub function to continue
    // booting the firmware.
    return;
  }

  // Print status
  ets_printf(sleep_fmt_str);
  // Wait for UART to end transmitting.
  // feed the watchdog
  REG_WRITE(TIMG_WDTFEED_REG(0), 1);
  while (REG_GET_FIELD(UART_STATUS_REG(0), UART_ST_UTX_OUT)) {

  }
  deepsleep_for_us(5 * S_TO_NS);

  // Set the pointer of the wake stub function.
  REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)&wake_stub);
  // Go to sleep.
  CLEAR_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
  SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
  // A few CPU cycles may be necessary for the sleep to start...
  while (true) {
    ;
  }
  // never reaches here.
}

// Comment out this line if you're using the internal RTC RC (150KHz) oscillator.
//#define USE_EXTERNAL_RTC_CRYSTAL
#ifdef USE_EXTERNAL_RTC_CRYSTAL
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ)
#else
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ)
#endif // USE_EXTERNAL_RTC_CRYSTAL

RTC_IRAM_ATTR void deepsleep_for_us(uint64_t duration_us) {
  // Feed watchdog
  REG_WRITE(TIMG_WDTFEED_REG(0), 1);
  // Get RTC calibration
  uint32_t period = REG_READ(RTC_SLOW_CLK_CAL_REG);
  // Calculate sleep duration in microseconds
  int64_t sleep_duration = (int64_t)duration_us - (int64_t)DEEP_SLEEP_TIME_OVERHEAD_US;
  if (sleep_duration < 0) {
    sleep_duration = 0;
  }
  // Convert microseconds to RTC clock cycles
  int64_t rtc_count_delta = (sleep_duration << RTC_CLK_CAL_FRACT) / period;
  // Feed watchdog
  REG_WRITE(TIMG_WDTFEED_REG(0), 1);
  // Get current RTC time
  SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
  while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) {
    ets_delay_us(1);
  }
  SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_TIME_VALID_INT_CLR);
  uint64_t now = READ_PERI_REG(RTC_CNTL_TIME0_REG);
  now |= ((uint64_t)READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
  // Set wakeup time
  uint64_t future = now + rtc_count_delta;
  WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, future & UINT32_MAX);
  WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, future >> 32);
  // Start RTC deepsleep timer
  REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, RTC_TIMER_TRIG_EN); // Wake up on timer
  WRITE_PERI_REG(RTC_CNTL_SLP_REJECT_CONF_REG, 0);                                  // Clear sleep rejection cause
  // Go to sleep
  CLEAR_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
  SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
}

Re: Deep Sleep Stub function? Sleep mode optimization TG0WDT_SYS_RESET

Posted: Fri Apr 17, 2020 5:33 am
by fasani
Great that you found a solution. I'm curious to know, what is the consumption when the ESP32 is in this stub mode?

Is the same as deepsleep? Looks very interesting

Re: Deep Sleep Stub function? Sleep mode optimization TG0WDT_SYS_RESET

Posted: Fri Apr 17, 2020 10:03 pm
by brolly759
Using a CurrentRanger / uCurrent tool, deep sleep it drops as low as 8uA and spikes to 17uA. (Most of the time hovers around 12uA). I have a LoRA module connected in sleep mode as well so remove at least 1uA for that.

So the answer is, 8-17uA but more likely 10-11uA in Deep-Sleep. I removed some of the printing functions in the above code and the delays and now the stub takes only 15ms. I have not measured the current during the 15ms spike but once it goes back to Deep Sleep the current is as expected.

Note: I have a PicoScope 5000, CurrentRanger, uCurrent Gold, CMicrotek uCP120, Fluke 179, Fluke 190-102 and still cannot good sleep current readings with so much noise... unless someone can help of course and point me in a good direction. ;)

Re: Deep Sleep Stub function? Sleep mode optimization TG0WDT_SYS_RESET

Posted: Mon Apr 20, 2020 3:13 pm
by fasani
Great thanks for the information. That's a very good low consumption!

Re: Deep Sleep Stub function? Sleep mode optimization TG0WDT_SYS_RESET

Posted: Sat Dec 12, 2020 11:25 pm
by brolly759
I have a better way of measuring current now.
For the above code: The Wakeup and on time is 10ms. Avg Current during wake up time. is 14.67mA (Spikes to 30mA). Avg Current in sleep mode is 8.27uA - 9.85uA
esp32_current.jpg
esp32_current.jpg (232.54 KiB) Viewed 13096 times

Re: Deep Sleep Stub function? Sleep mode optimization TG0WDT_SYS_RESET

Posted: Sat Dec 10, 2022 6:09 pm
by aag071976
brolly759 wrote:
Sat Dec 12, 2020 11:25 pm
I have a better way of measuring current now.
For the above code: The Wakeup and on time is 10ms. Avg Current during wake up time. is 14.67mA (Spikes to 30mA). Avg Current in sleep mode is 8.27uA - 9.85uA
esp32_current.jpg
brolly759, its Super!
but i cannot to implement my functiom to your code. i need this: while (digitalRead(_dataPin) == HIGH) delay(1)
but in result system is reset by WDT:
rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13516
load:0x40080400,len:3604
entry 0x400805f0
Please help me!!!

Re: Deep Sleep Stub function? Sleep mode optimization TG0WDT_SYS_RESET

Posted: Sat Dec 10, 2022 7:36 pm
by aag071976
Please help:
i need read after wake up stub: digitalRead(dataPin)
and then return to stub slep
but system reset by watchdog: rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
How to read GPIO input from a wake stub?
please help - i need working example

Re: Deep Sleep Stub function? Sleep mode optimization TG0WDT_SYS_RESET

Posted: Sat Nov 11, 2023 12:03 pm
by noobplayer48
[quote from user brolly759, post_id=58428, time=1587092165, user_id=10867]
I want deep sleep wake stubs for Arduino. Currently, I'm utilizing the Espressif IoT Development Framework (IDF) with Arduino as a component. Could you please provide guidance on incorporating the code you shared into my project? I appreciate any assistance you can offer.