Skip to content

Latest commit

 

History

History
179 lines (130 loc) · 8.14 KB

File metadata and controls

179 lines (130 loc) · 8.14 KB

netmsg

A reusable kit for driver-development labs in embedded systems courses: a custom QEMU virtual MMIO device, a driver skeleton, and a minimal HTTP backend.

What's included

  • qemu/vpos_netmsg.c — a SysBusDevice that emulates netmsg's register interface and translates POST/GET commands into HTTP requests to the lab server.
  • driver/netmsg.h — register definitions and the public driver API.
  • driver/netmsg.c — a fill-in-the-blanks driver source for students.
  • server/es.js — Express router that implements the backend protocol.
  • server/app.js — minimal server entry point that mounts the router.

The reference driver implementation and the original lab handouts are not included. They are kept private so the kit remains usable as a graded lab; instructors who adopt the kit are expected to author their own reference solution.

Architecture

+--------------+      +------------------+      +----------------------+
| VPOS shell   | ---> | netmsg driver    | ---> | MMIO registers       |
| (post / get) |      | (vh_netmsg_*)    |      | (CTRL/STATUS/...)    |
+--------------+      +------------------+      +----------+-----------+
                                                           |
                                                           v
                                            +------------------------------+
                                            | QEMU device (vpos_netmsg.c)  |
                                            | - register read/write        |
                                            | - command dispatch           |
                                            | - HTTP client                |
                                            +--------------+---------------+
                                                           |
                                                           | HTTP
                                                           v
                                            +------------------------------+
                                            | Backend server (server/)     |
                                            | - stores per-id messages     |
                                            +------------------------------+

The diagram assumes a VPOS-like RTOS environment, but netmsg is intentionally minimal: the device exposes a plain MMIO register interface, and the driver layer can be reimplemented for any environment that can issue MMIO reads and writes.

Design

A few choices are worth noting, since they were made specifically to expose students to ideas not commonly seen in self-contained microcontroller labs:

  • MMIO register interface instead of UART or virtio. Students reason about what each register is for and design their driver around device state, rather than reusing familiar character-device patterns.
  • Polling-based status interface. The driver loop checks STATUS.BUSY, STATUS.RX_READY, and STATUS.ERROR explicitly. This teaches the BUSY/READY/ERROR state machine without the added complexity of interrupt handling.
  • HTTP backend. A command issued at the shell results in a real network round-trip to a remote server. The intent is to show that a device driver is the interface between a software abstraction and an external system, not a self-contained simulation. Students can verify their driver by posting a message from one machine and retrieving it from another.

Register interface

Base address: 0x0A100000. All register accesses are 32-bit.

Offset Register Direction Bits
0x00 NETMSG_CTRL R/W bit 0: EN, bit 1: CLEAR
0x04 NETMSG_STATUS R bit 0: BUSY, bit 1: RX_READY, bit 2: ERROR
0x08 NETMSG_ID R/W bit 0–31: target message ID
0x0C NETMSG_CMD R/W bit 0: POST, bit 1: GET
0x10 NETMSG_DATA R/W one byte per access; string transfer

NETMSG_DATA is accessed one byte at a time; the device maintains internal TX and RX buffers.

Backend protocol

The QEMU device makes plain HTTP requests to the lab server when a command is dispatched.

POST /es/messages
Content-Type: application/json
Body: {"id": <uint>, "message": "<string>"}
Response: 200 OK with {"ok": true, "id": <uint>, "length": <uint>}
GET /es/messages/{id}
Response: 200 OK with the message in the response body (text/plain)

The reference implementation in server/es.js uses in-memory storage, so messages are lost on restart. Persistent storage can be substituted by replacing the backing Map without touching the protocol.

Setting up

The kit has four pieces: the backend server, the QEMU device, the driver, and the shell commands.

1. Run the backend server

cd server
npm install
node app.js

Any host reachable from QEMU works for the lab — a course VM, a small VPS, or a host on the same LAN as student machines. The server listens on port 3000 by default; override with the PORT environment variable.

2. Patch QEMU

Place the device source under hw/misc/ and add it to the build:

cp qemu/vpos_netmsg.c <qemu-source>/hw/misc/
echo "system_ss.add(files('vpos_netmsg.c'))" >> <qemu-source>/hw/misc/meson.build

Update the backend address. Open vpos_netmsg.c and edit the following macros to point at the server you deployed in step 1:

#define HTTP_HOST       "your-server.example.com"
#define HTTP_PORT       3000
#define HTTP_POST_PATH  "/es/messages"

Register the device in the ARM virt machine. In <qemu-source>/hw/arm/virt.c, inside machvirt_init, add the following block after fdt_add_pmu_nodes(vms);:

{
    DeviceState *dev = qdev_new("vpos-netmsg");
    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x0A100000);
}

Build QEMU with the ARM target:

./configure --target-list=arm-softmmu
make -j"$(nproc)"

3. Add the driver to the guest

Copy driver/netmsg.h and driver/netmsg.c into the guest source tree (in the original course, vpos/include/ and vpos/hal/io/ respectively) and add netmsg.c/netmsg.o to the build.

Students implement the TODOs in netmsg.c. The header lays out the public API (vh_netmsg_init, vh_netmsg_post, vh_netmsg_get); the skeleton comments walk through the expected register sequence.

4. Hook up shell commands

Add post and get commands to the guest shell that call the driver. With everything in place, the commands become usable from inside the guest:

Shell>post 1234 Hello_world!
netmsg post success (id=1234, msg=Hello_world!)

Shell>get 1234
netmsg[1234] = Hello_world!

Adapting to a different course

Most of the kit is independent of any particular RTOS. To use netmsg outside the original VPOS context:

  • Backend runs unchanged; just deploy it somewhere reachable from QEMU.
  • QEMU device runs unchanged; only the HTTP_HOST / HTTP_PORT macros need to be updated.
  • Driver needs to be ported. The header defines a minimal three-function API (vh_netmsg_init, vh_netmsg_post, vh_netmsg_get) that maps directly onto the register interface; any environment that can do MMIO can implement it.
  • Shell commands can be replaced with whatever invocation surface the target course uses (a user-space CLI, a test program, etc.).

Repository layout

netmsg/
├── README.md
├── LICENSE
├── qemu/
│   └── vpos_netmsg.c     # QEMU virtual device
├── driver/
│   ├── netmsg.h          # register definitions and driver API
│   └── netmsg.c          # student skeleton
└── server/
    ├── es.js             # Express router for the backend protocol
    ├── app.js            # minimal server entry point
    └── package.json

Credits

Designed and implemented by Jeongin Yeo as part of the Embedded Systems Design course at Hanyang University. Practice sessions were co-conducted with Jinho Shin.

License

GPL v2.