1use crate::gpio::{
4 gpioa::{PA6, PA7},
5 gpiob::{PB0, PB1, PB10, PB11},
6 gpioe::{PE10, PE11, PE12, PE13, PE14, PE15},
7};
8
9#[cfg(not(any(feature = "stm32l475")))]
10use crate::gpio::{
11 gpioa::{PA2, PA3},
12 gpiod::{PD3, PD4, PD5, PD6, PD7},
13};
14
15#[cfg(any(
16 feature = "stm32l476",
17 feature = "stm32l486",
18 feature = "stm32l496",
19 feature = "stm32l4a6"
20))]
21use crate::gpio::{
22 gpioc::{PC1, PC2, PC4, PC5},
23 gpiof::{PF6, PF7, PF8, PF9},
24};
25
26use crate::gpio::{Alternate, PushPull, Speed};
27use crate::rcc::{Enable, AHB3};
28use crate::stm32::QUADSPI;
29use core::ptr;
30
31#[doc(hidden)]
32mod private {
33 pub trait Sealed {}
34}
35
36pub trait ClkPin<QSPI>: private::Sealed {
38 fn set_speed(self, speed: Speed) -> Self;
39}
40pub trait NCSPin<QSPI>: private::Sealed {
42 fn set_speed(self, speed: Speed) -> Self;
43}
44pub trait IO0Pin<QSPI>: private::Sealed {
46 fn set_speed(self, speed: Speed) -> Self;
47}
48pub trait IO1Pin<QSPI>: private::Sealed {
50 fn set_speed(self, speed: Speed) -> Self;
51}
52pub trait IO2Pin<QSPI>: private::Sealed {
54 fn set_speed(self, speed: Speed) -> Self;
55}
56pub trait IO3Pin<QSPI>: private::Sealed {
58 fn set_speed(self, speed: Speed) -> Self;
59}
60
61macro_rules! pins {
62 ($qspi:ident, $af:literal, CLK: [$($clk:ident),*], nCS: [$($ncs:ident),*],
63 IO0: [$($io0:ident),*], IO1: [$($io1:ident),*], IO2: [$($io2:ident),*],
64 IO3: [$($io3:ident),*]) => {
65 $(
66 impl private::Sealed for $clk<Alternate<PushPull, $af>> {}
67 impl ClkPin<$qspi> for $clk<Alternate<PushPull, $af>> {
68 fn set_speed(self, speed: Speed) -> Self{
69 self.set_speed(speed)
70 }
71 }
72 )*
73 $(
74 impl private::Sealed for $ncs<Alternate<PushPull, $af>> {}
75 impl NCSPin<$qspi> for $ncs<Alternate<PushPull, $af>> {
76 fn set_speed(self, speed: Speed) -> Self{
77 self.set_speed(speed)
78 }
79 }
80 )*
81 $(
82 impl private::Sealed for $io0<Alternate<PushPull, $af>> {}
83 impl IO0Pin<$qspi> for $io0<Alternate<PushPull, $af>> {
84 fn set_speed(self, speed: Speed) -> Self{
85 self.set_speed(speed)
86 }
87 }
88 )*
89 $(
90 impl private::Sealed for $io1<Alternate<PushPull, $af>> {}
91 impl IO1Pin<$qspi> for $io1<Alternate<PushPull, $af>> {
92 fn set_speed(self, speed: Speed) -> Self{
93 self.set_speed(speed)
94 }
95 }
96 )*
97 $(
98 impl private::Sealed for $io2<Alternate<PushPull, $af>> {}
99 impl IO2Pin<$qspi> for $io2<Alternate<PushPull, $af>> {
100 fn set_speed(self, speed: Speed) -> Self{
101 self.set_speed(speed)
102 }
103 }
104 )*
105 $(
106 impl private::Sealed for $io3<Alternate<PushPull, $af>> {}
107 impl IO3Pin<$qspi> for $io3<Alternate<PushPull, $af>> {
108 fn set_speed(self, speed: Speed) -> Self{
109 self.set_speed(speed)
110 }
111 }
112 )*
113 }
114}
115
116#[derive(Copy, Clone, Debug, PartialEq)]
117#[repr(u8)]
118pub enum QspiMode {
119 SingleChannel = 0b01,
120 DualChannel = 0b10,
121 QuadChannel = 0b11,
122}
123
124#[derive(Copy, Clone, Debug, PartialEq)]
125#[repr(u8)]
126pub enum AddressSize {
127 Addr8Bit = 0b00,
128 Addr16Bit = 0b01,
129 Addr24Bit = 0b10,
130 Addr32Bit = 0b11,
131}
132
133#[derive(Copy, Clone, Debug, PartialEq)]
134pub enum SampleShift {
135 None,
136 HalfACycle,
137}
138
139#[derive(Copy, Clone, Debug, PartialEq)]
140pub enum ClockMode {
141 Mode0,
142 Mode3,
143}
144
145#[derive(Copy, Clone, Debug, PartialEq)]
146pub enum QspiError {
147 Busy,
148 Address,
149 Unknown,
150}
151
152#[derive(Copy, Clone, Debug, PartialEq)]
153pub struct QspiConfig {
154 clock_prescaler: u8,
157 flash_size: u8,
159 address_size: AddressSize,
160 clock_mode: ClockMode,
162 fifo_threshold: u8,
164 sample_shift: SampleShift,
165 chip_select_high_time: u8,
168 qpi_mode: bool,
169}
170
171impl Default for QspiConfig {
172 fn default() -> QspiConfig {
173 QspiConfig {
174 clock_prescaler: 0,
175 flash_size: 22, address_size: AddressSize::Addr24Bit,
177 clock_mode: ClockMode::Mode0,
178 fifo_threshold: 1,
179 sample_shift: SampleShift::HalfACycle,
180 chip_select_high_time: 1,
181 qpi_mode: false,
182 }
183 }
184}
185
186impl QspiConfig {
187 pub fn clock_prescaler(mut self, clk_pre: u8) -> Self {
188 self.clock_prescaler = clk_pre;
189 self
190 }
191
192 pub fn flash_size(mut self, fl_size: u8) -> Self {
193 self.flash_size = fl_size;
194 self
195 }
196
197 pub fn address_size(mut self, add_size: AddressSize) -> Self {
198 self.address_size = add_size;
199 self
200 }
201
202 pub fn clock_mode(mut self, clk_mode: ClockMode) -> Self {
203 self.clock_mode = clk_mode;
204 self
205 }
206
207 pub fn fifo_threshold(mut self, fifo_thres: u8) -> Self {
208 self.fifo_threshold = fifo_thres;
209 self
210 }
211
212 pub fn sample_shift(mut self, shift: SampleShift) -> Self {
213 self.sample_shift = shift;
214 self
215 }
216
217 pub fn chip_select_high_time(mut self, csht: u8) -> Self {
218 self.chip_select_high_time = csht;
219 self
220 }
221
222 pub fn qpi_mode(mut self, qpi: bool) -> Self {
223 self.qpi_mode = qpi;
224 self
225 }
226}
227
228#[derive(Copy, Clone, Debug, PartialEq)]
229pub struct QspiWriteCommand<'a> {
230 pub instruction: Option<(u8, QspiMode)>,
231 pub address: Option<(u32, QspiMode)>,
232 pub alternative_bytes: Option<(&'a [u8], QspiMode)>,
233 pub dummy_cycles: u8,
234 pub data: Option<(&'a [u8], QspiMode)>,
235 pub double_data_rate: bool,
236}
237
238#[derive(Copy, Clone, Debug, PartialEq)]
239pub struct QspiReadCommand<'a> {
240 pub instruction: Option<(u8, QspiMode)>,
241 pub address: Option<(u32, QspiMode)>,
242 pub alternative_bytes: Option<(&'a [u8], QspiMode)>,
243 pub dummy_cycles: u8,
244 pub data_mode: QspiMode,
245 pub receive_length: u32,
246 pub double_data_rate: bool,
247}
248
249impl<'a> QspiWriteCommand<'a> {
250 pub fn address(self, addr: u32, mode: QspiMode) -> Self {
251 QspiWriteCommand {
252 address: Some((addr, mode)),
253 ..self
254 }
255 }
256
257 pub fn alternative_bytes(self, bytes: &'a [u8], mode: QspiMode) -> Self {
258 QspiWriteCommand {
259 alternative_bytes: Some((bytes, mode)),
260 ..self
261 }
262 }
263
264 pub fn dummy_cycles(self, n: u8) -> Self {
265 QspiWriteCommand {
266 dummy_cycles: n,
267 ..self
268 }
269 }
270
271 pub fn data(self, bytes: &'a [u8], mode: QspiMode) -> Self {
272 QspiWriteCommand {
273 data: Some((bytes, mode)),
274 ..self
275 }
276 }
277}
278
279impl<'a> QspiReadCommand<'a> {
280 pub fn address(self, addr: u32, mode: QspiMode) -> Self {
281 QspiReadCommand {
282 address: Some((addr, mode)),
283 ..self
284 }
285 }
286
287 pub fn alternative_bytes(self, bytes: &'a [u8], mode: QspiMode) -> Self {
288 QspiReadCommand {
289 alternative_bytes: Some((bytes, mode)),
290 ..self
291 }
292 }
293
294 pub fn dummy_cycles(self, n: u8) -> Self {
295 QspiReadCommand {
296 dummy_cycles: n,
297 ..self
298 }
299 }
300
301 pub fn receive_length(self, length: u32) -> Self {
302 QspiReadCommand {
303 receive_length: length,
304 ..self
305 }
306 }
307}
308
309pub struct Qspi<PINS> {
310 qspi: QUADSPI,
311 _pins: PINS,
312 config: QspiConfig,
313}
314
315impl<CLK, NCS, IO0, IO1, IO2, IO3> Qspi<(CLK, NCS, IO0, IO1, IO2, IO3)> {
316 pub fn new(
317 qspi: QUADSPI,
318 pins: (CLK, NCS, IO0, IO1, IO2, IO3),
319 ahb3: &mut AHB3,
320 config: QspiConfig,
321 ) -> Self
322 where
323 CLK: ClkPin<QUADSPI>,
324 NCS: NCSPin<QUADSPI>,
325 IO0: IO0Pin<QUADSPI>,
326 IO1: IO1Pin<QUADSPI>,
327 IO2: IO2Pin<QUADSPI>,
328 IO3: IO3Pin<QUADSPI>,
329 {
330 QUADSPI::enable(ahb3);
332
333 qspi.cr.modify(|_, w| w.en().clear_bit());
335
336 qspi.fcr.write(|w| {
338 w.ctof()
339 .set_bit()
340 .csmf()
341 .set_bit()
342 .ctcf()
343 .set_bit()
344 .ctef()
345 .set_bit()
346 });
347
348 let high_speed_pins = (
350 pins.0.set_speed(Speed::VeryHigh),
351 pins.1.set_speed(Speed::VeryHigh),
352 pins.2.set_speed(Speed::VeryHigh),
353 pins.3.set_speed(Speed::VeryHigh),
354 pins.4.set_speed(Speed::VeryHigh),
355 pins.5.set_speed(Speed::VeryHigh),
356 );
357
358 let mut unit = Qspi {
359 qspi,
360 _pins: high_speed_pins,
361 config,
362 };
363 unit.apply_config(config);
364 unit
365 }
366
367 pub fn is_busy(&self) -> bool {
368 self.qspi.sr.read().busy().bit_is_set()
369 }
370
371 pub fn abort_transmission(&self) {
374 self.qspi.cr.modify(|_, w| w.abort().set_bit());
375 while self.qspi.sr.read().busy().bit_is_set() {}
376 }
377
378 pub fn get_config(&self) -> QspiConfig {
379 self.config
380 }
381
382 pub fn apply_config(&mut self, config: QspiConfig) {
383 if self.qspi.sr.read().busy().bit_is_set() {
384 self.abort_transmission();
385 }
386
387 self.qspi
388 .cr
389 .modify(|_, w| unsafe { w.fthres().bits(config.fifo_threshold as u8) });
390
391 while self.qspi.sr.read().busy().bit_is_set() {}
392
393 self.qspi.cr.modify(|_, w| unsafe {
395 w.prescaler()
396 .bits(config.clock_prescaler as u8)
397 .sshift()
398 .bit(config.sample_shift == SampleShift::HalfACycle)
399 });
400 while self.is_busy() {}
401
402 self.qspi.dcr.modify(|_, w| unsafe {
404 w.fsize()
405 .bits(config.flash_size as u8)
406 .csht()
407 .bits(config.chip_select_high_time as u8)
408 .ckmode()
409 .bit(config.clock_mode == ClockMode::Mode3)
410 });
411 while self.is_busy() {}
412
413 self.qspi.cr.modify(|_, w| w.en().set_bit());
415 while self.is_busy() {}
416
417 self.config = config;
418 }
419
420 pub fn transfer(&self, command: QspiReadCommand, buffer: &mut [u8]) -> Result<(), QspiError> {
421 if self.is_busy() {
422 return Err(QspiError::Busy);
423 }
424
425 if command.double_data_rate {
427 self.qspi.cr.modify(|_, w| w.sshift().bit(false));
428 }
429 while self.is_busy() {}
430
431 self.qspi.fcr.modify(|_, w| w.ctcf().set_bit());
433
434 let mut dmode: u8 = 0;
435 let mut instruction: u8 = 0;
436 let mut imode: u8 = 0;
437 let mut admode: u8 = 0;
438 let mut adsize: u8 = 0;
439 let mut abmode: u8 = 0;
440 let mut absize: u8 = 0;
441
442 if command.receive_length > 0 {
444 self.qspi
445 .dlr
446 .write(|w| unsafe { w.dl().bits(command.receive_length as u32 - 1) });
447 if self.config.qpi_mode {
448 dmode = QspiMode::QuadChannel as u8;
449 } else {
450 dmode = command.data_mode as u8;
451 }
452 }
453
454 if let Some((inst, mode)) = command.instruction {
456 if self.config.qpi_mode {
457 imode = QspiMode::QuadChannel as u8;
458 } else {
459 imode = mode as u8;
460 }
461 instruction = inst;
462 }
463
464 if let Some((_, mode)) = command.address {
466 if self.config.qpi_mode {
467 admode = QspiMode::QuadChannel as u8;
468 } else {
469 admode = mode as u8;
470 }
471 adsize = self.config.address_size as u8;
472 }
473
474 if let Some((a_bytes, mode)) = command.alternative_bytes {
476 if self.config.qpi_mode {
477 abmode = QspiMode::QuadChannel as u8;
478 } else {
479 abmode = mode as u8;
480 }
481
482 absize = a_bytes.len() as u8 - 1;
483
484 self.qspi.abr.write(|w| {
485 let mut reg_byte: u32 = 0;
486 for (i, element) in a_bytes.iter().rev().enumerate() {
487 reg_byte |= (*element as u32) << (i * 8);
488 }
489 unsafe { w.alternate().bits(reg_byte) }
490 });
491 }
492
493 self.qspi.ccr.modify(|_, w| unsafe {
495 w.fmode()
496 .bits(0b01)
497 .admode()
498 .bits(admode)
499 .adsize()
500 .bits(adsize)
501 .abmode()
502 .bits(abmode)
503 .absize()
504 .bits(absize)
505 .ddrm()
506 .bit(command.double_data_rate)
507 .dcyc()
508 .bits(command.dummy_cycles)
509 .dmode()
510 .bits(dmode)
511 .imode()
512 .bits(imode)
513 .instruction()
514 .bits(instruction)
515 });
516
517 if let Some((addr, _)) = command.address {
519 self.qspi.ar.write(|w| unsafe { w.address().bits(addr) });
520
521 if self.qspi.sr.read().tef().bit_is_set() {
523 return Err(QspiError::Address);
524 }
525 }
526
527 if self.qspi.sr.read().tef().bit_is_set() {
529 return Err(QspiError::Unknown);
530 }
531
532 let mut b = buffer.iter_mut();
534 while self.qspi.sr.read().tcf().bit_is_clear() {
535 if self.qspi.sr.read().ftf().bit_is_set() {
536 if let Some(v) = b.next() {
537 unsafe {
538 *v = ptr::read_volatile(&self.qspi.dr as *const _ as *const u8);
539 }
540 } else {
541 }
543 }
544 }
545 while self.qspi.sr.read().flevel().bits() > 0 {
547 if let Some(v) = b.next() {
548 unsafe {
549 *v = ptr::read_volatile(&self.qspi.dr as *const _ as *const u8);
550 }
551 } else {
552 }
554 }
555 if command.double_data_rate {
557 if self.is_busy() {
558 self.abort_transmission();
559 }
560 self.qspi.cr.modify(|_, w| {
561 w.sshift()
562 .bit(self.config.sample_shift == SampleShift::HalfACycle)
563 });
564 }
565 while self.is_busy() {}
566 self.qspi.fcr.write(|w| w.ctcf().set_bit());
567 Ok(())
568 }
569
570 pub fn write(&self, command: QspiWriteCommand) -> Result<(), QspiError> {
571 if self.is_busy() {
572 return Err(QspiError::Busy);
573 }
574 self.qspi.fcr.modify(|_, w| w.ctcf().set_bit());
576
577 let mut dmode: u8 = 0;
578 let mut instruction: u8 = 0;
579 let mut imode: u8 = 0;
580 let mut admode: u8 = 0;
581 let mut adsize: u8 = 0;
582 let mut abmode: u8 = 0;
583 let mut absize: u8 = 0;
584
585 if let Some((data, mode)) = command.data {
587 self.qspi
588 .dlr
589 .write(|w| unsafe { w.dl().bits(data.len() as u32 - 1) });
590 if self.config.qpi_mode {
591 dmode = QspiMode::QuadChannel as u8;
592 } else {
593 dmode = mode as u8;
594 }
595 }
596
597 if let Some((inst, mode)) = command.instruction {
599 if self.config.qpi_mode {
600 imode = QspiMode::QuadChannel as u8;
601 } else {
602 imode = mode as u8;
603 }
604 instruction = inst;
605 }
606
607 if let Some((_, mode)) = command.address {
609 if self.config.qpi_mode {
610 admode = QspiMode::QuadChannel as u8;
611 } else {
612 admode = mode as u8;
613 }
614 adsize = self.config.address_size as u8;
615 }
616
617 if let Some((a_bytes, mode)) = command.alternative_bytes {
619 if self.config.qpi_mode {
620 abmode = QspiMode::QuadChannel as u8;
621 } else {
622 abmode = mode as u8;
623 }
624
625 absize = a_bytes.len() as u8 - 1;
626
627 self.qspi.abr.write(|w| {
628 let mut reg_byte: u32 = 0;
629 for (i, element) in a_bytes.iter().rev().enumerate() {
630 reg_byte |= (*element as u32) << (i * 8);
631 }
632 unsafe { w.alternate().bits(reg_byte) }
633 });
634 }
635
636 if command.double_data_rate {
637 self.qspi.cr.modify(|_, w| w.sshift().bit(false));
638 }
639
640 self.qspi.ccr.modify(|_, w| unsafe {
642 w.fmode()
643 .bits(0b00)
644 .admode()
645 .bits(admode)
646 .adsize()
647 .bits(adsize)
648 .abmode()
649 .bits(abmode)
650 .absize()
651 .bits(absize)
652 .ddrm()
653 .bit(command.double_data_rate)
654 .dcyc()
655 .bits(command.dummy_cycles)
656 .dmode()
657 .bits(dmode)
658 .imode()
659 .bits(imode)
660 .instruction()
661 .bits(instruction)
662 });
663
664 if let Some((addr, _)) = command.address {
666 self.qspi.ar.write(|w| unsafe { w.address().bits(addr) });
667 }
668
669 if self.qspi.sr.read().tef().bit_is_set() {
671 return Err(QspiError::Unknown);
672 }
673
674 if let Some((data, _)) = command.data {
676 for byte in data {
677 while self.qspi.sr.read().ftf().bit_is_clear() {}
678 unsafe {
679 ptr::write_volatile(&self.qspi.dr as *const _ as *mut u8, *byte);
680 }
681 }
682 }
683
684 while self.qspi.sr.read().tcf().bit_is_clear() {}
685
686 self.qspi.fcr.write(|w| w.ctcf().set_bit());
687
688 if self.is_busy() {}
689
690 if command.double_data_rate {
691 self.qspi.cr.modify(|_, w| {
692 w.sshift()
693 .bit(self.config.sample_shift == SampleShift::HalfACycle)
694 });
695 }
696 Ok(())
697 }
698}
699
700pins!(
701 QUADSPI,
702 10,
703 CLK: [PE10, PB10],
704 nCS: [PE11, PB11],
705 IO0: [PE12, PB1],
706 IO1: [PE13, PB0],
707 IO2: [PE14, PA7],
708 IO3: [PE15, PA6]
709);
710
711#[cfg(not(any(feature = "stm32l475")))]
712pins!(
713 QUADSPI,
714 10,
715 CLK: [PA3],
716 nCS: [PA2, PD3],
717 IO0: [PD4],
718 IO1: [PD5],
719 IO2: [PD6],
720 IO3: [PD7]
721);
722
723#[cfg(any(
724 feature = "stm32l476",
725 feature = "stm32l486",
726 feature = "stm32l496",
727 feature = "stm32l4a6"
728))]
729pins!(
730 QUADSPI,
731 10,
732 CLK: [],
733 nCS: [],
734 IO0: [PC1, PF8],
735 IO1: [PC2, PF9],
736 IO2: [PC4, PF7],
737 IO3: [PC5, PF6]
738);