diff options
| author | okhsunrog <[email protected]> | 2025-05-21 01:21:43 +0300 |
|---|---|---|
| committer | okhsunrog <[email protected]> | 2025-05-21 01:21:43 +0300 |
| commit | 7be84f137c4f56842b6ebd6de3538b0081d42a09 (patch) | |
| tree | 872669c917ecc33d1bb689bc8d8f5e876ef93b62 | |
| parent | d335e309012020b5eab6f0d04ee63053365140ea (diff) | |
eeprom support
| -rw-r--r-- | embassy-stm32/src/flash/common.rs | 97 | ||||
| -rw-r--r-- | embassy-stm32/src/flash/l.rs | 2 |
2 files changed, 98 insertions, 1 deletions
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 10023e637..81d8966e9 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs | |||
| @@ -11,6 +11,9 @@ use crate::Peri; | |||
| 11 | use crate::_generated::FLASH_BASE; | 11 | use crate::_generated::FLASH_BASE; |
| 12 | use crate::peripherals::FLASH; | 12 | use crate::peripherals::FLASH; |
| 13 | 13 | ||
| 14 | #[cfg(eeprom)] | ||
| 15 | use crate::_generated::{EEPROM_BASE, EEPROM_SIZE}; | ||
| 16 | |||
| 14 | /// Internal flash memory driver. | 17 | /// Internal flash memory driver. |
| 15 | pub struct Flash<'d, MODE = Async> { | 18 | pub struct Flash<'d, MODE = Async> { |
| 16 | pub(crate) inner: Peri<'d, FLASH>, | 19 | pub(crate) inner: Peri<'d, FLASH>, |
| @@ -72,6 +75,100 @@ impl<'d, MODE> Flash<'d, MODE> { | |||
| 72 | } | 75 | } |
| 73 | } | 76 | } |
| 74 | 77 | ||
| 78 | #[cfg(eeprom)] | ||
| 79 | impl<'d> Flash<'d, Blocking> { | ||
| 80 | fn eeprom_base(&self) -> u32 { | ||
| 81 | EEPROM_BASE as u32 | ||
| 82 | } | ||
| 83 | |||
| 84 | fn eeprom_size(&self) -> u32 { | ||
| 85 | EEPROM_SIZE as u32 | ||
| 86 | } | ||
| 87 | |||
| 88 | fn check_eeprom_offset(&self, offset: u32, size: u32) -> Result<(), Error> { | ||
| 89 | if offset + size > self.eeprom_size() { | ||
| 90 | Err(Error::Size) | ||
| 91 | } else { | ||
| 92 | Ok(()) | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | /// Read a byte (u8) from EEPROM at the given offset. | ||
| 97 | pub fn eeprom_read_u8(&self, offset: u32) -> Result<u8, Error> { | ||
| 98 | self.check_eeprom_offset(offset, 1)?; | ||
| 99 | let addr = self.eeprom_base() + offset; | ||
| 100 | Ok(unsafe { core::ptr::read_volatile(addr as *const u8) }) | ||
| 101 | } | ||
| 102 | |||
| 103 | /// Read a half-word (u16) from EEPROM at the given offset. | ||
| 104 | pub fn eeprom_read_u16(&self, offset: u32) -> Result<u16, Error> { | ||
| 105 | if offset % 2 != 0 { | ||
| 106 | return Err(Error::Unaligned); | ||
| 107 | } | ||
| 108 | self.check_eeprom_offset(offset, 2)?; | ||
| 109 | let addr = self.eeprom_base() + offset; | ||
| 110 | Ok(unsafe { core::ptr::read_volatile(addr as *const u16) }) | ||
| 111 | } | ||
| 112 | |||
| 113 | /// Read a word (u32) from EEPROM at the given offset. | ||
| 114 | pub fn eeprom_read_u32(&self, offset: u32) -> Result<u32, Error> { | ||
| 115 | if offset % 4 != 0 { | ||
| 116 | return Err(Error::Unaligned); | ||
| 117 | } | ||
| 118 | self.check_eeprom_offset(offset, 4)?; | ||
| 119 | let addr = self.eeprom_base() + offset; | ||
| 120 | Ok(unsafe { core::ptr::read_volatile(addr as *const u32) }) | ||
| 121 | } | ||
| 122 | |||
| 123 | /// Write a byte (u8) to EEPROM at the given offset. | ||
| 124 | pub fn eeprom_write_u8(&mut self, offset: u32, value: u8) -> Result<(), Error> { | ||
| 125 | self.check_eeprom_offset(offset, 1)?; | ||
| 126 | let addr = self.eeprom_base() + offset; | ||
| 127 | unsafe { | ||
| 128 | family::unlock(); | ||
| 129 | core::ptr::write_volatile(addr as *mut u8, value); | ||
| 130 | family::wait_ready_blocking()?; | ||
| 131 | family::clear_all_err(); | ||
| 132 | family::lock(); | ||
| 133 | } | ||
| 134 | Ok(()) | ||
| 135 | } | ||
| 136 | |||
| 137 | /// Write a half-word (u16) to EEPROM at the given offset. | ||
| 138 | pub fn eeprom_write_u16(&mut self, offset: u32, value: u16) -> Result<(), Error> { | ||
| 139 | if offset % 2 != 0 { | ||
| 140 | return Err(Error::Unaligned); | ||
| 141 | } | ||
| 142 | self.check_eeprom_offset(offset, 2)?; | ||
| 143 | let addr = self.eeprom_base() + offset; | ||
| 144 | unsafe { | ||
| 145 | family::unlock(); | ||
| 146 | core::ptr::write_volatile(addr as *mut u16, value); | ||
| 147 | family::wait_ready_blocking()?; | ||
| 148 | family::clear_all_err(); | ||
| 149 | family::lock(); | ||
| 150 | } | ||
| 151 | Ok(()) | ||
| 152 | } | ||
| 153 | |||
| 154 | /// Write a word (u32) to EEPROM at the given offset. | ||
| 155 | pub fn eeprom_write_u32(&mut self, offset: u32, value: u32) -> Result<(), Error> { | ||
| 156 | if offset % 4 != 0 { | ||
| 157 | return Err(Error::Unaligned); | ||
| 158 | } | ||
| 159 | self.check_eeprom_offset(offset, 4)?; | ||
| 160 | let addr = self.eeprom_base() + offset; | ||
| 161 | unsafe { | ||
| 162 | family::unlock(); | ||
| 163 | core::ptr::write_volatile(addr as *mut u32, value); | ||
| 164 | family::wait_ready_blocking()?; | ||
| 165 | family::clear_all_err(); | ||
| 166 | family::lock(); | ||
| 167 | } | ||
| 168 | Ok(()) | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 75 | pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | 172 | pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { |
| 76 | if offset + bytes.len() as u32 > size { | 173 | if offset + bytes.len() as u32 > size { |
| 77 | return Err(Error::Size); | 174 | return Err(Error::Size); |
diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index 65cea005c..1b82704ec 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs | |||
| @@ -162,7 +162,7 @@ pub(crate) unsafe fn clear_all_err() { | |||
| 162 | pac::FLASH.nssr().modify(|_| {}); | 162 | pac::FLASH.nssr().modify(|_| {}); |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | unsafe fn wait_ready_blocking() -> Result<(), Error> { | 165 | pub(crate) unsafe fn wait_ready_blocking() -> Result<(), Error> { |
| 166 | loop { | 166 | loop { |
| 167 | #[cfg(not(flash_l5))] | 167 | #[cfg(not(flash_l5))] |
| 168 | { | 168 | { |
