Kinetis KL04 TPM Anomoly

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

Kinetis KL04 TPM Anomoly

1,135 Views
GordyCarlson
NXP Employee
NXP Employee

I've been working with a customer on something that we haven't been able to explain yet.

 

Setting the KL04 TPM's COV register to a value of 798 results in a PWM duty cycle that is approx 50% of the expected.  Yet setting the COV value to 797 or 799 results in correct/expected operation.

 

We have looked at several possible theories.....like if we inadvertently changed the timer prescale,  but as far as we can tell the ONLY value we are changing is the COV value....

 

I've checked errata, community postings and other documentation, and can't find a parallel issue.

 

The customer has a workaround,  but we would still like to determine if we are overlooking or misunderstanding something,  or if there truly is an unusual errata within the KL04.

 

Email thread, register captures, and scope shots attached as an Outlook format.

 

thanks,

Gordy

Original Attachment has been moved to: KL04-PWM-weirdness.msg.zip

Labels (1)
0 Kudos
8 Replies

711 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Gordon,

Of course, if the TPM0_MOD=800,  the TPM_C0V=798, that the 50% duty cycle PWM appear on TPM_CH0 is not correct. I suggest you check the TPM0_C0V register in debugger when the 50% duty cycle PWM appears and check what is the value of the FTM0_C0V register.

BR

XiangJun Rong

0 Kudos

711 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Gordon,

I read the FTM0 register setting in debugger screenshot you gave, I found that the TPM0_CONF is 0x09010000, it means that the TPM1 overflow event will trigger FTM0_CNT start counting, obviously, it is not what you expected.

Pls set the TPM0_CONF=0x00 or just clear the CSOT bit by the code TPM0_CONF&=~(0x10000); have try.

BR

XiangJun Rong

0 Kudos

711 Views
jonwarriner
Contributor I

XiangJun Rong,

Thanks for the reply.  Gordy originally posted this on my behalf.  I've included a sketch of my expected PWM and timer waveforms to help you visualize what I'm trying to do. 

TPM0 is configured in up/down count mode with a MOD value of 800.  TPM0 is used to drive PWMs on CH0 and CH2 through C0V and C2V.  Each signal is active low.  CH0 is centered about TPM0 CNT=MOD event while CH2 is centered about TPM0 CNT=0 event.  The intent is to give the two PWMs a 180 degree phase shift.  In my sketch the two PWMs have the same duty cycle but that won't necessarily happen in my application.  One thing that is not shown in my sketch is the C1V is always set to the same value as C0V and C3V is always set to the same value as C2V.  At any given moment only one set of outputs is enabled, either CH0 and CH2 or CH1 and CH3.  One set is for forward and one is for reverse. 

So, all that TPM0 does is generate PWM waveforms.  I also needed to generate a sequence of ADC samples specifically timed to the PWM waveforms.  These samples need to be triggered in the center of the active-low on-time of each PWM.  TPM1 was configured to trigger the ADC samples.  It was set to up count mode with a MOD value 1 less than the TPM0 counter.  So, the TPM1 MOD register is set to 799.  The TPM1 over-flow events align with the TPM0 CNT=MOD and CNT=0 events.  The ADC samples are triggered by the TPM1 C0V event.  The C0V event is configured to occur when TPM1 CNT=MOD by setting TPM1 C0V equal to TPM1 MOD. 

The DMA is used to buffer all of the ADC samples in my sequence.  At the end of the sequence there is a DMA event that restarts the sequence.  All TPM timers run continuously throughout this entire process. 

Now that I've explained all of that...I am intentionally configuring TPM0 to start counting based on a trigger from TPM1.  This is to ensure that TPM0 and TPM1 start up synchronized.  When they are enabled TPM1 starts counting immediately while TPM0 sits at CNT=0 waiting for a trigger.  When TPM1 hits its first overflow event it triggers TPM0 to start counting.  Now the two timers are synchronized and should remain that way forever.  This is important to ensure that my ADC samples are synchronized to the PWM waveforms. The left hand side of my sketch illustrates the expected start-up behavior of the two timers. 

For the most part all of this seems to be working very well.  The only problem I've encountered is what Gordy mentioned in the original post.  I stumbled across a specific value written to any of the CxV registers associated with TPM0 that causes strange PWM behavior.  A value of 798 should cause either a very low duty cycle on C0V or a very high duty cycle on C2V.  Instead it creates about a 50% duty cycle.  However, a value of 797 or 799 produces expected behavior. 

It's easy to write code to avoid this specific value.  My concern is that there may be other values that produce similar behavior.  It was really dumb luck that I stumbled across this value.  I haven't tried every single possible CxV value.  I'm also wondering is this an errata or something caused by my specific configuration. 

Thanks for the help.

Jon

0 Kudos

711 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Jon,

Thank you for your feedback, I see your complicated utilization of TPM modules, the TPM0 is set up in center-alignment mode, you set different mode for CH0 and CH1 so that you can get complementary PWM signals from the CH0/CH1. The TPM1 is set up so that the ADC is triggered by TPM1, while the TPM0 is synchronized by TPM1 so that the ADC sampling instant is synchronized with PWM waveform. If you use a chip with FTM, it is easy to implement, one FTM can generate all the PWM signals and trigger ADC at the same time.

Regarding your question, as you said the 50% duty cycle is abnormal,unexpected, I can not explain either.  but I suspect the the TPM1 triggering signal leads to the problem, if you clear the CSOT bit in FTM0_CONF, does the issue appear or disappear?

I suggest you change idea, do not use TPM1 overflow as synchronizing signal to TPM0. There is another mechanism to synchronize both TPM0 and TPM1, which means that the TPM0/TPM1 counters have same value anytime, the Global time base can make the two TPM modules synchronize. In the mode, as the figure you drew, you should set the TPM0/TPM1 in center-alignment mode, and you require that ADC converts twice in one PWM cycle. As you can see that the TPM1_C0V can triggers ADC with the ADC0PRETRGSEL cleared in SIM_SOPT7 register, in the ISR of ADC, you can set ADC0PRETRGSEL bit and write the FTM1_C1V register so that the ADC can be triggered again.

Can you attach your code with only the TPM so that we can test on my board?

Hope it can help you.

BR

XiangJun Rong

0 Kudos

711 Views
jonwarriner
Contributor I

XiangJun,

Using the code that Gordy sent to you last night I tried clearing the CSOT bit in TPM0 CONF register.  The issues still exists when CxV is set to 798.

Thanks,

Jon

0 Kudos

711 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Jon,

Because there is not KL04 board, I use FRDM-KL05 board, the KL05 and Kl04 are pin to pin compatible. I run your code without modification for the TPM0/TPM1 setting, and test FTM0_CH0(PTB11) and FTM0_CH1(PTB10), The output of the two signal is okay, I paste the screenshot from oscilloscope. As you can see there is not 50% duty cycle signals.

For your issue, how many boards have you populated? can you change another board to have a test? when you set the C0V as 798, does the 50% duty cycle appear always, frequently or sometimes?

I have a interest, if the 50% duty cycle happens, if you set the TOIE bit in FTM0_SC, can you enter interrupt of FTM overflow? If you can enter, it means that the FTM0_CNT can reach up to FTM0_MOD, I suspect that the FTM_CNT is reset before reaching FTM0_MOD for known reason.

If you clear the CSOT bit, the issue still exists, maybe it is a hardware bug.

BR

XiangJun Rong

pastedImage_0.png

0 Kudos

711 Views
jonwarriner
Contributor I

XiangJun,

I have tried my code on 3 different boards.  If the CxV value is 798 the duty cycle is ALWAYS about 50%.  My code is already setting TPM0 TOIE.  in main.c the function PWM_Run_Ramp() is triggered by the TPM0 timer overflow event.  That routine runs consistently regardless of CxV setting.  There's even a GPIO that you can uncomment in that function that will toggle at the beginning and end of the function.  If you do that you can see that the ISR runs consistently.  Also, it is within this ISR that the variable raw_duty is written to the TPM0 CxV registers.  If that ISR stopped running you wouldn't be able to update the duty cycle. 

I tried the same test you did using a FRDM-KL05 board.  I'm not sure why you are not seeing the issue.  I still see it using this platform.  I suspect the problem is the value you are setting for raw_duty vs. which TPM0 channel you are looking at.  Look in the code in the PWM_Run_Ramp() routine.  As mentioned this is the ISR triggered by the TPM0 overflow event.  In the ISR there are two functions that are called PWM_Set_PWMACount() and PWM_Set_PWMBCount().  Each function takes raw_duty as input.  PWM_Set_PWMACount() sets C0V and C1V to MOD-raw_duty.  Since MOD = 800 you'll need to set raw_duty to 2 in order to get C0V and C1V to equal 798.  PWM_Set_PWMBCount() directly sets C2V and C3V to raw_duty.  This difference is what gives me the 180 degree phase shift that I need between the two sets of PWMs.  If you don't trust my code check the values of all of the CxV registers in the debugger window.  That's what I did to verify that I wasn't screwing something up. 

One other thing to watch out for.  Within the two sets of PWMs, C0V/C1V and C2V/C3V only one of the PWMs is active at a time.  The other is set high.  The default when you start the PWMs by setting button2Count and button2HighAlert is for C1V to be PWM while C0V is high and C3V to be PWM while C2V is high.  This is done by changing the GPIO mux setting.  Based on that I don't see how the waveforms in your oscilloscope screenshot are possible without modifying my code.  If you were looking at the outputs associated with C0V and C1V they should never have both been active PWMs at the same time. 

Thanks,

Jon

0 Kudos

711 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Jon,

Thank you for your patience.

I have discussed with application team, this is a bug of TPM. As a work around, we suggest you set the PS(prescaler) in TPMx_SC as 1 so that you can get divider 2, although I see that the PWM resolution will decrease by one bit with the solution.

I have tested the workaround, it is okay. Regarding the root cause, the AE team is investigating.

BR

XiangJun Rong

0 Kudos