Просмотр исходного кода

lp_timer: add hal-layer codes for esp32c6

Li Shuai 3 лет назад
Родитель
Сommit
c0ddaa5920

+ 2 - 1
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"

+ 2 - 2
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)

+ 13 - 1
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)

+ 4 - 0
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()

+ 47 - 0
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 <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#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

+ 66 - 0
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 <stdlib.h>
+#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

+ 46 - 0
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 <stdint.h>
+#include <stdlib.h>
+#include <esp_types.h>
+#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);
+}

+ 32 - 0
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 <stdint.h>
+#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

+ 8 - 0
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

+ 4 - 0
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)