1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2021, 2022 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8 #ifndef FSL_TPM_H_
9 #define FSL_TPM_H_
10
11 #include "fsl_common.h"
12
13 /*
14 * $Coverage Justification Reference$
15 *
16 * $Justification tpm_h_ref_1$
17 * Hardware limitations make this code impossible to implement.
18 *
19 */
20
21 /*!
22 * @addtogroup tpm
23 * @{
24 */
25
26 /*******************************************************************************
27 * Definitions
28 ******************************************************************************/
29
30 /*! @name Driver version */
31 /*! @{ */
32 /*! @brief TPM driver version 2.3.1. */
33 #define FSL_TPM_DRIVER_VERSION (MAKE_VERSION(2, 3, 1))
34 /*! @} */
35
36 /*! @brief Help macro to get the max counter value */
37 #define TPM_MAX_COUNTER_VALUE(x) ((1U != (uint8_t)FSL_FEATURE_TPM_HAS_32BIT_COUNTERn(x)) ? 0xFFFFU : 0xFFFFFFFFU)
38
39 /*!
40 * @brief List of TPM channels.
41 * @note Actual number of available channels is SoC dependent
42 */
43 typedef enum _tpm_chnl
44 {
45 kTPM_Chnl_0 = 0U, /*!< TPM channel number 0*/
46 kTPM_Chnl_1, /*!< TPM channel number 1 */
47 kTPM_Chnl_2, /*!< TPM channel number 2 */
48 kTPM_Chnl_3, /*!< TPM channel number 3 */
49 kTPM_Chnl_4, /*!< TPM channel number 4 */
50 kTPM_Chnl_5, /*!< TPM channel number 5 */
51 kTPM_Chnl_6, /*!< TPM channel number 6 */
52 kTPM_Chnl_7 /*!< TPM channel number 7 */
53 } tpm_chnl_t;
54
55 /*! @brief TPM PWM operation modes */
56 typedef enum _tpm_pwm_mode
57 {
58 kTPM_EdgeAlignedPwm = 0U, /*!< Edge aligned PWM */
59 kTPM_CenterAlignedPwm, /*!< Center aligned PWM */
60 #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
61 kTPM_CombinedPwm /*!< Combined PWM (Edge-aligned, center-aligned, or asymmetrical PWMs can be obtained in combined
62 mode using different software configurations) */
63 #endif
64 } tpm_pwm_mode_t;
65
66 /*!
67 * @brief TPM PWM output pulse mode: high-true, low-true or no output
68 *
69 * @note When the TPM has PWM pause level select feature, the PWM output cannot be turned off by selecting the output
70 * level. In this case, the channel must be closed to close the PWM output.
71 */
72 typedef enum _tpm_pwm_level_select
73 {
74 #if !(defined(FSL_FEATURE_TPM_HAS_PAUSE_LEVEL_SELECT) && FSL_FEATURE_TPM_HAS_PAUSE_LEVEL_SELECT)
75 kTPM_NoPwmSignal = 0U, /*!< No PWM output on pin */
76 kTPM_LowTrue, /*!< Low true pulses */
77 kTPM_HighTrue /*!< High true pulses */
78 #else
79 kTPM_HighTrue = 0U, /*!< High true pulses */
80 kTPM_LowTrue /*!< Low true pulses */
81 #endif
82 } tpm_pwm_level_select_t;
83
84 #if (defined(FSL_FEATURE_TPM_HAS_PAUSE_LEVEL_SELECT) && FSL_FEATURE_TPM_HAS_PAUSE_LEVEL_SELECT)
85 /*! @brief TPM PWM output when first enabled or paused: set or clear */
86 typedef enum _tpm_pwm_pause_level_select
87 {
88 kTPM_ClearOnPause = 0U, /*!< Clear Output when counter first enabled or paused. */
89 kTPM_SetOnPause /*!< Set Output when counter first enabled or paused. */
90 } tpm_pwm_pause_level_select_t;
91 #endif
92
93 /*! @brief List of TPM channel modes and level control bit mask */
94 typedef enum _tpm_chnl_control_bit_mask
95 {
96 kTPM_ChnlELSnAMask = TPM_CnSC_ELSA_MASK, /*!< Channel ELSA bit mask.*/
97 kTPM_ChnlELSnBMask = TPM_CnSC_ELSB_MASK, /*!< Channel ELSB bit mask.*/
98 kTPM_ChnlMSAMask = TPM_CnSC_MSA_MASK, /*!< Channel MSA bit mask.*/
99 kTPM_ChnlMSBMask = TPM_CnSC_MSB_MASK, /*!< Channel MSB bit mask.*/
100 } tpm_chnl_control_bit_mask_t;
101
102 /*! @brief Options to configure a TPM channel's PWM signal */
103 typedef struct _tpm_chnl_pwm_signal_param
104 {
105 tpm_chnl_t chnlNumber; /*!< TPM channel to configure.
106 In combined mode (available in some SoC's), this represents the
107 channel pair number */
108 #if (defined(FSL_FEATURE_TPM_HAS_PAUSE_LEVEL_SELECT) && FSL_FEATURE_TPM_HAS_PAUSE_LEVEL_SELECT)
109 tpm_pwm_pause_level_select_t pauseLevel; /*!< PWM output level when counter first enabled or paused */
110 #endif
111 tpm_pwm_level_select_t level; /*!< PWM output active level select */
112 uint8_t dutyCyclePercent; /*!< PWM pulse width, value should be between 0 to 100
113 0=inactive signal(0% duty cycle)...
114 100=always active signal (100% duty cycle)*/
115 #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
116 uint8_t firstEdgeDelayPercent; /*!< Used only in combined PWM mode to generate asymmetrical PWM.
117 Specifies the delay to the first edge in a PWM period.
118 If unsure, leave as 0. Should be specified as percentage
119 of the PWM period, (dutyCyclePercent + firstEdgeDelayPercent) value
120 should be not greate than 100. */
121 bool enableComplementary; /*!< Used only in combined PWM mode.
122 true: The combined channels output complementary signals;
123 false: The combined channels output same signals; */
124 #if (defined(FSL_FEATURE_TPM_HAS_PAUSE_LEVEL_SELECT) && FSL_FEATURE_TPM_HAS_PAUSE_LEVEL_SELECT)
125 tpm_pwm_pause_level_select_t secPauseLevel; /*!< Used only in combined PWM mode. Define the second channel output
126 level when counter first enabled or paused */
127 #endif
128 uint8_t deadTimeValue[2]; /*!< The dead time value for channel n and n+1 in combined complementary PWM mode.
129 Deadtime insertion is disabled when this value is zero, otherwise deadtime insertion for
130 channel n/n+1 is configured as (deadTimeValue * 4) clock cycles. deadTimeValue's
131 available range is 0 ~ 15. */
132 #endif
133 } tpm_chnl_pwm_signal_param_t;
134
135 #if !(defined(FSL_FEATURE_TPM_HAS_NO_CONF) && FSL_FEATURE_TPM_HAS_NO_CONF)
136 /*!
137 * @brief Trigger sources available.
138 *
139 * This is used for both internal & external trigger sources (external trigger sources available in certain SoC's)
140 *
141 * @note The actual trigger sources available is SoC-specific.
142 */
143 typedef enum _tpm_trigger_select
144 {
145 kTPM_Trigger_Select_0 = 0U,
146 kTPM_Trigger_Select_1,
147 kTPM_Trigger_Select_2,
148 kTPM_Trigger_Select_3,
149 kTPM_Trigger_Select_4,
150 kTPM_Trigger_Select_5,
151 kTPM_Trigger_Select_6,
152 kTPM_Trigger_Select_7,
153 kTPM_Trigger_Select_8,
154 kTPM_Trigger_Select_9,
155 kTPM_Trigger_Select_10,
156 kTPM_Trigger_Select_11,
157 kTPM_Trigger_Select_12,
158 kTPM_Trigger_Select_13,
159 kTPM_Trigger_Select_14,
160 kTPM_Trigger_Select_15
161 } tpm_trigger_select_t;
162
163 #if defined(FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION) && FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
164 /*!
165 * @brief Trigger source options available
166 *
167 * @note This selection is available only on some SoC's. For SoC's without this selection, the only
168 * trigger source available is internal triger.
169 */
170 typedef enum _tpm_trigger_source
171 {
172 kTPM_TriggerSource_External = 0U, /*!< Use external trigger input */
173 kTPM_TriggerSource_Internal /*!< Use internal trigger (channel pin input capture) */
174 } tpm_trigger_source_t;
175
176 /*!
177 * @brief External trigger source polarity
178 *
179 * @note Selects the polarity of the external trigger source.
180 */
181 typedef enum _tpm_ext_trigger_polarity
182 {
183 kTPM_ExtTrigger_Active_High = 0U, /*!< External trigger input is active high */
184 kTPM_ExtTrigger_Active_Low /*!< External trigger input is active low */
185 } tpm_ext_trigger_polarity_t;
186 #endif
187 #endif
188
189 /*! @brief TPM output compare modes */
190 typedef enum _tpm_output_compare_mode
191 {
192 kTPM_NoOutputSignal = (1U << TPM_CnSC_MSA_SHIFT), /*!< No channel output when counter reaches CnV */
193 kTPM_ToggleOnMatch = ((1U << TPM_CnSC_MSA_SHIFT) | (1U << TPM_CnSC_ELSA_SHIFT)), /*!< Toggle output */
194 kTPM_ClearOnMatch = ((1U << TPM_CnSC_MSA_SHIFT) | (2U << TPM_CnSC_ELSA_SHIFT)), /*!< Clear output */
195 kTPM_SetOnMatch = ((1U << TPM_CnSC_MSA_SHIFT) | (3U << TPM_CnSC_ELSA_SHIFT)), /*!< Set output */
196 kTPM_HighPulseOutput = ((3U << TPM_CnSC_MSA_SHIFT) | (1U << TPM_CnSC_ELSA_SHIFT)), /*!< Pulse output high */
197 kTPM_LowPulseOutput = ((3U << TPM_CnSC_MSA_SHIFT) | (2U << TPM_CnSC_ELSA_SHIFT)) /*!< Pulse output low */
198 } tpm_output_compare_mode_t;
199
200 /*! @brief TPM input capture edge */
201 typedef enum _tpm_input_capture_edge
202 {
203 kTPM_RisingEdge = (1U << TPM_CnSC_ELSA_SHIFT), /*!< Capture on rising edge only */
204 kTPM_FallingEdge = (2U << TPM_CnSC_ELSA_SHIFT), /*!< Capture on falling edge only */
205 kTPM_RiseAndFallEdge = (3U << TPM_CnSC_ELSA_SHIFT) /*!< Capture on rising or falling edge */
206 } tpm_input_capture_edge_t;
207
208 #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
209 /*!
210 * @brief TPM dual edge capture parameters
211 *
212 * @note This mode is available only on some SoC's.
213 */
214 typedef struct _tpm_dual_edge_capture_param
215 {
216 bool enableSwap; /*!< true: Use channel n+1 input, channel n input is ignored;
217 false: Use channel n input, channel n+1 input is ignored */
218 tpm_input_capture_edge_t currChanEdgeMode; /*!< Input capture edge select for channel n */
219 tpm_input_capture_edge_t nextChanEdgeMode; /*!< Input capture edge select for channel n+1 */
220 } tpm_dual_edge_capture_param_t;
221 #endif
222
223 #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
224 /*!
225 * @brief TPM quadrature decode modes
226 *
227 * @note This mode is available only on some SoC's.
228 */
229 typedef enum _tpm_quad_decode_mode
230 {
231 kTPM_QuadPhaseEncode = 0U, /*!< Phase A and Phase B encoding mode */
232 kTPM_QuadCountAndDir /*!< Count and direction encoding mode */
233 } tpm_quad_decode_mode_t;
234
235 /*! @brief TPM quadrature phase polarities */
236 typedef enum _tpm_phase_polarity
237 {
238 kTPM_QuadPhaseNormal = 0U, /*!< Phase input signal is not inverted */
239 kTPM_QuadPhaseInvert /*!< Phase input signal is inverted */
240 } tpm_phase_polarity_t;
241
242 /*! @brief TPM quadrature decode phase parameters */
243 typedef struct _tpm_phase_param
244 {
245 uint32_t phaseFilterVal; /*!< Filter value, filter is disabled when the value is zero */
246 tpm_phase_polarity_t phasePolarity; /*!< Phase polarity */
247 } tpm_phase_params_t;
248 #endif
249
250 /*! @brief TPM clock source selection*/
251 typedef enum _tpm_clock_source
252 {
253 kTPM_SystemClock = 1U, /*!< System clock */
254 #if defined(FSL_FEATURE_TPM_HAS_SC_CLKS) && FSL_FEATURE_TPM_HAS_SC_CLKS
255 kTPM_FixedClock, /*!< Fixed frequency clock */
256 #endif
257 kTPM_ExternalClock, /*!< External TPM_EXTCLK pin clock */
258 #if defined(FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION) && FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
259 kTPM_ExternalInputTriggerClock /*!< Selected external input trigger clock */
260 #endif
261 } tpm_clock_source_t;
262
263 /*! @brief TPM prescale value selection for the clock source*/
264 typedef enum _tpm_clock_prescale
265 {
266 kTPM_Prescale_Divide_1 = 0U, /*!< Divide by 1 */
267 kTPM_Prescale_Divide_2, /*!< Divide by 2 */
268 kTPM_Prescale_Divide_4, /*!< Divide by 4 */
269 kTPM_Prescale_Divide_8, /*!< Divide by 8 */
270 kTPM_Prescale_Divide_16, /*!< Divide by 16 */
271 kTPM_Prescale_Divide_32, /*!< Divide by 32 */
272 kTPM_Prescale_Divide_64, /*!< Divide by 64 */
273 kTPM_Prescale_Divide_128 /*!< Divide by 128 */
274 } tpm_clock_prescale_t;
275
276 /*!
277 * @brief TPM config structure
278 *
279 * This structure holds the configuration settings for the TPM peripheral. To initialize this
280 * structure to reasonable defaults, call the TPM_GetDefaultConfig() function and pass a
281 * pointer to your config structure instance.
282 *
283 * The config struct can be made const so it resides in flash
284 */
285 typedef struct _tpm_config
286 {
287 tpm_clock_prescale_t prescale; /*!< Select TPM clock prescale value */
288 #if !(defined(FSL_FEATURE_TPM_HAS_NO_CONF) && FSL_FEATURE_TPM_HAS_NO_CONF)
289 bool useGlobalTimeBase; /*!< true: The TPM channels use an external global time base (the local counter still use
290 for generate overflow interrupt and DMA request);
291 false: All TPM channels use the local counter as their timebase */
292 bool syncGlobalTimeBase; /*!< true: The TPM counter is synchronized to the global time base;
293 false: disabled */
294 tpm_trigger_select_t triggerSelect; /*!< Input trigger to use for controlling the counter operation */
295 #if defined(FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION) && FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
296 tpm_trigger_source_t triggerSource; /*!< Decides if we use external or internal trigger. */
297 tpm_ext_trigger_polarity_t
298 extTriggerPolarity; /*!< when using external trigger source, need selects the polarity of it. */
299 #endif
300 bool enableDoze; /*!< true: TPM counter is paused in doze mode;
301 false: TPM counter continues in doze mode */
302 bool enableDebugMode; /*!< true: TPM counter continues in debug mode;
303 false: TPM counter is paused in debug mode */
304 bool enableReloadOnTrigger; /*!< true: TPM counter is reloaded on trigger;
305 false: TPM counter not reloaded */
306 bool enableStopOnOverflow; /*!< true: TPM counter stops after overflow;
307 false: TPM counter continues running after overflow */
308 bool enableStartOnTrigger; /*!< true: TPM counter only starts when a trigger is detected;
309 false: TPM counter starts immediately */
310 #if defined(FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER) && FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER
311 bool enablePauseOnTrigger; /*!< true: TPM counter will pause while trigger remains asserted;
312 false: TPM counter continues running */
313 #endif
314 #if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL
315 uint8_t chnlPolarity; /*!< Defines the input/output polarity of the channels in POL register */
316 #endif
317 #endif
318 } tpm_config_t;
319
320 /*! @brief List of TPM interrupts */
321 typedef enum _tpm_interrupt_enable
322 {
323 kTPM_Chnl0InterruptEnable = (1U << 0), /*!< Channel 0 interrupt.*/
324 kTPM_Chnl1InterruptEnable = (1U << 1), /*!< Channel 1 interrupt.*/
325 kTPM_Chnl2InterruptEnable = (1U << 2), /*!< Channel 2 interrupt.*/
326 kTPM_Chnl3InterruptEnable = (1U << 3), /*!< Channel 3 interrupt.*/
327 kTPM_Chnl4InterruptEnable = (1U << 4), /*!< Channel 4 interrupt.*/
328 kTPM_Chnl5InterruptEnable = (1U << 5), /*!< Channel 5 interrupt.*/
329 kTPM_Chnl6InterruptEnable = (1U << 6), /*!< Channel 6 interrupt.*/
330 kTPM_Chnl7InterruptEnable = (1U << 7), /*!< Channel 7 interrupt.*/
331 kTPM_TimeOverflowInterruptEnable = (1U << 8) /*!< Time overflow interrupt.*/
332 } tpm_interrupt_enable_t;
333
334 /*! @brief List of TPM flags */
335 typedef enum _tpm_status_flags
336 {
337 kTPM_Chnl0Flag = (1U << 0), /*!< Channel 0 flag */
338 kTPM_Chnl1Flag = (1U << 1), /*!< Channel 1 flag */
339 kTPM_Chnl2Flag = (1U << 2), /*!< Channel 2 flag */
340 kTPM_Chnl3Flag = (1U << 3), /*!< Channel 3 flag */
341 kTPM_Chnl4Flag = (1U << 4), /*!< Channel 4 flag */
342 kTPM_Chnl5Flag = (1U << 5), /*!< Channel 5 flag */
343 kTPM_Chnl6Flag = (1U << 6), /*!< Channel 6 flag */
344 kTPM_Chnl7Flag = (1U << 7), /*!< Channel 7 flag */
345 kTPM_TimeOverflowFlag = (1U << 8) /*!< Time overflow flag */
346 } tpm_status_flags_t;
347
348 /*!
349 * @brief TPM callback function pointer
350 *
351 * @param base TPM peripheral base address.
352 */
353 typedef void (*tpm_callback_t)(TPM_Type *base);
354
355 /*******************************************************************************
356 * API
357 ******************************************************************************/
358
359 #if defined(__cplusplus)
360 extern "C" {
361 #endif
362
363 /*!
364 * @name Initialization and deinitialization
365 * @{
366 */
367
368 /*!
369 * @brief Gets the instance from the base address
370 *
371 * @param base TPM peripheral base address
372 * @return The TPM instance
373 */
374 uint32_t TPM_GetInstance(TPM_Type *base);
375
376 /*!
377 * @brief Ungates the TPM clock and configures the peripheral for basic operation.
378 *
379 * @note This API should be called at the beginning of the application using the TPM driver.
380 *
381 * @param base TPM peripheral base address
382 * @param config Pointer to user's TPM config structure.
383 */
384 void TPM_Init(TPM_Type *base, const tpm_config_t *config);
385
386 /*!
387 * @brief Stops the counter and gates the TPM clock
388 *
389 * @param base TPM peripheral base address
390 */
391 void TPM_Deinit(TPM_Type *base);
392
393 /*!
394 * @brief Fill in the TPM config struct with the default settings
395 *
396 * The default values are:
397 * @code
398 * config->prescale = kTPM_Prescale_Divide_1;
399 * config->useGlobalTimeBase = false;
400 * config->syncGlobalTimeBase = false;
401 * config->dozeEnable = false;
402 * config->dbgMode = false;
403 * config->enableReloadOnTrigger = false;
404 * config->enableStopOnOverflow = false;
405 * config->enableStartOnTrigger = false;
406 *#if FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER
407 * config->enablePauseOnTrigger = false;
408 *#endif
409 * config->triggerSelect = kTPM_Trigger_Select_0;
410 *#if FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
411 * config->triggerSource = kTPM_TriggerSource_External;
412 * config->extTriggerPolarity = kTPM_ExtTrigger_Active_High;
413 *#endif
414 *#if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL
415 * config->chnlPolarity = 0U;
416 *#endif
417 * @endcode
418 * @param config Pointer to user's TPM config structure.
419 */
420 void TPM_GetDefaultConfig(tpm_config_t *config);
421
422 /*!
423 * @brief Calculates the counter clock prescaler.
424 *
425 * This function calculates the values for SC[PS].
426 *
427 * @param base TPM peripheral base address
428 * @param counterPeriod_Hz The desired frequency in Hz which corresponding to the time when the counter reaches the mod
429 * value
430 * @param srcClock_Hz TPM counter clock in Hz
431 *
432 * return Calculated clock prescaler value.
433 */
434 tpm_clock_prescale_t TPM_CalculateCounterClkDiv(TPM_Type *base, uint32_t counterPeriod_Hz, uint32_t srcClock_Hz);
435
436 /*! @}*/
437
438 /*!
439 * @name Channel mode operations
440 * @{
441 */
442
443 /*!
444 * @brief Configures the PWM signal parameters
445 *
446 * User calls this function to configure the PWM signals period, mode, dutycycle and edge. Use this
447 * function to configure all the TPM channels that will be used to output a PWM signal
448 *
449 * @param base TPM peripheral base address
450 * @param chnlParams Array of PWM channel parameters to configure the channel(s)
451 * @param numOfChnls Number of channels to configure, this should be the size of the array passed in
452 * @param mode PWM operation mode, options available in enumeration ::tpm_pwm_mode_t
453 * @param pwmFreq_Hz PWM signal frequency in Hz
454 * @param srcClock_Hz TPM counter clock in Hz
455 *
456 * @return kStatus_Success if the PWM setup was successful,
457 * kStatus_Error on failure
458 */
459 status_t TPM_SetupPwm(TPM_Type *base,
460 const tpm_chnl_pwm_signal_param_t *chnlParams,
461 uint8_t numOfChnls,
462 tpm_pwm_mode_t mode,
463 uint32_t pwmFreq_Hz,
464 uint32_t srcClock_Hz);
465
466 /*!
467 * @brief Update the duty cycle of an active PWM signal
468 *
469 * @param base TPM peripheral base address
470 * @param chnlNumber The channel number. In combined mode, this represents
471 * the channel pair number
472 * @param currentPwmMode The current PWM mode set during PWM setup
473 * @param dutyCyclePercent New PWM pulse width, value should be between 0 to 100
474 * 0=inactive signal(0% duty cycle)...
475 * 100=active signal (100% duty cycle)
476 * @return kStatus_Success if the PWM setup was successful,
477 * kStatus_Error on failure
478 */
479 status_t TPM_UpdatePwmDutycycle(TPM_Type *base,
480 tpm_chnl_t chnlNumber,
481 tpm_pwm_mode_t currentPwmMode,
482 uint8_t dutyCyclePercent);
483
484 /*!
485 * @brief Update the edge level selection for a channel
486 *
487 * @note When the TPM has PWM pause level select feature (FSL_FEATURE_TPM_HAS_PAUSE_LEVEL_SELECT = 1), the PWM output
488 * cannot be turned off by selecting the output level. In this case, must use TPM_DisableChannel API to close the
489 * PWM output.
490 *
491 * @param base TPM peripheral base address
492 * @param chnlNumber The channel number
493 * @param level The level to be set to the ELSnB:ELSnA field; valid values are 00, 01, 10, 11.
494 * See the appropriate SoC reference manual for details about this field.
495 */
496 void TPM_UpdateChnlEdgeLevelSelect(TPM_Type *base, tpm_chnl_t chnlNumber, uint8_t level);
497
498 /*!
499 * @brief Get the channel control bits value (mode, edge and level bit fileds).
500 *
501 * This function disable the channel by clear all mode and level control bits.
502 *
503 * @param base TPM peripheral base address
504 * @param chnlNumber The channel number
505 * @return The contorl bits value. This is the logical OR of members of the
506 * enumeration @ref tpm_chnl_control_bit_mask_t.
507 */
TPM_GetChannelContorlBits(TPM_Type * base,tpm_chnl_t chnlNumber)508 static inline uint8_t TPM_GetChannelContorlBits(TPM_Type *base, tpm_chnl_t chnlNumber)
509 {
510 return (uint8_t)(base->CONTROLS[chnlNumber].CnSC &
511 (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK));
512 }
513
514 /*!
515 * @brief Dsiable the channel.
516 *
517 * This function disable the channel by clear all mode and level control bits.
518 *
519 * @param base TPM peripheral base address
520 * @param chnlNumber The channel number
521 */
TPM_DisableChannel(TPM_Type * base,tpm_chnl_t chnlNumber)522 static inline void TPM_DisableChannel(TPM_Type *base, tpm_chnl_t chnlNumber)
523 {
524 do
525 {
526 /* Clear channel MSnB:MSnA and ELSnB:ELSnA to disable its output. */
527 base->CONTROLS[chnlNumber].CnSC &=
528 ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
529 /* Wait till mode change to disable channel is acknowledged */
530 /*
531 * $Branch Coverage Justification$
532 * (0U != (base->CONTROLS[chnlNumber].CnSC &
533 * (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
534 * not covered. $ref tpm_h_ref_1$.
535 */
536
537 } while (0U != (base->CONTROLS[chnlNumber].CnSC &
538 (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)));
539 }
540
541 /*!
542 * @brief Enable the channel according to mode and level configs.
543 *
544 * This function enable the channel output according to input mode/level config parameters.
545 *
546 * @param base TPM peripheral base address
547 * @param chnlNumber The channel number
548 * @param control The contorl bits value. This is the logical OR of members of the
549 * enumeration @ref tpm_chnl_control_bit_mask_t.
550 */
TPM_EnableChannel(TPM_Type * base,tpm_chnl_t chnlNumber,uint8_t control)551 static inline void TPM_EnableChannel(TPM_Type *base, tpm_chnl_t chnlNumber, uint8_t control)
552 {
553 #if defined(FSL_FEATURE_TPM_CnSC_CHF_WRITE_0_CLEAR) && FSL_FEATURE_TPM_CnSC_CHF_WRITE_0_CLEAR
554 control |= TPM_CnSC_CHF_MASK;
555 #endif
556
557 do
558 {
559 /* Set channel MSB:MSA and ELSB:ELSA bits. */
560 base->CONTROLS[chnlNumber].CnSC =
561 (base->CONTROLS[chnlNumber].CnSC &
562 ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)) |
563 (control & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK));
564 /* Wait till mode change is acknowledged */
565 /*
566 * $Branch Coverage Justification$
567 * ((control & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)) !=
568 * (uint8_t)(base->CONTROLS[chnlNumber].CnSC &
569 * (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
570 * not covered. $ref tpm_h_ref_1$.
571 */
572 } while ((control & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)) !=
573 (uint8_t)(base->CONTROLS[chnlNumber].CnSC &
574 (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)));
575 }
576
577 /*!
578 * @brief Enables capturing an input signal on the channel using the function parameters.
579 *
580 * When the edge specified in the captureMode argument occurs on the channel, the TPM counter is captured into
581 * the CnV register. The user has to read the CnV register separately to get this value.
582 *
583 * @param base TPM peripheral base address
584 * @param chnlNumber The channel number
585 * @param captureMode Specifies which edge to capture
586 */
587 void TPM_SetupInputCapture(TPM_Type *base, tpm_chnl_t chnlNumber, tpm_input_capture_edge_t captureMode);
588
589 /*!
590 * @brief Configures the TPM to generate timed pulses.
591 *
592 * When the TPM counter matches the value of compareVal argument (this is written into CnV reg), the channel
593 * output is changed based on what is specified in the compareMode argument.
594 *
595 * @param base TPM peripheral base address
596 * @param chnlNumber The channel number
597 * @param compareMode Action to take on the channel output when the compare condition is met
598 * @param compareValue Value to be programmed in the CnV register.
599 */
600 void TPM_SetupOutputCompare(TPM_Type *base,
601 tpm_chnl_t chnlNumber,
602 tpm_output_compare_mode_t compareMode,
603 uint32_t compareValue);
604
605 #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
606 /*!
607 * @brief Configures the dual edge capture mode of the TPM.
608 *
609 * This function allows to measure a pulse width of the signal on the input of channel of a
610 * channel pair. The filter function is disabled if the filterVal argument passed is zero.
611 *
612 * @param base TPM peripheral base address
613 * @param chnlPairNumber The TPM channel pair number; options are 0, 1, 2, 3
614 * @param edgeParam Sets up the dual edge capture function
615 * @param filterValue Filter value, specify 0 to disable filter.
616 */
617 void TPM_SetupDualEdgeCapture(TPM_Type *base,
618 tpm_chnl_t chnlPairNumber,
619 const tpm_dual_edge_capture_param_t *edgeParam,
620 uint32_t filterValue);
621 #endif
622
623 #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
624 /*!
625 * @brief Configures the parameters and activates the quadrature decode mode.
626 *
627 * @param base TPM peripheral base address
628 * @param phaseAParams Phase A configuration parameters
629 * @param phaseBParams Phase B configuration parameters
630 * @param quadMode Selects encoding mode used in quadrature decoder mode
631 */
632 void TPM_SetupQuadDecode(TPM_Type *base,
633 const tpm_phase_params_t *phaseAParams,
634 const tpm_phase_params_t *phaseBParams,
635 tpm_quad_decode_mode_t quadMode);
636 #endif
637
638 #if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL
639 /*!
640 * @brief Set the input and output polarity of each of the channels.
641 *
642 * @param base TPM peripheral base address
643 * @param chnlNumber The channel number
644 * @param enable true: Set the channel polarity to active high;
645 * false: Set the channel polarity to active low;
646 */
TPM_SetChannelPolarity(TPM_Type * base,tpm_chnl_t chnlNumber,bool enable)647 static inline void TPM_SetChannelPolarity(TPM_Type *base, tpm_chnl_t chnlNumber, bool enable)
648 {
649 assert(1U == (uint8_t)FSL_FEATURE_TPM_POL_HAS_EFFECTn(base));
650 if (enable)
651 {
652 base->POL &= ~((uint32_t)TPM_POL_POL0_MASK << (uint8_t)chnlNumber);
653 }
654 else
655 {
656 base->POL |= (uint32_t)TPM_POL_POL0_MASK << (uint8_t)chnlNumber;
657 }
658 }
659 #endif
660 #if defined(FSL_FEATURE_TPM_HAS_TRIG) && FSL_FEATURE_TPM_HAS_TRIG
661 /*!
662 * @brief Enable external trigger input to be used by channel.
663 *
664 * In input capture mode, configures the trigger input that is used by the channel to capture the
665 * counter value. In output compare or PWM mode, configures the trigger input used to modulate
666 * the channel output. When modulating the output, the output is forced to the channel initial
667 * value whenever the trigger is not asserted.
668 *
669 * @note No matter how many external trigger sources there are, only input trigger 0 and 1 are used. The even numbered
670 * channels share the input trigger 0 and the odd numbered channels share the second input trigger 1.
671 *
672 * @param base TPM peripheral base address
673 * @param chnlNumber The channel number
674 * @param enable true: Configures trigger input 0 or 1 to be used by channel;
675 * false: Trigger input has no effect on the channel
676 */
TPM_EnableChannelExtTrigger(TPM_Type * base,tpm_chnl_t chnlNumber,bool enable)677 static inline void TPM_EnableChannelExtTrigger(TPM_Type *base, tpm_chnl_t chnlNumber, bool enable)
678 {
679 assert(1U == (uint8_t)FSL_FEATURE_TPM_TRIG_HAS_EFFECTn(base));
680 if (enable)
681 {
682 base->TRIG |= (uint32_t)TPM_TRIG_TRIG0_MASK << (uint8_t)chnlNumber;
683 }
684 else
685 {
686 base->TRIG &= ~((uint32_t)TPM_TRIG_TRIG0_MASK << (uint8_t)chnlNumber);
687 }
688 }
689 #endif
690 /*! @}*/
691
692 /*!
693 * @name Interrupt Interface
694 * @{
695 */
696
697 /*!
698 * @brief Enables the selected TPM interrupts.
699 *
700 * @param base TPM peripheral base address
701 * @param mask The interrupts to enable. This is a logical OR of members of the
702 * enumeration ::tpm_interrupt_enable_t
703 */
704 void TPM_EnableInterrupts(TPM_Type *base, uint32_t mask);
705
706 /*!
707 * @brief Disables the selected TPM interrupts.
708 *
709 * @param base TPM peripheral base address
710 * @param mask The interrupts to disable. This is a logical OR of members of the
711 * enumeration ::tpm_interrupt_enable_t
712 */
713 void TPM_DisableInterrupts(TPM_Type *base, uint32_t mask);
714
715 /*!
716 * @brief Gets the enabled TPM interrupts.
717 *
718 * @param base TPM peripheral base address
719 *
720 * @return The enabled interrupts. This is the logical OR of members of the
721 * enumeration ::tpm_interrupt_enable_t
722 */
723 uint32_t TPM_GetEnabledInterrupts(TPM_Type *base);
724
725 /*!
726 * @brief Register callback.
727 *
728 * If channel or overflow interrupt is enabled by the user, then a callback can be registered
729 * which will be invoked when the interrupt is triggered.
730 *
731 * @param base TPM peripheral base address
732 * @param callback Callback function
733 */
734 void TPM_RegisterCallBack(TPM_Type *base, tpm_callback_t callback);
735
736 /*! @}*/
737
738 /*!
739 * @name Status Interface
740 * @{
741 */
742 /*!
743 * @brief Gets the TPM channel value
744 *
745 * @note The TPM channel value contain the captured TPM counter value for the input modes or the match value for the
746 * output modes.
747 *
748 * @param base TPM peripheral base address
749 * @param chnlNumber The channel number
750 * @return The channle CnV regisyer value.
751 */
TPM_GetChannelValue(TPM_Type * base,tpm_chnl_t chnlNumber)752 static inline uint32_t TPM_GetChannelValue(TPM_Type *base, tpm_chnl_t chnlNumber)
753 {
754 return base->CONTROLS[chnlNumber].CnV;
755 }
756
757 /*!
758 * @brief Gets the TPM status flags
759 *
760 * @param base TPM peripheral base address
761 *
762 * @return The status flags. This is the logical OR of members of the
763 * enumeration ::tpm_status_flags_t
764 */
TPM_GetStatusFlags(TPM_Type * base)765 static inline uint32_t TPM_GetStatusFlags(TPM_Type *base)
766 {
767 uint32_t statusFlags = 0;
768
769 #if defined(FSL_FEATURE_TPM_HAS_NO_STATUS) && FSL_FEATURE_TPM_HAS_NO_STATUS
770 uint8_t chanlNumber = 0;
771
772 /* Check the timer flag */
773 if (0U != (base->SC & TPM_SC_TOF_MASK))
774 {
775 statusFlags |= (uint32_t)kTPM_TimeOverflowFlag;
776 }
777
778 for (chanlNumber = 0; (int8_t)chanlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base); chanlNumber++)
779 {
780 /* Check the channel flag */
781 if (0U != (base->CONTROLS[chanlNumber].CnSC & TPM_CnSC_CHF_MASK))
782 {
783 statusFlags |= (1UL << chanlNumber);
784 }
785 }
786 #else
787 statusFlags = base->STATUS;
788 #endif
789
790 return statusFlags;
791 }
792
793 /*!
794 * @brief Clears the TPM status flags
795 *
796 * @param base TPM peripheral base address
797 * @param mask The status flags to clear. This is a logical OR of members of the
798 * enumeration ::tpm_status_flags_t
799 */
TPM_ClearStatusFlags(TPM_Type * base,uint32_t mask)800 static inline void TPM_ClearStatusFlags(TPM_Type *base, uint32_t mask)
801 {
802 #if defined(FSL_FEATURE_TPM_HAS_NO_STATUS) && FSL_FEATURE_TPM_HAS_NO_STATUS
803 uint32_t chnlStatusFlags = (mask & 0xFFU);
804 uint8_t chnlNumber = 0;
805
806 /* Clear the timer overflow flag by writing a 0 to the bit while it is set */
807 if (0U != (mask & (uint32_t)kTPM_TimeOverflowFlag))
808 {
809 base->SC &= ~TPM_SC_TOF_MASK;
810 }
811 /* Clear the channel flag */
812 while (0U != chnlStatusFlags)
813 {
814 if (0U != (chnlStatusFlags & 0x1U))
815 {
816 base->CONTROLS[chnlNumber].CnSC &= ~TPM_CnSC_CHF_MASK;
817 }
818 chnlNumber++;
819 chnlStatusFlags = chnlStatusFlags >> 1U;
820 }
821 #else
822 /* Clear the status flags */
823 base->STATUS = mask;
824 #endif
825 }
826
827 /*! @}*/
828
829 /*!
830 * @name Read and write the timer period
831 * @{
832 */
833
834 /*!
835 * @brief Sets the timer period in units of ticks.
836 *
837 * Timers counts from 0 until it equals the count value set here. The count value is written to
838 * the MOD register.
839 *
840 * @note
841 * 1. This API allows the user to use the TPM module as a timer. Do not mix usage
842 * of this API with TPM's PWM setup API's.
843 * 2. Call the utility macros provided in the fsl_common.h to convert usec or msec to ticks.
844 *
845 * @param base TPM peripheral base address
846 * @param ticks A timer period in units of ticks, which should be equal or greater than 1.
847 */
TPM_SetTimerPeriod(TPM_Type * base,uint32_t ticks)848 static inline void TPM_SetTimerPeriod(TPM_Type *base, uint32_t ticks)
849 {
850 if (1U != (uint8_t)FSL_FEATURE_TPM_HAS_32BIT_COUNTERn(base))
851 {
852 assert(ticks <= 0xFFFFU);
853 }
854 base->MOD = ticks;
855 }
856
857 /*!
858 * @brief Reads the current timer counting value.
859 *
860 * This function returns the real-time timer counting value in a range from 0 to a
861 * timer period.
862 *
863 * @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec.
864 *
865 * @param base TPM peripheral base address
866 *
867 * @return The current counter value in ticks
868 */
TPM_GetCurrentTimerCount(TPM_Type * base)869 static inline uint32_t TPM_GetCurrentTimerCount(TPM_Type *base)
870 {
871 return (uint32_t)((base->CNT & TPM_CNT_COUNT_MASK) >> TPM_CNT_COUNT_SHIFT);
872 }
873
874 /*!
875 * @name Timer Start and Stop
876 * @{
877 */
878
879 /*!
880 * @brief Starts the TPM counter.
881 *
882 * @param base TPM peripheral base address
883 * @param clockSource TPM clock source; once clock source is set the counter will start running
884 */
TPM_StartTimer(TPM_Type * base,tpm_clock_source_t clockSource)885 static inline void TPM_StartTimer(TPM_Type *base, tpm_clock_source_t clockSource)
886 {
887 uint32_t reg = base->SC;
888 #if defined(FSL_FEATURE_TPM_HAS_SC_CLKS) && FSL_FEATURE_TPM_HAS_SC_CLKS
889 reg &= ~(TPM_SC_CLKS_MASK);
890 reg |= TPM_SC_CLKS(clockSource);
891 #else
892 reg &= ~(TPM_SC_CMOD_MASK);
893 reg |= TPM_SC_CMOD(clockSource);
894 #endif
895 base->SC = reg;
896 }
897
898 /*!
899 * @brief Stops the TPM counter.
900 *
901 * @param base TPM peripheral base address
902 */
TPM_StopTimer(TPM_Type * base)903 static inline void TPM_StopTimer(TPM_Type *base)
904 {
905 #if defined(FSL_FEATURE_TPM_HAS_SC_CLKS) && FSL_FEATURE_TPM_HAS_SC_CLKS
906 /* Set clock source to none to disable counter */
907 base->SC &= ~(TPM_SC_CLKS_MASK);
908
909 /* Wait till this reads as zero acknowledging the counter is disabled */
910 while (0U != (base->SC & TPM_SC_CLKS_MASK))
911 {
912 }
913 #else
914 /* Set clock source to none to disable counter */
915 base->SC &= ~(TPM_SC_CMOD_MASK);
916
917 /* Wait till this reads as zero acknowledging the counter is disabled */
918 while (0U != (base->SC & TPM_SC_CMOD_MASK))
919 {
920 }
921 #endif
922 }
923
924 /*! @}*/
925
926 #if defined(FSL_FEATURE_TPM_HAS_GLOBAL) && FSL_FEATURE_TPM_HAS_GLOBAL
927 /*!
928 * @brief Performs a software reset on the TPM module.
929 *
930 * Reset all internal logic and registers, except the Global Register. Remains set until cleared by software.
931 *
932 * @note TPM software reset is available on certain SoC's only
933 *
934 * @param base TPM peripheral base address
935 */
TPM_Reset(TPM_Type * base)936 static inline void TPM_Reset(TPM_Type *base)
937 {
938 base->GLOBAL |= TPM_GLOBAL_RST_MASK;
939 base->GLOBAL &= ~TPM_GLOBAL_RST_MASK;
940 }
941 #endif
942
943 #if defined(__cplusplus)
944 }
945 #endif
946
947 /*! @}*/
948
949 #endif /* FSL_TPM_H_ */
950