STM32U5 SPI slave (hardware NSS) ends the transaction early when SPE is set while the master clocks another slave
- October 8, 2026
- 0 replies
- 16 views
Hello,
on a shared SPI bus (one master, several slaves, one NSS line per slave, the "Standard multislave communication" topology of RM0456 §68.4.5), an STM32U5 SPI slave with hardware NSS sometimes ends a transaction early. EOT is raised 112 or 126 bytes (frames) before TSIZE, with no UDR, OVR, MODF or FRE flag. The slave then stops driving MISO, so the master receives the last ~110 bytes as 0x00, while on the slave the HAL reports a normal "transfer complete". The data corruption is silent.
When it happens
Each slave prepares its next transfer on its own, with HAL_SPI_TransmitReceive_DMA, which sets SPE as its last step, and then raises a "ready" GPIO for the master. So the call sometimes falls while the master is clocking another slave: this slave's NSS is high and SCK is toggling. That is the only case in which the failure appears.
- With only one slave active (no foreign traffic on SCK) it never happens.
- It is the instant SPE is set that matters, not the DMA setup. Our workaround: prepare the transfer as the HAL does but without SPE, wait for ~2 µs of idle SCK, set SPE, check SCK again (abort and retry if it moved), and only then raise "ready". With it we saw 0 failures in more than one million transactions.
RM0456, "Enabling the SPI" (Rev 5 §68.4, p. 2905; Rev 7 §68.4.11, p. 2919), says:
"there is no impact if the configuration and enabling procedure is done while a traffic is ongoing on the bus, assuming that the SS signal is managed by hardware at slave"
What we observe
We first saw this on our application board (STM32U585, revision X, SCK 10.67 MHz, three slaves). Points marked [A] were measured there; the rest on the NUCLEO setup below.
- EOT always comes at the same distance from the end: 112 or 126 bytes before TSIZE, for TSIZE = 512, 1024 and 2048 (113 or 100 bytes on [A]).
- On the slave the RX side looks complete: the RX GPDMA channel still performs all TSIZE transfers. An RX buffer pre-filled with a guard value is overwritten up to the last byte, with 0x00 after the break point [A]. The only sign of the failure on the slave is that the TX GPDMA channel still holds undelivered bytes at EOT; this is how our firmware detects it.
- The HAL does not abort that TX channel, so every later
HAL_SPI_TransmitReceive_DMAfails until the channel is aborted by software. - The DMA is not involved: with SPE set during foreign traffic and the FIFOs serviced by the CPU (no DMA, no SPI interrupts), EOT still comes early [A].
Figure 1 is a logic analyzer capture of a failing transaction [A]: SPE is set during another slave's transfer, and this slave's own transfer then stops at byte 911 of 1024.

Reproduction on NUCLEO boards (projects attached)
- Slaves: 2 × NUCLEO-U575ZI-Q, STM32U575 revision X (DBGMCU_IDCODE 0x20016482), same firmware (SPI_slave_minimal). SYSCLK 128 MHz from HSI16. SPI1 slave, 8 bit, mode 0, hardware NSS on PA4, FIFO threshold 1, GPDMA1 ch14 TX / ch15 RX. Every 2 ms:
HAL_SPI_TransmitReceive_DMAof 1024 bytes (byte i = i), then the ready GPIO goes high. - Master: NUCLEO-U5A5ZJ-Q (SPI_master_minimal). SPI1 master mode 0 at 10 MHz, NSS by GPIO (one per slave), bytes back to back. It serves the slave whose ready line is high and checks every received block.
- VDD = 1.8 V on all three boards (JP4 on [2-3]). Wiring in figure 2.
- STM32CubeMX 6.18.1, STM32CubeU5 1.9.0, STM32CubeIDE (Debug configuration).

| TSIZE 1024, SCK 10 MHz | transactions | failures |
|---|---|---|
| two slaves (14 min) | 830 012 | 2 188 (0.26 %) |
| the other slave held in reset (no foreign traffic) | 30 704 | 0 |
That is about one failure per second per slave, so it shows up within seconds.
ES0499 Rev 12: none of the SPI errata seems to match.
How to run
- Import both projects in STM32CubeIDE, build, flash SPI_master_minimal to the NUCLEO-U5A5ZJ-Q and SPI_slave_minimal to both NUCLEO-U575ZI-Q.
- Wire as in figure 2. Start (or reset) the master first, then reset the two slaves, so all counters start clean.
- Open the three ST-LINK virtual COM ports at 115200 baud. Each board prints one line per second. The firmware labels are in Italian:
- slave:
blocchi 70332 errori 134 (resto 96) errori_hal 0 arming_falliti 0means transactions, early EOTs, TX bytes still undelivered at the last early EOT, HAL error callbacks, failedHAL_SPI_TransmitReceive_DMAcalls. - master:
s0 133/70500 (912,112) sf 0 | s1 179/71800 (898,126) sf 0 | hal 0means, per slave, corrupted blocks / blocks, (first wrong byte, number of wrong bytes) of the last corrupted block, blocks after which the slave did not end the transfer; then HAL errors.
- slave:
- Optional, for a logic analyzer: on each slave PD5 (CN11-41) is high while a transfer is armed, and PD6 (CN11-43) toggles at each early EOT.
Questions
- Are we missing something, or is this use within what RM0456 specifies for a slave with hardware NSS on a multi-slave bus?
- Is this a known issue of silicon revision X? Is it fixed in revisions W or U?
Attachments: SPI_master_minimal.zip, SPI_slave_minimal.zip (STM32CubeIDE projects; code comments are in Italian), figure 1 (EOT sequence), figure 2 (NUCLEO wiring).
Thanks.
