Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2018 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#ifndef _FSL_CTIMER_H_
#define _FSL_CTIMER_H_

#include "fsl_common.h"

/*!
 * @addtogroup ctimer
 * @{
 */

/*! @file */

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*! @name Driver version */
/*@{*/
#define FSL_CTIMER_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*!< Version 2.0.2 */
/*@}*/

/*! @brief List of Timer capture channels */
typedef enum _ctimer_capture_channel
{
    kCTIMER_Capture_0 = 0U, /*!< Timer capture channel 0 */
    kCTIMER_Capture_1,      /*!< Timer capture channel 1 */
    kCTIMER_Capture_2,      /*!< Timer capture channel 2 */
#if defined(FSL_FEATURE_CTIMER_HAS_CCR_CAP3) && FSL_FEATURE_CTIMER_HAS_CCR_CAP3
    kCTIMER_Capture_3 /*!< Timer capture channel 3 */
#endif                /* FSL_FEATURE_CTIMER_HAS_IR_CR3INT */
} ctimer_capture_channel_t;

/*! @brief List of capture edge options */
typedef enum _ctimer_capture_edge
{
    kCTIMER_Capture_RiseEdge = 1U, /*!< Capture on rising edge */
    kCTIMER_Capture_FallEdge = 2U, /*!< Capture on falling edge */
    kCTIMER_Capture_BothEdge = 3U, /*!< Capture on rising and falling edge */
} ctimer_capture_edge_t;

/*! @brief List of Timer match registers */
typedef enum _ctimer_match
{
    kCTIMER_Match_0 = 0U, /*!< Timer match register 0 */
    kCTIMER_Match_1,      /*!< Timer match register 1 */
    kCTIMER_Match_2,      /*!< Timer match register 2 */
    kCTIMER_Match_3       /*!< Timer match register 3 */
} ctimer_match_t;

/*! @brief List of output control options */
typedef enum _ctimer_match_output_control
{
    kCTIMER_Output_NoAction = 0U, /*!< No action is taken */
    kCTIMER_Output_Clear,         /*!< Clear the EM bit/output to 0 */
    kCTIMER_Output_Set,           /*!< Set the EM bit/output to 1 */
    kCTIMER_Output_Toggle         /*!< Toggle the EM bit/output */
} ctimer_match_output_control_t;

/*! @brief List of Timer modes */
typedef enum _ctimer_timer_mode
{
    kCTIMER_TimerMode = 0U,     /* TC is incremented every rising APB bus clock edge */
    kCTIMER_IncreaseOnRiseEdge, /* TC is incremented on rising edge of input signal */
    kCTIMER_IncreaseOnFallEdge, /* TC is incremented on falling edge of input signal */
    kCTIMER_IncreaseOnBothEdge  /* TC is incremented on both edges of input signal */
} ctimer_timer_mode_t;

/*! @brief List of Timer interrupts */
typedef enum _ctimer_interrupt_enable
{
    kCTIMER_Match0InterruptEnable = CTIMER_MCR_MR0I_MASK, /*!< Match 0 interrupt */
    kCTIMER_Match1InterruptEnable = CTIMER_MCR_MR1I_MASK, /*!< Match 1 interrupt */
    kCTIMER_Match2InterruptEnable = CTIMER_MCR_MR2I_MASK, /*!< Match 2 interrupt */
    kCTIMER_Match3InterruptEnable = CTIMER_MCR_MR3I_MASK, /*!< Match 3 interrupt */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
    kCTIMER_Capture0InterruptEnable = CTIMER_CCR_CAP0I_MASK, /*!< Capture 0 interrupt */
    kCTIMER_Capture1InterruptEnable = CTIMER_CCR_CAP1I_MASK, /*!< Capture 1 interrupt */
    kCTIMER_Capture2InterruptEnable = CTIMER_CCR_CAP2I_MASK, /*!< Capture 2 interrupt */
#if defined(FSL_FEATURE_CTIMER_HAS_CCR_CAP3) && FSL_FEATURE_CTIMER_HAS_CCR_CAP3
    kCTIMER_Capture3InterruptEnable = CTIMER_CCR_CAP3I_MASK, /*!< Capture 3 interrupt */
#endif                                                       /* FSL_FEATURE_CTIMER_HAS_CCR_CAP3 */
#endif
} ctimer_interrupt_enable_t;

/*! @brief List of Timer flags */
typedef enum _ctimer_status_flags
{
    kCTIMER_Match0Flag = CTIMER_IR_MR0INT_MASK, /*!< Match 0 interrupt flag */
    kCTIMER_Match1Flag = CTIMER_IR_MR1INT_MASK, /*!< Match 1 interrupt flag */
    kCTIMER_Match2Flag = CTIMER_IR_MR2INT_MASK, /*!< Match 2 interrupt flag */
    kCTIMER_Match3Flag = CTIMER_IR_MR3INT_MASK, /*!< Match 3 interrupt flag */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
    kCTIMER_Capture0Flag = CTIMER_IR_CR0INT_MASK, /*!< Capture 0 interrupt flag */
    kCTIMER_Capture1Flag = CTIMER_IR_CR1INT_MASK, /*!< Capture 1 interrupt flag */
    kCTIMER_Capture2Flag = CTIMER_IR_CR2INT_MASK, /*!< Capture 2 interrupt flag */
#if defined(FSL_FEATURE_CTIMER_HAS_IR_CR3INT) && FSL_FEATURE_CTIMER_HAS_IR_CR3INT
    kCTIMER_Capture3Flag = CTIMER_IR_CR3INT_MASK, /*!< Capture 3 interrupt flag */
#endif                                            /* FSL_FEATURE_CTIMER_HAS_IR_CR3INT */
#endif
} ctimer_status_flags_t;

typedef void (*ctimer_callback_t)(uint32_t flags);

/*! @brief Callback type when registering for a callback. When registering a callback
 *         an array of function pointers is passed the size could be 1 or 8, the callback
 *         type will tell that.
 */
typedef enum
{
    kCTIMER_SingleCallback,  /*!< Single Callback type where there is only one callback for the timer.
                                 based on the status flags different channels needs to be handled differently */
    kCTIMER_MultipleCallback /*!< Multiple Callback type where there can be 8 valid callbacks, one per channel.
                                 for both match/capture */
} ctimer_callback_type_t;

/*!
 * @brief Match configuration
 *
 * This structure holds the configuration settings for each match register.
 */
typedef struct _ctimer_match_config
{
    uint32_t matchValue;                      /*!< This is stored in the match register */
    bool enableCounterReset;                  /*!< true: Match will reset the counter
                                                   false: Match will not reser the counter */
    bool enableCounterStop;                   /*!< true: Match will stop the counter
                                                   false: Match will not stop the counter */
    ctimer_match_output_control_t outControl; /*!< Action to be taken on a match on the EM bit/output */
    bool outPinInitState;                     /*!< Initial value of the EM bit/output */
    bool enableInterrupt;                     /*!< true: Generate interrupt upon match
                                                   false: Do not generate interrupt on match */

} ctimer_match_config_t;

/*!
 * @brief Timer configuration structure
 *
 * This structure holds the configuration settings for the Timer peripheral. To initialize this
 * structure to reasonable defaults, call the CTIMER_GetDefaultConfig() function and pass a
 * pointer to the configuration structure instance.
 *
 * The configuration structure can be made constant so as to reside in flash.
 */
typedef struct _ctimer_config
{
    ctimer_timer_mode_t mode;       /*!< Timer mode */
    ctimer_capture_channel_t input; /*!< Input channel to increment the timer, used only in timer
                                        modes that rely on this input signal to increment TC */
    uint32_t prescale;              /*!< Prescale value */
} ctimer_config_t;

/*******************************************************************************
 * API
 ******************************************************************************/

#if defined(__cplusplus)
extern "C" {
#endif

/*!
 * @name Initialization and deinitialization
 * @{
 */

/*!
 * @brief Ungates the clock and configures the peripheral for basic operation.
 *
 * @note This API should be called at the beginning of the application before using the driver.
 *
 * @param base   Ctimer peripheral base address
 * @param config Pointer to the user configuration structure.
 */
void CTIMER_Init(CTIMER_Type *base, const ctimer_config_t *config);

/*!
 * @brief Gates the timer clock.
 *
 * @param base Ctimer peripheral base address
 */
void CTIMER_Deinit(CTIMER_Type *base);

/*!
 * @brief  Fills in the timers configuration structure with the default settings.
 *
 * The default values are:
 * @code
 *   config->mode = kCTIMER_TimerMode;
 *   config->input = kCTIMER_Capture_0;
 *   config->prescale = 0;
 * @endcode
 * @param config Pointer to the user configuration structure.
 */
void CTIMER_GetDefaultConfig(ctimer_config_t *config);

/*! @}*/

/*!
 * @name PWM setup operations
 * @{
 */

/*!
 * @brief Configures the PWM signal parameters.
 *
 * Enables PWM mode on the match channel passed in and will then setup the match value
 * and other match parameters to generate a PWM signal.
 * This function will assign match channel 3 to set the PWM cycle.
 *
 * @note When setting PWM output from multiple output pins, all should use the same PWM
 * period
 *
 * @param base             Ctimer peripheral base address
 * @param matchChannel     Match pin to be used to output the PWM signal
 * @param pwmPeriod        PWM period match value
 * @param pulsePeriod      Pulse width match value
 * @param enableInt        Enable interrupt when the timer value reaches the match value of the PWM pulse,
 *                         if it is 0 then no interrupt is generated
 *
 * @return kStatus_Success on success
 *         kStatus_Fail If matchChannel passed in is 3; this channel is reserved to set the PWM period
 */
status_t CTIMER_SetupPwmPeriod(
    CTIMER_Type *base, ctimer_match_t matchChannel, uint32_t pwmPeriod, uint32_t pulsePeriod, bool enableInt);

/*!
 * @brief Configures the PWM signal parameters.
 *
 * Enables PWM mode on the match channel passed in and will then setup the match value
 * and other match parameters to generate a PWM signal.
 * This function will assign match channel 3 to set the PWM cycle.
 *
 * @note When setting PWM output from multiple output pins, all should use the same PWM
 * frequency. Please use CTIMER_SetupPwmPeriod to set up the PWM with high resolution.
 *
 * @param base             Ctimer peripheral base address
 * @param matchChannel     Match pin to be used to output the PWM signal
 * @param dutyCyclePercent PWM pulse width; the value should be between 0 to 100
 * @param pwmFreq_Hz       PWM signal frequency in Hz
 * @param srcClock_Hz      Timer counter clock in Hz
 * @param enableInt        Enable interrupt when the timer value reaches the match value of the PWM pulse,
 *                         if it is 0 then no interrupt is generated
 *
 * @return kStatus_Success on success
 *         kStatus_Fail If matchChannel passed in is 3; this channel is reserved to set the PWM cycle
 */
status_t CTIMER_SetupPwm(CTIMER_Type *base,
                         ctimer_match_t matchChannel,
                         uint8_t dutyCyclePercent,
                         uint32_t pwmFreq_Hz,
                         uint32_t srcClock_Hz,
                         bool enableInt);

/*!
 * @brief Updates the pulse period of an active PWM signal.
 *
 * @param base         Ctimer peripheral base address
 * @param matchChannel Match pin to be used to output the PWM signal
 * @param pulsePeriod  New PWM pulse width match value
 */
static inline void CTIMER_UpdatePwmPulsePeriod(CTIMER_Type *base, ctimer_match_t matchChannel, uint32_t pulsePeriod)
{
    /* Update PWM pulse period match value */
    base->MR[matchChannel] = pulsePeriod;
}

/*!
 * @brief Updates the duty cycle of an active PWM signal.
 *
 * @note Please use CTIMER_UpdatePwmPulsePeriod to update the PWM with high resolution.
 *
 * @param base             Ctimer peripheral base address
 * @param matchChannel     Match pin to be used to output the PWM signal
 * @param dutyCyclePercent New PWM pulse width; the value should be between 0 to 100
 */
void CTIMER_UpdatePwmDutycycle(CTIMER_Type *base, ctimer_match_t matchChannel, uint8_t dutyCyclePercent);

/*! @}*/

/*!
 * @brief Setup the match register.
 *
 * User configuration is used to setup the match value and action to be taken when a match occurs.
 *
 * @param base         Ctimer peripheral base address
 * @param matchChannel Match register to configure
 * @param config       Pointer to the match configuration structure
 */
void CTIMER_SetupMatch(CTIMER_Type *base, ctimer_match_t matchChannel, const ctimer_match_config_t *config);

/*!
 * @brief Setup the capture.
 *
 * @param base      Ctimer peripheral base address
 * @param capture   Capture channel to configure
 * @param edge      Edge on the channel that will trigger a capture
 * @param enableInt Flag to enable channel interrupts, if enabled then the registered call back
 *                  is called upon capture
 */
void CTIMER_SetupCapture(CTIMER_Type *base,
                         ctimer_capture_channel_t capture,
                         ctimer_capture_edge_t edge,
                         bool enableInt);

/*!
 * @brief Get the timer count value from TC register.
 *
 * @param  base  Ctimer peripheral base address.
 * @return       return the timer count value.
 */
static inline uint32_t CTIMER_GetTimerCountValue(CTIMER_Type *base)
{
    return (base->TC);
}

/*!
 * @brief Register callback.
 *
 * @param base      Ctimer peripheral base address
 * @param cb_func   callback function
 * @param cb_type   callback function type, singular or multiple
 */
void CTIMER_RegisterCallBack(CTIMER_Type *base, ctimer_callback_t *cb_func, ctimer_callback_type_t cb_type);

/*!
 * @name Interrupt Interface
 * @{
 */

/*!
 * @brief Enables the selected Timer interrupts.
 *
 * @param base Ctimer peripheral base address
 * @param mask The interrupts to enable. This is a logical OR of members of the
 *             enumeration ::ctimer_interrupt_enable_t
 */
static inline void CTIMER_EnableInterrupts(CTIMER_Type *base, uint32_t mask)
{
    /* Enable match interrupts */
    base->MCR |= mask & (CTIMER_MCR_MR0I_MASK | CTIMER_MCR_MR1I_MASK | CTIMER_MCR_MR2I_MASK | CTIMER_MCR_MR3I_MASK);

/* Enable capture interrupts */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
    base->CCR |= mask & (CTIMER_CCR_CAP0I_MASK | CTIMER_CCR_CAP1I_MASK | CTIMER_CCR_CAP2I_MASK
#if defined(FSL_FEATURE_CTIMER_HAS_CCR_CAP3) && FSL_FEATURE_CTIMER_HAS_CCR_CAP3
                         | CTIMER_CCR_CAP3I_MASK
#endif /* FSL_FEATURE_CTIMER_HAS_CCR_CAP3 */
                         );
#endif
}

/*!
 * @brief Disables the selected Timer interrupts.
 *
 * @param base Ctimer peripheral base address
 * @param mask The interrupts to enable. This is a logical OR of members of the
 *             enumeration ::ctimer_interrupt_enable_t
 */
static inline void CTIMER_DisableInterrupts(CTIMER_Type *base, uint32_t mask)
{
    /* Disable match interrupts */
    base->MCR &= ~(mask & (CTIMER_MCR_MR0I_MASK | CTIMER_MCR_MR1I_MASK | CTIMER_MCR_MR2I_MASK | CTIMER_MCR_MR3I_MASK));

/* Disable capture interrupts */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
    base->CCR &= ~(mask & (CTIMER_CCR_CAP0I_MASK | CTIMER_CCR_CAP1I_MASK | CTIMER_CCR_CAP2I_MASK
#if defined(FSL_FEATURE_CTIMER_HAS_CCR_CAP3) && FSL_FEATURE_CTIMER_HAS_CCR_CAP3
                           | CTIMER_CCR_CAP3I_MASK
#endif /* FSL_FEATURE_CTIMER_HAS_CCR_CAP3 */
                           ));
#endif
}

/*!
 * @brief Gets the enabled Timer interrupts.
 *
 * @param base Ctimer peripheral base address
 *
 * @return The enabled interrupts. This is the logical OR of members of the
 *         enumeration ::ctimer_interrupt_enable_t
 */
static inline uint32_t CTIMER_GetEnabledInterrupts(CTIMER_Type *base)
{
    uint32_t enabledIntrs = 0;

    /* Get all the match interrupts enabled */
    enabledIntrs =
        base->MCR & (CTIMER_MCR_MR0I_MASK | CTIMER_MCR_MR1I_MASK | CTIMER_MCR_MR2I_MASK | CTIMER_MCR_MR3I_MASK);

/* Get all the capture interrupts enabled */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
    enabledIntrs |= base->CCR & (CTIMER_CCR_CAP0I_MASK | CTIMER_CCR_CAP1I_MASK | CTIMER_CCR_CAP2I_MASK
#if defined(FSL_FEATURE_CTIMER_HAS_CCR_CAP3) && FSL_FEATURE_CTIMER_HAS_CCR_CAP3
                                 | CTIMER_CCR_CAP3I_MASK
#endif /* FSL_FEATURE_CTIMER_HAS_CCR_CAP3 */
                                 );
#endif

    return enabledIntrs;
}

/*! @}*/

/*!
 * @name Status Interface
 * @{
 */

/*!
 * @brief Gets the Timer status flags.
 *
 * @param base Ctimer peripheral base address
 *
 * @return The status flags. This is the logical OR of members of the
 *         enumeration ::ctimer_status_flags_t
 */
static inline uint32_t CTIMER_GetStatusFlags(CTIMER_Type *base)
{
    return base->IR;
}

/*!
 * @brief Clears the Timer status flags.
 *
 * @param base Ctimer peripheral base address
 * @param mask The status flags to clear. This is a logical OR of members of the
 *             enumeration ::ctimer_status_flags_t
 */
static inline void CTIMER_ClearStatusFlags(CTIMER_Type *base, uint32_t mask)
{
    base->IR = mask;
}

/*! @}*/

/*!
 * @name Counter Start and Stop
 * @{
 */

/*!
 * @brief Starts the Timer counter.
 *
 * @param base Ctimer peripheral base address
 */
static inline void CTIMER_StartTimer(CTIMER_Type *base)
{
    base->TCR |= CTIMER_TCR_CEN_MASK;
}

/*!
 * @brief Stops the Timer counter.
 *
 * @param base Ctimer peripheral base address
 */
static inline void CTIMER_StopTimer(CTIMER_Type *base)
{
    base->TCR &= ~CTIMER_TCR_CEN_MASK;
}

/*! @}*/

/*!
 * @brief Reset the counter.
 *
 * The timer counter and prescale counter are reset on the next positive edge of the APB clock.
 *
 * @param base Ctimer peripheral base address
 */
static inline void CTIMER_Reset(CTIMER_Type *base)
{
    base->TCR |= CTIMER_TCR_CRST_MASK;
    base->TCR &= ~CTIMER_TCR_CRST_MASK;
}

#if defined(__cplusplus)
}
#endif

/*! @}*/

#endif /* _FSL_CTIMER_H_ */