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 */
0 commit comments