aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarun <[email protected]>2024-05-14 12:45:07 -0400
committerKarun <[email protected]>2024-05-14 12:45:07 -0400
commit3e399a9690b1623ce43ea94bf626bda573fac38b (patch)
tree68fe738a14e2f593c4afa8317e78db83a11e304c
parentea70b440cd1035f28c3f332a2f72d7fa42ac995d (diff)
update to remove dma generics
-rw-r--r--embassy-stm32/src/ospi/mod.rs817
1 files changed, 437 insertions, 380 deletions
diff --git a/embassy-stm32/src/ospi/mod.rs b/embassy-stm32/src/ospi/mod.rs
index c25ac4d24..536da4ca0 100644
--- a/embassy-stm32/src/ospi/mod.rs
+++ b/embassy-stm32/src/ospi/mod.rs
@@ -5,13 +5,16 @@
5 5
6pub mod enums; 6pub mod enums;
7 7
8use core::marker::PhantomData;
9
8use embassy_embedded_hal::{GetConfig, SetConfig}; 10use embassy_embedded_hal::{GetConfig, SetConfig};
9use embassy_hal_internal::{into_ref, PeripheralRef}; 11use embassy_hal_internal::{into_ref, PeripheralRef};
10pub use enums::*; 12pub use enums::*;
11use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits}; 13use stm32_metapac::octospi::vals::{PhaseMode, SizeInBits};
12 14
13use crate::dma::{word, Transfer}; 15use crate::dma::{word, ChannelAndRequest};
14use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _}; 16use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed};
17use crate::mode::{Async, Blocking, Mode as PeriMode};
15use crate::pac::octospi::{vals, Octospi as Regs}; 18use crate::pac::octospi::{vals, Octospi as Regs};
16use crate::rcc::RccPeripheral; 19use crate::rcc::RccPeripheral;
17use crate::{peripherals, Peripheral}; 20use crate::{peripherals, Peripheral};
@@ -154,7 +157,7 @@ pub enum OspiError {
154} 157}
155 158
156/// OSPI driver. 159/// OSPI driver.
157pub struct Ospi<'d, T: Instance, Dma> { 160pub struct Ospi<'d, T: Instance, M: PeriMode> {
158 _peri: PeripheralRef<'d, T>, 161 _peri: PeripheralRef<'d, T>,
159 sck: Option<PeripheralRef<'d, AnyPin>>, 162 sck: Option<PeripheralRef<'d, AnyPin>>,
160 d0: Option<PeripheralRef<'d, AnyPin>>, 163 d0: Option<PeripheralRef<'d, AnyPin>>,
@@ -167,259 +170,13 @@ pub struct Ospi<'d, T: Instance, Dma> {
167 d7: Option<PeripheralRef<'d, AnyPin>>, 170 d7: Option<PeripheralRef<'d, AnyPin>>,
168 nss: Option<PeripheralRef<'d, AnyPin>>, 171 nss: Option<PeripheralRef<'d, AnyPin>>,
169 dqs: Option<PeripheralRef<'d, AnyPin>>, 172 dqs: Option<PeripheralRef<'d, AnyPin>>,
170 dma: PeripheralRef<'d, Dma>, 173 dma: Option<ChannelAndRequest<'d>>,
174 _phantom: PhantomData<M>,
171 config: Config, 175 config: Config,
172 width: OspiWidth, 176 width: OspiWidth,
173} 177}
174 178
175impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> { 179impl<'d, T: Instance, M: PeriMode> Ospi<'d, T, M> {
176 /// Create new OSPI driver for a single spi external chip
177 pub fn new_singlespi(
178 peri: impl Peripheral<P = T> + 'd,
179 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
180 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
181 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
182 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
183 dma: impl Peripheral<P = Dma> + 'd,
184 config: Config,
185 ) -> Self {
186 into_ref!(peri, sck, d0, d1, nss);
187
188 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
189 sck.set_speed(crate::gpio::Speed::VeryHigh);
190 nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
191 nss.set_speed(crate::gpio::Speed::VeryHigh);
192 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
193 d0.set_speed(crate::gpio::Speed::VeryHigh);
194 d1.set_as_af_pull(d1.af_num(), AFType::Input, Pull::None);
195 d1.set_speed(crate::gpio::Speed::VeryHigh);
196
197 Self::new_inner(
198 peri,
199 Some(d0.map_into()),
200 Some(d1.map_into()),
201 None,
202 None,
203 None,
204 None,
205 None,
206 None,
207 Some(sck.map_into()),
208 Some(nss.map_into()),
209 None,
210 dma,
211 config,
212 OspiWidth::SING,
213 false,
214 )
215 }
216
217 /// Create new OSPI driver for a dualspi external chip
218 pub fn new_dualspi(
219 peri: impl Peripheral<P = T> + 'd,
220 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
221 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
222 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
223 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
224 dma: impl Peripheral<P = Dma> + 'd,
225 config: Config,
226 ) -> Self {
227 into_ref!(peri, sck, d0, d1, nss);
228
229 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
230 sck.set_speed(crate::gpio::Speed::VeryHigh);
231 nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
232 nss.set_speed(crate::gpio::Speed::VeryHigh);
233 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
234 d0.set_speed(crate::gpio::Speed::VeryHigh);
235 d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
236 d1.set_speed(crate::gpio::Speed::VeryHigh);
237
238 Self::new_inner(
239 peri,
240 Some(d0.map_into()),
241 Some(d1.map_into()),
242 None,
243 None,
244 None,
245 None,
246 None,
247 None,
248 Some(sck.map_into()),
249 Some(nss.map_into()),
250 None,
251 dma,
252 config,
253 OspiWidth::DUAL,
254 false,
255 )
256 }
257
258 /// Create new OSPI driver for a quadspi external chip
259 pub fn new_quadspi(
260 peri: impl Peripheral<P = T> + 'd,
261 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
262 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
263 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
264 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
265 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
266 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
267 dma: impl Peripheral<P = Dma> + 'd,
268 config: Config,
269 ) -> Self {
270 into_ref!(peri, sck, d0, d1, d2, d3, nss);
271
272 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
273 sck.set_speed(crate::gpio::Speed::VeryHigh);
274 nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
275 nss.set_speed(crate::gpio::Speed::VeryHigh);
276 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
277 d0.set_speed(crate::gpio::Speed::VeryHigh);
278 d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
279 d1.set_speed(crate::gpio::Speed::VeryHigh);
280 d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None);
281 d2.set_speed(crate::gpio::Speed::VeryHigh);
282 d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None);
283 d3.set_speed(crate::gpio::Speed::VeryHigh);
284
285 Self::new_inner(
286 peri,
287 Some(d0.map_into()),
288 Some(d1.map_into()),
289 Some(d2.map_into()),
290 Some(d3.map_into()),
291 None,
292 None,
293 None,
294 None,
295 Some(sck.map_into()),
296 Some(nss.map_into()),
297 None,
298 dma,
299 config,
300 OspiWidth::QUAD,
301 false,
302 )
303 }
304
305 /// Create new OSPI driver for two quadspi external chips
306 pub fn new_dualquadspi(
307 peri: impl Peripheral<P = T> + 'd,
308 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
309 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
310 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
311 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
312 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
313 d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
314 d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
315 d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
316 d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
317 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
318 dma: impl Peripheral<P = Dma> + 'd,
319 config: Config,
320 ) -> Self {
321 into_ref!(peri, sck, d0, d1, d2, d3, d4, d5, d6, d7, nss);
322
323 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
324 sck.set_speed(crate::gpio::Speed::VeryHigh);
325 nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
326 nss.set_speed(crate::gpio::Speed::VeryHigh);
327 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
328 d0.set_speed(crate::gpio::Speed::VeryHigh);
329 d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
330 d1.set_speed(crate::gpio::Speed::VeryHigh);
331 d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None);
332 d2.set_speed(crate::gpio::Speed::VeryHigh);
333 d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None);
334 d3.set_speed(crate::gpio::Speed::VeryHigh);
335 d4.set_as_af_pull(d4.af_num(), AFType::OutputPushPull, Pull::None);
336 d4.set_speed(crate::gpio::Speed::VeryHigh);
337 d5.set_as_af_pull(d5.af_num(), AFType::OutputPushPull, Pull::None);
338 d5.set_speed(crate::gpio::Speed::VeryHigh);
339 d6.set_as_af_pull(d6.af_num(), AFType::OutputPushPull, Pull::None);
340 d6.set_speed(crate::gpio::Speed::VeryHigh);
341 d7.set_as_af_pull(d7.af_num(), AFType::OutputPushPull, Pull::None);
342 d7.set_speed(crate::gpio::Speed::VeryHigh);
343
344 Self::new_inner(
345 peri,
346 Some(d0.map_into()),
347 Some(d1.map_into()),
348 Some(d2.map_into()),
349 Some(d3.map_into()),
350 Some(d4.map_into()),
351 Some(d5.map_into()),
352 Some(d6.map_into()),
353 Some(d7.map_into()),
354 Some(sck.map_into()),
355 Some(nss.map_into()),
356 None,
357 dma,
358 config,
359 OspiWidth::QUAD,
360 true,
361 )
362 }
363
364 /// Create new OSPI driver for octospi external chips
365 pub fn new_octospi(
366 peri: impl Peripheral<P = T> + 'd,
367 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
368 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
369 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
370 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
371 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
372 d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
373 d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
374 d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
375 d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
376 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
377 dma: impl Peripheral<P = Dma> + 'd,
378 config: Config,
379 ) -> Self {
380 into_ref!(peri, sck, d0, d1, d2, d3, d4, d5, d6, d7, nss);
381
382 sck.set_as_af_pull(sck.af_num(), AFType::OutputPushPull, Pull::None);
383 sck.set_speed(crate::gpio::Speed::VeryHigh);
384 nss.set_as_af_pull(nss.af_num(), AFType::OutputPushPull, Pull::Up);
385 nss.set_speed(crate::gpio::Speed::VeryHigh);
386 d0.set_as_af_pull(d0.af_num(), AFType::OutputPushPull, Pull::None);
387 d0.set_speed(crate::gpio::Speed::VeryHigh);
388 d1.set_as_af_pull(d1.af_num(), AFType::OutputPushPull, Pull::None);
389 d1.set_speed(crate::gpio::Speed::VeryHigh);
390 d2.set_as_af_pull(d2.af_num(), AFType::OutputPushPull, Pull::None);
391 d2.set_speed(crate::gpio::Speed::VeryHigh);
392 d3.set_as_af_pull(d3.af_num(), AFType::OutputPushPull, Pull::None);
393 d3.set_speed(crate::gpio::Speed::VeryHigh);
394 d4.set_as_af_pull(d4.af_num(), AFType::OutputPushPull, Pull::None);
395 d4.set_speed(crate::gpio::Speed::VeryHigh);
396 d5.set_as_af_pull(d5.af_num(), AFType::OutputPushPull, Pull::None);
397 d5.set_speed(crate::gpio::Speed::VeryHigh);
398 d6.set_as_af_pull(d6.af_num(), AFType::OutputPushPull, Pull::None);
399 d6.set_speed(crate::gpio::Speed::VeryHigh);
400 d7.set_as_af_pull(d7.af_num(), AFType::OutputPushPull, Pull::None);
401 d7.set_speed(crate::gpio::Speed::VeryHigh);
402
403 Self::new_inner(
404 peri,
405 Some(d0.map_into()),
406 Some(d1.map_into()),
407 Some(d2.map_into()),
408 Some(d3.map_into()),
409 Some(d4.map_into()),
410 Some(d5.map_into()),
411 Some(d6.map_into()),
412 Some(d7.map_into()),
413 Some(sck.map_into()),
414 Some(nss.map_into()),
415 None,
416 dma,
417 config,
418 OspiWidth::OCTO,
419 false,
420 )
421 }
422
423 fn new_inner( 180 fn new_inner(
424 peri: impl Peripheral<P = T> + 'd, 181 peri: impl Peripheral<P = T> + 'd,
425 d0: Option<PeripheralRef<'d, AnyPin>>, 182 d0: Option<PeripheralRef<'d, AnyPin>>,
@@ -433,12 +190,12 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
433 sck: Option<PeripheralRef<'d, AnyPin>>, 190 sck: Option<PeripheralRef<'d, AnyPin>>,
434 nss: Option<PeripheralRef<'d, AnyPin>>, 191 nss: Option<PeripheralRef<'d, AnyPin>>,
435 dqs: Option<PeripheralRef<'d, AnyPin>>, 192 dqs: Option<PeripheralRef<'d, AnyPin>>,
436 dma: impl Peripheral<P = Dma> + 'd, 193 dma: Option<ChannelAndRequest<'d>>,
437 config: Config, 194 config: Config,
438 width: OspiWidth, 195 width: OspiWidth,
439 dual_quad: bool, 196 dual_quad: bool,
440 ) -> Self { 197 ) -> Self {
441 into_ref!(peri, dma); 198 into_ref!(peri);
442 199
443 // System configuration 200 // System configuration
444 T::enable_and_reset(); 201 T::enable_and_reset();
@@ -519,6 +276,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
519 nss, 276 nss,
520 dqs, 277 dqs,
521 dma, 278 dma,
279 _phantom: PhantomData,
522 config, 280 config,
523 width, 281 width,
524 } 282 }
@@ -702,11 +460,410 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
702 Ok(()) 460 Ok(())
703 } 461 }
704 462
463 /// Set new bus configuration
464 pub fn set_config(&mut self, config: &Config) {
465 // Wait for busy flag to clear
466 while T::REGS.sr().read().busy() {}
467
468 // Disable DMA channel while configuring the peripheral
469 T::REGS.cr().modify(|w| {
470 w.set_dmaen(false);
471 });
472
473 // Device configuration
474 T::REGS.dcr1().modify(|w| {
475 w.set_devsize(config.device_size.into());
476 w.set_mtyp(vals::MemType::from_bits(config.memory_type.into()));
477 w.set_csht(config.chip_select_high_time.into());
478 w.set_dlybyp(config.delay_block_bypass);
479 w.set_frck(false);
480 w.set_ckmode(config.clock_mode);
481 });
482
483 T::REGS.dcr2().modify(|w| {
484 w.set_wrapsize(config.wrap_size.into());
485 });
486
487 T::REGS.dcr3().modify(|w| {
488 w.set_csbound(config.chip_select_boundary);
489 #[cfg(octospi_v1)]
490 {
491 w.set_maxtran(config.max_transfer);
492 }
493 });
494
495 T::REGS.dcr4().modify(|w| {
496 w.set_refresh(config.refresh);
497 });
498
499 T::REGS.cr().modify(|w| {
500 w.set_fthres(vals::Threshold(config.fifo_threshold.into()));
501 });
502
503 // Wait for busy flag to clear
504 while T::REGS.sr().read().busy() {}
505
506 T::REGS.dcr2().modify(|w| {
507 w.set_prescaler(config.clock_prescaler);
508 });
509
510 T::REGS.tcr().modify(|w| {
511 w.set_sshift(match config.sample_shifting {
512 true => vals::SampleShift::HALFCYCLE,
513 false => vals::SampleShift::NONE,
514 });
515 w.set_dhqc(config.delay_hold_quarter_cycle);
516 });
517
518 // Enable peripheral
519 T::REGS.cr().modify(|w| {
520 w.set_en(true);
521 });
522
523 // Free running clock needs to be set after peripheral enable
524 if config.free_running_clock {
525 T::REGS.dcr1().modify(|w| {
526 w.set_frck(config.free_running_clock);
527 });
528 }
529
530 self.config = *config;
531 }
532
533 /// Get current configuration
534 pub fn get_config(&self) -> Config {
535 self.config
536 }
537}
538
539impl<'d, T: Instance> Ospi<'d, T, Blocking> {
540 /// Create new blocking OSPI driver for a single spi external chip
541 pub fn new_blocking_singlespi(
542 peri: impl Peripheral<P = T> + 'd,
543 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
544 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
545 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
546 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
547 config: Config,
548 ) -> Self {
549 Self::new_inner(
550 peri,
551 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
552 new_pin!(d1, AFType::Input, Speed::VeryHigh),
553 None,
554 None,
555 None,
556 None,
557 None,
558 None,
559 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
560 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
561 None,
562 None,
563 config,
564 OspiWidth::SING,
565 false,
566 )
567 }
568
569 /// Create new blocking OSPI driver for a dualspi external chip
570 pub fn new_blocking_dualspi(
571 peri: impl Peripheral<P = T> + 'd,
572 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
573 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
574 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
575 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
576 config: Config,
577 ) -> Self {
578 Self::new_inner(
579 peri,
580 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
581 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
582 None,
583 None,
584 None,
585 None,
586 None,
587 None,
588 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
589 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
590 None,
591 None,
592 config,
593 OspiWidth::DUAL,
594 false,
595 )
596 }
597
598 /// Create new blocking OSPI driver for a quadspi external chip
599 pub fn new_blocking_quadspi(
600 peri: impl Peripheral<P = T> + 'd,
601 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
602 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
603 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
604 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
605 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
606 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
607 config: Config,
608 ) -> Self {
609 Self::new_inner(
610 peri,
611 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
612 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
613 new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
614 new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
615 None,
616 None,
617 None,
618 None,
619 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
620 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
621 None,
622 None,
623 config,
624 OspiWidth::QUAD,
625 false,
626 )
627 }
628
629 /// Create new blocking OSPI driver for two quadspi external chips
630 pub fn new_blocking_dualquadspi(
631 peri: impl Peripheral<P = T> + 'd,
632 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
633 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
634 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
635 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
636 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
637 d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
638 d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
639 d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
640 d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
641 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
642 config: Config,
643 ) -> Self {
644 Self::new_inner(
645 peri,
646 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
647 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
648 new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
649 new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
650 new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
651 new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
652 new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
653 new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
654 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
655 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
656 None,
657 None,
658 config,
659 OspiWidth::QUAD,
660 true,
661 )
662 }
663
664 /// Create new blocking OSPI driver for octospi external chips
665 pub fn new_blocking_octospi(
666 peri: impl Peripheral<P = T> + 'd,
667 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
668 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
669 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
670 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
671 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
672 d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
673 d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
674 d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
675 d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
676 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
677 config: Config,
678 ) -> Self {
679 Self::new_inner(
680 peri,
681 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
682 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
683 new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
684 new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
685 new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
686 new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
687 new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
688 new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
689 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
690 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
691 None,
692 None,
693 config,
694 OspiWidth::OCTO,
695 false,
696 )
697 }
698}
699
700impl<'d, T: Instance> Ospi<'d, T, Async> {
701 /// Create new blocking OSPI driver for a single spi external chip
702 pub fn new_singlespi(
703 peri: impl Peripheral<P = T> + 'd,
704 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
705 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
706 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
707 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
708 dma: impl Peripheral<P = impl OctoDma<T>> + 'd,
709 config: Config,
710 ) -> Self {
711 Self::new_inner(
712 peri,
713 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
714 new_pin!(d1, AFType::Input, Speed::VeryHigh),
715 None,
716 None,
717 None,
718 None,
719 None,
720 None,
721 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
722 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
723 None,
724 new_dma!(dma),
725 config,
726 OspiWidth::SING,
727 false,
728 )
729 }
730
731 /// Create new blocking OSPI driver for a dualspi external chip
732 pub fn new_dualspi(
733 peri: impl Peripheral<P = T> + 'd,
734 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
735 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
736 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
737 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
738 dma: impl Peripheral<P = impl OctoDma<T>> + 'd,
739 config: Config,
740 ) -> Self {
741 Self::new_inner(
742 peri,
743 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
744 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
745 None,
746 None,
747 None,
748 None,
749 None,
750 None,
751 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
752 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
753 None,
754 new_dma!(dma),
755 config,
756 OspiWidth::DUAL,
757 false,
758 )
759 }
760
761 /// Create new blocking OSPI driver for a quadspi external chip
762 pub fn new_quadspi(
763 peri: impl Peripheral<P = T> + 'd,
764 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
765 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
766 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
767 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
768 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
769 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
770 dma: impl Peripheral<P = impl OctoDma<T>> + 'd,
771 config: Config,
772 ) -> Self {
773 Self::new_inner(
774 peri,
775 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
776 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
777 new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
778 new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
779 None,
780 None,
781 None,
782 None,
783 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
784 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
785 None,
786 new_dma!(dma),
787 config,
788 OspiWidth::QUAD,
789 false,
790 )
791 }
792
793 /// Create new blocking OSPI driver for two quadspi external chips
794 pub fn new_dualquadspi(
795 peri: impl Peripheral<P = T> + 'd,
796 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
797 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
798 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
799 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
800 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
801 d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
802 d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
803 d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
804 d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
805 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
806 dma: impl Peripheral<P = impl OctoDma<T>> + 'd,
807 config: Config,
808 ) -> Self {
809 Self::new_inner(
810 peri,
811 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
812 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
813 new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
814 new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
815 new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
816 new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
817 new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
818 new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
819 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
820 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
821 None,
822 new_dma!(dma),
823 config,
824 OspiWidth::QUAD,
825 true,
826 )
827 }
828
829 /// Create new blocking OSPI driver for octospi external chips
830 pub fn new_octospi(
831 peri: impl Peripheral<P = T> + 'd,
832 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
833 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
834 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
835 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
836 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
837 d4: impl Peripheral<P = impl D4Pin<T>> + 'd,
838 d5: impl Peripheral<P = impl D5Pin<T>> + 'd,
839 d6: impl Peripheral<P = impl D6Pin<T>> + 'd,
840 d7: impl Peripheral<P = impl D7Pin<T>> + 'd,
841 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
842 dma: impl Peripheral<P = impl OctoDma<T>> + 'd,
843 config: Config,
844 ) -> Self {
845 Self::new_inner(
846 peri,
847 new_pin!(d0, AFType::OutputPushPull, Speed::VeryHigh),
848 new_pin!(d1, AFType::OutputPushPull, Speed::VeryHigh),
849 new_pin!(d2, AFType::OutputPushPull, Speed::VeryHigh),
850 new_pin!(d3, AFType::OutputPushPull, Speed::VeryHigh),
851 new_pin!(d4, AFType::OutputPushPull, Speed::VeryHigh),
852 new_pin!(d5, AFType::OutputPushPull, Speed::VeryHigh),
853 new_pin!(d6, AFType::OutputPushPull, Speed::VeryHigh),
854 new_pin!(d7, AFType::OutputPushPull, Speed::VeryHigh),
855 new_pin!(sck, AFType::OutputPushPull, Speed::VeryHigh),
856 new_pin!(nss, AFType::OutputPushPull, Speed::VeryHigh, Pull::Up),
857 None,
858 new_dma!(dma),
859 config,
860 OspiWidth::OCTO,
861 false,
862 )
863 }
864
705 /// Blocking read with DMA transfer 865 /// Blocking read with DMA transfer
706 pub fn blocking_read_dma<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> 866 pub fn blocking_read_dma<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> {
707 where
708 Dma: OctoDma<T>,
709 {
710 if buf.is_empty() { 867 if buf.is_empty() {
711 return Err(OspiError::EmptyBuffer); 868 return Err(OspiError::EmptyBuffer);
712 } 869 }
@@ -727,15 +884,11 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
727 T::REGS.ar().write(|v| v.set_address(current_address)); 884 T::REGS.ar().write(|v| v.set_address(current_address));
728 } 885 }
729 886
730 let request = self.dma.request();
731 let transfer = unsafe { 887 let transfer = unsafe {
732 Transfer::new_read( 888 self.dma
733 &mut self.dma, 889 .as_mut()
734 request, 890 .unwrap()
735 T::REGS.dr().as_ptr() as *mut W, 891 .read(T::REGS.dr().as_ptr() as *mut W, buf, Default::default())
736 buf,
737 Default::default(),
738 )
739 }; 892 };
740 893
741 T::REGS.cr().modify(|w| w.set_dmaen(true)); 894 T::REGS.cr().modify(|w| w.set_dmaen(true));
@@ -748,10 +901,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
748 } 901 }
749 902
750 /// Blocking write with DMA transfer 903 /// Blocking write with DMA transfer
751 pub fn blocking_write_dma<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> 904 pub fn blocking_write_dma<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> {
752 where
753 Dma: OctoDma<T>,
754 {
755 if buf.is_empty() { 905 if buf.is_empty() {
756 return Err(OspiError::EmptyBuffer); 906 return Err(OspiError::EmptyBuffer);
757 } 907 }
@@ -764,15 +914,11 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
764 .cr() 914 .cr()
765 .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE)); 915 .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
766 916
767 let request = self.dma.request();
768 let transfer = unsafe { 917 let transfer = unsafe {
769 Transfer::new_write( 918 self.dma
770 &mut self.dma, 919 .as_mut()
771 request, 920 .unwrap()
772 buf, 921 .write(buf, T::REGS.dr().as_ptr() as *mut W, Default::default())
773 T::REGS.dr().as_ptr() as *mut W,
774 Default::default(),
775 )
776 }; 922 };
777 923
778 T::REGS.cr().modify(|w| w.set_dmaen(true)); 924 T::REGS.cr().modify(|w| w.set_dmaen(true));
@@ -785,10 +931,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
785 } 931 }
786 932
787 /// Asynchronous read from external device 933 /// Asynchronous read from external device
788 pub async fn read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> 934 pub async fn read<W: Word>(&mut self, buf: &mut [W], transaction: TransferConfig) -> Result<(), OspiError> {
789 where
790 Dma: OctoDma<T>,
791 {
792 if buf.is_empty() { 935 if buf.is_empty() {
793 return Err(OspiError::EmptyBuffer); 936 return Err(OspiError::EmptyBuffer);
794 } 937 }
@@ -809,15 +952,11 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
809 T::REGS.ar().write(|v| v.set_address(current_address)); 952 T::REGS.ar().write(|v| v.set_address(current_address));
810 } 953 }
811 954
812 let request = self.dma.request();
813 let transfer = unsafe { 955 let transfer = unsafe {
814 Transfer::new_read( 956 self.dma
815 &mut self.dma, 957 .as_mut()
816 request, 958 .unwrap()
817 T::REGS.dr().as_ptr() as *mut W, 959 .read(T::REGS.dr().as_ptr() as *mut W, buf, Default::default())
818 buf,
819 Default::default(),
820 )
821 }; 960 };
822 961
823 T::REGS.cr().modify(|w| w.set_dmaen(true)); 962 T::REGS.cr().modify(|w| w.set_dmaen(true));
@@ -830,10 +969,7 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
830 } 969 }
831 970
832 /// Asynchronous write to external device 971 /// Asynchronous write to external device
833 pub async fn write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> 972 pub async fn write<W: Word>(&mut self, buf: &[W], transaction: TransferConfig) -> Result<(), OspiError> {
834 where
835 Dma: OctoDma<T>,
836 {
837 if buf.is_empty() { 973 if buf.is_empty() {
838 return Err(OspiError::EmptyBuffer); 974 return Err(OspiError::EmptyBuffer);
839 } 975 }
@@ -846,15 +982,11 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
846 .cr() 982 .cr()
847 .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE)); 983 .modify(|v| v.set_fmode(vals::FunctionalMode::INDIRECTWRITE));
848 984
849 let request = self.dma.request();
850 let transfer = unsafe { 985 let transfer = unsafe {
851 Transfer::new_write( 986 self.dma
852 &mut self.dma, 987 .as_mut()
853 request, 988 .unwrap()
854 buf, 989 .write(buf, T::REGS.dr().as_ptr() as *mut W, Default::default())
855 T::REGS.dr().as_ptr() as *mut W,
856 Default::default(),
857 )
858 }; 990 };
859 991
860 T::REGS.cr().modify(|w| w.set_dmaen(true)); 992 T::REGS.cr().modify(|w| w.set_dmaen(true));
@@ -865,84 +997,9 @@ impl<'d, T: Instance, Dma> Ospi<'d, T, Dma> {
865 997
866 Ok(()) 998 Ok(())
867 } 999 }
868
869 /// Set new bus configuration
870 pub fn set_config(&mut self, config: &Config) {
871 // Wait for busy flag to clear
872 while T::REGS.sr().read().busy() {}
873
874 // Disable DMA channel while configuring the peripheral
875 T::REGS.cr().modify(|w| {
876 w.set_dmaen(false);
877 });
878
879 // Device configuration
880 T::REGS.dcr1().modify(|w| {
881 w.set_devsize(config.device_size.into());
882 w.set_mtyp(vals::MemType::from_bits(config.memory_type.into()));
883 w.set_csht(config.chip_select_high_time.into());
884 w.set_dlybyp(config.delay_block_bypass);
885 w.set_frck(false);
886 w.set_ckmode(config.clock_mode);
887 });
888
889 T::REGS.dcr2().modify(|w| {
890 w.set_wrapsize(config.wrap_size.into());
891 });
892
893 T::REGS.dcr3().modify(|w| {
894 w.set_csbound(config.chip_select_boundary);
895 #[cfg(octospi_v1)]
896 {
897 w.set_maxtran(config.max_transfer);
898 }
899 });
900
901 T::REGS.dcr4().modify(|w| {
902 w.set_refresh(config.refresh);
903 });
904
905 T::REGS.cr().modify(|w| {
906 w.set_fthres(vals::Threshold(config.fifo_threshold.into()));
907 });
908
909 // Wait for busy flag to clear
910 while T::REGS.sr().read().busy() {}
911
912 T::REGS.dcr2().modify(|w| {
913 w.set_prescaler(config.clock_prescaler);
914 });
915
916 T::REGS.tcr().modify(|w| {
917 w.set_sshift(match config.sample_shifting {
918 true => vals::SampleShift::HALFCYCLE,
919 false => vals::SampleShift::NONE,
920 });
921 w.set_dhqc(config.delay_hold_quarter_cycle);
922 });
923
924 // Enable peripheral
925 T::REGS.cr().modify(|w| {
926 w.set_en(true);
927 });
928
929 // Free running clock needs to be set after peripheral enable
930 if config.free_running_clock {
931 T::REGS.dcr1().modify(|w| {
932 w.set_frck(config.free_running_clock);
933 });
934 }
935
936 self.config = *config;
937 }
938
939 /// Get current configuration
940 pub fn get_config(&self) -> Config {
941 self.config
942 }
943} 1000}
944 1001
945impl<'d, T: Instance, Dma> Drop for Ospi<'d, T, Dma> { 1002impl<'d, T: Instance, M: PeriMode> Drop for Ospi<'d, T, M> {
946 fn drop(&mut self) { 1003 fn drop(&mut self) {
947 self.sck.as_ref().map(|x| x.set_as_disconnected()); 1004 self.sck.as_ref().map(|x| x.set_as_disconnected());
948 self.d0.as_ref().map(|x| x.set_as_disconnected()); 1005 self.d0.as_ref().map(|x| x.set_as_disconnected());
@@ -1005,7 +1062,7 @@ foreach_peripheral!(
1005 }; 1062 };
1006); 1063);
1007 1064
1008impl<'d, T: Instance, Dma> SetConfig for Ospi<'d, T, Dma> { 1065impl<'d, T: Instance, M: PeriMode> SetConfig for Ospi<'d, T, M> {
1009 type Config = Config; 1066 type Config = Config;
1010 type ConfigError = (); 1067 type ConfigError = ();
1011 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { 1068 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
@@ -1014,7 +1071,7 @@ impl<'d, T: Instance, Dma> SetConfig for Ospi<'d, T, Dma> {
1014 } 1071 }
1015} 1072}
1016 1073
1017impl<'d, T: Instance, Dma> GetConfig for Ospi<'d, T, Dma> { 1074impl<'d, T: Instance, M: PeriMode> GetConfig for Ospi<'d, T, M> {
1018 type Config = Config; 1075 type Config = Config;
1019 fn get_config(&self) -> Self::Config { 1076 fn get_config(&self) -> Self::Config {
1020 self.get_config() 1077 self.get_config()