From a1030307f1ed4908427a277210adcf625d3263c4 Mon Sep 17 00:00:00 2001 From: morris Date: Wed, 13 Jul 2022 13:17:32 +0800 Subject: [PATCH] gptimer: bringup driver on esp32c6 --- components/driver/deprecated/timer_legacy.c | 2 +- components/driver/gptimer.c | 22 ++++++++--- components/hal/esp32/include/hal/timer_ll.h | 16 ++++++++ components/hal/esp32c2/include/hal/timer_ll.h | 13 +++++++ components/hal/esp32c3/include/hal/timer_ll.h | 13 +++++++ components/hal/esp32c6/include/hal/timer_ll.h | 38 ++++++++++++++++--- components/hal/esp32h2/include/hal/timer_ll.h | 13 +++++++ components/hal/esp32s2/include/hal/timer_ll.h | 16 ++++++++ components/hal/esp32s3/include/hal/timer_ll.h | 16 ++++++++ components/hal/include/hal/timer_hal.h | 7 ++++ components/hal/timer_hal.c | 26 +++++++++++++ .../esp32c6/include/soc/Kconfig.soc_caps.in | 8 ++++ .../soc/esp32c6/include/soc/clk_tree_defs.h | 17 +++++++-- components/soc/esp32c6/include/soc/soc_caps.h | 3 +- 14 files changed, 194 insertions(+), 16 deletions(-) diff --git a/components/driver/deprecated/timer_legacy.c b/components/driver/deprecated/timer_legacy.c index d18713d465..405d337f73 100644 --- a/components/driver/deprecated/timer_legacy.c +++ b/components/driver/deprecated/timer_legacy.c @@ -359,9 +359,9 @@ esp_err_t timer_deinit(timer_group_t group_num, timer_idx_t timer_num) timer_hal_context_t *hal = &p_timer_obj[group_num][timer_num]->hal; TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); - timer_ll_enable_counter(hal->dev, timer_num, false); timer_ll_enable_intr(hal->dev, TIMER_LL_EVENT_ALARM(timer_num), false); timer_ll_clear_intr_status(hal->dev, TIMER_LL_EVENT_ALARM(timer_num)); + timer_hal_deinit(hal); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); free(p_timer_obj[group_num][timer_num]); diff --git a/components/driver/gptimer.c b/components/driver/gptimer.c index 04e2962b17..358d2e7d9a 100644 --- a/components/driver/gptimer.c +++ b/components/driver/gptimer.c @@ -78,9 +78,10 @@ struct gptimer_t { timer_hal_context_t hal; gptimer_fsm_t fsm; intr_handle_t intr; - portMUX_TYPE spinlock; // to protect per-timer resources concurent accessed by task and ISR handler + portMUX_TYPE spinlock; // to protect per-timer resources concurrent accessed by task and ISR handler gptimer_alarm_cb_t on_alarm; void *user_ctx; + gptimer_clock_source_t clk_src; esp_pm_lock_handle_t pm_lock; // power management lock #if CONFIG_PM_ENABLE char pm_lock_name[GPTIMER_PM_LOCK_NAME_LEN_MAX]; // pm lock name @@ -176,10 +177,6 @@ esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *re // initialize HAL layer timer_hal_init(&timer->hal, group_id, timer_id); - // stop counter, alarm, auto-reload - timer_ll_enable_counter(timer->hal.dev, timer_id, false); - timer_ll_enable_auto_reload(timer->hal.dev, timer_id, false); - timer_ll_enable_alarm(timer->hal.dev, timer_id, false); // select clock source, set clock resolution ESP_GOTO_ON_ERROR(gptimer_select_periph_clock(timer, config->clk_src, config->resolution_hz), err, TAG, "set periph clock failed"); // initialize counter value to zero @@ -216,6 +213,13 @@ esp_err_t gptimer_del_timer(gptimer_handle_t timer) int group_id = group->group_id; int timer_id = timer->timer_id; ESP_LOGD(TAG, "del timer (%d,%d)", group_id, timer_id); + timer_hal_deinit(&timer->hal); + // [refactor-todo]: replace the following code with clk_tree_acquire/release, and call them in gptimer_enable/disable +#if SOC_TIMER_GROUP_SUPPORT_RC_FAST + if (timer->clk_src == GPTIMER_CLK_SRC_RC_FAST) { + periph_rtc_dig_clk8m_disable(); + } +#endif // recycle memory resource ESP_RETURN_ON_ERROR(gptimer_destory(timer), TAG, "destory gptimer failed"); return ESP_OK; @@ -471,11 +475,19 @@ static esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_sou counter_src_hz = esp_clk_xtal_freq(); break; #endif // SOC_TIMER_GROUP_SUPPORT_XTAL +#if SOC_TIMER_GROUP_SUPPORT_RC_FAST + case GPTIMER_CLK_SRC_RC_FAST: + // periph_rtc_dig_clk8m_enable must be called before periph_rtc_dig_clk8m_get_freq, to ensure a calibration is done + periph_rtc_dig_clk8m_enable(); + periph_src_clk_hz = periph_rtc_dig_clk8m_get_freq(); + break; +#endif // SOC_TIMER_GROUP_SUPPORT_RC_FAST default: ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "clock source %d is not support", src_clk); break; } timer_ll_set_clock_source(timer->hal.dev, timer_id, src_clk); + timer->clk_src = src_clk; unsigned int prescale = counter_src_hz / resolution_hz; // potential resolution loss here timer_ll_set_clock_prescale(timer->hal.dev, timer_id, prescale); timer->resolution_hz = counter_src_hz / prescale; // this is the real resolution diff --git a/components/hal/esp32/include/hal/timer_ll.h b/components/hal/esp32/include/hal/timer_ll.h index 7ceccbe954..63ba28801a 100644 --- a/components/hal/esp32/include/hal/timer_ll.h +++ b/components/hal/esp32/include/hal/timer_ll.h @@ -40,6 +40,22 @@ static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num, } } +/** + * @brief Enable Timer Group (GPTimer) module clock + * + * @note This function is not optional, created for backward compatible. + * + * @param hw Timer Group register base address + * @param timer_num Timer index in the group + * @param en true to enable, false to disable + */ +static inline void timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, bool en) +{ + (void)hw; + (void)timer_num; + (void)en; +} + /** * @brief Enable alarm event * diff --git a/components/hal/esp32c2/include/hal/timer_ll.h b/components/hal/esp32c2/include/hal/timer_ll.h index 4391314822..f77d5fc641 100644 --- a/components/hal/esp32c2/include/hal/timer_ll.h +++ b/components/hal/esp32c2/include/hal/timer_ll.h @@ -44,6 +44,19 @@ static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num, } } +/** + * @brief Enable Timer Group (GPTimer) module clock + * + * @param hw Timer Group register base address + * @param timer_num Timer index in the group + * @param en true to enable, false to disable + */ +static inline void timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, bool en) +{ + (void)timer_num; // only one timer in the group + hw->regclk.timer_clk_is_active = en; +} + /** * @brief Enable alarm event * diff --git a/components/hal/esp32c3/include/hal/timer_ll.h b/components/hal/esp32c3/include/hal/timer_ll.h index 2be3160b15..2c9ed9395d 100644 --- a/components/hal/esp32c3/include/hal/timer_ll.h +++ b/components/hal/esp32c3/include/hal/timer_ll.h @@ -44,6 +44,19 @@ static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num, } } +/** + * @brief Enable Timer Group (GPTimer) module clock + * + * @param hw Timer Group register base address + * @param timer_num Timer index in the group + * @param en true to enable, false to disable + */ +static inline void timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, bool en) +{ + (void)timer_num; // only one timer in the group + hw->regclk.timer_clk_is_active = en; +} + /** * @brief Enable alarm event * diff --git a/components/hal/esp32c6/include/hal/timer_ll.h b/components/hal/esp32c6/include/hal/timer_ll.h index fc40a312e8..1b4eb005b7 100644 --- a/components/hal/esp32c6/include/hal/timer_ll.h +++ b/components/hal/esp32c6/include/hal/timer_ll.h @@ -13,6 +13,7 @@ #include "hal/misc.h" #include "hal/timer_types.h" #include "soc/timer_group_struct.h" +#include "soc/pcr_struct.h" #ifdef __cplusplus extern "C" { @@ -31,17 +32,44 @@ extern "C" { */ static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num, gptimer_clock_source_t clk_src) { + (void)timer_num; // only one timer in each group + uint8_t clk_id = 0; switch (clk_src) { - case GPTIMER_CLK_SRC_APB: - hw->hw_timer[timer_num].config.tx_use_xtal = 0; - break; case GPTIMER_CLK_SRC_XTAL: - hw->hw_timer[timer_num].config.tx_use_xtal = 1; + clk_id = 0; + break; + case GPTIMER_CLK_SRC_APB: + clk_id = 1; + break; + case GPTIMER_CLK_SRC_RC_FAST: + clk_id = 2; break; default: - HAL_ASSERT(false && "unsupported clock source"); + HAL_ASSERT(false); break; } + if (hw == &TIMERG0) { + PCR.timergroup0_timer_clk_conf.tg0_timer_clk_sel = clk_id; + } else { + PCR.timergroup1_timer_clk_conf.tg1_timer_clk_sel = clk_id; + } +} + +/** + * @brief Enable Timer Group (GPTimer) module clock + * + * @param hw Timer Group register base address + * @param timer_num Timer index in the group + * @param en true to enable, false to disable + */ +static inline void timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, bool en) +{ + (void)timer_num; // only one timer in each group + if (hw == &TIMERG0) { + PCR.timergroup0_timer_clk_conf.tg0_timer_clk_en = en; + } else { + PCR.timergroup1_timer_clk_conf.tg1_timer_clk_en = en; + } } /** diff --git a/components/hal/esp32h2/include/hal/timer_ll.h b/components/hal/esp32h2/include/hal/timer_ll.h index 5c04ef1012..b0fe1c7b6a 100644 --- a/components/hal/esp32h2/include/hal/timer_ll.h +++ b/components/hal/esp32h2/include/hal/timer_ll.h @@ -44,6 +44,19 @@ static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num, } } +/** + * @brief Enable Timer Group (GPTimer) module clock + * + * @param hw Timer Group register base address + * @param timer_num Timer index in the group + * @param en true to enable, false to disable + */ +static inline void timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, bool en) +{ + (void)timer_num; // only one timer in the group + hw->regclk.timer_clk_is_active = en; +} + /** * @brief Enable alarm event * diff --git a/components/hal/esp32s2/include/hal/timer_ll.h b/components/hal/esp32s2/include/hal/timer_ll.h index a38ade4331..42daa564e3 100644 --- a/components/hal/esp32s2/include/hal/timer_ll.h +++ b/components/hal/esp32s2/include/hal/timer_ll.h @@ -44,6 +44,22 @@ static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num, } } +/** + * @brief Enable Timer Group (GPTimer) module clock + * + * @note This function is not optional, created for backward compatible. + * + * @param hw Timer Group register base address + * @param timer_num Timer index in the group + * @param en true to enable, false to disable + */ +static inline void timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, bool en) +{ + (void)hw; + (void)timer_num; + (void)en; +} + /** * @brief Enable alarm event * diff --git a/components/hal/esp32s3/include/hal/timer_ll.h b/components/hal/esp32s3/include/hal/timer_ll.h index 57f8ee29b6..f6bebcceea 100644 --- a/components/hal/esp32s3/include/hal/timer_ll.h +++ b/components/hal/esp32s3/include/hal/timer_ll.h @@ -44,6 +44,22 @@ static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num, } } +/** + * @brief Enable Timer Group (GPTimer) module clock + * + * @note This function is not optional, created for backward compatible. + * + * @param hw Timer Group register base address + * @param timer_num Timer index in the group + * @param en true to enable, false to disable + */ +static inline void timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, bool en) +{ + (void)hw; + (void)timer_num; + (void)en; +} + /** * @brief Enable alarm event * diff --git a/components/hal/include/hal/timer_hal.h b/components/hal/include/hal/timer_hal.h index e3d6469e40..02220ffa36 100644 --- a/components/hal/include/hal/timer_hal.h +++ b/components/hal/include/hal/timer_hal.h @@ -37,6 +37,13 @@ typedef struct { */ void timer_hal_init(timer_hal_context_t *hal, uint32_t group_num, uint32_t timer_num); +/** + * @brief Deinit timer hal context. + * + * @param hal Context of HAL layer + */ +void timer_hal_deinit(timer_hal_context_t *hal); + /** * @brief Load counter value into time-base counter * diff --git a/components/hal/timer_hal.c b/components/hal/timer_hal.c index d7bbd387be..ae4e55467d 100644 --- a/components/hal/timer_hal.c +++ b/components/hal/timer_hal.c @@ -4,11 +4,37 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include "hal/timer_hal.h" #include "hal/timer_ll.h" +#include "soc/soc_caps.h" void timer_hal_init(timer_hal_context_t *hal, uint32_t group_num, uint32_t timer_num) { hal->dev = TIMER_LL_GET_HW(group_num); hal->timer_id = timer_num; + // enable peripheral clock + timer_ll_enable_clock(hal->dev, timer_num, true); + // stop counter, alarm, auto-reload at first place + timer_ll_enable_counter(hal->dev, timer_num, false); + timer_ll_enable_auto_reload(hal->dev, timer_num, false); + timer_ll_enable_alarm(hal->dev, timer_num, false); + // enable RTM subsystem if available +#if SOC_TIMER_SUPPORT_ETM + timer_ll_enable_etm(hal->dev, true); +#endif +} + +void timer_hal_deinit(timer_hal_context_t *hal) +{ + // disable peripheral clock + timer_ll_enable_clock(hal->dev, hal->timer_id, false); + // ensure counter, alarm, auto-reload are disabled + timer_ll_enable_counter(hal->dev, hal->timer_id, false); + timer_ll_enable_auto_reload(hal->dev, hal->timer_id, false); + timer_ll_enable_alarm(hal->dev, hal->timer_id, false); +#if SOC_TIMER_SUPPORT_ETM + timer_ll_enable_etm(hal->dev, false); +#endif + hal->dev = NULL; } diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 36725e73cc..c654e5472c 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -603,10 +603,18 @@ config SOC_TIMER_GROUP_SUPPORT_APB bool default y +config SOC_TIMER_GROUP_SUPPORT_RC_FAST + bool + default y + config SOC_TIMER_GROUP_TOTAL_TIMERS int default 2 +config SOC_TIMER_SUPPORT_ETM + bool + default y + config SOC_TWAI_BRP_MIN int default 2 diff --git a/components/soc/esp32c6/include/soc/clk_tree_defs.h b/components/soc/esp32c6/include/soc/clk_tree_defs.h index f67ce27baf..737c140943 100644 --- a/components/soc/esp32c6/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c6/include/soc/clk_tree_defs.h @@ -128,15 +128,24 @@ typedef enum { * } * @endcode */ -#define SOC_GPTIMER_CLKS {SOC_MOD_CLK_APB, SOC_MOD_CLK_XTAL} +#if CONFIG_IDF_ENV_FPGA +#define SOC_GPTIMER_CLKS {SOC_MOD_CLK_XTAL} +#else +#define SOC_GPTIMER_CLKS {SOC_MOD_CLK_APB, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST} +#endif /** * @brief Type of GPTimer clock source */ typedef enum { - GPTIMER_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */ - GPTIMER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ - GPTIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */ + GPTIMER_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */ + GPTIMER_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + GPTIMER_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ +#if CONFIG_IDF_ENV_FPGA + GPTIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the default choice */ +#else + GPTIMER_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */ +#endif } soc_periph_gptimer_clk_src_t; /** diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 976f582eb4..46836c604f 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -322,14 +322,15 @@ #define SOC_SYSTIMER_INT_LEVEL 1 // Systimer peripheral uses level interrupt #define SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current) -// TODO: IDF-5332 (Copy from esp32c3, need check) /*--------------------------- TIMER GROUP CAPS ---------------------------------------*/ #define SOC_TIMER_GROUPS (2) #define SOC_TIMER_GROUP_TIMERS_PER_GROUP (1U) #define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (54) #define SOC_TIMER_GROUP_SUPPORT_XTAL (1) #define SOC_TIMER_GROUP_SUPPORT_APB (1) +#define SOC_TIMER_GROUP_SUPPORT_RC_FAST (1) #define SOC_TIMER_GROUP_TOTAL_TIMERS (2) +#define SOC_TIMER_SUPPORT_ETM (1) // TODO: IDF-5313 (Copy from esp32c3, need check) /*-------------------------- TWAI CAPS ---------------------------------------*/