1#![macro_use]
4
5use core::future::poll_fn;
6use core::marker::PhantomData;
7#[cfg(feature = "_nrf52832_anomaly_109")]
8use core::sync::atomic::AtomicU8;
9use core::sync::atomic::{Ordering, compiler_fence};
10use core::task::Poll;
11
12use embassy_embedded_hal::SetConfig;
13use embassy_hal_internal::{Peri, PeripheralType};
14use embassy_sync::waitqueue::AtomicWaker;
15pub use embedded_hal_02::spi::{MODE_0, MODE_1, MODE_2, MODE_3, Mode, Phase, Polarity};
16pub use pac::spim::vals::Order as BitOrder;
17
18use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
19use crate::gpio::{self, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, convert_drive};
20use crate::interrupt::typelevel::Interrupt;
21use crate::pac::gpio::vals as gpiovals;
22use crate::pac::spim::vals;
23use crate::util::slice_in_ram_or;
24use crate::{interrupt, pac};
25
26#[repr(transparent)]
28#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
29pub struct Frequency(u32);
30impl Frequency {
31 #[doc = "125 kbps"]
32 pub const K125: Self = Self(0x0200_0000);
33 #[doc = "250 kbps"]
34 pub const K250: Self = Self(0x0400_0000);
35 #[doc = "500 kbps"]
36 pub const K500: Self = Self(0x0800_0000);
37 #[doc = "1 Mbps"]
38 pub const M1: Self = Self(0x1000_0000);
39 #[doc = "2 Mbps"]
40 pub const M2: Self = Self(0x2000_0000);
41 #[doc = "4 Mbps"]
42 pub const M4: Self = Self(0x4000_0000);
43 #[doc = "8 Mbps"]
44 pub const M8: Self = Self(0x8000_0000);
45 #[cfg(not(feature = "_spi-v1"))]
46 #[doc = "16 Mbps"]
47 pub const M16: Self = Self(0x0a00_0000);
48 #[cfg(not(feature = "_spi-v1"))]
49 #[doc = "32 Mbps"]
50 pub const M32: Self = Self(0x1400_0000);
51}
52
53impl Frequency {
54 #[cfg(feature = "_nrf54l")]
55 fn to_divisor(&self, clk: u32) -> u8 {
56 let frequency = match *self {
57 #[cfg(not(feature = "_spi-v1"))]
58 Self::M32 => 32_000_000,
59 #[cfg(not(feature = "_spi-v1"))]
60 Self::M16 => 16_000_000,
61 Self::M8 => 8_000_000,
62 Self::M4 => 4_000_000,
63 Self::M2 => 2_000_000,
64 Self::M1 => 1_000_000,
65 Self::K500 => 500_000,
66 Self::K250 => 250_000,
67 Self::K125 => 125_000,
68 _ => unreachable!(),
69 };
70 let divisor = (clk / frequency) as u8;
71 divisor
72 }
73}
74impl core::fmt::Debug for Frequency {
75 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
76 match self.0 {
77 0x0200_0000 => f.write_str("K125"),
78 0x0400_0000 => f.write_str("K250"),
79 0x0800_0000 => f.write_str("K500"),
80 0x0a00_0000 => f.write_str("M16"),
81 0x1000_0000 => f.write_str("M1"),
82 0x1400_0000 => f.write_str("M32"),
83 0x2000_0000 => f.write_str("M2"),
84 0x4000_0000 => f.write_str("M4"),
85 0x8000_0000 => f.write_str("M8"),
86 other => core::write!(f, "0x{:02X}", other),
87 }
88 }
89}
90
91#[cfg(feature = "defmt")]
92impl defmt::Format for Frequency {
93 fn format(&self, f: defmt::Formatter) {
94 match self.0 {
95 0x0200_0000 => defmt::write!(f, "K125"),
96 0x0400_0000 => defmt::write!(f, "K250"),
97 0x0800_0000 => defmt::write!(f, "K500"),
98 0x0a00_0000 => defmt::write!(f, "M16"),
99 0x1000_0000 => defmt::write!(f, "M1"),
100 0x1400_0000 => defmt::write!(f, "M32"),
101 0x2000_0000 => defmt::write!(f, "M2"),
102 0x4000_0000 => defmt::write!(f, "M4"),
103 0x8000_0000 => defmt::write!(f, "M8"),
104 other => defmt::write!(f, "0x{:02X}", other),
105 }
106 }
107}
108
109#[cfg(not(feature = "_nrf54l"))]
110impl Into<pac::spim::vals::Frequency> for Frequency {
111 fn into(self) -> pac::spim::vals::Frequency {
112 use pac::spim::vals::Frequency as Freq;
113 match self {
114 #[cfg(not(feature = "_spi-v1"))]
115 Self::M32 => Freq::M32,
116 #[cfg(not(feature = "_spi-v1"))]
117 Self::M16 => Freq::M16,
118 Self::M8 => Freq::M8,
119 Self::M4 => Freq::M4,
120 Self::M2 => Freq::M2,
121 Self::M1 => Freq::M1,
122 Self::K500 => Freq::K500,
123 Self::K250 => Freq::K250,
124 Self::K125 => Freq::K125,
125 _ => unreachable!(),
126 }
127 }
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132#[cfg_attr(feature = "defmt", derive(defmt::Format))]
133#[non_exhaustive]
134pub enum Error {
135 BufferNotInRAM,
137}
138
139#[non_exhaustive]
141#[derive(Clone)]
142pub struct Config {
143 pub frequency: Frequency,
145
146 pub mode: Mode,
148
149 pub bit_order: BitOrder,
151
152 pub orc: u8,
157
158 pub sck_drive: OutputDrive,
160
161 pub mosi_drive: OutputDrive,
163}
164
165impl Default for Config {
166 fn default() -> Self {
167 Self {
168 frequency: Frequency::M1,
169 mode: MODE_0,
170 bit_order: BitOrder::MSB_FIRST,
171 orc: 0x00,
172 sck_drive: OutputDrive::HighDrive,
173 mosi_drive: OutputDrive::HighDrive,
174 }
175 }
176}
177
178pub struct InterruptHandler<T: Instance> {
180 _phantom: PhantomData<T>,
181}
182
183impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
184 unsafe fn on_interrupt() {
185 let r = T::regs();
186 let s = T::state();
187
188 #[cfg(feature = "_nrf52832_anomaly_109")]
189 {
190 if r.events_started().read() != 0 {
193 s.waker.wake();
194 r.intenclr().write(|w| w.set_started(true));
195 }
196 }
197
198 if r.events_end().read() != 0 {
199 s.waker.wake();
200 r.intenclr().write(|w| w.set_end(true));
201 }
202 }
203}
204
205pub struct Spim<'d> {
207 r: pac::spim::Spim,
208 irq: interrupt::Interrupt,
209 state: &'static State,
210 #[cfg(feature = "_nrf54l")]
211 clk: u32,
212 _p: PhantomData<&'d ()>,
213}
214
215impl<'d> Spim<'d> {
216 pub fn new<T: Instance>(
218 spim: Peri<'d, T>,
219 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
220 sck: Peri<'d, impl GpioPin>,
221 miso: Peri<'d, impl GpioPin>,
222 mosi: Peri<'d, impl GpioPin>,
223 config: Config,
224 ) -> Self {
225 Self::new_inner(spim, Some(sck.into()), Some(miso.into()), Some(mosi.into()), config)
226 }
227
228 pub fn new_txonly<T: Instance>(
230 spim: Peri<'d, T>,
231 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
232 sck: Peri<'d, impl GpioPin>,
233 mosi: Peri<'d, impl GpioPin>,
234 config: Config,
235 ) -> Self {
236 Self::new_inner(spim, Some(sck.into()), None, Some(mosi.into()), config)
237 }
238
239 pub fn new_rxonly<T: Instance>(
241 spim: Peri<'d, T>,
242 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
243 sck: Peri<'d, impl GpioPin>,
244 miso: Peri<'d, impl GpioPin>,
245 config: Config,
246 ) -> Self {
247 Self::new_inner(spim, Some(sck.into()), Some(miso.into()), None, config)
248 }
249
250 pub fn new_txonly_nosck<T: Instance>(
252 spim: Peri<'d, T>,
253 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
254 mosi: Peri<'d, impl GpioPin>,
255 config: Config,
256 ) -> Self {
257 Self::new_inner(spim, None, None, Some(mosi.into()), config)
258 }
259
260 fn new_inner<T: Instance>(
261 _spim: Peri<'d, T>,
262 sck: Option<Peri<'d, AnyPin>>,
263 miso: Option<Peri<'d, AnyPin>>,
264 mosi: Option<Peri<'d, AnyPin>>,
265 config: Config,
266 ) -> Self {
267 let r = T::regs();
268
269 if let Some(sck) = &sck {
271 sck.conf().write(|w| {
272 w.set_dir(gpiovals::Dir::OUTPUT);
273 convert_drive(w, config.sck_drive);
274 });
275 }
276 if let Some(mosi) = &mosi {
277 mosi.conf().write(|w| {
278 w.set_dir(gpiovals::Dir::OUTPUT);
279 convert_drive(w, config.mosi_drive);
280 });
281 }
282 if let Some(miso) = &miso {
283 miso.conf().write(|w| w.set_input(gpiovals::Input::CONNECT));
284 }
285
286 match config.mode.polarity {
287 Polarity::IdleHigh => {
288 if let Some(sck) = &sck {
289 sck.set_high();
290 }
291 if let Some(mosi) = &mosi {
292 mosi.set_high();
293 }
294 }
295 Polarity::IdleLow => {
296 if let Some(sck) = &sck {
297 sck.set_low();
298 }
299 if let Some(mosi) = &mosi {
300 mosi.set_low();
301 }
302 }
303 }
304
305 r.psel().sck().write_value(sck.psel_bits());
307 r.psel().mosi().write_value(mosi.psel_bits());
308 r.psel().miso().write_value(miso.psel_bits());
309
310 r.enable().write(|w| w.set_enable(vals::Enable::ENABLED));
312
313 let mut spim = Self {
314 r: T::regs(),
315 irq: T::Interrupt::IRQ,
316 state: T::state(),
317 #[cfg(feature = "_nrf54l")]
318 clk: T::clk(),
319 _p: PhantomData {},
320 };
321
322 Self::set_config(&mut spim, &config).unwrap();
324
325 r.intenclr().write(|w| w.0 = 0xFFFF_FFFF);
327
328 T::Interrupt::unpend();
329 unsafe { T::Interrupt::enable() };
330
331 spim
332 }
333
334 fn prepare_dma_transfer(&mut self, rx: *mut [u8], tx: *const [u8], offset: usize, length: usize) {
335 compiler_fence(Ordering::SeqCst);
336
337 let r = self.r;
338
339 fn xfer_params(ptr: u32, total: usize, offset: usize, length: usize) -> (u32, usize) {
340 if total > offset {
341 (ptr.wrapping_add(offset as _), core::cmp::min(total - offset, length))
342 } else {
343 (ptr, 0)
344 }
345 }
346
347 let (rx_ptr, rx_len) = xfer_params(rx as *mut u8 as _, rx.len() as _, offset, length);
349 r.dma().rx().ptr().write_value(rx_ptr);
350 r.dma().rx().maxcnt().write(|w| w.set_maxcnt(rx_len as _));
351
352 let (tx_ptr, tx_len) = xfer_params(tx as *const u8 as _, tx.len() as _, offset, length);
354 r.dma().tx().ptr().write_value(tx_ptr);
355 r.dma().tx().maxcnt().write(|w| w.set_maxcnt(tx_len as _));
356
357 #[cfg(feature = "_nrf52832_anomaly_109")]
364 if offset == 0 {
365 let s = self.state;
366
367 r.events_started().write_value(0);
368
369 r.dma().tx().maxcnt().write(|_| ());
371 r.dma().rx().maxcnt().write(|_| ());
372
373 s.tx.store(tx_len as _, Ordering::Relaxed);
375 s.rx.store(rx_len as _, Ordering::Relaxed);
376
377 r.intenset().write(|w| w.set_started(true));
379 }
380
381 r.events_end().write_value(0);
383 r.intenset().write(|w| w.set_end(true));
384
385 r.tasks_start().write_value(1);
387 }
388
389 fn blocking_inner_from_ram_chunk(&mut self, rx: *mut [u8], tx: *const [u8], offset: usize, length: usize) {
390 self.prepare_dma_transfer(rx, tx, offset, length);
391
392 #[cfg(feature = "_nrf52832_anomaly_109")]
393 if offset == 0 {
394 while self.nrf52832_dma_workaround_status().is_pending() {}
395 }
396
397 while self.r.events_end().read() == 0 {}
399
400 compiler_fence(Ordering::SeqCst);
401 }
402
403 fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
404 slice_in_ram_or(tx, Error::BufferNotInRAM)?;
405 let xfer_len = core::cmp::max(rx.len(), tx.len());
409 for offset in (0..xfer_len).step_by(EASY_DMA_SIZE) {
410 let length = core::cmp::min(xfer_len - offset, EASY_DMA_SIZE);
411 self.blocking_inner_from_ram_chunk(rx, tx, offset, length);
412 }
413 Ok(())
414 }
415
416 fn blocking_inner(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> {
417 match self.blocking_inner_from_ram(rx, tx) {
418 Ok(_) => Ok(()),
419 Err(Error::BufferNotInRAM) => {
420 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..tx.len()];
422 tx_ram_buf.copy_from_slice(tx);
423 self.blocking_inner_from_ram(rx, tx_ram_buf)
424 }
425 }
426 }
427
428 async fn async_inner_from_ram_chunk(&mut self, rx: *mut [u8], tx: *const [u8], offset: usize, length: usize) {
429 self.prepare_dma_transfer(rx, tx, offset, length);
430
431 #[cfg(feature = "_nrf52832_anomaly_109")]
432 if offset == 0 {
433 poll_fn(|cx| {
434 let s = self.state;
435
436 s.waker.register(cx.waker());
437
438 self.nrf52832_dma_workaround_status()
439 })
440 .await;
441 }
442
443 poll_fn(|cx| {
445 self.state.waker.register(cx.waker());
446 if self.r.events_end().read() != 0 {
447 return Poll::Ready(());
448 }
449
450 Poll::Pending
451 })
452 .await;
453
454 compiler_fence(Ordering::SeqCst);
455 }
456
457 async fn async_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
458 slice_in_ram_or(tx, Error::BufferNotInRAM)?;
459 let xfer_len = core::cmp::max(rx.len(), tx.len());
463 for offset in (0..xfer_len).step_by(EASY_DMA_SIZE) {
464 let length = core::cmp::min(xfer_len - offset, EASY_DMA_SIZE);
465 self.async_inner_from_ram_chunk(rx, tx, offset, length).await;
466 }
467 Ok(())
468 }
469
470 async fn async_inner(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> {
471 match self.async_inner_from_ram(rx, tx).await {
472 Ok(_) => Ok(()),
473 Err(Error::BufferNotInRAM) => {
474 let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..tx.len()];
476 tx_ram_buf.copy_from_slice(tx);
477 self.async_inner_from_ram(rx, tx_ram_buf).await
478 }
479 }
480 }
481
482 pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> {
484 self.blocking_inner(data, &[])
485 }
486
487 pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
490 self.blocking_inner(read, write)
491 }
492
493 pub fn blocking_transfer_from_ram(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
495 self.blocking_inner(read, write)
496 }
497
498 pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> {
501 self.blocking_inner_from_ram(data, data)
502 }
503
504 pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> {
507 self.blocking_inner(&mut [], data)
508 }
509
510 pub fn blocking_write_from_ram(&mut self, data: &[u8]) -> Result<(), Error> {
512 self.blocking_inner(&mut [], data)
513 }
514
515 pub async fn read(&mut self, data: &mut [u8]) -> Result<(), Error> {
517 self.async_inner(data, &[]).await
518 }
519
520 pub async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
523 self.async_inner(read, write).await
524 }
525
526 pub async fn transfer_from_ram(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
528 self.async_inner_from_ram(read, write).await
529 }
530
531 pub async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> {
533 self.async_inner_from_ram(data, data).await
534 }
535
536 pub async fn write(&mut self, data: &[u8]) -> Result<(), Error> {
539 self.async_inner(&mut [], data).await
540 }
541
542 pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<(), Error> {
544 self.async_inner_from_ram(&mut [], data).await
545 }
546
547 #[cfg(feature = "_nrf52832_anomaly_109")]
548 fn nrf52832_dma_workaround_status(&mut self) -> Poll<()> {
549 let r = self.r;
550 if r.events_started().read() != 0 {
551 let s = self.state;
552
553 r.events_started().write_value(0);
555 r.events_end().write_value(0);
556
557 r.dma()
559 .rx()
560 .maxcnt()
561 .write(|w| w.set_maxcnt(s.rx.load(Ordering::Relaxed)));
562 r.dma()
563 .tx()
564 .maxcnt()
565 .write(|w| w.set_maxcnt(s.tx.load(Ordering::Relaxed)));
566
567 r.intenset().write(|w| w.set_end(true));
568 r.tasks_start().write_value(1);
570 return Poll::Ready(());
571 }
572 Poll::Pending
573 }
574}
575
576impl<'d> Drop for Spim<'d> {
577 fn drop(&mut self) {
578 trace!("spim drop");
579
580 let r = self.r;
584 r.enable().write(|w| w.set_enable(vals::Enable::DISABLED));
585
586 gpio::deconfigure_pin(r.psel().sck().read());
587 gpio::deconfigure_pin(r.psel().miso().read());
588 gpio::deconfigure_pin(r.psel().mosi().read());
589
590 cortex_m::peripheral::NVIC::mask(self.irq);
592
593 trace!("spim drop: done");
594 }
595}
596
597pub(crate) struct State {
598 waker: AtomicWaker,
599 #[cfg(feature = "_nrf52832_anomaly_109")]
600 rx: AtomicU8,
601 #[cfg(feature = "_nrf52832_anomaly_109")]
602 tx: AtomicU8,
603}
604
605impl State {
606 pub(crate) const fn new() -> Self {
607 Self {
608 waker: AtomicWaker::new(),
609 #[cfg(feature = "_nrf52832_anomaly_109")]
610 rx: AtomicU8::new(0),
611 #[cfg(feature = "_nrf52832_anomaly_109")]
612 tx: AtomicU8::new(0),
613 }
614 }
615}
616
617pub(crate) trait SealedInstance {
618 fn regs() -> pac::spim::Spim;
619 fn state() -> &'static State;
620 #[cfg(feature = "_nrf54l")]
621 fn clk() -> u32;
622}
623
624#[allow(private_bounds)]
626pub trait Instance: SealedInstance + PeripheralType + 'static {
627 type Interrupt: interrupt::typelevel::Interrupt;
629}
630
631#[cfg(feature = "_nrf54l")]
632macro_rules! impl_spim {
633 ($type:ident, $pac_type:ident, $irq:ident, $clk:expr) => {
634 impl crate::spim::SealedInstance for peripherals::$type {
635 fn regs() -> pac::spim::Spim {
636 pac::$pac_type
637 }
638 fn state() -> &'static crate::spim::State {
639 static STATE: crate::spim::State = crate::spim::State::new();
640 &STATE
641 }
642 fn clk() -> u32 {
643 $clk
644 }
645 }
646 impl crate::spim::Instance for peripherals::$type {
647 type Interrupt = crate::interrupt::typelevel::$irq;
648 }
649 };
650}
651
652#[cfg(not(feature = "_nrf54l"))]
653macro_rules! impl_spim {
654 ($type:ident, $pac_type:ident, $irq:ident) => {
655 impl crate::spim::SealedInstance for peripherals::$type {
656 fn regs() -> pac::spim::Spim {
657 pac::$pac_type
658 }
659 fn state() -> &'static crate::spim::State {
660 static STATE: crate::spim::State = crate::spim::State::new();
661 &STATE
662 }
663 }
664 impl crate::spim::Instance for peripherals::$type {
665 type Interrupt = crate::interrupt::typelevel::$irq;
666 }
667 };
668}
669
670mod eh02 {
673 use super::*;
674
675 impl<'d> embedded_hal_02::blocking::spi::Transfer<u8> for Spim<'d> {
676 type Error = Error;
677 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
678 self.blocking_transfer_in_place(words)?;
679 Ok(words)
680 }
681 }
682
683 impl<'d> embedded_hal_02::blocking::spi::Write<u8> for Spim<'d> {
684 type Error = Error;
685
686 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
687 self.blocking_write(words)
688 }
689 }
690}
691
692impl embedded_hal_1::spi::Error for Error {
693 fn kind(&self) -> embedded_hal_1::spi::ErrorKind {
694 match *self {
695 Self::BufferNotInRAM => embedded_hal_1::spi::ErrorKind::Other,
696 }
697 }
698}
699
700impl<'d> embedded_hal_1::spi::ErrorType for Spim<'d> {
701 type Error = Error;
702}
703
704impl<'d> embedded_hal_1::spi::SpiBus<u8> for Spim<'d> {
705 fn flush(&mut self) -> Result<(), Self::Error> {
706 Ok(())
707 }
708
709 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
710 self.blocking_transfer(words, &[])
711 }
712
713 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
714 self.blocking_write(words)
715 }
716
717 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
718 self.blocking_transfer(read, write)
719 }
720
721 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
722 self.blocking_transfer_in_place(words)
723 }
724}
725
726impl<'d> embedded_hal_async::spi::SpiBus<u8> for Spim<'d> {
727 async fn flush(&mut self) -> Result<(), Error> {
728 Ok(())
729 }
730
731 async fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
732 self.read(words).await
733 }
734
735 async fn write(&mut self, data: &[u8]) -> Result<(), Error> {
736 self.write(data).await
737 }
738
739 async fn transfer(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> {
740 self.transfer(rx, tx).await
741 }
742
743 async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
744 self.transfer_in_place(words).await
745 }
746}
747
748impl<'d> SetConfig for Spim<'d> {
749 type Config = Config;
750 type ConfigError = ();
751 fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
752 let r = self.r;
753 let mode = config.mode;
755 r.config().write(|w| {
756 w.set_order(config.bit_order);
757 match mode {
758 MODE_0 => {
759 w.set_cpol(vals::Cpol::ACTIVE_HIGH);
760 w.set_cpha(vals::Cpha::LEADING);
761 }
762 MODE_1 => {
763 w.set_cpol(vals::Cpol::ACTIVE_HIGH);
764 w.set_cpha(vals::Cpha::TRAILING);
765 }
766 MODE_2 => {
767 w.set_cpol(vals::Cpol::ACTIVE_LOW);
768 w.set_cpha(vals::Cpha::LEADING);
769 }
770 MODE_3 => {
771 w.set_cpol(vals::Cpol::ACTIVE_LOW);
772 w.set_cpha(vals::Cpha::TRAILING);
773 }
774 }
775 });
776
777 let frequency = config.frequency;
779 #[cfg(not(feature = "_nrf54l"))]
780 r.frequency().write(|w| w.set_frequency(frequency.into()));
781 #[cfg(feature = "_nrf54l")]
782 {
783 r.prescaler().write(|w| w.set_divisor(frequency.to_divisor(self.clk)));
784 }
785
786 let orc = config.orc;
788 r.orc().write(|w| w.set_orc(orc));
789
790 Ok(())
791 }
792}