aboutsummaryrefslogtreecommitdiff
path: root/embassy-boot
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-01-11 19:51:02 +0100
committerGitHub <[email protected]>2024-01-11 19:51:02 +0100
commitc4241623ce01e798a6df3587ce54ae7e2e4fb90c (patch)
tree8b4afb7123039f4d85786fffce83b7a9d5d63d23 /embassy-boot
parentae84f2a157cf34c5bbc88ec4637f084f1ab924ea (diff)
parent0af44292a0862b1c115def1ed1a48e29daae241c (diff)
Merge pull request #2435 from embassy-rs/release-misc
Misc stuff for release
Diffstat (limited to 'embassy-boot')
-rw-r--r--embassy-boot/Cargo.toml (renamed from embassy-boot/boot/Cargo.toml)8
-rw-r--r--embassy-boot/README.md (renamed from embassy-boot/boot/README.md)15
-rw-r--r--embassy-boot/nrf/Cargo.toml44
-rw-r--r--embassy-boot/nrf/README.md26
-rw-r--r--embassy-boot/nrf/src/fmt.rs258
-rw-r--r--embassy-boot/nrf/src/lib.rs145
-rw-r--r--embassy-boot/rp/Cargo.toml79
-rw-r--r--embassy-boot/rp/README.md26
-rw-r--r--embassy-boot/rp/build.rs8
-rw-r--r--embassy-boot/rp/src/fmt.rs258
-rw-r--r--embassy-boot/rp/src/lib.rs90
-rw-r--r--embassy-boot/src/boot_loader.rs (renamed from embassy-boot/boot/src/boot_loader.rs)0
-rw-r--r--embassy-boot/src/digest_adapters/ed25519_dalek.rs (renamed from embassy-boot/boot/src/digest_adapters/ed25519_dalek.rs)0
-rw-r--r--embassy-boot/src/digest_adapters/mod.rs (renamed from embassy-boot/boot/src/digest_adapters/mod.rs)0
-rw-r--r--embassy-boot/src/digest_adapters/salty.rs (renamed from embassy-boot/boot/src/digest_adapters/salty.rs)0
-rw-r--r--embassy-boot/src/firmware_updater/asynch.rs (renamed from embassy-boot/boot/src/firmware_updater/asynch.rs)0
-rw-r--r--embassy-boot/src/firmware_updater/blocking.rs (renamed from embassy-boot/boot/src/firmware_updater/blocking.rs)0
-rw-r--r--embassy-boot/src/firmware_updater/mod.rs (renamed from embassy-boot/boot/src/firmware_updater/mod.rs)0
-rw-r--r--embassy-boot/src/fmt.rs (renamed from embassy-boot/boot/src/fmt.rs)0
-rw-r--r--embassy-boot/src/lib.rs (renamed from embassy-boot/boot/src/lib.rs)0
-rw-r--r--embassy-boot/src/mem_flash.rs (renamed from embassy-boot/boot/src/mem_flash.rs)0
-rw-r--r--embassy-boot/src/test_flash/asynch.rs (renamed from embassy-boot/boot/src/test_flash/asynch.rs)0
-rw-r--r--embassy-boot/src/test_flash/blocking.rs (renamed from embassy-boot/boot/src/test_flash/blocking.rs)0
-rw-r--r--embassy-boot/src/test_flash/mod.rs (renamed from embassy-boot/boot/src/test_flash/mod.rs)0
-rw-r--r--embassy-boot/stm32/Cargo.toml70
-rw-r--r--embassy-boot/stm32/README.md24
-rw-r--r--embassy-boot/stm32/build.rs8
-rw-r--r--embassy-boot/stm32/src/fmt.rs258
-rw-r--r--embassy-boot/stm32/src/lib.rs44
29 files changed, 4 insertions, 1357 deletions
diff --git a/embassy-boot/boot/Cargo.toml b/embassy-boot/Cargo.toml
index 3c84ffcd3..a70849018 100644
--- a/embassy-boot/boot/Cargo.toml
+++ b/embassy-boot/Cargo.toml
@@ -12,8 +12,8 @@ categories = [
12] 12]
13 13
14[package.metadata.embassy_docs] 14[package.metadata.embassy_docs]
15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-v$VERSION/embassy-boot/boot/src/" 15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-v$VERSION/embassy-boot/src/"
16src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-boot/boot/src/" 16src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-boot/src/"
17target = "thumbv7em-none-eabi" 17target = "thumbv7em-none-eabi"
18features = ["defmt"] 18features = ["defmt"]
19 19
@@ -27,8 +27,8 @@ defmt = { version = "0.3", optional = true }
27digest = "0.10" 27digest = "0.10"
28log = { version = "0.4", optional = true } 28log = { version = "0.4", optional = true }
29ed25519-dalek = { version = "2", default_features = false, features = ["digest"], optional = true } 29ed25519-dalek = { version = "2", default_features = false, features = ["digest"], optional = true }
30embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } 30embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" }
31embassy-sync = { version = "0.5.0", path = "../../embassy-sync" } 31embassy-sync = { version = "0.5.0", path = "../embassy-sync" }
32embedded-storage = "0.3.1" 32embedded-storage = "0.3.1"
33embedded-storage-async = { version = "0.4.1" } 33embedded-storage-async = { version = "0.4.1" }
34salty = { version = "0.3", optional = true } 34salty = { version = "0.3", optional = true }
diff --git a/embassy-boot/boot/README.md b/embassy-boot/README.md
index 3fc81f24b..3c2d45e96 100644
--- a/embassy-boot/boot/README.md
+++ b/embassy-boot/README.md
@@ -33,18 +33,3 @@ The bootloader supports different hardware in separate crates:
33* `embassy-boot-nrf` - for the nRF microcontrollers. 33* `embassy-boot-nrf` - for the nRF microcontrollers.
34* `embassy-boot-rp` - for the RP2040 microcontrollers. 34* `embassy-boot-rp` - for the RP2040 microcontrollers.
35* `embassy-boot-stm32` - for the STM32 microcontrollers. 35* `embassy-boot-stm32` - for the STM32 microcontrollers.
36
37
38## Minimum supported Rust version (MSRV)
39
40`embassy-boot` is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
41
42## License
43
44This work is licensed under either of
45
46- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
47 <http://www.apache.org/licenses/LICENSE-2.0>)
48- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
49
50at your option.
diff --git a/embassy-boot/nrf/Cargo.toml b/embassy-boot/nrf/Cargo.toml
deleted file mode 100644
index 9f74fb126..000000000
--- a/embassy-boot/nrf/Cargo.toml
+++ /dev/null
@@ -1,44 +0,0 @@
1[package]
2edition = "2021"
3name = "embassy-boot-nrf"
4version = "0.1.0"
5description = "Bootloader lib for nRF chips"
6license = "MIT OR Apache-2.0"
7repository = "https://github.com/embassy-rs/embassy"
8categories = [
9 "embedded",
10 "no-std",
11 "asynchronous",
12]
13
14[package.metadata.embassy_docs]
15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot/nrf/src/"
16src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-boot/nrf/src/"
17features = ["embassy-nrf/nrf52840"]
18target = "thumbv7em-none-eabi"
19
20[lib]
21
22[dependencies]
23defmt = { version = "0.3", optional = true }
24
25embassy-sync = { version = "0.5.0", path = "../../embassy-sync" }
26embassy-nrf = { path = "../../embassy-nrf" }
27embassy-boot = { path = "../boot", default-features = false }
28cortex-m = { version = "0.7.6" }
29cortex-m-rt = { version = "0.7" }
30embedded-storage = "0.3.1"
31embedded-storage-async = { version = "0.4.1" }
32cfg-if = "1.0.0"
33
34nrf-softdevice-mbr = { version = "0.2.0", optional = true }
35
36[features]
37defmt = [
38 "dep:defmt",
39 "embassy-boot/defmt",
40 "embassy-nrf/defmt",
41]
42softdevice = [
43 "nrf-softdevice-mbr",
44]
diff --git a/embassy-boot/nrf/README.md b/embassy-boot/nrf/README.md
deleted file mode 100644
index fe581823d..000000000
--- a/embassy-boot/nrf/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
1# embassy-boot-nrf
2
3An [Embassy](https://embassy.dev) project.
4
5An adaptation of `embassy-boot` for nRF.
6
7## Features
8
9* Load applications with or without the softdevice.
10* Configure bootloader partitions based on linker script.
11* Using watchdog timer to detect application failure.
12
13
14## Minimum supported Rust version (MSRV)
15
16`embassy-boot-nrf` is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
17
18## License
19
20This work is licensed under either of
21
22- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
23 <http://www.apache.org/licenses/LICENSE-2.0>)
24- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
25
26at your option.
diff --git a/embassy-boot/nrf/src/fmt.rs b/embassy-boot/nrf/src/fmt.rs
deleted file mode 100644
index 78e583c1c..000000000
--- a/embassy-boot/nrf/src/fmt.rs
+++ /dev/null
@@ -1,258 +0,0 @@
1#![macro_use]
2#![allow(unused_macros)]
3
4use core::fmt::{Debug, Display, LowerHex};
5
6#[cfg(all(feature = "defmt", feature = "log"))]
7compile_error!("You may not enable both `defmt` and `log` features.");
8
9macro_rules! assert {
10 ($($x:tt)*) => {
11 {
12 #[cfg(not(feature = "defmt"))]
13 ::core::assert!($($x)*);
14 #[cfg(feature = "defmt")]
15 ::defmt::assert!($($x)*);
16 }
17 };
18}
19
20macro_rules! assert_eq {
21 ($($x:tt)*) => {
22 {
23 #[cfg(not(feature = "defmt"))]
24 ::core::assert_eq!($($x)*);
25 #[cfg(feature = "defmt")]
26 ::defmt::assert_eq!($($x)*);
27 }
28 };
29}
30
31macro_rules! assert_ne {
32 ($($x:tt)*) => {
33 {
34 #[cfg(not(feature = "defmt"))]
35 ::core::assert_ne!($($x)*);
36 #[cfg(feature = "defmt")]
37 ::defmt::assert_ne!($($x)*);
38 }
39 };
40}
41
42macro_rules! debug_assert {
43 ($($x:tt)*) => {
44 {
45 #[cfg(not(feature = "defmt"))]
46 ::core::debug_assert!($($x)*);
47 #[cfg(feature = "defmt")]
48 ::defmt::debug_assert!($($x)*);
49 }
50 };
51}
52
53macro_rules! debug_assert_eq {
54 ($($x:tt)*) => {
55 {
56 #[cfg(not(feature = "defmt"))]
57 ::core::debug_assert_eq!($($x)*);
58 #[cfg(feature = "defmt")]
59 ::defmt::debug_assert_eq!($($x)*);
60 }
61 };
62}
63
64macro_rules! debug_assert_ne {
65 ($($x:tt)*) => {
66 {
67 #[cfg(not(feature = "defmt"))]
68 ::core::debug_assert_ne!($($x)*);
69 #[cfg(feature = "defmt")]
70 ::defmt::debug_assert_ne!($($x)*);
71 }
72 };
73}
74
75macro_rules! todo {
76 ($($x:tt)*) => {
77 {
78 #[cfg(not(feature = "defmt"))]
79 ::core::todo!($($x)*);
80 #[cfg(feature = "defmt")]
81 ::defmt::todo!($($x)*);
82 }
83 };
84}
85
86#[cfg(not(feature = "defmt"))]
87macro_rules! unreachable {
88 ($($x:tt)*) => {
89 ::core::unreachable!($($x)*)
90 };
91}
92
93#[cfg(feature = "defmt")]
94macro_rules! unreachable {
95 ($($x:tt)*) => {
96 ::defmt::unreachable!($($x)*)
97 };
98}
99
100macro_rules! panic {
101 ($($x:tt)*) => {
102 {
103 #[cfg(not(feature = "defmt"))]
104 ::core::panic!($($x)*);
105 #[cfg(feature = "defmt")]
106 ::defmt::panic!($($x)*);
107 }
108 };
109}
110
111macro_rules! trace {
112 ($s:literal $(, $x:expr)* $(,)?) => {
113 {
114 #[cfg(feature = "log")]
115 ::log::trace!($s $(, $x)*);
116 #[cfg(feature = "defmt")]
117 ::defmt::trace!($s $(, $x)*);
118 #[cfg(not(any(feature = "log", feature="defmt")))]
119 let _ = ($( & $x ),*);
120 }
121 };
122}
123
124macro_rules! debug {
125 ($s:literal $(, $x:expr)* $(,)?) => {
126 {
127 #[cfg(feature = "log")]
128 ::log::debug!($s $(, $x)*);
129 #[cfg(feature = "defmt")]
130 ::defmt::debug!($s $(, $x)*);
131 #[cfg(not(any(feature = "log", feature="defmt")))]
132 let _ = ($( & $x ),*);
133 }
134 };
135}
136
137macro_rules! info {
138 ($s:literal $(, $x:expr)* $(,)?) => {
139 {
140 #[cfg(feature = "log")]
141 ::log::info!($s $(, $x)*);
142 #[cfg(feature = "defmt")]
143 ::defmt::info!($s $(, $x)*);
144 #[cfg(not(any(feature = "log", feature="defmt")))]
145 let _ = ($( & $x ),*);
146 }
147 };
148}
149
150macro_rules! warn {
151 ($s:literal $(, $x:expr)* $(,)?) => {
152 {
153 #[cfg(feature = "log")]
154 ::log::warn!($s $(, $x)*);
155 #[cfg(feature = "defmt")]
156 ::defmt::warn!($s $(, $x)*);
157 #[cfg(not(any(feature = "log", feature="defmt")))]
158 let _ = ($( & $x ),*);
159 }
160 };
161}
162
163macro_rules! error {
164 ($s:literal $(, $x:expr)* $(,)?) => {
165 {
166 #[cfg(feature = "log")]
167 ::log::error!($s $(, $x)*);
168 #[cfg(feature = "defmt")]
169 ::defmt::error!($s $(, $x)*);
170 #[cfg(not(any(feature = "log", feature="defmt")))]
171 let _ = ($( & $x ),*);
172 }
173 };
174}
175
176#[cfg(feature = "defmt")]
177macro_rules! unwrap {
178 ($($x:tt)*) => {
179 ::defmt::unwrap!($($x)*)
180 };
181}
182
183#[cfg(not(feature = "defmt"))]
184macro_rules! unwrap {
185 ($arg:expr) => {
186 match $crate::fmt::Try::into_result($arg) {
187 ::core::result::Result::Ok(t) => t,
188 ::core::result::Result::Err(e) => {
189 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
190 }
191 }
192 };
193 ($arg:expr, $($msg:expr),+ $(,)? ) => {
194 match $crate::fmt::Try::into_result($arg) {
195 ::core::result::Result::Ok(t) => t,
196 ::core::result::Result::Err(e) => {
197 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
198 }
199 }
200 }
201}
202
203#[derive(Debug, Copy, Clone, Eq, PartialEq)]
204pub struct NoneError;
205
206pub trait Try {
207 type Ok;
208 type Error;
209 fn into_result(self) -> Result<Self::Ok, Self::Error>;
210}
211
212impl<T> Try for Option<T> {
213 type Ok = T;
214 type Error = NoneError;
215
216 #[inline]
217 fn into_result(self) -> Result<T, NoneError> {
218 self.ok_or(NoneError)
219 }
220}
221
222impl<T, E> Try for Result<T, E> {
223 type Ok = T;
224 type Error = E;
225
226 #[inline]
227 fn into_result(self) -> Self {
228 self
229 }
230}
231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]);
234
235impl<'a> Debug for Bytes<'a> {
236 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
237 write!(f, "{:#02x?}", self.0)
238 }
239}
240
241impl<'a> Display for Bytes<'a> {
242 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
243 write!(f, "{:#02x?}", self.0)
244 }
245}
246
247impl<'a> LowerHex for Bytes<'a> {
248 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
249 write!(f, "{:#02x?}", self.0)
250 }
251}
252
253#[cfg(feature = "defmt")]
254impl<'a> defmt::Format for Bytes<'a> {
255 fn format(&self, fmt: defmt::Formatter) {
256 defmt::write!(fmt, "{:02x}", self.0)
257 }
258}
diff --git a/embassy-boot/nrf/src/lib.rs b/embassy-boot/nrf/src/lib.rs
deleted file mode 100644
index 5b20a93c6..000000000
--- a/embassy-boot/nrf/src/lib.rs
+++ /dev/null
@@ -1,145 +0,0 @@
1#![no_std]
2#![warn(missing_docs)]
3#![doc = include_str!("../README.md")]
4mod fmt;
5
6pub use embassy_boot::{
7 AlignedBuffer, BlockingFirmwareState, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareState, FirmwareUpdater,
8 FirmwareUpdaterConfig,
9};
10use embassy_nrf::nvmc::PAGE_SIZE;
11use embassy_nrf::peripherals::WDT;
12use embassy_nrf::wdt;
13use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
14
15/// A bootloader for nRF devices.
16pub struct BootLoader<const BUFFER_SIZE: usize = PAGE_SIZE>;
17
18impl<const BUFFER_SIZE: usize> BootLoader<BUFFER_SIZE> {
19 /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware.
20 pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
21 config: BootLoaderConfig<ACTIVE, DFU, STATE>,
22 ) -> Self {
23 let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
24 let mut boot = embassy_boot::BootLoader::new(config);
25 boot.prepare_boot(&mut aligned_buf.0).expect("Boot prepare error");
26 Self
27 }
28
29 /// Boots the application without softdevice mechanisms.
30 ///
31 /// # Safety
32 ///
33 /// This modifies the stack pointer and reset vector and will run code placed in the active partition.
34 #[cfg(not(feature = "softdevice"))]
35 pub unsafe fn load(self, start: u32) -> ! {
36 let mut p = cortex_m::Peripherals::steal();
37 p.SCB.invalidate_icache();
38 p.SCB.vtor.write(start);
39 cortex_m::asm::bootload(start as *const u32)
40 }
41
42 /// Boots the application assuming softdevice is present.
43 ///
44 /// # Safety
45 ///
46 /// This modifies the stack pointer and reset vector and will run code placed in the active partition.
47 #[cfg(feature = "softdevice")]
48 pub unsafe fn load(self, _app: u32) -> ! {
49 use nrf_softdevice_mbr as mbr;
50 const NRF_SUCCESS: u32 = 0;
51
52 // Address of softdevice which we'll forward interrupts to
53 let addr = 0x1000;
54 let mut cmd = mbr::sd_mbr_command_t {
55 command: mbr::NRF_MBR_COMMANDS_SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET,
56 params: mbr::sd_mbr_command_t__bindgen_ty_1 {
57 irq_forward_address_set: mbr::sd_mbr_command_irq_forward_address_set_t { address: addr },
58 },
59 };
60 let ret = mbr::sd_mbr_command(&mut cmd);
61 assert_eq!(ret, NRF_SUCCESS);
62
63 let msp = *(addr as *const u32);
64 let rv = *((addr + 4) as *const u32);
65
66 trace!("msp = {=u32:x}, rv = {=u32:x}", msp, rv);
67
68 // These instructions perform the following operations:
69 //
70 // * Modify control register to use MSP as stack pointer (clear spsel bit)
71 // * Synchronize instruction barrier
72 // * Initialize stack pointer (0x1000)
73 // * Set link register to not return (0xFF)
74 // * Jump to softdevice reset vector
75 core::arch::asm!(
76 "mrs {tmp}, CONTROL",
77 "bics {tmp}, {spsel}",
78 "msr CONTROL, {tmp}",
79 "isb",
80 "msr MSP, {msp}",
81 "mov lr, {new_lr}",
82 "bx {rv}",
83 // `out(reg) _` is not permitted in a `noreturn` asm! call,
84 // so instead use `in(reg) 0` and don't restore it afterwards.
85 tmp = in(reg) 0,
86 spsel = in(reg) 2,
87 new_lr = in(reg) 0xFFFFFFFFu32,
88 msp = in(reg) msp,
89 rv = in(reg) rv,
90 options(noreturn),
91 );
92 }
93}
94
95/// A flash implementation that wraps any flash and will pet a watchdog when touching flash.
96pub struct WatchdogFlash<FLASH> {
97 flash: FLASH,
98 wdt: wdt::WatchdogHandle,
99}
100
101impl<FLASH> WatchdogFlash<FLASH> {
102 /// Start a new watchdog with a given flash and WDT peripheral and a timeout
103 pub fn start(flash: FLASH, wdt: WDT, config: wdt::Config) -> Self {
104 let (_wdt, [wdt]) = match wdt::Watchdog::try_new(wdt, config) {
105 Ok(x) => x,
106 Err(_) => {
107 // In case the watchdog is already running, just spin and let it expire, since
108 // we can't configure it anyway. This usually happens when we first program
109 // the device and the watchdog was previously active
110 info!("Watchdog already active with wrong config, waiting for it to timeout...");
111 loop {}
112 }
113 };
114 Self { flash, wdt }
115 }
116}
117
118impl<FLASH: ErrorType> ErrorType for WatchdogFlash<FLASH> {
119 type Error = FLASH::Error;
120}
121
122impl<FLASH: NorFlash> NorFlash for WatchdogFlash<FLASH> {
123 const WRITE_SIZE: usize = FLASH::WRITE_SIZE;
124 const ERASE_SIZE: usize = FLASH::ERASE_SIZE;
125
126 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
127 self.wdt.pet();
128 self.flash.erase(from, to)
129 }
130 fn write(&mut self, offset: u32, data: &[u8]) -> Result<(), Self::Error> {
131 self.wdt.pet();
132 self.flash.write(offset, data)
133 }
134}
135
136impl<FLASH: ReadNorFlash> ReadNorFlash for WatchdogFlash<FLASH> {
137 const READ_SIZE: usize = FLASH::READ_SIZE;
138 fn read(&mut self, offset: u32, data: &mut [u8]) -> Result<(), Self::Error> {
139 self.wdt.pet();
140 self.flash.read(offset, data)
141 }
142 fn capacity(&self) -> usize {
143 self.flash.capacity()
144 }
145}
diff --git a/embassy-boot/rp/Cargo.toml b/embassy-boot/rp/Cargo.toml
deleted file mode 100644
index 90bab0996..000000000
--- a/embassy-boot/rp/Cargo.toml
+++ /dev/null
@@ -1,79 +0,0 @@
1[package]
2edition = "2021"
3name = "embassy-boot-rp"
4version = "0.1.0"
5description = "Bootloader lib for RP2040 chips"
6license = "MIT OR Apache-2.0"
7repository = "https://github.com/embassy-rs/embassy"
8categories = [
9 "embedded",
10 "no-std",
11 "asynchronous",
12]
13
14[package.metadata.embassy_docs]
15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-rp-v$VERSION/src/"
16src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-boot/rp/src/"
17target = "thumbv6m-none-eabi"
18
19[lib]
20
21[dependencies]
22defmt = { version = "0.3", optional = true }
23defmt-rtt = { version = "0.4", optional = true }
24log = { version = "0.4", optional = true }
25
26embassy-sync = { version = "0.5.0", path = "../../embassy-sync" }
27embassy-rp = { path = "../../embassy-rp", default-features = false }
28embassy-boot = { path = "../boot", default-features = false }
29embassy-time = { path = "../../embassy-time" }
30
31cortex-m = { version = "0.7.6" }
32cortex-m-rt = { version = "0.7" }
33embedded-storage = "0.3.1"
34embedded-storage-async = { version = "0.4.1" }
35cfg-if = "1.0.0"
36
37[features]
38defmt = [
39 "dep:defmt",
40 "embassy-boot/defmt",
41 "embassy-rp/defmt",
42]
43log = [
44 "dep:log",
45 "embassy-boot/log",
46 "embassy-rp/log",
47]
48debug = ["defmt-rtt"]
49
50[profile.dev]
51debug = 2
52debug-assertions = true
53incremental = false
54opt-level = 'z'
55overflow-checks = true
56
57[profile.release]
58codegen-units = 1
59debug = 2
60debug-assertions = false
61incremental = false
62lto = 'fat'
63opt-level = 'z'
64overflow-checks = false
65
66# do not optimize proc-macro crates = faster builds from scratch
67[profile.dev.build-override]
68codegen-units = 8
69debug = false
70debug-assertions = false
71opt-level = 0
72overflow-checks = false
73
74[profile.release.build-override]
75codegen-units = 8
76debug = false
77debug-assertions = false
78opt-level = 0
79overflow-checks = false
diff --git a/embassy-boot/rp/README.md b/embassy-boot/rp/README.md
deleted file mode 100644
index 315d655e3..000000000
--- a/embassy-boot/rp/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
1# embassy-boot-rp
2
3An [Embassy](https://embassy.dev) project.
4
5An adaptation of `embassy-boot` for RP2040.
6
7NOTE: The applications using this bootloader should not link with the `link-rp.x` linker script.
8
9## Features
10
11* Configure bootloader partitions based on linker script.
12* Load applications from active partition.
13
14## Minimum supported Rust version (MSRV)
15
16`embassy-boot-rp` is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
17
18## License
19
20This work is licensed under either of
21
22- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
23 <http://www.apache.org/licenses/LICENSE-2.0>)
24- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
25
26at your option.
diff --git a/embassy-boot/rp/build.rs b/embassy-boot/rp/build.rs
deleted file mode 100644
index 2cbc7ef5e..000000000
--- a/embassy-boot/rp/build.rs
+++ /dev/null
@@ -1,8 +0,0 @@
1use std::env;
2
3fn main() {
4 let target = env::var("TARGET").unwrap();
5 if target.starts_with("thumbv6m-") {
6 println!("cargo:rustc-cfg=armv6m");
7 }
8}
diff --git a/embassy-boot/rp/src/fmt.rs b/embassy-boot/rp/src/fmt.rs
deleted file mode 100644
index 78e583c1c..000000000
--- a/embassy-boot/rp/src/fmt.rs
+++ /dev/null
@@ -1,258 +0,0 @@
1#![macro_use]
2#![allow(unused_macros)]
3
4use core::fmt::{Debug, Display, LowerHex};
5
6#[cfg(all(feature = "defmt", feature = "log"))]
7compile_error!("You may not enable both `defmt` and `log` features.");
8
9macro_rules! assert {
10 ($($x:tt)*) => {
11 {
12 #[cfg(not(feature = "defmt"))]
13 ::core::assert!($($x)*);
14 #[cfg(feature = "defmt")]
15 ::defmt::assert!($($x)*);
16 }
17 };
18}
19
20macro_rules! assert_eq {
21 ($($x:tt)*) => {
22 {
23 #[cfg(not(feature = "defmt"))]
24 ::core::assert_eq!($($x)*);
25 #[cfg(feature = "defmt")]
26 ::defmt::assert_eq!($($x)*);
27 }
28 };
29}
30
31macro_rules! assert_ne {
32 ($($x:tt)*) => {
33 {
34 #[cfg(not(feature = "defmt"))]
35 ::core::assert_ne!($($x)*);
36 #[cfg(feature = "defmt")]
37 ::defmt::assert_ne!($($x)*);
38 }
39 };
40}
41
42macro_rules! debug_assert {
43 ($($x:tt)*) => {
44 {
45 #[cfg(not(feature = "defmt"))]
46 ::core::debug_assert!($($x)*);
47 #[cfg(feature = "defmt")]
48 ::defmt::debug_assert!($($x)*);
49 }
50 };
51}
52
53macro_rules! debug_assert_eq {
54 ($($x:tt)*) => {
55 {
56 #[cfg(not(feature = "defmt"))]
57 ::core::debug_assert_eq!($($x)*);
58 #[cfg(feature = "defmt")]
59 ::defmt::debug_assert_eq!($($x)*);
60 }
61 };
62}
63
64macro_rules! debug_assert_ne {
65 ($($x:tt)*) => {
66 {
67 #[cfg(not(feature = "defmt"))]
68 ::core::debug_assert_ne!($($x)*);
69 #[cfg(feature = "defmt")]
70 ::defmt::debug_assert_ne!($($x)*);
71 }
72 };
73}
74
75macro_rules! todo {
76 ($($x:tt)*) => {
77 {
78 #[cfg(not(feature = "defmt"))]
79 ::core::todo!($($x)*);
80 #[cfg(feature = "defmt")]
81 ::defmt::todo!($($x)*);
82 }
83 };
84}
85
86#[cfg(not(feature = "defmt"))]
87macro_rules! unreachable {
88 ($($x:tt)*) => {
89 ::core::unreachable!($($x)*)
90 };
91}
92
93#[cfg(feature = "defmt")]
94macro_rules! unreachable {
95 ($($x:tt)*) => {
96 ::defmt::unreachable!($($x)*)
97 };
98}
99
100macro_rules! panic {
101 ($($x:tt)*) => {
102 {
103 #[cfg(not(feature = "defmt"))]
104 ::core::panic!($($x)*);
105 #[cfg(feature = "defmt")]
106 ::defmt::panic!($($x)*);
107 }
108 };
109}
110
111macro_rules! trace {
112 ($s:literal $(, $x:expr)* $(,)?) => {
113 {
114 #[cfg(feature = "log")]
115 ::log::trace!($s $(, $x)*);
116 #[cfg(feature = "defmt")]
117 ::defmt::trace!($s $(, $x)*);
118 #[cfg(not(any(feature = "log", feature="defmt")))]
119 let _ = ($( & $x ),*);
120 }
121 };
122}
123
124macro_rules! debug {
125 ($s:literal $(, $x:expr)* $(,)?) => {
126 {
127 #[cfg(feature = "log")]
128 ::log::debug!($s $(, $x)*);
129 #[cfg(feature = "defmt")]
130 ::defmt::debug!($s $(, $x)*);
131 #[cfg(not(any(feature = "log", feature="defmt")))]
132 let _ = ($( & $x ),*);
133 }
134 };
135}
136
137macro_rules! info {
138 ($s:literal $(, $x:expr)* $(,)?) => {
139 {
140 #[cfg(feature = "log")]
141 ::log::info!($s $(, $x)*);
142 #[cfg(feature = "defmt")]
143 ::defmt::info!($s $(, $x)*);
144 #[cfg(not(any(feature = "log", feature="defmt")))]
145 let _ = ($( & $x ),*);
146 }
147 };
148}
149
150macro_rules! warn {
151 ($s:literal $(, $x:expr)* $(,)?) => {
152 {
153 #[cfg(feature = "log")]
154 ::log::warn!($s $(, $x)*);
155 #[cfg(feature = "defmt")]
156 ::defmt::warn!($s $(, $x)*);
157 #[cfg(not(any(feature = "log", feature="defmt")))]
158 let _ = ($( & $x ),*);
159 }
160 };
161}
162
163macro_rules! error {
164 ($s:literal $(, $x:expr)* $(,)?) => {
165 {
166 #[cfg(feature = "log")]
167 ::log::error!($s $(, $x)*);
168 #[cfg(feature = "defmt")]
169 ::defmt::error!($s $(, $x)*);
170 #[cfg(not(any(feature = "log", feature="defmt")))]
171 let _ = ($( & $x ),*);
172 }
173 };
174}
175
176#[cfg(feature = "defmt")]
177macro_rules! unwrap {
178 ($($x:tt)*) => {
179 ::defmt::unwrap!($($x)*)
180 };
181}
182
183#[cfg(not(feature = "defmt"))]
184macro_rules! unwrap {
185 ($arg:expr) => {
186 match $crate::fmt::Try::into_result($arg) {
187 ::core::result::Result::Ok(t) => t,
188 ::core::result::Result::Err(e) => {
189 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
190 }
191 }
192 };
193 ($arg:expr, $($msg:expr),+ $(,)? ) => {
194 match $crate::fmt::Try::into_result($arg) {
195 ::core::result::Result::Ok(t) => t,
196 ::core::result::Result::Err(e) => {
197 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
198 }
199 }
200 }
201}
202
203#[derive(Debug, Copy, Clone, Eq, PartialEq)]
204pub struct NoneError;
205
206pub trait Try {
207 type Ok;
208 type Error;
209 fn into_result(self) -> Result<Self::Ok, Self::Error>;
210}
211
212impl<T> Try for Option<T> {
213 type Ok = T;
214 type Error = NoneError;
215
216 #[inline]
217 fn into_result(self) -> Result<T, NoneError> {
218 self.ok_or(NoneError)
219 }
220}
221
222impl<T, E> Try for Result<T, E> {
223 type Ok = T;
224 type Error = E;
225
226 #[inline]
227 fn into_result(self) -> Self {
228 self
229 }
230}
231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]);
234
235impl<'a> Debug for Bytes<'a> {
236 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
237 write!(f, "{:#02x?}", self.0)
238 }
239}
240
241impl<'a> Display for Bytes<'a> {
242 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
243 write!(f, "{:#02x?}", self.0)
244 }
245}
246
247impl<'a> LowerHex for Bytes<'a> {
248 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
249 write!(f, "{:#02x?}", self.0)
250 }
251}
252
253#[cfg(feature = "defmt")]
254impl<'a> defmt::Format for Bytes<'a> {
255 fn format(&self, fmt: defmt::Formatter) {
256 defmt::write!(fmt, "{:02x}", self.0)
257 }
258}
diff --git a/embassy-boot/rp/src/lib.rs b/embassy-boot/rp/src/lib.rs
deleted file mode 100644
index 07a5b3f4d..000000000
--- a/embassy-boot/rp/src/lib.rs
+++ /dev/null
@@ -1,90 +0,0 @@
1#![no_std]
2#![warn(missing_docs)]
3#![doc = include_str!("../README.md")]
4mod fmt;
5
6pub use embassy_boot::{
7 AlignedBuffer, BlockingFirmwareState, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareState, FirmwareUpdater,
8 FirmwareUpdaterConfig, State,
9};
10use embassy_rp::flash::{Blocking, Flash, ERASE_SIZE};
11use embassy_rp::peripherals::{FLASH, WATCHDOG};
12use embassy_rp::watchdog::Watchdog;
13use embassy_time::Duration;
14use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
15
16/// A bootloader for RP2040 devices.
17pub struct BootLoader<const BUFFER_SIZE: usize = ERASE_SIZE>;
18
19impl<const BUFFER_SIZE: usize> BootLoader<BUFFER_SIZE> {
20 /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
21 pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
22 config: BootLoaderConfig<ACTIVE, DFU, STATE>,
23 ) -> Self {
24 let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
25 let mut boot = embassy_boot::BootLoader::new(config);
26 boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error");
27 Self
28 }
29
30 /// Boots the application.
31 ///
32 /// # Safety
33 ///
34 /// This modifies the stack pointer and reset vector and will run code placed in the active partition.
35 pub unsafe fn load(self, start: u32) -> ! {
36 trace!("Loading app at 0x{:x}", start);
37 #[allow(unused_mut)]
38 let mut p = cortex_m::Peripherals::steal();
39 #[cfg(not(armv6m))]
40 p.SCB.invalidate_icache();
41 p.SCB.vtor.write(start);
42
43 cortex_m::asm::bootload(start as *const u32)
44 }
45}
46
47/// A flash implementation that will feed a watchdog when touching flash.
48pub struct WatchdogFlash<'d, const SIZE: usize> {
49 flash: Flash<'d, FLASH, Blocking, SIZE>,
50 watchdog: Watchdog,
51}
52
53impl<'d, const SIZE: usize> WatchdogFlash<'d, SIZE> {
54 /// Start a new watchdog with a given flash and watchdog peripheral and a timeout
55 pub fn start(flash: FLASH, watchdog: WATCHDOG, timeout: Duration) -> Self {
56 let flash = Flash::<_, Blocking, SIZE>::new_blocking(flash);
57 let mut watchdog = Watchdog::new(watchdog);
58 watchdog.start(timeout);
59 Self { flash, watchdog }
60 }
61}
62
63impl<'d, const SIZE: usize> ErrorType for WatchdogFlash<'d, SIZE> {
64 type Error = <Flash<'d, FLASH, Blocking, SIZE> as ErrorType>::Error;
65}
66
67impl<'d, const SIZE: usize> NorFlash for WatchdogFlash<'d, SIZE> {
68 const WRITE_SIZE: usize = <Flash<'d, FLASH, Blocking, SIZE> as NorFlash>::WRITE_SIZE;
69 const ERASE_SIZE: usize = <Flash<'d, FLASH, Blocking, SIZE> as NorFlash>::ERASE_SIZE;
70
71 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
72 self.watchdog.feed();
73 self.flash.blocking_erase(from, to)
74 }
75 fn write(&mut self, offset: u32, data: &[u8]) -> Result<(), Self::Error> {
76 self.watchdog.feed();
77 self.flash.blocking_write(offset, data)
78 }
79}
80
81impl<'d, const SIZE: usize> ReadNorFlash for WatchdogFlash<'d, SIZE> {
82 const READ_SIZE: usize = <Flash<'d, FLASH, Blocking, SIZE> as ReadNorFlash>::READ_SIZE;
83 fn read(&mut self, offset: u32, data: &mut [u8]) -> Result<(), Self::Error> {
84 self.watchdog.feed();
85 self.flash.blocking_read(offset, data)
86 }
87 fn capacity(&self) -> usize {
88 self.flash.capacity()
89 }
90}
diff --git a/embassy-boot/boot/src/boot_loader.rs b/embassy-boot/src/boot_loader.rs
index e568001bc..e568001bc 100644
--- a/embassy-boot/boot/src/boot_loader.rs
+++ b/embassy-boot/src/boot_loader.rs
diff --git a/embassy-boot/boot/src/digest_adapters/ed25519_dalek.rs b/embassy-boot/src/digest_adapters/ed25519_dalek.rs
index 2e4e03da3..2e4e03da3 100644
--- a/embassy-boot/boot/src/digest_adapters/ed25519_dalek.rs
+++ b/embassy-boot/src/digest_adapters/ed25519_dalek.rs
diff --git a/embassy-boot/boot/src/digest_adapters/mod.rs b/embassy-boot/src/digest_adapters/mod.rs
index 9b4b4b60c..9b4b4b60c 100644
--- a/embassy-boot/boot/src/digest_adapters/mod.rs
+++ b/embassy-boot/src/digest_adapters/mod.rs
diff --git a/embassy-boot/boot/src/digest_adapters/salty.rs b/embassy-boot/src/digest_adapters/salty.rs
index 2b5dcf3af..2b5dcf3af 100644
--- a/embassy-boot/boot/src/digest_adapters/salty.rs
+++ b/embassy-boot/src/digest_adapters/salty.rs
diff --git a/embassy-boot/boot/src/firmware_updater/asynch.rs b/embassy-boot/src/firmware_updater/asynch.rs
index 2e43e1cc1..2e43e1cc1 100644
--- a/embassy-boot/boot/src/firmware_updater/asynch.rs
+++ b/embassy-boot/src/firmware_updater/asynch.rs
diff --git a/embassy-boot/boot/src/firmware_updater/blocking.rs b/embassy-boot/src/firmware_updater/blocking.rs
index f1368540d..f1368540d 100644
--- a/embassy-boot/boot/src/firmware_updater/blocking.rs
+++ b/embassy-boot/src/firmware_updater/blocking.rs
diff --git a/embassy-boot/boot/src/firmware_updater/mod.rs b/embassy-boot/src/firmware_updater/mod.rs
index 4814786bf..4814786bf 100644
--- a/embassy-boot/boot/src/firmware_updater/mod.rs
+++ b/embassy-boot/src/firmware_updater/mod.rs
diff --git a/embassy-boot/boot/src/fmt.rs b/embassy-boot/src/fmt.rs
index 78e583c1c..78e583c1c 100644
--- a/embassy-boot/boot/src/fmt.rs
+++ b/embassy-boot/src/fmt.rs
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/src/lib.rs
index b4f03e01e..b4f03e01e 100644
--- a/embassy-boot/boot/src/lib.rs
+++ b/embassy-boot/src/lib.rs
diff --git a/embassy-boot/boot/src/mem_flash.rs b/embassy-boot/src/mem_flash.rs
index 40f352c8d..40f352c8d 100644
--- a/embassy-boot/boot/src/mem_flash.rs
+++ b/embassy-boot/src/mem_flash.rs
diff --git a/embassy-boot/boot/src/test_flash/asynch.rs b/embassy-boot/src/test_flash/asynch.rs
index 3ac9e71ab..3ac9e71ab 100644
--- a/embassy-boot/boot/src/test_flash/asynch.rs
+++ b/embassy-boot/src/test_flash/asynch.rs
diff --git a/embassy-boot/boot/src/test_flash/blocking.rs b/embassy-boot/src/test_flash/blocking.rs
index 5ec476c65..5ec476c65 100644
--- a/embassy-boot/boot/src/test_flash/blocking.rs
+++ b/embassy-boot/src/test_flash/blocking.rs
diff --git a/embassy-boot/boot/src/test_flash/mod.rs b/embassy-boot/src/test_flash/mod.rs
index 79b15a081..79b15a081 100644
--- a/embassy-boot/boot/src/test_flash/mod.rs
+++ b/embassy-boot/src/test_flash/mod.rs
diff --git a/embassy-boot/stm32/Cargo.toml b/embassy-boot/stm32/Cargo.toml
deleted file mode 100644
index 70919b76d..000000000
--- a/embassy-boot/stm32/Cargo.toml
+++ /dev/null
@@ -1,70 +0,0 @@
1[package]
2edition = "2021"
3name = "embassy-boot-stm32"
4version = "0.1.0"
5description = "Bootloader lib for STM32 chips"
6license = "MIT OR Apache-2.0"
7repository = "https://github.com/embassy-rs/embassy"
8categories = [
9 "embedded",
10 "no-std",
11 "asynchronous",
12]
13
14[package.metadata.embassy_docs]
15src_base = "https://github.com/embassy-rs/embassy/blob/embassy-boot-nrf-v$VERSION/embassy-boot/stm32/src/"
16src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-boot/stm32/src/"
17features = ["embassy-stm32/stm32f429zi"]
18target = "thumbv7em-none-eabi"
19
20[lib]
21
22[dependencies]
23defmt = { version = "0.3", optional = true }
24defmt-rtt = { version = "0.4", optional = true }
25log = { version = "0.4", optional = true }
26
27embassy-sync = { version = "0.5.0", path = "../../embassy-sync" }
28embassy-stm32 = { path = "../../embassy-stm32", default-features = false }
29embassy-boot = { path = "../boot", default-features = false }
30cortex-m = { version = "0.7.6" }
31cortex-m-rt = { version = "0.7" }
32embedded-storage = "0.3.1"
33embedded-storage-async = { version = "0.4.1" }
34cfg-if = "1.0.0"
35
36[features]
37defmt = ["dep:defmt", "embassy-boot/defmt", "embassy-stm32/defmt"]
38log = ["dep:log", "embassy-boot/log", "embassy-stm32/log"]
39debug = ["defmt-rtt"]
40
41[profile.dev]
42debug = 2
43debug-assertions = true
44incremental = false
45opt-level = 'z'
46overflow-checks = true
47
48[profile.release]
49codegen-units = 1
50debug = 2
51debug-assertions = false
52incremental = false
53lto = 'fat'
54opt-level = 'z'
55overflow-checks = false
56
57# do not optimize proc-macro crates = faster builds from scratch
58[profile.dev.build-override]
59codegen-units = 8
60debug = false
61debug-assertions = false
62opt-level = 0
63overflow-checks = false
64
65[profile.release.build-override]
66codegen-units = 8
67debug = false
68debug-assertions = false
69opt-level = 0
70overflow-checks = false
diff --git a/embassy-boot/stm32/README.md b/embassy-boot/stm32/README.md
deleted file mode 100644
index b4d7ba5a4..000000000
--- a/embassy-boot/stm32/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
1# embassy-boot-stm32
2
3An [Embassy](https://embassy.dev) project.
4
5An adaptation of `embassy-boot` for STM32.
6
7## Features
8
9* Configure bootloader partitions based on linker script.
10* Load applications from active partition.
11
12## Minimum supported Rust version (MSRV)
13
14`embassy-boot-stm32` is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
15
16## License
17
18This work is licensed under either of
19
20- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
21 <http://www.apache.org/licenses/LICENSE-2.0>)
22- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
23
24at your option.
diff --git a/embassy-boot/stm32/build.rs b/embassy-boot/stm32/build.rs
deleted file mode 100644
index 2cbc7ef5e..000000000
--- a/embassy-boot/stm32/build.rs
+++ /dev/null
@@ -1,8 +0,0 @@
1use std::env;
2
3fn main() {
4 let target = env::var("TARGET").unwrap();
5 if target.starts_with("thumbv6m-") {
6 println!("cargo:rustc-cfg=armv6m");
7 }
8}
diff --git a/embassy-boot/stm32/src/fmt.rs b/embassy-boot/stm32/src/fmt.rs
deleted file mode 100644
index 78e583c1c..000000000
--- a/embassy-boot/stm32/src/fmt.rs
+++ /dev/null
@@ -1,258 +0,0 @@
1#![macro_use]
2#![allow(unused_macros)]
3
4use core::fmt::{Debug, Display, LowerHex};
5
6#[cfg(all(feature = "defmt", feature = "log"))]
7compile_error!("You may not enable both `defmt` and `log` features.");
8
9macro_rules! assert {
10 ($($x:tt)*) => {
11 {
12 #[cfg(not(feature = "defmt"))]
13 ::core::assert!($($x)*);
14 #[cfg(feature = "defmt")]
15 ::defmt::assert!($($x)*);
16 }
17 };
18}
19
20macro_rules! assert_eq {
21 ($($x:tt)*) => {
22 {
23 #[cfg(not(feature = "defmt"))]
24 ::core::assert_eq!($($x)*);
25 #[cfg(feature = "defmt")]
26 ::defmt::assert_eq!($($x)*);
27 }
28 };
29}
30
31macro_rules! assert_ne {
32 ($($x:tt)*) => {
33 {
34 #[cfg(not(feature = "defmt"))]
35 ::core::assert_ne!($($x)*);
36 #[cfg(feature = "defmt")]
37 ::defmt::assert_ne!($($x)*);
38 }
39 };
40}
41
42macro_rules! debug_assert {
43 ($($x:tt)*) => {
44 {
45 #[cfg(not(feature = "defmt"))]
46 ::core::debug_assert!($($x)*);
47 #[cfg(feature = "defmt")]
48 ::defmt::debug_assert!($($x)*);
49 }
50 };
51}
52
53macro_rules! debug_assert_eq {
54 ($($x:tt)*) => {
55 {
56 #[cfg(not(feature = "defmt"))]
57 ::core::debug_assert_eq!($($x)*);
58 #[cfg(feature = "defmt")]
59 ::defmt::debug_assert_eq!($($x)*);
60 }
61 };
62}
63
64macro_rules! debug_assert_ne {
65 ($($x:tt)*) => {
66 {
67 #[cfg(not(feature = "defmt"))]
68 ::core::debug_assert_ne!($($x)*);
69 #[cfg(feature = "defmt")]
70 ::defmt::debug_assert_ne!($($x)*);
71 }
72 };
73}
74
75macro_rules! todo {
76 ($($x:tt)*) => {
77 {
78 #[cfg(not(feature = "defmt"))]
79 ::core::todo!($($x)*);
80 #[cfg(feature = "defmt")]
81 ::defmt::todo!($($x)*);
82 }
83 };
84}
85
86#[cfg(not(feature = "defmt"))]
87macro_rules! unreachable {
88 ($($x:tt)*) => {
89 ::core::unreachable!($($x)*)
90 };
91}
92
93#[cfg(feature = "defmt")]
94macro_rules! unreachable {
95 ($($x:tt)*) => {
96 ::defmt::unreachable!($($x)*)
97 };
98}
99
100macro_rules! panic {
101 ($($x:tt)*) => {
102 {
103 #[cfg(not(feature = "defmt"))]
104 ::core::panic!($($x)*);
105 #[cfg(feature = "defmt")]
106 ::defmt::panic!($($x)*);
107 }
108 };
109}
110
111macro_rules! trace {
112 ($s:literal $(, $x:expr)* $(,)?) => {
113 {
114 #[cfg(feature = "log")]
115 ::log::trace!($s $(, $x)*);
116 #[cfg(feature = "defmt")]
117 ::defmt::trace!($s $(, $x)*);
118 #[cfg(not(any(feature = "log", feature="defmt")))]
119 let _ = ($( & $x ),*);
120 }
121 };
122}
123
124macro_rules! debug {
125 ($s:literal $(, $x:expr)* $(,)?) => {
126 {
127 #[cfg(feature = "log")]
128 ::log::debug!($s $(, $x)*);
129 #[cfg(feature = "defmt")]
130 ::defmt::debug!($s $(, $x)*);
131 #[cfg(not(any(feature = "log", feature="defmt")))]
132 let _ = ($( & $x ),*);
133 }
134 };
135}
136
137macro_rules! info {
138 ($s:literal $(, $x:expr)* $(,)?) => {
139 {
140 #[cfg(feature = "log")]
141 ::log::info!($s $(, $x)*);
142 #[cfg(feature = "defmt")]
143 ::defmt::info!($s $(, $x)*);
144 #[cfg(not(any(feature = "log", feature="defmt")))]
145 let _ = ($( & $x ),*);
146 }
147 };
148}
149
150macro_rules! warn {
151 ($s:literal $(, $x:expr)* $(,)?) => {
152 {
153 #[cfg(feature = "log")]
154 ::log::warn!($s $(, $x)*);
155 #[cfg(feature = "defmt")]
156 ::defmt::warn!($s $(, $x)*);
157 #[cfg(not(any(feature = "log", feature="defmt")))]
158 let _ = ($( & $x ),*);
159 }
160 };
161}
162
163macro_rules! error {
164 ($s:literal $(, $x:expr)* $(,)?) => {
165 {
166 #[cfg(feature = "log")]
167 ::log::error!($s $(, $x)*);
168 #[cfg(feature = "defmt")]
169 ::defmt::error!($s $(, $x)*);
170 #[cfg(not(any(feature = "log", feature="defmt")))]
171 let _ = ($( & $x ),*);
172 }
173 };
174}
175
176#[cfg(feature = "defmt")]
177macro_rules! unwrap {
178 ($($x:tt)*) => {
179 ::defmt::unwrap!($($x)*)
180 };
181}
182
183#[cfg(not(feature = "defmt"))]
184macro_rules! unwrap {
185 ($arg:expr) => {
186 match $crate::fmt::Try::into_result($arg) {
187 ::core::result::Result::Ok(t) => t,
188 ::core::result::Result::Err(e) => {
189 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
190 }
191 }
192 };
193 ($arg:expr, $($msg:expr),+ $(,)? ) => {
194 match $crate::fmt::Try::into_result($arg) {
195 ::core::result::Result::Ok(t) => t,
196 ::core::result::Result::Err(e) => {
197 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
198 }
199 }
200 }
201}
202
203#[derive(Debug, Copy, Clone, Eq, PartialEq)]
204pub struct NoneError;
205
206pub trait Try {
207 type Ok;
208 type Error;
209 fn into_result(self) -> Result<Self::Ok, Self::Error>;
210}
211
212impl<T> Try for Option<T> {
213 type Ok = T;
214 type Error = NoneError;
215
216 #[inline]
217 fn into_result(self) -> Result<T, NoneError> {
218 self.ok_or(NoneError)
219 }
220}
221
222impl<T, E> Try for Result<T, E> {
223 type Ok = T;
224 type Error = E;
225
226 #[inline]
227 fn into_result(self) -> Self {
228 self
229 }
230}
231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]);
234
235impl<'a> Debug for Bytes<'a> {
236 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
237 write!(f, "{:#02x?}", self.0)
238 }
239}
240
241impl<'a> Display for Bytes<'a> {
242 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
243 write!(f, "{:#02x?}", self.0)
244 }
245}
246
247impl<'a> LowerHex for Bytes<'a> {
248 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
249 write!(f, "{:#02x?}", self.0)
250 }
251}
252
253#[cfg(feature = "defmt")]
254impl<'a> defmt::Format for Bytes<'a> {
255 fn format(&self, fmt: defmt::Formatter) {
256 defmt::write!(fmt, "{:02x}", self.0)
257 }
258}
diff --git a/embassy-boot/stm32/src/lib.rs b/embassy-boot/stm32/src/lib.rs
deleted file mode 100644
index 4b4091ac9..000000000
--- a/embassy-boot/stm32/src/lib.rs
+++ /dev/null
@@ -1,44 +0,0 @@
1#![no_std]
2#![warn(missing_docs)]
3#![doc = include_str!("../README.md")]
4mod fmt;
5
6pub use embassy_boot::{
7 AlignedBuffer, BlockingFirmwareState, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareState, FirmwareUpdater,
8 FirmwareUpdaterConfig, State,
9};
10use embedded_storage::nor_flash::NorFlash;
11
12/// A bootloader for STM32 devices.
13pub struct BootLoader {
14 /// The reported state of the bootloader after preparing for boot
15 pub state: State,
16}
17
18impl BootLoader {
19 /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
20 pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>(
21 config: BootLoaderConfig<ACTIVE, DFU, STATE>,
22 ) -> Self {
23 let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
24 let mut boot = embassy_boot::BootLoader::new(config);
25 let state = boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error");
26 Self { state }
27 }
28
29 /// Boots the application.
30 ///
31 /// # Safety
32 ///
33 /// This modifies the stack pointer and reset vector and will run code placed in the active partition.
34 pub unsafe fn load(self, start: u32) -> ! {
35 trace!("Loading app at 0x{:x}", start);
36 #[allow(unused_mut)]
37 let mut p = cortex_m::Peripherals::steal();
38 #[cfg(not(armv6m))]
39 p.SCB.invalidate_icache();
40 p.SCB.vtor.write(start);
41
42 cortex_m::asm::bootload(start as *const u32)
43 }
44}