1 /* 2 * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <stddef.h> 8 #include <string.h> 9 #include <sys/lock.h> 10 #include <sys/param.h> 11 12 #include "esp_attr.h" 13 #include "esp_sleep.h" 14 #include "esp_cpu.h" 15 16 #include "soc/soc.h" 17 #include "soc/rtc.h" 18 #include "soc/soc_caps.h" 19 #include "hal/uart_ll.h" 20 21 #if SOC_LP_TIMER_SUPPORTED 22 #include "hal/lp_timer_ll.h" 23 #include "hal/lp_timer_hal.h" 24 #else 25 #include "hal/rtc_cntl_ll.h" 26 #endif 27 28 #if SOC_PMU_SUPPORTED 29 #include "hal/pmu_ll.h" 30 #endif 31 32 #include "sdkconfig.h" 33 #include "esp_rom_uart.h" 34 #include "esp_rom_sys.h" 35 36 #ifdef CONFIG_IDF_TARGET_ESP32 37 #include "esp32/rom/rtc.h" 38 #elif CONFIG_IDF_TARGET_ESP32S2 39 #include "esp32s2/rom/rtc.h" 40 #elif CONFIG_IDF_TARGET_ESP32S3 41 #include "esp32s3/rom/rtc.h" 42 #elif CONFIG_IDF_TARGET_ESP32C3 43 #include "esp32c3/rom/rtc.h" 44 #elif CONFIG_IDF_TARGET_ESP32C6 45 #include "esp32c6/rom/rtc.h" 46 #elif CONFIG_IDF_TARGET_ESP32H2 47 #include "esp32h2/rom/rtc.h" 48 #endif 49 esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub)50void RTC_IRAM_ATTR esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub) 51 { 52 53 #if CONFIG_IDF_TARGET_ESP32 54 // Since the app core of esp32 does not support access to RTC_FAST_MEMORY, 55 // `esp_set_deep_sleep_wake_stub` is not declared in RTC_FAST_MEMORY, 56 // so we cannot call it here 57 REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub); 58 #else 59 esp_set_deep_sleep_wake_stub(new_stub); 60 #endif 61 62 #if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY 63 esp_set_deep_sleep_wake_stub_default_entry(); 64 #else 65 set_rtc_memory_crc(); 66 #endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_MEM 67 68 // Go to sleep. 69 #if SOC_PMU_SUPPORTED 70 pmu_ll_hp_clear_wakeup_intr_status(&PMU); 71 pmu_ll_hp_clear_reject_intr_status(&PMU); 72 pmu_ll_hp_clear_reject_cause(&PMU); 73 pmu_ll_hp_set_sleep_enable(&PMU); 74 #else 75 rtc_cntl_ll_sleep_enable(); 76 #endif 77 78 // A few CPU cycles may be necessary for the sleep to start... 79 #if __XTENSA__ 80 xt_utils_wait_for_intr(); 81 #else 82 rv_utils_wait_for_intr(); 83 #endif // __XTENSA__ 84 // never reaches here. 85 } 86 esp_wake_stub_uart_tx_wait_idle(uint8_t uart_no)87void RTC_IRAM_ATTR esp_wake_stub_uart_tx_wait_idle(uint8_t uart_no) 88 { 89 while (!uart_ll_is_tx_idle(UART_LL_GET_HW(uart_no))) {}; 90 } 91 esp_wake_stub_set_wakeup_time(uint64_t time_in_us)92void RTC_IRAM_ATTR esp_wake_stub_set_wakeup_time(uint64_t time_in_us) 93 { 94 #if SOC_LP_TIMER_SUPPORTED 95 uint64_t rtc_count_delta = lp_timer_ll_time_to_count(time_in_us); 96 97 lp_timer_ll_counter_snapshot(&LP_TIMER); 98 uint32_t lo = lp_timer_ll_get_counter_value_low(&LP_TIMER, 0); 99 uint32_t hi = lp_timer_ll_get_counter_value_high(&LP_TIMER, 0); 100 uint64_t rtc_curr_count = (uint64_t)hi << 32 | lo; 101 102 lp_timer_ll_clear_alarm_intr_status(&LP_TIMER); 103 lp_timer_ll_set_alarm_target(&LP_TIMER, 0, rtc_curr_count + rtc_count_delta); 104 lp_timer_ll_set_target_enable(&LP_TIMER, 0, true); 105 #else 106 uint64_t rtc_count_delta = rtc_cntl_ll_time_to_count(time_in_us); 107 uint64_t rtc_curr_count = rtc_cntl_ll_get_rtc_time(); 108 rtc_cntl_ll_set_wakeup_timer(rtc_curr_count + rtc_count_delta); 109 #endif 110 111 } 112 esp_wake_stub_get_wakeup_cause(void)113uint32_t RTC_IRAM_ATTR esp_wake_stub_get_wakeup_cause(void) 114 { 115 #if SOC_PMU_SUPPORTED 116 return pmu_ll_hp_get_wakeup_cause(&PMU); 117 #else 118 return rtc_cntl_ll_get_wakeup_cause(); 119 #endif 120 } 121