diff options
| author | Rasmus Melchior Jacobsen <[email protected]> | 2023-03-25 05:58:40 +0100 |
|---|---|---|
| committer | Rasmus Melchior Jacobsen <[email protected]> | 2023-03-25 05:58:40 +0100 |
| commit | 6b44027eab273d1589eb289044d1bd4d172477f6 (patch) | |
| tree | c601eb644ed391c44a82ee51f124fc60725e11f0 | |
| parent | cccceb88f2c91adcbdc6c1d07d785a97742f996b (diff) | |
Add FlashRegion trait and implement embedded_storage traits for each region
| -rw-r--r-- | embassy-stm32/src/flash/mod.rs | 156 |
1 files changed, 113 insertions, 43 deletions
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs index b7166a437..b6cecfdb3 100644 --- a/embassy-stm32/src/flash/mod.rs +++ b/embassy-stm32/src/flash/mod.rs | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | use embassy_hal_common::{into_ref, PeripheralRef}; | 1 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 2 | use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; | 2 | use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; |
| 3 | 3 | ||
| 4 | pub use crate::pac::{ERASE_SIZE, ERASE_VALUE, FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; | 4 | pub use crate::_generated::flash_regions::*; |
| 5 | pub use crate::pac::{FLASH_BASE, FLASH_SIZE}; | ||
| 5 | use crate::peripherals::FLASH; | 6 | use crate::peripherals::FLASH; |
| 6 | use crate::Peripheral; | 7 | use crate::Peripheral; |
| 7 | const FLASH_END: usize = FLASH_BASE + FLASH_SIZE; | ||
| 8 | 8 | ||
| 9 | #[cfg_attr(any(flash_wl, flash_wb, flash_l0, flash_l1, flash_l4), path = "l.rs")] | 9 | #[cfg_attr(any(flash_wl, flash_wb, flash_l0, flash_l1, flash_l4), path = "l.rs")] |
| 10 | #[cfg_attr(flash_f3, path = "f3.rs")] | 10 | #[cfg_attr(flash_f3, path = "f3.rs")] |
| @@ -23,60 +23,63 @@ impl<'d> Flash<'d> { | |||
| 23 | Self { _inner: p } | 23 | Self { _inner: p } |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | pub fn into_regions(self) -> FlashRegions { | ||
| 27 | FlashRegions::take() | ||
| 28 | } | ||
| 29 | |||
| 26 | pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | 30 | pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { |
| 27 | let offset = FLASH_BASE as u32 + offset; | 31 | if offset as usize + bytes.len() > FLASH_SIZE { |
| 28 | if offset as usize >= FLASH_END || offset as usize + bytes.len() > FLASH_END { | ||
| 29 | return Err(Error::Size); | 32 | return Err(Error::Size); |
| 30 | } | 33 | } |
| 31 | 34 | ||
| 32 | let flash_data = unsafe { core::slice::from_raw_parts(offset as *const u8, bytes.len()) }; | 35 | let first_address = FLASH_BASE as u32 + offset; |
| 36 | |||
| 37 | let flash_data = unsafe { core::slice::from_raw_parts(first_address as *const u8, bytes.len()) }; | ||
| 33 | bytes.copy_from_slice(flash_data); | 38 | bytes.copy_from_slice(flash_data); |
| 34 | Ok(()) | 39 | Ok(()) |
| 35 | } | 40 | } |
| 36 | 41 | ||
| 37 | pub fn blocking_write(&mut self, offset: u32, buf: &[u8]) -> Result<(), Error> { | 42 | pub fn blocking_write(&mut self, offset: u32, buf: &[u8]) -> Result<(), Error> { |
| 38 | let offset = FLASH_BASE as u32 + offset; | 43 | if offset as usize + buf.len() > FLASH_SIZE { |
| 39 | if offset as usize + buf.len() > FLASH_END { | ||
| 40 | return Err(Error::Size); | 44 | return Err(Error::Size); |
| 41 | } | 45 | } |
| 42 | if offset as usize % WRITE_SIZE != 0 || buf.len() as usize % WRITE_SIZE != 0 { | 46 | if offset as usize % family::MAX_WRITE_SIZE != 0 || buf.len() as usize % family::MAX_WRITE_SIZE != 0 { |
| 43 | return Err(Error::Unaligned); | 47 | return Err(Error::Unaligned); |
| 44 | } | 48 | } |
| 45 | trace!("Writing {} bytes at 0x{:x}", buf.len(), offset); | ||
| 46 | 49 | ||
| 47 | self.clear_all_err(); | 50 | let first_address = FLASH_BASE as u32 + offset; |
| 51 | trace!("Writing {} bytes at 0x{:x}", buf.len(), first_address); | ||
| 48 | 52 | ||
| 49 | unsafe { | 53 | unsafe { |
| 54 | family::clear_all_err(); | ||
| 55 | |||
| 50 | family::unlock(); | 56 | family::unlock(); |
| 51 | let res = family::blocking_write(offset, buf); | 57 | let res = family::blocking_write(first_address, buf); |
| 52 | family::lock(); | 58 | family::lock(); |
| 53 | res | 59 | res |
| 54 | } | 60 | } |
| 55 | } | 61 | } |
| 56 | 62 | ||
| 57 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | 63 | pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { |
| 58 | let from = FLASH_BASE as u32 + from; | 64 | if to < from || to as usize > FLASH_SIZE { |
| 59 | let to = FLASH_BASE as u32 + to; | ||
| 60 | if to < from || to as usize > FLASH_END { | ||
| 61 | return Err(Error::Size); | 65 | return Err(Error::Size); |
| 62 | } | 66 | } |
| 63 | if (from as usize % ERASE_SIZE) != 0 || (to as usize % ERASE_SIZE) != 0 { | 67 | if (from as usize % family::MAX_ERASE_SIZE) != 0 || (to as usize % family::MAX_ERASE_SIZE) != 0 { |
| 64 | return Err(Error::Unaligned); | 68 | return Err(Error::Unaligned); |
| 65 | } | 69 | } |
| 66 | 70 | ||
| 67 | self.clear_all_err(); | 71 | let from_address = FLASH_BASE as u32 + from; |
| 72 | let to_address = FLASH_BASE as u32 + to; | ||
| 68 | 73 | ||
| 69 | unsafe { | 74 | unsafe { |
| 75 | family::clear_all_err(); | ||
| 76 | |||
| 70 | family::unlock(); | 77 | family::unlock(); |
| 71 | let res = family::blocking_erase(from, to); | 78 | let res = family::blocking_erase(from_address, to_address); |
| 72 | family::lock(); | 79 | family::lock(); |
| 73 | res | 80 | res |
| 74 | } | 81 | } |
| 75 | } | 82 | } |
| 76 | |||
| 77 | fn clear_all_err(&mut self) { | ||
| 78 | unsafe { family::clear_all_err() }; | ||
| 79 | } | ||
| 80 | } | 83 | } |
| 81 | 84 | ||
| 82 | impl Drop for Flash<'_> { | 85 | impl Drop for Flash<'_> { |
| @@ -85,6 +88,69 @@ impl Drop for Flash<'_> { | |||
| 85 | } | 88 | } |
| 86 | } | 89 | } |
| 87 | 90 | ||
| 91 | pub trait FlashRegion { | ||
| 92 | const BASE: usize; | ||
| 93 | const SIZE: usize; | ||
| 94 | const ERASE_SIZE: usize; | ||
| 95 | const WRITE_SIZE: usize; | ||
| 96 | const ERASE_VALUE: u8; | ||
| 97 | |||
| 98 | fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | ||
| 99 | if offset as usize + bytes.len() > Self::SIZE { | ||
| 100 | return Err(Error::Size); | ||
| 101 | } | ||
| 102 | |||
| 103 | let first_address = Self::BASE as u32 + offset; | ||
| 104 | |||
| 105 | let flash_data = unsafe { core::slice::from_raw_parts(first_address as *const u8, bytes.len()) }; | ||
| 106 | bytes.copy_from_slice(flash_data); | ||
| 107 | Ok(()) | ||
| 108 | } | ||
| 109 | |||
| 110 | fn blocking_write(&mut self, offset: u32, buf: &[u8]) -> Result<(), Error> { | ||
| 111 | if offset as usize + buf.len() > Self::SIZE { | ||
| 112 | return Err(Error::Size); | ||
| 113 | } | ||
| 114 | if offset as usize % Self::WRITE_SIZE != 0 || buf.len() as usize % Self::WRITE_SIZE != 0 { | ||
| 115 | return Err(Error::Unaligned); | ||
| 116 | } | ||
| 117 | |||
| 118 | let first_address = Self::BASE as u32 + offset; | ||
| 119 | trace!("Writing {} bytes from 0x{:x}", buf.len(), first_address); | ||
| 120 | |||
| 121 | critical_section::with(|_| unsafe { | ||
| 122 | family::clear_all_err(); | ||
| 123 | |||
| 124 | family::unlock(); | ||
| 125 | let res = family::blocking_write(first_address, buf); | ||
| 126 | family::lock(); | ||
| 127 | res | ||
| 128 | }) | ||
| 129 | } | ||
| 130 | |||
| 131 | fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | ||
| 132 | if to < from || to as usize > Self::SIZE { | ||
| 133 | return Err(Error::Size); | ||
| 134 | } | ||
| 135 | if (from as usize % Self::ERASE_SIZE) != 0 || (to as usize % Self::ERASE_SIZE) != 0 { | ||
| 136 | return Err(Error::Unaligned); | ||
| 137 | } | ||
| 138 | |||
| 139 | let from_address = Self::BASE as u32 + from; | ||
| 140 | let to_address = Self::BASE as u32 + to; | ||
| 141 | trace!("Erasing from 0x{:x} to 0x{:x}", from_address, to_address); | ||
| 142 | |||
| 143 | critical_section::with(|_| unsafe { | ||
| 144 | family::clear_all_err(); | ||
| 145 | |||
| 146 | family::unlock(); | ||
| 147 | let res = family::blocking_erase(from_address, to_address); | ||
| 148 | family::lock(); | ||
| 149 | res | ||
| 150 | }) | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 88 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | 154 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| 89 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 155 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 90 | pub enum Error { | 156 | pub enum Error { |
| @@ -97,10 +163,6 @@ pub enum Error { | |||
| 97 | Parallelism, | 163 | Parallelism, |
| 98 | } | 164 | } |
| 99 | 165 | ||
| 100 | impl<'d> ErrorType for Flash<'d> { | ||
| 101 | type Error = Error; | ||
| 102 | } | ||
| 103 | |||
| 104 | impl NorFlashError for Error { | 166 | impl NorFlashError for Error { |
| 105 | fn kind(&self) -> NorFlashErrorKind { | 167 | fn kind(&self) -> NorFlashErrorKind { |
| 106 | match self { | 168 | match self { |
| @@ -111,27 +173,35 @@ impl NorFlashError for Error { | |||
| 111 | } | 173 | } |
| 112 | } | 174 | } |
| 113 | 175 | ||
| 114 | impl<'d> ReadNorFlash for Flash<'d> { | 176 | foreach_flash_region! { |
| 115 | const READ_SIZE: usize = WRITE_SIZE; | 177 | ($name:ident) => { |
| 178 | impl ErrorType for crate::_generated::flash_regions::$name { | ||
| 179 | type Error = Error; | ||
| 180 | } | ||
| 116 | 181 | ||
| 117 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { | 182 | impl ReadNorFlash for crate::_generated::flash_regions::$name { |
| 118 | self.blocking_read(offset, bytes) | 183 | const READ_SIZE: usize = <crate::_generated::flash_regions::$name as FlashRegion>::WRITE_SIZE; |
| 119 | } | ||
| 120 | 184 | ||
| 121 | fn capacity(&self) -> usize { | 185 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { |
| 122 | FLASH_SIZE | 186 | self.blocking_read(offset, bytes) |
| 123 | } | 187 | } |
| 124 | } | ||
| 125 | 188 | ||
| 126 | impl<'d> NorFlash for Flash<'d> { | 189 | fn capacity(&self) -> usize { |
| 127 | const WRITE_SIZE: usize = WRITE_SIZE; | 190 | <crate::_generated::flash_regions::$name as FlashRegion>::SIZE |
| 128 | const ERASE_SIZE: usize = ERASE_SIZE; | 191 | } |
| 192 | } | ||
| 129 | 193 | ||
| 130 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { | 194 | impl NorFlash for crate::_generated::flash_regions::$name { |
| 131 | self.blocking_erase(from, to) | 195 | const WRITE_SIZE: usize = <crate::_generated::flash_regions::$name as FlashRegion>::WRITE_SIZE; |
| 132 | } | 196 | const ERASE_SIZE: usize = <crate::_generated::flash_regions::$name as FlashRegion>::ERASE_SIZE; |
| 133 | 197 | ||
| 134 | fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { | 198 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { |
| 135 | self.blocking_write(offset, bytes) | 199 | self.blocking_erase(from, to) |
| 136 | } | 200 | } |
| 201 | |||
| 202 | fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { | ||
| 203 | self.blocking_write(offset, bytes) | ||
| 204 | } | ||
| 205 | } | ||
| 206 | }; | ||
| 137 | } | 207 | } |
