I have an application where I was using SPI to communicate with an external multichannel 24bit ADC and used DMA to move the samples into SRAM. I am using LPCopen 3.03 with GCC on a LPC54102 (custom board) M4F only. This has almost worked ok with some gotchas. I have a few questions and a LPCopen bug report.
The ADC asserts data ready (DR) when data conversion is complete. DR is used to trigger DMA to initiate an SPI transfer. Both data and transfer control can be sent with DMA to the SPI transmit through the TXDATCTL register. DR will also trigger the SPI RX channel to move data when available into SRAM using a pair of ping-pong buffers. At the end of the transfer, I want an interrupt that will ultimately trigger a thread to process the data.
I ended up using byte transfer rather than word because of endian problems between SPI (big endian) and the little endian ARM. I couldn't find a good way for the DMA to deal with this on it's own. This requires some backend processing so If you know of a way, please let me know.
I needed a hardware trigger of the DMA which is documented in the datasheet but I couldn't find any working examples.
The documentation states that NVIC has to be enabled for GPIO to trigger the DMA. So it is straightforward to set that up as a pinint.
Chip_INMUX_PinIntSel(PININTSELECT0, PIO1_1_PORT, PIO1_1_PIN);
The interrupt service routine doesn't really have to do much and adds unnecessary overhead. It could be used to clear the interrupt although I thought that was what DMA_XFERCFG_CLRTRIG was for but maybe both need to be cleared. I tried to not use it but DMA hardware trigger wont work without it. I need to test if the DMA trigger from the GPIO incurs a delay that might be seen with priortized interrupts because it is using the interrupt hardware.
The DMA setup itself is:.
Chip_DMA_SetupChannelTransfer(LPC_DMA, DMAREQ_SPI0_TX, DMASPITXDescriptor.xfercfg);
DMA_CFG_HWTRIGEN | DMA_CFG_TRIGPOL_LOW | DMA_CFG_TRIGTYPE_EDGE |
DMA_CFG_PERIPHREQEN | DMA_CFG_CHPRIORITY(1));
Map the pinint0 to DMA SPI TX/RX channels use the include file inmux_5410x.h with the following:
This didn't work.
There is a bug in LPCopen include file inmux_5410x.h file lines 72-95. The enumeration DMA_TRIGSRC_T does not match the datasheet UM10850 pg 103 DMA_ITRIG_INMUX register definition. The problem is that the datasheet does not have entries for CT32B1 Match 1 or CT32B3 Match 1 while the include file does. Since pinint0 follows the timer entries, the enumeration is off by two. With that enumeration fixed, hardware trigger worked as expected.
Please take this as a bug report and it would be great if it got fixed?