pwm_pal.c
Go to the documentation of this file.
1 /*
2  * Copyright 2017 NXP
3  * All rights reserved.
4  *
5  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
6  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
7  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
8  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
9  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
10  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
11  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
13  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
14  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
15  * THE POSSIBILITY OF SUCH DAMAGE.
16  */
17 
67 #include "pwm_pal.h"
68 
69 /* Include ETIMER special functions. */
70 #if (defined (PWM_OVER_ETIMER))
71 /* nothing here */
72 #endif
73 
74 /* Define state structures for FTM */
75 #if (defined(PWM_OVER_FTM))
76 
77  static ftm_state_t FtmState[NO_OF_FTM_INSTS_FOR_PWM];
79  static uint32_t FtmStateInstanceMapping[NO_OF_FTM_INSTS_FOR_PWM];
81  static bool FtmStateIsAllocated[NO_OF_FTM_INSTS_FOR_PWM];
82 
83 
84 /*FUNCTION**********************************************************************
85  *
86  * Function Name : PwmAllocateState
87  * Description : Allocates one of the available state structure.
88  *
89  *END**************************************************************************/
90 static uint8_t PwmAllocateState(bool* isAllocated, uint32_t* instanceMapping, const pwm_instance_t * const instance, uint8_t numberOfinstances)
91 {
92  uint8_t i;
93  /* Allocate one of the FTM state structure for this instance */
94  for (i = 0;i < numberOfinstances;i++)
95  {
96  if (isAllocated[i] == false)
97  {
98  instanceMapping[i] = instance->instIdx;
99  isAllocated[i] = true;
100  break;
101  }
102  }
103  return i;
104 }
105 
106 /*FUNCTION**********************************************************************
107  *
108  * Function Name : PwmFreeState
109  * Description : Deallocates one of the available state structure.
110  *
111  *END**************************************************************************/
112 static void PwmFreeState(bool* isAllocated, const uint32_t* instanceMapping, const pwm_instance_t * const instance, uint8_t numberOfinstances)
113 {
114  uint8_t i;
115  /* Allocate one of the FTM state structure for this instance */
116  for (i = 0;i < numberOfinstances;i++)
117  {
118  if (instanceMapping[i] == instance->instIdx)
119  {
120  isAllocated[i] = false;
121  break;
122  }
123  }
124 }
125 #endif
126 
127 /*FUNCTION**********************************************************************
128  *
129  * Function Name : PWM_Init
130  * Description : Initialize PWM channels based on config parameter.
131  *
132  * Implements : PWM_Init_Activity
133  *END**************************************************************************/
134 status_t PWM_Init(const pwm_instance_t * const instance, const pwm_global_config_t* config)
135 {
136  DEV_ASSERT(instance != NULL);
137  DEV_ASSERT(config != NULL);
138 
139  status_t status = STATUS_ERROR;
140 
141  #if (defined(PWM_OVER_FTM))
142  if(instance->instType == PWM_INST_TYPE_FTM)
143  {
144  /* Declare internal variables */
145  uint8_t channel;
146  uint8_t index;
147  uint32_t frequency;
148  uint32_t dutyPercent;
149  /* Declare the configuration structure for FTM */
150  ftm_pwm_param_t ftmPwmConfig;
151  ftm_independent_ch_param_t pwmIndependentChannelConfig[FEATURE_FTM_CHANNEL_COUNT];
152  ftm_combined_ch_param_t pwmCombinedChannelConfig[FEATURE_FTM_CHANNEL_COUNT >> 1U];
153  ftm_user_config_t ftmGlobalConfig;
154  /* Fault control feature is not supported, but this structure is filled with values which disable fault control */
155  ftm_pwm_fault_param_t faultConfig =
156  {
157  false, /* Output pin state on fault */
158  false, /* PWM fault interrupt state */
159  0U, /* Fault filter value */
160  FTM_FAULT_CONTROL_DISABLED, /* Fault mode */
161  {
162  {
163  false, /* Fault channel state (Enabled/Disabled) */
164  false, /* Fault channel filter state (Enabled/Disabled) */
165  FTM_POLARITY_LOW, /* Fault channel state (Enabled/Disabled) */
166  },
167  {
168  false, /* Fault channel state (Enabled/Disabled) */
169  false, /* Fault channel filter state (Enabled/Disabled) */
170  FTM_POLARITY_LOW, /* Fault channel state (Enabled/Disabled) */
171  },
172  {
173  false, /* Fault channel state (Enabled/Disabled) */
174  false, /* Fault channel filter state (Enabled/Disabled) */
175  FTM_POLARITY_LOW, /* Fault channel state (Enabled/Disabled) */
176  },
177  {
178  false, /* Fault channel state (Enabled/Disabled) */
179  false, /* Fault channel filter state (Enabled/Disabled) */
180  FTM_POLARITY_LOW, /* Fault channel state (Enabled/Disabled) */
181  }
182  }
183  };
184 
185  ftmPwmConfig.pwmCombinedChannelConfig = pwmCombinedChannelConfig;
186  ftmPwmConfig.pwmIndependentChannelConfig = pwmIndependentChannelConfig;
187  ftmPwmConfig.faultConfig = &faultConfig;
188 
189  /* Because FTM has only one timebase first channel is used to configure FTM clocking*/
190  ftmGlobalConfig.ftmClockSource = ((pwm_ftm_timebase_t*)(config->pwmChannels[0].timebase))->sourceClock;
191  ftmGlobalConfig.ftmPrescaler = ((pwm_ftm_timebase_t*)(config->pwmChannels[0].timebase))->prescaler;
192  ftmPwmConfig.deadTimePrescaler = ((pwm_ftm_timebase_t*)(config->pwmChannels[0].timebase))->deadtimePrescaler;
193 
194  /* Configure FTM mode according to first channel setup.
195  * All PWM channels must be PWM_EDGE_ALIGNED/PWM_Shifted or PWM_CENTER_ALIGNED */
196  if ((config->pwmChannels[0].channelType) == PWM_CENTER_ALIGNED)
197  {
198  ftmPwmConfig.mode = FTM_MODE_CEN_ALIGNED_PWM;
199  }
200  else
201  {
202  ftmPwmConfig.mode = FTM_MODE_EDGE_ALIGNED_PWM;
203  }
204  ftmGlobalConfig.ftmMode = ftmPwmConfig.mode;
205 
206  /* The synchronization for duty, period and phase shift will be update when
207  * signal period is done. Only overwrite function shall take effect immediate.
208  */
209  ftmGlobalConfig.syncMethod.softwareSync = true;
210  ftmGlobalConfig.syncMethod.hardwareSync1 = false;
211  ftmGlobalConfig.syncMethod.hardwareSync2 = false;
212  ftmGlobalConfig.syncMethod.hardwareSync0 = false;
213  ftmGlobalConfig.syncMethod.autoClearTrigger = false;
214  ftmGlobalConfig.syncMethod.maskRegSync = FTM_SYSTEM_CLOCK;
215  ftmGlobalConfig.syncMethod.initCounterSync = FTM_PWM_SYNC;
216  ftmGlobalConfig.syncMethod.inverterSync = FTM_PWM_SYNC;
217  ftmGlobalConfig.syncMethod.outRegSync = FTM_SYSTEM_CLOCK;
218  ftmGlobalConfig.syncMethod.maxLoadingPoint = true;
219  ftmGlobalConfig.syncMethod.minLoadingPoint = false;
220  ftmGlobalConfig.syncMethod.syncPoint = FTM_WAIT_LOADING_POINTS;
221  ftmGlobalConfig.isTofIsrEnabled = false;
222  ftmGlobalConfig.BDMMode = FTM_BDM_MODE_00;
223 
224  /* Configure FTM channels */
225  ftmPwmConfig.nNumCombinedPwmChannels = 0;
226  ftmPwmConfig.nNumIndependentPwmChannels = 0;
227  for (channel = 0; channel < config->numberOfPwmChannels; channel++)
228  {
229  /* Configure duty cycle in percents */
230  dutyPercent = (FTM_MAX_DUTY_CYCLE * config->pwmChannels[channel].duty) / config->pwmChannels[channel].period;
231  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].uDutyCyclePercent = (uint16_t)dutyPercent;
232 
233  /* Configure channel number */
234  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].hwChannelId = config->pwmChannels[channel].channel;
235 
236  /*Configure complementary mode */
237  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].enableSecondChannelOutput = config->pwmChannels[channel].enableComplementaryChannel;
238  if ((config->pwmChannels[channel].complementaryChannelPolarity) == PWM_DUPLICATED)
239  {
240  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].secondChannelPolarity = FTM_MAIN_DUPLICATED;
241  }
242  else
243  {
244  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].secondChannelPolarity = FTM_MAIN_INVERTED;
245  }
246 
247  /* Configure channel polarity */
248  if (config->pwmChannels[channel].polarity == PWM_ACTIVE_HIGH)
249  {
250  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].polarity = FTM_POLARITY_HIGH;
251  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].levelSelect = FTM_HIGH_TRUE_PULSE;
252  }
253  else
254  {
255  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].polarity = FTM_POLARITY_LOW;
256  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].levelSelect = FTM_LOW_TRUE_PULSE;
257  }
258 
259  /* Configure dead-time insertion. For them the dead time configuration is available for all channels. */
260  ftmPwmConfig.deadTimePrescaler = ((pwm_ftm_timebase_t*)(config->pwmChannels[0].timebase))->deadtimePrescaler;
261  ftmPwmConfig.deadTimeValue = config->pwmChannels[0].deadtime;
262 
263  /* Configure default value for fail safe value. */
264  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].enableExternalTrigger = false;
265  pwmIndependentChannelConfig[ftmPwmConfig.nNumIndependentPwmChannels].deadTime = config->pwmChannels[channel].insertDeadtime;
266  ftmPwmConfig.nNumIndependentPwmChannels++;
267  }
268 
269  /* Initialize FTM */
270  index = PwmAllocateState(FtmStateIsAllocated, FtmStateInstanceMapping, instance, NO_OF_FTM_INSTS_FOR_PWM);
271  (void)FTM_DRV_Init(instance->instIdx, &ftmGlobalConfig, (ftm_state_t*)(&FtmState[index]));
272 
273  /* Configure PWM frequency */
274  frequency = FTM_DRV_GetFrequency(instance->instIdx);
275  ftmPwmConfig.uFrequencyHZ = frequency / config->pwmChannels[0].period;
276 
277  /* Start PWM signal generation */
278  (void)FTM_DRV_InitPwm(instance->instIdx, &ftmPwmConfig);
279 
280  status = STATUS_SUCCESS;
281  }
282  else
283  #endif
284 
285  #if (defined(PWM_OVER_EMIOS))
286  if (instance->instType == PWM_INST_TYPE_EMIOS)
287  {
288  /* Configure the default configuration for eMIOS */
289  emios_common_param_t pwmGlobalConfig =
290  {
291  false,
292  false,
293  1U,
294  false,
295  false
296  };
297 
298  /* Initialize global configuration of the EMIOS. */
299  EMIOS_DRV_InitGlobal((uint8_t)instance->instIdx, &pwmGlobalConfig);
300 
301  /* Default timebase setup which will be changed accroding to config structure */
302  emios_mc_mode_param_t pwmTimebaseConfig =
303  {
304  EMIOS_MODE_MCB_UP_COUNTER_EXT_CLK,
305  10UL,
306  EMIOS_CLOCK_DIVID_BY_1,
307  false,
308  EMIOS_INPUT_FILTER_BYPASS,
309  false,
310  EMIOS_TRIGGER_EDGE_FALLING
311  };
312 
313  emios_pwm_param_t pwmChannelConfig=
314  {
315  EMIOS_MODE_OPWMCB_TRAIL_EDGE_DEADTIME_FLAGX1,
316  EMIOS_CLOCK_DIVID_BY_1,
317  true,
318  EMIOS_NEGATIVE_PULSE,
319  10000UL,
320  5000UL,
321  EMIOS_BUS_SEL_BCDE,
322  1UL,
323  0UL,
324  0UL
325  };
326  /* Configure all timebases */
327  uint8_t i;
328  for (i = 0; i < config->numberOfPwmChannels; i++)
329  {
330  /* Configure timebase counter mode. */
331  if(config->pwmChannels[i].channelType == PWM_EDGE_ALIGNED)
332  {
333  pwmTimebaseConfig.mode = EMIOS_MODE_MCB_UP_COUNTER_INT_CLK;
334  pwmChannelConfig.mode = EMIOS_MODE_OPWMB_FLAGX1;
335  /* Configure timebase period. */
336  pwmTimebaseConfig.period = config->pwmChannels[i].period;
337  }
338  else
339  {
340  pwmTimebaseConfig.mode = EMIOS_MODE_MCB_UPDOWN_CNT_FLAGX1_INT_CLK;
341  pwmChannelConfig.mode = EMIOS_MODE_OPWMCB_TRAIL_EDGE_DEADTIME_FLAGX1;
342  /* Configure timebase period. */
343  pwmTimebaseConfig.period = config->pwmChannels[i].period << 1U;
344  }
345 
346 
347  /* Configure timebase divider. */
348 
349  pwmTimebaseConfig.internalPrescalerEn = true;
350  pwmTimebaseConfig.internalPrescaler = ((pwm_emios_timebase_t*)(config->pwmChannels[i].timebase))->internalPrescaler;
351 
352  /* Configure timebase */
353  if(eMIOS[instance->instIdx]->UC[((pwm_emios_timebase_t*)(config->pwmChannels[i].timebase))->name].C == 0UL)
354  {
355  (void)EMIOS_DRV_MC_InitCounterMode((uint8_t)instance->instIdx, (uint8_t)((pwm_emios_timebase_t*)(config->pwmChannels[i].timebase))->name, &pwmTimebaseConfig);
356  }
357  /* Select timebase for current channel */
358  if (((pwm_emios_timebase_t*)(config->pwmChannels[i].timebase))->name == BUS_A)
359  {
360  pwmChannelConfig.timebase = EMIOS_BUS_SEL_A;
361  }
362  else if (((pwm_emios_timebase_t*)(config->pwmChannels[i].timebase))->name == BUS_F)
363  {
364  pwmChannelConfig.timebase = EMIOS_BUS_SEL_F;
365  }
366  else
367  {
368  pwmChannelConfig.timebase = EMIOS_BUS_SEL_BCDE;
369  }
370 
371  /* Select channel polarity */
372  if (config->pwmChannels[i].polarity == PWM_ACTIVE_HIGH)
373  {
374  pwmChannelConfig.outputActiveMode = EMIOS_POSITIVE_PULSE;
375  }
376  else
377  {
378  pwmChannelConfig.outputActiveMode = EMIOS_NEGATIVE_PULSE;
379  }
380 
381  /* Configure duty */
382  pwmChannelConfig.idealDutyCycle = config->pwmChannels[i].duty;
383  pwmChannelConfig.dutyCycleCount = config->pwmChannels[i].duty;
384 
385  /* Configure channel */
386  (void)EMIOS_DRV_PWM_InitMode((uint8_t)(instance->instIdx), config->pwmChannels[i].channel, &pwmChannelConfig);
387  }
388  EMIOS_DRV_EnableGlobalEmios((uint8_t)(instance->instIdx));
389  status = STATUS_SUCCESS;
390  }
391  else
392  #endif
393 
394  #if (defined (PWM_OVER_ETIMER))
395  if (instance->instType == PWM_INST_TYPE_ETIMER)
396  {
397  /* intial sanity check */
398  DEV_ASSERT(config->numberOfPwmChannels < ETIMER_CH_COUNT);
399 
400  /* default configuration for ETIMER for PWM mode */
401  etimer_user_channel_config_t etimerPwmPalCfg = {
402  .timerMode = ETIMER_MODE_VARIABLE_PWM,
403  .coreSettings = ETIMER_COUNTER_NORMAL,
404  .inputFilter =
405  {
406  .samples = ETIMER_FILT_CNT_3,
407  .rate = 0,
408  },
409  .primaryInput =
410  {
411  .source = ETIMER_IN_SRC_CLK_DIV_32,
412  .polarity = ETIMER_POLARITY_POSITIVE,
413  },
414  .secondaryInput =
415  {
416  .source = ETIMER_IN_SRC_CNT0_IN,
417  .polarity = ETIMER_POLARITY_POSITIVE,
418  },
419  .outputPin =
420  {
421  .enable = true,
422  .polarity = ETIMER_POLARITY_POSITIVE,
423  },
424  .countDirection = ETIMER_COUNT_UP,
425  .compareValues =
426  {
427  32767,
428  65535,
429  },
430  .compareLoading =
431  {
432  ETIMER_CLC_FROM_CMPLD1_WHEN_COMP1,
433  ETIMER_CLC_FROM_CMPLD2_WHEN_COMP2,
434  },
435  .compareOutputControl = ETIMER_OUTMODE_SOFTWARE,
436  .compareMode = ETIMER_CMPMODE_COMP1_UP_COMP2_UP,
437  .captureControl =
438  {
439  ETIMER_CPTMODE_DISABLED,
440  ETIMER_CPTMODE_DISABLED,
441  },
442  .captureWords = 0,
443  .interruptEnableMask = 0,
444  };
445 
446  /* initialize ETIMERx peripheral */
447  ETIMER_DRV_Init(instance->instIdx);
448  /* Configure all timebases */
449  uint8_t i;
450  uint16_t enmask=0;
451  for (i = 0; i < config->numberOfPwmChannels; i++)
452  {
453  /* sanity checks */
456  DEV_ASSERT(config->pwmChannels[i].insertDeadtime == false);
457  DEV_ASSERT(config->pwmChannels[i].period >= config->pwmChannels[i].duty);
458  /* double frequency ? */
459  if( (((pwm_etimer_timebase_t *)(config->pwmChannels[i].timebase))->halfClkPeriod) == true )
460  {
461  etimerPwmPalCfg.coreSettings = ETIMER_COUNTER_BOTHEDGE;
462  }
463  else
464  {
465  etimerPwmPalCfg.coreSettings = ETIMER_COUNTER_NORMAL;
466  }
467  /* clock source */
468  etimerPwmPalCfg.primaryInput.polarity = ((pwm_etimer_timebase_t *)(config->pwmChannels[i].timebase))->pwmClkSrc.polarity;
469  etimerPwmPalCfg.primaryInput.source = ((pwm_etimer_timebase_t *)(config->pwmChannels[i].timebase))->pwmClkSrc.source;
470  /* enable output ? */
471  if( (((pwm_etimer_timebase_t *)(config->pwmChannels[i].timebase))->enableOutSig) == true )
472  {
473  etimerPwmPalCfg.outputPin.enable = true;
474  }
475  else
476  {
477  etimerPwmPalCfg.outputPin.enable = false;
478  }
479  /* output polarity */
480  if(config->pwmChannels[i].polarity == PWM_ACTIVE_HIGH)
481  {
482  etimerPwmPalCfg.outputPin.polarity = ETIMER_POLARITY_POSITIVE;
483  }
484  else
485  {
486  etimerPwmPalCfg.outputPin.polarity = ETIMER_POLARITY_NEGATIVE;
487  }
488  /* COMP1 and COMP2 */
489  etimerPwmPalCfg.compareValues[0] = config->pwmChannels[i].duty;
490  etimerPwmPalCfg.compareValues[1] = (config->pwmChannels[i].period-config->pwmChannels[i].duty);
491  /* setup ETIMERx channels */
492  ETIMER_DRV_InitChannel(instance->instIdx, config->pwmChannels[i].channel, &etimerPwmPalCfg);
493  /* mask the enable bit */
494  enmask|=(1UL<<(config->pwmChannels[i].channel));
495  }
496  /* start channel operation */
497  ETIMER_DRV_StartTimerChannels(instance->instIdx, enmask);
498  /* all ok */
499  status = STATUS_SUCCESS;
500  }
501  else
502  #endif
503  {
504  DEV_ASSERT(false);
505  }
506  return status;
507 }
508 
509 /*FUNCTION**********************************************************************
510  *
511  * Function Name : PWM_UpdateDuty
512  * Description : Update duty cycle. The measurement unit for duty is clock ticks.
513  * Implements : PWM_UpdateDuty_Activity
514  *
515  *END**************************************************************************/
516 status_t PWM_UpdateDuty(const pwm_instance_t * const instance, uint8_t channel, uint32_t duty)
517 {
518  DEV_ASSERT(instance != NULL);
519  status_t status = STATUS_ERROR;
520 
521  #if (defined(PWM_OVER_FTM))
522  if (instance->instType == PWM_INST_TYPE_FTM)
523  {
524  (void)FTM_DRV_UpdatePwmChannel(instance->instIdx, channel, FTM_PWM_UPDATE_IN_TICKS, (uint16_t)duty, 0, true);
525  status = STATUS_SUCCESS;
526  }
527  else
528  #endif
529 
530  #if (defined(PWM_OVER_EMIOS))
531  if (instance->instType == PWM_INST_TYPE_EMIOS)
532  {
533  if ((eMIOS[instance->instIdx]->UC[channel].C & eMIOS_C_MODE_MASK) == (uint32_t)EMIOS_MODE_OPWMB_FLAGX1)
534  {
535  eMIOS[instance->instIdx]->UC[channel].B = duty;
536  }
537  else
538  {
539  eMIOS[instance->instIdx]->UC[channel].A = duty;
540  }
541  status = STATUS_SUCCESS;
542  }
543  else
544  #endif
545 
546  #if (defined (PWM_OVER_ETIMER))
547  uint16_t comp1,comp2;
548  if (instance->instType == PWM_INST_TYPE_ETIMER)
549  {
550  /* read current compare values */
551  ETIMER_DRV_GetCompareThresholdBuffered(instance->instIdx, channel, &comp1, &comp2);
552  /* the duty cycle must be lower or equal the period */
553  if(duty<=(comp1+comp2))
554  {
555  /* set it */
556  ETIMER_DRV_SetCompareThresholdBuffered(instance->instIdx, channel, duty, ((comp1+comp2)-duty));
557  /* all ok */
558  status = STATUS_SUCCESS;
559  }
560  else
561  {
562  /* duty is higher than period */
563  DEV_ASSERT(false);
564  }
565  }
566  else
567  #endif
568  {
569  DEV_ASSERT(false);
570  }
571 
572  return status;
573 }
574 
575 /*FUNCTION**********************************************************************
576  *
577  * Function Name : PWM_UpdatePeriod
578  * Description : Update period for specific a specific channel. This function changes period for
579  * all channels which shares the timebase with targeted channel.
580  * Implements : PWM_UpdatePeriod_Activity
581  *
582  *END**************************************************************************/
583 status_t PWM_UpdatePeriod(const pwm_instance_t * const instance, uint8_t channel, uint32_t period)
584 {
585 
586  DEV_ASSERT(instance != NULL);
587 
588  status_t status = STATUS_ERROR;
589 
590  #if (defined(PWM_OVER_FTM))
591  if (instance->instType == PWM_INST_TYPE_FTM)
592  {
593  (void)FTM_DRV_UpdatePwmPeriod(instance->instIdx, FTM_PWM_UPDATE_IN_TICKS, (uint16_t)period, true);
594  (void)channel;
595  status = STATUS_SUCCESS;
596  }
597  else
598  #endif
599 
600  #if (defined(PWM_OVER_EMIOS))
601  if (instance->instType == PWM_INST_TYPE_EMIOS)
602  {
603  switch (((eMIOS[instance->instIdx]->UC[channel].C) & eMIOS_C_BSL_MASK) >> eMIOS_C_BSL_SHIFT)
604  {
605  case 0U:
606  eMIOS[instance->instIdx]->UC[BUS_A].A = period;
607  break;
608  case 1U:
609  if(channel <=7U)
610  {
611  eMIOS[instance->instIdx]->UC[BUS_B].A = period;
612  }
613  else if (channel <= 15U)
614  {
615  eMIOS[instance->instIdx]->UC[BUS_C].A = period;
616  }
617  else if (channel <= 23U)
618  {
619  eMIOS[instance->instIdx]->UC[BUS_D].A = period;
620  }
621  else if (channel <= 31U)
622  {
623  eMIOS[instance->instIdx]->UC[BUS_E].A = period;
624  }
625  else
626  {
627  /* Noting to do */
628  }
629  break;
630  case 2U:
631  eMIOS[instance->instIdx]->UC[BUS_F].A = period;
632  break;
633  default: /* Noting to do */
634  break;
635  }
636  status = STATUS_SUCCESS;
637  }
638  else
639  #endif
640 
641  #if (defined (PWM_OVER_ETIMER))
642  uint16_t comp1,comp2;
643  if (instance->instType == PWM_INST_TYPE_ETIMER)
644  {
645  /* read current compare values */
646  ETIMER_DRV_GetCompareThresholdBuffered(instance->instIdx, channel, &comp1, &comp2);
647  /* the period cycle must be higher or equal with the duty */
648  if(period>=comp1)
649  {
650  /* set it */
651  ETIMER_DRV_SetCompareThresholdBuffered(instance->instIdx, channel, comp1, (period-comp1));
652  /* all ok */
653  status = STATUS_SUCCESS;
654  }
655  else
656  {
657  /* duty is higher than period */
658  DEV_ASSERT(false);
659  }
660  }
661  else
662  #endif
663  {
664  DEV_ASSERT(false);
665  }
666  return status;
667 }
668 
669 /*FUNCTION**********************************************************************
670  *
671  * Function Name : PWM_OverwriteOutputChannels
672  * Description : This function change the output value for some channels. channelsMask select
673  * which channels will be overwrite, each bit filed representing one channel: 1 - channel is controlled
674  * by channelsValues, 0 - channel is controlled by pwm. channelsValues select output values to be write on corresponding
675  * channel.
676  * Implements : PWM_OverwriteOutputChannels_Activity
677  *
678  *END**************************************************************************/
679 status_t PWM_OverwriteOutputChannels(const pwm_instance_t * const instance, uint32_t channelsMask, uint32_t channelsValues)
680 {
681  DEV_ASSERT(instance != NULL);
682 
683  status_t status = STATUS_ERROR;
684 
685  #if (defined(PWM_OVER_FTM))
686  if (instance->instType == PWM_INST_TYPE_FTM)
687  {
688  (void)FTM_DRV_SetAllChnSoftwareOutputControl(instance->instIdx, (uint8_t)channelsMask, (uint8_t)channelsValues);
689  status = STATUS_SUCCESS;
690  }
691  else
692  #endif
693 
694  #if (defined(PWM_OVER_EMIOS))
695  if (instance->instType == PWM_INST_TYPE_EMIOS)
696  {
697  status = STATUS_UNSUPPORTED;
698  }
699  else
700  #endif
701 
702  #if (defined (PWM_OVER_ETIMER))
703  if (instance->instType == PWM_INST_TYPE_ETIMER)
704  {
705  status = STATUS_UNSUPPORTED;
706  }
707  else
708  #endif
709  {
710  DEV_ASSERT(false);
711  }
712 
713  return status;
714 }
715 
716 /*FUNCTION**********************************************************************
717  *
718  * Function Name : PWM_Deinit
719  * Description : Uninitialised PWM instance.
720  * Implements : PWM_Deinit_Activity
721  *
722  *END**************************************************************************/
723 status_t PWM_Deinit(const pwm_instance_t * const instance)
724 {
725  DEV_ASSERT(instance != NULL);
726 
727  status_t status = STATUS_ERROR;
728 
729  #if (defined(PWM_OVER_FTM))
730  if (instance->instType == PWM_INST_TYPE_FTM)
731  {
732  (void)FTM_DRV_DeinitPwm(instance->instIdx);
733  (void)FTM_DRV_Deinit(instance->instIdx);
734  PwmFreeState(FtmStateIsAllocated, FtmStateInstanceMapping, instance, NO_OF_FTM_INSTS_FOR_PWM);
735  status = STATUS_SUCCESS;
736  }
737  else
738  #endif
739 
740  #if (defined(PWM_OVER_EMIOS))
741  if (instance->instType == PWM_INST_TYPE_EMIOS)
742  {
743  uint8_t index;
744  for (index = 0U; index < 32U; index++)
745  {
746  /* Disable channels in the output compare over EMIOS */
747  EMIOS_DRV_DeInitChannel((uint8_t)instance->instIdx,
748  index);
749  }
750  status = STATUS_SUCCESS;
751  }
752  else
753  #endif
754 
755  #if (defined (PWM_OVER_ETIMER))
756  if (instance->instType == PWM_INST_TYPE_ETIMER)
757  {
758  /* deinitialize ETIMERx peripheral */
759  ETIMER_DRV_Deinit(instance->instIdx);
760  status = STATUS_SUCCESS;
761  }
762  else
763  #endif
764 
765  {
766  DEV_ASSERT(false);
767  }
768 
769  return status;
770 }
ftm_reg_update_t initCounterSync
Definition: ftm_common.h:425
ftm_pwm_sync_t syncMethod
Definition: ftm_common.h:438
uint8_t channel
Definition: pwm_pal.h:153
status_t FTM_DRV_DeinitPwm(uint32_t instance)
Stops all PWM channels .
FlexTimer state structure of the driver.
Definition: ftm_common.h:391
FlexTimer driver independent PWM parameter.
ftm_safe_state_polarity_t levelSelect
ftm_bdm_mode_t BDMMode
Definition: ftm_common.h:444
bool hardwareSync2
Definition: ftm_common.h:416
pwm_polarity_t polarity
Definition: pwm_pal.h:157
#define FEATURE_FTM_CHANNEL_COUNT
Configuration structure that the user needs to set.
Definition: ftm_common.h:436
uint32_t uFrequencyHZ
status_t PWM_UpdatePeriod(const pwm_instance_t *const instance, uint8_t channel, uint32_t period)
Update period for specific a specific channel. This function changes period for all channels which sh...
Definition: pwm_pal.c:583
This structure is the configuration for initialization of PWM channels. Implements : pwm_global_confi...
Definition: pwm_pal.h:170
status_t PWM_Init(const pwm_instance_t *const instance, const pwm_global_config_t *config)
Initialize PWM channels based on config parameter.
Definition: pwm_pal.c:134
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 ...
bool hardwareSync1
Definition: ftm_common.h:414
uint8_t numberOfPwmChannels
Definition: pwm_pal.h:173
ftm_deadtime_ps_t deadTimePrescaler
uint8_t nNumCombinedPwmChannels
#define DEV_ASSERT(x)
Definition: devassert.h:77
uint32_t period
Definition: pwm_pal.h:155
#define FTM_MAX_DUTY_CYCLE
Maximum value for PWM duty cycle.
uint32_t FTM_DRV_GetFrequency(uint32_t instance)
Retrieves the frequency of the clock source feeding the FTM counter.
Definition: ftm_common.c:733
uint32_t duty
Definition: pwm_pal.h:156
bool hardwareSync0
Definition: ftm_common.h:412
status_t PWM_Deinit(const pwm_instance_t *const instance)
Uninitialised PWM instance.
Definition: pwm_pal.c:723
ftm_pwm_sync_mode_t syncPoint
Definition: ftm_common.h:427
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
bool enableComplementaryChannel
Definition: pwm_pal.h:160
bool maxLoadingPoint
Definition: ftm_common.h:418
ftm_second_channel_polarity_t secondChannelPolarity
FlexTimer driver combined PWM parameter.
uint8_t nNumIndependentPwmChannels
pwm_complementarty_mode_t complementaryChannelPolarity
Definition: pwm_pal.h:161
FlexTimer driver PWM parameters.
ftm_reg_update_t inverterSync
Definition: ftm_common.h:422
uint8_t deadtime
Definition: pwm_pal.h:159
ftm_independent_ch_param_t * pwmIndependentChannelConfig
pwm_channel_type_t channelType
Definition: pwm_pal.h:154
ftm_config_mode_t ftmMode
Definition: ftm_common.h:440
pwm_channel_t * pwmChannels
Definition: pwm_pal.h:172
status_t FTM_DRV_Deinit(uint32_t instance)
Shuts down the FTM driver.
Definition: ftm_common.c:196
ftm_reg_update_t maskRegSync
Definition: ftm_common.h:424
bool minLoadingPoint
Definition: ftm_common.h:420
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).
bool insertDeadtime
Definition: pwm_pal.h:158
bool autoClearTrigger
Definition: ftm_common.h:426
status_t PWM_UpdateDuty(const pwm_instance_t *const instance, uint8_t channel, uint32_t duty)
Update duty cycle. The measurement unit for duty is clock ticks.
Definition: pwm_pal.c:516
status_t FTM_DRV_Init(uint32_t instance, const ftm_user_config_t *info, ftm_state_t *state)
Initializes the FTM driver.
Definition: ftm_common.c:117
status_t PWM_OverwriteOutputChannels(const pwm_instance_t *const instance, uint32_t channelsMask, uint32_t channelsValues)
This function change the output value for some channels. channelsMask select which channels will be o...
Definition: pwm_pal.c:679
Structure storing PAL instance information.
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...
void * timebase
Definition: pwm_pal.h:162
ftm_clock_source_t ftmClockSource
Definition: ftm_common.h:443
FlexTimer driver PWM Fault parameter.
pwm_inst_type_t instType
ftm_pwm_fault_param_t * faultConfig
ftm_config_mode_t mode
ftm_reg_update_t outRegSync
Definition: ftm_common.h:423
ftm_combined_ch_param_t * pwmCombinedChannelConfig
status_t FTM_DRV_SetAllChnSoftwareOutputControl(uint32_t instance, uint8_t channelMask, uint8_t channelValueMask)
This function will control list of channels by software to force the output to specified value...
Definition: ftm_common.c:321
ftm_clock_ps_t ftmPrescaler
Definition: ftm_common.h:441