nrf/spim: do not use PeripheralMutex
This commit is contained in:
parent
ba6e0a4058
commit
f36cbe5e0c
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#[path = "../example_common.rs"]
|
#[path = "../example_common.rs"]
|
||||||
mod example_common;
|
mod example_common;
|
||||||
use embassy_nrf::gpio::{Level, Output};
|
use embassy_nrf::gpio::{Level, Output, OutputDrive};
|
||||||
use embassy_nrf::peripherals::Peripherals;
|
use embassy_nrf::peripherals::Peripherals;
|
||||||
use embassy_traits::spi::FullDuplex;
|
use embassy_traits::spi::FullDuplex;
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
@ -37,7 +37,7 @@ async fn run() {
|
|||||||
let spim = spim::Spim::new(p.spim3, irq, p.p0_29, p.p0_28, p.p0_30, config);
|
let spim = spim::Spim::new(p.spim3, irq, p.p0_29, p.p0_28, p.p0_30, config);
|
||||||
pin_mut!(spim);
|
pin_mut!(spim);
|
||||||
|
|
||||||
let mut ncs = Output::new(p.p0_31, Level::High);
|
let mut ncs = Output::new(p.p0_31, Level::High, OutputDrive::Standard);
|
||||||
|
|
||||||
// Example on how to talk to an ENC28J60 chip
|
// Example on how to talk to an ENC28J60 chip
|
||||||
|
|
||||||
|
@ -4,8 +4,7 @@ use core::pin::Pin;
|
|||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
use embassy::traits;
|
use embassy::traits;
|
||||||
use embassy::util::{PeripheralBorrow, WakerRegistration};
|
use embassy::util::{wake_on_interrupt, PeripheralBorrow};
|
||||||
use embassy_extras::peripheral::{PeripheralMutex, PeripheralState};
|
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
use traits::spi::FullDuplex;
|
use traits::spi::FullDuplex;
|
||||||
|
|
||||||
@ -26,13 +25,9 @@ pub enum Error {
|
|||||||
DMABufferNotInDataMemory,
|
DMABufferNotInDataMemory,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State<T: Instance> {
|
|
||||||
spim: T,
|
|
||||||
waker: WakerRegistration,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Spim<'d, T: Instance> {
|
pub struct Spim<'d, T: Instance> {
|
||||||
inner: PeripheralMutex<State<T>>,
|
spim: T,
|
||||||
|
irq: T::Interrupt,
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,20 +125,11 @@ impl<'d, T: Instance> Spim<'d, T> {
|
|||||||
r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
|
r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inner: PeripheralMutex::new(
|
|
||||||
State {
|
|
||||||
spim,
|
spim,
|
||||||
waker: WakerRegistration::new(),
|
|
||||||
},
|
|
||||||
irq,
|
irq,
|
||||||
),
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State<T>>> {
|
|
||||||
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
||||||
@ -157,29 +143,28 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
|||||||
type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
|
type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||||
|
|
||||||
fn read<'a>(self: Pin<&'a mut Self>, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
fn read<'a>(self: Pin<&'a mut Self>, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||||
async move { todo!() }
|
self.read_write(data, &[])
|
||||||
}
|
}
|
||||||
fn write<'a>(self: Pin<&'a mut Self>, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
fn write<'a>(self: Pin<&'a mut Self>, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||||
async move { todo!() }
|
self.read_write(&mut [], data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_write<'a>(
|
fn read_write<'a>(
|
||||||
mut self: Pin<&'a mut Self>,
|
self: Pin<&'a mut Self>,
|
||||||
rx: &'a mut [u8],
|
rx: &'a mut [u8],
|
||||||
tx: &'a [u8],
|
tx: &'a [u8],
|
||||||
) -> Self::WriteReadFuture<'a> {
|
) -> Self::WriteReadFuture<'a> {
|
||||||
async move {
|
async move {
|
||||||
|
let this = unsafe { self.get_unchecked_mut() };
|
||||||
slice_in_ram_or(rx, Error::DMABufferNotInDataMemory)?;
|
slice_in_ram_or(rx, Error::DMABufferNotInDataMemory)?;
|
||||||
slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?;
|
slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?;
|
||||||
|
|
||||||
self.as_mut().inner().register_interrupt();
|
|
||||||
self.as_mut().inner().with(|s, _irq| {
|
|
||||||
// Conservative compiler fence to prevent optimizations that do not
|
// Conservative compiler fence to prevent optimizations that do not
|
||||||
// take in to account actions by DMA. The fence has been placed here,
|
// take in to account actions by DMA. The fence has been placed here,
|
||||||
// before any DMA action has started.
|
// before any DMA action has started.
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
let r = s.spim.regs();
|
let r = this.spim.regs();
|
||||||
|
|
||||||
// Set up the DMA write.
|
// Set up the DMA write.
|
||||||
r.txd
|
r.txd
|
||||||
@ -208,19 +193,20 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
|||||||
// take in to account actions by DMA. The fence has been placed here,
|
// take in to account actions by DMA. The fence has been placed here,
|
||||||
// after all possible DMA actions have completed.
|
// after all possible DMA actions have completed.
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
});
|
|
||||||
|
|
||||||
// Wait for 'end' event.
|
// Wait for 'end' event.
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
self.as_mut().inner().with(|s, _irq| {
|
let r = this.spim.regs();
|
||||||
let r = s.spim.regs();
|
|
||||||
if r.events_end.read().bits() != 0 {
|
if r.events_end.read().bits() != 0 {
|
||||||
|
r.events_end.reset();
|
||||||
return Poll::Ready(());
|
return Poll::Ready(());
|
||||||
}
|
}
|
||||||
s.waker.register(cx.waker());
|
|
||||||
|
wake_on_interrupt(&mut this.irq, cx.waker());
|
||||||
|
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
})
|
})
|
||||||
})
|
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -228,16 +214,6 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<U: Instance> PeripheralState for State<U> {
|
|
||||||
type Interrupt = U::Interrupt;
|
|
||||||
fn on_interrupt(&mut self) {
|
|
||||||
if self.spim.regs().events_end.read().bits() != 0 {
|
|
||||||
self.spim.regs().intenclr.write(|w| w.end().clear());
|
|
||||||
self.waker.wake()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod sealed {
|
mod sealed {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user