cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H750 SPI errata 2.22.6 workaround – validating delay before SPI disable in low-speed mode

nonoriri
Associate III

Hello,

I am working with STM32H750 and encountered an issue related to SPI communication in low-speed mode.

Issue description

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"

errata_2_22_6.png

Root cause understanding

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


Implemented workaround

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


Questions

  1. Does this approach align with ST’s intended workaround for errata 2.22.6?

  2. Is it acceptable to use a fraction of SCK period (e.g. 0.25 cycle) instead of a full cycle delay?

  3. Would ST recommend a more robust or standardized method for handling this (e.g. based on TXC/EOT timing or internal flags)?

  4. 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.

2 REPLIES 2
Saket_Om
ST Employee

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.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

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.