1#![macro_use]
3
4use core::marker::PhantomData;
5use core::ptr;
6
7use embassy_embedded_hal::SetConfig;
8use embassy_futures::join::join;
9pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
10
11use crate::dma::{word, ChannelAndRequest};
12use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed};
13use crate::mode::{Async, Blocking, Mode as PeriMode};
14use crate::pac::spi::{regs, vals, Spi as Regs};
15use crate::rcc::{RccInfo, SealedRccPeripheral};
16use crate::time::Hertz;
17use crate::Peri;
18
19#[derive(Debug, PartialEq, Eq, Clone, Copy)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub enum Error {
23 Framing,
25 Crc,
27 ModeFault,
29 Overrun,
31}
32
33impl core::fmt::Display for Error {
34 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35 let message = match self {
36 Self::Framing => "Invalid Framing",
37 Self::Crc => "Hardware CRC Check Failed",
38 Self::ModeFault => "Mode Fault",
39 Self::Overrun => "Buffer Overrun",
40 };
41
42 write!(f, "{}", message)
43 }
44}
45
46impl core::error::Error for Error {}
47
48#[derive(Copy, Clone)]
50pub enum BitOrder {
51 LsbFirst,
53 MsbFirst,
55}
56
57#[non_exhaustive]
59#[derive(Copy, Clone)]
60pub struct Config {
61 pub mode: Mode,
63 pub bit_order: BitOrder,
65 pub frequency: Hertz,
67 pub miso_pull: Pull,
72 pub gpio_speed: Speed,
75}
76
77impl Default for Config {
78 fn default() -> Self {
79 Self {
80 mode: MODE_0,
81 bit_order: BitOrder::MsbFirst,
82 frequency: Hertz(1_000_000),
83 miso_pull: Pull::None,
84 gpio_speed: Speed::VeryHigh,
85 }
86 }
87}
88
89impl Config {
90 fn raw_phase(&self) -> vals::Cpha {
91 match self.mode.phase {
92 Phase::CaptureOnSecondTransition => vals::Cpha::SECOND_EDGE,
93 Phase::CaptureOnFirstTransition => vals::Cpha::FIRST_EDGE,
94 }
95 }
96
97 fn raw_polarity(&self) -> vals::Cpol {
98 match self.mode.polarity {
99 Polarity::IdleHigh => vals::Cpol::IDLE_HIGH,
100 Polarity::IdleLow => vals::Cpol::IDLE_LOW,
101 }
102 }
103
104 fn raw_byte_order(&self) -> vals::Lsbfirst {
105 match self.bit_order {
106 BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST,
107 BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST,
108 }
109 }
110
111 #[cfg(gpio_v1)]
112 fn sck_af(&self) -> AfType {
113 AfType::output(OutputType::PushPull, self.gpio_speed)
114 }
115
116 #[cfg(gpio_v2)]
117 fn sck_af(&self) -> AfType {
118 AfType::output_pull(
119 OutputType::PushPull,
120 self.gpio_speed,
121 match self.mode.polarity {
122 Polarity::IdleLow => Pull::Down,
123 Polarity::IdleHigh => Pull::Up,
124 },
125 )
126 }
127}
128pub struct Spi<'d, M: PeriMode> {
130 pub(crate) info: &'static Info,
131 kernel_clock: Hertz,
132 sck: Option<Peri<'d, AnyPin>>,
133 mosi: Option<Peri<'d, AnyPin>>,
134 miso: Option<Peri<'d, AnyPin>>,
135 tx_dma: Option<ChannelAndRequest<'d>>,
136 rx_dma: Option<ChannelAndRequest<'d>>,
137 _phantom: PhantomData<M>,
138 current_word_size: word_impl::Config,
139 gpio_speed: Speed,
140}
141
142impl<'d, M: PeriMode> Spi<'d, M> {
143 fn new_inner<T: Instance>(
144 _peri: Peri<'d, T>,
145 sck: Option<Peri<'d, AnyPin>>,
146 mosi: Option<Peri<'d, AnyPin>>,
147 miso: Option<Peri<'d, AnyPin>>,
148 tx_dma: Option<ChannelAndRequest<'d>>,
149 rx_dma: Option<ChannelAndRequest<'d>>,
150 config: Config,
151 ) -> Self {
152 let mut this = Self {
153 info: T::info(),
154 kernel_clock: T::frequency(),
155 sck,
156 mosi,
157 miso,
158 tx_dma,
159 rx_dma,
160 current_word_size: <u8 as SealedWord>::CONFIG,
161 _phantom: PhantomData,
162 gpio_speed: config.gpio_speed,
163 };
164 this.enable_and_init(config);
165 this
166 }
167
168 fn enable_and_init(&mut self, config: Config) {
169 let br = compute_baud_rate(self.kernel_clock, config.frequency);
170 let cpha = config.raw_phase();
171 let cpol = config.raw_polarity();
172 let lsbfirst = config.raw_byte_order();
173
174 self.info.rcc.enable_and_reset();
175
176 let regs = self.info.regs;
177 #[cfg(any(spi_v1, spi_f1))]
178 {
179 regs.cr2().modify(|w| {
180 w.set_ssoe(false);
181 });
182 regs.cr1().modify(|w| {
183 w.set_cpha(cpha);
184 w.set_cpol(cpol);
185
186 w.set_mstr(vals::Mstr::MASTER);
187 w.set_br(br);
188 w.set_spe(true);
189 w.set_lsbfirst(lsbfirst);
190 w.set_ssi(true);
191 w.set_ssm(true);
192 w.set_crcen(false);
193 w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL);
194 w.set_rxonly(vals::Rxonly::FULL_DUPLEX);
198 w.set_dff(<u8 as SealedWord>::CONFIG)
199 });
200 }
201 #[cfg(spi_v2)]
202 {
203 regs.cr2().modify(|w| {
204 let (ds, frxth) = <u8 as SealedWord>::CONFIG;
205 w.set_frxth(frxth);
206 w.set_ds(ds);
207 w.set_ssoe(false);
208 });
209 regs.cr1().modify(|w| {
210 w.set_cpha(cpha);
211 w.set_cpol(cpol);
212
213 w.set_mstr(vals::Mstr::MASTER);
214 w.set_br(br);
215 w.set_lsbfirst(lsbfirst);
216 w.set_ssi(true);
217 w.set_ssm(true);
218 w.set_crcen(false);
219 w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL);
220 w.set_spe(true);
221 });
222 }
223 #[cfg(any(spi_v3, spi_v4, spi_v5))]
224 {
225 regs.ifcr().write(|w| w.0 = 0xffff_ffff);
226 regs.cfg2().modify(|w| {
227 w.set_ssoe(false);
229 w.set_cpha(cpha);
230 w.set_cpol(cpol);
231 w.set_lsbfirst(lsbfirst);
232 w.set_ssm(true);
233 w.set_master(vals::Master::MASTER);
234 w.set_comm(vals::Comm::FULL_DUPLEX);
235 w.set_ssom(vals::Ssom::ASSERTED);
236 w.set_midi(0);
237 w.set_mssi(0);
238 w.set_afcntr(true);
239 w.set_ssiop(vals::Ssiop::ACTIVE_HIGH);
240 });
241 regs.cfg1().modify(|w| {
242 w.set_crcen(false);
243 w.set_mbr(br);
244 w.set_dsize(<u8 as SealedWord>::CONFIG);
245 w.set_fthlv(vals::Fthlv::ONE_FRAME);
246 });
247 regs.cr2().modify(|w| {
248 w.set_tsize(0);
249 });
250 regs.cr1().modify(|w| {
251 w.set_ssi(false);
252 w.set_spe(true);
253 });
254 }
255 }
256
257 pub fn set_config(&mut self, config: &Config) -> Result<(), ()> {
259 let cpha = config.raw_phase();
260 let cpol = config.raw_polarity();
261
262 let lsbfirst = config.raw_byte_order();
263
264 let br = compute_baud_rate(self.kernel_clock, config.frequency);
265
266 #[cfg(gpio_v2)]
267 {
268 self.gpio_speed = config.gpio_speed;
269 if let Some(sck) = self.sck.as_ref() {
270 sck.set_speed(config.gpio_speed);
271 }
272 if let Some(mosi) = self.mosi.as_ref() {
273 mosi.set_speed(config.gpio_speed);
274 }
275 }
276
277 #[cfg(any(spi_v1, spi_f1, spi_v2))]
278 self.info.regs.cr1().modify(|w| {
279 w.set_cpha(cpha);
280 w.set_cpol(cpol);
281 w.set_br(br);
282 w.set_lsbfirst(lsbfirst);
283 });
284
285 #[cfg(any(spi_v3, spi_v4, spi_v5))]
286 {
287 self.info.regs.cr1().modify(|w| {
288 w.set_spe(false);
289 });
290
291 self.info.regs.cfg2().modify(|w| {
292 w.set_cpha(cpha);
293 w.set_cpol(cpol);
294 w.set_lsbfirst(lsbfirst);
295 });
296 self.info.regs.cfg1().modify(|w| {
297 w.set_mbr(br);
298 });
299
300 self.info.regs.cr1().modify(|w| {
301 w.set_spe(true);
302 });
303 }
304 Ok(())
305 }
306
307 pub fn get_current_config(&self) -> Config {
309 #[cfg(any(spi_v1, spi_f1, spi_v2))]
310 let cfg = self.info.regs.cr1().read();
311 #[cfg(any(spi_v3, spi_v4, spi_v5))]
312 let cfg = self.info.regs.cfg2().read();
313 #[cfg(any(spi_v3, spi_v4, spi_v5))]
314 let cfg1 = self.info.regs.cfg1().read();
315
316 let polarity = if cfg.cpol() == vals::Cpol::IDLE_LOW {
317 Polarity::IdleLow
318 } else {
319 Polarity::IdleHigh
320 };
321 let phase = if cfg.cpha() == vals::Cpha::FIRST_EDGE {
322 Phase::CaptureOnFirstTransition
323 } else {
324 Phase::CaptureOnSecondTransition
325 };
326
327 let bit_order = if cfg.lsbfirst() == vals::Lsbfirst::LSBFIRST {
328 BitOrder::LsbFirst
329 } else {
330 BitOrder::MsbFirst
331 };
332
333 let miso_pull = match &self.miso {
334 None => Pull::None,
335 Some(pin) => pin.pull(),
336 };
337
338 #[cfg(any(spi_v1, spi_f1, spi_v2))]
339 let br = cfg.br();
340 #[cfg(any(spi_v3, spi_v4, spi_v5))]
341 let br = cfg1.mbr();
342
343 let frequency = compute_frequency(self.kernel_clock, br);
344
345 Config {
346 mode: Mode { polarity, phase },
347 bit_order,
348 frequency,
349 miso_pull,
350 gpio_speed: self.gpio_speed,
351 }
352 }
353
354 pub(crate) fn set_word_size(&mut self, word_size: word_impl::Config) {
355 if self.current_word_size == word_size {
356 return;
357 }
358
359 self.info.regs.cr1().modify(|w| {
360 w.set_spe(false);
361 });
362
363 #[cfg(any(spi_v1, spi_f1))]
364 self.info.regs.cr1().modify(|reg| {
365 reg.set_dff(word_size);
366 });
367 #[cfg(spi_v2)]
368 self.info.regs.cr2().modify(|w| {
369 w.set_frxth(word_size.1);
370 w.set_ds(word_size.0);
371 });
372 #[cfg(any(spi_v3, spi_v4, spi_v5))]
373 self.info.regs.cfg1().modify(|w| {
374 w.set_dsize(word_size);
375 });
376
377 self.current_word_size = word_size;
378 }
379
380 pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> {
382 #[cfg(any(spi_v3, spi_v4, spi_v5))]
384 self.info.regs.cr1().modify(|w| w.set_spe(false));
385 self.set_word_size(W::CONFIG);
386 self.info.regs.cr1().modify(|w| w.set_spe(true));
387 flush_rx_fifo(self.info.regs);
388 for word in words.iter() {
389 #[cfg(not(any(spi_v1, spi_f1)))]
395 write_word(self.info.regs, *word)?;
396
397 #[cfg(any(spi_v1, spi_f1))]
405 transfer_word(self.info.regs, *word)?;
406 }
407
408 #[cfg(not(any(spi_v1, spi_f1, spi_v2)))]
410 while !self.info.regs.sr().read().txc() {}
411 #[cfg(spi_v2)]
412 while self.info.regs.sr().read().bsy() {}
413
414 Ok(())
415 }
416
417 pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
419 #[cfg(any(spi_v3, spi_v4, spi_v5))]
421 self.info.regs.cr1().modify(|w| w.set_spe(false));
422 self.set_word_size(W::CONFIG);
423 self.info.regs.cr1().modify(|w| w.set_spe(true));
424 flush_rx_fifo(self.info.regs);
425 for word in words.iter_mut() {
426 *word = transfer_word(self.info.regs, W::default())?;
427 }
428 Ok(())
429 }
430
431 pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> {
435 #[cfg(any(spi_v3, spi_v4, spi_v5))]
437 self.info.regs.cr1().modify(|w| w.set_spe(false));
438 self.set_word_size(W::CONFIG);
439 self.info.regs.cr1().modify(|w| w.set_spe(true));
440 flush_rx_fifo(self.info.regs);
441 for word in words.iter_mut() {
442 *word = transfer_word(self.info.regs, *word)?;
443 }
444 Ok(())
445 }
446
447 pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
454 #[cfg(any(spi_v3, spi_v4, spi_v5))]
456 self.info.regs.cr1().modify(|w| w.set_spe(false));
457 self.set_word_size(W::CONFIG);
458 self.info.regs.cr1().modify(|w| w.set_spe(true));
459 flush_rx_fifo(self.info.regs);
460 let len = read.len().max(write.len());
461 for i in 0..len {
462 let wb = write.get(i).copied().unwrap_or_default();
463 let rb = transfer_word(self.info.regs, wb)?;
464 if let Some(r) = read.get_mut(i) {
465 *r = rb;
466 }
467 }
468 Ok(())
469 }
470}
471
472impl<'d> Spi<'d, Blocking> {
473 pub fn new_blocking<T: Instance>(
475 peri: Peri<'d, T>,
476 sck: Peri<'d, impl SckPin<T>>,
477 mosi: Peri<'d, impl MosiPin<T>>,
478 miso: Peri<'d, impl MisoPin<T>>,
479 config: Config,
480 ) -> Self {
481 Self::new_inner(
482 peri,
483 new_pin!(sck, config.sck_af()),
484 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
485 new_pin!(miso, AfType::input(config.miso_pull)),
486 None,
487 None,
488 config,
489 )
490 }
491
492 pub fn new_blocking_rxonly<T: Instance>(
494 peri: Peri<'d, T>,
495 sck: Peri<'d, impl SckPin<T>>,
496 miso: Peri<'d, impl MisoPin<T>>,
497 config: Config,
498 ) -> Self {
499 Self::new_inner(
500 peri,
501 new_pin!(sck, config.sck_af()),
502 None,
503 new_pin!(miso, AfType::input(config.miso_pull)),
504 None,
505 None,
506 config,
507 )
508 }
509
510 pub fn new_blocking_txonly<T: Instance>(
512 peri: Peri<'d, T>,
513 sck: Peri<'d, impl SckPin<T>>,
514 mosi: Peri<'d, impl MosiPin<T>>,
515 config: Config,
516 ) -> Self {
517 Self::new_inner(
518 peri,
519 new_pin!(sck, config.sck_af()),
520 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
521 None,
522 None,
523 None,
524 config,
525 )
526 }
527
528 pub fn new_blocking_txonly_nosck<T: Instance>(
532 peri: Peri<'d, T>,
533 mosi: Peri<'d, impl MosiPin<T>>,
534 config: Config,
535 ) -> Self {
536 Self::new_inner(
537 peri,
538 None,
539 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
540 None,
541 None,
542 None,
543 config,
544 )
545 }
546}
547
548impl<'d> Spi<'d, Async> {
549 pub fn new<T: Instance>(
551 peri: Peri<'d, T>,
552 sck: Peri<'d, impl SckPin<T>>,
553 mosi: Peri<'d, impl MosiPin<T>>,
554 miso: Peri<'d, impl MisoPin<T>>,
555 tx_dma: Peri<'d, impl TxDma<T>>,
556 rx_dma: Peri<'d, impl RxDma<T>>,
557 config: Config,
558 ) -> Self {
559 Self::new_inner(
560 peri,
561 new_pin!(sck, config.sck_af()),
562 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
563 new_pin!(miso, AfType::input(config.miso_pull)),
564 new_dma!(tx_dma),
565 new_dma!(rx_dma),
566 config,
567 )
568 }
569
570 pub fn new_rxonly<T: Instance>(
572 peri: Peri<'d, T>,
573 sck: Peri<'d, impl SckPin<T>>,
574 miso: Peri<'d, impl MisoPin<T>>,
575 #[cfg(any(spi_v1, spi_f1, spi_v2))] tx_dma: Peri<'d, impl TxDma<T>>,
576 rx_dma: Peri<'d, impl RxDma<T>>,
577 config: Config,
578 ) -> Self {
579 Self::new_inner(
580 peri,
581 new_pin!(sck, config.sck_af()),
582 None,
583 new_pin!(miso, AfType::input(config.miso_pull)),
584 #[cfg(any(spi_v1, spi_f1, spi_v2))]
585 new_dma!(tx_dma),
586 #[cfg(any(spi_v3, spi_v4, spi_v5))]
587 None,
588 new_dma!(rx_dma),
589 config,
590 )
591 }
592
593 pub fn new_txonly<T: Instance>(
595 peri: Peri<'d, T>,
596 sck: Peri<'d, impl SckPin<T>>,
597 mosi: Peri<'d, impl MosiPin<T>>,
598 tx_dma: Peri<'d, impl TxDma<T>>,
599 config: Config,
600 ) -> Self {
601 Self::new_inner(
602 peri,
603 new_pin!(sck, config.sck_af()),
604 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
605 None,
606 new_dma!(tx_dma),
607 None,
608 config,
609 )
610 }
611
612 pub fn new_txonly_nosck<T: Instance>(
616 peri: Peri<'d, T>,
617 mosi: Peri<'d, impl MosiPin<T>>,
618 tx_dma: Peri<'d, impl TxDma<T>>,
619 config: Config,
620 ) -> Self {
621 Self::new_inner(
622 peri,
623 None,
624 new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)),
625 None,
626 new_dma!(tx_dma),
627 None,
628 config,
629 )
630 }
631
632 #[cfg(stm32wl)]
633 pub fn new_subghz<T: Instance>(
635 peri: Peri<'d, T>,
636 tx_dma: Peri<'d, impl TxDma<T>>,
637 rx_dma: Peri<'d, impl RxDma<T>>,
638 ) -> Self {
639 let pclk3_freq = <crate::peripherals::SUBGHZSPI as SealedRccPeripheral>::frequency().0;
643 let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000));
644 let mut config = Config::default();
645 config.mode = MODE_0;
646 config.bit_order = BitOrder::MsbFirst;
647 config.frequency = freq;
648
649 Self::new_inner(peri, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config)
650 }
651
652 #[allow(dead_code)]
653 pub(crate) fn new_internal<T: Instance>(
654 peri: Peri<'d, T>,
655 tx_dma: Option<ChannelAndRequest<'d>>,
656 rx_dma: Option<ChannelAndRequest<'d>>,
657 config: Config,
658 ) -> Self {
659 Self::new_inner(peri, None, None, None, tx_dma, rx_dma, config)
660 }
661
662 pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> {
664 if data.is_empty() {
665 return Ok(());
666 }
667
668 self.info.regs.cr1().modify(|w| {
669 w.set_spe(false);
670 });
671 self.set_word_size(W::CONFIG);
672
673 let tx_dst = self.info.regs.tx_ptr();
674 let tx_f = unsafe { self.tx_dma.as_mut().unwrap().write(data, tx_dst, Default::default()) };
675
676 set_txdmaen(self.info.regs, true);
677 self.info.regs.cr1().modify(|w| {
678 w.set_spe(true);
679 });
680 #[cfg(any(spi_v3, spi_v4, spi_v5))]
681 self.info.regs.cr1().modify(|w| {
682 w.set_cstart(true);
683 });
684
685 tx_f.await;
686
687 finish_dma(self.info.regs);
688
689 Ok(())
690 }
691
692 #[cfg(any(spi_v3, spi_v4, spi_v5))]
694 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
695 if data.is_empty() {
696 return Ok(());
697 }
698
699 let regs = self.info.regs;
700
701 regs.cr1().modify(|w| {
702 w.set_spe(false);
703 });
704
705 self.set_word_size(W::CONFIG);
706
707 let comm = regs.cfg2().modify(|w| {
708 let prev = w.comm();
709 w.set_comm(vals::Comm::RECEIVER);
710 prev
711 });
712
713 #[cfg(spi_v3)]
714 let i2scfg = regs.i2scfgr().modify(|w| {
715 w.i2smod().then(|| {
716 let prev = w.i2scfg();
717 w.set_i2scfg(match prev {
718 vals::I2scfg::SLAVE_RX | vals::I2scfg::SLAVE_FULL_DUPLEX => vals::I2scfg::SLAVE_RX,
719 vals::I2scfg::MASTER_RX | vals::I2scfg::MASTER_FULL_DUPLEX => vals::I2scfg::MASTER_RX,
720 _ => panic!("unsupported configuration"),
721 });
722 prev
723 })
724 });
725
726 let rx_src = regs.rx_ptr();
727
728 for mut chunk in data.chunks_mut(u16::max_value().into()) {
729 set_rxdmaen(regs, true);
730
731 let tsize = chunk.len();
732
733 let transfer = unsafe {
734 self.rx_dma
735 .as_mut()
736 .unwrap()
737 .read(rx_src, &mut chunk, Default::default())
738 };
739
740 regs.cr2().modify(|w| {
741 w.set_tsize(tsize as u16);
742 });
743
744 regs.cr1().modify(|w| {
745 w.set_spe(true);
746 });
747
748 regs.cr1().modify(|w| {
749 w.set_cstart(true);
750 });
751
752 transfer.await;
753
754 finish_dma(regs);
755 }
756
757 regs.cr1().modify(|w| {
758 w.set_spe(false);
759 });
760
761 regs.cfg2().modify(|w| {
762 w.set_comm(comm);
763 });
764
765 regs.cr2().modify(|w| {
766 w.set_tsize(0);
767 });
768
769 #[cfg(spi_v3)]
770 if let Some(i2scfg) = i2scfg {
771 regs.i2scfgr().modify(|w| {
772 w.set_i2scfg(i2scfg);
773 });
774 }
775
776 Ok(())
777 }
778
779 #[cfg(any(spi_v1, spi_f1, spi_v2))]
781 pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
782 if data.is_empty() {
783 return Ok(());
784 }
785
786 self.info.regs.cr1().modify(|w| {
787 w.set_spe(false);
788 });
789
790 self.set_word_size(W::CONFIG);
791
792 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
794 flush_rx_fifo(self.info.regs);
795
796 set_rxdmaen(self.info.regs, true);
797
798 let clock_byte_count = data.len();
799
800 let rx_src = self.info.regs.rx_ptr();
801 let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read(rx_src, data, Default::default()) };
802
803 let tx_dst = self.info.regs.tx_ptr();
804 let clock_byte = W::default();
805 let tx_f = unsafe {
806 self.tx_dma
807 .as_mut()
808 .unwrap()
809 .write_repeated(&clock_byte, clock_byte_count, tx_dst, Default::default())
810 };
811
812 set_txdmaen(self.info.regs, true);
813 self.info.regs.cr1().modify(|w| {
814 w.set_spe(true);
815 });
816 #[cfg(any(spi_v3, spi_v4, spi_v5))]
817 self.info.regs.cr1().modify(|w| {
818 w.set_cstart(true);
819 });
820
821 join(tx_f, rx_f).await;
822
823 finish_dma(self.info.regs);
824
825 Ok(())
826 }
827
828 async fn transfer_inner<W: Word>(&mut self, read: *mut [W], write: *const [W]) -> Result<(), Error> {
829 assert_eq!(read.len(), write.len());
830 if read.len() == 0 {
831 return Ok(());
832 }
833
834 self.info.regs.cr1().modify(|w| {
835 w.set_spe(false);
836 });
837
838 self.set_word_size(W::CONFIG);
839
840 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
842 flush_rx_fifo(self.info.regs);
843
844 set_rxdmaen(self.info.regs, true);
845
846 let rx_src = self.info.regs.rx_ptr::<W>();
847 let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) };
848
849 let tx_dst: *mut W = self.info.regs.tx_ptr();
850 let tx_f = unsafe {
851 self.tx_dma
852 .as_mut()
853 .unwrap()
854 .write_raw(write, tx_dst, Default::default())
855 };
856
857 set_txdmaen(self.info.regs, true);
858 self.info.regs.cr1().modify(|w| {
859 w.set_spe(true);
860 });
861 #[cfg(any(spi_v3, spi_v4, spi_v5))]
862 self.info.regs.cr1().modify(|w| {
863 w.set_cstart(true);
864 });
865
866 join(tx_f, rx_f).await;
867
868 finish_dma(self.info.regs);
869
870 Ok(())
871 }
872
873 pub async fn transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> {
880 self.transfer_inner(read, write).await
881 }
882
883 pub async fn transfer_in_place<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> {
887 self.transfer_inner(data, data).await
888 }
889}
890
891impl<'d, M: PeriMode> Drop for Spi<'d, M> {
892 fn drop(&mut self) {
893 self.sck.as_ref().map(|x| x.set_as_disconnected());
894 self.mosi.as_ref().map(|x| x.set_as_disconnected());
895 self.miso.as_ref().map(|x| x.set_as_disconnected());
896
897 self.info.rcc.disable();
898 }
899}
900
901#[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
902use vals::Br;
903#[cfg(any(spi_v3, spi_v4, spi_v5))]
904use vals::Mbr as Br;
905
906fn compute_baud_rate(kernel_clock: Hertz, freq: Hertz) -> Br {
907 let val = match kernel_clock.0 / freq.0 {
908 0 => panic!("You are trying to reach a frequency higher than the clock"),
909 1..=2 => 0b000,
910 3..=5 => 0b001,
911 6..=11 => 0b010,
912 12..=23 => 0b011,
913 24..=39 => 0b100,
914 40..=95 => 0b101,
915 96..=191 => 0b110,
916 _ => 0b111,
917 };
918
919 Br::from_bits(val)
920}
921
922fn compute_frequency(kernel_clock: Hertz, br: Br) -> Hertz {
923 let div: u16 = match br {
924 Br::DIV2 => 2,
925 Br::DIV4 => 4,
926 Br::DIV8 => 8,
927 Br::DIV16 => 16,
928 Br::DIV32 => 32,
929 Br::DIV64 => 64,
930 Br::DIV128 => 128,
931 Br::DIV256 => 256,
932 };
933
934 kernel_clock / div
935}
936
937pub(crate) trait RegsExt {
938 fn tx_ptr<W>(&self) -> *mut W;
939 fn rx_ptr<W>(&self) -> *mut W;
940}
941
942impl RegsExt for Regs {
943 fn tx_ptr<W>(&self) -> *mut W {
944 #[cfg(any(spi_v1, spi_f1))]
945 let dr = self.dr();
946 #[cfg(spi_v2)]
947 let dr = self.dr16();
948 #[cfg(any(spi_v3, spi_v4, spi_v5))]
949 let dr = self.txdr32();
950 dr.as_ptr() as *mut W
951 }
952
953 fn rx_ptr<W>(&self) -> *mut W {
954 #[cfg(any(spi_v1, spi_f1))]
955 let dr = self.dr();
956 #[cfg(spi_v2)]
957 let dr = self.dr16();
958 #[cfg(any(spi_v3, spi_v4, spi_v5))]
959 let dr = self.rxdr32();
960 dr.as_ptr() as *mut W
961 }
962}
963
964fn check_error_flags(sr: regs::Sr, ovr: bool) -> Result<(), Error> {
965 if sr.ovr() && ovr {
966 return Err(Error::Overrun);
967 }
968 #[cfg(not(any(spi_f1, spi_v3, spi_v4, spi_v5)))]
969 if sr.fre() {
970 return Err(Error::Framing);
971 }
972 #[cfg(any(spi_v3, spi_v4, spi_v5))]
973 if sr.tifre() {
974 return Err(Error::Framing);
975 }
976 if sr.modf() {
977 return Err(Error::ModeFault);
978 }
979 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
980 if sr.crcerr() {
981 return Err(Error::Crc);
982 }
983 #[cfg(any(spi_v3, spi_v4, spi_v5))]
984 if sr.crce() {
985 return Err(Error::Crc);
986 }
987
988 Ok(())
989}
990
991fn spin_until_tx_ready(regs: Regs, ovr: bool) -> Result<(), Error> {
992 loop {
993 let sr = regs.sr().read();
994
995 check_error_flags(sr, ovr)?;
996
997 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
998 if sr.txe() {
999 return Ok(());
1000 }
1001 #[cfg(any(spi_v3, spi_v4, spi_v5))]
1002 if sr.txp() {
1003 return Ok(());
1004 }
1005 }
1006}
1007
1008fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> {
1009 loop {
1010 let sr = regs.sr().read();
1011
1012 check_error_flags(sr, true)?;
1013
1014 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
1015 if sr.rxne() {
1016 return Ok(());
1017 }
1018 #[cfg(any(spi_v3, spi_v4, spi_v5))]
1019 if sr.rxp() {
1020 return Ok(());
1021 }
1022 }
1023}
1024
1025pub(crate) fn flush_rx_fifo(regs: Regs) {
1026 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
1027 while regs.sr().read().rxne() {
1028 #[cfg(not(spi_v2))]
1029 let _ = regs.dr().read();
1030 #[cfg(spi_v2)]
1031 let _ = regs.dr16().read();
1032 }
1033 #[cfg(any(spi_v3, spi_v4, spi_v5))]
1034 while regs.sr().read().rxp() {
1035 let _ = regs.rxdr32().read();
1036 }
1037}
1038
1039pub(crate) fn set_txdmaen(regs: Regs, val: bool) {
1040 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
1041 regs.cr2().modify(|reg| {
1042 reg.set_txdmaen(val);
1043 });
1044 #[cfg(any(spi_v3, spi_v4, spi_v5))]
1045 regs.cfg1().modify(|reg| {
1046 reg.set_txdmaen(val);
1047 });
1048}
1049
1050pub(crate) fn set_rxdmaen(regs: Regs, val: bool) {
1051 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
1052 regs.cr2().modify(|reg| {
1053 reg.set_rxdmaen(val);
1054 });
1055 #[cfg(any(spi_v3, spi_v4, spi_v5))]
1056 regs.cfg1().modify(|reg| {
1057 reg.set_rxdmaen(val);
1058 });
1059}
1060
1061fn finish_dma(regs: Regs) {
1062 #[cfg(spi_v2)]
1063 while regs.sr().read().ftlvl().to_bits() > 0 {}
1064
1065 #[cfg(any(spi_v3, spi_v4, spi_v5))]
1066 {
1067 if regs.cr2().read().tsize() == 0 {
1068 while !regs.sr().read().txc() {}
1069 } else {
1070 while !regs.sr().read().eot() {}
1071 }
1072 }
1073 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
1074 while regs.sr().read().bsy() {}
1075
1076 regs.cr1().modify(|w| {
1078 w.set_spe(false);
1079 });
1080
1081 #[cfg(not(any(spi_v3, spi_v4, spi_v5)))]
1084 regs.cr2().modify(|reg| {
1085 reg.set_txdmaen(false);
1086 reg.set_rxdmaen(false);
1087 });
1088 #[cfg(any(spi_v3, spi_v4, spi_v5))]
1089 regs.cfg1().modify(|reg| {
1090 reg.set_txdmaen(false);
1091 reg.set_rxdmaen(false);
1092 });
1093}
1094
1095fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> {
1096 spin_until_tx_ready(regs, true)?;
1097
1098 unsafe {
1099 ptr::write_volatile(regs.tx_ptr(), tx_word);
1100
1101 #[cfg(any(spi_v3, spi_v4, spi_v5))]
1102 regs.cr1().modify(|reg| reg.set_cstart(true));
1103 }
1104
1105 spin_until_rx_ready(regs)?;
1106
1107 let rx_word = unsafe { ptr::read_volatile(regs.rx_ptr()) };
1108 Ok(rx_word)
1109}
1110
1111#[allow(unused)] fn write_word<W: Word>(regs: Regs, tx_word: W) -> Result<(), Error> {
1113 spin_until_tx_ready(regs, false)?;
1116
1117 unsafe {
1118 ptr::write_volatile(regs.tx_ptr(), tx_word);
1119
1120 #[cfg(any(spi_v3, spi_v4, spi_v5))]
1121 regs.cr1().modify(|reg| reg.set_cstart(true));
1122 }
1123 Ok(())
1124}
1125
1126macro_rules! impl_blocking {
1129 ($w:ident) => {
1130 impl<'d, M: PeriMode> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, M> {
1131 type Error = Error;
1132
1133 fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> {
1134 self.blocking_write(words)
1135 }
1136 }
1137
1138 impl<'d, M: PeriMode> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, M> {
1139 type Error = Error;
1140
1141 fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> {
1142 self.blocking_transfer_in_place(words)?;
1143 Ok(words)
1144 }
1145 }
1146 };
1147}
1148
1149impl_blocking!(u8);
1150impl_blocking!(u16);
1151
1152impl<'d, M: PeriMode> embedded_hal_1::spi::ErrorType for Spi<'d, M> {
1153 type Error = Error;
1154}
1155
1156impl<'d, W: Word, M: PeriMode> embedded_hal_1::spi::SpiBus<W> for Spi<'d, M> {
1157 fn flush(&mut self) -> Result<(), Self::Error> {
1158 Ok(())
1159 }
1160
1161 fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> {
1162 self.blocking_read(words)
1163 }
1164
1165 fn write(&mut self, words: &[W]) -> Result<(), Self::Error> {
1166 self.blocking_write(words)
1167 }
1168
1169 fn transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error> {
1170 self.blocking_transfer(read, write)
1171 }
1172
1173 fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Self::Error> {
1174 self.blocking_transfer_in_place(words)
1175 }
1176}
1177
1178impl embedded_hal_1::spi::Error for Error {
1179 fn kind(&self) -> embedded_hal_1::spi::ErrorKind {
1180 match *self {
1181 Self::Framing => embedded_hal_1::spi::ErrorKind::FrameFormat,
1182 Self::Crc => embedded_hal_1::spi::ErrorKind::Other,
1183 Self::ModeFault => embedded_hal_1::spi::ErrorKind::ModeFault,
1184 Self::Overrun => embedded_hal_1::spi::ErrorKind::Overrun,
1185 }
1186 }
1187}
1188
1189impl<'d, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, Async> {
1190 async fn flush(&mut self) -> Result<(), Self::Error> {
1191 Ok(())
1192 }
1193
1194 async fn write(&mut self, words: &[W]) -> Result<(), Self::Error> {
1195 self.write(words).await
1196 }
1197
1198 async fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> {
1199 self.read(words).await
1200 }
1201
1202 async fn transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error> {
1203 self.transfer(read, write).await
1204 }
1205
1206 async fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Self::Error> {
1207 self.transfer_in_place(words).await
1208 }
1209}
1210
1211pub(crate) trait SealedWord {
1212 const CONFIG: word_impl::Config;
1213}
1214
1215#[allow(private_bounds)]
1217pub trait Word: word::Word + SealedWord + Default {}
1218
1219macro_rules! impl_word {
1220 ($T:ty, $config:expr) => {
1221 impl SealedWord for $T {
1222 const CONFIG: Config = $config;
1223 }
1224 impl Word for $T {}
1225 };
1226}
1227
1228#[cfg(any(spi_v1, spi_f1))]
1229mod word_impl {
1230 use super::*;
1231
1232 pub type Config = vals::Dff;
1233
1234 impl_word!(u8, vals::Dff::BITS8);
1235 impl_word!(u16, vals::Dff::BITS16);
1236}
1237
1238#[cfg(spi_v2)]
1239mod word_impl {
1240 use super::*;
1241
1242 pub type Config = (vals::Ds, vals::Frxth);
1243
1244 impl_word!(word::U4, (vals::Ds::BITS4, vals::Frxth::QUARTER));
1245 impl_word!(word::U5, (vals::Ds::BITS5, vals::Frxth::QUARTER));
1246 impl_word!(word::U6, (vals::Ds::BITS6, vals::Frxth::QUARTER));
1247 impl_word!(word::U7, (vals::Ds::BITS7, vals::Frxth::QUARTER));
1248 impl_word!(u8, (vals::Ds::BITS8, vals::Frxth::QUARTER));
1249 impl_word!(word::U9, (vals::Ds::BITS9, vals::Frxth::HALF));
1250 impl_word!(word::U10, (vals::Ds::BITS10, vals::Frxth::HALF));
1251 impl_word!(word::U11, (vals::Ds::BITS11, vals::Frxth::HALF));
1252 impl_word!(word::U12, (vals::Ds::BITS12, vals::Frxth::HALF));
1253 impl_word!(word::U13, (vals::Ds::BITS13, vals::Frxth::HALF));
1254 impl_word!(word::U14, (vals::Ds::BITS14, vals::Frxth::HALF));
1255 impl_word!(word::U15, (vals::Ds::BITS15, vals::Frxth::HALF));
1256 impl_word!(u16, (vals::Ds::BITS16, vals::Frxth::HALF));
1257}
1258
1259#[cfg(any(spi_v3, spi_v4, spi_v5))]
1260mod word_impl {
1261 use super::*;
1262
1263 pub type Config = u8;
1264
1265 impl_word!(word::U4, 4 - 1);
1266 impl_word!(word::U5, 5 - 1);
1267 impl_word!(word::U6, 6 - 1);
1268 impl_word!(word::U7, 7 - 1);
1269 impl_word!(u8, 8 - 1);
1270 impl_word!(word::U9, 9 - 1);
1271 impl_word!(word::U10, 10 - 1);
1272 impl_word!(word::U11, 11 - 1);
1273 impl_word!(word::U12, 12 - 1);
1274 impl_word!(word::U13, 13 - 1);
1275 impl_word!(word::U14, 14 - 1);
1276 impl_word!(word::U15, 15 - 1);
1277 impl_word!(u16, 16 - 1);
1278 impl_word!(word::U17, 17 - 1);
1279 impl_word!(word::U18, 18 - 1);
1280 impl_word!(word::U19, 19 - 1);
1281 impl_word!(word::U20, 20 - 1);
1282 impl_word!(word::U21, 21 - 1);
1283 impl_word!(word::U22, 22 - 1);
1284 impl_word!(word::U23, 23 - 1);
1285 impl_word!(word::U24, 24 - 1);
1286 impl_word!(word::U25, 25 - 1);
1287 impl_word!(word::U26, 26 - 1);
1288 impl_word!(word::U27, 27 - 1);
1289 impl_word!(word::U28, 28 - 1);
1290 impl_word!(word::U29, 29 - 1);
1291 impl_word!(word::U30, 30 - 1);
1292 impl_word!(word::U31, 31 - 1);
1293 impl_word!(u32, 32 - 1);
1294}
1295
1296pub(crate) struct Info {
1297 pub(crate) regs: Regs,
1298 pub(crate) rcc: RccInfo,
1299}
1300
1301struct State {}
1302
1303impl State {
1304 #[allow(unused)]
1305 const fn new() -> Self {
1306 Self {}
1307 }
1308}
1309
1310peri_trait!();
1311
1312pin_trait!(SckPin, Instance);
1313pin_trait!(MosiPin, Instance);
1314pin_trait!(MisoPin, Instance);
1315pin_trait!(CsPin, Instance);
1316pin_trait!(MckPin, Instance);
1317pin_trait!(CkPin, Instance);
1318pin_trait!(WsPin, Instance);
1319dma_trait!(RxDma, Instance);
1320dma_trait!(TxDma, Instance);
1321
1322foreach_peripheral!(
1323 (spi, $inst:ident) => {
1324 peri_trait_impl!($inst, Info {
1325 regs: crate::pac::$inst,
1326 rcc: crate::peripherals::$inst::RCC_INFO,
1327 });
1328 };
1329);
1330
1331impl<'d, M: PeriMode> SetConfig for Spi<'d, M> {
1332 type Config = Config;
1333 type ConfigError = ();
1334 fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> {
1335 self.set_config(config)
1336 }
1337}