My approach to interrupt routing
Posted: Fri Oct 21, 2016 11:34 am
The fact that I've implemented my method for interrupt routing in a HDL and programmable logic is probably just a detail - doubtless what I've done could be implemented in traditional 74xxx parts.
So my micro has around 8 interrupt sources. I had a few goals in mind:
Fast - obviously it needs to be more efficient then simply polling each peripheral IC.
Enabling/disabling particular interrupts, so if the IC - for whatever reasons - generates an interrupt it can be ignored.
Work within the restrictions of my current circuit: there is no way to directly present a ISR vector on the databus due to some missing CPU pins at the programable logic part
So what I have is a register map like this:
SETINTMASK - write only: each bit that is a 1 is set in the "IRQ filter"
CLEARINTMASK - write only: each bit that is a 1 is cleared in the "IRQ filter"
INTSTATUS - read only: a priority encoded number for the interrupt bit that is currently active
At the same time as generating INTSTATUS the implementation also generates the CPUs IRQ line (by comparing the masked status against 0).
The reason for the SET and CLEAR action was to make the interrupt setup as simple as possible - no need to read in the current mask, OR the new mask and write it out again.
The priority encoding saves a whole bunch of code in the top-level ISR. It just has to read INTSTATUS, rotate it left once and extract the particular device's handler from a table. The value 0 means something has gone wrong (it should never happen because the IRQ line should be high in this case.) The priorities are hardcoded in the HDL, something I'm not especially pleased with (it could be nice to make them configurable from CPU code) but I can live with it. I'm not sure if this is how "real" interrupt routers deal with prioritising device interrupt lines?
I guess for efficiency I could rotate the INTSTATUS in the HDL, but that seems a bit dirty somehow.
One thing I've pondered is for the HDL itself to hold the table of the device ISRs. In theory that would reduce the CPU ISR code to reading the "INTSTATUS" 16 bit value and jumping through it, probably the next best thing to having the interrupt router present the device's vector directly. But this would consume a fair amount of resources in my limited FPGA.
What approaches have others taken for dealing with computers with "many" interrupt sources?
So my micro has around 8 interrupt sources. I had a few goals in mind:
So what I have is a register map like this:
SETINTMASK - write only: each bit that is a 1 is set in the "IRQ filter"
CLEARINTMASK - write only: each bit that is a 1 is cleared in the "IRQ filter"
INTSTATUS - read only: a priority encoded number for the interrupt bit that is currently active
At the same time as generating INTSTATUS the implementation also generates the CPUs IRQ line (by comparing the masked status against 0).
The reason for the SET and CLEAR action was to make the interrupt setup as simple as possible - no need to read in the current mask, OR the new mask and write it out again.
The priority encoding saves a whole bunch of code in the top-level ISR. It just has to read INTSTATUS, rotate it left once and extract the particular device's handler from a table. The value 0 means something has gone wrong (it should never happen because the IRQ line should be high in this case.) The priorities are hardcoded in the HDL, something I'm not especially pleased with (it could be nice to make them configurable from CPU code) but I can live with it. I'm not sure if this is how "real" interrupt routers deal with prioritising device interrupt lines?
I guess for efficiency I could rotate the INTSTATUS in the HDL, but that seems a bit dirty somehow.
One thing I've pondered is for the HDL itself to hold the table of the device ISRs. In theory that would reduce the CPU ISR code to reading the "INTSTATUS" 16 bit value and jumping through it, probably the next best thing to having the interrupt router present the device's vector directly. But this would consume a fair amount of resources in my limited FPGA.
What approaches have others taken for dealing with computers with "many" interrupt sources?