Skip to content

Commit 9fa5566

Browse files
committed
Add documentation for the new builtin 'avr-unknown-gnu-atmega328' target
This was added to Rust in rust-lang/rust#74941
1 parent 33bd7bc commit 9fa5566

3 files changed

+106
-9
lines changed

src/003-building-a-crate-for-avr.md

+31-9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@
22

33
After setting up the compiler, you may use it to generate assembly or machine code targeting a specific AVR microcontroller model.
44

5+
## Choosing a `--target`
6+
7+
The Rust nightly compiler includes a built-in target for ATmega328 named `avr-unknown-gnu-atmega328`
8+
9+
If you wish to target a microcontroller other than ATmega328, or you want to change any of the
10+
default builtin options like the linking parameters, then you will need to export the builtin
11+
`avr-unknown-gnu-atmega328` target to a custom target specification JSON file and modify
12+
it to suit your needs.
13+
14+
This target can be adapted to other microcontrollers as per the instructions in [3.1. The built-in `avr-unknown-gnu-atmega328` target](./003.1-the-avr-unknown-gnu-atmega328-target.md).
15+
16+
In summary, there are two options:
17+
18+
* Use `rustc --target=avr-unknown-gnu-atmega328` to use the default, builtin GCC based target for ATmega328
19+
* Or use `rustc --target=my-custom-avr-target.json` with either a JSON file adapted from the builtin
20+
`avr-unknown-gnu-atmega328` target above, or otherwise build the file manually you wish to avoiding the
21+
default path entirely.
22+
523
## Make sure you use the nightly version of Rust, not the default stable channel
624

725
The best way to ensure a crate is using the Nightly compiler is to run `rustup override set nightly` inside a terminal
@@ -12,25 +30,29 @@ any time `cargo` is used within the directory tree of the crate.
1230

1331
To compile and link an executable crate for AVR, run the following:
1432

33+
Using the builtin `avr-unknown-gnu-atmega328` target:
34+
35+
```rust
36+
cargo build -Z build-std=core --target avr-unknown-gnu-atmega328 --release
37+
```
38+
39+
Using a custom target specification JSON:
40+
41+
1542
```rust
16-
$ cargo build -Z build-std=core --target avr-atmega328p.json --release
43+
cargo build -Z build-std=core --target /path/to/my-custom-avr-target.json --release
1744
```
1845

19-
This will generate an AVR ELF file that can be subsequently flashed to a real device or ran inside a simulator.
20-
The ELF file will be available at `target/<TARGET JSON NAME>/release/<CRATE NAME>.elf`.
46+
Either or these generate an AVR ELF file that can be subsequently flashed to a real device or ran inside a simulator.
47+
The ELF file will be available at `target/<TARGET NAME>/release/<CRATE NAME>.elf`.
2148

2249
Notes:
2350

2451
* **`-Z build-std=core` is required whenever AVR is being targeted**. See [3.1. A note about the required Rust `-Z build-std=<CRATE,>` flag](./003.1-note-about-rust-build-std-flag.md) for more details.
25-
* **A target specification JSON file should almost always be specified**. There is a default target of `avr-unknown-unknown`, but this
26-
target should be avoided in virtually all real-life usecases[CITATION NEEDED]. The `avr-unknown-unknown` target is equivalent to the AVR-GCC default, partially-microcontroller-independent mode where the lowest common denominator - the `avr2` family - is targeted.
2752
* `--release` is not strictly required - debug mode should be as correct as release mode - however, **debug mode generates SLOW CODE, especially on AVR**. Release mode is much better.
2853

2954
**Example**: An in-context example of compiling a crate is given for the LED blinking example in [3.2. Example - Building the `blink` program for AVR](./003.2-example-building-blink.md).
3055

3156
### Targeting a different microcontroller model
3257

33-
Other models of AVR can be targeted by simply modifying the `cpu` field inside the target specification JSON. Each desired target microcontroller
34-
variant requires its own target specification JSON file differing only by the `cpu` field. You will find many of the existing AVR projects
35-
provide an-tree target specification JSON file only for the popular `atmega328p`, so you will in general need to duplicate the file and edit the `cpu`
36-
to get a crate compiling on a non-atmega328p microcontroler.
58+
The recommended way to do this is with a custom target specification JSON file per the instructions in [3.1. The built-in `avr-unknown-gnu-atmega328` target](./003.1-the-avr-unknown-gnu-atmega328-target.md).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# 3.1. The built-in `avr-unknown-gnu-atmega328` target
2+
3+
The Rust nightly compiler contains a built-in target, `avr-unknown-gnu-atmega328`, that
4+
generates code for the AVR [ATmega328](https://en.wikipedia.org/wiki/ATmega328) using the
5+
GNU AVR-GCC toolchain for linking support.
6+
7+
## Targeting custom microcontrollers by adapting 'avr-unkonwn-gnu-atmega328'
8+
9+
See the section [./005.1-the-target-specification-json-file.md](5.1. The Target Specification JSON File) for
10+
more information about how Rust target specification JSON files work.
11+
12+
To generate a Rust target specification JSON file from the builtin:
13+
14+
15+
```bash
16+
rustc --print target-spec-json -Z unstable-options --target avr-unknown-gnu-atmega328 > my-custom-avr-unknown-gnu-atmega328.json
17+
```
18+
19+
This prints the target specification JSON file `my-custom-avr-unknown-gnu-atmega328.json`:
20+
21+
```json
22+
{
23+
"arch": "avr",
24+
"cpu": "atmega328",
25+
"data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
26+
"eh-frame-header": false,
27+
"env": "",
28+
"exe-suffix": ".elf",
29+
"executables": true,
30+
"is-builtin": true,
31+
"late-link-args": {
32+
"gcc": [
33+
"-lgcc"
34+
]
35+
},
36+
"linker": "avr-gcc",
37+
"linker-flavor": "gcc",
38+
"linker-is-gnu": true,
39+
"llvm-target": "avr-unknown-unknown",
40+
"os": "unknown",
41+
"pre-link-args": {
42+
"gcc": [
43+
"-mmcu=atmega328",
44+
"-Wl,--as-needed"
45+
]
46+
},
47+
"target-c-int-width": "16",
48+
"target-endian": "little",
49+
"target-pointer-width": "16",
50+
"vendor": "unknown"
51+
}
52+
```
53+
54+
To adapt this file to target a different microcontroller:
55+
56+
* Replace the top-level `"cpu": "atmega328"` with `"cpu": "YOUR-AVR-VARIANT-NAME"`
57+
* Replace `"-mmcu=atmega328"` with `"-mmcu=YOUR-AVR-VARIANT-NAME"`
58+
59+
The file can then be passed to Rust via the `rustc --target <JSON FILE PATH>` instead of
60+
`rustc --target avr-unknown-gnu-atmega328`, which will tailor the generated code to your
61+
desired microcontroller.
62+
63+
It is also possible to customize link parameters if desired by modifying the JSON file.
64+
65+
## Compiling for AVR without the GNU toolchain
66+
67+
At the moment, the only builtin AVR target `avr-unknown-gnu-atmega328` always requires
68+
AVR-GCC, AVR-libc and AVR-binutils from the GNU project.
69+
70+
The LLVM LLD linker has some limited support for AVR which in the future could be leveraged
71+
to allow compiling AVR Rust binaries without the dependency on the GNU toolchain. Some work
72+
on `compiler-builtins` and others would also be required. At the moment, the GNU toolchain
73+
is a hard dependency.
74+
no t

src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- [2. Installing the compiler](./002-installing-the-compiler.md)
66
- [Installing required third party tools](./002.1-installing-required-third-party-tools.md)
77
- [3. Building a crate for AVR](./003-building-a-crate-for-avr.md)
8+
- [The built-in `avr-unknown-gnu-atmega328` target](./003.1-the-avr-unknown-gnu-atmega328-target.md)
89
- [A note about the required Rust `-Z build-std=<CRATE,>` flag](./003.2-note-about-rust-build-std-flag.md)
910
- [Example - Building the `blink` program for AVR](./003.3-example-building-blink.md)
1011
- [4. Flashing a crate to a real AVR chip](./004-flashing-a-crate-to-chip.md)

0 commit comments

Comments
 (0)