Up: Smart Plug

Previous: Smart Plug Prototype 2.0

Rust on Arduino

Last time we started writing some C code using the Arduino IDE. Arduino IDE provides a great interface, and it's an excellent way to get started writing embedded code. However, it has a drawback for me: I don't want to write in C. Instead, I would prefer to take this opportunity to learn Rust. Because Rust's run-time performance can be comparable to C and I've been wanting to learn it for a while, this seems like a really good opportunity to try it out.

While Rust does work on Arduino, not all device types are officially supported. Rust can compile to ARM architectures, and the Embedded devices Working Group has established a standard set of traits for unifying the interface between microcontroller implementations and device drivers.

I am using an Arduino Uno, which is not based on an ARM chip. Instead, it uses an ATMega328p, which has an 8-bit AVR architecture. Compiling to AVR is not officially supported by Rust. However, thanks to the work of the AVR Rust team, it is unofficially supported. Hopefully that “unofficial” caveat won't last long, with this upstream PR.

So being able to compile Rust to the AVR platform is great. However, there are still some things necessary before we can use it, the biggest being the ability to run drivers. Thanks to Embedded HAL, most drivers written in Rust are designed for a common interface. However, there has been no such chip implementation for HAL that would permit the program to mediate between the chip and the drivers. Until recently: enter AVR-HAL.

AVR-HAL is a very new project to implement the Embedded-HAL interfaces for AVR chips, so that a HAL driver can be used in a Rust program running on an AVR chip. Because it is so new however, it did not have everything I needed when I found it. Specifically, it lacked for support for a) the atmega328p chip (only supports atmega32u4), and b) no SPI support. SPI support is critical, as that is the interface of the w5500 (the Ethernet module I'm using).

So, because I really want to use Rust on this project, and I really wanted to dip my toes into actually writing useful Rust code and embedded development, I took it on myself to fill in the missing parts that I needed. This has the dual benefit of my learning, and other people being able to use my contributions to the project. So with much, much help from the original author, Rahix, I accomplished that.

Now at this point, it's fully possible to write a program, use Embedded-HAL drivers therein, compile for the AVR architecture, and flash to an Arduino Uno. To do all of that, you'll need to do quite a bit of set-up.

  1. Install Rustup: https://www.rust-lang.org/tools/install
  2. Install Xargo: https://github.com/japaric/xargo (used for making sure the Rust Core is compiled to AVR)
  3. Download and compile the official AVR toolchain provided by Microchip: https://www.microchip.com/mplab/avr-support/avr-and-arm-toolchains-c-compilers (required component for use by AVR-Rust) 3: Download and compile AVR-Rust fork: https://github.com/avr-rust/rust (for cross-compiling to AVR)
  4. Download and install AVRDUDE: https://www.nongnu.org/avrdude/ (used to flash programs to microcontroller)

Once that setup is complete, you can write and flash Rust to your Arduino Uno:

An example repo that can do all of these things is here.

  1. Write a program that depends on avr-hal project (not yet on Crates.io as of posting)
  2. Compile to an ELF file using Xargo: https://github.com/avr-rust/blink (example of a program that is compiled to Arduino with Xargo 3: Generate Intel Hex files from ELF (required by AVRDUDE): https://www.microchip.com/webdoc/AVRLibcReferenceManual/group__demo__project_1demo_ihex.html 4: Flash program to board with AVRDUDE: https://forum.arduino.cc/index.php?topic=417659.0

Now that all of these base requirements are complete, next up I'll be writing a UDP server in Rust in order to re-implement the original POC without the Beaglebone.

Next: W5500 Driver for Rust Embedded-HAL on AVR

Creative Commons License