Jp3141
Well-known member
I have 2 external pin interrupts to my Teensy 3.2 (48 MHz)-- one at ~60 Hz, the other at 1 Hz (see project at https://github.com/jp3141/60Hz)
Here's (what I think are) the relevant parts of the code. The main loop prints the value of 'phase' every approx. 5 s. Phase should be between 0 and 360. This works well, except occasionally (3 times in 6 days), phase becomes 4294 (and no other values > 360 occur). Phase is declared as volatile.
So: given that the 1 Hz 60 Hz interrupts have their own ISR routines -- and the 60 Hz can interrupt the 1 Hz routine -- and PhaseMicros should get reset to 0 every 1/60 s (i.e. every 16666 us), how do I get these rare 4294 values ?
At PhaseMicros of 16666 us, Phase should calculate to 16666*360*60/1000000 = 360; it can't (shouldn't) get larger than this. Even if I missed one 60 Hz interrupt (not really possible) it would be 720 max.
I do notice that these corruptions tend to occur at instants where it is probable that the 60 Hz ISR has interrupted the 1 Hz one, but I can't see any reason for that to be a problem.
Given that this is a 32 bit MCU, I expect that all updates of the variables are atomic. However I don't know where the code for micros() is -- are its updates atomic ?
Any ideas ? This is awkward to debug as the errors are quite rare (< 1 per 2 days). I could improve debugging by using a function generator to send in (say) 60 kHz and 1 kHz interrupts, but that's awkward right now.
Here's (what I think are) the relevant parts of the code. The main loop prints the value of 'phase' every approx. 5 s. Phase should be between 0 and 360. This works well, except occasionally (3 times in 6 days), phase becomes 4294 (and no other values > 360 occur). Phase is declared as volatile.
So: given that the 1 Hz 60 Hz interrupts have their own ISR routines -- and the 60 Hz can interrupt the 1 Hz routine -- and PhaseMicros should get reset to 0 every 1/60 s (i.e. every 16666 us), how do I get these rare 4294 values ?
At PhaseMicros of 16666 us, Phase should calculate to 16666*360*60/1000000 = 360; it can't (shouldn't) get larger than this. Even if I missed one 60 Hz interrupt (not really possible) it would be 720 max.
I do notice that these corruptions tend to occur at instants where it is probable that the 60 Hz ISR has interrupted the 1 Hz one, but I can't see any reason for that to be a problem.
Given that this is a 32 bit MCU, I expect that all updates of the variables are atomic. However I don't know where the code for micros() is -- are its updates atomic ?
Any ideas ? This is awkward to debug as the errors are quite rare (< 1 per 2 days). I could improve debugging by using a function generator to send in (say) 60 kHz and 1 kHz interrupts, but that's awkward right now.
Code:
elapsedMicros PhaseMicros;
volatile uint32_t Phase;
void setup() {
...
}
void loop() {
[COLOR="#FF0000"][B]... // every 5 s read 'Phase' and print it.
[/COLOR][/B]
}
FASTRUN void ftm0_isr(void) { // 60 Hz
... // other stuff
PhaseMicros = 0;
... // other stuff
}
FASTRUN void ftm1_isr(void) { // 1 Hz;
... // other stuff
Phase = PhaseMicros * 360 * 60 / 1000000;
... // other stuff
}