diff options
| author | chemicstry <[email protected]> | 2022-07-14 20:58:01 +0300 |
|---|---|---|
| committer | chemicstry <[email protected]> | 2022-07-14 20:58:01 +0300 |
| commit | 5a265661bb432de4d91a50f6250afde696b7f0f3 (patch) | |
| tree | bc5ea99d2c47572e9745cb89bc7663757e9cd6ee | |
| parent | 039acda3a8b9549a6056aafdc4344ea4c76b9f60 (diff) | |
Fix erasing across banks
| -rw-r--r-- | embassy-stm32/src/flash/f4.rs | 64 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/flash.rs | 8 |
2 files changed, 38 insertions, 34 deletions
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index ad71f145c..b8327ce4e 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs | |||
| @@ -7,8 +7,6 @@ use super::{ERASE_SIZE, FLASH_BASE, FLASH_SIZE}; | |||
| 7 | use crate::flash::Error; | 7 | use crate::flash::Error; |
| 8 | use crate::pac; | 8 | use crate::pac; |
| 9 | 9 | ||
| 10 | // Only available on some devices | ||
| 11 | const SECOND_BANK_OFFSET: usize = FLASH_SIZE / 2; | ||
| 12 | const SECOND_BANK_SECTOR_START: u32 = 12; | 10 | const SECOND_BANK_SECTOR_START: u32 = 12; |
| 13 | 11 | ||
| 14 | unsafe fn is_dual_bank() -> bool { | 12 | unsafe fn is_dual_bank() -> bool { |
| @@ -68,44 +66,52 @@ pub(crate) unsafe fn blocking_write(offset: u32, buf: &[u8]) -> Result<(), Error | |||
| 68 | ret | 66 | ret |
| 69 | } | 67 | } |
| 70 | 68 | ||
| 71 | unsafe fn get_sector(addr: u32) -> u8 { | 69 | struct FlashSector { |
| 70 | index: u8, | ||
| 71 | size: u32, | ||
| 72 | } | ||
| 73 | |||
| 74 | fn get_sector(addr: u32, dual_bank: bool) -> FlashSector { | ||
| 72 | let offset = addr - FLASH_BASE as u32; | 75 | let offset = addr - FLASH_BASE as u32; |
| 73 | 76 | ||
| 74 | let sector = if is_dual_bank() { | 77 | let bank_size = match dual_bank { |
| 75 | let bank = offset / SECOND_BANK_OFFSET as u32; | 78 | true => FLASH_SIZE / 2, |
| 76 | let offset_in_bank = offset % SECOND_BANK_OFFSET as u32; | 79 | false => FLASH_SIZE, |
| 80 | } as u32; | ||
| 77 | 81 | ||
| 78 | let sector_in_bank = if offset_in_bank >= ERASE_SIZE as u32 / 2 { | 82 | let bank = offset / bank_size; |
| 79 | 4 + offset_in_bank / ERASE_SIZE as u32 | 83 | let offset_in_bank = offset % bank_size; |
| 80 | } else { | ||
| 81 | offset_in_bank / (ERASE_SIZE as u32 / 8) | ||
| 82 | }; | ||
| 83 | 84 | ||
| 84 | if bank == 1 { | 85 | let index_in_bank = if offset_in_bank >= ERASE_SIZE as u32 / 2 { |
| 85 | SECOND_BANK_SECTOR_START + sector_in_bank | 86 | 4 + offset_in_bank / ERASE_SIZE as u32 |
| 86 | } else { | ||
| 87 | sector_in_bank | ||
| 88 | } | ||
| 89 | } else { | 87 | } else { |
| 90 | if offset >= ERASE_SIZE as u32 / 2 { | 88 | offset_in_bank / (ERASE_SIZE as u32 / 8) |
| 91 | 4 + offset / ERASE_SIZE as u32 | ||
| 92 | } else { | ||
| 93 | offset / (ERASE_SIZE as u32 / 8) | ||
| 94 | } | ||
| 95 | }; | 89 | }; |
| 96 | 90 | ||
| 97 | sector as u8 | 91 | // First 4 sectors are 16KB, then one 64KB, and rest are 128KB |
| 92 | let size = match index_in_bank { | ||
| 93 | 0..=3 => 16 * 1024, | ||
| 94 | 4 => 64 * 1024, | ||
| 95 | _ => 128 * 1024, | ||
| 96 | }; | ||
| 97 | |||
| 98 | let index = if bank == 1 { | ||
| 99 | SECOND_BANK_SECTOR_START + index_in_bank | ||
| 100 | } else { | ||
| 101 | index_in_bank | ||
| 102 | } as u8; | ||
| 103 | |||
| 104 | FlashSector { index, size } | ||
| 98 | } | 105 | } |
| 99 | 106 | ||
| 100 | pub(crate) unsafe fn blocking_erase(from: u32, to: u32) -> Result<(), Error> { | 107 | pub(crate) unsafe fn blocking_erase(from: u32, to: u32) -> Result<(), Error> { |
| 101 | let start_sector = get_sector(from); | 108 | let mut addr = from; |
| 102 | let end_sector = get_sector(to - 1); // end range is exclusive | 109 | let dual_bank = is_dual_bank(); |
| 103 | 110 | ||
| 104 | for sector in start_sector..=end_sector { | 111 | while addr < to { |
| 105 | let ret = erase_sector(sector as u8); | 112 | let sector = get_sector(addr, dual_bank); |
| 106 | if ret.is_err() { | 113 | erase_sector(sector.index)?; |
| 107 | return ret; | 114 | addr += sector.size; |
| 108 | } | ||
| 109 | } | 115 | } |
| 110 | 116 | ||
| 111 | Ok(()) | 117 | Ok(()) |
diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index ad45df825..265072aea 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs | |||
| @@ -7,6 +7,7 @@ use embassy::executor::Spawner; | |||
| 7 | use embassy::time::{Duration, Timer}; | 7 | use embassy::time::{Duration, Timer}; |
| 8 | use embassy_stm32::flash::Flash; | 8 | use embassy_stm32::flash::Flash; |
| 9 | use embassy_stm32::Peripherals; | 9 | use embassy_stm32::Peripherals; |
| 10 | use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 12 | ||
| 12 | #[embassy::main] | 13 | #[embassy::main] |
| @@ -18,11 +19,8 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 18 | // Sector 5 | 19 | // Sector 5 |
| 19 | test_flash(&mut f, 128 * 1024, 128 * 1024); | 20 | test_flash(&mut f, 128 * 1024, 128 * 1024); |
| 20 | 21 | ||
| 21 | // Sector 11, last in bank 1 | 22 | // Sectors 11..=16, across banks (128K, 16K, 16K, 16K, 16K, 64K) |
| 22 | test_flash(&mut f, (1024 - 128) * 1024, 128 * 1024); | 23 | test_flash(&mut f, (1024 - 128) * 1024, 256 * 1024); |
| 23 | |||
| 24 | // Sectors 12..=16, start of bank 2 (16K, 16K, 16K, 16K, 64K) | ||
| 25 | test_flash(&mut f, 1024 * 1024, 128 * 1024); | ||
| 26 | 24 | ||
| 27 | // Sectors 23, last in bank 2 | 25 | // Sectors 23, last in bank 2 |
| 28 | test_flash(&mut f, (2048 - 128) * 1024, 128 * 1024); | 26 | test_flash(&mut f, (2048 - 128) * 1024, 128 * 1024); |
