Set EXT0 and EXT1 wake interrupts from deep sleep wake stub

iParcelBox
Posts: 23
Joined: Sun Oct 27, 2019 3:12 pm

Set EXT0 and EXT1 wake interrupts from deep sleep wake stub

Postby iParcelBox » Wed Apr 06, 2022 6:07 pm

Hi,

When waking from deep sleep via a timer, I want to increment a counter and then go back to sleep. However, I also want to set wake interrupts for both EXT0 and EXT1 in the wake stub. I can do this no problem in the main code using esp_sleep_enable_ext0_wakeup and esp_sleep_enable_ext1_wakeup.

Is it possible to either retain these with the wake stub, or set them again in the stub before going back to sleep? Currently all I'm able to do is set a new timer, using the following code:

Code: Select all

static void RTC_IRAM_ATTR wake_stub() {
    esp_default_wake_deep_sleep();
    boots++;

  switch (stub_esp_sleep_get_wakeup_cause())
    {
      case ESP_SLEEP_WAKEUP_EXT0:
        ets_printf(wake_reason_ext0_msg);
        return;
        
      case ESP_SLEEP_WAKEUP_EXT1:
        ets_printf(wake_reason_ext1_msg);
        return;
            
      case ESP_SLEEP_WAKEUP_TIMER:
        ets_printf(wake_reason_timer_msg);
        break;
        
      default:
        // Boot normally;
        return;
    }

    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(sleep_duration * 1000000);

    // 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);
}
Thank you!

Who is online

Users browsing this forum: Google [Bot] and 80 guests