Skip to main content
Dub Bartolec
Associate III
October 29, 2020
Question

STM32H7xx - Serious Bug in SPI Driver HAL Version 1.3.0, 1.7.0 and 1.8.0

  • October 29, 2020
  • 7 replies
  • 4326 views

We were experiencing strange crashes originating from HAL_SPI_TransmitReceive and HAL_SPI_Receive when operating in SPI Slave mode.

Issue is that STM32 HAL code is not handling cases for 8 bit SPI Transfers correctly causing overflow of user buffers and corruption of stack or heap.

Here is simplified example of code:

uint8_t txData[4];

uint8_t rxData[4];

HAL_SPI_TransmitReceive(hspi, txData, rxData, 4, HAL_MAX_DELAY);

On some occasions function will increment rxData pointer past its size of 4 bytes and will copy SPI data to memory that was not designated to be written. In above case stack will be overwritten.

Bug is in function HAL_SPI_TransmitReceive() and HAL_SPI_Receive and it is in the block that handles 8 bit transfers:

/* Receive data in 8 Bit mode */
 else
 {
 /* Transfer loop */
 while (hspi->RxXferCount > 0U)
 {
 /* Check the RXWNE/FRLVL flag */
 if (hspi->Instance->SR & (SPI_FLAG_RXWNE|SPI_FLAG_FRLVL))
 {
 if (hspi->Instance->SR & SPI_FLAG_RXWNE)
 {
 *((uint32_t *)hspi->pRxBuffPtr) = *((__IO uint32_t *)&hspi->Instance->RXDR);
 hspi->pRxBuffPtr += sizeof(uint32_t);
 hspi->RxXferCount-=4;
 }
 else if ((hspi->Instance->SR & SPI_FLAG_FRLVL) > SPI_FRLVL_QUARTER_FULL)
 {
 *((uint16_t *)hspi->pRxBuffPtr) = *((__IO uint16_t *)&hspi->Instance->RXDR);
 hspi->pRxBuffPtr += sizeof(uint16_t);
 hspi->RxXferCount-=2;
 }
 else
 {
 *((uint8_t *)hspi->pRxBuffPtr) = *((__IO uint8_t *)&hspi->Instance->RXDR);
 hspi->pRxBuffPtr += sizeof(uint8_t);
 hspi->RxXferCount--;
 }
 }
 else
 {
....
...
}
 

It actually occurs that E.g. we are expecting 4 bytes, but master sends more than 4 bytes and by the time we poll SPI buffer we have:

  1. 1 byte in FIFO
  2. Code reads byte and decrements RxXferCount so its value is now 3.
  3. Another 4 bytes arrive to SPI FIFO
  4. At this point code reads 4 bytes into buffer as it runs if (hspi->Instance->SR & SPI_FLAG_RXWNE) condition. At this point corruption has already occured as only 3 bytes were requested by caller of the function.
  5. Code then subtracts 4 from RxXferCount and count is now 0xFFFF,
  6. The rest is now in a hands of master. If master sends more data if there is no timeout set it will copy up to 0xFFFF bytes into RAM causing catasrophic failure of the program.

This is very easy to reproduce.

Can someone from STM development team review this code and let us know what the next step should be ?

This topic has been closed for replies.

7 replies

Pavel A.
October 29, 2020

While you're waiting for useful answers - please note that version 1.3 is old. The current version is 1.9. Read the changelog to see what was changed for SPI:

https://htmlpreview.github.io/?https://github.com/STMicroelectronics/stm32h7xx_hal_driver/blob/master/Release_Notes.html

-- pa

TDK
October 29, 2020

For HAL_SPI_TransmitReceive, I don't see how it can be receiving more bytes than it sends. And it only sends the exact number of bytes you specify.

For HAL_SPI_Receive, it appears the bug is still in the current code. Note that this is only used when SPI is used in slave mode or in half duplex.

https://github.com/STMicroelectronics/STM32CubeH7/blob/master/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_spi.c#L1098

And since RxXferCount is unsigned, it'll overflow and you'll try to receive 2^32 bytes which clearly won't work.

Didn't reproduce but seems like an issue if your CPU doesn't keep up with the data.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Dub Bartolec
Associate III
October 29, 2020

Hi @Pavel A.​

One release not in 1.9.0 suggest that something has been fixed.

Question is ...

How to obtain H7 HAL 1.9.0 as STM32CubeMX doesn't suggest it as upgrade when we try "Check For Updates".

Highest suggested version is 1.7.0 and problem is there too.

We are using Stm32Cube 5.6.1 because version 6.xx.x.x has bugs in generating FreeRTOS projects that renders our older projects unusable.

Dub Bartolec
Associate III
October 29, 2020

Hi @Pavel A.​ ,

I've verified on STM32 Cube

https://www.st.com/content/st_com/en/products/embedded-software/mcu-mpu-embedded-software/stm32-embedded-software/stm32cube-mcu-mpu-packages/stm32cubeh7.html

And highers publicly available H7 HAL is still only 1.7.0.

When will 1.9.0 be available to developers ?

Dub Bartolec
Associate III
October 29, 2020

Hi @Pavel A.​ 

I've checked latest version in GIT repository of H7 Cube and problem is there too.

Dub Bartolec
Associate III
October 29, 2020

Hi @TDK​ .

Thanks for looking into it.

As impossible as it looks we actually noticed that problem first on HAL_SPI_TransmitReceive() where receive portion would receive more bytes than it sent. This is possible and it actually occurs.

We should not be relying on MCU having to keep with data. Code in STM32 HAL SPI in its current form is wrong.

As the matter of fact, what is letting this code down is the fact that H7 is actually too fast and it jumps and processes first byte in SPI before second one is received. Once this is done RxXferCount = 3.

In the meantime 4 more bytes are pushed into SPI FIFO by SPI MASTER, that causes another decision to be executed RxXferCount -= 4 and that overflows to 0xFFFF.

It is actual serious bug that should be fixed by STM.

TDK
October 29, 2020

The latest STM32CubeH7 repo is here and also in the latest CubeMX:

https://github.com/STMicroelectronics/STM32CubeH7

This is version "1.8.0" as listed in CubeMX. However, the internal version macro is one minor version ahead (no idea why) and internal comments refer to it as version "1.9.0". Perhaps this is what Pavel A is referring to. This inconsistency was in all previous versions as well.

https://github.com/STMicroelectronics/STM32CubeH7/blob/master/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c#L52

"If you feel a post has answered your question, please click ""Accept as Solution""."
Dub Bartolec
Associate III
October 29, 2020

Hi @TDK​ ,

Thanks I checked it out and problem is still there.

We do not tend to use releases that are on GIT for production code as if we end up with an issue then STM refers us to use only officially available HALs from respective sites (https://www.st.com/content/st_com/en/products/embedded-software/mcu-mpu-embedded-software/stm32-embedded-software/stm32cube-mcu-mpu-packages/stm32cubeh7.html)

We use GIT versions only for testing and I've already verified that problem is there too. I was curious about that 1.9.0 version in which Release notes are stating that it was some change in SPI driver.

smati2
Associate II
February 23, 2023

Hi @Dub Bartolec​ ,

I am having basically the same issue. In our setup under STM32H743, the SPI is in Slave mode. It is bare metal (no RTOS). I am using HAL_SPI_TransmitReceive function. It all works fine until the need for receiving 32 bytes. I get about half of them and the rest are all zero and the call gets stuck in HAL_SPI_TransmitReceive and never returns. After seeing your post, I saw ver 1.11.0 was available on Git. So, I replaced my stm32h7xx_hal_spi.c and stm32h7xx_hal_spi.h with that version. It now actually receives the entire 32 bytes and the bytes are valid. However, it does not come out of the HAL_SPI_TransmitReceive routine. The transmitter thinks it needs to send more but TXP is not set so it gets stuck in that loop. I am doing 8 bytes transfers.

So, what was your temporary fix? Can you please share that so I could try it at my end?

BTW and FYI, if I replaced my drivers folder under my STM32CubeIDE ver 1.10.1 and compile, I run into multiple errors. They mostly have to do with core M7 and time stuff and that's why I only updated the SPI driver. I think I may need to get the latest STM32CubeIDE (Ver 1.11.2) and install the drivers through it to remedy the compilation issue. However, I don't think it would resolve my SPI issue and that's why I am hoping your temporary fix (if you can share it) will fix my issue for the time being.

Thank you.

S.Ma
Principal
February 26, 2023

For SPI Slave mode, on STM32L4 which uses the SPI version with 32 bit RX and TX FIFO, I use 4 wire mode SPI and use DMA channels in cyclic buffer mode. The issue is that when NSS goes up by master, the DMA TX job is to keep the FIFO full, so it is.... for the next transaction, which is the undesired application need. Remedy was to use SYS/RCC full reset of the SPI IP to flush the HW FIFO. That works. It is unfortunate to nuke a fly with an H-bomb, until someone find a gentler way to do it.