Skip to content

RK0 on QEMU

Antonio Giacomelli edited this page Mar 18, 2026 · 23 revisions

This page explains how to configure QEMU on macOS, Windows and Linux. It also explains how to integrate VSCode with GDB for an integrated development environment.

Requirements

  • QEMU for ARM (qemu-system-arm)
  • ARM GCC Toolchain (arm-none-eabi-gcc)
  • ARM GDB
    • arm-none-eabi-gdb, for most Unixes
    • arm-gdb-multi-arch for Debian-based Linux (including Win Ubuntu subsystem.)

Target platform

  • lm3s6965evb (TI Stellaris LM3S Cortex M3)
  • microbit (BBC micro:bit Cortex-M0)

⚠️ The BBC micro:bit Cortex-M0 QEMU machine has not been extensively tested. For QEMU-only experimenting, recommend using Cortex-M3.

File Structure


├── arch/
│   ├── armv6m/           # ARMv6M port
│   │   └── kernel/
│   │       ├── inc/
│   │       └── src/
|   |
│   └── armv7m/           # ARMv7M port
│        └──kernel/
│           ├── inc/
│           └── src/
├── core/                # System core  
│   ├── inc/
│   └── src/
|
├── app/                 # Application  
│   ├── inc/
│   └── src/
|
├── build/               # Output directory 
└── Makefile             # Build system for QEMU target

Building and Running

To build and run

make ARCH=armv7m|armv6m qemu

To start in debug mode:

make ARCH=armv7m qemu-debug  

Then connect with GDB in a second terminal:

arm-none-eabi-gdb build/rk0_demo.elf -ex "target remote localhost:1234" 
# for a Debian-based OS, use `gdb-multiarch`

Screenshots

Here’s RK0 running on QEMU, showing UART output via GDB semihosting (QEMU 9.2.0 / macOS 15.2):

UART output shown in GDB TUI mode

Debugging from VSCodium:

GDB session in VSCodium using Cortex-Debug

🍎 macOS: VSCode+QEMU+GDB


Installing Dependencies

ARM Embedded Toolchain

brew install arm-none-eabi-gcc

QEMU

brew install qemu

Building RK0

Run from the RK0 project root:

make ARCH=armv7m   

To debug:

make qemu-debug

This will start QEMU and open a GDB server on localhost:1234.


Configure VS Code / VSCodium

tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Build RK0 for ARMv7-M",
      "type": "shell",
      "command": "make ARCH=armv7m",
      "group": {
        "kind": "build",
        "isDefault": true
      }
    },
    {
      "label": "Start QEMU in Debug Mode",
      "type": "shell",
      "command": "make qemu-debug",
      "isBackground": true,
      "problemMatcher": {
        "pattern": {
          "regexp": "."
        },
        "background": {
          "activeOnStart": true,
          "beginsPattern": "Start GDB with:",
          "endsPattern": "localhost:1234"
        }
      }
    }
  ]
}

launch.json

PS: On macOS, the cppdbg debugger type often fails to attach to GDB/LLDB. I use the cortex-debug only. I can't say if using pure VSCode (and not VSCodium as I do) would solve the issue.

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug RK0 - ARMv7M",
      "cwd": "${workspaceFolder}",
      "executable": "${workspaceFolder}/build/armv7m/rk0_demo.elf",
      "request": "attach",
      "type": "cortex-debug",
      "servertype": "external",
      "gdbTarget": "localhost:1234",
      "gdbPath": "arm-none-eabi-gdb",
      "device": "Cortex-M3",
      "runToEntryPoint": "main",
      "preLaunchTask": "Start QEMU in Debug Mode"
    }
  ]
}

Running

  1. Build and start QEMU in the background using the Run Panel.
  2. Launch the Debug configuration — VSCodium will attach to GDB server.

image


🟦 Windows (WSL/MSYS2): VSCode+QEMU+GDB

The build system assumes a Unix-like environment and uses make.

On Windows use either WSL or MSYS2 platform. If you are using Cygwin or something else, you likely already know what to do.

Using WSL

  • I guess it is the easiest.

  • In this case, I prefer connecting VSCode to the WSL (and having the source code in the subsystem instead of accessing a /mnt/ partition in Win).

  • The standard WSL distro is Ubuntu. Install the same packages as described for Debian-based Linux

  • For .json files, follow the same setup for macOS, replacing arm-none-eabi-gdb for gdb-multi-arch.

  • You call code from the WSL bash terminal. It will dispatch the VSCode installed on your Windows:

antonio@winbox:~$ uname -a
Linux winbox 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
antonio@winbox:~$ which code
/mnt/c/Users/anton/AppData/Local/Programs/Microsoft VS Code/bin/code

image VSCode forwarded to WSL and GDB server

Using MSYS2

  1. Install Chocolatey

At a Win PowerShell:

Set-ExecutionPolicy Bypass -Scope Process -Force; `
[System.Net.ServicePointManager]::SecurityProtocol = `
[System.Net.ServicePointManager]::SecurityProtocol -bor 3072; `
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
  1. Install toolchain and QEMU
choco install gcc-arm-embedded
choco install msys2
choco install qemu

Configure MSYS2 as the VS Code Terminal

In VS Code:

  1. Open Settings
  2. Search for: terminal.integrated.profiles.windows
  3. Edit your settings.json:
"terminal.integrated.profiles.windows": {
  "MSYS2 Bash": {
    "path": "C:\\msys64\\usr\\bin\\bash.exe",
    "args": ["--login", "-i"],
    "env": {
      "MSYSTEM": "MINGW64",
      "CHERE_INVOKING": "1"
    }
  }
},
"terminal.integrated.defaultProfile.windows": "MSYS2 Bash"

Set PATH for ARM Toolchain in MSYS2

Edit your MSYS2 ~/.bashrc:

export PATH=$PATH:/c/ProgramData/chocolatey/bin  # adjust path if needed

Then reload:

source ~/.bashrc

Configure Debugging in VS Code

Install the extensions cortex-debug and C/C++.

Option 1: Using Cortex-Debug

Create .vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug RK0 (QEMU ARMv7-M)",
      "type": "cortex-debug",
      "request": "launch",
      "servertype": "external",
      "gdbPath": "arm-none-eabi-gdb", 
      "cwd": "${workspaceRoot}",
      "executable": "${workspaceRoot}/build/armv7m/rk0_demo.elf",
      "armToolchainPath": "C:/ProgramData/chocolatey/bin",
      "device": "Cortex-M3"
    }
  ]
}

Option 2: Using cppdbg

{
  "name": "Debug RK0 (cppdbg - ARMv7M)",
  "type": "cppdbg",
  "request": "launch",
  "program": "${workspaceRoot}/build/armv7m/rk0_demo.elf",
  "miDebuggerPath": "arm-none-eabi-gdb",
  "miDebuggerServerAddress": "localhost:1234",
  "cwd": "${workspaceRoot}",
  "stopAtEntry": false,
  "environment": [],
  "MIMode": "gdb",
  "setupCommands": [
    {
      "description": "Enable pretty-printing for GDB",
      "text": "-enable-pretty-printing",
      "ignoreFailures": true
    }
  ]
}

Running

  1. Start QEMU in Debug Mode
make qemu-debug
  1. Launch Debugger in VS Code

Open the Run panel and press F5.


UART + GDB integration VS Code attached to QEMU GDB server, UART output visible.


🐧 Linux (Debian-based): QEMU and text-mode debugging

For the record: if you are using VSCode on Linux, besides not telling anyone -- follow the same procedures for WSL.

Dependencies

sudo apt install gcc-arm-none-eabi qemu-system-arm 

For Debian-based you install and use:

sudo apt install gdb-multiarch # not gdb-arm-none-eabi

Text Debug Flow

make qemu-debug   # starts QEMU and waits for GDB

Open another terminal

# within the project directory
gdb-multiarch  build/armv7m/rk0_demo.elf -ex 'target remote localhost:1234' 

image Debugging on pure text mode on a Gnome terminal.