Skip to content

Commit

Permalink
Merge branch 'feature/example_deep_sleep_wake_stub_backport_v4.4' int…
Browse files Browse the repository at this point in the history
…o 'release/v4.4'

example: add deepsleep_wake stub example (backport v4.4)

See merge request espressif/esp-idf!23360
  • Loading branch information
jack0c committed Jun 9, 2023
2 parents b04cd38 + ea02b6d commit 7200764
Show file tree
Hide file tree
Showing 32 changed files with 657 additions and 88 deletions.
5 changes: 5 additions & 0 deletions components/esp_hw_support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ if(NOT BOOTLOADER_BUILD)
if(NOT CONFIG_IDF_TARGET_ESP32 AND NOT CONFIG_IDF_TARGET_ESP32S2)
list(APPEND srcs "sleep_retention.c")
endif()

if(NOT CONFIG_IDF_TARGET_ESP32C2)
list(APPEND srcs "sleep_wake_stub.c")
endif()

list(APPEND requires esp_ipc)
else()
# Requires "_esp_error_check_failed()" function
Expand Down
68 changes: 68 additions & 0 deletions components/esp_hw_support/include/esp_wake_stub.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <stdint.h>
#include "esp_log.h"
#include "esp_sleep.h"

#ifdef __cplusplus
extern "C" {
#endif

#define RTC_STR(str) (__extension__({static const RTC_RODATA_ATTR char _fmt[] = (str); (const char *)&_fmt;}))
#define RTC_LOG_FORMAT(letter, format) LOG_COLOR_ ## letter format LOG_RESET_COLOR "\n"

#define ESP_RTC_LOG( level, format, ... ) if (LOG_LOCAL_LEVEL >= level) { esp_rom_printf(RTC_STR(format), ##__VA_ARGS__); \
esp_wake_stub_uart_tx_wait_idle(0); }

#define ESP_RTC_LOGE( format, ... ) ESP_RTC_LOG(ESP_LOG_ERROR, RTC_LOG_FORMAT(E, format), ##__VA_ARGS__)
#define ESP_RTC_LOGW( format, ... ) ESP_RTC_LOG(ESP_LOG_WARN, RTC_LOG_FORMAT(W, format), ##__VA_ARGS__)
#define ESP_RTC_LOGI( format, ... ) ESP_RTC_LOG(ESP_LOG_INFO, RTC_LOG_FORMAT(I, format), ##__VA_ARGS__)
#define ESP_RTC_LOGD( format, ... ) ESP_RTC_LOG(ESP_LOG_DEBUG, RTC_LOG_FORMAT(D, format), ##__VA_ARGS__)
#define ESP_RTC_LOGV( format, ... ) ESP_RTC_LOG(ESP_LOG_VERBOSE, RTC_LOG_FORMAT(V, format), ##__VA_ARGS__)

/**
* @brief Enter deep-sleep mode from deep sleep wake stub code
*
* This should be called from the wake stub code.
*
* @param new_stub new wake stub function will be set
*/
void esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub);

/**
* @brief Wait while uart transmission is in progress
*
* This function is waiting while uart transmission is not completed,
* and this function should be called from the wake stub code.
*
* @param uart_no UART port to wait idle
*/
void esp_wake_stub_uart_tx_wait_idle(uint8_t uart_no);

/**
* @brief Set wakeup time from deep sleep stub.
*
* This should be called from the wake stub code.
*
* @param time_in_us wakeup time in us
*/
void esp_wake_stub_set_wakeup_time(uint64_t time_in_us);

/**
* @brief Get wakeup cause from deep sleep stub.
*
* This should be called from the wake stub code.
*
* @return wakeup casue value
*/
uint32_t esp_wake_stub_get_wakeup_cause(void);

#ifdef __cplusplus
}
#endif
16 changes: 2 additions & 14 deletions components/esp_hw_support/port/esp32/rtc_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <stdint.h>
#include "esp_rom_sys.h"
#include "hal/rtc_cntl_ll.h"
#include "soc/rtc.h"
#include "soc/timer_periph.h"
#include "soc_log.h"
Expand Down Expand Up @@ -150,20 +151,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)

uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
int attempts = 1000;
while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) {
esp_rom_delay_us(1); // might take 1 RTC slowclk period, don't flood RTC bus
if (attempts) {
if (--attempts == 0 && REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN)) {
SOC_LOGE(TAG, "rtc_time_get() 32kHz xtal has been stopped");
}
}
}
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;
return rtc_cntl_ll_get_rtc_time();
}

void rtc_clk_wait_for_slow_cycle(void)
Expand Down
6 changes: 2 additions & 4 deletions components/esp_hw_support/port/esp32c3/rtc_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/timer_group_reg.h"
#include "hal/rtc_cntl_ll.h"
#include "esp_rom_sys.h"

/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
Expand Down Expand Up @@ -166,10 +167,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)

uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
return rtc_cntl_ll_get_rtc_time();
}

uint64_t rtc_light_slp_time_get(void)
Expand Down
6 changes: 2 additions & 4 deletions components/esp_hw_support/port/esp32s2/rtc_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/timer_group_reg.h"
#include "hal/rtc_cntl_ll.h"

/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
* This feature counts the number of XTAL clock cycles within a given number of
Expand Down Expand Up @@ -230,10 +231,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)

uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
return rtc_cntl_ll_get_rtc_time();
}

uint64_t rtc_light_slp_time_get(void)
Expand Down
6 changes: 2 additions & 4 deletions components/esp_hw_support/port/esp32s3/rtc_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/timer_group_reg.h"
#include "hal/rtc_cntl_ll.h"

/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
* This feature counts the number of XTAL clock cycles within a given number of
Expand Down Expand Up @@ -164,10 +165,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)

uint64_t rtc_time_get(void)
{
SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
return t;
return rtc_cntl_ll_get_rtc_time();
}

uint64_t rtc_light_slp_time_get(void)
Expand Down
14 changes: 8 additions & 6 deletions components/esp_hw_support/sleep_modes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1239,11 +1239,7 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
return ESP_SLEEP_WAKEUP_UNDEFINED;
}

#ifdef CONFIG_IDF_TARGET_ESP32
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);
#else
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE);
#endif
uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause();

if (wakeup_cause & RTC_TIMER_TRIG_EN) {
return ESP_SLEEP_WAKEUP_TIMER;
Expand Down Expand Up @@ -1420,7 +1416,13 @@ static uint32_t get_power_down_flags(void)
return pd_flags;
}

void esp_deep_sleep_disable_rom_logging(void)
#if CONFIG_IDF_TARGET_ESP32
/* APP core of esp32 can't access to RTC FAST MEMORY, do not define it with RTC_IRAM_ATTR */
void
#else
void RTC_IRAM_ATTR
#endif
esp_deep_sleep_disable_rom_logging(void)
{
rtc_suppress_rom_log();
}
Expand Down
77 changes: 77 additions & 0 deletions components/esp_hw_support/sleep_wake_stub.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stddef.h>
#include <string.h>
#include <sys/lock.h>
#include <sys/param.h>

#include "esp_attr.h"
#include "esp_sleep.h"

#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/soc_caps.h"
#include "hal/rtc_cntl_ll.h"
#include "hal/uart_ll.h"

#include "sdkconfig.h"
#include "esp_rom_uart.h"
#include "esp_rom_sys.h"

#ifdef CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/rtc.h"
#endif

void RTC_IRAM_ATTR esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub)
{
#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 // CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM
esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)new_stub, rtc_fast_length);
#else
// Set the pointer of the wake stub function.
REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub);
set_rtc_memory_crc();
#endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_MEM

// Go to sleep.
rtc_cntl_ll_sleep_enable();
// A few CPU cycles may be necessary for the sleep to start...
while (true) {};
// never reaches here.
}

void RTC_IRAM_ATTR esp_wake_stub_uart_tx_wait_idle(uint8_t uart_no)
{
while (!uart_ll_is_tx_idle(UART_LL_GET_HW(uart_no))) {};
}

void RTC_IRAM_ATTR esp_wake_stub_set_wakeup_time(uint64_t time_in_us)
{
uint64_t rtc_count_delta = rtc_cntl_ll_time_to_count(time_in_us);
uint64_t rtc_curr_count = rtc_cntl_ll_get_rtc_time();
rtc_cntl_ll_set_wakeup_timer(rtc_curr_count + rtc_count_delta);
}

uint32_t RTC_IRAM_ATTR esp_wake_stub_get_wakeup_cause(void)
{
return rtc_cntl_ll_get_wakeup_cause();
}
2 changes: 1 addition & 1 deletion components/esp_system/ld/esp32/sections.ld.in
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ SECTIONS

mapping[rtc_data]

*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.*)
_rtc_data_end = ABSOLUTE(.);

} > rtc_data_location
Expand Down
4 changes: 2 additions & 2 deletions components/esp_system/ld/esp32c3/sections.ld.in
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ SECTIONS

mapping[rtc_data]

*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_data_location

/* RTC bss, from any source file named rtc_wake_stub*.c */
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.*(.bss .bss.*)
*rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*)
*rtc_wake_stub*.*(COMMON)

mapping[rtc_bss]
Expand Down
4 changes: 2 additions & 2 deletions components/esp_system/ld/esp32h2/sections.ld.in
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,15 @@ SECTIONS

mapping[rtc_data]

*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_data_location

/* RTC bss, from any source file named rtc_wake_stub*.c */
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.*(.bss .bss.*)
*rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*)
*rtc_wake_stub*.*(COMMON)

mapping[rtc_bss]
Expand Down
2 changes: 1 addition & 1 deletion components/esp_system/ld/esp32s2/sections.ld.in
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ SECTIONS

mapping[rtc_data]

*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_data_location

Expand Down
2 changes: 1 addition & 1 deletion components/esp_system/ld/esp32s3/sections.ld.in
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ SECTIONS

mapping[rtc_data]

*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_data_location

Expand Down
3 changes: 1 addition & 2 deletions components/esp_system/test/test_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,7 @@ __attribute__((unused)) static float get_time_ms(void)

__attribute__((unused)) static uint32_t get_cause(void)
{
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, \
RTC_CNTL_WAKEUP_CAUSE);
uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause();
return wakeup_cause;
}

Expand Down
Loading

0 comments on commit 7200764

Please sign in to comment.