Skip to content
This repository was archived by the owner on Sep 2, 2025. It is now read-only.

Commit 9050c0e

Browse files
committed
Implement async traits for spi
1 parent ab1b0a7 commit 9050c0e

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

src/spi.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,76 @@ impl<SPI: SpiX, PINS> embedded_hal::blocking::spi::WriteIter<u8> for Spi<SPI, PI
352352
}
353353
}
354354

355+
#[cfg(feature = "async-traits")]
356+
mod async_impls {
357+
use core::convert::Infallible;
358+
use core::future::Future;
359+
use core::pin::Pin;
360+
use core::task::{Context, Poll};
361+
use async_embedded_traits::spi::AsyncTransfer;
362+
use super::{Spi, SpiX, qspi0::RegisterBlock};
363+
364+
impl<SPI: SpiX, PINS> AsyncTransfer for Spi<SPI, PINS> {
365+
type Error = Infallible;
366+
type TransferFuture<'t> = AsyncTransferFuture<'t>;
367+
368+
fn async_transfer<'a>(&'a mut self, data: &'a mut [u8]) -> Self::TransferFuture<'a> {
369+
// Ensure that RX FIFO is empty
370+
while self.spi.rxdata.read().empty().bit_is_clear() { }
371+
self.cs_mode_frame();
372+
373+
AsyncTransferFuture {
374+
spi: &self.spi,
375+
data,
376+
iwrite: 0,
377+
iread: 0,
378+
}
379+
}
380+
}
381+
382+
pub struct AsyncTransferFuture<'a> {
383+
spi: &'a RegisterBlock,
384+
data: &'a mut [u8],
385+
iwrite: usize,
386+
iread: usize,
387+
}
388+
389+
impl<'a> Future for AsyncTransferFuture<'a> {
390+
type Output = Result<(), Infallible>;
391+
392+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
393+
let data_len = self.data.len();
394+
395+
while self.iwrite < data_len || self.iread < data_len {
396+
if self.iwrite < data_len && self.spi.txdata.read().full().bit_is_clear() {
397+
let iwrite = self.iwrite;
398+
let byte = unsafe { *self.data.get_unchecked(iwrite) };
399+
self.iwrite = iwrite + 1;
400+
self.spi.txdata.write(|w| unsafe { w.data().bits(byte) });
401+
}
402+
403+
if self.iread < self.iwrite {
404+
let data = self.spi.rxdata.read();
405+
if data.empty().bit_is_clear() {
406+
let iread = self.iread;
407+
unsafe { *self.data.get_unchecked_mut(iread) = data.data().bits() };
408+
self.iread = iread + 1;
409+
} else {
410+
cx.waker().wake_by_ref();
411+
return Poll::Pending;
412+
}
413+
}
414+
}
415+
416+
// self.cs_mode_word();
417+
if self.spi.csmode.read().bits() != 3 {
418+
self.spi.csmode.write(|w| unsafe { w.bits(0) });
419+
}
420+
421+
Poll::Ready(Ok(()))
422+
}
423+
}
424+
}
355425

356426
// Backward compatibility
357427
impl<PINS> Spi<QSPI0, PINS> {

0 commit comments

Comments
 (0)