cancel
Showing results for 
Search instead for 
Did you mean: 

Bug in SPI Transmit ?

anio1491
Associate II

Dear ST-Team,

I am using the HAL SPI driver (v1.11.0) on an STM32L072 in blocking mode, 8-bit data size and calling HAL_SPI_Transmit. After some calls, the assert fails because the buffer I am calling it with has a non 16-bit aligned address.

I think the bug might be in line 757, in stm32l0xx_hal_spi.c, in this if:

if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || ((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (Size > 1U)))

and should be replaced with the following:

if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)

, as the next statement (the assert check) should be done only if the driver is used in the 16-bit mode.

Please let me know if this is a bug or am I getting it wrong.

Regards,

Andreea

7 REPLIES 7
Imen.D
ST Employee

Hello @anio1491​ ,

Thanks for reporting this issue. We will check this internally and come back to you with update.

Kind Regards,

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
Fran Buck
Associate II

I think that the condition should be

if ( ( hspi->Init.DataSize == SPI_DATASIZE_16BIT ) 

Version 1.11 has many spots with the condition:

|| ((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (Size > 1U))

Bob S
Principal

This is a common optimization in the HAL library. It uses 16-bit writes to the DR as long as there are at least 2 bytes left in the buffer. This reduces the number of writes, and reduces any delays between bytes on the SPI bus. However, it does require that the data buffer be aligned on a 16-bit boundary, as you've seen. The GCC compiler appears to force alignment of arrays to 32-bit boundaries (at least when compiling for the 32L4xx series). So I'm guessing you hit this when you pass a buffer pointer that isn't at the beginning of the buffer's allocated memory. For example:

MyFunc()
{
   uint8_t buf[50];  // buf[0] SHOULD be aligned to 32-bit address
 
   ... fill 11 bytes in buf[] starting at [0]
  HAL_SPI_Transmit( hspi1, buf, 11, 5000 );  // Send 11 bytes, works OK
 
   ,.. Append more data in buf[11] to buf[20]
   HAL_SPI_Transmit( hspi1, &buf[11], 10, 5000 );  // Fails, not aligned
}

Thanks!

I understand the reasons of the assertion and the missaligment issue for the SPI_DATASIZE_16BIT option (I had many with my M0+ core). Is just that the HAL seems to treat the 2 transfer options separately within the HAL_SPI_Receive function.

/* Receive data in 8 Bit mode */
if ( hspi->Init.DataSize == SPI_DATASIZE_8BIT )
{
   ...
}
else
{
   ...
}

Sorry - this slipped off my radar...

The receive function has to treat 8-bit and 16-bit data sizes differently. For 16-bit transfers, it reads 16 bit data from the SPI DR, and it uses the data buffer pointer as if it were a pointer to 16-bit data. For 8-bit transfers, it reads 8 bit data from the SPI DR and uses the data buffer pointer as if it were a pointer to 8-bit data.

S.Ma
Principal

Hmmm... why optimize bus access if it pushes the 16 bit alignment constrain up the application level?

sending 1 byte by SPI will take 16+ SYSCLK so we are talking optimizing 1 cycle over 32+

If the communication is polling (blocking), it's just not worth the complexity?

Newer STM32 have FIFO HW in the SPI to solve partially this "limitation" such as in the STM32L496.

Imen.D
ST Employee

Hello,

We confirm issue on L0 as SPI IP vesion is not supporting the data packing. So, in this particularity case, we can just check alignment when data size is equal to 16bit.

On STM32F0, who is also using a cortex M0, this assert cannot be modify as SPI IP version is not the same and Data packing is used. So even if we are in 8 bit, a 16bit transfer is performed for Performances.

Best Regards,

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen