cancel
Showing results for 
Search instead for 
Did you mean: 

Data bits shifted in SPI communication on STM32L462 after repeating one successful session (consisting of NSS falling edge, 3 separated transmissions with HAL_SPI_TransmitReceive, NSS, rising edge)

YVido.1
Associate

Data bits are shifted on second SPI session (BSY bit stay high at the end of data transfer in slave mode)

We are using STM32L462VET6, and initialize SPI2 in full duplex slave mode (CPOL=1, CPHA=2-edges) with software NSS and baudrate 960 kHz with HCLK = 80 MHz and whole the periphery set to the same freq in CubeMX (v5.6.1) with additional settings: HSI RC = 16 MHz, PLLM=/1, PLL*N=x10, PLL/R=/2

But we are facing an issue. First session is successful and the data transfer is correct (sequence: NSS falling edge, start transmission 5 bytes, then transmit more 14 bytes, and at the end more 2 bytes. Then Raise NSS up). This issue is observed with enabled as well as disabled DMA (by using HAL_SPI_TransmitReceive and HAL_SPI_TransmitReceive_DMA full duplex transfer functions).

The issue appears when next session is started with the same data content and tried to send data through function HAL_SPI_TransmitReceive().

SPIx_SR register becomes 0x82 (BSY + TXE) and next try to use HAL_SPI_TransmitReceive() command leads to hanging up in internal function SPI_EndRxTxTransaction(). If I force SPI_EndRxTxTransaction() to terminate, data is received with one bit shifting in right direction

(expected received bytes from SPI Slave side: %0000 0010, 1101 0000,

observed actual bytes: %1000 0001, 0110 1000).

This bit shifting probably causes the busy state.

I tried errata proposal (“BSY bit stay high at the end of data transfer in slave mode�?) to use the following code after HAL_SPI_TransmitReceive(), but without success:

1. Write last data to data register.

2. Poll the TXE flag until it becomes high, which occurs with the second bit of the data frame transfer.

3. Disable SPI by clearing the SPE bit mandatorily before the end of the frame transfer.

4. Poll the BSY bit until it becomes low, which signals the end of transfer.

Code:

    // 1. Write last data to data register

   U16 x = hspi2.Instance->DR;

   hspi2.Instance->DR = x;

   // 2. Poll the TXE flag until it becomes high

   while( HAL_IS_BIT_CLR(hspi2.Instance->SR, SPI_FLAG_TXE) ) ;

    // 3. clear CR1.SPE bit (bit6)

   hspi2.Instance->CR1 &= ~SPI_CR1_SPE;

   // 4. Poll the BSY bit until it becomes low

   while( HAL_IS_BIT_SET(hspi2.Instance->SR, SPI_FLAG_BSY) ) ;

3 REPLIES 3
S.Ma
Principal

Experiment with the following: When the communication is completed (NSS rise edge/EXTI), reset the SPI cell (check in RCC/SYS) and reinit evertything.

After implementing this, do you see any changes?

TDK
Guru

> 3 separated transmissions with HAL_SPI_TransmitReceive

You could be too late in calling the second one before the master sends another clock. Combine the 3 calls into a single call.

If you feel a post has answered your question, please click "Accept as Solution".
RMcCa
Senior II

I don't use hal, but it is my understanding the the slave needs to be enabled far enough ahead of transission so the slave's tx register is properly loaded at the start. Might expain the single bit shift. Best thing to do is reload & reenable the spi at the end of a transmission, not at the beginning when ss becomes active ( if you are using one )​