cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WBxx spi HAL driver seems buggy when transmitting in 8 bit modes (not interrupt nor DMA driven).

LVers.1
Associate III

In STM32Cube_FW_WB_V1.12.1 the function HAL_SPI_Transmit() increase buffer point per sizeof(uint16_t) when sending data in 8 bits mode; this lead to 1 byte every 2 bytes not being send out. See the below snippet from HAL_SPI_Transmit()

/* Transmit data in 16 Bit mode */
  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
  {
    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
    {
      hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
      hspi->pTxBuffPtr += sizeof(uint16_t);
      hspi->TxXferCount--;
    }
    /* Transmit data in 16 Bit mode */
    while (hspi->TxXferCount > 0U)
    {
      /* Wait until TXE flag is set to send data */
      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
      {
        hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
        hspi->pTxBuffPtr += sizeof(uint16_t);
        hspi->TxXferCount--;
      }
      else
      {
        /* Timeout management */
        if ((((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
        {
          errorcode = HAL_TIMEOUT;
          goto error;
        }
      }
    }
  }
  /* Transmit data in 8 Bit mode */
  else
  {
    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
    {
      if (hspi->TxXferCount > 1U)
      {
        /* write on the data register in packing mode */
        hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
        hspi->pTxBuffPtr += sizeof(uint16_t);
        hspi->TxXferCount -= 2U;
      }
      else
      {
        *((__IO uint8_t *)&hspi->Instance->DR) = (*hspi->pTxBuffPtr);
        hspi->pTxBuffPtr ++;
        hspi->TxXferCount--;
      }
    }
    while (hspi->TxXferCount > 0U)
    {
      /* Wait until TXE flag is set to send data */
      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
      {
        if (hspi->TxXferCount > 1U)
        {
          /* write on the data register in packing mode */
          hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
          hspi->pTxBuffPtr += sizeof(uint16_t);
          hspi->TxXferCount -= 2U;
        }
        else
        {
          *((__IO uint8_t *)&hspi->Instance->DR) = (*hspi->pTxBuffPtr);
          hspi->pTxBuffPtr++;
          hspi->TxXferCount--;
        }
      }
      else
      {
        /* Timeout management */
        if ((((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
        {
          errorcode = HAL_TIMEOUT;
          goto error;
        }
      }
    }

See lines 39-41 and 58-60 above. The lines 64-66 seems correct (they handle the case when 1 byte remain in the buffer)

It seems HAL_SPI_TransmitReceive() is affected the same way.

This being said, I have correct this in my project, but of course the file gets overwritten every time i "generate code" from MX. What's the best way to avoid this ? To make the correction in the file inside the STM32Cube_FW_WB_V1.12.1 "repository" that is used by MX ?

Thanks,

Laurent

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

> hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);

> hspi->pTxBuffPtr += sizeof(uint16_t);

This is called data packing. It writes two bytes at the same time into the TXFIFO and increments the pointer by 2. It only does this when there are 2+ bytes to send and when there is room in the TXFIFO. I do not see a bug here.

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

View solution in original post

5 REPLIES 5
TDK
Guru

> hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);

> hspi->pTxBuffPtr += sizeof(uint16_t);

This is called data packing. It writes two bytes at the same time into the TXFIFO and increments the pointer by 2. It only does this when there are 2+ bytes to send and when there is room in the TXFIFO. I do not see a bug here.

If you feel a post has answered your question, please click "Accept as Solution".
LVers.1
Associate III

Thanks a lot for your answer. You are correct, my problem was somewhere else.

I would have expect the FIFO to be filled by consequent 8 bits write to the DR registers but indeed I now see the reference to "data packing".

As a side note, any pointer where i could find a datasheet about the SPI peripheral of the STM32WB family ? All i could find is a power point presentation (https://www.st.com/content/ccc/resource/training/technical/product_training/group0/34/7d/28/20/b4/bc/47/69/STM32WB-Peripheral-Serial-Peripheral-interface-SPI/files/STM32WB-Peripheral-Serial-Peripheral-interface-SPI.pdf/jcr:content/translations/en.STM32WB-Peripheral-Serial-Peripheral-interface-SPI.pd...)

Wish you a nice day,

Laurent

TDK
Guru

> As a side note, any pointer where i could find a datasheet about the SPI peripheral of the STM32WB family ?

The reference manual (not the datasheet) is the best source of information on how the chip works and will include details on the SPI peripheral:

https://www.st.com/en/microcontrollers-microprocessors/stm32wb55rg.html#documentation

https://www.st.com/resource/en/reference_manual/rm0434-multiprotocol-wireless-32bit-mcu-armbased-cortexm4-with-fpu-bluetooth-lowenergy-and-802154-radio-solution-stmicroelectronics.pdf

If you feel a post has answered your question, please click "Accept as Solution".
LVers.1
Associate III

Thanks a lot, that's the document i was indeed looking for.

Sorry for looking dumb ... i'm coming from the low end 8/16 bits world where C is just another way to write assembler 🙂

TDK
Guru

No need to apologize. As long as you post well written question, I'm happy to answer them.

The reference manual / datasheet difference often trips up new users.

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