Remove Pin from SPI
This commit is contained in:
parent
8b1ffb2cb7
commit
c15411d1bd
@ -17,7 +17,6 @@ use embassy_nrf::{interrupt, spim};
|
|||||||
use embassy_traits::spi::FullDuplex;
|
use embassy_traits::spi::FullDuplex;
|
||||||
use embedded_hal::digital::v2::*;
|
use embedded_hal::digital::v2::*;
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
use futures::pin_mut;
|
|
||||||
|
|
||||||
#[embassy::main]
|
#[embassy::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
@ -32,8 +31,7 @@ async fn main(spawner: Spawner) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let irq = interrupt::take!(SPIM3);
|
let irq = interrupt::take!(SPIM3);
|
||||||
let spim = spim::Spim::new(p.SPIM3, irq, p.P0_29, p.P0_28, p.P0_30, config);
|
let mut spim = spim::Spim::new(p.SPIM3, irq, p.P0_29, p.P0_28, p.P0_30, config);
|
||||||
pin_mut!(spim);
|
|
||||||
|
|
||||||
let mut ncs = Output::new(p.P0_31, Level::High, OutputDrive::Standard);
|
let mut ncs = Output::new(p.P0_31, Level::High, OutputDrive::Standard);
|
||||||
|
|
||||||
@ -44,7 +42,7 @@ async fn main(spawner: Spawner) {
|
|||||||
ncs.set_low().unwrap();
|
ncs.set_low().unwrap();
|
||||||
cortex_m::asm::delay(5);
|
cortex_m::asm::delay(5);
|
||||||
let tx = [0xFF];
|
let tx = [0xFF];
|
||||||
unwrap!(spim.as_mut().read_write(&mut [], &tx).await);
|
unwrap!(spim.read_write(&mut [], &tx).await);
|
||||||
cortex_m::asm::delay(10);
|
cortex_m::asm::delay(10);
|
||||||
ncs.set_high().unwrap();
|
ncs.set_high().unwrap();
|
||||||
|
|
||||||
@ -57,7 +55,7 @@ async fn main(spawner: Spawner) {
|
|||||||
ncs.set_low().unwrap();
|
ncs.set_low().unwrap();
|
||||||
cortex_m::asm::delay(5000);
|
cortex_m::asm::delay(5000);
|
||||||
let tx = [0b000_11101, 0];
|
let tx = [0b000_11101, 0];
|
||||||
unwrap!(spim.as_mut().read_write(&mut rx, &tx).await);
|
unwrap!(spim.read_write(&mut rx, &tx).await);
|
||||||
cortex_m::asm::delay(5000);
|
cortex_m::asm::delay(5000);
|
||||||
ncs.set_high().unwrap();
|
ncs.set_high().unwrap();
|
||||||
info!("estat: {=[?]}", rx);
|
info!("estat: {=[?]}", rx);
|
||||||
@ -67,7 +65,7 @@ async fn main(spawner: Spawner) {
|
|||||||
ncs.set_low().unwrap();
|
ncs.set_low().unwrap();
|
||||||
cortex_m::asm::delay(5);
|
cortex_m::asm::delay(5);
|
||||||
let tx = [0b100_11111, 0b11];
|
let tx = [0b100_11111, 0b11];
|
||||||
unwrap!(spim.as_mut().read_write(&mut rx, &tx).await);
|
unwrap!(spim.read_write(&mut rx, &tx).await);
|
||||||
cortex_m::asm::delay(10);
|
cortex_m::asm::delay(10);
|
||||||
ncs.set_high().unwrap();
|
ncs.set_high().unwrap();
|
||||||
|
|
||||||
@ -76,7 +74,7 @@ async fn main(spawner: Spawner) {
|
|||||||
ncs.set_low().unwrap();
|
ncs.set_low().unwrap();
|
||||||
cortex_m::asm::delay(5);
|
cortex_m::asm::delay(5);
|
||||||
let tx = [0b000_10010, 0];
|
let tx = [0b000_10010, 0];
|
||||||
unwrap!(spim.as_mut().read_write(&mut rx, &tx).await);
|
unwrap!(spim.read_write(&mut rx, &tx).await);
|
||||||
cortex_m::asm::delay(10);
|
cortex_m::asm::delay(10);
|
||||||
ncs.set_high().unwrap();
|
ncs.set_high().unwrap();
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
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::interrupt::InterruptExt;
|
||||||
use embassy::traits;
|
use embassy::traits;
|
||||||
use embassy::util::{wake_on_interrupt, PeripheralBorrow};
|
use embassy::util::{AtomicWaker, PeripheralBorrow};
|
||||||
use embassy_extras::unborrow;
|
use embassy_extras::unborrow;
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
use traits::spi::FullDuplex;
|
use traits::spi::FullDuplex;
|
||||||
@ -50,7 +50,7 @@ impl<'d, T: Instance> Spim<'d, T> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
unborrow!(spim, irq, sck, miso, mosi);
|
unborrow!(spim, irq, sck, miso, mosi);
|
||||||
|
|
||||||
let r = spim.regs();
|
let r = T::regs();
|
||||||
|
|
||||||
// Configure pins
|
// Configure pins
|
||||||
sck.conf().write(|w| w.dir().output().drive().h0h1());
|
sck.conf().write(|w| w.dir().output().drive().h0h1());
|
||||||
@ -122,12 +122,26 @@ impl<'d, T: Instance> Spim<'d, T> {
|
|||||||
// Disable all events interrupts
|
// Disable all events interrupts
|
||||||
r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
|
r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
|
||||||
|
|
||||||
|
irq.set_handler(Self::on_interrupt);
|
||||||
|
irq.unpend();
|
||||||
|
irq.enable();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
peri: spim,
|
peri: spim,
|
||||||
irq,
|
irq,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_interrupt(_: *mut ()) {
|
||||||
|
let r = T::regs();
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
|
if r.events_end.read().bits() != 0 {
|
||||||
|
s.end_waker.wake();
|
||||||
|
r.intenclr.write(|w| w.end().clear());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
||||||
@ -140,20 +154,15 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
|||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
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>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||||
self.read_write(data, &[])
|
self.read_write(data, &[])
|
||||||
}
|
}
|
||||||
fn write<'a>(self: Pin<&'a mut Self>, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||||
self.read_write(&mut [], data)
|
self.read_write(&mut [], data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_write<'a>(
|
fn read_write<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::WriteReadFuture<'a> {
|
||||||
self: Pin<&'a mut Self>,
|
|
||||||
rx: &'a mut [u8],
|
|
||||||
tx: &'a [u8],
|
|
||||||
) -> 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)?;
|
||||||
|
|
||||||
@ -162,7 +171,8 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
|||||||
// before any DMA action has started.
|
// before any DMA action has started.
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
let r = this.peri.regs();
|
let r = T::regs();
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
// Set up the DMA write.
|
// Set up the DMA write.
|
||||||
r.txd
|
r.txd
|
||||||
@ -194,15 +204,11 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
|||||||
|
|
||||||
// Wait for 'end' event.
|
// Wait for 'end' event.
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
let r = this.peri.regs();
|
s.end_waker.register(cx.waker());
|
||||||
|
|
||||||
if r.events_end.read().bits() != 0 {
|
if r.events_end.read().bits() != 0 {
|
||||||
r.events_end.reset();
|
|
||||||
return Poll::Ready(());
|
return Poll::Ready(());
|
||||||
}
|
}
|
||||||
|
|
||||||
wake_on_interrupt(&mut this.irq, cx.waker());
|
|
||||||
|
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
@ -215,8 +221,21 @@ impl<'d, T: Instance> FullDuplex<u8> for Spim<'d, T> {
|
|||||||
mod sealed {
|
mod sealed {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
pub struct State {
|
||||||
|
pub end_waker: AtomicWaker,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
end_waker: AtomicWaker::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Instance {
|
pub trait Instance {
|
||||||
fn regs(&self) -> &pac::spim0::RegisterBlock;
|
fn regs() -> &'static pac::spim0::RegisterBlock;
|
||||||
|
fn state() -> &'static State;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,9 +246,13 @@ pub trait Instance: sealed::Instance + 'static {
|
|||||||
macro_rules! impl_instance {
|
macro_rules! impl_instance {
|
||||||
($type:ident, $irq:ident) => {
|
($type:ident, $irq:ident) => {
|
||||||
impl sealed::Instance for peripherals::$type {
|
impl sealed::Instance for peripherals::$type {
|
||||||
fn regs(&self) -> &pac::spim0::RegisterBlock {
|
fn regs() -> &'static pac::spim0::RegisterBlock {
|
||||||
unsafe { &*pac::$type::ptr() }
|
unsafe { &*pac::$type::ptr() }
|
||||||
}
|
}
|
||||||
|
fn state() -> &'static sealed::State {
|
||||||
|
static STATE: sealed::State = sealed::State::new();
|
||||||
|
&STATE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl Instance for peripherals::$type {
|
impl Instance for peripherals::$type {
|
||||||
type Interrupt = interrupt::$irq;
|
type Interrupt = interrupt::$irq;
|
||||||
|
@ -214,14 +214,13 @@ where
|
|||||||
type ReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
type ReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
||||||
type WriteReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
type WriteReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
||||||
|
|
||||||
fn read<'a>(self: Pin<&'a mut Self>, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||||
let this = unsafe { self.get_unchecked_mut() };
|
|
||||||
#[allow(mutable_transmutes)]
|
#[allow(mutable_transmutes)]
|
||||||
let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) };
|
let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) };
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let rx_stream = this.rx_stream.take().unwrap();
|
let rx_stream = self.rx_stream.take().unwrap();
|
||||||
let spi = this.spi.take().unwrap();
|
let spi = self.spi.take().unwrap();
|
||||||
|
|
||||||
spi.cr2.modify(|_, w| w.errie().set_bit());
|
spi.cr2.modify(|_, w| w.errie().set_bit());
|
||||||
|
|
||||||
@ -236,8 +235,8 @@ where
|
|||||||
.double_buffer(false),
|
.double_buffer(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
let fut = InterruptFuture::new(&mut this.rx_int);
|
let fut = InterruptFuture::new(&mut self.rx_int);
|
||||||
let fut_err = InterruptFuture::new(&mut this.spi_int);
|
let fut_err = InterruptFuture::new(&mut self.spi_int);
|
||||||
|
|
||||||
rx_transfer.start(|_spi| {});
|
rx_transfer.start(|_spi| {});
|
||||||
future::select(fut, fut_err).await;
|
future::select(fut, fut_err).await;
|
||||||
@ -245,21 +244,20 @@ where
|
|||||||
let (rx_stream, spi, _buf, _) = rx_transfer.free();
|
let (rx_stream, spi, _buf, _) = rx_transfer.free();
|
||||||
|
|
||||||
spi.cr2.modify(|_, w| w.errie().clear_bit());
|
spi.cr2.modify(|_, w| w.errie().clear_bit());
|
||||||
this.rx_stream.replace(rx_stream);
|
self.rx_stream.replace(rx_stream);
|
||||||
this.spi.replace(spi);
|
self.spi.replace(spi);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write<'a>(self: Pin<&'a mut Self>, buf: &'a [u8]) -> Self::WriteFuture<'a> {
|
fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||||
let this = unsafe { self.get_unchecked_mut() };
|
|
||||||
#[allow(mutable_transmutes)]
|
#[allow(mutable_transmutes)]
|
||||||
let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) };
|
let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) };
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let tx_stream = this.tx_stream.take().unwrap();
|
let tx_stream = self.tx_stream.take().unwrap();
|
||||||
let spi = this.spi.take().unwrap();
|
let spi = self.spi.take().unwrap();
|
||||||
|
|
||||||
// let mut tx_transfer = Transfer::init(
|
// let mut tx_transfer = Transfer::init(
|
||||||
// tx_stream,
|
// tx_stream,
|
||||||
@ -272,7 +270,7 @@ where
|
|||||||
// .double_buffer(false),
|
// .double_buffer(false),
|
||||||
// );
|
// );
|
||||||
//
|
//
|
||||||
// let fut = InterruptFuture::new(&mut this.tx_int);
|
// let fut = InterruptFuture::new(&mut self.tx_int);
|
||||||
//
|
//
|
||||||
// tx_transfer.start(|_spi| {});
|
// tx_transfer.start(|_spi| {});
|
||||||
// fut.await;
|
// fut.await;
|
||||||
@ -284,28 +282,26 @@ where
|
|||||||
nb::block!(write_sr(&spi, byte));
|
nb::block!(write_sr(&spi, byte));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tx_stream.replace(tx_stream);
|
self.tx_stream.replace(tx_stream);
|
||||||
this.spi.replace(spi);
|
self.spi.replace(spi);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_write<'a>(
|
fn read_write<'a>(
|
||||||
self: Pin<&'a mut Self>,
|
&'a mut self,
|
||||||
read_buf: &'a mut [u8],
|
read_buf: &'a mut [u8],
|
||||||
write_buf: &'a [u8],
|
write_buf: &'a [u8],
|
||||||
) -> Self::WriteReadFuture<'a> {
|
) -> Self::WriteReadFuture<'a> {
|
||||||
let this = unsafe { self.get_unchecked_mut() };
|
|
||||||
|
|
||||||
#[allow(mutable_transmutes)]
|
#[allow(mutable_transmutes)]
|
||||||
let write_static_buf: &'static mut [u8] = unsafe { mem::transmute(write_buf) };
|
let write_static_buf: &'static mut [u8] = unsafe { mem::transmute(write_buf) };
|
||||||
let read_static_buf: &'static mut [u8] = unsafe { mem::transmute(read_buf) };
|
let read_static_buf: &'static mut [u8] = unsafe { mem::transmute(read_buf) };
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let tx_stream = this.tx_stream.take().unwrap();
|
let tx_stream = self.tx_stream.take().unwrap();
|
||||||
let rx_stream = this.rx_stream.take().unwrap();
|
let rx_stream = self.rx_stream.take().unwrap();
|
||||||
let spi_tx = this.spi.take().unwrap();
|
let spi_tx = self.spi.take().unwrap();
|
||||||
let spi_rx: SPI = unsafe { mem::transmute_copy(&spi_tx) };
|
let spi_rx: SPI = unsafe { mem::transmute_copy(&spi_tx) };
|
||||||
|
|
||||||
spi_rx
|
spi_rx
|
||||||
@ -334,9 +330,9 @@ where
|
|||||||
// .double_buffer(false),
|
// .double_buffer(false),
|
||||||
// );
|
// );
|
||||||
//
|
//
|
||||||
// let tx_fut = InterruptFuture::new(&mut this.tx_int);
|
// let tx_fut = InterruptFuture::new(&mut self.tx_int);
|
||||||
// let rx_fut = InterruptFuture::new(&mut this.rx_int);
|
// let rx_fut = InterruptFuture::new(&mut self.rx_int);
|
||||||
// let rx_fut_err = InterruptFuture::new(&mut this.spi_int);
|
// let rx_fut_err = InterruptFuture::new(&mut self.spi_int);
|
||||||
//
|
//
|
||||||
// rx_transfer.start(|_spi| {});
|
// rx_transfer.start(|_spi| {});
|
||||||
// tx_transfer.start(|_spi| {});
|
// tx_transfer.start(|_spi| {});
|
||||||
@ -352,7 +348,7 @@ where
|
|||||||
for i in 0..(read_static_buf.len() - 1) {
|
for i in 0..(read_static_buf.len() - 1) {
|
||||||
let byte = write_static_buf[i];
|
let byte = write_static_buf[i];
|
||||||
loop {
|
loop {
|
||||||
let fut = InterruptFuture::new(&mut this.spi_int);
|
let fut = InterruptFuture::new(&mut self.spi_int);
|
||||||
match write_sr(&spi_tx, byte) {
|
match write_sr(&spi_tx, byte) {
|
||||||
Ok(()) => break,
|
Ok(()) => break,
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -361,7 +357,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let fut = InterruptFuture::new(&mut this.spi_int);
|
let fut = InterruptFuture::new(&mut self.spi_int);
|
||||||
match read_sr(&spi_tx) {
|
match read_sr(&spi_tx) {
|
||||||
Ok(byte) => {
|
Ok(byte) => {
|
||||||
read_static_buf[i] = byte;
|
read_static_buf[i] = byte;
|
||||||
@ -381,9 +377,9 @@ where
|
|||||||
.rxneie()
|
.rxneie()
|
||||||
.clear_bit()
|
.clear_bit()
|
||||||
});
|
});
|
||||||
this.rx_stream.replace(rx_stream);
|
self.rx_stream.replace(rx_stream);
|
||||||
this.tx_stream.replace(tx_stream);
|
self.tx_stream.replace(tx_stream);
|
||||||
this.spi.replace(spi_rx);
|
self.spi.replace(spi_rx);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -421,7 +417,7 @@ macro_rules! spi {
|
|||||||
impl Instance for pac::$SPI {
|
impl Instance for pac::$SPI {
|
||||||
unsafe fn enable_clock() {
|
unsafe fn enable_clock() {
|
||||||
const EN_BIT: u8 = $en;
|
const EN_BIT: u8 = $en;
|
||||||
// NOTE(unsafe) this reference will only be used for atomic writes with no side effects.
|
// NOTE(unsafe) self reference will only be used for atomic writes with no side effects.
|
||||||
let rcc = &(*pac::RCC::ptr());
|
let rcc = &(*pac::RCC::ptr());
|
||||||
// Enable clock.
|
// Enable clock.
|
||||||
bb::set(&rcc.$apbXenr, EN_BIT);
|
bb::set(&rcc.$apbXenr, EN_BIT);
|
||||||
|
@ -33,10 +33,10 @@ pub trait FullDuplex<Word> {
|
|||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
|
||||||
fn read<'a>(self: Pin<&'a mut Self>, data: &'a mut [Word]) -> Self::ReadFuture<'a>;
|
fn read<'a>(&'a mut self, data: &'a mut [Word]) -> Self::ReadFuture<'a>;
|
||||||
fn write<'a>(self: Pin<&'a mut Self>, data: &'a [Word]) -> Self::WriteFuture<'a>;
|
fn write<'a>(&'a mut self, data: &'a [Word]) -> Self::WriteFuture<'a>;
|
||||||
fn read_write<'a>(
|
fn read_write<'a>(
|
||||||
self: Pin<&'a mut Self>,
|
&'a mut self,
|
||||||
read: &'a mut [Word],
|
read: &'a mut [Word],
|
||||||
write: &'a [Word],
|
write: &'a [Word],
|
||||||
) -> Self::WriteReadFuture<'a>;
|
) -> Self::WriteReadFuture<'a>;
|
||||||
|
Loading…
Reference in New Issue
Block a user