I want to learn more about bare metal MCU programming. So I came with a crazy idea: instead of emulating webassembly, let’s emulate a RiscV MCU in serverless style.

REST API

Serverless means HTTP REST usually. Let’s have a very simple API.

PUT /mcu
> ...  ROM binary ...

GET /mcu
< ... ROM binary ...

POST /mcu
> ... IN binary ...
< ... OUT binary ...

Each call has 2 optional params : /mcu[/rom-uuid[/ram-uuid]].

They represent the ROM and the RAM. The ROM is autogenerated after a PUT and the RAM is autogenerated after a POST. The UUID are sent via Set-Cookie headers. This enables to transparently benefit of those, since the parameters are also picked from cookies.

URL parameters obviously have precedence over cookie ones.

The RAM uuid enables to chain multiple calls. Think of it as a session. Per default it is all zero initialized.

There is no encoding of binary content, as the HTTP layer takes eventually care of it. So TLS and Deflate are possible, even recommended.

HTTP Server

I went the simplest road ever : CGI.

Actually lighttpd and /bin/sh. Those setup the ROM, RAM and IO. Then they delegate to rv32im for the real execution.

rv32im Emulator

Launching is very easy.

rv32im /rom.file /ram.file /io/in.file /io/out.file

The ROM and IN file are R/O, the RAM is R/W and the OUT file is W/O.

The idea being that everything can be mmap inside the emulator address space so it offers nice memory protection, along with adequate performance since no copy takes place.

The emulator can then use those files in place and not worry about the filesystem. It is up to the caller to have correct file sizes.

Initial size is 32MiB for every file. The files are zero-padded or zero-truncated.

The number of CPU cycles is also capped, along with the maximum execution time. As soon as the POWER DOWN sequence is started or timeout happens, execution is stopped and the reply is sent.