For a change of pace, I have been learning embedded development using Rust in my spare time, which has been an exciting challenge. A core component of my project is to have two devices communicating wirelessly, and (at the time I started working on this) there were no “no-std” Rust Bluetooth crates available. So I started to write my own. I had already chosen to work on the Nucleo, and to use the IDB05A1 shield, which contains a BlueNRG-MS module.
Posts about using Rust on embedded systems. Including microcontrollers, IoT, and devices.
It is an exciting time to be working in embedded Rust. After writing my first driver, I mostly had the feeling that for driver writers there was a clear expectation and an obvious standard for how things should be done. My experience writing this driver, which uses I2C rather than GPIO, exposed me to a few topics of active discussion within the embedded Rust working group which I hadn’t seen before.
At the time of writing the previous blog the plan was to target the Raspberry Pi 3 (Cortex A53) as a development platform because of its availability, popularity and community. Sadly, it seems that Broadcom went through a lot of shortcuts while implementing this specific design, which means features like GIC are half-there or completely missing, like in this case.
After a discussion with @microcolonel, he proposed and kindly sent me a HiKey960 reference SoC from the awesome Linaro 96Boards initiative. The quality of this board is definitely a lot better than the Raspberry Pi and the documentation is detailed and open. Great stuff.
Here is a small walkthrough, on how to use Mac OSx, Linux or even Windows (hey not tested but I am sure you can make it work, the tools are the same) to compile your Rust marvellousness and run the binary directly on the Raspberry Pi (2/3/3+).
TL;DR: Up to now, I haven't had as much time or motivation as I would have like to contribute to the Embedded Rust Book. However, I am excited to see the initial version of the book launch with the 2018 edition of Rust (which will ship with stable support for embedded)!, so I will be committing to write one chapter per two weeks, until the end of the year.
Read below for my plan, and how you can help!
In a previous blog post I described how to get a very simple Rust program compiling for and running on the BetaFPV F3 drone flight controller. Since that time I’ve been working to create a board support crate to provide a high level API for the board.
Beginning of this year I wanted to experiment with some embedded development. I ended up looking into Ledger cryptocurrency hardware wallet application development. I wouldn’t actually consider this true embedded development as a lot of the heavy lifting has been done and abstracted away by Ledger, but it’s still writing software for a very constrained environment. Ledger applications only get 4KB of RAM to utilise and most of the embedded development practices still apply (no heap allocations for instance).
A couple of months ago I moved to a house, and the need to monitor-all-the-things guided me towards the affordable IKEA Sparsnäs energy display. Sparsnäs is made up of two parts, one being the transmitter that is attached to your electricity meter, and the other; the display that stores usage, and presents a variety of graphs. The downside is that there is no way of getting the data out of the display so you have to accept how it’s presented, and that it may get lost, or build something on your own. Thankfully the protocol has been thoroughly reverse engineered and documented in a very elaborate manner.
After many laborious hours of reading and interpreting the various online references, I've published the first release of my latest project, a crate to safely abstract Raspberry Pi's platform-specific features in Rust. I've (very creatively) named it Rustberry, and it's finally stable and clean enough that I'm able to publish it and receive initial feedback.
We recently had the opportunity to make a Visual Studio Code extension that needed to communicate with an embedded device. This post explains the architecture we chose to achieve that and the decisions that led to it.
It's a couple of months on from my talk at RustFest on Monotron, so I thought it was worth a quick catch up on where we're going next. As a recap, Monotron currently generates an 800 x 600 VGA signal at 60 Hz (with a pixel clock of 40 MHz). It does this using three synchronised SPI peripherals, a timer generating the horizontal-sync pulse and a GPIO pin for the vertical-sync. With the CPU running at a clock speed of 80 MHz, the SPI peripherals are clocked at 20 MHz producing 400 horizontal pixels per line. This is half the nominal 800 pixels, but we needed to sacrifice resolution to double the amount of CPU time we have to 4 clocks per pixel (i.e. 32 clocks per 8-bit character column).
This is just a small build script to automatically compile and create Rust binaries for your i86 32 and 64 bit machine and your Raspberry Pi(ARM) with Travis-CI. On the right side I added a little explanation of the following script.
A couple of months ago I released the rust_gpiozero¹ crate. It is a port of the GPIO Zero² library by the Raspberry Pi Foundation. The library provides a simple interface to control GPIO devices with a Raspberry Pi. Following this, recently ported the Raspberry Pi Foundation’s Physical Computing with Python³ guide for Rust.
One of the most exciting areas of hobbyist embedded programming, in my opinion, is flight controllers for remote controlled aircraft. In the particular case of a multi-rotor drone, the flight controller is responsible for converting the UP command from the transmitter into specific outputs for each of the motors. Maintaining the stability of a drone involves carefully adjusting the output of each motor thousands of times per second based on feedback from on-board sensors.
There are several great C-based open source drone flight controller firmware projects, but as far as I can see there are none written in Rust. The good news is that most drone flight controllers are based on STM32 MCUs, which Rust has strong support for. Robust flight controller firmware is quite complex, and there are a number of challenges to be solved before even getting the rotors spinning. The first of those challenges is building a Rust project for a particular flight controller board, and flashing the board with the compiled code. A single blinking LED is our goal for today.
Customized Linux distribution and a safe systems programming language sounds like a very interesting combination for embedded development. That is what makes Yocto and Rust such a good match. So, I wanted to see how Rust projects could be cross-compiled with Yocto-generated toolchain and root filesystem. The steps are described in this post.
All excited. A first calendar entry to describe my attempt on arm64 support in Redox OS. Specifically, looking into the Raspberry Pi2/3b/3+(all of them having a Cortex-A53 ARMv8 64-bit microprocessor, although for all my experiments I am going to use the Raspberry Pi 3b.
Thermometer adventure continuous with some progress over the last weekend. Little bit of refactoring, rewiring, X.org, matchbox, Piston, ... and some ugly (but working!) UI :)
I’ve decided to build a thermometer from scratch. I know, I can buy it, but it’s not fun. I found it as a perfect occasion to please my wife (she wants it) and to try new things. What new things? Mainly resin.io and resinOS.
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.
Bobbin SDK is a suite of tools and code that has been used in embedded development projects running on a variety of ARM Cortex-M MCUs over the last year and a half. It exists to bridge the gap between the existing Rust ecosystem centered around svd2rust and rich but proprietary vendor SDKs.
I've been playing around with the idea of running a neural network on a micro controller. This project is not designed to be the most efficient neural network, but rather one that runs on a micro controller with very limited resources.
Microcontrollers typically use memory-mapped I/O interfaces to control hardware peripherals. Driver code uses these memory-mapped registers and fields to interact with the peripheral while providing a higher-level interface to the rest of the system. This post describes how Tock deals with register memory maps and a new tool that can automatically generate memory maps for many ARM microcontrollers.
First of all, low level stuffs such as peripheral drivers should be hidden from the application developer. They should not be able to access directly the registers and mess with the peripheral states/control. The wrong flag in the wrong register can lead to dramatic failures and even damages to the products.
I am giving embedded systems another go with a side project of mine. The device has a single purpose. It captures network packets, and forwards them to a server. It is easily achieved with LIBpcap, but the device makes it interesting.
The GL-AR150 sells as a mini smart router. The limited storage makes it hard to install language interpreters, or virtual machines. This pushed me to look into standalone executables, and how to compile them for other devices.
Here I will document the steps to get started with STM32VLDISCOVERY board. We will take my favourite “from scratch” approach. That way, we build the final thing step by step while building our understanding of how it all fits together.
c3r3s is a tiny (1KB binary) serial bootloader for loading "bare metal" 64-bit kernels on the Raspberry Pi 3. You can iterate on your own kernel code without constantly moving the SD card back and forth.
Flipper is a new kind of development board that redefines the embedded software development cycle by offloading development/debugging into higher level languages + tools. One of the languages that we're putting the most focus into adding support for is Rust. We would love to see more embedded done with Rust and Flipper provides a great springboard for existing Rust developers to familiarize themselves with embedded hardware using the tools they already know how to use.
I will try to publish here a series of articles about my approach to embedded development and how I plan to achieve that in Rust.
Another topic of discussion at the Berlin Rust All Hands was the long-term story around Cargo, Xargo, and Rustup. The latter two tools are both involved in managing your Rust toolchain, with Xargo allowing you to build custom stds and Rustup managing pre-built artifacts for mainstream targets. Xargo is most commonly used for cross-compiling to less common platforms, but can also be used to customize the standard library on mainstream platforms.
At the recent 2018 Rust All Hands, I met up with Katharina @spacekookie, who works on an open source project that creates software for Embedded Linux Devices. She had talked with the other engineers on the project about including some Rust components, however with their limited flash storage space (8MB for the whole firmware, including operating system and all other software), she was worried that the Rust binaries wouldn’t fit. The current webserver component for their project was measured in the 100’s of KB, while the Rust binary she produced was already multiple MBs, even with a --release build!
After the MCP3425 ADC driver I published last month as part of the the weekly driver initiative, I wrote a second Rust embedded-hal driver, this time for the SGP30. The Sensirion SGP30 is a tiny low-power gas sensor (produced in Switzerland) for indoor air quality applications with good long-term stability. It has an I²C interface with TVOC (Total Volatile Organic Compounds) and CO₂ equivalent signals.
This post will document my process and thoughts on writing a driver for a bluetooth module using Rust and the embedded-hal crate. The specific bluetooth device I will be using is the RN4870 BLE castellated module. It features a simple UART interface and handles most of the complexities of BLE itself, making it very easy to get a simple BLE connection up and running.
This post describes the recently merged PeripheralManager, which helps software ensure it always accesses hardware correctly, and cleans up after it’s done.
ST Micro’s HTS221 is a “capacitive digital sensor for relative humidity and temperature” that can be used over either I²C or SPI. It is factory-calibrated, so there is no end-user calibration to incorporate into your application. The driver provides a simple, high-level API to configure the chip once on startup, then read the temperature and humidity.
A new generation of safe programming languages is leaving garbage collectors and runtimes behind, delivering memory safety and control.
We silently tag our first rolling release of the Tock kernel in February. If you’re building applications with Tock or porting to a new board, and want to be immune from updating your code everyday, you can work from that tag. We’ll also upload binary kernel images for the supported board sometime soon.
Announing the MCP3425 Rust driver.
This week I’m releasing a driver for the ENC28J60, an Ethernet controller with SPI interface. This IC lets you connect your microcontroller, if it has a SPI interface, to a Local Area Network or, with more work, to the internet. Apart from the IC you need a RJ45 connector and a few other components so I’m using this module which has the ENC28J60 and all the required components on a single board.
For the embedded portion of my project, I had two decisions to make: which processors and chips to use, and which language to write the firmware in. Since this personal project is about learning new skills, I decided to use Rust instead of C. I opted to use STMicro’s Nucleo boards, since their ecosystem has shields that do all of the things I would like (WiFi, BLE, and environmental sensing), and there was also a great Rust tutorial for a similar board. However, since I’ve never really done any embedded development, I decided to start with the old standby: copying code off the internet!
Mid January japaric started "The weekly driver initiative" with the goal to kick-start releases of platform agnostic embedded-hal based driver crates. In this post we'll build an embedded-hal-driver for the AT24C32-EEPROM chip.
This is an mdbook I wrote more than a year ago for a workshop and it's an introductory course to embedded systems that uses Rust as the teaching language. I just updated the starter code to use the latest versions of everything so it's now easier to jump from the book to use the latest developments in the Cortex-M ecosystem; there's no new content, though -- the exercises remain unchanged in terms of goals; just the code has changed.
This is a transcript of a talk I gave at the Vilnius Rust meetup.
It would not be an exaggeration to say that embedded is omnipresent. You can find embedded firmware everywhere from fridges, microwaves and personal computers to safety-critical applications in automotive, medical fields, etc.
Most of this software is still written in C or C++, and neither of these, given their non-ideal track record in relation to security critical software, are the most confidence inspiring choice for safety-critical systems.
In my experience, bugs occurring in embedded firmware tend to be fairly similar to those commonly found in the user-space software.
Here is how a device like an accelerometer works: you send the device commands over a serial interface (SPI, I2C), say something like: “get me the X-axis reading”; the device responds by sending back some data.
The way the SPI/I2C/GPIO (and other) interfaces are programmed is very much dependent on the specific microcontroller family. But the actions you need to perform to interface with a device like a temperature sensor / accelerometer etc depend only on the device and are independent of the controller being used. What if you can write a generic accelerometer driver and use it on any microcontroller platform - right from low-end ARM Cortex-M, AVR, MSP430 etc to complex Embedded Linux platforms like the Raspberry Pi? What if you can distribute these drivers on crates.io so that you only have to include one line in your Cargo.toml to use it in your code?
My first attempt at Rust programming was the stellaris-launchpad crate. This has a few demos that either blink the LED or roll it through an RGB rainbow using the PWM timers. Recently I've started a new version of the lm4f120 crate called tm4c123x-hal. The name change reflects TI's new name for basically the exact same part, while the -hal indicates that it's based upon the output of svd2rust and @japaric's new Embedded Hal crate. At the same time, I was watching videos on Youtube about a new wave of 1980's style 'retro' computing boards - text output, BASIC interpreter, etc. An idea started to form that I could put all three of these things together.
Covering: Why Rust on Microcontrollers, Level 1: Direct register access in an unsafe block, Level 2: No unsafe blocks, use the API provided by svd2rust, A problem, Level 3: The embedded HAL to the rescue, Level 4: Use a board support crate.
Oh, time flies. It’s already week 8 and we have zero weekly driver posts out there – don’t worry though because there’s plenty of drivers and embedded-hal implementations in the works. To play catch up in this post I’ll cover two embedded-hal drivers: the l3gd20 and the lsm303dlhc. The L3GD20 is an IC that contains a gyroscope and exposes I2C and SPI interfaces; the LSM303DLHC is an IC that contains an accelerometer and a magnetometer, and exposes an I2C interface. You can find these two ICs on the STM32F3DISCOVERY board.
One of the core features of Rust is memory safety. Whenever possible the compiler enforces memory safety at compile. One example of this is the borrow checker which prevents data races, iterator invalidation, pointer invalidation and other issues at compile time. Other memory problems like buffer overflows can’t be prevented at compile time. In those cases the compiler inserts runtime checks, bounds checks in this case, to enforce memory safety at runtime. What about stack overflows? For quite a long time Rust didn’t have stack overflow checking but that wasn’t much of a problem on tier 1 platforms since these platforms have an OS and a MMU (Memory Management Unit) that prevents stack overflows from wreaking havoc.
A blog about Rust and embedded stuff
Notes on Code, by Pramode C.E
There’s been a lot written about what can be done to make Rust’s tooling, libraries and infrastructure better for embedded programming, but I’d like to cover a slightly different topic: what can be done to make Rust the language itself safer and easier to use for low-level programming?
Hi there! I'm Nico, and I've been lurking around these parts for about a year now. I thought I'd give my 2 cents on Rust's 2018 plans. Note: this...
A blog about Rust and embedded stuff
I recently picked up an embedded project that I hadn't touched for a few months, so I could add some new features. I was disappointed to not...
Robotics developers face two main problems: