In this new era of work-from-home, firmware engineers may not have all the equipment and development boards they are used to having at the office. One way around this? Emulation!
While they’re not quite the real thing, emulators can run firmware, print data over UART, read registers from CAN sensors, and even run a filesystem on a SPI flash device. That’s more than enough to write some real firmware!
What is Renode?
Renode is an open-source Emulator for embedded platforms. Today, it supports x86 (Intel Quark), Cortex-A (NVIDIA Tegra), Cortex-M, SPARC (Leon), and RISC-V based platforms.
Renode can take the same firmware you are running in production, and run it against emulated cores, peripherals, and even sensors and actuators. Better yet, its extensive networking support and multi-system emulation make it a shoe in for testing systems made up of multiple devices talking together.
With Renode, you can start development before your hardware is ready, test your firmware without deploying racks of hardware, and shorten your iteration cycles by cutting out flash loading delays.
Renode is built using the Mono framework, which allows it to run cross-platform.
Why not QEMU? - Readers who have experience with emulation will point out that QEMU has existed for a long time, and is capable of emulating Cortex-M targets. In our experience, QEMU is focused on emulating systems meant for higher-level OSes (e.g. Linux computers) rather than embedded devices. To date, it only supports two cortex-M series targets, both made by TI.
Launching Renode
Launch Renode by running the renode
command in your terminal. You should see the Renode Monitor prompt:
|
|
A monitor window will pop up, let’s start by creating a new machine.
Creating machines
In the beginning, the emulation is empty as there is no machine to run. In order to add an empty one, execute:
|
|
This creates the first machine, which, if you don’t give it a custom name, will be indexed from 0 (and thus called machine-0). This command also switches the Monitor’s context to this new machine.
Executing the same command again will create another machine, called machine-1
:
|
|
You can create a machine with a custom name by providing it as the argument:
|
|
To list all created machines together with their names and indices, type:
|
|
Switching between machines
When you want to switch the Monitor’s context to another machine type:
|
|
Instead of the machine’s name, you can use its index as well:
|
|
Loading platforms
Once a machine is created, it contains only one peripheral - the system bus called simply sysbus
. There is no memory or CPU, so the machine is not yet ready to execute any code.
To list all peripherals, execute:
|
|
To load a predefined platform (in this example, Microsemi MiV), type:
|
|
The format of .repl
(Renode platform) files is presented in the Describing platforms section.
Accessing and manipulating peripherals
When you are in the context of a machine in the Monitor you can reference peripherals by name. You can read and write a peripheral’s properties as well as execute some actions on them. The set of available properties and operations depends on the type of peripheral.
For example, to check memory size, execute:
|
|
To call an action on the peripheral, use the same syntax but replace Size
with the action name, e.g., ZeroAll
:
|
|
To get the complete list of available properties or actions, just enter the peripheral’s name:
|
|
The Usage
sections describe the proper syntax for accessing the peripheral’s features.
Loading binaries
Once the platform is created and configured, you can upload the software onto it. Renode allows you to run exactly the same executable as on the real hardware, which means there is no need to alter the binary or recompile the source.
In Renode, you can use local binaries or load them via HTTPS. If you do not have a binary at your disposal, you can use this sample Zephyr Shell sample for MiV.
To load a local .elf
file into memory, execute:
|
|
To load a binary via HTTPS:
|
|
Renode supports other executable formats like raw binary, UImage
and HEX
as well. To load them, use LoadBinary
, LoadUImage
or LoadHEX
accordingly.
Clearing the emulation
If you want to switch to another project, you can drop the whole emulation:
|
|
All machines, peripherals, and loaded binaries will be removed, and Renode will return to its initial state.