diff options
| -rw-r--r-- | embassy-stm32/build.rs | 53 | ||||
| -rw-r--r-- | embassy-stm32/src/flash/common.rs | 98 | ||||
| -rw-r--r-- | embassy-stm32/src/flash/mod.rs | 16 |
3 files changed, 103 insertions, 64 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index d179f5e0f..8f34f510a 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -112,64 +112,58 @@ fn main() { | |||
| 112 | .filter(|x| x.kind == MemoryRegionKind::Flash && x.settings.is_some()) | 112 | .filter(|x| x.kind == MemoryRegionKind::Flash && x.settings.is_some()) |
| 113 | .collect(); | 113 | .collect(); |
| 114 | for region in flash_memory_regions.iter() { | 114 | for region in flash_memory_regions.iter() { |
| 115 | let region_name = get_flash_region_name(region.name); | 115 | let region_name = format_ident!("{}", get_flash_region_name(region.name)); |
| 116 | let region_type = format_ident!("{}", region_name); | 116 | let base = region.address; |
| 117 | let settings_name = format_ident!("{}_SETTINGS", region_name); | 117 | let size = region.size; |
| 118 | let base = region.address as usize; | ||
| 119 | let size = region.size as usize; | ||
| 120 | let settings = region.settings.as_ref().unwrap(); | 118 | let settings = region.settings.as_ref().unwrap(); |
| 121 | let erase_size = settings.erase_size as usize; | 119 | let erase_size = settings.erase_size; |
| 122 | let write_size = settings.write_size as usize; | 120 | let write_size = settings.write_size; |
| 123 | let erase_value = settings.erase_value; | 121 | let erase_value = settings.erase_value; |
| 124 | 122 | ||
| 125 | flash_regions.extend(quote! { | 123 | flash_regions.extend(quote! { |
| 126 | #[allow(non_camel_case_types)] | 124 | pub const #region_name: crate::flash::FlashRegion = crate::flash::FlashRegion { |
| 127 | pub struct #region_type(()); | ||
| 128 | }); | ||
| 129 | |||
| 130 | flash_regions.extend(quote! { | ||
| 131 | pub const #settings_name: crate::flash::FlashRegionSettings = crate::flash::FlashRegionSettings { | ||
| 132 | base: #base, | 125 | base: #base, |
| 133 | size: #size, | 126 | size: #size, |
| 134 | erase_size: #erase_size, | 127 | erase_size: #erase_size, |
| 135 | write_size: #write_size, | 128 | write_size: #write_size, |
| 136 | erase_value: #erase_value, | 129 | erase_value: #erase_value, |
| 137 | }; | 130 | }; |
| 131 | }); | ||
| 138 | 132 | ||
| 139 | impl crate::flash::FlashRegion for #region_type { | 133 | let region_type = format_ident!("{}", get_flash_region_type_name(region.name)); |
| 140 | const SETTINGS: crate::flash::FlashRegionSettings = #settings_name; | 134 | flash_regions.extend(quote! { |
| 141 | } | 135 | pub struct #region_type(pub(crate) &'static crate::flash::FlashRegion); |
| 142 | }); | 136 | }); |
| 143 | } | 137 | } |
| 144 | 138 | ||
| 145 | let (fields, (inits, settings)): (Vec<TokenStream>, (Vec<TokenStream>, Vec<Ident>)) = flash_memory_regions | 139 | let (fields, (inits, region_names)): (Vec<TokenStream>, (Vec<TokenStream>, Vec<Ident>)) = flash_memory_regions |
| 146 | .iter() | 140 | .iter() |
| 147 | .map(|f| { | 141 | .map(|f| { |
| 148 | let region_name = get_flash_region_name(f.name); | 142 | let region_name = get_flash_region_name(f.name); |
| 149 | let field_name = format_ident!("{}", region_name.to_lowercase()); | 143 | let field_name = format_ident!("{}", region_name.to_lowercase()); |
| 150 | let field_type = format_ident!("{}", region_name); | 144 | let field_type = format_ident!("{}", get_flash_region_type_name(f.name)); |
| 151 | let field = quote! { | 145 | let field = quote! { |
| 152 | pub #field_name: #field_type | 146 | pub #field_name: #field_type |
| 153 | }; | 147 | }; |
| 148 | let region_name = format_ident!("{}", region_name); | ||
| 154 | let init = quote! { | 149 | let init = quote! { |
| 155 | #field_name: #field_type(()) | 150 | #field_name: #field_type(&#region_name) |
| 156 | }; | 151 | }; |
| 157 | let settings_name = format_ident!("{}_SETTINGS", region_name); | ||
| 158 | 152 | ||
| 159 | (field, (init, settings_name)) | 153 | (field, (init, region_name)) |
| 160 | }) | 154 | }) |
| 161 | .unzip(); | 155 | .unzip(); |
| 162 | 156 | ||
| 163 | let regions_len = flash_memory_regions.len(); | 157 | let regions_len = flash_memory_regions.len(); |
| 164 | flash_regions.extend(quote! { | 158 | flash_regions.extend(quote! { |
| 165 | #[cfg(flash)] | 159 | #[cfg(flash)] |
| 166 | pub struct FlashRegions<'d> { | 160 | pub struct FlashLayout<'d> { |
| 167 | _inner: embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, | 161 | _inner: embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, |
| 168 | #(#fields),* | 162 | #(#fields),* |
| 169 | } | 163 | } |
| 170 | 164 | ||
| 171 | #[cfg(flash)] | 165 | #[cfg(flash)] |
| 172 | impl<'d> FlashRegions<'d> { | 166 | impl<'d> FlashLayout<'d> { |
| 173 | pub(crate) const fn new(p: embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self { | 167 | pub(crate) const fn new(p: embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self { |
| 174 | Self { | 168 | Self { |
| 175 | _inner: p, | 169 | _inner: p, |
| @@ -178,8 +172,8 @@ fn main() { | |||
| 178 | } | 172 | } |
| 179 | } | 173 | } |
| 180 | 174 | ||
| 181 | pub const FLASH_REGIONS: [&crate::flash::FlashRegionSettings; #regions_len] = [ | 175 | pub const FLASH_REGIONS: [&crate::flash::FlashRegion; #regions_len] = [ |
| 182 | #(&#settings),* | 176 | #(&#region_names),* |
| 183 | ]; | 177 | ]; |
| 184 | }); | 178 | }); |
| 185 | 179 | ||
| @@ -651,8 +645,11 @@ fn main() { | |||
| 651 | .iter() | 645 | .iter() |
| 652 | .filter(|m| m.kind == MemoryRegionKind::Flash && m.settings.is_some()) | 646 | .filter(|m| m.kind == MemoryRegionKind::Flash && m.settings.is_some()) |
| 653 | { | 647 | { |
| 648 | let settings = m.settings.as_ref().unwrap(); | ||
| 654 | let mut row = Vec::new(); | 649 | let mut row = Vec::new(); |
| 655 | row.push(get_flash_region_name(m.name)); | 650 | row.push(get_flash_region_type_name(m.name)); |
| 651 | row.push(settings.write_size.to_string()); | ||
| 652 | row.push(settings.erase_size.to_string()); | ||
| 656 | flash_regions_table.push(row); | 653 | flash_regions_table.push(row); |
| 657 | } | 654 | } |
| 658 | 655 | ||
| @@ -906,6 +903,10 @@ macro_rules! {} {{ | |||
| 906 | .unwrap(); | 903 | .unwrap(); |
| 907 | } | 904 | } |
| 908 | 905 | ||
| 906 | fn get_flash_region_type_name(name: &str) -> String { | ||
| 907 | name.replace("BANK_", "Bank").replace("REGION_", "Region") | ||
| 908 | } | ||
| 909 | |||
| 909 | fn get_flash_region_name(name: &str) -> String { | 910 | fn get_flash_region_name(name: &str) -> String { |
| 910 | name.replace("BANK_", "BANK").replace("REGION_", "REGION") | 911 | name.replace("BANK_", "BANK").replace("REGION_", "REGION") |
| 911 | } | 912 | } |
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index f92236bb0..b190a5a07 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs | |||
| @@ -2,7 +2,6 @@ use embassy_hal_common::drop::OnDrop; | |||
| 2 | use embassy_hal_common::{into_ref, PeripheralRef}; | 2 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 3 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 3 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 4 | use embassy_sync::mutex::{Mutex, MutexGuard}; | 4 | use embassy_sync::mutex::{Mutex, MutexGuard}; |
| 5 | use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; | ||
| 6 | 5 | ||
| 7 | use super::{family, Error, FlashRegion}; | 6 | use super::{family, Error, FlashRegion}; |
| 8 | pub use crate::_generated::flash_regions::*; | 7 | pub use crate::_generated::flash_regions::*; |
| @@ -19,10 +18,8 @@ impl<'d> Flash<'d> { | |||
| 19 | Self { inner: p } | 18 | Self { inner: p } |
| 20 | } | 19 | } |
| 21 | 20 | ||
| 22 | pub fn into_regions(self) -> FlashRegions<'d> { | 21 | pub fn into_regions(self) -> FlashLayout<'d> { |
| 23 | let mut flash = self; | 22 | FlashLayout::new(self.release()) |
| 24 | let p = unsafe { flash.inner.clone_unchecked() }; | ||
| 25 | FlashRegions::new(p) | ||
| 26 | } | 23 | } |
| 27 | 24 | ||
| 28 | pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | 25 | pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { |
| @@ -114,6 +111,11 @@ impl<'d> Flash<'d> { | |||
| 114 | } | 111 | } |
| 115 | Ok(()) | 112 | Ok(()) |
| 116 | } | 113 | } |
| 114 | |||
| 115 | pub(crate) fn release(self) -> PeripheralRef<'d, crate::peripherals::FLASH> { | ||
| 116 | let mut flash = self; | ||
| 117 | unsafe { flash.inner.clone_unchecked() } | ||
| 118 | } | ||
| 117 | } | 119 | } |
| 118 | 120 | ||
| 119 | impl Drop for Flash<'_> { | 121 | impl Drop for Flash<'_> { |
| @@ -132,45 +134,85 @@ fn take_lock_spin() -> MutexGuard<'static, CriticalSectionRawMutex, ()> { | |||
| 132 | } | 134 | } |
| 133 | } | 135 | } |
| 134 | 136 | ||
| 137 | impl FlashRegion { | ||
| 138 | pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | ||
| 139 | unsafe { self.blocking_read_inner(offset, bytes) } | ||
| 140 | } | ||
| 141 | |||
| 142 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | ||
| 143 | unsafe { self.blocking_write_inner(offset, bytes) } | ||
| 144 | } | ||
| 145 | |||
| 146 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | ||
| 147 | unsafe { self.blocking_erase_inner(from, to) } | ||
| 148 | } | ||
| 149 | |||
| 150 | unsafe fn blocking_read_inner(&self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | ||
| 151 | Flash::blocking_read_inner(self.base + offset, bytes) | ||
| 152 | } | ||
| 153 | |||
| 154 | unsafe fn blocking_write_inner(&self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | ||
| 155 | let start_address = self.base + offset; | ||
| 156 | |||
| 157 | // Protect agains simultaneous write/erase to multiple regions. | ||
| 158 | let _guard = take_lock_spin(); | ||
| 159 | |||
| 160 | Flash::blocking_write_inner(start_address, bytes) | ||
| 161 | } | ||
| 162 | |||
| 163 | unsafe fn blocking_erase_inner(&self, from: u32, to: u32) -> Result<(), Error> { | ||
| 164 | let start_address = self.base + from; | ||
| 165 | let end_address = self.base + to; | ||
| 166 | |||
| 167 | // Protect agains simultaneous write/erase to multiple regions. | ||
| 168 | let _guard = take_lock_spin(); | ||
| 169 | |||
| 170 | Flash::blocking_erase_inner(start_address, end_address) | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 135 | foreach_flash_region! { | 174 | foreach_flash_region! { |
| 136 | ($name:ident) => { | 175 | ($type_name:ident, $write_size:ident, $erase_size:ident) => { |
| 137 | impl ErrorType for crate::_generated::flash_regions::$name { | 176 | impl crate::_generated::flash_regions::$type_name { |
| 177 | pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | ||
| 178 | unsafe { self.0.blocking_read_inner(offset, bytes) } | ||
| 179 | } | ||
| 180 | |||
| 181 | pub fn blocking_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | ||
| 182 | unsafe { self.0.blocking_write_inner(offset, bytes) } | ||
| 183 | } | ||
| 184 | |||
| 185 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | ||
| 186 | unsafe { self.0.blocking_erase_inner(from, to) } | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | impl ErrorType for crate::_generated::flash_regions::$type_name { | ||
| 138 | type Error = Error; | 191 | type Error = Error; |
| 139 | } | 192 | } |
| 140 | 193 | ||
| 141 | impl ReadNorFlash for crate::_generated::flash_regions::$name { | 194 | impl ReadNorFlash for crate::_generated::flash_regions::$type_name { |
| 142 | const READ_SIZE: usize = 1; | 195 | const READ_SIZE: usize = 1; |
| 143 | 196 | ||
| 144 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { | 197 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { |
| 145 | Flash::blocking_read_inner(Self::SETTINGS.base as u32 + offset, bytes) | 198 | unsafe { self.0.blocking_read_inner(offset, bytes) } |
| 146 | } | 199 | } |
| 147 | 200 | ||
| 148 | fn capacity(&self) -> usize { | 201 | fn capacity(&self) -> usize { |
| 149 | <crate::_generated::flash_regions::$name as FlashRegion>::SETTINGS.size | 202 | self.0.size as usize |
| 150 | } | 203 | } |
| 151 | } | 204 | } |
| 152 | 205 | ||
| 153 | impl NorFlash for crate::_generated::flash_regions::$name { | 206 | impl NorFlash for crate::_generated::flash_regions::$type_name { |
| 154 | const WRITE_SIZE: usize = <crate::_generated::flash_regions::$name as FlashRegion>::SETTINGS.write_size; | 207 | const WRITE_SIZE: usize = $write_size; |
| 155 | const ERASE_SIZE: usize = <crate::_generated::flash_regions::$name as FlashRegion>::SETTINGS.erase_size; | 208 | const ERASE_SIZE: usize = $erase_size; |
| 156 | |||
| 157 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { | ||
| 158 | let start_address = Self::SETTINGS.base as u32 + from; | ||
| 159 | let end_address = Self::SETTINGS.base as u32 + to; | ||
| 160 | |||
| 161 | // Protect agains simultaneous write/erase to multiple regions. | ||
| 162 | let _guard = take_lock_spin(); | ||
| 163 | |||
| 164 | unsafe { Flash::blocking_erase_inner(start_address, end_address) } | ||
| 165 | } | ||
| 166 | 209 | ||
| 167 | fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { | 210 | fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { |
| 168 | let start_address = Self::SETTINGS.base as u32 + offset; | 211 | unsafe { self.0.blocking_write_inner(offset, bytes) } |
| 169 | 212 | } | |
| 170 | // Protect agains simultaneous write/erase to multiple regions. | ||
| 171 | let _guard = take_lock_spin(); | ||
| 172 | 213 | ||
| 173 | unsafe { Flash::blocking_write_inner(start_address, bytes) } | 214 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { |
| 215 | unsafe { self.0.blocking_erase_inner(from, to) } | ||
| 174 | } | 216 | } |
| 175 | } | 217 | } |
| 176 | }; | 218 | }; |
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index ec7c66947..1e7d4c657 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs | |||
| @@ -45,15 +45,11 @@ mod common; | |||
| 45 | #[cfg(flash)] | 45 | #[cfg(flash)] |
| 46 | pub use common::*; | 46 | pub use common::*; |
| 47 | 47 | ||
| 48 | pub trait FlashRegion { | 48 | pub struct FlashRegion { |
| 49 | const SETTINGS: FlashRegionSettings; | 49 | pub base: u32, |
| 50 | } | 50 | pub size: u32, |
| 51 | 51 | pub erase_size: u32, | |
| 52 | pub struct FlashRegionSettings { | 52 | pub write_size: u32, |
| 53 | pub base: usize, | ||
| 54 | pub size: usize, | ||
| 55 | pub erase_size: usize, | ||
| 56 | pub write_size: usize, | ||
| 57 | pub erase_value: u8, | 53 | pub erase_value: u8, |
| 58 | } | 54 | } |
| 59 | 55 | ||
| @@ -64,7 +60,7 @@ pub struct FlashSector { | |||
| 64 | pub size: u32, | 60 | pub size: u32, |
| 65 | } | 61 | } |
| 66 | 62 | ||
| 67 | impl Drop for FlashRegions<'_> { | 63 | impl Drop for FlashLayout<'_> { |
| 68 | fn drop(&mut self) { | 64 | fn drop(&mut self) { |
| 69 | unsafe { family::lock() }; | 65 | unsafe { family::lock() }; |
| 70 | } | 66 | } |
