PWM stops toggling between modulus register changes

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

PWM stops toggling between modulus register changes

Jump to solution
1,347 Views
markthedark
Contributor III

We have a product that uses the MC13237.

 

We are using TPM1 and TPM2 to generate an FSK modulated stream of 1s and 0s. TPM1 is responsible for the bit timing (when the frequency needs to change) and TPM2 generates an edge-aligned PWM output that shifts between two frequencies – each representing a 0 or 1, we’ll call FREQ_LO and FREQ_HI, respectively.

 

The baseband (demodulated) data is essentially a UART format with 1 start bit, 8 data bits, 1 parity bit and 1 stop bit. When there is no data  to be sent, the idle state is 1 (aka FREQ_HI). I don't think this is important, but I thought I would share anyway.

 

The majority of the time, the system operates as expected, but randomly, the TPM2 stops modulating one of the frequencies.

 

For example, if the bit pattern 0-1-0-1 was to be modulated, the TPM2 output would output

DC -> FREQ_HI -> DC -> FREQ_HI, where DC is either GND or VCC. I suspect the DC level is an artifact of the last output state before the frequency (modulus) was changed.

 

I have scope captures of when the FREQ_LO is at a DC level. Note: I am unsure of whether the issue happens for the FREQ_HI bit time in other situations.

 

156098_156098.jpgIMG_20160331_144153.jpg

 

To fix the issue, we have tried to turn it off and back on by disabling all interrupts, refreshing all the TPM registers and re-enabling the system. This does not seem to fix the issue.

 

In some situation, the issue has been seen to correct itself, although we cannot correlate when or why. In other system, the issue continues for weeks and never corrects.

 

The only course of action that always fixes it is power on reset.

 

NXP’s site has no errata sheets, but I have been told although I understand the MC13237 SoC implements a GT60 core (https://community.nxp.com/thread/389054). Unfortunately I have not heard back yet regarding what mask should be referenced.

 

Does anyone have any suggestions of what might cause this issue?

 

Thanks in advance for any help.

Labels (1)
0 Kudos
1 Solution
996 Views
markthedark
Contributor III

Problem solved!

The source of the error was found with the timer responsible for generating the two FSK frequencies out the output pin, TPM2.

The TPM timing system uses three registers in the output compare toggling mode: Counter (TPM2CNT), Modulus (TPM2MOD), and Value (TPM2C0V). The modulus register determines toggle frequency by controlling when the counter register should reset to 0. When the Value register matches the Counter register, the configured action will take place. In our application, the output will toggle.

In our firmware, the Counter register was never initialized because the reset value is 0. In a function that turns off the FSK system, the Value register was inadvertently being modified after the Mode Select field (TPM2C0SC_MS0x) was being set to 0. Mode Select 0 sets the timer to input capture, which loads the current Counter register value into the Value register. If the value loaded happens to be higher than the modulus value, the output would never toggle the next time the FSK was re-enabled.

The clearing of the TPM2C0SC_MS0x field was removed and the Value register is explicitly set each time the modulus is changed. This solved the issue.

Thank you scottm‌ for your time and assistance.

View solution in original post

0 Kudos
6 Replies
997 Views
markthedark
Contributor III

Problem solved!

The source of the error was found with the timer responsible for generating the two FSK frequencies out the output pin, TPM2.

The TPM timing system uses three registers in the output compare toggling mode: Counter (TPM2CNT), Modulus (TPM2MOD), and Value (TPM2C0V). The modulus register determines toggle frequency by controlling when the counter register should reset to 0. When the Value register matches the Counter register, the configured action will take place. In our application, the output will toggle.

In our firmware, the Counter register was never initialized because the reset value is 0. In a function that turns off the FSK system, the Value register was inadvertently being modified after the Mode Select field (TPM2C0SC_MS0x) was being set to 0. Mode Select 0 sets the timer to input capture, which loads the current Counter register value into the Value register. If the value loaded happens to be higher than the modulus value, the output would never toggle the next time the FSK was re-enabled.

The clearing of the TPM2C0SC_MS0x field was removed and the Value register is explicitly set each time the modulus is changed. This solved the issue.

Thank you scottm‌ for your time and assistance.

0 Kudos
996 Views
scottm
Senior Contributor II

I'm not sure off the top of my head.  I've been doing so much work on Coldfire and Kinetis platforms since then that I can't remember the exact behavior of the HC(S)08 timers.  Seems like resetting the value register is a safe bet, though.

Scott

0 Kudos
996 Views
scottm
Senior Contributor II

That sounds like what happens when you change the modulo register to a value that the counter has already passed.  It won't hit the modulo value again until the counter overflows.  I'm looking at some HCS08 code I wrote years ago for AFSK and it waits and polls the timer flag (with interrupts disabled) to see when it's reset and then sets the new modulo value at the same point every time.

If your frequencies divide evenly into your bit rate and the code that sets the new modulo value is synced only to the bit rate timer and not the FSK frequency timer, I can see that problem persisting for long periods because you'd be setting the modulo register at the wrong moment every time, until maybe some random interrupt gets things sufficiently out of sync again.

Scott

0 Kudos
996 Views
markthedark
Contributor III

Hi Scott,

Thanks for you reply. My apologies for such a LATE reply. I was unaware that someone had replied until I came back to post another question. I'm not sure why I don't receive an email notification that someone replied. Strange.

The two frequencies that I shift between are 32258 and 33333 Hz and my "baud" rate is approximately 300 Hz, so I don't think it divides evenly. Still, the race condition that you're describing seems like a logical path to explore.

For performance reasons, changing the TPMxMOD for the FSK Frequency timer would not be option since it would be interrupting at ~33 kHz. If I continue with changing the TPMxMOD for the FSK timer from within the Bit Rate timer, can I simply reset the Counter (TPMxCNT) value *after* setting the new TPMxMOD? To be safe, do I need to also clear the TPMxSC_TOF and/or the TPMxC0SC_CH0F flags of the FSK Frequency timer, just in case it was set while servicing the Bit Rate timer?

Thanks again for sharing your time and experience.

Mark

0 Kudos
996 Views
scottm
Senior Contributor II

It's been a long time since I've looked at this.  I checked my code and I don't think it's doing quite what you want - it's using AFSK with one timer channel acting as a PWM D/A, and the rate is constant - it just varies the pulse width.  It polls for timer overflow in a tight loop before setting the output compare value.  I was thinking of the output compare and not the modulo register - it wouldn't make sense that it ran past the modulo value.  BUT, writing TMODH inhibits timer overflow interrupts until TMODL is written, so watch out for that.  I would make sure the modulo update code is a critical section (no chance to get interrupted by anything else) and explicitly set TMODH and then TMODL in sequence.  If your code got out of step for some reason it could be stuck always in that hold mode, waiting for TMODL.

Probably wouldn't hurt to reset the counter and clear the flags, just in case.

Scott

0 Kudos
996 Views
markthedark
Contributor III

Hi Scott,

I like your suggestion of wrapping the TMODH and TMODL in a critical section, although may not be my issue since, in my code, the modification of these registers occurs within an ISR and I'm pretty sure that interrupts are not unmasked during this period, although I will confirm. Thanks!

I was working on another project that uses Processor Expert API to configure a TimerInt (TPM) component. In the initialization, the Value register is loaded at the same time the Modulus register is (see the code below). Could setting both of these registers to the same value "sync" the timing, thus avoiding my issue? Unfortunately, this bug is not my priority so I don't have the time to test it at this moment.

...

TI2_SetCV(0x04AFU);                  /* Initialize appropriate value to the compare/modulo/reload register */

...

Where TI2_SetCV is defined as:

#define TI2_SetCV(_Val) (TPM2MOD = (TPM2C1V = (word)(_Val)) )

0 Kudos