I am using a Stratix IV FPGA development kit. I have instantiated an IP Compiler PCIe core along with some custom logic. Since I'm using Qsys, I'm using the CRA port connected to BAR3 to configure interrupt behavior. For some reason, when I set the physical RxmIrq line and/or write to a A2P mailbox register, neither results in a call to my interrupt handler on the host. However, when I use the physical msi_interface to drive msi_app_req high, I do see my interrupt handler on the host called. However, it's always called MORE THAN ONCE. When I attempt to generate 3 interrupts upstream, I'm ending up with between 15 and 18 interrupts. I have wrestled with this for months now, and it seems I'm stuck with this functionality. Since I'm using Qsys and the Avalon MM interface, I believe the documentation tells me to use the RxmIrq lines or the mailbox register. I have not been able to get either of those to work AT ALL. Again, the msi_interface signals do work, but the documentation seems to suggest that interface is for Avalon ST use instead of Avalon MM. I'm really confused here and any help would be greatly appreciated!!! I am able to read BAR3 and see the interrupt enable bits set at address 0x50, but still I see NO INTERRUPTS when writing a mailbox register or setting the RxmIrq line high. This core doesn't seem to work as advertised.
Please check few things below:
1. Set the MSI Enable bit=1 of MSI Control Status register, this bit is mapped to bit of configuration space register offset 0x50.
2. Set the Interrupt Disable bit=1 of Command Register at configuration space offset register 0x4 to disable legacy interrupt.
3. Set the Memory Space enable bit and Bus Master bit in Command register to 1, this is bit and bit at configuration space offset 0x4.
4. Check the Avalon-MM Setting is Completer-only mode or Requester/Completer mode.
Support of MSI interrupt requires instantiation of the CRA slave module where the interrupt registers and control logic are implemented.
Please make sure it is set to 'Requester/Completer' mode and CRA option is being checked.
This information can be found at solution link: http://www.altera.com/support/kdb/solutions/spr335270.html
Thanks for the quick response. I mentioned in my post that interrupts do work when I use the msi_app_req line from the msi_interface, so I'm confident that the PCIe configuration space settings are correct. If they weren't, I doubt that interrupts would ever work. My issue is that when I do request an interrupt, I get more than one (15).
I think I found out today why I'm seeing so many excess interrupts though. I created an interrupt request portion of my design that requests an interrupt once every second using the msi_app_req line. Each request resulted in exactly one interrupt and one call to my interrupt handler routine. This is exactly the functionality I was looking for, and it revealed to me that I was requesting interrupts too fast. With my design, the shortest interval between the interrupt requests is on the order of 100 ns or so. Whenever I run that part of the design, I get the extra interrupts.
So, now that I've somewhat figured out the cause of my problem, I'd like to know what condition should I wait for before I send the next request. I ask because I assumed that the interrupt acknowledge bit (msi_app_ack) would assure me that I was free to submit the next request. This turned out to NOT be the case, as my current design requests the next interrupt only after having received the acknowledgement signal on msi_app_ack. So, if you could answer that question for me, I would really appreciate it. As a follow up to that, I have not been able to produce an interrupt that calls my interrupt handler with a different MessageID (vector). Am I correct in assuming that the msi_app_num signal is the value to change if I want to see a different MessageID (vector)?
If you could answer those two questions for me, that would be great. Thanks again for the timely response. It is greatly appreciated!!!
When the Hard IP asserts app_msi_ack, it just means the HIP has created the interrupt message and sent out. It does not mean the message is really out of the FPGA. The HIP can't know when the packet is really out of the TX pin. Second, it absolutely does not mean the host has serviced the interrupt.
Below describe the interrupt flow:
1. The application asserts the interrupt app_msi_req to the HIP.
2. The HIP creates an interrupt message and sends it to the host via the PCIe link.
3. The HIP gives a high pulse at the signal app_msi_ack to inform the application that the interrupt is generated.
4. The host side receives the interrupt, run the interrupt service routine, in the service routine, the software does what it needs to do. (Different application has different way to do the communication. Dependent on how users design their product).
The app_msi_num represents the interrupt vector. The app_msi_num could be between 0~31 (1 is the default value).