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