Getting DMA to work with SPI on a LPC1788, LPC4088
This tip is a little different from our usual style. This time we dive into one aspect in the world of firmware development on an ARM chip from NXP.
NXP have not explained how to use DMA with SPI. If you're accessing FLASH via SPI you'll want to use DMA to greatly boost performance. In the NXP Reference Manual there's no help, no pseudo code, just a mention of a single register:
Here is a 3 step guide that provides the core details NXP omitted.
With the LPC1788 or LPC4088 configured as a Master, reading from a Slave SPI device is the most challenging. This is because reading a byte on SPI requires you to send a byte first. So here's the first thing to know about the LPC:
To read using DMA with SPI, you need 2 DMA channels. One channel for is used for transmit while the other is used for receive.
Using 2 DMA channels leads to the next requirement, that of priority. So here's the next rule:
The receiving DMA must be a higher priority than the transmit DMA. This is because you don't want the transmitter
to send everything and not give the receiver a chance to receive. Remember, for each byte the transmitter sends, the receiver must receive a byte at the same
So it must TX + RX, TX + RX, ...
not TX, TX, TX, ..., RX, RX, RX, ...
However setting the priority isn't enough, you must also make the burst length asymetrical otherwise every now and then a receiving byte will go missing AND the receiving DMA will get stuck, waiting for a byte that it never saw.
Set the transmit DMA burst length to 1 byte, and the receive DMA burst length to 4 bytes. This little gem from the LPC User Manual explains why: "If the DMA Controller is transferring data for the lower priority channel and then the higher priority channel goes active, it completes the number of transfers delegated to the master interface by the lower priority channel before switching over to transfer data for the higher priority channel."
So setting the transmit burst to 1 ensures it will relinquish control to the receiver immediately the receiver asks for it. This ensures the transmitter can never run ahead of the receiver.
As for the SSP0DMACR register we mentioned at the start, both SSP0DMACR.RXDMAE and SSP0DMACR.TXDMAE must be 1 to allow DMA reception.