1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_ctimer.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.ctimer"
14 #endif
15 
16 /*******************************************************************************
17  * Prototypes
18  ******************************************************************************/
19 /*!
20  * @brief Gets the instance from the base address
21  *
22  * @param base Ctimer peripheral base address
23  *
24  * @return The Timer instance
25  */
26 static uint32_t CTIMER_GetInstance(CTIMER_Type *base);
27 
28 /*!
29  * @brief CTIMER generic IRQ handle function.
30  *
31  * @param index FlexCAN peripheral instance index.
32  */
33 static void CTIMER_GenericIRQHandler(uint32_t index);
34 
35 /*******************************************************************************
36  * Variables
37  ******************************************************************************/
38 /*! @brief Pointers to Timer bases for each instance. */
39 static CTIMER_Type *const s_ctimerBases[] = CTIMER_BASE_PTRS;
40 
41 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
42 /*! @brief Pointers to Timer clocks for each instance. */
43 static const clock_ip_name_t s_ctimerClocks[] = CTIMER_CLOCKS;
44 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
45 
46 #if !(defined(FSL_FEATURE_CTIMER_HAS_NO_RESET) && (FSL_FEATURE_CTIMER_HAS_NO_RESET))
47 #if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
48 #if defined(FSL_FEATURE_CTIMER_WRITE_ZERO_ASSERT_RESET) && FSL_FEATURE_CTIMER_WRITE_ZERO_ASSERT_RESET
49 /*! @brief Pointers to Timer resets for each instance, writing a zero asserts the reset */
50 static const reset_ip_name_t s_ctimerResets[] = CTIMER_RSTS_N;
51 #else
52 /*! @brief Pointers to Timer resets for each instance, writing a one asserts the reset */
53 static const reset_ip_name_t s_ctimerResets[] = CTIMER_RSTS;
54 #endif
55 #endif
56 #endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
57 
58 /*! @brief Pointers real ISRs installed by drivers for each instance. */
59 static ctimer_callback_t *s_ctimerCallback[sizeof(s_ctimerBases) / sizeof(s_ctimerBases[0])] = {0};
60 
61 /*! @brief Callback type installed by drivers for each instance. */
62 static ctimer_callback_type_t ctimerCallbackType[sizeof(s_ctimerBases) / sizeof(s_ctimerBases[0])] = {
63     kCTIMER_SingleCallback};
64 
65 /*! @brief Array to map timer instance to IRQ number. */
66 static const IRQn_Type s_ctimerIRQ[] = CTIMER_IRQS;
67 
68 /*******************************************************************************
69  * Code
70  ******************************************************************************/
CTIMER_GetInstance(CTIMER_Type * base)71 static uint32_t CTIMER_GetInstance(CTIMER_Type *base)
72 {
73     uint32_t instance;
74     uint32_t ctimerArrayCount = (sizeof(s_ctimerBases) / sizeof(s_ctimerBases[0]));
75 
76     /* Find the instance index from base address mappings. */
77     for (instance = 0; instance < ctimerArrayCount; instance++)
78     {
79         if (s_ctimerBases[instance] == base)
80         {
81             break;
82         }
83     }
84 
85     assert(instance < ctimerArrayCount);
86 
87     return instance;
88 }
89 
90 /*!
91  * brief Ungates the clock and configures the peripheral for basic operation.
92  *
93  * note This API should be called at the beginning of the application before using the driver.
94  *
95  * param base   Ctimer peripheral base address
96  * param config Pointer to the user configuration structure.
97  */
CTIMER_Init(CTIMER_Type * base,const ctimer_config_t * config)98 void CTIMER_Init(CTIMER_Type *base, const ctimer_config_t *config)
99 {
100     assert(config != NULL);
101 
102 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
103     /* Enable the timer clock*/
104     CLOCK_EnableClock(s_ctimerClocks[CTIMER_GetInstance(base)]);
105 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
106 
107 #if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
108 /* Reset the module. */
109 #if !(defined(FSL_FEATURE_CTIMER_HAS_NO_RESET) && (FSL_FEATURE_CTIMER_HAS_NO_RESET))
110     RESET_PeripheralReset(s_ctimerResets[CTIMER_GetInstance(base)]);
111 #endif
112 #endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
113 
114 /* Setup the cimer mode and count select */
115 #if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
116     base->CTCR = CTIMER_CTCR_CTMODE(config->mode) | CTIMER_CTCR_CINSEL(config->input);
117 #endif
118     /* Setup the timer prescale value */
119     base->PR = CTIMER_PR_PRVAL(config->prescale);
120 }
121 
122 /*!
123  * brief Gates the timer clock.
124  *
125  * param base Ctimer peripheral base address
126  */
CTIMER_Deinit(CTIMER_Type * base)127 void CTIMER_Deinit(CTIMER_Type *base)
128 {
129     uint32_t index = CTIMER_GetInstance(base);
130     /* Stop the timer */
131     base->TCR &= ~CTIMER_TCR_CEN_MASK;
132 
133 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
134     /* Disable the timer clock*/
135     CLOCK_DisableClock(s_ctimerClocks[index]);
136 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
137 
138     /* Disable IRQ at NVIC Level */
139     (void)DisableIRQ(s_ctimerIRQ[index]);
140 }
141 
142 /*!
143  * brief  Fills in the timers configuration structure with the default settings.
144  *
145  * The default values are:
146  * code
147  *   config->mode = kCTIMER_TimerMode;
148  *   config->input = kCTIMER_Capture_0;
149  *   config->prescale = 0;
150  * endcode
151  * param config Pointer to the user configuration structure.
152  */
CTIMER_GetDefaultConfig(ctimer_config_t * config)153 void CTIMER_GetDefaultConfig(ctimer_config_t *config)
154 {
155     assert(config != NULL);
156 
157     /* Initializes the configure structure to zero. */
158     (void)memset(config, 0, sizeof(*config));
159 
160     /* Run as a timer */
161     config->mode = kCTIMER_TimerMode;
162     /* This field is ignored when mode is timer */
163     config->input = kCTIMER_Capture_0;
164     /* Timer counter is incremented on every APB bus clock */
165     config->prescale = 0;
166 }
167 
168 /*!
169  * brief Configures the PWM signal parameters.
170  *
171  * Enables PWM mode on the match channel passed in and will then setup the match value
172  * and other match parameters to generate a PWM signal.
173  * This function can manually assign the specified channel to set the PWM cycle.
174  *
175  * note When setting PWM output from multiple output pins, all should use the same PWM
176  * frequency. Please use CTIMER_SetupPwmPeriod to set up the PWM with high resolution.
177  *
178  * param base             Ctimer peripheral base address
179  * param pwmPeriodChannel Specify the channel to control the PWM period
180  * param matchChannel     Match pin to be used to output the PWM signal
181  * param dutyCyclePercent PWM pulse width; the value should be between 0 to 100
182  * param pwmFreq_Hz       PWM signal frequency in Hz
183  * param srcClock_Hz      Timer counter clock in Hz
184  * param enableInt        Enable interrupt when the timer value reaches the match value of the PWM pulse,
185  *                         if it is 0 then no interrupt will be generated.
186  *
187  * return kStatus_Success on success
188  *         kStatus_Fail If matchChannel is equal to pwmPeriodChannel; this channel is reserved to set the PWM cycle
189  */
CTIMER_SetupPwm(CTIMER_Type * base,const ctimer_match_t pwmPeriodChannel,ctimer_match_t matchChannel,uint8_t dutyCyclePercent,uint32_t pwmFreq_Hz,uint32_t srcClock_Hz,bool enableInt)190 status_t CTIMER_SetupPwm(CTIMER_Type *base,
191                          const ctimer_match_t pwmPeriodChannel,
192                          ctimer_match_t matchChannel,
193                          uint8_t dutyCyclePercent,
194                          uint32_t pwmFreq_Hz,
195                          uint32_t srcClock_Hz,
196                          bool enableInt)
197 {
198     assert(pwmFreq_Hz > 0U);
199 
200     uint32_t reg;
201     uint32_t period, pulsePeriod = 0;
202     uint32_t timerClock = srcClock_Hz / (base->PR + 1U);
203     uint32_t index      = CTIMER_GetInstance(base);
204 
205     if (matchChannel == pwmPeriodChannel)
206     {
207         return kStatus_Fail;
208     }
209 
210     /* Enable PWM mode on the channel */
211     base->PWMC |= (1UL << (uint32_t)matchChannel);
212 
213     /* Clear the stop, reset and interrupt bits for this channel */
214     reg = base->MCR;
215     reg &=
216         ~(((uint32_t)((uint32_t)CTIMER_MCR_MR0R_MASK | (uint32_t)CTIMER_MCR_MR0S_MASK | (uint32_t)CTIMER_MCR_MR0I_MASK))
217           << ((uint32_t)matchChannel * 3U));
218 
219     /* If call back function is valid then enable match interrupt for the channel */
220     if (enableInt)
221     {
222         reg |= (((uint32_t)CTIMER_MCR_MR0I_MASK) << (CTIMER_MCR_MR0I_SHIFT + ((uint32_t)matchChannel * 3U)));
223     }
224 
225     /* Reset the counter when match on channel 3 */
226     reg |= CTIMER_MCR_MR3R_MASK;
227 
228     base->MCR = reg;
229 
230     /* Calculate PWM period match value */
231     period = (timerClock / pwmFreq_Hz) - 1U;
232 
233     /* Calculate pulse width match value */
234     if (dutyCyclePercent == 0U)
235     {
236         pulsePeriod = period + 1U;
237     }
238     else
239     {
240         pulsePeriod = (period * (100U - (uint32_t)dutyCyclePercent)) / 100U;
241     }
242 
243     /* Specified channel pwmPeriodChannel will define the PWM period */
244     base->MR[pwmPeriodChannel] = period;
245 
246     /* This will define the PWM pulse period */
247     base->MR[matchChannel] = pulsePeriod;
248     /* Clear status flags */
249     CTIMER_ClearStatusFlags(base, ((uint32_t)CTIMER_IR_MR0INT_MASK) << (uint32_t)matchChannel);
250     /* If call back function is valid then enable interrupt and update the call back function */
251     if (enableInt)
252     {
253         (void)EnableIRQ(s_ctimerIRQ[index]);
254     }
255 
256     return kStatus_Success;
257 }
258 
259 /*!
260  * brief Configures the PWM signal parameters.
261  *
262  * Enables PWM mode on the match channel passed in and will then setup the match value
263  * and other match parameters to generate a PWM signal.
264  * This function can manually assign the specified channel to set the PWM cycle.
265  *
266  * note When setting PWM output from multiple output pins, all should use the same PWM
267  * period
268  *
269  * param base             Ctimer peripheral base address
270  * param pwmPeriodChannel Specify the channel to control the PWM period
271  * param matchChannel     Match pin to be used to output the PWM signal
272  * param pwmPeriod        PWM period match value
273  * param pulsePeriod      Pulse width match value
274  * param enableInt        Enable interrupt when the timer value reaches the match value of the PWM pulse,
275  *                         if it is 0 then no interrupt will be generated.
276  *
277  * return kStatus_Success on success
278  *         kStatus_Fail If matchChannel is equal to pwmPeriodChannel; this channel is reserved to set the PWM period
279  */
CTIMER_SetupPwmPeriod(CTIMER_Type * base,const ctimer_match_t pwmPeriodChannel,ctimer_match_t matchChannel,uint32_t pwmPeriod,uint32_t pulsePeriod,bool enableInt)280 status_t CTIMER_SetupPwmPeriod(CTIMER_Type *base,
281                                const ctimer_match_t pwmPeriodChannel,
282                                ctimer_match_t matchChannel,
283                                uint32_t pwmPeriod,
284                                uint32_t pulsePeriod,
285                                bool enableInt)
286 {
287 /* Some CTimers only have 16bits , so the value is limited*/
288 #if defined(FSL_FEATURE_SOC_CTIMER16B) && FSL_FEATURE_SOC_CTIMER16B
289     assert(!((FSL_FEATURE_CTIMER_BIT_SIZEn(base) < 32) && (pulsePeriod > 0xFFFFU)));
290 #endif
291 
292     uint32_t reg;
293     uint32_t index = CTIMER_GetInstance(base);
294 
295     if (matchChannel == pwmPeriodChannel)
296     {
297         return kStatus_Fail;
298     }
299 
300     /* Enable PWM mode on PWM pulse channel */
301     base->PWMC |= (1UL << (uint32_t)matchChannel);
302 
303     /* Clear the stop, reset and interrupt bits for PWM pulse channel */
304     reg = base->MCR;
305     reg &=
306         ~((uint32_t)((uint32_t)CTIMER_MCR_MR0R_MASK | (uint32_t)CTIMER_MCR_MR0S_MASK | (uint32_t)CTIMER_MCR_MR0I_MASK)
307           << ((uint32_t)matchChannel * 3U));
308 
309     /* If call back function is valid then enable match interrupt for PWM pulse channel */
310     if (enableInt)
311     {
312         reg |= (((uint32_t)CTIMER_MCR_MR0I_MASK) << (CTIMER_MCR_MR0I_SHIFT + ((uint32_t)matchChannel * 3U)));
313     }
314 
315     /* Reset the counter when match on PWM period channel (pwmPeriodChannel)  */
316     reg |= ((uint32_t)((uint32_t)CTIMER_MCR_MR0R_MASK) << ((uint32_t)pwmPeriodChannel * 3U));
317 
318     base->MCR = reg;
319 
320     /* Specified channel pwmPeriodChannel will define the PWM period */
321     base->MR[pwmPeriodChannel] = pwmPeriod;
322 
323     /* This will define the PWM pulse period */
324     base->MR[matchChannel] = pulsePeriod;
325     /* Clear status flags */
326     CTIMER_ClearStatusFlags(base, ((uint32_t)CTIMER_IR_MR0INT_MASK) << (uint32_t)matchChannel);
327     /* If call back function is valid then enable interrupt and update the call back function */
328     if (enableInt)
329     {
330         (void)EnableIRQ(s_ctimerIRQ[index]);
331     }
332 
333     return kStatus_Success;
334 }
335 
336 /*!
337  * brief Updates the duty cycle of an active PWM signal.
338  *
339  * note Please use CTIMER_SetupPwmPeriod to update the PWM with high resolution.
340  * This function can manually assign the specified channel to set the PWM cycle.
341  *
342  * param base             Ctimer peripheral base address
343  * param pwmPeriodChannel Specify the channel to control the PWM period
344  * param matchChannel     Match pin to be used to output the PWM signal
345  * param dutyCyclePercent New PWM pulse width; the value should be between 0 to 100
346  */
CTIMER_UpdatePwmDutycycle(CTIMER_Type * base,const ctimer_match_t pwmPeriodChannel,ctimer_match_t matchChannel,uint8_t dutyCyclePercent)347 void CTIMER_UpdatePwmDutycycle(CTIMER_Type *base,
348                                const ctimer_match_t pwmPeriodChannel,
349                                ctimer_match_t matchChannel,
350                                uint8_t dutyCyclePercent)
351 {
352     uint32_t pulsePeriod = 0, period;
353 
354     /* Specified channel pwmPeriodChannel  defines the PWM period */
355     period = base->MR[pwmPeriodChannel];
356 
357     /* For 0% dutycyle, make pulse period greater than period so the event will never occur */
358     if (dutyCyclePercent == 0U)
359     {
360         pulsePeriod = period + 1U;
361     }
362     else
363     {
364         pulsePeriod = (period * (100U - (uint32_t)dutyCyclePercent)) / 100U;
365     }
366 
367     /* Update dutycycle */
368     base->MR[matchChannel] = pulsePeriod;
369 }
370 
371 /*!
372  * brief Setup the match register.
373  *
374  * User configuration is used to setup the match value and action to be taken when a match occurs.
375  *
376  * param base         Ctimer peripheral base address
377  * param matchChannel Match register to configure
378  * param config       Pointer to the match configuration structure
379  */
CTIMER_SetupMatch(CTIMER_Type * base,ctimer_match_t matchChannel,const ctimer_match_config_t * config)380 void CTIMER_SetupMatch(CTIMER_Type *base, ctimer_match_t matchChannel, const ctimer_match_config_t *config)
381 {
382 /* Some CTimers only have 16bits , so the value is limited*/
383 #if defined(FSL_FEATURE_SOC_CTIMER16B) && FSL_FEATURE_SOC_CTIMER16B
384     assert(!(FSL_FEATURE_CTIMER_BIT_SIZEn(base) < 32 && config->matchValue > 0xFFFFU));
385 #endif
386     uint32_t reg;
387     uint32_t index = CTIMER_GetInstance(base);
388 
389     /* Set the counter operation when a match on this channel occurs */
390     reg = base->MCR;
391     reg &=
392         ~((uint32_t)((uint32_t)CTIMER_MCR_MR0R_MASK | (uint32_t)CTIMER_MCR_MR0S_MASK | (uint32_t)CTIMER_MCR_MR0I_MASK)
393           << ((uint32_t)matchChannel * 3U));
394     reg |= ((uint32_t)(config->enableCounterReset) << (CTIMER_MCR_MR0R_SHIFT + ((uint32_t)matchChannel * 3U)));
395     reg |= ((uint32_t)(config->enableCounterStop) << (CTIMER_MCR_MR0S_SHIFT + ((uint32_t)matchChannel * 3U)));
396     reg |= ((uint32_t)(config->enableInterrupt) << (CTIMER_MCR_MR0I_SHIFT + ((uint32_t)matchChannel * 3U)));
397     base->MCR = reg;
398 
399     reg = base->EMR;
400     /* Set the match output operation when a match on this channel occurs */
401     reg &= ~(((uint32_t)CTIMER_EMR_EMC0_MASK) << ((uint32_t)matchChannel * 2U));
402     reg |= ((uint32_t)config->outControl) << (CTIMER_EMR_EMC0_SHIFT + ((uint32_t)matchChannel * 2U));
403 
404     /* Set the initial state of the EM bit/output */
405     reg &= ~(((uint32_t)CTIMER_EMR_EM0_MASK) << (uint32_t)matchChannel);
406     reg |= ((uint32_t)config->outPinInitState) << (uint32_t)matchChannel;
407     base->EMR = reg;
408 
409     /* Set the match value */
410     base->MR[matchChannel] = config->matchValue;
411     /* Clear status flags */
412     CTIMER_ClearStatusFlags(base, ((uint32_t)CTIMER_IR_MR0INT_MASK) << (uint32_t)matchChannel);
413     /* If interrupt is enabled then enable interrupt and update the call back function */
414     if (config->enableInterrupt)
415     {
416         (void)EnableIRQ(s_ctimerIRQ[index]);
417     }
418 }
419 
420 /*!
421  * brief Get the status of output match.
422  *
423  * This function gets the status of output MAT, whether or not this output is connected to a pin.
424  * This status is driven to the MAT pins if the match function is selected via IOCON. 0 = LOW. 1 = HIGH.
425  *
426  * param base         Ctimer peripheral base address
427  * param matchChannel External match channel, user can obtain the status of multiple match channels
428  *                    at the same time by using the logic of "|"
429  *                    enumeration ::ctimer_external_match_t
430  * return The mask of external match channel status flags. Users need to use the
431  *        _ctimer_external_match type to decode the return variables.
432  */
CTIMER_GetOutputMatchStatus(CTIMER_Type * base,uint32_t matchChannel)433 uint32_t CTIMER_GetOutputMatchStatus(CTIMER_Type *base, uint32_t matchChannel)
434 {
435     return (base->EMR & matchChannel);
436 }
437 
438 #if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
439 /*!
440  * brief Setup the capture.
441  *
442  * param base      Ctimer peripheral base address
443  * param capture   Capture channel to configure
444  * param edge      Edge on the channel that will trigger a capture
445  * param enableInt Flag to enable channel interrupts, if enabled then the registered call back
446  *                  is called upon capture
447  */
CTIMER_SetupCapture(CTIMER_Type * base,ctimer_capture_channel_t capture,ctimer_capture_edge_t edge,bool enableInt)448 void CTIMER_SetupCapture(CTIMER_Type *base,
449                          ctimer_capture_channel_t capture,
450                          ctimer_capture_edge_t edge,
451                          bool enableInt)
452 {
453     uint32_t reg   = base->CCR;
454     uint32_t index = CTIMER_GetInstance(base);
455 
456     /* Set the capture edge */
457     reg &= ~((uint32_t)((uint32_t)CTIMER_CCR_CAP0RE_MASK | (uint32_t)CTIMER_CCR_CAP0FE_MASK |
458                         (uint32_t)CTIMER_CCR_CAP0I_MASK)
459              << ((uint32_t)capture * 3U));
460     reg |= ((uint32_t)edge) << (CTIMER_CCR_CAP0RE_SHIFT + ((uint32_t)capture * 3U));
461     /* Clear status flags */
462     CTIMER_ClearStatusFlags(base, (((uint32_t)kCTIMER_Capture0Flag) << (uint32_t)capture));
463     /* If call back function is valid then enable capture interrupt for the channel and update the call back function */
464     if (enableInt)
465     {
466         reg |= ((uint32_t)CTIMER_CCR_CAP0I_MASK) << ((uint32_t)capture * 3U);
467         (void)EnableIRQ(s_ctimerIRQ[index]);
468     }
469     base->CCR = reg;
470 }
471 #endif
472 
473 /*!
474  * brief Register callback.
475  *
476  * param base      Ctimer peripheral base address
477  * param cb_func   callback function
478  * param cb_type   callback function type, singular or multiple
479  */
CTIMER_RegisterCallBack(CTIMER_Type * base,ctimer_callback_t * cb_func,ctimer_callback_type_t cb_type)480 void CTIMER_RegisterCallBack(CTIMER_Type *base, ctimer_callback_t *cb_func, ctimer_callback_type_t cb_type)
481 {
482     uint32_t index            = CTIMER_GetInstance(base);
483     s_ctimerCallback[index]   = cb_func;
484     ctimerCallbackType[index] = cb_type;
485 }
486 
487 /*!
488  * brief CTIMER generic IRQ handle function.
489  *
490  * param index FlexCAN peripheral instance index.
491  */
CTIMER_GenericIRQHandler(uint32_t index)492 static void CTIMER_GenericIRQHandler(uint32_t index)
493 {
494     uint32_t int_stat, i, mask;
495     /* Get Interrupt status flags */
496     int_stat = CTIMER_GetStatusFlags(s_ctimerBases[index]);
497     /* Clear the status flags that were set */
498     CTIMER_ClearStatusFlags(s_ctimerBases[index], int_stat);
499     if (ctimerCallbackType[index] == kCTIMER_SingleCallback)
500     {
501         if (s_ctimerCallback[index][0] != NULL)
502         {
503             s_ctimerCallback[index][0](int_stat);
504         }
505     }
506     else
507     {
508 #if defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE
509         for (i = 0; i <= CTIMER_IR_MR3INT_SHIFT; i++)
510 #else
511 #if defined(FSL_FEATURE_CTIMER_HAS_IR_CR3INT) && FSL_FEATURE_CTIMER_HAS_IR_CR3INT
512         for (i = 0; i <= CTIMER_IR_CR3INT_SHIFT; i++)
513 #else
514 #if !(defined(FSL_FEATURE_CTIMER_HAS_NO_IR_CR2INT) && FSL_FEATURE_CTIMER_HAS_NO_IR_CR2INT)
515         for (i = 0; i <= CTIMER_IR_CR2INT_SHIFT; i++)
516 #else
517         for (i = 0; i <= CTIMER_IR_CR1INT_SHIFT; i++)
518 #endif /* FSL_FEATURE_CTIMER_HAS_NO_IR_CR2INT */
519 #endif /* FSL_FEATURE_CTIMER_HAS_IR_CR3INT */
520 #endif
521         {
522             mask = 0x01UL << i;
523             /* For each status flag bit that was set call the callback function if it is valid */
524             if (((int_stat & mask) != 0U) && (s_ctimerCallback[index][i] != NULL))
525             {
526                 s_ctimerCallback[index][i](int_stat);
527             }
528         }
529     }
530     SDK_ISR_EXIT_BARRIER;
531 }
532 
533 /* IRQ handler functions overloading weak symbols in the startup */
534 #if defined(CTIMER0)
535 void CTIMER0_DriverIRQHandler(void);
CTIMER0_DriverIRQHandler(void)536 void CTIMER0_DriverIRQHandler(void)
537 {
538     CTIMER_GenericIRQHandler(0);
539     SDK_ISR_EXIT_BARRIER;
540 }
541 #endif
542 
543 #if defined(CTIMER1)
544 void CTIMER1_DriverIRQHandler(void);
CTIMER1_DriverIRQHandler(void)545 void CTIMER1_DriverIRQHandler(void)
546 {
547     CTIMER_GenericIRQHandler(1);
548     SDK_ISR_EXIT_BARRIER;
549 }
550 #endif
551 
552 #if defined(CTIMER2)
553 void CTIMER2_DriverIRQHandler(void);
CTIMER2_DriverIRQHandler(void)554 void CTIMER2_DriverIRQHandler(void)
555 {
556     CTIMER_GenericIRQHandler(2);
557     SDK_ISR_EXIT_BARRIER;
558 }
559 #endif
560 
561 #if defined(CTIMER3)
562 void CTIMER3_DriverIRQHandler(void);
CTIMER3_DriverIRQHandler(void)563 void CTIMER3_DriverIRQHandler(void)
564 {
565     CTIMER_GenericIRQHandler(3);
566     SDK_ISR_EXIT_BARRIER;
567 }
568 #endif
569 
570 #if defined(CTIMER4)
571 void CTIMER4_DriverIRQHandler(void);
CTIMER4_DriverIRQHandler(void)572 void CTIMER4_DriverIRQHandler(void)
573 {
574     CTIMER_GenericIRQHandler(4);
575     SDK_ISR_EXIT_BARRIER;
576 }
577 #endif
578