2026-03-24 6:00 AM - last edited on 2026-03-24 6:45 AM by mƎALLEm
Hello,
I am working with STM32H750 and encountered an issue related to SPI communication in low-speed mode.
When operating SPI in low-speed (e.g. prescaler /128, ~195 kHz), I observed that:
The last SCLK high pulse becomes shorter than the others
This may affect correct sampling of the last bit on the slave side
This behavior seems consistent with Errata 2.22.6: "Truncation of SPI output signals after EOT event"
From the errata description and signal observation, it appears that:
The SPI peripheral is disabled too quickly after the EOT event
Since the CPU (PCLK domain) is much faster than SCK,
the last SCLK high period is truncated
To address this, I modified the HAL driver (stm32h7xx_hal_spi.c::SPI_CloseTransfer()) to introduce a short delay between EOT and SPI disable, only in low-speed conditions.
Instead of using a fixed delay, I implemented a minimal delay proportional to SCK period, to avoid unnecessary packet gap increase.
Below is the relevant modification:
/* Workaround for STM32H750 errata 2.22.6 */
if ((hspi->Init.Mode == SPI_MODE_MASTER) && (g_spi_kernel_clock_hz != 0UL))
{
uint32_t mbr = (READ_BIT(hspi->Instance->CFG1, SPI_CFG1_MBR) >> SPI_CFG1_MBR_Pos);
/* Apply only in low-speed case (/128) */
if (mbr == 6UL)
{
uint32_t prescaler = (1UL << (mbr + 1UL));
uint32_t sck_hz = g_spi_kernel_clock_hz / prescaler;
if (sck_hz != 0UL)
{
/* ~0.25 SCK period + small guard */
uint32_t wait_cycles = ((SystemCoreClock / sck_hz) / 4UL) + 6UL;
while (wait_cycles > 0UL)
{
__NOP();
wait_cycles--;
}
}
}
}
Notes:
The delay is intentionally kept short (~0.25 SCK period + margin)
It is applied only in low-speed mode to avoid impacting high-speed throughput
The kernel clock is provided externally via SPI_SetKernelClockFreq()
The behavior was validated using oscilloscope measurements
Does this approach align with ST’s intended workaround for errata 2.22.6?
Is it acceptable to use a fraction of SCK period (e.g. 0.25 cycle) instead of a full cycle delay?
Would ST recommend a more robust or standardized method for handling this (e.g. based on TXC/EOT timing or internal flags)?
Are there any known side effects of delaying before __HAL_SPI_DISABLE() in this way?
Any feedback or confirmation would be greatly appreciated.
Thank you.
2026-03-24 7:59 AM
Hello @nonoriri
This workaround is valid for your specific low-speed configuration, we cannot add it generically into the standard HAL driver because it may negatively impact performance and latency in other applications. For this reason, this modification should be applied on the application side.
2026-03-24 7:13 PM - edited 2026-03-24 7:16 PM
Hello @Saket_Om,
Thank you for your quick and helpful response!
Could you clarify what “application side” means in this context? Does it mean modifying our local copy of the HAL driver (e.g., SPI_CloseTransfer() in stm32h7xx_hal_spi.c), or should the delay be placed in the application layer above the HAL?
Since __HAL_SPI_DISABLE() is called internally inside SPI_CloseTransfer(), there is no way to insert the delay from the application layer. Doesn’t this workaround require modifying the HAL driver directly?
Thank you again for your support.