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)
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) ) ;
