aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRasmus Melchior Jacobsen <[email protected]>2023-03-25 05:58:40 +0100
committerRasmus Melchior Jacobsen <[email protected]>2023-03-25 05:58:40 +0100
commit6b44027eab273d1589eb289044d1bd4d172477f6 (patch)
treec601eb644ed391c44a82ee51f124fc60725e11f0
parentcccceb88f2c91adcbdc6c1d07d785a97742f996b (diff)
Add FlashRegion trait and implement embedded_storage traits for each region
-rw-r--r--embassy-stm32/src/flash/mod.rs156
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 @@
1use embassy_hal_common::{into_ref, PeripheralRef}; 1use embassy_hal_common::{into_ref, PeripheralRef};
2use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; 2use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash};
3 3
4pub use crate::pac::{ERASE_SIZE, ERASE_VALUE, FLASH_BASE, FLASH_SIZE, WRITE_SIZE}; 4pub use crate::_generated::flash_regions::*;
5pub use crate::pac::{FLASH_BASE, FLASH_SIZE};
5use crate::peripherals::FLASH; 6use crate::peripherals::FLASH;
6use crate::Peripheral; 7use crate::Peripheral;
7const 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
82impl Drop for Flash<'_> { 85impl Drop for Flash<'_> {
@@ -85,6 +88,69 @@ impl Drop for Flash<'_> {
85 } 88 }
86} 89}
87 90
91pub 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))]
90pub enum Error { 156pub enum Error {
@@ -97,10 +163,6 @@ pub enum Error {
97 Parallelism, 163 Parallelism,
98} 164}
99 165
100impl<'d> ErrorType for Flash<'d> {
101 type Error = Error;
102}
103
104impl NorFlashError for Error { 166impl 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
114impl<'d> ReadNorFlash for Flash<'d> { 176foreach_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
126impl<'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}