Esp32 deep sleep issues: Won't wake up from ext1

chris1seto
Posts: 20
Joined: Tue Jun 12, 2018 5:05 pm

Esp32 deep sleep issues: Won't wake up from ext1

Postby chris1seto » Wed Aug 19, 2020 5:32 pm

I have the attached code, which is designed to wake up for ext1 all going low. For some reason, this does not wake up the esp32. I have confirmed the io really does go low. Any ideas what I could be doing wrong? Additionally, the ets printf calls do not work (no serial output) and it doesn't appear as though the timer wakes up the esp32 either. I do know for certain that thw wake stub is running.If I just return as soon as I'm in the wake stub, or even before twiddling the RTC_CNTL_STATE0_REG registers, the esp32 will wake up.

Interestingly enough, the ext1 wakeup source does cause the esp32 to wakeup, but it also frequently happens that the esp32 wakes up as soon as it goes to sleep as a result of this wake source. Debouncing shouldn't be an issue. There is a long time from when that button is hit to the time that the ESP32 actually goes to sleep.

Any ideas?

Edit: I think the timer prepare in my wake stub "sdk" is broken. It looks like the timer just keeps firing over and over again. IT looks like the real SDK all works great on the call to enter deep sleep from my application routine. I think the issues with this are purely in my stub_* functions, though I'm not familiar enough with the esp32 low levels to know what. Am I failing to initialize something in the wake handler?

Enter deep sleep routine:

Code: Select all

void Power_DeepSleep(const enum SLEEP_LEVEL sleep_level)
{
  // Power down radios
  esp_bluedroid_disable();
  esp_bt_controller_disable();
  esp_wifi_stop();
  
  // Sleep the board
  ToggleMotorControllerPower(false);
  ToggleSleepBoard(true);
  
  // We always want to wakeup for the button (falling edge)
  esp_sleep_enable_ext0_wakeup(POWER_BUTTON_GPIO, 0);
  
  if (sleep_level == SLEEP_LEVEL_LIGHT)
  {
    // For light sleep, we need to wake up for...
    // USB DCP
    esp_sleep_enable_ext1_wakeup(((uint64_t)1 << DCP_UFP_GPIO), ESP_EXT1_WAKEUP_ALL_LOW);
    
    // Timer
    esp_sleep_enable_timer_wakeup(DEEP_SLEEP_TIME);
  }

  // If there is a USB device in and we are light sleeping, we don't want to turn the buck off
  if (DcpUfpIsConnected() && sleep_level == SLEEP_LEVEL_LIGHT)
  {
    ToggleBuck(true);
  }
  else
  {
    printf("Buck disable for sleep\r\n");
    ToggleBuck(false);
  }
  
  // Keep power GPIO state held
  rtc_gpio_hold_en(BUCK_EN_GPIO);
  rtc_gpio_hold_en(MOTOR_CONTROLLER_POWER_EN_GPIO);
  rtc_gpio_hold_en(SLEEP_GPIO);
  rtc_gpio_hold_en(SLEEP_INVERTED_GPIO);

  // Enter deep sleep, we don't return from this
  esp_deep_sleep_start();
}

Deep sleep handler

Code: Select all

#include <string.h>
#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "soc/rtc.h"
#include "soc/rtc_periph.h"
#include "esp_sleep.h"
#include "PowerDefs.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/uart_reg.h"
#include "soc/timer_group_reg.h"
#include "esp_sleep.h"
#include "esp_attr.h"
#include "esp32/rom/rtc.h"
#include "esp32/rom/gpio.h"
//#include "esp-rom/esp_rom_sys.h"
#include "esp32/rom/ets_sys.h"
#include "soc/gpio_periph.h"
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "driver/adc.h"
#include "soc/uart_reg.h"
#include "StubSdk.h"

enum SLEEP_LEVEL
{
  SLEEP_LEVEL_LIGHT,
  SLEEP_LEVEL_DEEP
};

static RTC_IRAM_ATTR void LowPowerInit(void);
static RTC_IRAM_ATTR void ToggleBuck(const bool enabled);
static RTC_IRAM_ATTR void ToggleMcPower(const bool enabled);
static RTC_IRAM_ATTR void ToggleSleepBoard(const bool enabled);
static RTC_IRAM_ATTR void DeepSleep(const enum SLEEP_LEVEL sleep_level);
static RTC_IRAM_ATTR bool ReadGpio(const uint32_t gpio);

// Debug messages
static RTC_RODATA_ATTR const char wake_msg[] = "Low power up\r\n";
//static RTC_RODATA_ATTR const char wake_critical_battery_msg[] = "Critical battery\r\n";
static RTC_RODATA_ATTR const char wake_reason_timer_msg[] = "Wake reason timer\r\n";
static RTC_RODATA_ATTR const char wake_reason_ext0_msg[] = "Wake reason ext0\r\n";
static RTC_RODATA_ATTR const char wake_reason_ext1_msg[] = "Wake reason ext1\r\n";

// Deep sleep wake stub
void RTC_IRAM_ATTR esp_wake_deep_sleep(void)
{
  // https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/deep-sleep-stub.html
  esp_default_wake_deep_sleep();
  
  // Enter the full sized wake stub routine
  WakeStub_Run();
}

static RTC_IRAM_ATTR bool ReadGpio(const uint32_t gpio)
{
  return !!(gpio_input_get() & gpio); 
}

static RTC_IRAM_ATTR void LowPowerInit(void)
{
  gpio_config_t io_conf;

  CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_HOLD_M);
  
  // Buck enable
  ToggleBuck(false);
  io_conf.mode = GPIO_MODE_OUTPUT;
  io_conf.pin_bit_mask = ((uint64_t)1 << BUCK_EN_GPIO);
  io_conf.pull_down_en = 1;
  io_conf.pull_up_en = 0;
  stub_gpio_config(&io_conf);
  
  // Mc power
  io_conf.mode = GPIO_MODE_OUTPUT;
  io_conf.pin_bit_mask = ((uint64_t)1 << MOTOR_CONTROLLER_POWER_EN_GPIO);
  io_conf.pull_down_en = 1;
  io_conf.pull_up_en = 0;
  stub_gpio_config(&io_conf);

  // Sleep
  ToggleSleepBoard(false);
  io_conf.mode = GPIO_MODE_OUTPUT;
  io_conf.pin_bit_mask = ((uint64_t)1 << SLEEP_GPIO);
  io_conf.pull_down_en = 0;
  io_conf.pull_up_en = 1;
  stub_gpio_config(&io_conf);
  
  // Sleep inverted
  /*io_conf.mode = GPIO_MODE_OUTPUT;
  io_conf.pin_bit_mask = ((uint64_t)1 << SLEEP_INVERTED_GPIO);
  io_conf.pull_down_en = 1;
  io_conf.pull_up_en = 0;
  stub_gpio_config(&io_conf);*/

  // DCP UFP
  io_conf.mode = GPIO_MODE_INPUT;
  io_conf.pin_bit_mask = ((uint64_t)1 << DCP_UFP_GPIO);
  io_conf.pull_down_en = 0;
  io_conf.pull_up_en = 0;
  stub_gpio_config(&io_conf);
  
  // Power button
  io_conf.mode = GPIO_MODE_INPUT;
  io_conf.pin_bit_mask = ((uint64_t)1 << POWER_BUTTON_GPIO);
  io_conf.pull_down_en = 0;
  io_conf.pull_up_en = 0;
  stub_gpio_config(&io_conf);
  
  // Leds
  stub_gpio_set_level(GPIO_NUM_23, true);
  stub_gpio_set_level(GPIO_NUM_21, true);
  io_conf.mode = GPIO_MODE_OUTPUT;
  io_conf.pin_bit_mask = ((uint64_t)1 << GPIO_NUM_23) | (1 << GPIO_NUM_21);
  io_conf.pull_down_en = 0;
  io_conf.pull_up_en = 1;
  stub_gpio_config(&io_conf);
}

static RTC_IRAM_ATTR void ToggleBuck(const bool enabled)
{
  stub_gpio_set_level(BUCK_EN_GPIO, enabled);
}

static RTC_IRAM_ATTR void ToggleMcPower(const bool enabled)
{
  stub_gpio_set_level(MOTOR_CONTROLLER_POWER_EN_GPIO, enabled);
}

static RTC_IRAM_ATTR void ToggleLed1(const bool enabled)
{
  stub_gpio_set_level(GPIO_NUM_23, !enabled);
}

static RTC_IRAM_ATTR void ToggleSleepBoard(const bool enabled)
{
  stub_gpio_set_level(SLEEP_GPIO, enabled);
  stub_gpio_set_level(SLEEP_INVERTED_GPIO, false);
}

static RTC_IRAM_ATTR bool DcpUfpIsConnected(void)
{
  return !ReadGpio(DCP_UFP_GPIO);
}

// Call on fresh bootup
void RTC_IRAM_ATTR WakeStub_Run(void)
{
  // Configure IO
  LowPowerInit();

  // We're up
  esp_rom_printf(wake_msg);

  // Determine why we woke up
  switch (stub_esp_sleep_get_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(wake_reason_ext0_msg);
      break;
      
    // If we woke up from DCP, just turn the buck on
    case ESP_SLEEP_WAKEUP_EXT1:
      ets_printf(wake_reason_ext1_msg);
      DeepSleep(SLEEP_LEVEL_LIGHT);
      break;
     
    // If we woke up from the timer
    case ESP_SLEEP_WAKEUP_TIMER:
      ets_printf(wake_reason_timer_msg);
      DeepSleep(SLEEP_LEVEL_LIGHT);
      break;
      
    default:
      DeepSleep(SLEEP_LEVEL_LIGHT);
      break;
  }
  
  // If we're at this point, we can go ahead and begin bootup
  ToggleBuck(true);
}

static RTC_IRAM_ATTR void DeepSleep(const enum SLEEP_LEVEL sleep_level)
{
  // Sleep the board
  ToggleMcPower(false);
  ToggleSleepBoard(true);
  
  while (REG_GET_FIELD(UART_STATUS_REG(0), UART_ST_UTX_OUT));
  
  // We always want to wakeup for the button (falling edge)
  stub_ext0_wakeup_prepare(4, 0);
  
  if (sleep_level == SLEEP_LEVEL_LIGHT)
  {
    // For light sleep, we need to wake up for...
    // USB DCP
    stub_ext1_wakeup_prepare((1 << 0), ESP_EXT1_WAKEUP_ALL_LOW);
    
    // Timer
    stub_timer_wakeup_prepare((uint64_t)(DEEP_SLEEP_TIME));
  }
  else
  {
    // No wakeup from timer or ext1
    CLEAR_PERI_REG_MASK(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA_M);
    
    // Only wake up from power button
    REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, 0x01);
  }
  
  // If there is a USB device in and we are light sleeping, we don't want to turn the buck off
  if (DcpUfpIsConnected() && sleep_level == SLEEP_LEVEL_LIGHT)
  {
    ToggleBuck(true);
  }
  else
  {
    ToggleBuck(false);
  }

  // TODO: Fix rtc_hold_en
  SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_HOLD_M);
  
  // Enter deep sleep, we don't return from this
  // Set the pointer of the wake stub function.
  REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)&esp_wake_deep_sleep);
  
  // 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)
  {
  }
}

Code: Select all

#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "soc/rtc.h"
#include "driver/gpio.h"
#include "soc/rtc_periph.h"
#include "esp_sleep.h"
#include "PowerDefs.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/uart_reg.h"
#include "soc/timer_group_reg.h"
#include "esp_sleep.h"
#include "esp_attr.h"
#include "esp32/rom/rtc.h"
#include "esp32/rom/gpio.h"
#include "esp32/rom/ets_sys.h"
#include "soc/gpio_periph.h"
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "driver/adc.h"
#include "soc/rtc_io_periph.h"
#include "StubSdk.h"

#ifndef _SOC_RTC_GPIO_CHANNEL_H

//RTC GPIO channels
#define RTCIO_GPIO36_CHANNEL        0   //RTCIO_CHANNEL_0
#define RTCIO_CHANNEL_0_GPIO_NUM    36

#define RTCIO_GPIO37_CHANNEL        1   //RTCIO_CHANNEL_1
#define RTCIO_CHANNEL_1_GPIO_NUM    37

#define RTCIO_GPIO38_CHANNEL        2   //RTCIO_CHANNEL_2
#define RTCIO_CHANNEL_2_GPIO_NUM    38

#define RTCIO_GPIO39_CHANNEL        3   //RTCIO_CHANNEL_3
#define RTCIO_CHANNEL_3_GPIO_NUM    39

#define RTCIO_GPIO34_CHANNEL        4   //RTCIO_CHANNEL_4
#define RTCIO_CHANNEL_4_GPIO_NUM    34

#define RTCIO_GPIO35_CHANNEL        5   //RTCIO_CHANNEL_5
#define RTCIO_CHANNEL_5_GPIO_NUM    35

#define RTCIO_GPIO25_CHANNEL        6   //RTCIO_CHANNEL_6
#define RTCIO_CHANNEL_6_GPIO_NUM    25

#define RTCIO_GPIO26_CHANNEL        7   //RTCIO_CHANNEL_7
#define RTCIO_CHANNEL_7_GPIO_NUM    26

#define RTCIO_GPIO33_CHANNEL        8   //RTCIO_CHANNEL_8
#define RTCIO_CHANNEL_8_GPIO_NUM    33

#define RTCIO_GPIO32_CHANNEL        9   //RTCIO_CHANNEL_9
#define RTCIO_CHANNEL_9_GPIO_NUM    32

#define RTCIO_GPIO4_CHANNEL         10   //RTCIO_CHANNEL_10
#define RTCIO_CHANNEL_10_GPIO_NUM   4

#define RTCIO_GPIO0_CHANNEL         11   //RTCIO_CHANNEL_11
#define RTCIO_CHANNEL_11_GPIO_NUM   0

#define RTCIO_GPIO2_CHANNEL         12   //RTCIO_CHANNEL_12
#define RTCIO_CHANNEL_12_GPIO_NUM   2

#define RTCIO_GPIO15_CHANNEL        13   //RTCIO_CHANNEL_13
#define RTCIO_CHANNEL_13_GPIO_NUM   15

#define RTCIO_GPIO13_CHANNEL        14   //RTCIO_CHANNEL_14
#define RTCIO_CHANNEL_14_GPIO_NUM   13

#define RTCIO_GPIO12_CHANNEL        15   //RTCIO_CHANNEL_15
#define RTCIO_CHANNEL_15_GPIO_NUM   12

#define RTCIO_GPIO14_CHANNEL        16   //RTCIO_CHANNEL_16
#define RTCIO_CHANNEL_16_GPIO_NUM   14

#define RTCIO_GPIO27_CHANNEL        17   //RTCIO_CHANNEL_17
#define RTCIO_CHANNEL_17_GPIO_NUM   27

#endif

typedef struct {
    uint32_t reg;       /*!< Register of RTC pad, or 0 if not an RTC GPIO */
    uint32_t mux;       /*!< Bit mask for selecting digital pad or RTC pad */
    uint32_t func;      /*!< Shift of pad function (FUN_SEL) field */
    uint32_t ie;        /*!< Mask of input enable */
    uint32_t pullup;    /*!< Mask of pullup enable */
    uint32_t pulldown;  /*!< Mask of pulldown enable */
    uint32_t slpsel;    /*!< If slpsel bit is set, slpie will be used as pad input enabled signal in sleep mode */
    uint32_t slpie;     /*!< Mask of input enable in sleep mode */
    uint32_t hold;      /*!< Mask of hold enable */
    uint32_t hold_force;/*!< Mask of hold_force bit for RTC IO in RTC_CNTL_HOLD_FORCE_REG */
    uint32_t drv_v;     /*!< Mask of drive capability */
    uint32_t drv_s;     /*!< Offset of drive capability */
    int rtc_num;        /*!< RTC IO number, or -1 if not an RTC GPIO */
} __rtc_gpio_desc_t;

RTC_RODATA_ATTR uint32_t STUB_GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = {
    IO_MUX_GPIO0_REG,
    IO_MUX_GPIO1_REG,
    IO_MUX_GPIO2_REG,
    IO_MUX_GPIO3_REG,
    IO_MUX_GPIO4_REG,
    IO_MUX_GPIO5_REG,
    IO_MUX_GPIO6_REG,
    IO_MUX_GPIO7_REG,
    IO_MUX_GPIO8_REG,
    IO_MUX_GPIO9_REG,
    IO_MUX_GPIO10_REG,
    IO_MUX_GPIO11_REG,
    IO_MUX_GPIO12_REG,
    IO_MUX_GPIO13_REG,
    IO_MUX_GPIO14_REG,
    IO_MUX_GPIO15_REG,
    IO_MUX_GPIO16_REG,
    IO_MUX_GPIO17_REG,
    IO_MUX_GPIO18_REG,
    IO_MUX_GPIO19_REG,
    0,
    IO_MUX_GPIO21_REG,
    IO_MUX_GPIO22_REG,
    IO_MUX_GPIO23_REG,
    0,
    IO_MUX_GPIO25_REG,
    IO_MUX_GPIO26_REG,
    IO_MUX_GPIO27_REG,
    0,
    0,
    0,
    0,
    IO_MUX_GPIO32_REG,
    IO_MUX_GPIO33_REG,
    IO_MUX_GPIO34_REG,
    IO_MUX_GPIO35_REG,
    IO_MUX_GPIO36_REG,
    IO_MUX_GPIO37_REG,
    IO_MUX_GPIO38_REG,
    IO_MUX_GPIO39_REG,
};

//Reg,Mux,Fun,IE,Up,Down,Rtc_number
RTC_RODATA_ATTR __rtc_gpio_desc_t __rtc_gpio_desc[GPIO_PIN_COUNT] = {
    {RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_MUX_SEL_M, RTC_IO_TOUCH_PAD1_FUN_SEL_S, RTC_IO_TOUCH_PAD1_FUN_IE_M, RTC_IO_TOUCH_PAD1_RUE_M, RTC_IO_TOUCH_PAD1_RDE_M, RTC_IO_TOUCH_PAD1_SLP_SEL_M, RTC_IO_TOUCH_PAD1_SLP_IE_M, RTC_IO_TOUCH_PAD1_HOLD_M, RTC_CNTL_TOUCH_PAD1_HOLD_FORCE_M, RTC_IO_TOUCH_PAD1_DRV_V, RTC_IO_TOUCH_PAD1_DRV_S, RTCIO_GPIO0_CHANNEL}, //0
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //1
    {RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_M, RTC_IO_TOUCH_PAD2_FUN_SEL_S, RTC_IO_TOUCH_PAD2_FUN_IE_M, RTC_IO_TOUCH_PAD2_RUE_M, RTC_IO_TOUCH_PAD2_RDE_M, RTC_IO_TOUCH_PAD2_SLP_SEL_M, RTC_IO_TOUCH_PAD2_SLP_IE_M, RTC_IO_TOUCH_PAD2_HOLD_M, RTC_CNTL_TOUCH_PAD2_HOLD_FORCE_M, RTC_IO_TOUCH_PAD2_DRV_V, RTC_IO_TOUCH_PAD2_DRV_S, RTCIO_GPIO2_CHANNEL}, //2
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //3
    {RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_MUX_SEL_M, RTC_IO_TOUCH_PAD0_FUN_SEL_S, RTC_IO_TOUCH_PAD0_FUN_IE_M, RTC_IO_TOUCH_PAD0_RUE_M, RTC_IO_TOUCH_PAD0_RDE_M, RTC_IO_TOUCH_PAD0_SLP_SEL_M, RTC_IO_TOUCH_PAD0_SLP_IE_M, RTC_IO_TOUCH_PAD0_HOLD_M,  RTC_CNTL_TOUCH_PAD0_HOLD_FORCE_M, RTC_IO_TOUCH_PAD0_DRV_V, RTC_IO_TOUCH_PAD0_DRV_S, RTCIO_GPIO4_CHANNEL}, //4
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //5
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //6
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //7
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //8
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //9
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //10
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //11
    {RTC_IO_TOUCH_PAD5_REG, RTC_IO_TOUCH_PAD5_MUX_SEL_M, RTC_IO_TOUCH_PAD5_FUN_SEL_S, RTC_IO_TOUCH_PAD5_FUN_IE_M, RTC_IO_TOUCH_PAD5_RUE_M, RTC_IO_TOUCH_PAD5_RDE_M, RTC_IO_TOUCH_PAD5_SLP_SEL_M, RTC_IO_TOUCH_PAD5_SLP_IE_M, RTC_IO_TOUCH_PAD5_HOLD_M, RTC_CNTL_TOUCH_PAD5_HOLD_FORCE_M, RTC_IO_TOUCH_PAD5_DRV_V, RTC_IO_TOUCH_PAD5_DRV_S, RTCIO_GPIO12_CHANNEL}, //12
    {RTC_IO_TOUCH_PAD4_REG, RTC_IO_TOUCH_PAD4_MUX_SEL_M, RTC_IO_TOUCH_PAD4_FUN_SEL_S, RTC_IO_TOUCH_PAD4_FUN_IE_M, RTC_IO_TOUCH_PAD4_RUE_M, RTC_IO_TOUCH_PAD4_RDE_M, RTC_IO_TOUCH_PAD4_SLP_SEL_M, RTC_IO_TOUCH_PAD4_SLP_IE_M, RTC_IO_TOUCH_PAD4_HOLD_M, RTC_CNTL_TOUCH_PAD4_HOLD_FORCE_M, RTC_IO_TOUCH_PAD4_DRV_V, RTC_IO_TOUCH_PAD4_DRV_S, RTCIO_GPIO13_CHANNEL}, //13
    {RTC_IO_TOUCH_PAD6_REG, RTC_IO_TOUCH_PAD6_MUX_SEL_M, RTC_IO_TOUCH_PAD6_FUN_SEL_S, RTC_IO_TOUCH_PAD6_FUN_IE_M, RTC_IO_TOUCH_PAD6_RUE_M, RTC_IO_TOUCH_PAD6_RDE_M, RTC_IO_TOUCH_PAD6_SLP_SEL_M, RTC_IO_TOUCH_PAD6_SLP_IE_M, RTC_IO_TOUCH_PAD6_HOLD_M, RTC_CNTL_TOUCH_PAD6_HOLD_FORCE_M, RTC_IO_TOUCH_PAD6_DRV_V, RTC_IO_TOUCH_PAD6_DRV_S, RTCIO_GPIO14_CHANNEL}, //14
    {RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_MUX_SEL_M, RTC_IO_TOUCH_PAD3_FUN_SEL_S, RTC_IO_TOUCH_PAD3_FUN_IE_M, RTC_IO_TOUCH_PAD3_RUE_M, RTC_IO_TOUCH_PAD3_RDE_M, RTC_IO_TOUCH_PAD3_SLP_SEL_M, RTC_IO_TOUCH_PAD3_SLP_IE_M, RTC_IO_TOUCH_PAD3_HOLD_M, RTC_CNTL_TOUCH_PAD3_HOLD_FORCE_M, RTC_IO_TOUCH_PAD3_DRV_V, RTC_IO_TOUCH_PAD3_DRV_S, RTCIO_GPIO15_CHANNEL}, //15
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //16
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //17
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //18
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //19
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //20
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //21
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //22
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //23
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //24
    {RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_MUX_SEL_M, RTC_IO_PDAC1_FUN_SEL_S, RTC_IO_PDAC1_FUN_IE_M, RTC_IO_PDAC1_RUE_M, RTC_IO_PDAC1_RDE_M, RTC_IO_PDAC1_SLP_SEL_M, RTC_IO_PDAC1_SLP_IE_M, RTC_IO_PDAC1_HOLD_M, RTC_CNTL_PDAC1_HOLD_FORCE_M, RTC_IO_PDAC1_DRV_V, RTC_IO_PDAC1_DRV_S, RTCIO_GPIO25_CHANNEL},                           //25
    {RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_MUX_SEL_M, RTC_IO_PDAC2_FUN_SEL_S, RTC_IO_PDAC2_FUN_IE_M, RTC_IO_PDAC2_RUE_M, RTC_IO_PDAC2_RDE_M, RTC_IO_PDAC2_SLP_SEL_M, RTC_IO_PDAC2_SLP_IE_M, RTC_IO_PDAC2_HOLD_M, RTC_CNTL_PDAC2_HOLD_FORCE_M, RTC_IO_PDAC2_DRV_V, RTC_IO_PDAC2_DRV_S, RTCIO_GPIO26_CHANNEL},                           //26
    {RTC_IO_TOUCH_PAD7_REG, RTC_IO_TOUCH_PAD7_MUX_SEL_M, RTC_IO_TOUCH_PAD7_FUN_SEL_S, RTC_IO_TOUCH_PAD7_FUN_IE_M, RTC_IO_TOUCH_PAD7_RUE_M, RTC_IO_TOUCH_PAD7_RDE_M, RTC_IO_TOUCH_PAD7_SLP_SEL_M, RTC_IO_TOUCH_PAD7_SLP_IE_M, RTC_IO_TOUCH_PAD7_HOLD_M, RTC_CNTL_TOUCH_PAD7_HOLD_FORCE_M, RTC_IO_TOUCH_PAD7_DRV_V, RTC_IO_TOUCH_PAD7_DRV_S, RTCIO_GPIO27_CHANNEL}, //27
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //28
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //29
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //30
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},                                                                                                                                            //31
    {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_MUX_SEL_M, RTC_IO_X32P_FUN_SEL_S, RTC_IO_X32P_FUN_IE_M, RTC_IO_X32P_RUE_M, RTC_IO_X32P_RDE_M, RTC_IO_X32P_SLP_SEL_M, RTC_IO_X32P_SLP_IE_M, RTC_IO_X32P_HOLD_M, RTC_CNTL_X32P_HOLD_FORCE_M, RTC_IO_X32P_DRV_V, RTC_IO_X32P_DRV_S, RTCIO_GPIO32_CHANNEL},                            //32
    {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL_M, RTC_IO_X32N_FUN_SEL_S, RTC_IO_X32N_FUN_IE_M, RTC_IO_X32N_RUE_M, RTC_IO_X32N_RDE_M, RTC_IO_X32N_SLP_SEL_M, RTC_IO_X32N_SLP_IE_M, RTC_IO_X32N_HOLD_M, RTC_CNTL_X32N_HOLD_FORCE_M, RTC_IO_X32N_DRV_V, RTC_IO_X32N_DRV_S, RTCIO_GPIO33_CHANNEL},                            //33
    {RTC_IO_ADC_PAD_REG, RTC_IO_ADC1_MUX_SEL_M, RTC_IO_ADC1_FUN_SEL_S, RTC_IO_ADC1_FUN_IE_M, 0, 0, RTC_IO_ADC1_SLP_SEL_M, RTC_IO_ADC1_SLP_IE_M, RTC_IO_ADC1_HOLD_M, RTC_CNTL_ADC1_HOLD_FORCE_M, 0, 0, RTCIO_GPIO34_CHANNEL},                                                                //34
    {RTC_IO_ADC_PAD_REG, RTC_IO_ADC2_MUX_SEL_M, RTC_IO_ADC2_FUN_SEL_S, RTC_IO_ADC2_FUN_IE_M, 0, 0, RTC_IO_ADC2_SLP_SEL_M, RTC_IO_ADC2_SLP_IE_M, RTC_IO_ADC2_HOLD_M, RTC_CNTL_ADC2_HOLD_FORCE_M, 0, 0, RTCIO_GPIO35_CHANNEL},                                                                //35
    {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE1_MUX_SEL_M, RTC_IO_SENSE1_FUN_SEL_S, RTC_IO_SENSE1_FUN_IE_M, 0, 0, RTC_IO_SENSE1_SLP_SEL_M, RTC_IO_SENSE1_SLP_IE_M, RTC_IO_SENSE1_HOLD_M, RTC_CNTL_SENSE1_HOLD_FORCE_M, 0, 0, RTCIO_GPIO36_CHANNEL},                                                      //36
    {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE2_MUX_SEL_M, RTC_IO_SENSE2_FUN_SEL_S, RTC_IO_SENSE2_FUN_IE_M, 0, 0, RTC_IO_SENSE2_SLP_SEL_M, RTC_IO_SENSE2_SLP_IE_M, RTC_IO_SENSE2_HOLD_M, RTC_CNTL_SENSE2_HOLD_FORCE_M, 0, 0, RTCIO_GPIO37_CHANNEL},                                                      //37
    {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE3_MUX_SEL_M, RTC_IO_SENSE3_FUN_SEL_S, RTC_IO_SENSE3_FUN_IE_M, 0, 0, RTC_IO_SENSE3_SLP_SEL_M, RTC_IO_SENSE3_SLP_IE_M, RTC_IO_SENSE3_HOLD_M, RTC_CNTL_SENSE3_HOLD_FORCE_M, 0, 0, RTCIO_GPIO38_CHANNEL},                                                       //38
    {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE4_MUX_SEL_M, RTC_IO_SENSE4_FUN_SEL_S, RTC_IO_SENSE4_FUN_IE_M, 0, 0, RTC_IO_SENSE4_SLP_SEL_M, RTC_IO_SENSE4_SLP_IE_M, RTC_IO_SENSE4_HOLD_M, RTC_CNTL_SENSE4_HOLD_FORCE_M, 0, 0, RTCIO_GPIO39_CHANNEL},                                                      //39
};

static RTC_IRAM_ATTR bool rtc_gpio_is_valid_gpio(gpio_num_t gpio_num);

static RTC_IRAM_ATTR bool rtc_gpio_is_valid_gpio(gpio_num_t gpio_num)
{
    return gpio_num < GPIO_PIN_COUNT
        && __rtc_gpio_desc[gpio_num].reg != 0;
}

#define RTC_GPIO_IS_VALID_GPIO(gpio_num) rtc_gpio_is_valid_gpio(gpio_num) // Deprecated, use rtc_gpio_is_valid_gpio()

RTC_IRAM_ATTR void stub_rtc_gpio_deinit(gpio_num_t gpio_num)
{
    //Select Gpio as Digital Gpio
    CLEAR_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, (__rtc_gpio_desc[gpio_num].mux));
}

// https://github.com/espressif/esp-idf/blob/e7f85f1987aa9479c2dbab638ca83bcaef99be00/components/driver/gpio.c#L240
RTC_IRAM_ATTR void stub_gpio_config(const gpio_config_t *pGPIOConfig)
{
    uint64_t gpio_pin_mask = (pGPIOConfig->pin_bit_mask);
    uint32_t io_reg = 0;
    uint32_t io_num = 0;
    do {
        io_reg = STUB_GPIO_PIN_MUX_REG[io_num];
        if (((gpio_pin_mask >> io_num) & BIT(0))) {
            if(RTC_GPIO_IS_VALID_GPIO(io_num)){
                stub_rtc_gpio_deinit(io_num);
            }
            if ((pGPIOConfig->mode) & GPIO_MODE_DEF_INPUT) {
                PIN_INPUT_ENABLE(STUB_GPIO_PIN_MUX_REG[io_num]);
            } else {
                PIN_INPUT_DISABLE(STUB_GPIO_PIN_MUX_REG[io_num]);
            }
            if ((pGPIOConfig->mode) & GPIO_MODE_DEF_OD) {
                GPIO.pin[io_num].pad_driver = 1; /*0x01 Open-drain */
            } else {
                GPIO.pin[io_num].pad_driver = 0; /*0x00 Normal gpio output */
            }
            if ((pGPIOConfig->mode) & GPIO_MODE_DEF_OUTPUT) {
                //gpio_output_enable(io_num);
                stub_gpio_output_enable(io_num);
            } else {
                //gpio_output_disable(io_num);
                stub_gpio_output_disable(io_num);
            }
            if (pGPIOConfig->pull_up_en) {
                stub_gpio_pullup_en(io_num);
            } else {
                stub_gpio_pullup_dis(io_num);
            }
            if (pGPIOConfig->pull_down_en) {
                stub_gpio_pulldown_en(io_num);
            } else {
                stub_gpio_pulldown_dis(io_num);
            }
            
            PIN_FUNC_SELECT(io_reg, PIN_FUNC_GPIO); /*function number 2 is GPIO_FUNC for each pin */
        }
        io_num++;
    } while (io_num < GPIO_PIN_COUNT);
}

// https://github.com/espressif/esp-idf/blob/e7f85f1987aa9479c2dbab638ca83bcaef99be00/components/driver/gpio.c#L75
RTC_IRAM_ATTR void stub_gpio_pulldown_dis(gpio_num_t gpio_num)
{
    if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
        stub_rtc_gpio_pulldown_dis(gpio_num);
    } else {
        REG_CLR_BIT(STUB_GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
    }
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L323
RTC_IRAM_ATTR void stub_rtc_gpio_pulldown_dis(gpio_num_t gpio_num)
{
    CLEAR_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, __rtc_gpio_desc[gpio_num].pulldown);
}

// https://github.com/espressif/esp-idf/blob/e7f85f1987aa9479c2dbab638ca83bcaef99be00/components/driver/gpio.c#L64
RTC_IRAM_ATTR void stub_gpio_pulldown_en(gpio_num_t gpio_num)
{
    if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
        stub_rtc_gpio_pulldown_en(gpio_num);
    } else {
        REG_SET_BIT(STUB_GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
    }
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L293
RTC_IRAM_ATTR void stub_rtc_gpio_pulldown_en(gpio_num_t gpio_num)
{
    SET_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, __rtc_gpio_desc[gpio_num].pulldown);
}

// https://github.com/espressif/esp-idf/blob/e7f85f1987aa9479c2dbab638ca83bcaef99be00/components/driver/gpio.c#L53
RTC_IRAM_ATTR void stub_gpio_pullup_dis(gpio_num_t gpio_num)
{
    if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
        stub_rtc_gpio_pullup_dis(gpio_num);
    } else {
        REG_CLR_BIT(STUB_GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
    }
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L308
RTC_IRAM_ATTR void stub_rtc_gpio_pullup_dis(gpio_num_t gpio_num)
{
    CLEAR_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, __rtc_gpio_desc[gpio_num].pullup);
}

// https://github.com/espressif/esp-idf/blob/e7f85f1987aa9479c2dbab638ca83bcaef99be00/components/driver/gpio.c#L42
RTC_IRAM_ATTR void stub_gpio_pullup_en(gpio_num_t gpio_num)
{
    if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
        stub_rtc_gpio_pullup_en(gpio_num);
    } else {
        REG_SET_BIT(STUB_GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
    }
}

// https://github.com/espressif/esp-idf/blob/e7f85f1987aa9479c2dbab638ca83bcaef99be00/components/driver/gpio.c#L128
RTC_IRAM_ATTR void stub_gpio_output_disable(gpio_num_t gpio_num)
{
    if (gpio_num < 32) {
        GPIO.enable_w1tc = (0x1 << gpio_num);
    } else {
        GPIO.enable1_w1tc.data = (0x1 << (gpio_num - 32));
    }

    // Ensure no other output signal is routed via GPIO matrix to this pin
    REG_WRITE(GPIO_FUNC0_OUT_SEL_CFG_REG + (gpio_num * 4), SIG_GPIO_OUT_IDX);
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L1805
RTC_IRAM_ATTR void stub_dac1_output_enable()
{
    stub_rtc_gpio_init(GPIO_NUM_25);
    stub_rtc_gpio_output_disable(GPIO_NUM_25);
    stub_rtc_gpio_input_disable(GPIO_NUM_25);
    
    // Float the GPIO
    CLEAR_PERI_REG_MASK(__rtc_gpio_desc[GPIO_NUM_25].reg, __rtc_gpio_desc[GPIO_NUM_25].pulldown);
    CLEAR_PERI_REG_MASK(__rtc_gpio_desc[GPIO_NUM_25].reg, __rtc_gpio_desc[GPIO_NUM_25].pullup);

    RTCIO.pad_dac[DAC_CHANNEL_1].dac_xpd_force = true;
    RTCIO.pad_dac[DAC_CHANNEL_1].xpd_dac = true;
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L1826
RTC_IRAM_ATTR void stub_dac1_output_voltage(uint8_t dac_value)
{
    CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
    CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M);
    SET_PERI_REG_BITS(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC, dac_value, RTC_IO_PDAC1_DAC_S);   //dac_output
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L1469
RTC_IRAM_ATTR void stub_adc1_config_width()
{
    SENS.sar_start_force.sar1_bit_width = ADC_WIDTH_BIT_12;
    SENS.sar_read_ctrl.sar1_sample_bit = ADC_WIDTH_BIT_12;
    SENS.sar_read_ctrl.sar1_data_inv = true;
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L140
RTC_IRAM_ATTR void stub_rtc_gpio_init(gpio_num_t gpio_num)
{
    // 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module.
    SET_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, (__rtc_gpio_desc[gpio_num].mux));
    //0:RTC FUNCIOTN 1,2,3:Reserved
    SET_PERI_REG_BITS(__rtc_gpio_desc[gpio_num].reg, RTC_IO_TOUCH_PAD1_FUN_SEL_V, 0x0, __rtc_gpio_desc[gpio_num].func);
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L174
RTC_IRAM_ATTR void stub_rtc_gpio_output_disable(gpio_num_t gpio_num)
{
    int rtc_gpio_num = __rtc_gpio_desc[gpio_num].rtc_num;
    CLEAR_PERI_REG_MASK(RTC_GPIO_ENABLE_W1TS_REG, (1 << (rtc_gpio_num + RTC_GPIO_ENABLE_W1TS_S)));
    SET_PERI_REG_MASK(RTC_GPIO_ENABLE_W1TC_REG, (1 << ( rtc_gpio_num + RTC_GPIO_ENABLE_W1TC_S)));
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L194
RTC_IRAM_ATTR void stub_rtc_gpio_input_disable(gpio_num_t gpio_num)
{
    CLEAR_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, __rtc_gpio_desc[gpio_num].ie);
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L1125
RTC_IRAM_ATTR void stub_adc_set_atten(adc_unit_t adc_unit, adc_channel_t channel, adc_atten_t atten)
{
  SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, SENS_SAR1_ATTEN_VAL_MASK, atten, (channel * 2));
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L1460
RTC_IRAM_ATTR void stub_adc1_config_channel_atten(adc1_channel_t channel, gpio_num_t gpio_num, adc_atten_t atten)
{
    stub_rtc_gpio_init(gpio_num);
    stub_rtc_gpio_output_disable(gpio_num);
    stub_rtc_gpio_input_disable(gpio_num);

    // Float the GPIO
    CLEAR_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, __rtc_gpio_desc[gpio_num].pulldown);
    CLEAR_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, __rtc_gpio_desc[gpio_num].pullup);
    
    stub_adc_set_atten(ADC_UNIT_1, channel, atten);
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L1318
RTC_IRAM_ATTR int stub_adc_convert(const int channel)
{
    SENS.sar_meas_start1.sar1_en_pad = (1 << channel); //only one channel is selected.
    while (SENS.sar_slave_addr1.meas_status != 0);
    SENS.sar_meas_start1.meas1_start_sar = 0;
    SENS.sar_meas_start1.meas1_start_sar = 1;
    while (SENS.sar_meas_start1.meas1_done_sar == 0);
    return SENS.sar_meas_start1.meas1_data_sar;
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c#L1531
RTC_IRAM_ATTR int stub_adc1_get_raw(adc1_channel_t channel)
{
    SENS.sar_read_ctrl.sar1_dig_force = 0;

    //channel is set in the  convert function
    SENS.sar_meas_wait2.force_xpd_amp = SENS_FORCE_XPD_AMP_PD;
    //disable FSM, it's only used by the LNA.
    SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0;
    SENS.sar_meas_ctrl.amp_short_ref_fsm = 0;
    SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0;
    SENS.sar_meas_wait1.sar_amp_wait1 = 1;
    SENS.sar_meas_wait1.sar_amp_wait2 = 1;
    SENS.sar_meas_wait2.sar_amp_wait3 = 1;   
    
    //set controller
    SENS.sar_read_ctrl.sar1_dig_force = false;      //RTC controller controls the ADC, not digital controller
    SENS.sar_meas_start1.meas1_start_force = true;  //RTC controller controls the ADC,not ulp coprocessor
    SENS.sar_meas_start1.sar1_en_pad_force = true;  //RTC controller controls the data port, not ulp coprocessor
    SENS.sar_touch_ctrl1.xpd_hall_force = true;     // RTC controller controls the hall sensor power,not ulp coprocessor
    SENS.sar_touch_ctrl1.hall_phase_force = true;   // RTC controller controls the hall sensor phase,not ulp coprocessor
    
    //start conversion
    return stub_adc_convert(channel);
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c
RTC_IRAM_ATTR void stub_rtc_gpio_hold_en(gpio_num_t gpio_num)
{
    SET_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, __rtc_gpio_desc[gpio_num].hold);
}

RTC_IRAM_ATTR void stub_gpio_output_enable(gpio_num_t gpio_num)
{
    if (gpio_num < 32) {
        GPIO.enable_w1ts = (0x1 << gpio_num);
    } else {
        GPIO.enable1_w1ts.data = ((uint64_t)0x1 << (gpio_num - 32));
    }
    gpio_matrix_out(gpio_num, SIG_GPIO_OUT_IDX, false, false);
}

RTC_IRAM_ATTR void stub_gpio_set_level(gpio_num_t gpio_num, uint32_t level)
{
    if (level) {
        if (gpio_num < 32) {
            GPIO.out_w1ts = (1 << gpio_num);
        } else {
            GPIO.out1_w1ts.data = ((uint64_t)1 << (gpio_num - 32));
        }
    } else {
        if (gpio_num < 32) {
            GPIO.out_w1tc = (1 << gpio_num);
        } else {
            GPIO.out1_w1tc.data = ((uint64_t)1 << (gpio_num - 32));
        }
    }
}

// https://github.com/espressif/esp-idf/blob/a20d02b7f196c407bc9f39b781e31a0a4f665968/components/esp32/sleep_modes.c
/*RTC_IRAM_ATTR void stub_ext0_wakeup_prepare(const uint32_t gpio, const int level)
{
    // Set GPIO to be used for wakeup
    REG_SET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL, gpio);
    // Set level which will trigger wakeup
    SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, level, RTC_CNTL_EXT_WAKEUP0_LV_S);
    // Find GPIO descriptor in the __rtc_gpio_desc table and configure the pad
    for (size_t gpio_num = 0; gpio_num < GPIO_PIN_COUNT; ++gpio_num) {
        const __rtc_gpio_desc_t* desc = &__rtc_gpio_desc[gpio_num];
        if (desc->rtc_num == gpio) {
            REG_SET_BIT(desc->reg, desc->mux);
            SET_PERI_REG_BITS(desc->reg, 0x3, 0, desc->func);
            REG_SET_BIT(desc->reg, desc->ie);
            break;
        }
    }
}*/



RTC_IRAM_ATTR void stub_ext0_wakeup_prepare(uint32_t rtc_gpio_num, int level)
{
    // Set GPIO to be used for wakeup
    REG_SET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL, rtc_gpio_num);
    // Set level which will trigger wakeup
    SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, level, RTC_CNTL_EXT_WAKEUP0_LV_S);
    // Find GPIO descriptor in the rtc_io_desc table and configure the pad
    const __rtc_gpio_desc_t* desc = &__rtc_gpio_desc[rtc_gpio_num];
    REG_SET_BIT(desc->reg, desc->mux);
    SET_PERI_REG_BITS(desc->reg, 0x3, 0, desc->func);
    REG_SET_BIT(desc->reg, desc->ie);
}



// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c
RTC_IRAM_ATTR void stub_rtc_gpio_pullup_en(gpio_num_t gpio_num)
{
    SET_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, __rtc_gpio_desc[gpio_num].pullup);
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/driver/rtc_module.c
RTC_IRAM_ATTR void stub_rtc_gpio_hold_dis(gpio_num_t gpio_num)
{
    CLEAR_PERI_REG_MASK(__rtc_gpio_desc[gpio_num].reg, __rtc_gpio_desc[gpio_num].hold);
}

// https://github.com/espressif/esp-idf/blob/a20d02b7f196c407bc9f39b781e31a0a4f665968/components/esp32/sleep_modes.c
RTC_IRAM_ATTR void stub_ext1_wakeup_prepare(uint32_t mask, esp_sleep_ext1_wakeup_mode_t mode)
{
    // Clear state from previous wakeup
    REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
    // Set pins to be used for wakeup
    REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, mask);
    // Set logic function (any low, all high)
    SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, mode, RTC_CNTL_EXT_WAKEUP1_LV_S);
}

// https://github.com/espressif/esp-idf/blob/a20d02b7f196c407bc9f39b781e31a0a4f665968/components/esp32/sleep_modes.c
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;
    } 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;
    }
}

// https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/soc/esp32/rtc_time.c
RTC_IRAM_ATTR uint64_t stub_rtc_time_get()
{
    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); // might take 1 RTC slowclk period, don't flood RTC bus
    }
    SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_TIME_VALID_INT_CLR);
    uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
    t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
    return t;
}

RTC_IRAM_ATTR void stub_rtc_sleep_set_wakeup_time(uint64_t t)
{
    WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
    WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
}

// https://github.com/espressif/esp-idf/blob/a20d02b7f196c407bc9f39b781e31a0a4f665968/components/esp32/sleep_modes.c
RTC_IRAM_ATTR void stub_timer_wakeup_prepare(const uint64_t sleep_duration)
{
  // https://github.com/espressif/esp-idf/blob/3bb7dba9957ee71a236058322ae5e70f96f9a104/components/newlib/time.c
  uint32_t period = REG_READ(RTC_SLOW_CLK_CAL_REG);
  
  // https://github.com/espressif/esp-idf/blob/9f3b550ff4df63d0787f5ae6499eb97e13b954b9/components/soc/esp32/rtc_time.c
  /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days.
  * TODO: fix overflow.
  */
  int64_t rtc_count_delta = (sleep_duration << RTC_CLK_CAL_FRACT) / period;

   stub_rtc_sleep_set_wakeup_time(stub_rtc_time_get() + rtc_count_delta);
}

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

Re: Esp32 deep sleep issues: Won't wake up from ext1

Postby iParcelBox » Wed Apr 06, 2022 4:49 pm

I'd be very interested to know whether you ever got to the bottom of this, as I'm trying to do something very similar. My ESP32 goes into deep sleep, with EXT0, and EXT1 and Timer set as wake sources. When it wakes from timer, I need the wake stub to put it back to sleep with the same sources still set. I can successfully wake from timer and report on the wake source, but neither EXT0 or EXT1 seem to be working.

Who is online

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