diff options
| -rw-r--r-- | embassy-boot/nrf/src/lib.rs | 6 | ||||
| -rw-r--r-- | embassy-nrf/src/wdt.rs | 24 | ||||
| -rw-r--r-- | examples/boot/application/nrf/README.md | 4 | ||||
| -rw-r--r-- | examples/boot/application/nrf/memory-bl.x | 2 | ||||
| -rw-r--r-- | examples/boot/application/nrf/memory.x | 2 | ||||
| -rw-r--r-- | examples/boot/application/nrf/src/bin/a.rs | 18 | ||||
| -rw-r--r-- | examples/boot/bootloader/nrf/memory-bm.x | 2 | ||||
| -rw-r--r-- | examples/boot/bootloader/nrf/memory.x | 2 | ||||
| -rw-r--r-- | examples/boot/bootloader/nrf/src/main.rs | 9 |
9 files changed, 59 insertions, 10 deletions
diff --git a/embassy-boot/nrf/src/lib.rs b/embassy-boot/nrf/src/lib.rs index 205bbd6df..f40ae62d6 100644 --- a/embassy-boot/nrf/src/lib.rs +++ b/embassy-boot/nrf/src/lib.rs | |||
| @@ -149,11 +149,7 @@ pub struct WatchdogFlash<'d> { | |||
| 149 | 149 | ||
| 150 | impl<'d> WatchdogFlash<'d> { | 150 | impl<'d> WatchdogFlash<'d> { |
| 151 | /// Start a new watchdog with a given flash and WDT peripheral and a timeout | 151 | /// Start a new watchdog with a given flash and WDT peripheral and a timeout |
| 152 | pub fn start(flash: Nvmc<'d>, wdt: WDT, timeout: u32) -> Self { | 152 | pub fn start(flash: Nvmc<'d>, wdt: WDT, config: wdt::Config) -> Self { |
| 153 | let mut config = wdt::Config::default(); | ||
| 154 | config.timeout_ticks = 32768 * timeout; // timeout seconds | ||
| 155 | config.run_during_sleep = true; | ||
| 156 | config.run_during_debug_halt = false; | ||
| 157 | let (_wdt, [wdt]) = match wdt::Watchdog::try_new(wdt, config) { | 153 | let (_wdt, [wdt]) = match wdt::Watchdog::try_new(wdt, config) { |
| 158 | Ok(x) => x, | 154 | Ok(x) => x, |
| 159 | Err(_) => { | 155 | Err(_) => { |
diff --git a/embassy-nrf/src/wdt.rs b/embassy-nrf/src/wdt.rs index 8760aa301..330ca98bf 100644 --- a/embassy-nrf/src/wdt.rs +++ b/embassy-nrf/src/wdt.rs | |||
| @@ -23,6 +23,30 @@ pub struct Config { | |||
| 23 | pub run_during_debug_halt: bool, | 23 | pub run_during_debug_halt: bool, |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | impl Config { | ||
| 27 | /// Create a config structure from the current configuration of the WDT | ||
| 28 | /// peripheral. | ||
| 29 | pub fn try_new(_wdt: &peripherals::WDT) -> Option<Self> { | ||
| 30 | let r = unsafe { &*WDT::ptr() }; | ||
| 31 | |||
| 32 | #[cfg(not(feature = "_nrf9160"))] | ||
| 33 | let runstatus = r.runstatus.read().runstatus().bit(); | ||
| 34 | #[cfg(feature = "_nrf9160")] | ||
| 35 | let runstatus = r.runstatus.read().runstatuswdt().bit(); | ||
| 36 | |||
| 37 | if runstatus { | ||
| 38 | let config = r.config.read(); | ||
| 39 | Some(Self { | ||
| 40 | timeout_ticks: r.crv.read().bits(), | ||
| 41 | run_during_sleep: config.sleep().bit(), | ||
| 42 | run_during_debug_halt: config.halt().bit(), | ||
| 43 | }) | ||
| 44 | } else { | ||
| 45 | None | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 26 | impl Default for Config { | 50 | impl Default for Config { |
| 27 | fn default() -> Self { | 51 | fn default() -> Self { |
| 28 | Self { | 52 | Self { |
diff --git a/examples/boot/application/nrf/README.md b/examples/boot/application/nrf/README.md index 703377a20..a6719b505 100644 --- a/examples/boot/application/nrf/README.md +++ b/examples/boot/application/nrf/README.md | |||
| @@ -32,3 +32,7 @@ cargo objcopy --release --bin b -- -O binary b.bin | |||
| 32 | ``` | 32 | ``` |
| 33 | cargo flash --release --bin a --chip nRF52840_xxAA | 33 | cargo flash --release --bin a --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. \ No newline at end of file | ||
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.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 7a404a914..83191f388 100644 --- a/examples/boot/application/nrf/src/bin/a.rs +++ b/examples/boot/application/nrf/src/bin/a.rs | |||
| @@ -8,6 +8,7 @@ use embassy_embedded_hal::adapter::BlockingAsync; | |||
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; | 9 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; |
| 10 | use embassy_nrf::nvmc::Nvmc; | 10 | use embassy_nrf::nvmc::Nvmc; |
| 11 | use embassy_nrf::wdt::{self, Watchdog}; | ||
| 11 | use panic_reset as _; | 12 | use panic_reset as _; |
| 12 | 13 | ||
| 13 | static APP_B: &[u8] = include_bytes!("../../b.bin"); | 14 | static APP_B: &[u8] = include_bytes!("../../b.bin"); |
| @@ -20,6 +21,23 @@ async fn main(_spawner: Spawner) { | |||
| 20 | //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); | 21 | //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); |
| 21 | //let mut button = Input::new(p.P1_02, Pull::Up); | 22 | //let mut button = Input::new(p.P1_02, Pull::Up); |
| 22 | 23 | ||
| 24 | // The following code block illustrates how to obtain a watchdog that is configured | ||
| 25 | // as per the existing watchdog. Ordinarily, we'd use the handle returned to "pet" the | ||
| 26 | // watchdog periodically. If we don't, and we're not going to for this example, then | ||
| 27 | // the watchdog will cause the device to reset as per its configured timeout in the bootloader. | ||
| 28 | // This helps is avoid a situation where new firmware might be bad and block our executor. | ||
| 29 | // If firmware is bad in this way then the bootloader will revert to any previous version. | ||
| 30 | let wdt_config = wdt::Config::try_new(&p.WDT).unwrap(); | ||
| 31 | let (_wdt, [_wdt_handle]) = match Watchdog::try_new(p.WDT, wdt_config) { | ||
| 32 | Ok(x) => x, | ||
| 33 | Err(_) => { | ||
| 34 | // Watchdog already active with the wrong number of handles, waiting for it to timeout... | ||
| 35 | loop { | ||
| 36 | cortex_m::asm::wfe(); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | }; | ||
| 40 | |||
| 23 | let nvmc = Nvmc::new(p.NVMC); | 41 | let nvmc = Nvmc::new(p.NVMC); |
| 24 | let mut nvmc = BlockingAsync::new(nvmc); | 42 | let mut nvmc = BlockingAsync::new(nvmc); |
| 25 | 43 | ||
diff --git a/examples/boot/bootloader/nrf/memory-bm.x b/examples/boot/bootloader/nrf/memory-bm.x index 8a32b905f..257d65644 100644 --- a/examples/boot/bootloader/nrf/memory-bm.x +++ b/examples/boot/bootloader/nrf/memory-bm.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/bootloader/nrf/memory.x b/examples/boot/bootloader/nrf/memory.x index 8a32b905f..257d65644 100644 --- a/examples/boot/bootloader/nrf/memory.x +++ b/examples/boot/bootloader/nrf/memory.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/bootloader/nrf/src/main.rs b/examples/boot/bootloader/nrf/src/main.rs index 8266206b3..aca3b857a 100644 --- a/examples/boot/bootloader/nrf/src/main.rs +++ b/examples/boot/bootloader/nrf/src/main.rs | |||
| @@ -6,6 +6,7 @@ use cortex_m_rt::{entry, exception}; | |||
| 6 | use defmt_rtt as _; | 6 | use defmt_rtt as _; |
| 7 | use embassy_boot_nrf::*; | 7 | use embassy_boot_nrf::*; |
| 8 | use embassy_nrf::nvmc::Nvmc; | 8 | use embassy_nrf::nvmc::Nvmc; |
| 9 | use embassy_nrf::wdt; | ||
| 9 | 10 | ||
| 10 | #[entry] | 11 | #[entry] |
| 11 | fn main() -> ! { | 12 | fn main() -> ! { |
| @@ -20,8 +21,14 @@ fn main() -> ! { | |||
| 20 | */ | 21 | */ |
| 21 | 22 | ||
| 22 | let mut bl = BootLoader::default(); | 23 | let mut bl = BootLoader::default(); |
| 24 | |||
| 25 | let mut wdt_config = wdt::Config::default(); | ||
| 26 | wdt_config.timeout_ticks = 32768 * 5; // timeout seconds | ||
| 27 | wdt_config.run_during_sleep = true; | ||
| 28 | wdt_config.run_during_debug_halt = false; | ||
| 29 | |||
| 23 | let start = bl.prepare(&mut SingleFlashConfig::new(&mut BootFlash::<_, 4096>::new( | 30 | let start = bl.prepare(&mut SingleFlashConfig::new(&mut BootFlash::<_, 4096>::new( |
| 24 | WatchdogFlash::start(Nvmc::new(p.NVMC), p.WDT, 5), | 31 | WatchdogFlash::start(Nvmc::new(p.NVMC), p.WDT, wdt_config), |
| 25 | ))); | 32 | ))); |
| 26 | unsafe { bl.load(start) } | 33 | unsafe { bl.load(start) } |
| 27 | } | 34 | } |
