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.2.1. */
33 #define FSL_TPM_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
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 * API
350 ******************************************************************************/
351
352 #if defined(__cplusplus)
353 extern "C" {
354 #endif
355
356 /*!
357 * @name Initialization and deinitialization
358 * @{
359 */
360
361 /*!
362 * @brief Ungates the TPM clock and configures the peripheral for basic operation.
363 *
364 * @note This API should be called at the beginning of the application using the TPM driver.
365 *
366 * @param base TPM peripheral base address
367 * @param config Pointer to user's TPM config structure.
368 */
369 void TPM_Init(TPM_Type *base, const tpm_config_t *config);
370
371 /*!
372 * @brief Stops the counter and gates the TPM clock
373 *
374 * @param base TPM peripheral base address
375 */
376 void TPM_Deinit(TPM_Type *base);
377
378 /*!
379 * @brief Fill in the TPM config struct with the default settings
380 *
381 * The default values are:
382 * @code
383 * config->prescale = kTPM_Prescale_Divide_1;
384 * config->useGlobalTimeBase = false;
385 * config->syncGlobalTimeBase = false;
386 * config->dozeEnable = false;
387 * config->dbgMode = false;
388 * config->enableReloadOnTrigger = false;
389 * config->enableStopOnOverflow = false;
390 * config->enableStartOnTrigger = false;
391 *#if FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER
392 * config->enablePauseOnTrigger = false;
393 *#endif
394 * config->triggerSelect = kTPM_Trigger_Select_0;
395 *#if FSL_FEATURE_TPM_HAS_EXTERNAL_TRIGGER_SELECTION
396 * config->triggerSource = kTPM_TriggerSource_External;
397 * config->extTriggerPolarity = kTPM_ExtTrigger_Active_High;
398 *#endif
399 *#if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL
400 * config->chnlPolarity = 0U;
401 *#endif
402 * @endcode
403 * @param config Pointer to user's TPM config structure.
404 */
405 void TPM_GetDefaultConfig(tpm_config_t *config);
406
407 /*!
408 * @brief Calculates the counter clock prescaler.
409 *
410 * This function calculates the values for SC[PS].
411 *
412 * @param base TPM peripheral base address
413 * @param counterPeriod_Hz The desired frequency in Hz which corresponding to the time when the counter reaches the mod
414 * value
415 * @param srcClock_Hz TPM counter clock in Hz
416 *
417 * return Calculated clock prescaler value.
418 */
419 tpm_clock_prescale_t TPM_CalculateCounterClkDiv(TPM_Type *base, uint32_t counterPeriod_Hz, uint32_t srcClock_Hz);
420
421 /*! @}*/
422
423 /*!
424 * @name Channel mode operations
425 * @{
426 */
427
428 /*!
429 * @brief Configures the PWM signal parameters
430 *
431 * User calls this function to configure the PWM signals period, mode, dutycycle and edge. Use this
432 * function to configure all the TPM channels that will be used to output a PWM signal
433 *
434 * @param base TPM peripheral base address
435 * @param chnlParams Array of PWM channel parameters to configure the channel(s)
436 * @param numOfChnls Number of channels to configure, this should be the size of the array passed in
437 * @param mode PWM operation mode, options available in enumeration ::tpm_pwm_mode_t
438 * @param pwmFreq_Hz PWM signal frequency in Hz
439 * @param srcClock_Hz TPM counter clock in Hz
440 *
441 * @return kStatus_Success if the PWM setup was successful,
442 * kStatus_Error on failure
443 */
444 status_t TPM_SetupPwm(TPM_Type *base,
445 const tpm_chnl_pwm_signal_param_t *chnlParams,
446 uint8_t numOfChnls,
447 tpm_pwm_mode_t mode,
448 uint32_t pwmFreq_Hz,
449 uint32_t srcClock_Hz);
450
451 /*!
452 * @brief Update the duty cycle of an active PWM signal
453 *
454 * @param base TPM peripheral base address
455 * @param chnlNumber The channel number. In combined mode, this represents
456 * the channel pair number
457 * @param currentPwmMode The current PWM mode set during PWM setup
458 * @param dutyCyclePercent New PWM pulse width, value should be between 0 to 100
459 * 0=inactive signal(0% duty cycle)...
460 * 100=active signal (100% duty cycle)
461 * @return kStatus_Success if the PWM setup was successful,
462 * kStatus_Error on failure
463 */
464 status_t TPM_UpdatePwmDutycycle(TPM_Type *base,
465 tpm_chnl_t chnlNumber,
466 tpm_pwm_mode_t currentPwmMode,
467 uint8_t dutyCyclePercent);
468
469 /*!
470 * @brief Update the edge level selection for a channel
471 *
472 * @note When the TPM has PWM pause level select feature (FSL_FEATURE_TPM_HAS_PAUSE_LEVEL_SELECT = 1), the PWM output
473 * cannot be turned off by selecting the output level. In this case, must use TPM_DisableChannel API to close the
474 * PWM output.
475 *
476 * @param base TPM peripheral base address
477 * @param chnlNumber The channel number
478 * @param level The level to be set to the ELSnB:ELSnA field; valid values are 00, 01, 10, 11.
479 * See the appropriate SoC reference manual for details about this field.
480 */
481 void TPM_UpdateChnlEdgeLevelSelect(TPM_Type *base, tpm_chnl_t chnlNumber, uint8_t level);
482
483 /*!
484 * @brief Get the channel control bits value (mode, edge and level bit fileds).
485 *
486 * This function disable the channel by clear all mode and level control bits.
487 *
488 * @param base TPM peripheral base address
489 * @param chnlNumber The channel number
490 * @return The contorl bits value. This is the logical OR of members of the
491 * enumeration @ref tpm_chnl_control_bit_mask_t.
492 */
TPM_GetChannelContorlBits(TPM_Type * base,tpm_chnl_t chnlNumber)493 static inline uint8_t TPM_GetChannelContorlBits(TPM_Type *base, tpm_chnl_t chnlNumber)
494 {
495 return (uint8_t)(base->CONTROLS[chnlNumber].CnSC &
496 (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK));
497 }
498
499 /*!
500 * @brief Dsiable the channel.
501 *
502 * This function disable the channel by clear all mode and level control bits.
503 *
504 * @param base TPM peripheral base address
505 * @param chnlNumber The channel number
506 */
TPM_DisableChannel(TPM_Type * base,tpm_chnl_t chnlNumber)507 static inline void TPM_DisableChannel(TPM_Type *base, tpm_chnl_t chnlNumber)
508 {
509 do
510 {
511 /* Clear channel MSnB:MSnA and ELSnB:ELSnA to disable its output. */
512 base->CONTROLS[chnlNumber].CnSC &=
513 ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK);
514 /* Wait till mode change to disable channel is acknowledged */
515 /*
516 * $Branch Coverage Justification$
517 * (0U != (base->CONTROLS[chnlNumber].CnSC &
518 * (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
519 * not covered. $ref tpm_h_ref_1$.
520 */
521
522 } while (0U != (base->CONTROLS[chnlNumber].CnSC &
523 (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)));
524 }
525
526 /*!
527 * @brief Enable the channel according to mode and level configs.
528 *
529 * This function enable the channel output according to input mode/level config parameters.
530 *
531 * @param base TPM peripheral base address
532 * @param chnlNumber The channel number
533 * @param control The contorl bits value. This is the logical OR of members of the
534 * enumeration @ref tpm_chnl_control_bit_mask_t.
535 */
TPM_EnableChannel(TPM_Type * base,tpm_chnl_t chnlNumber,uint8_t control)536 static inline void TPM_EnableChannel(TPM_Type *base, tpm_chnl_t chnlNumber, uint8_t control)
537 {
538 #if defined(FSL_FEATURE_TPM_CnSC_CHF_WRITE_0_CLEAR) && FSL_FEATURE_TPM_CnSC_CHF_WRITE_0_CLEAR
539 control |= TPM_CnSC_CHF_MASK;
540 #endif
541
542 do
543 {
544 /* Set channel MSB:MSA and ELSB:ELSA bits. */
545 base->CONTROLS[chnlNumber].CnSC =
546 (base->CONTROLS[chnlNumber].CnSC &
547 ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)) |
548 (control & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK));
549 /* Wait till mode change is acknowledged */
550 /*
551 * $Branch Coverage Justification$
552 * ((control & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)) !=
553 * (uint8_t)(base->CONTROLS[chnlNumber].CnSC &
554 * (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)))
555 * not covered. $ref tpm_h_ref_1$.
556 */
557 } while ((control & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)) !=
558 (uint8_t)(base->CONTROLS[chnlNumber].CnSC &
559 (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK)));
560 }
561
562 /*!
563 * @brief Enables capturing an input signal on the channel using the function parameters.
564 *
565 * When the edge specified in the captureMode argument occurs on the channel, the TPM counter is captured into
566 * the CnV register. The user has to read the CnV register separately to get this value.
567 *
568 * @param base TPM peripheral base address
569 * @param chnlNumber The channel number
570 * @param captureMode Specifies which edge to capture
571 */
572 void TPM_SetupInputCapture(TPM_Type *base, tpm_chnl_t chnlNumber, tpm_input_capture_edge_t captureMode);
573
574 /*!
575 * @brief Configures the TPM to generate timed pulses.
576 *
577 * When the TPM counter matches the value of compareVal argument (this is written into CnV reg), the channel
578 * output is changed based on what is specified in the compareMode argument.
579 *
580 * @param base TPM peripheral base address
581 * @param chnlNumber The channel number
582 * @param compareMode Action to take on the channel output when the compare condition is met
583 * @param compareValue Value to be programmed in the CnV register.
584 */
585 void TPM_SetupOutputCompare(TPM_Type *base,
586 tpm_chnl_t chnlNumber,
587 tpm_output_compare_mode_t compareMode,
588 uint32_t compareValue);
589
590 #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE
591 /*!
592 * @brief Configures the dual edge capture mode of the TPM.
593 *
594 * This function allows to measure a pulse width of the signal on the input of channel of a
595 * channel pair. The filter function is disabled if the filterVal argument passed is zero.
596 *
597 * @param base TPM peripheral base address
598 * @param chnlPairNumber The TPM channel pair number; options are 0, 1, 2, 3
599 * @param edgeParam Sets up the dual edge capture function
600 * @param filterValue Filter value, specify 0 to disable filter.
601 */
602 void TPM_SetupDualEdgeCapture(TPM_Type *base,
603 tpm_chnl_t chnlPairNumber,
604 const tpm_dual_edge_capture_param_t *edgeParam,
605 uint32_t filterValue);
606 #endif
607
608 #if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL
609 /*!
610 * @brief Configures the parameters and activates the quadrature decode mode.
611 *
612 * @param base TPM peripheral base address
613 * @param phaseAParams Phase A configuration parameters
614 * @param phaseBParams Phase B configuration parameters
615 * @param quadMode Selects encoding mode used in quadrature decoder mode
616 */
617 void TPM_SetupQuadDecode(TPM_Type *base,
618 const tpm_phase_params_t *phaseAParams,
619 const tpm_phase_params_t *phaseBParams,
620 tpm_quad_decode_mode_t quadMode);
621 #endif
622
623 #if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL
624 /*!
625 * @brief Set the input and output polarity of each of the channels.
626 *
627 * @param base TPM peripheral base address
628 * @param chnlNumber The channel number
629 * @param enable true: Set the channel polarity to active high;
630 * false: Set the channel polarity to active low;
631 */
TPM_SetChannelPolarity(TPM_Type * base,tpm_chnl_t chnlNumber,bool enable)632 static inline void TPM_SetChannelPolarity(TPM_Type *base, tpm_chnl_t chnlNumber, bool enable)
633 {
634 assert(1U == (uint8_t)FSL_FEATURE_TPM_POL_HAS_EFFECTn(base));
635 if (enable)
636 {
637 base->POL &= ~((uint32_t)TPM_POL_POL0_MASK << (uint8_t)chnlNumber);
638 }
639 else
640 {
641 base->POL |= (uint32_t)TPM_POL_POL0_MASK << (uint8_t)chnlNumber;
642 }
643 }
644 #endif
645 #if defined(FSL_FEATURE_TPM_HAS_TRIG) && FSL_FEATURE_TPM_HAS_TRIG
646 /*!
647 * @brief Enable external trigger input to be used by channel.
648 *
649 * In input capture mode, configures the trigger input that is used by the channel to capture the
650 * counter value. In output compare or PWM mode, configures the trigger input used to modulate
651 * the channel output. When modulating the output, the output is forced to the channel initial
652 * value whenever the trigger is not asserted.
653 *
654 * @note No matter how many external trigger sources there are, only input trigger 0 and 1 are used. The even numbered
655 * channels share the input trigger 0 and the odd numbered channels share the second input trigger 1.
656 *
657 * @param base TPM peripheral base address
658 * @param chnlNumber The channel number
659 * @param enable true: Configures trigger input 0 or 1 to be used by channel;
660 * false: Trigger input has no effect on the channel
661 */
TPM_EnableChannelExtTrigger(TPM_Type * base,tpm_chnl_t chnlNumber,bool enable)662 static inline void TPM_EnableChannelExtTrigger(TPM_Type *base, tpm_chnl_t chnlNumber, bool enable)
663 {
664 assert(1U == (uint8_t)FSL_FEATURE_TPM_TRIG_HAS_EFFECTn(base));
665 if (enable)
666 {
667 base->TRIG |= (uint32_t)TPM_TRIG_TRIG0_MASK << (uint8_t)chnlNumber;
668 }
669 else
670 {
671 base->TRIG &= ~((uint32_t)TPM_TRIG_TRIG0_MASK << (uint8_t)chnlNumber);
672 }
673 }
674 #endif
675 /*! @}*/
676
677 /*!
678 * @name Interrupt Interface
679 * @{
680 */
681
682 /*!
683 * @brief Enables the selected TPM interrupts.
684 *
685 * @param base TPM peripheral base address
686 * @param mask The interrupts to enable. This is a logical OR of members of the
687 * enumeration ::tpm_interrupt_enable_t
688 */
689 void TPM_EnableInterrupts(TPM_Type *base, uint32_t mask);
690
691 /*!
692 * @brief Disables the selected TPM interrupts.
693 *
694 * @param base TPM peripheral base address
695 * @param mask The interrupts to disable. This is a logical OR of members of the
696 * enumeration ::tpm_interrupt_enable_t
697 */
698 void TPM_DisableInterrupts(TPM_Type *base, uint32_t mask);
699
700 /*!
701 * @brief Gets the enabled TPM interrupts.
702 *
703 * @param base TPM peripheral base address
704 *
705 * @return The enabled interrupts. This is the logical OR of members of the
706 * enumeration ::tpm_interrupt_enable_t
707 */
708 uint32_t TPM_GetEnabledInterrupts(TPM_Type *base);
709
710 /*! @}*/
711
712 /*!
713 * @name Status Interface
714 * @{
715 */
716 /*!
717 * @brief Gets the TPM channel value
718 *
719 * @note The TPM channel value contain the captured TPM counter value for the input modes or the match value for the
720 * output modes.
721 *
722 * @param base TPM peripheral base address
723 * @param chnlNumber The channel number
724 * @return The channle CnV regisyer value.
725 */
TPM_GetChannelValue(TPM_Type * base,tpm_chnl_t chnlNumber)726 static inline uint32_t TPM_GetChannelValue(TPM_Type *base, tpm_chnl_t chnlNumber)
727 {
728 return base->CONTROLS[chnlNumber].CnV;
729 }
730
731 /*!
732 * @brief Gets the TPM status flags
733 *
734 * @param base TPM peripheral base address
735 *
736 * @return The status flags. This is the logical OR of members of the
737 * enumeration ::tpm_status_flags_t
738 */
TPM_GetStatusFlags(TPM_Type * base)739 static inline uint32_t TPM_GetStatusFlags(TPM_Type *base)
740 {
741 uint32_t statusFlags = 0;
742
743 #if defined(FSL_FEATURE_TPM_HAS_NO_STATUS) && FSL_FEATURE_TPM_HAS_NO_STATUS
744 uint8_t chanlNumber = 0;
745
746 /* Check the timer flag */
747 if (0U != (base->SC & TPM_SC_TOF_MASK))
748 {
749 statusFlags |= (uint32_t)kTPM_TimeOverflowFlag;
750 }
751
752 for (chanlNumber = 0; (int8_t)chanlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base); chanlNumber++)
753 {
754 /* Check the channel flag */
755 if (0U != (base->CONTROLS[chanlNumber].CnSC & TPM_CnSC_CHF_MASK))
756 {
757 statusFlags |= (1UL << chanlNumber);
758 }
759 }
760 #else
761 statusFlags = base->STATUS;
762 #endif
763
764 return statusFlags;
765 }
766
767 /*!
768 * @brief Clears the TPM status flags
769 *
770 * @param base TPM peripheral base address
771 * @param mask The status flags to clear. This is a logical OR of members of the
772 * enumeration ::tpm_status_flags_t
773 */
TPM_ClearStatusFlags(TPM_Type * base,uint32_t mask)774 static inline void TPM_ClearStatusFlags(TPM_Type *base, uint32_t mask)
775 {
776 #if defined(FSL_FEATURE_TPM_HAS_NO_STATUS) && FSL_FEATURE_TPM_HAS_NO_STATUS
777 uint32_t chnlStatusFlags = (mask & 0xFFU);
778 uint8_t chnlNumber = 0;
779
780 /* Clear the timer overflow flag by writing a 0 to the bit while it is set */
781 if (0U != (mask & (uint32_t)kTPM_TimeOverflowFlag))
782 {
783 base->SC &= ~TPM_SC_TOF_MASK;
784 }
785 /* Clear the channel flag */
786 while (0U != chnlStatusFlags)
787 {
788 if (0U != (chnlStatusFlags & 0x1U))
789 {
790 base->CONTROLS[chnlNumber].CnSC &= ~TPM_CnSC_CHF_MASK;
791 }
792 chnlNumber++;
793 chnlStatusFlags = chnlStatusFlags >> 1U;
794 }
795 #else
796 /* Clear the status flags */
797 base->STATUS = mask;
798 #endif
799 }
800
801 /*! @}*/
802
803 /*!
804 * @name Read and write the timer period
805 * @{
806 */
807
808 /*!
809 * @brief Sets the timer period in units of ticks.
810 *
811 * Timers counts from 0 until it equals the count value set here. The count value is written to
812 * the MOD register.
813 *
814 * @note
815 * 1. This API allows the user to use the TPM module as a timer. Do not mix usage
816 * of this API with TPM's PWM setup API's.
817 * 2. Call the utility macros provided in the fsl_common.h to convert usec or msec to ticks.
818 *
819 * @param base TPM peripheral base address
820 * @param ticks A timer period in units of ticks, which should be equal or greater than 1.
821 */
TPM_SetTimerPeriod(TPM_Type * base,uint32_t ticks)822 static inline void TPM_SetTimerPeriod(TPM_Type *base, uint32_t ticks)
823 {
824 if (1U != (uint8_t)FSL_FEATURE_TPM_HAS_32BIT_COUNTERn(base))
825 {
826 assert(ticks <= 0xFFFFU);
827 }
828 base->MOD = ticks;
829 }
830
831 /*!
832 * @brief Reads the current timer counting value.
833 *
834 * This function returns the real-time timer counting value in a range from 0 to a
835 * timer period.
836 *
837 * @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec.
838 *
839 * @param base TPM peripheral base address
840 *
841 * @return The current counter value in ticks
842 */
TPM_GetCurrentTimerCount(TPM_Type * base)843 static inline uint32_t TPM_GetCurrentTimerCount(TPM_Type *base)
844 {
845 return (uint32_t)((base->CNT & TPM_CNT_COUNT_MASK) >> TPM_CNT_COUNT_SHIFT);
846 }
847
848 /*!
849 * @name Timer Start and Stop
850 * @{
851 */
852
853 /*!
854 * @brief Starts the TPM counter.
855 *
856 * @param base TPM peripheral base address
857 * @param clockSource TPM clock source; once clock source is set the counter will start running
858 */
TPM_StartTimer(TPM_Type * base,tpm_clock_source_t clockSource)859 static inline void TPM_StartTimer(TPM_Type *base, tpm_clock_source_t clockSource)
860 {
861 uint32_t reg = base->SC;
862 #if defined(FSL_FEATURE_TPM_HAS_SC_CLKS) && FSL_FEATURE_TPM_HAS_SC_CLKS
863 reg &= ~(TPM_SC_CLKS_MASK);
864 reg |= TPM_SC_CLKS(clockSource);
865 #else
866 reg &= ~(TPM_SC_CMOD_MASK);
867 reg |= TPM_SC_CMOD(clockSource);
868 #endif
869 base->SC = reg;
870 }
871
872 /*!
873 * @brief Stops the TPM counter.
874 *
875 * @param base TPM peripheral base address
876 */
TPM_StopTimer(TPM_Type * base)877 static inline void TPM_StopTimer(TPM_Type *base)
878 {
879 #if defined(FSL_FEATURE_TPM_HAS_SC_CLKS) && FSL_FEATURE_TPM_HAS_SC_CLKS
880 /* Set clock source to none to disable counter */
881 base->SC &= ~(TPM_SC_CLKS_MASK);
882
883 /* Wait till this reads as zero acknowledging the counter is disabled */
884 while (0U != (base->SC & TPM_SC_CLKS_MASK))
885 {
886 }
887 #else
888 /* Set clock source to none to disable counter */
889 base->SC &= ~(TPM_SC_CMOD_MASK);
890
891 /* Wait till this reads as zero acknowledging the counter is disabled */
892 while (0U != (base->SC & TPM_SC_CMOD_MASK))
893 {
894 }
895 #endif
896 }
897
898 /*! @}*/
899
900 #if defined(FSL_FEATURE_TPM_HAS_GLOBAL) && FSL_FEATURE_TPM_HAS_GLOBAL
901 /*!
902 * @brief Performs a software reset on the TPM module.
903 *
904 * Reset all internal logic and registers, except the Global Register. Remains set until cleared by software.
905 *
906 * @note TPM software reset is available on certain SoC's only
907 *
908 * @param base TPM peripheral base address
909 */
TPM_Reset(TPM_Type * base)910 static inline void TPM_Reset(TPM_Type *base)
911 {
912 base->GLOBAL |= TPM_GLOBAL_RST_MASK;
913 base->GLOBAL &= ~TPM_GLOBAL_RST_MASK;
914 }
915 #endif
916
917 #if defined(__cplusplus)
918 }
919 #endif
920
921 /*! @}*/
922
923 #endif /* _FSL_TPM_H_ */
924