diff options
| -rw-r--r-- | embassy-stm32/src/flash/f4.rs | 66 | ||||
| -rw-r--r-- | embassy-stm32/src/flash/mod.rs | 2 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/flash.rs | 27 |
3 files changed, 55 insertions, 40 deletions
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index f6dc7e955..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 | 89 | }; |
| 92 | } else { | 90 | |
| 93 | offset / (ERASE_SIZE as u32 / 8) | 91 | // First 4 sectors are 16KB, then one 64KB, and rest are 128KB |
| 94 | } | 92 | let size = match index_in_bank { |
| 93 | 0..=3 => 16 * 1024, | ||
| 94 | 4 => 64 * 1024, | ||
| 95 | _ => 128 * 1024, | ||
| 95 | }; | 96 | }; |
| 96 | 97 | ||
| 97 | sector as u8 | 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); | 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(()) |
| @@ -115,6 +121,8 @@ unsafe fn erase_sector(sector: u8) -> Result<(), Error> { | |||
| 115 | let bank = sector / SECOND_BANK_SECTOR_START as u8; | 121 | let bank = sector / SECOND_BANK_SECTOR_START as u8; |
| 116 | let snb = (bank << 4) + (sector % SECOND_BANK_SECTOR_START as u8); | 122 | let snb = (bank << 4) + (sector % SECOND_BANK_SECTOR_START as u8); |
| 117 | 123 | ||
| 124 | trace!("Erasing sector: {}", sector); | ||
| 125 | |||
| 118 | pac::FLASH.cr().modify(|w| { | 126 | pac::FLASH.cr().modify(|w| { |
| 119 | w.set_ser(true); | 127 | w.set_ser(true); |
| 120 | w.set_snb(snb) | 128 | w.set_snb(snb) |
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 59ca59f65..2047f70e1 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs | |||
| @@ -72,7 +72,7 @@ impl<'d> Flash<'d> { | |||
| 72 | if to < from || to as usize > FLASH_END { | 72 | if to < from || to as usize > FLASH_END { |
| 73 | return Err(Error::Size); | 73 | return Err(Error::Size); |
| 74 | } | 74 | } |
| 75 | if ((to - from) as usize % ERASE_SIZE) != 0 { | 75 | if (from as usize % ERASE_SIZE) != 0 || (to as usize % ERASE_SIZE) != 0 { |
| 76 | return Err(Error::Unaligned); | 76 | return Err(Error::Unaligned); |
| 77 | } | 77 | } |
| 78 | 78 | ||
diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index b531d6f13..13fd2c90b 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::{info, unwrap}; | 5 | use defmt::{info, unwrap}; |
| 6 | use embassy::executor::Spawner; | 6 | use embassy::executor::Spawner; |
| 7 | use embassy::time::{Duration, Timer}; | ||
| 8 | use embassy_stm32::flash::Flash; | 7 | use embassy_stm32::flash::Flash; |
| 9 | use embassy_stm32::Peripherals; | 8 | use embassy_stm32::Peripherals; |
| 10 | use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; | 9 | use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; |
| @@ -14,29 +13,37 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 14 | async fn main(_spawner: Spawner, p: Peripherals) { | 13 | async fn main(_spawner: Spawner, p: Peripherals) { |
| 15 | info!("Hello Flash!"); | 14 | info!("Hello Flash!"); |
| 16 | 15 | ||
| 17 | const ADDR: u32 = 0x10_0000; | 16 | let mut f = Flash::unlock(p.FLASH); |
| 18 | 17 | ||
| 19 | // wait a bit before accessing the flash | 18 | // Sector 5 |
| 20 | Timer::after(Duration::from_millis(300)).await; | 19 | test_flash(&mut f, 128 * 1024, 128 * 1024); |
| 21 | 20 | ||
| 22 | let mut f = Flash::unlock(p.FLASH); | 21 | // Sectors 11..=16, across banks (128K, 16K, 16K, 16K, 16K, 64K) |
| 22 | test_flash(&mut f, (1024 - 128) * 1024, 256 * 1024); | ||
| 23 | |||
| 24 | // Sectors 23, last in bank 2 | ||
| 25 | test_flash(&mut f, (2048 - 128) * 1024, 128 * 1024); | ||
| 26 | } | ||
| 27 | |||
| 28 | fn test_flash(f: &mut Flash, offset: u32, size: u32) { | ||
| 29 | info!("Testing offset: {=u32:#X}, size: {=u32:#X}", offset, size); | ||
| 23 | 30 | ||
| 24 | info!("Reading..."); | 31 | info!("Reading..."); |
| 25 | let mut buf = [0u8; 32]; | 32 | let mut buf = [0u8; 32]; |
| 26 | unwrap!(f.read(ADDR, &mut buf)); | 33 | unwrap!(f.read(offset, &mut buf)); |
| 27 | info!("Read: {=[u8]:x}", buf); | 34 | info!("Read: {=[u8]:x}", buf); |
| 28 | 35 | ||
| 29 | info!("Erasing..."); | 36 | info!("Erasing..."); |
| 30 | unwrap!(f.erase(ADDR, ADDR + 128 * 1024)); | 37 | unwrap!(f.erase(offset, offset + size)); |
| 31 | 38 | ||
| 32 | info!("Reading..."); | 39 | info!("Reading..."); |
| 33 | let mut buf = [0u8; 32]; | 40 | let mut buf = [0u8; 32]; |
| 34 | unwrap!(f.read(ADDR, &mut buf)); | 41 | unwrap!(f.read(offset, &mut buf)); |
| 35 | info!("Read after erase: {=[u8]:x}", buf); | 42 | info!("Read after erase: {=[u8]:x}", buf); |
| 36 | 43 | ||
| 37 | info!("Writing..."); | 44 | info!("Writing..."); |
| 38 | unwrap!(f.write( | 45 | unwrap!(f.write( |
| 39 | ADDR, | 46 | offset, |
| 40 | &[ | 47 | &[ |
| 41 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, | 48 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, |
| 42 | 30, 31, 32 | 49 | 30, 31, 32 |
| @@ -45,7 +52,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 45 | 52 | ||
| 46 | info!("Reading..."); | 53 | info!("Reading..."); |
| 47 | let mut buf = [0u8; 32]; | 54 | let mut buf = [0u8; 32]; |
| 48 | unwrap!(f.read(ADDR, &mut buf)); | 55 | unwrap!(f.read(offset, &mut buf)); |
| 49 | info!("Read: {=[u8]:x}", buf); | 56 | info!("Read: {=[u8]:x}", buf); |
| 50 | assert_eq!( | 57 | assert_eq!( |
| 51 | &buf[..], | 58 | &buf[..], |
