Files
hpw421/component/xc6xx_drivers/Drivers/xc_driver/xc_drv_timer.c
T
2026-07-03 18:08:25 +08:00

203 lines
7.0 KiB
C

/*!
* \file xc_drv_timer.c
*
* \brief Target xc timer driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_timer.h"
#if XC_CHECK(XC_TIMER_ENABLED)
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
timer_handler_callback timer_n_callback[4] = {timer0_callback, timer1_callback,
timer2_callback, timer3_callback};
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_timer_init(uint8_t reg_idx, Timer_InitCfg_t *init_cfg)
{
if (TIMER0_IDX == reg_idx) {
cpr_ctlapbclken_grctl__timer_pclk_en__setf(ENABLE);
cpr_timer0_clk_ctl__timer_clksel__setf(
(uint8_t)init_cfg->timer_src_clk);
cpr_timer0_clk_ctl__timer_clk0_div__setf(
(uint8_t)init_cfg->timer_div_clk);
cpr_timer0_clk_ctl__timer_clk1_div__setf(
(uint8_t)init_cfg->timer_div_clk);
} else if (TIMER1_IDX == reg_idx) {
cpr_ctlapbclken_grctl__timer_pclk_en__setf(ENABLE);
cpr_timer1_clk_ctl__timer_clksel__setf(
(uint8_t)init_cfg->timer_src_clk);
cpr_timer1_clk_ctl__timer_clk0_div__setf(
(uint8_t)init_cfg->timer_div_clk);
cpr_timer1_clk_ctl__timer_clk1_div__setf(
(uint8_t)init_cfg->timer_div_clk);
} else if (TIMER2_IDX == reg_idx) {
cpr_ctlapbclken_grctl__timer_pclk_en__setf(ENABLE);
cpr_timer2_clk_ctl__timer_clksel__setf(
(uint8_t)init_cfg->timer_src_clk);
cpr_timer2_clk_ctl__timer_clk0_div__setf(
(uint8_t)init_cfg->timer_div_clk);
cpr_timer2_clk_ctl__timer_clk1_div__setf(
(uint8_t)init_cfg->timer_div_clk);
} else if (TIMER3_IDX == reg_idx) {
cpr_ctlapbclken_grctl__timer_pclk_en__setf(ENABLE);
cpr_timer3_clk_ctl__timer_clksel__setf(
(uint8_t)init_cfg->timer_src_clk);
cpr_timer3_clk_ctl__timer_clk0_div__setf(
(uint8_t)init_cfg->timer_div_clk);
cpr_timer3_clk_ctl__timer_clk1_div__setf(
(uint8_t)init_cfg->timer_div_clk);
}
cpr_lp_ctl__timer_sysclk_sel__setf(ENABLE);
timer_tcr__tes__setf(reg_idx, TIMER_TCR_TES_DISABLE);
timer_tcr__tms__setf(reg_idx, (uint8_t)init_cfg->timer_mode);
}
static uint32_t xc_timer_us_to_ticks(uint8_t reg_idx, uint32_t us)
{
uint32_t ticks;
uint8_t src_clk;
if (TIMER0_IDX == reg_idx) {
src_clk = cpr_timer0_clk_ctl__timer_clksel__getf();
if (src_clk == TIMER_CLK_SRC_32M_DIV) {
ticks = TIMER_CLKSRC_32M_DIV_CAL(
us, cpr_timer0_clk_ctl__timer_clk0_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K_DIV) {
ticks = TIMER_CLKSRC_32K_DIV_CAL(
us, cpr_timer0_clk_ctl__timer_clk1_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K) {
ticks = TIMER_CLKSRC_32K_CAL(us);
}
} else if (TIMER1_IDX == reg_idx) {
src_clk = cpr_timer1_clk_ctl__timer_clksel__getf();
if (src_clk == TIMER_CLK_SRC_32M_DIV) {
ticks = TIMER_CLKSRC_32M_DIV_CAL(
us, cpr_timer1_clk_ctl__timer_clk0_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K_DIV) {
ticks = TIMER_CLKSRC_32K_DIV_CAL(
us, cpr_timer1_clk_ctl__timer_clk1_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K) {
ticks = TIMER_CLKSRC_32K_CAL(us);
}
} else if (TIMER2_IDX == reg_idx) {
src_clk = cpr_timer2_clk_ctl__timer_clksel__getf();
if (src_clk == TIMER_CLK_SRC_32M_DIV) {
ticks = TIMER_CLKSRC_32M_DIV_CAL(
us, cpr_timer2_clk_ctl__timer_clk0_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K_DIV) {
ticks = TIMER_CLKSRC_32K_DIV_CAL(
us, cpr_timer2_clk_ctl__timer_clk1_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K) {
ticks = TIMER_CLKSRC_32K_CAL(us);
}
} else if (TIMER3_IDX == reg_idx) {
src_clk = cpr_timer3_clk_ctl__timer_clksel__getf();
if (src_clk == TIMER_CLK_SRC_32M_DIV) {
ticks = TIMER_CLKSRC_32M_DIV_CAL(
us, cpr_timer3_clk_ctl__timer_clk0_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K_DIV) {
ticks = TIMER_CLKSRC_32K_DIV_CAL(
us, cpr_timer3_clk_ctl__timer_clk1_div__getf());
} else if (src_clk == TIMER_CLK_SRC_32K) {
ticks = TIMER_CLKSRC_32K_CAL(us);
}
}
if (ticks < TIMER_MIN_TLC_VAL)
ticks = TIMER_MIN_TLC_VAL;
return ticks;
}
void xc_timer_set_value(uint8_t reg_idx, uint32_t us)
{
uint32_t ticks = xc_timer_us_to_ticks(reg_idx, us);
timer_tcr__tes__setf(reg_idx, TIMER_TCR_TES_DISABLE);
timer_tlc_set(reg_idx, ticks);
}
void xc_timer_start(uint8_t reg_idx)
{
NVIC_EnableIRQ((IRQn_Type)(TIMER0_IRQn + reg_idx));
timer_tcr__tim__setf(reg_idx, TIMER_TCR_TIM_DISABLE);
timer_tcr__tes__setf(reg_idx, TIMER_TCR_TES_ENABLE);
}
void xc_timer_stop(uint8_t reg_idx)
{
timer_tcr__tes__setf(reg_idx, TIMER_TCR_TES_DISABLE);
}
void TIMER0_Handler(void)
{
(void)timer_tic_get(TIMER0_IDX);
if (timer_n_callback[0] != NULL)
timer_n_callback[0](NULL);
}
void TIMER1_Handler(void)
{
(void)timer_tic_get(TIMER1_IDX);
if (timer_n_callback[1] != NULL)
timer_n_callback[1](NULL);
}
void TIMER2_Handler(void)
{
(void)timer_tic_get(TIMER2_IDX);
if (timer_n_callback[2] != NULL)
timer_n_callback[2](NULL);
}
void TIMER3_Handler(void)
{
(void)timer_tic_get(TIMER3_IDX);
if (timer_n_callback[3] != NULL)
timer_n_callback[3](NULL);
}
__WEAK void timer0_callback(void *context) {}
__WEAK void timer1_callback(void *context) {}
__WEAK void timer2_callback(void *context) {}
__WEAK void timer3_callback(void *context) {}
#endif // XC_CHECK(XC_TIMER_ENABLED)