### Install ARM GDB and QEMU on macOS Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/preface.md Installs the ARM Embedded GCC toolchain (including GDB) and QEMU for ARM emulation on macOS using Homebrew. ```console $ brew install --cask gcc-arm-embedded $ brew install qemu ``` -------------------------------- ### Install ARM Toolchain Bundle from ARM (Ubuntu) Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/preface.md Installs the ARM GNU toolchain, which includes GCC and GDB, and adds its bin directory to the system's PATH. This is an optional step as LLD is now the default linker. ```console $ tar xvjf gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2 $ mv gcc-arm-none-eabi- # optional $ export PATH=${PATH}:/bin # add this line to .bashrc to make persistent ``` -------------------------------- ### Install Rust Toolchain and Targets Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/preface.md Installs the stable Rust toolchain, adds the ARM Cortex-M target, and installs `cargo-binutils` and `llvm-tools` for embedded development. ```console $ rustup default stable $ rustc -V rustc 1.89.0 (29483883e 2025-08-04) $ rustup target add thumbv7m-none-eabi $ cargo install cargo-binutils $ rustup component add llvm-tools ``` -------------------------------- ### Install ARM GDB and QEMU on Ubuntu Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/preface.md Installs the ARM Embedded GDB and QEMU for ARM emulation on Ubuntu systems. For newer Ubuntu/Debian versions, `gdb-multiarch` is used. ```console # Ubuntu 16.04 $ sudo apt install gdb-arm-none-eabi $ sudo apt install qemu-system-arm # Ubuntu 18.04+ or Debian $ sudo apt install gdb-multiarch $ sudo apt install qemu-system-arm ``` -------------------------------- ### Using Asynchronous Write API (Rust) Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/dma.md Demonstrates the usage of the asynchronous `write_all` function. This example shows how to initiate and await a DMA write operation. ```rust async fn example_write() { let mut serial = Serial1; let buf = [0u8; 10]; write_all(&mut serial, &buf).await?; } // And here's an example of using the `read_exact` API: ``` -------------------------------- ### Example Logging Implementation with Semihosting - Rust Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/logging.md This Rust code implements a logging mechanism where log messages are encoded into the symbol names of static variables. It uses `cortex-m-semihosting` for I/O on embedded targets, allowing QEMU to simulate host I/O capabilities. The `debug::exit` API is used for program termination. ```rust #![no_std] use cortex_m_semihosting::io; #[macro_use] extern crate cortex_m_rt; #[export_name = "log::info"] // This symbol will be used by the logging system static LOG_INFO: u8 = 0; #[export_name = "log::warn"] // This symbol will be used by the logging system static LOG_WARN: u8 = 0; #[export_name = "log::error"] // This symbol will be used by the logging system static LOG_ERROR: u8 = 0; #[entry] fn main() -> ! { // In a real application, you would have a logging system that // decodes these symbols and prints the corresponding messages. // For this example, we'll just demonstrate that the symbols exist. // Example of how a logging system might use these symbols: // let info_addr = &LOG_INFO as *const u8 as usize; // let warn_addr = &LOG_WARN as *const u8 as usize; // let error_addr = &LOG_ERROR as *const u8 as usize; // io::println!("Info address: {:x}", info_addr).unwrap(); // io::println!("Warn address: {:x}", warn_addr).unwrap(); // io::println!("Error address: {:x}", error_addr).unwrap(); // To make the program terminate cleanly in QEMU debug::exit(debug::ExitCode::Success); loop {} } ``` -------------------------------- ### Rust Build Script for Bundling Archives Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/asm.md An example Rust build script (`build.rs`) that demonstrates how to bundle a pre-assembled static archive (`.a`) with a Rust crate. This script configures Cargo to link against the static library, making it available for the embedded application. ```rust println!("cargo:rustc-link-search=native={}", env::var("CARGO_MANIFEST_DIR").unwrap()); println!("cargo:rustc-link-lib=static=rt"); ``` -------------------------------- ### Cargo.toml Dependencies for Singleton App Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/singleton.md The relevant section of the Cargo.toml file for the singleton example application. It specifies the necessary dependencies, including `cortex-m` and potentially other features required for the singleton implementation. ```toml [dependencies] cortex-m = "0.7.6" ``` -------------------------------- ### Using Asynchronous Read API (Rust) Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/dma.md Illustrates how to use the asynchronous `read_exact` function. This example shows the process of initiating and awaiting a DMA read operation. ```rust async fn example_read() { let mut serial = Serial1; let mut buf = [0u8; 10]; read_exact(&mut serial, &mut buf).await?; } ``` -------------------------------- ### Test Embedded Applications with QEMU and GDB Source: https://context7.com/rust-embedded/embedonomicon/llms.txt Run and debug embedded Rust applications on a virtual microcontroller (LM3S6965) using QEMU and GDB. This involves building the application, starting QEMU with a GDB server, and connecting GDB for debugging. ```console $ cargo build --target thumbv7m-none-eabi $ # Run in QEMU with GDB server $ qemu-system-arm \ -cpu cortex-m3 \ -machine lm3s6965evb \ -gdb tcp::3333 \ -S \ -nographic \ -kernel target/thumbv7m-none-eabi/debug/app $ # Connect with GDB in another terminal $ arm-none-eabi-gdb -q target/thumbv7m-none-eabi/debug/app (gdb) target remote :3333 (gdb) break Reset (gdb) continue (gdb) print/x $sp $1 = 0x20010000 ``` -------------------------------- ### Linker Script for Zero-Cost Sections Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/logging.md This linker script defines a new output section named '.log'. It collects symbols from input object files that are placed in '.log' sections and places them into the output '.log' section. The `(INFO)` flag marks it as a non-allocatable section, meaning it's kept as metadata in the ELF binary but not loaded onto the target device. The `0` specifies the start address for this output section. ```linker-script /* Example content of log.x */ .log 0 (INFO) : { *(.log) } ``` -------------------------------- ### Main Application with HardFault Handler Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/asm.md A simple Rust program designed to test the HardFault handler integration. It includes a basic setup and a call that is expected to trigger a HardFault, allowing verification of the trampoline and handler. ```rust #![no_std] #![no_main] use panic_halt as _; use cortex_m_rt::entry; use cortex_m_rt::exception::ExceptionFrame; #[entry] fn main() -> ! { // Trigger a HardFault unsafe { // Dereference a null pointer core::ptr::read_volatile(core::ptr::null()); } loop {} } #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { loop {} } // The HardFault handler must be defined. // It is called by the trampoline. #[no_mangle] fn HardFault(_ef: &ExceptionFrame) -> ! { loop {} } ``` -------------------------------- ### Get Binary Size for `#![no_std]` App Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/smallest-no-std.md This command calculates and displays the size of the compiled binary for the `#![no_std]` application targeting `thumbv7m-none-eabi`. This is useful for embedded development where binary size is critical. ```bash cargo size --target thumbv7m-none-eabi --bin app ``` -------------------------------- ### Linker Script for Section Definitions Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/sections-in-rust.md This snippet shows a portion of a linker script used in embedded projects. It defines the start and end symbols for the .bss and .data sections, which are crucial for the initialization process discussed in the chapter. ```linker script _sbss = adata + (.bss - .data); _ebss = adata + (.bss - .data) + SIZEOF(.bss); _sdata = adata + (.bss - .data) + SIZEOF(.bss); _edata = adata + (.bss - .data) + SIZEOF(.bss) + SIZEOF(.data); ``` -------------------------------- ### Cortex-M Reset Handler and Vector Table in Rust Source: https://context7.com/rust-embedded/embedonomicon/llms.txt Demonstrates setting up the reset handler and vector table for Cortex-M devices in Rust. The vector table is placed at the start of flash memory, with the first entry for the initial stack pointer and the second pointing to the reset handler. ```rust #![no_main] #![no_std] use core::panic::PanicInfo; // The reset handler - first function executed after reset #[unsafe(no_mangle)] pub unsafe extern "C" fn Reset() -> ! { let _x = 42; loop {} } // The reset vector placed in the vector table #[unsafe(link_section = ".vector_table.reset_vector")] #[unsafe(no_mangle)] pub static RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset; #[panic_handler] fn panic(_panic: &PanicInfo<'_>) -> ! { loop {} } ``` -------------------------------- ### Assembling and Archiving with `arm-none-eabi-as` and `ar` Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/asm.md Demonstrates the manual process of assembling an assembly file (`.s`) into an object file (`.o`) using `arm-none-eabi-as` and then creating a static archive (`.a`) from the object file using `ar`. This method is an alternative to using the `cc` crate for pre-assembled code. ```console $ arm-none-eabi-as -march=armv7-m asm.s -o asm.o $ ar crs librt.a asm.o $ arm-none-eabi-objdump -Cd librt.a ``` -------------------------------- ### Illustrating compiler_fence Ordering Effects (Rust) Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/dma.md This example visually demonstrates the effect of `compiler_fence` with `Ordering::Release` and `Ordering::Acquire`. The `Release` fence prevents preceding operations from moving after DMA start, and the `Acquire` fence prevents subsequent operations from moving before DMA completion check. ```rust pub fn read_exact(&mut self, buf: &mut [u8]) { // ... DMA setup ... compiler_fence(Ordering::Release); self.dma.start(); } pub fn wait(&mut self) { while !self.is_done() {} compiler_fence(Ordering::Acquire); // ... operations after DMA completion ... } ``` -------------------------------- ### Configure Linker Arguments for Target File Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/custom-target.md This JSON snippet demonstrates how to specify linker arguments for a target file. It includes `pre-link-args` and `post-link-args`, with keys corresponding to the linker flavor (e.g., 'gcc'). These arguments are crucial for integrating with specific toolchains and ensuring correct linking behavior. ```json { "pre-link-args": { "gcc": [ "-Wl,--as-needed", "-Wl,-z,noexecstack", "-m64" ] }, "post-link-args": { "gcc": [ "-Wl,--allow-multiple-definition", "-Wl,--start-group,-lc,-lm,-lgcc,-lstdc++,-lsupc++,--end-group" ] } } ``` -------------------------------- ### Build Commands for Object and Archive Files Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/asm.md Illustrates the command-line invocations used by the `cc` crate for assembling object files and creating static archives. This output, typically found in `target/output` files, shows the compiler and archiver commands being executed. ```console $ grep running $(find target -name output) ``` ```text running: "arm-none-eabi-gcc" "-O0" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "-mthumb" "-march=armv7-m" "-Wall" "-Wextra" "-o" "/tmp/app/target/thumbv7m-none-eabi/debug/build/rt-6ee84e54724f2044/out/asm.o" "-c" "asm.s" running: "ar" "crs" "/tmp/app/target/thumbv7m-none-eabi/debug/build/rt-6ee84e54724f2044/out/libasm.a" "/home/japaric/rust-embedded/embedonomicon/ci/asm/app/target/thumbv7m-none-eabi/debug/build/rt-6ee84e54724f2044/out/asm.o" ``` -------------------------------- ### Asynchronous Write Implementation (Rust) Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/dma.md Implements an asynchronous write operation for a DMA transfer, mirroring the `Write::write_all` API. This example demonstrates a potential memory-unsafe approach. ```rust use crate::{Serial1, Transfer}; /// Asynchronously writes a buffer to the serial port. pub async fn write_all<'a>( serial: &'a mut Serial1, buf: &'a [u8], ) -> Result<(), ()> { let transfer = Transfer::new(()); // Dummy transfer object // In a real scenario, this would initiate a DMA transfer. // For simplicity, we're just simulating the operation. serial.write(buf)?; // The actual DMA completion would be awaited here. Ok(()) } // We can also implement an asynchronous version of [`Read::read_exact`]. ``` -------------------------------- ### Create and Configure Logging Crate in Rust Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/logging.md Demonstrates creating a new Rust library crate for logging and defining its core functionality, including a logging macro and build script for linker script integration. ```rust pub macro log { ($($arg:tt)*) => { log::log(concat!(module_path!(), ":"), $($arg)*) }; } #[macro_export] pub fn log(location: &str, message: &str) { // In a real embedded system, this would write to a serial port or other output. // For this example, we'll just print to stdout. eprintln!("{}{}", location, message); } ``` ```rust fn main() { // This build script is used to include the linker script. // In a real project, you might have more complex build logic here. println!("cargo:rerun-if-changed=log.x"); } ``` -------------------------------- ### Define Text Section in Linker Script Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/memory-layout.md Defines the `.text` output section for program subroutines, located in FLASH memory after the preceding section. The linker automatically determines its start address. ```linker script .text : { /* .. */ } > FLASH ``` -------------------------------- ### Configure Cargo Runner for QEMU Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/logging.md This TOML snippet shows how to configure the `.cargo/config.toml` file to set a default runner for a specific target. This allows `cargo run` to automatically use a specified QEMU command for executing the compiled binary. ```toml # Example content of .cargo/config.toml target.thumbv7m-none-eabi.runner = "qemu-system-arm -cpu ... -kernel ..." ``` -------------------------------- ### Linker Script for Zero-Cost Logging Section Source: https://context7.com/rust-embedded/embedonomicon/llms.txt Defines a linker script section named `.log` for zero-cost logging. This section will contain the symbol addresses used for logging messages. ```text SECTIONS { .log 0 (INFO) : { *(.log); } } ``` -------------------------------- ### Asynchronous Read Implementation (Rust) Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/dma.md Implements an asynchronous read operation for a DMA transfer, analogous to `Read::read_exact`. This example highlights potential memory safety issues in asynchronous operations. ```rust /// Asynchronously reads data into a buffer from the serial port. pub async fn read_exact<'a>( serial: &'a mut Serial1, buf: &'a mut [u8], ) -> Result<(), ()> { let transfer = Transfer::new(()); // Dummy transfer object // In a real scenario, this would initiate a DMA transfer. // For simplicity, we're just simulating the operation. serial.read(buf)?; // The actual DMA completion would be awaited here. Ok(()) } // Here's how to use the `write_all` API: ``` -------------------------------- ### Rust Singleton Application Code Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/singleton.md The main Rust code for the singleton example application. This code likely defines and uses a global singleton, potentially for logging or device access, within a cortex-m environment. ```rust pub trait Logger { fn log(&self, data: &[u8]); } static mut LOGGER: Option<&'static dyn Logger> = None; pub fn init_logger(logger: &'static dyn Logger) { // SAFETY: This is safe because we are initializing the logger exactly once // at the beginning of the program. unsafe { LOGGER = Some(logger); } } pub fn log(data: &[u8]) { if let Some(logger) = LOGGER { logger.log(data); } } #[cfg(feature = "panic-handler")] #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } #[cfg(feature = "default-entry")] #[no_mangle] fn default_entry() -> ! { loop {} } ``` -------------------------------- ### Disassembly of Application Binary Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/main.md This is a sample disassembly output for the application binary. It shows the machine code instructions, including the user-defined `main` function, demonstrating the result of linking the application with the 'rt' runtime. ```text Disassembly of section .text: 0000000000000000 : 0: f8 df 80 00 ldr r0, [pc, #0] ; (4 ) 4: f8 df 80 00 ldr r0, [pc, #0] ; (8 ) 8: f8 df 80 00 ldr r0, [pc, #0] ; (c ) c: f8 df 80 00 ldr r0, [pc, #0] ; (10 ) 10: f8 df 80 00 ldr r0, [pc, #0] ; (14 ) 14: f8 df 80 00 ldr r0, [pc, #0] ; (18 ) 18: f8 df 80 00 ldr r0, [pc, #0] ; (1c ) 1c: f8 df 80 00 ldr r0, [pc, #0] ; (20 ) 20: f8 df 80 00 ldr r0, [pc, #0] ; (24 ) 24: f8 df 80 00 ldr r0, [pc, #0] ; (28 ) 28: f8 df 80 00 ldr r0, [pc, #0] ; (2c ) 2c: f8 df 80 00 ldr r0, [pc, #0] ; (30 ) 30: f8 df 80 00 ldr r0, [pc, #0] ; (34 ) 34: f8 df 80 00 ldr r0, [pc, #0] ; (38 ) 38: f8 df 80 00 ldr r0, [pc, #0] ; (3c ) 3c: f8 df 80 00 ldr r0, [pc, #0] ; (40 ) 40: f8 df 80 00 ldr r0, [pc, #0] ; (44 ) 44: f8 df 80 00 ldr r0, [pc, #0] ; (48 ) 48: f8 df 80 00 ldr r0, [pc, #0] ; (4c ) 4c: f8 df 80 00 ldr r0, [pc, #0] ; (50 ) 50: f8 df 80 00 ldr r0, [pc, #0] ; (54 ) 54: f8 df 80 00 ldr r0, [pc, #0] ; (58 ) 58: f8 df 80 00 ldr r0, [pc, #0] ; (5c ) 5c: f8 df 80 00 ldr r0, [pc, #0] ; (60 ) 60: f8 df 80 00 ldr r0, [pc, #0] ; (64 ) 64: f8 df 80 00 ldr r0, [pc, #0] ; (68 ) 68: f8 df 80 00 ldr r0, [pc, #0] ; (6c ) 6c: f8 df 80 00 ldr r0, [pc, #0] ; (70 ) 70: f8 df 80 00 ldr r0, [pc, #0] ; (74 ) 74: f8 df 80 00 ldr r0, [pc, #0] ; (78 ) 78: f8 df 80 00 ldr r0, [pc, #0] ; (7c ) 7c: f8 df 80 00 ldr r0, [pc, #0] ; (80 ) 80: f8 df 80 00 ldr r0, [pc, #0] ; (84 ) 84: f8 df 80 00 ldr r0, [pc, #0] ; (88 ) 88: f8 df 80 00 ldr r0, [pc, #0] ; (8c ) 8c: f8 df 80 00 ldr r0, [pc, #0] ; (90 ) 90: f8 df 80 00 ldr r0, [pc, #0] ; (94 ) 94: f8 df 80 00 ldr r0, [pc, #0] ; (98 ) 98: f8 df 80 00 ldr r0, [pc, #0] ; (9c ) 9c: f8 df 80 00 ldr r0, [pc, #0] ; (a0 ) a0: f8 df 80 00 ldr r0, [pc, #0] ; (a4 ) a4: f8 df 80 00 ldr r0, [pc, #0] ; (a8 ) a8: f8 df 80 00 ldr r0, [pc, #0] ; (ac ) ac: f8 df 80 00 ldr r0, [pc, #0] ; (b0 ) b0: f8 df 80 00 ldr r0, [pc, #0] ; (b4 ) b4: f8 df 80 00 ldr r0, [pc, #0] ; (b8 ) b8: f8 df 80 00 ldr r0, [pc, #0] ; (bc ) bc: f8 df 80 00 ldr r0, [pc, #0] ; (c0 ) c0: f8 df 80 00 ldr r0, [pc, #0] ; (c4 ) c4: f8 df 80 00 ldr r0, [pc, #0] ; (c8 ) c8: f8 df 80 00 ldr r0, [pc, #0] ; (cc ) cc: f8 df 80 00 ldr r0, [pc, #0] ; (d0 ) d0: f8 df 80 00 ldr r0, [pc, #0] ; (d4 ) d4: f8 df 80 00 ldr r0, [pc, #0] ; (d8 ) d8: f8 df 80 00 ldr r0, [pc, #0] ; (dc ) dc: f8 df 80 00 ldr r0, [pc, #0] ; (e0 ) e0: f8 df 80 00 ldr r0, [pc, #0] ; (e4 ) e4: f8 df 80 00 ldr r0, [pc, #0] ; (e8 ) e8: f8 df 80 00 ldr r0, [pc, #0] ; (ec ) ec: f8 df 80 00 ldr r0, [pc, #0] ; (f0 ) f0: f8 df 80 00 ldr r0, [pc, #0] ; (f4 ) f4: f8 df 80 00 ldr r0, [pc, #0] ; (f8 ) f8: f8 df 80 00 ldr r0, [pc, #0] ; (fc ) fc: f8 df 80 00 ldr r0, [pc, #0] ; (100 ) 100: f8 df 80 00 ldr r0, [pc, #0] ; (104 ) 104: f8 df 80 00 ldr r0, [pc, #0] ; (108 ) 108: f8 df 80 00 ldr r0, [pc, #0] ; (10c ) 10c: f8 df 80 00 ldr r0, [pc, #0] ; (110 ) 110: f8 df 80 00 ldr r0, [pc, #0] ; (114 ) 114: f8 df 80 00 ldr r0, [pc, #0] ; (118 ) 118: f8 df 80 00 ldr r0, [pc, #0] ; (11c ) 11c: f8 df 80 00 ldr r0, [pc, #0] ; (120 ) 120: f8 df 80 00 ldr r0, [pc, #0] ; (124 ) 124: f8 df 80 00 ldr r0, [pc, #0] ; (128 ) 128: f8 df 80 00 ldr r0, [pc, #0] ; (12c ) 12c: f8 df 80 00 ldr r0, [pc, #0] ; (130 ) 130: f8 df 80 00 ldr r0, [pc, #0] ; (134 ) 134: f8 df 80 00 ldr r0, [pc, #0] ; (138 ) 138: f8 df 80 00 ldr r0, [pc, #0] ; (13c ) 13c: f8 df 80 00 ldr r0, [pc, #0] ; (140 ) 140: f8 df 80 00 ldr r0, [pc, #0] ; (144 ) 144: f8 df 80 00 ldr r0, [pc, #0] ; (148 ) 148: f8 df 80 00 ldr r0, [pc, #0] ; (14c ) 14c: f8 df 80 00 ldr r0, [pc, #0] ; (150 ) 150: f8 df 80 00 ldr r0, [pc, #0] ; (154 ) 154: f8 df 80 00 ldr r0, [pc, #0] ; (158 ) 158: f8 df 80 00 ldr r0, [pc, #0] ; (15c ) 15c: f8 df 80 00 ldr r0, [pc, #0] ; (160 ) 160: f8 df 80 00 ldr r0, [pc, #0] ; (164 ) 164: f8 df 80 00 ldr r0, [pc, #0] ; (168 ) 168: f8 df 80 00 ldr r0, [pc, #0] ; (16c ) 16c: f8 df 80 00 ldr r0, [pc, #0] ; (170 ) 170: f8 df 80 00 ldr r0, [pc, #0] ; (174 ) 174: f8 df 80 00 ldr r0, [pc, #0] ; (178 ) 178: f8 df 80 00 ldr r0, [pc, #0] ; (17c ) 17c: f8 df 80 00 ldr r0, [pc, #0] ; (180 ) 180: f8 df 80 00 ldr r0, [pc, #0] ; (184 ) 184: f8 df 80 00 ldr r0, [pc, #0] ; (188 ) 188: f8 df 80 00 ldr r0, [pc, #0] ; (18c ) 18c: f8 df 80 00 ldr r0, [pc, #0] ; (190 ) 190: f8 df 80 00 ldr r0, [pc, #0] ; (194 ) 194: f8 df 80 00 ldr r0, [pc, #0] ; (198 ) 198: f8 df 80 00 ldr r0, [pc, #0] ; (19c ) 19c: f8 df 80 00 ldr r0, [pc, #0] ; (1a0 ) 1a0: f8 df 80 00 ldr r0, [pc, #0] ; (1a4 ) 1a4: f8 df 80 00 ldr r0, [pc, #0] ; (1a8 ) 1a8: f8 df 80 00 ldr r0, [pc, #0] ; (1ac ) 1ac: f8 df 80 00 ldr r0, [pc, #0] ; (1b0 ) 1b0: f8 df 80 00 ldr r0, [pc, #0] ; (1b4 ) 1b4: f8 df 80 00 ldr r0, [pc, #0] ; (1b8 ) 1b8: f8 df 80 00 ldr r0, [pc, #0] ; (1bc ) 1bc: f8 df 80 00 ldr r0, [pc, #0] ; (1c0 ) 1c0: f8 df 80 00 ldr r0, [pc, #0] ; (1c4 ) 1c4: f8 df 80 00 ldr r0, [pc, #0] ; (1c8 ) 1c8: f8 df 80 00 ldr r0, [pc, #0] ; (1cc ) 1cc: f8 df 80 00 ldr r0, [pc, #0] ; (1d0 ) 1d0: f8 df 80 00 ldr r0, [pc, #0] ; (1d4 ) 1d4: f8 df 80 00 ldr r0, [pc, #0] ; (1d8 ) 1d8: f8 df 80 00 ldr r0, [pc, #0] ; (1dc ) 1dc: f8 df 80 00 ldr r0, [pc, #0] ; (1e0 ) 1e0: f8 df 80 00 ldr r0, [pc, #0] ; (1e4 ) 1e4: f8 df 80 00 ldr r0, [pc, #0] ; (1e8 ) 1e8: f8 df 80 00 ldr r0, [pc, #0] ; (1ec ) 1ec: f8 df 80 00 ldr r0, [pc, #0] ; (1f0 ) 1f0: f8 df 80 00 ldr r0, [pc, #0] ; (1f4 ) 1f4: f8 df 80 00 ldr r0, [pc, #0] ; (1f8 ) 1f8: f8 df 80 00 ldr r0, [pc, #0] ; (1fc ) 1fc: f8 df 80 00 ldr r0, [pc, #0] ; (200 ) 200: f8 df 80 00 ldr r0, [pc, #0] ; (204 ) 204: f8 df 80 00 ldr r0, [pc, #0] ; (208 ) 208: f8 df 80 00 ldr r0, [pc, #0] ; (20c ) 20c: f8 df 80 00 ldr r0, [pc, #0] ; (210 ) 210: f8 df 80 00 ldr r0, [pc, #0] ; (214 ) 214: f8 df 80 00 ldr r0, [pc, #0] ; (218 ) 218: f8 df 80 00 ldr r0, [pc, #0] ; (21c ) 21c: f8 df 80 00 ldr r0, [pc, #0] ; (220 ) 220: f8 df 80 00 ldr r0, [pc, #0] ; (224 ) 224: f8 df 80 00 ldr r0, [pc, #0] ; (228 ) 228: f8 df 80 00 ldr r0, [pc, #0] ; (22c ) 22c: f8 df 80 00 ldr r0, [pc, #0] ; (230 ) 230: f8 df 80 00 ldr r0, [pc, #0] ; (234 ) 234: f8 df 80 00 ldr r0, [pc, #0] ; (238 ) 238: f8 df 80 00 ldr r0, [pc, #0] ; (23c ) 23c: f8 df 80 00 ldr r0, [pc, #0] ; (240 ) 240: f8 df 80 00 ldr r0, [pc, #0] ; (244 ) 244: f8 df 80 00 ldr r0, [pc, #0] ; (248 ) 248: f8 df 80 00 ldr r0, [pc, #0] ; (24c ) 24c: f8 df 80 00 ldr r0, [pc, #0] ; (250 ) 250: f8 df 80 00 ldr r0, [pc, #0] ; (254 ) 254: f8 df 80 00 ldr r0, [pc, #0] ; (258 ) 258: f8 df 80 00 ldr r0, [pc, #0] ; (25c ) 25c: f8 df 80 00 ldr r0, [pc, #0] ; (260 ) 260: f8 df 80 00 ldr r0, [pc, #0] ; (264 ) 264: f8 df 80 00 ldr r0, [pc, #0] ; (268 ) 268: f8 df 80 00 ldr r0, [pc, #0] ; (26c ) 26c: f8 df 80 00 ldr r0, [pc, #0] ; (270 ) 270: f8 df 80 00 ldr r0, [pc, #0] ; (274 ) 274: f8 df 80 00 ldr r0, [pc, #0] ; (278 ) 278: f8 df 80 00 ldr r0, [pc, #0] ; (27c ) 27c: f8 df 80 00 ldr r0, [pc, #0] ; (280 ) 280: f8 df 80 00 ldr r0, [pc, #0] ; (284 ) 284: f8 df 80 00 ldr r0, [pc, #0] ; (288 ) 288: f8 df 80 00 ldr r0, [pc, #0] ; (28c ) 28c ``` -------------------------------- ### Cortex-M Exception Handler Vector Table Setup in Rust Source: https://context7.com/rust-embedded/embedonomicon/llms.txt Defines the vector table for Cortex-M exceptions in Rust, allowing for the declaration of exception handlers. Default handlers can be overridden using linker script PROVIDE directives. ```rust #![no_std] use core::panic::PanicInfo; use core::ptr; pub union Vector { reserved: u32, handler: unsafe extern "C" fn(), } unsafe extern "C" { fn NMI(); fn HardFault(); fn MemManage(); fn BusFault(); fn UsageFault(); fn SVCall(); fn PendSV(); fn SysTick(); } #[unsafe(link_section = ".vector_table.exceptions")] #[unsafe(no_mangle)] pub static EXCEPTIONS: [Vector; 14] = [ Vector { handler: NMI }, Vector { handler: HardFault }, Vector { handler: MemManage }, Vector { handler: BusFault }, Vector { handler: UsageFault }, Vector { reserved: 0 }, Vector { reserved: 0 }, Vector { reserved: 0 }, Vector { reserved: 0 }, Vector { handler: SVCall }, Vector { reserved: 0 }, Vector { reserved: 0 }, Vector { handler: PendSV }, Vector { handler: SysTick }, ]; #[unsafe(no_mangle)] pub extern "C" fn DefaultExceptionHandler() { loop {} } ``` -------------------------------- ### Configure Cargo for Linker Script Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/logging.md This TOML snippet shows how to configure the `.cargo/config.toml` file to include a custom linker script. The `-Tlog.x` argument is appended to the linker arguments, instructing the linker to use the specified `log.x` script for building the output binary. ```toml # Example content of .cargo/config.toml [target.thumbv7m-none-eabi] linker = "thumbv7m-none-eabi-ld" rustflags = ["-C", "link-arg=-Tlog.x"] ``` -------------------------------- ### Define Custom Target for Unsupported Platforms Source: https://context7.com/rust-embedded/embedonomicon/llms.txt Create custom target JSON files for unsupported platforms. This specifies architecture, ABI, linker settings, and atomic operation support, enabling cross-compilation for new hardware. ```json { "llvm-target": "thumbv7m-none-eabi", "arch": "arm", "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", "os": "none", "env": "", "vendor": "", "target-endian": "little", "target-pointer-width": "32", "target-c-int-width": "32", "linker": "arm-none-eabi-gcc", "linker-flavor": "gcc", "panic-strategy": "abort", "max-atomic-width": 32, "relocation-model": "static", "executables": true, "emit-debug-gdb-scripts": false } ``` -------------------------------- ### Configure LLVM Features for Target File Source: https://github.com/rust-embedded/embedonomicon/blob/master/src/custom-target.md This JSON snippet shows how to configure LLVM features for a target file. The `features` field accepts a comma-separated string of features, prefixed with '+' to enable or '-' to disable. This is important for enabling CPU-specific optimizations and ensuring correct behavior, especially for targets requiring strict memory alignment. ```json { "features": "+soft-float,+neon" } ```