aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-07-15 06:19:05 +0000
committerGitHub <[email protected]>2022-07-15 06:19:05 +0000
commit9d388d357aefcb87677a70716e727bc91933191a (patch)
tree772ab06aa35aadd14b37f52baf62e97ac4ead287
parent5318fe404bed68a38a1d81eb7359ebc38e6fad15 (diff)
parent0b70cc554ed7fef7dc1c720c3d5e634039dd729a (diff)
Merge #866
866: F4 flash fixes r=Dirbaio a=chemicstry This discontinuous flash sector layout is too cursed and I left some mistakes in last PR. Erasing last sector did not work and it wasn't possible to erase between memory banks for 1MB dual-bank devices. So I changed the erase function to iterate over memory addresses (which is continuous) instead of sector numbers. It should also be possible to implement erase across memory banks for H7, but it requires special handling for write too. I don't have an H7 to test now so left it as is. I wasn't sure how to add tests to `embassy-stm32` and it seems that there are none, except for `subghz`, but no test runner? Anyway, I tested the `get_sector` on playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=13b59339fe6c70a3249e6183e81f869e Also fixed erase alignment requirements on `Flash::blocking_erase()`, as it previously only checked alignment on size, but not on offsets. P.S. the diff is a bit messed up, I recommend looking at files directly Co-authored-by: chemicstry <[email protected]>
-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[..],