1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date             Author           Notes
8  * 2023-10-30       ChuShicheng      first version
9  */
10 
11 #include "drv_hwtimer.h"
12 #include "board.h"
13 
14 #ifdef BSP_USING_HWTIMER
15 
16 #define DBG_LEVEL   DBG_LOG
17 #include <rtdbg.h>
18 #define LOG_TAG "DRV.HWTIMER"
19 
20 typedef struct _timer
21 {
22     char *name;
23     struct repeating_timer repeat_timer;
24     alarm_id_t alarm_id;
25     rt_hwtimer_t timer;
26 }_timer_t;
27 
28 static void _hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state);
29 static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode);
30 static void _hwtimer_stop(rt_hwtimer_t *timer);
31 static rt_uint32_t _hwtimer_count_get(rt_hwtimer_t *timer);
32 static rt_err_t _hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
33 static int64_t _hwtmr_isr(alarm_id_t id, void *user_data);
34 
35 static const struct rt_hwtimer_ops _hwtimer_ops = {
36     .init = _hwtimer_init,
37     .start = _hwtimer_start,
38     .stop = _hwtimer_stop,
39     .count_get = _hwtimer_count_get,
40     .control = _hwtimer_control
41 };
42 
43 static const struct rt_hwtimer_info _hwtimer_info = {
44     .maxfreq = 1000000UL,
45     .minfreq = 1000000UL,
46     .maxcnt = 0xFFFF,
47     .cntmode = HWTIMER_MODE_PERIOD
48 };
49 
50 #ifdef BSP_USING_TIMER0
51 static _timer_t timer0 = {.name = "timer0"};
52 #endif /* BSP_USING_TIMER0 */
53 #ifdef BSP_USING_TIMER1
54 static _timer_t timer1 = {.name = "timer1" };
55 #endif /* BSP_USING_TIMER1 */
56 #ifdef BSP_USING_TIMER2
57 static _timer_t timer2 = {.name = "timer2"};
58 #endif /* BSP_USING_TIMER2 */
59 #ifdef BSP_USING_TIMER3
60 static _timer_t timer3 = {.name = "timer3" };
61 #endif /* BSP_USING_TIMER3 */
62 
63 static _timer_t *_timer_obj[] = {
64 #ifdef BSP_USING_TIMER0
65         &timer0,
66 #endif  /* BSP_USING_TIMER0 */
67 #ifdef BSP_USING_TIMER1
68         &timer1,
69 #endif /* BSP_USING_TIMER1 */
70 #ifdef BSP_USING_TIMER2
71         &timer2,
72 #endif  /* BSP_USING_TIMER2 */
73 #ifdef BSP_USING_TIMER3
74         &timer3,
75 #endif /* BSP_USING_TIMER3 */
76 };
77 
_hwtmr_isr(alarm_id_t id,void * user_data)78 static int64_t _hwtmr_isr(alarm_id_t id, void *user_data)
79 {
80     _timer_t *_tmr = rt_container_of(id, _timer_t, alarm_id);
81     rt_device_hwtimer_isr(&_tmr->timer);
82     return RT_TRUE;
83 }
84 
_repeat_timer_isr(struct repeating_timer * t)85 static bool _repeat_timer_isr(struct repeating_timer *t)
86 {
87     _timer_t *_tmr = rt_container_of(t, _timer_t, repeat_timer);
88     rt_device_hwtimer_isr(&_tmr->timer);
89     return RT_TRUE;
90 }
91 
_hwtimer_init(rt_hwtimer_t * timer,rt_uint32_t state)92 static void _hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
93 {
94 }
95 
_hwtimer_start(rt_hwtimer_t * timer,rt_uint32_t cnt,rt_hwtimer_mode_t mode)96 static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
97 {
98     _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
99 
100     if(mode == HWTIMER_MODE_ONESHOT)
101         _tmr->alarm_id = add_alarm_in_us(cnt, _hwtmr_isr, RT_NULL, RT_TRUE);
102     else
103         add_repeating_timer_us(cnt, _repeat_timer_isr, RT_NULL, &_tmr->repeat_timer);
104 
105     return RT_EOK;
106 }
107 
_hwtimer_stop(rt_hwtimer_t * timer)108 static void _hwtimer_stop(rt_hwtimer_t *timer)
109 {
110     _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
111     if(timer->mode == HWTIMER_MODE_ONESHOT)
112         cancel_alarm(_tmr->alarm_id);
113     else
114         cancel_repeating_timer(&_tmr->repeat_timer);
115 }
116 
_hwtimer_count_get(rt_hwtimer_t * timer)117 static rt_uint32_t _hwtimer_count_get(rt_hwtimer_t *timer)
118 {
119     _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
120 
121     return timer_hw->alarm[_tmr->alarm_id];
122 }
123 
_hwtimer_control(rt_hwtimer_t * timer,rt_uint32_t cmd,void * args)124 static rt_err_t _hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
125 {
126     rt_err_t err = RT_EOK;
127     _timer_t *_tmr = rt_container_of(timer, _timer_t, timer);
128 
129     switch (cmd)
130     {
131     case HWTIMER_CTRL_FREQ_SET:
132         err = -RT_ERROR;
133         break;
134     case HWTIMER_CTRL_INFO_GET:
135         *(rt_hwtimer_t*)args = _tmr->timer;
136         break;
137     case HWTIMER_CTRL_MODE_SET:
138         _tmr->timer.mode = *(rt_uint32_t*)args;
139         break;
140     case HWTIMER_CTRL_STOP:
141         _hwtimer_stop(timer);
142         break;
143     }
144 
145     return err;
146 }
147 
rt_hw_hwtimer_init(void)148 int rt_hw_hwtimer_init(void)
149 {
150     int ret = RT_EOK;
151 
152     for (uint32_t i = 0; i < sizeof(_timer_obj) / sizeof(_timer_obj[0]); i++)
153     {
154         _timer_obj[i]->timer.info = &_hwtimer_info;
155         _timer_obj[i]->timer.ops = &_hwtimer_ops;
156         ret = rt_device_hwtimer_register(&_timer_obj[i]->timer, _timer_obj[i]->name, _timer_obj[i]);
157         if (ret != RT_EOK)
158         {
159             LOG_E("%s register failed", _timer_obj[i]->name);
160         }
161     }
162 
163     return ret;
164 }
165 
166 INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
167 #endif /* BSP_USING_HWTIMER */
168