aboutsummaryrefslogtreecommitdiff
path: root/embassy-boot/boot/src/boot_loader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-boot/boot/src/boot_loader.rs')
-rw-r--r--embassy-boot/boot/src/boot_loader.rs66
1 files changed, 31 insertions, 35 deletions
diff --git a/embassy-boot/boot/src/boot_loader.rs b/embassy-boot/boot/src/boot_loader.rs
index 698075599..db067da5b 100644
--- a/embassy-boot/boot/src/boot_loader.rs
+++ b/embassy-boot/boot/src/boot_loader.rs
@@ -32,14 +32,13 @@ where
32 32
33/// Extension of the embedded-storage flash type information with block size and erase value. 33/// Extension of the embedded-storage flash type information with block size and erase value.
34pub trait Flash: NorFlash { 34pub trait Flash: NorFlash {
35 /// The block size that should be used when writing to flash. For most builtin flashes, this is the same as the erase
36 /// size of the flash, but for external QSPI flash modules, this can be lower.
37 const BLOCK_SIZE: usize;
38 /// The erase value of the flash. Typically the default of 0xFF is used, but some flashes use a different value. 35 /// The erase value of the flash. Typically the default of 0xFF is used, but some flashes use a different value.
39 const ERASE_VALUE: u8 = 0xFF; 36 const ERASE_VALUE: u8 = 0xFF;
40} 37}
41 38
42/// Trait defining the flash handles used for active and DFU partition 39/// Trait defining the flash handles used for active and DFU partition.
40/// The ACTIVE and DFU erase sizes must be equal. If this is not the case, then consider adding an adapter for the
41/// smallest flash to increase its erase size such that they match. See e.g. [`crate::large_erase::LargeErase`].
43pub trait FlashConfig { 42pub trait FlashConfig {
44 /// Flash type used for the state partition. 43 /// Flash type used for the state partition.
45 type STATE: Flash; 44 type STATE: Flash;
@@ -62,12 +61,12 @@ trait FlashConfigEx {
62 61
63impl<T: FlashConfig> FlashConfigEx for T { 62impl<T: FlashConfig> FlashConfigEx for T {
64 fn page_size() -> usize { 63 fn page_size() -> usize {
65 core::cmp::max(T::ACTIVE::ERASE_SIZE, T::DFU::ERASE_SIZE) 64 assert_eq!(T::ACTIVE::ERASE_SIZE, T::DFU::ERASE_SIZE);
65 T::ACTIVE::ERASE_SIZE
66 } 66 }
67} 67}
68 68
69/// BootLoader works with any flash implementing embedded_storage and can also work with 69/// BootLoader works with any flash implementing embedded_storage.
70/// different page sizes and flash write sizes.
71pub struct BootLoader { 70pub struct BootLoader {
72 // Page with current state of bootloader. The state partition has the following format: 71 // Page with current state of bootloader. The state partition has the following format:
73 // All ranges are in multiples of WRITE_SIZE bytes. 72 // All ranges are in multiples of WRITE_SIZE bytes.
@@ -184,7 +183,9 @@ impl BootLoader {
184 /// 183 ///
185 pub fn prepare_boot<P: FlashConfig>(&mut self, p: &mut P, aligned_buf: &mut [u8]) -> Result<State, BootError> { 184 pub fn prepare_boot<P: FlashConfig>(&mut self, p: &mut P, aligned_buf: &mut [u8]) -> Result<State, BootError> {
186 // Ensure we have enough progress pages to store copy progress 185 // Ensure we have enough progress pages to store copy progress
187 assert_eq!(aligned_buf.len(), P::page_size()); 186 assert_eq!(0, P::page_size() % aligned_buf.len());
187 assert_eq!(0, P::page_size() % P::ACTIVE::WRITE_SIZE);
188 assert_eq!(0, P::page_size() % P::DFU::WRITE_SIZE);
188 assert!(aligned_buf.len() >= P::STATE::WRITE_SIZE); 189 assert!(aligned_buf.len() >= P::STATE::WRITE_SIZE);
189 assert_partitions(self.active, self.dfu, self.state, P::page_size(), P::STATE::WRITE_SIZE); 190 assert_partitions(self.active, self.dfu, self.state, P::page_size(), P::STATE::WRITE_SIZE);
190 191
@@ -277,20 +278,18 @@ impl BootLoader {
277 aligned_buf: &mut [u8], 278 aligned_buf: &mut [u8],
278 ) -> Result<(), BootError> { 279 ) -> Result<(), BootError> {
279 if self.current_progress(p, aligned_buf)? <= idx { 280 if self.current_progress(p, aligned_buf)? <= idx {
280 let mut offset = from_offset; 281 let page_size = P::page_size() as u32;
281 for chunk in aligned_buf.chunks_mut(P::DFU::BLOCK_SIZE) {
282 self.dfu.read_blocking(p.dfu(), offset, chunk)?;
283 offset += chunk.len() as u32;
284 }
285 282
286 self.active 283 self.active
287 .erase_blocking(p.active(), to_offset, to_offset + P::page_size() as u32)?; 284 .erase_blocking(p.active(), to_offset, to_offset + page_size)?;
288 285
289 let mut offset = to_offset; 286 for offset_in_page in (0..page_size).step_by(aligned_buf.len()) {
290 for chunk in aligned_buf.chunks(P::ACTIVE::BLOCK_SIZE) { 287 self.dfu
291 self.active.write_blocking(p.active(), offset, chunk)?; 288 .read_blocking(p.dfu(), from_offset + offset_in_page as u32, aligned_buf)?;
292 offset += chunk.len() as u32; 289 self.active
290 .write_blocking(p.active(), to_offset + offset_in_page as u32, aligned_buf)?;
293 } 291 }
292
294 self.update_progress(idx, p, aligned_buf)?; 293 self.update_progress(idx, p, aligned_buf)?;
295 } 294 }
296 Ok(()) 295 Ok(())
@@ -305,20 +304,18 @@ impl BootLoader {
305 aligned_buf: &mut [u8], 304 aligned_buf: &mut [u8],
306 ) -> Result<(), BootError> { 305 ) -> Result<(), BootError> {
307 if self.current_progress(p, aligned_buf)? <= idx { 306 if self.current_progress(p, aligned_buf)? <= idx {
308 let mut offset = from_offset; 307 let page_size = P::page_size() as u32;
309 for chunk in aligned_buf.chunks_mut(P::ACTIVE::BLOCK_SIZE) {
310 self.active.read_blocking(p.active(), offset, chunk)?;
311 offset += chunk.len() as u32;
312 }
313 308
314 self.dfu 309 self.dfu
315 .erase_blocking(p.dfu(), to_offset as u32, to_offset + P::page_size() as u32)?; 310 .erase_blocking(p.dfu(), to_offset as u32, to_offset + page_size)?;
316 311
317 let mut offset = to_offset; 312 for offset_in_page in (0..page_size).step_by(aligned_buf.len()) {
318 for chunk in aligned_buf.chunks(P::DFU::BLOCK_SIZE) { 313 self.active
319 self.dfu.write_blocking(p.dfu(), offset, chunk)?; 314 .read_blocking(p.active(), from_offset + offset_in_page as u32, aligned_buf)?;
320 offset += chunk.len() as u32; 315 self.dfu
316 .write_blocking(p.dfu(), to_offset + offset_in_page as u32, aligned_buf)?;
321 } 317 }
318
322 self.update_progress(idx, p, aligned_buf)?; 319 self.update_progress(idx, p, aligned_buf)?;
323 } 320 }
324 Ok(()) 321 Ok(())
@@ -389,14 +386,14 @@ fn assert_partitions(active: Partition, dfu: Partition, state: Partition, page_s
389} 386}
390 387
391/// A flash wrapper implementing the Flash and embedded_storage traits. 388/// A flash wrapper implementing the Flash and embedded_storage traits.
392pub struct BootFlash<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8 = 0xFF> 389pub struct BootFlash<F, const ERASE_VALUE: u8 = 0xFF>
393where 390where
394 F: NorFlash + ReadNorFlash, 391 F: NorFlash + ReadNorFlash,
395{ 392{
396 flash: F, 393 flash: F,
397} 394}
398 395
399impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> BootFlash<F, BLOCK_SIZE, ERASE_VALUE> 396impl<F, const ERASE_VALUE: u8> BootFlash<F, ERASE_VALUE>
400where 397where
401 F: NorFlash + ReadNorFlash, 398 F: NorFlash + ReadNorFlash,
402{ 399{
@@ -406,22 +403,21 @@ where
406 } 403 }
407} 404}
408 405
409impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> Flash for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> 406impl<F, const ERASE_VALUE: u8> Flash for BootFlash<F, ERASE_VALUE>
410where 407where
411 F: NorFlash + ReadNorFlash, 408 F: NorFlash + ReadNorFlash,
412{ 409{
413 const BLOCK_SIZE: usize = BLOCK_SIZE;
414 const ERASE_VALUE: u8 = ERASE_VALUE; 410 const ERASE_VALUE: u8 = ERASE_VALUE;
415} 411}
416 412
417impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> ErrorType for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> 413impl<F, const ERASE_VALUE: u8> ErrorType for BootFlash<F, ERASE_VALUE>
418where 414where
419 F: ReadNorFlash + NorFlash, 415 F: ReadNorFlash + NorFlash,
420{ 416{
421 type Error = F::Error; 417 type Error = F::Error;
422} 418}
423 419
424impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> NorFlash for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> 420impl<F, const ERASE_VALUE: u8> NorFlash for BootFlash<F, ERASE_VALUE>
425where 421where
426 F: ReadNorFlash + NorFlash, 422 F: ReadNorFlash + NorFlash,
427{ 423{
@@ -437,7 +433,7 @@ where
437 } 433 }
438} 434}
439 435
440impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> ReadNorFlash for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> 436impl<F, const ERASE_VALUE: u8> ReadNorFlash for BootFlash<F, ERASE_VALUE>
441where 437where
442 F: ReadNorFlash + NorFlash, 438 F: ReadNorFlash + NorFlash,
443{ 439{