Getting Something for Nothing

RustConf 2018

James Munns

@bitshiftmask

james.munns@ferrous-systems.com

Rust? for Embedded?

embedded rust isn’t a new idea

Rust in 2018

stabilizing things behind the scenes

LLVM

if they can do it, so can we!

#![no_std]

where we’re going, we don’t need operating systems

$ rustup default stable
$ cargo build --target thumbv7em-none-eabihf

building firmware doesn’t have to be complex

batteries included

Embedded Systems

computers you don’t sit in front of

Microcontrollers

phenomenal hardware powers

itty bitty living space

Peripherals

connecting your CPU to the physical world

Hardware API

herding bits

Memory Mapped Peripherals

0x2000_0000 is a real place

0x0000_0000 is too

Now what?

write code!

This smells like mutable global state

hardware is basically nothing but mutable global state

What are our rules?

We should be able to share any number of read-only accesses to these peripherals

If something has read-write access to a peripheral, it should be the only reference

Part I: The Borrow Checker

ownership and borrows

Singletons

In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object.

https://en.wikipedia.org/wiki/Singleton_pattern

close, but not quite there

take what you need, but only once

small runtime overhead, big impact

cortex_m docs

japaric.io rtfm v3

But why?

how do singletons make a difference?

This is allowed to change hardware settings:

This isn’t:

enforce whether code should or should not make changes to hardware

at compile time*

*: only works across one application, but for bare metal systems, we usually only have one anyway

Before you worry

you don’t have to write all of that code

this is rust. there’s a tool for that

it’s called svd2rust, and it turns XML files into rust code. like bindgen, but for hardware

Now that peripherals are structs…

what else can we do with Rust now?

Part II: The Type System

putting those strong types to work

GPIOs

take things one bit (of input or output) at a time

Enforce design contracts

entirely at compile time

no runtime cost

no room for human error

“no runtime cost”?

Zero Sized Types

acts real at compile time

doesn’t exist in the binary

no RAM, no CPU, no space

Can we do more with types?

oh, you bet we can

What if our OutputGpio has multiple modes?

(it does)

Part III: The Trait System

traits of a successful project

Building something bigger

drivers that work for more than one chip

rust-embedded/embedded-hal

this goes in your chip crate

japaric/l3gd20

N*M <<< N+M

to re-use a driver, just implement the embedded-hal interface

Outro

all good things must end

Ownership and Borrowing

treat hardware resources the way you treat any other struct. let the compiler manage who has access to what

The Type System

use types to enforce state transitions, pre-conditions, and post-conditions. stop trying to keep that all in your head or in the comments

The Trait System

enable code reuse for your embedded projects. no more copy and pasting from project to project

Rust, Cargo, Community

take advantage of modern language features, package management, tooling, and a group of people willing to work with you

Option<T>

you don’t have to use all of this…

Thank you!

Plugs

icon by Freepik from flaticon.com

github.com/rust-embedded/wg

The Embedded Working Group

Ferrous Systems

ferrous-systems.com

Getting Something For Nothing

James Munns

@bitshiftmask

james.munns@ferrous-systems.com

https://github.com/ferrous-systems/rustconf-james-2018

Secret Bonus Slides

todo: explain these differences

Wait, but if you generate all the code for the peripherals, how do you add functionality? or create instances?

error[E0451]: field `register` of struct `nrf52::PIN_CNF` is private
  --> src/main.rs:22:9
   |
22 |         register: VolatileCell::new(10)
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `register` is private

lets try that again

this is our pin configuration register

this is the larger block of registers that the PIN_CNF array lives in

Extension Traits

like DLC for someone else’s code