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 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: ClkPin<peripherals::$peripheral>,
76 MISO: MisoPin<peripherals::$peripheral>,
77 MOSI: MosiPin<peripherals::$peripheral>
78 >(
79 sck_pin: impl $crate::IntoPeripheral<'static, SCK>,
80 miso_pin: impl $crate::IntoPeripheral<'static, MISO>,
81 mosi_pin: impl $crate::IntoPeripheral<'static, MOSI>,
82 config: Config,
83 ) -> Spi {
84 paste::paste! {
87 #[allow(dead_code)]
88 static [<PREVENT_MULTIPLE_ $peripheral>]: () = ();
89 }
90
91 let (pol, phase) = crate::spi::from_mode(config.mode);
92
93 let mut spi_config = embassy_rp::spi::Config::default();
94 spi_config.frequency = config.frequency.as_hz();
95 spi_config.polarity = pol;
96 spi_config.phase = phase;
97
98 let spi_peripheral = unsafe { peripherals::$peripheral::steal() };
102
103 let spi = InnerSpi::new_blocking(
105 spi_peripheral,
106 sck_pin.into_hal_peripheral(),
107 mosi_pin.into_hal_peripheral(),
108 miso_pin.into_hal_peripheral(),
109 spi_config,
110 );
111
112 Spi::$peripheral(Self { spim: YieldingAsync::new(BlockingAsync::new(spi)) })
113 }
114 }
115 )*
116
117 pub enum Spi {
119 $(
120 #[doc = concat!(stringify!($peripheral), " peripheral.")]
121 $peripheral($peripheral)
122 ),*
123 }
124
125 impl embedded_hal_async::spi::ErrorType for Spi {
126 type Error = embassy_rp::spi::Error;
127 }
128
129 impl_async_spibus_for_driver_enum!(Spi, $( $peripheral ),*);
130 };
131}
132
133define_spi_drivers!(SPI0, SPI1);