AnsweredAssumed Answered

HAL_SPI_TransmitReceive_IT() issue in STM32Cube_FW_F4_V1.11.0

Question asked by tardy.vincent on Mar 2, 2016
Latest reply on Jan 19, 2017 by Imen D
Hello,

We are facing to an issue when we test HAL_SPI_TransmitReceive_IT() function with SPI high speed.

We can observe that, when SPI global interrupts occur and HAL_SPI_IRQHandler() is called, the process Tx->Rx - Tx>Rx is not respected and sometimes Overrun error is notified.

Indeed,we can observe the following scenario:
- HAL_SPI_TransmitReceive_IT() is called to transmit/receive few bytes
- HAL_SPI_IRQHandler() is called : SPI TXE Interrupt is detected. Consequently, SPI_2linesTxISR_16BIT() function is called. In this function, next byte to transmit is setting directly in the 'hspi->Instance->DR' register without wait for Rx data
- HAL_SPI_IRQHandler() is called : SPI TXE Interrupt is detected but not the SPI RXNE Interrupt. For this reason, we have lost the Rx data on the SPI peripheral. 

In order to solve this issue, we have added code in the SPI_2linesRxISR_16BIT() and SPI_2linesTxISR_16BIT() functions

static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
{
  /* Transmit data in 16 Bit mode */
  hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
  hspi->pTxBuffPtr += sizeof(uint16_t);
  hspi->TxXferCount--;

  /* Enable CRC Transmission */
  if(hspi->TxXferCount == 0U)
  {
#ifdef USE_SPI_CRC
    if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
      SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
    }
#endif

    /* Disable TXE interrupt */
    __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);

    if(hspi->RxXferCount == 0U)
    {
      SPI_CloseRxTx_ISR(hspi);
    }
  }
 else {
  __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE )); // Code added to fix the issue
 }
}

static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
{
  /* Receive data in 16 Bit mode */
  *((uint16_t*)hspi->pRxBuffPtr) = hspi->Instance->DR;
  hspi->pRxBuffPtr += sizeof(uint16_t);
  hspi->RxXferCount--;

  if(hspi->RxXferCount == 0U)
  {
#ifdef USE_SPI_CRC
    if(hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
      hspi->RxISR =  SPI_2linesRxISR_16BITCRC;
      return;
    }
#endif

    /* Disable RXNE interrupt */
    __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);

    if(hspi->TxXferCount == 0U)
    {
      SPI_CloseRxTx_ISR(hspi);
    }
  }
 else {
  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE ));// Code added to fix the issue
 }
}

Outcomes