From b2775fc90c3d7cc977f1ac3e15841462d7c8f1a4 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 12:17:12 +0200 Subject: [PATCH 01/47] stm32: Add async flash write/erase to f4 --- embassy-stm32/Cargo.toml | 4 +- embassy-stm32/src/flash/asynch.rs | 129 +++++++++++++++ embassy-stm32/src/flash/common.rs | 267 ++++++++++++++++-------------- embassy-stm32/src/flash/f0.rs | 18 +- embassy-stm32/src/flash/f3.rs | 18 +- embassy-stm32/src/flash/f4.rs | 183 +++++++++++++++++--- embassy-stm32/src/flash/f7.rs | 21 +-- embassy-stm32/src/flash/h7.rs | 21 +-- embassy-stm32/src/flash/l.rs | 19 ++- embassy-stm32/src/flash/mod.rs | 49 ++++++ embassy-stm32/src/flash/other.rs | 12 +- 11 files changed, 547 insertions(+), 194 deletions(-) create mode 100644 embassy-stm32/src/flash/asynch.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 21adb5dd..440de85e 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -47,6 +47,7 @@ embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true} embedded-hal-nb = { version = "=1.0.0-alpha.2", optional = true} embedded-storage = "0.3.0" +embedded-storage-async = { version = "0.4.0", optional = true } defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } @@ -68,6 +69,7 @@ cfg-if = "1.0.0" embedded-io = { version = "0.4.0", features = ["async"], optional = true } chrono = { version = "^0.4", default-features = false, optional = true} bit_field = "0.10.2" +paste = "1.0.12" [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } @@ -98,7 +100,7 @@ time-driver-tim12 = ["_time-driver"] time-driver-tim15 = ["_time-driver"] # Enable nightly-only features -nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"] +nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"] # Reexport stm32-metapac at `embassy_stm32::pac`. # This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version. diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs new file mode 100644 index 00000000..44e23d9c --- /dev/null +++ b/embassy-stm32/src/flash/asynch.rs @@ -0,0 +1,129 @@ +use atomic_polyfill::{fence, Ordering}; +use embassy_hal_common::drop::OnDrop; + +use super::{ + ensure_sector_aligned, family, get_sector, Error, Flash, FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, + REGION_ACCESS, WRITE_SIZE, +}; + +impl<'d> Flash<'d> { + pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await } + } + + pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + unsafe { erase_sectored(FLASH_BASE as u32, from, to).await } + } +} + +impl embedded_storage_async::nor_flash::NorFlash for Flash<'_> { + const WRITE_SIZE: usize = WRITE_SIZE; + const ERASE_SIZE: usize = MAX_ERASE_SIZE; + + async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(offset, bytes).await + } + + async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase(from, to).await + } +} + +pub(super) async unsafe fn write_chunked(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { + if offset + bytes.len() as u32 > size { + return Err(Error::Size); + } + if offset % WRITE_SIZE as u32 != 0 || bytes.len() % WRITE_SIZE != 0 { + return Err(Error::Unaligned); + } + + let mut address = base + offset; + trace!("Writing {} bytes at 0x{:x}", bytes.len(), address); + + for chunk in bytes.chunks(WRITE_SIZE) { + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); + family::enable_write(); + fence(Ordering::SeqCst); + + let _on_drop = OnDrop::new(|| { + family::disable_write(); + fence(Ordering::SeqCst); + family::lock(); + }); + + family::write(address, chunk.try_into().unwrap()).await?; + address += WRITE_SIZE as u32; + } + Ok(()) +} + +pub(super) async unsafe fn erase_sectored(base: u32, from: u32, to: u32) -> Result<(), Error> { + let start_address = base + from; + let end_address = base + to; + let regions = family::get_flash_regions(); + + ensure_sector_aligned(start_address, end_address, regions)?; + + trace!("Erasing from 0x{:x} to 0x{:x}", start_address, end_address); + + let mut address = start_address; + while address < end_address { + let sector = get_sector(address, regions); + trace!("Erasing sector: {:?}", sector); + + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); + + let _on_drop = OnDrop::new(|| family::lock()); + + family::erase_sector(§or).await?; + address += sector.size; + } + Ok(()) +} + +foreach_flash_region! { + ($type_name:ident, $write_size:literal, $erase_size:literal) => { + impl crate::_generated::flash_regions::$type_name<'_> { + pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + let _guard = REGION_ACCESS.lock().await; + unsafe { write_chunked(self.0.base, self.0.size, offset, bytes).await } + } + + pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + let _guard = REGION_ACCESS.lock().await; + unsafe { erase_sectored(self.0.base, from, to).await } + } + } + + impl embedded_storage_async::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_> { + const READ_SIZE: usize = READ_SIZE; + + async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read(offset, bytes) + } + + fn capacity(&self) -> usize { + self.0.size as usize + } + } + + impl embedded_storage_async::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_> { + const WRITE_SIZE: usize = $write_size; + const ERASE_SIZE: usize = $erase_size; + + async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(offset, bytes).await + } + + async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase(from, to).await + } + } + }; +} diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 432c8a43..990104a3 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -1,44 +1,55 @@ use atomic_polyfill::{fence, Ordering}; +use embassy_cortex_m::interrupt::InterruptExt; +use embassy_futures::block_on; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::mutex::Mutex; +use stm32_metapac::FLASH_BASE; -use super::{family, Error, FlashLayout, FlashRegion, FlashSector, FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, WRITE_SIZE}; -use crate::flash::FlashBank; +use super::{ + ensure_sector_aligned, family, get_sector, Error, FlashLayout, FlashRegion, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, + WRITE_SIZE, +}; +use crate::peripherals::FLASH; use crate::Peripheral; pub struct Flash<'d> { - inner: PeripheralRef<'d, crate::peripherals::FLASH>, + pub(crate) inner: PeripheralRef<'d, FLASH>, } +pub(crate) static REGION_ACCESS: Mutex = Mutex::new(()); + impl<'d> Flash<'d> { - pub fn new(p: impl Peripheral

+ 'd) -> Self { - into_ref!(p); + pub fn new(p: impl Peripheral

+ 'd, irq: impl Peripheral

+ 'd) -> Self { + into_ref!(p, irq); + + irq.set_handler(family::on_interrupt); + irq.unpend(); + irq.enable(); + Self { inner: p } } pub fn into_regions(self) -> FlashLayout<'d> { family::set_default_layout(); - FlashLayout::new(self.release()) + FlashLayout::new(self.inner) } - pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - blocking_read(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + read_blocking(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } - pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { blocking_write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } + pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + unsafe { write_chunked_blocking(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } } - pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { blocking_erase_sectored(FLASH_BASE as u32, from, to) } - } - - pub(crate) fn release(self) -> PeripheralRef<'d, crate::peripherals::FLASH> { - unsafe { self.inner.clone_unchecked() } + pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> { + unsafe { erase_sectored_blocking(FLASH_BASE as u32, from, to) } } } -pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { +pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); } @@ -49,7 +60,7 @@ pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) Ok(()) } -pub(super) unsafe fn blocking_write_chunked(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { +pub(super) unsafe fn write_chunked_blocking(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); } @@ -61,44 +72,31 @@ pub(super) unsafe fn blocking_write_chunked(base: u32, size: u32, offset: u32, b trace!("Writing {} bytes at 0x{:x}", bytes.len(), address); for chunk in bytes.chunks(WRITE_SIZE) { - critical_section::with(|_| { - family::clear_all_err(); - fence(Ordering::SeqCst); - family::unlock(); - fence(Ordering::SeqCst); - family::begin_write(); - fence(Ordering::SeqCst); + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); + family::enable_blocking_write(); + fence(Ordering::SeqCst); - let _on_drop = OnDrop::new(|| { - family::end_write(); - fence(Ordering::SeqCst); - family::lock(); - }); + let _on_drop = OnDrop::new(|| { + family::disable_blocking_write(); + fence(Ordering::SeqCst); + family::lock(); + }); - family::blocking_write(address, chunk.try_into().unwrap()) - })?; + family::write_blocking(address, chunk.try_into().unwrap())?; address += WRITE_SIZE as u32; } Ok(()) } -pub(super) unsafe fn blocking_erase_sectored(base: u32, from: u32, to: u32) -> Result<(), Error> { +pub(super) unsafe fn erase_sectored_blocking(base: u32, from: u32, to: u32) -> Result<(), Error> { let start_address = base + from; let end_address = base + to; 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 = get_sector(address, regions); - if sector.start != address { - return Err(Error::Unaligned); - } - address += sector.size; - } - if address != end_address { - return Err(Error::Unaligned); - } + ensure_sector_aligned(start_address, end_address, regions)?; trace!("Erasing from 0x{:x} to 0x{:x}", start_address, end_address); @@ -107,71 +105,28 @@ pub(super) unsafe fn blocking_erase_sectored(base: u32, from: u32, to: u32) -> R let sector = get_sector(address, regions); trace!("Erasing sector: {:?}", sector); - critical_section::with(|_| { - family::clear_all_err(); - fence(Ordering::SeqCst); - family::unlock(); - fence(Ordering::SeqCst); + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); - let _on_drop = OnDrop::new(|| { - family::lock(); - }); + let _on_drop = OnDrop::new(|| family::lock()); - family::blocking_erase_sector(§or) - })?; + family::erase_sector_blocking(§or)?; address += sector.size; } Ok(()) } -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> { - blocking_read(self.base, self.size, offset, bytes) - } - - pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { blocking_write_chunked(self.base, self.size, offset, bytes) } - } - - pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { blocking_erase_sectored(self.base, from, to) } - } -} - impl embedded_storage::nor_flash::ErrorType for Flash<'_> { type Error = Error; } impl embedded_storage::nor_flash::ReadNorFlash for Flash<'_> { - const READ_SIZE: usize = 1; + const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(offset, bytes) + self.read(offset, bytes) } fn capacity(&self) -> usize { @@ -184,27 +139,112 @@ impl embedded_storage::nor_flash::NorFlash for Flash<'_> { const ERASE_SIZE: usize = MAX_ERASE_SIZE; fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(offset, bytes) + self.write_blocking(offset, bytes) } fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.blocking_erase(from, to) + self.erase_blocking(from, to) + } +} + +#[cfg(feature = "nightly")] +impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_> { + const READ_SIZE: usize = READ_SIZE; + + async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read(offset, bytes) + } + + fn capacity(&self) -> usize { + FLASH_SIZE + } +} + +pub struct BlockingFlashRegion<'d, const WRITE_SIZE: u32, const ERASE_SIZE: u32>( + &'static FlashRegion, + PeripheralRef<'d, FLASH>, +); + +impl BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> { + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + read_blocking(self.0.base, self.0.size, offset, bytes) + } + + pub fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + let _guard = block_on(REGION_ACCESS.lock()); + unsafe { write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } + } + + pub fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + let _guard = block_on(REGION_ACCESS.lock()); + unsafe { erase_sectored_blocking(self.0.base, from, to) } + } +} + +impl embedded_storage::nor_flash::ErrorType + for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> +{ + type Error = Error; +} + +impl embedded_storage::nor_flash::ReadNorFlash + for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> +{ + const READ_SIZE: usize = READ_SIZE; + + fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read(offset, bytes) + } + + fn capacity(&self) -> usize { + self.0.size as usize + } +} + +impl embedded_storage::nor_flash::NorFlash + for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> +{ + const WRITE_SIZE: usize = WRITE_SIZE as usize; + const ERASE_SIZE: usize = ERASE_SIZE as usize; + + fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(offset, bytes) + } + + fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase(from, to) } } foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { - impl crate::_generated::flash_regions::$type_name<'_> { - pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - blocking_read(self.0.base, self.0.size, offset, bytes) + paste::paste! { + pub type []<'d> = BlockingFlashRegion<'d, $write_size, $erase_size>; + } + + impl<'d> crate::_generated::flash_regions::$type_name<'d> { + /// Make this flash region work in a blocking context. + /// + /// SAFETY + /// + /// This function is unsafe as incorect usage of parallel blocking operations + /// on multiple regions may cause a deadlock because each region requires mutual access to the flash. + pub unsafe fn into_blocking(self) -> BlockingFlashRegion<'d, $write_size, $erase_size> { + BlockingFlashRegion(self.0, self.1) } - pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { blocking_write_chunked(self.0.base, self.0.size, offset, bytes) } + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + read_blocking(self.0.base, self.0.size, offset, bytes) } - pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { blocking_erase_sectored(self.0.base, from, to) } + pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; + unsafe { write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } + } + + pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; + unsafe { erase_sectored_blocking(self.0.base, from, to) } } } @@ -213,28 +253,15 @@ foreach_flash_region! { } impl embedded_storage::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_> { - const READ_SIZE: usize = 1; + const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(offset, bytes) + self.read(offset, bytes) } fn capacity(&self) -> usize { self.0.size as usize } } - - impl embedded_storage::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_> { - const WRITE_SIZE: usize = $write_size; - const ERASE_SIZE: usize = $erase_size; - - fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(offset, bytes) - } - - fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.blocking_erase(from, to) - } - } }; } diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index c6441ef1..ecf3a698 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -13,6 +13,10 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } @@ -22,17 +26,17 @@ pub(crate) unsafe fn unlock() { pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 2); pac::FLASH.cr().write(|w| w.set_pg(true)); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for chunk in buf.chunks(2) { write_volatile(address as *mut u16, u16::from_le_bytes(chunk.try_into().unwrap())); @@ -42,10 +46,10 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - blocking_wait_ready() + wait_ready_blocking() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_per(true); }); @@ -56,7 +60,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let mut ret: Result<(), Error> = blocking_wait_ready(); + let mut ret: Result<(), Error> = wait_ready_blocking(); if !pac::FLASH.sr().read().eop() { trace!("FLASH: EOP not set"); @@ -88,7 +92,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn blocking_wait_ready() -> Result<(), Error> { +unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index 4c817220..fd778f2b 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -13,6 +13,10 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } @@ -22,17 +26,17 @@ pub(crate) unsafe fn unlock() { pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 2); pac::FLASH.cr().write(|w| w.set_pg(true)); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for chunk in buf.chunks(2) { write_volatile(address as *mut u16, u16::from_le_bytes(chunk.try_into().unwrap())); @@ -42,10 +46,10 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - blocking_wait_ready() + wait_ready_blocking() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_per(true); }); @@ -56,7 +60,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let mut ret: Result<(), Error> = blocking_wait_ready(); + let mut ret: Result<(), Error> = wait_ready_blocking(); if !pac::FLASH.sr().read().eop() { trace!("FLASH: EOP not set"); @@ -88,7 +92,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn blocking_wait_ready() -> Result<(), Error> { +unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 7f1c5f67..3c8f81eb 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -2,6 +2,8 @@ use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; +use embassy_sync::waitqueue::AtomicWaker; + use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; @@ -13,8 +15,8 @@ mod alt_regions { use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; use crate::flash::{ - blocking_erase_sectored, blocking_read, blocking_write_chunked, Bank1Region1, Bank1Region2, Error, Flash, - FlashBank, FlashRegion, + asynch, common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, + READ_SIZE, REGION_ACCESS, }; use crate::peripherals::FLASH; @@ -53,6 +55,15 @@ mod alt_regions { pub struct AltBank2Region2<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); pub struct AltBank2Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); + pub type BlockingAltBank1Region3<'d> = + BlockingFlashRegion<'d, { ALT_BANK1_REGION3.write_size }, { ALT_BANK1_REGION3.erase_size }>; + pub type BlockingAltBank2Region1<'d> = + BlockingFlashRegion<'d, { ALT_BANK2_REGION1.write_size }, { ALT_BANK2_REGION1.erase_size }>; + pub type BlockingAltBank2Region2<'d> = + BlockingFlashRegion<'d, { ALT_BANK2_REGION2.write_size }, { ALT_BANK2_REGION2.erase_size }>; + pub type BlockingAltBank2Region3<'d> = + BlockingFlashRegion<'d, { ALT_BANK2_REGION3.write_size }, { ALT_BANK2_REGION3.erase_size }>; + pub struct AltFlashLayout<'d> { pub bank1_region1: Bank1Region1<'d>, pub bank1_region2: Bank1Region2<'d>, @@ -69,7 +80,7 @@ mod alt_regions { // SAFETY: We never expose the cloned peripheral references, and their instance is not public. // Also, all blocking flash region operations are protected with a cs. - let p = self.release(); + let p = self.inner; AltFlashLayout { bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }), bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }), @@ -85,16 +96,30 @@ mod alt_regions { macro_rules! foreach_altflash_region { ($type_name:ident, $region:ident) => { impl $type_name<'_> { - pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - blocking_read(self.0.base, self.0.size, offset, bytes) + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + common::read_blocking(self.0.base, self.0.size, offset, bytes) } - pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { blocking_write_chunked(self.0.base, self.0.size, offset, bytes) } + #[cfg(all(feature = "nightly"))] + pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + let _guard = REGION_ACCESS.lock().await; + unsafe { asynch::write_chunked(self.0.base, self.0.size, offset, bytes).await } } - pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { blocking_erase_sectored(self.0.base, from, to) } + #[cfg(all(feature = "nightly"))] + pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + let _guard = REGION_ACCESS.lock().await; + unsafe { asynch::erase_sectored(self.0.base, from, to).await } + } + + pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; + unsafe { common::write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } + } + + pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; + unsafe { common::erase_sectored_blocking(self.0.base, from, to) } } } @@ -103,10 +128,10 @@ mod alt_regions { } impl embedded_storage::nor_flash::ReadNorFlash for $type_name<'_> { - const READ_SIZE: usize = 1; + const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(offset, bytes) + self.read(offset, bytes) } fn capacity(&self) -> usize { @@ -114,16 +139,28 @@ mod alt_regions { } } - impl embedded_storage::nor_flash::NorFlash for $type_name<'_> { + impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_> { + const READ_SIZE: usize = READ_SIZE; + + async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read(offset, bytes) + } + + fn capacity(&self) -> usize { + self.0.size as usize + } + } + + impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_> { const WRITE_SIZE: usize = $region.write_size as usize; const ERASE_SIZE: usize = $region.erase_size as usize; - fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(offset, bytes) + async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(offset, bytes).await } - fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.blocking_erase(from, to) + async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase(from, to).await } } }; @@ -138,6 +175,9 @@ mod alt_regions { #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub use alt_regions::*; +#[cfg(feature = "nightly")] +static WAKER: AtomicWaker = AtomicWaker::new(); + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub fn set_default_layout() { unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(false)) }; @@ -160,6 +200,16 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + // Clear IRQ flags + pac::FLASH.sr().write(|w| { + w.set_operr(true); + w.set_eop(true); + }); + + WAKER.wake(); +} + pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } @@ -169,7 +219,28 @@ pub(crate) unsafe fn unlock() { pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); } -pub(crate) unsafe fn begin_write() { +#[cfg(feature = "nightly")] +pub(crate) unsafe fn enable_write() { + assert_eq!(0, WRITE_SIZE % 4); + + pac::FLASH.cr().write(|w| { + w.set_pg(true); + w.set_psize(pac::flash::vals::Psize::PSIZE32); + w.set_eopie(true); + w.set_errie(true); + }); +} + +#[cfg(feature = "nightly")] +pub(crate) unsafe fn disable_write() { + pac::FLASH.cr().write(|w| { + w.set_pg(false); + w.set_eopie(false); + w.set_errie(false); + }); +} + +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 4); pac::FLASH.cr().write(|w| { @@ -178,11 +249,22 @@ pub(crate) unsafe fn begin_write() { }); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +#[cfg(feature = "nightly")] +pub(crate) async unsafe fn write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { + write_start(start_address, buf); + wait_ready().await +} + +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { + write_start(start_address, buf); + wait_ready_blocking() +} + +unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) { let mut address = start_address; for val in buf.chunks(4) { write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); @@ -191,11 +273,32 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) // prevents parallelism errors fence(Ordering::SeqCst); } - - blocking_wait_ready() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> { + let snb = ((sector.bank as u8) << 4) + sector.index_in_bank; + + pac::FLASH.cr().modify(|w| { + w.set_ser(true); + w.set_snb(snb); + w.set_eopie(true); + w.set_errie(true); + }); + + pac::FLASH.cr().modify(|w| { + w.set_strt(true); + }); + + let ret: Result<(), Error> = wait_ready().await; + pac::FLASH.cr().modify(|w| { + w.set_eopie(false); + w.set_errie(false); + }); + clear_all_err(); + ret +} + +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { let snb = ((sector.bank as u8) << 4) + sector.index_in_bank; pac::FLASH.cr().modify(|w| { @@ -207,10 +310,8 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let ret: Result<(), Error> = blocking_wait_ready(); - + let ret: Result<(), Error> = wait_ready_blocking(); clear_all_err(); - ret } @@ -220,11 +321,39 @@ pub(crate) unsafe fn clear_all_err() { w.set_pgperr(true); w.set_pgaerr(true); w.set_wrperr(true); - w.set_eop(true); }); } -unsafe fn blocking_wait_ready() -> Result<(), Error> { +#[cfg(feature = "nightly")] +pub(crate) async unsafe fn wait_ready() -> Result<(), Error> { + use core::task::Poll; + + use futures::future::poll_fn; + + poll_fn(|cx| { + WAKER.register(cx.waker()); + + let sr = pac::FLASH.sr().read(); + if !sr.bsy() { + Poll::Ready(if sr.pgserr() { + Err(Error::Seq) + } else if sr.pgperr() { + Err(Error::Parallelism) + } else if sr.pgaerr() { + Err(Error::Unaligned) + } else if sr.wrperr() { + Err(Error::Protected) + } else { + Ok(()) + }) + } else { + return Poll::Pending; + } + }) + .await +} + +unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index ac2834a8..a0593b14 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs @@ -12,6 +12,10 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } @@ -21,7 +25,7 @@ pub(crate) unsafe fn unlock() { pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 4); pac::FLASH.cr().write(|w| { @@ -30,11 +34,11 @@ pub(crate) unsafe fn begin_write() { }); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); @@ -44,10 +48,10 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - blocking_wait_ready() + wait_ready_blocking() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_ser(true); w.set_snb(sector.index_in_bank) @@ -57,12 +61,9 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let ret: Result<(), Error> = blocking_wait_ready(); - + let ret: Result<(), Error> = wait_ready_blocking(); pac::FLASH.cr().modify(|w| w.set_ser(false)); - clear_all_err(); - ret } @@ -86,7 +87,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn blocking_wait_ready() -> Result<(), Error> { +unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 1b163106..865f1328 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -17,6 +17,10 @@ pub fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { pac::FLASH.bank(0).cr().modify(|w| w.set_lock(true)); if is_dual_bank() { @@ -33,13 +37,13 @@ pub(crate) unsafe fn unlock() { } } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 4); } -pub(crate) unsafe fn end_write() {} +pub(crate) unsafe fn disable_blocking_write() {} -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { // We cannot have the write setup sequence in begin_write as it depends on the address let bank = if start_address < BANK1_REGION.end() { pac::FLASH.bank(0) @@ -60,7 +64,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); address += val.len() as u32; - res = Some(blocking_wait_ready(bank)); + res = Some(wait_ready_blocking(bank)); bank.sr().modify(|w| { if w.eop() { w.set_eop(true); @@ -80,7 +84,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) res.unwrap() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { let bank = pac::FLASH.bank(sector.bank as usize); bank.cr().modify(|w| { w.set_ser(true); @@ -91,12 +95,9 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_start(true); }); - let ret: Result<(), Error> = blocking_wait_ready(bank); - + let ret: Result<(), Error> = wait_ready_blocking(bank); bank.cr().modify(|w| w.set_ser(false)); - bank_clear_all_err(bank); - ret } @@ -141,7 +142,7 @@ unsafe fn bank_clear_all_err(bank: pac::flash::Bank) { }); } -unsafe fn blocking_wait_ready(bank: pac::flash::Bank) -> Result<(), Error> { +unsafe fn wait_ready_blocking(bank: pac::flash::Bank) -> Result<(), Error> { loop { let sr = bank.sr().read(); diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index c94f6190..f8a0dac4 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -12,6 +12,10 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().modify(|w| w.set_lock(true)); @@ -41,19 +45,19 @@ pub(crate) unsafe fn unlock() { } } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 4); #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().write(|w| w.set_pg(true)); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); @@ -63,10 +67,10 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - blocking_wait_ready() + wait_ready_blocking() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { #[cfg(any(flash_l0, flash_l1))] { pac::FLASH.pecr().modify(|w| { @@ -96,7 +100,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E }); } - let ret: Result<(), Error> = blocking_wait_ready(); + let ret: Result<(), Error> = wait_ready_blocking(); #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().modify(|w| w.set_per(false)); @@ -108,7 +112,6 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E }); clear_all_err(); - ret } @@ -150,7 +153,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn blocking_wait_ready() -> Result<(), Error> { +unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index b93270ae..e781f1b8 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -1,5 +1,7 @@ use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; +#[cfg(all(feature = "nightly", flash_f4))] +pub mod asynch; #[cfg(flash)] mod common; @@ -10,6 +12,8 @@ pub use crate::_generated::flash_regions::*; pub use crate::_generated::MAX_ERASE_SIZE; pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; +pub const READ_SIZE: usize = 1; + #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct FlashRegion { @@ -76,6 +80,7 @@ pub enum Error { Protected, Unaligned, Parallelism, + TryLockError, } impl NorFlashError for Error { @@ -87,3 +92,47 @@ impl NorFlashError for Error { } } } + +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"); +} + +pub(crate) fn ensure_sector_aligned( + start_address: u32, + end_address: u32, + regions: &[&FlashRegion], +) -> Result<(), Error> { + let mut address = start_address; + while address < end_address { + let sector = get_sector(address, regions); + if sector.start != address { + return Err(Error::Unaligned); + } + address += sector.size; + } + if address != end_address { + return Err(Error::Unaligned); + } + Ok(()) +} diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index 55603465..e21b0b24 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs @@ -8,22 +8,26 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { unimplemented!(); } pub(crate) unsafe fn unlock() { unimplemented!(); } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { unimplemented!(); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { unimplemented!(); } -pub(crate) unsafe fn blocking_write(_start_address: u32, _buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(_start_address: u32, _buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { unimplemented!(); } -pub(crate) unsafe fn blocking_erase_sector(_sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(_sector: &FlashSector) -> Result<(), Error> { unimplemented!(); } pub(crate) unsafe fn clear_all_err() { From 0a26870d363022a7d09500b6ecb28c0b455e81e7 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 12:41:52 +0200 Subject: [PATCH 02/47] Align examples --- examples/stm32f3/src/bin/flash.rs | 5 +- examples/stm32f4/src/bin/flash.rs | 14 ++--- examples/stm32f4/src/bin/flash_async.rs | 81 +++++++++++++++++++++++++ examples/stm32f7/src/bin/flash.rs | 5 +- examples/stm32h7/src/bin/flash.rs | 5 +- examples/stm32l0/src/bin/flash.rs | 5 +- examples/stm32l1/src/bin/flash.rs | 5 +- examples/stm32wl/src/bin/flash.rs | 5 +- 8 files changed, 100 insertions(+), 25 deletions(-) create mode 100644 examples/stm32f4/src/bin/flash_async.rs diff --git a/examples/stm32f3/src/bin/flash.rs b/examples/stm32f3/src/bin/flash.rs index e40ad4fc..0e5fb065 100644 --- a/examples/stm32f3/src/bin/flash.rs +++ b/examples/stm32f3/src/bin/flash.rs @@ -4,8 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use embassy_stm32::{flash::Flash, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH).into_regions().bank1_region; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index bd3a7c95..de4ecdb8 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; +use embassy_stm32::{flash::Flash, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { // Once can also call `into_regions()` to get access to NorFlash implementations // for each of the unique characteristics. - let mut f = Flash::new(p.FLASH); + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)); // Sector 5 test_flash(&mut f, 128 * 1024, 128 * 1024); @@ -31,19 +31,19 @@ fn test_flash(f: &mut Flash, offset: u32, size: u32) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.blocking_read(offset, &mut buf)); + unwrap!(f.read(offset, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.blocking_erase(offset, offset + size)); + unwrap!(f.erase_blocking(offset, offset + size)); info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.blocking_read(offset, &mut buf)); + unwrap!(f.read(offset, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.blocking_write( + unwrap!(f.write_blocking( offset, &[ 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, @@ -53,7 +53,7 @@ fn test_flash(f: &mut Flash, offset: u32, size: u32) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.blocking_read(offset, &mut buf)); + unwrap!(f.read(offset, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!( &buf[..], diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs new file mode 100644 index 00000000..c9d9df34 --- /dev/null +++ b/examples/stm32f4/src/bin/flash_async.rs @@ -0,0 +1,81 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::{info, unwrap}; +use embassy_executor::Spawner; +use embassy_time::{Timer, Duration}; +use embassy_stm32::flash::Flash; +use embassy_stm32::gpio::{AnyPin, Level, Output, Pin, Speed}; +use embassy_stm32::{interrupt}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello Flash!"); + + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)); + + // Led should blink uninterrupted during ~2sec erase operation + spawner.spawn(blinky(p.PB7.degrade())).unwrap(); + + // Test on bank 2 in order not to stall CPU. + test_flash(&mut f, 1024 * 1024, 128 * 1024).await; +} + +#[embassy_executor::task] +async fn blinky(p: AnyPin) { + let mut led = Output::new(p, Level::High, Speed::Low); + + loop { + info!("high"); + led.set_high(); + Timer::after(Duration::from_millis(300)).await; + + info!("low"); + led.set_low(); + Timer::after(Duration::from_millis(300)).await; + } +} + +async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) { + info!("Testing offset: {=u32:#X}, size: {=u32:#X}", offset, size); + + info!("Reading..."); + let mut buf = [0u8; 32]; + unwrap!(f.read(offset, &mut buf)); + info!("Read: {=[u8]:x}", buf); + + info!("Erasing..."); + unwrap!(f.erase(offset, offset + size).await); + + info!("Reading..."); + let mut buf = [0u8; 32]; + unwrap!(f.read(offset, &mut buf)); + info!("Read after erase: {=[u8]:x}", buf); + + info!("Writing..."); + unwrap!( + f.write( + offset, + &[ + 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, 30, 31, 32 + ] + ) + .await + ); + + info!("Reading..."); + let mut buf = [0u8; 32]; + unwrap!(f.read(offset, &mut buf)); + info!("Read: {=[u8]:x}", buf); + assert_eq!( + &buf[..], + &[ + 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, + 30, 31, 32 + ] + ); +} \ No newline at end of file diff --git a/examples/stm32f7/src/bin/flash.rs b/examples/stm32f7/src/bin/flash.rs index aabfe855..717c82e8 100644 --- a/examples/stm32f7/src/bin/flash.rs +++ b/examples/stm32f7/src/bin/flash.rs @@ -4,9 +4,8 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; +use embassy_stm32::{flash::Flash, interrupt}; use embassy_time::{Duration, Timer}; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -19,7 +18,7 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = Flash::new(p.FLASH).into_regions().bank1_region3; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region3.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 32]; diff --git a/examples/stm32h7/src/bin/flash.rs b/examples/stm32h7/src/bin/flash.rs index 7ee9838c..aab72cae 100644 --- a/examples/stm32h7/src/bin/flash.rs +++ b/examples/stm32h7/src/bin/flash.rs @@ -4,9 +4,8 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; +use embassy_stm32::{flash::Flash, interrupt}; use embassy_time::{Duration, Timer}; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -19,7 +18,7 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = Flash::new(p.FLASH).into_regions().bank2_region; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank2_region.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 32]; diff --git a/examples/stm32l0/src/bin/flash.rs b/examples/stm32l0/src/bin/flash.rs index 33742502..0ed0d05f 100644 --- a/examples/stm32l0/src/bin/flash.rs +++ b/examples/stm32l0/src/bin/flash.rs @@ -4,8 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use embassy_stm32::{flash::Flash, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH).into_regions().bank1_region; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32l1/src/bin/flash.rs b/examples/stm32l1/src/bin/flash.rs index 38feb0d7..c4d7d029 100644 --- a/examples/stm32l1/src/bin/flash.rs +++ b/examples/stm32l1/src/bin/flash.rs @@ -4,8 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use embassy_stm32::{flash::Flash, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH).into_regions().bank1_region; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs index e6bc2865..df51ceb6 100644 --- a/examples/stm32wl/src/bin/flash.rs +++ b/examples/stm32wl/src/bin/flash.rs @@ -4,8 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use embassy_stm32::{flash::Flash, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x36000; - let mut f = Flash::new(p.FLASH).into_regions().bank1_region; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 8]; From ff3a70ed9debd1ce4075c0a28c90bb0c6e693bce Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 12:42:35 +0200 Subject: [PATCH 03/47] Add missing nightly guards --- embassy-stm32/src/flash/f4.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 3c8f81eb..9698bcd5 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -139,6 +139,7 @@ mod alt_regions { } } + #[cfg(all(feature = "nightly"))] impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_> { const READ_SIZE: usize = READ_SIZE; @@ -151,6 +152,7 @@ mod alt_regions { } } + #[cfg(all(feature = "nightly"))] impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_> { const WRITE_SIZE: usize = $region.write_size as usize; const ERASE_SIZE: usize = $region.erase_size as usize; From 6804b6c0b49777489b132639290b5e977ec8ffd9 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 12:45:59 +0200 Subject: [PATCH 04/47] Fix unused get_sector and ensure_sector_aligned --- embassy-stm32/src/flash/common.rs | 49 +++++++++++++++++++++++++++++-- embassy-stm32/src/flash/mod.rs | 44 --------------------------- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 990104a3..7cec5a3c 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -8,8 +8,8 @@ use embassy_sync::mutex::Mutex; use stm32_metapac::FLASH_BASE; use super::{ - ensure_sector_aligned, family, get_sector, Error, FlashLayout, FlashRegion, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, - WRITE_SIZE, + family, Error, FlashLayout, FlashRegion, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, + WRITE_SIZE, FlashSector, FlashBank, }; use crate::peripherals::FLASH; use crate::Peripheral; @@ -118,6 +118,51 @@ pub(super) unsafe fn erase_sectored_blocking(base: u32, from: u32, to: u32) -> R Ok(()) } +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"); +} + +pub(crate) fn ensure_sector_aligned( + start_address: u32, + end_address: u32, + regions: &[&FlashRegion], +) -> Result<(), Error> { + let mut address = start_address; + while address < end_address { + let sector = get_sector(address, regions); + if sector.start != address { + return Err(Error::Unaligned); + } + address += sector.size; + } + if address != end_address { + return Err(Error::Unaligned); + } + Ok(()) +} + + impl embedded_storage::nor_flash::ErrorType for Flash<'_> { type Error = Error; } diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index e781f1b8..1ef04e56 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -92,47 +92,3 @@ impl NorFlashError for Error { } } } - -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"); -} - -pub(crate) fn ensure_sector_aligned( - start_address: u32, - end_address: u32, - regions: &[&FlashRegion], -) -> Result<(), Error> { - let mut address = start_address; - while address < end_address { - let sector = get_sector(address, regions); - if sector.start != address { - return Err(Error::Unaligned); - } - address += sector.size; - } - if address != end_address { - return Err(Error::Unaligned); - } - Ok(()) -} From 1329a387e060d60ee2833d2eed6393f5dfc84d1a Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 12:55:17 +0200 Subject: [PATCH 05/47] Add more missing nightly guards --- embassy-stm32/src/flash/f4.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 9698bcd5..0c008fd0 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -2,12 +2,13 @@ use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; -use embassy_sync::waitqueue::AtomicWaker; - use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; +#[cfg(feature = "nightly")] +use embassy_sync::waitqueue::AtomicWaker; + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] mod alt_regions { use embassy_hal_common::PeripheralRef; @@ -15,10 +16,12 @@ mod alt_regions { use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; use crate::flash::{ - asynch, common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, + common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, READ_SIZE, REGION_ACCESS, }; use crate::peripherals::FLASH; + #[cfg(feature = "nightly")] + use crate::flash::asynch; pub const ALT_BANK1_REGION3: FlashRegion = FlashRegion { size: 3 * BANK1_REGION3.erase_size, @@ -100,13 +103,13 @@ mod alt_regions { common::read_blocking(self.0.base, self.0.size, offset, bytes) } - #[cfg(all(feature = "nightly"))] + #[cfg(feature = "nightly")] pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { let _guard = REGION_ACCESS.lock().await; unsafe { asynch::write_chunked(self.0.base, self.0.size, offset, bytes).await } } - #[cfg(all(feature = "nightly"))] + #[cfg(feature = "nightly")] pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { let _guard = REGION_ACCESS.lock().await; unsafe { asynch::erase_sectored(self.0.base, from, to).await } @@ -139,7 +142,7 @@ mod alt_regions { } } - #[cfg(all(feature = "nightly"))] + #[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_> { const READ_SIZE: usize = READ_SIZE; @@ -152,7 +155,7 @@ mod alt_regions { } } - #[cfg(all(feature = "nightly"))] + #[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_> { const WRITE_SIZE: usize = $region.write_size as usize; const ERASE_SIZE: usize = $region.erase_size as usize; @@ -209,6 +212,7 @@ pub(crate) unsafe fn on_interrupt(_: *mut ()) { w.set_eop(true); }); + #[cfg(feature = "nightly")] WAKER.wake(); } @@ -277,6 +281,7 @@ unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) { } } +#[cfg(feature = "nightly")] pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> { let snb = ((sector.bank as u8) << 4) + sector.index_in_bank; From 966f0abf48cc143fc33e17a5fc9e138cf82ab05f Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 13:11:03 +0200 Subject: [PATCH 06/47] Run format with nightly --- embassy-stm32/src/flash/common.rs | 4 +--- embassy-stm32/src/flash/f4.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 7cec5a3c..e1fe7e9d 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -8,8 +8,7 @@ use embassy_sync::mutex::Mutex; use stm32_metapac::FLASH_BASE; use super::{ - family, Error, FlashLayout, FlashRegion, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, - WRITE_SIZE, FlashSector, FlashBank, + family, Error, FlashBank, FlashLayout, FlashRegion, FlashSector, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE, }; use crate::peripherals::FLASH; use crate::Peripheral; @@ -162,7 +161,6 @@ pub(crate) fn ensure_sector_aligned( Ok(()) } - impl embedded_storage::nor_flash::ErrorType for Flash<'_> { type Error = Error; } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 0c008fd0..084bbdc6 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -2,26 +2,26 @@ use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; +#[cfg(feature = "nightly")] +use embassy_sync::waitqueue::AtomicWaker; + use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; -#[cfg(feature = "nightly")] -use embassy_sync::waitqueue::AtomicWaker; - #[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::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; - use crate::flash::{ - common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, - READ_SIZE, REGION_ACCESS, - }; - use crate::peripherals::FLASH; #[cfg(feature = "nightly")] use crate::flash::asynch; + use crate::flash::{ + common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, READ_SIZE, + REGION_ACCESS, + }; + use crate::peripherals::FLASH; pub const ALT_BANK1_REGION3: FlashRegion = FlashRegion { size: 3 * BANK1_REGION3.erase_size, From dfd56031713aa04af682aa1b2b113a72831728f1 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 17:24:28 +0200 Subject: [PATCH 07/47] Let FlashLayout and FlashRegion depends on a Blocking/Async mode generic --- embassy-stm32/Cargo.toml | 1 - embassy-stm32/build.rs | 16 ++- embassy-stm32/src/flash/asynch.rs | 35 ++++- embassy-stm32/src/flash/common.rs | 218 ++++++++++++------------------ embassy-stm32/src/flash/f4.rs | 112 +++++++-------- embassy-stm32/src/flash/mod.rs | 3 + 6 files changed, 179 insertions(+), 206 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 440de85e..2572eafc 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -69,7 +69,6 @@ cfg-if = "1.0.0" embedded-io = { version = "0.4.0", features = ["async"], optional = true } chrono = { version = "^0.4", default-features = false, optional = true} bit_field = "0.10.2" -paste = "1.0.12" [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 54098172..29af3c80 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -213,7 +213,7 @@ fn main() { let region_type = format_ident!("{}", get_flash_region_type_name(region.name)); flash_regions.extend(quote! { #[cfg(flash)] - pub struct #region_type<'d>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>,); + pub struct #region_type<'d, MODE>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData); }); } @@ -224,11 +224,11 @@ fn main() { let field_name = format_ident!("{}", region_name.to_lowercase()); let field_type = format_ident!("{}", get_flash_region_type_name(f.name)); let field = quote! { - pub #field_name: #field_type<'d> + pub #field_name: #field_type<'d, MODE> }; let region_name = format_ident!("{}", region_name); let init = quote! { - #field_name: #field_type(&#region_name, unsafe { p.clone_unchecked()}) + #field_name: #field_type(&#region_name, unsafe { p.clone_unchecked()}, core::marker::PhantomData) }; (field, (init, region_name)) @@ -238,15 +238,17 @@ fn main() { let regions_len = flash_memory_regions.len(); flash_regions.extend(quote! { #[cfg(flash)] - pub struct FlashLayout<'d> { - #(#fields),* + pub struct FlashLayout<'d, MODE> { + #(#fields),*, + _mode: core::marker::PhantomData, } #[cfg(flash)] - impl<'d> FlashLayout<'d> { + impl<'d, MODE> FlashLayout<'d, MODE> { pub(crate) fn new(p: embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self { Self { - #(#inits),* + #(#inits),*, + _mode: core::marker::PhantomData, } } } diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 44e23d9c..3564bbff 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -1,12 +1,21 @@ use atomic_polyfill::{fence, Ordering}; use embassy_hal_common::drop::OnDrop; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::mutex::Mutex; use super::{ - ensure_sector_aligned, family, get_sector, Error, Flash, FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, - REGION_ACCESS, WRITE_SIZE, + ensure_sector_aligned, family, get_sector, read_blocking, Async, Error, Flash, FlashLayout, FLASH_BASE, FLASH_SIZE, + MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE, }; +pub(super) static REGION_ACCESS: Mutex = Mutex::new(()); + impl<'d> Flash<'d> { + pub fn into_regions(self) -> FlashLayout<'d, Async> { + family::set_default_layout(); + FlashLayout::new(self.inner) + } + pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await } } @@ -16,6 +25,18 @@ impl<'d> Flash<'d> { } } +impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_> { + const READ_SIZE: usize = READ_SIZE; + + async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read(offset, bytes) + } + + fn capacity(&self) -> usize { + FLASH_SIZE + } +} + impl embedded_storage_async::nor_flash::NorFlash for Flash<'_> { const WRITE_SIZE: usize = WRITE_SIZE; const ERASE_SIZE: usize = MAX_ERASE_SIZE; @@ -89,7 +110,11 @@ pub(super) async unsafe fn erase_sectored(base: u32, from: u32, to: u32) -> Resu foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { - impl crate::_generated::flash_regions::$type_name<'_> { + impl crate::_generated::flash_regions::$type_name<'_, Async> { + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + read_blocking(self.0.base, self.0.size, offset, bytes) + } + pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { let _guard = REGION_ACCESS.lock().await; unsafe { write_chunked(self.0.base, self.0.size, offset, bytes).await } @@ -101,7 +126,7 @@ foreach_flash_region! { } } - impl embedded_storage_async::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_> { + impl embedded_storage_async::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_, Async> { const READ_SIZE: usize = READ_SIZE; async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { @@ -113,7 +138,7 @@ foreach_flash_region! { } } - impl embedded_storage_async::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_> { + impl embedded_storage_async::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_, Async> { const WRITE_SIZE: usize = $write_size; const ERASE_SIZE: usize = $erase_size; diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index e1fe7e9d..8b38745c 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -1,14 +1,12 @@ use atomic_polyfill::{fence, Ordering}; use embassy_cortex_m::interrupt::InterruptExt; -use embassy_futures::block_on; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; -use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::mutex::Mutex; use stm32_metapac::FLASH_BASE; use super::{ - family, Error, FlashBank, FlashLayout, FlashRegion, FlashSector, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE, + family, Blocking, Error, FlashBank, FlashLayout, FlashRegion, FlashSector, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, + WRITE_SIZE, }; use crate::peripherals::FLASH; use crate::Peripheral; @@ -17,8 +15,6 @@ pub struct Flash<'d> { pub(crate) inner: PeripheralRef<'d, FLASH>, } -pub(crate) static REGION_ACCESS: Mutex = Mutex::new(()); - impl<'d> Flash<'d> { pub fn new(p: impl Peripheral

+ 'd, irq: impl Peripheral

+ 'd) -> Self { into_ref!(p, irq); @@ -30,7 +26,7 @@ impl<'d> Flash<'d> { Self { inner: p } } - pub fn into_regions(self) -> FlashLayout<'d> { + pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> { family::set_default_layout(); FlashLayout::new(self.inner) } @@ -40,11 +36,19 @@ impl<'d> Flash<'d> { } pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { write_chunked_blocking(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } + unsafe { + write_blocking( + FLASH_BASE as u32, + FLASH_SIZE as u32, + offset, + bytes, + write_chunk_unlocked, + ) + } } pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { erase_sectored_blocking(FLASH_BASE as u32, from, to) } + unsafe { erase_blocking(FLASH_BASE as u32, from, to, erase_sector_unlocked) } } } @@ -59,7 +63,13 @@ pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8]) Ok(()) } -pub(super) unsafe fn write_chunked_blocking(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { +pub(super) unsafe fn write_blocking( + base: u32, + size: u32, + offset: u32, + bytes: &[u8], + write_chunk: unsafe fn(u32, &[u8]) -> Result<(), Error>, +) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); } @@ -71,26 +81,39 @@ pub(super) unsafe fn write_chunked_blocking(base: u32, size: u32, offset: u32, b trace!("Writing {} bytes at 0x{:x}", bytes.len(), address); for chunk in bytes.chunks(WRITE_SIZE) { - family::clear_all_err(); - fence(Ordering::SeqCst); - family::unlock(); - fence(Ordering::SeqCst); - family::enable_blocking_write(); - fence(Ordering::SeqCst); - - let _on_drop = OnDrop::new(|| { - family::disable_blocking_write(); - fence(Ordering::SeqCst); - family::lock(); - }); - - family::write_blocking(address, chunk.try_into().unwrap())?; + write_chunk(address, chunk)?; address += WRITE_SIZE as u32; } Ok(()) } -pub(super) unsafe fn erase_sectored_blocking(base: u32, from: u32, to: u32) -> Result<(), Error> { +pub(super) unsafe fn write_chunk_unlocked(address: u32, chunk: &[u8]) -> Result<(), Error> { + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); + family::enable_blocking_write(); + fence(Ordering::SeqCst); + + let _on_drop = OnDrop::new(|| { + family::disable_blocking_write(); + fence(Ordering::SeqCst); + family::lock(); + }); + + family::write_blocking(address, chunk.try_into().unwrap()) +} + +pub(super) unsafe fn write_chunk_with_critical_section(address: u32, chunk: &[u8]) -> Result<(), Error> { + critical_section::with(|_| write_chunk_unlocked(address, chunk)) +} + +pub(super) unsafe fn erase_blocking( + base: u32, + from: u32, + to: u32, + erase_sector: unsafe fn(&FlashSector) -> Result<(), Error>, +) -> Result<(), Error> { let start_address = base + from; let end_address = base + to; let regions = family::get_flash_regions(); @@ -103,21 +126,28 @@ pub(super) unsafe fn erase_sectored_blocking(base: u32, from: u32, to: u32) -> R while address < end_address { let sector = get_sector(address, regions); trace!("Erasing sector: {:?}", sector); - - family::clear_all_err(); - fence(Ordering::SeqCst); - family::unlock(); - fence(Ordering::SeqCst); - - let _on_drop = OnDrop::new(|| family::lock()); - - family::erase_sector_blocking(§or)?; + erase_sector(§or)?; address += sector.size; } Ok(()) } -pub(crate) fn get_sector(address: u32, regions: &[&FlashRegion]) -> FlashSector { +pub(super) unsafe fn erase_sector_unlocked(sector: &FlashSector) -> Result<(), Error> { + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); + + let _on_drop = OnDrop::new(|| family::lock()); + + family::erase_sector_blocking(§or) +} + +pub(super) unsafe fn erase_sector_with_critical_section(sector: &FlashSector) -> Result<(), Error> { + critical_section::with(|_| erase_sector_unlocked(sector)) +} + +pub(super) fn get_sector(address: u32, regions: &[&FlashRegion]) -> FlashSector { let mut current_bank = FlashBank::Bank1; let mut bank_offset = 0; for region in regions { @@ -142,7 +172,7 @@ pub(crate) fn get_sector(address: u32, regions: &[&FlashRegion]) -> FlashSector panic!("Flash sector not found"); } -pub(crate) fn ensure_sector_aligned( +pub(super) fn ensure_sector_aligned( start_address: u32, end_address: u32, regions: &[&FlashRegion], @@ -190,121 +220,49 @@ impl embedded_storage::nor_flash::NorFlash for Flash<'_> { } } -#[cfg(feature = "nightly")] -impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_> { - const READ_SIZE: usize = READ_SIZE; - - async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) - } - - fn capacity(&self) -> usize { - FLASH_SIZE - } -} - -pub struct BlockingFlashRegion<'d, const WRITE_SIZE: u32, const ERASE_SIZE: u32>( - &'static FlashRegion, - PeripheralRef<'d, FLASH>, -); - -impl BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> { - pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - read_blocking(self.0.base, self.0.size, offset, bytes) - } - - pub fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - let _guard = block_on(REGION_ACCESS.lock()); - unsafe { write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } - } - - pub fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - let _guard = block_on(REGION_ACCESS.lock()); - unsafe { erase_sectored_blocking(self.0.base, from, to) } - } -} - -impl embedded_storage::nor_flash::ErrorType - for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> -{ - type Error = Error; -} - -impl embedded_storage::nor_flash::ReadNorFlash - for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> -{ - const READ_SIZE: usize = READ_SIZE; - - fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) - } - - fn capacity(&self) -> usize { - self.0.size as usize - } -} - -impl embedded_storage::nor_flash::NorFlash - for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> -{ - const WRITE_SIZE: usize = WRITE_SIZE as usize; - const ERASE_SIZE: usize = ERASE_SIZE as usize; - - fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.write(offset, bytes) - } - - fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.erase(from, to) - } -} - foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { - paste::paste! { - pub type []<'d> = BlockingFlashRegion<'d, $write_size, $erase_size>; - } - - impl<'d> crate::_generated::flash_regions::$type_name<'d> { - /// Make this flash region work in a blocking context. - /// - /// SAFETY - /// - /// This function is unsafe as incorect usage of parallel blocking operations - /// on multiple regions may cause a deadlock because each region requires mutual access to the flash. - pub unsafe fn into_blocking(self) -> BlockingFlashRegion<'d, $write_size, $erase_size> { - BlockingFlashRegion(self.0, self.1) - } - - pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + impl<'d> crate::_generated::flash_regions::$type_name<'d, Blocking> { + pub fn read_blocking(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { read_blocking(self.0.base, self.0.size, offset, bytes) } - pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; - unsafe { write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } + pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + unsafe { write_blocking(self.0.base, self.0.size, offset, bytes, write_chunk_with_critical_section) } } - pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; - unsafe { erase_sectored_blocking(self.0.base, from, to) } + pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> { + unsafe { erase_blocking(self.0.base, from, to, erase_sector_with_critical_section) } } } - impl embedded_storage::nor_flash::ErrorType for crate::_generated::flash_regions::$type_name<'_> { + impl embedded_storage::nor_flash::ErrorType for crate::_generated::flash_regions::$type_name<'_, MODE> { type Error = Error; } - impl embedded_storage::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_> { + impl embedded_storage::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_, Blocking> { const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) + self.read_blocking(offset, bytes) } fn capacity(&self) -> usize { self.0.size as usize } } + + impl embedded_storage::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_, Blocking> { + const WRITE_SIZE: usize = $write_size; + const ERASE_SIZE: usize = $erase_size; + + fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write_blocking(offset, bytes) + } + + fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase_blocking(from, to) + } + } }; } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 084bbdc6..d50a35b4 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -11,6 +11,8 @@ use crate::pac; #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] mod alt_regions { + use core::marker::PhantomData; + use embassy_hal_common::PeripheralRef; use stm32_metapac::FLASH_SIZE; @@ -18,8 +20,7 @@ mod alt_regions { #[cfg(feature = "nightly")] use crate::flash::asynch; use crate::flash::{ - common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, READ_SIZE, - REGION_ACCESS, + common, Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion, READ_SIZE, }; use crate::peripherals::FLASH; @@ -53,101 +54,86 @@ mod alt_regions { &ALT_BANK2_REGION3, ]; - pub struct AltBank1Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); - pub struct AltBank2Region1<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); - pub struct AltBank2Region2<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); - pub struct AltBank2Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); + pub struct AltBank1Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region1<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region2<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); - pub type BlockingAltBank1Region3<'d> = - BlockingFlashRegion<'d, { ALT_BANK1_REGION3.write_size }, { ALT_BANK1_REGION3.erase_size }>; - pub type BlockingAltBank2Region1<'d> = - BlockingFlashRegion<'d, { ALT_BANK2_REGION1.write_size }, { ALT_BANK2_REGION1.erase_size }>; - pub type BlockingAltBank2Region2<'d> = - BlockingFlashRegion<'d, { ALT_BANK2_REGION2.write_size }, { ALT_BANK2_REGION2.erase_size }>; - pub type BlockingAltBank2Region3<'d> = - BlockingFlashRegion<'d, { ALT_BANK2_REGION3.write_size }, { ALT_BANK2_REGION3.erase_size }>; - - pub struct AltFlashLayout<'d> { - pub bank1_region1: Bank1Region1<'d>, - pub bank1_region2: Bank1Region2<'d>, - pub bank1_region3: AltBank1Region3<'d>, - pub bank2_region1: AltBank2Region1<'d>, - pub bank2_region2: AltBank2Region2<'d>, - pub bank2_region3: AltBank2Region3<'d>, - pub otp_region: OTPRegion<'d>, + pub struct AltFlashLayout<'d, MODE> { + pub bank1_region1: Bank1Region1<'d, MODE>, + pub bank1_region2: Bank1Region2<'d, MODE>, + pub bank1_region3: AltBank1Region3<'d, MODE>, + pub bank2_region1: AltBank2Region1<'d, MODE>, + pub bank2_region2: AltBank2Region2<'d, MODE>, + pub bank2_region3: AltBank2Region3<'d, MODE>, + pub otp_region: OTPRegion<'d, MODE>, } impl<'d> Flash<'d> { - pub fn into_alt_regions(self) -> AltFlashLayout<'d> { + pub fn into_alt_regions(self) -> AltFlashLayout<'d, Async> { + unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; + + // SAFETY: We never expose the cloned peripheral references, and their instance is not public. + // Also, all async flash region operations are protected with a mutex. + let p = self.inner; + AltFlashLayout { + bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }, PhantomData), + bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }, PhantomData), + bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData), + otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }, PhantomData), + } + } + + pub fn into_alt_blocking_regions(self) -> AltFlashLayout<'d, Blocking> { unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; // SAFETY: We never expose the cloned peripheral references, and their instance is not public. // Also, all blocking flash region operations are protected with a cs. let p = self.inner; AltFlashLayout { - bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }), - bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }), - bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }), - bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }), - bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }), - bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }), - otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }), + bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }, PhantomData), + bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }, PhantomData), + bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData), + otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }, PhantomData), } } } macro_rules! foreach_altflash_region { ($type_name:ident, $region:ident) => { - impl $type_name<'_> { - pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + #[cfg(feature = "nightly")] + impl $type_name<'_, Async> { + pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { common::read_blocking(self.0.base, self.0.size, offset, bytes) } - #[cfg(feature = "nightly")] pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - let _guard = REGION_ACCESS.lock().await; + let _guard = asynch::REGION_ACCESS.lock().await; unsafe { asynch::write_chunked(self.0.base, self.0.size, offset, bytes).await } } - #[cfg(feature = "nightly")] pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - let _guard = REGION_ACCESS.lock().await; + let _guard = asynch::REGION_ACCESS.lock().await; unsafe { asynch::erase_sectored(self.0.base, from, to).await } } - - pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; - unsafe { common::write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } - } - - pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; - unsafe { common::erase_sectored_blocking(self.0.base, from, to) } - } } - impl embedded_storage::nor_flash::ErrorType for $type_name<'_> { + impl embedded_storage::nor_flash::ErrorType for $type_name<'_, Async> { type Error = Error; } - impl embedded_storage::nor_flash::ReadNorFlash for $type_name<'_> { - const READ_SIZE: usize = READ_SIZE; - - fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) - } - - fn capacity(&self) -> usize { - self.0.size as usize - } - } - #[cfg(feature = "nightly")] - impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_> { + impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_, Async> { const READ_SIZE: usize = READ_SIZE; async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) + self.read(offset, bytes).await } fn capacity(&self) -> usize { @@ -156,7 +142,7 @@ mod alt_regions { } #[cfg(feature = "nightly")] - impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_> { + impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_, Async> { const WRITE_SIZE: usize = $region.write_size as usize; const ERASE_SIZE: usize = $region.erase_size as usize; diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 1ef04e56..56a680a8 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -14,6 +14,9 @@ pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; pub const READ_SIZE: usize = 1; +pub struct Blocking; +pub struct Async; + #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct FlashRegion { From 8b13a7b33874483783cfd5be8fcbd73c888cd906 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 17:31:35 +0200 Subject: [PATCH 08/47] Align examples --- examples/stm32f3/src/bin/flash.rs | 12 ++++++------ examples/stm32f7/src/bin/flash.rs | 12 ++++++------ examples/stm32h7/src/bin/flash.rs | 12 ++++++------ examples/stm32l0/src/bin/flash.rs | 12 ++++++------ examples/stm32l1/src/bin/flash.rs | 12 ++++++------ examples/stm32wl/src/bin/flash.rs | 12 ++++++------ 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/examples/stm32f3/src/bin/flash.rs b/examples/stm32f3/src/bin/flash.rs index 0e5fb065..befae0a1 100644 --- a/examples/stm32f3/src/bin/flash.rs +++ b/examples/stm32f3/src/bin/flash.rs @@ -14,27 +14,27 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 2048)); + unwrap!(f.erase_blocking(ADDR, ADDR + 2048)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } diff --git a/examples/stm32f7/src/bin/flash.rs b/examples/stm32f7/src/bin/flash.rs index 717c82e8..5507e731 100644 --- a/examples/stm32f7/src/bin/flash.rs +++ b/examples/stm32f7/src/bin/flash.rs @@ -18,23 +18,23 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region3.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region3; info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 256 * 1024)); + unwrap!(f.erase_blocking(ADDR, ADDR + 256 * 1024)); info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write( + unwrap!(f.write_blocking( ADDR, &[ 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, @@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!( &buf[..], diff --git a/examples/stm32h7/src/bin/flash.rs b/examples/stm32h7/src/bin/flash.rs index aab72cae..fe6dad24 100644 --- a/examples/stm32h7/src/bin/flash.rs +++ b/examples/stm32h7/src/bin/flash.rs @@ -18,23 +18,23 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank2_region.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank2_region; info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 128 * 1024)); + unwrap!(f.erase_blocking(ADDR, ADDR + 128 * 1024)); info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write( + unwrap!(f.write_blocking( ADDR, &[ 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, @@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!( &buf[..], diff --git a/examples/stm32l0/src/bin/flash.rs b/examples/stm32l0/src/bin/flash.rs index 0ed0d05f..4182c87b 100644 --- a/examples/stm32l0/src/bin/flash.rs +++ b/examples/stm32l0/src/bin/flash.rs @@ -14,27 +14,27 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 128)); + unwrap!(f.erase_blocking(ADDR, ADDR + 128)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } diff --git a/examples/stm32l1/src/bin/flash.rs b/examples/stm32l1/src/bin/flash.rs index c4d7d029..53052e7c 100644 --- a/examples/stm32l1/src/bin/flash.rs +++ b/examples/stm32l1/src/bin/flash.rs @@ -14,27 +14,27 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 256)); + unwrap!(f.erase_blocking(ADDR, ADDR + 256)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs index df51ceb6..e03b69b8 100644 --- a/examples/stm32wl/src/bin/flash.rs +++ b/examples/stm32wl/src/bin/flash.rs @@ -14,27 +14,27 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x36000; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 2048)); + unwrap!(f.erase_blocking(ADDR, ADDR + 2048)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } From 9370973846310d013f5be586a4e37031fcb21a16 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 17:35:49 +0200 Subject: [PATCH 09/47] Remove TryLockError, --- embassy-stm32/src/flash/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 56a680a8..02f6c532 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -83,7 +83,6 @@ pub enum Error { Protected, Unaligned, Parallelism, - TryLockError, } impl NorFlashError for Error { From e65ff85b88deef3e32cc437d28e36274b82ce03e Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 23:51:48 +0200 Subject: [PATCH 10/47] Default to Async mode --- embassy-stm32/build.rs | 4 ++-- embassy-stm32/src/flash/f4.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 29af3c80..b766f073 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -213,7 +213,7 @@ fn main() { let region_type = format_ident!("{}", get_flash_region_type_name(region.name)); flash_regions.extend(quote! { #[cfg(flash)] - pub struct #region_type<'d, MODE>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData); + pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData); }); } @@ -238,7 +238,7 @@ fn main() { let regions_len = flash_memory_regions.len(); flash_regions.extend(quote! { #[cfg(flash)] - pub struct FlashLayout<'d, MODE> { + pub struct FlashLayout<'d, MODE = crate::flash::Async> { #(#fields),*, _mode: core::marker::PhantomData, } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index d50a35b4..3d696223 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -54,12 +54,12 @@ mod alt_regions { &ALT_BANK2_REGION3, ]; - pub struct AltBank1Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); - pub struct AltBank2Region1<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); - pub struct AltBank2Region2<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); - pub struct AltBank2Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank1Region3<'d, MODE = Async>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region1<'d, MODE = Async>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region2<'d, MODE = Async>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region3<'d, MODE = Async>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); - pub struct AltFlashLayout<'d, MODE> { + pub struct AltFlashLayout<'d, MODE = Async> { pub bank1_region1: Bank1Region1<'d, MODE>, pub bank1_region2: Bank1Region2<'d, MODE>, pub bank1_region3: AltBank1Region3<'d, MODE>, From cd8198037fa37db9af7e9dde1e00122df9ed15a3 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 13:08:40 +0200 Subject: [PATCH 11/47] Actually transition to dual bank mode - key was required --- embassy-stm32/src/flash/f4.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 3d696223..50ab446b 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -71,7 +71,7 @@ mod alt_regions { impl<'d> Flash<'d> { pub fn into_alt_regions(self) -> AltFlashLayout<'d, Async> { - unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; + super::set_alt_layout(); // SAFETY: We never expose the cloned peripheral references, and their instance is not public. // Also, all async flash region operations are protected with a mutex. @@ -88,7 +88,7 @@ mod alt_regions { } pub fn into_alt_blocking_regions(self) -> AltFlashLayout<'d, Blocking> { - unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; + super::set_alt_layout(); // SAFETY: We never expose the cloned peripheral references, and their instance is not public. // Also, all blocking flash region operations are protected with a cs. @@ -171,12 +171,31 @@ static WAKER: AtomicWaker = AtomicWaker::new(); #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub fn set_default_layout() { - unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(false)) }; + unsafe { + pac::FLASH.optkeyr().write(|w| w.set_optkey(0x08192A3B)); + pac::FLASH.optkeyr().write(|w| w.set_optkey(0x4C5D6E7F)); + pac::FLASH.optcr().modify(|r| { + r.set_db1m(false); + r.set_optlock(true) + }); + }; } #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)))] pub const fn set_default_layout() {} +#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] +fn set_alt_layout() { + unsafe { + pac::FLASH.optkeyr().write(|w| w.set_optkey(0x08192A3B)); + pac::FLASH.optkeyr().write(|w| w.set_optkey(0x4C5D6E7F)); + pac::FLASH.optcr().modify(|r| { + r.set_db1m(true); + r.set_optlock(true) + }); + }; +} + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub fn get_flash_regions() -> &'static [&'static FlashRegion] { if unsafe { pac::FLASH.optcr().read().db1m() } { @@ -207,8 +226,8 @@ pub(crate) unsafe fn lock() { } pub(crate) unsafe fn unlock() { - pac::FLASH.keyr().write(|w| w.set_key(0x4567_0123)); - pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); + pac::FLASH.keyr().write(|w| w.set_key(0x45670123)); + pac::FLASH.keyr().write(|w| w.set_key(0xCDEF89AB)); } #[cfg(feature = "nightly")] From baf1c2efbe0b218f86b491b88e48531fde691851 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 13:42:42 +0200 Subject: [PATCH 12/47] Align with new bind_interrupt --- embassy-stm32/src/flash/asynch.rs | 3 ++ embassy-stm32/src/flash/common.rs | 41 +++++++++++++++---- embassy-stm32/src/flash/f0.rs | 2 +- embassy-stm32/src/flash/f3.rs | 2 +- embassy-stm32/src/flash/f4.rs | 2 +- embassy-stm32/src/flash/f7.rs | 2 +- embassy-stm32/src/flash/h7.rs | 2 +- embassy-stm32/src/flash/l.rs | 2 +- embassy-stm32/src/flash/other.rs | 2 +- examples/boot/application/rp/src/bin/a.rs | 2 +- .../boot/application/stm32f3/src/bin/a.rs | 2 +- .../boot/application/stm32f7/src/bin/a.rs | 2 +- .../boot/application/stm32h7/src/bin/a.rs | 2 +- .../boot/application/stm32l0/src/bin/a.rs | 2 +- .../boot/application/stm32l1/src/bin/a.rs | 2 +- .../boot/application/stm32l4/src/bin/a.rs | 2 +- .../boot/application/stm32wl/src/bin/a.rs | 2 +- examples/boot/bootloader/stm32/src/main.rs | 3 +- examples/stm32f3/src/bin/flash.rs | 4 +- examples/stm32f4/src/bin/flash.rs | 4 +- examples/stm32f4/src/bin/flash_async.rs | 10 +++-- examples/stm32h7/src/bin/flash.rs | 4 +- examples/stm32l0/src/bin/flash.rs | 4 +- examples/stm32l1/src/bin/flash.rs | 4 +- examples/stm32wl/src/bin/flash.rs | 4 +- 25 files changed, 71 insertions(+), 40 deletions(-) diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 3564bbff..017fb17f 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -12,15 +12,18 @@ pub(super) static REGION_ACCESS: Mutex = Mutex::new impl<'d> Flash<'d> { pub fn into_regions(self) -> FlashLayout<'d, Async> { + assert!(!self.blocking_only); family::set_default_layout(); FlashLayout::new(self.inner) } pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + assert!(!self.blocking_only); unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await } } pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + assert!(!self.blocking_only); unsafe { erase_sectored(FLASH_BASE as u32, from, to).await } } } diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 8b38745c..0a1ee516 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -1,5 +1,5 @@ use atomic_polyfill::{fence, Ordering}; -use embassy_cortex_m::interrupt::InterruptExt; +use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use stm32_metapac::FLASH_BASE; @@ -9,21 +9,37 @@ use super::{ WRITE_SIZE, }; use crate::peripherals::FLASH; -use crate::Peripheral; +use crate::{interrupt, Peripheral}; pub struct Flash<'d> { pub(crate) inner: PeripheralRef<'d, FLASH>, + pub(crate) blocking_only: bool, } impl<'d> Flash<'d> { - pub fn new(p: impl Peripheral

+ 'd, irq: impl Peripheral

+ 'd) -> Self { - into_ref!(p, irq); + pub fn new( + p: impl Peripheral

+ 'd, + _irq: impl interrupt::Binding + 'd, + ) -> Self { + into_ref!(p); - irq.set_handler(family::on_interrupt); - irq.unpend(); - irq.enable(); + let flash_irq = unsafe { crate::interrupt::FLASH::steal() }; + flash_irq.unpend(); + flash_irq.enable(); - Self { inner: p } + Self { + inner: p, + blocking_only: false, + } + } + + pub fn new_blocking_only(p: impl Peripheral

+ 'd) -> Self { + into_ref!(p); + + Self { + inner: p, + blocking_only: true, + } } pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> { @@ -52,6 +68,15 @@ impl<'d> Flash<'d> { } } +/// Interrupt handler +pub struct InterruptHandler; + +impl interrupt::Handler for InterruptHandler { + unsafe fn on_interrupt() { + family::on_interrupt(); + } +} + pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index ecf3a698..cd17486e 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -13,7 +13,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index fd778f2b..4ce39128 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -13,7 +13,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 50ab446b..2b047264 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -210,7 +210,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { // Clear IRQ flags pac::FLASH.sr().write(|w| { w.set_operr(true); diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index a0593b14..ab518bf8 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs @@ -12,7 +12,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 865f1328..d6818d59 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -17,7 +17,7 @@ pub fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index f8a0dac4..c2394e0c 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -12,7 +12,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index e21b0b24..e569951f 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs @@ -8,7 +8,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs index e3ac634c..2b84ec61 100644 --- a/examples/boot/application/rp/src/bin/a.rs +++ b/examples/boot/application/rp/src/bin/a.rs @@ -26,7 +26,7 @@ async fn main(_s: Spawner) { let mut watchdog = Watchdog::new(p.WATCHDOG); watchdog.start(Duration::from_secs(8)); - let mut flash: Flash<_, FLASH_SIZE> = Flash::new(p.FLASH); + let mut flash: Flash<_, FLASH_SIZE> = Flash::new_blocking_only(p.FLASH); let mut updater = FirmwareUpdater::default(); diff --git a/examples/boot/application/stm32f3/src/bin/a.rs b/examples/boot/application/stm32f3/src/bin/a.rs index d92d59b2..a69b6327 100644 --- a/examples/boot/application/stm32f3/src/bin/a.rs +++ b/examples/boot/application/stm32f3/src/bin/a.rs @@ -17,7 +17,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new(p.FLASH); + let flash = Flash::new_blocking_only(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PC13, Pull::Up); diff --git a/examples/boot/application/stm32f7/src/bin/a.rs b/examples/boot/application/stm32f7/src/bin/a.rs index 79ab80e0..1f55db93 100644 --- a/examples/boot/application/stm32f7/src/bin/a.rs +++ b/examples/boot/application/stm32f7/src/bin/a.rs @@ -16,7 +16,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let mut flash = Flash::new(p.FLASH); + let mut flash = Flash::new_blocking_only(p.FLASH); let button = Input::new(p.PC13, Pull::Down); let mut button = ExtiInput::new(button, p.EXTI13); diff --git a/examples/boot/application/stm32h7/src/bin/a.rs b/examples/boot/application/stm32h7/src/bin/a.rs index 8b452be3..b8617c3b 100644 --- a/examples/boot/application/stm32h7/src/bin/a.rs +++ b/examples/boot/application/stm32h7/src/bin/a.rs @@ -16,7 +16,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let mut flash = Flash::new(p.FLASH); + let mut flash = Flash::new_blocking_only(p.FLASH); let button = Input::new(p.PC13, Pull::Down); let mut button = ExtiInput::new(button, p.EXTI13); diff --git a/examples/boot/application/stm32l0/src/bin/a.rs b/examples/boot/application/stm32l0/src/bin/a.rs index 59ca3438..c6663563 100644 --- a/examples/boot/application/stm32l0/src/bin/a.rs +++ b/examples/boot/application/stm32l0/src/bin/a.rs @@ -18,7 +18,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new(p.FLASH); + let flash = Flash::new_blocking_only(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PB2, Pull::Up); diff --git a/examples/boot/application/stm32l1/src/bin/a.rs b/examples/boot/application/stm32l1/src/bin/a.rs index 59ca3438..c6663563 100644 --- a/examples/boot/application/stm32l1/src/bin/a.rs +++ b/examples/boot/application/stm32l1/src/bin/a.rs @@ -18,7 +18,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new(p.FLASH); + let flash = Flash::new_blocking_only(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PB2, Pull::Up); diff --git a/examples/boot/application/stm32l4/src/bin/a.rs b/examples/boot/application/stm32l4/src/bin/a.rs index 6cddc6cc..86936222 100644 --- a/examples/boot/application/stm32l4/src/bin/a.rs +++ b/examples/boot/application/stm32l4/src/bin/a.rs @@ -17,7 +17,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new(p.FLASH); + let flash = Flash::new_blocking_only(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PC13, Pull::Up); diff --git a/examples/boot/application/stm32wl/src/bin/a.rs b/examples/boot/application/stm32wl/src/bin/a.rs index 1ff47edd..2982e8df 100644 --- a/examples/boot/application/stm32wl/src/bin/a.rs +++ b/examples/boot/application/stm32wl/src/bin/a.rs @@ -17,7 +17,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new(p.FLASH); + let flash = Flash::new_blocking_only(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PA0, Pull::Up); diff --git a/examples/boot/bootloader/stm32/src/main.rs b/examples/boot/bootloader/stm32/src/main.rs index 49c21920..5e8a4f2b 100644 --- a/examples/boot/bootloader/stm32/src/main.rs +++ b/examples/boot/bootloader/stm32/src/main.rs @@ -20,8 +20,7 @@ fn main() -> ! { */ let mut bl: BootLoader<2048> = BootLoader::default(); - let flash = Flash::new(p.FLASH); - let layout = flash.into_regions(); + let layout = Flash::new_blocking_only(p.FLASH).into_blocking_regions(); let mut flash = BootFlash::new(layout.bank1_region); let start = bl.prepare(&mut SingleFlashConfig::new(&mut flash)); core::mem::drop(flash); diff --git a/examples/stm32f3/src/bin/flash.rs b/examples/stm32f3/src/bin/flash.rs index befae0a1..9a31b548 100644 --- a/examples/stm32f3/src/bin/flash.rs +++ b/examples/stm32f3/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index de4ecdb8..455af930 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { // Once can also call `into_regions()` to get access to NorFlash implementations // for each of the unique characteristics. - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)); + let mut f = Flash::new_blocking_only(p.FLASH); // Sector 5 test_flash(&mut f, 128 * 1024, 128 * 1024); diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs index c9d9df34..67533708 100644 --- a/examples/stm32f4/src/bin/flash_async.rs +++ b/examples/stm32f4/src/bin/flash_async.rs @@ -5,17 +5,21 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; use embassy_time::{Timer, Duration}; -use embassy_stm32::flash::Flash; +use embassy_stm32::flash::{Flash, InterruptHandler}; use embassy_stm32::gpio::{AnyPin, Level, Output, Pin, Speed}; -use embassy_stm32::{interrupt}; +use embassy_stm32::bind_interrupts; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + FLASH => InterruptHandler; +}); + #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello Flash!"); - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)); + let mut f = Flash::new(p.FLASH, Irqs); // Led should blink uninterrupted during ~2sec erase operation spawner.spawn(blinky(p.PB7.degrade())).unwrap(); diff --git a/examples/stm32h7/src/bin/flash.rs b/examples/stm32h7/src/bin/flash.rs index fe6dad24..c0c332c3 100644 --- a/examples/stm32h7/src/bin/flash.rs +++ b/examples/stm32h7/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -18,7 +18,7 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank2_region; + let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank2_region; info!("Reading..."); let mut buf = [0u8; 32]; diff --git a/examples/stm32l0/src/bin/flash.rs b/examples/stm32l0/src/bin/flash.rs index 4182c87b..57ccf7f5 100644 --- a/examples/stm32l0/src/bin/flash.rs +++ b/examples/stm32l0/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32l1/src/bin/flash.rs b/examples/stm32l1/src/bin/flash.rs index 53052e7c..71174bfb 100644 --- a/examples/stm32l1/src/bin/flash.rs +++ b/examples/stm32l1/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs index e03b69b8..51bd0db4 100644 --- a/examples/stm32wl/src/bin/flash.rs +++ b/examples/stm32wl/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x36000; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; From 8b1eaf00a0fd24459407a70e76bdbc16983b9af6 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 13:54:40 +0200 Subject: [PATCH 13/47] Simplify SR->Result --- embassy-stm32/src/flash/f4.rs | 45 +++++++++++++---------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 2b047264..53e58835 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -4,6 +4,7 @@ use core::sync::atomic::{fence, Ordering}; #[cfg(feature = "nightly")] use embassy_sync::waitqueue::AtomicWaker; +use pac::flash::regs::Sr; use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; @@ -347,17 +348,7 @@ pub(crate) async unsafe fn wait_ready() -> Result<(), Error> { let sr = pac::FLASH.sr().read(); if !sr.bsy() { - Poll::Ready(if sr.pgserr() { - Err(Error::Seq) - } else if sr.pgperr() { - Err(Error::Parallelism) - } else if sr.pgaerr() { - Err(Error::Unaligned) - } else if sr.wrperr() { - Err(Error::Protected) - } else { - Ok(()) - }) + Poll::Ready(get_result(sr)) } else { return Poll::Pending; } @@ -370,27 +361,25 @@ unsafe fn wait_ready_blocking() -> Result<(), Error> { let sr = pac::FLASH.sr().read(); if !sr.bsy() { - if sr.pgserr() { - return Err(Error::Seq); - } - - if sr.pgperr() { - return Err(Error::Parallelism); - } - - if sr.pgaerr() { - return Err(Error::Unaligned); - } - - if sr.wrperr() { - return Err(Error::Protected); - } - - return Ok(()); + return get_result(sr); } } } +fn get_result(sr: Sr) -> Result<(), Error> { + if sr.pgserr() { + Err(Error::Seq) + } else if sr.pgperr() { + Err(Error::Parallelism) + } else if sr.pgaerr() { + Err(Error::Unaligned) + } else if sr.wrperr() { + Err(Error::Protected) + } else { + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; From c02759ad91994191944b4fd1a4b47cd310416c04 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 13:59:32 +0200 Subject: [PATCH 14/47] Fix unused errors --- embassy-stm32/src/flash/common.rs | 3 +++ embassy-stm32/src/flash/f4.rs | 8 +++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 0a1ee516..547e3031 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -13,6 +13,7 @@ use crate::{interrupt, Peripheral}; pub struct Flash<'d> { pub(crate) inner: PeripheralRef<'d, FLASH>, + #[cfg(all(feature = "nightly", flash_f4))] pub(crate) blocking_only: bool, } @@ -29,6 +30,7 @@ impl<'d> Flash<'d> { Self { inner: p, + #[cfg(all(feature = "nightly", flash_f4))] blocking_only: false, } } @@ -38,6 +40,7 @@ impl<'d> Flash<'d> { Self { inner: p, + #[cfg(all(feature = "nightly", flash_f4))] blocking_only: true, } } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 53e58835..aa3433b2 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -20,9 +20,7 @@ mod alt_regions { use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; #[cfg(feature = "nightly")] use crate::flash::asynch; - use crate::flash::{ - common, Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion, READ_SIZE, - }; + use crate::flash::{Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion}; use crate::peripherals::FLASH; pub const ALT_BANK1_REGION3: FlashRegion = FlashRegion { @@ -111,7 +109,7 @@ mod alt_regions { #[cfg(feature = "nightly")] impl $type_name<'_, Async> { pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - common::read_blocking(self.0.base, self.0.size, offset, bytes) + crate::flash::common::read_blocking(self.0.base, self.0.size, offset, bytes) } pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { @@ -131,7 +129,7 @@ mod alt_regions { #[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_, Async> { - const READ_SIZE: usize = READ_SIZE; + const READ_SIZE: usize = crate::flash::READ_SIZE; async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { self.read(offset, bytes).await From 0e90e98e9b477302a3cd2550dbd438907ed10ca6 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 12:17:12 +0200 Subject: [PATCH 15/47] stm32: Add async flash write/erase to f4 --- embassy-stm32/Cargo.toml | 4 +- embassy-stm32/src/flash/asynch.rs | 129 +++++++++++++++ embassy-stm32/src/flash/common.rs | 267 ++++++++++++++++-------------- embassy-stm32/src/flash/f0.rs | 18 +- embassy-stm32/src/flash/f3.rs | 18 +- embassy-stm32/src/flash/f4.rs | 183 +++++++++++++++++--- embassy-stm32/src/flash/f7.rs | 21 +-- embassy-stm32/src/flash/h7.rs | 21 +-- embassy-stm32/src/flash/l.rs | 19 ++- embassy-stm32/src/flash/mod.rs | 49 ++++++ embassy-stm32/src/flash/other.rs | 12 +- 11 files changed, 547 insertions(+), 194 deletions(-) create mode 100644 embassy-stm32/src/flash/asynch.rs diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 0d7e03bf..73841bdc 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -47,6 +47,7 @@ embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true} embedded-hal-nb = { version = "=1.0.0-alpha.2", optional = true} embedded-storage = "0.3.0" +embedded-storage-async = { version = "0.4.0", optional = true } defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } @@ -68,6 +69,7 @@ cfg-if = "1.0.0" embedded-io = { version = "0.4.0", features = ["async"], optional = true } chrono = { version = "^0.4", default-features = false, optional = true} bit_field = "0.10.2" +paste = "1.0.12" [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } @@ -98,7 +100,7 @@ time-driver-tim12 = ["_time-driver"] time-driver-tim15 = ["_time-driver"] # Enable nightly-only features -nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"] +nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"] # Reexport stm32-metapac at `embassy_stm32::pac`. # This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version. diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs new file mode 100644 index 00000000..44e23d9c --- /dev/null +++ b/embassy-stm32/src/flash/asynch.rs @@ -0,0 +1,129 @@ +use atomic_polyfill::{fence, Ordering}; +use embassy_hal_common::drop::OnDrop; + +use super::{ + ensure_sector_aligned, family, get_sector, Error, Flash, FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, + REGION_ACCESS, WRITE_SIZE, +}; + +impl<'d> Flash<'d> { + pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await } + } + + pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + unsafe { erase_sectored(FLASH_BASE as u32, from, to).await } + } +} + +impl embedded_storage_async::nor_flash::NorFlash for Flash<'_> { + const WRITE_SIZE: usize = WRITE_SIZE; + const ERASE_SIZE: usize = MAX_ERASE_SIZE; + + async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(offset, bytes).await + } + + async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase(from, to).await + } +} + +pub(super) async unsafe fn write_chunked(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { + if offset + bytes.len() as u32 > size { + return Err(Error::Size); + } + if offset % WRITE_SIZE as u32 != 0 || bytes.len() % WRITE_SIZE != 0 { + return Err(Error::Unaligned); + } + + let mut address = base + offset; + trace!("Writing {} bytes at 0x{:x}", bytes.len(), address); + + for chunk in bytes.chunks(WRITE_SIZE) { + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); + family::enable_write(); + fence(Ordering::SeqCst); + + let _on_drop = OnDrop::new(|| { + family::disable_write(); + fence(Ordering::SeqCst); + family::lock(); + }); + + family::write(address, chunk.try_into().unwrap()).await?; + address += WRITE_SIZE as u32; + } + Ok(()) +} + +pub(super) async unsafe fn erase_sectored(base: u32, from: u32, to: u32) -> Result<(), Error> { + let start_address = base + from; + let end_address = base + to; + let regions = family::get_flash_regions(); + + ensure_sector_aligned(start_address, end_address, regions)?; + + trace!("Erasing from 0x{:x} to 0x{:x}", start_address, end_address); + + let mut address = start_address; + while address < end_address { + let sector = get_sector(address, regions); + trace!("Erasing sector: {:?}", sector); + + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); + + let _on_drop = OnDrop::new(|| family::lock()); + + family::erase_sector(§or).await?; + address += sector.size; + } + Ok(()) +} + +foreach_flash_region! { + ($type_name:ident, $write_size:literal, $erase_size:literal) => { + impl crate::_generated::flash_regions::$type_name<'_> { + pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + let _guard = REGION_ACCESS.lock().await; + unsafe { write_chunked(self.0.base, self.0.size, offset, bytes).await } + } + + pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + let _guard = REGION_ACCESS.lock().await; + unsafe { erase_sectored(self.0.base, from, to).await } + } + } + + impl embedded_storage_async::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_> { + const READ_SIZE: usize = READ_SIZE; + + async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read(offset, bytes) + } + + fn capacity(&self) -> usize { + self.0.size as usize + } + } + + impl embedded_storage_async::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_> { + const WRITE_SIZE: usize = $write_size; + const ERASE_SIZE: usize = $erase_size; + + async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(offset, bytes).await + } + + async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase(from, to).await + } + } + }; +} diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 432c8a43..990104a3 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -1,44 +1,55 @@ use atomic_polyfill::{fence, Ordering}; +use embassy_cortex_m::interrupt::InterruptExt; +use embassy_futures::block_on; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::mutex::Mutex; +use stm32_metapac::FLASH_BASE; -use super::{family, Error, FlashLayout, FlashRegion, FlashSector, FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, WRITE_SIZE}; -use crate::flash::FlashBank; +use super::{ + ensure_sector_aligned, family, get_sector, Error, FlashLayout, FlashRegion, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, + WRITE_SIZE, +}; +use crate::peripherals::FLASH; use crate::Peripheral; pub struct Flash<'d> { - inner: PeripheralRef<'d, crate::peripherals::FLASH>, + pub(crate) inner: PeripheralRef<'d, FLASH>, } +pub(crate) static REGION_ACCESS: Mutex = Mutex::new(()); + impl<'d> Flash<'d> { - pub fn new(p: impl Peripheral

+ 'd) -> Self { - into_ref!(p); + pub fn new(p: impl Peripheral

+ 'd, irq: impl Peripheral

+ 'd) -> Self { + into_ref!(p, irq); + + irq.set_handler(family::on_interrupt); + irq.unpend(); + irq.enable(); + Self { inner: p } } pub fn into_regions(self) -> FlashLayout<'d> { family::set_default_layout(); - FlashLayout::new(self.release()) + FlashLayout::new(self.inner) } - pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - blocking_read(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + read_blocking(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } - pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { blocking_write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } + pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + unsafe { write_chunked_blocking(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } } - pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { blocking_erase_sectored(FLASH_BASE as u32, from, to) } - } - - pub(crate) fn release(self) -> PeripheralRef<'d, crate::peripherals::FLASH> { - unsafe { self.inner.clone_unchecked() } + pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> { + unsafe { erase_sectored_blocking(FLASH_BASE as u32, from, to) } } } -pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { +pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); } @@ -49,7 +60,7 @@ pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) Ok(()) } -pub(super) unsafe fn blocking_write_chunked(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { +pub(super) unsafe fn write_chunked_blocking(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); } @@ -61,44 +72,31 @@ pub(super) unsafe fn blocking_write_chunked(base: u32, size: u32, offset: u32, b trace!("Writing {} bytes at 0x{:x}", bytes.len(), address); for chunk in bytes.chunks(WRITE_SIZE) { - critical_section::with(|_| { - family::clear_all_err(); - fence(Ordering::SeqCst); - family::unlock(); - fence(Ordering::SeqCst); - family::begin_write(); - fence(Ordering::SeqCst); + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); + family::enable_blocking_write(); + fence(Ordering::SeqCst); - let _on_drop = OnDrop::new(|| { - family::end_write(); - fence(Ordering::SeqCst); - family::lock(); - }); + let _on_drop = OnDrop::new(|| { + family::disable_blocking_write(); + fence(Ordering::SeqCst); + family::lock(); + }); - family::blocking_write(address, chunk.try_into().unwrap()) - })?; + family::write_blocking(address, chunk.try_into().unwrap())?; address += WRITE_SIZE as u32; } Ok(()) } -pub(super) unsafe fn blocking_erase_sectored(base: u32, from: u32, to: u32) -> Result<(), Error> { +pub(super) unsafe fn erase_sectored_blocking(base: u32, from: u32, to: u32) -> Result<(), Error> { let start_address = base + from; let end_address = base + to; 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 = get_sector(address, regions); - if sector.start != address { - return Err(Error::Unaligned); - } - address += sector.size; - } - if address != end_address { - return Err(Error::Unaligned); - } + ensure_sector_aligned(start_address, end_address, regions)?; trace!("Erasing from 0x{:x} to 0x{:x}", start_address, end_address); @@ -107,71 +105,28 @@ pub(super) unsafe fn blocking_erase_sectored(base: u32, from: u32, to: u32) -> R let sector = get_sector(address, regions); trace!("Erasing sector: {:?}", sector); - critical_section::with(|_| { - family::clear_all_err(); - fence(Ordering::SeqCst); - family::unlock(); - fence(Ordering::SeqCst); + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); - let _on_drop = OnDrop::new(|| { - family::lock(); - }); + let _on_drop = OnDrop::new(|| family::lock()); - family::blocking_erase_sector(§or) - })?; + family::erase_sector_blocking(§or)?; address += sector.size; } Ok(()) } -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> { - blocking_read(self.base, self.size, offset, bytes) - } - - pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { blocking_write_chunked(self.base, self.size, offset, bytes) } - } - - pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { blocking_erase_sectored(self.base, from, to) } - } -} - impl embedded_storage::nor_flash::ErrorType for Flash<'_> { type Error = Error; } impl embedded_storage::nor_flash::ReadNorFlash for Flash<'_> { - const READ_SIZE: usize = 1; + const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(offset, bytes) + self.read(offset, bytes) } fn capacity(&self) -> usize { @@ -184,27 +139,112 @@ impl embedded_storage::nor_flash::NorFlash for Flash<'_> { const ERASE_SIZE: usize = MAX_ERASE_SIZE; fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(offset, bytes) + self.write_blocking(offset, bytes) } fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.blocking_erase(from, to) + self.erase_blocking(from, to) + } +} + +#[cfg(feature = "nightly")] +impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_> { + const READ_SIZE: usize = READ_SIZE; + + async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read(offset, bytes) + } + + fn capacity(&self) -> usize { + FLASH_SIZE + } +} + +pub struct BlockingFlashRegion<'d, const WRITE_SIZE: u32, const ERASE_SIZE: u32>( + &'static FlashRegion, + PeripheralRef<'d, FLASH>, +); + +impl BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> { + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + read_blocking(self.0.base, self.0.size, offset, bytes) + } + + pub fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + let _guard = block_on(REGION_ACCESS.lock()); + unsafe { write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } + } + + pub fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + let _guard = block_on(REGION_ACCESS.lock()); + unsafe { erase_sectored_blocking(self.0.base, from, to) } + } +} + +impl embedded_storage::nor_flash::ErrorType + for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> +{ + type Error = Error; +} + +impl embedded_storage::nor_flash::ReadNorFlash + for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> +{ + const READ_SIZE: usize = READ_SIZE; + + fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read(offset, bytes) + } + + fn capacity(&self) -> usize { + self.0.size as usize + } +} + +impl embedded_storage::nor_flash::NorFlash + for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> +{ + const WRITE_SIZE: usize = WRITE_SIZE as usize; + const ERASE_SIZE: usize = ERASE_SIZE as usize; + + fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(offset, bytes) + } + + fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase(from, to) } } foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { - impl crate::_generated::flash_regions::$type_name<'_> { - pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - blocking_read(self.0.base, self.0.size, offset, bytes) + paste::paste! { + pub type []<'d> = BlockingFlashRegion<'d, $write_size, $erase_size>; + } + + impl<'d> crate::_generated::flash_regions::$type_name<'d> { + /// Make this flash region work in a blocking context. + /// + /// SAFETY + /// + /// This function is unsafe as incorect usage of parallel blocking operations + /// on multiple regions may cause a deadlock because each region requires mutual access to the flash. + pub unsafe fn into_blocking(self) -> BlockingFlashRegion<'d, $write_size, $erase_size> { + BlockingFlashRegion(self.0, self.1) } - pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { blocking_write_chunked(self.0.base, self.0.size, offset, bytes) } + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + read_blocking(self.0.base, self.0.size, offset, bytes) } - pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { blocking_erase_sectored(self.0.base, from, to) } + pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; + unsafe { write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } + } + + pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; + unsafe { erase_sectored_blocking(self.0.base, from, to) } } } @@ -213,28 +253,15 @@ foreach_flash_region! { } impl embedded_storage::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_> { - const READ_SIZE: usize = 1; + const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(offset, bytes) + self.read(offset, bytes) } fn capacity(&self) -> usize { self.0.size as usize } } - - impl embedded_storage::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_> { - const WRITE_SIZE: usize = $write_size; - const ERASE_SIZE: usize = $erase_size; - - fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(offset, bytes) - } - - fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.blocking_erase(from, to) - } - } }; } diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index c6441ef1..ecf3a698 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -13,6 +13,10 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } @@ -22,17 +26,17 @@ pub(crate) unsafe fn unlock() { pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 2); pac::FLASH.cr().write(|w| w.set_pg(true)); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for chunk in buf.chunks(2) { write_volatile(address as *mut u16, u16::from_le_bytes(chunk.try_into().unwrap())); @@ -42,10 +46,10 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - blocking_wait_ready() + wait_ready_blocking() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_per(true); }); @@ -56,7 +60,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let mut ret: Result<(), Error> = blocking_wait_ready(); + let mut ret: Result<(), Error> = wait_ready_blocking(); if !pac::FLASH.sr().read().eop() { trace!("FLASH: EOP not set"); @@ -88,7 +92,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn blocking_wait_ready() -> Result<(), Error> { +unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index 4c817220..fd778f2b 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -13,6 +13,10 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } @@ -22,17 +26,17 @@ pub(crate) unsafe fn unlock() { pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB)); } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 2); pac::FLASH.cr().write(|w| w.set_pg(true)); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for chunk in buf.chunks(2) { write_volatile(address as *mut u16, u16::from_le_bytes(chunk.try_into().unwrap())); @@ -42,10 +46,10 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - blocking_wait_ready() + wait_ready_blocking() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_per(true); }); @@ -56,7 +60,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let mut ret: Result<(), Error> = blocking_wait_ready(); + let mut ret: Result<(), Error> = wait_ready_blocking(); if !pac::FLASH.sr().read().eop() { trace!("FLASH: EOP not set"); @@ -88,7 +92,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn blocking_wait_ready() -> Result<(), Error> { +unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 7f1c5f67..3c8f81eb 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -2,6 +2,8 @@ use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; +use embassy_sync::waitqueue::AtomicWaker; + use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; @@ -13,8 +15,8 @@ mod alt_regions { use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; use crate::flash::{ - blocking_erase_sectored, blocking_read, blocking_write_chunked, Bank1Region1, Bank1Region2, Error, Flash, - FlashBank, FlashRegion, + asynch, common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, + READ_SIZE, REGION_ACCESS, }; use crate::peripherals::FLASH; @@ -53,6 +55,15 @@ mod alt_regions { pub struct AltBank2Region2<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); pub struct AltBank2Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); + pub type BlockingAltBank1Region3<'d> = + BlockingFlashRegion<'d, { ALT_BANK1_REGION3.write_size }, { ALT_BANK1_REGION3.erase_size }>; + pub type BlockingAltBank2Region1<'d> = + BlockingFlashRegion<'d, { ALT_BANK2_REGION1.write_size }, { ALT_BANK2_REGION1.erase_size }>; + pub type BlockingAltBank2Region2<'d> = + BlockingFlashRegion<'d, { ALT_BANK2_REGION2.write_size }, { ALT_BANK2_REGION2.erase_size }>; + pub type BlockingAltBank2Region3<'d> = + BlockingFlashRegion<'d, { ALT_BANK2_REGION3.write_size }, { ALT_BANK2_REGION3.erase_size }>; + pub struct AltFlashLayout<'d> { pub bank1_region1: Bank1Region1<'d>, pub bank1_region2: Bank1Region2<'d>, @@ -69,7 +80,7 @@ mod alt_regions { // SAFETY: We never expose the cloned peripheral references, and their instance is not public. // Also, all blocking flash region operations are protected with a cs. - let p = self.release(); + let p = self.inner; AltFlashLayout { bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }), bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }), @@ -85,16 +96,30 @@ mod alt_regions { macro_rules! foreach_altflash_region { ($type_name:ident, $region:ident) => { impl $type_name<'_> { - pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - blocking_read(self.0.base, self.0.size, offset, bytes) + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + common::read_blocking(self.0.base, self.0.size, offset, bytes) } - pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { blocking_write_chunked(self.0.base, self.0.size, offset, bytes) } + #[cfg(all(feature = "nightly"))] + pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + let _guard = REGION_ACCESS.lock().await; + unsafe { asynch::write_chunked(self.0.base, self.0.size, offset, bytes).await } } - pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { blocking_erase_sectored(self.0.base, from, to) } + #[cfg(all(feature = "nightly"))] + pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + let _guard = REGION_ACCESS.lock().await; + unsafe { asynch::erase_sectored(self.0.base, from, to).await } + } + + pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; + unsafe { common::write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } + } + + pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; + unsafe { common::erase_sectored_blocking(self.0.base, from, to) } } } @@ -103,10 +128,10 @@ mod alt_regions { } impl embedded_storage::nor_flash::ReadNorFlash for $type_name<'_> { - const READ_SIZE: usize = 1; + const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.blocking_read(offset, bytes) + self.read(offset, bytes) } fn capacity(&self) -> usize { @@ -114,16 +139,28 @@ mod alt_regions { } } - impl embedded_storage::nor_flash::NorFlash for $type_name<'_> { + impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_> { + const READ_SIZE: usize = READ_SIZE; + + async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read(offset, bytes) + } + + fn capacity(&self) -> usize { + self.0.size as usize + } + } + + impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_> { const WRITE_SIZE: usize = $region.write_size as usize; const ERASE_SIZE: usize = $region.erase_size as usize; - fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.blocking_write(offset, bytes) + async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(offset, bytes).await } - fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.blocking_erase(from, to) + async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase(from, to).await } } }; @@ -138,6 +175,9 @@ mod alt_regions { #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub use alt_regions::*; +#[cfg(feature = "nightly")] +static WAKER: AtomicWaker = AtomicWaker::new(); + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub fn set_default_layout() { unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(false)) }; @@ -160,6 +200,16 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + // Clear IRQ flags + pac::FLASH.sr().write(|w| { + w.set_operr(true); + w.set_eop(true); + }); + + WAKER.wake(); +} + pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } @@ -169,7 +219,28 @@ pub(crate) unsafe fn unlock() { pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); } -pub(crate) unsafe fn begin_write() { +#[cfg(feature = "nightly")] +pub(crate) unsafe fn enable_write() { + assert_eq!(0, WRITE_SIZE % 4); + + pac::FLASH.cr().write(|w| { + w.set_pg(true); + w.set_psize(pac::flash::vals::Psize::PSIZE32); + w.set_eopie(true); + w.set_errie(true); + }); +} + +#[cfg(feature = "nightly")] +pub(crate) unsafe fn disable_write() { + pac::FLASH.cr().write(|w| { + w.set_pg(false); + w.set_eopie(false); + w.set_errie(false); + }); +} + +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 4); pac::FLASH.cr().write(|w| { @@ -178,11 +249,22 @@ pub(crate) unsafe fn begin_write() { }); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +#[cfg(feature = "nightly")] +pub(crate) async unsafe fn write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { + write_start(start_address, buf); + wait_ready().await +} + +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { + write_start(start_address, buf); + wait_ready_blocking() +} + +unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) { let mut address = start_address; for val in buf.chunks(4) { write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); @@ -191,11 +273,32 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) // prevents parallelism errors fence(Ordering::SeqCst); } - - blocking_wait_ready() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> { + let snb = ((sector.bank as u8) << 4) + sector.index_in_bank; + + pac::FLASH.cr().modify(|w| { + w.set_ser(true); + w.set_snb(snb); + w.set_eopie(true); + w.set_errie(true); + }); + + pac::FLASH.cr().modify(|w| { + w.set_strt(true); + }); + + let ret: Result<(), Error> = wait_ready().await; + pac::FLASH.cr().modify(|w| { + w.set_eopie(false); + w.set_errie(false); + }); + clear_all_err(); + ret +} + +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { let snb = ((sector.bank as u8) << 4) + sector.index_in_bank; pac::FLASH.cr().modify(|w| { @@ -207,10 +310,8 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let ret: Result<(), Error> = blocking_wait_ready(); - + let ret: Result<(), Error> = wait_ready_blocking(); clear_all_err(); - ret } @@ -220,11 +321,39 @@ pub(crate) unsafe fn clear_all_err() { w.set_pgperr(true); w.set_pgaerr(true); w.set_wrperr(true); - w.set_eop(true); }); } -unsafe fn blocking_wait_ready() -> Result<(), Error> { +#[cfg(feature = "nightly")] +pub(crate) async unsafe fn wait_ready() -> Result<(), Error> { + use core::task::Poll; + + use futures::future::poll_fn; + + poll_fn(|cx| { + WAKER.register(cx.waker()); + + let sr = pac::FLASH.sr().read(); + if !sr.bsy() { + Poll::Ready(if sr.pgserr() { + Err(Error::Seq) + } else if sr.pgperr() { + Err(Error::Parallelism) + } else if sr.pgaerr() { + Err(Error::Unaligned) + } else if sr.wrperr() { + Err(Error::Protected) + } else { + Ok(()) + }) + } else { + return Poll::Pending; + } + }) + .await +} + +unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index ac2834a8..a0593b14 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs @@ -12,6 +12,10 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } @@ -21,7 +25,7 @@ pub(crate) unsafe fn unlock() { pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 4); pac::FLASH.cr().write(|w| { @@ -30,11 +34,11 @@ pub(crate) unsafe fn begin_write() { }); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); @@ -44,10 +48,10 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - blocking_wait_ready() + wait_ready_blocking() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_ser(true); w.set_snb(sector.index_in_bank) @@ -57,12 +61,9 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let ret: Result<(), Error> = blocking_wait_ready(); - + let ret: Result<(), Error> = wait_ready_blocking(); pac::FLASH.cr().modify(|w| w.set_ser(false)); - clear_all_err(); - ret } @@ -86,7 +87,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn blocking_wait_ready() -> Result<(), Error> { +unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 1b163106..865f1328 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -17,6 +17,10 @@ pub fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { pac::FLASH.bank(0).cr().modify(|w| w.set_lock(true)); if is_dual_bank() { @@ -33,13 +37,13 @@ pub(crate) unsafe fn unlock() { } } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 4); } -pub(crate) unsafe fn end_write() {} +pub(crate) unsafe fn disable_blocking_write() {} -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { // We cannot have the write setup sequence in begin_write as it depends on the address let bank = if start_address < BANK1_REGION.end() { pac::FLASH.bank(0) @@ -60,7 +64,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); address += val.len() as u32; - res = Some(blocking_wait_ready(bank)); + res = Some(wait_ready_blocking(bank)); bank.sr().modify(|w| { if w.eop() { w.set_eop(true); @@ -80,7 +84,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) res.unwrap() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { let bank = pac::FLASH.bank(sector.bank as usize); bank.cr().modify(|w| { w.set_ser(true); @@ -91,12 +95,9 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E w.set_start(true); }); - let ret: Result<(), Error> = blocking_wait_ready(bank); - + let ret: Result<(), Error> = wait_ready_blocking(bank); bank.cr().modify(|w| w.set_ser(false)); - bank_clear_all_err(bank); - ret } @@ -141,7 +142,7 @@ unsafe fn bank_clear_all_err(bank: pac::flash::Bank) { }); } -unsafe fn blocking_wait_ready(bank: pac::flash::Bank) -> Result<(), Error> { +unsafe fn wait_ready_blocking(bank: pac::flash::Bank) -> Result<(), Error> { loop { let sr = bank.sr().read(); diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index c94f6190..f8a0dac4 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -12,6 +12,10 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().modify(|w| w.set_lock(true)); @@ -41,19 +45,19 @@ pub(crate) unsafe fn unlock() { } } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 4); #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().write(|w| w.set_pg(true)); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); @@ -63,10 +67,10 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - blocking_wait_ready() + wait_ready_blocking() } -pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { #[cfg(any(flash_l0, flash_l1))] { pac::FLASH.pecr().modify(|w| { @@ -96,7 +100,7 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E }); } - let ret: Result<(), Error> = blocking_wait_ready(); + let ret: Result<(), Error> = wait_ready_blocking(); #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().modify(|w| w.set_per(false)); @@ -108,7 +112,6 @@ pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), E }); clear_all_err(); - ret } @@ -150,7 +153,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn blocking_wait_ready() -> Result<(), Error> { +unsafe fn wait_ready_blocking() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index b93270ae..e781f1b8 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -1,5 +1,7 @@ use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; +#[cfg(all(feature = "nightly", flash_f4))] +pub mod asynch; #[cfg(flash)] mod common; @@ -10,6 +12,8 @@ pub use crate::_generated::flash_regions::*; pub use crate::_generated::MAX_ERASE_SIZE; pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; +pub const READ_SIZE: usize = 1; + #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct FlashRegion { @@ -76,6 +80,7 @@ pub enum Error { Protected, Unaligned, Parallelism, + TryLockError, } impl NorFlashError for Error { @@ -87,3 +92,47 @@ impl NorFlashError for Error { } } } + +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"); +} + +pub(crate) fn ensure_sector_aligned( + start_address: u32, + end_address: u32, + regions: &[&FlashRegion], +) -> Result<(), Error> { + let mut address = start_address; + while address < end_address { + let sector = get_sector(address, regions); + if sector.start != address { + return Err(Error::Unaligned); + } + address += sector.size; + } + if address != end_address { + return Err(Error::Unaligned); + } + Ok(()) +} diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index 55603465..e21b0b24 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs @@ -8,22 +8,26 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +pub(crate) unsafe fn on_interrupt(_: *mut ()) { + unimplemented!(); +} + pub(crate) unsafe fn lock() { unimplemented!(); } pub(crate) unsafe fn unlock() { unimplemented!(); } -pub(crate) unsafe fn begin_write() { +pub(crate) unsafe fn enable_blocking_write() { unimplemented!(); } -pub(crate) unsafe fn end_write() { +pub(crate) unsafe fn disable_blocking_write() { unimplemented!(); } -pub(crate) unsafe fn blocking_write(_start_address: u32, _buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn write_blocking(_start_address: u32, _buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { unimplemented!(); } -pub(crate) unsafe fn blocking_erase_sector(_sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn erase_sector_blocking(_sector: &FlashSector) -> Result<(), Error> { unimplemented!(); } pub(crate) unsafe fn clear_all_err() { From 7477785bbb469a1d8d3cf21a74fd61cb12f59640 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 12:41:52 +0200 Subject: [PATCH 16/47] Align examples --- examples/stm32f3/src/bin/flash.rs | 5 +- examples/stm32f4/src/bin/flash.rs | 14 ++--- examples/stm32f4/src/bin/flash_async.rs | 81 +++++++++++++++++++++++++ examples/stm32f7/src/bin/flash.rs | 5 +- examples/stm32h7/src/bin/flash.rs | 5 +- examples/stm32l0/src/bin/flash.rs | 5 +- examples/stm32l1/src/bin/flash.rs | 5 +- examples/stm32wl/src/bin/flash.rs | 5 +- 8 files changed, 100 insertions(+), 25 deletions(-) create mode 100644 examples/stm32f4/src/bin/flash_async.rs diff --git a/examples/stm32f3/src/bin/flash.rs b/examples/stm32f3/src/bin/flash.rs index e40ad4fc..0e5fb065 100644 --- a/examples/stm32f3/src/bin/flash.rs +++ b/examples/stm32f3/src/bin/flash.rs @@ -4,8 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use embassy_stm32::{flash::Flash, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH).into_regions().bank1_region; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index bd3a7c95..de4ecdb8 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; +use embassy_stm32::{flash::Flash, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { // Once can also call `into_regions()` to get access to NorFlash implementations // for each of the unique characteristics. - let mut f = Flash::new(p.FLASH); + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)); // Sector 5 test_flash(&mut f, 128 * 1024, 128 * 1024); @@ -31,19 +31,19 @@ fn test_flash(f: &mut Flash, offset: u32, size: u32) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.blocking_read(offset, &mut buf)); + unwrap!(f.read(offset, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.blocking_erase(offset, offset + size)); + unwrap!(f.erase_blocking(offset, offset + size)); info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.blocking_read(offset, &mut buf)); + unwrap!(f.read(offset, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.blocking_write( + unwrap!(f.write_blocking( offset, &[ 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, @@ -53,7 +53,7 @@ fn test_flash(f: &mut Flash, offset: u32, size: u32) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.blocking_read(offset, &mut buf)); + unwrap!(f.read(offset, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!( &buf[..], diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs new file mode 100644 index 00000000..c9d9df34 --- /dev/null +++ b/examples/stm32f4/src/bin/flash_async.rs @@ -0,0 +1,81 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::{info, unwrap}; +use embassy_executor::Spawner; +use embassy_time::{Timer, Duration}; +use embassy_stm32::flash::Flash; +use embassy_stm32::gpio::{AnyPin, Level, Output, Pin, Speed}; +use embassy_stm32::{interrupt}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello Flash!"); + + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)); + + // Led should blink uninterrupted during ~2sec erase operation + spawner.spawn(blinky(p.PB7.degrade())).unwrap(); + + // Test on bank 2 in order not to stall CPU. + test_flash(&mut f, 1024 * 1024, 128 * 1024).await; +} + +#[embassy_executor::task] +async fn blinky(p: AnyPin) { + let mut led = Output::new(p, Level::High, Speed::Low); + + loop { + info!("high"); + led.set_high(); + Timer::after(Duration::from_millis(300)).await; + + info!("low"); + led.set_low(); + Timer::after(Duration::from_millis(300)).await; + } +} + +async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) { + info!("Testing offset: {=u32:#X}, size: {=u32:#X}", offset, size); + + info!("Reading..."); + let mut buf = [0u8; 32]; + unwrap!(f.read(offset, &mut buf)); + info!("Read: {=[u8]:x}", buf); + + info!("Erasing..."); + unwrap!(f.erase(offset, offset + size).await); + + info!("Reading..."); + let mut buf = [0u8; 32]; + unwrap!(f.read(offset, &mut buf)); + info!("Read after erase: {=[u8]:x}", buf); + + info!("Writing..."); + unwrap!( + f.write( + offset, + &[ + 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, 30, 31, 32 + ] + ) + .await + ); + + info!("Reading..."); + let mut buf = [0u8; 32]; + unwrap!(f.read(offset, &mut buf)); + info!("Read: {=[u8]:x}", buf); + assert_eq!( + &buf[..], + &[ + 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, + 30, 31, 32 + ] + ); +} \ No newline at end of file diff --git a/examples/stm32f7/src/bin/flash.rs b/examples/stm32f7/src/bin/flash.rs index aabfe855..717c82e8 100644 --- a/examples/stm32f7/src/bin/flash.rs +++ b/examples/stm32f7/src/bin/flash.rs @@ -4,9 +4,8 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; +use embassy_stm32::{flash::Flash, interrupt}; use embassy_time::{Duration, Timer}; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -19,7 +18,7 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = Flash::new(p.FLASH).into_regions().bank1_region3; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region3.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 32]; diff --git a/examples/stm32h7/src/bin/flash.rs b/examples/stm32h7/src/bin/flash.rs index 7ee9838c..aab72cae 100644 --- a/examples/stm32h7/src/bin/flash.rs +++ b/examples/stm32h7/src/bin/flash.rs @@ -4,9 +4,8 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; +use embassy_stm32::{flash::Flash, interrupt}; use embassy_time::{Duration, Timer}; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -19,7 +18,7 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = Flash::new(p.FLASH).into_regions().bank2_region; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank2_region.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 32]; diff --git a/examples/stm32l0/src/bin/flash.rs b/examples/stm32l0/src/bin/flash.rs index 33742502..0ed0d05f 100644 --- a/examples/stm32l0/src/bin/flash.rs +++ b/examples/stm32l0/src/bin/flash.rs @@ -4,8 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use embassy_stm32::{flash::Flash, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH).into_regions().bank1_region; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32l1/src/bin/flash.rs b/examples/stm32l1/src/bin/flash.rs index 38feb0d7..c4d7d029 100644 --- a/examples/stm32l1/src/bin/flash.rs +++ b/examples/stm32l1/src/bin/flash.rs @@ -4,8 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use embassy_stm32::{flash::Flash, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH).into_regions().bank1_region; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs index e6bc2865..df51ceb6 100644 --- a/examples/stm32wl/src/bin/flash.rs +++ b/examples/stm32wl/src/bin/flash.rs @@ -4,8 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; -use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use embassy_stm32::{flash::Flash, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -15,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x36000; - let mut f = Flash::new(p.FLASH).into_regions().bank1_region; + let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; info!("Reading..."); let mut buf = [0u8; 8]; From cdb14475696484d08d717194074c4d85cff5eb63 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 12:42:35 +0200 Subject: [PATCH 17/47] Add missing nightly guards --- embassy-stm32/src/flash/f4.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 3c8f81eb..9698bcd5 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -139,6 +139,7 @@ mod alt_regions { } } + #[cfg(all(feature = "nightly"))] impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_> { const READ_SIZE: usize = READ_SIZE; @@ -151,6 +152,7 @@ mod alt_regions { } } + #[cfg(all(feature = "nightly"))] impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_> { const WRITE_SIZE: usize = $region.write_size as usize; const ERASE_SIZE: usize = $region.erase_size as usize; From 34a2804b544206920b6e960e3443a2b2f6e41f2b Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 12:45:59 +0200 Subject: [PATCH 18/47] Fix unused get_sector and ensure_sector_aligned --- embassy-stm32/src/flash/common.rs | 49 +++++++++++++++++++++++++++++-- embassy-stm32/src/flash/mod.rs | 44 --------------------------- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 990104a3..7cec5a3c 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -8,8 +8,8 @@ use embassy_sync::mutex::Mutex; use stm32_metapac::FLASH_BASE; use super::{ - ensure_sector_aligned, family, get_sector, Error, FlashLayout, FlashRegion, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, - WRITE_SIZE, + family, Error, FlashLayout, FlashRegion, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, + WRITE_SIZE, FlashSector, FlashBank, }; use crate::peripherals::FLASH; use crate::Peripheral; @@ -118,6 +118,51 @@ pub(super) unsafe fn erase_sectored_blocking(base: u32, from: u32, to: u32) -> R Ok(()) } +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"); +} + +pub(crate) fn ensure_sector_aligned( + start_address: u32, + end_address: u32, + regions: &[&FlashRegion], +) -> Result<(), Error> { + let mut address = start_address; + while address < end_address { + let sector = get_sector(address, regions); + if sector.start != address { + return Err(Error::Unaligned); + } + address += sector.size; + } + if address != end_address { + return Err(Error::Unaligned); + } + Ok(()) +} + + impl embedded_storage::nor_flash::ErrorType for Flash<'_> { type Error = Error; } diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index e781f1b8..1ef04e56 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -92,47 +92,3 @@ impl NorFlashError for Error { } } } - -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"); -} - -pub(crate) fn ensure_sector_aligned( - start_address: u32, - end_address: u32, - regions: &[&FlashRegion], -) -> Result<(), Error> { - let mut address = start_address; - while address < end_address { - let sector = get_sector(address, regions); - if sector.start != address { - return Err(Error::Unaligned); - } - address += sector.size; - } - if address != end_address { - return Err(Error::Unaligned); - } - Ok(()) -} From c6ffece410a12779ba1ae2289782ca5a3d00dbaf Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 12:55:17 +0200 Subject: [PATCH 19/47] Add more missing nightly guards --- embassy-stm32/src/flash/f4.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 9698bcd5..0c008fd0 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -2,12 +2,13 @@ use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; -use embassy_sync::waitqueue::AtomicWaker; - use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; +#[cfg(feature = "nightly")] +use embassy_sync::waitqueue::AtomicWaker; + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] mod alt_regions { use embassy_hal_common::PeripheralRef; @@ -15,10 +16,12 @@ mod alt_regions { use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; use crate::flash::{ - asynch, common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, + common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, READ_SIZE, REGION_ACCESS, }; use crate::peripherals::FLASH; + #[cfg(feature = "nightly")] + use crate::flash::asynch; pub const ALT_BANK1_REGION3: FlashRegion = FlashRegion { size: 3 * BANK1_REGION3.erase_size, @@ -100,13 +103,13 @@ mod alt_regions { common::read_blocking(self.0.base, self.0.size, offset, bytes) } - #[cfg(all(feature = "nightly"))] + #[cfg(feature = "nightly")] pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { let _guard = REGION_ACCESS.lock().await; unsafe { asynch::write_chunked(self.0.base, self.0.size, offset, bytes).await } } - #[cfg(all(feature = "nightly"))] + #[cfg(feature = "nightly")] pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { let _guard = REGION_ACCESS.lock().await; unsafe { asynch::erase_sectored(self.0.base, from, to).await } @@ -139,7 +142,7 @@ mod alt_regions { } } - #[cfg(all(feature = "nightly"))] + #[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_> { const READ_SIZE: usize = READ_SIZE; @@ -152,7 +155,7 @@ mod alt_regions { } } - #[cfg(all(feature = "nightly"))] + #[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_> { const WRITE_SIZE: usize = $region.write_size as usize; const ERASE_SIZE: usize = $region.erase_size as usize; @@ -209,6 +212,7 @@ pub(crate) unsafe fn on_interrupt(_: *mut ()) { w.set_eop(true); }); + #[cfg(feature = "nightly")] WAKER.wake(); } @@ -277,6 +281,7 @@ unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) { } } +#[cfg(feature = "nightly")] pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> { let snb = ((sector.bank as u8) << 4) + sector.index_in_bank; From 6df62397048778ce521c14b21b4aced7c22567c2 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 13:11:03 +0200 Subject: [PATCH 20/47] Run format with nightly --- embassy-stm32/src/flash/common.rs | 4 +--- embassy-stm32/src/flash/f4.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 7cec5a3c..e1fe7e9d 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -8,8 +8,7 @@ use embassy_sync::mutex::Mutex; use stm32_metapac::FLASH_BASE; use super::{ - family, Error, FlashLayout, FlashRegion, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, - WRITE_SIZE, FlashSector, FlashBank, + family, Error, FlashBank, FlashLayout, FlashRegion, FlashSector, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE, }; use crate::peripherals::FLASH; use crate::Peripheral; @@ -162,7 +161,6 @@ pub(crate) fn ensure_sector_aligned( Ok(()) } - impl embedded_storage::nor_flash::ErrorType for Flash<'_> { type Error = Error; } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 0c008fd0..084bbdc6 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -2,26 +2,26 @@ use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; +#[cfg(feature = "nightly")] +use embassy_sync::waitqueue::AtomicWaker; + use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; -#[cfg(feature = "nightly")] -use embassy_sync::waitqueue::AtomicWaker; - #[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::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; - use crate::flash::{ - common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, - READ_SIZE, REGION_ACCESS, - }; - use crate::peripherals::FLASH; #[cfg(feature = "nightly")] use crate::flash::asynch; + use crate::flash::{ + common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, READ_SIZE, + REGION_ACCESS, + }; + use crate::peripherals::FLASH; pub const ALT_BANK1_REGION3: FlashRegion = FlashRegion { size: 3 * BANK1_REGION3.erase_size, From 44b6494ab7ec3e742aa9f82a8ca9ebdfc23ebbba Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 17:24:28 +0200 Subject: [PATCH 21/47] Let FlashLayout and FlashRegion depends on a Blocking/Async mode generic --- embassy-stm32/Cargo.toml | 1 - embassy-stm32/build.rs | 16 ++- embassy-stm32/src/flash/asynch.rs | 35 ++++- embassy-stm32/src/flash/common.rs | 218 ++++++++++++------------------ embassy-stm32/src/flash/f4.rs | 112 +++++++-------- embassy-stm32/src/flash/mod.rs | 3 + 6 files changed, 179 insertions(+), 206 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 73841bdc..4e29bb32 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -69,7 +69,6 @@ cfg-if = "1.0.0" embedded-io = { version = "0.4.0", features = ["async"], optional = true } chrono = { version = "^0.4", default-features = false, optional = true} bit_field = "0.10.2" -paste = "1.0.12" [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 54098172..29af3c80 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -213,7 +213,7 @@ fn main() { let region_type = format_ident!("{}", get_flash_region_type_name(region.name)); flash_regions.extend(quote! { #[cfg(flash)] - pub struct #region_type<'d>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>,); + pub struct #region_type<'d, MODE>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData); }); } @@ -224,11 +224,11 @@ fn main() { let field_name = format_ident!("{}", region_name.to_lowercase()); let field_type = format_ident!("{}", get_flash_region_type_name(f.name)); let field = quote! { - pub #field_name: #field_type<'d> + pub #field_name: #field_type<'d, MODE> }; let region_name = format_ident!("{}", region_name); let init = quote! { - #field_name: #field_type(&#region_name, unsafe { p.clone_unchecked()}) + #field_name: #field_type(&#region_name, unsafe { p.clone_unchecked()}, core::marker::PhantomData) }; (field, (init, region_name)) @@ -238,15 +238,17 @@ fn main() { let regions_len = flash_memory_regions.len(); flash_regions.extend(quote! { #[cfg(flash)] - pub struct FlashLayout<'d> { - #(#fields),* + pub struct FlashLayout<'d, MODE> { + #(#fields),*, + _mode: core::marker::PhantomData, } #[cfg(flash)] - impl<'d> FlashLayout<'d> { + impl<'d, MODE> FlashLayout<'d, MODE> { pub(crate) fn new(p: embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self { Self { - #(#inits),* + #(#inits),*, + _mode: core::marker::PhantomData, } } } diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 44e23d9c..3564bbff 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -1,12 +1,21 @@ use atomic_polyfill::{fence, Ordering}; use embassy_hal_common::drop::OnDrop; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::mutex::Mutex; use super::{ - ensure_sector_aligned, family, get_sector, Error, Flash, FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, - REGION_ACCESS, WRITE_SIZE, + ensure_sector_aligned, family, get_sector, read_blocking, Async, Error, Flash, FlashLayout, FLASH_BASE, FLASH_SIZE, + MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE, }; +pub(super) static REGION_ACCESS: Mutex = Mutex::new(()); + impl<'d> Flash<'d> { + pub fn into_regions(self) -> FlashLayout<'d, Async> { + family::set_default_layout(); + FlashLayout::new(self.inner) + } + pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await } } @@ -16,6 +25,18 @@ impl<'d> Flash<'d> { } } +impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_> { + const READ_SIZE: usize = READ_SIZE; + + async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read(offset, bytes) + } + + fn capacity(&self) -> usize { + FLASH_SIZE + } +} + impl embedded_storage_async::nor_flash::NorFlash for Flash<'_> { const WRITE_SIZE: usize = WRITE_SIZE; const ERASE_SIZE: usize = MAX_ERASE_SIZE; @@ -89,7 +110,11 @@ pub(super) async unsafe fn erase_sectored(base: u32, from: u32, to: u32) -> Resu foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { - impl crate::_generated::flash_regions::$type_name<'_> { + impl crate::_generated::flash_regions::$type_name<'_, Async> { + pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + read_blocking(self.0.base, self.0.size, offset, bytes) + } + pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { let _guard = REGION_ACCESS.lock().await; unsafe { write_chunked(self.0.base, self.0.size, offset, bytes).await } @@ -101,7 +126,7 @@ foreach_flash_region! { } } - impl embedded_storage_async::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_> { + impl embedded_storage_async::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_, Async> { const READ_SIZE: usize = READ_SIZE; async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { @@ -113,7 +138,7 @@ foreach_flash_region! { } } - impl embedded_storage_async::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_> { + impl embedded_storage_async::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_, Async> { const WRITE_SIZE: usize = $write_size; const ERASE_SIZE: usize = $erase_size; diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index e1fe7e9d..8b38745c 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -1,14 +1,12 @@ use atomic_polyfill::{fence, Ordering}; use embassy_cortex_m::interrupt::InterruptExt; -use embassy_futures::block_on; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; -use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::mutex::Mutex; use stm32_metapac::FLASH_BASE; use super::{ - family, Error, FlashBank, FlashLayout, FlashRegion, FlashSector, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE, + family, Blocking, Error, FlashBank, FlashLayout, FlashRegion, FlashSector, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, + WRITE_SIZE, }; use crate::peripherals::FLASH; use crate::Peripheral; @@ -17,8 +15,6 @@ pub struct Flash<'d> { pub(crate) inner: PeripheralRef<'d, FLASH>, } -pub(crate) static REGION_ACCESS: Mutex = Mutex::new(()); - impl<'d> Flash<'d> { pub fn new(p: impl Peripheral

+ 'd, irq: impl Peripheral

+ 'd) -> Self { into_ref!(p, irq); @@ -30,7 +26,7 @@ impl<'d> Flash<'d> { Self { inner: p } } - pub fn into_regions(self) -> FlashLayout<'d> { + pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> { family::set_default_layout(); FlashLayout::new(self.inner) } @@ -40,11 +36,19 @@ impl<'d> Flash<'d> { } pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { write_chunked_blocking(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } + unsafe { + write_blocking( + FLASH_BASE as u32, + FLASH_SIZE as u32, + offset, + bytes, + write_chunk_unlocked, + ) + } } pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { erase_sectored_blocking(FLASH_BASE as u32, from, to) } + unsafe { erase_blocking(FLASH_BASE as u32, from, to, erase_sector_unlocked) } } } @@ -59,7 +63,13 @@ pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8]) Ok(()) } -pub(super) unsafe fn write_chunked_blocking(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { +pub(super) unsafe fn write_blocking( + base: u32, + size: u32, + offset: u32, + bytes: &[u8], + write_chunk: unsafe fn(u32, &[u8]) -> Result<(), Error>, +) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); } @@ -71,26 +81,39 @@ pub(super) unsafe fn write_chunked_blocking(base: u32, size: u32, offset: u32, b trace!("Writing {} bytes at 0x{:x}", bytes.len(), address); for chunk in bytes.chunks(WRITE_SIZE) { - family::clear_all_err(); - fence(Ordering::SeqCst); - family::unlock(); - fence(Ordering::SeqCst); - family::enable_blocking_write(); - fence(Ordering::SeqCst); - - let _on_drop = OnDrop::new(|| { - family::disable_blocking_write(); - fence(Ordering::SeqCst); - family::lock(); - }); - - family::write_blocking(address, chunk.try_into().unwrap())?; + write_chunk(address, chunk)?; address += WRITE_SIZE as u32; } Ok(()) } -pub(super) unsafe fn erase_sectored_blocking(base: u32, from: u32, to: u32) -> Result<(), Error> { +pub(super) unsafe fn write_chunk_unlocked(address: u32, chunk: &[u8]) -> Result<(), Error> { + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); + family::enable_blocking_write(); + fence(Ordering::SeqCst); + + let _on_drop = OnDrop::new(|| { + family::disable_blocking_write(); + fence(Ordering::SeqCst); + family::lock(); + }); + + family::write_blocking(address, chunk.try_into().unwrap()) +} + +pub(super) unsafe fn write_chunk_with_critical_section(address: u32, chunk: &[u8]) -> Result<(), Error> { + critical_section::with(|_| write_chunk_unlocked(address, chunk)) +} + +pub(super) unsafe fn erase_blocking( + base: u32, + from: u32, + to: u32, + erase_sector: unsafe fn(&FlashSector) -> Result<(), Error>, +) -> Result<(), Error> { let start_address = base + from; let end_address = base + to; let regions = family::get_flash_regions(); @@ -103,21 +126,28 @@ pub(super) unsafe fn erase_sectored_blocking(base: u32, from: u32, to: u32) -> R while address < end_address { let sector = get_sector(address, regions); trace!("Erasing sector: {:?}", sector); - - family::clear_all_err(); - fence(Ordering::SeqCst); - family::unlock(); - fence(Ordering::SeqCst); - - let _on_drop = OnDrop::new(|| family::lock()); - - family::erase_sector_blocking(§or)?; + erase_sector(§or)?; address += sector.size; } Ok(()) } -pub(crate) fn get_sector(address: u32, regions: &[&FlashRegion]) -> FlashSector { +pub(super) unsafe fn erase_sector_unlocked(sector: &FlashSector) -> Result<(), Error> { + family::clear_all_err(); + fence(Ordering::SeqCst); + family::unlock(); + fence(Ordering::SeqCst); + + let _on_drop = OnDrop::new(|| family::lock()); + + family::erase_sector_blocking(§or) +} + +pub(super) unsafe fn erase_sector_with_critical_section(sector: &FlashSector) -> Result<(), Error> { + critical_section::with(|_| erase_sector_unlocked(sector)) +} + +pub(super) fn get_sector(address: u32, regions: &[&FlashRegion]) -> FlashSector { let mut current_bank = FlashBank::Bank1; let mut bank_offset = 0; for region in regions { @@ -142,7 +172,7 @@ pub(crate) fn get_sector(address: u32, regions: &[&FlashRegion]) -> FlashSector panic!("Flash sector not found"); } -pub(crate) fn ensure_sector_aligned( +pub(super) fn ensure_sector_aligned( start_address: u32, end_address: u32, regions: &[&FlashRegion], @@ -190,121 +220,49 @@ impl embedded_storage::nor_flash::NorFlash for Flash<'_> { } } -#[cfg(feature = "nightly")] -impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_> { - const READ_SIZE: usize = READ_SIZE; - - async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) - } - - fn capacity(&self) -> usize { - FLASH_SIZE - } -} - -pub struct BlockingFlashRegion<'d, const WRITE_SIZE: u32, const ERASE_SIZE: u32>( - &'static FlashRegion, - PeripheralRef<'d, FLASH>, -); - -impl BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> { - pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - read_blocking(self.0.base, self.0.size, offset, bytes) - } - - pub fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - let _guard = block_on(REGION_ACCESS.lock()); - unsafe { write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } - } - - pub fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - let _guard = block_on(REGION_ACCESS.lock()); - unsafe { erase_sectored_blocking(self.0.base, from, to) } - } -} - -impl embedded_storage::nor_flash::ErrorType - for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> -{ - type Error = Error; -} - -impl embedded_storage::nor_flash::ReadNorFlash - for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> -{ - const READ_SIZE: usize = READ_SIZE; - - fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) - } - - fn capacity(&self) -> usize { - self.0.size as usize - } -} - -impl embedded_storage::nor_flash::NorFlash - for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> -{ - const WRITE_SIZE: usize = WRITE_SIZE as usize; - const ERASE_SIZE: usize = ERASE_SIZE as usize; - - fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.write(offset, bytes) - } - - fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.erase(from, to) - } -} - foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { - paste::paste! { - pub type []<'d> = BlockingFlashRegion<'d, $write_size, $erase_size>; - } - - impl<'d> crate::_generated::flash_regions::$type_name<'d> { - /// Make this flash region work in a blocking context. - /// - /// SAFETY - /// - /// This function is unsafe as incorect usage of parallel blocking operations - /// on multiple regions may cause a deadlock because each region requires mutual access to the flash. - pub unsafe fn into_blocking(self) -> BlockingFlashRegion<'d, $write_size, $erase_size> { - BlockingFlashRegion(self.0, self.1) - } - - pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + impl<'d> crate::_generated::flash_regions::$type_name<'d, Blocking> { + pub fn read_blocking(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { read_blocking(self.0.base, self.0.size, offset, bytes) } - pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; - unsafe { write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } + pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + unsafe { write_blocking(self.0.base, self.0.size, offset, bytes, write_chunk_with_critical_section) } } - pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; - unsafe { erase_sectored_blocking(self.0.base, from, to) } + pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> { + unsafe { erase_blocking(self.0.base, from, to, erase_sector_with_critical_section) } } } - impl embedded_storage::nor_flash::ErrorType for crate::_generated::flash_regions::$type_name<'_> { + impl embedded_storage::nor_flash::ErrorType for crate::_generated::flash_regions::$type_name<'_, MODE> { type Error = Error; } - impl embedded_storage::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_> { + impl embedded_storage::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_, Blocking> { const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) + self.read_blocking(offset, bytes) } fn capacity(&self) -> usize { self.0.size as usize } } + + impl embedded_storage::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_, Blocking> { + const WRITE_SIZE: usize = $write_size; + const ERASE_SIZE: usize = $erase_size; + + fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write_blocking(offset, bytes) + } + + fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase_blocking(from, to) + } + } }; } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 084bbdc6..d50a35b4 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -11,6 +11,8 @@ use crate::pac; #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] mod alt_regions { + use core::marker::PhantomData; + use embassy_hal_common::PeripheralRef; use stm32_metapac::FLASH_SIZE; @@ -18,8 +20,7 @@ mod alt_regions { #[cfg(feature = "nightly")] use crate::flash::asynch; use crate::flash::{ - common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, READ_SIZE, - REGION_ACCESS, + common, Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion, READ_SIZE, }; use crate::peripherals::FLASH; @@ -53,101 +54,86 @@ mod alt_regions { &ALT_BANK2_REGION3, ]; - pub struct AltBank1Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); - pub struct AltBank2Region1<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); - pub struct AltBank2Region2<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); - pub struct AltBank2Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); + pub struct AltBank1Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region1<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region2<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); - pub type BlockingAltBank1Region3<'d> = - BlockingFlashRegion<'d, { ALT_BANK1_REGION3.write_size }, { ALT_BANK1_REGION3.erase_size }>; - pub type BlockingAltBank2Region1<'d> = - BlockingFlashRegion<'d, { ALT_BANK2_REGION1.write_size }, { ALT_BANK2_REGION1.erase_size }>; - pub type BlockingAltBank2Region2<'d> = - BlockingFlashRegion<'d, { ALT_BANK2_REGION2.write_size }, { ALT_BANK2_REGION2.erase_size }>; - pub type BlockingAltBank2Region3<'d> = - BlockingFlashRegion<'d, { ALT_BANK2_REGION3.write_size }, { ALT_BANK2_REGION3.erase_size }>; - - pub struct AltFlashLayout<'d> { - pub bank1_region1: Bank1Region1<'d>, - pub bank1_region2: Bank1Region2<'d>, - pub bank1_region3: AltBank1Region3<'d>, - pub bank2_region1: AltBank2Region1<'d>, - pub bank2_region2: AltBank2Region2<'d>, - pub bank2_region3: AltBank2Region3<'d>, - pub otp_region: OTPRegion<'d>, + pub struct AltFlashLayout<'d, MODE> { + pub bank1_region1: Bank1Region1<'d, MODE>, + pub bank1_region2: Bank1Region2<'d, MODE>, + pub bank1_region3: AltBank1Region3<'d, MODE>, + pub bank2_region1: AltBank2Region1<'d, MODE>, + pub bank2_region2: AltBank2Region2<'d, MODE>, + pub bank2_region3: AltBank2Region3<'d, MODE>, + pub otp_region: OTPRegion<'d, MODE>, } impl<'d> Flash<'d> { - pub fn into_alt_regions(self) -> AltFlashLayout<'d> { + pub fn into_alt_regions(self) -> AltFlashLayout<'d, Async> { + unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; + + // SAFETY: We never expose the cloned peripheral references, and their instance is not public. + // Also, all async flash region operations are protected with a mutex. + let p = self.inner; + AltFlashLayout { + bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }, PhantomData), + bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }, PhantomData), + bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData), + otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }, PhantomData), + } + } + + pub fn into_alt_blocking_regions(self) -> AltFlashLayout<'d, Blocking> { unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; // SAFETY: We never expose the cloned peripheral references, and their instance is not public. // Also, all blocking flash region operations are protected with a cs. let p = self.inner; AltFlashLayout { - bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }), - bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }), - bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }), - bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }), - bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }), - bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }), - otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }), + bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }, PhantomData), + bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }, PhantomData), + bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData), + bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData), + otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }, PhantomData), } } } macro_rules! foreach_altflash_region { ($type_name:ident, $region:ident) => { - impl $type_name<'_> { - pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + #[cfg(feature = "nightly")] + impl $type_name<'_, Async> { + pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { common::read_blocking(self.0.base, self.0.size, offset, bytes) } - #[cfg(feature = "nightly")] pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - let _guard = REGION_ACCESS.lock().await; + let _guard = asynch::REGION_ACCESS.lock().await; unsafe { asynch::write_chunked(self.0.base, self.0.size, offset, bytes).await } } - #[cfg(feature = "nightly")] pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - let _guard = REGION_ACCESS.lock().await; + let _guard = asynch::REGION_ACCESS.lock().await; unsafe { asynch::erase_sectored(self.0.base, from, to).await } } - - pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; - unsafe { common::write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } - } - - pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; - unsafe { common::erase_sectored_blocking(self.0.base, from, to) } - } } - impl embedded_storage::nor_flash::ErrorType for $type_name<'_> { + impl embedded_storage::nor_flash::ErrorType for $type_name<'_, Async> { type Error = Error; } - impl embedded_storage::nor_flash::ReadNorFlash for $type_name<'_> { - const READ_SIZE: usize = READ_SIZE; - - fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) - } - - fn capacity(&self) -> usize { - self.0.size as usize - } - } - #[cfg(feature = "nightly")] - impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_> { + impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_, Async> { const READ_SIZE: usize = READ_SIZE; async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) + self.read(offset, bytes).await } fn capacity(&self) -> usize { @@ -156,7 +142,7 @@ mod alt_regions { } #[cfg(feature = "nightly")] - impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_> { + impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_, Async> { const WRITE_SIZE: usize = $region.write_size as usize; const ERASE_SIZE: usize = $region.erase_size as usize; diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 1ef04e56..56a680a8 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -14,6 +14,9 @@ pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; pub const READ_SIZE: usize = 1; +pub struct Blocking; +pub struct Async; + #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct FlashRegion { From 525e06547483de4d431bda2991555a97a0197346 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 17:31:35 +0200 Subject: [PATCH 22/47] Align examples --- examples/stm32f3/src/bin/flash.rs | 12 ++++++------ examples/stm32f7/src/bin/flash.rs | 12 ++++++------ examples/stm32h7/src/bin/flash.rs | 12 ++++++------ examples/stm32l0/src/bin/flash.rs | 12 ++++++------ examples/stm32l1/src/bin/flash.rs | 12 ++++++------ examples/stm32wl/src/bin/flash.rs | 12 ++++++------ 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/examples/stm32f3/src/bin/flash.rs b/examples/stm32f3/src/bin/flash.rs index 0e5fb065..befae0a1 100644 --- a/examples/stm32f3/src/bin/flash.rs +++ b/examples/stm32f3/src/bin/flash.rs @@ -14,27 +14,27 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 2048)); + unwrap!(f.erase_blocking(ADDR, ADDR + 2048)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } diff --git a/examples/stm32f7/src/bin/flash.rs b/examples/stm32f7/src/bin/flash.rs index 717c82e8..5507e731 100644 --- a/examples/stm32f7/src/bin/flash.rs +++ b/examples/stm32f7/src/bin/flash.rs @@ -18,23 +18,23 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region3.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region3; info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 256 * 1024)); + unwrap!(f.erase_blocking(ADDR, ADDR + 256 * 1024)); info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write( + unwrap!(f.write_blocking( ADDR, &[ 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, @@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!( &buf[..], diff --git a/examples/stm32h7/src/bin/flash.rs b/examples/stm32h7/src/bin/flash.rs index aab72cae..fe6dad24 100644 --- a/examples/stm32h7/src/bin/flash.rs +++ b/examples/stm32h7/src/bin/flash.rs @@ -18,23 +18,23 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank2_region.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank2_region; info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 128 * 1024)); + unwrap!(f.erase_blocking(ADDR, ADDR + 128 * 1024)); info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write( + unwrap!(f.write_blocking( ADDR, &[ 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, @@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!( &buf[..], diff --git a/examples/stm32l0/src/bin/flash.rs b/examples/stm32l0/src/bin/flash.rs index 0ed0d05f..4182c87b 100644 --- a/examples/stm32l0/src/bin/flash.rs +++ b/examples/stm32l0/src/bin/flash.rs @@ -14,27 +14,27 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 128)); + unwrap!(f.erase_blocking(ADDR, ADDR + 128)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } diff --git a/examples/stm32l1/src/bin/flash.rs b/examples/stm32l1/src/bin/flash.rs index c4d7d029..53052e7c 100644 --- a/examples/stm32l1/src/bin/flash.rs +++ b/examples/stm32l1/src/bin/flash.rs @@ -14,27 +14,27 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 256)); + unwrap!(f.erase_blocking(ADDR, ADDR + 256)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs index df51ceb6..e03b69b8 100644 --- a/examples/stm32wl/src/bin/flash.rs +++ b/examples/stm32wl/src/bin/flash.rs @@ -14,27 +14,27 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x36000; - let mut f = unsafe { Flash::new(p.FLASH, interrupt::take!(FLASH)).into_regions().bank1_region.into_blocking() }; + let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase(ADDR, ADDR + 2048)); + unwrap!(f.erase_blocking(ADDR, ADDR + 2048)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read(ADDR, &mut buf)); + unwrap!(f.read_blocking(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } From bac8ad565e459320e8ecc2224233d69fa02f6306 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 17:35:49 +0200 Subject: [PATCH 23/47] Remove TryLockError, --- embassy-stm32/src/flash/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 56a680a8..02f6c532 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -83,7 +83,6 @@ pub enum Error { Protected, Unaligned, Parallelism, - TryLockError, } impl NorFlashError for Error { From efc71e08c45a29ab9bdb940af8e7321917d7b234 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 24 May 2023 23:51:48 +0200 Subject: [PATCH 24/47] Default to Async mode --- embassy-stm32/build.rs | 4 ++-- embassy-stm32/src/flash/f4.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 29af3c80..b766f073 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -213,7 +213,7 @@ fn main() { let region_type = format_ident!("{}", get_flash_region_type_name(region.name)); flash_regions.extend(quote! { #[cfg(flash)] - pub struct #region_type<'d, MODE>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData); + pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData); }); } @@ -238,7 +238,7 @@ fn main() { let regions_len = flash_memory_regions.len(); flash_regions.extend(quote! { #[cfg(flash)] - pub struct FlashLayout<'d, MODE> { + pub struct FlashLayout<'d, MODE = crate::flash::Async> { #(#fields),*, _mode: core::marker::PhantomData, } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index d50a35b4..3d696223 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -54,12 +54,12 @@ mod alt_regions { &ALT_BANK2_REGION3, ]; - pub struct AltBank1Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); - pub struct AltBank2Region1<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); - pub struct AltBank2Region2<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); - pub struct AltBank2Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank1Region3<'d, MODE = Async>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region1<'d, MODE = Async>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region2<'d, MODE = Async>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); + pub struct AltBank2Region3<'d, MODE = Async>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData); - pub struct AltFlashLayout<'d, MODE> { + pub struct AltFlashLayout<'d, MODE = Async> { pub bank1_region1: Bank1Region1<'d, MODE>, pub bank1_region2: Bank1Region2<'d, MODE>, pub bank1_region3: AltBank1Region3<'d, MODE>, From 15636f05f54458a184f0e117b1cfdb9d8e929f1d Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 13:08:40 +0200 Subject: [PATCH 25/47] Actually transition to dual bank mode - key was required --- embassy-stm32/src/flash/f4.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 3d696223..50ab446b 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -71,7 +71,7 @@ mod alt_regions { impl<'d> Flash<'d> { pub fn into_alt_regions(self) -> AltFlashLayout<'d, Async> { - unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; + super::set_alt_layout(); // SAFETY: We never expose the cloned peripheral references, and their instance is not public. // Also, all async flash region operations are protected with a mutex. @@ -88,7 +88,7 @@ mod alt_regions { } pub fn into_alt_blocking_regions(self) -> AltFlashLayout<'d, Blocking> { - unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; + super::set_alt_layout(); // SAFETY: We never expose the cloned peripheral references, and their instance is not public. // Also, all blocking flash region operations are protected with a cs. @@ -171,12 +171,31 @@ static WAKER: AtomicWaker = AtomicWaker::new(); #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub fn set_default_layout() { - unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(false)) }; + unsafe { + pac::FLASH.optkeyr().write(|w| w.set_optkey(0x08192A3B)); + pac::FLASH.optkeyr().write(|w| w.set_optkey(0x4C5D6E7F)); + pac::FLASH.optcr().modify(|r| { + r.set_db1m(false); + r.set_optlock(true) + }); + }; } #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479)))] pub const fn set_default_layout() {} +#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] +fn set_alt_layout() { + unsafe { + pac::FLASH.optkeyr().write(|w| w.set_optkey(0x08192A3B)); + pac::FLASH.optkeyr().write(|w| w.set_optkey(0x4C5D6E7F)); + pac::FLASH.optcr().modify(|r| { + r.set_db1m(true); + r.set_optlock(true) + }); + }; +} + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub fn get_flash_regions() -> &'static [&'static FlashRegion] { if unsafe { pac::FLASH.optcr().read().db1m() } { @@ -207,8 +226,8 @@ pub(crate) unsafe fn lock() { } pub(crate) unsafe fn unlock() { - pac::FLASH.keyr().write(|w| w.set_key(0x4567_0123)); - pac::FLASH.keyr().write(|w| w.set_key(0xCDEF_89AB)); + pac::FLASH.keyr().write(|w| w.set_key(0x45670123)); + pac::FLASH.keyr().write(|w| w.set_key(0xCDEF89AB)); } #[cfg(feature = "nightly")] From 7371eefa8666c304fce5c0e25f5315b1f10161fa Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 13:42:42 +0200 Subject: [PATCH 26/47] Align with new bind_interrupt --- embassy-stm32/src/flash/asynch.rs | 3 ++ embassy-stm32/src/flash/common.rs | 41 +++++++++++++++---- embassy-stm32/src/flash/f0.rs | 2 +- embassy-stm32/src/flash/f3.rs | 2 +- embassy-stm32/src/flash/f4.rs | 2 +- embassy-stm32/src/flash/f7.rs | 2 +- embassy-stm32/src/flash/h7.rs | 2 +- embassy-stm32/src/flash/l.rs | 2 +- embassy-stm32/src/flash/other.rs | 2 +- examples/boot/application/rp/src/bin/a.rs | 2 +- .../boot/application/stm32f3/src/bin/a.rs | 2 +- .../boot/application/stm32f7/src/bin/a.rs | 2 +- .../boot/application/stm32h7/src/bin/a.rs | 2 +- .../boot/application/stm32l0/src/bin/a.rs | 2 +- .../boot/application/stm32l1/src/bin/a.rs | 2 +- .../boot/application/stm32l4/src/bin/a.rs | 2 +- .../boot/application/stm32wl/src/bin/a.rs | 2 +- examples/boot/bootloader/stm32/src/main.rs | 3 +- examples/stm32f3/src/bin/flash.rs | 4 +- examples/stm32f4/src/bin/flash.rs | 4 +- examples/stm32f4/src/bin/flash_async.rs | 10 +++-- examples/stm32h7/src/bin/flash.rs | 4 +- examples/stm32l0/src/bin/flash.rs | 4 +- examples/stm32l1/src/bin/flash.rs | 4 +- examples/stm32wl/src/bin/flash.rs | 4 +- 25 files changed, 71 insertions(+), 40 deletions(-) diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 3564bbff..017fb17f 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -12,15 +12,18 @@ pub(super) static REGION_ACCESS: Mutex = Mutex::new impl<'d> Flash<'d> { pub fn into_regions(self) -> FlashLayout<'d, Async> { + assert!(!self.blocking_only); family::set_default_layout(); FlashLayout::new(self.inner) } pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + assert!(!self.blocking_only); unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await } } pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + assert!(!self.blocking_only); unsafe { erase_sectored(FLASH_BASE as u32, from, to).await } } } diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 8b38745c..0a1ee516 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -1,5 +1,5 @@ use atomic_polyfill::{fence, Ordering}; -use embassy_cortex_m::interrupt::InterruptExt; +use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use stm32_metapac::FLASH_BASE; @@ -9,21 +9,37 @@ use super::{ WRITE_SIZE, }; use crate::peripherals::FLASH; -use crate::Peripheral; +use crate::{interrupt, Peripheral}; pub struct Flash<'d> { pub(crate) inner: PeripheralRef<'d, FLASH>, + pub(crate) blocking_only: bool, } impl<'d> Flash<'d> { - pub fn new(p: impl Peripheral

+ 'd, irq: impl Peripheral

+ 'd) -> Self { - into_ref!(p, irq); + pub fn new( + p: impl Peripheral

+ 'd, + _irq: impl interrupt::Binding + 'd, + ) -> Self { + into_ref!(p); - irq.set_handler(family::on_interrupt); - irq.unpend(); - irq.enable(); + let flash_irq = unsafe { crate::interrupt::FLASH::steal() }; + flash_irq.unpend(); + flash_irq.enable(); - Self { inner: p } + Self { + inner: p, + blocking_only: false, + } + } + + pub fn new_blocking_only(p: impl Peripheral

+ 'd) -> Self { + into_ref!(p); + + Self { + inner: p, + blocking_only: true, + } } pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> { @@ -52,6 +68,15 @@ impl<'d> Flash<'d> { } } +/// Interrupt handler +pub struct InterruptHandler; + +impl interrupt::Handler for InterruptHandler { + unsafe fn on_interrupt() { + family::on_interrupt(); + } +} + pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index ecf3a698..cd17486e 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -13,7 +13,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index fd778f2b..4ce39128 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -13,7 +13,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 50ab446b..2b047264 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -210,7 +210,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { // Clear IRQ flags pac::FLASH.sr().write(|w| { w.set_operr(true); diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index a0593b14..ab518bf8 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs @@ -12,7 +12,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 865f1328..d6818d59 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -17,7 +17,7 @@ pub fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index f8a0dac4..c2394e0c 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -12,7 +12,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index e21b0b24..e569951f 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs @@ -8,7 +8,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt(_: *mut ()) { +pub(crate) unsafe fn on_interrupt() { unimplemented!(); } diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs index e3ac634c..2b84ec61 100644 --- a/examples/boot/application/rp/src/bin/a.rs +++ b/examples/boot/application/rp/src/bin/a.rs @@ -26,7 +26,7 @@ async fn main(_s: Spawner) { let mut watchdog = Watchdog::new(p.WATCHDOG); watchdog.start(Duration::from_secs(8)); - let mut flash: Flash<_, FLASH_SIZE> = Flash::new(p.FLASH); + let mut flash: Flash<_, FLASH_SIZE> = Flash::new_blocking_only(p.FLASH); let mut updater = FirmwareUpdater::default(); diff --git a/examples/boot/application/stm32f3/src/bin/a.rs b/examples/boot/application/stm32f3/src/bin/a.rs index d92d59b2..a69b6327 100644 --- a/examples/boot/application/stm32f3/src/bin/a.rs +++ b/examples/boot/application/stm32f3/src/bin/a.rs @@ -17,7 +17,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new(p.FLASH); + let flash = Flash::new_blocking_only(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PC13, Pull::Up); diff --git a/examples/boot/application/stm32f7/src/bin/a.rs b/examples/boot/application/stm32f7/src/bin/a.rs index 79ab80e0..1f55db93 100644 --- a/examples/boot/application/stm32f7/src/bin/a.rs +++ b/examples/boot/application/stm32f7/src/bin/a.rs @@ -16,7 +16,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let mut flash = Flash::new(p.FLASH); + let mut flash = Flash::new_blocking_only(p.FLASH); let button = Input::new(p.PC13, Pull::Down); let mut button = ExtiInput::new(button, p.EXTI13); diff --git a/examples/boot/application/stm32h7/src/bin/a.rs b/examples/boot/application/stm32h7/src/bin/a.rs index 8b452be3..b8617c3b 100644 --- a/examples/boot/application/stm32h7/src/bin/a.rs +++ b/examples/boot/application/stm32h7/src/bin/a.rs @@ -16,7 +16,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let mut flash = Flash::new(p.FLASH); + let mut flash = Flash::new_blocking_only(p.FLASH); let button = Input::new(p.PC13, Pull::Down); let mut button = ExtiInput::new(button, p.EXTI13); diff --git a/examples/boot/application/stm32l0/src/bin/a.rs b/examples/boot/application/stm32l0/src/bin/a.rs index 59ca3438..c6663563 100644 --- a/examples/boot/application/stm32l0/src/bin/a.rs +++ b/examples/boot/application/stm32l0/src/bin/a.rs @@ -18,7 +18,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new(p.FLASH); + let flash = Flash::new_blocking_only(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PB2, Pull::Up); diff --git a/examples/boot/application/stm32l1/src/bin/a.rs b/examples/boot/application/stm32l1/src/bin/a.rs index 59ca3438..c6663563 100644 --- a/examples/boot/application/stm32l1/src/bin/a.rs +++ b/examples/boot/application/stm32l1/src/bin/a.rs @@ -18,7 +18,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new(p.FLASH); + let flash = Flash::new_blocking_only(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PB2, Pull::Up); diff --git a/examples/boot/application/stm32l4/src/bin/a.rs b/examples/boot/application/stm32l4/src/bin/a.rs index 6cddc6cc..86936222 100644 --- a/examples/boot/application/stm32l4/src/bin/a.rs +++ b/examples/boot/application/stm32l4/src/bin/a.rs @@ -17,7 +17,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new(p.FLASH); + let flash = Flash::new_blocking_only(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PC13, Pull::Up); diff --git a/examples/boot/application/stm32wl/src/bin/a.rs b/examples/boot/application/stm32wl/src/bin/a.rs index 1ff47edd..2982e8df 100644 --- a/examples/boot/application/stm32wl/src/bin/a.rs +++ b/examples/boot/application/stm32wl/src/bin/a.rs @@ -17,7 +17,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new(p.FLASH); + let flash = Flash::new_blocking_only(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PA0, Pull::Up); diff --git a/examples/boot/bootloader/stm32/src/main.rs b/examples/boot/bootloader/stm32/src/main.rs index 49c21920..5e8a4f2b 100644 --- a/examples/boot/bootloader/stm32/src/main.rs +++ b/examples/boot/bootloader/stm32/src/main.rs @@ -20,8 +20,7 @@ fn main() -> ! { */ let mut bl: BootLoader<2048> = BootLoader::default(); - let flash = Flash::new(p.FLASH); - let layout = flash.into_regions(); + let layout = Flash::new_blocking_only(p.FLASH).into_blocking_regions(); let mut flash = BootFlash::new(layout.bank1_region); let start = bl.prepare(&mut SingleFlashConfig::new(&mut flash)); core::mem::drop(flash); diff --git a/examples/stm32f3/src/bin/flash.rs b/examples/stm32f3/src/bin/flash.rs index befae0a1..9a31b548 100644 --- a/examples/stm32f3/src/bin/flash.rs +++ b/examples/stm32f3/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index de4ecdb8..455af930 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { // Once can also call `into_regions()` to get access to NorFlash implementations // for each of the unique characteristics. - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)); + let mut f = Flash::new_blocking_only(p.FLASH); // Sector 5 test_flash(&mut f, 128 * 1024, 128 * 1024); diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs index c9d9df34..67533708 100644 --- a/examples/stm32f4/src/bin/flash_async.rs +++ b/examples/stm32f4/src/bin/flash_async.rs @@ -5,17 +5,21 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; use embassy_time::{Timer, Duration}; -use embassy_stm32::flash::Flash; +use embassy_stm32::flash::{Flash, InterruptHandler}; use embassy_stm32::gpio::{AnyPin, Level, Output, Pin, Speed}; -use embassy_stm32::{interrupt}; +use embassy_stm32::bind_interrupts; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + FLASH => InterruptHandler; +}); + #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello Flash!"); - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)); + let mut f = Flash::new(p.FLASH, Irqs); // Led should blink uninterrupted during ~2sec erase operation spawner.spawn(blinky(p.PB7.degrade())).unwrap(); diff --git a/examples/stm32h7/src/bin/flash.rs b/examples/stm32h7/src/bin/flash.rs index fe6dad24..c0c332c3 100644 --- a/examples/stm32h7/src/bin/flash.rs +++ b/examples/stm32h7/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -18,7 +18,7 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank2_region; + let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank2_region; info!("Reading..."); let mut buf = [0u8; 32]; diff --git a/examples/stm32l0/src/bin/flash.rs b/examples/stm32l0/src/bin/flash.rs index 4182c87b..57ccf7f5 100644 --- a/examples/stm32l0/src/bin/flash.rs +++ b/examples/stm32l0/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32l1/src/bin/flash.rs b/examples/stm32l1/src/bin/flash.rs index 53052e7c..71174bfb 100644 --- a/examples/stm32l1/src/bin/flash.rs +++ b/examples/stm32l1/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs index e03b69b8..51bd0db4 100644 --- a/examples/stm32wl/src/bin/flash.rs +++ b/examples/stm32wl/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x36000; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; From 49a31bd5d8496e8ceb1144e6e02de0e55dd0508b Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 13:54:40 +0200 Subject: [PATCH 27/47] Simplify SR->Result --- embassy-stm32/src/flash/f4.rs | 45 +++++++++++++---------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 2b047264..53e58835 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -4,6 +4,7 @@ use core::sync::atomic::{fence, Ordering}; #[cfg(feature = "nightly")] use embassy_sync::waitqueue::AtomicWaker; +use pac::flash::regs::Sr; use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; @@ -347,17 +348,7 @@ pub(crate) async unsafe fn wait_ready() -> Result<(), Error> { let sr = pac::FLASH.sr().read(); if !sr.bsy() { - Poll::Ready(if sr.pgserr() { - Err(Error::Seq) - } else if sr.pgperr() { - Err(Error::Parallelism) - } else if sr.pgaerr() { - Err(Error::Unaligned) - } else if sr.wrperr() { - Err(Error::Protected) - } else { - Ok(()) - }) + Poll::Ready(get_result(sr)) } else { return Poll::Pending; } @@ -370,27 +361,25 @@ unsafe fn wait_ready_blocking() -> Result<(), Error> { let sr = pac::FLASH.sr().read(); if !sr.bsy() { - if sr.pgserr() { - return Err(Error::Seq); - } - - if sr.pgperr() { - return Err(Error::Parallelism); - } - - if sr.pgaerr() { - return Err(Error::Unaligned); - } - - if sr.wrperr() { - return Err(Error::Protected); - } - - return Ok(()); + return get_result(sr); } } } +fn get_result(sr: Sr) -> Result<(), Error> { + if sr.pgserr() { + Err(Error::Seq) + } else if sr.pgperr() { + Err(Error::Parallelism) + } else if sr.pgaerr() { + Err(Error::Unaligned) + } else if sr.wrperr() { + Err(Error::Protected) + } else { + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; From e764a3d9ca7a4a0ccdf800c61a388dd103de5ac1 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 13:59:32 +0200 Subject: [PATCH 28/47] Fix unused errors --- embassy-stm32/src/flash/common.rs | 3 +++ embassy-stm32/src/flash/f4.rs | 8 +++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 0a1ee516..547e3031 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -13,6 +13,7 @@ use crate::{interrupt, Peripheral}; pub struct Flash<'d> { pub(crate) inner: PeripheralRef<'d, FLASH>, + #[cfg(all(feature = "nightly", flash_f4))] pub(crate) blocking_only: bool, } @@ -29,6 +30,7 @@ impl<'d> Flash<'d> { Self { inner: p, + #[cfg(all(feature = "nightly", flash_f4))] blocking_only: false, } } @@ -38,6 +40,7 @@ impl<'d> Flash<'d> { Self { inner: p, + #[cfg(all(feature = "nightly", flash_f4))] blocking_only: true, } } diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 53e58835..aa3433b2 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -20,9 +20,7 @@ mod alt_regions { use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; #[cfg(feature = "nightly")] use crate::flash::asynch; - use crate::flash::{ - common, Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion, READ_SIZE, - }; + use crate::flash::{Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion}; use crate::peripherals::FLASH; pub const ALT_BANK1_REGION3: FlashRegion = FlashRegion { @@ -111,7 +109,7 @@ mod alt_regions { #[cfg(feature = "nightly")] impl $type_name<'_, Async> { pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - common::read_blocking(self.0.base, self.0.size, offset, bytes) + crate::flash::common::read_blocking(self.0.base, self.0.size, offset, bytes) } pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { @@ -131,7 +129,7 @@ mod alt_regions { #[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_, Async> { - const READ_SIZE: usize = READ_SIZE; + const READ_SIZE: usize = crate::flash::READ_SIZE; async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { self.read(offset, bytes).await From 8073bf22e92791618e1a11c58901f5b98ff002d1 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 20:07:29 +0200 Subject: [PATCH 29/47] Add sector number tests --- embassy-stm32/src/flash/f4.rs | 88 +++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index aa3433b2..e8ac95ae 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -168,6 +168,12 @@ pub use alt_regions::*; #[cfg(feature = "nightly")] static WAKER: AtomicWaker = AtomicWaker::new(); +impl FlashSector { + const fn snb(&self) -> u8 { + ((self.bank as u8) << 4) + self.index_in_bank + } +} + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub fn set_default_layout() { unsafe { @@ -287,11 +293,9 @@ unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) { #[cfg(feature = "nightly")] pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> { - let snb = ((sector.bank as u8) << 4) + sector.index_in_bank; - pac::FLASH.cr().modify(|w| { w.set_ser(true); - w.set_snb(snb); + w.set_snb(sector.snb()); w.set_eopie(true); w.set_errie(true); }); @@ -310,11 +314,9 @@ pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Erro } pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { - let snb = ((sector.bank as u8) << 4) + sector.index_in_bank; - pac::FLASH.cr().modify(|w| { w.set_ser(true); - w.set_snb(snb) + w.set_snb(sector.snb()) }); pac::FLASH.cr().modify(|w| { @@ -390,7 +392,9 @@ mod tests { 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| { + let assert_sector = |snb: u8, index_in_bank: u8, start: u32, size: u32, address: u32| { + let sector = get_sector(address, &FLASH_REGIONS); + assert_eq!(snb, sector.snb()); assert_eq!( FlashSector { bank: FlashBank::Bank1, @@ -398,24 +402,26 @@ mod tests { start, size }, - get_sector(address, &FLASH_REGIONS) - ) + sector + ); }; - 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(0x00, 0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_0000); + assert_sector(0x00, 0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_3FFF); + assert_sector(0x03, 3, 0x0800_C000, SMALL_SECTOR_SIZE, 0x0800_C000); + assert_sector(0x03, 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(0x04, 4, 0x0801_0000, MEDIUM_SECTOR_SIZE, 0x0801_0000); + assert_sector(0x04, 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(11, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080E_0000); - assert_sector(11, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080F_FFFF); + assert_sector(0x05, 5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0802_0000); + assert_sector(0x05, 5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0803_FFFF); + assert_sector(0x0B, 11, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080E_0000); + assert_sector(0x0B, 11, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080F_FFFF); - let assert_sector = |bank: FlashBank, index_in_bank: u8, start: u32, size: u32, address: u32| { + let assert_sector = |snb: u8, bank: FlashBank, index_in_bank: u8, start: u32, size: u32, address: u32| { + let sector = get_sector(address, &ALT_FLASH_REGIONS); + assert_eq!(snb, sector.snb()); assert_eq!( FlashSector { bank, @@ -423,34 +429,34 @@ mod tests { start, size }, - get_sector(address, &ALT_FLASH_REGIONS) + sector ) }; - 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(0x00, FlashBank::Bank1, 0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_0000); + assert_sector(0x00, FlashBank::Bank1, 0, 0x0800_0000, SMALL_SECTOR_SIZE, 0x0800_3FFF); + assert_sector(0x03, FlashBank::Bank1, 3, 0x0800_C000, SMALL_SECTOR_SIZE, 0x0800_C000); + assert_sector(0x03, FlashBank::Bank1, 3, 0x0800_C000, SMALL_SECTOR_SIZE, 0x0800_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(0x04, FlashBank::Bank1, 4, 0x0801_0000, MEDIUM_SECTOR_SIZE, 0x0801_0000); + assert_sector(0x04, FlashBank::Bank1, 4, 0x0801_0000, MEDIUM_SECTOR_SIZE, 0x0801_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(0x05, FlashBank::Bank1, 5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0802_0000); + assert_sector(0x05, FlashBank::Bank1, 5, 0x0802_0000, LARGE_SECTOR_SIZE, 0x0803_FFFF); + assert_sector(0x07, FlashBank::Bank1, 7, 0x0806_0000, LARGE_SECTOR_SIZE, 0x0806_0000); + assert_sector(0x07, FlashBank::Bank1, 7, 0x0806_0000, LARGE_SECTOR_SIZE, 0x0807_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(0x10, FlashBank::Bank2, 0, 0x0808_0000, SMALL_SECTOR_SIZE, 0x0808_0000); + assert_sector(0x10, FlashBank::Bank2, 0, 0x0808_0000, SMALL_SECTOR_SIZE, 0x0808_3FFF); + assert_sector(0x13, FlashBank::Bank2, 3, 0x0808_C000, SMALL_SECTOR_SIZE, 0x0808_C000); + assert_sector(0x13, FlashBank::Bank2, 3, 0x0808_C000, SMALL_SECTOR_SIZE, 0x0808_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(0x14, FlashBank::Bank2, 4, 0x0809_0000, MEDIUM_SECTOR_SIZE, 0x0809_0000); + assert_sector(0x14, FlashBank::Bank2, 4, 0x0809_0000, MEDIUM_SECTOR_SIZE, 0x0809_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); + assert_sector(0x15, FlashBank::Bank2, 5, 0x080A_0000, LARGE_SECTOR_SIZE, 0x080A_0000); + assert_sector(0x15, FlashBank::Bank2, 5, 0x080A_0000, LARGE_SECTOR_SIZE, 0x080B_FFFF); + assert_sector(0x17, FlashBank::Bank2, 7, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080E_0000); + assert_sector(0x17, FlashBank::Bank2, 7, 0x080E_0000, LARGE_SECTOR_SIZE, 0x080F_FFFF); } } From b412784a7aea102ef53744fbb11d473fa3c0c984 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 20:55:12 +0200 Subject: [PATCH 30/47] Add runtime checks for errata 2.2.11 --- embassy-stm32/src/flash/common.rs | 3 ++ embassy-stm32/src/flash/f4.rs | 73 ++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 547e3031..3eb4a0f1 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -85,6 +85,9 @@ pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8]) return Err(Error::Size); } + #[cfg(flash_f4)] + family::assert_not_corrupted_read(); + let start_address = base + offset; let flash_data = unsafe { core::slice::from_raw_parts(start_address as *const u8, bytes.len()) }; bytes.copy_from_slice(flash_data); diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index e8ac95ae..48858421 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -380,6 +380,77 @@ fn get_result(sr: Sr) -> Result<(), Error> { } } +pub(crate) fn assert_not_corrupted_read() { + #[allow(unused)] + const REVISION_3: u16 = 0x2001; + + #[cfg(any( + feature = "stm32f427ai", + feature = "stm32f427ii", + feature = "stm32f427vi", + feature = "stm32f427zi", + feature = "stm32f429ai", + feature = "stm32f429bi", + feature = "stm32f429ii", + feature = "stm32f429ni", + feature = "stm32f429vi", + feature = "stm32f429zi", + feature = "stm32f437ai", + feature = "stm32f437ii", + feature = "stm32f437vi", + feature = "stm32f437zi", + feature = "stm32f439ai", + feature = "stm32f439bi", + feature = "stm32f439ii", + feature = "stm32f439ni", + feature = "stm32f439vi", + feature = "stm32f439zi", + ))] + if unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && pa12_is_output_pull_low() } { + panic!("Read corruption for stm32f42xxI and stm32f43xxI when PA12 is in use for chips below revision 3, see errata 2.2.11"); + } + + #[cfg(any( + feature = "stm32f427ag", + feature = "stm32f427ig", + feature = "stm32f427vg", + feature = "stm32f427zg", + feature = "stm32f429ag", + feature = "stm32f429bg", + feature = "stm32f429ig", + feature = "stm32f429ng", + feature = "stm32f429vg", + feature = "stm32f429zg", + feature = "stm32f437ig", + feature = "stm32f437vg", + feature = "stm32f437zg", + feature = "stm32f439bg", + feature = "stm32f439ig", + feature = "stm32f439ng", + feature = "stm32f439vg", + feature = "stm32f439zg", + ))] + if unsafe { + pac::FLASH.optcr().read().db1m() + && pac::DBGMCU.idcode().read().rev_id() < REVISION_3 + && pa12_is_output_pull_low() + } { + panic!("Read corruption for stm32f42xxG and stm32f43xxG in dual bank mode when PA12 is in use for chips below revision 3, see errata 2.2.11"); + } +} + +#[allow(unused)] +fn pa12_is_output_pull_low() -> bool { + use pac::gpio::vals; + use pac::GPIOA; + const PIN: usize = 12; + unsafe { + GPIOA.moder().read().moder(PIN) == vals::Moder::OUTPUT + && GPIOA.pupdr().read().pupdr(PIN) == vals::Pupdr::PULLDOWN + && GPIOA.odr().read().odr(PIN) == vals::Odr::LOW + } +} + #[cfg(test)] mod tests { use super::*; @@ -387,7 +458,7 @@ mod tests { #[test] #[cfg(stm32f429)] - fn can_get_sector_single_bank() { + fn can_get_sector() { const SMALL_SECTOR_SIZE: u32 = 16 * 1024; const MEDIUM_SECTOR_SIZE: u32 = 64 * 1024; const LARGE_SECTOR_SIZE: u32 = 128 * 1024; From 18d14dff48d1fd49cfd43fb94304bf932a74a6ca Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 21:14:35 +0200 Subject: [PATCH 31/47] Handle errata 2.2.12 --- embassy-stm32/src/flash/f4.rs | 41 ++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 48858421..d67e6d0a 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -2,11 +2,12 @@ use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; +use atomic_polyfill::AtomicBool; #[cfg(feature = "nightly")] use embassy_sync::waitqueue::AtomicWaker; use pac::flash::regs::Sr; -use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; +use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; use crate::pac; @@ -167,6 +168,7 @@ pub use alt_regions::*; #[cfg(feature = "nightly")] static WAKER: AtomicWaker = AtomicWaker::new(); +static DATA_CACHE_WAS_ENABLED: AtomicBool = AtomicBool::new(false); impl FlashSector { const fn snb(&self) -> u8 { @@ -238,6 +240,7 @@ pub(crate) unsafe fn unlock() { #[cfg(feature = "nightly")] pub(crate) unsafe fn enable_write() { assert_eq!(0, WRITE_SIZE % 4); + save_data_cache_state(); pac::FLASH.cr().write(|w| { w.set_pg(true); @@ -254,10 +257,12 @@ pub(crate) unsafe fn disable_write() { w.set_eopie(false); w.set_errie(false); }); + restore_data_cache_state(); } pub(crate) unsafe fn enable_blocking_write() { assert_eq!(0, WRITE_SIZE % 4); + save_data_cache_state(); pac::FLASH.cr().write(|w| { w.set_pg(true); @@ -267,6 +272,7 @@ pub(crate) unsafe fn enable_blocking_write() { pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); + restore_data_cache_state(); } #[cfg(feature = "nightly")] @@ -293,6 +299,8 @@ unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) { #[cfg(feature = "nightly")] pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> { + save_data_cache_state(); + pac::FLASH.cr().modify(|w| { w.set_ser(true); w.set_snb(sector.snb()); @@ -310,10 +318,13 @@ pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Erro w.set_errie(false); }); clear_all_err(); + restore_data_cache_state(); ret } pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { + save_data_cache_state(); + pac::FLASH.cr().modify(|w| { w.set_ser(true); w.set_snb(sector.snb()) @@ -325,6 +336,7 @@ pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), E let ret: Result<(), Error> = wait_ready_blocking(); clear_all_err(); + restore_data_cache_state(); ret } @@ -380,6 +392,33 @@ fn get_result(sr: Sr) -> Result<(), Error> { } } +fn save_data_cache_state() { + let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2; + if dual_bank { + // Disable data cache during write/erase if there are two banks, see errata 2.2.12 + let dcen = unsafe { pac::FLASH.acr().read().dcen() }; + DATA_CACHE_WAS_ENABLED.store(dcen, Ordering::Relaxed); + if dcen { + unsafe { pac::FLASH.acr().modify(|w| w.set_dcen(false)) }; + } + } +} + +fn restore_data_cache_state() { + let dual_bank = get_flash_regions().last().unwrap().bank == FlashBank::Bank2; + if dual_bank { + // Restore data cache if it was enabled + let dcen = DATA_CACHE_WAS_ENABLED.load(Ordering::Relaxed); + if dcen { + unsafe { + // Reset data cache before we enable it again + pac::FLASH.acr().modify(|w| w.set_dcrst(true)); + pac::FLASH.acr().modify(|w| w.set_dcen(true)) + }; + } + } +} + pub(crate) fn assert_not_corrupted_read() { #[allow(unused)] const REVISION_3: u16 = 0x2001; From 860b519f9993bd8991849c680aae058558aadfbd Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 21:40:54 +0200 Subject: [PATCH 32/47] Let Flash be a thing --- embassy-stm32/src/flash/asynch.rs | 13 +++---- embassy-stm32/src/flash/common.rs | 37 +++++++++++-------- embassy-stm32/src/flash/f4.rs | 22 ++++++++++- examples/boot/application/rp/src/bin/a.rs | 2 +- .../boot/application/stm32f3/src/bin/a.rs | 2 +- .../boot/application/stm32f7/src/bin/a.rs | 2 +- .../boot/application/stm32h7/src/bin/a.rs | 2 +- .../boot/application/stm32l0/src/bin/a.rs | 2 +- .../boot/application/stm32l1/src/bin/a.rs | 2 +- .../boot/application/stm32l4/src/bin/a.rs | 2 +- .../boot/application/stm32wl/src/bin/a.rs | 2 +- examples/boot/bootloader/stm32/src/main.rs | 2 +- examples/stm32f3/src/bin/flash.rs | 2 +- examples/stm32f4/src/bin/flash.rs | 2 +- examples/stm32f7/src/bin/flash.rs | 4 +- examples/stm32h7/src/bin/flash.rs | 2 +- examples/stm32l0/src/bin/flash.rs | 2 +- examples/stm32l1/src/bin/flash.rs | 2 +- examples/stm32wl/src/bin/flash.rs | 2 +- 19 files changed, 63 insertions(+), 43 deletions(-) diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 017fb17f..74c54ff3 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -10,25 +10,22 @@ use super::{ pub(super) static REGION_ACCESS: Mutex = Mutex::new(()); -impl<'d> Flash<'d> { +impl<'d> Flash<'d, Async> { pub fn into_regions(self) -> FlashLayout<'d, Async> { - assert!(!self.blocking_only); family::set_default_layout(); FlashLayout::new(self.inner) } pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - assert!(!self.blocking_only); unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await } } pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - assert!(!self.blocking_only); unsafe { erase_sectored(FLASH_BASE as u32, from, to).await } } } -impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_> { +impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_, Async> { const READ_SIZE: usize = READ_SIZE; async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { @@ -40,7 +37,7 @@ impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_> { } } -impl embedded_storage_async::nor_flash::NorFlash for Flash<'_> { +impl embedded_storage_async::nor_flash::NorFlash for Flash<'_, Async> { const WRITE_SIZE: usize = WRITE_SIZE; const ERASE_SIZE: usize = MAX_ERASE_SIZE; @@ -114,7 +111,7 @@ pub(super) async unsafe fn erase_sectored(base: u32, from: u32, to: u32) -> Resu foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { impl crate::_generated::flash_regions::$type_name<'_, Async> { - pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { read_blocking(self.0.base, self.0.size, offset, bytes) } @@ -133,7 +130,7 @@ foreach_flash_region! { const READ_SIZE: usize = READ_SIZE; async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read(offset, bytes) + self.read(offset, bytes).await } fn capacity(&self) -> usize { diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 3eb4a0f1..8ae72ebc 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -1,3 +1,5 @@ +use core::marker::PhantomData; + use atomic_polyfill::{fence, Ordering}; use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; use embassy_hal_common::drop::OnDrop; @@ -5,19 +7,18 @@ use embassy_hal_common::{into_ref, PeripheralRef}; use stm32_metapac::FLASH_BASE; use super::{ - family, Blocking, Error, FlashBank, FlashLayout, FlashRegion, FlashSector, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, - WRITE_SIZE, + family, Async, Blocking, Error, FlashBank, FlashLayout, FlashRegion, FlashSector, FLASH_SIZE, MAX_ERASE_SIZE, + READ_SIZE, WRITE_SIZE, }; use crate::peripherals::FLASH; use crate::{interrupt, Peripheral}; -pub struct Flash<'d> { +pub struct Flash<'d, MODE = Async> { pub(crate) inner: PeripheralRef<'d, FLASH>, - #[cfg(all(feature = "nightly", flash_f4))] - pub(crate) blocking_only: bool, + _mode: PhantomData, } -impl<'d> Flash<'d> { +impl<'d> Flash<'d, Async> { pub fn new( p: impl Peripheral

+ 'd, _irq: impl interrupt::Binding + 'd, @@ -30,21 +31,23 @@ impl<'d> Flash<'d> { Self { inner: p, - #[cfg(all(feature = "nightly", flash_f4))] - blocking_only: false, + _mode: PhantomData, } } +} - pub fn new_blocking_only(p: impl Peripheral

+ 'd) -> Self { +impl<'d> Flash<'d, Blocking> { + pub fn new_blocking(p: impl Peripheral

+ 'd) -> Self { into_ref!(p); Self { inner: p, - #[cfg(all(feature = "nightly", flash_f4))] - blocking_only: true, + _mode: PhantomData, } } +} +impl<'d, MODE> Flash<'d, MODE> { pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> { family::set_default_layout(); FlashLayout::new(self.inner) @@ -222,11 +225,11 @@ pub(super) fn ensure_sector_aligned( Ok(()) } -impl embedded_storage::nor_flash::ErrorType for Flash<'_> { +impl embedded_storage::nor_flash::ErrorType for Flash<'_, MODE> { type Error = Error; } -impl embedded_storage::nor_flash::ReadNorFlash for Flash<'_> { +impl embedded_storage::nor_flash::ReadNorFlash for Flash<'_, MODE> { const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { @@ -238,7 +241,7 @@ impl embedded_storage::nor_flash::ReadNorFlash for Flash<'_> { } } -impl embedded_storage::nor_flash::NorFlash for Flash<'_> { +impl embedded_storage::nor_flash::NorFlash for Flash<'_, MODE> { const WRITE_SIZE: usize = WRITE_SIZE; const ERASE_SIZE: usize = MAX_ERASE_SIZE; @@ -253,11 +256,13 @@ impl embedded_storage::nor_flash::NorFlash for Flash<'_> { foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { - impl<'d> crate::_generated::flash_regions::$type_name<'d, Blocking> { + impl crate::_generated::flash_regions::$type_name<'_, MODE> { pub fn read_blocking(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { read_blocking(self.0.base, self.0.size, offset, bytes) } + } + impl crate::_generated::flash_regions::$type_name<'_, Blocking> { pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { unsafe { write_blocking(self.0.base, self.0.size, offset, bytes, write_chunk_with_critical_section) } } @@ -271,7 +276,7 @@ foreach_flash_region! { type Error = Error; } - impl embedded_storage::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_, Blocking> { + impl embedded_storage::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_, MODE> { const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index d67e6d0a..875bb912 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -107,10 +107,16 @@ mod alt_regions { macro_rules! foreach_altflash_region { ($type_name:ident, $region:ident) => { + impl $type_name<'_, MODE> { + pub fn read_blocking(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + crate::flash::common::read_blocking(self.0.base, self.0.size, offset, bytes) + } + } + #[cfg(feature = "nightly")] impl $type_name<'_, Async> { pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - crate::flash::common::read_blocking(self.0.base, self.0.size, offset, bytes) + self.read_blocking(offset, bytes) } pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { @@ -124,10 +130,22 @@ mod alt_regions { } } - impl embedded_storage::nor_flash::ErrorType for $type_name<'_, Async> { + impl embedded_storage::nor_flash::ErrorType for $type_name<'_, MODE> { type Error = Error; } + impl embedded_storage::nor_flash::ReadNorFlash for $type_name<'_, MODE> { + const READ_SIZE: usize = crate::flash::READ_SIZE; + + fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + self.read_blocking(offset, bytes) + } + + fn capacity(&self) -> usize { + self.0.size as usize + } + } + #[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_, Async> { const READ_SIZE: usize = crate::flash::READ_SIZE; diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs index 2b84ec61..47f1d16d 100644 --- a/examples/boot/application/rp/src/bin/a.rs +++ b/examples/boot/application/rp/src/bin/a.rs @@ -26,7 +26,7 @@ async fn main(_s: Spawner) { let mut watchdog = Watchdog::new(p.WATCHDOG); watchdog.start(Duration::from_secs(8)); - let mut flash: Flash<_, FLASH_SIZE> = Flash::new_blocking_only(p.FLASH); + let mut flash: Flash<_, FLASH_SIZE> = Flash::new_blocking(p.FLASH); let mut updater = FirmwareUpdater::default(); diff --git a/examples/boot/application/stm32f3/src/bin/a.rs b/examples/boot/application/stm32f3/src/bin/a.rs index a69b6327..5db1dbb5 100644 --- a/examples/boot/application/stm32f3/src/bin/a.rs +++ b/examples/boot/application/stm32f3/src/bin/a.rs @@ -17,7 +17,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new_blocking_only(p.FLASH); + let flash = Flash::new_blocking(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PC13, Pull::Up); diff --git a/examples/boot/application/stm32f7/src/bin/a.rs b/examples/boot/application/stm32f7/src/bin/a.rs index 1f55db93..5d586445 100644 --- a/examples/boot/application/stm32f7/src/bin/a.rs +++ b/examples/boot/application/stm32f7/src/bin/a.rs @@ -16,7 +16,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let mut flash = Flash::new_blocking_only(p.FLASH); + let mut flash = Flash::new_blocking(p.FLASH); let button = Input::new(p.PC13, Pull::Down); let mut button = ExtiInput::new(button, p.EXTI13); diff --git a/examples/boot/application/stm32h7/src/bin/a.rs b/examples/boot/application/stm32h7/src/bin/a.rs index b8617c3b..20222022 100644 --- a/examples/boot/application/stm32h7/src/bin/a.rs +++ b/examples/boot/application/stm32h7/src/bin/a.rs @@ -16,7 +16,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let mut flash = Flash::new_blocking_only(p.FLASH); + let mut flash = Flash::new_blocking(p.FLASH); let button = Input::new(p.PC13, Pull::Down); let mut button = ExtiInput::new(button, p.EXTI13); diff --git a/examples/boot/application/stm32l0/src/bin/a.rs b/examples/boot/application/stm32l0/src/bin/a.rs index c6663563..4033ac59 100644 --- a/examples/boot/application/stm32l0/src/bin/a.rs +++ b/examples/boot/application/stm32l0/src/bin/a.rs @@ -18,7 +18,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new_blocking_only(p.FLASH); + let flash = Flash::new_blocking(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PB2, Pull::Up); diff --git a/examples/boot/application/stm32l1/src/bin/a.rs b/examples/boot/application/stm32l1/src/bin/a.rs index c6663563..4033ac59 100644 --- a/examples/boot/application/stm32l1/src/bin/a.rs +++ b/examples/boot/application/stm32l1/src/bin/a.rs @@ -18,7 +18,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new_blocking_only(p.FLASH); + let flash = Flash::new_blocking(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PB2, Pull::Up); diff --git a/examples/boot/application/stm32l4/src/bin/a.rs b/examples/boot/application/stm32l4/src/bin/a.rs index 86936222..141d82af 100644 --- a/examples/boot/application/stm32l4/src/bin/a.rs +++ b/examples/boot/application/stm32l4/src/bin/a.rs @@ -17,7 +17,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new_blocking_only(p.FLASH); + let flash = Flash::new_blocking(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PC13, Pull::Up); diff --git a/examples/boot/application/stm32wl/src/bin/a.rs b/examples/boot/application/stm32wl/src/bin/a.rs index 2982e8df..5f48dbe5 100644 --- a/examples/boot/application/stm32wl/src/bin/a.rs +++ b/examples/boot/application/stm32wl/src/bin/a.rs @@ -17,7 +17,7 @@ static APP_B: &[u8] = include_bytes!("../../b.bin"); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); - let flash = Flash::new_blocking_only(p.FLASH); + let flash = Flash::new_blocking(p.FLASH); let mut flash = BlockingAsync::new(flash); let button = Input::new(p.PA0, Pull::Up); diff --git a/examples/boot/bootloader/stm32/src/main.rs b/examples/boot/bootloader/stm32/src/main.rs index 5e8a4f2b..f81fdbc5 100644 --- a/examples/boot/bootloader/stm32/src/main.rs +++ b/examples/boot/bootloader/stm32/src/main.rs @@ -20,7 +20,7 @@ fn main() -> ! { */ let mut bl: BootLoader<2048> = BootLoader::default(); - let layout = Flash::new_blocking_only(p.FLASH).into_blocking_regions(); + let layout = Flash::new_blocking(p.FLASH).into_blocking_regions(); let mut flash = BootFlash::new(layout.bank1_region); let start = bl.prepare(&mut SingleFlashConfig::new(&mut flash)); core::mem::drop(flash); diff --git a/examples/stm32f3/src/bin/flash.rs b/examples/stm32f3/src/bin/flash.rs index 9a31b548..2432a29d 100644 --- a/examples/stm32f3/src/bin/flash.rs +++ b/examples/stm32f3/src/bin/flash.rs @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index 455af930..cadb0129 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { // Once can also call `into_regions()` to get access to NorFlash implementations // for each of the unique characteristics. - let mut f = Flash::new_blocking_only(p.FLASH); + let mut f = Flash::new_blocking(p.FLASH); // Sector 5 test_flash(&mut f, 128 * 1024, 128 * 1024); diff --git a/examples/stm32f7/src/bin/flash.rs b/examples/stm32f7/src/bin/flash.rs index 5507e731..f3b66755 100644 --- a/examples/stm32f7/src/bin/flash.rs +++ b/examples/stm32f7/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::{flash::Flash, interrupt}; +use embassy_stm32::flash::Flash; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -18,7 +18,7 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = Flash::new(p.FLASH, interrupt::take!(FLASH)).into_blocking_regions().bank1_region3; + let mut f = Flash::new_blocking(p.FLASH).into_blocking_regions().bank1_region3; info!("Reading..."); let mut buf = [0u8; 32]; diff --git a/examples/stm32h7/src/bin/flash.rs b/examples/stm32h7/src/bin/flash.rs index c0c332c3..982e2451 100644 --- a/examples/stm32h7/src/bin/flash.rs +++ b/examples/stm32h7/src/bin/flash.rs @@ -18,7 +18,7 @@ async fn main(_spawner: Spawner) { // wait a bit before accessing the flash Timer::after(Duration::from_millis(300)).await; - let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank2_region; + let mut f = Flash::new_blocking(p.FLASH).into_blocking_regions().bank2_region; info!("Reading..."); let mut buf = [0u8; 32]; diff --git a/examples/stm32l0/src/bin/flash.rs b/examples/stm32l0/src/bin/flash.rs index 57ccf7f5..f057421f 100644 --- a/examples/stm32l0/src/bin/flash.rs +++ b/examples/stm32l0/src/bin/flash.rs @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32l1/src/bin/flash.rs b/examples/stm32l1/src/bin/flash.rs index 71174bfb..8046f16b 100644 --- a/examples/stm32l1/src/bin/flash.rs +++ b/examples/stm32l1/src/bin/flash.rs @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x26000; - let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs index 51bd0db4..81e365fb 100644 --- a/examples/stm32wl/src/bin/flash.rs +++ b/examples/stm32wl/src/bin/flash.rs @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { const ADDR: u32 = 0x36000; - let mut f = Flash::new_blocking_only(p.FLASH).into_blocking_regions().bank1_region; + let mut f = Flash::new_blocking(p.FLASH).into_blocking_regions().bank1_region; info!("Reading..."); let mut buf = [0u8; 8]; From 9eca19b49d462e57308e8b13f7ff03e10cfb0557 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 21:46:26 +0200 Subject: [PATCH 33/47] *_blocking -> blocking_* --- embassy-stm32/src/flash/asynch.rs | 4 +-- embassy-stm32/src/flash/common.rs | 42 +++++++++++++++---------------- embassy-stm32/src/flash/f0.rs | 10 ++++---- embassy-stm32/src/flash/f3.rs | 10 ++++---- embassy-stm32/src/flash/f4.rs | 18 ++++++------- embassy-stm32/src/flash/f7.rs | 10 ++++---- embassy-stm32/src/flash/h7.rs | 10 ++++---- embassy-stm32/src/flash/l.rs | 10 ++++---- embassy-stm32/src/flash/other.rs | 4 +-- 9 files changed, 59 insertions(+), 59 deletions(-) diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 74c54ff3..de53f6c8 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -4,7 +4,7 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::mutex::Mutex; use super::{ - ensure_sector_aligned, family, get_sector, read_blocking, Async, Error, Flash, FlashLayout, FLASH_BASE, FLASH_SIZE, + blocking_read, ensure_sector_aligned, family, get_sector, Async, Error, Flash, FlashLayout, FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE, }; @@ -112,7 +112,7 @@ foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { impl crate::_generated::flash_regions::$type_name<'_, Async> { pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - read_blocking(self.0.base, self.0.size, offset, bytes) + blocking_read(self.0.base, self.0.size, offset, bytes) } pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 8ae72ebc..54c8d681 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -54,12 +54,12 @@ impl<'d, MODE> Flash<'d, MODE> { } pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - read_blocking(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) + blocking_read(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } - pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { unsafe { - write_blocking( + blocking_write( FLASH_BASE as u32, FLASH_SIZE as u32, offset, @@ -69,8 +69,8 @@ impl<'d, MODE> Flash<'d, MODE> { } } - pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { erase_blocking(FLASH_BASE as u32, from, to, erase_sector_unlocked) } + pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + unsafe { blocking_erase(FLASH_BASE as u32, from, to, erase_sector_unlocked) } } } @@ -83,7 +83,7 @@ impl interrupt::Handler for InterruptHandler { } } -pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { +pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); } @@ -97,7 +97,7 @@ pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8]) Ok(()) } -pub(super) unsafe fn write_blocking( +pub(super) unsafe fn blocking_write( base: u32, size: u32, offset: u32, @@ -135,14 +135,14 @@ pub(super) unsafe fn write_chunk_unlocked(address: u32, chunk: &[u8]) -> Result< family::lock(); }); - family::write_blocking(address, chunk.try_into().unwrap()) + family::blocking_write(address, chunk.try_into().unwrap()) } pub(super) unsafe fn write_chunk_with_critical_section(address: u32, chunk: &[u8]) -> Result<(), Error> { critical_section::with(|_| write_chunk_unlocked(address, chunk)) } -pub(super) unsafe fn erase_blocking( +pub(super) unsafe fn blocking_erase( base: u32, from: u32, to: u32, @@ -174,7 +174,7 @@ pub(super) unsafe fn erase_sector_unlocked(sector: &FlashSector) -> Result<(), E let _on_drop = OnDrop::new(|| family::lock()); - family::erase_sector_blocking(§or) + family::blocking_erase_sector(§or) } pub(super) unsafe fn erase_sector_with_critical_section(sector: &FlashSector) -> Result<(), Error> { @@ -246,29 +246,29 @@ impl embedded_storage::nor_flash::NorFlash for Flash<'_, MODE> { const ERASE_SIZE: usize = MAX_ERASE_SIZE; fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.write_blocking(offset, bytes) + self.blocking_write(offset, bytes) } fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.erase_blocking(from, to) + self.blocking_erase(from, to) } } foreach_flash_region! { ($type_name:ident, $write_size:literal, $erase_size:literal) => { impl crate::_generated::flash_regions::$type_name<'_, MODE> { - pub fn read_blocking(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - read_blocking(self.0.base, self.0.size, offset, bytes) + pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + blocking_read(self.0.base, self.0.size, offset, bytes) } } impl crate::_generated::flash_regions::$type_name<'_, Blocking> { - pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { - unsafe { write_blocking(self.0.base, self.0.size, offset, bytes, write_chunk_with_critical_section) } + pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { + unsafe { blocking_write(self.0.base, self.0.size, offset, bytes, write_chunk_with_critical_section) } } - pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> { - unsafe { erase_blocking(self.0.base, from, to, erase_sector_with_critical_section) } + pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { + unsafe { blocking_erase(self.0.base, from, to, erase_sector_with_critical_section) } } } @@ -280,7 +280,7 @@ foreach_flash_region! { const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read_blocking(offset, bytes) + self.blocking_read(offset, bytes) } fn capacity(&self) -> usize { @@ -293,11 +293,11 @@ foreach_flash_region! { const ERASE_SIZE: usize = $erase_size; fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.write_blocking(offset, bytes) + self.blocking_write(offset, bytes) } fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.erase_blocking(from, to) + self.blocking_erase(from, to) } } }; diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index cd17486e..9adf3fab 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -36,7 +36,7 @@ pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for chunk in buf.chunks(2) { write_volatile(address as *mut u16, u16::from_le_bytes(chunk.try_into().unwrap())); @@ -46,10 +46,10 @@ pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - wait_ready_blocking() + blocking_wait_ready() } -pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_per(true); }); @@ -60,7 +60,7 @@ pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let mut ret: Result<(), Error> = wait_ready_blocking(); + let mut ret: Result<(), Error> = blocking_wait_ready(); if !pac::FLASH.sr().read().eop() { trace!("FLASH: EOP not set"); @@ -92,7 +92,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn wait_ready_blocking() -> Result<(), Error> { +unsafe fn blocking_wait_ready() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index 4ce39128..b052b4d4 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -36,7 +36,7 @@ pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for chunk in buf.chunks(2) { write_volatile(address as *mut u16, u16::from_le_bytes(chunk.try_into().unwrap())); @@ -46,10 +46,10 @@ pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - wait_ready_blocking() + blocking_wait_ready() } -pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_per(true); }); @@ -60,7 +60,7 @@ pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let mut ret: Result<(), Error> = wait_ready_blocking(); + let mut ret: Result<(), Error> = blocking_wait_ready(); if !pac::FLASH.sr().read().eop() { trace!("FLASH: EOP not set"); @@ -92,7 +92,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn wait_ready_blocking() -> Result<(), Error> { +unsafe fn blocking_wait_ready() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 875bb912..5e0e9620 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -108,15 +108,15 @@ mod alt_regions { macro_rules! foreach_altflash_region { ($type_name:ident, $region:ident) => { impl $type_name<'_, MODE> { - pub fn read_blocking(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - crate::flash::common::read_blocking(self.0.base, self.0.size, offset, bytes) + pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { + crate::flash::common::blocking_read(self.0.base, self.0.size, offset, bytes) } } #[cfg(feature = "nightly")] impl $type_name<'_, Async> { pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - self.read_blocking(offset, bytes) + self.blocking_read(offset, bytes) } pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { @@ -138,7 +138,7 @@ mod alt_regions { const READ_SIZE: usize = crate::flash::READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read_blocking(offset, bytes) + self.blocking_read(offset, bytes) } fn capacity(&self) -> usize { @@ -299,9 +299,9 @@ pub(crate) async unsafe fn write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> wait_ready().await } -pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { write_start(start_address, buf); - wait_ready_blocking() + blocking_wait_ready() } unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) { @@ -340,7 +340,7 @@ pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Erro ret } -pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { save_data_cache_state(); pac::FLASH.cr().modify(|w| { @@ -352,7 +352,7 @@ pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let ret: Result<(), Error> = wait_ready_blocking(); + let ret: Result<(), Error> = blocking_wait_ready(); clear_all_err(); restore_data_cache_state(); ret @@ -386,7 +386,7 @@ pub(crate) async unsafe fn wait_ready() -> Result<(), Error> { .await } -unsafe fn wait_ready_blocking() -> Result<(), Error> { +unsafe fn blocking_wait_ready() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index ab518bf8..f0c6bf81 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs @@ -38,7 +38,7 @@ pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); @@ -48,10 +48,10 @@ pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - wait_ready_blocking() + blocking_wait_ready() } -pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { +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_in_bank) @@ -61,7 +61,7 @@ pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), E w.set_strt(true); }); - let ret: Result<(), Error> = wait_ready_blocking(); + let ret: Result<(), Error> = blocking_wait_ready(); pac::FLASH.cr().modify(|w| w.set_ser(false)); clear_all_err(); ret @@ -87,7 +87,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn wait_ready_blocking() -> Result<(), Error> { +unsafe fn blocking_wait_ready() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index d6818d59..ee824ed2 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -43,7 +43,7 @@ pub(crate) unsafe fn enable_blocking_write() { pub(crate) unsafe fn disable_blocking_write() {} -pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { // We cannot have the write setup sequence in begin_write as it depends on the address let bank = if start_address < BANK1_REGION.end() { pac::FLASH.bank(0) @@ -64,7 +64,7 @@ pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); address += val.len() as u32; - res = Some(wait_ready_blocking(bank)); + res = Some(blocking_wait_ready(bank)); bank.sr().modify(|w| { if w.eop() { w.set_eop(true); @@ -84,7 +84,7 @@ pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) res.unwrap() } -pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { let bank = pac::FLASH.bank(sector.bank as usize); bank.cr().modify(|w| { w.set_ser(true); @@ -95,7 +95,7 @@ pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), E w.set_start(true); }); - let ret: Result<(), Error> = wait_ready_blocking(bank); + let ret: Result<(), Error> = blocking_wait_ready(bank); bank.cr().modify(|w| w.set_ser(false)); bank_clear_all_err(bank); ret @@ -142,7 +142,7 @@ unsafe fn bank_clear_all_err(bank: pac::flash::Bank) { }); } -unsafe fn wait_ready_blocking(bank: pac::flash::Bank) -> Result<(), Error> { +unsafe fn blocking_wait_ready(bank: pac::flash::Bank) -> Result<(), Error> { loop { let sr = bank.sr().read(); diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index c2394e0c..76cad6d1 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -57,7 +57,7 @@ pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); @@ -67,10 +67,10 @@ pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) fence(Ordering::SeqCst); } - wait_ready_blocking() + blocking_wait_ready() } -pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { #[cfg(any(flash_l0, flash_l1))] { pac::FLASH.pecr().modify(|w| { @@ -100,7 +100,7 @@ pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), E }); } - let ret: Result<(), Error> = wait_ready_blocking(); + let ret: Result<(), Error> = blocking_wait_ready(); #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().modify(|w| w.set_per(false)); @@ -153,7 +153,7 @@ pub(crate) unsafe fn clear_all_err() { }); } -unsafe fn wait_ready_blocking() -> Result<(), Error> { +unsafe fn blocking_wait_ready() -> Result<(), Error> { loop { let sr = pac::FLASH.sr().read(); diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index e569951f..c007f117 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs @@ -24,10 +24,10 @@ pub(crate) unsafe fn enable_blocking_write() { pub(crate) unsafe fn disable_blocking_write() { unimplemented!(); } -pub(crate) unsafe fn write_blocking(_start_address: u32, _buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(_start_address: u32, _buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { unimplemented!(); } -pub(crate) unsafe fn erase_sector_blocking(_sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn blocking_erase_sector(_sector: &FlashSector) -> Result<(), Error> { unimplemented!(); } pub(crate) unsafe fn clear_all_err() { From 344e28360ff55771379202ecd06eb0cb1db38a29 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 22:09:28 +0200 Subject: [PATCH 34/47] More blocking rename --- embassy-stm32/src/flash/common.rs | 12 ++++++------ embassy-stm32/src/flash/f0.rs | 2 +- embassy-stm32/src/flash/f3.rs | 2 +- embassy-stm32/src/flash/l.rs | 2 +- embassy-stm32/src/flash/other.rs | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 1ea65c0b..0729771a 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -92,7 +92,7 @@ impl interrupt::Handler for InterruptHandler { } } -pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { +pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); } @@ -255,11 +255,11 @@ impl embedded_storage::nor_flash::NorFlash for Flash<'_, MODE> { const ERASE_SIZE: usize = MAX_ERASE_SIZE; fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.write_blocking(offset, bytes) + self.blocking_write(offset, bytes) } fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.erase_blocking(from, to) + self.blocking_erase(from, to) } } @@ -289,7 +289,7 @@ foreach_flash_region! { const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { - self.read_blocking(offset, bytes) + self.blocking_read(offset, bytes) } fn capacity(&self) -> usize { @@ -302,11 +302,11 @@ foreach_flash_region! { const ERASE_SIZE: usize = $erase_size; fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { - self.write_blocking(offset, bytes) + self.blocking_write(offset, bytes) } fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { - self.erase_blocking(from, to) + self.blocking_erase(from, to) } } }; diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index cd17486e..22e08e91 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -36,7 +36,7 @@ pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for chunk in buf.chunks(2) { write_volatile(address as *mut u16, u16::from_le_bytes(chunk.try_into().unwrap())); diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index 4ce39128..e0573470 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -36,7 +36,7 @@ pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for chunk in buf.chunks(2) { write_volatile(address as *mut u16, u16::from_le_bytes(chunk.try_into().unwrap())); diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index c2394e0c..e27accb0 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -57,7 +57,7 @@ pub(crate) unsafe fn disable_blocking_write() { pac::FLASH.cr().write(|w| w.set_pg(false)); } -pub(crate) unsafe fn write_blocking(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { let mut address = start_address; for val in buf.chunks(4) { write_volatile(address as *mut u32, u32::from_le_bytes(val.try_into().unwrap())); diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index e569951f..73266177 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs @@ -24,7 +24,7 @@ pub(crate) unsafe fn enable_blocking_write() { pub(crate) unsafe fn disable_blocking_write() { unimplemented!(); } -pub(crate) unsafe fn write_blocking(_start_address: u32, _buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { +pub(crate) unsafe fn blocking_write(_start_address: u32, _buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { unimplemented!(); } pub(crate) unsafe fn erase_sector_blocking(_sector: &FlashSector) -> Result<(), Error> { From 8528455a75aa33cf774d72ba6b35a4298bca511e Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 22:20:05 +0200 Subject: [PATCH 35/47] Errata if _not_ pa12 out low --- embassy-stm32/src/flash/f4.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 5e0e9620..8c9c9369 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -463,7 +463,7 @@ pub(crate) fn assert_not_corrupted_read() { feature = "stm32f439vi", feature = "stm32f439zi", ))] - if unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && pa12_is_output_pull_low() } { + if unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } { panic!("Read corruption for stm32f42xxI and stm32f43xxI when PA12 is in use for chips below revision 3, see errata 2.2.11"); } @@ -490,7 +490,7 @@ pub(crate) fn assert_not_corrupted_read() { if unsafe { pac::FLASH.optcr().read().db1m() && pac::DBGMCU.idcode().read().rev_id() < REVISION_3 - && pa12_is_output_pull_low() + && !pa12_is_output_pull_low() } { panic!("Read corruption for stm32f42xxG and stm32f43xxG in dual bank mode when PA12 is in use for chips below revision 3, see errata 2.2.11"); } From ce331b411c3a6c69fbfefa968319f8eba5ad813f Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 22:31:24 +0200 Subject: [PATCH 36/47] Only assert_not_corrupted_read if we read from the second bank --- embassy-stm32/src/flash/common.rs | 7 ++++--- embassy-stm32/src/flash/f4.rs | 15 ++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 0729771a..35f5a464 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -97,10 +97,11 @@ pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) return Err(Error::Size); } - #[cfg(flash_f4)] - family::assert_not_corrupted_read(); - let start_address = base + offset; + + #[cfg(flash_f4)] + family::assert_not_corrupted_read(start_address + bytes.len()); + let flash_data = unsafe { core::slice::from_raw_parts(start_address as *const u8, bytes.len()) }; bytes.copy_from_slice(flash_data); Ok(()) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 8c9c9369..a43efc51 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -6,6 +6,7 @@ use atomic_polyfill::AtomicBool; #[cfg(feature = "nightly")] use embassy_sync::waitqueue::AtomicWaker; use pac::flash::regs::Sr; +use pac::FLASH_SIZE; use super::{FlashBank, FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; @@ -437,10 +438,13 @@ fn restore_data_cache_state() { } } -pub(crate) fn assert_not_corrupted_read() { +pub(crate) fn assert_not_corrupted_read(end_address: u32) { #[allow(unused)] const REVISION_3: u16 = 0x2001; + #[allow(unused)] + let second_bank_read = get_flash_regions().last().unwrap().bank == FlashBank::Bank2 && end_address > FLASH_SIZE / 2; + #[cfg(any( feature = "stm32f427ai", feature = "stm32f427ii", @@ -463,7 +467,7 @@ pub(crate) fn assert_not_corrupted_read() { feature = "stm32f439vi", feature = "stm32f439zi", ))] - if unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } { + if second_bank_read && unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } { panic!("Read corruption for stm32f42xxI and stm32f43xxI when PA12 is in use for chips below revision 3, see errata 2.2.11"); } @@ -487,11 +491,8 @@ pub(crate) fn assert_not_corrupted_read() { feature = "stm32f439vg", feature = "stm32f439zg", ))] - if unsafe { - pac::FLASH.optcr().read().db1m() - && pac::DBGMCU.idcode().read().rev_id() < REVISION_3 - && !pa12_is_output_pull_low() - } { + if second_bank_read && unsafe { &&pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } + { panic!("Read corruption for stm32f42xxG and stm32f43xxG in dual bank mode when PA12 is in use for chips below revision 3, see errata 2.2.11"); } } From b50d04336ee3608e36545908cbf45969e81c9807 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 22:32:57 +0200 Subject: [PATCH 37/47] Fix merge error --- embassy-stm32/src/flash/common.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 35f5a464..400831e0 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -83,15 +83,6 @@ impl interrupt::Handler for InterruptHandler { } } -/// Interrupt handler -pub struct InterruptHandler; - -impl interrupt::Handler for InterruptHandler { - unsafe fn on_interrupt() { - family::on_interrupt(); - } -} - pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); From 8938d928f8c3920a5777b0537d5d9ab3fec94586 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 22:36:56 +0200 Subject: [PATCH 38/47] Fix examples --- examples/stm32f3/src/bin/flash.rs | 10 +++++----- examples/stm32f4/src/bin/flash.rs | 4 ++-- examples/stm32f7/src/bin/flash.rs | 10 +++++----- examples/stm32h7/src/bin/flash.rs | 10 +++++----- examples/stm32l0/src/bin/flash.rs | 10 +++++----- examples/stm32l1/src/bin/flash.rs | 10 +++++----- examples/stm32wl/src/bin/flash.rs | 10 +++++----- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/examples/stm32f3/src/bin/flash.rs b/examples/stm32f3/src/bin/flash.rs index 2432a29d..236fb36c 100644 --- a/examples/stm32f3/src/bin/flash.rs +++ b/examples/stm32f3/src/bin/flash.rs @@ -18,23 +18,23 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase_blocking(ADDR, ADDR + 2048)); + unwrap!(f.blocking_erase(ADDR, ADDR + 2048)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.blocking_write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index cadb0129..4a77595c 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs @@ -35,7 +35,7 @@ fn test_flash(f: &mut Flash, offset: u32, size: u32) { info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase_blocking(offset, offset + size)); + unwrap!(f.blocking_erase(offset, offset + size)); info!("Reading..."); let mut buf = [0u8; 32]; @@ -43,7 +43,7 @@ fn test_flash(f: &mut Flash, offset: u32, size: u32) { info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write_blocking( + unwrap!(f.blocking_write( offset, &[ 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, diff --git a/examples/stm32f7/src/bin/flash.rs b/examples/stm32f7/src/bin/flash.rs index f3b66755..35d3059b 100644 --- a/examples/stm32f7/src/bin/flash.rs +++ b/examples/stm32f7/src/bin/flash.rs @@ -22,19 +22,19 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase_blocking(ADDR, ADDR + 256 * 1024)); + unwrap!(f.blocking_erase(ADDR, ADDR + 256 * 1024)); info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write_blocking( + unwrap!(f.blocking_write( ADDR, &[ 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, @@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!( &buf[..], diff --git a/examples/stm32h7/src/bin/flash.rs b/examples/stm32h7/src/bin/flash.rs index 982e2451..f66df770 100644 --- a/examples/stm32h7/src/bin/flash.rs +++ b/examples/stm32h7/src/bin/flash.rs @@ -22,19 +22,19 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase_blocking(ADDR, ADDR + 128 * 1024)); + unwrap!(f.blocking_erase(ADDR, ADDR + 128 * 1024)); info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write_blocking( + unwrap!(f.blocking_write( ADDR, &[ 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, @@ -44,7 +44,7 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 32]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!( &buf[..], diff --git a/examples/stm32l0/src/bin/flash.rs b/examples/stm32l0/src/bin/flash.rs index f057421f..86f6c70b 100644 --- a/examples/stm32l0/src/bin/flash.rs +++ b/examples/stm32l0/src/bin/flash.rs @@ -18,23 +18,23 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase_blocking(ADDR, ADDR + 128)); + unwrap!(f.blocking_erase(ADDR, ADDR + 128)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.blocking_write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } diff --git a/examples/stm32l1/src/bin/flash.rs b/examples/stm32l1/src/bin/flash.rs index 8046f16b..aeb535cc 100644 --- a/examples/stm32l1/src/bin/flash.rs +++ b/examples/stm32l1/src/bin/flash.rs @@ -18,23 +18,23 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase_blocking(ADDR, ADDR + 256)); + unwrap!(f.blocking_erase(ADDR, ADDR + 256)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read after erase: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.blocking_write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs index 81e365fb..5e52d49e 100644 --- a/examples/stm32wl/src/bin/flash.rs +++ b/examples/stm32wl/src/bin/flash.rs @@ -18,23 +18,23 @@ async fn main(_spawner: Spawner) { info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Erasing..."); - unwrap!(f.erase_blocking(ADDR, ADDR + 2048)); + unwrap!(f.blocking_erase(ADDR, ADDR + 2048)); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); info!("Writing..."); - unwrap!(f.write_blocking(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); + unwrap!(f.blocking_write(ADDR, &[1, 2, 3, 4, 5, 6, 7, 8])); info!("Reading..."); let mut buf = [0u8; 8]; - unwrap!(f.read_blocking(ADDR, &mut buf)); + unwrap!(f.blocking_read(ADDR, &mut buf)); info!("Read: {=[u8]:x}", buf); assert_eq!(&buf[..], &[1, 2, 3, 4, 5, 6, 7, 8]); } From 41a632a56c40d0ac522a8dcf20b95ed478dc41ea Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 22:48:17 +0200 Subject: [PATCH 39/47] Formatting --- examples/stm32f4/src/bin/flash_async.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/stm32f4/src/bin/flash_async.rs b/examples/stm32f4/src/bin/flash_async.rs index 67533708..6c9689d9 100644 --- a/examples/stm32f4/src/bin/flash_async.rs +++ b/examples/stm32f4/src/bin/flash_async.rs @@ -4,10 +4,10 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_time::{Timer, Duration}; +use embassy_stm32::bind_interrupts; use embassy_stm32::flash::{Flash, InterruptHandler}; use embassy_stm32::gpio::{AnyPin, Level, Output, Pin, Speed}; -use embassy_stm32::bind_interrupts; +use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -82,4 +82,4 @@ async fn test_flash<'a>(f: &mut Flash<'a>, offset: u32, size: u32) { 30, 31, 32 ] ); -} \ No newline at end of file +} From 88543445d8414b94720654f1e5dba900e8a75cce Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 22:48:54 +0200 Subject: [PATCH 40/47] Fix end address for assertion --- embassy-stm32/src/flash/common.rs | 2 +- embassy-stm32/src/flash/f4.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 400831e0..c190eaf9 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -91,7 +91,7 @@ pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) let start_address = base + offset; #[cfg(flash_f4)] - family::assert_not_corrupted_read(start_address + bytes.len()); + family::assert_not_corrupted_read(start_address + bytes.len() as u32); let flash_data = unsafe { core::slice::from_raw_parts(start_address as *const u8, bytes.len()) }; bytes.copy_from_slice(flash_data); diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index a43efc51..2dd6d85f 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -443,7 +443,7 @@ pub(crate) fn assert_not_corrupted_read(end_address: u32) { const REVISION_3: u16 = 0x2001; #[allow(unused)] - let second_bank_read = get_flash_regions().last().unwrap().bank == FlashBank::Bank2 && end_address > FLASH_SIZE / 2; + let second_bank_read = get_flash_regions().last().unwrap().bank == FlashBank::Bank2 && end_address > (FLASH_SIZE / 2) as u32; #[cfg(any( feature = "stm32f427ai", @@ -491,7 +491,7 @@ pub(crate) fn assert_not_corrupted_read(end_address: u32) { feature = "stm32f439vg", feature = "stm32f439zg", ))] - if second_bank_read && unsafe { &&pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } + if second_bank_read && unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } { panic!("Read corruption for stm32f42xxG and stm32f43xxG in dual bank mode when PA12 is in use for chips below revision 3, see errata 2.2.11"); } From 4478d8322b41b614599202711ddbf42df1c8b50b Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 22:58:13 +0200 Subject: [PATCH 41/47] Endless rustfmt pain --- embassy-stm32/src/flash/f4.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 2dd6d85f..8a0e2001 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -443,7 +443,8 @@ pub(crate) fn assert_not_corrupted_read(end_address: u32) { const REVISION_3: u16 = 0x2001; #[allow(unused)] - let second_bank_read = get_flash_regions().last().unwrap().bank == FlashBank::Bank2 && end_address > (FLASH_SIZE / 2) as u32; + let second_bank_read = + get_flash_regions().last().unwrap().bank == FlashBank::Bank2 && end_address > (FLASH_SIZE / 2) as u32; #[cfg(any( feature = "stm32f427ai", @@ -491,8 +492,7 @@ pub(crate) fn assert_not_corrupted_read(end_address: u32) { feature = "stm32f439vg", feature = "stm32f439zg", ))] - if second_bank_read && unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } - { + if second_bank_read && unsafe { pac::DBGMCU.idcode().read().rev_id() < REVISION_3 && !pa12_is_output_pull_low() } { panic!("Read corruption for stm32f42xxG and stm32f43xxG in dual bank mode when PA12 is in use for chips below revision 3, see errata 2.2.11"); } } From 74104aafda4a16b7be66f8d1634fc4b663721c49 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 23:13:20 +0200 Subject: [PATCH 42/47] erase_sector_blocking -> blocking_erase_sector --- embassy-stm32/src/flash/f0.rs | 2 +- embassy-stm32/src/flash/f3.rs | 2 +- embassy-stm32/src/flash/f4.rs | 4 ++++ embassy-stm32/src/flash/l.rs | 2 +- embassy-stm32/src/flash/other.rs | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index 22e08e91..bf601f05 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -49,7 +49,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) wait_ready_blocking() } -pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_per(true); }); diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index e0573470..5b566a62 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -49,7 +49,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) wait_ready_blocking() } -pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { pac::FLASH.cr().modify(|w| { w.set_per(true); }); diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 8a0e2001..a9ebaa35 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -320,6 +320,8 @@ unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) { pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> { save_data_cache_state(); + trace!("Erasing sector number {}", sector.snb()); + pac::FLASH.cr().modify(|w| { w.set_ser(true); w.set_snb(sector.snb()); @@ -344,6 +346,8 @@ pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Erro pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { save_data_cache_state(); + trace!("Blocking erasing sector number {}", sector.snb()); + pac::FLASH.cr().modify(|w| { w.set_ser(true); w.set_snb(sector.snb()) diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index e27accb0..0a5b6301 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -70,7 +70,7 @@ pub(crate) unsafe fn blocking_write(start_address: u32, buf: &[u8; WRITE_SIZE]) wait_ready_blocking() } -pub(crate) unsafe fn erase_sector_blocking(sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn blocking_erase_sector(sector: &FlashSector) -> Result<(), Error> { #[cfg(any(flash_l0, flash_l1))] { pac::FLASH.pecr().modify(|w| { diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index 73266177..c007f117 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs @@ -27,7 +27,7 @@ pub(crate) unsafe fn disable_blocking_write() { pub(crate) unsafe fn blocking_write(_start_address: u32, _buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { unimplemented!(); } -pub(crate) unsafe fn erase_sector_blocking(_sector: &FlashSector) -> Result<(), Error> { +pub(crate) unsafe fn blocking_erase_sector(_sector: &FlashSector) -> Result<(), Error> { unimplemented!(); } pub(crate) unsafe fn clear_all_err() { From e08267df54a78106f4c03958346c81ae7e169bd6 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Thu, 25 May 2023 23:51:10 +0200 Subject: [PATCH 43/47] Move new async to asynch module to guard for models without flash interrupt --- embassy-stm32/src/flash/asynch.rs | 31 ++++++++++++++++++++++++++++++ embassy-stm32/src/flash/common.rs | 32 ++----------------------------- embassy-stm32/src/flash/f0.rs | 4 ---- embassy-stm32/src/flash/f3.rs | 4 ---- embassy-stm32/src/flash/f7.rs | 4 ---- embassy-stm32/src/flash/h7.rs | 4 ---- embassy-stm32/src/flash/l.rs | 4 ---- embassy-stm32/src/flash/mod.rs | 4 +++- embassy-stm32/src/flash/other.rs | 4 ---- 9 files changed, 36 insertions(+), 55 deletions(-) diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index de53f6c8..6ad1e90d 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -1,5 +1,9 @@ +use core::marker::PhantomData; + use atomic_polyfill::{fence, Ordering}; +use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; use embassy_hal_common::drop::OnDrop; +use embassy_hal_common::into_ref; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::mutex::Mutex; @@ -7,10 +11,28 @@ use super::{ blocking_read, ensure_sector_aligned, family, get_sector, Async, Error, Flash, FlashLayout, FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE, }; +use crate::peripherals::FLASH; +use crate::{interrupt, Peripheral}; pub(super) static REGION_ACCESS: Mutex = Mutex::new(()); impl<'d> Flash<'d, Async> { + pub fn new( + p: impl Peripheral

+ 'd, + _irq: impl interrupt::Binding + 'd, + ) -> Self { + into_ref!(p); + + let flash_irq = unsafe { crate::interrupt::FLASH::steal() }; + flash_irq.unpend(); + flash_irq.enable(); + + Self { + inner: p, + _mode: PhantomData, + } + } + pub fn into_regions(self) -> FlashLayout<'d, Async> { family::set_default_layout(); FlashLayout::new(self.inner) @@ -25,6 +47,15 @@ impl<'d> Flash<'d, Async> { } } +/// Interrupt handler +pub struct InterruptHandler; + +impl interrupt::Handler for InterruptHandler { + unsafe fn on_interrupt() { + family::on_interrupt(); + } +} + impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_, Async> { const READ_SIZE: usize = READ_SIZE; diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index c190eaf9..cc0e2572 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -1,7 +1,6 @@ use core::marker::PhantomData; use atomic_polyfill::{fence, Ordering}; -use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use stm32_metapac::FLASH_BASE; @@ -11,29 +10,11 @@ use super::{ READ_SIZE, WRITE_SIZE, }; use crate::peripherals::FLASH; -use crate::{interrupt, Peripheral}; +use crate::Peripheral; pub struct Flash<'d, MODE = Async> { pub(crate) inner: PeripheralRef<'d, FLASH>, - _mode: PhantomData, -} - -impl<'d> Flash<'d, Async> { - pub fn new( - p: impl Peripheral

+ 'd, - _irq: impl interrupt::Binding + 'd, - ) -> Self { - into_ref!(p); - - let flash_irq = unsafe { crate::interrupt::FLASH::steal() }; - flash_irq.unpend(); - flash_irq.enable(); - - Self { - inner: p, - _mode: PhantomData, - } - } + pub(crate) _mode: PhantomData, } impl<'d> Flash<'d, Blocking> { @@ -74,15 +55,6 @@ impl<'d, MODE> Flash<'d, MODE> { } } -/// Interrupt handler -pub struct InterruptHandler; - -impl interrupt::Handler for InterruptHandler { - unsafe fn on_interrupt() { - family::on_interrupt(); - } -} - pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { if offset + bytes.len() as u32 > size { return Err(Error::Size); diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index bf601f05..e9916d14 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -13,10 +13,6 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt() { - unimplemented!(); -} - pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index 5b566a62..4e65f558 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -13,10 +13,6 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt() { - unimplemented!(); -} - pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index f0c6bf81..e6267e17 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs @@ -12,10 +12,6 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt() { - unimplemented!(); -} - pub(crate) unsafe fn lock() { pac::FLASH.cr().modify(|w| w.set_lock(true)); } diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index ee824ed2..d09ebc0d 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -17,10 +17,6 @@ pub fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt() { - unimplemented!(); -} - pub(crate) unsafe fn lock() { pac::FLASH.bank(0).cr().modify(|w| w.set_lock(true)); if is_dual_bank() { diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index 0a5b6301..c4bbd547 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -12,10 +12,6 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt() { - unimplemented!(); -} - pub(crate) unsafe fn lock() { #[cfg(any(flash_wl, flash_wb, flash_l4))] pac::FLASH.cr().modify(|w| w.set_lock(true)); diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 02f6c532..2cc92f51 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -1,10 +1,12 @@ use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; #[cfg(all(feature = "nightly", flash_f4))] -pub mod asynch; +mod asynch; #[cfg(flash)] mod common; +#[cfg(all(feature = "nightly", flash_f4))] +pub use asynch::InterruptHandler; #[cfg(flash)] pub use common::*; diff --git a/embassy-stm32/src/flash/other.rs b/embassy-stm32/src/flash/other.rs index c007f117..ccdcfeb7 100644 --- a/embassy-stm32/src/flash/other.rs +++ b/embassy-stm32/src/flash/other.rs @@ -8,10 +8,6 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -pub(crate) unsafe fn on_interrupt() { - unimplemented!(); -} - pub(crate) unsafe fn lock() { unimplemented!(); } From 9115431d358628f2d0ff9f9b5d017e2f3b23472b Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Fri, 26 May 2023 00:12:22 +0200 Subject: [PATCH 44/47] Move nightly guard and clear data cache reset bit --- embassy-stm32/src/flash/f4.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index a9ebaa35..35548a55 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -236,6 +236,7 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } +#[cfg(feature = "nightly")] pub(crate) unsafe fn on_interrupt() { // Clear IRQ flags pac::FLASH.sr().write(|w| { @@ -243,7 +244,6 @@ pub(crate) unsafe fn on_interrupt() { w.set_eop(true); }); - #[cfg(feature = "nightly")] WAKER.wake(); } @@ -436,6 +436,7 @@ fn restore_data_cache_state() { unsafe { // Reset data cache before we enable it again pac::FLASH.acr().modify(|w| w.set_dcrst(true)); + pac::FLASH.acr().modify(|w| w.set_dcrst(false)); pac::FLASH.acr().modify(|w| w.set_dcen(true)) }; } From 35d8edbc4104be16d1b1437b32a135a411b2d0e1 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Fri, 26 May 2023 00:31:41 +0200 Subject: [PATCH 45/47] nightly guard async traits only --- embassy-stm32/src/flash/asynch.rs | 12 ++++++++---- embassy-stm32/src/flash/f4.rs | 11 +---------- embassy-stm32/src/flash/mod.rs | 4 ++-- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 6ad1e90d..a0d99495 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -9,7 +9,7 @@ use embassy_sync::mutex::Mutex; use super::{ blocking_read, ensure_sector_aligned, family, get_sector, Async, Error, Flash, FlashLayout, FLASH_BASE, FLASH_SIZE, - MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE, + WRITE_SIZE, }; use crate::peripherals::FLASH; use crate::{interrupt, Peripheral}; @@ -56,8 +56,9 @@ impl interrupt::Handler for InterruptHandler { } } +#[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_, Async> { - const READ_SIZE: usize = READ_SIZE; + const READ_SIZE: usize = super::READ_SIZE; async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { self.read(offset, bytes) @@ -68,9 +69,10 @@ impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_, Async> { } } +#[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::NorFlash for Flash<'_, Async> { const WRITE_SIZE: usize = WRITE_SIZE; - const ERASE_SIZE: usize = MAX_ERASE_SIZE; + const ERASE_SIZE: usize = super::MAX_ERASE_SIZE; async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { self.write(offset, bytes).await @@ -157,8 +159,9 @@ foreach_flash_region! { } } + #[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_, Async> { - const READ_SIZE: usize = READ_SIZE; + const READ_SIZE: usize = super::READ_SIZE; async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { self.read(offset, bytes).await @@ -169,6 +172,7 @@ foreach_flash_region! { } } + #[cfg(feature = "nightly")] impl embedded_storage_async::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_, Async> { const WRITE_SIZE: usize = $write_size; const ERASE_SIZE: usize = $erase_size; diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 35548a55..dd7a04aa 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -3,7 +3,6 @@ use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; use atomic_polyfill::AtomicBool; -#[cfg(feature = "nightly")] use embassy_sync::waitqueue::AtomicWaker; use pac::flash::regs::Sr; use pac::FLASH_SIZE; @@ -20,7 +19,7 @@ mod alt_regions { use stm32_metapac::FLASH_SIZE; use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; - #[cfg(feature = "nightly")] + use crate::flash::asynch; use crate::flash::{Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion}; use crate::peripherals::FLASH; @@ -114,7 +113,6 @@ mod alt_regions { } } - #[cfg(feature = "nightly")] impl $type_name<'_, Async> { pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { self.blocking_read(offset, bytes) @@ -185,7 +183,6 @@ mod alt_regions { #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] pub use alt_regions::*; -#[cfg(feature = "nightly")] static WAKER: AtomicWaker = AtomicWaker::new(); static DATA_CACHE_WAS_ENABLED: AtomicBool = AtomicBool::new(false); @@ -236,7 +233,6 @@ pub const fn get_flash_regions() -> &'static [&'static FlashRegion] { &FLASH_REGIONS } -#[cfg(feature = "nightly")] pub(crate) unsafe fn on_interrupt() { // Clear IRQ flags pac::FLASH.sr().write(|w| { @@ -256,7 +252,6 @@ pub(crate) unsafe fn unlock() { pac::FLASH.keyr().write(|w| w.set_key(0xCDEF89AB)); } -#[cfg(feature = "nightly")] pub(crate) unsafe fn enable_write() { assert_eq!(0, WRITE_SIZE % 4); save_data_cache_state(); @@ -269,7 +264,6 @@ pub(crate) unsafe fn enable_write() { }); } -#[cfg(feature = "nightly")] pub(crate) unsafe fn disable_write() { pac::FLASH.cr().write(|w| { w.set_pg(false); @@ -294,7 +288,6 @@ pub(crate) unsafe fn disable_blocking_write() { restore_data_cache_state(); } -#[cfg(feature = "nightly")] pub(crate) async unsafe fn write(start_address: u32, buf: &[u8; WRITE_SIZE]) -> Result<(), Error> { write_start(start_address, buf); wait_ready().await @@ -316,7 +309,6 @@ unsafe fn write_start(start_address: u32, buf: &[u8; WRITE_SIZE]) { } } -#[cfg(feature = "nightly")] pub(crate) async unsafe fn erase_sector(sector: &FlashSector) -> Result<(), Error> { save_data_cache_state(); @@ -372,7 +364,6 @@ pub(crate) unsafe fn clear_all_err() { }); } -#[cfg(feature = "nightly")] pub(crate) async unsafe fn wait_ready() -> Result<(), Error> { use core::task::Poll; diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 2cc92f51..f44ef2c1 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -1,11 +1,11 @@ use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; -#[cfg(all(feature = "nightly", flash_f4))] +#[cfg(flash_f4)] mod asynch; #[cfg(flash)] mod common; -#[cfg(all(feature = "nightly", flash_f4))] +#[cfg(flash_f4)] pub use asynch::InterruptHandler; #[cfg(flash)] pub use common::*; From d82ba4af8a826b5e8f8273b6f314e9c799a0b99c Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Fri, 26 May 2023 00:35:53 +0200 Subject: [PATCH 46/47] WHY does format on save not work --- embassy-stm32/src/flash/f4.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index dd7a04aa..25d96ca1 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -19,9 +19,7 @@ mod alt_regions { use stm32_metapac::FLASH_SIZE; use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; - - use crate::flash::asynch; - use crate::flash::{Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion}; + use crate::flash::{asynch, Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion}; use crate::peripherals::FLASH; pub const ALT_BANK1_REGION3: FlashRegion = FlashRegion { From 307f2365da9b24fac2a0c312106a5f9986c4b5ea Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Fri, 26 May 2023 04:53:43 +0200 Subject: [PATCH 47/47] Fix blocking example --- examples/stm32f4/src/bin/flash.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/stm32f4/src/bin/flash.rs b/examples/stm32f4/src/bin/flash.rs index 4a77595c..93c54e94 100644 --- a/examples/stm32f4/src/bin/flash.rs +++ b/examples/stm32f4/src/bin/flash.rs @@ -4,7 +4,7 @@ use defmt::{info, unwrap}; use embassy_executor::Spawner; -use embassy_stm32::flash::Flash; +use embassy_stm32::flash::{Blocking, Flash}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -26,7 +26,7 @@ async fn main(_spawner: Spawner) { test_flash(&mut f, (2048 - 128) * 1024, 128 * 1024); } -fn test_flash(f: &mut Flash, offset: u32, size: u32) { +fn test_flash(f: &mut Flash<'_, Blocking>, offset: u32, size: u32) { info!("Testing offset: {=u32:#X}, size: {=u32:#X}", offset, size); info!("Reading...");