/*! * \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) {}