209 lines
7.1 KiB
C
209 lines
7.1 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"
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
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_start_noirq(uint8_t reg_idx)
|
|
{
|
|
NVIC_DisableIRQ((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) {}
|