cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 SPI TxFIFO problem

nellemannen
Associate II

Hi!

I have a SPI master that communicates in the following way:

CS is set

Start sending data in the following format -

2 bytes of "request"

2 bytes of crc for the "request"

x bytes to clock out the response from the slave

CS is released

On the slave side (STM32F746ZG) I have implemented a circular DMA which operates on a buffer of size 4 bytes. (This is only initiated once)

The SPI data size is 8-bit (1 byte).

I have implemented both HAL_SPI_TxRxHalfCpltCallback and HAL_SPI_TxRxCpltCallback.

This means that one of HalfCplt and Cplt callbacks will be triggered for every 2 bytes (since the full buffer is 4 bytes).

When I start my communication the Slave first receives 2 bytes and triggers HAL_SPI_TxRxHalfCpltCallback, I check for the "request" code and fill the 2 first bytes (since those were already traversed by the DMA when Half Cplt happens) of the Tx-buffer with the response for that specific "request".

After 2 more bytes HAL_SPI_TxRxCpltCallback is triggered and I fill the 2 last bytes of the Tx-buffer with the continuation of the response for previous "request".

I continue filling in the continuation of the response in both HAL_SPI_TxRxHalfCpltCallback and HAL_SPI_TxRxCpltCallback until the CS is released.

Describing the problem:

I can see that the Tx-Buffer that DMA is working with is as expected at all times, but the output of the SPI slave is wrong. This made me start looking at the TxFIFO behaviour.

What I think is happening is that the SPI TxFIFO is being filled with the wrong data since it will start filling as soon as there is room (triggered by TXE). Looking in the reference manual it says the following "The TXE flag is set when transmission TXFIFO has enough space to store data to send. TXE flag is linked to the TXFIFO level. The flag goes high and stays high until the TXFIFO level is lower or equal to 1/2 of the FIFO depth. The bit is cleared automatically when the TXFIFO level becomes greater than 1/2"

Based on this information I would guess what is happening is that before HAL_SPI_TxRxHalfCpltCallback (and HAL_SPI_TxRxCpltCallback) is triggered, we have already pushed 1 more byte (from the "old" buffer) into the TxFIFO instead of the new data that we are filling into the Tx-Buffer.

The result is that the output from slave on MISO is duplicated, for example if the original buffer is {1, 2, 3, 4} and the response is {5, 6, 7, 8}, then the output on MISO will be

1, 2, 3, 4, 1, 2, 3, 4 (duplicated part due to FIFO in bold).

And then next transmit starting with 5, 6 etc.

Anyway to test it I used a STM32F446 which does not have any Tx-FIFO for the SPI peripheral. On the STM32F446 everything worked perfectly and in the example above the output on MISO is 1, 2, 3, 4, 5, 6, 7, 8

So to my question, how can we make sure that the TxFIFO is not being filled up with "old" data during transmission? Looks like there is a Rx-Fifo threshold configurable, but not for Tx.

Is there some way to disable the Tx FIFO (I know flushing operation is not supported for STM32F7), or any other idea how to solve this? For example if we could ensure that the DMA transfer request is only set when the TxFIFO is completely empty.

If anyone has another idea of what might be happening that would be very appreciated as well.

Best regards

2 REPLIES 2

In 'F7 SPI, you cannot avoid using the TXFIFO. Take it as a fact and plan accordingly. For your mode of usage, you cannot use DMA in circular mode.

JW

nellemannen
Associate II

That was my understanding as well, thanks for confirming it. For anyone else that might get the same problem, the problem occurs because the SPI Tx-FIFO is larger than half of the buffer size (and since the FIFO not possible to clear or configure the threshold for) the circular DMA is operating on. I didn't manage to solve this communication problem in any other way than with circular DMA so I will go for either a device without this FIFO or a newer (e.g H7 family) which supports programming the fifo-level or flushing the Tx-FIFO.