aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/ospi/mod.rs178
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;
57pub mod low_power; 57pub mod low_power;
58#[cfg(opamp)] 58#[cfg(opamp)]
59pub mod opamp; 59pub mod opamp;
60#[cfg(octospi)]
61pub mod ospi;
60#[cfg(quadspi)] 62#[cfg(quadspi)]
61pub mod qspi; 63pub 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
6use core::ptr;
7
8use embassy_embedded_hal::SetConfig;
9use embassy_futures::join::join;
10use embassy_hal_internal::{into_ref, PeripheralRef};
11pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
12
13use crate::dma::{slice_ptr_parts, word, Transfer};
14use crate::gpio::sealed::{AFType, Pin as _};
15use crate::gpio::{AnyPin, Pull};
16use crate::pac::octospi::{regs, vals, Octospi as Regs};
17use crate::rcc::RccPeripheral;
18use crate::time::Hertz;
19use crate::{peripherals, Peripheral};
20
21pub struct Config;
22
23pub 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
40impl<'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
144pub(crate) mod sealed {
145 use super::*;
146
147 pub trait Instance {
148 const REGS: Regs;
149 }
150}
151
152/// OSPI instance trait.
153pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
154
155pin_trait!(SckPin, Instance);
156pin_trait!(NckPin, Instance);
157pin_trait!(D0Pin, Instance);
158pin_trait!(D1Pin, Instance);
159pin_trait!(D2Pin, Instance);
160pin_trait!(D3Pin, Instance);
161pin_trait!(D4Pin, Instance);
162pin_trait!(D5Pin, Instance);
163pin_trait!(D6Pin, Instance);
164pin_trait!(D7Pin, Instance);
165pin_trait!(DQSPin, Instance);
166pin_trait!(NSSPin, Instance);
167
168dma_trait!(OctoDma, Instance);
169
170foreach_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);