linuxrustcross-compilingavr

How can I get "avr-unknown-gnu-atmega328" target working?


I have started to learn Rust where I would like to see now if embedded Rust can be used with a suitable amount of duct tape to write new programs for the old 8-bit CP/M systems I play with as a hobby.

I am therefore looking at whether I can make the "generate z80 binary for Rust" toolchain described in https://github.com/MartinezTorres/z80_babel working on Ubuntu 22.04. (The trick is having Rust generate LLVM-IR for a known target with the same characteristics as an Z80, and then massage that into a binary).

The target suggested for LLVM-IR generation is avr-unknown-gnu-atmega328 which I have troubles with building.

$ rustup target add avr-unknown-gnu-atmega328
error: toolchain 'nightly-x86_64-unknown-linux-gnu' does not contain component 'rust-std' for target 'avr-unknown-gnu-atmega328'
note: not all platforms have the standard library pre-compiled: https://doc.rust-lang.org/nightly/rustc/platform-support.html
help: consider using `cargo build -Z build-std` instead
$ cargo build -Z build-std --target=avr-unknown-gnu-atmega328
   Compiling core v0.0.0 (/home/..../.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core)
   Compiling rustc-std-workspace-core v1.99.0 (/home/...../.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/rustc-std-workspace-core)
   Compiling compiler_builtins v0.1.108
   Compiling libc v0.2.153
error: ran out of registers during register allocation

Based on https://github.com/rust-lang/rust/issues/108232#issuecomment-1435958663 I edited Cargo.toml and tried with the --release flag which gave me these errors:

$ cargo build -Z build-std --target=avr-unknown-gnu-atmega328 --release
warning: `/home/..../.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
warning: `/home/..../.cargo/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
   Compiling gimli v0.28.1
   Compiling miniz_oxide v0.7.2
error[E0432]: unresolved import `alloc::sync`
 --> /home/...../.cargo/registry/src/index.crates.io-6f17d22bba15001f/gimli-0.28.1/src/read/dwarf.rs:2:12
  |
2 | use alloc::sync::Arc;
  |            ^^^^ could not find `sync` in `alloc`

error[E0432]: unresolved import `alloc::sync`
 --> /home/..../.cargo/registry/src/index.crates.io-6f17d22bba15001f/gimli-0.28.1/src/read/abbrev.rs:4:12
  |
4 | use alloc::sync::Arc;
  |            ^^^^ could not find `sync` in `alloc`

error: values of the type `[u8; 32768]` are too big for the current architecture
   --> /home/...../.cargo/registry/src/index.crates.io-6f17d22bba15001f/miniz_oxide-0.7.2/src/inflate/stream.rs:186:5
    |
186 |     state: &mut InflateState,
    |     ^^^^^

I could make the arm-unknown-linux-gnueabihf target work so I am possibly just missing a minor thing.

How should I approach getting the avr-unknown-gnu-atmega328 target working for my purpose on Ubuntu 22.04 x64 (or others)? Is another target a better choice?


Solution

  • It looks like this target does not support compare-and-swap with atomics, which means that Arc is not available, which in turn means std is not supported. You can still use core and alloc, though.

    To build only them:

    cargo +nightly build -Z build-std=core,alloc --target=avr-unknown-gnu-atmega328 --release
    

    You will also need to specify panic = "abort" and #![no_std] and #![no_main] and a custom panic handler and a start entry, since all of those are usually provided by std.

    You can also specify this in .cargo/config.toml:

    [build]
    target = "avr-unknown-gnu-atmega328"
    
    [unstable]
    build-std = ["core", "alloc"]
    

    Then, combined with override for using the nightly channel, the build can be as simple as cargo build --release.