[rust-dev] Rust on bare metal ARM - sample project

Svetoslav Neykov svetoslav at neykov.name
Sun Jul 14 13:04:40 PDT 2013


My interest in Rust is from the point of view of an embedded
microcontrollers running bare metal programs with no underlying OS. I
decided to explore what the language offers in that space by creating an
actual running program. For the target I used STM32F4Discovery board since
it has an ARM CPU which is already supported by the compiler. What is
special about this board with comparison to the Android port is that it has
only 192K internal memory (no SDRAM) and no MMU.


You can find the project at https://github.com/neykov/armboot.


For the first step I chose the fastest approach possible - to generate an
intermediate .ll, convert it to assembler and compile it with the gcc
cross-compiler for the target (arm-none-eabi). One change was required to
the compiler to skip the generation of function prologue for split stacks
(see https://raw.github.com/neykov/armboot/master/rustc.patch). This version
supports only static memory allocation, though heap access (owned pointers)
is easily implemented (i.e. use malloc/free linked to newlib). Zero.rs is
used so no managed pointers and garbage collection.

The generation of the executable file is automated. After generation the .ll
file is corrected so it works with unpatched llvm 3.4 and the .note.rustc
section is removed so it doesn't take space on the target device.


Major points from the effort: 

.         I ported a basic C program to equivalent safe Rust program (see
main.rs vs blinky.c). It is interesting because it uses an interrupt
callback for the actual blinking logic.

.         The platform definitions were needed - like IO register locations
and memory layout. I created a subset of them, mostly by hand, taking the
output from rust-bindgen for the structures. All the #defines and enums had
to be created as macros so as not to allocate actual memory on the device if
declared as static (which I tried and ran out of memory J ). This is
somewhat cumbersome since it requires adding "!()" but not a huge problem.

.         "unsafe" is not a normal block and doesn't return a value, can't
be used as an expression. This made it impossible to wrap the unsafe casts
from fixed memory locations to borrowed pointers in macros. Instead I had to
use inline functions and assign the resulting value to a local function

.         No "volatile" equivalent in Rust - currently all code is compiled
with disabled optimizations so IO code is not optimized away. Another
possible workaround is to use extern "C" functions to do the actual hardware

.         I couldn't move the platform code to a separate library since
macros can't be exported (I saw that this is still a work in progress
according to #3114 so not a long term problem).

.         There were problems with the code comments in the original source
files (i.e. see
https://github.com/neykov/armboot/blob/master/sys/inc/stm32f4xx.h). I got
compile-time errors because of the special symbol combinations in them which
are reserved in Rust.

.         No core/std since I used zero.rs.


As a future development I will look into adding support for the
arm-none-eabi target by the Rust compiler and getting at least part of
"core" working on the target device in memory constrained environment.



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20130714/5b2f3cfb/attachment-0001.html>

More information about the Rust-dev mailing list