Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

QEMU Bare-Metal Testing

This document describes how to run bare-metal nros applications in QEMU with network connectivity.

Overview

QEMU emulates the MPS2-AN385 board (ARM Cortex-M3) with LAN9118 Ethernet, allowing full network testing without physical hardware.

Network Topology

┌─────────────────────────────────────────────────────────────────┐
│                         Host System                              │
├─────────────────────────────────────────────────────────────────┤
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────────────┐  │
│  │  zenohd     │    │ ROS 2 Node  │    │   Test Runner       │  │
│  │  (router)   │    │ (rmw_zenoh) │    │   (cargo test)      │  │
│  └──────┬──────┘    └──────┬──────┘    └──────────┬──────────┘  │
│         │                  │                       │            │
│         └─────────┬────────┴───────────────────────┘            │
│                   │                                             │
│         ┌─────────▼─────────┐                                   │
│         │   Bridge          │  192.0.2.1                        │
│         │   (qemu-br)       │                                   │
│         └─────────┬─────────┘                                   │
│                   │                                             │
│    ┌──────────────┼──────────────┐                              │
│    │              │              │                              │
│    ▼              ▼              ▼                              │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐                          │
│ │tap-qemu0 │ │tap-qemu1 │ │tap-qemu2 │                          │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘                          │
└──────┼────────────┼────────────┼────────────────────────────────┘
       │            │            │
  ┌────▼────┐  ┌────▼────┐  ┌────▼────┐
  │  QEMU   │  │  QEMU   │  │  QEMU   │
  │ MPS2    │  │ MPS2    │  │ MPS2    │
  │ talker  │  │listener │  │  node   │
  │192.0.2.10│ │192.0.2.11│ │192.0.2.12│
  └─────────┘  └─────────┘  └─────────┘

IP Address Allocation

AddressDevice
192.0.2.1Host bridge (zenohd)
192.0.2.10QEMU node 0 (tap-qemu0)
192.0.2.11QEMU node 1 (tap-qemu1)
192.0.2.12+Additional QEMU nodes

Prerequisites

Install QEMU

sudo apt install qemu-system-arm

Verify Installation

just qemu check

Quick Start

1. Build QEMU Examples

just qemu build-examples

2. Run Tests (No Networking)

# Run all QEMU tests
just qemu test

# Run only LAN9118 driver test
just qemu test-lan9118

3. Setup Networking (For Full Stack Tests)

# Create TAP bridge (requires sudo)
just qemu setup-network

# Verify setup
just qemu status-network

4. Run with Networking

# Terminal 1: Start zenoh router
ZENOH_CONFIG_OVERRIDE='listen/endpoints=["tcp/0.0.0.0:7447"];scouting/multicast/enabled=false' ros2 run rmw_zenoh_cpp rmw_zenohd

# Terminal 2: Run QEMU with network
./scripts/qemu/launch-mps2-an385.sh \
    --tap tap-qemu0 \
    --ip 192.0.2.10 \
    --binary examples/mps2-an385-baremetal/rust/standalone/lan9118/target/thumbv7m-none-eabi/release/qemu-rs-lan9118

5. Teardown

just qemu teardown-network

Scripts Reference

scripts/qemu/setup-network.sh

Creates Linux bridge and TAP interfaces for QEMU networking.

# Create default setup (2 TAP interfaces)
sudo ./scripts/qemu/setup-network.sh

# Create with more TAP interfaces
sudo ./scripts/qemu/setup-network.sh -n 4

# Show current status
./scripts/qemu/setup-network.sh --status

# Tear down
sudo ./scripts/qemu/setup-network.sh --down

scripts/qemu/launch-mps2-an385.sh

Launches QEMU mps2-an385 with optional networking.

# Basic usage (no network)
./scripts/qemu/launch-mps2-an385.sh --binary app.elf

# With networking
./scripts/qemu/launch-mps2-an385.sh \
    --tap tap-qemu0 \
    --ip 192.0.2.10 \
    --binary app.elf

# With GDB debugging
./scripts/qemu/launch-mps2-an385.sh --gdb --binary app.elf
# Then: arm-none-eabi-gdb -ex "target remote :1234" app.elf

# Show full command without executing
./scripts/qemu/launch-mps2-an385.sh --debug --tap tap-qemu0 --binary app.elf

Justfile Recipes

RecipeDescription
build-examples-qemuBuild all QEMU examples
test-qemuRun all QEMU tests
test-qemu-basicRun basic serialization test
test-qemu-lan9118Run LAN9118 driver test
setup-qemu-networkCreate TAP bridge (sudo)
teardown-qemu-networkRemove TAP bridge (sudo)
status-qemu-networkShow network status
qemu-helpShow QEMU help

Available Examples

qemu-rs-test

Basic nros test on Cortex-M3 (lm3s6965evb machine, no networking).

  • Tests CDR serialization
  • Tests Node API
  • Uses semihosting for output

qemu-rs-lan9118

LAN9118 Ethernet driver test on MPS2-AN385.

  • Tests driver initialization
  • Tests smoltcp Device trait
  • Uses semihosting for output

qemu-rs-talker

TCP client example with smoltcp networking on MPS2-AN385.

  • Connects to a TCP server on the host (192.0.2.1:7777)
  • Sends 5 test messages
  • Demonstrates LAN9118 + smoltcp integration
  • Static IP: 192.0.2.10

qemu-rs-listener

TCP server example with smoltcp networking on MPS2-AN385.

  • Listens on port 7778
  • Echoes received data
  • Demonstrates TCP server pattern
  • Static IP: 192.0.2.11

Debugging

Using GDB

# Terminal 1: Start QEMU with GDB server
./scripts/qemu/launch-mps2-an385.sh --gdb --binary app.elf

# Terminal 2: Connect GDB
arm-none-eabi-gdb \
    -ex "target remote :1234" \
    -ex "load" \
    app.elf

Semihosting Output

All examples use semihosting for debug output. Output appears directly in the terminal where QEMU runs.

Common Issues

TAP interface not found

Error: TAP interface tap-qemu0 does not exist

Solution: Run just qemu setup-network

Permission denied on TAP

qemu-system-arm: -netdev tap,id=net0,ifname=tap-qemu0: could not open /dev/net/tun: Permission denied

Solution: Ensure TAP is owned by your user. Re-run sudo ./scripts/qemu/setup-network.sh $USER

QEMU not found

Error: qemu-system-arm not found

Solution: sudo apt install qemu-system-arm

QEMU version compatibility

The LAN9118 networking requires QEMU 7.0+ for full TAP networking support. On older versions (e.g., QEMU 6.2), the LAN9118 driver tests work but TAP networking may have issues.

Check your QEMU version:

qemu-system-arm --version

To install a newer QEMU version on Ubuntu:

sudo add-apt-repository ppa:canonical-server/server-backports
sudo apt update
sudo apt install qemu-system-arm

Hardware Details

MPS2-AN385 Machine

FeatureValue
CPUARM Cortex-M3
Flash4MB at 0x00000000
SRAM4MB at 0x20000000
EthernetLAN9118 at 0x40200000

LAN9118 Ethernet Controller

The lan9118-smoltcp crate provides a Rust driver for the LAN9118.

#![allow(unused)]
fn main() {
use lan9118_smoltcp::{Lan9118, Config};

let config = Config {
    base_addr: 0x4020_0000,
    mac_addr: [0x02, 0x00, 0x00, 0x00, 0x00, 0x01],
};

let mut eth = unsafe { Lan9118::new(config) }?;
eth.init()?;

// Use with smoltcp
let mut iface = Interface::new(iface_config, &mut eth, instant);
}

See Also