Skip to content

Commit 3bc5ffb

Browse files
authored
Merge pull request #5297 from chenyingchun0312/fea_nrf5x_hwtimer
[bsp/nrf5x] add hwtimer driver
2 parents 6a6b43f + 0903003 commit 3bc5ffb

File tree

5 files changed

+387
-12
lines changed

5 files changed

+387
-12
lines changed

bsp/nrf5x/docs/images/nrf52832.png

730 KB
Loading

bsp/nrf5x/libraries/drivers/SConscript

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ if GetDepend(['BSP_USING_WDT']):
3939

4040
if GetDepend(['BSP_USING_ONCHIP_RTC']):
4141
src += ['drv_rtc.c']
42+
43+
if GetDepend(['BSP_USING_TIM']):
44+
src += ['drv_hwtimer.c']
4245

4346
path = [cwd]
4447

Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
/*
2+
* Copyright (c) 2006-2021, 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+
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+
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+
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+
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+
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+
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+
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+
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+

bsp/nrf5x/nrf52832/README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ PCA10040-nRF52832是Nordic 官方的开发板,搭载nRF52832 芯片,基于AR
1414

1515
开发板外观如下图所示
1616

17-
![](../docs/images/nrf52832.jpg)
17+
![](../docs/images/nrf52832.png)
1818

1919
PCA10040-nrf52832开发板常用 **板载资源** 如下:
2020

@@ -34,17 +34,17 @@ PCA10040-nrf52832开发板常用 **板载资源** 如下:
3434

3535
本 BSP 目前对外设的支持情况如下:
3636

37-
| **片上外设** | **支持情况** | **备注** |
38-
| :----------- | :----------: | :------: |
39-
| GPIO | 支持 | GPION |
40-
| UART | 支持 | UART0 |
41-
| PWM | 支持 | 支持 |
42-
| SPI | 支持 | 支持 |
43-
| RTC | 支持 | |
44-
| ADC | 支持 | |
45-
| | | |
46-
| | | |
47-
| | | |
37+
| **片上外设** | **支持情况** | **备注** |
38+
| :----------- | :----------: | :-----------: |
39+
| GPIO | 支持 | GPION |
40+
| UART | 支持 | UART0 |
41+
| PWM | 支持 | 支持 |
42+
| SPI | 支持 | 支持 |
43+
| RTC | 支持 | |
44+
| ADC | 支持 | |
45+
| TIMER | 支持 | TIMER0~TIMER4 |
46+
| | | |
47+
| | | |
4848

4949

5050

0 commit comments

Comments
 (0)