Hello everybody... I've got this strange problem. I'm working with CW4.6 and MC9S12A256.
I'm using two timer channels (CH0 and CH7). CH0 for output compare; and CH7 for Input Capture that only interrupts when a falling edge occurs.
The Output Compare is ALWAYS running and interupting every 1mseg, When that occurs, I toggle a pin (an output).
With an oscilloscope I view the Input Capture pin and the pin that I toggle each time an output compare ocurrs.
Normally, I see this on the oscilloscope.
CH0 Output Compare
--+ +--+ +--+ +--+ +--+ +--+ +--+
| | | | | | | | | | | |
| | | | | | | | | | | |
+--+ +--+ +--+ +--+ +--+ +--+
CH7 Input Capture
--+ +--+ +-+ +-+ +--+ +--+
| | | | | | | | | | |
| | | | | | | | | | |
+----+ +-+ +--+ +-----+ +--+ +--+
The input capture channel is not important... The important thing is that the Output Compare has always the same high and low time, equal to 1mseg.
The problem is that sometimes, the following happens. (only when working with input capture, if I disable it the problem doesn't show)
CH0 Output Compare
--+ +--+ +-----------------+ +--+
| | | | | | |
| | | | | | |
+--+ +--+ +--+ +--+
CH7 Input Capture
--+ +--+ +-+ +-+ +--+ +--+
| | | | | | | | | | |
| | | | | | | | | | |
+----+ +-+ +--+ +-----+ +--+ +--+
It's difficult to me to explain what I think is happening with words, so I'll put it graphically
+---------------------------------------> (1)
| +------------------------------------> (2)
| | +------------------------> (3)
| | | +---------------------> (4)
| | | |
--+ +--+ +--|-----------|--+ +--+
| | | | | | |
| | | | | | |
+--+ +--+ +--+ +--+
(1) Let's assume that here the TCNT = 0x0000
(2) Here the IRQ should happend but it didn't
(3) Here ocurrs an OVF (TCNT from 0xFFFF to 0)
(4) Here the TCNT reaches the ch0_REG value
Why's that happening??
The code in the Output Compare only does this:
TC0 += 12000; // IRQ every 1msegtoggled_pin = ~toggled_pin; // Toggle pinTFLG1_C0F = 1;// Clear flag
And in the Input Capture, I only clear the IRQ flag
Thank you in advance!!!
I've manage to solve the problem... But maybe someone can explain me a bit more.
I was using BSET to clear interrupt flags. I've read that this instructions it's a read and write instruction, and clearing should be done with a write-only instruction. And that was causing the "missed" interrupt, if the two IRQ ocurrs simultaneously, then when clearing one, I was clearing both.
Arghhhh. It was explained zilion of times what you can and what you can't do with flags registers, which contain more than one flag clearable writing one to flag. Using BSET , TFLG1_C0F = 1 and TFLG1 |= TFLG1_C0F_MASK will clear ALL TFLG1 flags, since bits you "are not using in expression" are PRESERVED = OVERWRITTEN with their old value. What happens when unused bit is ONE? Right, ONE is written back to flag, which is set, and you clear them ALL. You can use read modify write without problems:
BCLR TFLG1,#~TFLG1_C0F_MASK;
TFLG1 &= TFLG1_C0F_MASK; // Notice no '~' on the right side
and of course write only
TFLG1 = TFLG1_C0F_MASK;
You can't use TFLG1_C0F = 0 or TFLG1_C0F = 1. Both are bad
Thanks kef!
I know it was explained a lot, but it always confused me. The reason of my confusion is that no one ever explain it to me like you did. They always talk about read-write instructions, and write-only... What I didn't know is why a BSET was a read-write. Now I know!
Thanks again!
Best regards!