►
Description
RustConf 2018 - Getting Something for Nothing by James Munns
This talk explores how to use the Rust Type System and Borrow Checker to write safe abstractions of hardware, even when using direct control of memory mapped peripherals with unsafe blocks. Because these techniques move all (or most) of the checking to compile time, these techniques are perfect for systems where high performance or resource constraints are a requirement.
This talk will explain and explore how these techniques are used on Microcontroller systems as a critical part of the embedded-hal ecosystem.
A
Okay,
so
we're
going
without
speaker
notes
here,
so
if
I
stumble
for
a
second
than
a
bear
with
me,
but
this
is
getting
something
for
nothing.
So
I'll
put
this
up
here
while
I'm
talking.
So
if
you
want
to
take
a
picture,
I'm
James,
Muntz,
I'm,
an
embedded
systems
developer.
My
background
is
in
developing
everything
from
avionics.
Iot
connected
devices
on
bit
should
mapped
on
Twitter
and
here's
my
email.
So
if
anyone
wants
to
take
a
picture
of
that
and
come
talk
to
me,
I
would
love
to
hear
from
you
all.
A
So
this
talk
is
sort
of
about
embedded
systems,
but
what
this
talk
is
really
about
is
how
we
can
teach
the
rust
compiler
about
what
we're
trying
to
do
with
embedded
systems
to
get
it
to
enforce
what
we
want
it
to
enforce,
so
that
we're
not
manually
checking
this
out
the
concept
of
getting
something
for
nothing
or
as
it's
more
commonly
called
zero
cost.
Abstractions
is
not
super
new
to
the
rest
compiler.
A
A
Also,
if
you
haven't
so
how
many
embedded
developers
do
we
have
here,
who's
worked
on
a
microcontroller
or
a
Raspberry
Pi,
okay,
awesome,
so
the
use
of
rust
for
embedded
systems
isn't
super
new
back
in
2014
the
crew
from
pebble
liked.
The
SmartWatch
that
was
on
Kickstarter
actually
had
a
user
space
application
written
in
rust.
So
this
is
an
August
of
2014,
so
this
worked
with
rust,
0.12.
A
So
not
super
new,
but
we've
come
a
long
way
since
then,
so
rust
in
2018,
especially
for
the
2018
Aero
release,
has
a
lot
of
stuff
in
the
keynote.
This
morning
they
talked
about
all
the
stuff,
that's
stabilizing
this
year
and
some
of
thats
things
that
you
notice,
when
you're
developing
rust
on
any
platform,
but
there's
also
been
a
lot
of
things
that
have
been
stabilizing
for
embedded
systems
and
a
lot
of
it
has
to
do
with
the
weirdness
of
running
code
outside
of
an
operating
system.
A
A
Luckily,
rust
has
the
backing
of
LVM,
so
we're
using
LVM
as
a
compiler,
back-end
and
LOV
M
has
already
been
used
for
C
and
C++
to
target
these
embedded
microcontrollers,
so
kind
of
the
really
low-level
plumbing
has
already
been
done
in
LOV
M.
So
getting
rust
to
support
things
that
already
exist
in
LLVM
is
a
much
more
straightforward
process
than
if
we
were
trying
to
bring
all
of
rusts
to
a
microcontroller
that
it
had
never
had
a
concept
of
before.
A
Whatever
we're
building
is
no
standard,
and
then,
if
we
want,
we
can
progressively
add
these
features
that
we
do
want
to
support
back
into
what
we're
building
and
with
all
the
things
that
are
stabilizing
in
2018.
It's
our
goal
and
I
say
are
the
embedded
working
group.
Who's
working
in
getting
rust,
working
or
embedded
working
with
rust
is
that
you
can
just
install
the
stable
version
of
rust.
Do
cargo
build
for
one
of
these
microcontroller
targets
and
you
get
a
working
microcontroller
binary
building
firmware
doesn't
have
to
be
complex
and
the
batteries
are
still
included.
A
You
still
have
all
the
great
things
that
come
come
with
rust
and
all
you
had
to
do
was
install
Russ,
No,
downloading
tons
of
dependencies
and
making
sure
you
had
the
right
version
of
GCC
and
getting
all
yeah.
None
of
that.
The
idea
is
just
like
you
build
a
rust
application,
so
I've
been
talking
a
lot
about
embedded
systems,
but
I
haven't
done
a
good
job
of
defining
what
embedded
systems
are.
So
my
tongue-in-cheek
description
is
computers.
A
You
don't
sit
in
front
of
and
could
be
anything
from
the
TV
remote
sitting
on
the
coffee
table
at
home
to
the
engine
control
system
for
a
rocket.
It
could
be
satellites,
it
could
be
electronics
and
airplanes.
All
of
this
are
combinations
of
hardware
and
software
that
we're
designed
to
do
one
thing,
and
do
it
really
well
not
like
a
general-purpose
computer
but
very
purpose-built
system.
So
this
definition
covers
a
huge
range.
A
A
So
these
microcontrollers
have
a
phenomenal
amount
of
hardware
powers
ability
to
react
to
the
real
world
while
being
really
a
TBD
tiny.
So,
specifically,
this
is
an
example
of
a
microcontroller.
This
is
a
Nordic
and
RF
52
Bluetooth
chip,
and
if
you
have
some
bluetooth
devices
in
your
home
chances
are.
This
is
what's
powering
at
least
some
of
them,
so
I
actually
have
this
board.
So
this
is
a
really
big
picture,
but
this
is
the
board
that
I'm
talking
about
all
that's
upside
down,
but
this
is
a
whole
development
kit.
A
The
actual
embedded
system
is
in
this,
while
it's
Red
Square
up
there,
but
this
tiny
white
square
here,
which
is
a
little
smaller
than
a
postage
stamp,
so
an
entire
running
computer
system
fits
way
smaller
than
a
postage
stamp
and
they
actually
get
way
smaller
than
this.
This
is
like
a
medium
sized
one,
so
these
little
micro
controllers
have
CPU
and
RAM
and
I,
say
Ram
I
mean
like
20
or
64
kilobytes
of
RAM
and
a
tens
or
hundreds
of
megahertz
of
CPU,
but
that's
not
all
they
have.
A
They
have
this
hidden
superpower
called
peripherals
which
are
a
way
of
interacting
with
the
real
physical
world
or
electronics
that
help
you
interact
with
the
physical
world.
The
cool
thing
about
these
peripherals
is
they
can
go
off
and
do
stuff,
while
your
CPU
is
off
doing
something
more
important
kind
of
like
offloading
computation
to
a
GPU,
but
for
a
lot
of
really
domain-specific,
interesting
things
and
then
nice
thing
about
being
able
to
offload.
A
So
these
are
called
memory
map
peripherals,
because
the
way
they're
exposed
to
your
CPU
is
there's
a
chunk
of
memory
at
an
arbitrary
location,
and
you
have
to
know
if
I
write
a
bit
here,
it
will
do
something
if
I
write
a
whole
byte
here,
it
will
do
something
else.
These
microcontrollers
have
a
real
and
linear
32-bit
addressing
space.
So
these
are
32-bit
microcontrollers,
which
means
everything
from
0
0
0
0
to
F
F
F,
F
F
is
a
real
location
and
you
can
write
stuff
to
it.
A
So
these
are
real
places
and
there's
nothing
like
an
MMU.
That's
gonna
protect
you
of
virtualizing
the
memory
or
making
sure
that
you
have
access
to
certain
tables
and
because
these
microcontrollers
only
have
tens
or
hundreds
of
kilobytes
of
RAM
there's
a
lot
of
extra
room.
This
is
for
gigabyte
or
for
word.
What
is
it
4
gigabytes
of
address
space?
You
know
it's
a
lot
of
room,
so
the
developers
of
these
marek
controller
said
well
we're
only
using
like
64
kilobytes
of
it
for
memory.
So
what
can
we
do
with
all
of
that
extra
space.
A
So
what
they
do
is
they
design
a
system
that
looks
kind
of
like
this,
and
this
is
a
really
dense
diagram
from
a
data
sheet.
But
this
shows
you
everything
from
zero,
like
that's,
where
your
Flash
non-volatile
storage
lives,
all
the
way
up
to
F,
which
might
be
a
ROM
table,
or
something
like
that.
So
this
is
the
memory
map
of
this
specific
processor
and
you
see
over
on
the
right.
A
There
are
some
peripherals
up
there
and
these
are
the
that
magic
stuff
that
allows
you
to
interact
with
the
real
world
and
one
of
these
registers.
So
this
one
32
bit
register
is
the
SPI
peripheral
frequency
configuration
register
for
the
NRF
52
and
there's
also
a
lot
on
here,
but
the
important
part
is:
is
it
shows
you
the
different
values?
So
if
you
write
eight
zero,
zero,
zero,
zero
to
this
register,
this
serial
port
will
now
begin
sending
at
8
megabit
per
second
and
all
the
registers.
Work
like
this
there's
arbitrary
stuff
at
arbitrary
locations.
A
A
So
great
we
have
a
language
that
works
with
microcontrollers
and
we've
got
a
great
way
of
working
with
them.
So
now
what
we
do?
We
we
write
code.
That's
obviously
the
first
thing
you
do
before
planning,
so
you
might
write
some
code
that
looks
like
this.
You
go
I've
got
this
serial
port
at
this
memory
location.
So
it's
a
mutable
reference
to
a
32-bit
word.
So
this
is
my
pointer,
so
I
want
might
want
to
make
a
function
that
reads,
and
because
of
this
Hardware
is
interacting
with
the
real
world.
A
This
memory
can
change
out
from
underneath
you,
so
it's
a
volatile,
read
or
a
volatile
write.
So
you
write
this.
You
wrap
the
function
and
unsafe
so
that
your
user
doesn't
have
to
call
unsafe
every
time
you
call
it,
and
this
is
kind
of
gross
to
look
at,
but
it
does
work
and
you
can
read
this
serial
port
speed
and
you
can
write
this
serial
port
speed,
but
it's
it's
not
so
great
and
if
you're
coming
from
a
rust
background,
you
might
go
this
isn't
really
what
rust
library
code
looks
like
right.
A
I
want
something
more
rusty,
so
you
might
break
it
up
into
a
struct.
You
might
call
a
serial
port
struct
where
you
organized
this
and
now
you've
nicely
hidden
this
point
in
the
arbitrary
values
inside
of
the
struct
as
constant
values.
So
you
can
use
them
and
you've,
given
yourself
a
way
to
create
this
new
serial
port
and
then
you
might
give
it
like
member
functions
where
you
can
do
this.
So
now
you
can
go
serial
port
dot.
Read
speed
great!
A
This
actually
works,
so
you
can,
in
your
function,
do
something
you
get
one
of
these
serial
port
handles.
You
read
the
speed
and
then
maybe
you
do
some
work
and
then
you're
like
now.
I
want
to
go
high
speed
and
you
change
the
speed,
and
this
kind
of
thing
would
work,
but
the
problem
with
this
is,
if
you
notice,
I,
just
kind
of
conjured
the
serial
port
out
of
nowhere
and
the
problem
is,
if
you
can
do
it
once
you
can
do
whatever
wherever
you
want.
A
You
also
have
one
of
these,
and
this
is
changing
the
speed
out
from
under
you,
and
this
is
not
a
great
thing,
because
if
you
wrote
those
code
on
different
days
or
with
two
different
developers
or
months
apart,
you're
gonna
forget
that
these
things
are
related
and
now
you've
got
mutable.
Aliasing
pointers,
which
is
kind
of
a
whole
reason
we
wanted
to
switch
to
realist,
was
to
avoid
these
kind
of
problems.
A
So
this
is
smelling
like
mutable,
global
state
and,
unfortunately,
hardware
is
nothing
but
a
big
collection
of
mutable
global
State,
which
is
painful
if
you're
coming
from
a
rust
background.
So
if
we
wanted
to
fix
this,
if
we
were
to
set
some
rules,
how
do
we
avoid
global
mutable
state?
Well,
let's
come
up
with
some
rules.
The
first
one
you
might
come
up
with
is
yeah.
What
are
our
rules
if
everyone
just
has
read
access
to
everything?
We
should
probably
let
everyone
have
it
because
you're
not
touching
anything.
A
You
know
everyone
can
look
and
that's
not
going
to
hurt
anyone,
but
if
someone
has
readwrite
access
to
these,
it
should
be
the
only
one
because
otherwise,
all
the
other
places
are
going
to
be
confused
because
they
thought
that
they
had
a
read-only
handle
to
something.
Now,
if
you're
paying
attention,
these
rules
sound,
really
familiar
and
it
turns
out.
These
are
exactly
the
rules
for
the
borrow
checker.
A
So
how
can
we
use
the
borrow
checker
to
enforce
these
ownerships
and
borrowing
of
these
peripherals?
So
we
can
get
the
kind
of
really
rusty
a
viewer
from
a
library
that
we
want,
but
it
also
works
on
real
hardware.
Well,
the
important
part
with
the
bio
checker
is:
it
has
to
track
this
ownership
and
moving
around,
so
we
can't
just
conjure
these
out
of
nowhere.
We
have
to
have
the
one
serial
port
that
we're
tracking
it
as
it's
moving
around
and
we
give
away
references
to
it
and
things
like
that.
A
So
this
pattern
in
CS
is
not
new
to
rust,
they're
called
Singleton's.
It
means
that
you
can
only
instantiate
a
class
once
so
there
there
can
be
only
one
I
couldn't
find
a
good
Highlander
gift
to
put
here.
So
if
anyone
wants
to
send
me
a
good
Highlander
gift
and
I'll,
add
it
to
this
presentation,
so
you
might
say:
ok,
I
need
one,
so
great
I'll
make
it
a
I'll,
make
it
a
global
mutable
variable.
So
that
way,
there's
only
one
wall.
These
just
be
talking
about
this
one
and
it
kind
of
works.
A
But
the
problem
is
in
rust
when
you
have
a
mutable
global
variable
everything
you
do
with
it
has
to
be
unsafe.
So
it's
never
going
to
be
very
convenient
to
use
and
the
problem
is
this
actually
doesn't
help
us
get
to
the
borrowed
checker,
because
this
giant
global
mutable
variable
is
accessible
everywhere
and
we're
not
tracking
it
moving
around
different
places.
It
just
is
so
this
would
work,
but
this
isn't
really
what
we
want
to
be
doing.
Instead,
we
could
write
something
like
this.
A
So
this
is
a
small
runtime
overhead,
with
a
huge
impact
for
what
we
want
to
be
doing
and
I
wrote
my
own,
but
this
is
rust.
You
don't
have
to
rewrite
that.
Someone
else
has
written
in
the
cortex-m
crate,
there's
a
singleton
macro
that
does
this
for
you
and
I've
used
RTFM,
which
is
kind
of
like
a
really
lightweight
operating
system
for
these
embedded
devices.
It
actually
even
handles
it
all
for
you
in
macro,
so
you
don't
even
have
to
think
about
unwrapping
it
or
taking
it
just
on
the
initialization.
A
It
goes
here
are
all
of
the
peripherals,
and
now
you
have
all
of
them
and
do
with
what
do
with
them.
What
you
want
so
again,
you
don't
have
to
rewrite
this
from
scratch.
There's
there's
stuff
out
there,
but
I
wanted
to
show
you
kind
of
how
it
worked
under
the
hood.
Excuse
me,
but
why
so
now
we
have
Singleton's
and
they're
related
to
peripherals,
and
we
have
this
but
ok,
wait.
Why
is
this
useful
again?
How
does
a
singleton
make
a
difference?
A
You
write
a
little
bit
better
if
you
have
a
function
of
their
called
setup,
SPI
port
and
it
takes
a
mutable
reference
to
an
SPI
port
which
is
a
serial
port
and
a
GPIO
pin,
and
if
it's
mutable
reference
you're
like
ok,
this
can
probably
change
my
hardware.
This
is
this.
Could
if
it
wanted
to
change
some
stuff
out
from
underneath
me,
but
the
second
one
that
just
reads
a
button
that
only
takes
an
immutable
reference.
You
go
ok!
Well,
this
probably
isn't
going
to
change
anything.
A
A
This
allows
us
to
enforce
weather
code
should
or
shouldn't
make
changes
to
Hardware
entirely
at
compile
time.
There
is
no
runtime
checking
in
this.
The
compiler
is
making
sure
this
for
you,
not
your
runtime,
so
there's
a
little
asterisks
there.
The
little
Asterix
is.
This
only
works
across
one
application,
because
Russ
only
has
a
concept
of
tracking
these
borrows
and
ownerships
with
one
application,
but
for
these
microcontroller
systems
there
is
no
OS
running
multiple
applications.
There
is
the
application
that
you
are
running
on
your
microcontroller,
so
this
is
a
problem,
but
not
for
us
before.
A
You
worry
all
that
stuff
about
writing,
registers
and
stuff,
like
that.
That
looked
like
a
lot
of
code,
especially
when
you
have
to
do
every
feature,
the
microcontroller,
but
don't
worry.
This
is
Russ
and
it's
2018
there's
a
tool
for
that.
It's
called
SVD
to
rust
and
it
takes
XML
files
that
are
provided
by
the
manufacturer
that
have
every
register
every
value.
Everything
like
that
and
it
vomits
out
tens
or
hundreds
of
thousands
of
lines
of
usable
rust
code
with
comments
with
modules
nicely
laid
out.
It's
kind
of
like
bind
gen,
but
for
hardware.
A
So
now
that
peripherals
are
structs,
what
else
can
we
do
with
rust?
We've
we've
figured
out
a
way
to
map
these.
What,
but
what
can
we
do?
Well,
we've
got
the
type
system
we
haven't
touched
on
that.
Yet
we
can
put
these
strong
types
to
work,
so
scaling
back
a
little
bit,
microcontrollers
the
smallest
most
simplest
thing
you
can
do
with
them
or
use
their
GPIO
s
or
general
purpose
input
outputs.
This
is
like
a
single
pin
if
you've
used
Arduino,
it's
like
digital
input,
digital
output.
A
So
if
you
were
writing
one
of
these
in
rust,
you
might
have
a
GPIO
pin
and
it
starts
maybe
unconfigured,
and
so
you
also
need
an
input
GPIO
and
an
output
GPIO.
So
I've
made
these
Struck's
here
and
when
we've
got
our
initial
GPIO
pin
it's
not
configured.
If
we
want
to
read
a
button,
we've
got
to
put
it
into
input
mode.
A
So
what
we
might
do
with
the
type
system
here
is
take
a
function
or
give
a
function
to
GPIO
that
takes
ownership
of
a
GPIO
pin
and
the
return
type
is
an
input
GPIO
type,
so
it
consumes
the
original
GPIO
pin,
which
is
an
unconformity
configures
it
the
way
you
want
it
and
gives
you
back
something
that
is
an
input
pin.
So
you're
kind
of
making
these
state
transitions
using
the
type
system.
A
So
let's
look
like
what
we
could
do
with
one
of
these
output
GPIO
types
we
might
want
to
come
up
with
a
driver
for
an
LED,
so
the
LEDs
are
the
little
blinky
lights
on
these
embedded
systems
and
blinking
a
light
for
embedded
systems
is
like
hello
world.
You
don't
have
a
screen.
So
how
are
you
going
to
say
hello,
you're,
gonna
blink,
a
light,
so
our
LED
driver
we
might
want
to
be
able
to
create
a
new
instance
of
this
LED
driver
and
we
say
well
to
make
an
LED
driver.
A
You
have
to
tell
me
which
output
pin
you're
gonna
use,
so
it
needs
to
consume
this
output,
pin
and
give
you
back
an
LED
pin
and
then
once
you
have
this
LED
pin
the
LED
pin
has
a
function
called
toggle,
which
requires
a
mutable
reference
to
self.
So,
if
you
want
to
toggle
an
LED,
you
have
to
go
through
the
motions
of
taking
an
uninitialized
GPIO,
pin,
turn
it
into
an
output
and
then
turn
that
output
into
specifically
an
LED
driver.
A
And
if
you
don't
go
through
this
transition,
then
the
types
this
isn't
isn't
gonna,
let
you
do
it
it
goes.
Gpio
pin
has
no
toggle
method
on
it.
What
am
I
supposed
to
do
here?
You
need
to
go
through,
and
this
shouldn't
start
to
sound
a
little
familiar.
If
you
use
the
Builder
pattern
in
rust
before
it's
forcing
you
to
go
through
these
transitions
to
get
the
structure
that
you
want.
That
has
the
interface
that
you
want
on
it.
A
This
allows
you
to
enforce
design
contracts
entirely
at
compile
time
again,
with
no
runtime
cost
and
no
room
for
human
error.
All
of
this
exists
only
at
compile
time.
You
only
get
access
to
it
if
you've
made
the
compiler
happy
now.
What
do
I
mean
by
no
run
time
cost?
So
all
of
these
struck
that
I've
shown
you
the
GPIO,
pin
the
input.
Pin
the
output,
pin,
there's
nothing
in
them.
There's
no
memory
to
take
up.
Why
would
we
allocate
space
at
run
time
if
nothing
exists?
A
These
are
exactly
the
same
sizes
like
the
tuple
type,
if
you've
ever
seen
or
an
empty
tuple
type
in
rust,
and
what
that
means
is
that
at
compile
time
rust
treats
these
like
real
objects
and
moves
them
around
and
make
sure
you
have
Baro
and
you
can
take
references
to
them,
but
then
it
goes
but
wait
a
minute.
We're
not
talking
about
anything
here.
So
at
compile
time.
This
all
evaporates
off.
So
you've
done
all
of
this
checking
at
compile
time,
and
this
doesn't
even
exist.
There's
no
code
that
checks
this
at
run
time.
A
It's
not
even
in
a
no
op,
it
just
doesn't
exist
in
the
final
binary.
These
are
all
zero
size
types.
They
act
as
real
time
real
types
at
compile
time,
but
they
don't
exist
in
the
binary.
They
don't
take
up
your
RAM.
They
don't
take
up
your
CPU
time.
They
don't
take
up
your
space.
They
take
up
your
compilers,
RAM
and
CPU
time,
but
not
your
microcontrollers
and
that's
nice,
because
we
might
have
like
an
eight-core
build
machine
building.
This
binary
and
a
single
core
16
megahertz
processor
running
that.
A
So
we
want
to
offload
all
the
hard
stuff
to
the
big
powerful
machine.
Can
we
do
more
with
types
yeah?
We
can
do
more
types.
So
what?
If
our
output
GPIO
has
multiple
modes
and
it
does
because
these
microcontrollers
have
a
million
different
specialized
features
because
they
want
you
to
be
able
to
interact
with
all
the
stuff
in
the
real
world
that
you
really
want.
A
So
we
might
have
this
output
GPIO
might
have
push-pull
mode,
which
is
kind
of
like
a
general-purpose
turnin
LED
on
do
something
a
little
bit
here
and
there
or
it
might
have
an
open
drain
mode,
which
is
really
good
for
like
driving
a
motor
or
an
LED.
That
requires
a
lot
of
power
and
they
might
have
different
characteristics.
So
we
could
make
our
output
GPIO
generic
over
these
different
kinds,
so
maybe
by
default,
when
you
just
create
one
of
these,
the
hardware
is
by
default
and
open
drain.
A
So
when
we
have
our
default,
you'll
get
back
an
output
GPIO,
that's
in
open
drain
mode
and
again
the
same
way
that
we
did
those
state
transitions
before
we
can
do
the
same
thing
with
generic
types.
So
you
can
turn
it
into
a
push-pull
and
you'll
get
back
a
flavor
of
that
structure
like
that
using
generics
or
you
could
put
it
into
an
opening
drain
again,
and
it
will
give
you
back
a
flavor
of
this
now.
A
The
cool
part
here
is:
if
push,
pull
and
open
drain
are
zero
size
types
and
we
put
a
zero
size
type
inside
of
another
zero
size
type.
How
big
do
you
think
that
type
is
it's
still
zero?
You
can
go
infinitely
deep
and
have
as
many
of
these
abstractions
as
you
want,
and
if
they're
all
zero
size
type,
you
could
go
30
layers
deep
and
it
still
evaporates
away
at
time,
so
you
could
have
a
driver.
That's
specified
to
only
work
with
this,
so
you
can.
A
Even
though
it's
a
generic,
you
say,
I
only
take
the
opened
rain
flavor
of
this
or
if
you
have
something
that's
kind
of
a
little
more
general
purpose.
You
could
say
I,
don't
even
care
what
kind
of
mode
as
long
as
it's
now
put.
Pin
I
can
work
with
that.
So
you
could
either
have
one
that's
very
specifically
tied
to
some
flavor
or
you
could
have
one
that
just
says
it
all
works
the
same
anyway
set
it
up.
A
However,
you
want
and
then
just
give
me
give
it
to
me
and
I'll
work
with
it,
so
that
was
the
borrowed
checker
in
the
type
system.
What
about
the
trade
system?
Russ
gives
us
that
well.
This
is
really
useful
when
you're
building
something
bigger,
if
you
are
like
10,
writing
10
lines
of
code
to
blink
an
LED
yeah.
You
probably
don't
need
anything
like
this,
but
if
you
are
building
code,
that's
meant
to
be
reused
in
many
many
places
or
drivers
that
work
for
multiple
kinds
of
chips.
A
You
need
a
way
to
abstract
over
that
so
I'll
get
into
what
each
of
these
different
parts
are,
but
the
ecosystem
in
rust.
Looking
like
that
is
looking
a
little
something
like
this:
that
blue
over
there
is
a
this
blue
board
and
you've
got
the
actual
hardware.
You've
got
your
low-level
peripheral
drivers
like
your
NRF,
52
crate
and
you've
got
your
higher
like
human,
readable
interface.
That
says,
like
I,
want
to
send
eight
over
a
serial
port,
not
like
shove.
A
This
data
at
this
register
I
just
want
to
send
bytes,
but
while
you're
writing
that
you
could
say
well,
there's
these
traits
called
embedded
Hal
that
are
a
generic
way
of
looking
at
a
serial
port.
It
might
look
something
like
this.
Like
an
output
pin,
what
can
you
do
with
an
output?
Pin
you
can
you
can
set
it
low
and
you
can
set
it
high?
That's
all
I
can
do
so.
This
is
kind
of
the
interface
or
the
trait
that
goes
with
that.
A
A
Instead
of
multiplying
these
together
to
get
all
the
possible
combinations
that
are
ever
so
slightly
different
and
never
work
the
way
that
you
want
them
to.
Instead,
it's
just
n
plus
M,
which
means
you
have
to
implement
your
chips
and
you
have
to
implement
your
drivers,
but
the
longer
we
go.
The
bigger
this
difference
ends
up
being,
and
this
makes
things
actually
reasonable
to
do
at
scale.
So.
A
Unfortunately,
all
good
things
must
end,
so
I
wanted
to
recap
what
we've
gone
over
today
to
kind
of
like
solidify
the
concepts
in
your
head.
So
we
talked
about
how
ownership
and
borrowing
can
help
us
as
embedded
developers.
We
can
treat
hardware
resources
the
same
way
you
treat
any
other
data
type
in
rust
and
let
the
compiler
manage
who
has
access
to
what
and
what
they
should
be
able
to
do
with
it.
We
use
the
type
system
to
enforce
state
transitions,
preconditions
and
postconditions.
A
This
means
we
know
that
if
we've
gotten
one
of
these
strokes,
it's
set
up
the
way
it's
supposed
to
be
and
when
we
leave
it
gets
torn
down
the
way
it's
supposed
to
be.
This
is
a
concept
called
functional
safety
and
embedded
systems.
If
everyone's
worked
in
the
safety
critical
field,
you
can
stop
trying
to
keep
all
of
that
in
your
head
or
in
the
comments
or
like
remembering
a
day
to
day.
A
If
a
computer
can
check
it,
let
the
computer
check
it
they're
way
better
at
checking
normal
stuff
than
or
add
like
stuff
that's
done
over
and
over
and
over.
Then
then,
humans
are
because
everyone
has
a
bad
day
as
a
developer,
and
the
trade
system
lets
us
enable
code,
reuse
for
your
embedded
projects,
no
more
copy
and
pasting
from
like
the
Adafruit
library
for
this
and
then
tweaking
it
to
work
with
my
controller
and
I
forgot
to
change
a
variable
name
and
now,
all
of
a
sudden
it
doesn't
work
at
all.
A
You
can
just
write
things
for
interfaces
that
really
work
and,
for
me,
I'm
a
big
fan
of
Rost
cargo
in
the
community,
so
anything
I
can
do
to
stay
in
this
field,
while
taking
advantage
of
modern
language
features
enumerated
types
match
statements.
All
of
that
still
exists
in
no
standard.
So
why
lose
access
to
it
and
package
management,
which
is
not
really
a
thing
in
embedded
systems,
except
for
a
couple?
A
Little
little
cases
and
a
group
of
people
who
are
willing
to
work
with
you
to
solve
problems
and
a
reminder
all
the
stuff
I
showed
you
today
is
optional.
You
can
go
and
write
a
giant,
unsafe
block
and
if
all
you're
doing
is
writing
ten
lines
of
blinking
LED,
that's
probably
the
fastest
way,
and
if
it
all
fits
on
your
screen,
you
can
verify
all
that
stuff
in
your
head,
but
as
these
projects
scale
or
you're
writing
reusable
libraries
that
are
meant
to
be
used
by
very
many
people
who
are
not
familiar
with
that
hardware.
A
You
should
give
them
all
the
tools
you
possibly
can
to
make
sure
that
they
get
things
right
the
first
time
and
they
don't
have
to
figure
things
out
the
hard
way.
So,
thank
you
very
much.
I
hope
you
for
those
of
you
who
are
embedded
systems
developers,
I,
hope,
you're
really
excited
to
write
Ross
now
and
for
those
of
you
who
have
never
worked
with
embedded
systems.
I
hope
this
is
feeling
way
more
accessible
and
hopefully
all
of
you
can
get
started.
So
thank
you.
All
for
listening,
I
have
a
couple
plugs
before
I.
A
Don't
have
my
timer
because
I
don't
have
things
so
I'll
go
really
quickly.
I'm,
a
part
of
the
embedded
working
group
we're
a
part
of
the
RUS
team
and
we're
Matt
doesn't
quite
fit
but
part
of
the
embedded
working
group.
We're
trying
to
make
things
as
usable
and
scalable
as
possible
for
embedded
systems.
So
come
check
us
out
on
github.
That's
our
coordination
repository.
A
We
would
love
to
have
your
help
and
we're
expanding
now
so
now's,
a
great
time
to
join
I
also
am
founding
a
company
with
some
of
the
other
people
in
the
rust
community,
including
Caterina
who's
speaking
later
today,
and
we're
focusing
on
low-level
and
embedded
problems
in
Ross.
So
if
you're,
a
company
that
has
the
level
and
embedded
problems
or
systems,
level
problems
and
Ross
come
talk
to
us,
we
would
love
to
chat
with
you.
So
thank
you
very
much
I'm
James
Monza!
This
is
getting
something
for
nothing.