RP2350 Button Driver RISC-V

March 23, 2026 · View on GitHub

FREE Embedded Hacking Course HERE

VIDEO PROMO HERE


RP2350 Button Driver RISC-V

An RP2350 Button driver written entirely in RISC-V Assembler.


Install RISC-V Toolchain (Windows / RP2350 Hazard3)

Official Raspberry Pi guidance for RP2350 RISC-V points to pico-sdk-tools prebuilt releases.

Official References

  • RP2350 RISC-V quick start in pico-sdk: HERE
  • Tool downloads (official): HERE

Install (PowerShell)

$url = "https://github.com/raspberrypi/pico-sdk-tools/releases/download/v2.0.0-5/riscv-toolchain-14-x64-win.zip"
$zipPath = "$env:TEMP\riscv-toolchain-14-x64-win.zip"
$dest = "$HOME\riscv-toolchain-14"

Invoke-WebRequest -Uri $url -OutFile $zipPath
New-Item -ItemType Directory -Path $dest -Force | Out-Null
Expand-Archive -LiteralPath $zipPath -DestinationPath $dest -Force
Get-ChildItem -Path $dest | Select-Object Name

Add Toolchain To User PATH (PowerShell)

$toolBin = "$HOME\riscv-toolchain-14\bin"
$currentUserPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($currentUserPath -notlike "*$toolBin*") {
  [Environment]::SetEnvironmentVariable("Path", "$currentUserPath;$toolBin", "User")
}

Close and reopen your terminal after updating PATH.

Verify Toolchain

riscv32-unknown-elf-as --version
riscv32-unknown-elf-ld --version
riscv32-unknown-elf-objcopy --version

Build This Project

.\build.bat

If your toolchain uses a different prefix, pass it explicitly:

.\build.bat riscv-none-elf

Button + LED Wiring (Pico 2 Target)

  • GP15 (Pin 20) → tactile button → GND (internal pull-up enabled)
  • GP16 (Pin 21) → 330 ohm resistor → LED anode
  • LED cathode → GND (Pin 23)

Hardware

Raspberry Pi Pico 2 w/ Header BUY

USB A-Male to USB Micro-B Cable BUY

Raspberry Pi Pico Debug Probe BUY

Complete Component Kit for Raspberry Pi BUY

10pc 25v 1000uF Capacitor BUY

10% PiShop DISCOUNT CODE - KVPE_HS320548_10PC


Build

.\build.bat

Optional Toolchain Prefix Override

.\build.bat riscv-none-elf

Clean

.\clean.bat

Tutorial

A comprehensive 30-chapter technical book teaching RP2350 RISC-V assembly from absolute scratch. Every line of assembler is explained.

Foundations

Chapter 1: What Is a Computer?

Chapter 2: Number Systems — Binary, Hexadecimal, and Decimal

Chapter 3: Memory — Addresses, Bytes, Words, and Endianness

Chapter 4: What Is a Register?

Chapter 5: Load-Store Architecture

Chapter 6: The Fetch-Decode-Execute Cycle in Detail

RISC-V Instruction Set

Chapter 7: RISC-V Hazard3 ISA Overview

Chapter 8: Immediate and Upper-Immediate Instructions

Chapter 9: Arithmetic and Logic Instructions

Chapter 10: Memory Access — Load and Store Deep Dive

Chapter 11: Branch Instructions

Chapter 12: Jumps, Calls, and Returns

Assembly Programming

Chapter 13: Pseudo-Instructions and Assembler Conveniences

Chapter 14: Assembler Directives

Chapter 15: Calling Convention and Stack Frames

Chapter 16: Bitwise Operations for Hardware Control

Chapter 17: Memory-Mapped I/O and Volatile Access

Hardware Concepts

Chapter 18: RP2350 Hardware Architecture

Build System

Chapter 19: The Linker Script — linker.ld

Chapter 20: The Build System — build.bat and clean.bat

Source Code Walkthroughs

Chapter 21: Boot Metadata — image_def.s

Chapter 22: Constants and Definitions — constants.s

Chapter 23: Stack and Vector Table — stack.s, vector_table.s

Chapter 24: Reset Handler — reset_handler.s

Chapter 25: Crystal Oscillator — xosc.s

Chapter 26: Reset Controller — reset.s

Chapter 27: GPIO Configuration — gpio.s

Chapter 28: Button Driver — button.s

Chapter 29: Application Entry Point — main.s

Integration

Chapter 30: Full Integration — Build, Flash, Wire, and Test


main.s Code

/**
 * FILE: main.s
 *
 * DESCRIPTION:
 * RP2350 Button Driver Main Application (RISC-V).
 * 
 * BRIEF:
 * Main application entry point for RP2350 RISC-V button driver. Monitors
 * button on GPIO15 and controls LED on GPIO16 based on button state.
 *
 * AUTHOR: Kevin Thomas
 * CREATION DATE: November 2, 2025
 * UPDATE DATE: March 21, 2026
 */


.include "constants.s"

/**
 * Initialize the .text section. 
 * The .text section contains executable code.
 */
.section .text                                   # code section
.align 2                                         # align to 4-byte boundary

/**
 * @brief   Main application entry point.
 *
 * @details Implements button monitoring loop. LED on GPIO16 lights up
 *          when button on GPIO15 is pressed.
 *
 * @param   None
 * @retval  None
 */
.global main                                     # export main
.type main, @function                            # mark as function
main:
.GPIO16_Config:
  li    a0, PADS_BANK0_GPIO16_OFFSET             # load PADS_BANK0_GPIO16_OFFSET
  li    a1, IO_BANK0_GPIO16_CTRL_OFFSET          # load IO_BANK0_GPIO16_CTRL_OFFSET
  li    a2, 16                                   # load GPIO number
  call  GPIO_Config                              # call GPIO_Config
.Button_Init:
  call  Button_Init                              # initialize button on GPIO15
.Loop:
  call  Button_Read                              # read button state (0=pressed, 1=released)
  beqz  a0, .Button_Pressed                      # branch if button pressed (a0==0)
.Button_Released:
  li    a0, 16                                   # load GPIO number
  call  GPIO_Clear                               # turn off LED
  j     .Loop_Delay                              # continue to delay
.Button_Pressed:
  li    a0, 16                                   # load GPIO number
  call  GPIO_Set                                 # turn on LED
.Loop_Delay:
  li    a0, 10                                   # 10ms debounce delay
  call  Delay_MS                                 # call Delay_MS
  j     .Loop                                    # loop forever
  ret                                            # return to caller

/**
 * Test data and constants.
 * The .rodata section is used for constants and static data.
 */
.section .rodata                                 # read-only data section

/**
 * Initialized global data.
 * The .data section is used for initialized global or static variables.
 */
.section .data                                   # data section

/**
 * Uninitialized global data.
 * The .bss section is used for uninitialized global or static variables.
 */
.section .bss                                    # BSS section

License

Apache License 2.0