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?
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
.