547x DMA DSPI Problems

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

547x DMA DSPI Problems

4,907 Views
SteveJoiner
Contributor I
I am using LTIB (20051213) on a custom 5472 board. I am converting the DSPI driver in drivers/char/dspi to use DMA.

Initially, I was having problems that seemed like the DMA transfers were transferring data to the DSPI as fast as possible instead of waiting for the FIFO interrupts from the DSPI. I found the Freescale DMA example code posted on this forum and it had a fix for the problem. The fix was to set bit 0x40 in the flags argument when calling MCD_startDma(). So, instead of specifying MCD_SINGLE_DMA, I would specify MCD_SINGLE_DMA | 0x40.

So that fixed the problem, but introduced a new one. With the 0x40 flag, any DMA transfers after the first don't happen. If I take the 0x40 out, I get my transfers back, but the original problem of not waiting for the DSPI FIFO interrupts comes back.

Does anyone know what is going on here? Any suggestions as to how to fix it? Also, does anyone know where the 0x40 is documented? I couldn't find it in any of the 547x Reference Manual.

Thanks,
Steve
Labels (1)
0 Kudos
3 Replies

477 Views
ricks
Contributor I
We developed an application using DMA with the DSPI, and encountered many of the same headaches.

0x40 is the "PRECISE INCREMENT" flag, as I've been told by Freescale support. Its not documented anywhere publicly (like the rest of the DMA apparently). All I know is that without this flag, using the DMA with the DSPI is virtually meaningless.

We would have liked to have written our own descriptors for the DMA engine, but that isn't documented either. So we used the distributed DMA API from Freescale. As far as keeping the transfers going, when you get an interrupt (like an end of queue from the dspi), be sure the MCD_BUF_READY flag is set on the descriptors you want restarted. This flag is cleared on descriptors when the associated dma transfer is completed. A call to continue the dma transfers(s) (like the API function MCD_continDma) will get it going again, so long as the ready flag is set.

~Rick

PS, the cache is not coherent with the DMA engine.
0 Kudos

477 Views
SteveJoiner
Contributor I
I still can't get any transfers after the first to work. I saw your comments about making sure MCD_BUF_READY is set in the descriptors, however I'm using single DMA transfers. My MCD_startDma looks like this:

MCD_startDma(dev->tx_channel, /* channel */
(s8*) virt_to_phys(dev->dtfr_buf), /* srcAddr */
4, /* srcIncr */
(s8*) &(MCF_DSPI_DTFR), /* destAddr */
0, /* destIncr */
dma_tx_size, /* dmaSize */
4, /* xferSize */
dev->tx_initiator, /* initiator */
DSPI_TX_DMA_PRI, /* priority */
MCD_SINGLE_DMA | MCD_INTERRUPT | 0x40, /* flags */
MCD_NO_BYTE_SWAP | MCD_NO_BIT_REV | MCD_NO_CSUM); /* funcDesc*/

The first transfer completes fine, and calling MCD_dmaStatus returns MCD_DONE. However, when I call MCD_startDma the second time with the same parameters, the transfer doesn't happen and MCD_dmaStatus returns MCD_IDLE. The comments in MCD_dma.h say that MCD_IDLE means "DMA active, but the initiator is currently inactive."

Any ideas on how to get that second transfer to start?

Thanks,
Steve
0 Kudos

477 Views
mnorman
NXP Employee
NXP Employee
Steve,
 
Since this issue was resolved outside of the forum, I'm posting the resolution here in case it is of use to someone else.
 

1. To clear the flag bits in the DSR, you have to _set_ them.

2. Don't call dma_remove_initiator() for fixed initiators (like the DSPI TX and RX).

3. I'm doing TX and RX in pairs so there's always a matching RX for every TX. I thought I could wait for the RX DMA interrupt to know when I was done with the transfer.  Unfortunately, that interrupt would happen before the transfer was complete. I'm still not sure why. I worked around it by using the DSPI EOQF interrupt instead.

Message Edited by mnorman on 05-30-2006 04:30 PM

0 Kudos