cancel
Showing results for 
Search instead for 
Did you mean: 

SPI with mixed DMA / manual XFER and TXFIFO issue

gahelton1
Associate III
Posted on February 15, 2015 at 21:59

I am using SPI in slave mode with a mix of manual transmission/reception at the beginning of my message protocol (first 3 bytes manual), then DMA in the middle for the data transfer, then manual ACK/NAK byte response at the end based on the received CRC.

The first message goes through and slave code responds exactly as expected. However, when the master sends the second message, the first byte in response sent by the slave is incorrect, and the other response bytes are skewed/delayed by 1 byte. It appears as if the TXFIFO has an extra byte in it (that I didn't load, or didn't intentionally load), and this byte is sent before my ''good'' data.

Setting a breakpoint at the beginning of the routine, I can see that the setup for SPI and DMA are identical for the first message which works, and second message that does not work.

After I finish a message, I would like to clear the transmit and receive FIFOs to get a fresh start. Clearing the receive FIFO is not a problem (just read SPI1->DR four times and discard the results). Is there a way to clear the TXFIFO, or at least reset the internal TXFIFO pointer ?

It is strange that I would have to do this at all since there shouldn't be any ''extra'' bytes in the TXFIFO anyway. Everything that I've loaded has been sent -  no less - no more.  I waited unit the DMA indicated that the transfer was complete, and that the BSY flag was set, indicating the last DMA byte was in flight, before the last manual byte was sent. A screen capture of my Total Phase Cheetah log is attached. The format is 

Master Sent/Slave Sent

The first message is good. The slave response to the master 81 is AA. However, in the second message, when the master sends 81, the slave sends 15. I have no idea where this came from. I searched in memory in the areas close to the DMA buffer, but could not find it.

Any help or insight would be appreciated.

Thanks

4 REPLIES 4
gahelton1
Associate III
Posted on February 15, 2015 at 23:42

OK. I have found a brute force method of reseting the TXFIFO - Force an SPI reset.

RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST;

RCC->APB2RSTR &= ~RCC_APB2RSTR_SPI1RST;

Of course, this is just like a power on reset, and all of the SPI configuration must be re-entered, but this works. If anyone can find a better way, I would be interested in knowing.

Posted on February 16, 2015 at 08:54

That's a symptomatic cure. I personally would work on finding the root cause of the problem - did you use the CRC mode of SPI, for example?

JW

gahelton1
Associate III
Posted on February 17, 2015 at 03:10

I totally agree JW. I wish I had a better solution, or enough energy to work on finding out why the problem exists, but right now, I'm just happy that the code is working the way it's supposed to (at least from an external point of view).

But with that being said, it seems like there would be a ''cleaner'' way of clearing or reseting the TXFIFO. One can foresee instances where the TXFIFO is loaded with the intention of sending all of the data, and something happens where the transmission has to be aborted. In these cases, the FIFO must be cleared so the protocol can get re-synced. 

I am using DMA and CRC modes, and I do have the CRCERR flag issue resolved finally. Although I cannot tell you why. I've changed a lot of things in this program, but the SPI configuration has remained constant.

I will post updates here when I find out more.

tilmann
Associate III
Posted on March 09, 2015 at 13:49

Hello,

I ran into similar problems and I think I know the root of the problem.

The TXE flag is set as long as the TX FIFO is *not full*. So you're always stuffing too much data into the TX FIFO - and after the SPI transfer is completed, there's no way to get it out of there. The data that remained in the TX FIFO will be shifted out during the next SPI transfer.

In my case (with an F303), I am using the DMA to provide /all/ data to the SPI. But if the transfer is prematurely ended by the master, the next three data bytes are already in the TX FIFO and these will be sent first at the next transfer. Indeed the only way around this is a peripheral reset on the SPI - apparently, there really is no other way to reset the TX FIFO and state! I'd call that a bug. (In fact, this FIFO implementation is the worst I've ever seen...)

Tilmann