S32 SDK
ftm_pwm_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
14  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
15  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
28 #include "ftm_pwm_driver.h"
29 
30 
31 /*******************************************************************************
32  * Code
33  ******************************************************************************/
34 
35 /*FUNCTION**********************************************************************
36  *
37  * Function Name : FTM_DRV_InitPwm
38  * Description : Configures duty cycle and frequency and starts outputting
39  * PWM on specified channels.
40  *
41  * Implements : FTM_DRV_InitPwm_Activity
42  *END**************************************************************************/
43 status_t FTM_DRV_InitPwm(uint32_t instance,
44  const ftm_pwm_param_t * param)
45 {
46  DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
47  DEV_ASSERT(param != NULL);
48  status_t retVal = STATUS_SUCCESS;
49  uint8_t index = 0U;
50  uint8_t hwChannel = 0U;
51  uint8_t fltChannel = 0U;
52  uint8_t chnlPairNum = 0U;
53  uint8_t channelId = 0U;
54  ftm_state_t * state = ftmStatePtr[instance];
55  FTM_Type * ftmBase = g_ftmBase[instance];
56 
57  if ((NULL != state) && (FTM_MODE_NOT_INITIALIZED == state->ftmMode))
58  {
59  /* Disable counter clock */
60  FTM_DRV_SetClockSource(ftmBase, FTM_CLOCK_SOURCE_NONE);
61  /* Clear the overflow flag */
62  FTM_DRV_ClearTimerOverflow(ftmBase);
63  /* Disable write protection */
64  FTM_DRV_SetWriteProtectionCmd(ftmBase, false);
65  /* Configure FTM mode */
66  state->ftmMode = param->mode;
67 
68  /* Configure independent PWM channels */
69  for (index = 0U; index < param->nNumIndependentPwmChannels; index++)
70  {
71  channelId = param->pwmIndependentChannelConfig[index].hwChannelId;
72  chnlPairNum = (uint8_t)(channelId >> 1U);
73  FTM_DRV_SetDualEdgeCaptureCmd(ftmBase, chnlPairNum, false);
74  /* Set ELSB bit and clear ELSA bit*/
75  FTM_DRV_SetChnEdgeLevel(ftmBase, channelId, 2U);
76  /* Set MSB and MSA bits*/
77  FTM_DRV_SetChnMSnBAMode(ftmBase, channelId, 3U);
78  /* Write FTMn_PWMLOAD register to enable synchronized loading points for the given channel */
79  FTM_DRV_EnablePwmChannelOutputs(ftmBase, channelId);
80  FTM_DRV_SetChnOutputPolarityCmd(ftmBase, channelId, param->pwmIndependentChannelConfig[index].polarity);
81  FTM_DRV_SetDualChnFaultCmd(ftmBase, chnlPairNum, ((param->faultConfig)->faultMode != FTM_FAULT_CONTROL_DISABLED) ? true : false);
82  /* Enable sync control for channels*/
83  FTM_DRV_SetDualChnPwmSyncCmd(ftmBase, chnlPairNum, true);
84  FTM_DRV_SetDualChnCombineCmd(ftmBase, chnlPairNum, false);
85  FTM_DRV_SetDualChnMofCombineCmd(ftmBase, chnlPairNum, false);
86  /* Enable the generation a trigger on chip module */
87  FTM_DRV_SetChnTriggerCmd(ftmBase, channelId, param->pwmIndependentChannelConfig[index].enableExternalTrigger);
88  }
89 
90  /* Configure combined PWM channels */
91  for (index = 0U; index < param->nNumCombinedPwmChannels; index++)
92  {
93  channelId = param->pwmCombinedChannelConfig[index].hwChannelId;
94  chnlPairNum = (uint8_t)(channelId >> 1U);
95  FTM_DRV_SetDualEdgeCaptureCmd(ftmBase, chnlPairNum, false);
96  /* Set ELSB bit and clear ELSA bit*/
97  FTM_DRV_SetChnEdgeLevel(ftmBase, channelId, 2U);
98  /* Set MSB and MSA bits */
99  FTM_DRV_SetChnMSnBAMode(ftmBase, channelId, 3U);
100  /* Write FTMn_PWMLOAD register to enable synchronized loading points for the given channel */
101  /* Enable channel (n) output */
102  FTM_DRV_EnablePwmChannelOutputs(ftmBase, channelId);
103  /* Enable channel (n+1) output */
105  {
106  FTM_DRV_EnablePwmChannelOutputs(ftmBase, (uint8_t)(channelId + 1U));
107  /* When ELSB = 0 and ELSA = 0 for channel (n+1) output is not available */
108  FTM_DRV_SetChnEdgeLevel(ftmBase, (uint8_t)(channelId + 1U), 2U);
109  /* Configure complementary mode for channel (n+1) */
110  FTM_DRV_SetDualChnCompCmd(ftmBase, chnlPairNum, param->pwmCombinedChannelConfig[index].secondChannelPolarity);
111  }
112  else
113  {
114  FTM_DRV_DisablePwmChannelOutputs(ftmBase, (uint8_t)(channelId + 1U));
115  }
116 
117  FTM_DRV_SetChnOutputPolarityCmd(ftmBase, channelId, param->pwmCombinedChannelConfig[index].mainChannelPolarity);
118  FTM_DRV_SetDualChnFaultCmd(ftmBase, chnlPairNum, ((param->faultConfig)->faultMode != FTM_FAULT_CONTROL_DISABLED) ? true : false);
119  /* Enable sync control for channels */
120  FTM_DRV_SetDualChnPwmSyncCmd(ftmBase, chnlPairNum, true);
121  /* Enable the combine mode */
122  FTM_DRV_SetDualChnCombineCmd(ftmBase, chnlPairNum, true);
123  /* Configure the modified combine mode */
124  FTM_DRV_SetDualChnMofCombineCmd(ftmBase, chnlPairNum, param->pwmCombinedChannelConfig[index].enableModifiedCombine);
125  /* Configure dead time */
126  FTM_DRV_SetDualChnDeadtimeCmd(ftmBase, chnlPairNum, param->pwmCombinedChannelConfig[index].deadTime);
127  /* Enable the generation a trigger on the channel (n) */
128  FTM_DRV_SetChnTriggerCmd(ftmBase, (chnlPairNum << 1U), param->pwmCombinedChannelConfig[index].enableExternalTrigger);
129  /* Enable the generation a trigger on the channel (n+1) */
130  FTM_DRV_SetChnTriggerCmd(ftmBase, (chnlPairNum << 1U) + 1U, param->pwmCombinedChannelConfig[index].enableExternalTriggerOnNextChn);
131  }
132 
133  /* Set enable outputs to be set to Initial/default value */
134  FTM_DRV_SetInitChnOutputCmd(ftmBase, true);
135  /* Enable faults (if faults were configured) */
136  if ((param->faultConfig)->faultMode != FTM_FAULT_CONTROL_DISABLED)
137  {
138  /* Configure PWM Output behavior */
139  FTM_DRV_SetPwmFaultBehavior(ftmBase, ((param->faultConfig)->pwmOutputStateOnFault) ? true : false);
140  /* Configure fault filter value */
141  FTM_DRV_SetFaultInputFilterVal(ftmBase, ((param->faultConfig)->faultFilterValue));
142  for (fltChannel = 0U; fltChannel < FTM_FEATURE_FAULT_CHANNELS; fltChannel++)
143  {
144  if (true == (param->faultConfig)->ftmFaultChannelParam[fltChannel].faultChannelEnabled)
145  {
146  /* Enable fault channel */
147  FTM_DRV_SetFaultInputCmd(ftmBase, fltChannel, true);
148  /* Configure fault filter */
149  FTM_DRV_SetFaultInputFilterCmd(ftmBase,
150  fltChannel,
151  ((param->faultConfig)->ftmFaultChannelParam[fltChannel].faultFilterEnabled) ? true : false);
152  /* Configure fault outputs */
153  FTM_DRV_SetChnFaultInputPolarityCmd(ftmBase, fltChannel,
154  ((param->faultConfig)->ftmFaultChannelParam[fltChannel].ftmFaultPinPolarity));
155  }
156  }
157 
158  /* Set fault interrupt */
159  if (true == ((param->faultConfig)->pwmFaultInterrupt))
160  {
161  FTM_DRV_SetFaultInt(ftmBase, true);
162  }
163 
164  /* Enable fault control */
165  FTM_DRV_SetFaultControlMode(ftmBase, (param->faultConfig)->faultMode);
166  }
167 
168  /* Configure PWM mode: edge or center aligned */
169  FTM_DRV_SetCpwms(ftmBase, (param->mode == FTM_MODE_CEN_ALIGNED_PWM) ? true : false);
170  /* Calculate frequency of the give FTM hardware module - all channels will run at the same frequency */
171  state->ftmPeriod = FTM_DRV_ConvertFreqToPeriodTicks(instance, param->uFrequencyHZ);
172  /* Based on reference manual, in PWM mode CNTIN is to be set 0*/
173  FTM_DRV_SetCounterInitVal(ftmBase, 0U);
174  /* Write MOD register with the value of the period */
175  /* For center aligned mode MOD register should be divided by 2 */
176  /* For edge aligned mode period is determined by: MOD-CNTIN+1 */
177  if (param->mode == FTM_MODE_CEN_ALIGNED_PWM)
178  {
179  FTM_DRV_SetMod(ftmBase, (uint16_t)(state->ftmPeriod >> 1U));
180  }
181  else
182  {
183  FTM_DRV_SetMod(ftmBase, (uint16_t)(state->ftmPeriod - 1U));
184  }
185 
186  for (index = 0U; index < param->nNumIndependentPwmChannels; index++)
187  {
188  hwChannel = param->pwmIndependentChannelConfig[index].hwChannelId;
189  /* Write CnV registers and setup duty cycle and phase values */
190  retVal = FTM_DRV_UpdatePwmChannel(instance,
191  hwChannel,
194  0U,
195  false);
196  }
197 
198  for (index = 0U; index < param->nNumCombinedPwmChannels; index++)
199  {
200  hwChannel = param->pwmCombinedChannelConfig[index].hwChannelId;
201  /* Write CnV registers and setup duty cycle and phase values */
202  retVal = FTM_DRV_UpdatePwmChannel(instance,
203  hwChannel,
205  param->pwmCombinedChannelConfig[index].firstEdge,
206  param->pwmCombinedChannelConfig[index].secondEdge,
207  false);
208  }
209 
210  if (STATUS_SUCCESS == retVal)
211  {
212  /* Configure dead time for combine mode */
213  FTM_DRV_SetDeadtimeCount(ftmBase, param->deadTimeValue);
214  FTM_DRV_SetDeadtimePrescale(ftmBase, param->deadTimePrescaler);
215  FTM_DRV_Enable(ftmBase, true);
216  FTM_DRV_SetPwmSyncMode(ftmBase, true);
217  /* Set clock source to start counter */
218  FTM_DRV_SetClockSource(ftmBase, state->ftmClockSource);
219  }
220  else
221  {
222  /* Restore FTM mode if initialization fails */
224  }
225  }
226  else
227  {
228  retVal = STATUS_ERROR;
229  }
230 
231  return retVal;
232 }
233 
234 /*FUNCTION**********************************************************************
235  *
236  * Function Name : FTM_DRV_DeinitPwm
237  * Description : Stops all PWM channels.
238  *
239  * Implements : FTM_DRV_DeinitPwm_Activity
240  *END**************************************************************************/
241 status_t FTM_DRV_DeinitPwm(uint32_t instance)
242 {
243  DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
244  FTM_Type * ftmBase = g_ftmBase[instance];
245  uint8_t channel;
246  uint8_t chnlPairNum;
247  ftm_state_t * state = ftmStatePtr[instance];
248 
249  /* Stop the FTM counter */
250  FTM_DRV_SetClockSource(ftmBase, FTM_CLOCK_SOURCE_NONE);
251  for (channel = 0U; channel < FEATURE_FTM_CHANNEL_COUNT; channel++)
252  {
253  chnlPairNum = (uint8_t)(channel >> 1U);
254  /* Disable PWM mode in hardware */
255  FTM_DRV_SetChnCountVal(ftmBase, channel, 0U);
256  FTM_DRV_SetChnEdgeLevel(ftmBase, channel, 0U);
257  FTM_DRV_SetChnMSnBAMode(ftmBase, channel, 0U);
258  FTM_DRV_SetCpwms(ftmBase, false);
259  /* Configure polarity bit */
260  FTM_DRV_SetChnOutputPolarityCmd(ftmBase, channel, FTM_POLARITY_LOW);
261  FTM_DRV_DisablePwmChannelOutputs(ftmBase, channel);
262  /* Clear the PWM synchronization */
263  FTM_DRV_SetDualChnPwmSyncCmd(ftmBase, chnlPairNum, false);
264  /* Clear combination for each pair of channels */
265  FTM_DRV_SetDualChnMofCombineCmd(ftmBase, chnlPairNum, false);
266  FTM_DRV_SetDualChnCombineCmd(ftmBase, chnlPairNum, false);
267  FTM_DRV_SetDualChnDeadtimeCmd(ftmBase, chnlPairNum, false);
268  FTM_DRV_SetDualChnFaultCmd(ftmBase, chnlPairNum, false);
269  }
270 
271  /* Clear the dead-time pre-scaler and value */
272  FTM_DRV_SetExtDeadtimeValue(ftmBase, 0U);
273  FTM_DRV_SetDeadtimePrescale(ftmBase, FTM_DEADTIME_DIVID_BY_1);
274  FTM_DRV_SetDeadtimeCount(ftmBase, 0U);
275  /* Clear fault control register */
276  FTM_DRV_ClearFaultControl(ftmBase);
277  /* Disable fault interrupt */
278  FTM_DRV_SetFaultInt(ftmBase, false);
279  /* Disable fault control */
280  FTM_DRV_SetFaultControlMode(ftmBase, FTM_FAULT_CONTROL_DISABLED);
281  /* Clear the module value of the registers */
282  FTM_DRV_SetMod(ftmBase, 0U);
283  FTM_DRV_SetCounter(ftmBase, 0U);
285 
286  return STATUS_SUCCESS;
287 }
288 
289 /*FUNCTION**********************************************************************
290  *
291  * Function Name : FTM_DRV_UpdatePwmChannel
292  * Description : This function will update the duty cycle of PWM output.
293  * - If the type of update in the duty cycle, this function will convert the input parameters representing
294  * frequency in Hz to a period value in ticks needed by the hardware timer. Period is calculated depending
295  * on the operating mode of the FTM module and is stored in internal state structure.
296  * firstEdge and secondEdge can have value between 0 - FTM_MAX_DUTY_CYCLE(0 = 0% duty
297  * and FTM_MAX_DUTY_CYCLE = 100% duty). secondEdge value is used only whenFTM module is used in PWM combine mode.
298  * - If the type of update in ticks, this function will get value in ticks to the hardware timer.
299  * firstEdge and secondEdge variables can have value between 0 and ftmPeriod is stored in the state structure.
300  * - in the modified combine mode, the firstEdge parameter is fixed value and only can modify the secondEdge variables
301  * which is the initial value in the channel (n+1) match edge when the FTM counter has been ran.
302  *
303  * Implements : FTM_DRV_UpdatePwmChannel_Activity
304  *END**************************************************************************/
306  uint8_t channel,
307  ftm_pwm_update_option_t typeOfUpdate,
308  uint16_t firstEdge,
309  uint16_t secondEdge,
310  bool softwareTrigger)
311 {
312  DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
314  uint16_t hwFirstEdge = 0U;
315  uint16_t hwSecondEdge = 0U;
316  uint16_t ftmPeriod = 0U;
317  uint8_t chnlPairNum = (uint8_t)(channel >> 1U);
318  FTM_Type * ftmBase = g_ftmBase[instance];
319  ftm_state_t * state = ftmStatePtr[instance];
320  status_t retStatus = STATUS_SUCCESS;
321 
322  /* Get the newest period in the MOD register */
323  ftmPeriod = FTM_DRV_GetMod(ftmBase);
324  /* Check the mode operation in FTM module */
325  if (state->ftmMode == FTM_MODE_CEN_ALIGNED_PWM)
326  {
327  ftmPeriod = (uint16_t)(ftmPeriod << 1U);
328  }
329  else if (state->ftmMode == FTM_MODE_EDGE_ALIGNED_PWM)
330  {
331  ftmPeriod = (uint16_t)(ftmPeriod + 1U);
332  }
333  else
334  {
335  retStatus = STATUS_ERROR;
336  }
337 
338  /* Check the type of update for PWM */
339  if (FTM_PWM_UPDATE_IN_DUTY_CYCLE == typeOfUpdate)
340  {
341  if ((firstEdge <= FTM_MAX_DUTY_CYCLE) && (secondEdge <= FTM_MAX_DUTY_CYCLE))
342  {
343  /* Calculate DutyCycle based of the previously calculated frequency*/
344  /* For greater resolution the DutyCycle values are in the range [0. FTM_MAX_DUTY_CYCLE]
345  * where 0 = 0% or PWM always at Low and FTM_MAX_DUTY_CYCLE = 100% or PWM always HIGH;
346  * a value of 0x4000 is equivalent of 50% DutyCycle. */
347  hwFirstEdge = (uint16_t)((ftmPeriod * firstEdge) >> FTM_DUTY_TO_TICKS_SHIFT);
348  hwSecondEdge = (uint16_t)((ftmPeriod * secondEdge) >> FTM_DUTY_TO_TICKS_SHIFT);
349  /* adjust DutyCycle if 100% value is to be achieved. */
350  if (FTM_MAX_DUTY_CYCLE == firstEdge)
351  {
352  /* If expected duty is 100% then increase by 1 the value that is to be written
353  * to Hardware so it will exceed value of period */
354  hwFirstEdge = (uint16_t)(hwFirstEdge + 1U);
355  }
356  }
357  else
358  {
359  retStatus = STATUS_ERROR;
360  }
361  }
362  else
363  {
364  if ((firstEdge <= (state->ftmPeriod)) && (secondEdge <= (state->ftmPeriod)))
365  {
366  hwFirstEdge = firstEdge;
367  hwSecondEdge = secondEdge;
368  }
369  else
370  {
371  retStatus = STATUS_ERROR;
372  }
373  }
374 
375  if (STATUS_SUCCESS == retStatus)
376  {
377  if (true == FTM_DRV_GetDualChnCombineCmd(ftmBase, chnlPairNum))
378  {
379  if (true == FTM_DRV_GetDualChnMofCombineCmd(ftmBase, chnlPairNum))
380  {
381  /* Check the clock source for FTM counter is disabled or not */
382  if (FTM_DRV_GetClockSource(ftmBase) == 0U)
383  {
384  FTM_DRV_SetChnCountVal(ftmBase, (uint8_t)(chnlPairNum * 2U), hwFirstEdge);
385  }
386  }
387  else
388  {
389  FTM_DRV_SetChnCountVal(ftmBase, (uint8_t)(chnlPairNum * 2U), hwFirstEdge);
390  }
391 
392  /* Modify the initial value in the channel (n+1) match edge */
393  FTM_DRV_SetChnCountVal(ftmBase, (uint8_t)((chnlPairNum * 2U) + 1U), hwSecondEdge);
394  }
395  else
396  {
397  /* Channel value is divided by 2 for up down counter mode to keep same duty */
398  if (true == FTM_DRV_GetCpwms(ftmBase))
399  {
400  FTM_DRV_SetChnCountVal(ftmBase, channel, (uint16_t)(hwFirstEdge >> 1U));
401  }
402  else
403  {
404  FTM_DRV_SetChnCountVal(ftmBase, channel, hwFirstEdge);
405  }
406  }
407 
408  /* Software trigger is generated to change CnV registers */
409  /* Before this please configure sync mechanism to use software trigger */
410  if (softwareTrigger)
411  {
412  FTM_DRV_SetSoftwareTriggerCmd(ftmBase, true);
413  }
414 
415  /* Store the PWM period in the state structure */
416  state->ftmPeriod = ftmPeriod;
417  }
418 
419  return retStatus;
420 }
421 
422 /*FUNCTION**********************************************************************
423  *
424  * Function Name : FTM_DRV_UpdatePwmPeriod
425  * Description : This function will update the new period in the frequency or
426  * in the counter value into mode register which modify the period of PWM signal
427  * on the channel output.
428  * - If the type of update in the duty cycle which is reused in FTM_DRV_UpdatePwmChannel
429  * function to convert the newValue parameters representing frequency in Hz to
430  * a period value to update the MOD register. The newValue parameter must be value
431  * between 1U and maximum is the frequency of the FTM counter.
432  * - If the type of update in ticks, this function will get value in counting to
433  * the MOD register. The newValue parameter must be value between 1U and 0xFFFFU
434  *
435  * Implements : FTM_DRV_UpdatePwmPeriod_Activity
436  *END**************************************************************************/
438  ftm_pwm_update_option_t typeOfUpdate,
439  uint32_t newValue,
440  bool softwareTrigger)
441 {
442  DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
443  DEV_ASSERT(newValue != 0U);
444  uint32_t ftmPeriod = 0U;
445  FTM_Type * ftmBase = g_ftmBase[instance];
446  const ftm_state_t * state = ftmStatePtr[instance];
447  status_t retStatus = STATUS_SUCCESS;
448 
449  /* Check the type of update for period in PWM mode */
450  if (FTM_PWM_UPDATE_IN_TICKS == typeOfUpdate)
451  {
452  ftmPeriod = newValue;
453  }
454  else
455  {
456  if (newValue <= state->ftmSourceClockFrequency)
457  {
458  ftmPeriod = (uint32_t)FTM_DRV_ConvertFreqToPeriodTicks(instance, newValue);
459  }
460  else
461  {
462  retStatus = STATUS_ERROR;
463  }
464  }
465 
466  if (STATUS_SUCCESS == retStatus)
467  {
468  /* Check the ftmPeriod is invalid */
469  DEV_ASSERT(ftmPeriod <= 0xFFFFU);
470  /* Check the signal operation in which PWM mode */
472  if (FTM_MODE_CEN_ALIGNED_PWM == state->ftmMode)
473  {
474  ftmPeriod = (ftmPeriod >> 1U);
475  }
476  else
477  {
478  ftmPeriod = (ftmPeriod - 1U);
479  }
480  /* Set the new modulo value into MOD register */
481  FTM_DRV_SetMod(ftmBase, (uint16_t)(ftmPeriod));
482  /* Software trigger is generated to change MOD registers */
483  if (softwareTrigger)
484  {
485  FTM_DRV_SetSoftwareTriggerCmd(ftmBase, true);
486  }
487  }
488 
489  return retStatus;
490 }
491 
492 /*FUNCTION**********************************************************************
493  *
494  * Function Name : FTM_DRV_FastUpdatePwmChannels
495  * Description : This function will update the duty cycle of PWM output for multiple channels.
496  *
497  * The main differences between this function and FTM_DRV_UpdatePwmChannel is the execution speed. This
498  * feature makes this function ideal for applications like motor controlling.
499  * The downside is the low flexibility of the parameters (this function accept only updates in ticks).
500  *
501  * Implements : FTM_DRV_FastUpdatePwmChannels_Activity
502  *END**************************************************************************/
504  uint8_t numberOfChannels,
505  const uint8_t * channels,
506  const uint16_t * duty,
507  bool softwareTrigger)
508 {
509  FTM_Type * ftmBase = g_ftmBase[instance];
510  DEV_ASSERT(instance < FTM_INSTANCE_COUNT);
511  DEV_ASSERT(numberOfChannels < FEATURE_FTM_CHANNEL_COUNT);
512  uint8_t i;
513 
514  for (i = 0U; i < numberOfChannels; i++)
515  {
516  ((ftmBase)->CONTROLS[channels[i]].CnV) = duty[i];
517  }
518 
519  if (softwareTrigger)
520  {
521  ftmBase->SYNC |= FTM_SYNC_SWSYNC_MASK;
522  }
523 
524  return STATUS_SUCCESS;
525 }
526 
527 #if FEATURE_FTM_HAS_SUPPORTED_DITHERING
528 /*FUNCTION**********************************************************************
529  *
530  * Function Name : FTM_DRV_UpdatePwmPeriodDither
531  * Description : This function will use in the PWM period dithering. This value
532  * is added to an internal accumulator at the end of each PWM period. The value is
533  * updated with its write buffer value according to the register synchronization.
534  *
535  * Implements : FTM_DRV_UpdatePwmPeriodDither_Activity
536  *END**************************************************************************/
537 status_t FTM_DRV_UpdatePwmPeriodDither(uint32_t instance,
538  uint8_t newModFracVal,
539  bool softwareTrigger)
540 {
541  DEV_ASSERT((instance == FTM1_IDX) || (instance == FTM2_IDX));
542  DEV_ASSERT(newModFracVal <= 32U);
543  FTM_Type * ftmBase = g_ftmBase[instance];
544 
545  FTM_DRV_SetModFracVal(ftmBase, newModFracVal);
546  /* Software trigger is generated to change MOD_MIRROR registers */
547  if (softwareTrigger)
548  {
549  FTM_DRV_SetSoftwareTriggerCmd(ftmBase, true);
550  }
551 
552  return STATUS_SUCCESS;
553 }
554 
555 /*FUNCTION**********************************************************************
556  *
557  * Function Name : FTM_DRV_UpdatePwmEdgeChannelDither
558  * Description : This function will use in the PWM edge dithering. This value
559  * is added to the channel (n) internal accumulator at the end of each PWM period.
560  * The FRACVAL is updated with its write buffer value according to the register
561  * synchronization. The PWM edge dithering is not available when the channel in the
562  * input capture modes, and the channel in output compare mode.
563  *
564  * Implements : FTM_DRV_UpdatePwmEdgeChannelDither_Activity
565  *END**************************************************************************/
566 status_t FTM_DRV_UpdatePwmEdgeChannelDither(uint32_t instance,
567  uint8_t channel,
568  uint8_t newMatchFracVal,
569  bool softwareTrigger)
570 {
571  DEV_ASSERT((instance == FTM1_IDX) || (instance == FTM2_IDX));
573  DEV_ASSERT(newMatchFracVal <= 32U);
574  FTM_Type * ftmBase = g_ftmBase[instance];
575 
576  FTM_DRV_SetChnMatchFracVal(ftmBase, channel, newMatchFracVal);
577  /* Software trigger is generated to change CnV_MIRROR registers */
578  if (softwareTrigger)
579  {
580  FTM_DRV_SetSoftwareTriggerCmd(ftmBase, true);
581  }
582 
583  return STATUS_SUCCESS;
584 }
585 #endif
586 
587 #ifdef ERRATA_E10856
588 /*FUNCTION**********************************************************************
589  *
590  * Function Name : FTM_PWM_DRV_IrqHandler
591  * Description : This function is used to workaround an errata which the safe state
592  * is not removed from channel outputs after fault condition ends if SWOCTRL is being
593  * used to control the pin. The FTM_MODE[FAULTM] should be configured for manual fault
594  * clearing (0b10)
595  * This function must be used in the TOF interrupt handler when a fault is detected to
596  * ensure that the outputs return to the value configured by FTM_SWOCTR
597  *
598  * Implements : FTM_PWM_DRV_IrqHandler_Activity
599  *END**************************************************************************/
600 void FTM_PWM_DRV_IrqHandler(uint32_t instance,
601  uint32_t chnOutCtrlVal)
602 {
603  FTM_Type * ftmBase = g_ftmBase[instance];
604 
605  /* 1. Check the value of FTM_FMS[FAULTF] */
606  if (FTM_DRV_GetDetectedFaultInput(ftmBase) == true)
607  {
608  faultDetection = true;
609  /* 2. Write the FTM_OUTMASK register to set the bit */
610  FTM_DRV_SetOutmaskReg(ftmBase, chnOutCtrlVal);
611  /* 3. Clear fault conditions by reading the FTM_FMS register and then writing FTM_FMS with all zeroes */
612  FTM_DRV_ClearFaultsIsr(ftmBase);
613  /* 4. Clear the FTM_SC[TOF] bit by reading the FTM_SC register, then writing a 0 to FTM_SC[TOF] */
614  FTM_DRV_ClearTimerOverflow(ftmBase);
615  /* 5. Exit the interrupt handler to skip following steps */
616  }
617  else if (faultDetection == true)
618  {
619  /* 6. Clear the FTM_SWOCTRL by writing all zeroes to it */
620  FTM_DRV_SetAllChnSoftwareCtrlCmd(ftmBase, 0x00U);
621  FTM_DRV_SetAllChnSoftwareCtrlVal(ftmBase, 0x00U);
622  /* 7. Write FTM_SWOCTRL with the desired value again */
623  uint8_t u8chnOutCtrlVal = (uint8_t)(chnOutCtrlVal & 0xFFu);
624  FTM_DRV_SetAllChnSoftwareCtrlCmd(ftmBase, u8chnOutCtrlVal);
625  FTM_DRV_SetAllChnSoftwareCtrlVal(ftmBase, u8chnOutCtrlVal);
626  /* 8. Clear the FTM_OUTMASK bits that were set in step 2 */
627  FTM_DRV_SetOutmaskReg(ftmBase, 0x00U);
628  /* 9. Clear the fault variable that was set in step 1 when the fault condition was originally detected */
629  faultDetection = false;
630  /* 10. Clear the FTM_SC[TOF] bit by reading the FTM_SC register, then writing a 0 to FTM_SC[TOF] */
631  FTM_DRV_ClearTimerOverflow(ftmBase);
632  }
633  else
634  {
635  /* Nothing to do */
636  }
637 }
638 #endif
639 
640 /*******************************************************************************
641 * EOF
642 ******************************************************************************/
status_t FTM_DRV_DeinitPwm(uint32_t instance)
Stops all PWM channels .
FlexTimer state structure of the driver.
Definition: ftm_common.h:121
uint16_t ftmPeriod
Definition: ftm_common.h:125
uint32_t uFrequencyHZ
FTM_Type *const g_ftmBase[FTM_INSTANCE_COUNT]
Table of base addresses for FTM instances.
Definition: ftm_common.c:70
#define FTM_DUTY_TO_TICKS_SHIFT
Shift value which converts duty to ticks.
static bool FTM_DRV_GetCpwms(const FTM_Type *ftmBase)
Gets the FTM count direction bit.
Definition: ftm_common.h:297
ftm_state_t * ftmStatePtr[FTM_INSTANCE_COUNT]
Pointer to runtime state structure.
Definition: ftm_common.c:83
const ftm_combined_ch_param_t * pwmCombinedChannelConfig
status_t FTM_DRV_UpdatePwmPeriod(uint32_t instance, ftm_pwm_update_option_t typeOfUpdate, uint32_t newValue, bool softwareTrigger)
This function will update the new period in the frequency or in the counter value into mode register ...
static void FTM_DRV_ClearFaultsIsr(FTM_Type *const ftmBase)
Clears all fault interrupt flags that are active.
Definition: ftm_common.h:807
ftm_deadtime_ps_t deadTimePrescaler
uint8_t nNumCombinedPwmChannels
#define FEATURE_FTM_CHANNEL_COUNT
static void FTM_DRV_SetInitChnOutputCmd(FTM_Type *const ftmBase, bool enable)
Initializes the channels output.
Definition: ftm_common.h:860
static bool FTM_DRV_GetDualChnCombineCmd(const FTM_Type *ftmBase, uint8_t chnlPairNum)
Verify if an channels pair is used in combine mode or not.
Definition: ftm_common.h:915
#define DEV_ASSERT(x)
Definition: devassert.h:77
#define FTM_MAX_DUTY_CYCLE
Maximum value for PWM duty cycle.
uint16_t FTM_DRV_ConvertFreqToPeriodTicks(uint32_t instance, uint32_t freqencyHz)
This function is used to covert the given frequency to period in ticks.
Definition: ftm_common.c:501
static uint8_t FTM_DRV_GetClockSource(const FTM_Type *ftmBase)
Reads the FTM clock source.
Definition: ftm_common.h:235
ftm_clock_source_t ftmClockSource
Definition: ftm_common.h:123
const ftm_pwm_fault_param_t * faultConfig
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
status_t FTM_DRV_FastUpdatePwmChannels(uint32_t instance, uint8_t numberOfChannels, const uint8_t *channels, const uint16_t *duty, bool softwareTrigger)
This function will update the duty cycle of PWM output for multiple channels.
#define FTM_INSTANCE_COUNT
Definition: S32K142.h:3939
uint8_t nNumIndependentPwmChannels
FlexTimer driver PWM parameters.
#define FTM_FEATURE_FAULT_CHANNELS
ftm_polarity_t mainChannelPolarity
__IO uint32_t SYNC
Definition: S32K142.h:3908
ftm_config_mode_t ftmMode
Definition: ftm_common.h:124
ftm_second_channel_polarity_t secondChannelPolarity
const ftm_independent_ch_param_t * pwmIndependentChannelConfig
static uint16_t FTM_DRV_GetMod(const FTM_Type *ftmBase)
Returns the FTM peripheral counter modulo value.
Definition: ftm_common.h:372
status_t FTM_DRV_UpdatePwmChannel(uint32_t instance, uint8_t channel, ftm_pwm_update_option_t typeOfUpdate, uint16_t firstEdge, uint16_t secondEdge, bool softwareTrigger)
This function updates the waveform output in PWM mode (duty cycle and phase).
ftm_pwm_update_option_t
FlexTimer Configure type of PWM update in the duty cycle or in ticks.
static bool FTM_DRV_GetDetectedFaultInput(const FTM_Type *ftmBase)
Gets the FTM detected fault input.
Definition: ftm_common.h:964
status_t FTM_DRV_InitPwm(uint32_t instance, const ftm_pwm_param_t *param)
Configures the duty cycle and frequency and starts outputting the PWM on all channels configured in p...
ftm_config_mode_t mode
#define FTM_SYNC_SWSYNC_MASK
Definition: S32K142.h:4212