mirror of https://github.com/rust-lang/rust.git
Create a generic AVR target: avr-none
This commit removes the `avr-unknown-gnu-atmega328` target and replaces it with a more generic `avr-none` variant that must be specialized with the `-C target-cpu` flag (e.g. `-C target-cpu=atmega328p`).
This commit is contained in:
parent
ed49386d3a
commit
78ddabf31d
|
@ -1990,6 +1990,7 @@ fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor)
|
|||
if let Some(args) = sess.target.pre_link_args.get(&flavor) {
|
||||
cmd.verbatim_args(args.iter().map(Deref::deref));
|
||||
}
|
||||
|
||||
cmd.verbatim_args(&sess.opts.unstable_opts.pre_link_args);
|
||||
}
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ pub(crate) fn get_linker<'a>(
|
|||
hinted_static: None,
|
||||
is_ld: cc == Cc::No,
|
||||
is_gnu: flavor.is_gnu(),
|
||||
uses_lld: flavor.uses_lld(),
|
||||
}) as Box<dyn Linker>,
|
||||
LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
|
@ -361,6 +362,7 @@ struct GccLinker<'a> {
|
|||
// Link as ld
|
||||
is_ld: bool,
|
||||
is_gnu: bool,
|
||||
uses_lld: bool,
|
||||
}
|
||||
|
||||
impl<'a> GccLinker<'a> {
|
||||
|
@ -552,6 +554,7 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
self.link_args(&["--entry", "_initialize"]);
|
||||
}
|
||||
}
|
||||
|
||||
// VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
|
||||
// it switches linking for libc and similar system libraries to static without using
|
||||
// any `#[link]` attributes in the `libc` crate, see #72782 for details.
|
||||
|
@ -567,6 +570,15 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
{
|
||||
self.cc_arg("--static-crt");
|
||||
}
|
||||
|
||||
// avr-none doesn't have default ISA, users must specify which specific
|
||||
// CPU (well, microcontroller) they are targetting using `-Ctarget-cpu`.
|
||||
//
|
||||
// Currently this makes sense only when using avr-gcc as a linker, since
|
||||
// it brings a couple of hand-written important intrinsics from libgcc.
|
||||
if self.sess.target.arch == "avr" && !self.uses_lld {
|
||||
self.verbatim_arg(format!("-mmcu={}", self.target_cpu));
|
||||
}
|
||||
}
|
||||
|
||||
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) {
|
||||
|
|
|
@ -1,45 +1,5 @@
|
|||
use object::elf;
|
||||
|
||||
use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
|
||||
|
||||
/// A base target for AVR devices using the GNU toolchain.
|
||||
///
|
||||
/// Requires GNU avr-gcc and avr-binutils on the host system.
|
||||
/// FIXME: Remove the second parameter when const string concatenation is possible.
|
||||
pub(crate) fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
|
||||
Target {
|
||||
arch: "avr".into(),
|
||||
metadata: crate::spec::TargetMetadata {
|
||||
description: None,
|
||||
tier: None,
|
||||
host_tools: None,
|
||||
std: None,
|
||||
},
|
||||
data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
|
||||
llvm_target: "avr-unknown-unknown".into(),
|
||||
pointer_width: 16,
|
||||
options: TargetOptions {
|
||||
env: "gnu".into(),
|
||||
|
||||
c_int_width: "16".into(),
|
||||
cpu: target_cpu.into(),
|
||||
exe_suffix: ".elf".into(),
|
||||
|
||||
linker: Some("avr-gcc".into()),
|
||||
eh_frame_header: false,
|
||||
pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[mmcu]),
|
||||
late_link_args: TargetOptions::link_args(
|
||||
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
|
||||
&["-lgcc"],
|
||||
),
|
||||
max_atomic_width: Some(16),
|
||||
atomic_cas: false,
|
||||
relocation_model: RelocModel::Static,
|
||||
..TargetOptions::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve the value of the EF_AVR_ARCH field for AVR ELF files, given the
|
||||
/// name of the target CPU / MCU.
|
||||
///
|
|
@ -1,7 +1,7 @@
|
|||
pub(crate) mod aix;
|
||||
pub(crate) mod android;
|
||||
pub(crate) mod apple;
|
||||
pub(crate) mod avr_gnu;
|
||||
pub(crate) mod avr;
|
||||
pub(crate) mod bpf;
|
||||
pub(crate) mod cygwin;
|
||||
pub(crate) mod dragonfly;
|
||||
|
|
|
@ -60,7 +60,7 @@ pub mod crt_objects;
|
|||
mod base;
|
||||
mod json;
|
||||
|
||||
pub use base::avr_gnu::ef_avr_arch;
|
||||
pub use base::avr::ef_avr_arch;
|
||||
|
||||
/// Linker is called through a C/C++ compiler.
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
|
@ -1797,7 +1797,7 @@ supported_targets! {
|
|||
("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia),
|
||||
("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia),
|
||||
|
||||
("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328),
|
||||
("avr-none", avr_none),
|
||||
|
||||
("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
|
||||
|
||||
|
@ -3062,7 +3062,10 @@ impl Target {
|
|||
&self.post_link_args,
|
||||
] {
|
||||
for (&flavor, flavor_args) in args {
|
||||
check!(!flavor_args.is_empty(), "linker flavor args must not be empty");
|
||||
check!(
|
||||
!flavor_args.is_empty() || self.arch == "avr",
|
||||
"linker flavor args must not be empty"
|
||||
);
|
||||
// Check that flavors mentioned in link args are compatible with the default flavor.
|
||||
match self.linker_flavor {
|
||||
LinkerFlavor::Gnu(..) => {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
Target {
|
||||
arch: "avr".into(),
|
||||
metadata: crate::spec::TargetMetadata {
|
||||
description: None,
|
||||
tier: None,
|
||||
host_tools: None,
|
||||
std: None,
|
||||
},
|
||||
data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
|
||||
llvm_target: "avr-unknown-unknown".into(),
|
||||
pointer_width: 16,
|
||||
options: TargetOptions {
|
||||
c_int_width: "16".into(),
|
||||
exe_suffix: ".elf".into(),
|
||||
linker: Some("avr-gcc".into()),
|
||||
eh_frame_header: false,
|
||||
pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[]),
|
||||
late_link_args: TargetOptions::link_args(
|
||||
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
|
||||
&["-lgcc"],
|
||||
),
|
||||
max_atomic_width: Some(16),
|
||||
atomic_cas: false,
|
||||
relocation_model: RelocModel::Static,
|
||||
need_explicit_cpu: true,
|
||||
..TargetOptions::default()
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
use crate::spec::{Target, base};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
base::avr_gnu::target("atmega328", "-mmcu=atmega328")
|
||||
}
|
|
@ -301,7 +301,7 @@ target | std | host | notes
|
|||
[`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare Armv8-R, hardfloat
|
||||
[`armv7a-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX
|
||||
[`armv7a-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX, hardfloat
|
||||
`avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core`
|
||||
`avr-none` | * | | AVR; requires `-Zbuild-std=core` and `-Ctarget-cpu=...`
|
||||
`bpfeb-unknown-none` | * | | BPF (big endian)
|
||||
`bpfel-unknown-none` | * | | BPF (little endian)
|
||||
`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian)
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
# `avr-none`
|
||||
|
||||
Series of microcontrollers from Atmel: ATmega8, ATmega328p etc.
|
||||
|
||||
**Tier: 3**
|
||||
|
||||
## Target maintainers
|
||||
|
||||
- [Patryk Wychowaniec](https://github.com/Patryk27) <pwychowaniec@pm.me>
|
||||
|
||||
## Requirements
|
||||
|
||||
This target is only cross-compiled; x86-64 Linux, x86-64 macOS and aarch64 macOS
|
||||
hosts are confirmed to work, but in principle any machine able to run rustc and
|
||||
avr-gcc should be good.
|
||||
|
||||
Compiling for this target requires `avr-gcc` installed, because a couple of
|
||||
intrinsics (like 32-bit multiplication) rely on [`libgcc`](https://github.com/gcc-mirror/gcc/blob/3269a722b7a03613e9c4e2862bc5088c4a17cc11/libgcc/config/avr/lib1funcs.S)
|
||||
and can't be provided through `compiler-builtins` yet. This is a limitation that
|
||||
[we hope to lift in the future](https://github.com/rust-lang/compiler-builtins/issues/711).
|
||||
|
||||
You'll also need to setup the `.cargo/config` file - see below for details.
|
||||
|
||||
## Building the target
|
||||
|
||||
Rust comes with AVR support enabled, you don't have to rebuild the compiler.
|
||||
|
||||
## Building Rust programs
|
||||
|
||||
Install `avr-gcc`:
|
||||
|
||||
```console
|
||||
# Ubuntu:
|
||||
$ sudo apt-get install gcc-avr
|
||||
|
||||
# Mac:
|
||||
$ brew tap osx-cross/avr && brew install avr-gcc
|
||||
|
||||
# NixOS (takes a couple of minutes, since it's not provided through Hydra):
|
||||
$ nix shell nixpkgs#pkgsCross.avr.buildPackages.gcc11
|
||||
```
|
||||
|
||||
... setup `.cargo/config` for your project:
|
||||
|
||||
```toml
|
||||
[build]
|
||||
target = "avr-none"
|
||||
rustflags = ["-C", "target-cpu=atmega328p"]
|
||||
|
||||
[unstable]
|
||||
build-std = ["core"]
|
||||
```
|
||||
|
||||
... and then simply run:
|
||||
|
||||
```console
|
||||
$ cargo build --release
|
||||
```
|
||||
|
||||
The final binary will be placed into
|
||||
`./target/avr-none/release/your-project.elf`.
|
||||
|
||||
Note that since AVRs have rather small amounts of registers, ROM and RAM, it's
|
||||
recommended to always use `--release` to avoid running out of space.
|
||||
|
||||
Also, please note that specifying `-C target-cpu` is required - here's a list of
|
||||
the possible variants:
|
||||
|
||||
https://github.com/llvm/llvm-project/blob/093d4db2f3c874d4683fb01194b00dbb20e5c713/clang/lib/Basic/Targets/AVR.cpp#L32
|
||||
|
||||
## Testing
|
||||
|
||||
You can use [`simavr`](https://github.com/buserror/simavr) to emulate the
|
||||
resulting firmware on your machine:
|
||||
|
||||
```console
|
||||
$ simavr -m atmega328p ./target/avr-none/release/your-project.elf
|
||||
```
|
||||
|
||||
Alternatively, if you want to write a couple of actual `#[test]`s, you can use
|
||||
[`avr-tester`](https://github.com/Patryk27/avr-tester).
|
|
@ -465,7 +465,10 @@ fn profiler_runtime() {
|
|||
#[test]
|
||||
fn asm_support() {
|
||||
let asms = [
|
||||
#[cfg(bootstrap)]
|
||||
("avr-unknown-gnu-atmega328", false),
|
||||
#[cfg(not(bootstrap))]
|
||||
("avr-none", false),
|
||||
("i686-unknown-netbsd", true),
|
||||
("riscv32gc-unknown-linux-gnu", true),
|
||||
("riscv64imac-unknown-none-elf", true),
|
||||
|
|
|
@ -253,6 +253,13 @@ impl Rustc {
|
|||
self
|
||||
}
|
||||
|
||||
/// Specify the target CPU.
|
||||
pub fn target_cpu<S: AsRef<str>>(&mut self, target_cpu: S) -> &mut Self {
|
||||
let target_cpu = target_cpu.as_ref();
|
||||
self.cmd.arg(format!("-Ctarget-cpu={target_cpu}"));
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify the crate type.
|
||||
pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
|
||||
self.cmd.arg("--crate-type");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//@ add-core-stubs
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --target avr-unknown-gnu-atmega328
|
||||
//@ compile-flags: --target avr-none -C target-cpu=atmega328p
|
||||
//@ needs-llvm-components: avr
|
||||
|
||||
#![feature(no_core, asm_experimental_arch)]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//@ add-core-stubs
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --target avr-unknown-gnu-atmega328
|
||||
//@ compile-flags: --target avr-none -C target-cpu=atmega328p
|
||||
//@ needs-llvm-components: avr
|
||||
|
||||
#![feature(no_core, asm_experimental_arch)]
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
//@ revisions: arm64ec_pc_windows_msvc
|
||||
//@ [arm64ec_pc_windows_msvc] compile-flags: --target arm64ec-pc-windows-msvc
|
||||
//@ [arm64ec_pc_windows_msvc] needs-llvm-components: aarch64
|
||||
//@ revisions: avr_unknown_gnu_atmega328
|
||||
//@ [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328
|
||||
//@ [avr_unknown_gnu_atmega328] needs-llvm-components: avr
|
||||
//@ revisions: avr_none
|
||||
//@ [avr_none] compile-flags: --target avr-none -C target-cpu=atmega328p
|
||||
//@ [avr_none] needs-llvm-components: avr
|
||||
//@ revisions: bpfeb_unknown_none
|
||||
//@ [bpfeb_unknown_none] compile-flags: --target bpfeb-unknown-none
|
||||
//@ [bpfeb_unknown_none] needs-llvm-components: bpf
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//@ add-core-stubs
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --target avr-unknown-gnu-atmega328
|
||||
//@ compile-flags: --target avr-none -C target-cpu=atmega328p
|
||||
//@ needs-llvm-components: avr
|
||||
|
||||
#![crate_type = "rlib"]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//@ compile-flags: -Copt-level=3 --target=avr-unknown-gnu-atmega328 --crate-type=rlib -C panic=abort
|
||||
//@ compile-flags: -Copt-level=3 --target=avr-none -C target-cpu=atmega328p --crate-type=rlib -C panic=abort
|
||||
//@ needs-llvm-components: avr
|
||||
|
||||
// This test validates that function pointers can be stored in global variables
|
||||
|
|
|
@ -22,7 +22,8 @@ fn main() {
|
|||
.input("avr-rjmp-offsets.rs")
|
||||
.opt_level("s")
|
||||
.panic("abort")
|
||||
.target("avr-unknown-gnu-atmega328")
|
||||
.target("avr-none")
|
||||
.target_cpu("avr")
|
||||
// normally one links with `avr-gcc`, but this is not available in CI,
|
||||
// hence this test diverges from the default behavior to enable linking
|
||||
// at all, which is necessary for the test (to resolve the labels). To
|
||||
|
@ -49,6 +50,7 @@ fn main() {
|
|||
// of the Rust compiler did produce a label `rjmp .-4` (misses the first
|
||||
// instruction in the loop).
|
||||
assert!(disassembly.contains("<main>"), "no main function in output");
|
||||
|
||||
disassembly
|
||||
.trim()
|
||||
.lines()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//@ needs-llvm-components: avr
|
||||
//@ compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib
|
||||
//@ compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib
|
||||
#![no_core]
|
||||
#![feature(no_core, lang_items)]
|
||||
#[lang="sized"]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//@ revisions: avr msp430
|
||||
//
|
||||
//@ [avr] needs-llvm-components: avr
|
||||
//@ [avr] compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib
|
||||
//@ [avr] compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib
|
||||
//@ [msp430] needs-llvm-components: msp430
|
||||
//@ [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib
|
||||
#![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)]
|
||||
|
|
Loading…
Reference in New Issue