aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorokhsunrog <[email protected]>2025-05-21 08:41:04 +0300
committerokhsunrog <[email protected]>2025-05-21 08:46:52 +0300
commitbc265b98b7597ffb90fe4e951beee5d65c6c481f (patch)
tree448e8c1546e2c220e9f20ca2a46c08ff38353d7a /embassy-stm32
parent1accd560054f4203e193c6e77baca1c448fbf1c9 (diff)
adding docs
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/flash/eeprom.rs88
1 files changed, 45 insertions, 43 deletions
diff --git a/embassy-stm32/src/flash/eeprom.rs b/embassy-stm32/src/flash/eeprom.rs
index 74aedb7c0..99c6b9c10 100644
--- a/embassy-stm32/src/flash/eeprom.rs
+++ b/embassy-stm32/src/flash/eeprom.rs
@@ -4,6 +4,7 @@ use super::{family, Blocking, Error, Flash, EEPROM_BASE, EEPROM_SIZE};
4impl<'d> Flash<'d, Blocking> { 4impl<'d> Flash<'d, Blocking> {
5 // --- Internal helpers --- 5 // --- Internal helpers ---
6 6
7 /// Checks if the given offset and size are within the EEPROM bounds.
7 fn check_eeprom_offset(&self, offset: u32, size: u32) -> Result<(), Error> { 8 fn check_eeprom_offset(&self, offset: u32, size: u32) -> Result<(), Error> {
8 if offset 9 if offset
9 .checked_add(size) 10 .checked_add(size)
@@ -18,6 +19,10 @@ impl<'d> Flash<'d, Blocking> {
18 19
19 // --- Unlocked (unsafe, internal) functions --- 20 // --- Unlocked (unsafe, internal) functions ---
20 21
22 /// Writes a slice of bytes to EEPROM at the given offset without locking.
23 ///
24 /// # Safety
25 /// Caller must ensure EEPROM is unlocked and offset is valid.
21 unsafe fn eeprom_write_u8_slice_unlocked(&self, offset: u32, data: &[u8]) -> Result<(), Error> { 26 unsafe fn eeprom_write_u8_slice_unlocked(&self, offset: u32, data: &[u8]) -> Result<(), Error> {
22 for (i, &byte) in data.iter().enumerate() { 27 for (i, &byte) in data.iter().enumerate() {
23 let addr = EEPROM_BASE as u32 + offset + i as u32; 28 let addr = EEPROM_BASE as u32 + offset + i as u32;
@@ -28,6 +33,10 @@ impl<'d> Flash<'d, Blocking> {
28 Ok(()) 33 Ok(())
29 } 34 }
30 35
36 /// Writes a slice of u16 values to EEPROM at the given offset without locking.
37 ///
38 /// # Safety
39 /// Caller must ensure EEPROM is unlocked and offset is valid and aligned.
31 unsafe fn eeprom_write_u16_slice_unlocked(&self, offset: u32, data: &[u16]) -> Result<(), Error> { 40 unsafe fn eeprom_write_u16_slice_unlocked(&self, offset: u32, data: &[u16]) -> Result<(), Error> {
32 for (i, &value) in data.iter().enumerate() { 41 for (i, &value) in data.iter().enumerate() {
33 let addr = EEPROM_BASE as u32 + offset + i as u32 * 2; 42 let addr = EEPROM_BASE as u32 + offset + i as u32 * 2;
@@ -38,6 +47,10 @@ impl<'d> Flash<'d, Blocking> {
38 Ok(()) 47 Ok(())
39 } 48 }
40 49
50 /// Writes a slice of u32 values to EEPROM at the given offset without locking.
51 ///
52 /// # Safety
53 /// Caller must ensure EEPROM is unlocked and offset is valid and aligned.
41 unsafe fn eeprom_write_u32_slice_unlocked(&self, offset: u32, data: &[u32]) -> Result<(), Error> { 54 unsafe fn eeprom_write_u32_slice_unlocked(&self, offset: u32, data: &[u32]) -> Result<(), Error> {
42 for (i, &value) in data.iter().enumerate() { 55 for (i, &value) in data.iter().enumerate() {
43 let addr = EEPROM_BASE as u32 + offset + i as u32 * 4; 56 let addr = EEPROM_BASE as u32 + offset + i as u32 * 4;
@@ -50,20 +63,20 @@ impl<'d> Flash<'d, Blocking> {
50 63
51 // --- Public, safe API --- 64 // --- Public, safe API ---
52 65
66 /// Writes a single byte to EEPROM at the given offset.
53 pub fn eeprom_write_u8(&mut self, offset: u32, value: u8) -> Result<(), Error> { 67 pub fn eeprom_write_u8(&mut self, offset: u32, value: u8) -> Result<(), Error> {
54 self.check_eeprom_offset(offset, 1)?; 68 self.check_eeprom_offset(offset, 1)?;
55 unsafe { 69 unsafe {
56 family::unlock(); 70 family::unlock();
57 }
58 unsafe {
59 self.eeprom_write_u8_slice_unlocked(offset, core::slice::from_ref(&value))?; 71 self.eeprom_write_u8_slice_unlocked(offset, core::slice::from_ref(&value))?;
60 }
61 unsafe {
62 family::lock(); 72 family::lock();
63 } 73 }
64 Ok(()) 74 Ok(())
65 } 75 }
66 76
77 /// Writes a single 16-bit value to EEPROM at the given offset.
78 ///
79 /// Returns an error if the offset is not 2-byte aligned.
67 pub fn eeprom_write_u16(&mut self, offset: u32, value: u16) -> Result<(), Error> { 80 pub fn eeprom_write_u16(&mut self, offset: u32, value: u16) -> Result<(), Error> {
68 if offset % 2 != 0 { 81 if offset % 2 != 0 {
69 return Err(Error::Unaligned); 82 return Err(Error::Unaligned);
@@ -71,16 +84,15 @@ impl<'d> Flash<'d, Blocking> {
71 self.check_eeprom_offset(offset, 2)?; 84 self.check_eeprom_offset(offset, 2)?;
72 unsafe { 85 unsafe {
73 family::unlock(); 86 family::unlock();
74 }
75 unsafe {
76 self.eeprom_write_u16_slice_unlocked(offset, core::slice::from_ref(&value))?; 87 self.eeprom_write_u16_slice_unlocked(offset, core::slice::from_ref(&value))?;
77 }
78 unsafe {
79 family::lock(); 88 family::lock();
80 } 89 }
81 Ok(()) 90 Ok(())
82 } 91 }
83 92
93 /// Writes a single 32-bit value to EEPROM at the given offset.
94 ///
95 /// Returns an error if the offset is not 4-byte aligned.
84 pub fn eeprom_write_u32(&mut self, offset: u32, value: u32) -> Result<(), Error> { 96 pub fn eeprom_write_u32(&mut self, offset: u32, value: u32) -> Result<(), Error> {
85 if offset % 4 != 0 { 97 if offset % 4 != 0 {
86 return Err(Error::Unaligned); 98 return Err(Error::Unaligned);
@@ -88,30 +100,26 @@ impl<'d> Flash<'d, Blocking> {
88 self.check_eeprom_offset(offset, 4)?; 100 self.check_eeprom_offset(offset, 4)?;
89 unsafe { 101 unsafe {
90 family::unlock(); 102 family::unlock();
91 }
92 unsafe {
93 self.eeprom_write_u32_slice_unlocked(offset, core::slice::from_ref(&value))?; 103 self.eeprom_write_u32_slice_unlocked(offset, core::slice::from_ref(&value))?;
94 }
95 unsafe {
96 family::lock(); 104 family::lock();
97 } 105 }
98 Ok(()) 106 Ok(())
99 } 107 }
100 108
109 /// Writes a slice of bytes to EEPROM at the given offset.
101 pub fn eeprom_write_u8_slice(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> { 110 pub fn eeprom_write_u8_slice(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> {
102 self.check_eeprom_offset(offset, data.len() as u32)?; 111 self.check_eeprom_offset(offset, data.len() as u32)?;
103 unsafe { 112 unsafe {
104 family::unlock(); 113 family::unlock();
105 }
106 unsafe {
107 self.eeprom_write_u8_slice_unlocked(offset, data)?; 114 self.eeprom_write_u8_slice_unlocked(offset, data)?;
108 }
109 unsafe {
110 family::lock(); 115 family::lock();
111 } 116 }
112 Ok(()) 117 Ok(())
113 } 118 }
114 119
120 /// Writes a slice of 16-bit values to EEPROM at the given offset.
121 ///
122 /// Returns an error if the offset is not 2-byte aligned.
115 pub fn eeprom_write_u16_slice(&mut self, offset: u32, data: &[u16]) -> Result<(), Error> { 123 pub fn eeprom_write_u16_slice(&mut self, offset: u32, data: &[u16]) -> Result<(), Error> {
116 if offset % 2 != 0 { 124 if offset % 2 != 0 {
117 return Err(Error::Unaligned); 125 return Err(Error::Unaligned);
@@ -119,16 +127,15 @@ impl<'d> Flash<'d, Blocking> {
119 self.check_eeprom_offset(offset, data.len() as u32 * 2)?; 127 self.check_eeprom_offset(offset, data.len() as u32 * 2)?;
120 unsafe { 128 unsafe {
121 family::unlock(); 129 family::unlock();
122 }
123 unsafe {
124 self.eeprom_write_u16_slice_unlocked(offset, data)?; 130 self.eeprom_write_u16_slice_unlocked(offset, data)?;
125 }
126 unsafe {
127 family::lock(); 131 family::lock();
128 } 132 }
129 Ok(()) 133 Ok(())
130 } 134 }
131 135
136 /// Writes a slice of 32-bit values to EEPROM at the given offset.
137 ///
138 /// Returns an error if the offset is not 4-byte aligned.
132 pub fn eeprom_write_u32_slice(&mut self, offset: u32, data: &[u32]) -> Result<(), Error> { 139 pub fn eeprom_write_u32_slice(&mut self, offset: u32, data: &[u32]) -> Result<(), Error> {
133 if offset % 4 != 0 { 140 if offset % 4 != 0 {
134 return Err(Error::Unaligned); 141 return Err(Error::Unaligned);
@@ -136,23 +143,18 @@ impl<'d> Flash<'d, Blocking> {
136 self.check_eeprom_offset(offset, data.len() as u32 * 4)?; 143 self.check_eeprom_offset(offset, data.len() as u32 * 4)?;
137 unsafe { 144 unsafe {
138 family::unlock(); 145 family::unlock();
139 }
140 unsafe {
141 self.eeprom_write_u32_slice_unlocked(offset, data)?; 146 self.eeprom_write_u32_slice_unlocked(offset, data)?;
142 }
143 unsafe {
144 family::lock(); 147 family::lock();
145 } 148 }
146 Ok(()) 149 Ok(())
147 } 150 }
148 151
152 /// Writes a byte slice to EEPROM at the given offset, handling alignment.
153 ///
154 /// This method will write unaligned prefix and suffix as bytes, and aligned middle as u32.
149 pub fn eeprom_write(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> { 155 pub fn eeprom_write(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> {
156 self.check_eeprom_offset(offset, data.len() as u32)?;
150 let start = offset; 157 let start = offset;
151 let end = offset.checked_add(data.len() as u32).ok_or(Error::Size)?;
152 if end > EEPROM_SIZE as u32 {
153 return Err(Error::Size);
154 }
155
156 let misalign = (start % 4) as usize; 158 let misalign = (start % 4) as usize;
157 let prefix_len = if misalign == 0 { 159 let prefix_len = if misalign == 0 {
158 0 160 0
@@ -165,37 +167,33 @@ impl<'d> Flash<'d, Blocking> {
165 167
166 unsafe { 168 unsafe {
167 family::unlock(); 169 family::unlock();
168 } 170 if !prefix.is_empty() {
169 if !prefix.is_empty() {
170 unsafe {
171 self.eeprom_write_u8_slice_unlocked(start, prefix)?; 171 self.eeprom_write_u8_slice_unlocked(start, prefix)?;
172 } 172 }
173 } 173 if !aligned.is_empty() {
174 if !aligned.is_empty() { 174 let aligned_offset = start + prefix_len as u32;
175 let aligned_offset = start + prefix_len as u32; 175 let u32_data = core::slice::from_raw_parts(aligned.as_ptr() as *const u32, aligned.len() / 4);
176 let u32_data = unsafe { core::slice::from_raw_parts(aligned.as_ptr() as *const u32, aligned.len() / 4) };
177 unsafe {
178 self.eeprom_write_u32_slice_unlocked(aligned_offset, u32_data)?; 176 self.eeprom_write_u32_slice_unlocked(aligned_offset, u32_data)?;
179 } 177 }
180 } 178 if !suffix.is_empty() {
181 if !suffix.is_empty() { 179 let suffix_offset = start + (prefix_len + aligned_len) as u32;
182 let suffix_offset = start + (prefix_len + aligned_len) as u32;
183 unsafe {
184 self.eeprom_write_u8_slice_unlocked(suffix_offset, suffix)?; 180 self.eeprom_write_u8_slice_unlocked(suffix_offset, suffix)?;
185 } 181 }
186 }
187 unsafe {
188 family::lock(); 182 family::lock();
189 } 183 }
190 Ok(()) 184 Ok(())
191 } 185 }
192 186
187 /// Reads a single byte from EEPROM at the given offset.
193 pub fn eeprom_read_u8(&self, offset: u32) -> Result<u8, Error> { 188 pub fn eeprom_read_u8(&self, offset: u32) -> Result<u8, Error> {
194 self.check_eeprom_offset(offset, 1)?; 189 self.check_eeprom_offset(offset, 1)?;
195 let addr = EEPROM_BASE as u32 + offset; 190 let addr = EEPROM_BASE as u32 + offset;
196 Ok(unsafe { core::ptr::read_volatile(addr as *const u8) }) 191 Ok(unsafe { core::ptr::read_volatile(addr as *const u8) })
197 } 192 }
198 193
194 /// Reads a single 16-bit value from EEPROM at the given offset.
195 ///
196 /// Returns an error if the offset is not 2-byte aligned.
199 pub fn eeprom_read_u16(&self, offset: u32) -> Result<u16, Error> { 197 pub fn eeprom_read_u16(&self, offset: u32) -> Result<u16, Error> {
200 if offset % 2 != 0 { 198 if offset % 2 != 0 {
201 return Err(Error::Unaligned); 199 return Err(Error::Unaligned);
@@ -205,6 +203,9 @@ impl<'d> Flash<'d, Blocking> {
205 Ok(unsafe { core::ptr::read_volatile(addr as *const u16) }) 203 Ok(unsafe { core::ptr::read_volatile(addr as *const u16) })
206 } 204 }
207 205
206 /// Reads a single 32-bit value from EEPROM at the given offset.
207 ///
208 /// Returns an error if the offset is not 4-byte aligned.
208 pub fn eeprom_read_u32(&self, offset: u32) -> Result<u32, Error> { 209 pub fn eeprom_read_u32(&self, offset: u32) -> Result<u32, Error> {
209 if offset % 4 != 0 { 210 if offset % 4 != 0 {
210 return Err(Error::Unaligned); 211 return Err(Error::Unaligned);
@@ -214,6 +215,7 @@ impl<'d> Flash<'d, Blocking> {
214 Ok(unsafe { core::ptr::read_volatile(addr as *const u32) }) 215 Ok(unsafe { core::ptr::read_volatile(addr as *const u32) })
215 } 216 }
216 217
218 /// Reads a slice of bytes from EEPROM at the given offset into the provided buffer.
217 pub fn eeprom_read_slice(&self, offset: u32, buf: &mut [u8]) -> Result<(), Error> { 219 pub fn eeprom_read_slice(&self, offset: u32, buf: &mut [u8]) -> Result<(), Error> {
218 self.check_eeprom_offset(offset, buf.len() as u32)?; 220 self.check_eeprom_offset(offset, buf.len() as u32)?;
219 let addr = EEPROM_BASE as u32 + offset; 221 let addr = EEPROM_BASE as u32 + offset;