1 /*
2  * Copyright (c) 2006-2025, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-11-21     chenyingchun first version
9  */
10 #include <rtthread.h>
11 #include <rtdevice.h>
12 #include <board.h>
13 #include <nrfx_timer.h>
14 
15 #ifdef SOFTDEVICE_PRESENT
16 #ifdef BSP_USING_TIM0
17 #error "TIMER0 cannot be used when SOFTDEVICE has been used."
18 #endif
19 #endif
20 
21 #ifdef BSP_USING_TIM
22 
23 #define LOG_TAG             "drv.hwtimer"
24 #define DBG_LVL              DBG_INFO
25 #include <rtdbg.h>
26 
27 #ifdef RT_USING_HWTIMER
28 
29 #ifndef TIM_DEV_INFO_CONFIG
30 /* maxfreq and minfreq unit is HZ */
31 #define TIM_DEV_INFO_CONFIG                     \
32     {                                           \
33         .maxfreq = 16000000,                    \
34         .minfreq = 31250,                       \
35         .maxcnt  = 0xFFFFFFFF,                  \
36         .cntmode = HWTIMER_CNTMODE_UP,          \
37     }
38 #endif
39 
40 typedef struct
41 {
42     nrfx_timer_t            timer_inst;
43     nrfx_timer_config_t     timer_cfg;
44     nrf_timer_cc_channel_t  cc_channel;
45 }nrf5x_timer_info_t;
46 
47 struct nrf5x_hwtimer
48 {
49     rt_hwtimer_t            timer_device;
50     nrf5x_timer_info_t      timer_info;
51     char                    *name;
52 };
53 
54 static struct nrf5x_hwtimer nrf5x_hwtimer_obj[] =
55 {
56 #ifdef BSP_USING_TIM0
57     {
58        .timer_info.timer_inst = NRFX_TIMER_INSTANCE(0),
59        .timer_info.timer_cfg  = NRFX_TIMER_DEFAULT_CONFIG,
60        .timer_info.cc_channel = NRF_TIMER_CC_CHANNEL0,
61        .name                  = "timer0",
62     },
63 #endif
64 
65 #ifdef BSP_USING_TIM1
66     {
67        .timer_info.timer_inst = NRFX_TIMER_INSTANCE(1),
68        .timer_info.timer_cfg  = NRFX_TIMER_DEFAULT_CONFIG,
69        .timer_info.cc_channel = NRF_TIMER_CC_CHANNEL1,
70        .name                  = "timer1",
71     },
72 #endif
73 
74 #ifdef BSP_USING_TIM2
75      {
76         .timer_info.timer_inst = NRFX_TIMER_INSTANCE(2),
77         .timer_info.timer_cfg  = NRFX_TIMER_DEFAULT_CONFIG,
78         .timer_info.cc_channel = NRF_TIMER_CC_CHANNEL2,
79         .name                  = "timer2",
80      },
81 #endif
82 
83 #ifdef BSP_USING_TIM3
84      {
85         .timer_info.timer_inst = NRFX_TIMER_INSTANCE(3),
86         .timer_info.timer_cfg  = NRFX_TIMER_DEFAULT_CONFIG,
87         .timer_info.cc_channel = NRF_TIMER_CC_CHANNEL3,
88         .name                  = "timer3",
89      },
90 #endif
91 
92 #ifdef BSP_USING_TIM4
93      {
94         .timer_info.timer_inst = NRFX_TIMER_INSTANCE(4),
95         .timer_info.timer_cfg  = NRFX_TIMER_DEFAULT_CONFIG,
96         .timer_info.cc_channel = NRF_TIMER_CC_CHANNEL4,
97         .name                  = "timer4",
98      }
99 #endif
100 };
101 
timer_callback(nrf_timer_event_t event_type,void * p_context)102 static void timer_callback(nrf_timer_event_t event_type, void* p_context)
103 {
104     rt_hwtimer_t       *timer_device = (struct rt_hwtimer_device *)p_context;
105 
106     /* no matter what event_type is(NRF_TIMER_EVENT_COMPARE0 or others), call same function "rt_device_hwtimer_isr" */
107     LOG_D("timer_callback event_type = %d, inst_id = %d, cc conunt = %d\r\n",
108            event_type, timer_info->timer_inst.instance_id, timer_info->timer_inst.cc_channel_count);
109     rt_device_hwtimer_isr(timer_device);
110 }
111 
timer_init(struct rt_hwtimer_device * timer,rt_uint32_t state)112 static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
113 {
114     nrf5x_timer_info_t *timer_info   = RT_NULL;
115     nrfx_timer_config_t *timer_cfg   = RT_NULL;
116 
117     RT_ASSERT(timer != RT_NULL);
118     if (state)
119     {
120         timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
121         timer_cfg  = &(timer_info->timer_cfg);
122         timer_cfg->bit_width = NRF_TIMER_BIT_WIDTH_32;
123         timer_cfg->p_context = timer;
124 
125         nrfx_timer_init(&(timer_info->timer_inst), timer_cfg, timer_callback);
126     }
127 }
128 
timer_start(rt_hwtimer_t * timer,rt_uint32_t t,rt_hwtimer_mode_t opmode)129 static rt_err_t timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode)
130 {
131     nrf5x_timer_info_t *timer_info   = RT_NULL;
132     nrf_timer_short_mask_t mask = NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK;
133 
134     RT_ASSERT(timer != RT_NULL);
135 
136     timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
137 
138     if (opmode == HWTIMER_MODE_ONESHOT)
139     {
140         /* means TIMER_SHORTS_COMPARE0_STOP_Msk or TIMER_SHORTS_COMPARE1_STOP_Msk ..., according to cc_channel. */
141         mask = (nrf_timer_short_mask_t)(1 << (timer_info->cc_channel + 8));
142     }
143     else
144     {
145         /* means TIMER_SHORTS_COMPARE0_CLEAR_Msk or TIMER_SHORTS_COMPARE1_CLEAR_Msk ..., according to cc_channel. */
146         mask = (nrf_timer_short_mask_t)(1 << timer_info->cc_channel);
147     }
148 
149     nrfx_timer_extended_compare(&(timer_info->timer_inst), timer_info->cc_channel, t, mask, true);
150     nrfx_timer_enable(&(timer_info->timer_inst));
151     return RT_EOK;
152 }
153 
timer_stop(rt_hwtimer_t * timer)154 static void timer_stop(rt_hwtimer_t *timer)
155 {
156     nrf5x_timer_info_t *timer_info = RT_NULL;
157 
158     RT_ASSERT(timer != RT_NULL);
159 
160     timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
161 
162     nrfx_timer_disable(&(timer_info->timer_inst));
163 
164     /* set time count register to zero*/
165     nrfx_timer_clear(&(timer_info->timer_inst));
166 }
167 
frequency_convert(rt_uint32_t freq)168 static nrf_timer_frequency_t frequency_convert(rt_uint32_t freq)
169 {
170     nrf_timer_frequency_t frequency = NRF_TIMER_FREQ_1MHz;
171     switch (freq)
172     {
173         case 16000000:
174         {
175             frequency = NRF_TIMER_FREQ_16MHz;
176             break;
177         }
178 
179         case 8000000:
180         {
181             frequency = NRF_TIMER_FREQ_8MHz;
182             break;
183         }
184 
185         case 2000000:
186         {
187             frequency = NRF_TIMER_FREQ_2MHz;
188             break;
189         }
190 
191         case 1000000:
192         {
193             frequency = NRF_TIMER_FREQ_1MHz;
194             break;
195         }
196 
197         case 500000:
198         {
199             frequency = NRF_TIMER_FREQ_500kHz;
200             break;
201         }
202 
203         case 250000:
204         {
205             frequency = NRF_TIMER_FREQ_250kHz;
206             break;
207         }
208 
209         case 125000:
210         {
211             frequency = NRF_TIMER_FREQ_125kHz;
212             break;
213         }
214 
215          case 62500:
216         {
217             frequency = NRF_TIMER_FREQ_62500Hz;
218             break;
219         }
220 
221         case 31250:
222         {
223             frequency = NRF_TIMER_FREQ_31250Hz;
224             break;
225         }
226 
227         default:
228         {
229             break;
230         }
231     }
232 
233     return frequency;
234 }
235 
timer_ctrl(rt_hwtimer_t * timer,rt_uint32_t cmd,void * arg)236 static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
237 {
238     rt_err_t result = RT_EOK;
239     nrf5x_timer_info_t *timer_info = RT_NULL;
240     nrfx_timer_t *timer_inst = RT_NULL;
241 
242     RT_ASSERT(timer != RT_NULL);
243     RT_ASSERT(arg != RT_NULL);
244 
245     timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
246     timer_inst = &(timer_info->timer_inst);
247 
248     switch (cmd)
249     {
250         case HWTIMER_CTRL_FREQ_SET:
251         {
252             rt_uint32_t freq;
253             /* set timer frequence */
254             freq = *((rt_uint32_t *)arg);
255 
256             nrf_timer_frequency_set(timer_inst->p_reg, frequency_convert(freq));
257             break;
258         }
259         default:
260         {
261             result = -RT_ENOSYS;
262             break;
263         }
264 
265     }
266 
267     return result;
268 }
269 
timer_counter_get(rt_hwtimer_t * timer)270 static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer)
271 {
272     rt_uint32_t count = 0;
273     nrf5x_timer_info_t *timer_info = RT_NULL;
274 
275     RT_ASSERT(timer != RT_NULL);
276 
277     timer_info = (nrf5x_timer_info_t *)timer->parent.user_data;
278 
279     /* capture method will copy the current counter register to the specified cc channel (here is NRF_TIMER_CC_CHANNEL5). */
280     /* the specified cc channel cannot be same with the already used cc channels */
281     count = nrfx_timer_capture(&(timer_info->timer_inst), NRF_TIMER_CC_CHANNEL5);
282     return count;
283 }
284 
285 static const struct rt_hwtimer_info _info = TIM_DEV_INFO_CONFIG;
286 static const struct rt_hwtimer_ops _ops =
287 {
288     .init = timer_init,
289     .start = timer_start,
290     .stop = timer_stop,
291     .count_get = timer_counter_get,
292     .control = timer_ctrl,
293 };
294 
nrf5x_hwtimer_init(void)295 static int nrf5x_hwtimer_init(void)
296 {
297     int i = 0;
298     int result = RT_EOK;
299 
300     for (i = 0; i < sizeof(nrf5x_hwtimer_obj) / sizeof(nrf5x_hwtimer_obj[0]); i++)
301     {
302         nrf5x_hwtimer_obj[i].timer_device.info = &_info;
303         nrf5x_hwtimer_obj[i].timer_device.ops  = &_ops;
304         if (rt_device_hwtimer_register(&nrf5x_hwtimer_obj[i].timer_device, nrf5x_hwtimer_obj[i].name, &nrf5x_hwtimer_obj[i].timer_info) == RT_EOK)
305         {
306             LOG_D("%s register success", nrf5x_hwtimer_obj[i].name);
307         }
308         else
309         {
310             LOG_E("%s register failed", nrf5x_hwtimer_obj[i].name);
311             result = -RT_ERROR;
312         }
313     }
314 
315     return result;
316 }
317 INIT_BOARD_EXPORT(nrf5x_hwtimer_init);
318 
319 #endif /* RT_USING_HWTIMER */
320 #endif /* BSP_USING_TIM */
321 
322