K64 SPI - DMA - missing a byte on transfer

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

K64 SPI - DMA - missing a byte on transfer

5,115 Views
JHinkle
Senior Contributor I

I have implemented a detection and recovery method - but I would like to understand root-cause of the issue.

Two mcus communicate via SPI.  The K64 is the slave.  The master's spi clock is 8mhz.

69 byte Data packets are passed between the two mcus with an external IO pin being used for handshake/flow control.

The K64 (cpu clock is 120mhz) uses DMA to receive the incoming 69 byte packet and fire an interrupt upon completion.  Upon processing the packet, the flow control pin is toggled signaling the master to send another 69 byte packet.

Issue:  I can receive tens of thousands of these packets without an issue.  Then randomly, the process stalls and the stream of packets is halted.  Investigating the issue I found the K64 failed to acquire one of the bytes in the packet and the DMA counter is at one - so the DMA IRQ never fires.

Is there a known SPI hardware issue that may be causing this?

I have implemented a timeout detection process which resets the SPI's DMA channel and requests the last data packet be resent by the master.

As a side note - question #2.  The DMA documentation on the K64 states that once the DMA is engaged, the DMA channel can't be stopped until the inner DMA loop is completed.  It also states that CX in the DMA_CR register can be used to cancel the remaining data transfer.  My question is why is this not a per channel operation instead of one that is global to all channels.  In my case, I have two active dma channels in operation, so when I activate CX to kill the data transfer of my SPI-DMA receive process, I am also affecting the transfer of the other channel.

I found zero information being documented on how to recover from a failed DMA transfer.  After a lot of reading and trying different methods to stop the transfer (CX above) - I was able to reset the channel and continue with the flow of my data packets.  I suggest NXP think about adding some fault recovery documentation.

Third question/comment.  At first I was unable to reset the SPI's DMA channel - so after 10 hours of work I decided to use SPI interrupts instead of DMA.  I found time to reply to the IRQ and return was longer than 1 usec so I had to stay within the IRQ function and poll the SPI_SR RFDF status bit or I would get a SPI overrun condition SPI_SR - RFOF being set.

The K64's documentation states the the SPI_SR RFDF would fire an interrupt if any of the 4 FIFO locations was filled.  My testing suggested that the IRQ is not firing until the FIFO has more than one location filled - is that true?  The documentation also states that writing a one to the SPI_SR RFDF bit will reset it (which is what I did after each read of the SPI_POPR).  If there is more than one location filled in the FIFO when a POPR - Set RFDF operational pair is performed, will the K64 reset the RFDF bit immediately since the FIFO is NOT empty?  These are questions I was not able to determine based on code execution since I was unable to acquire all 69 data bytes without issue using polling.  I went back and finally figured out how to reset the DMA channel.

I know I asked a lot of questions in this post but they all came up in trying to understand why the K64's SPI/DMA would occasionally miss a data byte.

Thanks for any comments.

Joe 

Labels (1)
Tags (2)
25 Replies

386 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Joe,

The DMA handling multiple transfer is quite similar as Interrupt handler.

Whatever priority-preemption and round-robin mode, it need to consider the low priority request has chance to occupy the DMA engine. DMA can do two data streams, while it need system level balance.


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

386 Views
JHinkle
Senior Contributor I

Mike:

I back up.  I don't know if we are referring to different operations but i'm of the opinion that my original understanding of the DMA transfer is/was correct.  I reread AN4765 after it occurred to me that currently I am running multiple data stream simultaneously with DMA.  I run an Audio I2S continiously with DMA and also push data out two SPI ports - all at the same time.

AN4765 talks about "transfer".  I thought it was talking about completing a "transfer process as defined by the TCD" which was NOT to my understanding.  It is talking about individual data transfer requests - not complete TCD requests.  Since I am using "fixed" priority, I am only allowed one level of preemption so two data streams can operate at the same time.

This discussion was a detour from my original question as to why the DMA missed a SPI data transfer request.  The detour occured when I asked why the CX (cancel TCD transfer request) was global thereby affect multiple channels.  I guess that question is still open because as stated above, you can have multiple active channels.

Joe 

0 Kudos

386 Views
JHinkle
Senior Contributor I

Mike:

Thanks for your reply.

I don't use your SDK.  It is designed for general use, and very blotted - hard to read sometimes to.

I do not believe the issue is software.  As I stated, I can process millions of bytes thru the channel before this event occurs.

My DMA driver is very simple - as shown below.  Once initialized, I only set the DMA destination and byte count.

[CODE]

void DMA_Init(void)
{

SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK; // enable mux
SIM_SCGC7 |= SIM_SCGC7_DMA_MASK; // enable DMA

DMA_CR = 0; // dma based on priority - NOT Round Robin

DMAMUX_CHCFG14 = 0; // disable the channel to configure it
DMAMUX_CHCFG14 = DMAMUX_CHCFG_SOURCE(17) ; // SPI2 .. page 95
DMAMUX_CHCFG14 |= DMAMUX_CHCFG_ENBL_MASK ; // enable the mux


// fill the TCD area
DMA_TCD14_SADDR = (dword)&SPI2_POPR;
DMA_TCD14_SOFF = 0; // no offset
DMA_TCD14_ATTR = DMA_ATTR_SMOD(0) | DMA_ATTR_SSIZE(0) | DMA_ATTR_DMOD(0) | DMA_ATTR_DSIZE(0); // no circular addressing S&D, 8 bit S&D
DMA_TCD14_NBYTES_MLNO = 1; // 8bit sample every minor loop
DMA_TCD14_SLAST = 0; // not needed 

DMA_TCD14_DOFF = 1; // 1 byte each move
DMA_TCD14_CITER_ELINKNO = 64+5; // total samples
DMA_TCD14_DLASTSGA = 0;
DMA_TCD14_CSR = DMA_CSR_INTMAJOR_MASK ; // interrupt when done
DMA_TCD14_BITER_ELINKNO = 64+5; // no chan links, total samples


DMA_SERQ = DMA_SERQ_SERQ(14); // now enable chan .. set start to begin


NVIC_SetPriority(DMA14_IRQn, AudioDMA_Priority);
NVIC_EnableIRQ(DMA14_IRQn);

}


void DMA_Perform_Move(byte *B, dword Cnt)
{

DMA_TCD14_DADDR = (dword)B;

DMA_TCD14_CITER_ELINKNO = Cnt; // total samples
DMA_TCD14_BITER_ELINKNO = Cnt; // no chan links, total samples

}

[/CODE]

By the way -- what is the correct tags to use to include code as above.

Thanks.

Joe

0 Kudos

386 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Joe,

1> When the SPI communication issue happen (K64 failed to acquire one of the bytes in the packet), could you debug and provide SPI and DMA module registers value for deep dive analysis?

2> DMA transfer can be cancelled by software with the CR[CX] bit. When a cancel transfer request is recognized, the DMA engine stops processing the channel. The current read/write sequence is allowed to finish. The TCD of a cancelled channel contains the source and destination addresses of the last transfer saved in the TCD. If the channel needs to be restarted, you must re-initialize the TCD.

If there with DMA error status register DMA_ES flag was set?

3> There with one DMA engine, only one DMA channel can do the transfer at same time.

4> Which SPI module you are using? The RX FIFO size is different for different SPI module:

pastedImage_1.png

Thank you for the attention.


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

386 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Joe,

I would recommend to refer and use MCUXpresso SDK for K64 provided <fsl_dspi_edma.c> driver.

You could download the MCUXpresso SDK software package from here.

The <edma_b2b_transfer> demo located with below path:

..\TWR-K64F120M\boards\twrk64f120m\driver_examples\dspi\edma_b2b_transfer

Please let us know if that driver also has the same issue.

Thank you for the attention.


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos