> Relatedly, we've seen some odd, rare cases where interrupts can be take ~150us to enter the ISR
So your code is doing something you don't understand and don't expect. That's always dangerous.
I wouldn't try to work around a problem like that, but would try to find the buggy code that is locking the CPU out for that long.
This is very easy to do - it's about 10 minutes of programming to find the culprit, and an hour or two to implement a really useful solution you can leave in there that enhances the system for future monitoring and testing.
As part of your basic system design (stating what it is and what it does) you should have a line stating "Interrupt latency must be less than so-many microseconds". You may be a bit more sophisticated and separately list the required IPL0 latency, IPL1 latency, all the way up to IPL6 latency.
Then you have to enforce these requirements by actively measuring the interrupt latency, and declaring any code that disobeys those requirements to be broken, and then fix it.
The toughest one to measure is the IPL0 latency - the maximum time IPL0 can be locked out by interrupts. You need intrusive loop-testing to do this. Basically, replace your "waiting for something to do" loop with code that reads a DMA timer and measures the maximum time it has been locked out for. To find out what locked you out you throw a breakpoint, and then check the stack FORWARDS (not back) to see what the ISR pushed onto the stack. That should let you know which one did it. But you really need "interrupt logging" to track this down (see later).
All the other levels can be measured with a periodic timer interrupt that reads the timer in its ISR, calculated the latency and then throws a breakpoint when it detects a "latency violation". Usually you'll find the interrupt has happened to a line of code that just re-enabled interrupts, and then you know what function ran for a long time with interrupts locked out (that you probably didn't intend).
In the more complicated case of a higher interrupt service routine taking too long (and causing the latency), you write "ISR_LOG_START" and "ISR_LOG_FINISH" macros that you add to the start and finish of all interrupt service routines. They keep a log of start and finish times, and that then provides the evidence of what is taking too long.
I have those functions recording the total and maximum times taken at each IPL (automatically subtracting time taken at higher IPLs that interrupted the lower ones) and also the IPL0 non-idle time, and can track which execution levels are taking how much of the CPU.
Of course if you're using a third-party USB stack, and it is causing the problems, you're in for a lot of work trying to fix it.
Rant over, back to your original question...
> I can't seem to find anything in the reference manual (version 3 or 4) about how
> to enable DMA requests instead of interrupts on the UART.
I just started in the UART chapter and searched for every instance of "DMA":
41.3 Memory Map/Register Definition
NOTE: Interrupt can mean an interrupt request asserted to the CPU or a DMA
request.
41.4.2.3 FIFO
The RXRDY or FFULL bit can be selected to cause an interrupt and TXRDY or RXRDY can be used to generate a DMA
request.
41.5.1 Interrupt and DMA Request Initialization
41.5.1.2 Setting up the UART to Request DMA Service
Table 41-15. UART DMA Requests
UISRn 1 Receive DMA request
UISRn 0 Transmit DMA request
Well that was a bust. As you found, that didn't help answer your question at all!
Let's try searching the eDMA chapter for "UART":
19.4.3 eDMA Enable Request Registers (EDMA_ERQH, EDMA_ERQL)
The EDMA_ERQ{H,L} registers provide a bit map for the 64 implemented channels to enable the request
2 UISR0[FFULL/RXRDY] UART0 Receive
3 UISR0[TXRDY] UART0 Transmit
4 UISR1[FFULL/RXRDY] UART1 Receive
5 UISR1[TXRDY] UART1 Transmit
6 UISR2[FFULL/RXRDY] UART2 Receive
7 UISR2[TXRDY] UART2 Transmit
And so on. So it looks like you enable the UART Interrupts within the eDMA module.
Tom