|
| 1 | +# Frequently Asked Questions |
| 2 | + |
| 3 | +# Does Rust support my device? |
| 4 | + |
| 5 | +## Short answer |
| 6 | + |
| 7 | +As of 2018-09-18 the Rust compiler supports cross compiling to these embedded |
| 8 | +architectures (see `rustup target list`): |
| 9 | + |
| 10 | +- ARM Cortex-M (since 1.27) |
| 11 | + - `thumbv6m-none-eabi`, Cortex-M0 |
| 12 | + - `thumbv7m-none-eabi`, Cortex-M3 |
| 13 | + - `thumbv7em-none-eabi`, Cortex-M4 and Cortex-M7 |
| 14 | + - `thumbv7em-none-eabihf`, Cortex-M4F and Cortex-M7F |
| 15 | +- ARM Cortex-R (1.30-beta) |
| 16 | + - `armebv7r-none-eabi`, big endian Cortex-R4 and Cortex-R5 |
| 17 | + - `armebv7r-none-eabihf`, big endian Cortex-R4F and Cortex-R5F |
| 18 | + - `armv7r-none-eabi`, little endian Cortex-R4 and Cortex-R5 |
| 19 | + - `armv7r-none-eabihf`, little endian Cortex-R4F and Cortex-R5F |
| 20 | +- ARM Linux |
| 21 | + - ARMv5TE (e.g. ARM926EJ-S), |
| 22 | + - ARMv6 (e.g. ARM11 as found in the Raspberry Pi 1 / Zero), |
| 23 | + - ARMv7-A (e.g. Cortex-A8 as found in the Beaglebones), |
| 24 | + - and ARMv8 (e.g. Cortex-A53 as found in the ODROID-C2) ... |
| 25 | + - ... in GNU and MUSL flavors and in soft float and hard float variants; |
| 26 | + - notably, support for ARMv4T (e.g. ARM7) and older versions is missing. |
| 27 | +- RISCV (1.30-beta) |
| 28 | + - `riscv32imac-unknown-none-elf`, RV32I base instruction set with M, A and C |
| 29 | + extensions |
| 30 | + - `riscv32imc-unknown-none-elf`, RV32I base instruction set with M, and C |
| 31 | + extensions |
| 32 | + |
| 33 | +`rustc` also supports code generation for the MSP430 architecture (see `rustc |
| 34 | +--print target-list`). |
| 35 | + |
| 36 | +In general, ARM Cortex-M and ARM Linux have the most mature ecosystems whereas |
| 37 | +the ARM Cortex-R, MSP430 and RISCV ecosystems are in early stages or not as |
| 38 | +mature. |
| 39 | + |
| 40 | +For specific device support check [awesome-embedded-rust]. |
| 41 | + |
| 42 | +[awesome-embedded-rust]: https://github.com/rust-embedded/awesome-embedded-rust |
| 43 | + |
| 44 | +## Long answer |
| 45 | + |
| 46 | +We can talk about support at different levels: does the compiler support my |
| 47 | +device? does the crate ecosystem support my device? |
| 48 | + |
| 49 | +Let's start with compiler support. The compiler supports architectures or ISA |
| 50 | +(Instruction Set Architectures) rather than specific devices. Compiler support |
| 51 | +can be further divided in two levels: compilation target support and |
| 52 | +architecture support. |
| 53 | + |
| 54 | +### Compilation target support |
| 55 | + |
| 56 | +By compilation target support we mean that you can readily cross compile a crate |
| 57 | +for a certain *compilation target* using Cargo. To keep the default installation |
| 58 | +slim only the native compilation target is installed and other targets have to |
| 59 | +be installed using the `rustup target` subcommand. If `rustup target list` lists |
| 60 | +a compilation target that matches your device then Cargo supports cross |
| 61 | +compiling to your device. |
| 62 | + |
| 63 | +For example, let's say we want to know if `rustc` supports cross compiling to |
| 64 | +32-bit RISCV. We check `rustup target list` |
| 65 | + |
| 66 | +``` console |
| 67 | +$ rustup default 1.29.0 |
| 68 | +$ rustup target list | grep -i riscv || echo not supported |
| 69 | +not supported |
| 70 | + |
| 71 | +$ rustup default nightly-2018-09-18 # this date is just an example |
| 72 | +$ rustc -V |
| 73 | +rustc 1.30.0-nightly (2224a42c3 2018-09-17) |
| 74 | +$ rustup target list | grep -i riscv || echo not supported |
| 75 | +riscv32imac-unknown-none-elf |
| 76 | +riscv32imc-unknown-none-elf |
| 77 | +``` |
| 78 | + |
| 79 | +This indicates that 1.29 doesn't support 32-bit RISCV but that 1.30 will. |
| 80 | + |
| 81 | +Once you have installed a compilation target using `rustup target add $T` you'll |
| 82 | +be able to cross compile crates to it using `cargo build --target $T`. |
| 83 | + |
| 84 | +``` console |
| 85 | +$ rustup target add riscv32imac-unknown-none-elf |
| 86 | +$ cargo build --target riscv32imac-unknown-none-elf |
| 87 | +``` |
| 88 | + |
| 89 | +### Architecture support |
| 90 | + |
| 91 | +If your device doesn't appear in `rustup target list` that doesn't mean that |
| 92 | +`rustc` doesn't support your device at all. It could still support code |
| 93 | +generation for your device *architecture*. `rustc` uses LLVM to generate machine |
| 94 | +code; if the LLVM backend for your device architecture is enabled in `rustc` |
| 95 | +then `rustc` can produce assembly and/or object files for that architecture. |
| 96 | + |
| 97 | +The easiest way to list the architectures that LLVM supports is to run |
| 98 | +`cargo objdump -- -version` where `cargo-objdump` is one of [`cargo-binutils`] |
| 99 | +subcommands. |
| 100 | + |
| 101 | +[`cargo-binutils`]: https://github.com/rust-embedded/cargo-binutils |
| 102 | + |
| 103 | +``` console |
| 104 | +$ rustup default nightly-2018-09-18 # this date is just an example |
| 105 | +$ rustup component add llvm-tools-preview |
| 106 | +$ cargo install cargo-binutils |
| 107 | + |
| 108 | +$ cargo objdump -- -version |
| 109 | +LLVM (http://llvm.org/): |
| 110 | + LLVM version 8.0.0svn |
| 111 | + Optimized build. |
| 112 | + Default target: x86_64-unknown-linux-gnu |
| 113 | + Host CPU: skylake |
| 114 | + |
| 115 | + Registered Targets: |
| 116 | + aarch64 - AArch64 (little endian) |
| 117 | + aarch64_be - AArch64 (big endian) |
| 118 | + arm - ARM |
| 119 | + arm64 - ARM64 (little endian) |
| 120 | + armeb - ARM (big endian) |
| 121 | + hexagon - Hexagon |
| 122 | + mips - Mips |
| 123 | + mips64 - Mips64 [experimental] |
| 124 | + mips64el - Mips64el [experimental] |
| 125 | + mipsel - Mipsel |
| 126 | + msp430 - MSP430 [experimental] |
| 127 | + nvptx - NVIDIA PTX 32-bit |
| 128 | + nvptx64 - NVIDIA PTX 64-bit |
| 129 | + ppc32 - PowerPC 32 |
| 130 | + ppc64 - PowerPC 64 |
| 131 | + ppc64le - PowerPC 64 LE |
| 132 | + riscv32 - 32-bit RISC-V |
| 133 | + riscv64 - 64-bit RISC-V |
| 134 | + sparc - Sparc |
| 135 | + sparcel - Sparc LE |
| 136 | + sparcv9 - Sparc V9 |
| 137 | + systemz - SystemZ |
| 138 | + thumb - Thumb |
| 139 | + thumbeb - Thumb (big endian) |
| 140 | + wasm32 - WebAssembly 32-bit |
| 141 | + wasm64 - WebAssembly 64-bit |
| 142 | + x86 - 32-bit X86: Pentium-Pro and above |
| 143 | + x86-64 - 64-bit X86: EM64T and AMD64 |
| 144 | +``` |
| 145 | + |
| 146 | +If your device architecture is not there that means `rustc` doesn't support your |
| 147 | +device. It could be that LLVM doesn't support the architecture (e.g. Xtensa, |
| 148 | +ESP8266's architecture) or that LLVM's support for the architecture is not |
| 149 | +considered stable enough and has not been enabled in `rustc` (e.g. AVR, the |
| 150 | +architecture most commonly found in Arduino microcontrollers). |
| 151 | + |
| 152 | +If your device architecture is there then that means that, in principle, `rustc` |
| 153 | +supports your device. However, an architecture like ARM can be very broad |
| 154 | +covering several ISAs and extensions. Instead, you'll want to work with a |
| 155 | +compilation target tailored to your device. Custom compilation targets are out |
| 156 | +of scope for this document; you should refer to the [embedonomicon] for more |
| 157 | +information. |
| 158 | + |
| 159 | +[embedonomicon]: https://rust-embedded.github.io/embedonomicon/compiler-support.html |
| 160 | + |
| 161 | +### Crate ecosystem support |
| 162 | + |
| 163 | +Crate ecosystem support can range from generic support for the architecture to |
| 164 | +device-specific support. We recommend that you search on crates.io for the |
| 165 | +architecture (e.g. ARM or Cortex-M), for the microcontroller vendor (e.g. |
| 166 | +STM32), for the target device (e.g. STM32F103) and the target development board |
| 167 | +(e.g. STM32F3DISCOVERY). We also suggest that you check the |
| 168 | +[awesome-embedded-rust] list and [the crates maintained by the embedded Working |
| 169 | +Group][wg-crates]. |
| 170 | + |
| 171 | +[wg-crates]: https://github.com/rust-embedded/wg#organization |
| 172 | + |
| 173 | +# (When) will Rust support the AVR architecture? |
| 174 | + |
| 175 | +As of 2018-09-19 the official Rust compiler, `rustc`, relies on LLVM for |
| 176 | +generating machine code. It's a requirement that LLVM supports an architecture |
| 177 | +for `rustc` to support it. |
| 178 | + |
| 179 | +LLVM does support the AVR architecture but the AVR backend has bugs that prevent |
| 180 | +it from being enabled in `rustc`. In particular, the AVR backend should be able |
| 181 | +to compile the `core` crate without hitting any LLVM assertion before it's |
| 182 | +enabled in `rustc`. A likely outdated list of LLVM bugs that need to be fixed |
| 183 | +can be found in [the issue tracker of the the rust-avr fork of rustc][rust-avr]. |
| 184 | + |
| 185 | +[rust-var]: https://github.com/avr-rust/rust/issues |
| 186 | + |
| 187 | +TL;DR `rustc` will support the AVR architecture when the LLVM backend is |
| 188 | +relatively bug free. As LLVM is a project independent of the Rust project we |
| 189 | +can't give you any estimate on when that might happen. |
| 190 | + |
| 191 | +# (When) will Rust support the Xtensa architecture? |
| 192 | + |
| 193 | +As of 2018-09-19 the official Rust compiler, `rustc`, relies on LLVM for |
| 194 | +generating machine code. It's a requirement that LLVM supports an architecture |
| 195 | +for `rustc` to support it. |
| 196 | + |
| 197 | +There is no support for the Xtensa architecture in LLVM proper. You may be able |
| 198 | +to find several forks of LLVM with varying levels of support for the Xtensa |
| 199 | +architecture but `rustc` will not be able to use any of those forks due to the |
| 200 | +maintenance and infrastructure costs of developing `rustc` against different |
| 201 | +versions of LLVM. |
| 202 | + |
| 203 | +TL;DR `rustc` will support the Xtensa architecture when the official LLVM gains |
| 204 | +support for the Xtensa architecture. As LLVM is a project independent of the |
| 205 | +Rust project we can't give you any estimate on when that might happen. |
| 206 | + |
| 207 | +# My embedded Rust program is too big! |
| 208 | + |
| 209 | +We sometimes get questions like this one: "My Rust program is 500 KB but my |
| 210 | +microcontroller only has 16 KB of Flash; how can I make it fit?". |
| 211 | + |
| 212 | +The first thing to confirm is that correctly measuring the size of your program. |
| 213 | +`rustc` produces ELF files for most embedded targets. ELF files have metadata |
| 214 | +and contain debug information so measuring their size on disk with e.g. `ls -l` |
| 215 | +will give you the wrong number. |
| 216 | + |
| 217 | +``` console |
| 218 | +$ # 500 KB? |
| 219 | +$ ls -hl target/thumbv7m-none-eabi/debug/app |
| 220 | +-rwxr-xr-x 2 japaric japaric 554K Sep 19 13:37 target/thumbv7m-none-eabi/debug/app |
| 221 | +``` |
| 222 | + |
| 223 | +The correct way to measure the size of an embedded program is to use the `size` |
| 224 | +program or the [`cargo size`] subcommand. |
| 225 | + |
| 226 | +[`cargo size`]: https://github.com/rust-embedded/cargo-binutils |
| 227 | + |
| 228 | +``` console |
| 229 | +$ # ~ 2 KB of Flash |
| 230 | +$ cargo size --bin app -- -A |
| 231 | + Finished dev [unoptimized + debuginfo] target(s) in 0.01s |
| 232 | +app : |
| 233 | +section size addr |
| 234 | +.vector_table 1024 0x8000000 |
| 235 | +.text 776 0x8000400 |
| 236 | +.rodata 208 0x8000708 |
| 237 | +.data 0 0x20000000 |
| 238 | +.bss 0 0x20000000 |
| 239 | +.debug_str 145354 0x0 |
| 240 | +.debug_abbrev 11264 0x0 |
| 241 | +.debug_info 139259 0x0 |
| 242 | +.debug_macinfo 33 0x0 |
| 243 | +.debug_pubnames 40901 0x0 |
| 244 | +.debug_pubtypes 14326 0x0 |
| 245 | +.ARM.attributes 50 0x0 |
| 246 | +.debug_frame 21224 0x0 |
| 247 | +.debug_line 117666 0x0 |
| 248 | +.debug_ranges 63800 0x0 |
| 249 | +.comment 75 0x0 |
| 250 | +Total 555960 |
| 251 | +``` |
| 252 | + |
| 253 | +Of the standard sections, `.text`, `.rodata` and `.data` will occupy Flash / |
| 254 | +ROM; `.bss` and `.data` will occupy RAM; `.debug_*`, `.ARM.attributes` and |
| 255 | +`.comments` can be ignored as they won't be loaded into the target device |
| 256 | +memory. For the other sections you'll have to check your dependencies' docs. |
| 257 | + |
| 258 | +In this examples the program will occupy `2008` bytes of Flash. |
| 259 | + |
| 260 | +Note that most (all?) runtime crates, like `cortex-m-rt`, will check at link |
| 261 | +time that the program fits in the target device memory. If it doesn't fit you'll |
| 262 | +get a linker error and no output binary. So, provided that you correctly entered |
| 263 | +the size of the memory regions of your device then if it links it should fit in |
| 264 | +the target device! |
| 265 | + |
| 266 | +If you are measuring size using the right method and your program is still too |
| 267 | +big then check out our section on optimizations. |
| 268 | + |
| 269 | +> **TODO**(resources team) add link to the optimizations section |
0 commit comments