S08SH8 TPM v3 strange behaviour

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

S08SH8 TPM v3 strange behaviour

2,698 Views
admin
Specialist II
HI,

I'm using the new S08SH8 for some projects and I discovered a strange behaviour of the new TPM used in this  controller.
I use a channel in software compare mode (it's like output compare but with no control on pin) and in the irq vector I change the compare value for the next event. The problem arise if I modify the status register (TPMxCnSC) after updating the channel value (TPMxCnV), in this case it seems that the new value is lost. If I touch the status register before updating the value, all is ok.
In datasheet is clearly noted that the new TPMv3 has a different coherency mechanism that update the values on the next change of TPM counter and that it can be forced writing to TPMxCnSC, but it seems wrong.

Anyone experienced this too?

Andrea
Labels (1)
0 Kudos
11 Replies

738 Views
cwt
Contributor II

I am using s/w compare mode (MS=01, ELS=00) on a S08QD4. Clock source is FFL.

Constant value for TPMxCnV.  No interupts enabled.

Code Warrior simulator shows that CHnF gets set when TPMxCNT = TPMxCnV as expected but cannot clear this flag immediately by reading TPMxCnSC and then writing zero to CHnF.

Is this a related problem?

Anyone got any suggestions?

Bill


0 Kudos

738 Views
cwt
Contributor II

Forget this, it works fine.  I found the problem elsewhere in the application.

Bill

0 Kudos

738 Views
MplsMan
Contributor II
I ran into the same problem.  The output compare values were only being updated intermittantly for me when the same code worked fine on a 9S08AW microcontroller.  It turns out that on the TPMv3 (as opposed to the TPMv2), you need to be careful that you do not immediately write to the TPMxCnSC register (eg., to clear the interrupt flag) after updating the value in TPMxCnVH:TPMxCnVL.  The channel value registers are not immediately loaded in the TPMV3 (in OC or PWM mode), but are rather held longer in a coherency buffer, until the next TPM clock tick.  So, I suspect that the culprit in your case may have been a subsequent access to the corresponding status and control register.  Although it was OK to update the channel value (TPMxCnVH:TPMxCnVL) and then clear the interrupt flag (within TPMxCnSC) on the TPMv2, that register update sequence may prevent the channel value from actually being updated on TPMv3.  Here is description from Freescale as provided within some of the 9S08AC manuals and application notes:
 
In output compare or PWM mode, writing to TPMxCnSC (after writing to the channel value registers, TPMxCnVH:TPMxCnVL, but before they are updated) cancels the write to TPMxCnVH:TPMxCnVL and leaves the register values unchanged.

This is particularly relevant for the AC60 because, depending upon the configuration of CLKS and the selected mode, there could be a considerable time before registers TPMxCnVH:TPMxCnVL are updated.  It is, therefore, important to ensure TPMxCnSC is not written during this time unless you want to cancel a previous write to the channel value registers.

As a result of these differences in the latching mechanism, you may have to initialise the timer registers in a different order than before to allow for this.

0 Kudos

738 Views
admin
Specialist II

If the description of this functionallity was in the MC9S08JM60 manuals it would of save me a lot of time.

0 Kudos

738 Views
CarlFST60L
Senior Contributor II

I am unable to see a way to solve this problem and make it portable across patforms. The only solution I can see is adding a fixed cycle delay, which is really bad coding.

 

Can someone offer a 'nice' way to do this?

 

          //Start output event in 0x0100 counts, this could be called at ANYTIME, so it has to happen before TMPxCnSC.
          TPM1C3V = TPM1CNT + 0x0100;             

          //Worlds worst fix; eat a few bus cycles, this must be greater than the slowest TMP tick rate (will change with bus frequency change and prescale change so I cannot see a way to make this code nice and portable across processors with different prescale rates and different bus rates as this code's speed will change with bus, and the TPM will change depending on its setings. Its also bad as it holds up the processor in interrupt eating up valuable processor cycles.

          for(i = 0;i != 5; ++i);

          //Set output on compare
          //Enable interrupt
          //Clear previously set interrupt flag
          TPM1C3SC = 0b01011000;

 

This is ugly, surely I have missed an obvious way to make this work 'nicely'

0 Kudos

738 Views
kef
Specialist I

Won't something like this work?:

 

char c;

 

    c = TPM1CNTL;

    while(c == TPM1CNTL){}

 

 

 

0 Kudos

738 Views
CarlFST60L
Senior Contributor II

I guess it will work, but, if you have a very slow TPM rate and it ticks over straight after the update, you could end up waiting in interrupt an entire PCM tick eating up valuable processing power...

 

Maybe its just me, but, this update seems, well, dumb. Maybe I am still a little frustrated after spending a day working out this was the cause to all our problems after updating from AC16 to AC32.

 

Any other idea's? Is there some logic to why 'they' would do this? it just seems a step in the wrong direction...

0 Kudos

738 Views
bigmac
Specialist III

Hello all,

 

The coherency mechanism for the V3 module differs whether the CLKSA:CLKSB bits within TPMxSC register are both zero, or not.  When both bits are zero (the TPM clock is disabled) there will be immediate update of the TPMxCnV value, similar to the earlier TPM versions.

 

To avoid the more lengthy coherency mechanism, my suggestion is to alter TPMxSC so as to zero the bits, prior to writing a new value to TPMxCnV.  Then restore TPMxSC to its previous value.

 

The suggestion in an earlier post, that any write to the TPMxSC register will reset the count value, I believe is incorrect.

 

Regards,

Mac

 

0 Kudos

738 Views
CarlFST60L
Senior Contributor II

Thanks Bigmac, its always good to here from you.

 

Neither solution is ideal for our application as the TPM shares its resources with decoders and encoders and this output compare is forever setting up various short / long pulses both in and out of interrupt.

 

The RM suggest writing to TPMxCnSC prior to updating TPMxCnV, which is no good as if the tick is in the wrong spot, it will set the interrupt flag immediately after, or while the TPMxCnV is being updated, so its certainly a dangerous suggestion for some applications (like ours).

 

I am still completely baffled by Freescales reasoning behind this update. Oh well, time to move on...

 

 

0 Kudos

738 Views
Denn
Contributor I
Hello Andrea,
 
Are you really sure you are updating ( TPMxCnSC) rather than Timer x Status and Control Register (TPMxSC).Any write into this Timer x Status and Control Register (TPMxSC) will initiate a reset in the free running counter Timer x Counter Registers (TPMxCNTH:TPMxCNTL) and it starts from 0000 to the initial counts where the first ISR is expected.

 

-Denn

0 Kudos

738 Views
Denn
Contributor I
Hello Andrea,


acno wrote:
HI,

 The problem arise if I modify the status register (TPMxCnSC) after updating the channel value (TPMxCnV), in this case it seems that the new value is lost. If I touch the status register before updating the value, all is ok.
 
In that case why update status register (TPMxCnSC) after updating the channel value (TPMxCnV). First have status register (TPMxCnSC) update ,then channel value reg.
 
Is there any requirement which dictates you to change control and staus register ( TPMxCnSC)at run time. If no then don't write to ( TPMxCnSC) unless it is required you to do it. Clearing the flag could be done by CHnF=0;
 
Regards,
Denn.
0 Kudos