ariel_os_nrf/spi/main/
mod.rs
1use ariel_os_embassy_common::{
4 impl_async_spibus_for_driver_enum,
5 spi::{BitOrder, Mode},
6};
7
8use embassy_nrf::{
9 bind_interrupts,
10 gpio::Pin as GpioPin,
11 peripherals,
12 spim::{InterruptHandler, Spim},
13 Peripheral,
14};
15
16#[derive(Clone)]
18#[non_exhaustive]
19pub struct Config {
20 pub frequency: Frequency,
22 pub mode: Mode,
24 #[doc(hidden)]
25 pub bit_order: BitOrder,
26}
27
28impl Default for Config {
29 fn default() -> Self {
30 Self {
31 frequency: Frequency::_1M,
32 mode: Mode::Mode0,
33 bit_order: BitOrder::default(),
34 }
35 }
36}
37
38#[derive(Debug, Copy, Clone, PartialEq, Eq)]
41#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42#[repr(u32)]
43pub enum Frequency {
44 _125k,
46 _250k,
48 _500k,
50 _1M,
52 _2M,
54 _4M,
56 _8M,
58 }
65
66#[doc(hidden)]
67impl Frequency {
68 pub const fn first() -> Self {
69 Self::_125k
70 }
71
72 pub const fn last() -> Self {
73 Self::_8M
74 }
75
76 pub const fn next(self) -> Option<Self> {
77 match self {
78 Self::_125k => Some(Self::_250k),
79 Self::_250k => Some(Self::_500k),
80 Self::_500k => Some(Self::_1M),
81 Self::_1M => Some(Self::_2M),
82 Self::_2M => Some(Self::_4M),
83 Self::_4M => Some(Self::_8M),
84 Self::_8M => None,
85 }
86 }
87
88 pub const fn prev(self) -> Option<Self> {
89 match self {
90 Self::_125k => None,
91 Self::_250k => Some(Self::_125k),
92 Self::_500k => Some(Self::_250k),
93 Self::_1M => Some(Self::_500k),
94 Self::_2M => Some(Self::_1M),
95 Self::_4M => Some(Self::_2M),
96 Self::_8M => Some(Self::_4M),
97 }
98 }
99
100 pub const fn khz(self) -> u32 {
101 match self {
102 Self::_125k => 125,
103 Self::_250k => 250,
104 Self::_500k => 500,
105 Self::_1M => 1000,
106 Self::_2M => 2000,
107 Self::_4M => 4000,
108 Self::_8M => 8000,
109 }
110 }
111}
112
113impl From<ariel_os_embassy_common::spi::main::Frequency> for Frequency {
114 fn from(freq: ariel_os_embassy_common::spi::main::Frequency) -> Self {
115 match freq {
116 ariel_os_embassy_common::spi::main::Frequency::_125k => Self::_125k,
117 ariel_os_embassy_common::spi::main::Frequency::_250k => Self::_250k,
118 ariel_os_embassy_common::spi::main::Frequency::_500k => Self::_500k,
119 ariel_os_embassy_common::spi::main::Frequency::_1M => Self::_1M,
120 ariel_os_embassy_common::spi::main::Frequency::_2M => Self::_2M,
121 ariel_os_embassy_common::spi::main::Frequency::_4M => Self::_4M,
122 ariel_os_embassy_common::spi::main::Frequency::_8M => Self::_8M,
123 }
124 }
125}
126
127impl From<Frequency> for embassy_nrf::spim::Frequency {
128 fn from(freq: Frequency) -> Self {
129 match freq {
130 Frequency::_125k => embassy_nrf::spim::Frequency::K125,
131 Frequency::_250k => embassy_nrf::spim::Frequency::K250,
132 Frequency::_500k => embassy_nrf::spim::Frequency::K500,
133 Frequency::_1M => embassy_nrf::spim::Frequency::M1,
134 Frequency::_2M => embassy_nrf::spim::Frequency::M2,
135 Frequency::_4M => embassy_nrf::spim::Frequency::M4,
136 Frequency::_8M => embassy_nrf::spim::Frequency::M8,
137 }
138 }
139}
140
141macro_rules! define_spi_drivers {
142 ($( $interrupt:ident => $peripheral:ident ),* $(,)?) => {
143 $(
144 pub struct $peripheral {
146 spim: Spim<'static, peripherals::$peripheral>,
147 }
148
149 impl $peripheral {
150 #[expect(clippy::new_ret_no_self)]
153 #[must_use]
154 pub fn new(
155 sck_pin: impl Peripheral<P: GpioPin> + 'static,
156 miso_pin: impl Peripheral<P: GpioPin> + 'static,
157 mosi_pin: impl Peripheral<P: GpioPin> + 'static,
158 config: Config,
159 ) -> Spi {
160 let mut spi_config = embassy_nrf::spim::Config::default();
161 spi_config.frequency = config.frequency.into();
162 spi_config.mode = crate::spi::from_mode(config.mode);
163 spi_config.bit_order = crate::spi::from_bit_order(config.bit_order);
164
165 bind_interrupts!(
166 struct Irqs {
167 $interrupt => InterruptHandler<peripherals::$peripheral>;
168 }
169 );
170
171 paste::paste! {
174 #[allow(dead_code)]
175 static [<PREVENT_MULTIPLE_ $peripheral>]: () = ();
176 }
177
178 let spim_peripheral = unsafe { peripherals::$peripheral::steal() };
182
183 let spim = Spim::new(
184 spim_peripheral,
185 Irqs,
186 sck_pin,
187 miso_pin,
188 mosi_pin,
189 spi_config,
190 );
191
192 Spi::$peripheral(Self { spim })
193 }
194 }
195 )*
196
197 pub enum Spi {
199 $(
200 #[doc = concat!(stringify!($peripheral), " peripheral.")]
201 $peripheral($peripheral)
202 ),*
203 }
204
205 impl embedded_hal_async::spi::ErrorType for Spi {
206 type Error = embassy_nrf::spim::Error;
207 }
208
209 impl_async_spibus_for_driver_enum!(Spi, $( $peripheral ),*);
210 };
211}
212
213#[cfg(context = "nrf52833")]
215define_spi_drivers!(
216 SPIM3 => SPI3,
221);
222#[cfg(context = "nrf52840")]
223define_spi_drivers!(
224 SPIM3 => SPI3,
229);
230#[cfg(context = "nrf5340")]
232define_spi_drivers!(
233 SERIAL2 => SERIAL2,
234 SERIAL3 => SERIAL3,
235);