feat(gptimer): use RCC atomic block to enable/reset peripheral

This commit is contained in:
morris 2023-08-18 13:26:46 +08:00
parent a9c813ca3e
commit 71cf16ec01
27 changed files with 488 additions and 113 deletions

View File

@ -34,6 +34,12 @@ static const char *TIMER_TAG = "timer_group";
#define TIMER_ENTER_CRITICAL(mux) portENTER_CRITICAL_SAFE(mux);
#define TIMER_EXIT_CRITICAL(mux) portEXIT_CRITICAL_SAFE(mux);
#if CONFIG_IDF_TARGET_ESP32P4
#define GPTIMER_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define GPTIMER_CLOCK_SRC_ATOMIC()
#endif
typedef struct {
timer_isr_t fn; /*!< isr function */
void *args; /*!< isr function args */
@ -305,7 +311,12 @@ esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer
}
timer_hal_context_t *hal = &p_timer_obj[group_num][timer_num]->hal;
periph_module_enable(timer_group_periph_signals.groups[group_num].module);
PERIPH_RCC_ACQUIRE_ATOMIC(timer_group_periph_signals.groups[group_num].module, ref_count) {
if (ref_count == 0) {
timer_ll_enable_bus_clock(group_num, true);
timer_ll_reset_register(group_num);
}
}
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
timer_hal_init(hal, group_num, timer_num);
@ -315,9 +326,12 @@ esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer
if (config->clk_src) {
clk_src = config->clk_src;
}
// although `clk_src` is of `timer_src_clk_t` type, but it's binary compatible with `gptimer_clock_source_t`,
// as the underlying enum entries come from the same `soc_module_clk_t`
timer_ll_set_clock_source(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, (gptimer_clock_source_t)clk_src);
GPTIMER_CLOCK_SRC_ATOMIC() {
// although `clk_src` is of `timer_src_clk_t` type, but it's binary compatible with `gptimer_clock_source_t`,
// as the underlying enum entries come from the same `soc_module_clk_t`
timer_ll_set_clock_source(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, (gptimer_clock_source_t)clk_src);
timer_ll_enable_clock(hal->dev, timer_num, true);
}
timer_ll_set_clock_prescale(hal->dev, timer_num, config->divider);
timer_ll_set_count_direction(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, config->counter_dir);
timer_ll_enable_intr(hal->dev, TIMER_LL_EVENT_ALARM(timer_num), false);
@ -343,12 +357,22 @@ esp_err_t timer_deinit(timer_group_t group_num, timer_idx_t timer_num)
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
timer_hal_context_t *hal = &p_timer_obj[group_num][timer_num]->hal;
// disable the source clock
GPTIMER_CLOCK_SRC_ATOMIC() {
timer_ll_enable_clock(hal->dev, hal->timer_id, false);
}
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
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]);
PERIPH_RCC_RELEASE_ATOMIC(timer_group_periph_signals.groups[group_num].module, ref_count) {
if (ref_count == 0) {
timer_ll_enable_bus_clock(group_num, false);
}
}
free(p_timer_obj[group_num][timer_num]);
p_timer_obj[group_num][timer_num] = NULL;

View File

@ -32,6 +32,12 @@
static const char *TAG = "gptimer";
#if CONFIG_IDF_TARGET_ESP32P4
#define GPTIMER_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define GPTIMER_CLOCK_SRC_ATOMIC()
#endif
typedef struct gptimer_platform_t {
_lock_t mutex; // platform level mutex lock
gptimer_group_t *groups[SOC_TIMER_GROUPS]; // timer group pool
@ -163,8 +169,13 @@ esp_err_t gptimer_del_timer(gptimer_handle_t timer)
gptimer_clock_source_t clk_src = timer->clk_src;
int group_id = group->group_id;
int timer_id = timer->timer_id;
timer_hal_context_t *hal = &timer->hal;
ESP_LOGD(TAG, "del timer (%d,%d)", group_id, timer_id);
timer_hal_deinit(&timer->hal);
// disable the source clock
GPTIMER_CLOCK_SRC_ATOMIC() {
timer_ll_enable_clock(hal->dev, hal->timer_id, false);
}
timer_hal_deinit(hal);
// recycle memory resource
ESP_RETURN_ON_ERROR(gptimer_destroy(timer), TAG, "destroy gptimer failed");
@ -382,8 +393,6 @@ static gptimer_group_t *gptimer_acquire_group_handle(int group_id)
// initialize timer group members
group->group_id = group_id;
group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
// enable APB access timer registers
periph_module_enable(timer_group_periph_signals.groups[group_id].module);
}
} else {
group = s_platform.groups[group_id];
@ -395,6 +404,15 @@ static gptimer_group_t *gptimer_acquire_group_handle(int group_id)
_lock_release(&s_platform.mutex);
if (new_group) {
// !!! HARDWARE SHARED RESOURCE !!!
// the gptimer and watchdog reside in the same the timer group
// we need to increase/decrease the reference count before enable/disable/reset the peripheral
PERIPH_RCC_ACQUIRE_ATOMIC(timer_group_periph_signals.groups[group_id].module, ref_count) {
if (ref_count == 0) {
timer_ll_enable_bus_clock(group_id, true);
timer_ll_reset_register(group_id);
}
}
ESP_LOGD(TAG, "new group (%d) @%p", group_id, group);
}
@ -412,11 +430,16 @@ static void gptimer_release_group_handle(gptimer_group_t *group)
assert(s_platform.groups[group_id]);
do_deinitialize = true;
s_platform.groups[group_id] = NULL;
periph_module_disable(timer_group_periph_signals.groups[group_id].module);
}
_lock_release(&s_platform.mutex);
if (do_deinitialize) {
// disable bus clock for the timer group
PERIPH_RCC_RELEASE_ATOMIC(timer_group_periph_signals.groups[group_id].module, ref_count) {
if (ref_count == 0) {
timer_ll_enable_bus_clock(group_id, false);
}
}
free(group);
ESP_LOGD(TAG, "del group (%d)", group_id);
}
@ -476,9 +499,15 @@ static esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_sou
}
#endif // CONFIG_PM_ENABLE
timer_ll_set_clock_source(timer->hal.dev, timer_id, src_clk);
// !!! HARDWARE SHARED RESOURCE !!!
// on some ESP chip, different peripheral's clock source setting are mixed in the same register
// so we need to make this done in an atomic way
GPTIMER_CLOCK_SRC_ATOMIC() {
timer_ll_set_clock_source(timer->hal.dev, timer_id, src_clk);
timer_ll_enable_clock(timer->hal.dev, timer_id, true);
}
timer->clk_src = src_clk;
unsigned int prescale = counter_src_hz / resolution_hz; // potential resolution loss here
uint32_t 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
if (timer->resolution_hz != resolution_hz) {

View File

@ -77,14 +77,6 @@ void esp_clk_init(void)
void esp_perip_clk_init(void)
{
/* Enable TimerGroup 0 clock to ensure its reference counter will never
* be decremented to 0 during normal operation and preventing it from
* being disabled.
* If the TimerGroup 0 clock is disabled and then reenabled, the watchdog
* registers (Flashboot protection included) will be reenabled, and some
* seconds later, will trigger an unintended reset.
*/
periph_module_enable(PERIPH_TIMG0_MODULE);
}
/**

View File

@ -11,6 +11,7 @@
#include "soc/soc_caps.h"
#include "hal/wdt_hal.h"
#include "hal/mwdt_ll.h"
#include "hal/timer_ll.h"
#include "freertos/FreeRTOS.h"
#include "esp_cpu.h"
#include "esp_err.h"
@ -30,6 +31,8 @@
#define IWDT_TICKS_PER_US 500
#define IWDT_INSTANCE WDT_MWDT1
#define IWDT_INITIAL_TIMEOUT_S 5
#define IWDT_PERIPH PERIPH_TIMG1_MODULE
#define IWDT_TIMER_GROUP 1
#else
@ -38,6 +41,8 @@
#define IWDT_TICKS_PER_US 500
#define IWDT_INSTANCE WDT_MWDT0
#define IWDT_INITIAL_TIMEOUT_S 5
#define IWDT_PERIPH PERIPH_TIMG0_MODULE
#define IWDT_TIMER_GROUP 0
#endif // SOC_TIMER_GROUPS > 1
@ -99,7 +104,12 @@ static void IRAM_ATTR tick_hook(void)
void esp_int_wdt_init(void)
{
periph_module_enable(PERIPH_TIMG1_MODULE);
PERIPH_RCC_ACQUIRE_ATOMIC(IWDT_PERIPH, ref_count) {
if (ref_count == 0) {
timer_ll_enable_bus_clock(IWDT_TIMER_GROUP, true);
timer_ll_reset_register(IWDT_TIMER_GROUP);
}
}
/*
* Initialize the WDT timeout stages. Note that the initial timeout is set to 5 seconds as variable startup times of
* each CPU can lead to a timeout. The tick hooks will set the WDT timers to the actual timeout.

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -300,15 +300,6 @@ __attribute__((weak)) void esp_perip_clk_init(void)
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
/* Enable TimerGroup 0 clock to ensure its reference counter will never
* be decremented to 0 during normal operation and preventing it from
* being disabled.
* If the TimerGroup 0 clock is disabled and then reenabled, the watchdog
* registers (Flashboot protection included) will be reenabled, and some
* seconds later, will trigger an unintended reset.
*/
periph_module_enable(PERIPH_TIMG0_MODULE);
}
void rtc_clk_select_rtc_slow_clk(void)

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -251,13 +251,4 @@ __attribute__((weak)) void esp_perip_clk_init(void)
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
/* Enable TimerGroup 0 clock to ensure its reference counter will never
* be decremented to 0 during normal operation and preventing it from
* being disabled.
* If the TimerGroup 0 clock is disabled and then reenabled, the watchdog
* registers (Flashboot protection included) will be reenabled, and some
* seconds later, will trigger an unintended reset.
*/
periph_module_enable(PERIPH_TIMG0_MODULE);
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -294,13 +294,4 @@ __attribute__((weak)) void esp_perip_clk_init(void)
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
/* Enable TimerGroup 0 clock to ensure its reference counter will never
* be decremented to 0 during normal operation and preventing it from
* being disabled.
* If the TimerGroup 0 clock is disabled and then reenabled, the watchdog
* registers (Flashboot protection included) will be reenabled, and some
* seconds later, will trigger an unintended reset.
*/
periph_module_enable(PERIPH_TIMG0_MODULE);
}

View File

@ -294,13 +294,4 @@ __attribute__((weak)) void esp_perip_clk_init(void)
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
#endif
/* Enable TimerGroup 0 clock to ensure its reference counter will never
* be decremented to 0 during normal operation and preventing it from
* being disabled.
* If the TimerGroup 0 clock is disabled and then reenabled, the watchdog
* registers (Flashboot protection included) will be reenabled, and some
* seconds later, will trigger an unintended reset.
*/
periph_module_enable(PERIPH_TIMG0_MODULE);
}

View File

@ -286,13 +286,4 @@ __attribute__((weak)) void esp_perip_clk_init(void)
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
#endif
/* Enable TimerGroup 0 clock to ensure its reference counter will never
* be decremented to 0 during normal operation and preventing it from
* being disabled.
* If the TimerGroup 0 clock is disabled and then reenabled, the watchdog
* registers (Flashboot protection included) will be reenabled, and some
* seconds later, will trigger an unintended reset.
*/
periph_module_enable(PERIPH_TIMG0_MODULE);
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -312,13 +312,4 @@ __attribute__((weak)) void esp_perip_clk_init(void)
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
/* Enable TimerGroup 0 clock to ensure its reference counter will never
* be decremented to 0 during normal operation and preventing it from
* being disabled.
* If the TimerGroup 0 clock is disabled and then reenabled, the watchdog
* registers (Flashboot protection included) will be reenabled, and some
* seconds later, will trigger an unintended reset.
*/
periph_module_enable(PERIPH_TIMG0_MODULE);
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -314,13 +314,4 @@ __attribute__((weak)) void esp_perip_clk_init(void)
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
/* Enable TimerGroup 0 clock to ensure its reference counter will never
* be decremented to 0 during normal operation and preventing it from
* being disabled.
* If the TimerGroup 0 clock is disabled and then reenabled, the watchdog
* registers (Flashboot protection included) will be reenabled, and some
* seconds later, will trigger an unintended reset.
*/
periph_module_enable(PERIPH_TIMG0_MODULE);
}

View File

@ -10,6 +10,7 @@
#include "sdkconfig.h"
#include "hal/wdt_hal.h"
#include "hal/mwdt_ll.h"
#include "hal/timer_ll.h"
#include "esp_err.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
@ -21,6 +22,7 @@
#define TWDT_TICKS_PER_US 500
#define TWDT_PRESCALER MWDT_LL_DEFAULT_CLK_PRESCALER // Tick period of 500us if WDT source clock is 80MHz
#define TWDT_PERIPH_MODULE PERIPH_TIMG0_MODULE
#define TWDT_TIMER_GROUP 0
#define TWDT_INTR_SOURCE ETS_TG0_WDT_LEVEL_INTR_SOURCE
/**
@ -55,7 +57,13 @@ esp_err_t esp_task_wdt_impl_timer_allocate(const esp_task_wdt_config_t *config,
}
if (ret == ESP_OK) {
periph_module_enable(TWDT_PERIPH_MODULE);
// enable bus clock for the timer group registers
PERIPH_RCC_ACQUIRE_ATOMIC(TWDT_PERIPH_MODULE, ref_count) {
if (ref_count == 0) {
timer_ll_enable_bus_clock(TWDT_TIMER_GROUP, true);
timer_ll_reset_register(TWDT_TIMER_GROUP);
}
}
wdt_hal_init(&ctx->hal, TWDT_INSTANCE, TWDT_PRESCALER, true);
wdt_hal_write_protect_disable(&ctx->hal);
@ -106,7 +114,11 @@ void esp_task_wdt_impl_timer_free(twdt_ctx_t obj)
ESP_ERROR_CHECK(esp_intr_disable(ctx->intr_handle));
/* Disable the Timer Group module */
periph_module_disable(TWDT_PERIPH_MODULE);
PERIPH_RCC_RELEASE_ATOMIC(TWDT_PERIPH_MODULE, ref_count) {
if (ref_count == 0) {
timer_ll_enable_bus_clock(TWDT_TIMER_GROUP, false);
}
}
/* Deregister interrupt */
ESP_ERROR_CHECK(esp_intr_free(ctx->intr_handle));

View File

@ -18,6 +18,7 @@
#include "soc/soc.h"
#include "soc/timer_group_reg.h"
#include "soc/rtc.h"
#include "hal/timer_ll.h"
#include "freertos/FreeRTOS.h"
/**
@ -245,7 +246,12 @@ void esp_timer_impl_advance(int64_t time_diff_us)
esp_err_t esp_timer_impl_early_init(void)
{
periph_module_enable(PERIPH_LACT);
PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_LACT, ref_count) {
if (ref_count == 0) {
timer_ll_enable_bus_clock(LACT_MODULE, true);
timer_ll_reset_register(LACT_MODULE);
}
}
REG_WRITE(CONFIG_REG, 0);
REG_WRITE(LOAD_LO_REG, 0);
@ -319,6 +325,11 @@ void esp_timer_impl_deinit(void)
}
}
s_alarm_handler = NULL;
PERIPH_RCC_RELEASE_ATOMIC(PERIPH_LACT, ref_count) {
if (ref_count == 0) {
timer_ll_enable_bus_clock(LACT_MODULE, false);
}
}
}
uint64_t esp_timer_impl_get_alarm_reg(void)

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -13,6 +13,7 @@
#include "hal/misc.h"
#include "hal/timer_types.h"
#include "soc/timer_group_struct.h"
#include "soc/dport_reg.h"
#ifdef __cplusplus
extern "C" {
@ -22,6 +23,55 @@ extern "C" {
#define TIMER_LL_GET_HW(group_id) ((group_id == 0) ? (&TIMERG0) : (&TIMERG1))
#define TIMER_LL_EVENT_ALARM(timer_id) (1 << (timer_id))
/**
* @brief Enable the bus clock for timer group module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void timer_ll_enable_bus_clock(int group_id, bool enable)
{
uint32_t reg_val = DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
if (group_id == 0) {
reg_val &= ~DPORT_TIMERGROUP_CLK_EN;
reg_val |= enable << 13;
} else {
reg_val &= ~DPORT_TIMERGROUP1_CLK_EN;
reg_val |= enable << 15;
}
DPORT_WRITE_PERI_REG(DPORT_PERIP_CLK_EN_REG, reg_val);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the timer group module
*
* @note After reset the register, the "flash boot protection" will be enabled again.
* FLash boot protection is not used anymore after system boot up.
* This function will disable it by default in order to prevent the system from being reset unexpectedly.
*
* @param group_id Group ID
*/
static inline void timer_ll_reset_register(int group_id)
{
if (group_id == 0) {
DPORT_WRITE_PERI_REG(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP_RST);
DPORT_WRITE_PERI_REG(DPORT_PERIP_RST_EN_REG, 0);
TIMERG0.wdtconfig0.wdt_flashboot_mod_en = 0;
} else {
DPORT_WRITE_PERI_REG(DPORT_PERIP_RST_EN_REG, DPORT_TIMERGROUP1_RST);
DPORT_WRITE_PERI_REG(DPORT_PERIP_RST_EN_REG, 0);
TIMERG1.wdtconfig0.wdt_flashboot_mod_en = 0;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_reset_register(__VA_ARGS__)
/**
* @brief Set clock source for timer
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -13,6 +13,7 @@
#include "hal/misc.h"
#include "hal/timer_types.h"
#include "soc/timer_group_struct.h"
#include "soc/system_struct.h"
#ifdef __cplusplus
extern "C" {
@ -22,6 +23,43 @@ extern "C" {
#define TIMER_LL_GET_HW(group_id) (&TIMERG0)
#define TIMER_LL_EVENT_ALARM(timer_id) (1 << (timer_id))
/**
* @brief Enable the bus clock for timer group module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void timer_ll_enable_bus_clock(int group_id, bool enable)
{
(void)group_id;
SYSTEM.perip_clk_en0.timergroup_clk_en = enable;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the timer group module
*
* @note After reset the register, the "flash boot protection" will be enabled again.
* FLash boot protection is not used anymore after system boot up.
* This function will disable it by default in order to prevent the system from being reset unexpectedly.
*
* @param group_id Group ID
*/
static inline void timer_ll_reset_register(int group_id)
{
(void)group_id;
SYSTEM.perip_rst_en0.timergroup_rst = 1;
SYSTEM.perip_rst_en0.timergroup_rst = 0;
TIMERG0.wdtconfig0.wdt_flashboot_mod_en = 0;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_reset_register(__VA_ARGS__)
/**
* @brief Set clock source for timer
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -13,6 +13,7 @@
#include "hal/misc.h"
#include "hal/timer_types.h"
#include "soc/timer_group_struct.h"
#include "soc/system_struct.h"
#ifdef __cplusplus
extern "C" {
@ -22,6 +23,51 @@ extern "C" {
#define TIMER_LL_GET_HW(group_id) ((group_id == 0) ? (&TIMERG0) : (&TIMERG1))
#define TIMER_LL_EVENT_ALARM(timer_id) (1 << (timer_id))
/**
* @brief Enable the bus clock for timer group module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void timer_ll_enable_bus_clock(int group_id, bool enable)
{
if (group_id == 0) {
SYSTEM.perip_clk_en0.reg_timergroup_clk_en = enable;
} else {
SYSTEM.perip_clk_en0.reg_timergroup1_clk_en = enable;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the timer group module
*
* @note After reset the register, the "flash boot protection" will be enabled again.
* FLash boot protection is not used anymore after system boot up.
* This function will disable it by default in order to prevent the system from being reset unexpectedly.
*
* @param group_id Group ID
*/
static inline void timer_ll_reset_register(int group_id)
{
if (group_id == 0) {
SYSTEM.perip_rst_en0.reg_timergroup_rst = 1;
SYSTEM.perip_rst_en0.reg_timergroup_rst = 0;
TIMERG0.wdtconfig0.wdt_flashboot_mod_en = 0;
} else {
SYSTEM.perip_rst_en0.reg_timergroup1_rst = 1;
SYSTEM.perip_rst_en0.reg_timergroup1_rst = 0;
TIMERG1.wdtconfig0.wdt_flashboot_mod_en = 0;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_reset_register(__VA_ARGS__)
/**
* @brief Set clock source for timer
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -50,6 +50,51 @@ extern "C" {
}}, \
}[group][timer][event]
/**
* @brief Enable the bus clock for timer group module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void timer_ll_enable_bus_clock(int group_id, bool enable)
{
if (group_id == 0) {
PCR.timergroup0_conf.tg0_clk_en = enable;
} else {
PCR.timergroup1_conf.tg1_clk_en = enable;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the timer group module
*
* @note After reset the register, the "flash boot protection" will be enabled again.
* FLash boot protection is not used anymore after system boot up.
* This function will disable it by default in order to prevent the system from being reset unexpectedly.
*
* @param group_id Group ID
*/
static inline void timer_ll_reset_register(int group_id)
{
if (group_id == 0) {
PCR.timergroup0_conf.tg0_rst_en = 1;
PCR.timergroup0_conf.tg0_rst_en = 0;
TIMERG0.wdtconfig0.wdt_flashboot_mod_en = 0;
} else {
PCR.timergroup1_conf.tg1_rst_en = 1;
PCR.timergroup1_conf.tg1_rst_en = 0;
TIMERG1.wdtconfig0.wdt_flashboot_mod_en = 0;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_reset_register(__VA_ARGS__)
/**
* @brief Set clock source for timer
*

View File

@ -50,6 +50,51 @@ extern "C" {
}}, \
}[group][timer][event]
/**
* @brief Enable the bus clock for timer group module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void timer_ll_enable_bus_clock(int group_id, bool enable)
{
if (group_id == 0) {
PCR.timergroup0_conf.tg0_clk_en = enable;
} else {
PCR.timergroup1_conf.tg1_clk_en = enable;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the timer group module
*
* @note After reset the register, the "flash boot protection" will be enabled again.
* FLash boot protection is not used anymore after system boot up.
* This function will disable it by default in order to prevent the system from being reset unexpectedly.
*
* @param group_id Group ID
*/
static inline void timer_ll_reset_register(int group_id)
{
if (group_id == 0) {
PCR.timergroup0_conf.tg0_rst_en = 1;
PCR.timergroup0_conf.tg0_rst_en = 0;
TIMERG0.wdtconfig0.wdt_flashboot_mod_en = 0;
} else {
PCR.timergroup1_conf.tg1_rst_en = 1;
PCR.timergroup1_conf.tg1_rst_en = 0;
TIMERG1.wdtconfig0.wdt_flashboot_mod_en = 0;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_reset_register(__VA_ARGS__)
/**
* @brief Set clock source for timer
*

View File

@ -80,10 +80,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
return HP_SYS_CLKRST_REG_MCPWM0_APB_CLK_EN;
case PERIPH_MCPWM1_MODULE:
return HP_SYS_CLKRST_REG_MCPWM1_APB_CLK_EN;
case PERIPH_TIMG0_MODULE:
return HP_SYS_CLKRST_REG_TIMERGRP0_T0_CLK_EN | HP_SYS_CLKRST_REG_TIMERGRP0_T1_CLK_EN | HP_SYS_CLKRST_REG_TIMERGRP0_WDT_CLK_EN;
case PERIPH_TIMG1_MODULE:
return HP_SYS_CLKRST_REG_TIMERGRP1_T0_CLK_EN | HP_SYS_CLKRST_REG_TIMERGRP1_T1_CLK_EN | HP_SYS_CLKRST_REG_TIMERGRP1_WDT_CLK_EN;
case PERIPH_SYSTIMER_MODULE:
return HP_SYS_CLKRST_REG_SYSTIMER_CLK_EN;
case PERIPH_LEDC_MODULE:
@ -148,10 +144,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
return HP_SYS_CLKRST_REG_RST_EN_AXI_PDMA;
case PERIPH_SYSTIMER_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_STIMER;
case PERIPH_TIMG0_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_TIMERGRP0;
case PERIPH_TIMG1_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_TIMERGRP1;
case PERIPH_UART0_MODULE:
return HP_SYS_CLKRST_REG_RST_EN_UART0_CORE;
case PERIPH_UART1_MODULE:
@ -268,9 +260,6 @@ static inline uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
case PERIPH_MCPWM1_MODULE:
case PERIPH_PCNT_MODULE:
return HP_SYS_CLKRST_SOC_CLK_CTRL2_REG;
case PERIPH_TIMG0_MODULE:
return HP_SYS_CLKRST_PERI_CLK_CTRL20_REG;
case PERIPH_TIMG1_MODULE:
case PERIPH_SYSTIMER_MODULE:
case PERIPH_LEDC_MODULE:
case PERIPH_RMT_MODULE:
@ -312,8 +301,6 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
case PERIPH_AHB_PDMA_MODULE:
case PERIPH_AXI_PDMA_MODULE:
case PERIPH_SYSTIMER_MODULE:
case PERIPH_TIMG0_MODULE:
case PERIPH_TIMG1_MODULE:
case PERIPH_UART0_MODULE:
case PERIPH_UART1_MODULE:
case PERIPH_UART2_MODULE:

View File

@ -24,6 +24,51 @@ extern "C" {
#define TIMER_LL_GET_HW(group_id) ((group_id == 0) ? (&TIMERG0) : (&TIMERG1))
#define TIMER_LL_EVENT_ALARM(timer_id) (1 << (timer_id))
/**
* @brief Enable the bus clock for timer group module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void timer_ll_enable_bus_clock(int group_id, bool enable)
{
if (group_id == 0) {
HP_SYS_CLKRST.soc_clk_ctrl2.reg_timergrp0_apb_clk_en = enable;
} else {
HP_SYS_CLKRST.soc_clk_ctrl2.reg_timergrp1_apb_clk_en = enable;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the timer group module
*
* @note After reset the register, the "flash boot protection" will be enabled again.
* FLash boot protection is not used anymore after system boot up.
* This function will disable it by default in order to prevent the system from being reset unexpectedly.
*
* @param group_id Group ID
*/
static inline void timer_ll_reset_register(int group_id)
{
if (group_id == 0) {
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_timergrp0 = 1;
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_timergrp0 = 0;
TIMERG0.wdtconfig0.wdt_flashboot_mod_en = 0;
} else {
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_timergrp1 = 1;
HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_timergrp1 = 0;
TIMERG1.wdtconfig0.wdt_flashboot_mod_en = 0;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_reset_register(__VA_ARGS__)
/**
* @brief Set clock source for timer
*
@ -63,6 +108,10 @@ static inline void timer_ll_set_clock_source(timg_dev_t *hw, uint32_t timer_num,
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define timer_ll_set_clock_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; timer_ll_set_clock_source(__VA_ARGS__)
/**
* @brief Enable Timer Group (GPTimer) module clock
*
@ -87,6 +136,10 @@ static inline void timer_ll_enable_clock(timg_dev_t *hw, uint32_t timer_num, boo
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define timer_ll_enable_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; timer_ll_enable_clock(__VA_ARGS__)
/**
* @brief Enable alarm event
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -13,6 +13,7 @@
#include "hal/misc.h"
#include "hal/timer_types.h"
#include "soc/timer_group_struct.h"
#include "soc/system_reg.h"
#ifdef __cplusplus
extern "C" {
@ -22,6 +23,55 @@ extern "C" {
#define TIMER_LL_GET_HW(group_id) ((group_id == 0) ? (&TIMERG0) : (&TIMERG1))
#define TIMER_LL_EVENT_ALARM(timer_id) (1 << (timer_id))
/**
* @brief Enable the bus clock for timer group module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void timer_ll_enable_bus_clock(int group_id, bool enable)
{
uint32_t reg_val = READ_PERI_REG(DPORT_PERIP_CLK_EN0_REG);
if (group_id == 0) {
reg_val &= ~DPORT_TIMERGROUP_CLK_EN_M;
reg_val |= enable << DPORT_TIMERGROUP_CLK_EN_S;
} else {
reg_val &= ~DPORT_TIMERGROUP1_CLK_EN_M;
reg_val |= enable << DPORT_TIMERGROUP1_CLK_EN_S;
}
WRITE_PERI_REG(DPORT_PERIP_CLK_EN0_REG, reg_val);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the timer group module
*
* @note After reset the register, the "flash boot protection" will be enabled again.
* FLash boot protection is not used anymore after system boot up.
* This function will disable it by default in order to prevent the system from being reset unexpectedly.
*
* @param group_id Group ID
*/
static inline void timer_ll_reset_register(int group_id)
{
if (group_id == 0) {
WRITE_PERI_REG(DPORT_PERIP_RST_EN0_REG, DPORT_TIMERGROUP_RST_M);
WRITE_PERI_REG(DPORT_PERIP_RST_EN0_REG, 0);
TIMERG0.wdtconfig0.wdt_flashboot_mod_en = 0;
} else {
WRITE_PERI_REG(DPORT_PERIP_RST_EN0_REG, DPORT_TIMERGROUP1_RST_M);
WRITE_PERI_REG(DPORT_PERIP_RST_EN0_REG, 0);
TIMERG1.wdtconfig0.wdt_flashboot_mod_en = 0;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_reset_register(__VA_ARGS__)
/**
* @brief Set clock source for timer
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -13,6 +13,7 @@
#include "hal/misc.h"
#include "hal/timer_types.h"
#include "soc/timer_group_struct.h"
#include "soc/system_struct.h"
#ifdef __cplusplus
extern "C" {
@ -22,6 +23,51 @@ extern "C" {
#define TIMER_LL_GET_HW(group_id) ((group_id == 0) ? (&TIMERG0) : (&TIMERG1))
#define TIMER_LL_EVENT_ALARM(timer_id) (1 << (timer_id))
/**
* @brief Enable the bus clock for timer group module
*
* @param group_id Group ID
* @param enable true to enable, false to disable
*/
static inline void timer_ll_enable_bus_clock(int group_id, bool enable)
{
if (group_id == 0) {
SYSTEM.perip_clk_en0.timergroup_clk_en = enable;
} else {
SYSTEM.perip_clk_en0.timergroup1_clk_en = enable;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the timer group module
*
* @note After reset the register, the "flash boot protection" will be enabled again.
* FLash boot protection is not used anymore after system boot up.
* This function will disable it by default in order to prevent the system from being reset unexpectedly.
*
* @param group_id Group ID
*/
static inline void timer_ll_reset_register(int group_id)
{
if (group_id == 0) {
SYSTEM.perip_rst_en0.timergroup_rst = 1;
SYSTEM.perip_rst_en0.timergroup_rst = 0;
TIMERG0.wdtconfig0.wdt_flashboot_mod_en = 0;
} else {
SYSTEM.perip_rst_en0.timergroup1_rst = 1;
SYSTEM.perip_rst_en0.timergroup1_rst = 0;
TIMERG1.wdtconfig0.wdt_flashboot_mod_en = 0;
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
#define timer_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; timer_ll_reset_register(__VA_ARGS__)
/**
* @brief Set clock source for timer
*

View File

@ -13,8 +13,6 @@ void timer_hal_init(timer_hal_context_t *hal, uint32_t group_num, uint32_t timer
{
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);
@ -27,8 +25,6 @@ void timer_hal_init(timer_hal_context_t *hal, uint32_t group_num, uint32_t timer
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);

View File

@ -905,6 +905,7 @@ typedef struct {
volatile system_reg_date_reg_t reg_date;
} system_dev_t;
extern system_dev_t SYSTEM;
#ifndef __cplusplus
_Static_assert(sizeof(system_dev_t) == 0x1000, "Invalid size of system_dev_t structure");

View File

@ -20,3 +20,4 @@ PROVIDE ( GPSPI3 = 0x60025000 );
PROVIDE ( SYSCON = 0x60026000 );
PROVIDE ( APB_SARADC = 0x60040000 );
PROVIDE ( GDMA = 0x6003F000 );
PROVIDE ( SYSTEM = 0x600c0000 );

View File

@ -33,3 +33,4 @@ PROVIDE ( GPSPI4 = 0x60037000 );
PROVIDE ( APB_SARADC = 0x60040000 );
PROVIDE ( USB_SERIAL_JTAG = 0x60043000 );
PROVIDE ( GDMA = 0x6003F000 );
PROVIDE ( SYSTEM = 0x600c0000 );

View File

@ -49,3 +49,4 @@ PROVIDE ( USB0 = 0x60080000 );
PROVIDE ( USB_DWC = 0x60080000 );
PROVIDE ( USB_WRAP = 0x60039000 );
PROVIDE ( WORLD_CONTROLLER = 0x600D0000 );
PROVIDE ( SYSTEM = 0x600C0000 );