Add STM32C5 target (NUCLEO-C5A3ZG)#768
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds wolfBoot support for the STM32C5 family (validated on NUCLEO-C5A3ZG) by introducing a new STM32C5 HAL, a test application + linker script, example configuration, build/CI wiring, and target documentation.
Changes:
- Added STM32C5 HAL implementation and linker script (
hal/stm32c5.{c,h,ld}). - Added STM32C5 test app + build integration (
test-app/app_stm32c5.c,test-app/ARM-stm32c5.ld,test-app/Makefile,arch.mk). - Added docs + CI build coverage (
docs/Targets.md,.github/workflows/test-configs.yml,config/examples/stm32c5.config).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| test-app/app_stm32c5.c | New STM32C5 bare-metal test app exercising versioning + update trigger/confirm. |
| test-app/Makefile | Adds stm32c5 target flags + flash write-once define for test app builds. |
| test-app/ARM-stm32c5.ld | New test-app linker script template for STM32C5. |
| hal/stm32c5.ld | New wolfBoot linker script for STM32C5 memory layout. |
| hal/stm32c5.h | New STM32C5 register/memory map definitions and cache/reset helpers. |
| hal/stm32c5.c | New STM32C5 HAL: flash ops (quad-word/ECC), UART2, cache, clock init. |
| docs/Targets.md | Adds STM32C5 target documentation section + TOC entry. |
| config/examples/stm32c5.config | Adds an STM32C5 example config consistent with the described flash layout. |
| arch.mk | Wires stm32c5 target into ARM arch build settings. |
| .github/workflows/test-configs.yml | Adds CI matrix entry to ensure stm32c5 config builds. |
Comments suppressed due to low confidence (2)
test-app/app_stm32c5.c:1
numis sized for at most 3 digits + NUL, butwolfBoot_current_firmware_version()returns auint32_t. Versions >= 1000 will either overflownumor produce incorrect ASCII (e.g.,'0' + (v/100)whenv/100 > 9). Use a larger buffer and a bounded formatting approach (e.g.,snprintf) or explicitly clamp/handle higher versions.
/* app_stm32c5.c
test-app/app_stm32c5.c:1
- This file defines both active-high (
led_on/off) and active-low (led_active_low_on/off) control paths, but the rest of the test app uses only the active-low variants. Consider removing the unused active-high helpers (or aliasing the correct polarity via a singleled_on/offimplementation) to avoid confusion about the board’s LED polarity.
/* app_stm32c5.c
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Adds wolfBoot support for the STM32C5 family, validated on the NUCLEO-C5A3ZG (STM32C5A3ZGT6, Cortex-M33, no TrustZone, 1 MB dual-bank flash with 8 KB pages and 128-bit ECC quad-word writes).
hal/stm32c5.{c,h,ld}— flash (with per-quad-word ECC merging for unaligned writes), USART2 VCP, ICACHE, and a PSIS clock-up to 144 MHz (HSE 48 MHz reference -> PSI -> PSIS, all bus prescalers /1, flash 4 WS + WRHIGHFREQ delay 2). Mirrors STM32CubeMX's generatedmx_rcc_init()for this target.test-app/app_stm32c5.candtest-app/ARM-stm32c5.ld— LD2 (PG1, active-low) blink with v1 -> v2 update trigger and v2 confirm.arch.mkadds thestm32c5target,test-app/Makefileadds the per-target flags, and the example configs live atconfig/examples/stm32c5.configandconfig/examples/stm32c5-dualbank.config..github/workflows/test-configs.ymlbuilds three matrix entries on every PR — the default config, the same config withWOLFBOOT_RESTORE_CLOCK=0, and the dual-bank-swap config.STM32C5section indocs/Targets.md(flash layout, clock paragraph, build/flash/test instructions, dual-bank-swap variant, TZEN-not-supported note).Highlights
144 MHz clock-up.
clock_psi_on()brings SYSCLK from the post-reset HSIDIV3 (16 MHz) up to 144 MHz via the PSIS clock chain, mirroring the ST HAL bring-up sequence. Each polling loop has a generous timeout that, on failure, returns and falls back to the reset clock so the bootloader still runs (just slower); the SYSCLK-switch timeout also short-circuits the 144-MHz-onlyFLASH_ACR.WRHIGHFREQwrite so a stuck switch can't leave flash configured for a frequency the chip isn't actually running at.USART2_BRRis computed forPCLK1 = 144 MHzand resolves to 1250 exactly for 115200 baud.Lightweight
hal_prepare_boot()clock restore. WhenWOLFBOOT_RESTORE_CLOCKis set (project default inoptions.mk),hal_prepare_boot()switches SYSCLK back to HSIDIV3 before handoff but leaves PSIS, PSI and HSE running. The loaded firmware's ownclock_psi_on()then fast-paths through the HSE/PSI bring-up (everything already configured) and just bumps SYSCLK back to PSIS. This mirrors ST'sHAL_RCC_ResetSystemClock()rather than the fullHAL_RCC_Reset(). A full HSE/PSI tear-down was prototyped and works for the v1 boot loop (each cycle ends in a hardware reset) but breaks the swap-then-jump path where wolfBoot completes the partition swap, runsclock_psi_off(), and jumps directly into the loaded firmware without a reset between — the crystal does not always restart cleanly in that window. Hardware-tested bothWOLFBOOT_RESTORE_CLOCK=1(default) and=0end-to-end.Pre-clock-switch UART drain.
hal_prepare_boot()pollsUSART2_ISR.TCto make sure the TX shift register has fully emptied before the SYSCLK switch — otherwise the trailing byte of wolfBoot's last UART line was being shifted out at the wrong baud and showed up as a glitch byte at the start of the loaded firmware's first line.128-bit ECC writes.
hal_flash_write()always assembles 16-byte aligned quad-words from the caller buffer (two memcpys: read existing flash, overlay caller bytes), so every programmed quad-word is a complete ECC block. Sub-quad-word writes leave per-quad-word ECC undefined and reads come back with bit-flipped "corrected" data, so the merge step is mandatory. Errors from the FLASH controller (WRPERR / PGSERR / STRBERR / INCERR / OPTCHANGEERR) are checked after every program / erase and propagated as-1. The erase loop uses an end-exclusive bound so single-page erases actually run, andhal_flash_opt_lock()does not unconditionally triggerOPTSTRT(which would be a foot-gun on a function called*_lock).system_reset()preservesPRIGROUPand addsDSBbarriers so theSYSRESETREQwrite doesn't clobber unrelatedAIRCRfields and pending stores complete before reset.DUALBANK_SWAP variant (new,
config/examples/stm32c5-dualbank.config). Uses the chip'sFLASH_OPTCR.SWAP_BANKoption byte (bit 31) to flip which physical bank is mapped at0x08000000, replacing the copy-based swap with a single option-byte toggle and a system reset.hal_flash_dualbank_swap()readsFLASH_OPTSR_CUR.SWAP_BANK, toggles viaFLASH_OPTSR_PRG, kicksFLASH_OPTCR.OPTSTRT, and triggersSYSRESETREQ(no separateOBL_LAUNCHregister on this chip — the new bank mapping kicks in on the resulting reset).fork_bootloader()runs fromhal_init()on first boot and copies wolfBoot from bank 1 to bank 2 if they differ, so the chip can boot from0x08000000regardless of which physical bankSWAP_BANKcurrently maps there. Hardware-tested: stage v2 at0x08090000, reset, observeVersions: Boot 1, Update 2 -> Versions: Boot 2, Update 1, App version: 2, update OK -- success confirmed.TZEN is not supported on this silicon.
__SAUREGION_PRESENTis0in the CMSIS device header, no GTZC, noFLASH_NS_*/FLASH_SECCR*aliases, no secure peripheral address space — the hardware needed to partition memory and peripherals into secure / non-secure worlds is absent. The L5 / U5 / H5 TrustZone ports cannot be ported to the C5. For application security on the C5 use the MPU (__MPU_PRESENT 1U) and flash RDP. This is a deliberate roadmap close-out, documented indocs/Targets.md.Flash layout
Default (copy-based update,
config/examples/stm32c5.config):Dual-bank swap (
config/examples/stm32c5-dualbank.config):Default signing scheme is ECC256 + SHA256.