Reflow oven controller, Cortex-M0 clone, arm-none-eabi-gcc -O2, Fedora. TMR3 runs at 1 MHz. Update event is the 1 ms tick, CH1 captures mains zero-cross, CH2 compare fires the triac.
Problem: after 60 s on 50 Hz, zc_count should be about 6000. I get between 5900 and 5990, different on every run. A missed zero-cross means no gate pulse in that half-wave, so the heater power flickers. It gets worse when I raise the UART log rate.
What I checked:
- Scope shows clean zero-cross pulses, constant 10 ms spacing. So it is not the optocoupler or noise.
- Counters are volatile.
- Moved the capture block above the tick block. Loss is less frequent, not gone.
- Higher TMR3 interrupt priority changes nothing.
I don't get it. The datasheet says SR flags are write-1-to-clear, and I clear each flag as soon as I handle it. If a flag is set, the NVIC must enter the handler again. So how can an event with a set flag be missed?
void TMR3_IRQHandler(void)
{
uint32_t sr = TMR3_SR;
if (sr & TMR_SR_UIF) {
TMR3_SR |= TMR_SR_UIF;
tick_ms++;
if ((tick_ms % 500u) == 0)
log_due = 1;
}
if (sr & TMR_SR_CC1IF) {
TMR3_SR |= TMR_SR_CC1IF;
zc_count++;
zc_stamp = TMR3_CCR1;
TMR3_CCR2 = (zc_stamp + fire_delay_us) & 0xFFFFu;
}
if (sr & TMR_SR_CC2IF) {
TMR3_SR |= TMR_SR_CC2IF;
TRIAC_ON();
}
}
SR is defined in regs.h as a plain volatile uint32_t at base + 0x10. Eventually the clone has a silicon quirk, but I can't test off-target. Only UART counters and the scope.