diff options
Diffstat (limited to 'examples/boot/application/nrf')
| -rw-r--r-- | examples/boot/application/nrf/.cargo/config.toml | 4 | ||||
| -rw-r--r-- | examples/boot/application/nrf/Cargo.toml | 21 | ||||
| -rw-r--r-- | examples/boot/application/nrf/README.md | 14 | ||||
| -rw-r--r-- | examples/boot/application/nrf/memory-bl-nrf91.x | 19 | ||||
| -rw-r--r-- | examples/boot/application/nrf/memory-bl.x | 2 | ||||
| -rw-r--r-- | examples/boot/application/nrf/memory-nrf91.x | 16 | ||||
| -rw-r--r-- | examples/boot/application/nrf/memory.x | 2 | ||||
| -rw-r--r-- | examples/boot/application/nrf/src/bin/a.rs | 41 | ||||
| -rw-r--r-- | examples/boot/application/nrf/src/bin/b.rs | 6 |
9 files changed, 101 insertions, 24 deletions
diff --git a/examples/boot/application/nrf/.cargo/config.toml b/examples/boot/application/nrf/.cargo/config.toml index 8ca28df39..17616a054 100644 --- a/examples/boot/application/nrf/.cargo/config.toml +++ b/examples/boot/application/nrf/.cargo/config.toml | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] |
| 2 | # replace nRF82840_xxAA with your chip as listed in `probe-run --list-chips` | 2 | # replace nRF82840_xxAA with your chip as listed in `probe-rs chip list` |
| 3 | runner = "probe-run --chip nRF52840_xxAA" | 3 | runner = "probe-rs run --chip nRF52840_xxAA" |
| 4 | 4 | ||
| 5 | [build] | 5 | [build] |
| 6 | target = "thumbv7em-none-eabi" | 6 | target = "thumbv7em-none-eabi" |
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index b9ff92578..2a0cf7818 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml | |||
| @@ -2,19 +2,26 @@ | |||
| 2 | edition = "2021" | 2 | edition = "2021" |
| 3 | name = "embassy-boot-nrf-examples" | 3 | name = "embassy-boot-nrf-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.0" |
| 5 | license = "MIT OR Apache-2.0" | ||
| 5 | 6 | ||
| 6 | [dependencies] | 7 | [dependencies] |
| 7 | embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync" } | 8 | embassy-sync = { version = "0.2.0", path = "../../../../embassy-sync" } |
| 8 | embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } |
| 9 | embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] } | 10 | embassy-time = { version = "0.1.2", path = "../../../../embassy-time", features = ["nightly"] } |
| 10 | embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly", "nrf52840"] } | 11 | embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] } |
| 11 | embassy-boot-nrf = { version = "0.1.0", path = "../../../../embassy-boot/nrf" } | 12 | embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot", features = ["nightly"] } |
| 13 | embassy-boot-nrf = { version = "0.1.0", path = "../../../../embassy-boot/nrf", features = ["nightly"] } | ||
| 12 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } | 14 | embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } |
| 13 | 15 | ||
| 14 | defmt = { version = "0.3", optional = true } | 16 | defmt = { version = "0.3", optional = true } |
| 15 | defmt-rtt = { version = "0.3", optional = true } | 17 | defmt-rtt = { version = "0.4", optional = true } |
| 16 | panic-reset = { version = "0.1.1" } | 18 | panic-reset = { version = "0.1.1" } |
| 17 | embedded-hal = { version = "0.2.6" } | 19 | embedded-hal = { version = "0.2.6" } |
| 18 | 20 | ||
| 19 | cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 21 | cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } |
| 20 | cortex-m-rt = "0.7.0" | 22 | cortex-m-rt = "0.7.0" |
| 23 | |||
| 24 | [features] | ||
| 25 | ed25519-dalek = ["embassy-boot/ed25519-dalek"] | ||
| 26 | ed25519-salty = ["embassy-boot/ed25519-salty"] | ||
| 27 | skip-include = [] | ||
diff --git a/examples/boot/application/nrf/README.md b/examples/boot/application/nrf/README.md index 703377a20..9d6d20336 100644 --- a/examples/boot/application/nrf/README.md +++ b/examples/boot/application/nrf/README.md | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | # Examples using bootloader | 1 | # Examples using bootloader |
| 2 | 2 | ||
| 3 | Example for nRF52 demonstrating the bootloader. The example consists of application binaries, 'a' | 3 | Example for nRF demonstrating the bootloader. The example consists of application binaries, 'a' |
| 4 | which allows you to press a button to start the DFU process, and 'b' which is the updated | 4 | which allows you to press a button to start the DFU process, and 'b' which is the updated |
| 5 | application. | 5 | application. |
| 6 | 6 | ||
| @@ -20,15 +20,19 @@ application. | |||
| 20 | cp memory-bl.x ../../bootloader/nrf/memory.x | 20 | cp memory-bl.x ../../bootloader/nrf/memory.x |
| 21 | 21 | ||
| 22 | # Flash bootloader | 22 | # Flash bootloader |
| 23 | cargo flash --manifest-path ../../bootloader/nrf/Cargo.toml --features embassy-nrf/nrf52840 --release --chip nRF52840_xxAA | 23 | cargo flash --manifest-path ../../bootloader/nrf/Cargo.toml --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi --release --chip nRF52840_xxAA |
| 24 | # Build 'b' | 24 | # Build 'b' |
| 25 | cargo build --release --bin b | 25 | cargo build --release --bin b --features embassy-nrf/nrf52840 |
| 26 | # Generate binary for 'b' | 26 | # Generate binary for 'b' |
| 27 | cargo objcopy --release --bin b -- -O binary b.bin | 27 | cargo objcopy --release --bin b --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi -- -O binary b.bin |
| 28 | ``` | 28 | ``` |
| 29 | 29 | ||
| 30 | # Flash `a` (which includes b.bin) | 30 | # Flash `a` (which includes b.bin) |
| 31 | 31 | ||
| 32 | ``` | 32 | ``` |
| 33 | cargo flash --release --bin a --chip nRF52840_xxAA | 33 | cargo flash --release --bin a --features embassy-nrf/nrf52840 --target thumbv7em-none-eabi --chip nRF52840_xxAA |
| 34 | ``` | 34 | ``` |
| 35 | |||
| 36 | You should then see a solid LED. Pressing button 1 will cause the DFU to be loaded by the bootloader. Upon | ||
| 37 | successfully loading, you'll see the LED flash. After 5 seconds, because there is no petting of the watchdog, | ||
| 38 | you'll see the LED go solid again. This indicates that the bootloader has reverted the update. | ||
diff --git a/examples/boot/application/nrf/memory-bl-nrf91.x b/examples/boot/application/nrf/memory-bl-nrf91.x new file mode 100644 index 000000000..14ceffa73 --- /dev/null +++ b/examples/boot/application/nrf/memory-bl-nrf91.x | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ | ||
| 4 | /* Assumes Secure Partition Manager (SPM) flashed at the start */ | ||
| 5 | FLASH : ORIGIN = 0x00050000, LENGTH = 24K | ||
| 6 | BOOTLOADER_STATE : ORIGIN = 0x00056000, LENGTH = 4K | ||
| 7 | ACTIVE : ORIGIN = 0x00057000, LENGTH = 64K | ||
| 8 | DFU : ORIGIN = 0x00067000, LENGTH = 68K | ||
| 9 | RAM (rwx) : ORIGIN = 0x20018000, LENGTH = 32K | ||
| 10 | } | ||
| 11 | |||
| 12 | __bootloader_state_start = ORIGIN(BOOTLOADER_STATE); | ||
| 13 | __bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE); | ||
| 14 | |||
| 15 | __bootloader_active_start = ORIGIN(ACTIVE); | ||
| 16 | __bootloader_active_end = ORIGIN(ACTIVE) + LENGTH(ACTIVE); | ||
| 17 | |||
| 18 | __bootloader_dfu_start = ORIGIN(DFU); | ||
| 19 | __bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU); | ||
diff --git a/examples/boot/application/nrf/memory-bl.x b/examples/boot/application/nrf/memory-bl.x index 8a32b905f..257d65644 100644 --- a/examples/boot/application/nrf/memory-bl.x +++ b/examples/boot/application/nrf/memory-bl.x | |||
| @@ -5,7 +5,7 @@ MEMORY | |||
| 5 | BOOTLOADER_STATE : ORIGIN = 0x00006000, LENGTH = 4K | 5 | BOOTLOADER_STATE : ORIGIN = 0x00006000, LENGTH = 4K |
| 6 | ACTIVE : ORIGIN = 0x00007000, LENGTH = 64K | 6 | ACTIVE : ORIGIN = 0x00007000, LENGTH = 64K |
| 7 | DFU : ORIGIN = 0x00017000, LENGTH = 68K | 7 | DFU : ORIGIN = 0x00017000, LENGTH = 68K |
| 8 | RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 32K | 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K |
| 9 | } | 9 | } |
| 10 | 10 | ||
| 11 | __bootloader_state_start = ORIGIN(BOOTLOADER_STATE); | 11 | __bootloader_state_start = ORIGIN(BOOTLOADER_STATE); |
diff --git a/examples/boot/application/nrf/memory-nrf91.x b/examples/boot/application/nrf/memory-nrf91.x new file mode 100644 index 000000000..2bc13c0d6 --- /dev/null +++ b/examples/boot/application/nrf/memory-nrf91.x | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | /* NOTE 1 K = 1 KiBi = 1024 bytes */ | ||
| 4 | /* Assumes Secure Partition Manager (SPM) flashed at the start */ | ||
| 5 | BOOTLOADER : ORIGIN = 0x00050000, LENGTH = 24K | ||
| 6 | BOOTLOADER_STATE : ORIGIN = 0x00056000, LENGTH = 4K | ||
| 7 | FLASH : ORIGIN = 0x00057000, LENGTH = 64K | ||
| 8 | DFU : ORIGIN = 0x00067000, LENGTH = 68K | ||
| 9 | RAM (rwx) : ORIGIN = 0x20018000, LENGTH = 32K | ||
| 10 | } | ||
| 11 | |||
| 12 | __bootloader_state_start = ORIGIN(BOOTLOADER_STATE); | ||
| 13 | __bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE); | ||
| 14 | |||
| 15 | __bootloader_dfu_start = ORIGIN(DFU); | ||
| 16 | __bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU); | ||
diff --git a/examples/boot/application/nrf/memory.x b/examples/boot/application/nrf/memory.x index 3a54ca460..c6926e422 100644 --- a/examples/boot/application/nrf/memory.x +++ b/examples/boot/application/nrf/memory.x | |||
| @@ -5,7 +5,7 @@ MEMORY | |||
| 5 | BOOTLOADER_STATE : ORIGIN = 0x00006000, LENGTH = 4K | 5 | BOOTLOADER_STATE : ORIGIN = 0x00006000, LENGTH = 4K |
| 6 | FLASH : ORIGIN = 0x00007000, LENGTH = 64K | 6 | FLASH : ORIGIN = 0x00007000, LENGTH = 64K |
| 7 | DFU : ORIGIN = 0x00017000, LENGTH = 68K | 7 | DFU : ORIGIN = 0x00017000, LENGTH = 68K |
| 8 | RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 32K | 8 | RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K |
| 9 | } | 9 | } |
| 10 | 10 | ||
| 11 | __bootloader_state_start = ORIGIN(BOOTLOADER_STATE); | 11 | __bootloader_state_start = ORIGIN(BOOTLOADER_STATE); |
diff --git a/examples/boot/application/nrf/src/bin/a.rs b/examples/boot/application/nrf/src/bin/a.rs index bd8fa3246..021d77f3b 100644 --- a/examples/boot/application/nrf/src/bin/a.rs +++ b/examples/boot/application/nrf/src/bin/a.rs | |||
| @@ -1,42 +1,71 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![macro_use] | 3 | #![macro_use] |
| 4 | #![feature(generic_associated_types)] | ||
| 5 | #![feature(type_alias_impl_trait)] | 4 | #![feature(type_alias_impl_trait)] |
| 6 | 5 | ||
| 7 | use embassy_boot_nrf::FirmwareUpdater; | 6 | use embassy_boot_nrf::{FirmwareUpdater, FirmwareUpdaterConfig}; |
| 8 | use embassy_embedded_hal::adapter::BlockingAsync; | 7 | use embassy_embedded_hal::adapter::BlockingAsync; |
| 9 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 10 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; | 9 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; |
| 11 | use embassy_nrf::nvmc::Nvmc; | 10 | use embassy_nrf::nvmc::Nvmc; |
| 11 | use embassy_nrf::wdt::{self, Watchdog}; | ||
| 12 | use embassy_sync::mutex::Mutex; | ||
| 12 | use panic_reset as _; | 13 | use panic_reset as _; |
| 13 | 14 | ||
| 15 | #[cfg(feature = "skip-include")] | ||
| 16 | static APP_B: &[u8] = &[0, 1, 2, 3]; | ||
| 17 | #[cfg(not(feature = "skip-include"))] | ||
| 14 | static APP_B: &[u8] = include_bytes!("../../b.bin"); | 18 | static APP_B: &[u8] = include_bytes!("../../b.bin"); |
| 15 | 19 | ||
| 16 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 17 | async fn main(_spawner: Spawner) { | 21 | async fn main(_spawner: Spawner) { |
| 18 | let p = embassy_nrf::init(Default::default()); | 22 | let p = embassy_nrf::init(Default::default()); |
| 23 | |||
| 19 | let mut button = Input::new(p.P0_11, Pull::Up); | 24 | let mut button = Input::new(p.P0_11, Pull::Up); |
| 20 | let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); | 25 | let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); |
| 26 | |||
| 21 | //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); | 27 | //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); |
| 22 | //let mut button = Input::new(p.P1_02, Pull::Up); | 28 | //let mut button = Input::new(p.P1_02, Pull::Up); |
| 23 | 29 | ||
| 30 | // nRF91 DK | ||
| 31 | // let mut led = Output::new(p.P0_02, Level::Low, OutputDrive::Standard); | ||
| 32 | // let mut button = Input::new(p.P0_06, Pull::Up); | ||
| 33 | |||
| 34 | // The following code block illustrates how to obtain a watchdog that is configured | ||
| 35 | // as per the existing watchdog. Ordinarily, we'd use the handle returned to "pet" the | ||
| 36 | // watchdog periodically. If we don't, and we're not going to for this example, then | ||
| 37 | // the watchdog will cause the device to reset as per its configured timeout in the bootloader. | ||
| 38 | // This helps is avoid a situation where new firmware might be bad and block our executor. | ||
| 39 | // If firmware is bad in this way then the bootloader will revert to any previous version. | ||
| 40 | let wdt_config = wdt::Config::try_new(&p.WDT).unwrap(); | ||
| 41 | let (_wdt, [_wdt_handle]) = match Watchdog::try_new(p.WDT, wdt_config) { | ||
| 42 | Ok(x) => x, | ||
| 43 | Err(_) => { | ||
| 44 | // Watchdog already active with the wrong number of handles, waiting for it to timeout... | ||
| 45 | loop { | ||
| 46 | cortex_m::asm::wfe(); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | }; | ||
| 50 | |||
| 24 | let nvmc = Nvmc::new(p.NVMC); | 51 | let nvmc = Nvmc::new(p.NVMC); |
| 25 | let mut nvmc = BlockingAsync::new(nvmc); | 52 | let nvmc = Mutex::new(BlockingAsync::new(nvmc)); |
| 26 | 53 | ||
| 27 | let mut updater = FirmwareUpdater::default(); | 54 | let config = FirmwareUpdaterConfig::from_linkerfile(&nvmc); |
| 55 | let mut updater = FirmwareUpdater::new(config); | ||
| 28 | loop { | 56 | loop { |
| 29 | led.set_low(); | 57 | led.set_low(); |
| 30 | button.wait_for_any_edge().await; | 58 | button.wait_for_any_edge().await; |
| 31 | if button.is_low() { | 59 | if button.is_low() { |
| 32 | let mut offset = 0; | 60 | let mut offset = 0; |
| 61 | let mut magic = [0; 4]; | ||
| 33 | for chunk in APP_B.chunks(4096) { | 62 | for chunk in APP_B.chunks(4096) { |
| 34 | let mut buf: [u8; 4096] = [0; 4096]; | 63 | let mut buf: [u8; 4096] = [0; 4096]; |
| 35 | buf[..chunk.len()].copy_from_slice(chunk); | 64 | buf[..chunk.len()].copy_from_slice(chunk); |
| 36 | updater.write_firmware(offset, &buf, &mut nvmc, 4096).await.unwrap(); | 65 | updater.write_firmware(&mut magic, offset, &buf).await.unwrap(); |
| 37 | offset += chunk.len(); | 66 | offset += chunk.len(); |
| 38 | } | 67 | } |
| 39 | updater.update(&mut nvmc).await.unwrap(); | 68 | updater.mark_updated(&mut magic).await.unwrap(); |
| 40 | led.set_high(); | 69 | led.set_high(); |
| 41 | cortex_m::peripheral::SCB::sys_reset(); | 70 | cortex_m::peripheral::SCB::sys_reset(); |
| 42 | } | 71 | } |
diff --git a/examples/boot/application/nrf/src/bin/b.rs b/examples/boot/application/nrf/src/bin/b.rs index 5394bf0c7..15ebce5fa 100644 --- a/examples/boot/application/nrf/src/bin/b.rs +++ b/examples/boot/application/nrf/src/bin/b.rs | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![macro_use] | 3 | #![macro_use] |
| 4 | #![feature(generic_associated_types)] | ||
| 5 | #![feature(type_alias_impl_trait)] | 4 | #![feature(type_alias_impl_trait)] |
| 6 | 5 | ||
| 7 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| @@ -13,7 +12,10 @@ use panic_reset as _; | |||
| 13 | async fn main(_spawner: Spawner) { | 12 | async fn main(_spawner: Spawner) { |
| 14 | let p = embassy_nrf::init(Default::default()); | 13 | let p = embassy_nrf::init(Default::default()); |
| 15 | let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); | 14 | let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); |
| 16 | //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); | 15 | // let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); |
| 16 | |||
| 17 | // nRF91 DK | ||
| 18 | // let mut led = Output::new(p.P0_02, Level::Low, OutputDrive::Standard); | ||
| 17 | 19 | ||
| 18 | loop { | 20 | loop { |
| 19 | led.set_high(); | 21 | led.set_high(); |
