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

Hello, 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 variable. . 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 communication. . 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. Svetoslav -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20130714/5b2f3cfb/attachment-0001.html>