diff options
| author | Ulf Lilleengen <[email protected]> | 2022-04-19 14:42:38 +0200 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2022-04-19 20:07:06 +0200 |
| commit | 2afff617f652d0fdcfa9ffcfd49062e3d2c996a3 (patch) | |
| tree | bc531122365086cd24a12a9331c94f9f042cad3a /embassy-boot | |
| parent | e2ed41b3832db17633ae8ae1ee9391639c3a9229 (diff) | |
Support multiple flash instances in embassy-boot
* Add FlashProvider and FlashConfig traits to define flash
characteristics
* Use traits in bootloader to retrieve flash handles and for
copying data between flash instances
* Add convenience implementations for using a single flash instance.
Diffstat (limited to 'embassy-boot')
| -rw-r--r-- | embassy-boot/boot/src/lib.rs | 234 | ||||
| -rw-r--r-- | embassy-boot/nrf/.cargo/config.toml | 1 | ||||
| -rw-r--r-- | embassy-boot/nrf/Cargo.toml | 2 | ||||
| -rw-r--r-- | embassy-boot/nrf/src/lib.rs | 6 | ||||
| -rw-r--r-- | embassy-boot/nrf/src/main.rs | 6 |
5 files changed, 203 insertions, 46 deletions
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs index 6f31e280d..0d33ad1a6 100644 --- a/embassy-boot/boot/src/lib.rs +++ b/embassy-boot/boot/src/lib.rs | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | ///! | 14 | ///! |
| 15 | mod fmt; | 15 | mod fmt; |
| 16 | 16 | ||
| 17 | use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; | 17 | use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; |
| 18 | use embedded_storage_async::nor_flash::AsyncNorFlash; | 18 | use embedded_storage_async::nor_flash::AsyncNorFlash; |
| 19 | 19 | ||
| 20 | pub const BOOT_MAGIC: u32 = 0xD00DF00D; | 20 | pub const BOOT_MAGIC: u32 = 0xD00DF00D; |
| @@ -44,18 +44,41 @@ pub enum State { | |||
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | #[derive(PartialEq, Debug)] | 46 | #[derive(PartialEq, Debug)] |
| 47 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 47 | pub enum BootError { |
| 48 | pub enum BootError<E> { | 48 | Flash(NorFlashErrorKind), |
| 49 | Flash(E), | ||
| 50 | BadMagic, | 49 | BadMagic, |
| 51 | } | 50 | } |
| 52 | 51 | ||
| 53 | impl<E> From<E> for BootError<E> { | 52 | impl<E> From<E> for BootError |
| 53 | where | ||
| 54 | E: NorFlashError, | ||
| 55 | { | ||
| 54 | fn from(error: E) -> Self { | 56 | fn from(error: E) -> Self { |
| 55 | BootError::Flash(error) | 57 | BootError::Flash(error.kind()) |
| 56 | } | 58 | } |
| 57 | } | 59 | } |
| 58 | 60 | ||
| 61 | pub trait FlashConfig { | ||
| 62 | const BLOCK_SIZE: usize; | ||
| 63 | type FLASH: NorFlash + ReadNorFlash; | ||
| 64 | |||
| 65 | fn flash(&mut self) -> &mut Self::FLASH; | ||
| 66 | } | ||
| 67 | |||
| 68 | /// Trait defining the flash handles used for active and DFU partition | ||
| 69 | pub trait FlashProvider { | ||
| 70 | type STATE: FlashConfig; | ||
| 71 | type ACTIVE: FlashConfig; | ||
| 72 | type DFU: FlashConfig; | ||
| 73 | |||
| 74 | /// Return flash instance used to write/read to/from active partition. | ||
| 75 | fn active(&mut self) -> &mut Self::ACTIVE; | ||
| 76 | /// Return flash instance used to write/read to/from dfu partition. | ||
| 77 | fn dfu(&mut self) -> &mut Self::DFU; | ||
| 78 | /// Return flash instance used to write/read to/from bootloader state. | ||
| 79 | fn state(&mut self) -> &mut Self::STATE; | ||
| 80 | } | ||
| 81 | |||
| 59 | /// BootLoader works with any flash implementing embedded_storage and can also work with | 82 | /// BootLoader works with any flash implementing embedded_storage and can also work with |
| 60 | /// different page sizes. | 83 | /// different page sizes. |
| 61 | pub struct BootLoader<const PAGE_SIZE: usize> { | 84 | pub struct BootLoader<const PAGE_SIZE: usize> { |
| @@ -168,29 +191,27 @@ impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> { | |||
| 168 | /// | DFU | 3 | 3 | 2 | 1 | 3 | | 191 | /// | DFU | 3 | 3 | 2 | 1 | 3 | |
| 169 | /// +-----------+--------------+--------+--------+--------+--------+ | 192 | /// +-----------+--------------+--------+--------+--------+--------+ |
| 170 | /// | 193 | /// |
| 171 | pub fn prepare_boot<F: NorFlash + ReadNorFlash>( | 194 | pub fn prepare_boot<P: FlashProvider>(&mut self, p: &mut P) -> Result<State, BootError> { |
| 172 | &mut self, | ||
| 173 | flash: &mut F, | ||
| 174 | ) -> Result<State, BootError<F::Error>> { | ||
| 175 | // Copy contents from partition N to active | 195 | // Copy contents from partition N to active |
| 176 | let state = self.read_state(flash)?; | 196 | let state = self.read_state(p.state())?; |
| 177 | match state { | 197 | match state { |
| 178 | State::Swap => { | 198 | State::Swap => { |
| 179 | // | 199 | // |
| 180 | // Check if we already swapped. If we're in the swap state, this means we should revert | 200 | // Check if we already swapped. If we're in the swap state, this means we should revert |
| 181 | // since the app has failed to mark boot as successful | 201 | // since the app has failed to mark boot as successful |
| 182 | // | 202 | // |
| 183 | if !self.is_swapped(flash)? { | 203 | if !self.is_swapped(p.state())? { |
| 184 | trace!("Swapping"); | 204 | trace!("Swapping"); |
| 185 | self.swap(flash)?; | 205 | self.swap(p)?; |
| 186 | } else { | 206 | } else { |
| 187 | trace!("Reverting"); | 207 | trace!("Reverting"); |
| 188 | self.revert(flash)?; | 208 | self.revert(p)?; |
| 189 | 209 | ||
| 190 | // Overwrite magic and reset progress | 210 | // Overwrite magic and reset progress |
| 191 | flash.write(self.state.from as u32, &[0, 0, 0, 0])?; | 211 | let fstate = p.state().flash(); |
| 192 | flash.erase(self.state.from as u32, self.state.to as u32)?; | 212 | fstate.write(self.state.from as u32, &[0, 0, 0, 0])?; |
| 193 | flash.write(self.state.from as u32, &BOOT_MAGIC.to_le_bytes())?; | 213 | fstate.erase(self.state.from as u32, self.state.to as u32)?; |
| 214 | fstate.write(self.state.from as u32, &BOOT_MAGIC.to_le_bytes())?; | ||
| 194 | } | 215 | } |
| 195 | } | 216 | } |
| 196 | _ => {} | 217 | _ => {} |
| @@ -198,15 +219,16 @@ impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> { | |||
| 198 | Ok(state) | 219 | Ok(state) |
| 199 | } | 220 | } |
| 200 | 221 | ||
| 201 | fn is_swapped<F: ReadNorFlash>(&mut self, flash: &mut F) -> Result<bool, F::Error> { | 222 | fn is_swapped<P: FlashConfig>(&mut self, p: &mut P) -> Result<bool, BootError> { |
| 202 | let page_count = self.active.len() / PAGE_SIZE; | 223 | let page_count = self.active.len() / PAGE_SIZE; |
| 203 | let progress = self.current_progress(flash)?; | 224 | let progress = self.current_progress(p)?; |
| 204 | 225 | ||
| 205 | Ok(progress >= page_count * 2) | 226 | Ok(progress >= page_count * 2) |
| 206 | } | 227 | } |
| 207 | 228 | ||
| 208 | fn current_progress<F: ReadNorFlash>(&mut self, flash: &mut F) -> Result<usize, F::Error> { | 229 | fn current_progress<P: FlashConfig>(&mut self, p: &mut P) -> Result<usize, BootError> { |
| 209 | let max_index = ((self.state.len() - 4) / 4) - 1; | 230 | let max_index = ((self.state.len() - 4) / 4) - 1; |
| 231 | let flash = p.flash(); | ||
| 210 | for i in 0..max_index { | 232 | for i in 0..max_index { |
| 211 | let mut buf: [u8; 4] = [0; 4]; | 233 | let mut buf: [u8; 4] = [0; 4]; |
| 212 | flash.read((self.state.from + 4 + i * 4) as u32, &mut buf)?; | 234 | flash.read((self.state.from + 4 + i * 4) as u32, &mut buf)?; |
| @@ -217,7 +239,8 @@ impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> { | |||
| 217 | Ok(max_index) | 239 | Ok(max_index) |
| 218 | } | 240 | } |
| 219 | 241 | ||
| 220 | fn update_progress<F: NorFlash>(&mut self, idx: usize, flash: &mut F) -> Result<(), F::Error> { | 242 | fn update_progress<P: FlashConfig>(&mut self, idx: usize, p: &mut P) -> Result<(), BootError> { |
| 243 | let flash = p.flash(); | ||
| 221 | let w = self.state.from + 4 + idx * 4; | 244 | let w = self.state.from + 4 + idx * 4; |
| 222 | flash.write(w as u32, &[0, 0, 0, 0])?; | 245 | flash.write(w as u32, &[0, 0, 0, 0])?; |
| 223 | Ok(()) | 246 | Ok(()) |
| @@ -231,62 +254,104 @@ impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> { | |||
| 231 | self.dfu.from + n * PAGE_SIZE | 254 | self.dfu.from + n * PAGE_SIZE |
| 232 | } | 255 | } |
| 233 | 256 | ||
| 234 | fn copy_page_once<F: NorFlash + ReadNorFlash>( | 257 | fn copy_page_once_to_active<P: FlashProvider>( |
| 235 | &mut self, | 258 | &mut self, |
| 236 | idx: usize, | 259 | idx: usize, |
| 237 | from: usize, | 260 | from_page: usize, |
| 238 | to: usize, | 261 | to_page: usize, |
| 239 | flash: &mut F, | 262 | p: &mut P, |
| 240 | ) -> Result<(), F::Error> { | 263 | ) -> Result<(), BootError> { |
| 264 | let mut buf: [u8; PAGE_SIZE] = [0; PAGE_SIZE]; | ||
| 265 | if self.current_progress(p.state())? <= idx { | ||
| 266 | let mut offset = from_page; | ||
| 267 | for chunk in buf.chunks_mut(P::DFU::BLOCK_SIZE) { | ||
| 268 | p.dfu().flash().read(offset as u32, chunk)?; | ||
| 269 | offset += chunk.len(); | ||
| 270 | } | ||
| 271 | |||
| 272 | p.active() | ||
| 273 | .flash() | ||
| 274 | .erase(to_page as u32, (to_page + PAGE_SIZE) as u32)?; | ||
| 275 | |||
| 276 | let mut offset = to_page; | ||
| 277 | for chunk in buf.chunks(P::ACTIVE::BLOCK_SIZE) { | ||
| 278 | p.active().flash().write(offset as u32, &chunk)?; | ||
| 279 | offset += chunk.len(); | ||
| 280 | } | ||
| 281 | self.update_progress(idx, p.state())?; | ||
| 282 | } | ||
| 283 | Ok(()) | ||
| 284 | } | ||
| 285 | |||
| 286 | fn copy_page_once_to_dfu<P: FlashProvider>( | ||
| 287 | &mut self, | ||
| 288 | idx: usize, | ||
| 289 | from_page: usize, | ||
| 290 | to_page: usize, | ||
| 291 | p: &mut P, | ||
| 292 | ) -> Result<(), BootError> { | ||
| 241 | let mut buf: [u8; PAGE_SIZE] = [0; PAGE_SIZE]; | 293 | let mut buf: [u8; PAGE_SIZE] = [0; PAGE_SIZE]; |
| 242 | if self.current_progress(flash)? <= idx { | 294 | if self.current_progress(p.state())? <= idx { |
| 243 | flash.read(from as u32, &mut buf)?; | 295 | let mut offset = from_page; |
| 244 | flash.erase(to as u32, (to + PAGE_SIZE) as u32)?; | 296 | for chunk in buf.chunks_mut(P::ACTIVE::BLOCK_SIZE) { |
| 245 | flash.write(to as u32, &buf)?; | 297 | p.active().flash().read(offset as u32, chunk)?; |
| 246 | self.update_progress(idx, flash)?; | 298 | offset += chunk.len(); |
| 299 | } | ||
| 300 | |||
| 301 | p.dfu() | ||
| 302 | .flash() | ||
| 303 | .erase(to_page as u32, (to_page + PAGE_SIZE) as u32)?; | ||
| 304 | |||
| 305 | let mut offset = to_page; | ||
| 306 | for chunk in buf.chunks(P::DFU::BLOCK_SIZE) { | ||
| 307 | p.dfu().flash().write(offset as u32, chunk)?; | ||
| 308 | offset += chunk.len(); | ||
| 309 | } | ||
| 310 | self.update_progress(idx, p.state())?; | ||
| 247 | } | 311 | } |
| 248 | Ok(()) | 312 | Ok(()) |
| 249 | } | 313 | } |
| 250 | 314 | ||
| 251 | fn swap<F: NorFlash + ReadNorFlash>(&mut self, flash: &mut F) -> Result<(), F::Error> { | 315 | fn swap<P: FlashProvider>(&mut self, p: &mut P) -> Result<(), BootError> { |
| 252 | let page_count = self.active.len() / PAGE_SIZE; | 316 | let page_count = self.active.len() / PAGE_SIZE; |
| 253 | // trace!("Page count: {}", page_count); | 317 | // trace!("Page count: {}", page_count); |
| 254 | for page in 0..page_count { | 318 | for page in 0..page_count { |
| 255 | // Copy active page to the 'next' DFU page. | 319 | // Copy active page to the 'next' DFU page. |
| 256 | let active_page = self.active_addr(page_count - 1 - page); | 320 | let active_page = self.active_addr(page_count - 1 - page); |
| 257 | let dfu_page = self.dfu_addr(page_count - page); | 321 | let dfu_page = self.dfu_addr(page_count - page); |
| 258 | // info!("Copy active {} to dfu {}", active_page, dfu_page); | 322 | info!("Copy active {} to dfu {}", active_page, dfu_page); |
| 259 | self.copy_page_once(page * 2, active_page, dfu_page, flash)?; | 323 | self.copy_page_once_to_dfu(page * 2, active_page, dfu_page, p)?; |
| 260 | 324 | ||
| 261 | // Copy DFU page to the active page | 325 | // Copy DFU page to the active page |
| 262 | let active_page = self.active_addr(page_count - 1 - page); | 326 | let active_page = self.active_addr(page_count - 1 - page); |
| 263 | let dfu_page = self.dfu_addr(page_count - 1 - page); | 327 | let dfu_page = self.dfu_addr(page_count - 1 - page); |
| 264 | //info!("Copy dfy {} to active {}", dfu_page, active_page); | 328 | info!("Copy dfy {} to active {}", dfu_page, active_page); |
| 265 | self.copy_page_once(page * 2 + 1, dfu_page, active_page, flash)?; | 329 | self.copy_page_once_to_active(page * 2 + 1, dfu_page, active_page, p)?; |
| 266 | } | 330 | } |
| 267 | 331 | ||
| 268 | Ok(()) | 332 | Ok(()) |
| 269 | } | 333 | } |
| 270 | 334 | ||
| 271 | fn revert<F: NorFlash + ReadNorFlash>(&mut self, flash: &mut F) -> Result<(), F::Error> { | 335 | fn revert<P: FlashProvider>(&mut self, p: &mut P) -> Result<(), BootError> { |
| 272 | let page_count = self.active.len() / PAGE_SIZE; | 336 | let page_count = self.active.len() / PAGE_SIZE; |
| 273 | for page in 0..page_count { | 337 | for page in 0..page_count { |
| 274 | // Copy the bad active page to the DFU page | 338 | // Copy the bad active page to the DFU page |
| 275 | let active_page = self.active_addr(page); | 339 | let active_page = self.active_addr(page); |
| 276 | let dfu_page = self.dfu_addr(page); | 340 | let dfu_page = self.dfu_addr(page); |
| 277 | self.copy_page_once(page_count * 2 + page * 2, active_page, dfu_page, flash)?; | 341 | self.copy_page_once_to_dfu(page_count * 2 + page * 2, active_page, dfu_page, p)?; |
| 278 | 342 | ||
| 279 | // Copy the DFU page back to the active page | 343 | // Copy the DFU page back to the active page |
| 280 | let active_page = self.active_addr(page); | 344 | let active_page = self.active_addr(page); |
| 281 | let dfu_page = self.dfu_addr(page + 1); | 345 | let dfu_page = self.dfu_addr(page + 1); |
| 282 | self.copy_page_once(page_count * 2 + page * 2 + 1, dfu_page, active_page, flash)?; | 346 | self.copy_page_once_to_active(page_count * 2 + page * 2 + 1, dfu_page, active_page, p)?; |
| 283 | } | 347 | } |
| 284 | 348 | ||
| 285 | Ok(()) | 349 | Ok(()) |
| 286 | } | 350 | } |
| 287 | 351 | ||
| 288 | fn read_state<F: ReadNorFlash>(&mut self, flash: &mut F) -> Result<State, BootError<F::Error>> { | 352 | fn read_state<P: FlashConfig>(&mut self, p: &mut P) -> Result<State, BootError> { |
| 289 | let mut magic: [u8; 4] = [0; 4]; | 353 | let mut magic: [u8; 4] = [0; 4]; |
| 354 | let flash = p.flash(); | ||
| 290 | flash.read(self.state.from as u32, &mut magic)?; | 355 | flash.read(self.state.from as u32, &mut magic)?; |
| 291 | 356 | ||
| 292 | match u32::from_le_bytes(magic) { | 357 | match u32::from_le_bytes(magic) { |
| @@ -296,6 +361,62 @@ impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> { | |||
| 296 | } | 361 | } |
| 297 | } | 362 | } |
| 298 | 363 | ||
| 364 | /// Convenience provider that uses a single flash for everything | ||
| 365 | pub struct SingleFlashProvider<'a, F> | ||
| 366 | where | ||
| 367 | F: NorFlash + ReadNorFlash, | ||
| 368 | { | ||
| 369 | config: SingleFlashConfig<'a, F>, | ||
| 370 | } | ||
| 371 | |||
| 372 | impl<'a, F> SingleFlashProvider<'a, F> | ||
| 373 | where | ||
| 374 | F: NorFlash + ReadNorFlash, | ||
| 375 | { | ||
| 376 | pub fn new(flash: &'a mut F) -> Self { | ||
| 377 | Self { | ||
| 378 | config: SingleFlashConfig { flash }, | ||
| 379 | } | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | pub struct SingleFlashConfig<'a, F> | ||
| 384 | where | ||
| 385 | F: NorFlash + ReadNorFlash, | ||
| 386 | { | ||
| 387 | flash: &'a mut F, | ||
| 388 | } | ||
| 389 | |||
| 390 | impl<'a, F> FlashProvider for SingleFlashProvider<'a, F> | ||
| 391 | where | ||
| 392 | F: NorFlash + ReadNorFlash, | ||
| 393 | { | ||
| 394 | type STATE = SingleFlashConfig<'a, F>; | ||
| 395 | type ACTIVE = SingleFlashConfig<'a, F>; | ||
| 396 | type DFU = SingleFlashConfig<'a, F>; | ||
| 397 | |||
| 398 | fn active(&mut self) -> &mut Self::STATE { | ||
| 399 | &mut self.config | ||
| 400 | } | ||
| 401 | fn dfu(&mut self) -> &mut Self::ACTIVE { | ||
| 402 | &mut self.config | ||
| 403 | } | ||
| 404 | fn state(&mut self) -> &mut Self::DFU { | ||
| 405 | &mut self.config | ||
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | impl<'a, F> FlashConfig for SingleFlashConfig<'a, F> | ||
| 410 | where | ||
| 411 | F: NorFlash + ReadNorFlash, | ||
| 412 | { | ||
| 413 | const BLOCK_SIZE: usize = F::ERASE_SIZE; | ||
| 414 | type FLASH = F; | ||
| 415 | fn flash(&mut self) -> &mut F { | ||
| 416 | self.flash | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 299 | /// FirmwareUpdater is an application API for interacting with the BootLoader without the ability to | 420 | /// FirmwareUpdater is an application API for interacting with the BootLoader without the ability to |
| 300 | /// 'mess up' the internal bootloader state | 421 | /// 'mess up' the internal bootloader state |
| 301 | pub struct FirmwareUpdater { | 422 | pub struct FirmwareUpdater { |
| @@ -371,7 +492,10 @@ impl FirmwareUpdater { | |||
| 371 | offset: usize, | 492 | offset: usize, |
| 372 | data: &[u8], | 493 | data: &[u8], |
| 373 | flash: &mut F, | 494 | flash: &mut F, |
| 495 | block_size: usize, | ||
| 374 | ) -> Result<(), F::Error> { | 496 | ) -> Result<(), F::Error> { |
| 497 | assert!(data.len() >= F::ERASE_SIZE); | ||
| 498 | |||
| 375 | trace!( | 499 | trace!( |
| 376 | "Writing firmware at offset 0x{:x} len {}", | 500 | "Writing firmware at offset 0x{:x} len {}", |
| 377 | self.dfu.from + offset, | 501 | self.dfu.from + offset, |
| @@ -384,7 +508,35 @@ impl FirmwareUpdater { | |||
| 384 | (self.dfu.from + offset + data.len()) as u32, | 508 | (self.dfu.from + offset + data.len()) as u32, |
| 385 | ) | 509 | ) |
| 386 | .await?; | 510 | .await?; |
| 387 | flash.write((self.dfu.from + offset) as u32, data).await | 511 | |
| 512 | trace!( | ||
| 513 | "Erased from {} to {}", | ||
| 514 | self.dfu.from + offset, | ||
| 515 | self.dfu.from + offset + data.len() | ||
| 516 | ); | ||
| 517 | |||
| 518 | let mut write_offset = self.dfu.from + offset; | ||
| 519 | for chunk in data.chunks(block_size) { | ||
| 520 | trace!("Wrote chunk at {}: {:?}", write_offset, chunk); | ||
| 521 | flash.write(write_offset as u32, chunk).await?; | ||
| 522 | write_offset += chunk.len(); | ||
| 523 | } | ||
| 524 | /* | ||
| 525 | trace!("Wrote data, reading back for verification"); | ||
| 526 | |||
| 527 | let mut buf: [u8; 4096] = [0; 4096]; | ||
| 528 | let mut data_offset = 0; | ||
| 529 | let mut read_offset = self.dfu.from + offset; | ||
| 530 | for chunk in buf.chunks_mut(block_size) { | ||
| 531 | flash.read(read_offset as u32, chunk).await?; | ||
| 532 | trace!("Read chunk at {}: {:?}", read_offset, chunk); | ||
| 533 | assert_eq!(&data[data_offset..data_offset + block_size], chunk); | ||
| 534 | read_offset += chunk.len(); | ||
| 535 | data_offset += chunk.len(); | ||
| 536 | } | ||
| 537 | */ | ||
| 538 | |||
| 539 | Ok(()) | ||
| 388 | } | 540 | } |
| 389 | } | 541 | } |
| 390 | 542 | ||
diff --git a/embassy-boot/nrf/.cargo/config.toml b/embassy-boot/nrf/.cargo/config.toml index c3957b866..27bc9708c 100644 --- a/embassy-boot/nrf/.cargo/config.toml +++ b/embassy-boot/nrf/.cargo/config.toml | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | [unstable] | 1 | [unstable] |
| 2 | namespaced-features = true | ||
| 3 | build-std = ["core"] | 2 | build-std = ["core"] |
| 4 | build-std-features = ["panic_immediate_abort"] | 3 | build-std-features = ["panic_immediate_abort"] |
| 5 | 4 | ||
diff --git a/embassy-boot/nrf/Cargo.toml b/embassy-boot/nrf/Cargo.toml index 512e7d378..97207ac29 100644 --- a/embassy-boot/nrf/Cargo.toml +++ b/embassy-boot/nrf/Cargo.toml | |||
| @@ -12,7 +12,7 @@ defmt = { version = "0.3", optional = true } | |||
| 12 | defmt-rtt = { version = "0.3", optional = true } | 12 | defmt-rtt = { version = "0.3", optional = true } |
| 13 | 13 | ||
| 14 | embassy = { path = "../../embassy", default-features = false } | 14 | embassy = { path = "../../embassy", default-features = false } |
| 15 | embassy-nrf = { path = "../../embassy-nrf", default-features = false } | 15 | embassy-nrf = { path = "../../embassy-nrf", default-features = false, features = ["nightly"] } |
| 16 | embassy-boot = { path = "../boot", default-features = false } | 16 | embassy-boot = { path = "../boot", default-features = false } |
| 17 | cortex-m = { version = "0.7" } | 17 | cortex-m = { version = "0.7" } |
| 18 | cortex-m-rt = { version = "0.7" } | 18 | cortex-m-rt = { version = "0.7" } |
diff --git a/embassy-boot/nrf/src/lib.rs b/embassy-boot/nrf/src/lib.rs index 32250b2db..785cb67e8 100644 --- a/embassy-boot/nrf/src/lib.rs +++ b/embassy-boot/nrf/src/lib.rs | |||
| @@ -4,7 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | mod fmt; | 5 | mod fmt; |
| 6 | 6 | ||
| 7 | pub use embassy_boot::{FirmwareUpdater, Partition, State, BOOT_MAGIC}; | 7 | pub use embassy_boot::{ |
| 8 | FirmwareUpdater, FlashProvider, Partition, SingleFlashProvider, State, BOOT_MAGIC, | ||
| 9 | }; | ||
| 8 | use embassy_nrf::{ | 10 | use embassy_nrf::{ |
| 9 | nvmc::{Nvmc, PAGE_SIZE}, | 11 | nvmc::{Nvmc, PAGE_SIZE}, |
| 10 | peripherals::WDT, | 12 | peripherals::WDT, |
| @@ -62,7 +64,7 @@ impl BootLoader { | |||
| 62 | } | 64 | } |
| 63 | 65 | ||
| 64 | /// Boots the application without softdevice mechanisms | 66 | /// Boots the application without softdevice mechanisms |
| 65 | pub fn prepare<F: NorFlash + ReadNorFlash>(&mut self, flash: &mut F) -> usize { | 67 | pub fn prepare<F: FlashProvider>(&mut self, flash: &mut F) -> usize { |
| 66 | match self.boot.prepare_boot(flash) { | 68 | match self.boot.prepare_boot(flash) { |
| 67 | Ok(_) => self.boot.boot_address(), | 69 | Ok(_) => self.boot.boot_address(), |
| 68 | Err(_) => panic!("boot prepare error!"), | 70 | Err(_) => panic!("boot prepare error!"), |
diff --git a/embassy-boot/nrf/src/main.rs b/embassy-boot/nrf/src/main.rs index cd264d4c2..63de7c869 100644 --- a/embassy-boot/nrf/src/main.rs +++ b/embassy-boot/nrf/src/main.rs | |||
| @@ -22,7 +22,11 @@ fn main() -> ! { | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | let mut bl = BootLoader::default(); | 24 | let mut bl = BootLoader::default(); |
| 25 | let start = bl.prepare(&mut WatchdogFlash::start(Nvmc::new(p.NVMC), p.WDT, 5)); | 25 | let start = bl.prepare(&mut SingleFlashProvider::new(&mut WatchdogFlash::start( |
| 26 | Nvmc::new(p.NVMC), | ||
| 27 | p.WDT, | ||
| 28 | 5, | ||
| 29 | ))); | ||
| 26 | unsafe { bl.load(start) } | 30 | unsafe { bl.load(start) } |
| 27 | } | 31 | } |
| 28 | 32 | ||
