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

Commit bce59b2

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

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

src/spi.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,77 @@ 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+
use crate::core::plic::Priority::P0;
364+
365+
impl<SPI: SpiX, PINS> AsyncTransfer for Spi<SPI, PINS> {
366+
type Error = Infallible;
367+
type TransferFuture<'t> = AsyncTransferFuture<'t>;
368+
369+
fn async_transfer<'a>(&'a mut self, data: &'a mut [u8]) -> Self::TransferFuture<'a> {
370+
// Ensure that RX FIFO is empty
371+
while self.spi.rxdata.read().empty().bit_is_clear() { }
372+
self.cs_mode_frame();
373+
374+
AsyncTransferFuture {
375+
spi: &self.spi,
376+
data,
377+
iwrite: 0,
378+
iread: 0,
379+
}
380+
}
381+
}
382+
383+
pub struct AsyncTransferFuture<'a> {
384+
spi: &'a RegisterBlock,
385+
data: &'a mut [u8],
386+
iwrite: usize,
387+
iread: usize,
388+
}
389+
390+
impl<'a> Future for AsyncTransferFuture<'a> {
391+
type Output = Result<(), Infallible>;
392+
393+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
394+
let data_len = self.data.len();
395+
396+
while self.iwrite < data_len || self.iread < data_len {
397+
if self.iwrite < data_len && self.spi.txdata.read().full().bit_is_clear() {
398+
let iwrite = self.iwrite;
399+
let byte = unsafe { *self.data.get_unchecked(iwrite) };
400+
self.iwrite = iwrite + 1;
401+
self.spi.txdata.write(|w| unsafe { w.data().bits(byte) });
402+
}
403+
404+
if self.iread < self.iwrite {
405+
let data = self.spi.rxdata.read();
406+
if data.empty().bit_is_clear() {
407+
let iread = self.iread;
408+
unsafe { *self.data.get_unchecked_mut(iread) = data.data().bits() };
409+
self.iread = iread + 1;
410+
} else {
411+
cx.waker().wake_by_ref();
412+
return Poll::Pending;
413+
}
414+
}
415+
}
416+
417+
// self.cs_mode_word();
418+
if self.spi.csmode.read().bits() != 3 {
419+
self.spi.csmode.write(|w| unsafe { w.bits(0) });
420+
}
421+
422+
Poll::Ready(Ok(()))
423+
}
424+
}
425+
}
355426

356427
// Backward compatibility
357428
impl<PINS> Spi<QSPI0, PINS> {

0 commit comments

Comments
 (0)