Skip to main content
Evgeny Sobolev
Associate II
September 21, 2018
Solved

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

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.

    This topic has been closed for replies.
    waclawek.jan
    waclawek.janBest answer
    Super User
    September 21, 2018

    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

    11 replies

    waclawek.jan
    waclawek.janBest answer
    Super User
    September 21, 2018

    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 II
    September 21, 2018

    Resolved. Thanks!

    waclawek.jan
    Super User
    September 21, 2018

    Please mark as answered (Best). Thanks

    DAnsp
    Associate
    May 9, 2020

    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

    yliu.3
    Visitor II
    March 5, 2022

    Thank you for saving my day!

    waclawek.jan
    Super User
    May 9, 2020

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

    JW

    DAnsp
    Associate
    May 9, 2020

    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.

    waclawek.jan
    Super User
    May 9, 2020

    > 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

    JSing.11
    Associate
    May 9, 2020

    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!!

    waclawek.jan
    Super User
    May 9, 2020

    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

    RusikOk
    Associate III
    October 19, 2022

    hi! on the M0 + core, it worked for me only like this:

     HAL_SPI_DMAStop(&hspi1);
     __HAL_RCC_SPI1_FORCE_RESET();
     __HAL_RCC_SPI1_RELEASE_RESET();
     MX_SPI1_Init();