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-04-01 wcx1024979076 first version
9 */
10
11 #include "drv_hwtimer.h"
12 #include <rtthread.h>
13 #include <rtdevice.h>
14
15 #ifdef BSP_USING_HWTIMER
16
17 #define DBG_LEVEL DBG_LOG
18 #include <rtdbg.h>
19 #define LOG_TAG "DRV.HWTIMER"
20
21
22 typedef struct _gptimer
23 {
24 const char *name;
25 rt_hwtimer_t timer;
26 struct bflb_device_s *bflb_timer;
27 } _gptimer_t;
28
29 static void _hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state);
30 static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode);
31 static void _hwtimer_stop(rt_hwtimer_t *timer);
32 static rt_uint32_t _hwtimer_count_get(rt_hwtimer_t *timer);
33 static rt_err_t _hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
34
35 static void _hwtmr_isr(_gptimer_t *gptmr);
36
37 static const struct rt_hwtimer_ops _hwtimer_ops = {
38 .init = _hwtimer_init,
39 .start = _hwtimer_start,
40 .stop = _hwtimer_stop,
41 .count_get = _hwtimer_count_get,
42 .control = _hwtimer_control
43 };
44
45 static const struct rt_hwtimer_info _hwtimer_info = {
46 .maxfreq = 1000000UL,
47 .minfreq = 1000000UL,
48 .maxcnt = 0xFFFFFFFFUL,
49 .cntmode = HWTIMER_MODE_PERIOD
50 };
51
52 #ifdef BSP_USING_TIMER0
53 static _gptimer_t timer0 = {.name = "timer0"};
54 #endif /* BSP_USING_TIMER0 */
55 #ifdef BSP_USING_TIMER1
56 static _gptimer_t timer1 = {.name = "timer1" };
57 #endif /* BSP_USING_TIMER1 */
58
59 static _gptimer_t *s_gptimers[] = {
60 #ifdef BSP_USING_TIMER0
61 &timer0,
62 #endif /* BSP_USING_TIMER0 */
63 #ifdef BSP_USING_TIMER1
64 &timer1,
65 #endif /* BSP_USING_TIMER1 */
66 };
67
68 #ifdef BSP_USING_TIMER0
timer0_isr(int irq,void * arg)69 void timer0_isr(int irq, void *arg)
70 {
71 _hwtmr_isr(&timer0);
72 }
73 #endif /* BSP_USING_TIMER0 */
74
75 #ifdef BSP_USING_TIMER1
timer1_isr(int irq,void * arg)76 void timer1_isr(int irq, void *arg)
77 {
78 _hwtmr_isr(&timer1);
79 }
80 #endif /* BSP_USING_TIMER1 */
81
_hwtmr_isr(_gptimer_t * timer)82 static void _hwtmr_isr(_gptimer_t *timer)
83 {
84 bool hwtmr_stat = bflb_timer_get_compint_status(timer->bflb_timer, TIMER_COMP_ID_0);
85 if (hwtmr_stat)
86 {
87 rt_device_hwtimer_isr(&timer->timer);
88 bflb_timer_compint_clear(timer->bflb_timer, TIMER_COMP_ID_0);
89 }
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 _gptimer_t *_gptmr = (_gptimer_t*)timer->parent.user_data;
95
96 struct bflb_timer_config_s cfg;
97 cfg.counter_mode = TIMER_COUNTER_MODE_PROLOAD;
98 cfg.clock_source = TIMER_CLKSRC_XTAL;
99 cfg.clock_div = 40;
100 cfg.trigger_comp_id = TIMER_COMP_ID_0;
101 cfg.comp0_val = 0;
102 cfg.comp1_val = 0;
103 cfg.comp2_val = 0;
104 cfg.preload_val = 0;
105
106 bflb_timer_init(_gptmr->bflb_timer, &cfg);
107 }
108
_hwtimer_start(rt_hwtimer_t * timer,rt_uint32_t cnt,rt_hwtimer_mode_t mode)109 static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
110 {
111 _gptimer_t *_gptmr = (_gptimer_t*) timer->parent.user_data;
112
113 struct bflb_timer_config_s cfg;
114 if(mode == HWTIMER_MODE_ONESHOT)
115 cfg.counter_mode = TIMER_COUNTER_MODE_UP;
116 else
117 cfg.counter_mode = TIMER_COUNTER_MODE_PROLOAD;
118 cfg.clock_source = TIMER_CLKSRC_XTAL;
119 cfg.clock_div = 40;
120 cfg.trigger_comp_id = TIMER_COMP_ID_0;
121 cfg.comp0_val = cnt;
122 cfg.comp1_val = cnt;
123 cfg.comp2_val = cnt;
124 cfg.preload_val = 0;
125
126 bflb_timer_init(_gptmr->bflb_timer, &cfg);
127 bflb_irq_enable(_gptmr->bflb_timer->irq_num);
128 bflb_timer_start(_gptmr->bflb_timer);
129
130 return RT_EOK;
131 }
132
_hwtimer_stop(rt_hwtimer_t * timer)133 static void _hwtimer_stop(rt_hwtimer_t *timer)
134 {
135 _gptimer_t *_gptmr = (_gptimer_t*)timer->parent.user_data;
136 bflb_timer_stop(_gptmr->bflb_timer);
137 }
138
_hwtimer_count_get(rt_hwtimer_t * timer)139 static rt_uint32_t _hwtimer_count_get(rt_hwtimer_t *timer)
140 {
141 _gptimer_t *_gptmr = (_gptimer_t*)timer->parent.user_data;
142
143 rt_uint32_t current_cnt = bflb_timer_get_countervalue(_gptmr->bflb_timer);
144
145 return current_cnt;
146 }
147
_hwtimer_control(rt_hwtimer_t * timer,rt_uint32_t cmd,void * args)148 static rt_err_t _hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
149 {
150 rt_err_t err = RT_EOK;
151 _gptimer_t *_gptmr = (_gptimer_t*) timer->parent.user_data;
152 switch (cmd)
153 {
154 case HWTIMER_CTRL_FREQ_SET:
155 err = -RT_ERROR;
156 break;
157 case HWTIMER_CTRL_INFO_GET:
158 *(rt_hwtimer_t*)args = _gptmr->timer;
159 break;
160 case HWTIMER_CTRL_MODE_SET:
161 _gptmr->timer.mode = *(rt_uint32_t*)args;
162 break;
163 case HWTIMER_CTRL_STOP:
164 bflb_timer_stop(_gptmr->bflb_timer);
165 break;
166 }
167
168 return err;
169 }
170
171
rt_hw_hwtimer_init(void)172 int rt_hw_hwtimer_init(void)
173 {
174 int ret = RT_EOK;
175 for (uint32_t i = 0; i < sizeof(s_gptimers) / sizeof(s_gptimers[0]); i++)
176 {
177 s_gptimers[i]->timer.info = &_hwtimer_info;
178 s_gptimers[i]->timer.ops = &_hwtimer_ops;
179 s_gptimers[i]->bflb_timer = bflb_device_get_by_name(s_gptimers[i]->name);
180 ret = rt_device_hwtimer_register(&s_gptimers[i]->timer, s_gptimers[i]->name, s_gptimers[i]);
181 if (ret != RT_EOK)
182 {
183 LOG_E("%s register failed", s_gptimers[i]->name);
184 }
185 }
186
187 #ifdef BSP_USING_TIMER0
188 bflb_irq_attach(bflb_device_get_by_name("timer0")->irq_num, timer0_isr, NULL);
189 #endif /* BSP_USING_TIMER0 */
190
191 #ifdef BSP_USING_TIMER1
192 bflb_irq_attach(bflb_device_get_by_name("timer1")->irq_num, timer1_isr, NULL);
193 #endif /* BSP_USING_TIMER1 */
194
195 return ret;
196 }
197
198 INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
199 #endif /* BSP_USING_HWTIMER */
200