Chapter 22: constants.s

September 17, 2026 · View on GitHub

Introduction

Every peripheral on the RP2350 is accessed at a fixed memory address. Rather than scattering magic numbers throughout our source files, we centralize all addresses and constants in constants.s using .equ directives. Every other source file includes this file, creating a single source of truth for the entire firmware. This chapter examines every constant and explains what it references in hardware.

Complete Source Code

.syntax unified                                  // use unified assembly syntax
.cpu cortex-m33                                  // target Cortex-M33 core
.thumb                                           // use Thumb instruction set

/**
 * Memory addresses and constants.
 */
.equ STACK_TOP,                   0x20082000
.equ STACK_LIMIT,                 0x2007a000
.equ XOSC_BASE,                   0x40048000
.equ XOSC_CTRL,                   XOSC_BASE + 0x00
.equ XOSC_STATUS,                 XOSC_BASE + 0x04
.equ XOSC_STARTUP,                XOSC_BASE + 0x0c
.equ PPB_BASE,                    0xe0000000
.equ CPACR,                       PPB_BASE + 0x0ed88
.equ CLOCKS_BASE,                 0x40010000
.equ CLK_PERI_CTRL,               CLOCKS_BASE + 0x48
.equ RESETS_BASE,                 0x40020000
.equ RESETS_RESET,                RESETS_BASE + 0x0
.equ RESETS_RESET_CLEAR,          RESETS_BASE + 0x3000
.equ RESETS_RESET_DONE,           RESETS_BASE + 0x8
.equ IO_BANK0_BASE,               0x40028000
.equ IO_BANK0_GPIO16_CTRL_OFFSET, 0x84
.equ PADS_BANK0_BASE,             0x40038000
.equ PADS_BANK0_GPIO16_OFFSET,    0x44

Preamble

.syntax unified                                  // use unified assembly syntax
.cpu cortex-m33                                  // target Cortex-M33 core
.thumb                                           // use Thumb instruction set

Every source file that .includes constants.s inherits these directives. They establish the instruction set context for the assembler.

Stack Constants

.equ STACK_TOP,                   0x20082000
.equ STACK_LIMIT,                 0x2007a000
ConstantValueDescription
STACK_TOP0x20082000Top of stack (highest address)
STACK_LIMIT0x2007a000Bottom of stack (32 KB below top)

SRAM on the RP2350 extends from 0x20000000 to 0x20082000. The stack occupies the top 32 KB. The limit register triggers a fault if SP drops below this value, preventing silent stack overflow.

Crystal Oscillator Constants

.equ XOSC_BASE,                   0x40048000
.equ XOSC_CTRL,                   XOSC_BASE + 0x00
.equ XOSC_STATUS,                 XOSC_BASE + 0x04
.equ XOSC_STARTUP,                XOSC_BASE + 0x0c
ConstantAddressDescription
XOSC_BASE0x40048000XOSC peripheral base
XOSC_CTRL0x40048000Control register
XOSC_STATUS0x40048004Status register (bit 31 = STABLE)
XOSC_STARTUP0x4004800CStartup delay register

These addresses are defined in the RP2350 datasheet. The assembler computes derived addresses at assembly time (e.g., XOSC_BASE + 0x04 = 0x40048004).

System Registers

.equ PPB_BASE,                    0xe0000000
.equ CPACR,                       PPB_BASE + 0x0ed88
ConstantAddressDescription
PPB_BASE0xE0000000Private Peripheral Bus base
CPACR0xE000ED88Coprocessor Access Control Register

The PPB region contains ARM-defined system registers. CPACR controls which coprocessors the firmware can access. Our firmware sets bits [1:0] to enable CP0 (SIO).

Clock Constants

.equ CLOCKS_BASE,                 0x40010000
.equ CLK_PERI_CTRL,               CLOCKS_BASE + 0x48
ConstantAddressDescription
CLOCKS_BASE0x40010000Clocks controller base
CLK_PERI_CTRL0x40010048Peripheral clock control

CLK_PERI_CTRL selects the clock source for peripherals and enables the clock output.

Reset Controller Constants

.equ RESETS_BASE,                 0x40020000
.equ RESETS_RESET,                RESETS_BASE + 0x0
.equ RESETS_RESET_CLEAR,          RESETS_BASE + 0x3000
.equ RESETS_RESET_DONE,           RESETS_BASE + 0x8
ConstantAddressDescription
RESETS_BASE0x40020000Reset controller base
RESETS_RESET0x40020000Reset control register
RESETS_RESET_CLEAR0x40023000Atomic clear alias
RESETS_RESET_DONE0x40020008Reset done status

Bit 6 in these registers corresponds to IO_BANK0 (GPIO controller). Clearing bit 6 in RESETS_RESET releases GPIO from reset.

GPIO Constants

.equ IO_BANK0_BASE,               0x40028000
.equ IO_BANK0_GPIO16_CTRL_OFFSET, 0x84
.equ PADS_BANK0_BASE,             0x40038000
.equ PADS_BANK0_GPIO16_OFFSET,    0x44
ConstantValueDescription
IO_BANK0_BASE0x40028000IO control base
IO_BANK0_GPIO16_CTRL_OFFSET0x84GPIO16 control register offset
PADS_BANK0_BASE0x40038000Pad control base
PADS_BANK0_GPIO16_OFFSET0x44GPIO16 pad register offset

The control register offset 0x84 comes from the formula: each GPIO has an 8-byte register pair (status + ctrl), and GPIO16 is at offset 16 * 8 + 4 = 0x84 (the +4 selects the ctrl register).

The pad offset 0x44 comes from: each GPIO has a 4-byte pad register, starting at offset 4 (GPIO0 is at 0x04), so GPIO16 is at 4 + 16 * 4 = 0x44.

How .include Works

Every source file begins with:

.include "constants.s"

The assembler textually inserts the entire contents of constants.s at that point. This means every file has access to all constants with no runtime cost — .equ definitions produce no code.

Design Principle

Centralizing constants provides three benefits:

  1. Single source of truth — change an address in one place, all files see the update
  2. Readabilityldr r0, =XOSC_BASE is clearer than ldr r0, =0x40048000
  3. Correctness — derived addresses (base + offset) are computed by the assembler, eliminating manual arithmetic errors

Summary

  • constants.s defines 19 .equ constants covering stack, XOSC, system, clock, reset, and GPIO addresses.
  • All addresses come directly from the RP2350 datasheet.
  • Derived addresses use assembler arithmetic (e.g., XOSC_BASE + 0x04).
  • .include "constants.s" in every source file provides universal access with zero runtime cost.
  • GPIO16 offsets are computed from the GPIO number using the register layout formulas in the datasheet.