ariel_os_stm32/spi/main/
mod.rs1#![expect(unsafe_code)]
4
5use ariel_os_embassy_common::{
6 impl_async_spibus_for_driver_enum,
7 spi::{BitOrder, Mode, main::Kilohertz},
8};
9use embassy_embedded_hal::adapter::{BlockingAsync, YieldingAsync};
10use embassy_stm32::{
11 gpio,
12 mode::Blocking,
13 peripherals,
14 spi::{MisoPin, MosiPin, SckPin, Spi as InnerSpi},
15 time::Hertz,
16};
17
18#[cfg(context = "stm32c031c6")]
22const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(24);
23#[cfg(any(context = "stm32f303cb", context = "stm32f303re"))]
24const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(18);
25#[cfg(context = "stm32f401re")]
26const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(21);
27#[cfg(context = "stm32f411re")]
28const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(25);
29#[cfg(any(context = "stm32h755zi", context = "stm32h753zi"))]
30const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(150);
31#[cfg(context = "stm32l475vg")]
32const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(40);
33#[cfg(any(context = "stm32u073kc", context = "stm32u083mc"))]
34const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(32);
35#[cfg(context = "stm32u585ai")]
38const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(80);
39#[cfg(context = "stm32wb55rg")]
40const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(32);
41
42#[derive(Clone)]
44#[non_exhaustive]
45pub struct Config {
46 pub frequency: Frequency,
48 pub mode: Mode,
50 #[doc(hidden)]
51 pub bit_order: BitOrder,
52}
53
54impl Default for Config {
55 fn default() -> Self {
56 Self {
57 frequency: Frequency::F(Kilohertz::MHz(1)),
58 mode: Mode::Mode0,
59 bit_order: BitOrder::default(),
60 }
61 }
62}
63
64#[derive(Debug, Copy, Clone, PartialEq, Eq)]
66#[cfg_attr(feature = "defmt", derive(defmt::Format))]
67#[repr(u32)]
68pub enum Frequency {
69 F(Kilohertz),
71}
72
73impl From<Frequency> for Hertz {
74 fn from(freq: Frequency) -> Self {
75 match freq {
76 Frequency::F(kilohertz) => Hertz::khz(kilohertz.to_kHz()),
77 }
78 }
79}
80
81ariel_os_embassy_common::impl_spi_from_frequency!();
82ariel_os_embassy_common::impl_spi_frequency_const_functions!(MAX_FREQUENCY);
83
84macro_rules! define_spi_drivers {
85 ($( $interrupt:ident => $peripheral:ident ),* $(,)?) => {
86 $(
87 pub struct $peripheral {
89 spim: YieldingAsync<BlockingAsync<InnerSpi<'static, Blocking>>>,
90 }
91
92 impl $peripheral {
93 #[expect(clippy::new_ret_no_self)]
96 #[must_use]
97 pub fn new<
98 SCK: SckPin<peripherals::$peripheral>,
99 MISO: MisoPin<peripherals::$peripheral>,
100 MOSI: MosiPin<peripherals::$peripheral>,
101 >(
102 sck_pin: impl $crate::IntoPeripheral<'static, SCK>,
103 miso_pin: impl $crate::IntoPeripheral<'static, MISO>,
104 mosi_pin: impl $crate::IntoPeripheral<'static, MOSI>,
105 config: Config,
106 ) -> Spi {
107 paste::paste! {
110 #[allow(dead_code)]
111 static [<PREVENT_MULTIPLE_ $peripheral>]: () = ();
112 }
113
114 let mut spi_config = embassy_stm32::spi::Config::default();
115 spi_config.frequency = config.frequency.into();
116 spi_config.mode = crate::spi::from_mode(config.mode);
117 spi_config.bit_order = crate::spi::from_bit_order(config.bit_order);
118 spi_config.miso_pull = gpio::Pull::None;
119
120 let spim_peripheral = unsafe { peripherals::$peripheral::steal() };
124
125 let spim = InnerSpi::new_blocking(
127 spim_peripheral,
128 sck_pin.into_hal_peripheral(),
129 mosi_pin.into_hal_peripheral(),
130 miso_pin.into_hal_peripheral(),
131 spi_config,
132 );
133
134 Spi::$peripheral(Self { spim: YieldingAsync::new(BlockingAsync::new(spim)) })
135 }
136 }
137 )*
138
139 pub enum Spi {
141 $(
142 #[doc = concat!(stringify!($peripheral), " peripheral.")]
143 $peripheral($peripheral)
144 ),*
145 }
146
147 impl embedded_hal_async::spi::ErrorType for Spi {
148 type Error = embassy_stm32::spi::Error;
149 }
150
151 impl_async_spibus_for_driver_enum!(Spi, $( $peripheral ),*);
152 };
153}
154
155#[cfg(context = "stm32c031c6")]
157define_spi_drivers!(
158 SPI1 => SPI1,
159);
160#[cfg(context = "stm32f303cb")]
161define_spi_drivers!(
162 SPI1 => SPI1,
163 SPI2 => SPI2,
164 SPI3 => SPI3,
165);
166#[cfg(context = "stm32f303re")]
167define_spi_drivers!(
168 SPI1 => SPI1,
169 SPI2 => SPI2,
170 SPI3 => SPI3,
171 );
173#[cfg(context = "stm32f401re")]
174define_spi_drivers!(
175 SPI1 => SPI1,
176 SPI2 => SPI2,
177 SPI3 => SPI3,
178);
179#[cfg(context = "stm32f411re")]
180define_spi_drivers!(
181 SPI1 => SPI1,
182 SPI2 => SPI2,
183 SPI3 => SPI3,
184 SPI4 => SPI4,
185 SPI5 => SPI5,
186);
187#[cfg(any(context = "stm32h755zi", context = "stm32h753zi"))]
188define_spi_drivers!(
189 SPI1 => SPI1,
190 SPI2 => SPI2,
191 SPI3 => SPI3,
192 SPI4 => SPI4,
193 SPI5 => SPI5,
194 SPI6 => SPI6,
195);
196#[cfg(context = "stm32l475vg")]
197define_spi_drivers!(
198 SPI1 => SPI1,
199 SPI2 => SPI2,
200 SPI3 => SPI3,
201);
202#[cfg(any(context = "stm32u073kc", context = "stm32u083mc"))]
203define_spi_drivers!(
204 SPI1 => SPI1,
205 );
207#[cfg(context = "stm32u585ai")]
208define_spi_drivers!(
209 SPI1 => SPI1,
210 SPI2 => SPI2,
211 SPI3 => SPI3,
212);
213#[cfg(context = "stm32wb55rg")]
214define_spi_drivers!(
215 SPI1 => SPI1,
216 SPI2 => SPI2,
217);