diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-10-03 01:55:27 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-03 01:55:27 +0000 |
| commit | 6e901846df7ab0c3cede02974d6d3bec14410f83 (patch) | |
| tree | f3044d065603a8d79db5088b7061d4133ce9d660 | |
| parent | 58280048e332fadd73dc8b48588b0112c61b8ff9 (diff) | |
| parent | 923f1851ee02f697989fd25b6e93d22f30cb6b28 (diff) | |
Merge pull request #1995 from JuliDi/quadspi
[STM32] QUADSPI support bank 2
| -rw-r--r-- | embassy-stm32/build.rs | 15 | ||||
| -rw-r--r-- | embassy-stm32/src/qspi/enums.rs | 16 | ||||
| -rw-r--r-- | embassy-stm32/src/qspi/mod.rs | 120 |
3 files changed, 123 insertions, 28 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 76db0a762..ed5fa84d6 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -719,12 +719,17 @@ fn main() { | |||
| 719 | (("sdmmc", "D6"), quote!(crate::sdmmc::D6Pin)), | 719 | (("sdmmc", "D6"), quote!(crate::sdmmc::D6Pin)), |
| 720 | (("sdmmc", "D6"), quote!(crate::sdmmc::D7Pin)), | 720 | (("sdmmc", "D6"), quote!(crate::sdmmc::D7Pin)), |
| 721 | (("sdmmc", "D8"), quote!(crate::sdmmc::D8Pin)), | 721 | (("sdmmc", "D8"), quote!(crate::sdmmc::D8Pin)), |
| 722 | (("quadspi", "BK1_IO0"), quote!(crate::qspi::D0Pin)), | 722 | (("quadspi", "BK1_IO0"), quote!(crate::qspi::BK1D0Pin)), |
| 723 | (("quadspi", "BK1_IO1"), quote!(crate::qspi::D1Pin)), | 723 | (("quadspi", "BK1_IO1"), quote!(crate::qspi::BK1D1Pin)), |
| 724 | (("quadspi", "BK1_IO2"), quote!(crate::qspi::D2Pin)), | 724 | (("quadspi", "BK1_IO2"), quote!(crate::qspi::BK1D2Pin)), |
| 725 | (("quadspi", "BK1_IO3"), quote!(crate::qspi::D3Pin)), | 725 | (("quadspi", "BK1_IO3"), quote!(crate::qspi::BK1D3Pin)), |
| 726 | (("quadspi", "BK1_NCS"), quote!(crate::qspi::BK1NSSPin)), | ||
| 727 | (("quadspi", "BK2_IO0"), quote!(crate::qspi::BK2D0Pin)), | ||
| 728 | (("quadspi", "BK2_IO1"), quote!(crate::qspi::BK2D1Pin)), | ||
| 729 | (("quadspi", "BK2_IO2"), quote!(crate::qspi::BK2D2Pin)), | ||
| 730 | (("quadspi", "BK2_IO3"), quote!(crate::qspi::BK2D3Pin)), | ||
| 731 | (("quadspi", "BK2_NCS"), quote!(crate::qspi::BK2NSSPin)), | ||
| 726 | (("quadspi", "CLK"), quote!(crate::qspi::SckPin)), | 732 | (("quadspi", "CLK"), quote!(crate::qspi::SckPin)), |
| 727 | (("quadspi", "BK1_NCS"), quote!(crate::qspi::NSSPin)), | ||
| 728 | ].into(); | 733 | ].into(); |
| 729 | 734 | ||
| 730 | for p in METADATA.peripherals { | 735 | for p in METADATA.peripherals { |
diff --git a/embassy-stm32/src/qspi/enums.rs b/embassy-stm32/src/qspi/enums.rs index 2dbe2b061..0412d991a 100644 --- a/embassy-stm32/src/qspi/enums.rs +++ b/embassy-stm32/src/qspi/enums.rs | |||
| @@ -38,6 +38,22 @@ impl Into<u8> for QspiWidth { | |||
| 38 | } | 38 | } |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | #[allow(dead_code)] | ||
| 42 | #[derive(Copy, Clone)] | ||
| 43 | pub enum FlashSelection { | ||
| 44 | Flash1, | ||
| 45 | Flash2, | ||
| 46 | } | ||
| 47 | |||
| 48 | impl Into<bool> for FlashSelection { | ||
| 49 | fn into(self) -> bool { | ||
| 50 | match self { | ||
| 51 | FlashSelection::Flash1 => false, | ||
| 52 | FlashSelection::Flash2 => true, | ||
| 53 | } | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 41 | #[derive(Copy, Clone)] | 57 | #[derive(Copy, Clone)] |
| 42 | pub enum MemorySize { | 58 | pub enum MemorySize { |
| 43 | _1KiB, | 59 | _1KiB, |
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 32382fb28..8fb7df646 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs | |||
| @@ -7,7 +7,7 @@ use enums::*; | |||
| 7 | 7 | ||
| 8 | use crate::dma::Transfer; | 8 | use crate::dma::Transfer; |
| 9 | use crate::gpio::sealed::AFType; | 9 | use crate::gpio::sealed::AFType; |
| 10 | use crate::gpio::AnyPin; | 10 | use crate::gpio::{AnyPin, Pull}; |
| 11 | use crate::pac::quadspi::Quadspi as Regs; | 11 | use crate::pac::quadspi::Quadspi as Regs; |
| 12 | use crate::rcc::RccPeripheral; | 12 | use crate::rcc::RccPeripheral; |
| 13 | use crate::{peripherals, Peripheral}; | 13 | use crate::{peripherals, Peripheral}; |
| @@ -83,30 +83,30 @@ pub struct Qspi<'d, T: Instance, Dma> { | |||
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | 85 | impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { |
| 86 | pub fn new( | 86 | pub fn new_bk1( |
| 87 | peri: impl Peripheral<P = T> + 'd, | 87 | peri: impl Peripheral<P = T> + 'd, |
| 88 | d0: impl Peripheral<P = impl D0Pin<T>> + 'd, | 88 | d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd, |
| 89 | d1: impl Peripheral<P = impl D1Pin<T>> + 'd, | 89 | d1: impl Peripheral<P = impl BK1D1Pin<T>> + 'd, |
| 90 | d2: impl Peripheral<P = impl D2Pin<T>> + 'd, | 90 | d2: impl Peripheral<P = impl BK1D2Pin<T>> + 'd, |
| 91 | d3: impl Peripheral<P = impl D3Pin<T>> + 'd, | 91 | d3: impl Peripheral<P = impl BK1D3Pin<T>> + 'd, |
| 92 | sck: impl Peripheral<P = impl SckPin<T>> + 'd, | 92 | sck: impl Peripheral<P = impl SckPin<T>> + 'd, |
| 93 | nss: impl Peripheral<P = impl NSSPin<T>> + 'd, | 93 | nss: impl Peripheral<P = impl BK1NSSPin<T>> + 'd, |
| 94 | dma: impl Peripheral<P = Dma> + 'd, | 94 | dma: impl Peripheral<P = Dma> + 'd, |
| 95 | config: Config, | 95 | config: Config, |
| 96 | ) -> Self { | 96 | ) -> Self { |
| 97 | into_ref!(peri, d0, d1, d2, d3, sck, nss); | 97 | into_ref!(peri, d0, d1, d2, d3, sck, nss); |
| 98 | 98 | ||
| 99 | sck.set_as_af(sck.af_num(), AFType::OutputPushPull); | 99 | sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); |
| 100 | sck.set_speed(crate::gpio::Speed::VeryHigh); | 100 | sck.set_speed(crate::gpio::Speed::VeryHigh); |
| 101 | nss.set_as_af(nss.af_num(), AFType::OutputPushPull); | 101 | nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); |
| 102 | nss.set_speed(crate::gpio::Speed::VeryHigh); | 102 | nss.set_speed(crate::gpio::Speed::VeryHigh); |
| 103 | d0.set_as_af(d0.af_num(), AFType::OutputPushPull); | 103 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); |
| 104 | d0.set_speed(crate::gpio::Speed::VeryHigh); | 104 | d0.set_speed(crate::gpio::Speed::VeryHigh); |
| 105 | d1.set_as_af(d1.af_num(), AFType::OutputPushPull); | 105 | d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); |
| 106 | d1.set_speed(crate::gpio::Speed::VeryHigh); | 106 | d1.set_speed(crate::gpio::Speed::VeryHigh); |
| 107 | d2.set_as_af(d2.af_num(), AFType::OutputPushPull); | 107 | d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None); |
| 108 | d2.set_speed(crate::gpio::Speed::VeryHigh); | 108 | d2.set_speed(crate::gpio::Speed::VeryHigh); |
| 109 | d3.set_as_af(d3.af_num(), AFType::OutputPushPull); | 109 | d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None); |
| 110 | d3.set_speed(crate::gpio::Speed::VeryHigh); | 110 | d3.set_speed(crate::gpio::Speed::VeryHigh); |
| 111 | 111 | ||
| 112 | Self::new_inner( | 112 | Self::new_inner( |
| @@ -119,6 +119,47 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 119 | Some(nss.map_into()), | 119 | Some(nss.map_into()), |
| 120 | dma, | 120 | dma, |
| 121 | config, | 121 | config, |
| 122 | FlashSelection::Flash2, | ||
| 123 | ) | ||
| 124 | } | ||
| 125 | |||
| 126 | pub fn new_bk2( | ||
| 127 | peri: impl Peripheral<P = T> + 'd, | ||
| 128 | d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd, | ||
| 129 | d1: impl Peripheral<P = impl BK2D1Pin<T>> + 'd, | ||
| 130 | d2: impl Peripheral<P = impl BK2D2Pin<T>> + 'd, | ||
| 131 | d3: impl Peripheral<P = impl BK2D3Pin<T>> + 'd, | ||
| 132 | sck: impl Peripheral<P = impl SckPin<T>> + 'd, | ||
| 133 | nss: impl Peripheral<P = impl BK2NSSPin<T>> + 'd, | ||
| 134 | dma: impl Peripheral<P = Dma> + 'd, | ||
| 135 | config: Config, | ||
| 136 | ) -> Self { | ||
| 137 | into_ref!(peri, d0, d1, d2, d3, sck, nss); | ||
| 138 | |||
| 139 | sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); | ||
| 140 | sck.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 141 | nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); | ||
| 142 | nss.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 143 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); | ||
| 144 | d0.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 145 | d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); | ||
| 146 | d1.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 147 | d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None); | ||
| 148 | d2.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 149 | d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None); | ||
| 150 | d3.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 151 | |||
| 152 | Self::new_inner( | ||
| 153 | peri, | ||
| 154 | Some(d0.map_into()), | ||
| 155 | Some(d1.map_into()), | ||
| 156 | Some(d2.map_into()), | ||
| 157 | Some(d3.map_into()), | ||
| 158 | Some(sck.map_into()), | ||
| 159 | Some(nss.map_into()), | ||
| 160 | dma, | ||
| 161 | config, | ||
| 162 | FlashSelection::Flash2, | ||
| 122 | ) | 163 | ) |
| 123 | } | 164 | } |
| 124 | 165 | ||
| @@ -132,22 +173,40 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 132 | nss: Option<PeripheralRef<'d, AnyPin>>, | 173 | nss: Option<PeripheralRef<'d, AnyPin>>, |
| 133 | dma: impl Peripheral<P = Dma> + 'd, | 174 | dma: impl Peripheral<P = Dma> + 'd, |
| 134 | config: Config, | 175 | config: Config, |
| 176 | fsel: FlashSelection, | ||
| 135 | ) -> Self { | 177 | ) -> Self { |
| 136 | into_ref!(peri, dma); | 178 | into_ref!(peri, dma); |
| 137 | 179 | ||
| 138 | T::enable(); | 180 | T::enable(); |
| 139 | T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); | 181 | T::reset(); |
| 140 | 182 | ||
| 141 | while T::REGS.sr().read().busy() {} | 183 | while T::REGS.sr().read().busy() {} |
| 142 | 184 | ||
| 143 | T::REGS.cr().write(|w| { | 185 | #[cfg(stm32h7)] |
| 144 | w.set_prescaler(config.prescaler); | 186 | { |
| 187 | use stm32_metapac::quadspi::regs::Cr; | ||
| 188 | // Apply precautionary steps according to the errata... | ||
| 189 | T::REGS.cr().write_value(Cr(0)); | ||
| 190 | while T::REGS.sr().read().busy() {} | ||
| 191 | T::REGS.cr().write_value(Cr(0xFF000001)); | ||
| 192 | T::REGS.ccr().write(|w| w.set_frcm(true)); | ||
| 193 | T::REGS.ccr().write(|w| w.set_frcm(true)); | ||
| 194 | T::REGS.cr().write_value(Cr(0)); | ||
| 195 | while T::REGS.sr().read().busy() {} | ||
| 196 | } | ||
| 197 | |||
| 198 | T::REGS.cr().modify(|w| { | ||
| 145 | w.set_en(true); | 199 | w.set_en(true); |
| 200 | //w.set_tcen(false); | ||
| 201 | w.set_sshift(false); | ||
| 202 | w.set_fthres(config.fifo_threshold.into()); | ||
| 203 | w.set_prescaler(config.prescaler); | ||
| 204 | w.set_fsel(fsel.into()); | ||
| 146 | }); | 205 | }); |
| 147 | T::REGS.dcr().write(|w| { | 206 | T::REGS.dcr().modify(|w| { |
| 148 | w.set_fsize(config.memory_size.into()); | 207 | w.set_fsize(config.memory_size.into()); |
| 149 | w.set_csht(config.cs_high_time.into()); | 208 | w.set_csht(config.cs_high_time.into()); |
| 150 | w.set_ckmode(false); | 209 | w.set_ckmode(true); |
| 151 | }); | 210 | }); |
| 152 | 211 | ||
| 153 | Self { | 212 | Self { |
| @@ -164,6 +223,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 164 | } | 223 | } |
| 165 | 224 | ||
| 166 | pub fn command(&mut self, transaction: TransferConfig) { | 225 | pub fn command(&mut self, transaction: TransferConfig) { |
| 226 | #[cfg(not(stm32h7))] | ||
| 167 | T::REGS.cr().modify(|v| v.set_dmaen(false)); | 227 | T::REGS.cr().modify(|v| v.set_dmaen(false)); |
| 168 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); | 228 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); |
| 169 | 229 | ||
| @@ -172,6 +232,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 172 | } | 232 | } |
| 173 | 233 | ||
| 174 | pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { | 234 | pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { |
| 235 | #[cfg(not(stm32h7))] | ||
| 175 | T::REGS.cr().modify(|v| v.set_dmaen(false)); | 236 | T::REGS.cr().modify(|v| v.set_dmaen(false)); |
| 176 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); | 237 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); |
| 177 | 238 | ||
| @@ -195,7 +256,10 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 195 | } | 256 | } |
| 196 | 257 | ||
| 197 | pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { | 258 | pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { |
| 259 | // STM32H7 does not have dmaen | ||
| 260 | #[cfg(not(stm32h7))] | ||
| 198 | T::REGS.cr().modify(|v| v.set_dmaen(false)); | 261 | T::REGS.cr().modify(|v| v.set_dmaen(false)); |
| 262 | |||
| 199 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); | 263 | self.setup_transaction(QspiMode::IndirectWrite, &transaction); |
| 200 | 264 | ||
| 201 | if let Some(len) = transaction.data_len { | 265 | if let Some(len) = transaction.data_len { |
| @@ -238,6 +302,8 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 238 | ) | 302 | ) |
| 239 | }; | 303 | }; |
| 240 | 304 | ||
| 305 | // STM32H7 does not have dmaen | ||
| 306 | #[cfg(not(stm32h7))] | ||
| 241 | T::REGS.cr().modify(|v| v.set_dmaen(true)); | 307 | T::REGS.cr().modify(|v| v.set_dmaen(true)); |
| 242 | 308 | ||
| 243 | transfer.blocking_wait(); | 309 | transfer.blocking_wait(); |
| @@ -264,6 +330,8 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { | |||
| 264 | ) | 330 | ) |
| 265 | }; | 331 | }; |
| 266 | 332 | ||
| 333 | // STM32H7 does not have dmaen | ||
| 334 | #[cfg(not(stm32h7))] | ||
| 267 | T::REGS.cr().modify(|v| v.set_dmaen(true)); | 335 | T::REGS.cr().modify(|v| v.set_dmaen(true)); |
| 268 | 336 | ||
| 269 | transfer.blocking_wait(); | 337 | transfer.blocking_wait(); |
| @@ -313,11 +381,17 @@ pub(crate) mod sealed { | |||
| 313 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} | 381 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} |
| 314 | 382 | ||
| 315 | pin_trait!(SckPin, Instance); | 383 | pin_trait!(SckPin, Instance); |
| 316 | pin_trait!(D0Pin, Instance); | 384 | pin_trait!(BK1D0Pin, Instance); |
| 317 | pin_trait!(D1Pin, Instance); | 385 | pin_trait!(BK1D1Pin, Instance); |
| 318 | pin_trait!(D2Pin, Instance); | 386 | pin_trait!(BK1D2Pin, Instance); |
| 319 | pin_trait!(D3Pin, Instance); | 387 | pin_trait!(BK1D3Pin, Instance); |
| 320 | pin_trait!(NSSPin, Instance); | 388 | pin_trait!(BK1NSSPin, Instance); |
| 389 | |||
| 390 | pin_trait!(BK2D0Pin, Instance); | ||
| 391 | pin_trait!(BK2D1Pin, Instance); | ||
| 392 | pin_trait!(BK2D2Pin, Instance); | ||
| 393 | pin_trait!(BK2D3Pin, Instance); | ||
| 394 | pin_trait!(BK2NSSPin, Instance); | ||
| 321 | 395 | ||
| 322 | dma_trait!(QuadDma, Instance); | 396 | dma_trait!(QuadDma, Instance); |
| 323 | 397 | ||
