Kinetis K10 CPWM and Enhanced FTMEN registers

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Kinetis K10 CPWM and Enhanced FTMEN registers

1,799 Views
tommyp
Contributor III

I am using a K10 72Mhz and configured it for legacy Center Aligned PWM.   This has been working fine, but I need to stop the PWM on a fault.

The first thing  I turned on the FTMEN=1 per the datasheet to allow access to the fault control options.

When FTMEN is 1, I can no longer generate a PWM.  I suspect there is some other register that needs to be tweaked to allow a reload of the duty cycle, but I can not find it.

I have tried COMBINED, SYNC and other register values, but it won't turn on.  If I manually update the C0V with a value from jtag, I do generate a PWM, but no values are ever loaded that I set programatically.

I've looked through some app notes, but even with the suggested settings, the PWM duty is never updated.

What am I missing? 

0 Kudos
12 Replies

1,236 Views
dereksnell
NXP Employee
NXP Employee

Hi Tom,

From the Kinetis reference manual, the Center Aligned PWM mode is not supported in FTM mode when FTMEN=1. Also, to use the hardware faults with FTM, the PWM chnnel should be setup in COMBINED mode.  You can still setup PWM waveforms as center aligned in COMBINED mode.  In this mode, you control the timing of both the rising and falling edge using the CnV channel value registers of the channel pairs n and n+1.

I’ve attached an example project created for you using Kinetis Design Studio and Processor Expert (PEx).  This configures the two FTM channels in COMBINED mode, uses hardware faults with the analog comparator, and clears the fault manually in firmware.  More details on the attached project are below.

Main() clears the hardware fault using this code:

if(FTM0_FMS & FTM_FMS_FAULTF0_MASK)

FTM0_FMS &= !FTM_FMS_FAULTF0_MASK; // Clear fault flag

The generated code from PEx for the FTM is in FTM0_Init() in FTM0.c.  Here is the code used:

/* SIM_SCGC6: FTM0=1 */

  SIM_SCGC6 |= SIM_SCGC6_FTM0_MASK;

  (void)(FTM0_SC == 0U);               /* Dummy read of the FTM0_SC register to clear the interrupt flag */

  /* FTM0_SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,TOF=0,TOIE=0,CPWMS=0,CLKS=0,PS=0 */

  FTM0_SC = (FTM_SC_CLKS(0x00) | FTM_SC_PS(0x00)); /* Stop the counter */

    (void)(FTM0_C2SC == 0U);           /* Dummy read of the FTM0_C2SC register to clear the interrupt flag */

    (void)(FTM0_C3SC == 0U);           /* Dummy read of the FTM0_C3SC register to clear the interrupt flag */

  /* FTM0_MODE: WPDIS=1 */

  FTM0_MODE |= FTM_MODE_WPDIS_MASK;    /* Disable write protection */

  /* FTM0_C0SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */

  FTM0_C0SC = 0x00U;

  /* FTM0_C1SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */

  FTM0_C1SC = 0x00U;

  /* FTM0_C2SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */

  FTM0_C2SC = 0x00U;

  /* FTM0_C3SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */

  FTM0_C3SC = 0x00U;

  /* FTM0_C4SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */

  FTM0_C4SC = 0x00U;

  /* FTM0_C5SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */

  FTM0_C5SC = 0x00U;

  /* FTM0_C6SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */

  FTM0_C6SC = 0x00U;

  /* FTM0_C7SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0,DMA=0 */

  FTM0_C7SC = 0x00U;

  /* FTM0_SC: TOF=0,CPWMS=0 */

  FTM0_SC &= (uint32_t)~(uint32_t)((FTM_SC_TOF_MASK | FTM_SC_CPWMS_MASK));

  /* FTM0_MODE: FTMEN=1 */

  FTM0_MODE |= FTM_MODE_FTMEN_MASK;

  /* FTM0_COMBINE: FAULTEN3=0,SYNCEN3=0,DTEN3=0,COMP3=0,FAULTEN2=0,SYNCEN2=0,DTEN2=0,COMP2=0,FAULTEN1=1,SYNCEN1=0,DTEN1=0,DECAPEN1=0,COMP1=0,COMBINE1=1,FAULTEN0=0,SYNCEN0=0,DTEN0=0,COMP0=0 */

  FTM0_COMBINE = (uint32_t)((FTM0_COMBINE & (uint32_t)~(uint32_t)(

                  FTM_COMBINE_FAULTEN3_MASK |

                  FTM_COMBINE_SYNCEN3_MASK |

                  FTM_COMBINE_DTEN3_MASK |

                  FTM_COMBINE_COMP3_MASK |

                  FTM_COMBINE_FAULTEN2_MASK |

                  FTM_COMBINE_SYNCEN2_MASK |

                  FTM_COMBINE_DTEN2_MASK |

                  FTM_COMBINE_COMP2_MASK |

                  FTM_COMBINE_SYNCEN1_MASK |

                  FTM_COMBINE_DTEN1_MASK |

                  FTM_COMBINE_DECAPEN1_MASK |

                  FTM_COMBINE_COMP1_MASK |

                  FTM_COMBINE_FAULTEN0_MASK |

                  FTM_COMBINE_SYNCEN0_MASK |

                  FTM_COMBINE_DTEN0_MASK |

                  FTM_COMBINE_COMP0_MASK

                 )) | (uint32_t)(

                  FTM_COMBINE_FAULTEN1_MASK |

                  FTM_COMBINE_COMBINE1_MASK

                 ));

  /* FTM0_INVCTRL: INV3EN=0,INV2EN=0,INV1EN=0,INV0EN=0 */

  FTM0_INVCTRL &= (uint32_t)~(uint32_t)(

                   FTM_INVCTRL_INV3EN_MASK |

                   FTM_INVCTRL_INV2EN_MASK |

                   FTM_INVCTRL_INV1EN_MASK |

                   FTM_INVCTRL_INV0EN_MASK

                  );

  /* FTM0_C0SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0 */

  FTM0_C0SC &= (uint32_t)~(uint32_t)(

                FTM_CnSC_CHF_MASK |

                FTM_CnSC_MSB_MASK |

                FTM_CnSC_MSA_MASK |

                FTM_CnSC_ELSB_MASK |

                FTM_CnSC_ELSA_MASK |

                0xFFFFFF02U

               );

  /* FTM0_C1SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0 */

  FTM0_C1SC &= (uint32_t)~(uint32_t)(

                FTM_CnSC_CHF_MASK |

                FTM_CnSC_MSB_MASK |

                FTM_CnSC_MSA_MASK |

                FTM_CnSC_ELSB_MASK |

                FTM_CnSC_ELSA_MASK |

                0xFFFFFF02U

               );

  /* FTM0_C2SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,ELSB=1,ELSA=0,??=0,DMA=0 */

  FTM0_C2SC = (uint32_t)((FTM0_C2SC & (uint32_t)~(uint32_t)(

               FTM_CnSC_CHF_MASK |

               FTM_CnSC_CHIE_MASK |

               FTM_CnSC_ELSA_MASK |

               FTM_CnSC_DMA_MASK |

               0xFFFFFF02U

              )) | (uint32_t)(

               FTM_CnSC_ELSB_MASK

              ));

  /* FTM0_C3SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,CHIE=0,ELSB=1,ELSA=0,??=0,DMA=0 */

  FTM0_C3SC = (uint32_t)((FTM0_C3SC & (uint32_t)~(uint32_t)(

               FTM_CnSC_CHF_MASK |

               FTM_CnSC_CHIE_MASK |

               FTM_CnSC_ELSA_MASK |

               FTM_CnSC_DMA_MASK |

               0xFFFFFF02U

              )) | (uint32_t)(

               FTM_CnSC_ELSB_MASK

              ));

  /* FTM0_C4SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0 */

  FTM0_C4SC &= (uint32_t)~(uint32_t)(

                FTM_CnSC_CHF_MASK |

                FTM_CnSC_MSB_MASK |

                FTM_CnSC_MSA_MASK |

                FTM_CnSC_ELSB_MASK |

                FTM_CnSC_ELSA_MASK |

                0xFFFFFF02U

               );

  /* FTM0_C5SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0 */

  FTM0_C5SC &= (uint32_t)~(uint32_t)(

                FTM_CnSC_CHF_MASK |

                FTM_CnSC_MSB_MASK |

                FTM_CnSC_MSA_MASK |

                FTM_CnSC_ELSB_MASK |

                FTM_CnSC_ELSA_MASK |

                0xFFFFFF02U

               );

  /* FTM0_C6SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0 */

  FTM0_C6SC &= (uint32_t)~(uint32_t)(

                FTM_CnSC_CHF_MASK |

                FTM_CnSC_MSB_MASK |

                FTM_CnSC_MSA_MASK |

                FTM_CnSC_ELSB_MASK |

                FTM_CnSC_ELSA_MASK |

                0xFFFFFF02U

               );

  /* FTM0_C7SC: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CHF=0,MSB=0,MSA=0,ELSB=0,ELSA=0,??=0 */

  FTM0_C7SC &= (uint32_t)~(uint32_t)(

                FTM_CnSC_CHF_MASK |

                FTM_CnSC_MSB_MASK |

                FTM_CnSC_MSA_MASK |

                FTM_CnSC_ELSB_MASK |

                FTM_CnSC_ELSA_MASK |

                0xFFFFFF02U

               );

  /* FTM0_C2V: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,VAL=0x3A98 */

  FTM0_C2V = FTM_CnV_VAL(0x3A98);

  /* FTM0_C3V: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,VAL=0xAFC8 */

  FTM0_C3V = FTM_CnV_VAL(0xAFC8);

  /* FTM0_POL: POL3=0,POL2=0 */

  FTM0_POL &= (uint32_t)~(uint32_t)((FTM_POL_POL3_MASK | FTM_POL_POL2_MASK));

  /* FTM0_FILTER: CH3FVAL=0,CH2FVAL=0 */

  FTM0_FILTER &= (uint32_t)~(uint32_t)(

                  FTM_FILTER_CH3FVAL(0x0F) |

                  FTM_FILTER_CH2FVAL(0x0F)

                 );

  /* FTM0_OUTINIT: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,CH3OI=0,CH2OI=0 */

  FTM0_OUTINIT &= (uint32_t)~(uint32_t)(

                   FTM_OUTINIT_CH3OI_MASK |

                   FTM_OUTINIT_CH2OI_MASK |

                   0xFFFFFF00U

                  );

  /* FTM0_OUTMASK: CH3OM=0,CH2OM=0 */

  FTM0_OUTMASK &= (uint32_t)~(uint32_t)(

                   FTM_OUTMASK_CH3OM_MASK |

                   FTM_OUTMASK_CH2OM_MASK

                  );

  /* FTM0_FLTCTRL: FFVAL=0 */

  FTM0_FLTCTRL &= (uint32_t)~(uint32_t)(FTM_FLTCTRL_FFVAL(0x0F));

  /* FTM0_FLTPOL: FLT3POL=0,FLT2POL=0,FLT1POL=0,FLT0POL=0 */

  FTM0_FLTPOL &= (uint32_t)~(uint32_t)(

                  FTM_FLTPOL_FLT3POL_MASK |

                  FTM_FLTPOL_FLT2POL_MASK |

                  FTM_FLTPOL_FLT1POL_MASK |

                  FTM_FLTPOL_FLT0POL_MASK

                 );

  /* FTM0_FLTCTRL: FFLTR3EN=0,FFLTR2EN=0,FFLTR1EN=0,FFLTR0EN=0,FAULT3EN=0,FAULT2EN=0,FAULT1EN=0,FAULT0EN=1 */

  FTM0_FLTCTRL = (uint32_t)((FTM0_FLTCTRL & (uint32_t)~(uint32_t)(

                  FTM_FLTCTRL_FFLTR3EN_MASK |

                  FTM_FLTCTRL_FFLTR2EN_MASK |

                  FTM_FLTCTRL_FFLTR1EN_MASK |

                  FTM_FLTCTRL_FFLTR0EN_MASK |

                  FTM_FLTCTRL_FAULT3EN_MASK |

                  FTM_FLTCTRL_FAULT2EN_MASK |

                  FTM_FLTCTRL_FAULT1EN_MASK

                 )) | (uint32_t)(

                  FTM_FLTCTRL_FAULT0EN_MASK

                 ));

  /* FTM0_SYNC: SWSYNC=0,TRIG2=0,TRIG1=0,TRIG0=0,SYNCHOM=0,REINIT=0,CNTMAX=0,CNTMIN=0 */

  FTM0_SYNC &= (uint32_t)~(uint32_t)(

                FTM_SYNC_SWSYNC_MASK |

                FTM_SYNC_TRIG2_MASK |

                FTM_SYNC_TRIG1_MASK |

                FTM_SYNC_TRIG0_MASK |

                FTM_SYNC_SYNCHOM_MASK |

                FTM_SYNC_REINIT_MASK |

                FTM_SYNC_CNTMAX_MASK |

                FTM_SYNC_CNTMIN_MASK

               );

  /* FTM0_EXTTRIG: INITTRIGEN=0,CH1TRIG=0,CH0TRIG=0,CH5TRIG=0,CH4TRIG=0,CH3TRIG=0,CH2TRIG=0 */

  FTM0_EXTTRIG &= (uint32_t)~(uint32_t)(

                   FTM_EXTTRIG_INITTRIGEN_MASK |

                   FTM_EXTTRIG_CH1TRIG_MASK |

                   FTM_EXTTRIG_CH0TRIG_MASK |

                   FTM_EXTTRIG_CH5TRIG_MASK |

                   FTM_EXTTRIG_CH4TRIG_MASK |

                   FTM_EXTTRIG_CH3TRIG_MASK |

                   FTM_EXTTRIG_CH2TRIG_MASK

                  );

  /* FTM0_MOD: MOD=0xEA60 */

  FTM0_MOD = (uint32_t)((FTM0_MOD & (uint32_t)~(uint32_t)(

              FTM_MOD_MOD(0x159F)

             )) | (uint32_t)(

              FTM_MOD_MOD(0xEA60)

             ));

  /* FTM0_CNTIN: INIT=0 */

  FTM0_CNTIN &= (uint32_t)~(uint32_t)(FTM_CNTIN_INIT(0xFFFF));

  /* FTM0_DEADTIME: DTPS=0,DTVAL=0 */

  FTM0_DEADTIME &= (uint32_t)~(uint32_t)(

                    FTM_DEADTIME_DTPS(0x03) |

                    FTM_DEADTIME_DTVAL(0x3F)

                   );

  /* FTM0_CNT: COUNT=0 */

  FTM0_CNT &= (uint32_t)~(uint32_t)(FTM_CNT_COUNT(0xFFFF));

  /* FTM0_MODE: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,FAULTIE=1,FAULTM=2,PWMSYNC=0,INIT=0,FTMEN=1 */

  FTM0_MODE = (uint32_t)((FTM0_MODE & (uint32_t)~(uint32_t)(

               FTM_MODE_FAULTM(0x01) |

               FTM_MODE_PWMSYNC_MASK |

               FTM_MODE_INIT_MASK |

               0xFFFFFF00U

              )) | (uint32_t)(

               FTM_MODE_FAULTIE_MASK |

               FTM_MODE_FAULTM(0x02) |

               FTM_MODE_FTMEN_MASK

              ));

  /* FTM0_SYNCONF: ??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,SYNCMODE=0,??=0,SWOC=0,INVC=0,??=0,CNTINC=0,??=0,HWTRIGMODE=0 */

  FTM0_SYNCONF &= (uint32_t)~(uint32_t)(

                   FTM_SYNCONF_SYNCMODE_MASK |

                   FTM_SYNCONF_SWOC_MASK |

                   FTM_SYNCONF_INVC_MASK |

                   FTM_SYNCONF_CNTINC_MASK |

                   FTM_SYNCONF_HWTRIGMODE_MASK |

                   0xFFE0E04AU

                  );

  /* FTM0_SC: TOF=0,TOIE=0,CPWMS=0,CLKS=1,PS=0 */

  FTM0_SC = (uint32_t)((FTM0_SC & (uint32_t)~(uint32_t)(

             FTM_SC_TOF_MASK |

             FTM_SC_TOIE_MASK |

             FTM_SC_CPWMS_MASK |

             FTM_SC_CLKS(0x02) |

             FTM_SC_PS(0x07)

            )) | (uint32_t)(

             FTM_SC_CLKS(0x01)

            ));

  /* FTM0_FMS: FAULTF=0,WPEN=0,FAULTF3=0,FAULTF2=0,FAULTF1=0,FAULTF0=0 */

  FTM0_FMS &= (uint32_t)~(uint32_t)(

               FTM_FMS_FAULTF_MASK |

               FTM_FMS_WPEN_MASK |

               FTM_FMS_FAULTF3_MASK |

               FTM_FMS_FAULTF2_MASK |

               FTM_FMS_FAULTF1_MASK |

               FTM_FMS_FAULTF0_MASK

              );

  /* FTM0_SWOCTRL: CH3OC=0,CH2OC=0 */

  FTM0_SWOCTRL &= (uint32_t)~(uint32_t)(

                   FTM_SWOCTRL_CH3OC_MASK |

                   FTM_SWOCTRL_CH2OC_MASK

                  );

  /* FTM0_CONF: GTBEOUT=0,GTBEEN=0,BDMMODE=0,NUMTOF=0 */

  FTM0_CONF &= (uint32_t)~(uint32_t)(

                FTM_CONF_GTBEOUT_MASK |

                FTM_CONF_GTBEEN_MASK |

                FTM_CONF_BDMMODE(0x03) |

                FTM_CONF_NUMTOF(0x1F)

               );

  /* FTM0_PWMLOAD: LDOK=0,CH7SEL=0,CH6SEL=0,CH5SEL=0,CH4SEL=0,CH3SEL=0,CH2SEL=0,CH1SEL=0,CH0SEL=0 */

  FTM0_PWMLOAD &= (uint32_t)~(uint32_t)(

                   FTM_PWMLOAD_LDOK_MASK |

                   FTM_PWMLOAD_CH7SEL_MASK |

                   FTM_PWMLOAD_CH6SEL_MASK |

                   FTM_PWMLOAD_CH5SEL_MASK |

                   FTM_PWMLOAD_CH4SEL_MASK |

                   FTM_PWMLOAD_CH3SEL_MASK |

                   FTM_PWMLOAD_CH2SEL_MASK |

                   FTM_PWMLOAD_CH1SEL_MASK |

                   FTM_PWMLOAD_CH0SEL_MASK

                  );

Here’s more details on the example project.  This comes from the included readme.txt:

This is an example project using FlexTimer (FTM) hardware

faults to disable the PWM output.  The project is created

for the TWR-K20D72M Tower board, using KDS v2.0.0 and

Processor Expert (PEx).

PEx is used to configure FTM0 for PWM in combined mode,

with hardware fault enabled using the Init_FTM component. 

The PWM signal is output on FTM0_CH2, which is pin PTC3.

This PWM can be captured with a scope on the Tower Elevator

header A38.  Init_FTM component also configures hardware fault

input on FTM0 FAULT0 input, configured for the analog comparator

CMP0. 

The comparator is configured using PEx component AnalogComp_LDD.

The positive input of the comparator is set to the external pin

CMP0_IN1, which is pin PTC7. On the Tower board, PTC7 is connected

to pin1 on the two-pin header J3.  The comparator negative input

is connected to the internal 6-bit DAC reference.  The DAC is

configured using the PEx component DAC_LDD to set the output at

half the supply voltage. The comparator output is also driven

out the output pin CMP0_OUT, which is pin PTC5.  This signal

can be monitored with a scope on the Elevator header pin B62.

The FTM0 is configured to disable the PWM when the fault signal

is asserted, and the fault needs to be cleared manually by software.

The example code clears the fault in main().

To run the example, download the code to the Tower board and run.

Connect a scope to watch the PWM signal on PTC3.  When the

comparator input signal pin1 on J3 is shorted to VSS, there is

no fault asserted, and the PWM waveform is present.  When the short

to VSS on J3 is removed, the comparator output signal goes high

and the PWM signal stops. When the comparator input on J3 is shorted

to VSS again, the application clears the fault, and the PWM signal

  1. resumes.

NOTE: using the debugger to halt the MCU will stop the PWM.  To see

the PWM operation, reset the MCU in the debugger and run without

halting, or run the MCU without the debugger from the application

in flash.

0 Kudos

1,236 Views
tommyp
Contributor III

I had missed the InitFTM option in PEx, I'm looking at it now.


Where in the manual did you find that "From the Kinetis reference manual, the Center Aligned PWM mode is not supported in FTM mode when FTMEN=1" ??

Also for COMBINE mode, maybe it is just the register name, but I really don't give a frake about the CNv+1 channel, I'm only using CNv.

Can you clarify these please.

0 Kudos

1,236 Views
dereksnell
NXP Employee
NXP Employee

Hi Tom,

Sorry, the FTM does allow center aligned PWM channels when FTMEN=1. But in the reference manual section “Fault Control”, it states “The fault control must be used only in Combine mode.” This was why I have the sample project setup for COMBINED mode of channels 2 and 3.

Thanks

0 Kudos

1,236 Views
tommyp
Contributor III

Can you check with the factory regarding the fault inputs.  I'm able to set/reset faults when FTMEN =0, and as the previous person indicated, this seems to be separate from combine mode.

Also, when I set ftmen=1, and set the channel value register to non zero value, it does output my pwm at the non zero value, but it does not load new CnV values.  THis may be my problem, how do I force it to update CnV from the buffered value....

0 Kudos

1,236 Views
dereksnell
NXP Employee
NXP Employee

Hi Tom,

Our design team did confirm hardware faults can be used when FTMEN=0:

"It is OK to use fault control when FTMEN is disabled. That usage has been blocked in older documentation because the feature had not been verified at that time for FTMEN = 0. This restriction was removed from the latest documentation source."

The 72MHz reference manuals have not been updated yet since this change was made to the source documentation used to create the reference manuals. But a newer reference manual for a different device is K22P121M100SF9RM<http://cache.freescale.com/files/microcontrollers/doc/ref_manual/K22P121M100SF9RM.pdf>, and it uses the same FlexTimer hardware. We changed the statement in “Fault Control” section to say “The fault control is enabled if (FAULTM[1:0] != 0:0)”, and removed the requirement for FTMEN=1.

Thanks

0 Kudos

1,235 Views
dereksnell
NXP Employee
NXP Employee

Hi Tom,

I will verify if the fault inputs are supported when FTMEN=0, or when not used with PWM in COMBINED mode.

As for updating the PWM duty cycles with the channel value registers, I will assume for now FTMEN=1 is required until we learn otherwise. The PWM registers are buffered, and changes to those registers do not happen immediately while the PWM is active, which enables the changes to PWM registers to be synchronized. The registers are updated with their buffer values according to the reference manual documentation in FTM section “Registers updated from write buffers”. The registers can also be loaded with the buffer values at loading points (like a new PWM period) using the FTMx_PWMLOAD[LDOK] bit, and this is documented in the FTM section “Intermediate load”.

I’ve updated the attached example project to change the PWM duty cycles with hardware faults enabled using the LDOK bit. Since this still uses the PWM channels in combined mode, the FTM0_COMBINE[SYNCEN1] is set to allow updates to channels 2 & 3 used in this example. The update occurs periodically using the PIT timer interrupt. The interrupt callback is in Events.c. To change the duty cycle, the combined channel value registers FTM0_C2V and FTM0_C3V are updated, and then FTM0_PWMLOAD[LDOK] is set.

Thanks

0 Kudos

1,235 Views
tommyp
Contributor III

Setting LDOK is software driven, what settings are needed to allow the duty to update automagically when the counter hits 0 (in terms of up/down counting).   This would force a load of new duty at the beginning of the Low pulse in my case, well before the center aligned value hits during the count up.  Ive tried various options load load point of CNTMIN, etc.

0 Kudos

1,235 Views
dereksnell
NXP Employee
NXP Employee

Hi Tom,

The LDOK bit signals the hardware that the PWM register values are ready to be updated, and the hardware will load the new values from the buffers into the registers at the start of the new PWM cycle, like you are trying to do. Or at a different loading point if desired, see FTM section “Intermediate Load”. Setting LDOK doesn’t immediately update the PWM registers. It’s intended for the hardware to do the update at the next loading point, like you desire.

From FTM section “FTM PWM Load (FTMx_PWMLOAD)”:

Enables the loading of the MOD, CNTIN, C(n)V, and C(n+1)V registers with the values

of their write buffers when the FTM counter changes from the MOD register value to its

next value or when a channel (j) match occurs. A match occurs for the channel (j) when

FTM counter = C(j)V.

When using center-aligned PWM mode, the PWM period starts when the counter reaches the value in the FTMx_MOD register, and the counter overflow flag is set. Then the counter counts down to the value in FTMx_CNTIN register, then counts back up to MOD, and repeats. The MOD value is the center of one pulse, and CNTIN is the center of the pulse of opposite polarity. In this case, using LDOK updates the PWM registers when the counter counts up to MOD value and then starts the new PWM period. That sounds like what you need.

Also note, this is the same point the center aligned PWM updates the CnV registers if FTMEN=0, and writing LDOK is not needed. The snippet below from the reference manual shows when center-aligned PWM is updated when FTMEN=0. After the CnV registers are written, the update doesn’t happen immediately. It happens at the start of the next PWM period, which is when the counter changes from MOD value to MOD-1. That is the same register loading time when FTMEN=1 and the LDOK bit was set. Thanks

0 Kudos

1,235 Views
tommyp
Contributor III

Update.  I found by leaving the FTM in non enhanced, the fault detect still works, and to clear it I write 0 to the CNT register.   Now, is this a work around, bad idea, or is there a better approach?

0 Kudos

1,234 Views
jeremyzhou
NXP Employee
NXP Employee

Hi TOM,

FTM module support to detect fault issue through the FTM fault input pin when FTM module work in enhanced mode ( FTMEN=1 ), and after

I've had a brief look through the reference manual, I find the fault detect function is independent of the other functions.

I'm surely that you must miss some things when you want to integrate the COMBINED mode with the Fault detect mode.

So I was wondering if you could share the project about COMBINED mode with the Fault detect mode, then I can reproduce the issue within my board.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,234 Views
tommyp
Contributor III

I am not able to post the codebase. sorry

0 Kudos

1,234 Views
jeremyzhou
NXP Employee
NXP Employee

Hi TOM,

Derek shared a good demo, I think it will help you out.

Please refer to it for details.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos