aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/qspi
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-05-22 00:23:14 +0200
committerDario Nieuwenhuis <[email protected]>2024-05-22 00:23:42 +0200
commite7161aa085bb145df6607eff5b2c2d0ed06acda1 (patch)
treed1b1a6ed5f443aa19b198277894d504569a2e7b2 /embassy-stm32/src/qspi
parent6fa608f516cf21f38a5592eaf1d176c683a7b6dd (diff)
stm32/qspi: remove DMA generic param.
Diffstat (limited to 'embassy-stm32/src/qspi')
-rw-r--r--embassy-stm32/src/qspi/mod.rs305
1 files changed, 160 insertions, 145 deletions
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index 0a4b4f074..a82e93b5b 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -4,11 +4,14 @@
4 4
5pub mod enums; 5pub mod enums;
6 6
7use core::marker::PhantomData;
8
7use embassy_hal_internal::{into_ref, PeripheralRef}; 9use embassy_hal_internal::{into_ref, PeripheralRef};
8use enums::*; 10use enums::*;
9 11
10use crate::dma::Transfer; 12use crate::dma::ChannelAndRequest;
11use crate::gpio::{AFType, AnyPin, Pull}; 13use crate::gpio::{AFType, AnyPin, Pull, Speed};
14use crate::mode::{Async, Blocking, Mode as PeriMode};
12use crate::pac::quadspi::Quadspi as Regs; 15use crate::pac::quadspi::Quadspi as Regs;
13use crate::rcc::RccPeripheral; 16use crate::rcc::RccPeripheral;
14use crate::{peripherals, Peripheral}; 17use crate::{peripherals, Peripheral};
@@ -71,7 +74,7 @@ impl Default for Config {
71 74
72/// QSPI driver. 75/// QSPI driver.
73#[allow(dead_code)] 76#[allow(dead_code)]
74pub struct Qspi<'d, T: Instance, Dma> { 77pub struct Qspi<'d, T: Instance, M: PeriMode> {
75 _peri: PeripheralRef<'d, T>, 78 _peri: PeripheralRef<'d, T>,
76 sck: Option<PeripheralRef<'d, AnyPin>>, 79 sck: Option<PeripheralRef<'d, AnyPin>>,
77 d0: Option<PeripheralRef<'d, AnyPin>>, 80 d0: Option<PeripheralRef<'d, AnyPin>>,
@@ -79,93 +82,12 @@ pub struct Qspi<'d, T: Instance, Dma> {
79 d2: Option<PeripheralRef<'d, AnyPin>>, 82 d2: Option<PeripheralRef<'d, AnyPin>>,
80 d3: Option<PeripheralRef<'d, AnyPin>>, 83 d3: Option<PeripheralRef<'d, AnyPin>>,
81 nss: Option<PeripheralRef<'d, AnyPin>>, 84 nss: Option<PeripheralRef<'d, AnyPin>>,
82 dma: PeripheralRef<'d, Dma>, 85 dma: Option<ChannelAndRequest<'d>>,
86 _phantom: PhantomData<M>,
83 config: Config, 87 config: Config,
84} 88}
85 89
86impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { 90impl<'d, T: Instance, M: PeriMode> Qspi<'d, T, M> {
87 /// Create a new QSPI driver for bank 1.
88 pub fn new_bk1(
89 peri: impl Peripheral<P = T> + 'd,
90 d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd,
91 d1: impl Peripheral<P = impl BK1D1Pin<T>> + 'd,
92 d2: impl Peripheral<P = impl BK1D2Pin<T>> + 'd,
93 d3: impl Peripheral<P = impl BK1D3Pin<T>> + 'd,
94 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
95 nss: impl Peripheral<P = impl BK1NSSPin<T>> + 'd,
96 dma: impl Peripheral<P = Dma> + 'd,
97 config: Config,
98 ) -> Self {
99 into_ref!(peri, d0, d1, d2, d3, sck, nss);
100
101 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
102 sck.set_speed(crate::gpio::Speed::VeryHigh);
103 nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
104 nss.set_speed(crate::gpio::Speed::VeryHigh);
105 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
106 d0.set_speed(crate::gpio::Speed::VeryHigh);
107 d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
108 d1.set_speed(crate::gpio::Speed::VeryHigh);
109 d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None);
110 d2.set_speed(crate::gpio::Speed::VeryHigh);
111 d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None);
112 d3.set_speed(crate::gpio::Speed::VeryHigh);
113
114 Self::new_inner(
115 peri,
116 Some(d0.map_into()),
117 Some(d1.map_into()),
118 Some(d2.map_into()),
119 Some(d3.map_into()),
120 Some(sck.map_into()),
121 Some(nss.map_into()),
122 dma,
123 config,
124 FlashSelection::Flash1,
125 )
126 }
127
128 /// Create a new QSPI driver for bank 2.
129 pub fn new_bk2(
130 peri: impl Peripheral<P = T> + 'd,
131 d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd,
132 d1: impl Peripheral<P = impl BK2D1Pin<T>> + 'd,
133 d2: impl Peripheral<P = impl BK2D2Pin<T>> + 'd,
134 d3: impl Peripheral<P = impl BK2D3Pin<T>> + 'd,
135 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
136 nss: impl Peripheral<P = impl BK2NSSPin<T>> + 'd,
137 dma: impl Peripheral<P = Dma> + 'd,
138 config: Config,
139 ) -> Self {
140 into_ref!(peri, d0, d1, d2, d3, sck, nss);
141
142 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
143 sck.set_speed(crate::gpio::Speed::VeryHigh);
144 nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
145 nss.set_speed(crate::gpio::Speed::VeryHigh);
146 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
147 d0.set_speed(crate::gpio::Speed::VeryHigh);
148 d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
149 d1.set_speed(crate::gpio::Speed::VeryHigh);
150 d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None);
151 d2.set_speed(crate::gpio::Speed::VeryHigh);
152 d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None);
153 d3.set_speed(crate::gpio::Speed::VeryHigh);
154
155 Self::new_inner(
156 peri,
157 Some(d0.map_into()),
158 Some(d1.map_into()),
159 Some(d2.map_into()),
160 Some(d3.map_into()),
161 Some(sck.map_into()),
162 Some(nss.map_into()),
163 dma,
164 config,
165 FlashSelection::Flash2,
166 )
167 }
168
169 fn new_inner( 91 fn new_inner(
170 peri: impl Peripheral<P = T> + 'd, 92 peri: impl Peripheral<P = T> + 'd,
171 d0: Option<PeripheralRef<'d, AnyPin>>, 93 d0: Option<PeripheralRef<'d, AnyPin>>,
@@ -174,11 +96,11 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
174 d3: Option<PeripheralRef<'d, AnyPin>>, 96 d3: Option<PeripheralRef<'d, AnyPin>>,
175 sck: Option<PeripheralRef<'d, AnyPin>>, 97 sck: Option<PeripheralRef<'d, AnyPin>>,
176 nss: Option<PeripheralRef<'d, AnyPin>>, 98 nss: Option<PeripheralRef<'d, AnyPin>>,
177 dma: impl Peripheral<P = Dma> + 'd, 99 dma: Option<ChannelAndRequest<'d>>,
178 config: Config, 100 config: Config,
179 fsel: FlashSelection, 101 fsel: FlashSelection,
180 ) -> Self { 102 ) -> Self {
181 into_ref!(peri, dma); 103 into_ref!(peri);
182 104
183 T::enable_and_reset(); 105 T::enable_and_reset();
184 106
@@ -220,6 +142,7 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
220 d3, 142 d3,
221 nss, 143 nss,
222 dma, 144 dma,
145 _phantom: PhantomData,
223 config, 146 config,
224 } 147 }
225 } 148 }
@@ -278,11 +201,146 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
278 T::REGS.fcr().modify(|v| v.set_ctcf(true)); 201 T::REGS.fcr().modify(|v| v.set_ctcf(true));
279 } 202 }
280 203
204 fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig, data_len: Option<usize>) {
205 T::REGS.fcr().modify(|v| {
206 v.set_csmf(true);
207 v.set_ctcf(true);
208 v.set_ctef(true);
209 v.set_ctof(true);
210 });
211
212 while T::REGS.sr().read().busy() {}
213
214 if let Some(len) = data_len {
215 T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1));
216 }
217
218 T::REGS.ccr().write(|v| {
219 v.set_fmode(fmode.into());
220 v.set_imode(transaction.iwidth.into());
221 v.set_instruction(transaction.instruction);
222 v.set_admode(transaction.awidth.into());
223 v.set_adsize(self.config.address_size.into());
224 v.set_dmode(transaction.dwidth.into());
225 v.set_abmode(QspiWidth::NONE.into());
226 v.set_dcyc(transaction.dummy.into());
227 });
228
229 if let Some(addr) = transaction.address {
230 T::REGS.ar().write(|v| {
231 v.set_address(addr);
232 });
233 }
234 }
235}
236
237impl<'d, T: Instance> Qspi<'d, T, Blocking> {
238 /// Create a new QSPI driver for bank 1, in blocking mode.
239 pub fn new_blocking_bank1(
240 peri: impl Peripheral<P = T> + 'd,
241 d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd,
242 d1: impl Peripheral<P = impl BK1D1Pin<T>> + 'd,
243 d2: impl Peripheral<P = impl BK1D2Pin<T>> + 'd,
244 d3: impl Peripheral<P = impl BK1D3Pin<T>> + 'd,
245 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
246 nss: impl Peripheral<P = impl BK1NSSPin<T>> + 'd,
247 config: Config,
248 ) -> Self {
249 Self::new_inner(
250 peri,
251 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
252 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
253 new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
254 new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
255 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
256 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
257 None,
258 config,
259 FlashSelection::Flash1,
260 )
261 }
262
263 /// Create a new QSPI driver for bank 2, in blocking mode.
264 pub fn new_blocking_bank2(
265 peri: impl Peripheral<P = T> + 'd,
266 d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd,
267 d1: impl Peripheral<P = impl BK2D1Pin<T>> + 'd,
268 d2: impl Peripheral<P = impl BK2D2Pin<T>> + 'd,
269 d3: impl Peripheral<P = impl BK2D3Pin<T>> + 'd,
270 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
271 nss: impl Peripheral<P = impl BK2NSSPin<T>> + 'd,
272 config: Config,
273 ) -> Self {
274 Self::new_inner(
275 peri,
276 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
277 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
278 new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
279 new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
280 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
281 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
282 None,
283 config,
284 FlashSelection::Flash2,
285 )
286 }
287}
288
289impl<'d, T: Instance> Qspi<'d, T, Async> {
290 /// Create a new QSPI driver for bank 1.
291 pub fn new_bank1(
292 peri: impl Peripheral<P = T> + 'd,
293 d0: impl Peripheral<P = impl BK1D0Pin<T>> + 'd,
294 d1: impl Peripheral<P = impl BK1D1Pin<T>> + 'd,
295 d2: impl Peripheral<P = impl BK1D2Pin<T>> + 'd,
296 d3: impl Peripheral<P = impl BK1D3Pin<T>> + 'd,
297 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
298 nss: impl Peripheral<P = impl BK1NSSPin<T>> + 'd,
299 dma: impl Peripheral<P = impl QuadDma<T>> + 'd,
300 config: Config,
301 ) -> Self {
302 Self::new_inner(
303 peri,
304 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
305 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
306 new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
307 new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
308 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
309 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
310 new_dma!(dma),
311 config,
312 FlashSelection::Flash1,
313 )
314 }
315
316 /// Create a new QSPI driver for bank 2.
317 pub fn new_bank2(
318 peri: impl Peripheral<P = T> + 'd,
319 d0: impl Peripheral<P = impl BK2D0Pin<T>> + 'd,
320 d1: impl Peripheral<P = impl BK2D1Pin<T>> + 'd,
321 d2: impl Peripheral<P = impl BK2D2Pin<T>> + 'd,
322 d3: impl Peripheral<P = impl BK2D3Pin<T>> + 'd,
323 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
324 nss: impl Peripheral<P = impl BK2NSSPin<T>> + 'd,
325 dma: impl Peripheral<P = impl QuadDma<T>> + 'd,
326 config: Config,
327 ) -> Self {
328 Self::new_inner(
329 peri,
330 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
331 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
332 new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
333 new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
334 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
335 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
336 new_dma!(dma),
337 config,
338 FlashSelection::Flash2,
339 )
340 }
341
281 /// Blocking read data, using DMA. 342 /// Blocking read data, using DMA.
282 pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) 343 pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) {
283 where
284 Dma: QuadDma<T>,
285 {
286 self.setup_transaction(QspiMode::IndirectWrite, &transaction, Some(buf.len())); 344 self.setup_transaction(QspiMode::IndirectWrite, &transaction, Some(buf.len()));
287 345
288 T::REGS.ccr().modify(|v| { 346 T::REGS.ccr().modify(|v| {
@@ -293,15 +351,11 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
293 v.set_address(current_ar); 351 v.set_address(current_ar);
294 }); 352 });
295 353
296 let request = self.dma.request();
297 let transfer = unsafe { 354 let transfer = unsafe {
298 Transfer::new_read( 355 self.dma
299 &mut self.dma, 356 .as_mut()
300 request, 357 .unwrap()
301 T::REGS.dr().as_ptr() as *mut u8, 358 .read(T::REGS.dr().as_ptr() as *mut u8, buf, Default::default())
302 buf,
303 Default::default(),
304 )
305 }; 359 };
306 360
307 // STM32H7 does not have dmaen 361 // STM32H7 does not have dmaen
@@ -312,25 +366,18 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
312 } 366 }
313 367
314 /// Blocking write data, using DMA. 368 /// Blocking write data, using DMA.
315 pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) 369 pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) {
316 where
317 Dma: QuadDma<T>,
318 {
319 self.setup_transaction(QspiMode::IndirectWrite, &transaction, Some(buf.len())); 370 self.setup_transaction(QspiMode::IndirectWrite, &transaction, Some(buf.len()));
320 371
321 T::REGS.ccr().modify(|v| { 372 T::REGS.ccr().modify(|v| {
322 v.set_fmode(QspiMode::IndirectWrite.into()); 373 v.set_fmode(QspiMode::IndirectWrite.into());
323 }); 374 });
324 375
325 let request = self.dma.request();
326 let transfer = unsafe { 376 let transfer = unsafe {
327 Transfer::new_write( 377 self.dma
328 &mut self.dma, 378 .as_mut()
329 request, 379 .unwrap()
330 buf, 380 .write(buf, T::REGS.dr().as_ptr() as *mut u8, Default::default())
331 T::REGS.dr().as_ptr() as *mut u8,
332 Default::default(),
333 )
334 }; 381 };
335 382
336 // STM32H7 does not have dmaen 383 // STM32H7 does not have dmaen
@@ -339,38 +386,6 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
339 386
340 transfer.blocking_wait(); 387 transfer.blocking_wait();
341 } 388 }
342
343 fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig, data_len: Option<usize>) {
344 T::REGS.fcr().modify(|v| {
345 v.set_csmf(true);
346 v.set_ctcf(true);
347 v.set_ctef(true);
348 v.set_ctof(true);
349 });
350
351 while T::REGS.sr().read().busy() {}
352
353 if let Some(len) = data_len {
354 T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1));
355 }
356
357 T::REGS.ccr().write(|v| {
358 v.set_fmode(fmode.into());
359 v.set_imode(transaction.iwidth.into());
360 v.set_instruction(transaction.instruction);
361 v.set_admode(transaction.awidth.into());
362 v.set_adsize(self.config.address_size.into());
363 v.set_dmode(transaction.dwidth.into());
364 v.set_abmode(QspiWidth::NONE.into());
365 v.set_dcyc(transaction.dummy.into());
366 });
367
368 if let Some(addr) = transaction.address {
369 T::REGS.ar().write(|v| {
370 v.set_address(addr);
371 });
372 }
373 }
374} 389}
375 390
376trait SealedInstance { 391trait SealedInstance {