diff options
| -rw-r--r-- | embassy-stm32/src/lib.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/ospi/mod.rs | 178 |
2 files changed, 180 insertions, 0 deletions
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index a465fccd8..e18b16935 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -57,6 +57,8 @@ pub mod ipcc; | |||
| 57 | pub mod low_power; | 57 | pub mod low_power; |
| 58 | #[cfg(opamp)] | 58 | #[cfg(opamp)] |
| 59 | pub mod opamp; | 59 | pub mod opamp; |
| 60 | #[cfg(octospi)] | ||
| 61 | pub mod ospi; | ||
| 60 | #[cfg(quadspi)] | 62 | #[cfg(quadspi)] |
| 61 | pub mod qspi; | 63 | pub mod qspi; |
| 62 | #[cfg(rng)] | 64 | #[cfg(rng)] |
diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs new file mode 100644 index 000000000..44824e42a --- /dev/null +++ b/embassy-stm32/src/ospi/mod.rs | |||
| @@ -0,0 +1,178 @@ | |||
| 1 | //! OCTOSPI Serial Peripheral Interface | ||
| 2 | //! | ||
| 3 | |||
| 4 | #![macro_use] | ||
| 5 | |||
| 6 | use core::ptr; | ||
| 7 | |||
| 8 | use embassy_embedded_hal::SetConfig; | ||
| 9 | use embassy_futures::join::join; | ||
| 10 | use embassy_hal_internal::{into_ref, PeripheralRef}; | ||
| 11 | pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | ||
| 12 | |||
| 13 | use crate::dma::{slice_ptr_parts, word, Transfer}; | ||
| 14 | use crate::gpio::sealed::{AFType, Pin as _}; | ||
| 15 | use crate::gpio::{AnyPin, Pull}; | ||
| 16 | use crate::pac::octospi::{regs, vals, Octospi as Regs}; | ||
| 17 | use crate::rcc::RccPeripheral; | ||
| 18 | use crate::time::Hertz; | ||
| 19 | use crate::{peripherals, Peripheral}; | ||
| 20 | |||
| 21 | pub struct Config; | ||
| 22 | |||
| 23 | pub struct Ospi<'d, T: Instance, Dma> { | ||
| 24 | _peri: PeripheralRef<'d, T>, | ||
| 25 | sck: Option<PeripheralRef<'d, AnyPin>>, | ||
| 26 | d0: Option<PeripheralRef<'d, AnyPin>>, | ||
| 27 | d1: Option<PeripheralRef<'d, AnyPin>>, | ||
| 28 | d2: Option<PeripheralRef<'d, AnyPin>>, | ||
| 29 | d3: Option<PeripheralRef<'d, AnyPin>>, | ||
| 30 | d4: Option<PeripheralRef<'d, AnyPin>>, | ||
| 31 | d5: Option<PeripheralRef<'d, AnyPin>>, | ||
| 32 | d6: Option<PeripheralRef<'d, AnyPin>>, | ||
| 33 | d7: Option<PeripheralRef<'d, AnyPin>>, | ||
| 34 | nss: Option<PeripheralRef<'d, AnyPin>>, | ||
| 35 | dqs: Option<PeripheralRef<'d, AnyPin>>, | ||
| 36 | dma: PeripheralRef<'d, Dma>, | ||
| 37 | config: Config, | ||
| 38 | } | ||
| 39 | |||
| 40 | impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { | ||
| 41 | /// Create new OSPI driver for a dualspi external chip | ||
| 42 | pub fn new_dualspi( | ||
| 43 | peri: impl Peripheral<P = T> + 'd, | ||
| 44 | sck: impl Peripheral<P = impl SckPin<T>> + 'd, | ||
| 45 | d0: impl Peripheral<P = impl D0Pin<T>> + 'd, | ||
| 46 | d1: impl Peripheral<P = impl D1Pin<T>> + 'd, | ||
| 47 | nss: impl Peripheral<P = impl NSSPin<T>> + 'd, | ||
| 48 | dma: impl Peripheral<P = Dma> + 'd, | ||
| 49 | config: Config, | ||
| 50 | ) -> Self { | ||
| 51 | into_ref!(peri, sck, d0, d1, nss); | ||
| 52 | |||
| 53 | sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None); | ||
| 54 | sck.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 55 | nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up); | ||
| 56 | nss.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 57 | d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None); | ||
| 58 | d0.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 59 | d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None); | ||
| 60 | d1.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 61 | |||
| 62 | Self::new_inner( | ||
| 63 | peri, | ||
| 64 | Some(d0.map_into()), | ||
| 65 | Some(d1.map_into()), | ||
| 66 | None, | ||
| 67 | None, | ||
| 68 | None, | ||
| 69 | None, | ||
| 70 | None, | ||
| 71 | None, | ||
| 72 | Some(sck.map_into()), | ||
| 73 | Some(nss.map_into()), | ||
| 74 | None, | ||
| 75 | dma, | ||
| 76 | config, | ||
| 77 | ) | ||
| 78 | } | ||
| 79 | |||
| 80 | fn new_inner( | ||
| 81 | peri: impl Peripheral<P = T> + 'd, | ||
| 82 | d0: Option<PeripheralRef<'d, AnyPin>>, | ||
| 83 | d1: Option<PeripheralRef<'d, AnyPin>>, | ||
| 84 | d2: Option<PeripheralRef<'d, AnyPin>>, | ||
| 85 | d3: Option<PeripheralRef<'d, AnyPin>>, | ||
| 86 | d4: Option<PeripheralRef<'d, AnyPin>>, | ||
| 87 | d5: Option<PeripheralRef<'d, AnyPin>>, | ||
| 88 | d6: Option<PeripheralRef<'d, AnyPin>>, | ||
| 89 | d7: Option<PeripheralRef<'d, AnyPin>>, | ||
| 90 | sck: Option<PeripheralRef<'d, AnyPin>>, | ||
| 91 | nss: Option<PeripheralRef<'d, AnyPin>>, | ||
| 92 | dqs: Option<PeripheralRef<'d, AnyPin>>, | ||
| 93 | dma: impl Peripheral<P = Dma> + 'd, | ||
| 94 | config: Config, | ||
| 95 | ) -> Self { | ||
| 96 | into_ref!(peri, dma); | ||
| 97 | |||
| 98 | T::enable_and_reset(); | ||
| 99 | T::REGS.sr().read().busy(); | ||
| 100 | |||
| 101 | T::REGS.cr().modify(|w| { | ||
| 102 | w.set_en(true); | ||
| 103 | }); | ||
| 104 | |||
| 105 | #[cfg(octospi_v1)] | ||
| 106 | { | ||
| 107 | T::REGS.ccr().modify(|w| { | ||
| 108 | w.set_imode(vals::PhaseMode::TWOLINES); | ||
| 109 | w.set_admode(vals::PhaseMode::TWOLINES); | ||
| 110 | w.set_abmode(vals::PhaseMode::TWOLINES); | ||
| 111 | w.set_dmode(vals::PhaseMode::TWOLINES); | ||
| 112 | }); | ||
| 113 | T::REGS.wccr().modify(|w| { | ||
| 114 | w.set_imode(vals::PhaseMode::TWOLINES); | ||
| 115 | w.set_admode(vals::PhaseMode::TWOLINES); | ||
| 116 | w.set_abmode(vals::PhaseMode::TWOLINES); | ||
| 117 | w.set_dmode(vals::PhaseMode::TWOLINES); | ||
| 118 | }); | ||
| 119 | } | ||
| 120 | |||
| 121 | // | ||
| 122 | |||
| 123 | // while T::REGS::sr().read().busy() {} | ||
| 124 | |||
| 125 | Self { | ||
| 126 | _peri: peri, | ||
| 127 | sck, | ||
| 128 | d0, | ||
| 129 | d1, | ||
| 130 | d2, | ||
| 131 | d3, | ||
| 132 | d4, | ||
| 133 | d5, | ||
| 134 | d6, | ||
| 135 | d7, | ||
| 136 | nss, | ||
| 137 | dqs, | ||
| 138 | dma, | ||
| 139 | config, | ||
| 140 | } | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | pub(crate) mod sealed { | ||
| 145 | use super::*; | ||
| 146 | |||
| 147 | pub trait Instance { | ||
| 148 | const REGS: Regs; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | /// OSPI instance trait. | ||
| 153 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} | ||
| 154 | |||
| 155 | pin_trait!(SckPin, Instance); | ||
| 156 | pin_trait!(NckPin, Instance); | ||
| 157 | pin_trait!(D0Pin, Instance); | ||
| 158 | pin_trait!(D1Pin, Instance); | ||
| 159 | pin_trait!(D2Pin, Instance); | ||
| 160 | pin_trait!(D3Pin, Instance); | ||
| 161 | pin_trait!(D4Pin, Instance); | ||
| 162 | pin_trait!(D5Pin, Instance); | ||
| 163 | pin_trait!(D6Pin, Instance); | ||
| 164 | pin_trait!(D7Pin, Instance); | ||
| 165 | pin_trait!(DQSPin, Instance); | ||
| 166 | pin_trait!(NSSPin, Instance); | ||
| 167 | |||
| 168 | dma_trait!(OctoDma, Instance); | ||
| 169 | |||
| 170 | foreach_peripheral!( | ||
| 171 | (octospi, $inst:ident) => { | ||
| 172 | impl sealed::Instance for peripherals::$inst { | ||
| 173 | const REGS: Regs = crate::pac::$inst; | ||
| 174 | } | ||
| 175 | |||
| 176 | impl Instance for peripherals::$inst {} | ||
| 177 | }; | ||
| 178 | ); | ||
