In this part 1 of 2 posts, I share the process of a heartwarming maker project built on top of Raspberry Pi and Rust. It's more a story than a how-to guide, but provides an interesting chronology of problems encountered. In part 2 I'll be getting technical and discussing Rust in-depth.
EmbeddedRust on microcontrollers, IoT, devices.
During last episode, we went on a tour of the pleasantly boring world of flash memory, drafted some driver interfaces, and toyed with the idea of generics at both levels of crate visibility. What's conspicuously absent is, well, working code. It's one thing to lay down data structures, and another entirely to weave generics between the raw ones and zeros of bare metal firmware. Today we'll gaze long into the void*, and, hopefully, the void* won't gaze back into us.
We're happy to announce the newest crate published as part of our knurling project: panic-probe.
panic-probe is a simple panic and fault handler that integrates into probe-run, our host-side tooling for embedded programs. When using panic-probe in your firmware, probe-run will detect both Rust panics as well as HardFaults raised by the Cortex-M processor, and exit with an error code after printing a stack backtrace.
I often got interested by Arduino’s because of some specific problems they can solve, like: programming your thermostat for instance, automate your house, etc… When I first heard of it a friend of mine gave me some hardware so I can experiment. Unfortunately I never really managed to get into it mainly because it was not what I imagined. Coming from a “Python Developer” background, doing C/C++ felt really bad and using an IDE in Java felt like I had no control or no idea of what I was actually doing.
But ~2 years ago I’ve discovered Rust and it changed completely my career. Rust quickly became my favorite programming language and it allowed me to explore new horizons. The news did reach me when I heard it is coming to embedded development and I decided recently to give it a real shot. Not because I needed anymore, but just because I could.
Arduino and embedded development in general are not easy to grasp as you need general knowledge in electronic engineering: what is a resistor, how to measure things, what happens if I measure from here to there, how do I even find the information about what am I supposed to connect where. But on the other hand it is important to say that Arduino did make everything very easy and accessible to anyone… (if you don’t mind C/C++ and an opinionated IDE.)
This is the 25th newsletter of the Embedded WG where we highlight new progress, celebrate cool projects, thank the community, and advertise projects that need help!
As a note, some of these stories have happened over the past months. We're still working on catching up, but wanted to share them with you!
Today we are thrilled to announce the public release of defmt ("de format"). defmt stands for "deferred formatting" and it's a highly efficient logging framework. As we covered in our blog post about embedded tooling for the 21st century we hope defmt will serve as the base for features like data visualization and interactive logging front-ends. In this post we'll cover how to use defmt with probe-rs supported devices and what you can do with defmt today.
At the time of writing this, about a month ago, the rust-avr fork was merged upstream. This means that you can now compile Rust programs for the avr microcontroller board by just running cargo +nightly build, providing a .cargo/config.toml for your target (avr-unknown-unknown). That's huge!
I have always been fascinated with the idea of using code to manipulate and affect physical objects. This is probably going to be a series of blog posts on my adventures with Rust on Arduino and maybe ESP8266 and discovery F3 in future. (I have these lying around too). Kicking off the series with this first post.
I've had the pleasure to work with very experienced firmware developers; the kind of people who know the size of their red zones and routinely transform coffee into linker scripts and pointer dereferences. In other words, the Mels and Zeus Hammers of the world.
When it comes to the tools of our trade, many of them are curious and experimental. Some of them—very much myself included—explore far enough to leave pragmatism behind and veer into idealism, stubbornly forcing beautiful round pegs into industrial square holes. Hey, maybe they're square for a reason, but it doesn't hurt to try.
The majority of them aren't like that. Your average battle-tested firmware developer has accrued a healthy distrust of the abstract, probably born of watching shiny platonic constructs crash and burn with painfully real and concrete error traces. It is sobering, having to chase a hardfault on a tiny MCU across enough vtables and templated code to make Herb Sutter puke angle brackets. No wonder modern approaches are met with some resistance unless the LOADs and the STOREs are in clear view.
I felt this way too when someone suggested to me, back in 2014, that an up-and-coming language called Rust showed promise in the embedded field. Surely not, I thought, too high level. Even though I had been playing with it already, my profoundly ingrained bit-twiddling instincts told me not to trust a language that supported functional programming, or one that dared to have an opinion on how I managed my memory. Bah! That's how you get philosophers to run out of forks, and your forks to turn into SIGSEGVs.
I was wrong.
The rust-analyzer plugin for VSCode provides you with a helpful little ▶ Run button above every test or main() function that lets you execute your code right out of the editor. Unfortunately though, this won't work out of the box in embedded projects, since rust-analyzer will invoke cargo run when you click on ▶ Run, and cargo itself does not know how to flash and run applications on embedded targets.
However, Rust-Analyzer does seamlessly integrate with probe-run, a custom cargo runner for embedded development: Since probe-run is a cargo runner and not a cargo subcommand, all we have to do is modify our settings to use probe-run instead whenever cargo run is called. After that, we can use the ▶ Run button like we would in a native project.
Today we are pleased to announce the public release of probe-run, a custom Cargo runner for embedded development. This host application integrates into your Cargo workflow and lets you cargo run embedded applications. Let's see how to use it for ARM Cortex-M application development.
After a few months off, we're bringing back the @rustlang Embedded WG Newsletter! 🎉
Check out our special catch-up issue here covering some of the amazing things released over the past 6 months, and stay tuned for the next weeks as we share more!
This blog post will have a closer look at the architecture of the Mender client. I figured that one of the best ways of getting a birds-eye view of the client is to rewrite the core functionality from scratch. And what better language to rewrite existing functionality than Rust. Thus, in the spirit of Rust we are going to rewrite the existing and well tested functionality of the Mender client in the Rust programming language!
These days GDB is the go-to development/debugging tool of many embedded Rust developers. We think there's room for complementary tools that could provide a better development workflow and improve productivity. In this blog post we'll share our vision for great embedded Rust tooling and share info about the tools we have been building.
This is an early preview of our tool binfmt, which is the first tool included in our knurling project. It is available for preview and usage today for sponsors of the knurling-rs efforts, and will be made public in the future, when we feel the tool is ready for general availabilty (think "0.7" release or so).
Typically embedded devices are developed using C++. At Tweede golf we have chosen to use Rust instead for implementing our embedded devices. This is controversial as the embedded hardware field is generally quite conservative. Convincing our clients to adopt Rust for their products can be a challenge.
Today we're announcing Knurling - Ferrous' effort to sustainably build better tooling for developing and debugging Rust software for embedded systems.
A few weeks ago, I built a new workstation with somewhat beefy AMD Ryzen 3950x CPU and got a bit over-excited with tuning it and getting the max (trying to reduce rust compile times) out of it 😅. One thing led to another and I ended up with a Corsair H150i RGB PRO XT AIO to keep this thing cool enough. Everything worked well until I found out that Corsair does not provide any support for Linux 🙄. It was usable, as this device holds its config on board and does not need support from OS/Software to run, but one can only adjust any settings or view any status in Windows.
How do I use this device in Linux? I wanted to look at the useless but pretty stats about how fast the pump and fans are spinning, what is the temperature of the coolant? After all I gotta kill time when ferris is churning bits…
With the recent ability for Rust to compile for AVR microcontrollers, I thought that it's time for me to bring my favorite feature of Rust to Arduino: async/await.
Welcome to another pointless tangent into the exciting world of line joints in embedded-graphics! embedded-graphics is an integer only, iterator based no-std graphics library for environments with low resource availability. This time, we’ll be looking at some not-so-great optimisations made to a point sorting function.
An updated version of my previous post on Rust on the STM32F1 I plan to make more shorter and more modular posts, but to get started, here is a short tutorial on how to get started: Blink an LED in Rust on a cheap microcontroller.
The avr-rust compiler, once existing as a fork, has since been merged into upstream Rust as of July 2020.
The standard Rust nightly compiler can be used to compile crates for AVR - no compiling from source required.
The recommended way to use avr-rust is via rustup using the official nightly version of the Rust compiler.
If a custom target triple is not available for your platform, you must create a custom target file that describes your target to rustc.
Keep in mind that it is required to use a nightly compiler to build the core library, which must be done for a target unknown to rustc.
How should you do concurrency in an embedded no_std application? There's no built-in support for time-sliced threads in core; that abstraction is only available in std (see std::thread). The latest stable release brought the async/await feature to no_std thanks to our compiler work. Should you always use that instead? Is cooperative scheduling appropriate for all kind of embedded applications? What about applications with soft or hard real-time requirements?
If you have asked yourself these questions before then this post is for you! We'll look into a few commonly used embedded concurrency patterns and then into some less common ones. We'll compare their runtime characteristics in practical terms so you get a better feel for which one is appropriate for your application.
In our previous post we discussed about how Rust can be a great language for embedded programming. In this article, we'll explain an easy way to setup to cross build Rust code depending on system libraries, a common requirement when working on embedded systems.
I’m new to rust and new to embedded programming. I wanted to document my experience getting started. This started when I bought an Arduino kit to do some projects with my family while we’re stuck inside avoiding the pandemic.
During this time I also started learning the rust programming language. Rust can be used for embedded programming, but unfortunately the Arduino Uno that I had wasn’t really supported as a compilation target from rust. This compatibility issue stems from the AVR microcontroller used on the Uno.
In the end I decided to purchase a new, and cheap, STM32 based board with good support from the Rust embedded community.
A wide variety of widely-available flight controllers have been released in the past five years. These boards incorporate a careful selection of sensors and actuator outputs useful for robotics-- not just for flying vehicles, but also rovers and underwater vehicles. This living document analyzes briefly the compatibility of embedded Rust with these inexpensive and powerful boards.
I recently tried my hand at running Rust on an ATSAMD51 ARM microcontroller. Rust is well setup for embedded work, and this experiment proved this to be true. I designed a prototype PCB, with the goal of figuring out a Rust based toolchain and workflow.
While learning Rust one of the exercises I always wanted to try is GPIO and low-level device communication. Simple examples like configuring button handler or led blinking are not that exciting because they are not practical. Reading temperature and humidity, on the contrary, allows building something like a weather station or just simple graphs. While it will be much easier to use python with existing libraries. In my opinion, writing it in Rust assembles efficiency of C and readability and safety of Python.
This is going to be somewhat reminscent of that owl meme. I had plans for some more posts about a new codec abstraction, my async STM32 IO crate, and maybe the overall architecture, but one thing led to another, and now I have a complete project to talk about. I'll give an overview of the main points of interest so that the other rust/embedded posts aren't required reading. I'm also kind of writing to two audiences here, so if you're a Rust person, but not a keeb person, feel free to skip stuff and vice-versa.
In about 4 weeks time from the publish date of this blog post, you'll be able to use the async/await feature in no_std code on stable! In this blog post we go over the work we did to make it happen and what we learned from building a proof of concept executor for the ARM Cortex-M architecture.
Now that I’m 6,400 miles away from my dear robot track saw and its precision positioning system, I need to find a new outlet for my embedded Rust habit.
Luckily, I’m now that much closer to Shenzhen, so I thought I’d build myself a travel ergonomic keyboard — in particular, a low profile, ortholinear (keys are in straight columns, not staggered), split (two entirely separate halves) wireless keyboard.
A common complaint heard about Rust is the size of the binary it produces. They are various reasons explaining why Rust binaries are generally bigger that ones produced with lower level languages such as C. The main one is Cargo, Rust's package manager and building tool, producing static binaries by default. While larger binaries are generally not much of an issue for desktop or server applications, it may become more of a problem on embedded systems where storage and/or memory may be very limited.
GStreamer is used extensively at Collabora to help our clients to build embedded multimedia solutions. With Rust gaining traction among the GStreamer community as an alternative to C to write GStreamer applications and plugins, we began wondering if the size of such Rust plugins would be a problem for embedded systems, and what could be done to reduce sizes as much as possible.
Inspired by this Tiny Rocket analysis and the Minimizing Rust Binary Size repository, here are the different strategies we tried to reduce the size of a minimal Rust GStreamer plugin.
Now that we developed a high-level Servo trait that allows controlling servo motors, we can start writing code that will animate our spider bot by rotating multiple motors synchronously. The idea is that the robot’s movement takes some fixed amount of time during which each moving motor may travel a different angle. Importantly, all moving motors should start and stop at the same time, and therefore, they will have different angular speeds. Such movements then are sequenced one after another to appear like a well-coordinated action.
To implement this in Rust, we introduce the Move structure that captures a reference to a servo motor and the desired degrees where it should be at the end of the animation.
"Zero Sized Reference" (ZSR) sounds like an impossible thing given that mem::size_of returns a non-zero value for references to Zero Sized Types (ZST) like &() but ZSRs can in fact be constructed and they can improve both the performance and correctness of your embedded application.
In this post, we'll introduce you to this pattern which is actually used in many embedded crates – though many developers may not have given the actual pattern much attention.
Let's start by motivating the need for zero sized references.
This week, I played around with an ultrasonic range finder and wrote a little library for it in Rust. This system measures the distance between myself and Ferris. I used a ultrasonic sensor from Maxbotix to measure distance. This project monitors the sensor’s output and shows the measured distance on a LED display.
This is the book for writing a 64-bit RISC-V emulator from scratch in Rust. It shows us how to implement an emulator in 10 steps. You can run xv6, a simple Unix-like OS, in your emulator in the final step.
You'll learn basic computer architecture from making an emulator in Rust.
In my previous blog post, I described how to use LXC containers to run an arbitrary Ubuntu package on Turris Omnia. While easy to configure, I find such setup rather wasteful. I don’t want to run another full Linux distro on my router to be able to run small (home) automation programs.
What other options do we have?
In the previous part, we were able to control the servo motor by writing to PWM registers of the FE310 microcontroller. Now it’s time to have more fun with Rust by writing high-level servo motor abstraction that is suitable for controlling multiple servo motors in a uniform fashion.
The Decawave DW1000 Radio IC is an ultra-wideband wireless transceiver chip, supporting wireless communication based on the IEEE 802.15.4 standard. It is low-cost, low-power, has a high data rate, and, according to the manufacturer, a range of up to 290 meters.
But arguably the main feature is its ability to measure the distance between two DW1000 nodes, by precisely measuring the in-flight time of the wireless packages sent between them. This makes it possible to build highly accurate (within 10 cm, according to Decawave) position tracking solutions based on this chip.
I worked on building Rust support for the DW1000 and some related hardware (namely the DWM1001 Module and DWM1001 Development Board), which resulted in the release of the dw1000 and dwm1001 crates, as well as the more broadly applicable ieee802154 and embedded-timeout-macros crates.
From this post you can learn how to write simple bare metal program in Rust for ARM AArch64 architecture, run it with QEMU on virtual device, attach a debugger and disassemble it.
The ALLBOT spider uses the 9G servo motors to animate its legs. The Arduino implementation uses a built-in servo library that allows assigning servo instance to a pin and then writing desired orientation degrees between 0 and 180. The e310x HAL does not have servo implementation, nor the Embedded HAL have the servo trait. Time to face the hardware at the lowest level!
The first thing is to find the datasheet for the 9G servo motor. The datasheet summarizes the entire servo interface in one simple diagram!
I came to know about Oxidize 1K, a remote-only conference on Embedded Rust development, through a twitter post. I was working from home, all the time getting inundated by morbid reports of Covid-19 taking over the world. It was a very long time since I had participated in any developer event, and I thought this was a good opportunity to jump in and immerse myself in something positive at least for a short period. And, I am glad I did it!
After reading The Rust Programming Language book and falling in love with the language, I was on the lookout for my first Rust project. In the “old hardware projects” box, I had a HiFive1 board with SiFive FE310 RISC-V microcontroller, and Velleman’s Arduino based ALLBOT spider robot. Replacing Arduino with HiFive1 and rewriting ALLBOT’s C-based firmware from the ground up in Rust felt exciting!
In this blog entry I will explain a bit what interrupts are and they work in embedded systems and compare various interrupt implementation and sharing methods in Rust.
AVRA-RS is a Rust rewrite of AVRA. I have created AVRA-RS to fix various shortcomings of the original software. This project now became something more.
First of all, this is not a complete implementation of the original assembler. It also has some important differences, for example, it is tested as much as possible.
Running Retro Games with Rust is not that hard on PineTime Smart Watch... Here's how I ported the libchip8 CHIP8 Game Emulator to PineTime.
In a previous post we explored what needs to be done on the rustc side to bring async/await to no_std Rust.
In this post we'll explore what could be done once async/await is available in no_std land and why we think async/await is a big deal for embedded development.
Back in high school I built a clock using Nixie Tubes. It was of a very primitive construction: plenty of hand-wiring, protoboard, and self-etched PCBs. Remarkably, it worked great! However, the end result was so ugly that I never used it - the negative aesthetics of the poorly cut and glued prefab plastic container more than cancelled out the positive aesthetics of the Nixie Tubes.
Something that I also wanted to do in high school, but lacked the funds (and probably the patience) to pull off, was a spectrometer-style audio meter using old Russian bargraph tubes. These are high-voltage gas-discharge tubes that display a vertical bar, which varies in length depending on how much current you supply it.
I figured it was time to revisit this old project idea.
My ultimate goal for Matrix Voice w/ ESP32 is to be able to develop in Rust.
A Rust driver crate for the ADXL355 digital accelerometer. This driver accepts an embedded-hal SPI interface and a GPIO OutputPin (for the chip select). It implements the Accelerometer Trait so you can easily obtain both raw sensor data and scaled-to-Standard-gravity sensor data.
The ADXL355 is one of the best three axis digital accelerometers that I know of. It has a noise floor of only 25 µg/√Hz. For example, the very popular MPU9250 Inertial Measurement Unit (IMU) specifies 300 µg/√Hz for its noise density. One order of magnitude higher.
Of course the ADXL355 is more expensive, but I think it hits a nice sweet spot between the low end IMUs and very high end and high cost MEMS accelerometers (with noise densities of around 7 µg/√Hz).
Sealed Rust is the effort led by Ferrous Systems GmbH to qualify the Rust Language and Compiler for use in the Safety Critical domain. This is the second post in a series detailing our plans around this effort. In this post, we'll discuss our initial approach to the problem, and in our next post, we will discuss our potential funding approaches.
The case is 3D printed with natural PLA. The development board is based on a STM32F401 with a USB-C port.
Gateron silent clear as switches, and basic DSA keycaps.
Layout is basically based on the Lily58 without the inner keys and with more stagger (but less than a Kyria). Angle between the 2 parts is 30°. You can also feel the Atreus inspiration in the unsplitted with a convex case design.
Thoughts on embedded Rust
After a few months, I have some thoughts about all this:
RTFM is an amazing framework that makes concurrency safe, fast, and easy (compared to C, anyway); it leverages hardware priority levels to prove (at compile-time) that resources can be shared without runtime overhead (i.e., mutexes), includes a low-overhead task scheduler, and eliminates the hard-to-debug concurrency/interrupt memory corruption nonsense that would absolutely be plaguing me if I were coding C.
Cargo is great: It’s easy to split code up in packages, run on both desktop (for debug/testing) and microcontroller, and also grab handy open source packages.
Shout-out in particular to bitvec, a package for easy manipulation of bits. Seriously, I’m decoding one-bit-at-a-time from timed flashes of light, and nowhere does my code include inscrutable bitwise shifts or boolean operations; this is amazing for code readability (and my sanity).
At Ferrous Systems, we've worked on a wide range of software in Rust, from embedded systems, to highly concurrent asynchronous applications. While the environments that these systems operate in are wildly different, they both can be boiled down to the same problem statement:
How can I process multiple events coming from outside of my own system in a way that is both efficient at runtime, as well as clear to develop and understand?
When you step back a little bit, server applications and embedded systems are not so different. They spend their time waiting for events to occur, whether that is a button press from a user, or a connection request from a browser. They then must handle many of these events concurrently and expediently, all the while waiting for the next event in a complex sequence of states to occur.
We think that libraries like async-std have made it easier to let the compiler generate the necessary state machines for people writing highly concurrent and efficient server and desktop applications. But what if we could have these same benefits when writing Embedded Rust?
What do Rust, Risc-V, and SpinalHDL all have in common? They can all run on the Hackaday Supercon 2019 badge! In this rather lengthy post, I go through how to get started with SpinalHDL on the badge, how to setup a Risc-V soft core using VexRiscv, how to assemble a basic program for it, and finally how to target and build embedded Rust for it.
In this post, I go over how Rust can be used to implement DSP algorithms for firmware today, and compare the process and performance to the equivalent code written with CMSIS-DSP.
It's the 23rd embedded Rust newsletter!
This month is a giant update with UI widgets on the PineTime, OpenSK from Google, using Cloudflare's QUIC library over LTE-M, controllers for Quantum Physics, new chip+driver crates, and more!
Last time, I wrote about how to configure VS Code to debug Rust Cortex-M programs, but you know what's better than writing documentation for how to do a thing?
I'm very happy to announce my PR to add a basic debug configuration for VS Code has been merged into the cortex-m-quickstart template. VS Code is now supported out of the box when you cargo generate a new project. When I say "out of the box", I really mean "out of the box". I've also added a QEMU configuration, so you can go experiment with debugging embedded Rust with VS Code right now, without any additional hardware.
This project was our first firmware project written in Rust. Most firmware projects for embedded devices are written in C or C++. However, Rust is slowly gaining traction as a promising alternative as it has a few important advantages. We were waiting for the right opportunity to dive in. And this project seemed simple and low risk enough that it was worth the extra time investment.
Piano technology is a discipline that studies piano mechanisms and their interaction with the pianist. For example one of the most important research areas is modelling piano actions to simulate a mechanical piano action with an electronic piano action. To investigate interactions between piano keys and pianists, we have installed an array of sensors in an experimental keyboard. The sensors are optical encoders aimed at measuring space-time behaviours of the keys when pushed by a pianist or by a robotic finger with different forces.
Using only a Raspberry Pi, we can debug the firmware on PineTime Smart Watch: Step into the flashed program line by line, set a breakpoint to pause execution at a line, inspect variables at runtime, … Just like the Embedded Pros!
It’s a great way to learn how real IoT gadgets are created… At a fraction of the cost of professional embedded tools and workstations!
Here are the steps to configure a Raspberry Pi (1, 2, 3 or 4, with 1 GB RAM or more) for debugging the Rust+Mynewt Firmware for PineTime…
Since my last post I've been working on building the humble beginnings of an ecosystem around the ESP32 for Rust. The short version of this post is as follows:
* This PR means the quickstart repo can now flash and run code without a debugger! Simply using the flash or flash_release scripts will flash your code and begin running your code
* idf2svd has been created which uses the documentation from esp-idf to generate svd files fit for consumption by svd2rust
* Based on the generated SVD file, there is now a PAC (Peripheral access crate) for the ESP32.
I've previously worked the ESP32's predecessor, the ESP8266, both devices have a RISC CPU that runs an ISA called Xtensa.
This was a few years back and I was programming most of my embedded projects in C, Since then I fell in love with Rust and have been using it for a few projects, especially ones which are relatively close to hardware, such as programming an ESP32, so last week when I started looking programming the device I checked to see if I could target it with rust.
All you need is a Raspberry Pi and a Windows or macOS computer!
Welcome to the World of Modern IoT Gadgets! If you’re used to old-school IoT gadgets like Arduino Uno that are underpowered and have no networking and display… PineTime Smart Watch will surprise you! PineTime is powered by a Nordic nRF52 Microcontroller with an Arm Cortex-M4F CPU… The same microcontroller found in a high-end gaming mouse! With built-in colour touchscreen and Bluetooth networking, embedded programming on PineTime becomes really fun and exciting.
PineTime is a prime example of a real-world, off-the-shelf gadget that’s powerful and yet affordable, because it’s manufactured in huge quantities. But they can be intimidating to newbies who have not programmed such commercial devices. Today I’ll show you that programming a PineTime is not that hard… All you need is a Raspberry Pi, some wires and a little creativity!
I wanted to learn embedded programming with Rust, so I made this little project. It's a battery powered pocket sized video game. The idea of the game is to be ridiculously small. It's played by two players each grabbing one end of the board. I’ve programmed two games for it: pong and tetris.
- @andre-richter added a new tutorial for the Operating System development tutorials in Rust on the Raspberry Pi series: Tutorial 13: Integrated Testing - Kernel Unit tests, Integration tests and Console tests using QEMU.
- @jamesmunns sketched out a few introductory notes about foundational Embedded Rust Crates like r0, cortex-m, PACs, and HALs. See part 1 and part 2 on Twitter!
- @jamesmunns wrote about the cost of Formatting in Embedded Rust as part of the #rust2020 effort, and how to reduce code size while maintaining panic debug-ability
- Craig Bishop wrote an overview of Getting Started on the STM32L0, which contains an excellent breakdown of what makes up an Embedded Rust project
If this isn't your first time visiting my blog, you may recall that I've spent the past several years building an elaborate microcontroller graphics demo using C++.
Over the past few months, I've been rewriting it — in Rust.
This is an interesting test case for Rust, because we're very much in C/C++'s home court here: the demo runs on the bare metal, without an operating system, and is very sensitive to both CPU timing and memory usage.
The results so far? The Rust implementation is simpler, shorter (in lines of code), faster, and smaller (in bytes of Flash) than my heavily-optimized C++ version — and because it's almost entirely safe code, several types of bugs that I fought regularly, such as race conditions and dangling pointers, are now caught by the compiler.
It's fantastic. Read on for my notes on the process.
The embedded Rust development ecosystem is changing fast. A bunch has changed even since early 2019 when I started prototyping firmware for the Gameslab’s system controller (STM32L0). Most of the changes are incredible! Device support crates, hardware abstraction layers (HALs), and even USB support are all very usable now for Cortex-M devices. In this post, I’ll summarize the ecosystem and show how to get started with embedded Rust on a STM32L0 part.
Simple tweaks like Batched Updates and Non-Blocking SPI can have a huge impact on rendering performance… PineTime Smart Watch has been an awesome educational tool for teaching embedded coding with Rust and Mynewt OS… But stare closely at the video demos in the articles… You’ll realise that the rendering of graphics on PineTime’s LCD display looks sluggish. Can we expect speedy screen updates from a $20 smart watch… Powered by a Nordic nRF52832 Microcontroller that drives an ST7789 Display Controller over SPI? Yes we can! Check the rendering performance of Rust and Mynewt OS on PineTime, before and after optimisation…
SDC Systems contacted me about their need for a Rust driver for Vishay’s VEML6030 ambient light sensor as they had seen that I have written drivers for the VEML6075, VEML6070 and VEML6040 devices.
Happy to see Rust being used commercially in an embedded application, I accepted the offer and here is the result.
Since 2015, Rust has been redefining what it means to combine the best-in-class aspects of performance, correctness, and developer convenience into one language, without compromise. In this post, we’ll bootstrap a Rust environment on a Cortex-M microcontroller from scratch, and explain a few of the language concepts you might not have seen before.
A button that responds to our tapping and increments a counter… That’s what we shall accomplish today on the PineTime Smart Watch…
Platform-agnostic driver for the PCA9685 PWM LED/Servo motor controller written in Rust.
Platform-agnostic driver for the Si4703 and Si4702 FM radio receivers (turners) written in Rust.
I've been toying with embedded Rust off and on for some time now. I picked up one of the STM Discovery boards and it's been an interesting novelty for me to be able to remotely debug code running on the microcontroller. I've never been willing to spring for the external hardware debugger required to do so, but the Discovery has a STLink built into the board. The Rust Embedded and Discovery books have great instructions for remote debugging Rust programs, but rely soley on command line tools for doing so. I like the terminal as much as, if not more, than the next person, but it's also really nice to be able to set breakpoints and step through code right inside of the editor.
I tend to use VS Code as my main editor these days, so that's what we'll set up today. We'll take a look at the hardware and setting up the toolchain first, before moving on to setting up our editor. The prior is essentially a condensed version of the information in the Discovery book, so if you've already worked your way through that, feel free to skip to setting up VS Code.
In our previous posts, we wrote about generating Rust code for an STM32F7 processor. This was enough to get a simple LED blinking program working but for creating more complicated software we need to be able to develop, compile, deploy and debug from an IDE. We will use the same source code and many of the same tools as in the previous post so make sure to have a look if you want the complete picture. The tools you need to have installed before starting are VS Code with the Rust(rls) extension, a cross-compilation toolchain and GDB debugger (we are using the one provided by ARM) and OpenOCD (for example from here) as the remote debugging server.
Pretend you’re my IoT student. I give you a PineTime Smart Watch and challenge you to “Make it work… Especially the touch screen!” The Touch Screen appears to be lacking some documentation. What would you do?
I’m one of the lucky few who received the developer preview version of the PineTime Smart Watch by Pine64. After coding on PineTime for a few days (in Rust), it suddenly struck me… I felt really comfortable and productive coding the new gadget. Even though I have never coded a smart watch. PineTime is a terrific tool for teaching IoT! And I have taught IoT with so many different gadgets.
Neotron is an attempt to make computers simple again, whilst also taking advantage of the very latest in programming language development. It is based around four simple concepts: The ARM Thumb-v7M instruction set, A standardised OS interface, A standardised BIOS interface, and Use of the Rust Programming Language.
Platform-agnostic driver for the OPT300x ambient light sensor written in Rust.
Recently, my colleague introduced me to QMK 1, an open-source keyboard firmware. Like many non-trivia C projects, macro is heavily used everywhere, especially in keymap files 2. It didn’t bother me much since I have been programming C for many years. But I kept thinking to myself, “what would it look like if I can start from scratch and redesign everything using Rust’s more powerful macro system?” After couple nights of hacking, I was able to come up with something I am quite happy with.
Let's actually hook up our LED matrix driver to the RTFM (RealTime For the Masses) library
In the world of systems programming where one may find themselves writing hardware drivers or interacting directly with memory-mapped devices, that interaction is almost always through memory-mapped registers provided by the hardware. We typically interact with these things through bitwise operations on some fixed-width numeric type.
So, OK, that was originally the point. It's awfulness was part of the joke - "Hey look what you can do, but totally shouldn't do, in Embedded Rust". But as time went on, I was thinking - maybe I could just ... make it better? Yes, there's value in setting an arbitrary goal and seeing what can be squeezed from it, but, if the goal was arbitrary, couldn't we just reset it a little bit? Take a step back and say, is it possible to build something impressive but also useful? So this is where the Neotron came from. It's a Monotron 2.0 if you like.
We create some firmware for the cube from scratch using Rust and the awesome RTFM library!
Recently, I’ve been trying to learn more about electronics and embedded development. Maybe I’m just tired of operating purely in the virtual, but there’s something cool about being able to physically put together a circuit and push a button to make something happen. I went through the usual Arduino resources before seeing what Rust had to offer. I’m happy to report there’s some really good material out there.
The nRF52 Microcontroller by Nordic Semiconductor is an awesome gadget with powerful Bluetooth Low Energy networking capability. It’s affordable too… For under $8, I can buy an EBYTE E73-TBB Development Board with onboard nRF52. Powered by an Arm Cortex-M4 CPU (hardware floating-point) with 64 KB of RAM and 512 KB of Flash ROM, the nRF52 has plenty of capacity to run modern embedded platforms… Like Apache Mynewt realtime OS and Embedded Rust!
The Sipeed Longan Nano is a $5 development board based on a new RISC-V processor from Gigadevices. The processor and the dev board are properly documented in English. If you are a RISC-V enthusiast, I believe this is the best option you have at the moment for learning and experimentation. I was able to run Rust code on this board by making small changes to the riscv/rust PicoSoc example.
This is the 19th newsletter of the Embedded WG where we highlight new progress, celebrate cool projects, thank the community, and advertise projects that need help!
Ferrous Systems GmbH was fully incorporated in Berlin, on October 1st, 2018; which makes today Ferrous' first birthday! It's been a busy year (or really more than a year) for us, full of ups, downs, growth, challenges, stress, and opportunities, and it finally feels like the right time to write a bit more about it from a personal perspective.
Drone is an Embedded Operating System for writing real-time applications in Rust. It aims to bring modern development approaches without compromising performance into the world of embedded programming.
Let’s build an NB-IoT GPS Tracker! A simple gadget that determines its current location based on received GPS signals… And transmits the location to a server via NB-IoT. We shall take an existing Apache Mynewt Embedded OS + Embedded Rust project from the article “Rust Rocks NB-IoT! STM32 Blue Pill with Quectel BC95-G on Apache Mynewt”… And extend it with a GPS module: Quectel L70-R.
In March of 2019, Espressif released their first run at an llvm fork to support the xtensa architecure. Shortly after I got to work bootstrapping Rust to use this newly created fork. Prior to this project, I'd had no experience with the compiler, fortunately I came across the RISCV PR which gave me a rough idea of what was required. After many build attempts I finally got it working; I was now able to generate xtensa assembly from Rust source code!
In this article we’ll learn to optimise the power consumption of the NB-IoT Sensor Application in the previous tutorial from this jagged power-hungry mess… To these well-disciplined bars… It’s a simple application (coded in Embedded Rust) that polls Blue Pill’s internal temperature sensor and transmits the sensor data to a server over NB-IoT.
Most embedded systems will implement multi-tasking by rapidly polling each system within an infinite loop. A motion controller will normally spend most of its time polling, but there are places where polling isn’t appropriate. For example, accurate movement of a stepper motor relies on sending pulses at very precise times. Another scenario is in the handling of communication, where waiting for the next poll to read a byte may result in missing part of a message.
Blue Pill was chosen for the tutorial because it best represents a real-world, low-cost microcontroller with limited RAM and ROM. To be clear what’s a “Blue Pill”… The heart of Blue Pill is an STMicroelectronics STM32F103C8T6 microcontroller. That’s a tiny module surface-mounted on a Blue printed-circuit board (hence the name Blue Pill). Without the Blue (and Yellow) parts, it would be extremely difficult for us to experiment with the microcontroller. So we buy a Blue Pill and use it like an Arduino.
Create and edit Embedded Rust programs for STM32 Blue Pill and Apache Mynewt… By dragging and dropping blocks!
We’re back in 2019… Hardly anyone writes embedded programs in Rust for microcontrollers (like STM32 Blue Pill), we all use C. But we really should switch to Rust! Moon Base One has given us 2 key reasons…
I gotta admit — Embedded Programs are getting darned hard to code on modern microcontrollers, sensors and networks. Faced with the ultra-daunting task of coding a readable, reusable, open-source NB-IoT application for STM32, I asked myself… Could Visual Programming with Embedded Rust solve this problem? Like this…
I'd been playing around with a couple of LED matrices bought from AliExpress. The LED's on one of the matrices were the very popular WS2812b variant. These panels are made up of addressable RGB LED's soldered to a flexible PCB, giving you three wires out the back -- data, 5V, and ground.
After not being able to find a Rust library which supported these things at the time (a few have popped up since), I decided I would instead learn the protocol and try to fiddle with it myself. This is a brief overview of that experience.
Declarative and Procedural Macros (plus bindgen and tips for Visual Studio Code) to protect Embedded Rust coders from stumbling into embedded traps.
This is the eighteenth newsletter of the Embedded WG where we highlight new progress, celebrate cool projects, thank the community, and advertise projects that need help!
v0.5.0 of Real Time For the Masses (RTFM), the embedded concurrency framework, is coming out soon-ish – some time after Rust 1.36 is released – and will include experimental support for homogeneous and heterogeneous multi-core Cortex-M devices. This blog post covers the upcoming multi-core API and includes a refresher on the single-core API.
Read about a simple quickstart with Rust on the ESP, using a ready-to-run container setup that should make this as easy as possible.
Jonas Schievink and I have been working on a Bluetooth Low Energy stack in Rust, Rubble. It is now in a state where hard-coded services can be created and used, with all lower layers of the stack functioning.
The next step is designing and implementing both an interface for managing Services and Characteristics, as well as a system for notifications when a value is changed. This is fairly complex, with no clear or obvious solution hence the call for help.
Today’s microcontrollers (like the STM32 Blue Pill) pack so many features in a tiny package… yet few embedded programmers are capable of exploiting the full potential of modern microcontrollers. Many of us (my IoT students included) seem to be stuck in the 1980s — painstakingly writing C programs for small computers.
It’s time to drop our legacy programming practices and adopt smarter, safer ways to exploit these microcontrollers… starting with Apache Mynewt and Rust.
Platform-agnostic driver for the AD9833 and AD9837 waveform generators / direct digital synthesizers written in Rust.
In this project, we have used Raspberry Pi and its camera to authenticate whether the RFID card is punched by the card’s owner or not. HAWK is a Rust based Image Recognition project, which implements a two-factor authentication by using the RFID card for user identification and Image for user validation. In this blog, I’ll show you how to trigger RPi’s camera using Rust Programming Language. To know more about HAWK click here
My experience writing embedded OS in Rust. The target architecture is Arm Cortex-M series. My application is running on Nucleo-F4291ZI board and QEMU. Currently, I implemented those functionality: Round-robin scheduler to schedule processes running in Thread mode, SVC interfaces to call kernel function for user processes (e.g. print messages using USART, sleep to wait for interrupts), Move to sleep mode to wait for interrupt when there is no executable processes. There are only a few functionality yet, but the core structure is being completed, I think.
What is it? Recently I heard that LLVM for xtensa is working, so I tried to build Rust for ESP32.
microamp (styled as μAMP) is a framework (library plus cargo subcommand) for building bare-metal applications that target AMP systems. This blog post is a deep dive into this framework which serves as the core foundation of the multi-core version of Real Time For the Masses (RTFM), which I’ll cover in the next blog post.
I do love working with Rust. I deliberately create excuses to work on mini projects that ultimately involves coding in Rust. Recently, I have bought a blue pill which is a little board that costs about 1$. Although, I have zero experience in embedded programming I always wanted to give it a try with Rust which, in my case, boils down to blinking a LED on the board. I know there are excellent materials about embedded programming with Rust out there, but things do change very rapidly.
In this article you will learn how to use the Direct Memory Access (DMA) controller to transfer data from memory to the built-in Digital to Analog Converter (DAC) on the STM32F3DISCOVERY board.
Every year I define a super ambitious goal for my learning process to keep myself motivated on the way. This year I defined my goal as writing a bootable kernel image for my old HTC One X android smartphone. I knew it was going to be hard but I never thought I’d fail in the end. It was clearly the Dunning–Kruger effect that made me think that I can achieve what I want to do with my limited knowledge/experience on the subject.
This week's highlights: The Embedded Rust Showcase, Oxidize speakers announced, docs on interrupts, and Life before Main!
Using Embedded Rust to configure and service a hardware interrupt on the STM32F3 Discovery board.
This blog covers the implementation details of cargo-call-stack v0.1.2. So, why would you ever want to analyze the stack usage of your program at compile time? The obvious answer is when you want to know if your application can stack overflow at runtime without actually running your program. This is important for embedded applications where stack overflows can corrupt memory, and it’s actually a hard requirement for certifying the functional safety of embedded applications.
This past long weekend some friends on I went on a coding retreat inspired by John Carmack doing similar in 2018. During the weekend I worked on adding support for the Texas Instruments SensorTag to the embedded Rust ecosystem. This post is a summary of the weekend and what I was able to achieve code wise.
Functionally, this tutorial is the same as the previous one, where we reset or power down the RPi. Around that, we add infrastructure for JTAG debugging.
This is the sixteenth newsletter of the Embedded WG where we highlight new progress, celebrate cool projects, thank the community, and advertise projects that need help!
Embedded graphics 0.4.7 has been released, along with a new sister crate, tinybmp! TinyBMP aims to parse BMP-format image data using no dynamic allocations. It targets embedded environments but can be used in any place a small BMP parser is required. Thanks to TinyBMP, Embedded Graphics now supports loading this simple image format. The header photo was made using Embedded Graphics and the SSD1331 driver in pure Rust. In this post, I’ll talk through how the BMP file is parsed in no_std environments with nom and how to get BMP images working with embedded_graphics.
A new version packed with new features and improvements: Blink leds without blocking main thread and adjust brightness. ⚙️ Work with servo motors and adjust motor speed. 〜 Work with software PWM.
[Experiment] JNeT: japaric's network thingies.
161 votes and 6 comments so far on Reddit
This is the fifteenth newsletter of the Embedded WG where we highlight new progress, celebrate cool projects, thank the community, and advertise projects that need help!
I’ve released the ieee802154 crate, a partial implementation of the IEEE 802.15.4 standard, earlier this week. IEEE 802.15.4 is a standard for low-rate wireless personal area networks. It is used as the basis for higher-level protocols like 6LoWPAN, Zigbee, or Thread. The ieee802154 crate is only a partial implementation of this standard, but I hope it can be used as a basis for future work by extending it as required.
All tutorials I found felt somehow outdated and I don't have the board used in the embedded Rust book. So I wanted to document how I got some Rust code running on the BluePill.
Part 2 of my embedded executor journey! Part 1 ended up getting a little long, so I cut it short while still missing some key features like more flexible task spawning and putting the executor to sleep when there's nothing needing to be polled. This time, we'll fill in those gaps!
After discovering that the embedded-hal ecosystem wasn't quite what I wanted it to be, I set out to build the abstractions that I wanted to use, namely: async-first and core::future compatible. The first thing on the list? A way to run the Futures of course!
I attended linux.conf.au (for the first time) in Christchurch, New Zealand. It’s a week long conference covering Linux, open source software and hardware, privacy, security and much more. The theme this year was IoT. In line with the theme I built a digital conference badge to take to the conference. It used a tri-colour e-Paper display and was powered by a Rust program I built running on Raspbian Linux. This post describes how it was built, how it works, and how it fared at the conference. The source code is on GitHub.
So, I have this STM32VLDISCOVERY dev board. It has the STM32F100RBT6B MCU, capable of running at 24MHz. On the board, there is a 8MHz crystal. Naturally, when you are new to microcontrollers (like me), you may have a few questions: When we upload a program on this development board, at what speed it is actually running? Is it using this external crystal? Why is this crystal 8MHz if the MCU is capable of 24MHz? If our program is not running at the maximum speed, how do we make it run at the maximum speed?
The Rust programming language’s rich type system and ownership model guarantee memory-safety and thread-safety — and eliminate many classes of bugs and security vulnerabilities at compile-time.
This post details the steps needed to start programming an Arduino UNO board using the Rust programming language and working on Mac OS.
Today I’m pleased to announce v0.4.0 of the Real Time for The Masses framework (AKA RTFM), a concurrency framework for building real time applications. This release also packs quite a few new features which I’ll briefly cover in this post. For a more throughout explanation of RTFM’s task model and its capabilities check out the RTFM book, which includes examples you can run on your laptop (yay for emulation), and the API documentation.
After a few weeks of reverse-engineering, internal dogfooding, and API design discussion, we're finally publishing our gbl crate for good.
The library implements a parser and writer for GBL firmware update containers, which are used to perform secure OTA updates for certain microcontrollers.
The tool produces a call graph of the selected program as a dot file. Each node (function) in the call graph includes the local stack usage of the function, if provided by LLVM (see -Z emit-stack-sizes). If the call graph contains no cycles then the tool also computes the maximum stack usage of each function, that is the stack usage that includes the stack usage of the functions the function may invoke.
After watching James Munns' Something for Nothing talk at RustConf about all of the cool things in the embedded Rust world that have been going on, I decided to take a crack at some embedded work. I built an ErgoDox a while back and already had some basic understanding of how its keyboard controller operates, so I thought "why not design my own keyboard?"
To make it easier to load programs on to the Monotron, I've been working on a crate to make it really simple to read data from SD and SDHC cards formatted with FAT16 or FAT32. The crate is written without `alloc` so it uses zero heap, and I try to keep no more than one 512 byte block on the stack at a time.
This alarm clock is programed in bare metal rust (no OS). It features pressure, temperature, humidity, monophonic alarm on a e-paper display.
This year the Embedded WG set out to build the solid foundation that the embedded Rust ecosystem requires to thrive. As we approach the date of the 2018 edition release we reflect on our progress and share our achievements with you in this post.
So now @rustbeltrust is over, I thought it was worth writing down a few details about what Monotron can do. It's had a few upgrades since @RustFest Paris! I tried to keep them under wraps to avoid spoilers but I can share them now. This is an un-roll and re-edit of my Twitter thread, and the features listed here are in no particular order.
This is a special "spotlight" edition of the newsletter, where we look at a few topics in a bit more detail: Embedded Rust Applications on Stable, Cortex-A team, shared-bus, and more.
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.
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.
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).
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).
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.
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.
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.
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.
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.
Here is a small walkthrough, on how to use Mac OS X, 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+).
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Announing the MCP3425 Rust driver.
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.
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!
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.
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 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: