From 6806bb969278acc9d3cde34897453b29807157c1 Mon Sep 17 00:00:00 2001 From: Rasmus Melchior Jacobsen Date: Wed, 29 Mar 2023 11:52:18 +0200 Subject: [PATCH] Expose flash region settings as an array --- embassy-stm32/build.rs | 42 ++++++++++++++++++++++------------ embassy-stm32/src/flash/mod.rs | 40 +++++++++++++++++--------------- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 393efc426..53f209780 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -3,7 +3,7 @@ use std::fmt::Write as _; use std::path::PathBuf; use std::{env, fs}; -use proc_macro2::TokenStream; +use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use stm32_metapac::metadata::{MemoryRegionKind, METADATA}; @@ -106,12 +106,15 @@ fn main() { // ======== // Generate FLASH regions let mut flash_regions = TokenStream::new(); - let flash_memory_regions = METADATA + let flash_memory_regions: Vec<_> = METADATA .memory .iter() - .filter(|x| x.kind == MemoryRegionKind::Flash && x.settings.is_some()); - for region in flash_memory_regions.clone() { - let region_name = format_ident!("{}", get_flash_region_name(region.name)); + .filter(|x| x.kind == MemoryRegionKind::Flash && x.settings.is_some()) + .collect(); + for region in flash_memory_regions.iter() { + let region_name = get_flash_region_name(region.name); + let region_type = format_ident!("{}", region_name); + let settings_name = format_ident!("{}_SETTINGS", region_name); let base = region.address as usize; let size = region.size as usize; let settings = region.settings.as_ref().unwrap(); @@ -121,21 +124,26 @@ fn main() { flash_regions.extend(quote! { #[allow(non_camel_case_types)] - pub struct #region_name(()); + pub struct #region_type(()); }); flash_regions.extend(quote! { - impl crate::flash::FlashRegion for #region_name { - const BASE: usize = #base; - const SIZE: usize = #size; - const ERASE_SIZE: usize = #erase_size; - const WRITE_SIZE: usize = #write_size; - const ERASE_VALUE: u8 = #erase_value; + pub const #settings_name: crate::flash::FlashRegionSettings = crate::flash::FlashRegionSettings { + base: #base, + size: #size, + erase_size: #erase_size, + write_size: #write_size, + erase_value: #erase_value, + }; + + impl crate::flash::FlashRegion for #region_type { + const SETTINGS: crate::flash::FlashRegionSettings = #settings_name; } }); } - let (fields, inits): (Vec, Vec) = flash_memory_regions + let (fields, (inits, settings)): (Vec, (Vec, Vec)) = flash_memory_regions + .iter() .map(|f| { let region_name = get_flash_region_name(f.name); let field_name = format_ident!("{}", region_name.to_lowercase()); @@ -146,11 +154,13 @@ fn main() { let init = quote! { #field_name: #field_type(()) }; + let settings_name = format_ident!("{}_SETTINGS", region_name); - (field, init) + (field, (init, settings_name)) }) .unzip(); + let regions_len = flash_memory_regions.len(); flash_regions.extend(quote! { pub struct FlashRegions { #(#fields),* @@ -163,6 +173,10 @@ fn main() { } } } + + pub const FLASH_REGIONS: [&crate::flash::FlashRegionSettings; #regions_len] = [ + #(&#settings),* + ]; }); g.extend(quote! { pub mod flash_regions { #flash_regions } }); diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index 6906bd09a..29db2d132 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs @@ -19,6 +19,14 @@ pub struct Flash<'d> { _inner: PeripheralRef<'d, FLASH>, } +pub struct FlashRegionSettings { + pub base: usize, + pub size: usize, + pub erase_size: usize, + pub write_size: usize, + pub erase_value: u8, +} + #[derive(Debug, PartialEq)] pub struct FlashSector { pub index: u8, @@ -122,32 +130,28 @@ impl Drop for FlashRegions { } pub trait FlashRegion { - const BASE: usize; - const SIZE: usize; - const ERASE_SIZE: usize; - const WRITE_SIZE: usize; - const ERASE_VALUE: u8; + const SETTINGS: FlashRegionSettings; fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { - if offset as usize + bytes.len() > Self::SIZE { + if offset as usize + bytes.len() > Self::SETTINGS.size { return Err(Error::Size); } - let first_address = Self::BASE as u32 + offset; + let first_address = Self::SETTINGS.base as u32 + offset; let flash_data = unsafe { core::slice::from_raw_parts(first_address as *const u8, bytes.len()) }; bytes.copy_from_slice(flash_data); Ok(()) } fn blocking_write(&mut self, offset: u32, buf: &[u8]) -> Result<(), Error> { - if offset as usize + buf.len() > Self::SIZE { + if offset as usize + buf.len() > Self::SETTINGS.size { return Err(Error::Size); } - if offset as usize % Self::WRITE_SIZE != 0 || buf.len() as usize % Self::WRITE_SIZE != 0 { + if offset as usize % Self::SETTINGS.write_size != 0 || buf.len() as usize % Self::SETTINGS.write_size != 0 { return Err(Error::Unaligned); } - let start_address = Self::BASE as u32 + offset; + let start_address = Self::SETTINGS.base as u32 + offset; trace!("Writing {} bytes from 0x{:x}", buf.len(), start_address); // Protect agains simultaneous write/erase to multiple regions. @@ -163,15 +167,15 @@ pub trait FlashRegion { } fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { - if to < from || to as usize > Self::SIZE { + if to < from || to as usize > Self::SETTINGS.size { return Err(Error::Size); } - if (from as usize % Self::ERASE_SIZE) != 0 || (to as usize % Self::ERASE_SIZE) != 0 { + if (from as usize % Self::SETTINGS.erase_size) != 0 || (to as usize % Self::SETTINGS.erase_size) != 0 { return Err(Error::Unaligned); } - let start_address = Self::BASE as u32 + from; - let end_address = Self::BASE as u32 + to; + let start_address = Self::SETTINGS.base as u32 + from; + let end_address = Self::SETTINGS.base as u32 + to; trace!("Erasing from 0x{:x} to 0x{:x}", start_address, end_address); // Protect agains simultaneous write/erase to multiple regions. @@ -224,20 +228,20 @@ foreach_flash_region! { } impl ReadNorFlash for crate::_generated::flash_regions::$name { - const READ_SIZE: usize = ::WRITE_SIZE; + const READ_SIZE: usize = ::SETTINGS.write_size; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { self.blocking_read(offset, bytes) } fn capacity(&self) -> usize { - ::SIZE + ::SETTINGS.size } } impl NorFlash for crate::_generated::flash_regions::$name { - const WRITE_SIZE: usize = ::WRITE_SIZE; - const ERASE_SIZE: usize = ::ERASE_SIZE; + const WRITE_SIZE: usize = ::SETTINGS.write_size; + const ERASE_SIZE: usize = ::SETTINGS.erase_size; fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { self.blocking_erase(from, to)