1 /*
2  * Copyright (c) 2020-2021, Bluetrum Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author            Notes
8  * 2021-01-22     greedyhao         first version
9  */
10 
11 #include "board.h"
12 #ifdef BSP_USING_TIM
13 #include "tim_config.h"
14 
15 //#define DRV_DEBUG
16 #define LOG_TAG             "drv.hwtimer"
17 #include <drv_log.h>
18 
19 #ifdef RT_USING_HWTIMER
20 
21 enum
22 {
23 #ifdef BSP_USING_TIM1
24     TIM1_INDEX,
25 #endif
26 #ifdef BSP_USING_TIM2
27     TIM2_INDEX,
28 #endif
29 #ifdef BSP_USING_TIM3
30     TIM3_INDEX,
31 #endif
32 #ifdef BSP_USING_TIM4
33     TIM4_INDEX,
34 #endif
35 #ifdef BSP_USING_TIM5
36     TIM5_INDEX,
37 #endif
38 };
39 
40 struct ab32_hwtimer
41 {
42     rt_hwtimer_t time_device;
43     hal_sfr_t     tim_handle;
44     char *name;
45     irq_type tim_irqn;
46 };
47 
48 static struct ab32_hwtimer ab32_hwtimer_obj[] =
49 {
50 #ifdef BSP_USING_TIM1
51     TIM1_CONFIG,
52 #endif
53 
54 #ifdef BSP_USING_TIM2
55     TIM2_CONFIG,
56 #endif
57 
58 #ifdef BSP_USING_TIM3
59     TIM3_CONFIG,
60 #endif
61 
62 #ifdef BSP_USING_TIM4
63     TIM4_CONFIG,
64 #endif
65 
66 #ifdef BSP_USING_TIM5
67     TIM5_CONFIG,
68 #endif
69 };
70 
71 rt_section(".irq.timer")
_rt_device_hwtimer_isr(rt_hwtimer_t * timer)72 static void _rt_device_hwtimer_isr(rt_hwtimer_t *timer)
73 {
74     RT_ASSERT(timer != RT_NULL);
75 
76     timer->overflow ++;
77 
78     if (timer->cycles != 0)
79     {
80         timer->cycles --;
81     }
82 
83     if (timer->cycles == 0)
84     {
85         timer->cycles = timer->reload;
86 
87         if (timer->mode == HWTIMER_MODE_ONESHOT)
88         {
89             if (timer->ops->stop != RT_NULL)
90             {
91                 timer->ops->stop(timer);
92             }
93         }
94 
95         if (timer->parent.rx_indicate != RT_NULL)
96         {
97             timer->parent.rx_indicate(&timer->parent, sizeof(struct rt_hwtimerval));
98         }
99     }
100 }
101 
timer_init(struct rt_hwtimer_device * timer,rt_uint32_t state)102 static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
103 {
104     rt_uint32_t prescaler_value = 0;
105     hal_sfr_t tim = RT_NULL;
106     struct ab32_hwtimer *tim_device = RT_NULL;
107 
108     RT_ASSERT(timer != RT_NULL);
109     tim = (hal_sfr_t)timer->parent.user_data;
110 
111     if (state)
112     {
113         tim_device = (struct ab32_hwtimer *)timer;
114 
115         if (timer->info->cntmode != HWTIMER_CNTMODE_UP)
116         {
117             LOG_E("Only support HWTIMER_CNTMODE_UP!");
118         }
119 
120         /* set tim int */
121         tim[TMRxCON] = BIT(7);
122 
123         LOG_D("%s init success", tim_device->name);
124     } else {
125         /* stop timer */
126         tim[TMRxCON] = 0;
127     }
128 }
129 
timer_start(rt_hwtimer_t * timer,rt_uint32_t t,rt_hwtimer_mode_t opmode)130 static rt_err_t timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode)
131 {
132     rt_err_t result = RT_EOK;
133     hal_sfr_t tim = RT_NULL;
134 
135     RT_ASSERT(timer != RT_NULL);
136 
137     tim = (hal_sfr_t)timer->parent.user_data;
138 
139     /* set tim cnt */
140     tim[TMRxCNT] = 0;
141     tim[TMRxPR] = t * (get_sysclk_nhz() / timer->freq) - 1;
142 
143     if (opmode != HWTIMER_MODE_PERIOD)
144     {
145         LOG_E("Opmode only support HWTIMER_MODE_PERIOD!");
146         return -RT_EINVAL;
147     }
148 
149     /* start timer */
150     tim[TMRxCON] |= BIT(0);
151 
152     return result;
153 }
154 
timer_stop(rt_hwtimer_t * timer)155 static void timer_stop(rt_hwtimer_t *timer)
156 {
157     hal_sfr_t tim = RT_NULL;
158 
159     RT_ASSERT(timer != RT_NULL);
160 
161     tim = (hal_sfr_t)timer->parent.user_data;
162 
163     /* stop timer */
164     tim[TMRxCON] &= ~BIT(0);
165 
166     /* set tim cnt */
167     tim[TMRxCNT] = 0;
168 }
169 
timer_ctrl(rt_hwtimer_t * timer,rt_uint32_t cmd,void * arg)170 static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
171 {
172     hal_sfr_t tim = RT_NULL;
173     rt_err_t result = RT_EOK;
174 
175     RT_ASSERT(timer != RT_NULL);
176     RT_ASSERT(arg != RT_NULL);
177 
178     tim = (hal_sfr_t)timer->parent.user_data;
179 
180     switch (cmd)
181     {
182     case HWTIMER_CTRL_FREQ_SET:
183     {
184     }
185     break;
186     default:
187     {
188         result = -RT_ENOSYS;
189     }
190     break;
191     }
192 
193     return result;
194 }
195 
timer_counter_get(rt_hwtimer_t * timer)196 static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer)
197 {
198     hal_sfr_t tim = RT_NULL;
199 
200     RT_ASSERT(timer != RT_NULL);
201 
202     tim = (hal_sfr_t)timer->parent.user_data;
203 
204     return tim[TMRxCNT] / (get_sysclk_nhz() / timer->freq);
205 }
206 
207 static const struct rt_hwtimer_info _info = TIM_DEV_INFO_CONFIG;
208 
209 static const struct rt_hwtimer_ops _ops =
210 {
211     .init = timer_init,
212     .start = timer_start,
213     .stop = timer_stop,
214     .count_get = timer_counter_get,
215     .control = timer_ctrl,
216 };
217 
218 #if defined(BSP_USING_TIM2) || defined(BSP_USING_TIM4) || defined(BSP_USING_TIM5)
219 rt_section(".irq.timer")
timer2_4_5_isr(int vector,void * param)220 void timer2_4_5_isr(int vector, void *param)
221 {
222     rt_interrupt_enter();
223 #ifdef BSP_USING_TIM2
224     if (ab32_hwtimer_obj[TIM2_INDEX].tim_handle[TMRxCON] != 0) {
225         ab32_hwtimer_obj[TIM2_INDEX].tim_handle[TMRxCPND] = BIT(9);
226         _rt_device_hwtimer_isr(&ab32_hwtimer_obj[TIM2_INDEX].time_device);
227     }
228 #endif
229 #ifdef BSP_USING_TIM4
230     if (ab32_hwtimer_obj[TIM4_INDEX].tim_handle[TMRxCON] != 0) {
231         ab32_hwtimer_obj[TIM4_INDEX].tim_handle[TMRxCPND] = BIT(9);
232         _rt_device_hwtimer_isr(&ab32_hwtimer_obj[TIM4_INDEX].time_device);
233     }
234 #endif
235 #ifdef BSP_USING_TIM5
236     if (ab32_hwtimer_obj[TIM5_INDEX].tim_handle[TMRxCON] != 0) {
237         ab32_hwtimer_obj[TIM5_INDEX].tim_handle[TMRxCPND] = BIT(9);
238         _rt_device_hwtimer_isr(&ab32_hwtimer_obj[TIM5_INDEX].time_device);
239     }
240 #endif
241     rt_interrupt_leave();
242 }
243 #endif
244 
245 #ifdef BSP_USING_TIM3
246 rt_section(".irq.timer")
timer3_isr(int vector,void * param)247 void timer3_isr(int vector, void *param)
248 {
249     rt_interrupt_enter();
250     ab32_hwtimer_obj[TIM3_INDEX].tim_handle[TMRxCPND] = BIT(9);
251     _rt_device_hwtimer_isr(&ab32_hwtimer_obj[TIM3_INDEX].time_device);
252     rt_interrupt_leave();
253 }
254 #endif
255 
256 #ifdef BSP_USING_TIM1
257 rt_section(".irq.timer")
timer1_isr(int vector,void * param)258 void timer1_isr(int vector, void *param)
259 {
260     rt_interrupt_enter();
261     ab32_hwtimer_obj[TIM1_INDEX].tim_handle[TMRxCPND] = BIT(9);
262     _rt_device_hwtimer_isr(&ab32_hwtimer_obj[TIM1_INDEX].time_device);
263     rt_interrupt_leave();
264 }
265 #endif
266 
ab32_hwtimer_init(void)267 static int ab32_hwtimer_init(void)
268 {
269     int i = 0;
270     int result = RT_EOK;
271 
272     for (i = 0; i < sizeof(ab32_hwtimer_obj) / sizeof(ab32_hwtimer_obj[0]); i++)
273     {
274         ab32_hwtimer_obj[i].time_device.info = &_info;
275         ab32_hwtimer_obj[i].time_device.ops  = &_ops;
276         if (rt_device_hwtimer_register(&ab32_hwtimer_obj[i].time_device, ab32_hwtimer_obj[i].name, (void *)ab32_hwtimer_obj[i].tim_handle) == RT_EOK)
277         {
278             LOG_D("%s register success", ab32_hwtimer_obj[i].name);
279         }
280         else
281         {
282             LOG_E("%s register failed", ab32_hwtimer_obj[i].name);
283             result = -RT_ERROR;
284         }
285     }
286 
287 #ifdef BSP_USING_TIM1
288     rt_hw_interrupt_install(IRQ_TMR1_VECTOR, timer1_isr, RT_NULL, "t1_isr");
289 #endif
290 #if defined(BSP_USING_TIM2) || defined(BSP_USING_TIM4) || defined(BSP_USING_TIM5)
291     rt_hw_interrupt_install(IRQ_TMR2_4_5_VECTOR, timer2_4_5_isr, RT_NULL, "t245_isr");
292 #endif
293 #ifdef BSP_USING_TIM3
294     rt_hw_interrupt_install(IRQ_IRRX_VECTOR, timer3_isr, RT_NULL, "t3_isr");
295 #endif
296 
297     return result;
298 }
299 INIT_BOARD_EXPORT(ab32_hwtimer_init);
300 
301 #endif /* RT_USING_HWTIMER */
302 #endif /* BSP_USING_TIM */
303