I am using the LPC54608 controller and have configured Flexcomm 5 interface for SPI communication in master mode. The RX FIFO is emptied by the DMA controller, which is triggered for a transfer by an external pin (burst mode is enabled for a transfer of 32 bytes upon each pin interrupt). Therefore, the "source" address for the DMA transfer is the SPI's RX FIFO. The "destination" address of the transfer is in the EMC's address range.
For your reference, the SPI interface is connected to an external 8-channel ADC, the external pin that triggers the transfer is a data ready input for reading all channel's data (8-chan *4B/chan = 32Bytes). For generating the SPI interface clock, and due to the data rates, we are using the Audio PLL at a frequency of 5.12 MHz.
This entire process of SPI->DMA->EMC (SDRAM) works for a period of time (ranges from 30mins to 8 hours) as configured. Then, the SPI status register begins indicating an Rx FIFO Error, which indicates the FIFO is overflowing, and, since this is being emptied by the DMA controller, that the DMA controller is not emptying it fast enough.
Unfortunately, there's not much available regarding the status of the DMA controller itself. I can see the triggers are still occurring, and that there are no errors for the channel (channel 10). Nor is there any ability to increase the DMA contoller's clock (SYS clock is at 180MHz).
Can you direct me to where I can look to identify what happens, and why the FIFO is no longer getting emptied fast enough?
I am using the input pin to trigger the transfer. The ADC we are using is AD7770ACPZ
The 4 yellow signals at the bottom are part of the SPI interface (I can share the specific pins if needed, but they are configured correctly for SPI). The other 4 signals are:
The hardware triggering off the pin interrupt is configured as such:
INPUTMUX_AttachSignal( INPUTMUX, kPINT_PinInt0, kINPUTMUX_GpioPort0Pin1ToPintsel);
INPUTMUX_AttachSignal( INPUTMUX, DMA_FC5_RX_CHANNEL, kINPUTMUX_PinInt0ToDma);
INPUTMUX_AttachSignal( INPUTMUX, DMA_FC5_TX_CHANNEL, kINPUTMUX_PinInt0ToDma);
PINT_PinInterruptConfig( PINT, kPINT_PinInt0, kPINT_PinIntEnableFallEdge, NULL );
You see it is used to trigger both tx and rx. Tx is only triggered to generate the spi clock. The priorities are then set:
DMA_SetChannelPriority( DMA0, DMA_FC5_TX_CHANNEL, kDMA_ChannelPriority1 );
DMA_SetChannelPriority( DMA0, DMA_FC5_RX_CHANNEL, kDMA_ChannelPriority0 );
The channel configuration registers are set to use a hardware trigger:
trigger.burst = kDMA_EdgeBurstTransfer32;
trigger.type = kDMA_FallingEdgeTrigger;
trigger.wrap = kDMA_NoWrap;
DMA_SetChannelConfig( DMA0, DMA_FC5_RX_CHANNEL, &trigger, true );
DMA_SetChannelConfig( DMA0, DMA_FC5_TX_CHANNEL, &trigger, true );
Just an idea...
While DMA does not need the core, it needs the bus. Do you have another routine/process that might block the bus to the SDRAM ?
Like a routine performing periodical calculations over the gathered values, or saving them to mass storage ?
Thank you so much for the idea! To test this out, I thought I'd stop all other tasks reading and writing to the SDRAM, to see if this had an effect. Unfortunately, it did not - it didn't seem to make a difference at all, with the SPI Rx Errors starting to increment about 30mins after running. Do you see an obvious flaw in this test, maybe? Or if you have any other ideas, I'd love to hear them.
Such delayed problems are usually not so easy to debug, and sometimes tend to fall into the Heisenberg category.
But often, such errors are related to stack overflows, out-of-bound access (arrays), or race conditions. Especially race conditions with interrupts are sometimes quite elusive.
Perhaps you could instrument you code to toggle IO signals on entry/exit of routines supposedly involved, and watch them with a scope or logic analyzer . A proper (scope) trigger at the error condition would give you a visual signal representation of the application behaviour at the critical point.
But by instinct, I would consider to change the ADC DMA destinationto SRAM, and either move them manually to SDRAM, or by another DMA. Internal SRAM is faster, and has 32-bit width.
I would like to confirm which source triggers the DMA transfer.
case 1: the spi ADC device has an output pin, it is connected to Pin interrupt pin, it triggers the DMA transfer.
Case 2: You use the DMA channel 10 (Flexcomm Interface 5 RX / I2C Slave) to request the DMA transfer
Pls check, if you use case 1, can you give the external SPI ADC part number and connection?
If you use case 2, I think we have to find out a workaround.