Build & Load: RP2350 (S/NS)
Build and load programs with S/NS segregation on RP2350 without debugging
Overview
This document describes how to build, load, and run RTK-based programs with S/NS segregation for the RP2350 without debugging.
-
S/NS programs comprise two ELF files, one for the Secure program and the NSC veneers, one for the Non-secure program.
-
Since two images must be loaded, the UF2 path is not available – ELF binaries via
picotoolare the load format. -
make-elf creates the ELF files. The S image is the bootable image and includes the
IMAGE_DEFmetadata block; the NS image is loaded by the S image and does not needIMAGE_DEF. The framework default is Path A (see IMAGE_DEF). -
Other guides:
- Secure/Non-secure with debugging: Build, Load & Debug: RP2350 (S/NS)
- Non-S/NS, without debugging: Build & Load: RP2350
- Non-S/NS, with debugging: Build, Load & Debug: RP2350
See also Practical Notes.
Set-up
Prerequisites
The build configuration must be set up as explained in:
Flash Layout
RP2350 S/NS programs can be built for two flash layouts:
-
without flash partitions – single contiguous flash region; both images use absolute addresses.
-
with flash partitions – the S image and NS image live in separate partitions; the S image configures QMI address translation so the CPU fetches NS code from a translated virtual address.
Two reference example programs illustrate the difference:
<repo>/examples/v3.1/rpi/pico2/Secure– without flash partitions<repo>/examples/v3.1/rpi/pico2/SecurePart– with flash partitions
See Compile and Link: RP2350 for the address-range tables.
Project
-
Directories:
- S program in
<project-dir>/sec - NS program in
<project-dir>/nonsec
- S program in
-
Commands as shown are run with
cwd = <project-dir>. -
Two Astrobe configuration files are required, one for the Secure and one for the Non-secure program. An easy way to provide the configuration files is to place them directly in the project directories
secandnonsec, where they can be picked up by the build scripts. -
Refer to Compile and Link: RP2350 for the address ranges as used by the example programs.
Steps
1. Build the ELF Files
Building the two ELF files for the Secure and the Non-secure program is a multi-step process, which is best implemented and executed using a build script.
The S/NS example programs provide build-elf.cmd, which builds both the Secure and Non-secure ELF binaries, called S-program.elf and NS-program.elf below. This script can serve as basis for your own projects and programs.
2. Load the ELF Files
2a. Put the RP2350 in BOOTSEL mode, which mounts the virtual volume RP2350.
2b. Load the two ELF files using picotool.
- Without partition table:
picotool load nonsec/<NS-program>.elf -v
picotool load sec/<S-program>.elf -v -x
- With partition table (assuming partition 0 for S, partition 1 for NS):
picotool load -p 1 nonsec/<NS-program>.elf -v
picotool load -p 0 sec/<S-program>.elf -v -x
The -x option on the second command resets and starts the Secure program.
Inside the Build Script
The build script executes the following steps. Upon error, the script terminates.
-
Compile the Secure program, running AstrobeBuild, which recursively compiles all modules as needed.
-
Run sec-epilogue to add the Secure epilogues to all procedures that are exposed to the Non-secure world.
-
Re-compile the Secure program to ensure that it contains the Secure epilogues.
-
Link the Secure program, running AstrobeLink.
-
Run gen-secure to create the Non-secure Callable (NSC) binary, containing one gateway veneer block per procedure exposed to the Non-secure world, plus the interface modules for the Non-secure code to call into the Secure world via the gateways.
-
Run make-elf to create the Secure ELF binary in
sec, with the NSC binary embedded and theIMAGE_DEFblock prepended (--image-def). -
Compile the Non-secure program, running AstrobeBuild.
-
Link the Non-secure program, running AstrobeLink.
-
Run make-elf to create the Non-secure ELF binary in
nonsec. NoIMAGE_DEFis needed – the NS image is loaded by the S image rather than booted by the boot ROM.
Last updated: 16 May 2026