spim: Fix SPIM with polling executors
Co-authored-by: Priit Laes <plaes@plaes.org>
This commit is contained in:
parent
f1488864eb
commit
2b7b7a917d
@ -69,29 +69,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
|||||||
let s = T::state();
|
let s = T::state();
|
||||||
|
|
||||||
#[cfg(feature = "nrf52832")]
|
#[cfg(feature = "nrf52832")]
|
||||||
// NRF32 Anomaly 109 workaround... NRF52832
|
if r.events_started.read().bits() != 0 {
|
||||||
if r.intenset.read().started().is_enabled() && r.events_started.read().bits() != 0 {
|
s.waker.wake();
|
||||||
// Handle the first "fake" transmission
|
|
||||||
r.events_started.reset();
|
|
||||||
r.events_end.reset();
|
|
||||||
|
|
||||||
// Update DMA registers with correct rx/tx buffer sizes
|
|
||||||
r.rxd
|
|
||||||
.maxcnt
|
|
||||||
.write(|w| unsafe { w.maxcnt().bits(s.rx.load(Ordering::Relaxed)) });
|
|
||||||
r.txd
|
|
||||||
.maxcnt
|
|
||||||
.write(|w| unsafe { w.maxcnt().bits(s.tx.load(Ordering::Relaxed)) });
|
|
||||||
|
|
||||||
// Disable interrupt for STARTED event...
|
|
||||||
r.intenclr.write(|w| w.started().clear());
|
r.intenclr.write(|w| w.started().clear());
|
||||||
// ... and start actual, hopefully glitch-free transmission
|
|
||||||
r.tasks_start.write(|w| unsafe { w.bits(1) });
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.events_end.read().bits() != 0 {
|
if r.events_end.read().bits() != 0 {
|
||||||
s.end_waker.wake();
|
s.waker.wake();
|
||||||
r.intenclr.write(|w| w.end().clear());
|
r.intenclr.write(|w| w.end().clear());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,6 +238,9 @@ impl<'d, T: Instance> Spim<'d, T> {
|
|||||||
fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
|
fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
|
||||||
self.prepare(rx, tx)?;
|
self.prepare(rx, tx)?;
|
||||||
|
|
||||||
|
#[cfg(feature = "nrf52832")]
|
||||||
|
while let Poll::Pending = self.nrf52832_dma_workaround_status() {}
|
||||||
|
|
||||||
// Wait for 'end' event.
|
// Wait for 'end' event.
|
||||||
while T::regs().events_end.read().bits() == 0 {}
|
while T::regs().events_end.read().bits() == 0 {}
|
||||||
|
|
||||||
@ -278,9 +265,19 @@ impl<'d, T: Instance> Spim<'d, T> {
|
|||||||
async fn async_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
|
async fn async_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
|
||||||
self.prepare(rx, tx)?;
|
self.prepare(rx, tx)?;
|
||||||
|
|
||||||
|
#[cfg(feature = "nrf52832")]
|
||||||
|
poll_fn(|cx| {
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
|
s.waker.register(cx.waker());
|
||||||
|
|
||||||
|
self.nrf52832_dma_workaround_status()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
// Wait for 'end' event.
|
// Wait for 'end' event.
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
T::state().end_waker.register(cx.waker());
|
T::state().waker.register(cx.waker());
|
||||||
if T::regs().events_end.read().bits() != 0 {
|
if T::regs().events_end.read().bits() != 0 {
|
||||||
return Poll::Ready(());
|
return Poll::Ready(());
|
||||||
}
|
}
|
||||||
@ -371,6 +368,32 @@ impl<'d, T: Instance> Spim<'d, T> {
|
|||||||
pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<(), Error> {
|
pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<(), Error> {
|
||||||
self.async_inner_from_ram(&mut [], data).await
|
self.async_inner_from_ram(&mut [], data).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "nrf52832")]
|
||||||
|
fn nrf52832_dma_workaround_status(&mut self) -> Poll<()> {
|
||||||
|
let r = T::regs();
|
||||||
|
if r.events_started.read().bits() != 0 {
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
|
// Handle the first "fake" transmission
|
||||||
|
r.events_started.reset();
|
||||||
|
r.events_end.reset();
|
||||||
|
|
||||||
|
// Update DMA registers with correct rx/tx buffer sizes
|
||||||
|
r.rxd
|
||||||
|
.maxcnt
|
||||||
|
.write(|w| unsafe { w.maxcnt().bits(s.rx.load(Ordering::Relaxed)) });
|
||||||
|
r.txd
|
||||||
|
.maxcnt
|
||||||
|
.write(|w| unsafe { w.maxcnt().bits(s.tx.load(Ordering::Relaxed)) });
|
||||||
|
|
||||||
|
r.intenset.write(|w| w.end().set());
|
||||||
|
// ... and start actual, hopefully glitch-free transmission
|
||||||
|
r.tasks_start.write(|w| unsafe { w.bits(1) });
|
||||||
|
return Poll::Ready(());
|
||||||
|
}
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Drop for Spim<'d, T> {
|
impl<'d, T: Instance> Drop for Spim<'d, T> {
|
||||||
@ -403,7 +426,7 @@ pub(crate) mod sealed {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub end_waker: AtomicWaker,
|
pub waker: AtomicWaker,
|
||||||
#[cfg(feature = "nrf52832")]
|
#[cfg(feature = "nrf52832")]
|
||||||
pub rx: AtomicU8,
|
pub rx: AtomicU8,
|
||||||
#[cfg(feature = "nrf52832")]
|
#[cfg(feature = "nrf52832")]
|
||||||
@ -413,7 +436,7 @@ pub(crate) mod sealed {
|
|||||||
impl State {
|
impl State {
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
end_waker: AtomicWaker::new(),
|
waker: AtomicWaker::new(),
|
||||||
#[cfg(feature = "nrf52832")]
|
#[cfg(feature = "nrf52832")]
|
||||||
rx: AtomicU8::new(0),
|
rx: AtomicU8::new(0),
|
||||||
#[cfg(feature = "nrf52832")]
|
#[cfg(feature = "nrf52832")]
|
||||||
|
Loading…
Reference in New Issue
Block a user