From 776be79f7bb10b09e795e2ea93bb795a653c9b4c Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 24 Jun 2022 19:56:15 +0200 Subject: Move bootloader main to examples This should remove some confusion around embassy-boot-* being a library vs. a binary. The binary is now an example bootloader instead. --- examples/boot/bootloader/nrf/.cargo/config.toml | 20 +++++++++ examples/boot/bootloader/nrf/Cargo.toml | 58 +++++++++++++++++++++++++ examples/boot/bootloader/nrf/README.md | 11 +++++ examples/boot/bootloader/nrf/build.rs | 37 ++++++++++++++++ examples/boot/bootloader/nrf/memory-bm.x | 18 ++++++++ examples/boot/bootloader/nrf/memory-s140.x | 31 +++++++++++++ examples/boot/bootloader/nrf/memory.x | 18 ++++++++ examples/boot/bootloader/nrf/src/main.rs | 48 ++++++++++++++++++++ 8 files changed, 241 insertions(+) create mode 100644 examples/boot/bootloader/nrf/.cargo/config.toml create mode 100644 examples/boot/bootloader/nrf/Cargo.toml create mode 100644 examples/boot/bootloader/nrf/README.md create mode 100644 examples/boot/bootloader/nrf/build.rs create mode 100644 examples/boot/bootloader/nrf/memory-bm.x create mode 100644 examples/boot/bootloader/nrf/memory-s140.x create mode 100644 examples/boot/bootloader/nrf/memory.x create mode 100644 examples/boot/bootloader/nrf/src/main.rs (limited to 'examples/boot/bootloader/nrf') diff --git a/examples/boot/bootloader/nrf/.cargo/config.toml b/examples/boot/bootloader/nrf/.cargo/config.toml new file mode 100644 index 000000000..1060800a3 --- /dev/null +++ b/examples/boot/bootloader/nrf/.cargo/config.toml @@ -0,0 +1,20 @@ +[unstable] +build-std = ["core"] +build-std-features = ["panic_immediate_abort"] + +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +#runner = "./fruitrunner" +runner = "probe-run --chip nrf52840_xxAA" + +rustflags = [ + # Code-size optimizations. + "-Z", "trap-unreachable=no", + #"-C", "no-vectorize-loops", + "-C", "force-frame-pointers=yes", +] + +[build] +target = "thumbv7em-none-eabi" + +[env] +DEFMT_LOG = "trace" diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml new file mode 100644 index 000000000..8eb98623c --- /dev/null +++ b/examples/boot/bootloader/nrf/Cargo.toml @@ -0,0 +1,58 @@ +[package] +edition = "2021" +name = "nrf-bootloader-example" +version = "0.1.0" +description = "Bootloader for nRF chips" + +[dependencies] +defmt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.3", optional = true } + +embassy = { path = "../../../../embassy", default-features = false } +embassy-nrf = { path = "../../../../embassy-nrf", default-features = false, features = ["nightly"] } +embassy-boot-nrf = { path = "../../../../embassy-boot/nrf", default-features = false } +cortex-m = { version = "0.7" } +cortex-m-rt = { version = "0.7" } +cfg-if = "1.0.0" + +[features] +defmt = [ + "dep:defmt", + "embassy-boot-nrf/defmt", + "embassy-nrf/defmt", +] +softdevice = [ + "embassy-boot-nrf/softdevice", +] +debug = ["defmt-rtt"] + +[profile.dev] +debug = 2 +debug-assertions = true +incremental = false +opt-level = 'z' +overflow-checks = true + +[profile.release] +codegen-units = 1 +debug = 2 +debug-assertions = false +incremental = false +lto = 'fat' +opt-level = 'z' +overflow-checks = false + +# do not optimize proc-macro crates = faster builds from scratch +[profile.dev.build-override] +codegen-units = 8 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false + +[profile.release.build-override] +codegen-units = 8 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false diff --git a/examples/boot/bootloader/nrf/README.md b/examples/boot/bootloader/nrf/README.md new file mode 100644 index 000000000..23497a038 --- /dev/null +++ b/examples/boot/bootloader/nrf/README.md @@ -0,0 +1,11 @@ +# Bootloader for nRF + +The bootloader uses `embassy-boot` to interact with the flash. + +# Usage + +Flash the bootloader + +``` +cargo flash --features embassy-nrf/nrf52832 --release --chip nRF52832_xxAA +``` diff --git a/examples/boot/bootloader/nrf/build.rs b/examples/boot/bootloader/nrf/build.rs new file mode 100644 index 000000000..e1da69328 --- /dev/null +++ b/examples/boot/bootloader/nrf/build.rs @@ -0,0 +1,37 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + if env::var("CARGO_FEATURE_DEFMT").is_ok() { + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + } +} diff --git a/examples/boot/bootloader/nrf/memory-bm.x b/examples/boot/bootloader/nrf/memory-bm.x new file mode 100644 index 000000000..8a32b905f --- /dev/null +++ b/examples/boot/bootloader/nrf/memory-bm.x @@ -0,0 +1,18 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + FLASH : ORIGIN = 0x00000000, LENGTH = 24K + BOOTLOADER_STATE : ORIGIN = 0x00006000, LENGTH = 4K + ACTIVE : ORIGIN = 0x00007000, LENGTH = 64K + DFU : ORIGIN = 0x00017000, LENGTH = 68K + RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 32K +} + +__bootloader_state_start = ORIGIN(BOOTLOADER_STATE); +__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE); + +__bootloader_active_start = ORIGIN(ACTIVE); +__bootloader_active_end = ORIGIN(ACTIVE) + LENGTH(ACTIVE); + +__bootloader_dfu_start = ORIGIN(DFU); +__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU); diff --git a/examples/boot/bootloader/nrf/memory-s140.x b/examples/boot/bootloader/nrf/memory-s140.x new file mode 100644 index 000000000..105db9972 --- /dev/null +++ b/examples/boot/bootloader/nrf/memory-s140.x @@ -0,0 +1,31 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + MBR : ORIGIN = 0x00000000, LENGTH = 4K + SOFTDEVICE : ORIGIN = 0x00001000, LENGTH = 155648 + ACTIVE : ORIGIN = 0x00027000, LENGTH = 425984 + DFU : ORIGIN = 0x0008F000, LENGTH = 430080 + FLASH : ORIGIN = 0x000f9000, LENGTH = 24K + BOOTLOADER_STATE : ORIGIN = 0x000ff000, LENGTH = 4K + RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 0x2fff8 + uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4 +} + +__bootloader_state_start = ORIGIN(BOOTLOADER_STATE); +__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE); + +__bootloader_active_start = ORIGIN(ACTIVE); +__bootloader_active_end = ORIGIN(ACTIVE) + LENGTH(ACTIVE); + +__bootloader_dfu_start = ORIGIN(DFU); +__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU); + +__bootloader_start = ORIGIN(FLASH); + +SECTIONS +{ + .uicr_bootloader_start_address : + { + LONG(__bootloader_start) + } > uicr_bootloader_start_address +} diff --git a/examples/boot/bootloader/nrf/memory.x b/examples/boot/bootloader/nrf/memory.x new file mode 100644 index 000000000..8a32b905f --- /dev/null +++ b/examples/boot/bootloader/nrf/memory.x @@ -0,0 +1,18 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + FLASH : ORIGIN = 0x00000000, LENGTH = 24K + BOOTLOADER_STATE : ORIGIN = 0x00006000, LENGTH = 4K + ACTIVE : ORIGIN = 0x00007000, LENGTH = 64K + DFU : ORIGIN = 0x00017000, LENGTH = 68K + RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 32K +} + +__bootloader_state_start = ORIGIN(BOOTLOADER_STATE); +__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE); + +__bootloader_active_start = ORIGIN(ACTIVE); +__bootloader_active_end = ORIGIN(ACTIVE) + LENGTH(ACTIVE); + +__bootloader_dfu_start = ORIGIN(DFU); +__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU); diff --git a/examples/boot/bootloader/nrf/src/main.rs b/examples/boot/bootloader/nrf/src/main.rs new file mode 100644 index 000000000..bc7e0755f --- /dev/null +++ b/examples/boot/bootloader/nrf/src/main.rs @@ -0,0 +1,48 @@ +#![no_std] +#![no_main] + +use cortex_m_rt::{entry, exception}; +#[cfg(feature = "defmt")] +use defmt_rtt as _; +use embassy_boot_nrf::*; +use embassy_nrf::nvmc::Nvmc; + +#[entry] +fn main() -> ! { + let p = embassy_nrf::init(Default::default()); + + // Uncomment this if you are debugging the bootloader with debugger/RTT attached, + // as it prevents a hard fault when accessing flash 'too early' after boot. + /* + for i in 0..10000000 { + cortex_m::asm::nop(); + } + */ + + let mut bl = BootLoader::default(); + let start = bl.prepare(&mut SingleFlashProvider::new(&mut WatchdogFlash::start( + Nvmc::new(p.NVMC), + p.WDT, + 5, + ))); + unsafe { bl.load(start) } +} + +#[no_mangle] +#[cfg_attr(target_os = "none", link_section = ".HardFault.user")] +unsafe extern "C" fn HardFault() { + cortex_m::peripheral::SCB::sys_reset(); +} + +#[exception] +unsafe fn DefaultHandler(_: i16) -> ! { + const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; + let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; + + panic!("DefaultHandler #{:?}", irqn); +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + cortex_m::asm::udf(); +} -- cgit