aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/flash/f4.rs66
-rw-r--r--embassy-stm32/src/flash/mod.rs2
-rw-r--r--examples/stm32f4/src/bin/flash.rs27
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};
7use crate::flash::Error; 7use crate::flash::Error;
8use crate::pac; 8use crate::pac;
9 9
10// Only available on some devices
11const SECOND_BANK_OFFSET: usize = FLASH_SIZE / 2;
12const SECOND_BANK_SECTOR_START: u32 = 12; 10const SECOND_BANK_SECTOR_START: u32 = 12;
13 11
14unsafe fn is_dual_bank() -> bool { 12unsafe 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
71unsafe fn get_sector(addr: u32) -> u8 { 69struct FlashSector {
70 index: u8,
71 size: u32,
72}
73
74fn 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
100pub(crate) unsafe fn blocking_erase(from: u32, to: u32) -> Result<(), Error> { 107pub(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
5use defmt::{info, unwrap}; 5use defmt::{info, unwrap};
6use embassy::executor::Spawner; 6use embassy::executor::Spawner;
7use embassy::time::{Duration, Timer};
8use embassy_stm32::flash::Flash; 7use embassy_stm32::flash::Flash;
9use embassy_stm32::Peripherals; 8use embassy_stm32::Peripherals;
10use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; 9use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
@@ -14,29 +13,37 @@ use {defmt_rtt as _, panic_probe as _};
14async fn main(_spawner: Spawner, p: Peripherals) { 13async 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
28fn 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[..],