diff options
| author | Rasmus Melchior Jacobsen <[email protected]> | 2023-04-04 21:09:30 +0200 |
|---|---|---|
| committer | Rasmus Melchior Jacobsen <[email protected]> | 2023-04-04 21:09:30 +0200 |
| commit | 25577e0eafd8a3d4ffaa4b8f17cb55399fd58038 (patch) | |
| tree | 8e465872041cd22d1f15c2fd81cd43063d1d1a58 /embassy-boot/boot/src/boot_loader.rs | |
| parent | 9242ad89d436422fd5abdafadb2faf845e730a16 (diff) | |
Assert active and dfu have same erase size and copy in smaller chunks
The copy from active to dfu (and vice versa) is now done in smaller portions depending on aligned_buf, which now does not need to be erase_size big.
Diffstat (limited to 'embassy-boot/boot/src/boot_loader.rs')
| -rw-r--r-- | embassy-boot/boot/src/boot_loader.rs | 66 |
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. |
| 34 | pub trait Flash: NorFlash { | 34 | pub 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`]. | ||
| 43 | pub trait FlashConfig { | 42 | pub 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 | ||
| 63 | impl<T: FlashConfig> FlashConfigEx for T { | 62 | impl<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. | ||
| 71 | pub struct BootLoader { | 70 | pub 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. |
| 392 | pub struct BootFlash<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8 = 0xFF> | 389 | pub struct BootFlash<F, const ERASE_VALUE: u8 = 0xFF> |
| 393 | where | 390 | where |
| 394 | F: NorFlash + ReadNorFlash, | 391 | F: NorFlash + ReadNorFlash, |
| 395 | { | 392 | { |
| 396 | flash: F, | 393 | flash: F, |
| 397 | } | 394 | } |
| 398 | 395 | ||
| 399 | impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> BootFlash<F, BLOCK_SIZE, ERASE_VALUE> | 396 | impl<F, const ERASE_VALUE: u8> BootFlash<F, ERASE_VALUE> |
| 400 | where | 397 | where |
| 401 | F: NorFlash + ReadNorFlash, | 398 | F: NorFlash + ReadNorFlash, |
| 402 | { | 399 | { |
| @@ -406,22 +403,21 @@ where | |||
| 406 | } | 403 | } |
| 407 | } | 404 | } |
| 408 | 405 | ||
| 409 | impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> Flash for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> | 406 | impl<F, const ERASE_VALUE: u8> Flash for BootFlash<F, ERASE_VALUE> |
| 410 | where | 407 | where |
| 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 | ||
| 417 | impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> ErrorType for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> | 413 | impl<F, const ERASE_VALUE: u8> ErrorType for BootFlash<F, ERASE_VALUE> |
| 418 | where | 414 | where |
| 419 | F: ReadNorFlash + NorFlash, | 415 | F: ReadNorFlash + NorFlash, |
| 420 | { | 416 | { |
| 421 | type Error = F::Error; | 417 | type Error = F::Error; |
| 422 | } | 418 | } |
| 423 | 419 | ||
| 424 | impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> NorFlash for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> | 420 | impl<F, const ERASE_VALUE: u8> NorFlash for BootFlash<F, ERASE_VALUE> |
| 425 | where | 421 | where |
| 426 | F: ReadNorFlash + NorFlash, | 422 | F: ReadNorFlash + NorFlash, |
| 427 | { | 423 | { |
| @@ -437,7 +433,7 @@ where | |||
| 437 | } | 433 | } |
| 438 | } | 434 | } |
| 439 | 435 | ||
| 440 | impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> ReadNorFlash for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> | 436 | impl<F, const ERASE_VALUE: u8> ReadNorFlash for BootFlash<F, ERASE_VALUE> |
| 441 | where | 437 | where |
| 442 | F: ReadNorFlash + NorFlash, | 438 | F: ReadNorFlash + NorFlash, |
| 443 | { | 439 | { |
