gptimer: bringup driver on esp32c6

This commit is contained in:
morris 2022-07-13 13:17:32 +08:00
parent 890a84dcc4
commit a1030307f1
14 changed files with 194 additions and 16 deletions

View File

@ -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_hal_context_t *hal = &p_timer_obj[group_num][timer_num]->hal;
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); 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_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_ll_clear_intr_status(hal->dev, TIMER_LL_EVENT_ALARM(timer_num));
timer_hal_deinit(hal);
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]); TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
free(p_timer_obj[group_num][timer_num]); free(p_timer_obj[group_num][timer_num]);

View File

@ -78,9 +78,10 @@ struct gptimer_t {
timer_hal_context_t hal; timer_hal_context_t hal;
gptimer_fsm_t fsm; gptimer_fsm_t fsm;
intr_handle_t intr; 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; gptimer_alarm_cb_t on_alarm;
void *user_ctx; void *user_ctx;
gptimer_clock_source_t clk_src;
esp_pm_lock_handle_t pm_lock; // power management lock esp_pm_lock_handle_t pm_lock; // power management lock
#if CONFIG_PM_ENABLE #if CONFIG_PM_ENABLE
char pm_lock_name[GPTIMER_PM_LOCK_NAME_LEN_MAX]; // pm lock name 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 // initialize HAL layer
timer_hal_init(&timer->hal, group_id, timer_id); 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 // 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"); 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 // 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 group_id = group->group_id;
int timer_id = timer->timer_id; int timer_id = timer->timer_id;
ESP_LOGD(TAG, "del timer (%d,%d)", group_id, 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 // recycle memory resource
ESP_RETURN_ON_ERROR(gptimer_destory(timer), TAG, "destory gptimer failed"); ESP_RETURN_ON_ERROR(gptimer_destory(timer), TAG, "destory gptimer failed");
return ESP_OK; 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(); counter_src_hz = esp_clk_xtal_freq();
break; break;
#endif // SOC_TIMER_GROUP_SUPPORT_XTAL #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: default:
ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "clock source %d is not support", src_clk); ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "clock source %d is not support", src_clk);
break; break;
} }
timer_ll_set_clock_source(timer->hal.dev, timer_id, src_clk); 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 unsigned int prescale = counter_src_hz / resolution_hz; // potential resolution loss here
timer_ll_set_clock_prescale(timer->hal.dev, timer_id, prescale); timer_ll_set_clock_prescale(timer->hal.dev, timer_id, prescale);
timer->resolution_hz = counter_src_hz / prescale; // this is the real resolution timer->resolution_hz = counter_src_hz / prescale; // this is the real resolution

View File

@ -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 * @brief Enable alarm event
* *

View File

@ -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 * @brief Enable alarm event
* *

View File

@ -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 * @brief Enable alarm event
* *

View File

@ -13,6 +13,7 @@
#include "hal/misc.h" #include "hal/misc.h"
#include "hal/timer_types.h" #include "hal/timer_types.h"
#include "soc/timer_group_struct.h" #include "soc/timer_group_struct.h"
#include "soc/pcr_struct.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { 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) 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) { switch (clk_src) {
case GPTIMER_CLK_SRC_APB:
hw->hw_timer[timer_num].config.tx_use_xtal = 0;
break;
case GPTIMER_CLK_SRC_XTAL: 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; break;
default: default:
HAL_ASSERT(false && "unsupported clock source"); HAL_ASSERT(false);
break; 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;
}
} }
/** /**

View File

@ -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 * @brief Enable alarm event
* *

View File

@ -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 * @brief Enable alarm event
* *

View File

@ -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 * @brief Enable alarm event
* *

View File

@ -37,6 +37,13 @@ typedef struct {
*/ */
void timer_hal_init(timer_hal_context_t *hal, uint32_t group_num, uint32_t timer_num); 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 * @brief Load counter value into time-base counter
* *

View File

@ -4,11 +4,37 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <stdlib.h>
#include "hal/timer_hal.h" #include "hal/timer_hal.h"
#include "hal/timer_ll.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) 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->dev = TIMER_LL_GET_HW(group_num);
hal->timer_id = timer_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;
} }

View File

@ -603,10 +603,18 @@ config SOC_TIMER_GROUP_SUPPORT_APB
bool bool
default y default y
config SOC_TIMER_GROUP_SUPPORT_RC_FAST
bool
default y
config SOC_TIMER_GROUP_TOTAL_TIMERS config SOC_TIMER_GROUP_TOTAL_TIMERS
int int
default 2 default 2
config SOC_TIMER_SUPPORT_ETM
bool
default y
config SOC_TWAI_BRP_MIN config SOC_TWAI_BRP_MIN
int int
default 2 default 2

View File

@ -128,15 +128,24 @@ typedef enum {
* } * }
* @endcode * @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 * @brief Type of GPTimer clock source
*/ */
typedef enum { typedef enum {
GPTIMER_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */ 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_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_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; } soc_periph_gptimer_clk_src_t;
/** /**

View File

@ -322,14 +322,15 @@
#define SOC_SYSTIMER_INT_LEVEL 1 // Systimer peripheral uses level interrupt #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) #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 ---------------------------------------*/ /*--------------------------- TIMER GROUP CAPS ---------------------------------------*/
#define SOC_TIMER_GROUPS (2) #define SOC_TIMER_GROUPS (2)
#define SOC_TIMER_GROUP_TIMERS_PER_GROUP (1U) #define SOC_TIMER_GROUP_TIMERS_PER_GROUP (1U)
#define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (54) #define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (54)
#define SOC_TIMER_GROUP_SUPPORT_XTAL (1) #define SOC_TIMER_GROUP_SUPPORT_XTAL (1)
#define SOC_TIMER_GROUP_SUPPORT_APB (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_GROUP_TOTAL_TIMERS (2)
#define SOC_TIMER_SUPPORT_ETM (1)
// TODO: IDF-5313 (Copy from esp32c3, need check) // TODO: IDF-5313 (Copy from esp32c3, need check)
/*-------------------------- TWAI CAPS ---------------------------------------*/ /*-------------------------- TWAI CAPS ---------------------------------------*/