Page 1 of 1

Getting Wake Cause in Wake Stub not working on S3

Posted: Tue Nov 21, 2023 5:37 pm
by PeteDD
I have switched a project from ESP32 to ESP32-S3 and can't figure out why I can't get a correct wake cause in my wake stub. It only returns 0 for the wake cause value when waking from EXT0 input. Can anyone see what I am missing here? Again, this code works fine on the ESP32 such as the TTGO T-Display. I am thinking it must be in the line:

Code: Select all

uint32_t _wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);

but why is that working on other processors but not on the S3?
(I have googled extensively on this and tried many alternative approaches, but to no avail).
Here is a reduced code example:

THANKS!

Code: Select all

#include <Arduino.h>
#include "esp_sleep.h"
#include "esp_cpu.h"
#include "esp_rom_sys.h"
#include "rom\rtc.h"             // needed for rtc_get_reset_reason, DEEPSLEEP_RESET, RTC_ENTRY_ADDR_REG
#include "driver\rtc_io.h"       // needed for rtc_gpio_pullup_en
#include "soc/rtc.h"             // needed for RTC_EXT0_TRIG_EN, RTC_EXT1_TRIG_EN, RTC_TIMER_TRIG_EN, RTC_TOUCH_TRIG_EN, RTC_ULP_TRIG_EN


void setup()
{
    	rtc_gpio_init(GPIO_NUM)_17;
    	rtc_gpio_set_direction(GPIO_NUM_17, RTC_GPIO_MODE_INPUT_ONLY);
   	rtc_gpio_pulldown_dis(GPIO_NUM_17);
 	rtc_gpio_pullup_en(GPIO_NUM_17);
 	esp_sleep_enable_timer_wakeup(wakeup_time_sec * uS_TO_S_FACTOR);
 	esp_sleep_enable_ext0_wakeup(GPIO_NUM_17, 0); // 1 = High, 0 = Low
 	esp_set_deep_sleep_wake_stub(&wake_stub);
 	esp_deep_sleep_start();
 }
 
 RTC_IRAM_ATTR esp_sleep_wakeup_cause_t stub_esp_sleep_get_wakeup_cause()
{
  uint32_t _wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);
  if (_wakeup_cause & RTC_EXT0_TRIG_EN)
  {
    return ESP_SLEEP_WAKEUP_EXT0;  // 2
  }
  else if (_wakeup_cause & RTC_EXT1_TRIG_EN)
  {
    return ESP_SLEEP_WAKEUP_EXT1;  // 3
  }
  else if (_wakeup_cause & RTC_TIMER_TRIG_EN)
  {
    return ESP_SLEEP_WAKEUP_TIMER;  // 4
  }
  else if (_wakeup_cause & RTC_TOUCH_TRIG_EN)
  {
    return ESP_SLEEP_WAKEUP_TOUCHPAD;  // 5
  }
  else if (_wakeup_cause & RTC_ULP_TRIG_EN)
  {
    return ESP_SLEEP_WAKEUP_ULP;  // 6
  }
  else
  {
    return ESP_SLEEP_WAKEUP_UNDEFINED;  // 0
  }
}


//! Begin Wake Stub content
static const char RTC_RODATA_ATTR wakeup_cause_number_str[] = "Wakeup cause = %d\n";
static RTC_DATA_ATTR uint32_t wakeup_cause;

static void RTC_IRAM_ATTR wake_stub(void)
{
	esp_default_wake_deep_sleep();
	wakeup_cause = stub_esp_sleep_get_wakeup_cause();
	ets_printf(wakeup_cause_number_str, wakeup_cause);
	
	//... the rest does not really matter.... if ext0 is the wake cause, I wait for it to return high, then go back to sleep
	// ... and if the cause is the timer or undefined, I wake up completely with a "return"
}
and my platformio.ini

Code: Select all

[env:esp32-s3-devkitc-1]
platform = espressif32@6.4.0
board = esp32-s3-devkitc-1

board_build.arduino.memory_type = dio_opi
monitor_speed = 115200
framework = arduino
board_build.partitions = default_partitions.csv

build_flags = 
	-I./src/
	-DCORE_DEBUG_LEVEL=5
	-DBOARD_HAS_PSRAM
	-mfix-esp32-psram-cache-issue
	-fmax-errors=5

Re: Getting Wake Cause in Wake Stub not working on S3

Posted: Wed Nov 22, 2023 3:29 am
by ESP-Marius
Looking at the TRM,

Code: Select all

RTC_CNTL_WAKEUP_STATE_REG
does not seem to be the correct register for reading the wake-up cause on S3.

Code: Select all

RTC_CNTL_WAKEUP_CAUSE
is from

Code: Select all

RTC_CNTL_SLP_WAKEUP_CAUSE_REG
You can take a look at

Code: Select all

rtc_cntl_ll_get_wakeup_cause()
to see how it is done on different chips (you could use this in function in your stub) and see if that solves your issue.

Re: Getting Wake Cause in Wake Stub not working on S3

Posted: Wed Nov 22, 2023 1:41 pm
by PeteDD
@ESP_Marius, Thank you.

Re: Getting Wake Cause in Wake Stub not working on S3

Posted: Wed Nov 22, 2023 11:33 pm
by PeteDD
@ESP_Marius... I am finding LOTS of things that work on ESP32 but not on ESP32-S3. I wish there were a list of these things somewhere...

Here is what I ended up with for the capture of the wake reason in a wake stub. But, I still have an odd problem that I will write about separately.

Code: Select all

#include "rom\rtc.h"             // needed for rtc_get_reset_reason, DEEPSLEEP_RESET, RTC_ENTRY_ADDR_REG
#include "esp_sleep.h"          // needed for ESP_SLEEP_WAKEUP_* values
#include "soc/rtc_cntl_reg.h"  // needed for  RTC_CNTL_SLP_WAKEUP_CAUSE_REG 
// (other includes that are needed are possibly not listed here)

static const char RTC_RODATA_ATTR wakeup_cause_EXT0_str[] = "WAKE_STUB: Wakeup Cause EXT0\n";
static const char RTC_RODATA_ATTR wakeup_cause_TIMER_str[] = "WAKE_STUB: Wakeup Cause TIMER\n";
static RTC_DATA_ATTR uint32_t wakeup_cause;

RTC_IRAM_ATTR esp_sleep_wakeup_cause_t stub_esp_sleep_get_wakeup_cause()
{
    uint32_t _wakeup_cause = REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE);
    if (_wakeup_cause & RTC_EXT0_TRIG_EN)
  {
    return ESP_SLEEP_WAKEUP_EXT0;
  }
  else if (_wakeup_cause & RTC_EXT1_TRIG_EN)
  {
    return ESP_SLEEP_WAKEUP_EXT1;
  }
  else if (_wakeup_cause & RTC_TIMER_TRIG_EN)
  {
    return ESP_SLEEP_WAKEUP_TIMER;
  }
  else if (_wakeup_cause & RTC_TOUCH_TRIG_EN)
  {
    return ESP_SLEEP_WAKEUP_TOUCHPAD;
  }
  else if (_wakeup_cause & RTC_ULP_TRIG_EN)
  {
    return ESP_SLEEP_WAKEUP_ULP;
  }
  else
  {
    return ESP_SLEEP_WAKEUP_UNDEFINED;
  }
}

static void RTC_IRAM_ATTR wake_stub(void)
{
  esp_default_wake_deep_sleep(); // If supplying a custom wake stub, the first thing it does should be to call
  //  https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/deep-sleep-stub.html#implementing-a-stub

  wakeup_cause = stub_esp_sleep_get_wakeup_cause();

  switch (wakeup_cause)
  {
    // If we woke up from the power button, and we're not critical voltage just boot up
  case ESP_SLEEP_WAKEUP_EXT0:
    	ets_printf(wakeup_cause_EXT0_str);

	// do stuff here
	
	// and go prepare to go back to sleep
	
	// Wait for pin level to be high.
    	// If we go to sleep when the pin is still low, the chip
    	// will wake up again immediately. Hardware doesn't have
    	// edge trigger support for deep sleep wakeup.
   	 while (GPIO_INPUT_GET(RAIN_CNT_GPIO_NUM) == 0)
   	 {
      		// feed the watchdog
     		 REG_WRITE(TIMG_WDTFEED_REG(0), 1);
      		 ets_delay_us(RAIN_COUNT_PULSE_DEBOUNCE_US);
   	 }
	
	    // Set the pointer of the wake stub function.
    	REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)&wake_stub);

    	// Go back 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.
   	 break; // case ESP_SLEEP_WAKEUP_EXT0:
   	 
   case ESP_SLEEP_WAKEUP_TIMER:
   	 ets_printf(wakeup_cause_TIMER_str);
	 esp_default_wake_deep_sleep();
	  // Return from the wake stub function to continue
    // booting the firmware.
    return;

    break; // case ESP_SLEEP_WAKEUP_TIMER:
  }
}