1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017, 2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 #ifndef FSL_MRT_H_
9 #define FSL_MRT_H_
10 
11 #include "fsl_common.h"
12 
13 /*!
14  * @addtogroup mrt
15  * @{
16  */
17 
18 /*! @file */
19 
20 /*******************************************************************************
21  * Definitions
22  ******************************************************************************/
23 
24 /*! @name Driver version */
25 /*! @{ */
26 #define FSL_MRT_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) /*!< Version 2.0.3 */
27 /*! @} */
28 
29 /*! @brief List of MRT channels */
30 typedef enum _mrt_chnl
31 {
32     kMRT_Channel_0 = 0U, /*!< MRT channel number 0*/
33     kMRT_Channel_1,      /*!< MRT channel number 1 */
34     kMRT_Channel_2,      /*!< MRT channel number 2 */
35     kMRT_Channel_3       /*!< MRT channel number 3 */
36 } mrt_chnl_t;
37 
38 /*! @brief List of MRT timer modes */
39 typedef enum _mrt_timer_mode
40 {
41     kMRT_RepeatMode       = (0 << MRT_CHANNEL_CTRL_MODE_SHIFT), /*!< Repeat Interrupt mode */
42     kMRT_OneShotMode      = (1 << MRT_CHANNEL_CTRL_MODE_SHIFT), /*!< One-shot Interrupt mode */
43     kMRT_OneShotStallMode = (2 << MRT_CHANNEL_CTRL_MODE_SHIFT)  /*!< One-shot stall mode */
44 } mrt_timer_mode_t;
45 
46 /*! @brief List of MRT interrupts */
47 typedef enum _mrt_interrupt_enable
48 {
49     kMRT_TimerInterruptEnable = MRT_CHANNEL_CTRL_INTEN_MASK /*!< Timer interrupt enable*/
50 } mrt_interrupt_enable_t;
51 
52 /*! @brief List of MRT status flags */
53 typedef enum _mrt_status_flags
54 {
55     kMRT_TimerInterruptFlag = MRT_CHANNEL_STAT_INTFLAG_MASK, /*!< Timer interrupt flag */
56     kMRT_TimerRunFlag       = MRT_CHANNEL_STAT_RUN_MASK,     /*!< Indicates state of the timer */
57 } mrt_status_flags_t;
58 
59 /*!
60  * @brief MRT configuration structure
61  *
62  * This structure holds the configuration settings for the MRT peripheral. To initialize this
63  * structure to reasonable defaults, call the MRT_GetDefaultConfig() function and pass a
64  * pointer to your config structure instance.
65  *
66  * The config struct can be made const so it resides in flash
67  */
68 typedef struct _mrt_config
69 {
70     bool enableMultiTask; /*!< true: Timers run in multi-task mode; false: Timers run in hardware status mode */
71 } mrt_config_t;
72 
73 /*******************************************************************************
74  * API
75  ******************************************************************************/
76 
77 #if defined(__cplusplus)
78 extern "C" {
79 #endif
80 
81 /*!
82  * @name Initialization and deinitialization
83  * @{
84  */
85 
86 /*!
87  * @brief Ungates the MRT clock and configures the peripheral for basic operation.
88  *
89  * @note This API should be called at the beginning of the application using the MRT driver.
90  *
91  * @param base   Multi-Rate timer peripheral base address
92  * @param config Pointer to user's MRT config structure. If MRT has  MULTITASK bit field in
93  *               MODCFG reigster, param config is useless.
94  */
95 void MRT_Init(MRT_Type *base, const mrt_config_t *config);
96 
97 /*!
98  * @brief Gate the MRT clock
99  *
100  * @param base Multi-Rate timer peripheral base address
101  */
102 void MRT_Deinit(MRT_Type *base);
103 
104 /*!
105  * @brief Fill in the MRT config struct with the default settings
106  *
107  * The default values are:
108  * @code
109  *     config->enableMultiTask = false;
110  * @endcode
111  * @param config Pointer to user's MRT config structure.
112  */
MRT_GetDefaultConfig(mrt_config_t * config)113 static inline void MRT_GetDefaultConfig(mrt_config_t *config)
114 {
115     assert(config != NULL);
116 #if !(defined(FSL_FEATURE_MRT_HAS_NO_MODCFG_MULTITASK) && FSL_FEATURE_MRT_HAS_NO_MODCFG_MULTITASK)
117     /* Use hardware status operating mode */
118     config->enableMultiTask = false;
119 #endif
120 }
121 
122 /*!
123  * @brief Sets up an MRT channel mode.
124  *
125  * @param base    Multi-Rate timer peripheral base address
126  * @param channel Channel that is being configured.
127  * @param mode    Timer mode to use for the channel.
128  */
MRT_SetupChannelMode(MRT_Type * base,mrt_chnl_t channel,const mrt_timer_mode_t mode)129 static inline void MRT_SetupChannelMode(MRT_Type *base, mrt_chnl_t channel, const mrt_timer_mode_t mode)
130 {
131     assert((uint8_t)channel < (uint8_t)FSL_FEATURE_MRT_NUMBER_OF_CHANNELS);
132 
133     uint32_t reg = base->CHANNEL[channel].CTRL;
134 
135     /* Clear old value */
136     reg &= ~MRT_CHANNEL_CTRL_MODE_MASK;
137     /* Add the new mode */
138     reg |= (uint32_t)mode;
139 
140     base->CHANNEL[channel].CTRL = reg;
141 }
142 
143 /*! @}*/
144 
145 /*!
146  * @name Interrupt Interface
147  * @{
148  */
149 
150 /*!
151  * @brief Enables the MRT interrupt.
152  *
153  * @param base    Multi-Rate timer peripheral base address
154  * @param channel Timer channel number
155  * @param mask    The interrupts to enable. This is a logical OR of members of the
156  *                enumeration ::mrt_interrupt_enable_t
157  */
MRT_EnableInterrupts(MRT_Type * base,mrt_chnl_t channel,uint32_t mask)158 static inline void MRT_EnableInterrupts(MRT_Type *base, mrt_chnl_t channel, uint32_t mask)
159 {
160     assert((uint8_t)channel < (uint8_t)FSL_FEATURE_MRT_NUMBER_OF_CHANNELS);
161     base->CHANNEL[channel].CTRL |= mask;
162 }
163 
164 /*!
165  * @brief Disables the selected MRT interrupt.
166  *
167  * @param base    Multi-Rate timer peripheral base address
168  * @param channel Timer channel number
169  * @param mask    The interrupts to disable. This is a logical OR of members of the
170  *                enumeration ::mrt_interrupt_enable_t
171  */
MRT_DisableInterrupts(MRT_Type * base,mrt_chnl_t channel,uint32_t mask)172 static inline void MRT_DisableInterrupts(MRT_Type *base, mrt_chnl_t channel, uint32_t mask)
173 {
174     assert((uint8_t)channel < (uint8_t)FSL_FEATURE_MRT_NUMBER_OF_CHANNELS);
175     base->CHANNEL[channel].CTRL &= ~mask;
176 }
177 
178 /*!
179  * @brief Gets the enabled MRT interrupts.
180  *
181  * @param base    Multi-Rate timer peripheral base address
182  * @param channel Timer channel number
183  *
184  * @return The enabled interrupts. This is the logical OR of members of the
185  *         enumeration ::mrt_interrupt_enable_t
186  */
MRT_GetEnabledInterrupts(MRT_Type * base,mrt_chnl_t channel)187 static inline uint32_t MRT_GetEnabledInterrupts(MRT_Type *base, mrt_chnl_t channel)
188 {
189     assert((uint8_t)channel < (uint8_t)FSL_FEATURE_MRT_NUMBER_OF_CHANNELS);
190     return (base->CHANNEL[channel].CTRL & MRT_CHANNEL_CTRL_INTEN_MASK);
191 }
192 
193 /*! @}*/
194 
195 /*!
196  * @name Status Interface
197  * @{
198  */
199 
200 /*!
201  * @brief Gets the MRT status flags
202  *
203  * @param base    Multi-Rate timer peripheral base address
204  * @param channel Timer channel number
205  *
206  * @return The status flags. This is the logical OR of members of the
207  *         enumeration ::mrt_status_flags_t
208  */
MRT_GetStatusFlags(MRT_Type * base,mrt_chnl_t channel)209 static inline uint32_t MRT_GetStatusFlags(MRT_Type *base, mrt_chnl_t channel)
210 {
211     assert((uint8_t)channel < (uint8_t)FSL_FEATURE_MRT_NUMBER_OF_CHANNELS);
212     return (base->CHANNEL[channel].STAT & (MRT_CHANNEL_STAT_INTFLAG_MASK | MRT_CHANNEL_STAT_RUN_MASK));
213 }
214 
215 /*!
216  * @brief Clears the MRT status flags.
217  *
218  * @param base    Multi-Rate timer peripheral base address
219  * @param channel Timer channel number
220  * @param mask    The status flags to clear. This is a logical OR of members of the
221  *                enumeration ::mrt_status_flags_t
222  */
MRT_ClearStatusFlags(MRT_Type * base,mrt_chnl_t channel,uint32_t mask)223 static inline void MRT_ClearStatusFlags(MRT_Type *base, mrt_chnl_t channel, uint32_t mask)
224 {
225     assert((uint8_t)channel < (uint8_t)FSL_FEATURE_MRT_NUMBER_OF_CHANNELS);
226     base->CHANNEL[channel].STAT = (mask & MRT_CHANNEL_STAT_INTFLAG_MASK);
227 }
228 
229 /*! @}*/
230 
231 /*!
232  * @name Read and Write the timer period
233  * @{
234  */
235 
236 /*!
237  * @brief Used to update the timer period in units of count.
238  *
239  * The new value will be immediately loaded or will be loaded at the end of the current time
240  * interval. For one-shot interrupt mode the new value will be immediately loaded.
241  *
242  * @note User can call the utility macros provided in fsl_common.h to convert to ticks
243  *
244  * @param base          Multi-Rate timer peripheral base address
245  * @param channel       Timer channel number
246  * @param count         Timer period in units of ticks
247  * @param immediateLoad true: Load the new value immediately into the TIMER register;
248  *                      false: Load the new value at the end of current timer interval
249  */
250 void MRT_UpdateTimerPeriod(MRT_Type *base, mrt_chnl_t channel, uint32_t count, bool immediateLoad);
251 
252 /*!
253  * @brief Reads the current timer counting value.
254  *
255  * This function returns the real-time timer counting value, in a range from 0 to a
256  * timer period.
257  *
258  * @note User can call the utility macros provided in fsl_common.h to convert ticks to usec or msec
259  *
260  * @param base    Multi-Rate timer peripheral base address
261  * @param channel Timer channel number
262  *
263  * @return Current timer counting value in ticks
264  */
MRT_GetCurrentTimerCount(MRT_Type * base,mrt_chnl_t channel)265 static inline uint32_t MRT_GetCurrentTimerCount(MRT_Type *base, mrt_chnl_t channel)
266 {
267     assert((uint8_t)channel < (uint8_t)FSL_FEATURE_MRT_NUMBER_OF_CHANNELS);
268     return base->CHANNEL[channel].TIMER;
269 }
270 
271 /*! @}*/
272 
273 /*!
274  * @name Timer Start and Stop
275  * @{
276  */
277 
278 /*!
279  * @brief Starts the timer counting.
280  *
281  * After calling this function, timers load period value, counts down to 0 and
282  * depending on the timer mode it will either load the respective start value again or stop.
283  *
284  * @note User can call the utility macros provided in fsl_common.h to convert to ticks
285  *
286  * @param base    Multi-Rate timer peripheral base address
287  * @param channel Timer channel number.
288  * @param count   Timer period in units of ticks. Count can contain the LOAD bit, which control the force load feature.
289  */
MRT_StartTimer(MRT_Type * base,mrt_chnl_t channel,uint32_t count)290 static inline void MRT_StartTimer(MRT_Type *base, mrt_chnl_t channel, uint32_t count)
291 {
292     assert((uint8_t)channel < (uint8_t)FSL_FEATURE_MRT_NUMBER_OF_CHANNELS);
293     assert((uint32_t)(count & ~MRT_CHANNEL_INTVAL_LOAD_MASK) <= (uint32_t)MRT_CHANNEL_INTVAL_IVALUE_MASK);
294     /* Write the timer interval value */
295     base->CHANNEL[channel].INTVAL = count;
296 }
297 
298 /*!
299  * @brief Stops the timer counting.
300  *
301  * This function stops the timer from counting.
302  *
303  * @param base    Multi-Rate timer peripheral base address
304  * @param channel Timer channel number.
305  */
MRT_StopTimer(MRT_Type * base,mrt_chnl_t channel)306 static inline void MRT_StopTimer(MRT_Type *base, mrt_chnl_t channel)
307 {
308     assert((uint8_t)channel < (uint8_t)FSL_FEATURE_MRT_NUMBER_OF_CHANNELS);
309     /* Stop the timer immediately */
310     base->CHANNEL[channel].INTVAL = MRT_CHANNEL_INTVAL_LOAD_MASK;
311 }
312 
313 /*! @}*/
314 
315 /*!
316  * @name Get & release channel
317  * @{
318  */
319 
320 /*!
321  * @brief Find the available channel.
322  *
323  * This function returns the lowest available channel number.
324  *
325  * @param base Multi-Rate timer peripheral base address
326  */
MRT_GetIdleChannel(MRT_Type * base)327 static inline uint32_t MRT_GetIdleChannel(MRT_Type *base)
328 {
329     return base->IDLE_CH;
330 }
331 
332 #if !(defined(FSL_FEATURE_MRT_HAS_NO_CHANNEL_STAT_INUSE) && FSL_FEATURE_MRT_HAS_NO_CHANNEL_STAT_INUSE)
333 /*!
334  * @brief Release the channel when the timer is using the multi-task mode.
335  *
336  * In multi-task mode, the INUSE flags allow more control over when MRT channels are released for
337  * further use. The user can hold on to a channel acquired by calling MRT_GetIdleChannel() for as
338  * long as it is needed and release it by calling this function. This removes the need to ask for
339  * an available channel for every use.
340  *
341  * @param base    Multi-Rate timer peripheral base address
342  * @param channel Timer channel number.
343  */
MRT_ReleaseChannel(MRT_Type * base,mrt_chnl_t channel)344 static inline void MRT_ReleaseChannel(MRT_Type *base, mrt_chnl_t channel)
345 {
346     assert((uint8_t)channel < (uint8_t)FSL_FEATURE_MRT_NUMBER_OF_CHANNELS);
347 
348     uint32_t reg = base->CHANNEL[channel].STAT;
349 
350     /* Clear flag bits to prevent accidentally clearing anything when writing back */
351     reg = ~MRT_CHANNEL_STAT_INTFLAG_MASK;
352     reg |= MRT_CHANNEL_STAT_INUSE_MASK;
353 
354     base->CHANNEL[channel].STAT = reg;
355 }
356 #endif
357 
358 /*! @}*/
359 
360 #if defined(__cplusplus)
361 }
362 #endif
363 
364 /*! @}*/
365 
366 #endif /* FSL_MRT_H_ */
367