Running Rust and FreeRTOS on the PADI IoT Stamp

Now is the best time to experiment with low-cost, low-power IoT microcontrollers.

For under US$ 14, I can buy a tiny stamp-sized PADI microcontroller with ARM Cortex-M3 and built-in WiFi plus SPI, I2C and UART interfaces. And it comes with an SWD USB adapter for flashing and debugging. All set for building the latest and greatest IoT devices!

But where are the software tools for writing robust and reliable programs for microcontrollers?

Today my IoT students at Temasek Polytechnic are still writing Arduino programs in C++. Which is perfectly fine for toy programs but becomes a nightmare when you need to manage multiple sensors concurrently.

Some years back an IoT product I created started having problems distinguishing between Japan and Singapore networks. The country encoding scheme was defective all along! Clearly we need a better way to write safe programs for embedded systems.

In this article we’ll explore a better way to build and test programs for microcontroller platforms. Specifically we’ll look at Rust, FreeRTOS and Visual Studio Code. And how I made them run on the PADI IoT Stamp. Source code and detailed instructions are available in my GitHub repository:

Why Rust?

“The Rust project was initiated to solve two thorny problems:
How do you do safe systems programming?
How do you make concurrency painless?”

This quote explains perfectly the purpose of Rust. The biggest problem with C and C++ programming: Pointers. We can’t really be sure whether a pointer is referencing a valid object in memory. Or whether another function is attempting to dereference the pointer to an object that we have already deallocated. With microcontrollers we can’t afford to have safe pointers and automatic garbage collection that’s used in modern languages: Java, JavaScript, C#, Go, …

Rust performs pointer checking at compile time, not run time. It use some ingenious tricks for checking whether your pointers are really valid, without sacrificing any runtime performance. That surely helps in creating embedded programs that will run forever without crashing due to bad pointers.

Why FreeRTOS?

In the real world, embedded systems need to support multiple sensors and actuators. Doing this on a simplistic platform like Arduino will lead to very messy code or incredibly complex Finite State Machines.

With FreeRTOS we switch the microcontroller’s operating system to a Real-Time Operating System (RTOS) that’s open source. FreeRTOS is less efficient than Arduino for running a single task. But FreeRTOS lets us run multiple tasks concurrently while keeping our code clean and clear.

When we combine FreeRTOS (written in C) with Rust, we may exploit Rust’s concurrency patterns for writing concurrent programs painlessly. For this exploration we’ll use the excellent open-source freertos.rs Rust wrapper created by Rudi Benkovič:

Why PADI / Realtek RTL8710?

Two hardware platforms are popular for creating commercial IoT devices today:

  1. ESP32: Uses a Tensilica Xtensa configurable microprocessor. The ESP platform became popular when developers realised that they could write small microcontroller programs and embed them into ESP controllers, which were originally WiFi controllers.
  2. ARM: The ARM Architecture powers the vast majority of mobile phones and embedded devices today. Open source compiler and debugging tools are available, e.g. gcc-arm-none-eabi which we’ll be using here. Some people have speculated that ARM microcontrollers are more costly than ESP32 due to the licensing of ARM intellectual property.

The PADI is based on the Realtek RTL8710, a WiFi controller that’s functionally similar to the ESP32. However the Realtek RTL8710 includes a ARM Cortex-M3 microcontroller that’s more popular than the Tensilica Xtensa. We’ll use the PADI because it’s low cost (US$ 1.99 without the frills) and it offers the benefits of both ESP32 and ARM platforms.

Why Visual Studio Code?

Visual Studio has grown up and it’s no longer the huge and sluggish Integrated Development Environment (IDE) for Windows that it used to be. Visual Studio Code runs on Windows, MacOS and Linux, and works with virtually every programming language.

Visual Studio Code is the perfect IDE for teaching microcontroller programming because it’s open source, easy to use and has an enormous marketplace of extensions.

We’ll be using the Native Debug extension for Visual Studio Code to provide a friendly visual debugger for our Rust programs running on the PADI.

Rust + FreeRTOS + PADI + Visual Studio Code = Dependency Hell

Getting Rust and FreeRTOS to run on the PADI can’t be hard right? Wrong!

Thanks to the excellent open-source contribution by Zachary Tong, we had a version of Rust + FreeRTOS running on the PADI some years back.

Rust also has a helpful cross-compilation tool (xargo) that lets us compile PADI programs (32-bit ARM) on an Ubuntu PC (64-bit Intel). The problem: Too many shifting dependencies:

  1. JLink Issues: Zachary’s code assumes that we will be using the JLink software to flash the PADI. That no longer works, as explained here. I had to replace the proprietary JLink software by open-source OpenOCD. OpenOCD is really valuable for all embedded developers — please check it out.
  2. Upgrade to gdb_multiarch: Zachary’s code (and the Realtek RTL8710 SDK) uses the open-source debugger gdb-arm-none-eabi, which is now obsolete. I upgraded the PADI flash and debug scripts to use gdb_multiarch.
  3. Standardise on Ubuntu: For this exploration I standardised on Ubuntu 18.04 LTS x86 64-bit. We support two options: You could run Ubuntu directly on a PC. Or you could run Ubuntu on Oracle VirtualBox 5.2.12, hosted on Windows 10. This helps to trim down the dependencies for the time being and get it working.
  4. Visual Studio Code: Visual Studio Code wasn’t so popular some years back. And I needed a friendly developer experience to keep my IoT students engaged. So I used Visual Studio Code to dress up the PADI flash and debug scripts to present a decent visual interface.
Debugging the PADI with Visual Studio Code

Ready To Start?

You will need the following development hardware (total US$ 14):

  1. PADI IoT Stamp with Assembled PADI Breadboard Adapter
    https://www.pine64.org/?product=assembled-padi-breadboard-adapter
  2. PADI SWD Debugger: For flashing and debugging the PADI
    https://www.pine64.org/?product=swd-debugger
  3. PADI Serial Console: For interacting with the PADI serial console input / output
    https://www.pine64.org/?product=padi-serial-console
PADI with SWD Debugger (left) and Serial Console (right)

The SWD Debugger and Serial Console adapters need some assembly (refer to the instructions). Be prepared to plug in and plug out the adapter cables from the PADI quite often. I used sticky tape to help align the pins.

We’ll be running this sample Rust program on the PADI. It echos every character that you type.

Just follow the instructions here:
https://github.com/lupyuen/rustl8710/blob/master/README.md

What’s Next?

This is an experiment to see whether it’s feasible to teach embedded IoT programming using modern open-source development tools that will solve the headaches of IoT teachers and students everywhere: pointers and concurrency.

I welcome contributions to the open-source project to make it even more useful for IoT teachers and students.

BTW I have always dreamt about connecting a Sigfox breakout board to the PADI so that I can do away with the clunky Arduino sandwich that I’m now teaching (Arduino Uno + Sigfox Arduino Shield).

Anybody knows how we could create such a breakout board? Thanks!