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