cancel
Showing results for 
Search instead for 
Did you mean: 

How to clear internal SPI TX buffer in slave mode after transaction cancellation? SPI used in slave mode with DMA circular buffer.

Evgeny Sobolev
Associate III

Hello. I am using STM32F407VG controller. I have to transfer data from another device via SPI interface. STM32 SPI is used in slave mode, circular DMA enabled. Devices are connected via joint.

In some cases I need to resynchronize data exchange. At this moment SPI master device stops data exchange for some time (clock is stopped, CS is high). SPI slave (STM32F407VG) after some time tried to stop SPI  (HAL_SPI_Abort(&hspi1); ) and then restart SPI with circular DMA again. 

But after this operation other side (SPI master) receive one unnecessary byte. This byte have been transferred by DMA to SPI TX buffer before transaction is stopped. How to remove this byte from SPI TX buffer before start transaction. I tried to disable SPI, disable SPI pheripheral clock, but nothing help.

I have an idea to disable GPIO and switch SPI to master mode. Is there another way possible? May be unreferenced register to reset spi buffer or spi module exists.

1 ACCEPTED SOLUTION

Accepted Solutions

This has been discussed here several times, you may want to search. The consensus appears to be that the easiest way is to reset SPI through its respective RCC_APBxRSTR bit, and then configure it again.

JW

View solution in original post

11 REPLIES 11

This has been discussed here several times, you may want to search. The consensus appears to be that the easiest way is to reset SPI through its respective RCC_APBxRSTR bit, and then configure it again.

JW

Evgeny Sobolev
Associate III

Resolved. Thanks!

Please mark as answered (Best). Thanks

DAnsp
Associate II

I've been struggling with a similar problem on an STM32L073 and resetting the SPI though the RCC_APBxRSTR bit and reconfiguring it did not resolve this issue.

I'm using the SPI in full duplex slave mode. The workaround I've come up with to flush the SPI TX buffer is to briefly switch to Master mode, which will clock out the TX byte/word in the buffer, then immediately switch back to Slave mode once the byte is flushed. The SPI_SCK and SPI_ MOSI pins are also briefly switched to inputs during this operation to avoid bus contention. The example below is specific to SPI1 on the STM32L073

HAL_SPI_DMAStop(&hspi1);				  // Disable DMA before flushing TX buffer
// Flush TX byte in TX DR
GPIOB->MODER &= ~GPIO_MODER_MODE3;	  // Set SPI CLK pin (PB3) to input to avoid bus contention
GPIOA->MODER &= ~GPIO_MODER_MODE12;  // Set SPI MOSI pin (PA12) to input to avoid bus contention
SET_BIT(SPI1->CR1,SPI_CR1_MSTR);		           // Change to Master mode to flush TX buffer
while (SPI1->SR & SPI_SR_BSY) {}		           // Wait for byte/word to be clocked out
CLEAR_BIT(SPI1->CR1,SPI_CR1_MSTR);	          // Switch back to Slave mode
GPIOB->MODER |= GPIO_MODE_AF_PP << GPIO_MODER_MODE3_Pos;	// Set SPI CLK Pin (PB3) back to Alternate Function
GPIOA->MODER |= GPIO_MODE_AF_PP << GPIO_MODER_MODE12_Pos;	// Set SPI MOSI Pin (PA12) back to Alternate Function

So, SPI transmitted old bytes from FIFO/buffer after being reset? Are you sure you've stopped DMA before the reset?

JW

DAnsp
Associate II

Not sure if it's different on the STM32L073, but stopping the TX/RX DMAs, deinitializing them, shutting down the SPI, then reconfiguring everything didn't flush that byte from the TX buffer.

JSing.11
Associate II

I have been going through the same issue with STM32F302VCT as a SPI1 slave (full duplex) connected with raspberry pi as master SPI. Even de-init of SPI1+dma and re-configuring / re-init of SPI1+dma don't resolve the issue. The issue is that transmit buffer fifo (SPI_FLAG_FTLVL) is not cleared after a successful transfer. I am amazed that ST doesn't have any example solution to handle such scenerio.

Please Help!!

> stopping the TX/RX DMAs, deinitializing them, shutting down the SPI,

> then reconfiguring everything didn't flush that byte from the TX buffer.

Can you please post the code you used for all this?

And how exactly do you know it does not clear the Tx buffer - do you observe the SPI bus using a LA, or some other way?

Thanks,

JW

To avoid confusion with others, please start a new thread, stating the problem and posting relevant portions of code, perhaps also linking this thread.

Thanks,

JW