I am trying to figure out how reentrant interrupts are supposed to work on ARMv7. According to the ARM document DUI0203H, this is what you have to do:
Example 6.16. Nested Interrupt (ARMv6, non-vectored interrupts) IRQ_Handler SUB lr, lr, #4 SRSFD #0x1f! ; Save LR_irq and SPSR_irq to System mode stack CPS #0x1f ; Switch to System mode STMFD sp!, {r0-r3,r12} ; Store other AAPCS registers AND r1, sp, #4 SUB sp, sp, r1 STMFD sp!, {r1, lr} BL identify_and_clear_source ; *** 1 *** CPSIE i ; Enable IRQ BL C_irq_handler ; *** 2 *** CPSID i ; Disable IRQ LDMFD sp!, {r1,lr} ADD sp, sp, r1 LDMFD sp!, {r0-r3, r12} ; Restore registers RFEFD sp! ; Return using RFE from System mode stack
The problem I see is that the interrupt usually needs to be acknowledged and cleared at two locations, once for the source of the interrupt and once for the interrupt controller and in that order. The snippet below (from ARM Knowledge Base on nested interrupts) illustrates this on the first and last lines:
/* External Interrupt 1 Service */ void eint1_srv (void) __irq { EXTINT = 2; // Clear EINT1 interrupt flag IENABLE; // allow nested interrupts delay (); ++intrp_count; // increment interrupt count IDISABLE; // disable interrupt nesting VICVectAddr = 0; // Acknowledge Interrupt }
So going back to the first code, exactly what happens in the identify_and_clear_source() function? Does it clear both the interrupt source module and the interrupt controller? Can this single function really know about all interrupt sources and how you clear them (they can be hundreds in a large soc)? Or do we have to implement one such function for each interrupt (in which case, the name identify_and_clear_source doesn't make sense).
If anyone could explain this to me, or point me to some snippets, articles or literatures explaining this I would be very grateful.