Written by Michael Gielda, Zephyr Project Community Member and Business Development and Board Member for Antmicro
If you’re working with multi-node Internet of Things (IoT) systems, you probably have experienced problems related to testing, security, interoperability, reuse, lifecycle management, and code quality involved in building real-life networks.
To address these problems, new tools and workflows are needed that allow developers to collaborate around code more effectively. These tools and workflows must increase the test coverage and understanding of the software and protocols running on the devices that form the backbone of our homes, offices, factories, and cities, both now and in the future.
The open source Renode framework from Antmicro, which started a collaboration with the Zephyr project in 2017, is aimed at doing exactly that: Renode lets you simulate complex wireless (and wired) setups running real binaries so that you can do testing, continuous integration, and debugging to an extent that wasn’t possible before.
Sound promising? We hope it does. And it’s not as complex as it sounds. In this blog note, we’ll explain how Renode can help you in your daily development without forcing you to rewrite your software or abandon your familiar toolset.
Renode can simulate physical hardware systems – including the CPU, peripherals, sensors, environment, and wireless medium between nodes. Just develop your IoT software, including software based on the Zephyr RTOS (real-time operating system) using your familiar processes, and then use Renode to debug and test it in various circumstances. The tests includes protocols and applications that span multiple nodes. You can run them in a joint virtual environment with full determinism and control over the execution parameters.
For example, at the 2017 Embedded Linux Conference (ELC) Europe, the Renode and Zephyr teams jointly showcased a fairly complex simulated wireless setup. With nodes based on two architectures (x86 and ARM) and running two different RTOSes (Zephyr and Contiki), the demo showed how easy it is to perform interoperability testing with Renode.
In this note, we’d like to focus on how a simple multi-node setup can be reproduced from the comfort of your chair. This short tutorial can act as a starting point for your development with Renode and Zephyr.
The Renode framework is hosted on GitHub - https://github.com/renode/renode. You can use the README file to download and install it, but the easiest way to start is by downloading a binary release from https://github.com/renode/renode/releases. The precompiled packages are provided as deb and rpm packages for Linux, a dmg package for macOS, and a zip archive for Windows.
This tutorial uses the Renode command line interface, which is one of many ways to interact with Renode. After installation, run the renode command. Alternatively, look for the Renode.exe binary. Once Renode is started, you will see two windows: one for Renode’s smart logger (you can control what’s being logged) and one for the command line interface (CLI) called the Monitor.
From this CLI window you can create and control the whole emulation environment.
While you can type all commands interactively, it’s a good idea to group them into reusable Renode scripts, which typically have the .resc extension. The scripts can be used to load binaries, set starting conditions, prepare the environment, connect machines to the network, and other tasks.
This tutorial uses scripts available in the Renode package named: scripts/many-nodes/quark-c1000-zephyr/demo.resc and scripts/many-nodes/quark-c1000-zephyr/quark_c1000.resc. For details on the scripts, please review the commented files in the Renode installation directory. (For Linux, opt/renode/scripts is the default.)
Loading our setup
The tutorial setup consists of two Intel Quark C1000 nodes with a TI CC2520 radio connected via SPI. The nodes run applications based on Zephyr demos, an echo_server and an echo_client, compiled as normal for the target hardware. (The provided scripts use precompiled binaries hosted online, but you can provide your own binaries by changing the relevant $BIN variable in the scripts.)
In Renode, the nodes are assigned coordinates in a virtual 3D space. By manipulating the maximum range of the wireless medium or moving the nodes around, we can put them in or out of each other’s range, and form different topologies, building routing scenarios of various complexity. In this simple example, the nodes are within each other’s range and we won’t move them around or make them lose packets.
To run a script, use the include command (or i, for short), with a path to the script to load, prepended with the @ sign, like this:
After the script is loaded, you will see two new terminal windows. These are UART windows opened for each machine.
The emulation is now loaded, but not started. You can control it using start and pause and other commands that are described in the next section.
- Start and pause
To control whether the simulation is running, use start and pause.
- Start and pause
All peripherals are accessible in the Monitor, with most of their methods and properties exposed to the user. To list all available peripherals, use the peripherals command.
- Peripheral methods and properties
To access a peripheral, you have to provide its path. All peripherals are registered in sysbus, so use sysbus.uartB to access the second UART or sysbus.spi1.radio to access the CC2520. The using sysbus command is used in most of the provided demos, allowing you to drop the sysbus. prefix. Typing a peripheral name gives you a list of available methods, fields, and properties. The list is automatically generated, and most of the accessible members are not designed for the end user. The list shows examples of correct Monitor syntax for each member type.
To find information about built-in Monitor commands, type help and refer to the documentation. Running help
prints out the help for the given command.
In the provided scripts, we use the mach create command to create new machines. This switches the context in the Monitor. All subsequent commands are executed with regard to the current machine.
To change the machine, use the mach set command. Use a number or the name of the machine, for example, mach set 1 or mach set servername.
All machines can be listed with the mach command. To clear the current selection, use mach clear.
Renode provides many ways to verify the behavior of your applications. Thanks to having full control over the environment, you can add logging, hooks on events, interactive code debugging, and more in a way that is completely transparent to the emulated application. Since this is a simple tutorial, only a few debugging options are listed below, however, many more are available.
- Function name logging
When the application is stuck or misbehaves, it is a good idea to inspect the trace of function calls. To enable logging of function names in a selected machine, run cpu LogFunctionNames true (use false to disable it). Since the amount of logged data may be too overwhelming to be useful, you can filter the logged functions to the ones that begin with a specified prefix. For example cpu LogFunctionNames true “uart_ qm_” only logs functions that begin with either the uart_ or qm_ prefix.
- Logging of peripheral accesses
If your driver does not behave correctly, it may be beneficial to investigate communication with the device it controls. To enable logging of each interaction between the CPU and the UART peripheral, run the sysbus LogPeripheralAccess uartB command. This feature is available only for peripherals registered directly on the system bus.
Network traffic analysis is a common task in every multi-node system. Since Wireshark is a tool of choice for programmers, Renode supports it for both Ethernet and wireless networks. There are multiple options for choosing which interfaces should be logged, but the easiest way to observe all packets in an IEEE 802.15.4 network is to run the emulation LogWirelessTraffic command.
This command opens a new Wireshark window. If you close it, you can always reopen it by running host.wireshark-allWirelessTraffic Run.
- GDB (GNU Project Debugger)
A popular tool for debugging, GDB can be used to analyze applications running in Renode. It uses the same remote protocol as OpenOCD, so it can be easily integrated with most GDB-based IDEs, such as Eclipse. To start a GDB stub in Renode, run cpu StartGDBServer 3333 (where 3333 is a sample port number) and connect from GDB by calling (gdb) target remote :3333. To start the emulation, you have to run both start in Renode and continue in GDB.
You can use most of GDB’s regular features: breakpoints, watchpoints, stepping, reading/writing to variables, etc. You can also use the monitor command in GDB to send commands directly to the Renode CLI, to avoid switching between two console windows.
We hope that this short tutorial will help you get started with Zephyr and Renode, which has recently become one of Zephyr’s recommended developer tools: https://www.zephyrproject.org/developers/developer-tools/.
In a future blog post we’ll continue this tutorial with details on more complex wireless setups – stay tuned!
RenodeTM is a software development framework from Antmicro, a technology company building software-driven IoT systems. If you need help with implementing your platforms and setups in Renode, adopting a Continuous Integration workflow inside your organization, integrating with your tools or building custom ones, or IoT system development services using the Renode methodology, please contact them at firstname.lastname@example.org.