Where are CPPI DMA completion queue interrupts registered? What register do they show up in?
The Tech Ref Manual says they are not in INTSRCR or INTMSKR. I've looked all over for this.
Thanks for your help.
-- Walter Snafu
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
(Regarding the OMAP-L138)
I'm going to guess an answer to my question. The CPPI DMA interrupts are not registered in the usual manner of interrupts (with enable, mask, set, clear, and so forth). Rather, they are handled in the Queue Manager Queue Pending Registers: PEND0 and PEND1. The interrupt is enabled along with the USB interrupts, and appears exactly like a USB interrupt. Then one must poll the PENDx registers, to see which queue completed and was the source of interrupt.
After fielding a particular queue, one must then re-poll the PENDx registers to see if any further Buffer Descriptors exist in those queues.
When all the necessary queues have been handled (and show up zero'd in the PENDx registers), then the interrupt service routine is nearly done.
The last thing to do is zero the EOIR (End of Interrupt Register). (Though the Tech Ref Manual doesn't explain the eight-bit EOI_VECTOR field, and why it must all be zero'd. Why is it a "vector" if it's effectively just binary: zero or not-zero)
It is not clear from the Tech Ref Manual whether or not this EOIR handling prevents a race condition. What if, during the interrupt service routine, another completion queue issues an interrupt. Is there a race between that and the EOIR reset? Is it possible to "fall through the cracks" and not be seen for a very long time (until the next interrupt happens to come along). The Tech Ref Manual doesn't answer that, and provides no confidence.
The TRM says: "NOTE: While EOIR is not written, the interrupt from the USB controller remains asserted." That's a bit cryptic. How does that solve the race condition? It's not clear.
Any thoughts?
-- Walter Snafu
Hi Walter Snafu,
Thanks for your observation and projection. I will look into it in detail,
Meanwhile,look at this below if time permits for you.
There is a sample source code for USB in the starterware package of OMAPL138 to demonstrate the USB host and device capabilities which has the CPPI DMA implementation as well. Please do check those CPPI DMA drivers as well to understand the flow of register settings and interrupts.
Regards,
Shankari
-------------------------------------------------------------------------------------------------------
Please click the Verify Answer button on this post if it answers your question.
--------------------------------------------------------------------------------------------------------
I've spent a lot of time looking for how the CPPI DMA interrupts are handled (in the OMAP-L138). In Starterware, I looked in the usb_dev_bulk example (which does not use DMA), and in the usb_dev_msc example (which does use DMA). In either case, the key material shows up in the routine called "HandleEndpoints()", where the differences can be compared. I also carefully read the OMAP-L138 Tech Ref Manual.
Here is my best understanding of it.
The CPPI DMAs do not issue completion interrupts in the usual sense. You can't enable or disable them in the usual way. Rather, some of the Completion Queues generate interrupts, and if you want a DMA interrupt, then you program the channel/endpoint to use one of those dedicated Completion Queues. (Channel# = Endpoint# - 1. Duh.) There is no enabling, disabling, masking, setting, or clearing these interrupts. These particular interrupts are hard-wired. The interrupt is issued from the USB, but does not show up in any of the USB interrupt status registers. It looks and acts exactly like a USB interrupt -- but there are no registers for it, in the usual sense. I spent a lot of time looking, but they're just not there.
In my following discussion, set aside the CPPI queues that do not issue interrupts. Ignore those here. I discuss only the CPPI queues that issue interrupts.
So you must poll the PENDx registers, to see if your particular Completion Queues have something in them. If there is a BD (Buffer Descriptor) in that queue, then that was the source of your interrupt. That's how you tell where your DMA interrupt came from. You poll the PENDx registers. That's the only way to know it was a DMA interrupt.
I am not sure, but I suspect there is no race condition. Your interrupt service routine should process the completion queues until they are empty. And if you miss one (or ten, or more, it doesn't matter), then another interrupt will be generated as soon as your interrupt service routine finishes. (I suspect this is why one guy here posted about getting "an infinite number" of interrupts -- I suspect he wasn't emptying his completion queues.) So there is no danger of losing an interrupt. It will just keep interrupting until you've emptied your queues. The Tech Ref Manual is unclear about this, but that's my best understanding of it. Can someone verify this?
Resetting the EOIR (End of Interrupt Register) to zero should always be done, and the last thing done by your USB interrupt service routine. It has to do with a deep, dark, technicality about how TI absorbed a design from another company (the Mentor USB core) into TI's larger USB design (which added CPPI and FIFOs, etc.) TI did it with a bunch of "wrapper registers" and "PDR compliance" and stuff you don't need to know much about. The EOIR register appears to be one of those. Zeroing the EOIR is like re-enabling the USB interrupts -- if you haven't emptied your Completion Queues, you're immediately going to get another interrupt -- but if you haven't zero'd the EOIR, then you won't get any more USB interrupts.
TI recommends that you avoid using the interrupt registers from the Mentor core (these are eight bit registers). Rather, they recommend consistently using the so-called interrupt "wrapper registers" (starting with INTSRCR), and set the CTRLR.UINT bit to zero (the default).
-- Walter Snafu