Skip to content

Commit c224278

Browse files
imi415mysterywolf
authored andcommitted
[bsp][nxp/mcxn] hwtimer: initial support for MRT.
This patch adds support for hwtimer using MRT0 instance which simulates 4 independent timers. The frequency is fixed to AHB bus frequency and not adjustable. Signed-off-by: Yilin Sun <[email protected]>
1 parent 1b81128 commit c224278

File tree

2 files changed

+203
-0
lines changed

2 files changed

+203
-0
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*
2+
* Copyright (c) 2006-2024, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2024-02-21 Yilin Sun Initial revision.
9+
*/
10+
11+
#include "drv_hwtimer.h"
12+
13+
#ifdef BSP_USING_HWTIMER
14+
15+
#include "fsl_mrt.h"
16+
17+
typedef struct
18+
{
19+
rt_hwtimer_t timer_device;
20+
mrt_chnl_t channel;
21+
char *name;
22+
} mcx_hwtimer_obj_t;
23+
24+
static inline rt_err_t mcx_hwtimer_mode_set(mcx_hwtimer_obj_t *handle, rt_hwtimer_mode_t mode)
25+
{
26+
mrt_timer_mode_t mrt_mode;
27+
switch (mode)
28+
{
29+
case HWTIMER_MODE_ONESHOT:
30+
mrt_mode = kMRT_OneShotMode;
31+
break;
32+
33+
case HWTIMER_MODE_PERIOD:
34+
mrt_mode = kMRT_RepeatMode;
35+
break;
36+
37+
default:
38+
return -RT_EINVAL;
39+
}
40+
41+
MRT_SetupChannelMode(MRT0, handle->channel, mrt_mode);
42+
43+
return RT_EOK;
44+
}
45+
46+
static void mcx_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
47+
{
48+
mrt_config_t mrt_config;
49+
MRT_GetDefaultConfig(&mrt_config);
50+
51+
MRT_Init(MRT0, &mrt_config);
52+
}
53+
54+
static rt_err_t mcx_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
55+
{
56+
rt_err_t ret = RT_EOK;
57+
58+
mcx_hwtimer_obj_t *handle = timer->parent.user_data;
59+
60+
MRT_StopTimer(MRT0, handle->channel);
61+
62+
ret = mcx_hwtimer_mode_set(handle, mode);
63+
if (ret != RT_EOK)
64+
{
65+
return ret;
66+
}
67+
68+
MRT_StartTimer(MRT0, handle->channel, cnt);
69+
MRT_EnableInterrupts(MRT0, handle->channel, kMRT_TimerInterruptEnable);
70+
71+
return ret;
72+
}
73+
74+
static void mcx_hwtimer_stop(rt_hwtimer_t *timer)
75+
{
76+
mcx_hwtimer_obj_t *handle = timer->parent.user_data;
77+
MRT_StopTimer(MRT0, handle->channel);
78+
MRT_DisableInterrupts(MRT0, handle->channel, kMRT_TimerInterruptEnable);
79+
}
80+
81+
static rt_uint32_t mcx_hwtimer_count_get(rt_hwtimer_t *timer)
82+
{
83+
mcx_hwtimer_obj_t *handle = timer->parent.user_data;
84+
85+
return MRT_GetCurrentTimerCount(MRT0, handle->channel);
86+
}
87+
88+
static rt_err_t mcx_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
89+
{
90+
rt_err_t ret = RT_EOK;
91+
92+
mcx_hwtimer_obj_t *handle = timer->parent.user_data;
93+
switch (cmd)
94+
{
95+
case HWTIMER_CTRL_STOP:
96+
mcx_hwtimer_stop(timer);
97+
break;
98+
99+
case HWTIMER_CTRL_MODE_SET:
100+
ret = mcx_hwtimer_mode_set(handle, *(rt_hwtimer_mode_t *)args);
101+
if (ret != RT_EOK)
102+
{
103+
return ret;
104+
}
105+
break;
106+
107+
default:
108+
return -RT_EINVAL;
109+
}
110+
111+
return RT_EOK;
112+
}
113+
114+
static mcx_hwtimer_obj_t mcx_hwtimer_list[] =
115+
{
116+
{ .name = "timer0", .channel = kMRT_Channel_0, },
117+
{ .name = "timer1", .channel = kMRT_Channel_1, },
118+
{ .name = "timer2", .channel = kMRT_Channel_2, },
119+
{ .name = "timer3", .channel = kMRT_Channel_3, },
120+
};
121+
122+
static struct rt_hwtimer_info mcx_hwtimer_info =
123+
{
124+
.cntmode = HWTIMER_CNTMODE_DW,
125+
.maxcnt = 0x00FFFFFF, /* 24bit counter */
126+
.minfreq = 150000000,
127+
.maxfreq = 150000000,
128+
};
129+
130+
static const struct rt_hwtimer_ops mcx_hwtimer_ops =
131+
{
132+
.init = mcx_hwtimer_init,
133+
.control = mcx_hwtimer_control,
134+
.start = mcx_hwtimer_start,
135+
.stop = mcx_hwtimer_stop,
136+
.count_get = mcx_hwtimer_count_get,
137+
};
138+
139+
int rt_hw_hwtimer_init(void)
140+
{
141+
/* MRT frequency is fixed to AHB clock */
142+
uint32_t mrt_freq = CLOCK_GetFreq(kCLOCK_BusClk);
143+
144+
mcx_hwtimer_info.minfreq = mrt_freq;
145+
mcx_hwtimer_info.maxfreq = mrt_freq;
146+
147+
for (uint8_t i = 0; i < ARRAY_SIZE(mcx_hwtimer_list); i++)
148+
{
149+
mcx_hwtimer_list[i].timer_device.info = &mcx_hwtimer_info;
150+
mcx_hwtimer_list[i].timer_device.ops = &mcx_hwtimer_ops;
151+
152+
rt_err_t ret = rt_device_hwtimer_register(&mcx_hwtimer_list[i].timer_device, mcx_hwtimer_list[i].name, &mcx_hwtimer_list[i]);
153+
if (ret != RT_EOK)
154+
{
155+
return ret;
156+
}
157+
}
158+
159+
EnableIRQ(MRT0_IRQn);
160+
161+
return RT_EOK;
162+
}
163+
164+
void MRT0_IRQHandler(void)
165+
{
166+
/* Get channel interrupt flags */
167+
uint32_t mrt_flag = MRT0->IRQ_FLAG;
168+
169+
/* Clear interrupt flags (W1C). */
170+
MRT0->IRQ_FLAG = mrt_flag;
171+
172+
for (uint8_t i = 0; i < 4; i++)
173+
{
174+
if (mrt_flag & (1U << i))
175+
{
176+
rt_device_hwtimer_isr(&mcx_hwtimer_list[i].timer_device);
177+
}
178+
}
179+
}
180+
181+
INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
182+
183+
#endif /* BSP_USING_HWTIMER */
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2006-2024, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2024-02-21 Yilin Sun Initial revision.
9+
*/
10+
11+
#ifndef __DRV_HWTIMER_H__
12+
#define __DRV_HWTIMER_H__
13+
14+
#include <rtthread.h>
15+
#include <rtdevice.h>
16+
17+
int rt_hw_hwtimer_init(void);
18+
19+
#endif /* __DRV_HWTIMER_H__ */
20+

0 commit comments

Comments
 (0)