Handling PCIe Interrupts
This article details the interrupts mechanisms in PCI Express and how to generate interrupts on the reference design provided by Altera. It will be helpful to those wanting to know the PCI Express interrupt model and how to handle the two kinds of interrupts, that is, Legacy interrupt, MSI interrupt and MSI-X interrupt.
Legacy Interrupt (INTx Emulation)
For legacy compatibility, PCI Express provides a PCI INTx emulation mechanism to signal interrupts to the system interrupt controller (typically part of the Root Complex). This mechanism is compatible with existing PCI software, and provides the same level and type of service as the corresponding PCI interrupt signaling mechanism and is independent of system interrupt controller specifics. The legacy compatibility mechanism allows boot device support without requiring complex BIOS-level interrupt configuration/control service stacks. It virtualizes PCI physical interrupt signals by using an in-band signaling mechanism.
Generation of Legacy Interrupts
Legacy interrupts are signaled on the PCI Express link using message TLPs that are generated internally by the IP Compiler for PCI Express. The app_int_sts input port controls interrupt generation. When the input port asserts app_int_sts, it causes an Assert_INTA message TLP to be generated and sent upstream. Deassertion of the app_int_sts input port causes a Deassert_INTA message TLP to be generated and sent upstream.
The above figure illustrates interrupt timing for the legacy interface. In this figure the assertion of app_int_ack indicates that the Assert_INTA message TLP has been sent.
The above figure illustrates the timing for deassertion of legacy interrupts. The assertion of app_int_ack indicates that the Deassert_INTA message TLP has been sent.
Message Signaled Interrupt (MSI)
All PCI Express device Functions that are capable of generating interrupts must support MSI or MSI-X or both. MSI is edge-triggered interrupt mechanism. The MSI mechanism deliver interrupts by performing memory write transactions. A memory write associated with an MSI can only be distinguished from other memory writes by the address locations they target, which are reserved by the system for interrupt delivery.
MSI interrupts are signaled on the PCI Express link using a single double-word memory write TLP generated internally by the IP Compiler for PCI Express.
For Avalon-ST interface, the app_msi_req input port controls MSI interrupt generation. When the input port asserts app_msi_req, it causes a MSI posted write TLP to be generated based on the MSI configuration register values and the app_msi_tc and app_msi_num input ports.
The following figure illustrates the interactions among MSI interrupt signals for the root port. The minimum latency possible between app_msi_req and app_msi_ack is one clock cycle.
For Qsys-generated Avalon-MM PCIe Hard IP, it has up to 16 individual interrupt signals, RxmIrq_<n>[<m>:0], <m>< 16.
All these inputs will be mapped to one single MSI interrupt output.
The PCIe core will OR the multiple input signals, and generate only one single MSI interrupt output.
There exist an additional registers to find out which interrupt is active.
In Interrupt Status Register, signal AVL_IRQ_ASSERTED[15:0] will reflects which value on the corresponding interrupt input port.
Value 0 means Avalon-MM interrupt is not being signaled, value 1 means Avalon-MM interrupt is being signaled.
In Interrupt Enable Register, you would expect AVL_IRQ bit being set when a specified Avalon-MM interrupt signal is being asserted.
(Please refer to the PCI Express User Guide for the detail definition of Interrupt Status Register and Interrupt Enable Register)
After servicing the interrupt, software must clear the appropriate serviced interrupt status bit and ensure that no other interrupts are pending.
Switch Between Legacy And MSI
Since MSI and Legacy interrupts are mutually exclusive and reference design supports Legacy interrupts by default, we need to enable MSI and also disable Legacy interrupt and then assert MSI request signal in order to transmit MSI.
To enable MSI, set the bit of the MSI Capability Register Set (0x050h in configuration space) to 1, which is also the bit of Message Control Register.
The following figure shows the format of MSI Capability Register. And Message Control Register is located in the upper 16-bit of the Dword 0.
The following figure shows the layout of the Message Control Register whose less significant bit is MSI Enable bit.
For the MSI Enable bit, it can be both read and written.
• 0 = Function is disabled from using MSI. It must use INTx signals to deliver interrupts
• 1 = Function is enabled to use MSI to request service and is forbidden to use its interrupt pin (Legacy interrupt)
Disable Legacy Interrupts
To disable Legacy interrupt, set the Interrupt Disable at bit of Command Register (0x004h in the configuration space) to 1.
Please also ensure bit Memory Space Enable and bit Bus Master are being set as well because MSI interrupt is a memory TLP.
The above figure shows the layout for the Command Register.
The Interrupt Disable bit can be both read and written as well. And it controls the ability of a bridge to generate INTx interrupt messages.
• 0 = The bridge is enabled to generate INTx interrupt messages
• 1 = The bridge’s ability to generate INTx interrupt messages is disabled
If the bridge had already transmitted any Assert_INTx emulation interrupt messages and this bit is then set, it must transmit a corresponding Deassert_INTx message for each assert message transmitted earlier.
The two procedure ebfm_cfgrd_wait() and ebfm_cfgwr_imm_wait() can be used to implement the enable the desired interrupt mode and disable the previous mode, which indicate the configuration read and configuration write transaction separately. That is, use ebfm_cfgrd_wait() procedure to read data from the specified configuration register, update the corresponding bit as we mentioned above, and then write the updated contents back to the configuration register with the ebfm_cfgwr_imm_wait() procedure. The details for the two procedures can be found from the user guide as reference.
MSI Design Example
The following code allows for multiple MSI interrupts to be used. It is based on the Stratix V device. The original compilation was Quartus II 13.0 and it can be upgraded to more recent versions of the Quartus II software using QSYS.
For MSI-X details, refer to this Altera Wiki page : http://www.alterawiki.com/wiki/Implementing_MSI-X_for_PCI_Express_in_Altera_FPGA_Devices.