MC9S08RG60 TPM use

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

MC9S08RG60 TPM use

694 Views
stevec
Contributor III

I have an application which needs to do the following:

1. Register an event input (negative edge)

2. Start a timer on this event but loaded with full house as time as yet unknown.

3. Input a serial data string which holds the 'real' timer duration.

4. Load this 'real' timer data into the already running timer.

5. On timeout of this timer, output a 1mS pulse.

6. I also need to set  a 5mS timer running on this input event so I can determine if the serial data occurs within 5mS of the event.

 

Timer clock of 1MHz. All elapsed times well within the 16 bit count.

 

I have parts 1 to 5 running using the TPM in straight forward up count mode and testing for flags. However this does not appear to be the most efficient and also has inherent time delays. Using the TPM in edge-aligned PWM mode on channel 0 looks the way to go but all attempts at utilising this mode have failed so far. Also part 6 I expect can be done using channel 1, but I need to optimise the first parts first.

 

I've looked on the website for application notes but not a lot other than the data sheet. Has anyone any pointers?

 

Regards,

Steve

Labels (1)
0 Kudos
7 Replies

378 Views
bigmac
Specialist III

Hello Steve,

.

I don't think that PWM mode is suited to your task.  Free-running operation of the TPM would seem more appropriate.

.

Since the device you are using is limited to a single TPM module, with two channels, and assuming that Ch 0 is used for detecting the input transition, Ch 1 would be used to output the timed pulse at the completion of the delay period.  Here, I assume the use of hardware output compare, to eliminate any latency issues.

.

The remaining issue is the data timing window.  Once an input capure event has occurred on Ch 0, the mode of this channel may be altered to software compare mode, to indicate whether the timing window has timed out.  At the conclusion of the output pulse, Ch 0 would revert to input capture mode, ready for the next event.

.

The following untested code snippet is given as an example of this concept.  Firstly the TPM initialisation code.
.

// TPM initialisation:TPM1MOD = 0;       // Free-running modeTPM1SC = 0x08;     // Bus clock source, prescale 1TPM1C0SC = 0x48;   // Ch 0: Input capture :smileyminus:, interrupt enabledTPM1C0SC_CH0F = 0; // Clear Ch0 flagTPM1C1SC = 0x18;   // Ch 1: Clear output on compare, no interrupt

 

Next is the function for setting the variable delay, following the SCI communications.

.

// Global variables:word tstart;void set_delay( word value){  DisableInterrupts;  if (TPM1C0SC == 0x10) {     // Compare mode & flag is clear    TPM1C1SC = 0x5C;          // Set o/p on next compare, int. enabled    TPM1C1V = tstart + value; // Set delay period  }  else {                      // Outside data timing window    TPM1C0SC = 0x48;          // Revert to input capture mode    TPM1C0SC_CH0F = 0;        // Clear flag  }  TPM1C1SC_CH1F = 0;          // Clear flag  EnableInterrupts;}

 .

Finally, the code for the two TPM channel ISRs.

.

/*******************************************************************/// TPM1 Ch 0 Interrupt handler:__interrupt ISR_TPM1C0( void){  tstart = TPM1C0V;       // Timing start value  TPM1C0SC = 0x10;        // Software compare mode, no interrupt  TPM1C0V += 5000;        // Set data timing window  TPM1C0SC_CH0F = 0;      // Clear flag}/*******************************************************************/// TPM1 Ch 1 Interrupt handler:__interrupt ISR_TPM1C1( void){  if (TPM1C1SC == 0x5C) { // Output pulse currently high    TPM1C1SC = 0x58;      // Clear o/p on next compare, int. enabled    TPM1C0V += 1000;      // Set output pulse duration  }  else {                  // Output pulse finished    TPM1C0SC = 0x48;      // Revert to Ch0 input capture mode    TPM1C0SC_CH0F = 0;    // Clear Ch0 flag    TPM1C1SC = 0x18;      // Clear output on compare, no interrupt  }  TPM1C1SC_CH1F = 0;      // Clear flag}

 .

Regards,
Mac

0 Kudos

378 Views
stevec
Contributor III

Hi Mac,

Many thanks for the prompt reply. I haven't studied it in detail but thought I'd get a thanks off before I take a weeks vacation. I am actually using a keyboard edge detect flag as the detection mechanism for the initial pulse. I hadn't considered the input capture mode of the TPM.

 

I'll let you know how it goes when I get back.

 

Steve

0 Kudos

378 Views
bigmac
Specialist III

Hello Steve,

 

Using a KBI input means that you must get your timing reference by reading TPM1CNT register within the ISR code.  This is therefore subject to the latency associated with the interrupt processing, and may also be affected by the ISR processing of other unrelated interrupts.  The use of input capture mode latches the TPM1CNT value on the occurrence of the input event, and therefore suffers no latency (apart from a small synchronisation delay).

 

I would tend to use the latter method, which will give a more accurate result.  However, the exception would be if a limited accuracy is sufficient for your application and you need to utilise the second TPM channel for another purpose.

 

Regards,

Mac

 

0 Kudos

378 Views
stevec
Contributor III

Hi Mac,

 

I've had a chance to try out your code and I have a result of sorts. It generally does as you said apart from the following.

1. The input line (a negative going pulse on TPMCH0) only goes back up to around 600mV at the end of the input pulse and remains there until the output pulse goes high. Seems like it is being held low by the processor. Maybe I am not initialising the ports correctly to start with.

2. The output pulse is 65.5mS long ( a full house) and not 5mS.

 

I need to monitor the 5mS timer whilst waiting for the serial data. Presumably I do this by looking at the TPM1C1SC_CH1F flag. I use the 5mS window to wait for the serial data. If no data within 5mS of the input pulse it is assumed something is wrong and I report this back to the sending device before waiting for the next i/p pulse.

 

I'll plug away at it , but thanks very much for the initial starting point.

 

Steve

0 Kudos

378 Views
bigmac
Specialist III

Hello Steve,

 

1.  Immediately following the input capture event, TPM channel 0 reverts to software only compare mode, to be used for the data window timing.  This means that the TPM module no longer has control of the channel pin, an it will revert to GPIO.  Thus, this pin should be initalised as an input, maybe with pullup enabled.  I suspect the pin may be currently initialised as a low output state.  At the conclusion of the output pulse at channel 1, channel 0 will revert to input capture operation, so the TPM module will again take control of the pin.

 

2.  The channel 1 interrupt handler controls the output pulse width, and I think I can see a potential problem.  When a compare interrupt occurs it needs to be tested whether it is the first or the second interrupt in the sequence.  If the first compare interrupt, the output pulse timing is set, otherwise further interrupts are disabled, and the channel initialisation state is resumed (all further compares will give a low pulse output state).  The test is as follows -

if (TPM1C1SC == 0x5C) { // Output pulse currently high

 

Of course, I did not allow for the channel flag being set at this point within the ISR, so the test value should actually be 0xDC for the correct branch to be taken on the first interrupt.

 

The function set_delay() attempts to provide the data window monitoring.  This would be called as a result of the SCI processing to obtain the variable delay data.

 

// Global variables:word tstart;void set_delay( word value){  DisableInterrupts;  if (TPM1C0SC == 0x10) {     // Compare mode & flag is clear    TPM1C1SC = 0x5C;          // Set o/p on next compare, int. enabled    TPM1C1V = tstart + value; // Set delay period  }  else {                      // Outside data timing window    TPM1C0SC = 0x48;          // Revert to input capture mode    TPM1C0SC_CH0F = 0;        // Clear flag  }  TPM1C1SC_CH1F = 0;          // Clear flag  EnableInterrupts;}

The test for software output compare mode is current, and the channel flag is clear (window timeout has not yet occurred) results in the variable delay being set.  Otherwise, we revert to input capture mode ready for the next input pulse.  It is at this point you may require to add some code to report the window timing error.

 

A possible circumstance that may still be a problem would be if the serial data never arrived, and set_delay() was never called.  So perhaps an alternaltive way of handling the data timing window would be to enable interrupts for the software compare operation, and modify the channel 0 ISR code.  If an output compare interrupt should occur, then revert to input capture mode, and set a global flag variable.  The set_delay() function could then test for the global flag currently set (since the TPM channel flag would have been cleared within the ISR).

 

Regards,

Mac

 

0 Kudos

378 Views
stevec
Contributor III

Hi Mac

 

Thanks again for the help. I must admit to still trying to understand the timer operation. More studyimng required I think. I have not used this aspect of the chip before.

 

I am tempted to zero the counter within the edge detect interrupt. I have to carry out timing checks to make sure that the value input in the serial data is not less than the current time (which would imply that the output pulse should already have started). This is a quality check which has to be fed back to the sending computer. Starting the counter at zero means I don't have to worry about wrap around of the counter. But it means that I will have an artificial offset caused by the interrupt latency. Do you know how many clock cycles are taken up in the interrupt handling. I can start the counter at this number of uS. I only need the o/p pulse start to be accurate to 10uS so with an 8MHz bus clock I reckon I can afford to be a few clock cycles out!

 

If my quality check fails I need to immediately start the o/p pulse. Can I force the line active but still get the counter channel timing working to clear the line after 1mS? (Or I could set a value in which is just ahead of 'now' time).

 

Regards,

 

Steve

0 Kudos

378 Views
bigmac
Specialist III

Hello Steve,

 

Resist the temtation to zero the TPM counter - it is quite unnecessary in this instance, and in most other instances.  The elapsed time calculation is very simple.  Subtract the input capture value from the current TPMCNT value.  Provided the time difference does not exceed the TPM overflow period (that you originally stated would always be the case) the correct unsigned result will be obtained.  This is true even if an overflow has occurred, and the second value is less than the first value.

 

My assumption was that, since you provided a 5 millisecond data window, the variable delay requirement would always exceed the window period.  If this is not the case, what is the minimum variable delay, and why the data window?

 

To generate an "immediate" pulse within the set_delay() function, you would set a channel value that is just ahead of the "now" time, with high output on compare.  Then poll until the flag becomes set, and then increase the value by 1 millisecond, with low output on compare, in a similar manner as the channel 1 ISR code.  At this point, the channel 1 interrupt would be disabled.  Make sure that interrupts are globally disabled during this process, to prevent any problems with intervening interrupts from any source.

 

To determine the number of cycles requred for execution of ISR code, or any other code block, make use of full chip simulation available within CW, which provides a cycle counter.  If you set a breakpoint to the beginning of ISR code, be aware that by the time the breakpoint is reached, a number of cycles will already have elapsed from the interrupt trigger. This amounts to 11 cycles, plus the cycles to complete the current instruction executing prior to the interrupt occurring, and assumes that no other interrupt is currently being processed.  Otherwise this will be completed first, and the timer interrupt will remain pending.

 

Regards,

Mac

 

0 Kudos