Skip to main content
Byann.1
Associate II
September 29, 2026
Question

STM32H757 system bootloader (SPI2) never sends ACK

 Summary

We program a slave STM32H757 through its system bootloader over SPI (AN4286), driven by a second STM32H757 acting as SPI master. About 20 % of our production boards cannot be programmed: after the 0x5A synchronization byte, the bootloader returns the byte 0xA5 on every poll and never 0x79 (ACK) or 0x1F (NACK). The other 80 % of the boards are programmed reliably with exactly the same master firmware.

Bootloader version (0x91), device ID (0x450) and silicon revision (Rev V) are identical on working and failing boards. The failing boards are otherwise fully functional: firmware loaded through JTAG/SWD runs normally on them. Register dumps taken through SWD show that the bootloader has selected SPI2 and is running, but that the SPI2 slave is in TX underrun (SR.UDR = 1) on failing boards and not on working boards.

 

Hardware configuration

Item Value
Slave device STM32H757XI , device ID 0x450, Rev V, bootloader V9.1 (0x91) (identical on working and failing boards)
Slave clock 25 MHz crystal on HSE (PH0/PH1)
Slave supply VDD = 3.3 V; SMPS configuration
Slave option bytes original options bytes
Boot control BOOT0 driven by the master (push-pull GPIO); NRST driven by the master (push-pull GPIO with internal pull-up, not open-drain); PDR_ON is not driven by the master (no power-on reset possible by software)
SPI link, slave side SPI2: PI0 = NSS, PI1 = SCK, PI2 = MISO, PI3 = MOSI (SPI2 is the only SPI clock enabled in RCC during the failure)
Master device STM32H757, firmware running on the CM4 core
SPI link, master side SPI4: PE11 = NSS (software GPIO, push-pull, no pull), PE12 = SCK, PE13 = MISO, PE14 = MOSI (AF5, medium speed, no pull)
SPI settings Master, full duplex, 8-bit, MSB first, CPOL = 0, CPHA = 0 (mode 0), no CRC, FIFO threshold 1 data, no inter-data idleness, NSS active low
SPI clock Kernel clock HSI 64 MHz, prescaler /8, SCK = 8 MHz (4 MHz and 2 MHz also tested)
Logic level 3.3 V (scope: MISO high level about 3.3 V on a working board)
Wiring Board-level traces, one master and one slave, no other device on the SPI nets

Boot and synchronization sequence (master side)

  1. BOOT0 = 1.
  2. NRST low for 300 ms, then NRST high.
  3. Wait 60 ms (160 ms also tested). AN2606 gives 53.975 ms as the startup time for STM32H74x/75x.
    • NSS low, held for the whole frame (AN4286 figure 3):send 0x5A;
    • wait at least 10 µs, then poll with 0x00 bytes, at least 10 µs apart, for up to 5 ms, checking every received byte;
    • on 0x79, send 0x79 (Get ACK procedure, AN4286 figure 2). On 0x1F the procedure ends.
  1. NSS high.
  2. If no ACK: repeat step 4 up to 200 times, then repeat the whole sequence (new reset) up to 4 times, so up to 800 synchronization attempts per power-up.

 

Pseudo-code of the exchange:

NSS_LOW();tx = 0x5A;  spi_txrx(&tx, &rx);          // rx not useddo{  delay_us(10);                          // AN2606: 10 us SPI connection, 8 us between bytes  tx = 0x00;  spi_txrx(&tx, &rx);} while ((rx != 0x79) && (rx != 0x1F) && (elapsed < 5 ms));if (rx == 0x79) { delay_us(10); tx = 0x79; spi_txrx(&tx, &rx); }NSS_HIGH();

Observed behaviour

  • Working boards (about 80 %): 0x79 is received and programming works every time.
  • Failing boards (about 20 %): the master reads 0xA5 on every poll, indefinitely. Never 0x79, never 0x1F. Not a single ACK in 800 attempts per power-up.
  • The failure is reproducible per board. Two failing boards were analysed in detail (including one named Board028).
  • Rare exceptions: on one failing board, programming succeeded once during a series of tests and then never again. Another failing board started working spontaneously for some time, and now fails again one month later with the same symptom (0xA5, no ACK).
  • The problem does not depend on the SPI frequency (8, 4 or 2 MHz), on the master firmware timing, or on temperature (hot air had no effect).
  • X-ray inspection of a failing board shows no visible defect.

What we tried

# Test Result
1 Sync loop re-sending 0x5A (our original code) replaced by one 0x5A followed by 0x00 polls, as per AN4286 No change
2 AN2606 timings (10 µs after 0x5A, at least 8 µs between bytes). Also single-stepping with the debugger, which gives delays of milliseconds to seconds between bytes No change. Still 0xA5, no ACK
3 SCK 8 MHz, 4 MHz, 2 MHz, with slow GPIO edges (low speed setting) No change. SR.UDR stays 1 on failing boards
4 Internal pull-down on master SCK; master MasterKeepIOState (AFCNTR) enabled No change
5 NSS held low over the whole frame versus one NSS frame per byte. With NSS low and the HAL disabling SPI4 between bytes, we saw the idle pattern read back bit-shifted (0x4B, 0x96), meaning extra SCK edges Fixed by AFCNTR or by NSS per byte: 0xA5 is then read correctly aligned, but still no ACK
6 Delay after NRST release 160 ms versus 60 ms; up to 800 synchronization attempts per power-up No ACK
7 Master stopped for 1 s (debugger halt) inside the frame, then one more poll Still idle pattern, no ACK
8 Hot air on the board No change
9 X-ray of a failing board Nothing visible
10 Slave test program flashed through JTAG that logs the state of all bootloader interface pins (USART, I2C, FDCAN, SPI, USB): pull-up / pull-down probing and activity Identical on working and failing boards; all other interfaces' RX pins are floating on both. Limitation: run in application mode, not during the bootloader detection window. PA3 (USART2_RX) has an external 100 kΩ pull-down
11 Register dumps of the slave through SWD hot-plug (STM32CubeProgrammer) on working and failing boards See section 6
12 Bootloader version and device ID Identical: V9.1 (0x91), ID 0x450, Rev V

 

Register evidence (slave, SWD hot-plug, bootloader running)

Working board versus failing boards (two failing boards, same result):

Register Working board Failing boards
RCC peripheral clocks only SPI2 enabled only SPI2 enabled
SPI2 CR1 (SPE, SSI), CFG1, CFG2, IER (0x320) same same
SPI2 UDRDR 0xA5A5A5A5 0xA5A5A5A5
SPI2 SR 0x0000 (0x1002 during detection phase), UDR = 0 0x1022, UDR = 1
DMA1 LISR 0 0x40 (FEIF1, FEIE = 0)
NVIC ISPR1 0 0x10 (IRQ 36, SPI2, pending)
SCB ICSR 0 0x00400000 (ISRPENDING)
CFSR / HFSR 0 / 0 0 / 0 (no fault; VECTACTIVE = 0)

 

Additional observations on the failing board:

  • SPI2 TX is fed by DMA1 Stream 1 in circular mode (S1CR = 0x0002055F, NDTR = 20, PAR = SPI2_TXDR, M0AR = 0x24000790, DMAMUX1_C1CR = 0x28), reading a 20-byte buffer filled with 0xA5. No 0x79 is present in the buffer.
  • The CPU is not in a fault, and interrupts are not being serviced for SPI2 (UDR flag and pending IRQ remain set).

Caveat: all dumps were taken with a debugger attached in hot-plug mode, which halts the core.

 

Related link

SPI Bootloader Synchronization Issue | Community

ROM Bootloader - only responds with 0xA5 | Community

STM32L496 SPI Bootloader fails to synchronize | Community

STM32G473 system bootloader responds with 0xA5 continuously on SPI1 | Community

 

Some topics already spoke of this problem but I didn’t found a solution that is working for me. Do you have any ideas of more tests to do in order to find the root cause? Do you know a solution or a workaround on this problem?

Thanks in advanced for your help

 

3 replies

TDK
September 29, 2026

Probably another bootloader interface was activated so it’s no longer monitoring SPI2 anymore. Look at other active pins that the bootloader listens to. Post schematic.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Byann.1
Byann.1Author
Associate II
September 30, 2026

Thank you for the suggestion. We looked at this early on, and the evidence says the bootloader is still on SPI2.

1. The bootloader has selected SPI2 and kept it.
We attached to the running slave over SWD (hot-plug) on a failing board. In RCC, only the SPI2 clock is enabled. The USART, I2C, FDCAN and USB clocks are off. SPI2 is configured as a slave (mode 0, hardware NSS) with its TX fed by DMA1 Stream 1 in circular mode. The bootloader is not faulted and is executing normally. This matches the interface selection flow in AN2606 (Figure 60), where the other interfaces are de-initialized once one is detected.

2. The slave is listening on SPI2 and answering, but the answer is wrong.
After 0x5A it returns 0xA5 on every poll, forever. SR.UDR is 1 on failing boards and 0 on working boards. The SPI2 TX DMA buffer contains 20 bytes of 0xA5, with no 0x79 in it.

3.Here is the schematic on slave

 

Byann.1
Byann.1Author
Associate II
October 6, 2026

Update: root cause found and fixed. 

**Symptom**

STM32H757 (dual core, Rev V, system bootloader V9.1 / 0x91), programmed through the ROM bootloader on SPI2 (PI0..PI3, mode 0, 8 MHz). On about 20 % of our boards the bootloader answers 0xA5 to every poll, forever, and never sends the ACK (0x79). The failure is repeatable per board. Slower SCK, AN2606 timings, NSS handling, retries, temperature and pull resistors had no effect, and all the other bootloader interfaces' pins looked identical on good and bad boards.

**Root cause**

With BOOT0 = 1 the Cortex-M4 also starts, from BOOT_CM4_ADD1, which defaults to 0x10000000 (SRAM1). SRAM1 is not initialised, so its content after power-up is random. It is also specific to each chip: two power cycles on the same failing board gave dumps that differed by only 5.6 % of the bits. That is why the failure is board-dependent and repeatable.

On our failing board the CM4 reads an invalid vector table (initial SP in non-RAM space, Reset vector 0x44C78104 with the Thumb bit clear), faults, and locks up. In that state the ROM bootloader running on the CM7 detects the SPI2 synchronisation but never loads the ACK. SPI2 sits in TX underrun (SR.UDR = 1) and only the 0xA5 filler is sent. ST confirmed that this is a new limitation, which will be added to AN2606: non-controlled SRAM content can prevent the bootloader from working over SPI2.

Dumping SRAM1 over SWD and decoding its first words is a quick way to check a suspected board.

**Solution (confirmed on our boards)**

Stop the CM4 from booting in bootloader mode. Either:

- clear BCM4 (bit 22 of FLASH_OPTSR_PRG), as recommended by ST. The CM7 application then starts the CM4 when needed with HAL_RCCEx_EnableBootCore(RCC_BOOT_C2); or

- point BOOT_CM4_ADD1 to an erased flash area (we used 0x081F0000, the last 64 KB of bank 2). The CM4 locks up in the same way on every board, so the behaviour is deterministic. Do not point it to an area that holds a valid CM4 image.

Both can be written from the CM7 application (HAL_FLASHEx_OBProgram) or with STM32CubeProgrammer over SWD:

STM32_Programmer_CLI -c port=SWD mode=UR -ob BCM4=0

Note that BOOT_CM4_ADD1 in the HAL takes the full address (0x081F0000), not the shifted value.

**Limits**

- This has to be done once per device. Boards that already fail cannot be fixed through the bootloader (AN2606 says CM4_BOOT_ADDx cannot be programmed by the bootloader in dual-core), so they need SWD/JTAG once. 

If you see "0xA5 but never 0x79" on an STM32H745/H747/H755/H757, check what BOOT_CM4_ADD1 points to.