Oberon RTK

Build, Load & Debug: RP2350 (S/NS)

Build, load, and debug programs with S/NS segregation on RP2350

Overview

This document describes how to build, load, and run RTK-based programs with S/NS segregation for the RP2350 for 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 the debugger (or picotool for the partition-table case) are the load format.

  • make-elf creates the ELF files. It creates and embeds the necessary DWARF debug data. Note that the executable binaries are 100% the same with or without debug data, and consequently there is no "debug overhead" with debug data included if run outside a debugger.

  • The S image is the bootable image and includes the IMAGE_DEF metadata block; the NS image is loaded by the S image and does not need IMAGE_DEF. The framework default is Path A (see IMAGE_DEF).

  • Other guides:

See also Practical Notes.

Set-up

Prerequisites

The build and debug tools 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
  • 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 sec and nonsec, 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 debug 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-db-elf.cmd, which builds both the Secure and Non-secure debug ELF binaries, called S-program.elf and NS-program.elf below. This script can serve as basis for your own projects and programs.

To continue, the build must complete without errors or alerts; warnings are OK.

2. Load the ELF Files

The ELF files are loaded by the debugger:

  • GUI: Cortex-Debug inside Visual Studio Code – see Debugging § VS Code + Cortex-Debug
  • command line: OpenOCD and GDB – see Debugging § GDB Command Line

Hence, with a partition table:

  • put the RP2350 in BOOTSEL mode, which mounts the virtual volume RP2350
  • load both images with picotool as below
  • use the attach flow in Debugging § Loading Without Flashing (Attach)

For loading into partitions (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

Inside the Build Script

The build script executes the following steps. Upon error, the script terminates.

  1. Compile the Secure program, running AstrobeBuild, which recursively compiles all modules as needed.

  2. Run sec-epilogue to add the Secure epilogues to all procedures that are exposed to the Non-secure world.

  3. Re-compile the Secure program to ensure that it contains the Secure epilogues.

  4. Link the Secure program, running AstrobeLink.

  5. 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.

  6. Run gen-rdb to create an .alst file for each module in the Secure program, plus _startup.alst for the start-up sequence inserted by the linker at the end of the program; make-elf requires the .alst files to create symbols and DWARF debug data.

  7. Run make-elf to create the Secure debug ELF binary in sec, with the NSC binary embedded, the IMAGE_DEF block prepended (--image-def), DWARF debug data, and symbol prefix S.

  8. Compile the Non-secure program, running AstrobeBuild.

  9. Link the Non-secure program, running AstrobeLink.

  10. Run gen-rdb to create the .alst files for the Non-secure program.

  11. Run make-elf to create the Non-secure debug ELF binary in nonsec, with DWARF debug data and symbol prefix NS. No IMAGE_DEF is needed – the NS image is loaded by the S image rather than booted by the boot ROM.

Last updated: 17 May 2026