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);
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:
Is the above code all your configuration?
Best Regards,
Alejandro
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
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);
}
}
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
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
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
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.
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. )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
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
alejandrolozano do you have an update?
alejandrolozano can you continue with the follow up?
Sure, l will delve into it
Regards,
Alejandro