1use crate::{
2 async_hal::interrupts::{Binding, Handler, InterruptSource},
3 sercom::{
4 spi::{
5 Capability, Config, DataWidth, Duplex, Error, Flags, MasterMode, OpMode, Rx, Size, Spi,
6 Tx, ValidConfig, ValidPads,
7 },
8 Sercom,
9 },
10 typelevel::NoneT,
11};
12use atsamd_hal_macros::hal_macro_helper;
13use core::{marker::PhantomData, task::Poll};
14use embedded_hal_async::spi::{ErrorType, SpiBus};
15use num_traits::{AsPrimitive, PrimInt};
16
17#[cfg(feature = "dma")]
18mod dma;
19#[cfg(feature = "dma")]
20pub use dma::*;
21
22use super::{Receive, Slave, Transmit};
23
24pub struct InterruptHandler<S: Sercom> {
26 _private: (),
27 _sercom: PhantomData<S>,
28}
29
30impl<S: Sercom> crate::typelevel::Sealed for InterruptHandler<S> {}
31
32impl<S: Sercom> Handler<S::Interrupt> for InterruptHandler<S> {
33 #[inline]
34 #[hal_macro_helper]
35 unsafe fn on_interrupt() {
36 unsafe {
37 let mut peripherals = crate::pac::Peripherals::steal();
38
39 #[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
40 let spi = S::reg_block(&mut peripherals).spi();
41 #[hal_cfg("sercom0-d5x")]
42 let spi = S::reg_block(&mut peripherals).spim();
43
44 let flags_pending = Flags::from_bits_truncate(spi.intflag().read().bits());
45 let enabled_flags = Flags::from_bits_truncate(spi.intenset().read().bits());
46
47 if (Flags::RX & enabled_flags).intersects(flags_pending) {
50 spi.intenclr().write(|w| w.bits(flags_pending.bits()));
51 S::rx_waker().wake();
52 }
53
54 if (Flags::TX & enabled_flags).intersects(flags_pending) {
55 spi.intenclr().write(|w| w.bits(flags_pending.bits()));
56 S::tx_waker().wake();
57 }
58 }
59 }
60}
61
62impl<C, A, S> Spi<C, A>
63where
64 C: ValidConfig<Sercom = S>,
65 A: Capability,
66 S: Sercom,
67{
68 #[inline]
74 pub fn into_future<I>(self, _interrupts: I) -> SpiFuture<C, A>
75 where
76 C::Word: Copy,
77 u8: AsPrimitive<C::Word>,
78 I: Binding<S::Interrupt, InterruptHandler<S>>,
79 {
80 S::Interrupt::unpend();
81 unsafe { S::Interrupt::enable() };
82
83 SpiFuture { spi: self }
84 }
85}
86
87pub struct SpiFuture<C, A, R = NoneT, T = NoneT>
91where
92 C: ValidConfig,
93 A: Capability,
94{
95 spi: Spi<C, A, R, T>,
96}
97
98#[cfg(feature = "defmt")]
99impl<C, A, R, T> defmt::Format for SpiFuture<C, A, R, T>
100where
101 C: ValidConfig,
102 A: Capability,
103{
104 fn format(&self, f: defmt::Formatter) {
105 defmt::write!(f, "SpiFuture defmt shim\n");
106 }
107}
108
109pub type SpiFutureDuplex<C> = SpiFuture<C, Duplex>;
111
112pub type SpiFutureRx<C> = SpiFuture<C, Rx>;
114
115pub type SpiFutureTx<C> = SpiFuture<C, Tx>;
117
118impl<C, A, S, R, T> SpiFuture<C, A, R, T>
119where
120 C: ValidConfig<Sercom = S>,
121 A: Capability,
122 S: Sercom,
123{
124 #[inline]
125 async fn wait_flags(&mut self, flags_to_wait: Flags) -> Result<(), Error> {
126 let flags_to_wait = flags_to_wait | Flags::ERROR;
127
128 core::future::poll_fn(|cx| {
129 {
131 let maybe_pending = self.spi.config.as_ref().regs.read_flags();
132 if flags_to_wait.intersects(maybe_pending) {
133 return Poll::Ready(self.spi.check_and_clear_error(maybe_pending));
134 }
135 }
136
137 self.spi.disable_interrupts(Flags::all());
138
139 if flags_to_wait.intersects(Flags::RX) {
140 S::rx_waker().register(cx.waker());
141 }
142 if flags_to_wait.intersects(Flags::TX) {
143 S::tx_waker().register(cx.waker());
144 }
145
146 self.spi.enable_interrupts(flags_to_wait);
147 let maybe_pending = self.spi.config.as_ref().regs.read_flags();
148
149 if !flags_to_wait.intersects(maybe_pending) {
150 Poll::Pending
151 } else {
152 Poll::Ready(self.spi.check_and_clear_error(maybe_pending))
153 }
154 })
155 .await?;
156
157 Ok(())
158 }
159}
160
161impl<C, D> SpiFuture<C, D, NoneT, NoneT>
162where
163 C: ValidConfig,
164 D: Capability,
165{
166 pub fn free(self) -> Spi<C, D> {
168 self.spi
169 }
170}
171
172impl<P, M, C, D, R, S> SpiFuture<Config<P, M, C>, D, R, NoneT>
173where
174 Config<P, M, C>: ValidConfig<Sercom = S>,
175 P: ValidPads,
176 M: OpMode,
177 C: Size + 'static,
178 C::Word: PrimInt + AsPrimitive<DataWidth>,
179 D: Transmit,
180 DataWidth: AsPrimitive<C::Word>,
181 S: Sercom,
182{
183 #[inline]
185 pub async fn write(&mut self, words: &[C::Word]) -> Result<(), Error> {
186 if words.is_empty() {
187 return Ok(());
188 }
189 for word in words {
191 let _ = self.transfer_word_in_place(*word).await?;
192 }
193
194 Ok(())
195 }
196}
197
198impl<P, M, C, D, T, S> SpiFuture<Config<P, M, C>, D, NoneT, T>
199where
200 Config<P, M, C>: ValidConfig<Sercom = S>,
201 P: ValidPads,
202 M: MasterMode,
203 C: Size + 'static,
204 C::Word: PrimInt + AsPrimitive<DataWidth>,
205 D: Receive,
206 DataWidth: AsPrimitive<C::Word>,
207 S: Sercom,
208{
209 #[inline]
215 pub async fn read(&mut self, buffer: &mut [C::Word]) -> Result<(), Error> {
216 if buffer.is_empty() {
217 return Ok(());
218 }
219
220 let nop_word = self.spi.config.as_ref().nop_word.as_();
221 for byte in buffer.iter_mut() {
222 *byte = self.transfer_word_in_place(nop_word).await?;
223 }
224
225 Ok(())
226 }
227}
228
229impl<P, M, C, S, D, R, T> SpiFuture<Config<P, M, C>, D, R, T>
230where
231 Config<P, M, C>: ValidConfig<Sercom = S>,
232 P: ValidPads,
233 M: OpMode,
234 C: Size + 'static,
235 C::Word: PrimInt + AsPrimitive<DataWidth>,
236 DataWidth: AsPrimitive<C::Word>,
237 D: Capability,
238 S: Sercom,
239{
240 pub async fn transfer_word_in_place(&mut self, to_send: C::Word) -> Result<C::Word, Error> {
242 self.wait_flags(Flags::DRE).await?;
243 unsafe {
244 self.spi.write_data(to_send.as_());
245 }
246
247 self.flush_rx().await?;
248 let word = unsafe { self.spi.read_data().as_() };
249
250 Ok(word)
251 }
252
253 async fn transfer_word_by_word(
258 &mut self,
259 read: &mut [C::Word],
260 write: &[C::Word],
261 ) -> Result<(), Error> {
262 let nop_word = self.spi.config.as_ref().nop_word.as_();
263 for (r, w) in read
264 .iter_mut()
265 .zip(write.iter().chain(core::iter::repeat(&nop_word)))
266 {
267 *r = self.transfer_word_in_place(*w).await?;
268 }
269
270 Ok(())
271 }
272
273 #[inline]
275 async fn flush_tx(&mut self) {
276 let _ = self.wait_flags(Flags::TXC).await;
278 }
279
280 #[inline]
282 async fn flush_rx(&mut self) -> Result<(), Error> {
283 self.wait_flags(Flags::RXC).await
284 }
285}
286
287impl<C, A, R, T> AsRef<Spi<C, A, R, T>> for SpiFuture<C, A, R, T>
288where
289 C: ValidConfig,
290 A: Capability,
291{
292 #[inline]
293 fn as_ref(&self) -> &Spi<C, A, R, T> {
294 &self.spi
295 }
296}
297
298impl<C, A, R, T> AsMut<Spi<C, A, R, T>> for SpiFuture<C, A, R, T>
299where
300 C: ValidConfig,
301 A: Capability,
302{
303 #[inline]
304 fn as_mut(&mut self) -> &mut Spi<C, A, R, T> {
305 &mut self.spi
306 }
307}
308
309impl<C, A, R, T> ErrorType for SpiFuture<C, A, R, T>
310where
311 C: ValidConfig,
312 A: Capability,
313{
314 type Error = Error;
315}
316
317impl<C, A, R, T> embedded_io::ErrorType for SpiFuture<C, A, R, T>
318where
319 C: ValidConfig,
320 A: Capability,
321{
322 type Error = Error;
323}
324
325impl<P, M, C, S> SpiBus<C::Word> for SpiFuture<Config<P, M, C>, Duplex>
326where
327 Config<P, M, C>: ValidConfig<Sercom = S>,
328 P: ValidPads,
329 M: MasterMode,
330 C: Size + 'static,
331 C::Word: PrimInt + AsPrimitive<DataWidth>,
332 DataWidth: AsPrimitive<C::Word>,
333 S: Sercom,
334{
335 async fn read(&mut self, words: &mut [C::Word]) -> Result<(), Self::Error> {
336 self.read(words).await
337 }
338
339 async fn write(&mut self, words: &[C::Word]) -> Result<(), Self::Error> {
340 self.write(words).await
341 }
342
343 async fn transfer(
344 &mut self,
345 read: &mut [C::Word],
346 write: &[C::Word],
347 ) -> Result<(), Self::Error> {
348 self.transfer_word_by_word(read, write).await
349 }
350
351 async fn transfer_in_place(&mut self, words: &mut [C::Word]) -> Result<(), Self::Error> {
352 for word in words {
354 let read = self.transfer_word_in_place(*word).await?;
355 *word = read;
356 }
357
358 Ok(())
359 }
360
361 async fn flush(&mut self) -> Result<(), Self::Error> {
362 self.flush_tx().await;
364 Ok(())
365 }
366}
367
368impl<P, M, Z, D, R, S> embedded_io_async::Write for SpiFuture<Config<P, M, Z>, D, R, NoneT>
371where
372 Config<P, M, Z>: ValidConfig<Sercom = S>,
373 P: ValidPads,
374 M: OpMode,
375 Z: Size<Word = u8> + 'static,
376 D: Transmit,
377 S: Sercom,
378{
379 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
380 self.write(buf).await?;
381 Ok(buf.len())
382 }
383
384 async fn flush(&mut self) -> Result<(), Self::Error> {
385 self.flush_tx().await;
386 Ok(())
387 }
388}
389
390impl<P, M, Z, D, T, S> embedded_io_async::Read for SpiFuture<Config<P, M, Z>, D, NoneT, T>
393where
394 P: ValidPads,
395 M: MasterMode,
396 Z: Size<Word = u8> + 'static,
397 Config<P, M, Z>: ValidConfig<Sercom = S>,
398 D: Receive,
399 S: Sercom,
400{
401 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
402 self.read(buf).await?;
403 Ok(buf.len())
404 }
405}
406
407impl<P, Z, D, T, S> embedded_io_async::Read for SpiFuture<Config<P, Slave, Z>, D, NoneT, T>
410where
411 P: ValidPads,
412 Z: Size<Word = u8> + 'static,
413 Config<P, Slave, Z>: ValidConfig<Sercom = S>,
414 D: Receive,
415 S: Sercom,
416{
417 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
418 if buf.is_empty() {
419 return Ok(0);
420 }
421
422 for word in buf.iter_mut() {
423 self.flush_rx().await?;
424 *word = unsafe { self.spi.read_data().as_() };
425 }
426
427 Ok(buf.len())
428 }
429}