Hi to all,
I'm trying to generate PWM signal starting from fsl_ftm component.
developing with KDS 2.0.0 and KSDK 1.1.0 on K20 device (i'm using K60 for PEx because KSDK for k20 is not ready yet)
I want to generate a PWM with frequency 10 Hz and 50 duty cycle
setting of PEx flex timer are:
device FTM0
counter FTM0_CNT
basic config: overflow= 0, write protection disable, BDM = zero mode, SW trigger enabled and disabled all HW trigger
pwm chan config: Freq= 10 Duty=50, Edge mode= high true. mode= edge alligned pwm
quadrature disabled
pin, all disabled (fault all disabled; external clock pin disabled, HW sync disabled)
init: timer overflow interrupt and fault interrupt disabled
PWM channel: #2 ---> Pin PTA5
If I use Freq > 400 Hz all work right... but if I set 100 Hz (more then my 10Hz wanted) i see a PWM of about 550 Hz....
Why this problem occours?
thanks,
Massimiliano
已解决! 转到解答。
Hello Massimiliano,
The fsl_ftm SDK peripheral driver (version 1.1.0) contains limitations that blocks usage of this SDK driver as you have described (one PWM channel can be initialized only; the counter prescaler cannot be selected/updated according to required PWM frequency). Your issue is caused by overflow, i.e. if you select high bus clock and low FTM counter prescaler, the modulo register cannot be set to the requested frequency of the PWM signal (the computed value is higher than 0xFFFF).
You can use Init_FTM component for initialization of the FTM device and fsl_sdk_hal component (runtime functions), e.g. you can use FTM_HAL_SetChnCountVal for PWM runtime duty settings (the duty can be computed as the ratio: Channel Counter Value Register / Modulo Counter Register. The FTM_HAL_SetMod function, that set the FTM counter modulo register, can be used for period settings (Note: when you set the module register the duty of all PWM channels is also changed and these values must be updated to set the original duty).
The PWM period is defined by selection of the clock source, prescaler selection and Modulo Counter Register value, see the Period property of the Init_FTM component.
See example of Init_FTM configuration below. You can see that when you select Clock source and Prescaler value the counter frequency is computed (see the Counter frequency property). When you set the Modulo counter value the period is computed and displayed in the Period property. You should select the maximal value of the Prescaler to allow maximal value of the modulo register and the maximal precision of the duty selection.
The ADC can be synchronized with FTM device by using PDB (Programmable Delay Block), see the chip configuration in the reference manual of the used derivative.
Best Regards,
Marek Neuzil
Hello Massimiliano,
The fsl_ftm SDK peripheral driver (version 1.1.0) contains limitations that blocks usage of this SDK driver as you have described (one PWM channel can be initialized only; the counter prescaler cannot be selected/updated according to required PWM frequency). Your issue is caused by overflow, i.e. if you select high bus clock and low FTM counter prescaler, the modulo register cannot be set to the requested frequency of the PWM signal (the computed value is higher than 0xFFFF).
You can use Init_FTM component for initialization of the FTM device and fsl_sdk_hal component (runtime functions), e.g. you can use FTM_HAL_SetChnCountVal for PWM runtime duty settings (the duty can be computed as the ratio: Channel Counter Value Register / Modulo Counter Register. The FTM_HAL_SetMod function, that set the FTM counter modulo register, can be used for period settings (Note: when you set the module register the duty of all PWM channels is also changed and these values must be updated to set the original duty).
The PWM period is defined by selection of the clock source, prescaler selection and Modulo Counter Register value, see the Period property of the Init_FTM component.
See example of Init_FTM configuration below. You can see that when you select Clock source and Prescaler value the counter frequency is computed (see the Counter frequency property). When you set the Modulo counter value the period is computed and displayed in the Period property. You should select the maximal value of the Prescaler to allow maximal value of the modulo register and the maximal precision of the duty selection.
The ADC can be synchronized with FTM device by using PDB (Programmable Delay Block), see the chip configuration in the reference manual of the used derivative.
Best Regards,
Marek Neuzil
Hi Marek, do you know what prevents the fsl_ftm PEx component from working with more than one PWM channel? I just happened to come across your post today after having trouble getting FTM3_CH6 and FTM3_CH7 working with different configs. I could get one or the other working, but not both simultaneously. Is there an ETA on when this functionality can be expected to work? Isn't this a KSDK issue and not a PEx issue, since the latter could technically be fixed by modifying the generated code?
Hi Dave,
It is the problem of fsl_ftm SDK peripheral driver. The FTM_DRV_PwmStart function of this component reinitialized always the whole FTM counter a the counter channel (and there is also problem of modulo register settings and prescaler). We know about this issue and the development team working on the resolution. The new version of the fsl_ftm component will be provided in Kinetis SDK 1.2.0 release.
You can modify the static source code file of the fsl_ftm driver (fsl_ftm_driver.c).
Best Regards,
Marek Neuzil
Thanks for the clarification, Marek. I've been reading through FTM_DRV_PwmStart, looking for the problems that you have indicated with the counter, mod, and prescaler settings. I haven't been able to find anything, yet.
From your description of the problem, it sounds like the last call to FTM_DRV_PwmStart would determine which channel works, if the counter channel is always getting reinitialized. But what I see from my code is that the first call to FTM_DRV_PwmStart is the one that works. For example, I have flexTimer1_ChnConfig0 using PTC10 and flexTimer1_ChnConfig1 using PTC11. When I call FTM_DRV_PwmStart, passing flexTimer1_ChnConfig0 first, the PWM on PTC10 works and PTC11 doesn't. If I pass flexTimer1_ChnConfig1 first, then PTC11 work and PTC10 doesn't.
One thing that I find very strange is that when I single step through all of the code in FTM_DRV_PwmStart, both PWM channels "work". I say "work" because while PWM is clearly active on both channels, the settings are all messed up, and the results are inconsistent. The channels seems to run with a mixture of parameters. For example, let's say my PEx settings include:
PTC10: 1MHz, 50% duty cycle
PTC11: 2MHz, 25% duty cycle
Sometimes after single-stepping, PTC11 might be running at 2MHz with a 25% duty cycle (correct), but PTC10 would run at 1MHz and 100% duty cycle. Other times, PTC11 would run at 1MHz with a 12.5% duty cycle while PTC10 runs at 1MHz and 50% duty cycle (correct).
Hi Dave,
The problem, that you have described, is cause by the reinitialization of the FTM counter and modulo register without regard to previous PWM channel initialization. When you have two PWM configuration with different frequency (e.g. PTC10: 1MHz, 50% duty cycle and PTC11: 2MHz, 25% duty cycle), you setup 50% duty for the 1MHz frequency of the FTM counter (frequency is defined by the FTM modulo register and the duty by the channel register) and then initialize the second PWM channel to 2MHz frequency the FTM modulo register is set again (it will contains the half value with compare to 1MHz initialization) the first PWM channel will have 100% duty as the result (side effect) of the second channel initialization.
Please note, that FTM device itself does not support different PWM frequencies on FTM channels (there is one counter and modulo register the define the frequency and it is shared by all channels; FTM channels just contains match registers that define the duty of the signal). When you need this functionality you must emulate it by the driver.
Best Regards,
Marek Neuzil
Marek, one last comment -- I changed my PWM configs to use the same frequency and different duty cycles to rule out misconfiguration.
If I run the code, as before only the first configured PWM channel runs. However, the way I understand your problem description, it sounds like the PWM information is overwritten, so wouldn't you expect the *second* PWM channel to be the one that's working?
I also cannot explain why *both* PWM channels work if I step into every line of FTM_DRV_PwmStart. Stepping over the functions called from FTM_DRV_PwmStart doesn't work, I *must* step into each called function for the 2nd channel to start working. Normally, I'd say there's some kind of a race condition, but at this time nothing else could possibly be happening (except for an ISR) because the RTOS hasn't started running yet. Do you have any idea what this could be?
Hello Dave,
The KSDK development team has provided a hot fix for the fsl_ftm and fsl_tpm drivers. They have fix a bug of the timer modulo register overflow and they have implemented a new function for the duty update. See the attached hot fix. Please note, that this hot fix provides update of SDK source code only. The fsl_ftm and fsl_tpm Processor Expert components will not be affected (they will not contain the new function PwmUpdate in the list of methods).
Best Regards,
Marek Neuzil
Hello Dave,
I have analyzed the fsl_ftm a possible cause of your issue. It seems that you have enabled a trigger (e.g. Software trigger - see Settings/Basic configurations/Triggers group of properties).
When the FTM_DRV_Init is executed the counter is not started. You can write into all channel registers (CnV registers). When you start the first PWM channel by the PwmStart method (the FTM counter is also started) and the writing to the FTM registers is triggered. So you must execute the trigger to start the second PWM (after call of the PwmStart method for the second channel).
For example, when you enable Software trigger, you must call FTM_HAL_SetSoftwareTriggerCmd(FTM0_BASE, true). See for example the initialization sequence of two PWM channels
FTM_DRV_Init(FSL_FLEXTIMER1,&flexTimer1_InitConfig0);
FTM_DRV_CounterStart(FSL_FLEXTIMER1,kCounting_FTM_UP, 0, 0xFFFF, false); // starting of the FTM counter
FTM_DRV_PwmStart(FSL_FLEXTIMER1,&flexTimer1_ChnConfig0,0U); //register values are stored into FTM buffers and PWM channel is not running after execution (channel registers are not updated)
FTM_DRV_PwmStart(FSL_FLEXTIMER1,&flexTimer1_ChnConfig1,1U); //register values are stored into buffers and PWM channel is not running after execution (channel registers are not updated)
FTM_HAL_SetSoftwareTriggerCmd(FTM0_BASE, true); // when executed both PWM channels start running
For details, see chapter PWM synchronization of FTM device description in a reference manual (e.g. K64P144M120SF5RM)
Best Regards,
Marek Neuzil