Interrupts¶
An interrupt service routine (ISR) is a top-level handler bound to a hardware interrupt vector. ik makes ISRs a first-class declaration so you never write a vector table or a context save/restore by hand.
The isr declaration¶
isr <VECTOR_NAME> {
# handler body
}
For example, a Timer0 compare-match handler on an ATmega328P:
isr TIMER0_COMPA {
1 ->+ $ticks
}
An ISR:
takes no parameters and returns no value;
is bound by vector name, validated against the selected
target;causes the compiler to emit the jump from the correct vector-table slot, a full register/context save on entry, the matching restore on exit, and the
reti(return-from-interrupt) instruction.
Vector names¶
The set of valid vector names is device-specific. The compiler knows the
ordered vector table for every supported device and checks your isr name
against it. Common examples:
Vector |
Meaning (device-dependent) |
|---|---|
|
External interrupt 0 |
|
External interrupt 1 |
|
Timer/Counter0 compare match A (e.g. ATmega328P) |
|
Timer/Counter0 compare match (e.g. ATmega32A) |
|
Timer/Counter1 compare match A |
|
USART receive complete |
|
ADC conversion complete |
Because the exact names and their ordering differ between parts, the complete,
authoritative list of bindable vector names for every supported device is in
Interrupt vector reference. Look up your target there to see exactly which
isr names you may use. The compiler also validates the name for you and
rejects an unknown one; make test-interrupts checks vector binding for every
supported device.
Enabling an interrupt¶
Two independent gates must be open before a handler runs:
The peripheral’s interrupt-mask bit must be set, so the source is allowed to request an interrupt. The peripheral libraries expose helpers for this — for example
@timer0_enable_compa_int.The global interrupt flag (the I bit in SREG) must be set. Do this with the
@seiintrinsic. Clear it with@cli.
@timer0_enable_compa_int() # unmask the specific source
@sei() # globally enable interrupts