0

I'm having trouble with timer output compare interrupts on the HCS12. The problem seems to be that I'm writing calculated values to the output compare registers rather than immediates, ie...

OCval = x + y ; ldd OC1, OCval ; // what I need to do

ldd OC1, #3000 ; // what works

With the calculated values, the timer interrupt is erratic, which is unacceptable in my application. The problem has been firmly pinned down to the documented requirement to access the timer and OC registers in a single cycle, anything other than an immediate write violates this. I also note that all the sample code on the web uses immediate ops.

Just wondering if there is a software workaround. I need to allow the counter to free run (ie. no reset) because there are other output compares with immediate writes that have to remain in action. Only two of my interrupts need to be calculated.

A software fix would be nice because the only other options I can see involve additional hardware to handle the dynamic timing, messy. TIA

Lundin
  • 195,001
  • 40
  • 254
  • 396
BruceV
  • 117
  • 2
  • 10
  • This is hard to answer without any code provided. I take it that the code is written in C? If so you should view the disassembly to see what code that was actually generated. Which compiler are you using? Generally, when you encounter undesired operations in C, you should write the C code in several steps such as `volatile uint16_t result = x + y; OCval = result;`. – Lundin Aug 07 '17 at 07:32
  • Specifically for the HCS12, C code often result in the wrong assembler when clearing the timer flags. You _must_ disassemble the code for clearing of timer flags no matter compiler, to see that it works as intended. A common bug is when you have something like `FLAGREG |= MASK;` which results in "read FLAGREG, store result in accumulator, add mask, write result back". And then as flags are cleared by writing a 1 to them, you also destroy all other flags in the same register. To get the right assembler code (BSET), `FLAGREG = MASK;` usually gives the correct instructions. Depending on compiler. – Lundin Aug 07 '17 at 07:34
  • Thanks for responding. You're correct regarding the flag clearing, in this case the ASM listing showed that that is not a problem. Testing has since proved clearly that the problem is writing the value to the compare reg across more than one cycle. Moving that function to the modular downcounter has stabilised the app. – BruceV Aug 14 '17 at 07:55

1 Answers1

0

This is a bit tentative, but early tests are encouraging. I've moved the offending interrupts from the main timer to the modulo downcounter, which also provides clocked interrupts. The documentation states that setting the count register is subject to the same single-cycle write rules, however my extensive testing with the main timer indicates that problems are very unlikely to occur until the counter has run for a while with the new setting. The advantage of the new approach is that a value needs to be written only once, on initially setting the time value, unlike the main timer where a rewrite needed to be performed many times a second.

In case it helps, I'm stopping the counter before doing the write, then restarting it.

BruceV
  • 117
  • 2
  • 10