5.3. Creating an executable entry point with #[no_main]

The standard Rust AVR toolchain will use AVR-GCC's linker and chip-specific startup runtime libraries. Due to this, it is necessary to override Rust's default behaviour for the main function and instead write one that looks exactly like a AVR-GCC C/C++ main function so that the regular AVR-GCC libraries will link to it correctly.

To define a main function for AVR:

  • Add the #![no_main] attribute to the top of the crate root (src/main.rs)
  • Add a custom main function callable from C that will be picked up by AVR-GCC's startup libraries
// src/main.rs

#![no_std] // from the previous step
#![no_main]

#[no_mangle]
pub extern fn main() {
}

Notes:

  • The #![no_main] attribute tells Rust to skip its usual expectations on the main function, instead letting the developer manually handle it. In the usual case for AVR, the target specification JSON file will link startup files from AVR-GCC and thus the ABI of the Rust main function must match that of the of AVR-GCC startup files.
  • These steps can be applied to any executable within a crate, including those in the examples/ directory for a library and those injected via [[bin]] attributes in the Cargo.toml.