LPC55xx SPI DMA pacing

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC55xx SPI DMA pacing

1,127 Views
Bacterius
Contributor II

Hello,

I am trying to use DMA with SPI (Flexcomm0) on LPC550x. I have this current setup:

  1. set up peripheral -> memory DMA transfer to read 10 bytes from FIFORD
  2. trigger the transfer
  3. set up memory -> peripheral DMA transfer to write 10 bytes to FIFOWR
  4. trigger the transfer

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:

  1. set up memory -> peripheral DMA transfer to write 10 bytes to FIFOWR
  2. trigger the transfer
  3. set up peripheral -> memory DMA transfer to read 10 bytes from FIFORD
  4. trigger the transfer

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!

Labels (3)
0 Kudos
Reply
3 Replies

1,108 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

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

 

0 Kudos
Reply

1,025 Views
Bacterius
Contributor II

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?

0 Kudos
Reply

1,041 Views
Bacterius
Contributor II

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)

0 Kudos
Reply