Skip to content

Commit 6585a0b

Browse files
committed
Fixes to support botting image on QSPI NOR flash from boot ROM (existing code was only loading to SRAM)
1 parent 896c2a7 commit 6585a0b

3 files changed

Lines changed: 88 additions & 25 deletions

File tree

arch.mk

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,10 @@ ifeq ($(ARCH),ARM)
274274
CORTEX_M55=1
275275
CFLAGS+=-Ihal
276276
ARCH_FLASH_OFFSET=0x70000000
277-
ifeq ($(TZEN),1)
278-
WOLFBOOT_ORIGIN=0x24000000
279-
else
280-
WOLFBOOT_ORIGIN=0x34000000
281-
endif
277+
# Boot ROM copies FSBL from NOR to AXISRAM2 at 0x34180400.
278+
# Use the same address for both TZEN=0 and TZEN=1 since the Boot ROM
279+
# always uses the non-secure alias. SAU is configured in hal_init().
280+
WOLFBOOT_ORIGIN=0x34180400
282281
EXT_FLASH=1
283282
PART_UPDATE_EXT=1
284283
PART_SWAP_EXT=1

docs/Targets.md

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,13 +1839,13 @@ XSPI2 NOR Flash (memory-mapped at 0x70000000):
18391839
0x70020000 Boot partition (1MB, app runs from here via XIP)
18401840
0x70120000 Update partition (1MB, device-relative: 0x00120000)
18411841

1842-
AXISRAM — without TrustZone (non-secure alias):
1843-
0x34000000 wolfBoot (loaded to SRAM via SWD or Boot ROM FSBL copy)
1844-
0x34020000 Stack / work area
1842+
AXISRAM2 — without TrustZone (non-secure alias):
1843+
0x34180400 wolfBoot FSBL (Boot ROM copies from NOR to here)
1844+
0x341A0400 Stack top (128KB above origin)
18451845

1846-
AXISRAM — with TrustZone (TZEN=1, secure alias):
1847-
0x24000000 wolfBoot (secure SRAM — IDAU marks 0x24xxxxxx as secure)
1848-
0x24020000 Stack / work area (secure)
1846+
AXISRAM2 — with TrustZone (TZEN=1, secure alias):
1847+
0x24180400 wolfBoot FSBL (secure — IDAU marks 0x24xxxxxx as secure)
1848+
0x241A0400 Stack top (secure)
18491849
0x34000000 Application SRAM (SAU region: non-secure)
18501850
```
18511851
@@ -1866,14 +1866,65 @@ make flash
18661866
```
18671867

18681868
`make flash` uses OpenOCD with the stmqspi driver to:
1869-
1. Program the signed application to NOR flash at 0x70020000
1870-
2. Load wolfBoot to SRAM (0x24000000 for TZEN=1, 0x34000000 otherwise)
1871-
3. Start wolfBoot, which verifies and boots the application via XIP
1869+
1. Generate a Boot ROM FSBL header using `STM32_SigningTool_CLI` and program
1870+
`wolfboot-trusted.bin` to NOR flash at 0x70000000 (for autonomous boot on reset)
1871+
2. Load wolfBoot directly to SRAM for immediate execution
1872+
3. Program the signed application to NOR flash at 0x70020000
1873+
4. Start wolfBoot, which verifies and boots the application via XIP
1874+
1875+
The Boot ROM copies the FSBL from NOR flash to AXISRAM2 at `0x34180400`.
1876+
wolfBoot is linked at this address so it runs correctly after both
1877+
OpenOCD-initiated and reset-initiated boots.
18721878

18731879
Prerequisites:
1874-
- OpenOCD 0.12+ with stm32n6x target support (build from source if needed)
1880+
- OpenOCD 0.12+ with stm32n6x target support (build from
1881+
[openocd-org/openocd](https://github.com/openocd-org/openocd) if needed)
1882+
- `STM32_SigningTool_CLI` (included with STM32CubeIDE) for Boot ROM FSBL header
1883+
generation. The flash script auto-detects the tool location. Without it,
1884+
wolfBoot is loaded to SRAM only (no autonomous boot on reset).
18751885
- ST-Link connected to the Nucleo board
18761886
- arm-none-eabi toolchain in PATH
1887+
- OTP fuse VDDIO3_HSLV programmed (see [OTP Configuration](#otp-configuration)
1888+
below)
1889+
1890+
### OTP Configuration (One-Time)
1891+
1892+
The STM32N6 Boot ROM requires OTP fuse configuration to boot from external
1893+
XSPI2 NOR flash. This is a **one-time permanent** operation.
1894+
1895+
**OTP Word 124** (BSEC_HW_CONFIG) — set bit 15:
1896+
1897+
| Bit | Name | Value | Description |
1898+
|-----|------|-------|-------------|
1899+
| 15 | VDDIO3_HSLV | 1 | Enable XSPI2 I/O high-speed low-voltage mode |
1900+
1901+
**Using STM32CubeProgrammer (GUI):**
1902+
1903+
1. Connect to the board via SWD (JP2/BOOT1 in position 2-3 for development mode)
1904+
2. Select **OTP** in the left menu
1905+
3. Find word 124 and set value to `0x00008000`
1906+
4. Click **Program**
1907+
1908+
**Using STM32_Programmer_CLI:**
1909+
1910+
```sh
1911+
STM32_Programmer_CLI -c port=SWD ap=1 \
1912+
-el <path>/OTP_FUSES_STM32N6xx.stldr \
1913+
-otp write word=124 value=0x00008000
1914+
```
1915+
1916+
### Boot Mode Switches (JP1/JP2)
1917+
1918+
The NUCLEO-N657X0-Q has two boot mode jumpers:
1919+
1920+
| Mode | JP1 (BOOT0) | JP2 (BOOT1) | Description |
1921+
|------|-------------|-------------|-------------|
1922+
| Development | don't care | 2-3 | Boot ROM waits for debugger (OpenOCD/SWD) |
1923+
| External flash | 1-2 | 1-2 | Boot ROM loads FSBL from XSPI2 NOR flash |
1924+
1925+
For development, use JP2=2-3 to flash via OpenOCD. After flashing, switch
1926+
both JP1 and JP2 to position 1-2 and press reset for autonomous boot from
1927+
NOR flash.
18771928

18781929
### Build Options
18791930

tools/scripts/stm32n6_flash.sh

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,14 @@ OPENOCD_CFG="${WOLFBOOT_ROOT}/config/openocd/openocd_stm32n6.cfg"
4444
BOOT_ADDR=0x70020000
4545
UPDATE_ADDR=0x70120000
4646

47-
# Determine SRAM load address from TZEN config
48-
TZEN_CHECK=$(grep -E '^TZEN\?*=' "${WOLFBOOT_ROOT}/.config" 2>/dev/null | head -1 | sed 's/.*=//;s/[[:space:]]//g')
49-
if [ "$TZEN_CHECK" = "1" ]; then
50-
SRAM_ADDR=0x24000000
51-
SRAM_WORK=0x24020000
52-
else
53-
SRAM_ADDR=0x34000000
54-
SRAM_WORK=0x34020000
55-
fi
47+
# Boot ROM always copies FSBL to AXISRAM2 at this address
48+
SRAM_ADDR=0x34180400
49+
50+
# STM32_SigningTool_CLI for Boot ROM FSBL header (use latest version)
51+
SIGN_TOOL=""
52+
for d in $(ls -rd /opt/st/stm32cubeide_*/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.*/tools/bin 2>/dev/null); do
53+
[ -x "$d/STM32_SigningTool_CLI" ] && SIGN_TOOL="$d/STM32_SigningTool_CLI" && break
54+
done
5655

5756
check_tool() {
5857
command -v "$1" &>/dev/null || { echo -e "${RED}Error: $1 not found${NC}"; exit 1; }
@@ -109,6 +108,20 @@ sleep 1
109108
OPENOCD_CMDS="reset init; "
110109

111110
if [ $APP_ONLY -eq 0 ]; then
111+
# Generate Boot ROM FSBL header using STM32_SigningTool_CLI
112+
if [ -n "$SIGN_TOOL" ]; then
113+
TRUSTED_BIN="${WOLFBOOT_ROOT}/wolfboot-trusted.bin"
114+
chmod u+w "${TRUSTED_BIN}" 2>/dev/null; rm -f "${TRUSTED_BIN}"
115+
echo -e "${CYAN} Generating FSBL header (STM32_SigningTool_CLI)...${NC}"
116+
"$SIGN_TOOL" -bin "${WOLFBOOT_ROOT}/wolfboot.bin" -nk -of 0x80000000 -t fsbl -hv 2.3 -align -la ${SRAM_ADDR} -ep ${SRAM_ADDR} -o "${TRUSTED_BIN}" || true
117+
[ -f "${TRUSTED_BIN}" ] || { echo -e "${RED}Failed to generate trusted binary${NC}"; exit 1; }
118+
echo -e "${CYAN} wolfboot-trusted.bin -> NOR 0x70000000${NC}"
119+
OPENOCD_CMDS+="flash write_image erase ${TRUSTED_BIN} 0x70000000; "
120+
else
121+
echo -e "${YELLOW} STM32_SigningTool_CLI not found, loading wolfBoot to SRAM only${NC}"
122+
fi
123+
124+
# Also load wolfBoot directly to SRAM for immediate execution
112125
echo -e "${CYAN} wolfboot.bin -> SRAM ${SRAM_ADDR}${NC}"
113126
OPENOCD_CMDS+="load_image ${WOLFBOOT_ROOT}/wolfboot.bin ${SRAM_ADDR} bin; "
114127
fi
@@ -130,7 +143,7 @@ if [ $TEST_UPDATE -eq 1 ]; then
130143
OPENOCD_CMDS+="flash write_image /tmp/trigger_magic.bin ${TRIGGER_ADDR}; "
131144
fi
132145

133-
# Boot wolfBoot from SRAM (reset would clear SRAM, so we jump directly)
146+
# Boot wolfBoot from SRAM (also loaded to NOR for reset persistence)
134147
if [ $APP_ONLY -eq 0 ]; then
135148
# Extract initial SP (word 0) and entry point (word 1) from vector table
136149
INIT_SP=$(od -A n -t x4 -N 4 "${WOLFBOOT_ROOT}/wolfboot.bin" | awk '{print "0x"$1}')

0 commit comments

Comments
 (0)