2022-10-12 01:34 PM
Hello.
I have noticed a SCK clock error on the SPI bus in the STM32H730 processor. It may be due to the HAL library I am using (v1.10.0).
My SPI configuration (SPI2 in this case) in CubeMX:I use SPI in Polling Mode. I send 8 bits of data using the function: HAL_SPI_TransmitReceive(). The SPI clock is relatively small (about 6kHz).
The problem is that the last clock lasts much shorter than the other seven, as shown by the SCK line dump from the oscilloscope:
The probable cause of this behavior may be the implementation of the HAL_SPI_TransmitReceive() function. File stm32h7xx_hal_spi.c, line 1217.
This function, after copying and reading data to/from the SPI registers in a while() loop, waits for the EOT flag in the SF register to be reset.
Immediately after resetting the EOT flag, the SPI_CloseTransfer(hspi) function is called, which shuts down the entire SPI module. I think that disabling the SPI module at this point may be the reason for the short duration of the last clock tick. The second possibility is that the EOT flag is not in the high state at all.
For testing purposes, I added a 1ms delay in the program code between waiting for the EOT flag to reset and calling the SPI_CloseTransfer(hspi) function.
This delay caused the last clock to take the same amount of time as the other seven. Unfortunately, after rebuilding and re-generating the project in CubeMX, my piece of code was removed from the function.
Is it possible to configure the SPI module in such a way as to work around the above problem?
Is the error actually due to the SPI driver implementation in the HAL library?
Could the error be due to poor handling of the EOT flag in the SR register?
Best regards, Kuba.
2022-10-12 08:08 PM
The full completion of an spi transaction is by monitoring the rxne flag, which tells that the last incoming data bit has been acquired.
TXE monitoring only tells that data can be preloaded in the shift register, hardly connected to what happens on the wired bus on the board....
2022-10-13 05:01 AM
The error is caused by incorrect implementation of the function: SPI_WaitOnFlagUntilTimeout() in the file stm32h7xx_hal_spi.c, line 3827:
The function call (in the HAL_SPI_TransmitReceive() function) is as follows:
So the function should wait in the while() loop until the EOT flag is cleared. This doesn't happen, because the condition that is checked in the while() loop from the beginning is false, so the function skips the while() loop and returns Status HAL_OK.
The EOT flag is in a high state (logical 1), while the Status variable is a logical zero. Hence 1 != 0, so the lines of code in the while() loop will not be executed.
The solution is to change the while() loop condition as follows (EOT flag different from Status):
while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != Status)
After this change, the last clock bar takes the same amount of time as the other seven.
2022-10-13 05:45 AM
> So the function should wait in the while() loop until the EOT flag is cleared.
No. End of transfer is indicated by hardwer by *setting* SPI2S_SR.EOT, see SPI2S_SR register description in RM.
JW
2022-10-13 05:51 AM
Sorry, my mistake, you are right.
So my solution does not make sense here. However, the problem with the clock is quite serious, do you have any idea how it can be solved?
2022-10-13 06:30 AM
Well, maybe just don't switch off SPI at the end of transfer. Or use the RXNE flag as . suggested above.
But maybe the EOT flag is OK - did you verify it's zero at the beginning of transfer? Do you clear it (using the method described in RM) after transfer ends?
Using Cube/HAL is no excuse - it's your program, your responsibility. Maybe you just don't call the Cube/HAL function in a way its authors envisaged.
I don't use 'H7 nor Cube.
JW