POD Interrupt handler

From ArmadeusWiki
Jump to: navigation, search

Interrupt handler mechanism

This page details the software mechanism we have to implement in the CPU connected to the FPGA, to handle the multiple IP interrupt sources with only one interrupt physical signal. Althought dedicated to Linux on ARM9, it should applies to every "well coded" OSes.

Preamble

ARM cores handle only 2 interrupts by default:

  • FIQ: "Fast interrupt", highest priority one
  • NIQ: "Normal interrupt"

Then constructors add their own logic to extend the number of interrupts connected to these 2 ones.

So on ARM systems there is a global interrupt handler which is called each time an interrupt occurs. Its job is to identify the interrupt source and then to delegate the job to the sub "interrupt handler".

Linux integrates this mechanism and provides an API to handle multiple interrupt handler registering and IT dispatching:

 set_irq_chip(irq, struct irq_chip*);
 set_irq_handler(irq, handler);
 set_irq_flags(irq, flad);
 set_irq_chained_handler(muxed_irq, demux_handler);
 set_irq_chained_handler(muxed_irq, demux_handler);
 ...

How it actually works on i.XML

Interrupts are divided in 2 categories:

  • i.MXL internal peripheral interrupts ("MPU"), with attributed numbers between 0 and 64
  • GPIO interrupts ("GPIO"), with attributed numbers between 65 and 192 (32x 4 GPIO ports)

On a running system:

# cat /proc/interrupts
           CPU0
 26:          0         MPU  IMX-uart
 29:        183         MPU  IMX-uart
 30:        495         MPU  IMX-uart
 35:       4592         MPU  imx-mmc
 39:          1         MPU  I2C_IMX
 40:      56534         MPU  spi_imx.2
 41:          0         MPU  spi_imx.1
 59:     326869         MPU  i.MX Timer Tick
 60:          0         MPU  DMA
 61:       1405         MPU  DMA
110:        935        GPIO  eth0
168:       6517        GPIO  tsc2102
Err:          0

The GPIO family interrupts can be seen as a subclass of MPU interrupts (ITs). Indeed there is only one hardware interrupt per GPIO ports.

  • GPIO_INT_PORTA has number 11
  • GPIO_INT_PORTB has number 12
  • GPIO_INT_PORTC has number 13
  • GPIO_INT_PORTD has number 62

So, GPIO ITs are multiplexed for each port. Linux allows to have a "virtual" interrupt number, not reflecting the hardware one and which remove demultiplexing handling from the peripheral drivers. This mechanism is used for handling POD single IT.

How to implement it for POD

We will declare IT 65 as a chained IRQ (if possible as it's already a virtual interrupt of IT 11) and add a demultiplexer for FPGA in the IRQ handler. This way usable IT numbers for IP will be in the range [192-255?].

figure 1 - i.MX IRQ schematic

Interrupt register in the FPGA

To handle the interrupts, the IT manager IP will have 2 registers:

  • an Interrupt Mask Register (IMR) for interrupt activation/deactivation. Actually this is a 16 bits register at address 0x00 with 1 bit per IT -> 16 IT handled:
FPGA_IMR Interrupt Mask Register Addr 0x0000
BIT 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
IT_15 IT_14 IT_13 IT_12 IT_11 IT_10 IT_9 IT_8 IT_7 IT_6 IT_5 IT_4 IT_3 IT_2 IT_1 IT_0
TYPE rw rw rw rw rw rw rw rw rw rw rw rw rw rw rw rw
RESET 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0x0000
Name Description Settings
Bit 15-0 Enable/disable corresponding interrupt 0 -> IT masked/deactivated
1 -> IT enabled


  • an Interrupt Status Register (ISR) which holds the number of the IT generating the interrupt:
FPGA_ISR Interrupt Status Register Addr 0x0002
BIT 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
IT_15 IT_14 IT_13 IT_12 IT_11 IT_10 IT_9 IT_8 IT_7 IT_6 IT_5 IT_4 IT_3 IT_2 IT_1 IT_0
TYPE rw rw rw rw rw rw rw rw rw rw rw rw rw rw rw rw
RESET 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0x0000
Name Description Settings
Bit 15-0 Indicate whether the corresponding IT is pending or not.
Writing a 1 to this bit acknowledges the IT and clears it.
0 -> IT not pending
1 -> IT pending

Links