Hello,
I am trying to use DMA with SPI (Flexcomm0) on LPC550x. I have this current setup:
My DMA requests all have PERIPHREQEN enabled and the Flexcomm has DMA enabled for both FIFOs. They use normal 8-bit transfer descriptors without linked descriptors, so just one-off transfers.
When I do this, I get a 0xFF byte at the beginning of my output buffer (read from SPI). I do not see this byte on the wire, so it looks like the DMA channel has tried to read from an empty FIFORD.
However, when I change the order to this, where I trigger the TX DMA first:
Then everything works properly and I read 10 correct bytes.
My question: does the DMA controller look at the DMA request line from the peripheral on the first transfer, immediately after triggering the channel, or does it ignore it? Because according to the tests above it looks like the controller will always read FIFORD immediately on triggering the RX channel, even if the FIFO is empty.
I think this is the case because the issue occurring seems to depend on the ratio between the SPI clock and the DMA clock (AHB clock), so it seems that the RX DMA channel is racing the SPI peripheral on the first transfer without looking at the request line.
Thanks!
Hi,
As you know that the spi module in master mode is synchronized for transmitter and receiver, in other words, after the spi module in master mode transfers data to slave spi can the master spi receives data from slave spi, so the transmitter channel DMA has to transfer data to slave, then the receiver channel DMA can read data.
Can you post the code so that we can understand your software scheme?
BR
XiangJun Rong
As a follow-up to my other reply (below):
It seems that if I try a DMA RX transfer immediately after the SPI is initialized, without ever sending anything, it behaves properly (and does not transfer anything since there is no transmitter activity yet).
But if I write anything to the FIFOWR, and then clear the FIFORD afterwards (after it becomes not empty), no matter what I do after, the DMA RX transfer will always transfer 1 byte even though no further SPI transmissions have taken place after both FIFOs are empty.
In other words, this is what I see if I use DMA RX straight after init:
SPI0.FIFOCFG = 0x00000000 // disable all FIFOs
SPI0.CFG = 0x00000004 // select master mode
SPI0.DIV = 0x0000012c // set bit rate
SPI0.FIFOCFG = 0x00033003 // enable TX/RX and empty them
SPI0.CFG |= 0x00000001 // enable SPI peripheral
fifostat = SPI0.FIFOSTAT // fifostat = 0x00000030 = all empty
stat = SPI0.STAT // stat = 0x00000100
DMA0.CHANNEL4.CFG = 0x00000001 // enable PERIPHREQEN
DMA0.CHANNEL4.XFERCFG = 0x01ff4013 // set up 512-byte RX transfer
DMA0.SETTRIG = 0x00000010 // trigger channel 4
while (1) {}
// stop with debugger later
// DMA0.CHANNEL4.XFERCFG = 0x01ff4013
But if I transmit and receive at least one byte on the FIFOs before:
SPI0.FIFOCFG = 0x00000000 // disable all FIFOs
SPI0.CFG = 0x00000004 // select master mode
SPI0.DIV = 0x0000012c // set bit rate
SPI0.FIFOCFG = 0x00033003 // enable TX/RX and empty them
SPI0.CFG |= 0x00000001 // enable SPI peripheral
while (SPI0.FIFOSTAT & TXNOTFULL == 0) {} // wait for transmit space
SPI0.FIFOWR = 0xFF | DATA_LEN_8_BITS | EOT // transmit one byte with EOT
while (SPI0.FIFOSTAT & RXNOTEMPTY == 0) {} // wait for received data
tmp = SPI0.FIFORD // read received byte
fifostat = SPI0.FIFOSTAT // fifostat = 0x00000030 = all empty
stat = SPI0.STAT // stat = 0x00000130
DMA0.CHANNEL4.CFG = 0x00000001 // enable PERIPHREQEN
DMA0.CHANNEL4.XFERCFG = 0x01ff4013 // set up 512-byte RX transfer
DMA0.SETTRIG = 0x00000010 // trigger channel 4
while (1) {}
// stop with debugger later
// DMA0.CHANNEL4.XFERCFG = 0x01fe4013
Can you please explain this behaviour? It seems the only difference is SSD/SSA asserted in STAT, but these don't affect SPI/DMA operation?
Hi Xiangjun,
Sorry for the late reply; I am not developing in C so it would take me a while to produce some code.
I think the problem is that I am mixing DMA and direct FIFO access for SPI. I am implementing a SD card driver, so I use the FIFO to write out the command and wait for the responses, and only use DMA when reading out the data blocks as a second step.
Because I don't set EOT = 1 except at the end of an SD card operation, the SPI is stalled (STAT.STALLED = 1) when I submit my DMA operations. This seems to cause the RX DMA to immediately read from FIFORD even though the read FIFO is empty.
I can see this because when I am in this state (SPI.STAT = 0x00000070, SPI.FIFOSTAT = 0x00000030), I can set up a RX DMA transfer with XFERCFG = 0x01ff4013 and it immediately becomes 0x01fe4013, so one byte was read from FIFORD without any writes to FIFOWR.
Writing to FIFOWR and allowing the transmitter to begin sending before submitting the DMA transfer appears to clear this issue.
Is it allowed to submit a DMA RX transfer when the SPI master transmitter is stalled? (or if STALLED = 0 but MSTIDLE = 0 also)