S32K14X FTM Combine Mode MOD and CnV register update

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

S32K14X FTM Combine Mode MOD and CnV register update

Jump to solution
581 Views
yumi
Contributor II

The specific application scenarios are as follows: two PWMs are required, and the periods of the two PWMs are the same; but the period, duty cycle, and phase shift are all adjustable.

My program is initialized as follows. Set Ch2/3/6/7 of FTM0 to Combine Mode, where Ch2/3 forms one output, Ch6/7 forms one output, and Ch6 serves as the trigger source of LPTMR to trigger LPTMR counting.

void FTM0_Init(void)

{

  PCC->PCCn[PCC_FTM0_INDEX] &= ~PCC_PCCn_CGC_MASK;                                                                /* Disable clock for FTM0 during configuration */

  PCC->PCCn[PCC_FTM0_INDEX] &= ~PCC_PCCn_PCS_MASK;

  PCC->PCCn[PCC_FTM0_INDEX] |= PCC_PCCn_PCS(6);                                                                            /* Source clock SPLLDIV1_CLK=80M, refer to Peripheral module clocking(Clocking Gating) */

  PCC->PCCn[PCC_FTM0_INDEX] |= PCC_PCCn_CGC_MASK;                                                               /* Enable clock for FTM0 register */

   

  FTM0->OUTINIT = 0x00;                                                                                                                                /* Channel n output initialization value,channel 0& channel6=0 */

  FTM0->MODE = FTM_MODE_WPDIS(1)                                                                                             /* WPDIS=1b,write protect to registers disabled (default) */

         | FTM_MODE_INIT(1);                                                                                                                              /* When a 1 is written to INIT bit the channels output is initialized according to the state of their corresponding bit in the OUTINIT register */

  FTM0->CNTIN = FTM_CNTIN_INIT(0);                                                                                                   /*Set CNTIN in initialization stage */ 

  /* Clear TOF */

  if((FTM0->SC & FTM_SC_TOF_MASK)== FTM_SC_TOF_MASK)

  {   /* CHF = 1, set by hardware when an event occurs on channel 0 */

         (void)FTM0->SC;                                                                                                                                         /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */

         FTM0->SC &= ~FTM_SC_TOF_MASK;                                                                                                     /* Bit9=0,clear the timer overflow flag */

  }

  /* Clear RF */

  if((FTM0->SC & FTM_SC_RF_MASK)== FTM_SC_RF_MASK)

  {   /* CHF = 1, set by hardware when an event occurs on channel 0 */

         (void)FTM0->SC;                                                                                                                                         /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */

         FTM0->SC &= FTM_SC_RF_MASK;                                                                                                          /* Bit7=0,clear the reload flag */

  }

 

  /* Clear CHF */

  if((FTM0->CONTROLS[2].CnSC & FTM_CnSC_CHF_MASK)== FTM_CnSC_CHF_MASK)

  {   /* CHF = 1, set by hardware when an event occurs on channel 2 */

         (void)FTM0->CONTROLS[2].CnSC;                                                                                                  /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */

         FTM0->CONTROLS[2].CnSC &= ~FTM_CnSC_CHF_MASK;                                                                   /* Bit7=0,clear the channel interrupt flag */

  }

  if((FTM0->CONTROLS[3].CnSC & FTM_CnSC_CHF_MASK)== FTM_CnSC_CHF_MASK)

  {   /* CHF = 1, set by hardware when an event occurs on channel 3 */

         (void)FTM0->CONTROLS[3].CnSC;                                                                                                  /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */

         FTM0->CONTROLS[3].CnSC &= ~FTM_CnSC_CHF_MASK;                                                                   /* Bit7=0,clear the channel interrupt flag */

  }

  if((FTM0->CONTROLS[6].CnSC & FTM_CnSC_CHF_MASK)== FTM_CnSC_CHF_MASK)

  {   /* CHF = 1, set by hardware when an event occurs on channel 6 */

         (void)FTM0->CONTROLS[6].CnSC;                                                                                                  /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */

         FTM0->CONTROLS[6].CnSC &= ~FTM_CnSC_CHF_MASK;                                                                   /* Bit7=0,clear the channel interrupt flag */

  }

  if((FTM0->CONTROLS[7].CnSC & FTM_CnSC_CHF_MASK)== FTM_CnSC_CHF_MASK)

  {   /* CHF = 1, set by hardware when an event occurs on channel 7 */

         (void)FTM0->CONTROLS[7].CnSC;                                                                                                  /* Read the CnSC register while CHF is set,then write a 0 to the CHF bit,the CHF will be cleared */

         FTM0->CONTROLS[7].CnSC &= ~FTM_CnSC_CHF_MASK;                                                                   /* Bit7=0,clear the channel interrupt flag */

  }

 

  /* Enable combine mode for channel pair CH2/CH3 and CH6/CH7 */

  FTM0->COMBINE = FTM_COMBINE_COMBINE1_MASK| FTM_COMBINE_COMBINE3_MASK|FTM_COMBINE_SYNCEN1_MASK|FTM_COMBINE_SYNCEN3_MASK;

  FTM0->CONTROLS[2].CnSC=FTM_CnSC_ELSB_MASK;                                                                            /* Select high-true pulses(set on channel 2 match, and clear on channel 3 match)*/

  FTM0->CONTROLS[3].CnSC=FTM_CnSC_ELSB_MASK;                                                                            /* Select high-true pulses(set on channel 2 match, and clear on channel 3 match)*/

  FTM0->CONTROLS[6].CnSC=FTM_CnSC_ELSB_MASK;                                                                            /* Select high-true pulses(set on channel 6 match, and clear on channel 7 match)*/ 

  FTM0->CONTROLS[7].CnSC=FTM_CnSC_ELSB_MASK;                                                                            /* Select high-true pulses(set on channel 6 match, and clear on channel 7 match)*/  

 

  FTM0->EXTTRIG = FTM_EXTTRIG_CH6TRIG(1);                                                                        /* Enables the generation of the trigger when the FTM counter is equal to C6V */

}

It stands to reason that in my settings, both MOD and CnV can be updated when the counter changes from MOD to CNTIN, but during actual testing, I found that only MOD will be updated;

yumi_2-1701685659916.png

 

Currently, MOD and CnV can only be updated by pausing FTM0_CLKS(as follows), but this will cause the PWM output to pause, as shown in the waveform below.

void FTM0_SetPeriodDutyAndPhsShft(uint16 Period, uint16 Duty1, uint16 Duty2, uint16 Phase)                 

{

  if((Duty1 < Period)&&(Duty1 + Phase <= Period))         /* phase range: 0~50 degree */

  {                                                                        

         FTM0_DisablePwmOutput();

         FTM0->MOD = FTM_MOD_MOD(Period-1);                                                                      

         FTM0->CONTROLS[2].CnV=FTM_CnV_VAL(0);/* Set as base */

         FTM0->CONTROLS[3].CnV=FTM_CnV_VAL(Duty1);                                                  

         FTM0->CONTROLS[6].CnV=FTM_CnV_VAL(Period/2-Phase);                                                                                               

         FTM0->CONTROLS[7].CnV=FTM_CnV_VAL(Period/2-Phase + Duty2);

         FTM0_EnablePwmOutput();

  }

  else

  {

      /* Should report error*/

  }

}

 

yumi_1-1701685633788.png

 

If I want to control the updates of the FTM's MOD and CnV registers smoothly without stopping the PWM output, is there any recommended method?

 

0 Kudos
1 Solution
521 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @yumi,

What is the content of MOD, INIT and CnV before and after the update?

Is a loading point selected?

danielmartynek_0-1701768762644.png

 

BR, Daniel

 

View solution in original post

0 Kudos
6 Replies
559 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hello @yumi,

You need to set FTMEN and SYNCMODE which I don't see in the code you posted.

The MOD and CnV synchronization is similar.

Have a look at RM, Section 47.5.13.4 MOD register synchronization.

There is the whole flowchart.

Can you follow the FTM Initialization Procedure (RM, Section 47.8) step by step?

 

Thank you,

 

Regards,

Daniel

0 Kudos
547 Views
yumi
Contributor II

So the problem is:

The update method you suggested me to use is the 3rd method in Table 47-10/11, which is CLKS[1:0] != 0:0 and FTMEN = 1, then MOD is updated by MOD register synchronization in 47.5.13.4, and C(n)V and C(n+1)V register synchronization in 47.5.13.6.

So why don't you suggest me to use the 2nd method in Table 47-10/11, which is CLKS[1:0] != 0:0 and FTMEN = 0? Actually I am not sure what TPM is.

yumi_0-1701737226732.png

yumi_1-1701737843661.png

 

 

0 Kudos
535 Views
danielmartynek
NXP TechSupport
NXP TechSupport

The FTMEN = 0 mode can be used as well.

But with FTMEN = 1, we can update the PWM using triggers.

Regarding TPM, have a look at AN5303 Features and Operation Modes of FlexTimer Module on S32K

https://www.nxp.com/docs/en/application-note/AN5303.pdf

danielmartynek_0-1701765557846.png

 

0 Kudos
544 Views
yumi
Contributor II

I changed my initiation software as follows, but the PWM update is still not very smooth.

Could you please give me some advice?

void FTM0_Init(void)
{
PCC->PCCn[PCC_FTM0_INDEX] &= ~PCC_PCCn_CGC_MASK; /* Disable clock for FTM0 during configuration */
PCC->PCCn[PCC_FTM0_INDEX] &= ~PCC_PCCn_PCS_MASK;
PCC->PCCn[PCC_FTM0_INDEX] |= PCC_PCCn_PCS(6); /* Source clock SPLLDIV1_CLK=80M, refer to Peripheral module clocking(Clocking Gating) */
PCC->PCCn[PCC_FTM0_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable clock for FTM0 register */

FTM0->POL = 0x00000000; /* Polarity for all channels is active high (default)*/
FTM0->CNTIN = FTM_CNTIN_INIT(0); /* Set CNTIN in initialization stage */
FTM0->OUTINIT = 0x00; /* Channel n output initialization value */
FTM0->MODE = FTM_MODE_WPDIS(1) /* WPDIS=1b,write protect to registers disabled (default) */
| FTM_MODE_INIT(1); /* When a 1 is written to INIT bit the channels output is initialized according to the state of their corresponding bit in the OUTINIT register */

FTM0->SC &= ~FTM_SC_CLKS_MASK; /* Disable the clock*/

/* Enable combine mode for channel pair CH2/CH3 and CH6/CH7 */
FTM0->COMBINE = FTM_COMBINE_COMBINE1_MASK| FTM_COMBINE_COMBINE3_MASK|FTM_COMBINE_SYNCEN1_MASK|FTM_COMBINE_SYNCEN3_MASK;
FTM0->CONTROLS[2].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 2 match, and clear on channel 3 match)*/
FTM0->CONTROLS[3].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 2 match, and clear on channel 3 match)*/
FTM0->CONTROLS[6].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 6 match, and clear on channel 7 match)*/
FTM0->CONTROLS[7].CnSC=FTM_CnSC_ELSB_MASK; /* Select high-true pulses(set on channel 6 match, and clear on channel 7 match)*/

FTM0->EXTTRIG = FTM_EXTTRIG_CH6TRIG(1); /* Enables the generation of the trigger when the FTM counter is equal to C6V */

/* Select synchronization for Output Mask */
/* SWSYNC=0(software trigger is not selected), TRIG2/1/0=0(Trigger 0/1/2 are disabled),*/
/* SYNCHOM=1(OUTMASK register is updated with the value of its buffer only by the PWM synchronization), */
/* REINIT=0(FTM counter continues to count normally) ,CNTMAX=0(The maximum loading point is disabled), */
/*CNTMIN=0(The minimum loading point is disabled) */
FTM0->SYNC = FTM_SYNC_SYNCHOM(1);

/* Write to SYNCONF */
FTM0->SYNCONF = FTM_SYNCONF_SWOM(1) /* The software trigger activates the OUTMASK register synchronization */
| FTM_SYNCONF_SWWRBUF(1) /* The software trigger activates MOD, HCR, CNTIN, and CV registers synchronization */
| FTM_SYNCONF_SWRSTCNT(1) /* The software trigger activates the FTM counter synchronization */
| FTM_SYNCONF_SYNCMODE(1); /* Enhanced PWM synchronization is selected */
FTM0->MODE = FTM_MODE_FTMEN(1);

FTM0->SC |= FTM_SC_CLKS(1) /* Clock Selection, FTM system clock*/
| FTM_SC_PWMEN2_MASK /* PWMEN2 = 1b, Enable channel 2 PWM output */
| FTM_SC_PWMEN3_MASK /* PWMEN3 = 1b, Enable channel 3 PWM output */
| FTM_SC_PWMEN6_MASK /* PWMEN6 = 1b, Enable channel 6 PWM output */
| FTM_SC_PWMEN7_MASK; /* PWMEN7 = 1b, Enable channel 7 PWM output */
}

void FTM0_SetPeriodDutyAndPhsShft(uint16 Period, uint16 Duty1, uint16 Duty2, uint16 Phase)
{
  if((Duty1 < Period)&&(Duty1 + Phase <= Period)) /* phase range: 0~50 degree */
  {
// FTM0_DisablePwmOutput();
FTM0->MOD = FTM_MOD_MOD(Period-1);
FTM0->CONTROLS[2].CnV=FTM_CnV_VAL(0);/* Set as base */
FTM0->CONTROLS[3].CnV=FTM_CnV_VAL(Duty1);
FTM0->CONTROLS[6].CnV=FTM_CnV_VAL(Period/2-Phase);
FTM0->CONTROLS[7].CnV=FTM_CnV_VAL(Period/2-Phase + Duty2);
FTM0->SYNC &= ~(FTM_SYNC_SWSYNC_MASK);
FTM0->SYNC |= FTM_SYNC_SWSYNC(1);
// FTM0_EnablePwmOutput();
  }
  else
  {
  /* Should report error*/
  }
}
 
yumi_0-1701751988167.png

 

0 Kudos
522 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @yumi,

What is the content of MOD, INIT and CnV before and after the update?

Is a loading point selected?

danielmartynek_0-1701768762644.png

 

BR, Daniel

 

0 Kudos
443 Views
yumi
Contributor II

I selected a loading point, then the problem was solved.