deep sleep: add deep sleep support for esp32s3

pull/7751/head
Li Shuai 2021-08-11 22:06:47 +08:00
rodzic 9298db641e
commit 881e1b0fd5
4 zmienionych plików z 72 dodań i 29 usunięć

Wyświetl plik

@ -188,12 +188,41 @@ static void touch_wakeup_prepare(void);
static void esp_deep_sleep_wakeup_prepare(void);
#endif
#if SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
static RTC_FAST_ATTR esp_deep_sleep_wake_stub_fn_t wake_stub_fn_handler = NULL;
static void RTC_IRAM_ATTR __attribute__((used, noinline)) esp_wake_stub_start(void)
{
if (wake_stub_fn_handler) {
(*wake_stub_fn_handler)();
}
}
/* We must have a default deep sleep wake stub entry function, which must be
* located at the start address of the RTC fast memory, and its implementation
* must be simple enough to ensure that there is no litteral data before the
* wake stub entry, otherwise, the litteral data before the wake stub entry
* will not be CRC checked. */
static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void)
{
#define _SYM2STR(s) # s
#define SYM2STR(s) _SYM2STR(s)
// call4 has a larger effective addressing range (-524284 to 524288 bytes),
// which is sufficient for instruction addressing in RTC fast memory.
__asm__ __volatile__ ("call4 " SYM2STR(esp_wake_stub_start) "\n");
}
#endif // SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
/* Wake from deep sleep stub
See esp_deepsleep.h esp_wake_deep_sleep() comments for details.
*/
esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
{
#if SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
esp_deep_sleep_wake_stub_fn_t stub_ptr = wake_stub_fn_handler;
#else
esp_deep_sleep_wake_stub_fn_t stub_ptr = (esp_deep_sleep_wake_stub_fn_t) REG_READ(RTC_ENTRY_ADDR_REG);
#endif
if (!esp_ptr_executable(stub_ptr)) {
return NULL;
}
@ -202,7 +231,11 @@ esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub)
{
#if SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
wake_stub_fn_handler = new_stub;
#else
REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub);
#endif
}
void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void)
@ -416,18 +449,27 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
*/
portENTER_CRITICAL(&spinlock_rtc_deep_sleep);
#if SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
extern char _rtc_text_start[];
#if CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM
extern char _rtc_noinit_end[];
size_t rtc_fast_length = (size_t)_rtc_noinit_end - (size_t)_rtc_text_start;
#else
extern char _rtc_force_fast_end[];
size_t rtc_fast_length = (size_t)_rtc_force_fast_end - (size_t)_rtc_text_start;
#endif
esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)esp_wake_stub_entry, rtc_fast_length);
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu);
#else
#if !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
/* If not possible stack is in RTC FAST memory, use the ROM function to calculate the CRC and save ~140 bytes IRAM */
#if CONFIG_IDF_TARGET_ESP32S3//TODO: WIFI-3542
result = 0;
#else
set_rtc_memory_crc();
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu);
#endif
#else
/* Otherwise, need to call the dedicated soc function for this */
result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers);
#endif
#endif // SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
portEXIT_CRITICAL(&spinlock_rtc_deep_sleep);
} else {

Wyświetl plik

@ -62,6 +62,7 @@ extern "C" {
#define RTC_BOOT_TIME_LOW_REG RTC_CNTL_STORE2_REG
#define RTC_BOOT_TIME_HIGH_REG RTC_CNTL_STORE3_REG
#define RTC_XTAL_FREQ_REG RTC_CNTL_STORE4_REG
#define RTC_ENTRY_LENGTH_REG RTC_CNTL_STORE5_REG
#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG
#define RTC_RESET_CAUSE_REG RTC_CNTL_STORE6_REG
#define RTC_MEMORY_CRC_REG RTC_CNTL_STORE7_REG
@ -173,16 +174,31 @@ RESET_REASON rtc_get_reset_reason(int cpu_no);
*/
WAKEUP_REASON rtc_get_wakeup_cause(void);
typedef void (* esp_rom_wake_func_t)(void);
/**
* @brief Get CRC for Fast RTC Memory.
* @brief Read stored RTC wake function address
*
* @param uint32_t start_addr : 0 - 0x7ff for Fast RTC Memory.
* Returns pointer to wake address if a value is set in RTC registers, and stored length & CRC all valid.
*
* @param uint32_t crc_len : 0 - 0x7ff, 0 for 4 byte, 0x7ff for 0x2000 byte.
* @param None
*
* @return uint32_t : CRC32 result
* @return esp_rom_wake_func_t : Returns pointer to wake address if a value is set in RTC registers
*/
uint32_t calc_rtc_memory_crc(uint32_t start_addr, uint32_t crc_len);
esp_rom_wake_func_t esp_rom_get_rtc_wake_addr(void);
/**
* @brief Store new RTC wake function address
*
* Set a new RTC wake address function. If a non-NULL function pointer is set then the function
* memory is calculated and stored also.
*
* @param entry_addr Address of function. If NULL, length is ignored and all registers are cleared to 0.
* @param length of function in RTC fast memory. cannot be larger than RTC Fast memory size.
*
* @return None
*/
void esp_rom_set_rtc_wake_addr(esp_rom_wake_func_t entry_addr, size_t length);
/**
* @brief Suppress ROM log by setting specific RTC control register.
@ -202,26 +218,6 @@ static inline void rtc_suppress_rom_log(void)
REG_SET_BIT(RTC_CNTL_STORE4_REG, RTC_DISABLE_ROM_LOG);
}
/**
* @brief Set CRC of Fast RTC memory 0-0x7ff into RTC STORE7.
*
* @param None
*
* @return None
*/
void set_rtc_memory_crc(void);
/**
* @brief Fetch entry from RTC memory and RTC STORE reg
*
* @param uint32_t * entry_addr : the address to save entry
*
* @param RESET_REASON reset_reason : reset reason this time
*
* @return None
*/
void rtc_boot_control(uint32_t *entry_addr, RESET_REASON reset_reason);
/**
* @brief Software Reset digital core.
*

Wyświetl plik

@ -18,6 +18,8 @@ SECTIONS
.rtc.text :
{
. = ALIGN(4);
_rtc_text_start = ABSOLUTE(.);
*(.rtc.entry.text)
mapping[rtc_text]

Wyświetl plik

@ -287,6 +287,9 @@
#define SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP (1) /*!<Supports waking up from touch pad trigger */
#define SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY (1)
/*-------------------------- Flash Encryption CAPS----------------------------*/
#define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (64)