STM32U575 (NUCLEO-U575ZI-Q)
The STM32U575ZI (Arm Cortex-M33 with FPU, up to 160 MHz, 2 MB flash,
768 KB SRAM + 16 KB SRAM4) is LabWired's first STM32U5 target and the first
U5 part in the fleet. The port reuses the shared V2 register engines
(gpio/uart stm32v2, i2c stm32l4, spi stm32h5, timers,
ADC), and adds the U5-specific pieces the bring-up needs: the full U5 RCC
map (the stm32v2 RCC profile is U5-only — ICSCR1/2/3 0x08/0x0C/0x10,
CRRCR 0x14, CFGR1/2/3 0x1C/0x20/0x24, PLL1/2/3 blocks
0x28..0x48, CIER/CIFR/CICR 0x50..0x58, AHB1ENR 0x88, AHB2ENR1/2
0x8C/0x90, AHB3ENR 0x94, APB1ENR1/2 0x9C/0xA0, APB2ENR 0xA4,
APB3ENR 0xA8 plus the eight *RSTRs at 0x60..0x80, BDCR 0xF0,
CSR 0xF4), the U5 CR ready pairs (MSISRDY/HSI48RDY and PLL1/2/3
ready), clock: gates for every RCC-gated peripheral (RM0456 enable
bits, verified against the vendored SVD), and a CRS register-surface
model (CR/CFGR/ISR/ICR).
Fidelity: SIM-DERIVED. LabWired has no U575 bench part. Every reset value and behaviour is SVD / RM0456 / DS13736-derived, not a silicon capture — there is no
reg_oracle, no MMIO diff and no Renode differential (Renode master ships no STM32U5 platform; closest references arestm32wba52.replandstm32l552.repl, checked 2026-09-17). Promote to a silicon tier only when a real NUCLEO-U575ZI-Q is diffed over SWD.
Status at a glance
Live status: the table below is a hand-maintained snapshot. For the authoritative, auto-generated view see the chip conformance scoreboard and the tier-1 matrix.
| Aspect | Status |
|---|---|
| Chip yaml | configs/chips/stm32u575.yaml |
| System yaml | configs/systems/nucleo-u575zi.yaml |
| Example | examples/nucleo-u575zi/ (VALIDATION.md = runbook + evidence) |
| Reference firmware | crates/firmware-stm32u575-demo (Rust io-smoke), examples/nucleo-u575zi/board_firmware/ (stock STM32CubeU5 HAL, 160 MHz PLL1 + USART1 VCP + LD1 loop) |
| Validation | real CubeU5 HAL firmware runs in-sim (U575-HAL OK + BLINK n LD1=<0\|1>); stock Zephyr nucleo_u575zi_q hello boots (test_stm32u575_zephyr_survival); Arduino matrix L0–L8 (CI lane); Zephyr matrix L0–L3 (local run; no CI workflow yet); flash unlock→erase→program→flags pinned by the u575_flash tests over the committed chip yaml; unsupported-instruction audit 0/0/0 at 200k steps |
| Tier | sim-validated — reference-manual-derived, no silicon diff |
| Core type | Arm Cortex-M33 (TrustZone present in the core, factory-disabled per UM2883) |
Peripherals (from chip yaml)
| Peripheral | Base | Status | Notes |
|---|---|---|---|
| Cortex-M33 | — | ✅ modeled | Thumb-2 + FPU; RRX (ror #0) rotate-through-carry modeled in interpreter + JIT lockstep |
| RCC | 0x46020C00 | ✅ tested in-sim | stm32v2 is U5-only: full enable/reset block (AHB1/AHB2ENR1+2/AHB3/APB1ENR1+2/APB2/APB3 + RSTRs), ICSCR1/2/3, CRRCR@0x14, CFGR1/2/3, PLL1/2/3 blocks, CIER/CIFR/CICR, BDCR@0xF0/CSR@0xF4 (RMVF W1C), U5 CR ready pairs; per-peripheral clock: gates |
| PWR | 0x46020800 | ✅ tested in-sim | wba profile — VOSR ready + supply config for the 160 MHz bring-up |
| FLASH | 0x40022000 | ✅ tested in-sim | stm32u5 profile: ACR latency read-back + full non-secure program/erase controller (RM0456 §7) — NSKEYR/OPTKEYR unlock, NSCR PG/PER/PNB/BKER/STRT, NSSR EOP/WRPERR W1C, 2 × 1 MiB banks / 8 KiB pages, 128-bit quad-word program; option-byte OPTR storage |
| GPIOA–I | 0x42020000 | ✅ tested in-sim | stm32v2 MODER/AFR/ODR/BSRR; LD1 on PC7 |
| USART1 | 0x40013800 | ✅ tested in-sim | VCP console (PA9/PA10), IRQ 61 — Cube HAL + Zephyr + Arduino all use it |
| USART2–3, UART4 | 0x40004400.. | ✅ modeled | stm32v2; no VCP wiring on the board |
| LPUART1 | 0x46002400 | ✅ modeled | stm32v2 |
| I2C1–3 | 0x40005400 | ✅ tested in-sim | stm32l4 engine; INA219 @0x40 ACKs on I2C1 (Arduino L3, Zephyr L3) |
| SPI1–3 | 0x40013000 | ✅ tested in-sim | stm32h5 engine + declared pad_map: "stm32u5" (DS13737 Table 27); MAX31855 frame 0x01901600 over SPI1 (Arduino L4), pad edges scored by bus_visibility |
| FDCAN1 | 0x4000A400 | ✅ tested in-sim | Bosch M_CAN, register/reset-identical to the H563 file (SVD CREL 0x3214_1218, ENDN 0x8765_4321, 37 registers); 4 KiB window includes FDCAN1_RAM @ 0x4000_AC00 (+0x800, hardwired SRAMCAN layout); RCC_APB1ENR2.FDCAN1EN bit 9 gate (0xA0, SVD/RM0456 — not APB1ENR1); internal loopback (TEST.LBCK) runs Arduino L8 (LW_L8_OK) |
| TIM1/2/3/6/7 | 0x40000000 (TIM1: 0x40012C00) | ✅ modeled | TIM2 32-bit; TIM1 advanced/PWM; Arduino L6/L7 exercise the timer path |
| GPDMA1 | 0x40020000 | ✅ modeled | 16 channels (SVD map to 0x84C, 4 KiB window); CH0–7 IRQs 29–36 via irq_base: 29. The SVD puts CH8–15 on separate NVIC lines 80–87 — not routed yet |
| ADC1 | 0x42028000 | ✅ tested in-sim | stm32u5 map, SVD-verified: CFGR1.RES[3:2] = 14/12/10/8, PCSEL@0x1C, LTR1-3/HTR1-3@0xA8..0xBC (HTRx reset 0x01FF_FFFF), GCOMP@0x70, CALFACT2@0xC8, DR@0x40; Arduino L5 analogRead passes |
| RTC | 0x46007800 | ✅ modeled | rtc_v3 calendar |
| IWDG | 0x40003000 | ✅ modeled | |
| CRC | 0x40023000 | ✅ tested in-sim | Arduino core startup writes CRC->POL; the Arduino survival case pins the path |
| CRS | 0x40006000 | ⚠️ register surface | reset/writable fields + SWSYNC→SYNCOKF; no SYNC source, no trim loop |
| RNG | 0x420C0800 | ✅ modeled | seeded in-sim, not silicon-faithful |
| ICACHE | 0x40030400 | ⚠️ stub | declared so Cube HAL's HAL_ICACHE_Enable cannot bus-fault |
| DBGMCU | 0xE0044000 | ✅ modeled | IDCODE reset 0x30016482 per SVD |
| SysTick / NVIC | 0xE000E010 / 0xE000E100 | ✅ modeled | scheduler-backed counter; NVIC masking exercised by the matrices |
Flash / firmware artifacts
| Use | Artifact | Notes |
|---|---|---|
| Rust io-smoke | crates/firmware-stm32u575-demo (thumbv8m.main-none-eabi) |
built from source by strict_onboarding / the onboarding workflow |
| Vendor HAL | examples/nucleo-u575zi/board_firmware/build/u575_hal_smoke.elf |
stock STM32CubeU5 HAL checkout; not committed (build it locally) |
| Zephyr | stock hello_world for nucleo_u575zi_q (Zephyr 3.7.2) |
committed fixture tests/fixtures/stm32u575-zephyr-hello.elf |
| Arduino | PlatformIO stm32 core sketch ELF |
committed fixture tests/fixtures/stm32u575-arduino-serial.elf (L0 marker) |
Pins (NUCLEO-U575ZI-Q)
| Board label | MCU pin | Notes |
|---|---|---|
| LD1 (green) | PC7 | Arduino LED_BUILTIN (LED_GREEN = LED_LD1); led_watch: gpioc:7 in the matrix |
| LD2 (blue) | PB7 | |
| LD3 (red) | PG2 | |
| USER button | PC13 | |
| VCP TX/RX | PA9 / PA10 | USART1 (AF7), 115200 8N1 — CubeU5 COM1, Zephyr console, Arduino Serial |
| Arduino SPI | PA5/PA6/PA7 + PA4 NSS | SPI1; pad_map: "stm32u5" publishes SCK/MISO/MOSI onto the pads (NSS is AF5 but not routable) |
| Arduino I2C | I2C1 (default Wire) |
INA219 kit attaches at 0x40 |
| FDCAN1 | PB8 / PB9 | AF9 (RX/TX); alternates PA11/PA12, PD0/PD1, PF7/PF8 also AF9 (DS13737 Table 27, PlatformIO variant). Not on the Arduino headers — the L8 sketch uses internal loopback, so no pad is wired |
Known omissions / documented gaps
The chip yaml does not declare: TrustZone/GTZC/SAU enforcement
(factory TZEN=0, so the non-secure 0x0800_0000 alias is the boot path),
OCTOSPI/HSPI, USB OTG, ADC4, ethernet. Extra honest gaps:
- Flash program/erase is modeled (RM0456 §7, SVD-verified offsets): the
stm32u5profile keeps theACRlatency read-back the HAL polls and adds the non-secure controller —NSKEYR/OPTKEYRunlock (LOCK@NSCR.31, OPTLOCK@NSCR.30),NSCRPG/PER/PNB/BKER/STRT,NSSREOP/WRPERR/PGAERR/ PGSERR/SIZERR/OPTWERR as write-1-to-clear, 8 KiB page erase drained per instruction and filled with 0xFF, and 128-bit quad-word programming as four successive 32-bit stores (flash only flips 1→0). Remaining gaps: mass erase (MER1/MER2) is accepted but not applied, read-while-write is not enforced (flash routines need not run from SRAM in-sim), and program-over-not-erased commits the bitwise AND instead of raisingPROGERR. Option bytes are storage-only:OPTRreads back when written after the OPTKEYR sequence,NSCR.OPTSTRTcompletes with EOP, and no option reload/SWAP_BANKis applied to the backing store. - FDCAN1 is the only CAN instance: DS13737 lists "1 CAN FD controller", and
both the vendored SVD and ST's
stm32u575xx.hdeclare only FDCAN1, so there is nofdcan2at0x4000_A800. As with the H563 sibling, acceptance filtering, dedicated RX buffers and theFDCAN1_IT1(ILS line 1, NVIC 40) routing are not modeled — all enabled interrupts assert IT0 (NVIC 39) and loopback frames follow the model's fixed FIFO0 path. - SPI NSS is not routable: the
stm32u5AF table covers all SCK/MISO/MOSI rows for SPI1–3 (DS13737 Table 27), but the pad mechanism carries only those three signals, so PA4 (SPI1_NSS, AF5) and the other NSS alternates stay unrouted. Port-I alternates (PI1/PI2/PI3 = SPI2 SCK/MISO/MOSI, AF5) are not transcribed either: the router walks ports A–H only. - CRS has no SYNC source:
SWSYNClatchesSYNCOKF, but USB SOF/LSE synchronization and HSI48 trimming are not simulated. - ADC4 is not declared: the vendored SVD's ADC4 (0x46021000, IRQ 113) is a
different 12-bit class from ADC1 —
SMPR/AWDxTR/CHSELRMOD0/1, noPCSEL, noLTR/HTRpairs, noCALFACT2,CRreset 0 — so it is not a register-compatible sibling of the newstm32u5ADC1 map. ADC1 is fully modeled and exercised by Arduino L5 (analogRead). - GPDMA1 models all 16 channels; per-channel NVIC routing is
irq_base + n, so the SVD's CH8–15 lines (80–87) are not yet routed while CH0–7 (29–36) are. - Clock gating is modeled: every RCC-gated peripheral in the chip yaml
declares its RM0456 enable bit (and the RTC additionally its BDCR kernel
clock), so an unclocked register access reads 0 / drops the write.
IWDG, ICACHE and DBGMCU stay deliberately ungated — U5 has no RCC bus-enable
bit for them (IWDG is always-on LSI-clocked, ICACHE has only the sleep-mode
SMENRbit, DBGMCU is in the debug domain). - PLL2/PLL3 register blocks (
PLL2/3CFGR,PLL2/3DIVR,PLL2/3FRACR) and theirCRready pairs are modeled as storage/status — frequencies are not computed. - CFGR2/CFGR3 (AHB/APB prescalers + domain clock-disable bits) are plain storage; prescaler effects on peripheral timing are not modeled.
- CIER/CIFR/CICR (RCC clock-interrupt block) are storage + W1C; the RCC IRQ itself is not wired to the NVIC.
- CSR.RMVF is write-1-to-clear for the reset flags, matching RM0456.
Firmware that touches an undeclared window hits MemoryAccessViolation or
stalls in a polling loop; see
docs/getting_started_firmware.md.
What this catches (and what it cannot)
This target catches model regressions on the U5 boot path: PLL1/2/3 bring-up and ready-bit gating, RCC clock-enable gating (an unclocked peripheral reads 0 / drops writes), flash-latency sequencing, VOS/supply config, USART1 VCP bytes, GPIO output state, I2C device ACK/readback, SPI device frames, FDCAN internal-loopback ID/data, timer irq delivery, and CPU decode gaps — driven by three independent real firmware stacks (STM32CubeU5 HAL, upstream Zephyr, Arduino STM32 core). Because there is no bench part, it cannot catch a divergence from silicon that all three stacks happen to avoid, and no silicon-parity claim is made.
How to run
Run from the repo root.
# Rust io-smoke (builds firmware-stm32u575-demo, asserts "OK" on USART1)
labwired test --script examples/nucleo-u575zi/io-smoke.yaml
# Vendor CubeU5 HAL firmware (needs an STM32CubeU5 checkout; see
# examples/nucleo-u575zi/EXTERNAL_COMPONENTS.md)
make -C examples/nucleo-u575zi/board_firmware
labwired run --chip configs/chips/stm32u575.yaml \
--firmware examples/nucleo-u575zi/board_firmware/build/u575_hal_smoke.elf \
--max-steps 20000000
# → U575-HAL OK / BLINK 0 LD1=1
The hosted playground does not carry a U575 board id yet (the superproject's
BOARDS array has no U575 entry). The example directory is the supported
entry point: examples/nucleo-u575zi/README.md.
Related systems & examples
examples/nucleo-u575zi/VALIDATION.md— exact commands + captured evidence (io-smoke, HAL run, determinism diff, matrices, L3 negative control)examples/nucleo-u575zi/REQUIRED_DOCS.md— SVD hash, DS13736 / RM0456 / UM2861, BSP, Zephyr board docs, Renode findingcrates/core/tests/firmware_survival.rs—test_stm32u575_zephyr_survival/test_stm32u575_arduino_serial_survivalvalidation/arduino-matrix/andvalidation/zephyr-matrix/— the fidelity matrices (per-board outputs underout/<board>/, fleet scoreboards underdocs/coverage/)