FTM Channel (n) Value (FTMx_CnV) issue

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

FTM Channel (n) Value (FTMx_CnV) issue

1,860 Views
kef2
Senior Contributor IV

Hello,

It looks like writes to FTM channel timer compare value register (FTMx_CnV) are often ignored. I see it both reading compare register and observing pin output with o-scope.
I'm not sure if maskset 1N02G errata "e6165 FTM: FlexTimer external clock source cannot be faster than 20MHz" applies here. I'm using Fast OSC clock /2 clocking option (see Vybrid RM 9.10.3 FTM clocking). That's 12MHz. I further prescale it down by 1/128. What I see is that I need to loop writing FTMx_CnV about 40 times at 500MHz A5 core clock. Lowering FTM prescaler to 1/16 I need up to 6 write loop iterations.
If this is normal, then please point me to Vybrid RM where this is explained.

Thanks


Edward


P.S. Initialization and write-verify loop.


   // ungate Flextimer
   CCM->CCGR1 |= CCM_CCGR1_CG9(CCM_CCGR_BITS_ON_ALWAYS);

   // use "external" Fast OSC clock/2
   CCM->CSCMR2 = (CCM->CSCMR2 & CCM_CSCMR2_FTM1_EXT_CLK_SEL_MASK) | CCM_CSCMR2_FTM1_EXT_CLK_SEL(2);
   CCM->CSCDR1 |= CCM_CSCDR1_FTM1_CLK_EN_MASK;

   FTM1->SC =   (3<<3) // "ext" clock
             | 7;      // 1/128 divider

   FTM1->CONTROLS[TRIGCH].CnSC = 0x18; //output compare, set pin low on match
...

#define PulseWTicks 100
unsigned int newtv;
volatile int i;

   FTM1->CONTROLS[TRIGCH].CnSC &= ~FTM_CnSC_CHF_MASK; // clear flag

   newtv= FTM->CONTROLS[TRIGCH].CnV + PulseWTicks;
   newtv &= 0xFFFF;

   i = 0;
   do
   {
      FTM1->CONTROLS[TRIGCH].CnV = newtv;
      i++;
   }while(newtv != FTM->CONTROLS[TRIGCH].CnV);

13 Replies

974 Views
alejandrolozan1
NXP Employee
NXP Employee

Hi,

One thing that you have to keep in mind is that the FTM features different modes for writing coherency and it varies depending on the FTM mode and which register you intend to write.

For example in the RM:

pastedImage_0.png

Is the above code all your configuration?

Best Regards,

Alejandro

0 Kudos

974 Views
kef2
Senior Contributor IV

Hi

CnV register description includes this:

"In output modes, writing to a CnV register latches the value into a buffer. A CnV register

is updated with the value of its write buffer according to Registers updated from write

buffers."

I just want what is written here, I want single write to CnV to latch value in some internal FTM buffer. Value latched could be applied to timer compare register later, no problem. This is how things work in other FSL microcontroller timers. It is up to internal timer logic, where it takes value latched in buffer. Contrary to this, on Vybrid, most often a write to CnV is just ignored.

Table 39-305 IMO agrees with my expectations. Write to CnV should latch new value in some buffer, and then apply it in case of FTMEN=0 at the end of prescaler counting, fine. But I see it different. Single write to CnV never confirms (unless it happens on some clever time moment), also timer output pins toggle time doesn't confirm with new CnV value.

Regards

Edward

0 Kudos

974 Views
alejandrolozan1
NXP Employee
NXP Employee

I have tried the below code and it is working, it does not need to keep writing to the CNV register. I used IAR.

#include "common.h"

#include "sysinit.h"

#include "FTM_test.h"

#include "lpt.h"

#define PulseWTicks 100

  unsigned int newtv;

  volatile int i;

int main()

{

 

  printf("Hello World!\n");

 

  //led_blink_tower(); 

 

  // ungate Flextimer

   CCM->CCGR1 |= CCM_CCGR1_CG9(0x3);

   // use "external" Fast OSC clock/2

   CCM->CSCMR2 = (CCM->CSCMR2 & CCM_CSCMR2_FTM1_EXT_CLK_SEL_MASK) | CCM_CSCMR2_FTM1_EXT_CLK_SEL(2);

   CCM->CSCDR1 |= CCM_CSCDR1_FTM1_CLK_EN_MASK;

   FTM1->SC =   (3<<3) // "ext" clock

             | 7;      // 1/128 divider

   FTM1->CONTROLS[0].CnSC = 0x18; //output compare, set pin low on match

   FTM1->CONTROLS[0].CnSC &= ~FTM_CnSC_CHF_MASK; // clear flag

   newtv= FTM1->CONTROLS[0].CnV + PulseWTicks;

   newtv &= 0xFFFF;

   i = 0;

  // do

  // {

      FTM1->CONTROLS[0].CnV = newtv;

      i++;

   /*}*/while(newtv != FTM1->CONTROLS[0].CnV);

 

      FTM1->CONTROLS[0].CnV = newtv + 1;

      i++;

   /*}*/while(newtv + 1 != FTM1->CONTROLS[0].CnV);

  return 0;

}

/* Blink LEDs on TWR-VF600 */

void led_blink_tower()

{

  //Setup GPIO output on LED pins (PTB0-PTB3)

  IOMUXC->SINGLE.PTB0 = IOMUXC_PTB0_DSE(0x1)| IOMUXC_PTB0_OBE_MASK; //enable GPIO output for PTB0

  IOMUXC->SINGLE.PTB1 = IOMUXC_PTB1_DSE(0x1)| IOMUXC_PTB1_OBE_MASK; //enable GPIO output for PTB1

  IOMUXC->SINGLE.PTB2 = IOMUXC_PTB2_DSE(0x1)| IOMUXC_PTB2_OBE_MASK; //enable GPIO output for PTB2

  IOMUXC->SINGLE.PTB3 = IOMUXC_PTB3_DSE(0x1)| IOMUXC_PTB3_OBE_MASK; //enable GPIO output for PTB3

 

 

  //Flash on and off LED's

  while(1)

  {

    //Turn on LED's by driving 0 (active low)

    GPIO0->PDOR=~(PIN(22)|PIN(23)|PIN(24)|PIN(25)); //corresponds with PTB0-PTB3   

   

    //Delay

    time_delay_ms(1000);

   

    //Turn off LED's by driving 1

    GPIO0->PDOR=PIN(22)|PIN(23)|PIN(24)|PIN(25); //corresponds with PTB0-PTB3

   

    //Delay

    time_delay_ms(1000);

  }

}

974 Views
kef2
Senior Contributor IV

Hi Alejandro

Thank you for trying reproducing the issue. May I ask you what maskset is your Vybrid device? I tried executing code with your modifications on 1N02G, Vybrid Tower card.

1)

conditions: hit reset, reset default clocks, caches and MMU disabled, boot ROM code not executed

result: code hangs on first while loop.

2)

conditions: 500MHz core, 83MHz IPG, caches and MMU enabled

result: code doesn't hang

Then I tried executing my old variant of while loop. Interesting is that loop iterations count depends on value written to CnV. If new value differs by one, then one iteration may be enough. If value differs say by 0x1000, then it may need 41 loop iterations @500MHz to set.

So you didn't persuade me there's no problem. Something very odd and more dangerous than I thought. At low speed it doesn't help to keep writing-verifying CnV. This workaround doesn't work and hangs at low core speed!

Regards

Edward

0 Kudos

974 Views
alejandrolozan1
NXP Employee
NXP Employee

Hi

As I mentioned before I created a new project using as reference, the projects of the Vybrid code example found at:TWR-VF65GS10: Vybrid Controller Solutions Tower System Module

Can you give more details about your environment? Maybe you can share your projects.

Best Regards,

Alejandro

0 Kudos

974 Views
kef2
Senior Contributor IV

Hi

Yes, I just tried Gpio project from Vybrid Sample Code (VSC). Now I see why you didn't find problems. It works for me too at VSC-default 396MHz core clock. To see problem please reset target, point program counter at next after   printf("Hello World!\n");  code line and click continue. This way high frequency core clock initialization will be skipped and code will stuck at first while loop. 

Regards

Edward

0 Kudos

974 Views
alejandrolozan1
NXP Employee
NXP Employee

I just tried to skip the clock initialization and the FTM is still working.

Also, I tried with the project you sent but I found a compiling error, after fixing it I noticed that my DS-5 license expired, so I tried with the attached IAR example.

I contains the same code you sent and the FTMx_CnV register is being updated. The code does not hang.

974 Views
kef2
Senior Contributor IV

Code provided shouldn't hang. When it reaches for(;;) loop, i variable has to be =1. But it is much higher than 1. The same on 1N02G and 2N02G masksets.

(I didn't study your attachment. )
0 Kudos

974 Views
alejandrolozan1
NXP Employee
NXP Employee

I have been testing this and I just modified the Clock setups.

It does not change the PLL settings, it just enables the clock gates and it is working too.

To modify that,  I chose the below define in the tower.h

#define CLOCK_SETUP

2    /* Leave BootROM defaults - Uses 264MHz CA5 and 83.5MHz bus, 24MHz XOSC clock source */

And commented this in the system_Vybrid.c file

#elif (CLOCK_SETUP == 2)

  //Do nothing, just update the SystemClock variable

// SystemCoreClockUpdate();

The code is working. You have to enable the clock gate of the module.

Best Regards,

Alejandro

0 Kudos

974 Views
kef2
Senior Contributor IV


Hi

Leaving boot ROM defaults isn't interesting. This and some other clocks setup in vybrid_sc doesn't work if I command debugger to reset target and reload app and start from scratch.

See attached complete demo. Compile, reset target from debugger and run from start. I see i loop count =11 running at 266MHz and i =16 at 500MHz.

Edward

0 Kudos

974 Views
karina_valencia
NXP Apps Support
NXP Apps Support

alejandrolozano  do you have an update?

0 Kudos

974 Views
karina_valencia
NXP Apps Support
NXP Apps Support

alejandrolozano can you continue with the follow up?

0 Kudos

974 Views
alejandrolozan1
NXP Employee
NXP Employee

Sure, l will delve into it

Regards,

Alejandro