diff --git a/components/esp_hw_support/port/esp32c6/CMakeLists.txt b/components/esp_hw_support/port/esp32c6/CMakeLists.txt index 33047b7052..92e9f981b4 100644 --- a/components/esp_hw_support/port/esp32c6/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c6/CMakeLists.txt @@ -4,7 +4,8 @@ set(srcs "rtc_clk_init.c" "pmu_init.c" "pmu_sleep.c" "rtc_time.c" - "chip_info.c") + "chip_info.c" + ) if(NOT BOOTLOADER_BUILD) list(APPEND srcs "sar_periph_ctrl.c" diff --git a/components/esp_hw_support/port/esp32c6/rtc_time.c b/components/esp_hw_support/port/esp32c6/rtc_time.c index 98bf1e6f82..483b9fc0bc 100644 --- a/components/esp_hw_support/port/esp32c6/rtc_time.c +++ b/components/esp_hw_support/port/esp32c6/rtc_time.c @@ -8,8 +8,8 @@ #include "esp32c6/rom/ets_sys.h" #include "soc/rtc.h" #include "soc/lp_timer_reg.h" +#include "hal/lp_timer_hal.h" #include "hal/clk_tree_ll.h" -#include "hal/rtc_cntl_ll.h" #include "soc/timer_group_reg.h" #include "esp_rom_sys.h" #include "assert.h" @@ -207,7 +207,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period) uint64_t rtc_time_get(void) { - return rtc_cntl_ll_get_rtc_time(); + return lp_timer_hal_get_cycle_count(0); } uint64_t rtc_light_slp_time_get(void) diff --git a/components/esp_hw_support/sleep_wake_stub.c b/components/esp_hw_support/sleep_wake_stub.c index bb6257a7b9..ba0c411de8 100644 --- a/components/esp_hw_support/sleep_wake_stub.c +++ b/components/esp_hw_support/sleep_wake_stub.c @@ -15,9 +15,14 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/soc_caps.h" -#include "hal/rtc_cntl_ll.h" #include "hal/uart_ll.h" +#if SOC_LP_TIMER_SUPPORTED +#include "hal/lp_timer_ll.h" +#include "hal/lp_timer_hal.h" +#else +#include "hal/rtc_cntl_ll.h" +#endif #include "sdkconfig.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" @@ -70,9 +75,16 @@ void RTC_IRAM_ATTR esp_wake_stub_uart_tx_wait_idle(uint8_t uart_no) void RTC_IRAM_ATTR esp_wake_stub_set_wakeup_time(uint64_t time_in_us) { +#if SOC_LP_TIMER_SUPPORTED + uint64_t rtc_count_delta = lp_timer_ll_time_to_count(time_in_us); + uint64_t rtc_curr_count = lp_timer_hal_get_cycle_count(0); + lp_timer_hal_set_alarm_target(0, rtc_curr_count + rtc_count_delta); +#else 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); +#endif + } uint32_t RTC_IRAM_ATTR esp_wake_stub_get_wakeup_cause(void) diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 4ed06a0139..da8ae89434 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -118,6 +118,10 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "${target}/modem_clock_hal.c") endif() + if(CONFIG_SOC_LP_TIMER_SUPPORTED) + list(APPEND srcs "${target}/lp_timer_hal.c") + endif() + if(CONFIG_SOC_BOD_SUPPORTED) list(APPEND srcs "brownout_hal.c") endif() diff --git a/components/hal/esp32c6/include/hal/lp_timer_hal.h b/components/hal/esp32c6/include/hal/lp_timer_hal.h new file mode 100644 index 0000000000..813b865fef --- /dev/null +++ b/components/hal/esp32c6/include/hal/lp_timer_hal.h @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "soc/soc.h" +#include "hal/lp_timer_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @brief set alarm target value + * + * @param timer_id timer num of lp_timer, 0 or 1 for esp32c6 + * + * @param value when counter reaches alarm value, alarm event will be triggered + */ +void lp_timer_hal_set_alarm_target(uint8_t timer_id, uint64_t value); + +/** + * @brief get current counter value + * + * @param timer_id timer num of lp_timer, 0 or 1 for esp32c6 + */ +uint64_t lp_timer_hal_get_cycle_count(uint8_t timer_id); + +/** + * @brief clear alarm interrupt status + */ +void lp_timer_hal_clear_alarm_intr_status(void); + +/** + * @brief clear overflow interrupt status + */ +void lp_timer_hal_clear_overflow_intr_status(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c6/include/hal/lp_timer_ll.h b/components/hal/esp32c6/include/hal/lp_timer_ll.h new file mode 100644 index 0000000000..7f2aa34460 --- /dev/null +++ b/components/hal/esp32c6/include/hal/lp_timer_ll.h @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for ESP32-C6 LP_Timer register operations + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/rtc.h" +#include "soc/lp_timer_struct.h" +#include "soc/lp_aon_reg.h" +#include "hal/lp_timer_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +FORCE_INLINE_ATTR void lp_timer_ll_set_alarm_target(lp_timer_dev_t *dev, uint8_t timer_id, uint64_t value) +{ + dev->target[timer_id].hi.target_hi = (value >> 32) & 0xFFFF; + dev->target[timer_id].lo.target_lo = value & 0xFFFFFFFF; +} + +FORCE_INLINE_ATTR void lp_timer_ll_set_target_enable(lp_timer_dev_t *dev, uint8_t timer_id, bool en) +{ + dev->target[timer_id].hi.enable = en; +} + +FORCE_INLINE_ATTR uint32_t lp_timer_ll_get_counter_value_low(lp_timer_dev_t *dev, uint8_t timer_id) +{ + return dev->counter[timer_id].lo.counter_lo; +} + +FORCE_INLINE_ATTR uint32_t lp_timer_ll_get_counter_value_high(lp_timer_dev_t *dev, uint8_t timer_id) +{ + return dev->counter[timer_id].hi.counter_hi; +} + +FORCE_INLINE_ATTR void lp_timer_ll_counter_snapshot(lp_timer_dev_t *dev) +{ + dev->update.update = 1; +} + +FORCE_INLINE_ATTR void lp_timer_ll_clear_alarm_intr_status(lp_timer_dev_t *dev) +{ + dev->int_clr.alarm = 1; +} + +FORCE_INLINE_ATTR void lp_timer_ll_clear_overflow_intr_status(lp_timer_dev_t *dev) +{ + dev->int_clr.overflow = 1; +} + +FORCE_INLINE_ATTR uint64_t lp_timer_ll_time_to_count(uint64_t time_in_us) +{ + uint32_t slow_clk_value = REG_READ(LP_AON_STORE1_REG); + return ((time_in_us * (1 << RTC_CLK_CAL_FRACT)) / slow_clk_value); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c6/lp_timer_hal.c b/components/hal/esp32c6/lp_timer_hal.c new file mode 100644 index 0000000000..caba3725f8 --- /dev/null +++ b/components/hal/esp32c6/lp_timer_hal.c @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc.h" +#include "hal/lp_timer_ll.h" + +static DRAM_ATTR struct { + lp_timer_dev_t *dev; +} lp_timer_context = { .dev = &LP_TIMER }; + +void IRAM_ATTR lp_timer_hal_set_alarm_target(uint8_t timer_id, uint64_t value) +{ + lp_timer_ll_clear_alarm_intr_status(lp_timer_context.dev); + lp_timer_ll_set_alarm_target(lp_timer_context.dev, timer_id, value); + lp_timer_ll_set_target_enable(lp_timer_context.dev, timer_id, true); +} + +uint64_t IRAM_ATTR lp_timer_hal_get_cycle_count(uint8_t timer_id) +{ + lp_timer_ll_counter_snapshot(lp_timer_context.dev); + uint32_t lo = lp_timer_ll_get_counter_value_low(lp_timer_context.dev, timer_id); + uint32_t hi = lp_timer_ll_get_counter_value_high(lp_timer_context.dev, timer_id); + lp_timer_counter_value_t result = { + .lo = lo, + .hi = hi + }; + return result.val; +} + +void IRAM_ATTR lp_timer_hal_clear_alarm_intr_status(void) +{ + lp_timer_ll_clear_alarm_intr_status(lp_timer_context.dev); +} + +void IRAM_ATTR lp_timer_hal_clear_overflow_intr_status(void) +{ + lp_timer_ll_clear_overflow_intr_status(lp_timer_context.dev); +} diff --git a/components/hal/include/hal/lp_timer_types.h b/components/hal/include/hal/lp_timer_types.h new file mode 100644 index 0000000000..ebb808ca50 --- /dev/null +++ b/components/hal/include/hal/lp_timer_types.h @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "soc/soc_caps.h" + +/** + * @brief The structure of the counter value in lower power timer + */ +typedef struct { + union { + struct { + uint32_t lo: SOC_LP_TIMER_BIT_WIDTH_LO; /*!< Low part of counter value */ + uint32_t hi: SOC_LP_TIMER_BIT_WIDTH_HI; /*!< High part of counter value */ + uint32_t reserved: 16; + }; + uint64_t val; /*!< counter value */ + }; +} lp_timer_counter_value_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index f7ffb86ce6..c7781b8e8d 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -839,6 +839,14 @@ config SOC_SYSTIMER_SUPPORT_ETM bool default y +config SOC_LP_TIMER_BIT_WIDTH_LO + int + default 32 + +config SOC_LP_TIMER_BIT_WIDTH_HI + int + default 16 + config SOC_TIMER_GROUPS int default 2 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 66d625c26a..d1dd2a4cd9 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -361,6 +361,10 @@ #define SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current) #define SOC_SYSTIMER_SUPPORT_ETM 1 // Systimer comparator can generate ETM event +/*-------------------------- LP_TIMER CAPS ----------------------------------*/ +#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part +#define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part + /*--------------------------- TIMER GROUP CAPS ---------------------------------------*/ #define SOC_TIMER_GROUPS (2) #define SOC_TIMER_GROUP_TIMERS_PER_GROUP (1U)