diff options
| author | Rasmus Melchior Jacobsen <[email protected]> | 2023-05-24 17:24:28 +0200 |
|---|---|---|
| committer | Rasmus Melchior Jacobsen <[email protected]> | 2023-05-25 20:07:42 +0200 |
| commit | 44b6494ab7ec3e742aa9f82a8ca9ebdfc23ebbba (patch) | |
| tree | b1266b7f9f0488017098bcca3f7ba3fb9e93603e /embassy-stm32/src/flash/f4.rs | |
| parent | 6df62397048778ce521c14b21b4aced7c22567c2 (diff) | |
Let FlashLayout and FlashRegion depends on a Blocking/Async mode generic
Diffstat (limited to 'embassy-stm32/src/flash/f4.rs')
| -rw-r--r-- | embassy-stm32/src/flash/f4.rs | 114 |
1 files changed, 50 insertions, 64 deletions
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 084bbdc6e..d50a35b41 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs | |||
| @@ -11,6 +11,8 @@ use crate::pac; | |||
| 11 | 11 | ||
| 12 | #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] | 12 | #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] |
| 13 | mod alt_regions { | 13 | mod alt_regions { |
| 14 | use core::marker::PhantomData; | ||
| 15 | |||
| 14 | use embassy_hal_common::PeripheralRef; | 16 | use embassy_hal_common::PeripheralRef; |
| 15 | use stm32_metapac::FLASH_SIZE; | 17 | use stm32_metapac::FLASH_SIZE; |
| 16 | 18 | ||
| @@ -18,8 +20,7 @@ mod alt_regions { | |||
| 18 | #[cfg(feature = "nightly")] | 20 | #[cfg(feature = "nightly")] |
| 19 | use crate::flash::asynch; | 21 | use crate::flash::asynch; |
| 20 | use crate::flash::{ | 22 | use crate::flash::{ |
| 21 | common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, READ_SIZE, | 23 | common, Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion, READ_SIZE, |
| 22 | REGION_ACCESS, | ||
| 23 | }; | 24 | }; |
| 24 | use crate::peripherals::FLASH; | 25 | use crate::peripherals::FLASH; |
| 25 | 26 | ||
| @@ -53,101 +54,86 @@ mod alt_regions { | |||
| 53 | &ALT_BANK2_REGION3, | 54 | &ALT_BANK2_REGION3, |
| 54 | ]; | 55 | ]; |
| 55 | 56 | ||
| 56 | pub struct AltBank1Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); | 57 | pub struct AltBank1Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData<MODE>); |
| 57 | pub struct AltBank2Region1<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); | 58 | pub struct AltBank2Region1<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData<MODE>); |
| 58 | pub struct AltBank2Region2<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); | 59 | pub struct AltBank2Region2<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData<MODE>); |
| 59 | pub struct AltBank2Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); | 60 | pub struct AltBank2Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData<MODE>); |
| 60 | 61 | ||
| 61 | pub type BlockingAltBank1Region3<'d> = | 62 | pub struct AltFlashLayout<'d, MODE> { |
| 62 | BlockingFlashRegion<'d, { ALT_BANK1_REGION3.write_size }, { ALT_BANK1_REGION3.erase_size }>; | 63 | pub bank1_region1: Bank1Region1<'d, MODE>, |
| 63 | pub type BlockingAltBank2Region1<'d> = | 64 | pub bank1_region2: Bank1Region2<'d, MODE>, |
| 64 | BlockingFlashRegion<'d, { ALT_BANK2_REGION1.write_size }, { ALT_BANK2_REGION1.erase_size }>; | 65 | pub bank1_region3: AltBank1Region3<'d, MODE>, |
| 65 | pub type BlockingAltBank2Region2<'d> = | 66 | pub bank2_region1: AltBank2Region1<'d, MODE>, |
| 66 | BlockingFlashRegion<'d, { ALT_BANK2_REGION2.write_size }, { ALT_BANK2_REGION2.erase_size }>; | 67 | pub bank2_region2: AltBank2Region2<'d, MODE>, |
| 67 | pub type BlockingAltBank2Region3<'d> = | 68 | pub bank2_region3: AltBank2Region3<'d, MODE>, |
| 68 | BlockingFlashRegion<'d, { ALT_BANK2_REGION3.write_size }, { ALT_BANK2_REGION3.erase_size }>; | 69 | pub otp_region: OTPRegion<'d, MODE>, |
| 69 | |||
| 70 | pub struct AltFlashLayout<'d> { | ||
| 71 | pub bank1_region1: Bank1Region1<'d>, | ||
| 72 | pub bank1_region2: Bank1Region2<'d>, | ||
| 73 | pub bank1_region3: AltBank1Region3<'d>, | ||
| 74 | pub bank2_region1: AltBank2Region1<'d>, | ||
| 75 | pub bank2_region2: AltBank2Region2<'d>, | ||
| 76 | pub bank2_region3: AltBank2Region3<'d>, | ||
| 77 | pub otp_region: OTPRegion<'d>, | ||
| 78 | } | 70 | } |
| 79 | 71 | ||
| 80 | impl<'d> Flash<'d> { | 72 | impl<'d> Flash<'d> { |
| 81 | pub fn into_alt_regions(self) -> AltFlashLayout<'d> { | 73 | pub fn into_alt_regions(self) -> AltFlashLayout<'d, Async> { |
| 74 | unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; | ||
| 75 | |||
| 76 | // SAFETY: We never expose the cloned peripheral references, and their instance is not public. | ||
| 77 | // Also, all async flash region operations are protected with a mutex. | ||
| 78 | let p = self.inner; | ||
| 79 | AltFlashLayout { | ||
| 80 | bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }, PhantomData), | ||
| 81 | bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }, PhantomData), | ||
| 82 | bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }, PhantomData), | ||
| 83 | bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData), | ||
| 84 | bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData), | ||
| 85 | bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData), | ||
| 86 | otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }, PhantomData), | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | pub fn into_alt_blocking_regions(self) -> AltFlashLayout<'d, Blocking> { | ||
| 82 | unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; | 91 | unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; |
| 83 | 92 | ||
| 84 | // SAFETY: We never expose the cloned peripheral references, and their instance is not public. | 93 | // SAFETY: We never expose the cloned peripheral references, and their instance is not public. |
| 85 | // Also, all blocking flash region operations are protected with a cs. | 94 | // Also, all blocking flash region operations are protected with a cs. |
| 86 | let p = self.inner; | 95 | let p = self.inner; |
| 87 | AltFlashLayout { | 96 | AltFlashLayout { |
| 88 | bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }), | 97 | bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }, PhantomData), |
| 89 | bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }), | 98 | bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }, PhantomData), |
| 90 | bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }), | 99 | bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }, PhantomData), |
| 91 | bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }), | 100 | bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData), |
| 92 | bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }), | 101 | bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData), |
| 93 | bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }), | 102 | bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData), |
| 94 | otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }), | 103 | otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }, PhantomData), |
| 95 | } | 104 | } |
| 96 | } | 105 | } |
| 97 | } | 106 | } |
| 98 | 107 | ||
| 99 | macro_rules! foreach_altflash_region { | 108 | macro_rules! foreach_altflash_region { |
| 100 | ($type_name:ident, $region:ident) => { | 109 | ($type_name:ident, $region:ident) => { |
| 101 | impl $type_name<'_> { | 110 | #[cfg(feature = "nightly")] |
| 102 | pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | 111 | impl $type_name<'_, Async> { |
| 112 | pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { | ||
| 103 | common::read_blocking(self.0.base, self.0.size, offset, bytes) | 113 | common::read_blocking(self.0.base, self.0.size, offset, bytes) |
| 104 | } | 114 | } |
| 105 | 115 | ||
| 106 | #[cfg(feature = "nightly")] | ||
| 107 | pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | 116 | pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { |
| 108 | let _guard = REGION_ACCESS.lock().await; | 117 | let _guard = asynch::REGION_ACCESS.lock().await; |
| 109 | unsafe { asynch::write_chunked(self.0.base, self.0.size, offset, bytes).await } | 118 | unsafe { asynch::write_chunked(self.0.base, self.0.size, offset, bytes).await } |
| 110 | } | 119 | } |
| 111 | 120 | ||
| 112 | #[cfg(feature = "nightly")] | ||
| 113 | pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | 121 | pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { |
| 114 | let _guard = REGION_ACCESS.lock().await; | 122 | let _guard = asynch::REGION_ACCESS.lock().await; |
| 115 | unsafe { asynch::erase_sectored(self.0.base, from, to).await } | 123 | unsafe { asynch::erase_sectored(self.0.base, from, to).await } |
| 116 | } | 124 | } |
| 117 | |||
| 118 | pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { | ||
| 119 | let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; | ||
| 120 | unsafe { common::write_chunked_blocking(self.0.base, self.0.size, offset, bytes) } | ||
| 121 | } | ||
| 122 | |||
| 123 | pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { | ||
| 124 | let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; | ||
| 125 | unsafe { common::erase_sectored_blocking(self.0.base, from, to) } | ||
| 126 | } | ||
| 127 | } | 125 | } |
| 128 | 126 | ||
| 129 | impl embedded_storage::nor_flash::ErrorType for $type_name<'_> { | 127 | impl embedded_storage::nor_flash::ErrorType for $type_name<'_, Async> { |
| 130 | type Error = Error; | 128 | type Error = Error; |
| 131 | } | 129 | } |
| 132 | 130 | ||
| 133 | impl embedded_storage::nor_flash::ReadNorFlash for $type_name<'_> { | ||
| 134 | const READ_SIZE: usize = READ_SIZE; | ||
| 135 | |||
| 136 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { | ||
| 137 | self.read(offset, bytes) | ||
| 138 | } | ||
| 139 | |||
| 140 | fn capacity(&self) -> usize { | ||
| 141 | self.0.size as usize | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | #[cfg(feature = "nightly")] | 131 | #[cfg(feature = "nightly")] |
| 146 | impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_> { | 132 | impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_, Async> { |
| 147 | const READ_SIZE: usize = READ_SIZE; | 133 | const READ_SIZE: usize = READ_SIZE; |
| 148 | 134 | ||
| 149 | async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { | 135 | async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { |
| 150 | self.read(offset, bytes) | 136 | self.read(offset, bytes).await |
| 151 | } | 137 | } |
| 152 | 138 | ||
| 153 | fn capacity(&self) -> usize { | 139 | fn capacity(&self) -> usize { |
| @@ -156,7 +142,7 @@ mod alt_regions { | |||
| 156 | } | 142 | } |
| 157 | 143 | ||
| 158 | #[cfg(feature = "nightly")] | 144 | #[cfg(feature = "nightly")] |
| 159 | impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_> { | 145 | impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_, Async> { |
| 160 | const WRITE_SIZE: usize = $region.write_size as usize; | 146 | const WRITE_SIZE: usize = $region.write_size as usize; |
| 161 | const ERASE_SIZE: usize = $region.erase_size as usize; | 147 | const ERASE_SIZE: usize = $region.erase_size as usize; |
| 162 | 148 | ||
