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 Peripheral, 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(context = "stm32f401re")]
24const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(21);
25#[cfg(context = "stm32f411re")]
26const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(25);
27#[cfg(any(context = "stm32h755zi", context = "stm32h753zi"))]
28const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(150);
29#[cfg(context = "stm32l475vg")]
30const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(40);
31#[cfg(any(context = "stm32u073kc", context = "stm32u083mc"))]
32const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(32);
33#[cfg(context = "stm32u585ai")]
36const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(80);
37#[cfg(context = "stm32wb55rg")]
38const MAX_FREQUENCY: Kilohertz = Kilohertz::MHz(32);
39
40#[derive(Clone)]
42#[non_exhaustive]
43pub struct Config {
44 pub frequency: Frequency,
46 pub mode: Mode,
48 #[doc(hidden)]
49 pub bit_order: BitOrder,
50}
51
52impl Default for Config {
53 fn default() -> Self {
54 Self {
55 frequency: Frequency::F(Kilohertz::MHz(1)),
56 mode: Mode::Mode0,
57 bit_order: BitOrder::default(),
58 }
59 }
60}
61
62#[derive(Debug, Copy, Clone, PartialEq, Eq)]
64#[cfg_attr(feature = "defmt", derive(defmt::Format))]
65#[repr(u32)]
66pub enum Frequency {
67 F(Kilohertz),
69}
70
71impl From<Frequency> for Hertz {
72 fn from(freq: Frequency) -> Self {
73 match freq {
74 Frequency::F(kilohertz) => Hertz::khz(kilohertz.to_kHz()),
75 }
76 }
77}
78
79ariel_os_embassy_common::impl_spi_from_frequency!();
80ariel_os_embassy_common::impl_spi_frequency_const_functions!(MAX_FREQUENCY);
81
82macro_rules! define_spi_drivers {
83 ($( $interrupt:ident => $peripheral:ident ),* $(,)?) => {
84 $(
85 pub struct $peripheral {
87 spim: YieldingAsync<BlockingAsync<InnerSpi<'static, Blocking>>>,
88 }
89
90 impl $peripheral {
91 #[expect(clippy::new_ret_no_self)]
94 #[must_use]
95 pub fn new(
96 sck_pin: impl Peripheral<P: SckPin<peripherals::$peripheral>> + 'static,
97 miso_pin: impl Peripheral<P: MisoPin<peripherals::$peripheral>> + 'static,
98 mosi_pin: impl Peripheral<P: MosiPin<peripherals::$peripheral>> + 'static,
99 config: Config,
100 ) -> Spi {
101 paste::paste! {
104 #[allow(dead_code)]
105 static [<PREVENT_MULTIPLE_ $peripheral>]: () = ();
106 }
107
108 let mut spi_config = embassy_stm32::spi::Config::default();
109 spi_config.frequency = config.frequency.into();
110 spi_config.mode = crate::spi::from_mode(config.mode);
111 spi_config.bit_order = crate::spi::from_bit_order(config.bit_order);
112 spi_config.miso_pull = gpio::Pull::None;
113
114 let spim_peripheral = unsafe { peripherals::$peripheral::steal() };
118
119 let spim = InnerSpi::new_blocking(
121 spim_peripheral,
122 sck_pin,
123 mosi_pin,
124 miso_pin,
125 spi_config,
126 );
127
128 Spi::$peripheral(Self { spim: YieldingAsync::new(BlockingAsync::new(spim)) })
129 }
130 }
131 )*
132
133 pub enum Spi {
135 $(
136 #[doc = concat!(stringify!($peripheral), " peripheral.")]
137 $peripheral($peripheral)
138 ),*
139 }
140
141 impl embedded_hal_async::spi::ErrorType for Spi {
142 type Error = embassy_stm32::spi::Error;
143 }
144
145 impl_async_spibus_for_driver_enum!(Spi, $( $peripheral ),*);
146 };
147}
148
149#[cfg(context = "stm32c031c6")]
151define_spi_drivers!(
152 SPI1 => SPI1,
153);
154#[cfg(context = "stm32f401re")]
155define_spi_drivers!(
156 SPI1 => SPI1,
157 SPI2 => SPI2,
158 SPI3 => SPI3,
159);
160#[cfg(context = "stm32f411re")]
161define_spi_drivers!(
162 SPI1 => SPI1,
163 SPI2 => SPI2,
164 SPI3 => SPI3,
165 SPI4 => SPI4,
166 SPI5 => SPI5,
167);
168#[cfg(any(context = "stm32h755zi", context = "stm32h753zi"))]
169define_spi_drivers!(
170 SPI1 => SPI1,
171 SPI2 => SPI2,
172 SPI3 => SPI3,
173 SPI4 => SPI4,
174 SPI5 => SPI5,
175 SPI6 => SPI6,
176);
177#[cfg(context = "stm32l475vg")]
178define_spi_drivers!(
179 SPI1 => SPI1,
180 SPI2 => SPI2,
181 SPI3 => SPI3,
182);
183#[cfg(any(context = "stm32u073kc", context = "stm32u083mc"))]
184define_spi_drivers!(
185 SPI1 => SPI1,
186 );
188#[cfg(context = "stm32u585ai")]
189define_spi_drivers!(
190 SPI1 => SPI1,
191 SPI2 => SPI2,
192 SPI3 => SPI3,
193);
194#[cfg(context = "stm32wb55rg")]
195define_spi_drivers!(
196 SPI1 => SPI1,
197 SPI2 => SPI2,
198);