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