From e7129371d0d543394c070671490a796ddbb10e3f Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 30 Mar 2023 08:32:36 +0200 Subject: [PATCH] Let sector computation be shared across families --- ci.sh | 1 + embassy-stm32/build.rs | 13 +++ embassy-stm32/src/flash/common.rs | 35 +++++- embassy-stm32/src/flash/f3.rs | 16 +-- embassy-stm32/src/flash/f4.rs | 181 ++++++++++++------------------ embassy-stm32/src/flash/f7.rs | 95 +++++++++------- embassy-stm32/src/flash/h7.rs | 21 ++-- embassy-stm32/src/flash/l.rs | 18 +-- embassy-stm32/src/flash/mod.rs | 15 ++- embassy-stm32/src/flash/other.rs | 12 +- 10 files changed, 208 insertions(+), 199 deletions(-) diff --git a/ci.sh b/ci.sh index d86c93520..b9dddad3a 100755 --- a/ci.sh +++ b/ci.sh @@ -49,6 +49,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f411ce,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f413vh,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f429zi,log,exti,time-driver-any,unstable-traits,embedded-sdmmc \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f730i8,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h755zi-cm7,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32h7b3ai,defmt,exti,time-driver-any,unstable-traits \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32l476vg,defmt,exti,time-driver-any,unstable-traits \ diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 6b203a3f1..007409242 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -113,6 +113,18 @@ fn main() { .collect(); for region in flash_memory_regions.iter() { let region_name = format_ident!("{}", get_flash_region_name(region.name)); + let bank = format_ident!( + "{}", + if region.name.starts_with("BANK_1") { + "Bank1" + } else if region.name.starts_with("BANK_2") { + "Bank2" + } else if region.name == "OTP" { + "Otp" + } else { + unimplemented!() + } + ); let base = region.address; let size = region.size; let settings = region.settings.as_ref().unwrap(); @@ -122,6 +134,7 @@ fn main() { flash_regions.extend(quote! { pub const #region_name: crate::flash::FlashRegion = crate::flash::FlashRegion { + bank: crate::flash::FlashBank::#bank, base: #base, size: #size, erase_size: #erase_size, diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 6534e1b8e..31dd1136f 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -3,7 +3,8 @@ use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::mutex::{Mutex, MutexGuard}; -use super::{family, Error, FlashLayout, FlashRegion, FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; +use super::{family, Error, FlashLayout, FlashRegion, FlashSector, FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; +use crate::flash::FlashBank; use crate::Peripheral; pub struct Flash<'d> { @@ -79,10 +80,12 @@ impl<'d> Flash<'d> { } unsafe fn blocking_erase_inner(start_address: u32, end_address: u32) -> Result<(), Error> { + let regions = family::get_flash_regions(); + // Test if the address range is aligned at sector base addresses let mut address = start_address; while address < end_address { - let sector = family::get_sector(address); + let sector = get_sector(address, regions); if sector.start != address { return Err(Error::Unaligned); } @@ -103,7 +106,8 @@ impl<'d> Flash<'d> { let mut address = start_address; while address < end_address { - let sector = family::get_sector(address); + let sector = get_sector(address, regions); + trace!("Erasing sector: {}", sector); family::blocking_erase_sector(§or)?; address += sector.size; } @@ -138,6 +142,31 @@ fn take_lock_spin() -> MutexGuard<'static, CriticalSectionRawMutex, ()> { } } +pub(crate) fn get_sector(address: u32, regions: &[&FlashRegion]) -> FlashSector { + let mut current_bank = FlashBank::Bank1; + let mut bank_offset = 0; + for region in regions { + if region.bank != current_bank { + current_bank = region.bank; + bank_offset = 0; + } + + if address < region.end() { + let index_in_region = (address - region.base) / region.erase_size; + return FlashSector { + bank: region.bank, + index_in_bank: bank_offset + index_in_region as u8, + start: region.base + index_in_region * region.erase_size, + size: region.erase_size, + }; + } + + bank_offset += region.sectors(); + } + + panic!("Flash sector not found"); +} + impl FlashRegion { pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { unsafe { self.blocking_read_inner(offset, bytes) } diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index 5ac1d8fdf..c1ed33f9d 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -3,10 +3,14 @@ use core::ptr::write_volatile; use atomic_polyfill::{fence, Ordering}; -use super::{FlashSector, BANK1_REGION, WRITE_SIZE}; +use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; +pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { + &FLASH_REGIONS +} + pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } @@ -99,13 +103,3 @@ unsafe fn blocking_wait_ready() -> Result<(), Error> { } } } - -pub(crate) fn get_sector(address: u32) -> FlashSector { - let sector_size = BANK1_REGION.erase_size; - let index = address / sector_size; - FlashSector { - index: index as u8, - start: BANK1_REGION.base + index * sector_size, - size: sector_size, - } -} diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 52ef7ad50..61ac8afd5 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -2,22 +2,17 @@ use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; -use super::{FlashSector, FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; +use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; -const SMALL_SECTOR_SIZE: u32 = 16 * 1024; -const MEDIUM_SECTOR_SIZE: u32 = 64 * 1024; -const LARGE_SECTOR_SIZE: u32 = 128 * 1024; -const SECOND_BANK_SECTOR_OFFSET: u8 = 12; - #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] mod alt_regions { use embassy_hal_common::PeripheralRef; use stm32_metapac::FLASH_SIZE; use crate::_generated::flash_regions::{BANK1_REGION1, BANK1_REGION2, BANK1_REGION3}; - use crate::flash::{Bank1Region1, Bank1Region2, Flash, FlashRegion}; + use crate::flash::{Bank1Region1, Bank1Region2, Flash, FlashBank, FlashRegion}; use crate::peripherals::FLASH; pub const ALT_BANK1_REGION3: FlashRegion = FlashRegion { @@ -25,19 +20,31 @@ mod alt_regions { ..BANK1_REGION3 }; pub const ALT_BANK2_REGION1: FlashRegion = FlashRegion { + bank: FlashBank::Bank2, base: BANK1_REGION1.base + FLASH_SIZE as u32 / 2, ..BANK1_REGION1 }; pub const ALT_BANK2_REGION2: FlashRegion = FlashRegion { + bank: FlashBank::Bank2, base: BANK1_REGION2.base + FLASH_SIZE as u32 / 2, ..BANK1_REGION2 }; pub const ALT_BANK2_REGION3: FlashRegion = FlashRegion { + bank: FlashBank::Bank2, base: BANK1_REGION3.base + FLASH_SIZE as u32 / 2, size: 3 * BANK1_REGION3.erase_size, ..BANK1_REGION3 }; + pub const ALT_FLASH_REGIONS: [&FlashRegion; 6] = [ + &BANK1_REGION1, + &BANK1_REGION2, + &ALT_BANK1_REGION3, + &ALT_BANK2_REGION1, + &ALT_BANK2_REGION2, + &ALT_BANK2_REGION3, + ]; + pub type AltBank1Region1 = Bank1Region1; pub type AltBank1Region2 = Bank1Region2; pub struct AltBank1Region3(&'static FlashRegion); @@ -81,25 +88,22 @@ mod alt_regions { } #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] -pub use alt_regions::AltFlashLayout; +pub use alt_regions::{AltFlashLayout, ALT_FLASH_REGIONS}; -fn is_dual_bank() -> bool { - match FLASH_SIZE / 1024 { - // 1 MB devices depend on configuration - 1024 => { - if cfg!(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)) { - unsafe { pac::FLASH.optcr().read().db1m() } - } else { - false - } - } - // 2 MB devices are always dual bank - 2048 => true, - // All other devices are single bank - _ => false, +#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] +pub(crate) fn get_flash_regions() -> &'static [&'static FlashRegion] { + if unsafe { pac::FLASH.optcr().read().db1m() } { + &ALT_FLASH_REGIONS + } else { + &FLASH_REGIONS } } +#[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)))] +pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { + &FLASH_REGIONS +} + pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } @@ -136,11 +140,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) } pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { - let sector = sector.index; - let bank = sector / SECOND_BANK_SECTOR_OFFSET as u8; - let snb = (bank << 4) + (sector % SECOND_BANK_SECTOR_OFFSET as u8); - - trace!("Erasing sector: {}", sector); + let snb = ((sector.bank as u8) << 4) + sector.index_in_bank; pac::FLASH.cr().modify(|w| { w.set_ser(true); @@ -194,72 +194,27 @@ unsafe fn blocking_wait_ready() -> Result<(), Error> { } } -pub(crate) fn get_sector(address: u32) -> FlashSector { - get_sector_inner(address, is_dual_bank(), FLASH_SIZE as u32) -} - -fn get_sector_inner(address: u32, dual_bank: bool, flash_size: u32) -> FlashSector { - let offset = address - FLASH_BASE as u32; - if !dual_bank { - get_single_bank_sector(offset) - } else { - let bank_size = flash_size / 2; - if offset < bank_size { - get_single_bank_sector(offset) - } else { - let sector = get_single_bank_sector(offset - bank_size); - FlashSector { - index: SECOND_BANK_SECTOR_OFFSET + sector.index, - start: sector.start + bank_size, - size: sector.size, - } - } - } -} - -fn get_single_bank_sector(offset: u32) -> FlashSector { - // First 4 sectors are 16KB, then one 64KB, and rest are 128KB - match offset / LARGE_SECTOR_SIZE { - 0 => { - if offset < 4 * SMALL_SECTOR_SIZE { - let small_sector_index = offset / SMALL_SECTOR_SIZE; - FlashSector { - index: small_sector_index as u8, - start: FLASH_BASE as u32 + small_sector_index * SMALL_SECTOR_SIZE, - size: SMALL_SECTOR_SIZE, - } - } else { - FlashSector { - index: 4, - start: FLASH_BASE as u32 + 4 * SMALL_SECTOR_SIZE, - size: MEDIUM_SECTOR_SIZE, - } - } - } - i => { - let large_sector_index = i - 1; - FlashSector { - index: (5 + large_sector_index) as u8, - start: FLASH_BASE as u32 - + 4 * SMALL_SECTOR_SIZE - + MEDIUM_SECTOR_SIZE - + large_sector_index * LARGE_SECTOR_SIZE, - size: LARGE_SECTOR_SIZE, - } - } - } -} - #[cfg(test)] mod tests { use super::*; + use crate::flash::{get_sector, FlashBank}; #[test] + #[cfg(stm32f429)] fn can_get_sector_single_bank() { - let assert_sector = |index: u8, start: u32, size: u32, addr: u32| { + const SMALL_SECTOR_SIZE: u32 = 16 * 1024; + const MEDIUM_SECTOR_SIZE: u32 = 64 * 1024; + const LARGE_SECTOR_SIZE: u32 = 128 * 1024; + + let assert_sector = |index_in_bank: u8, start: u32, size: u32, address: u32| { assert_eq!( - FlashSector { index, start, size }, - get_sector_inner(addr, false, 1024 * 1024) + FlashSector { + bank: FlashBank::Bank1, + index_in_bank, + start, + size + }, + get_sector(address, &FLASH_REGIONS) ) }; @@ -275,41 +230,43 @@ mod tests { assert_sector(5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0803_FFFF); assert_sector(11, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080E_0000); assert_sector(11, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080F_FFFF); - } - #[test] - fn can_get_sector_dual_bank() { - let assert_sector = |index: u8, start: u32, size: u32, addr: u32| { + let assert_sector = |bank: FlashBank, index_in_bank: u8, start: u32, size: u32, address: u32| { assert_eq!( - FlashSector { index, start, size }, - get_sector_inner(addr, true, 1024 * 1024) + FlashSector { + bank, + index_in_bank, + start, + size + }, + get_sector(address, &ALT_FLASH_REGIONS) ) }; - assert_sector(0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_0000); - assert_sector(0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_3FFF); - assert_sector(3, 0x0800_C000, SMALL_SECTOR_SIZE, 0x0800_C000); - assert_sector(3, 0x0800_C000, SMALL_SECTOR_SIZE, 0x0800_FFFF); + assert_sector(FlashBank::Bank1, 0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_0000); + assert_sector(FlashBank::Bank1, 0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_3FFF); + assert_sector(FlashBank::Bank1, 3, 0x0800_C000, SMALL_SECTOR_SIZE, 0x0800_C000); + assert_sector(FlashBank::Bank1, 3, 0x0800_C000, SMALL_SECTOR_SIZE, 0x0800_FFFF); - assert_sector(4, 0x0801_0000, MEDIUM_SECTOR_SIZE, 0x0801_0000); - assert_sector(4, 0x0801_0000, MEDIUM_SECTOR_SIZE, 0x0801_FFFF); + assert_sector(FlashBank::Bank1, 4, 0x0801_0000, MEDIUM_SECTOR_SIZE, 0x0801_0000); + assert_sector(FlashBank::Bank1, 4, 0x0801_0000, MEDIUM_SECTOR_SIZE, 0x0801_FFFF); - assert_sector(5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0802_0000); - assert_sector(5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0803_FFFF); - assert_sector(7, 0x0806_0000, LARGE_SECTOR_SIZE, 0x0806_0000); - assert_sector(7, 0x0806_0000, LARGE_SECTOR_SIZE, 0x0807_FFFF); + assert_sector(FlashBank::Bank1, 5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0802_0000); + assert_sector(FlashBank::Bank1, 5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0803_FFFF); + assert_sector(FlashBank::Bank1, 7, 0x0806_0000, LARGE_SECTOR_SIZE, 0x0806_0000); + assert_sector(FlashBank::Bank1, 7, 0x0806_0000, LARGE_SECTOR_SIZE, 0x0807_FFFF); - assert_sector(12, 0x0808_0000, SMALL_SECTOR_SIZE, 0x0808_0000); - assert_sector(12, 0x0808_0000, SMALL_SECTOR_SIZE, 0x0808_3FFF); - assert_sector(15, 0x0808_C000, SMALL_SECTOR_SIZE, 0x0808_C000); - assert_sector(15, 0x0808_C000, SMALL_SECTOR_SIZE, 0x0808_FFFF); + assert_sector(FlashBank::Bank2, 0, 0x0808_0000, SMALL_SECTOR_SIZE, 0x0808_0000); + assert_sector(FlashBank::Bank2, 0, 0x0808_0000, SMALL_SECTOR_SIZE, 0x0808_3FFF); + assert_sector(FlashBank::Bank2, 3, 0x0808_C000, SMALL_SECTOR_SIZE, 0x0808_C000); + assert_sector(FlashBank::Bank2, 3, 0x0808_C000, SMALL_SECTOR_SIZE, 0x0808_FFFF); - assert_sector(16, 0x0809_0000, MEDIUM_SECTOR_SIZE, 0x0809_0000); - assert_sector(16, 0x0809_0000, MEDIUM_SECTOR_SIZE, 0x0809_FFFF); + assert_sector(FlashBank::Bank2, 4, 0x0809_0000, MEDIUM_SECTOR_SIZE, 0x0809_0000); + assert_sector(FlashBank::Bank2, 4, 0x0809_0000, MEDIUM_SECTOR_SIZE, 0x0809_FFFF); - assert_sector(17, 0x080A_0000, LARGE_SECTOR_SIZE, 0x080A_0000); - assert_sector(17, 0x080A_0000, LARGE_SECTOR_SIZE, 0x080B_FFFF); - assert_sector(19, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080E_0000); - assert_sector(19, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080F_FFFF); + assert_sector(FlashBank::Bank2, 5, 0x080A_0000, LARGE_SECTOR_SIZE, 0x080A_0000); + assert_sector(FlashBank::Bank2, 5, 0x080A_0000, LARGE_SECTOR_SIZE, 0x080B_FFFF); + assert_sector(FlashBank::Bank2, 7, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080E_0000); + assert_sector(FlashBank::Bank2, 7, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080F_FFFF); } } diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index eba7df467..7111f5cc4 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs @@ -2,13 +2,13 @@ use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; -use super::{FlashSector, FLASH_BASE, WRITE_SIZE}; +use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; -const SMALL_SECTOR_SIZE: u32 = 32 * 1024; -const MEDIUM_SECTOR_SIZE: u32 = 128 * 1024; -const LARGE_SECTOR_SIZE: u32 = 256 * 1024; +pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { + &FLASH_REGIONS +} pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); @@ -48,7 +48,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_ser(true); - w.set_snb(sector.index) + w.set_snb(sector.index_in_bank) }); pac::FLASH.cr().modify(|w| { @@ -110,48 +110,61 @@ unsafe fn blocking_wait_ready() -> Result<(), Error> { } } -pub(crate) fn get_sector(address: u32) -> FlashSector { - // First 4 sectors are 32KB, then one 128KB, and rest are 256KB - let offset = address - FLASH_BASE as u32; - match offset / LARGE_SECTOR_SIZE { - 0 => { - if offset < 4 * SMALL_SECTOR_SIZE { - let small_sector_index = offset / SMALL_SECTOR_SIZE; - FlashSector { - index: small_sector_index as u8, - start: FLASH_BASE as u32 + small_sector_index * SMALL_SECTOR_SIZE, - size: SMALL_SECTOR_SIZE, - } - } else { - FlashSector { - index: 4, - start: FLASH_BASE as u32 + 4 * SMALL_SECTOR_SIZE, - size: MEDIUM_SECTOR_SIZE, - } - } - } - i => { - let large_sector_index = i - 1; - FlashSector { - index: (5 + large_sector_index) as u8, - start: FLASH_BASE as u32 - + 4 * SMALL_SECTOR_SIZE - + MEDIUM_SECTOR_SIZE - + large_sector_index * LARGE_SECTOR_SIZE, - size: LARGE_SECTOR_SIZE, - } - } - } -} - #[cfg(test)] mod tests { use super::*; + use crate::flash::{get_sector, FlashBank}; #[test] + #[cfg(stm32f732)] fn can_get_sector() { - let assert_sector = |index: u8, start: u32, size: u32, addr: u32| { - assert_eq!(FlashSector { index, start, size }, get_sector(addr)) + const SMALL_SECTOR_SIZE: u32 = 16 * 1024; + const MEDIUM_SECTOR_SIZE: u32 = 64 * 1024; + const LARGE_SECTOR_SIZE: u32 = 128 * 1024; + + let assert_sector = |index_in_bank: u8, start: u32, size: u32, address: u32| { + assert_eq!( + FlashSector { + bank: FlashBank::Bank1, + index_in_bank, + start, + size + }, + get_sector(address, &FLASH_REGIONS) + ) + }; + + assert_sector(0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_0000); + assert_sector(0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_3FFF); + assert_sector(3, 0x0800_C000, SMALL_SECTOR_SIZE, 0x0800_C000); + assert_sector(3, 0x0800_C000, SMALL_SECTOR_SIZE, 0x0800_FFFF); + + assert_sector(4, 0x0801_0000, MEDIUM_SECTOR_SIZE, 0x0801_0000); + assert_sector(4, 0x0801_0000, MEDIUM_SECTOR_SIZE, 0x0801_FFFF); + + assert_sector(5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0802_0000); + assert_sector(5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0803_FFFF); + assert_sector(7, 0x0806_0000, LARGE_SECTOR_SIZE, 0x0806_0000); + assert_sector(7, 0x0806_0000, LARGE_SECTOR_SIZE, 0x0807_FFFF); + } + + #[test] + #[cfg(stm32f769)] + fn can_get_sector() { + const SMALL_SECTOR_SIZE: u32 = 32 * 1024; + const MEDIUM_SECTOR_SIZE: u32 = 128 * 1024; + const LARGE_SECTOR_SIZE: u32 = 256 * 1024; + + let assert_sector = |index_in_bank: u8, start: u32, size: u32, address: u32| { + assert_eq!( + FlashSector { + bank: FlashBank::Bank1, + index_in_bank, + start, + size + }, + get_sector(address, &FLASH_REGIONS) + ) }; assert_sector(0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_0000); diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 360ad77db..5ea57ccde 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -3,7 +3,7 @@ use core::ptr::write_volatile; use atomic_polyfill::{fence, Ordering}; -use super::{FlashSector, BANK1_REGION, FLASH_REGIONS, WRITE_SIZE}; +use super::{FlashRegion, FlashSector, BANK1_REGION, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; @@ -11,6 +11,10 @@ const fn is_dual_bank() -> bool { FLASH_REGIONS.len() == 2 } +pub(crate) fn get_flash_regions() -> &'static [&'static FlashRegion] { + &FLASH_REGIONS +} + pub(crate) unsafe fn lock() { pac::FLASH.bank(0).cr().modify(|w| w.set_lock(true)); if is_dual_bank() { @@ -75,11 +79,10 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) } pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { - let bank = pac::FLASH.bank(if sector.index >= 8 { 1 } else { 0 }); - let sector = sector.index % 8; + let bank = pac::FLASH.bank(sector.bank as usize); bank.cr().modify(|w| { w.set_ser(true); - w.set_snb(sector) + w.set_snb(sector.index_in_bank) }); bank.cr().modify(|w| { @@ -175,13 +178,3 @@ unsafe fn blocking_wait_ready(bank: pac::flash::Bank) -> Result<(), Error> { } } } - -pub(crate) fn get_sector(address: u32) -> FlashSector { - let sector_size = BANK1_REGION.erase_size; - let index = address / sector_size; - FlashSector { - index: index as u8, - start: BANK1_REGION.base + index * sector_size, - size: sector_size, - } -} diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index f4b11011f..f5ebc0a5f 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -2,10 +2,14 @@ use core::ptr::write_volatile; use atomic_polyfill::{fence, Ordering}; -use super::{FlashSector, BANK1_REGION, WRITE_SIZE}; +use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; +pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { + &FLASH_REGIONS +} + pub(crate) unsafe fn lock() { #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().modify(|w| w.set_lock(true)); @@ -73,7 +77,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E #[cfg(any(flash_wl, flash_wb, flash_l4))] { - let idx = (sector.start - super::FLASH_BASE as u32) / BANK1_REGION.erase_size as u32; + let idx = (sector.start - super::FLASH_BASE as u32) / super::BANK1_REGION.erase_size as u32; #[cfg(flash_l4)] let (idx, bank) = if idx > 255 { (idx - 256, true) } else { (idx, false) }; @@ -180,13 +184,3 @@ unsafe fn blocking_wait_ready() -> Result<(), Error> { } } } - -pub(crate) fn get_sector(address: u32) -> FlashSector { - let sector_size = BANK1_REGION.erase_size; - let index = address / sector_size; - FlashSector { - index: index as u8, - start: BANK1_REGION.base + index * sector_size, - size: sector_size, - } -} diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 110b81496..794d32ccd 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -10,6 +10,7 @@ pub use crate::_generated::flash_regions::*; pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; pub struct FlashRegion { + pub bank: FlashBank, pub base: u32, pub size: u32, pub erase_size: u32, @@ -19,15 +20,27 @@ pub struct FlashRegion { #[derive(Debug, PartialEq)] pub struct FlashSector { - pub index: u8, + pub bank: FlashBank, + pub index_in_bank: u8, pub start: u32, pub size: u32, } +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum FlashBank { + Bank1 = 0, + Bank2 = 1, + Otp, +} + impl FlashRegion { pub const fn end(&self) -> u32 { self.base + self.size } + + pub const fn sectors(&self) -> u8 { + (self.size / self.erase_size) as u8 + } } #[cfg_attr(any(flash_l0, flash_l1, flash_l4, flash_wl, flash_wb), path = "l.rs")] diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index fd3551224..d329dcab4 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs @@ -1,5 +1,10 @@ -#[allow(unused)] -use super::{Error, FlashSector, WRITE_SIZE}; +#![allow(unused)] + +use super::{Error, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; + +pub(crate) const fn get_flash_regions() -> &'static [&'static FlashRegion] { + &FLASH_REGIONS +} pub(crate) unsafe fn lock() { unimplemented!(); @@ -22,6 +27,3 @@ pub(crate) unsafe fn blocking_erase_sector(_sector: &FlashSector) -> Result<(), pub(crate) unsafe fn clear_all_err() { unimplemented!(); } -pub(crate) fn get_sector(_address: u32) -> FlashSector { - unimplemented!(); -}