The FIQ is a second instance of the interrupt logic. The key differences are:
low-latency, low-jitter entry
The entry for the FIQ is at the end of the vector table, so it isn't limited to a single instruction, which allows you to begin the interrupt handler directly at this point.
In addition, the time between the assertion of the FIQ and the execution of the first instruction in the FIQ handler is guaranteed to be fixed, so it is possible to implement exactly timed processing here. If the current instruction needs multiple cycles to complete (e.g. an ldm
instruction), it is aborted and restarted after the handler completed.
In addition, the FIQ mode has shadow registers for r8
to r14
, while the other special modes (IRQ
, SVC
, ABT
, UND
) only have r13
and r14
shadowed, so it is possible to keep local state between runs in registers, which again speeds up handler startup.
separate enable/disable logic
The FIQ can remain enabled while IRQs are executing (the FIQ logic disables interrupts, so the FIQ is higher priority), which is again a nod towards realtime applications.
The Cortex-M implements priority handling inside the interrupt controller, guarantees constant time entering any interrupt and does away with the shadow registers as entering the interrupt handler requires multiple memory accesses anyway.
This means the interrupt latency is significantly higher on Cortex-M, but still low-jitter. For high-frequency interrupts, this is a significant disadvantage.
For example, implementing a software serial port in an FIQ handler is easy:
fiq_setup:
MOV r0, #MODE_FIQ
MOV cpsr, r0 // switch mode to FIQ
MOV r8, #GPIO_BASE // address of GPIO controller
MOV r9, #2 // Tx line high
MOV r0, #MODE_SVC
MOV cpsr, r0 // switch back to SVC mode
This prepares registers r8
and r9
for when the FIQ handler runs
fiq_handler:
str r9, [r8]
ldr r9, [r8]
// handle the bit read from the Rx line
// prepare the next bit for Tx
subs r15, r14, #-4
If the routine is short enough, you can set up a timer with several hundred KHz that triggers an FIQ, and still use a single-digit percentage of CPU time only.