ariel_os_rp/spi/main/
mod.rs1#![expect(unsafe_code)]
4
5use ariel_os_embassy_common::{
6 impl_async_spibus_for_driver_enum,
7 spi::{Mode, main::Kilohertz},
8};
9use embassy_embedded_hal::adapter::{BlockingAsync, YieldingAsync};
10use embassy_rp::{
11 Peripheral, peripherals,
12 spi::{Blocking, ClkPin, MisoPin, MosiPin, Spi as InnerSpi},
13};
14
15#[cfg(context = "rp2040")]
18const MAX_FREQUENCY: Kilohertz = Kilohertz::kHz(62_500);
19#[cfg(context = "rp235xa")]
20const MAX_FREQUENCY: Kilohertz = Kilohertz::kHz(70_500);
21
22#[derive(Clone)]
24#[non_exhaustive]
25pub struct Config {
26 pub frequency: Frequency,
28 pub mode: Mode,
30}
31
32impl Default for Config {
33 fn default() -> Self {
34 Self {
35 frequency: Frequency::F(Kilohertz::MHz(1)),
36 mode: Mode::Mode0,
37 }
38 }
39}
40
41#[derive(Debug, Copy, Clone, PartialEq, Eq)]
43#[cfg_attr(feature = "defmt", derive(defmt::Format))]
44#[repr(u32)]
45pub enum Frequency {
46 F(Kilohertz),
48}
49
50ariel_os_embassy_common::impl_spi_from_frequency!();
51ariel_os_embassy_common::impl_spi_frequency_const_functions!(MAX_FREQUENCY);
52
53impl Frequency {
54 fn as_hz(self) -> u32 {
55 match self {
56 Self::F(kilohertz) => kilohertz.to_Hz(),
57 }
58 }
59}
60
61macro_rules! define_spi_drivers {
62 ($( $peripheral:ident ),* $(,)?) => {
63 $(
64 pub struct $peripheral {
66 spim: YieldingAsync<BlockingAsync<InnerSpi<'static, peripherals::$peripheral, Blocking>>>,
67 }
68
69 impl $peripheral {
70 #[expect(clippy::new_ret_no_self)]
73 #[must_use]
74 pub fn new(
75 sck_pin: impl Peripheral<P: ClkPin<peripherals::$peripheral>> + 'static,
76 miso_pin: impl Peripheral<P: MisoPin<peripherals::$peripheral>> + 'static,
77 mosi_pin: impl Peripheral<P: MosiPin<peripherals::$peripheral>> + 'static,
78 config: Config,
79 ) -> Spi {
80 paste::paste! {
83 #[allow(dead_code)]
84 static [<PREVENT_MULTIPLE_ $peripheral>]: () = ();
85 }
86
87 let (pol, phase) = crate::spi::from_mode(config.mode);
88
89 let mut spi_config = embassy_rp::spi::Config::default();
90 spi_config.frequency = config.frequency.as_hz();
91 spi_config.polarity = pol;
92 spi_config.phase = phase;
93
94 let spi_peripheral = unsafe { peripherals::$peripheral::steal() };
98
99 let spi = InnerSpi::new_blocking(
101 spi_peripheral,
102 sck_pin,
103 mosi_pin,
104 miso_pin,
105 spi_config,
106 );
107
108 Spi::$peripheral(Self { spim: YieldingAsync::new(BlockingAsync::new(spi)) })
109 }
110 }
111 )*
112
113 pub enum Spi {
115 $(
116 #[doc = concat!(stringify!($peripheral), " peripheral.")]
117 $peripheral($peripheral)
118 ),*
119 }
120
121 impl embedded_hal_async::spi::ErrorType for Spi {
122 type Error = embassy_rp::spi::Error;
123 }
124
125 impl_async_spibus_for_driver_enum!(Spi, $( $peripheral ),*);
126 };
127}
128
129define_spi_drivers!(SPI0, SPI1);