Handling interrupts¶
Interrupts are first-class in ik. You declare a handler with the isr
keyword followed by the vector name for your device, and the compiler wires
it into the interrupt vector table — including the full register save/restore
and the reti at the end.
An interrupt service routine¶
target atmega328p
import std/timer
const %PORTB: u16 = 0x0025
const %DDRB: u16 = 0x0024
ram mut $ticks: u16 = 0
# Fires every time Timer0 reaches its compare-A value.
isr TIMER0_COMPA {
1 ->+ $ticks
0x20 ->^ %PORTB # toggle PB5
}
@main {
0x20 -> %DDRB
@timer0_ctc_mode()
@timer0_set_compare_a(249)
@timer0_set_prescaler(3) # /64 prescaler
@timer0_enable_compa_int() # unmask the Timer0 compare-A interrupt
@sei() # globally enable interrupts
loop * { } # the ISR does all the work
}
The pieces¶
isr TIMER0_COMPA { ... }Binds a handler to the named vector. The name must be one that exists for the selected
target—TIMER0_COMPAon an ATmega328P,TIMER0_COMPon an ATmega32A,INT0for the external interrupt, and so on. The compiler validates the name against the device’s vector table and emits a jump from the right table slot. An ISR takes no parameters and returns no value. The full list of valid names for your device is in Interrupt vector reference.- Per-peripheral enable, then global enable
Two gates must open before an interrupt fires. First unmask the specific source (here
@timer0_enable_compa_int()sets the timer’s interrupt-mask bit). Then enable interrupts globally with the@seiintrinsic. Use@clito disable them globally again.