Add wolfBoot port for STM32N6 (NUCLEO-N657X0-Q)#720
Merged
Conversation
fedaf00 to
1416f2f
Compare
dgarske
requested changes
Mar 13, 2026
Member
dgarske
left a comment
There was a problem hiding this comment.
Great work! I haven't tested on hardware yet, but have looked over each line.
dgarske
requested changes
Mar 18, 2026
dgarske
previously approved these changes
Mar 18, 2026
4100805 to
cc789ae
Compare
cc789ae to
896c2a7
Compare
Member
|
@aidangarske how's this going? If you won't have time in the next week let me know and I can finish it up. |
6585a0b to
aa524f9
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 9 comments.
Comments suppressed due to low confidence (1)
src/boot_arm.c:519
do_boot()disables the CMSE/TZEN non-secure handoff path whenCORTEX_M55is defined (&& !defined(CORTEX_M55)). That means forstm32n6-tz.configwolfBoot will not setVTOR_NS/MSP_NSand will jump toapp_entryin the current security state instead of doing ablxns. This looks inconsistent with the STM32N6 TrustZone model (secure bootloader, non-secure app) and likely breaks the TZ configuration at runtime. The CMSE/TZEN branch should handle Cortex-M55 as well (or the docs/config should be adjusted to reflect that non-secure apps aren’t supported).
#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && \
defined(TZEN) && !defined(CORTEX_M55)
#include "hal.h"
#define VTOR (*(volatile uint32_t *)(0xE002ED08)) /* Non-secure VTOR */
#else
#define VTOR (*(volatile uint32_t *)(0xE000ED08))
#endif
static void *app_entry;
static uint32_t app_end_stack;
void RAMFUNCTION do_boot(const uint32_t *app_offset)
{
#if defined(CORTEX_R5)
(void)app_entry;
(void)app_end_stack;
/* limitations with TI arm compiler requires assembly */
asm volatile("do_boot_r5:\n"
" mov pc, r0\n");
#elif defined(CORTEX_M33) || defined(CORTEX_M55) /* Armv8 boot procedure */
/* Get stack pointer, entry point */
app_end_stack = (*((uint32_t *)(app_offset)));
app_entry = (void *)(*((uint32_t *)(app_offset + 1)));
/* Disable interrupts */
asm volatile("cpsid i");
/* Update IV */
VTOR = ((uint32_t)app_offset);
asm volatile("msr msplim, %0" ::"r"(0));
# if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && \
defined(TZEN) && !defined(CORTEX_M55)
asm volatile("msr msp_ns, %0" ::"r"(app_end_stack));
/* Jump to non secure app_entry */
asm volatile("mov r7, %0" ::"r"(app_entry));
asm volatile("bic.w r7, r7, #1");
/* Re-enable interrupts to allow non-secure OS handlers */
asm volatile("cpsie i");
asm volatile("blxns r7" );
# else
asm volatile("msr msp, %0" ::"r"(app_end_stack));
asm volatile("mov pc, %0":: "r"(app_entry));
# endif
c6fa180 to
b4fd37e
Compare
3377112 to
74d150b
Compare
Co-authored-by: Aidan Garske <aidan@wolfssl.com>
danielinux
previously approved these changes
May 27, 2026
dgarske
previously approved these changes
May 27, 2026
74d150b to
30de6b2
Compare
danielinux
approved these changes
May 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
arch.mk(inherits Cortex-M33 settings, adds-mcpu=cortex-m55).hal/stm32n6.{c,h,ld}: clock tree to 600 MHz (HSI -> PLL1 -> IC1/IC2/IC6/IC11), OCTOSPI/XSPI2 in single-SPI mmap mode with NORFAST_READ_4B, I/D-cache control, SAU (TZ and non-TZ), USART1 forwolfBoot_printf, and thehal_flash_*/ext_flash_*API on top of anoctospi_cmdpage-program/sector-erase helper.src/boot_arm.c): nakedisr_resetfor STM32N6 that setsSCB->VTOR = WOLFBOOT_ORIGIN, reloads MSP from word 0 of the FSBL vector table, then tail-calls intoisr_reset_c. Also writesMSPLIM_Sto_end_bssafter BSS init (raw T2 MSR encoding because-mcmseis not in the build) so a future stack overflow trips a cleanUsageFault.STKOF.hal/stm32n6.ld(wolfBoot in AXISRAM2 atWOLFBOOT_ORIGIN=0x34180400, 256 KB region) andtest-app/ARM-stm32n6.ld(app XIP at0x70020400).test-app/app_stm32n6.c): bare-metal LED blinker that reads partition state, callswolfBoot_success(), blinks blue (v1) or red (v>=2).tools/scripts/stm32n6_flash.sh): wrapsSTM32_SigningTool_CLIand OpenOCD for one-shot programming. Supports--skip-build,--app-only,--test-update(signs a v2 withIMAGE_HEADER_SIZEmatching the wolfBoot build),--halt.config/openocd/openocd_stm32n6.cfg): brings up XSPI2 single-SPI mmap onreset-initso flash programming via stmqspi works without the wolfBoot HAL.docs/Targets.md): full STM32N6 section with memory layout, OTP fuse requirements, jumper table, build/flash/debug instructions, TrustZone notes..github/workflows/test-configs.yml): addsstm32n6.configto the build matrix.Non-obvious gotchas captured in the port
clock_config()parksCPUSW/SYSSWon HSI before clearingPLL1ON. Disabling PLL1 while the CPU runs on it stops the CPU clock. OpenOCD-loaded boot masks this becausereset_haltleaves the CPU on reset-state HSI; cold boot was the only path that hit it.STM32_SigningTool_CLI -ep <addr>writes the address verbatim with no Thumb bit. The flash script never passes-ep/-la; the tool reads the entry point with the Thumb bit set from the binary's vector table at offset0x04. Wrong settings result in a silent hardfault on the first instruction.XSPIM_CRswaps XSPI1/XSPI2 port routing. Boot ROM leavesXSPIM_CR.MODE=1, sending XSPI2 traffic to Port 1 (nothing wired there).octospi_init()disables XSPI1, RCC-resets XSPI2, then writesXSPIM_CR=0so XSPI2 reaches Port 2 (where MX25UM51245G is wired).FAST_READ_4Bworks directly.BUSY=1and full FIFO.octospi_init()ends with one warmup XIP read ofWOLFBOOT_PARTITION_BOOT_ADDRESS; without it the first XIP access fromwolfBoot_startstalls (looks like a prefetch/AXI pipeline cold-start quirk).BXes the entry point with MSP still pointing at the Boot ROM's tiny scratch stack (~0x341037f4). Nakedisr_resetinsrc/boot_arm.csetsVTORand reloads MSP before any C prologue. Without this, wolfBoot's signature-verify path overflows the scratch stack, corrupts a saved LR into aFNC_RETURNsignature (0xFEFFFFFx), the nextBX LRdoes an S->NS state transition with garbage PC, the resulting MemManage fault is also stack-busted, double-fault -> LOCKUP.octospi_cmddata pump uses byte-wide DR access driven byFLEVEL. The DR32+FTHRESpolling path stalls on transfers larger than the FIFO depth (32 bytes).FLEVELis correct for any transfer size and threshold.ext_flash_write/ext_flash_erasemust invalidate the D-cache for the XIP alias. Without it, reads of just-modified regions return stale data. The A/B swap and signature re-verify after swap depend on this.IMAGE_HEADER_SIZEfrom env. The flash script's--test-updateinvocation now exports it from.configso v2 has the same 1024-byte manifest header as v1 (default is 256, which causes hash verification to fail at update time).Validation
wolfBoot Init->Verifying signature...done-> app banner, blue/red LED.TESTING -> SUCCESS.SUCCESS.config/examples/stm32n6.config): builds and runs end-to-end.config/examples/stm32n6-tz.config): config in place but the test-app linker script needs a separate fix; pre-existing issue, not part of this work.