AnsweredAssumed Answered

K64 SPI - DMA - missing a byte on transfer

Question asked by joe hinkle on Dec 24, 2018
Latest reply on Dec 30, 2018 by joe hinkle

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.