1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2020 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8 #ifndef _FSL_PWM_H_
9 #define _FSL_PWM_H_
10
11 #include "fsl_common.h"
12
13 /*!
14 * @addtogroup pwm_driver
15 * @{
16 */
17
18 /*******************************************************************************
19 * Definitions
20 ******************************************************************************/
21
22 /*! @name Driver version */
23 /*@{*/
24 #define FSL_PWM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
25 /*@}*/
26
27 /*! @brief PWM clock source select. */
28 typedef enum _pwm_clock_source
29 {
30 kPWM_PeripheralClock = 1U, /*!< The Peripheral clock is used as the clock */
31 kPWM_HighFrequencyClock, /*!< High-frequency reference clock is used as the clock */
32 kPWM_LowFrequencyClock /*!< Low-frequency reference clock(32KHz) is used as the clock */
33 } pwm_clock_source_t;
34
35 /*!
36 * @brief PWM FIFO water mark select.
37 * Sets the data level at which the FIFO empty flag will be set
38 */
39 typedef enum _pwm_fifo_water_mark
40 {
41 kPWM_FIFOWaterMark_1 = 0U, /*!< FIFO empty flag is set when there are more than or equal to 1 empty slots */
42 kPWM_FIFOWaterMark_2, /*!< FIFO empty flag is set when there are more than or equal to 2 empty slots */
43 kPWM_FIFOWaterMark_3, /*!< FIFO empty flag is set when there are more than or equal to 3 empty slots */
44 kPWM_FIFOWaterMark_4 /*!< FIFO empty flag is set when there are more than or equal to 4 empty slots */
45 } pwm_fifo_water_mark_t;
46
47 /*!
48 * @brief PWM byte data swap select.
49 * It determines the byte ordering of the 16-bit data when it goes into the FIFO from the sample register.
50 */
51 typedef enum _pwm_byte_data_swap
52 {
53 kPWM_ByteNoSwap = 0U, /*!< byte ordering remains the same */
54 kPWM_ByteSwap /*!< byte ordering is reversed */
55 } pwm_byte_data_swap_t;
56
57 /*! @brief PWM half-word data swap select. */
58 typedef enum _pwm_half_word_data_swap
59 {
60 kPWM_HalfWordNoSwap = 0U, /*!< Half word swapping does not take place */
61 kPWM_HalfWordSwap /*!< Half word from write data bus are swapped */
62 } pwm_half_word_data_swap_t;
63
64 /*! @brief PWM Output Configuration */
65 typedef enum _pwm_output_configuration
66 {
67 kPWM_SetAtRolloverAndClearAtcomparison = 0U, /*!< Output pin is set at rollover and cleared at comparison */
68 kPWM_ClearAtRolloverAndSetAtcomparison, /*!< Output pin is cleared at rollover and set at comparison */
69 kPWM_NoConfigure /*!< PWM output is disconnected */
70 } pwm_output_configuration_t;
71
72 /*!
73 * @brief PWM FIFO sample repeat
74 * It determines the number of times each sample from the FIFO is to be used.
75 */
76 typedef enum _pwm_sample_repeat
77 {
78 kPWM_EachSampleOnce = 0u, /*!< Use each sample once */
79 kPWM_EachSampletwice, /*!< Use each sample twice */
80 kPWM_EachSampleFourTimes, /*!< Use each sample four times */
81 kPWM_EachSampleEightTimes /*!< Use each sample eight times */
82 } pwm_sample_repeat_t;
83
84 /*! @brief List of PWM interrupt options */
85 typedef enum _pwm_interrupt_enable
86 {
87 kPWM_FIFOEmptyInterruptEnable = (1U << 0), /*!< This bit controls the generation of the FIFO Empty interrupt. */
88 kPWM_RolloverInterruptEnable = (1U << 1), /*!< This bit controls the generation of the Rollover interrupt. */
89 kPWM_CompareInterruptEnable = (1U << 2) /*!< This bit controls the generation of the Compare interrupt */
90 } pwm_interrupt_enable_t;
91
92 /*! @brief List of PWM status flags */
93 typedef enum _pwm_status_flags
94 {
95 kPWM_FIFOEmptyFlag = (1U << 3), /*!< This bit indicates the FIFO data level in comparison to the water
96 level set by FWM field in the control register. */
97 kPWM_RolloverFlag = (1U << 4), /*!< This bit shows that a roll-over event has occurred. */
98 kPWM_CompareFlag = (1U << 5), /*!< This bit shows that a compare event has occurred. */
99 kPWM_FIFOWriteErrorFlag =
100 (1U << 6) /*!< This bit shows that an attempt has been made to write FIFO when it is full. */
101 } pwm_status_flags_t;
102
103 /*! @brief List of PWM FIFO available */
104 typedef enum _pwm_fifo_available
105 {
106 kPWM_NoDataInFIFOFlag = 0U, /*!< No data available */
107 kPWM_OneWordInFIFOFlag, /*!< 1 word of data in FIFO */
108 kPWM_TwoWordsInFIFOFlag, /*!< 2 word of data in FIFO */
109 kPWM_ThreeWordsInFIFOFlag, /*!< 3 word of data in FIFO */
110 kPWM_FourWordsInFIFOFlag /*!< 4 word of data in FIFO */
111 } pwm_fifo_available_t;
112
113 typedef struct _pwm_config
114 {
115 bool enableStopMode; /*!< True: PWM continues to run in stop mode;
116 False: PWM is paused in stop mode. */
117 bool enableDozeMode; /*!< True: PWM continues to run in doze mode;
118 False: PWM is paused in doze mode. */
119 bool enableWaitMode; /*!< True: PWM continues to run in wait mode;
120 False: PWM is paused in wait mode. */
121 bool enableDebugMode; /*!< True: PWM continues to run in debug mode;
122 False: PWM is paused in debug mode. */
123 uint16_t prescale; /*!< Pre-scaler to divide down the clock
124 The prescaler value is not more than 0xFFF. Divide by (value + 1)*/
125 pwm_clock_source_t clockSource; /*!< Clock source for the counter */
126 pwm_output_configuration_t outputConfig; /*!< Set the mode of the PWM output on the output pin. */
127 pwm_fifo_water_mark_t fifoWater; /*!< Set the data level for FIFO. */
128 pwm_sample_repeat_t sampleRepeat; /*!< The number of times each sample from the FIFO is to be used. */
129 pwm_byte_data_swap_t byteSwap; /*!< It determines the byte ordering of the 16-bit data when it goes into the
130 FIFO from the sample register. */
131 pwm_half_word_data_swap_t halfWordSwap; /*!< It determines which half word data from the 32-bit IP Bus interface is
132 written into the lower 16 bits of the sample register. */
133 } pwm_config_t;
134
135 /*******************************************************************************
136 * API
137 ******************************************************************************/
138
139 #if defined(__cplusplus)
140 extern "C" {
141 #endif
142
143 /*!
144 * @name Initialization and deinitialization
145 * @{
146 */
147
148 /*!
149 * @brief Ungates the PWM clock and configures the peripheral for basic operation.
150 *
151 * @note This API should be called at the beginning of the application using the PWM driver.
152 *
153 * @param base PWM peripheral base address
154 * @param config Pointer to user's PWM config structure.
155 *
156 * @return kStatus_Success means success; else failed.
157 */
158 status_t PWM_Init(PWM_Type *base, const pwm_config_t *config);
159
160 /*!
161 * @brief Gate the PWM submodule clock
162 *
163 * @param base PWM peripheral base address
164 */
165 void PWM_Deinit(PWM_Type *base);
166
167 /*!
168 * @brief Fill in the PWM config struct with the default settings
169 *
170 * The default values are:
171 * @code
172 * config->enableStopMode = false;
173 * config->enableDozeMode = false;
174 * config->enableWaitMode = false;
175 * config->enableDozeMode = false;
176 * config->clockSource = kPWM_LowFrequencyClock;
177 * config->prescale = 0U;
178 * config->outputConfig = kPWM_SetAtRolloverAndClearAtcomparison;
179 * config->fifoWater = kPWM_FIFOWaterMark_2;
180 * config->sampleRepeat = kPWM_EachSampleOnce;
181 * config->byteSwap = kPWM_ByteNoSwap;
182 * config->halfWordSwap = kPWM_HalfWordNoSwap;
183 * @endcode
184 * @param config Pointer to user's PWM config structure.
185 */
186 void PWM_GetDefaultConfig(pwm_config_t *config);
187
188 /*! @}*/
189
190 /*!
191 * @name PWM start and stop.
192 * @{
193 */
194
195 /*!
196 * @brief Starts the PWM counter when the PWM is enabled.
197 *
198 * When the PWM is enabled, it begins a new period, the output pin is set to start a new period while
199 * the prescaler and counter are released and counting begins.
200 *
201 * @param base PWM peripheral base address
202 */
PWM_StartTimer(PWM_Type * base)203 static inline void PWM_StartTimer(PWM_Type *base)
204 {
205 base->PWMCR |= PWM_PWMCR_EN_MASK;
206 }
207
208 /*!
209 * @brief Stops the PWM counter when the pwm is disabled.
210 *
211 * @param base PWM peripheral base address
212 */
PWM_StopTimer(PWM_Type * base)213 static inline void PWM_StopTimer(PWM_Type *base)
214 {
215 base->PWMCR &= ~(PWM_PWMCR_EN_MASK);
216 }
217
218 /*! @}*/
219
220 /*!
221 * @brief Sofrware reset.
222 *
223 * PWM is reset when this bit is set to 1. It is a self clearing bit.
224 * Setting this bit resets all the registers to their reset values except for the STOPEN,
225 * DOZEN, WAITEN, and DBGEN bits in this control register.
226 *
227 * @param base PWM peripheral base address
228 */
PWM_SoftwareReset(PWM_Type * base)229 static inline void PWM_SoftwareReset(PWM_Type *base)
230 {
231 base->PWMCR |= PWM_PWMCR_SWR_MASK;
232 }
233
234 /*!
235 * @name Interrupt Interface
236 * @{
237 */
238
239 /*!
240 * @brief Enables the selected PWM interrupts.
241 *
242 * @param base PWM peripheral base address
243 * @param mask The interrupts to enable. This is a logical OR of members of the
244 * enumeration ::pwm_interrupt_enable_t
245 */
PWM_EnableInterrupts(PWM_Type * base,uint32_t mask)246 static inline void PWM_EnableInterrupts(PWM_Type *base, uint32_t mask)
247 {
248 base->PWMIR |= (mask & (PWM_PWMIR_FIE_MASK | PWM_PWMIR_RIE_MASK | PWM_PWMIR_CIE_MASK));
249 }
250
251 /*!
252 * @brief Disables the selected PWM interrupts.
253 *
254 * @param base PWM peripheral base address
255 * @param mask The interrupts to disable. This is a logical OR of members of the
256 * enumeration ::pwm_interrupt_enable_t
257 */
PWM_DisableInterrupts(PWM_Type * base,uint32_t mask)258 static inline void PWM_DisableInterrupts(PWM_Type *base, uint32_t mask)
259 {
260 base->PWMIR &= ~(mask & (PWM_PWMIR_FIE_MASK | PWM_PWMIR_RIE_MASK | PWM_PWMIR_CIE_MASK));
261 }
262
263 /*!
264 * @brief Gets the enabled PWM interrupts.
265 *
266 * @param base PWM peripheral base address
267 *
268 * @return The enabled interrupts. This is the logical OR of members of the
269 * enumeration ::pwm_interrupt_enable_t
270 */
PWM_GetEnabledInterrupts(PWM_Type * base)271 static inline uint32_t PWM_GetEnabledInterrupts(PWM_Type *base)
272 {
273 return base->PWMIR;
274 }
275
276 /*! @}*/
277
278 /*!
279 * @name Status Interface
280 * @{
281 */
282
283 /*!
284 * @brief Gets the PWM status flags.
285 *
286 * @param base PWM peripheral base address
287 *
288 * @return The status flags. This is the logical OR of members of the
289 * enumeration ::pwm_status_flags_t
290 */
PWM_GetStatusFlags(PWM_Type * base)291 static inline uint32_t PWM_GetStatusFlags(PWM_Type *base)
292 {
293 uint32_t statusFlags = base->PWMSR;
294
295 statusFlags &= (PWM_PWMSR_FE_MASK | PWM_PWMSR_ROV_MASK | PWM_PWMSR_CMP_MASK | PWM_PWMSR_FWE_MASK);
296 return statusFlags;
297 }
298
299 /*!
300 * @brief Clears the PWM status flags.
301 *
302 * @param base PWM peripheral base address
303 * @param mask The status flags to clear. This is a logical OR of members of the
304 * enumeration ::pwm_status_flags_t
305 */
PWM_clearStatusFlags(PWM_Type * base,uint32_t mask)306 static inline void PWM_clearStatusFlags(PWM_Type *base, uint32_t mask)
307 {
308 base->PWMSR = (mask & (PWM_PWMSR_FE_MASK | PWM_PWMSR_ROV_MASK | PWM_PWMSR_CMP_MASK | PWM_PWMSR_FWE_MASK));
309 }
310
311 /*!
312 * @brief Gets the PWM FIFO available.
313 *
314 * @param base PWM peripheral base address
315 *
316 * @return The status flags. This is the logical OR of members of the
317 * enumeration ::pwm_fifo_available_t
318 */
PWM_GetFIFOAvailable(PWM_Type * base)319 static inline uint32_t PWM_GetFIFOAvailable(PWM_Type *base)
320 {
321 return (base->PWMSR & PWM_PWMSR_FIFOAV_MASK);
322 }
323
324 /*! @}*/
325
326 /*!
327 * @name Sample Interface
328 * @{
329 */
330
331 /*!
332 * @brief Sets the PWM sample value.
333 *
334 * @param base PWM peripheral base address
335 * @param value The sample value. This is the input to the 4x16 FIFO. The value in this register denotes
336 * the value of the sample being currently used.
337 */
PWM_SetSampleValue(PWM_Type * base,uint32_t value)338 static inline void PWM_SetSampleValue(PWM_Type *base, uint32_t value)
339 {
340 base->PWMSAR = (value & PWM_PWMSAR_SAMPLE_MASK);
341 }
342
343 /*!
344 * @brief Gets the PWM sample value.
345 *
346 * @param base PWM peripheral base address
347 *
348 * @return The sample value. It can be read only when the PWM is enable.
349 */
PWM_GetSampleValue(PWM_Type * base)350 static inline uint32_t PWM_GetSampleValue(PWM_Type *base)
351 {
352 return base->PWMSAR;
353 }
354
355 /*! @}*/
356
357 /*!
358 * @brief Sets the PWM period value.
359 *
360 * @param base PWM peripheral base address
361 * @param value The period value. The PWM period register (PWM_PWMPR) determines the period of
362 * the PWM output signal.
363 * Writing 0xFFFF to this register will achieve the same result as writing 0xFFFE.
364 * PWMO (Hz) = PCLK(Hz) / (period +2)
365 */
PWM_SetPeriodValue(PWM_Type * base,uint32_t value)366 static inline void PWM_SetPeriodValue(PWM_Type *base, uint32_t value)
367 {
368 base->PWMPR = (value & PWM_PWMPR_PERIOD_MASK);
369 }
370
371 /*!
372 * @brief Gets the PWM period value.
373 *
374 * @param base PWM peripheral base address
375 *
376 * @return The period value. The PWM period register (PWM_PWMPR) determines the period of
377 * the PWM output signal.
378 */
PWM_GetPeriodValue(PWM_Type * base)379 static inline uint32_t PWM_GetPeriodValue(PWM_Type *base)
380 {
381 return (base->PWMPR & PWM_PWMPR_PERIOD_MASK);
382 }
383
384 /*!
385 * @brief Gets the PWM counter value.
386 *
387 * @param base PWM peripheral base address
388 *
389 * @return The counter value. The current count value.
390 */
PWM_GetCounterValue(PWM_Type * base)391 static inline uint32_t PWM_GetCounterValue(PWM_Type *base)
392 {
393 return (base->PWMCNR & PWM_PWMCNR_COUNT_MASK);
394 }
395
396 #if defined(__cplusplus)
397 }
398 #endif
399
400 /*! @}*/
401
402 #endif /* _FSL_PWM_H_ */
403