/* * Copyright (c) 2006-2022, Synwit Technology Co.,Ltd. * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-12-10 Zohar_Lee first version * 2020-07-10 lik format file */ #include "drv_hwtimer.h" #ifdef RT_USING_HWTIMER #ifdef BSP_USING_TIM //#define DRV_DEBUG #define LOG_TAG "drv.hwtimer" #include #if !defined(BSP_USING_TIM0) && !defined(BSP_USING_TIM1) && !defined(BSP_USING_TIM2) && !defined(BSP_USING_TIM3) \ && !defined(BSP_USING_TIM4) && !defined(BSP_USING_TIM5) #error "Please define at least one BSP_USING_TIMx" /* this driver can be disabled at menuconfig ? RT-Thread Components ? Device Drivers */ #endif #ifndef TIM_DEV_INFO_CONFIG #define TIM_DEV_INFO_CONFIG \ { \ .maxfreq = 120000000, \ .minfreq = 120000000, \ .maxcnt = 0xFFFFFFFF, \ .cntmode = HWTIMER_CNTMODE_DW, \ } #endif /* TIM_DEV_INFO_CONFIG */ #ifdef BSP_USING_TIM0 #ifndef TIM0_CFG #define TIM0_CFG \ { \ .name = "timer0", \ .TIMRx = TIMR0, \ } #endif /* TIM0_CFG */ #endif /* BSP_USING_TIM0 */ #ifdef BSP_USING_TIM1 #ifndef TIM1_CFG #define TIM1_CFG \ { \ .name = "timer1", \ .TIMRx = TIMR1, \ } #endif /* TIM1_CFG */ #endif /* BSP_USING_TIM1 */ #ifdef BSP_USING_TIM2 #ifndef TIM2_CFG #define TIM2_CFG \ { \ .name = "timer2", \ .TIMRx = TIMR2, \ } #endif /* TIM2_CFG */ #endif /* BSP_USING_TIM2 */ #ifdef BSP_USING_TIM3 #ifndef TIM3_CFG #define TIM3_CFG \ { \ .name = "timer3", \ .TIMRx = TIMR3, \ } #endif /* TIM3_CFG */ #endif /* BSP_USING_TIM3 */ #ifdef BSP_USING_TIM4 #ifndef TIM4_CFG #define TIM4_CFG \ { \ .name = "timer4", \ .TIMRx = TIMR4, \ } #endif /* TIM4_CFG */ #endif /* BSP_USING_TIM4 */ #ifdef BSP_USING_TIM5 #ifndef TIM5_CFG #define TIM5_CFG \ { \ .name = "timer5", \ .TIMRx = TIMR5, \ } #endif /* TIM5_CFG */ #endif /* BSP_USING_TIM5 */ struct swm_hwtimer_cfg { char *name; TIMR_TypeDef *TIMRx; }; struct swm_hwtimer_device { struct swm_hwtimer_cfg *hwtimer_cfg; rt_hwtimer_t time_device; }; enum { #ifdef BSP_USING_TIM0 TIM0_INDEX, #endif #ifdef BSP_USING_TIM1 TIM1_INDEX, #endif #ifdef BSP_USING_TIM2 TIM2_INDEX, #endif #ifdef BSP_USING_TIM3 TIM3_INDEX, #endif #ifdef BSP_USING_TIM4 TIM4_INDEX, #endif #ifdef BSP_USING_TIM5 TIM5_INDEX, #endif }; static struct swm_hwtimer_cfg swm_hwtimer_cfg[] = { #ifdef BSP_USING_TIM0 TIM0_CFG, #endif #ifdef BSP_USING_TIM1 TIM1_CFG, #endif #ifdef BSP_USING_TIM2 TIM2_CFG, #endif #ifdef BSP_USING_TIM3 TIM3_CFG, #endif #ifdef BSP_USING_TIM4 TIM4_CFG, #endif #ifdef BSP_USING_TIM5 TIM5_CFG, #endif }; static struct swm_hwtimer_device hwtimer_obj[sizeof(swm_hwtimer_cfg) / sizeof(swm_hwtimer_cfg[0])] = {0}; static void swm_timer_configure(struct rt_hwtimer_device *timer_device, rt_uint32_t state) { struct swm_hwtimer_cfg *hwtimer_cfg = RT_NULL; RT_ASSERT(timer_device != RT_NULL); if (state) { hwtimer_cfg = timer_device->parent.user_data; TIMR_Init(hwtimer_cfg->TIMRx, TIMR_MODE_TIMER, SystemCoreClock, 1); timer_device->freq = SystemCoreClock; } } static rt_err_t swm_timer_start(rt_hwtimer_t *timer_device, rt_uint32_t cnt, rt_hwtimer_mode_t opmode) { rt_err_t result = RT_EOK; struct swm_hwtimer_cfg *hwtimer_cfg = RT_NULL; RT_ASSERT(timer_device != RT_NULL); hwtimer_cfg = timer_device->parent.user_data; if (opmode == HWTIMER_MODE_ONESHOT) { /* set timer to single mode */ timer_device->mode = HWTIMER_MODE_ONESHOT; } else { timer_device->mode = HWTIMER_MODE_PERIOD; } TIMR_SetPeriod(hwtimer_cfg->TIMRx, cnt); TIMR_Stop(hwtimer_cfg->TIMRx); TIMR_Start(hwtimer_cfg->TIMRx); return result; } static void swm_timer_stop(rt_hwtimer_t *timer_device) { struct swm_hwtimer_cfg *hwtimer_cfg = RT_NULL; RT_ASSERT(timer_device != RT_NULL); hwtimer_cfg = timer_device->parent.user_data; /* stop timer */ TIMR_Stop(hwtimer_cfg->TIMRx); } static rt_uint32_t swm_timer_count_get(rt_hwtimer_t *timer_device) { struct swm_hwtimer_cfg *hwtimer_cfg = RT_NULL; RT_ASSERT(timer_device != RT_NULL); hwtimer_cfg = timer_device->parent.user_data; return TIMR_GetCurValue(hwtimer_cfg->TIMRx); } static rt_err_t swm_timer_control(rt_hwtimer_t *timer_device, rt_uint32_t cmd, void *args) { struct swm_hwtimer_cfg *hwtimer_cfg = RT_NULL; rt_err_t result = RT_EOK; RT_ASSERT(timer_device != RT_NULL); RT_ASSERT(args != RT_NULL); hwtimer_cfg = timer_device->parent.user_data; switch (cmd) { case HWTIMER_CTRL_FREQ_SET: { rt_uint32_t freq; freq = *(rt_uint32_t *)args; TIMR_Init(hwtimer_cfg->TIMRx, TIMR_MODE_TIMER, SystemCoreClock / freq, 1); } break; default: { result = -RT_ENOSYS; } break; } return result; } static const struct rt_hwtimer_info _info = TIM_DEV_INFO_CONFIG; static const struct rt_hwtimer_ops swm_timer_ops = { .init = swm_timer_configure, .start = swm_timer_start, .stop = swm_timer_stop, .count_get = swm_timer_count_get, .control = swm_timer_control}; void swm_timer_isr(rt_hwtimer_t *timer_device) { struct swm_hwtimer_cfg *hwtimer_cfg = RT_NULL; RT_ASSERT(timer_device != RT_NULL); hwtimer_cfg = timer_device->parent.user_data; TIMR_INTClr(hwtimer_cfg->TIMRx); rt_device_hwtimer_isr(timer_device); } #ifdef BSP_USING_TIM0 void TIMR0_Handler(void) { /* enter interrupt */ rt_interrupt_enter(); swm_timer_isr(&(hwtimer_obj[TIM0_INDEX].time_device)); /* leave interrupt */ rt_interrupt_leave(); } #endif //BSP_USING_TIM0 #ifdef BSP_USING_TIM1 void TIMR1_Handler(void) { /* enter interrupt */ rt_interrupt_enter(); swm_timer_isr(&(hwtimer_obj[TIM1_INDEX].time_device)); /* leave interrupt */ rt_interrupt_leave(); } #endif //BSP_USING_TIM1 #ifdef BSP_USING_TIM2 void TIMR2_Handler(void) { /* enter interrupt */ rt_interrupt_enter(); swm_timer_isr(&(hwtimer_obj[TIM2_INDEX].time_device)); /* leave interrupt */ rt_interrupt_leave(); } #endif //BSP_USING_TIM2 #ifdef BSP_USING_TIM3 void TIMR3_Handler(void) { /* enter interrupt */ rt_interrupt_enter(); swm_timer_isr(&(hwtimer_obj[TIM3_INDEX].time_device)); /* leave interrupt */ rt_interrupt_leave(); } #endif //BSP_USING_TIM3 #ifdef BSP_USING_TIM4 void TIMR4_Handler(void) { /* enter interrupt */ rt_interrupt_enter(); swm_timer_isr(&(hwtimer_obj[TIM4_INDEX].time_device)); /* leave interrupt */ rt_interrupt_leave(); } #endif //BSP_USING_TIM4 #ifdef BSP_USING_TIM5 void TIMR5_Handler(void) { /* enter interrupt */ rt_interrupt_enter(); swm_timer_isr(&(hwtimer_obj[TIM5_INDEX].time_device)); /* leave interrupt */ rt_interrupt_leave(); } #endif //BSP_USING_TIM5 static int swm_timer_init(void) { int i = 0; int result = RT_EOK; for (i = 0; i < sizeof(swm_hwtimer_cfg) / sizeof(swm_hwtimer_cfg[0]); i++) { hwtimer_obj[i].hwtimer_cfg = &swm_hwtimer_cfg[i]; hwtimer_obj[i].time_device.info = &_info; hwtimer_obj[i].time_device.ops = &swm_timer_ops; result = rt_device_hwtimer_register(&hwtimer_obj[i].time_device, hwtimer_obj[i].hwtimer_cfg->name, hwtimer_obj[i].hwtimer_cfg); if (result != RT_EOK) { LOG_E("%s register fail.", hwtimer_obj[i].hwtimer_cfg->name); } else { LOG_D("%s register success.", hwtimer_obj[i].hwtimer_cfg->name); } } return result; } INIT_BOARD_EXPORT(swm_timer_init); #endif /* BSP_USING_TIM */ #endif /* RT_USING_HWTIMER */