Merge branch 'master' into nrf91/53-nvmc
This commit is contained in:
@ -75,8 +75,8 @@ embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optiona
|
||||
|
||||
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
|
||||
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9", optional = true}
|
||||
embedded-hal-async = { version = "=0.1.0-alpha.3", optional = true}
|
||||
embedded-io = { version = "0.3.1", features = ["async"], optional = true }
|
||||
embedded-hal-async = { version = "=0.2.0-alpha.0", optional = true}
|
||||
embedded-io = { version = "0.4.0", features = ["async"], optional = true }
|
||||
|
||||
defmt = { version = "0.3", optional = true }
|
||||
log = { version = "0.4.14", optional = true }
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
use core::cell::RefCell;
|
||||
use core::cmp::min;
|
||||
use core::future::{poll_fn, Future};
|
||||
use core::future::poll_fn;
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::task::Poll;
|
||||
|
||||
@ -341,32 +341,20 @@ impl<'u, 'd, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUar
|
||||
}
|
||||
|
||||
impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarte<'d, U, T> {
|
||||
type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.inner_read(buf)
|
||||
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||
self.inner_read(buf).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarteRx<'u, 'd, U, T> {
|
||||
type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.inner.inner_read(buf)
|
||||
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
||||
self.inner.inner_read(buf).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarte<'d, U, T> {
|
||||
type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn fill_buf<'a>(&'a mut self) -> Self::FillBufFuture<'a> {
|
||||
self.inner_fill_buf()
|
||||
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
|
||||
self.inner_fill_buf().await
|
||||
}
|
||||
|
||||
fn consume(&mut self, amt: usize) {
|
||||
@ -375,12 +363,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for Bu
|
||||
}
|
||||
|
||||
impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarteRx<'u, 'd, U, T> {
|
||||
type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn fill_buf<'a>(&'a mut self) -> Self::FillBufFuture<'a> {
|
||||
self.inner.inner_fill_buf()
|
||||
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
|
||||
self.inner.inner_fill_buf().await
|
||||
}
|
||||
|
||||
fn consume(&mut self, amt: usize) {
|
||||
@ -389,38 +373,22 @@ impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRea
|
||||
}
|
||||
|
||||
impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarte<'d, U, T> {
|
||||
type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.inner_write(buf)
|
||||
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
self.inner_write(buf).await
|
||||
}
|
||||
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
self.inner_flush()
|
||||
async fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
self.inner_flush().await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarteTx<'u, 'd, U, T> {
|
||||
type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.inner.inner_write(buf)
|
||||
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
||||
self.inner.inner_write(buf).await
|
||||
}
|
||||
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
self.inner.inner_flush()
|
||||
async fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
self.inner.inner_flush().await
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,8 +131,12 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
|
||||
|
||||
impl_spim!(SPI0, SPIM0, SPIM0_SPIS0_SPI0);
|
||||
|
||||
impl_spis!(SPI0, SPIS0, SPIM0_SPIS0_SPI0);
|
||||
|
||||
impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0);
|
||||
|
||||
impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
|
||||
|
||||
impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||
impl_timer!(TIMER1, TIMER1, TIMER1);
|
||||
impl_timer!(TIMER2, TIMER2, TIMER2);
|
||||
|
@ -137,8 +137,12 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
|
||||
|
||||
impl_spim!(SPI0, SPIM0, SPIM0_SPIS0_SPI0);
|
||||
|
||||
impl_spis!(SPI0, SPIS0, SPIM0_SPIS0_SPI0);
|
||||
|
||||
impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0);
|
||||
|
||||
impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
|
||||
|
||||
impl_pwm!(PWM0, PWM0, PWM0);
|
||||
|
||||
impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||
|
@ -138,8 +138,13 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
|
||||
impl_spim!(TWISPI0, SPIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
|
||||
impl_spim!(SPI1, SPIM1, SPIM1_SPIS1_SPI1);
|
||||
|
||||
impl_spis!(TWISPI0, SPIS0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
|
||||
impl_spis!(SPI1, SPIS1, SPIM1_SPIS1_SPI1);
|
||||
|
||||
impl_twim!(TWISPI0, TWIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
|
||||
|
||||
impl_twis!(TWISPI0, TWIS0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
|
||||
|
||||
impl_pwm!(PWM0, PWM0, PWM0);
|
||||
|
||||
impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||
|
@ -136,9 +136,15 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
|
||||
impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
|
||||
impl_spis!(TWISPI0, SPIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_spis!(TWISPI1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
|
||||
impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
|
||||
impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
|
||||
impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||
impl_timer!(TIMER1, TIMER1, TIMER1);
|
||||
impl_timer!(TIMER2, TIMER2, TIMER2);
|
||||
|
@ -138,6 +138,9 @@ embassy_hal_common::peripherals! {
|
||||
|
||||
// QDEC
|
||||
QDEC,
|
||||
|
||||
// I2S
|
||||
I2S,
|
||||
}
|
||||
|
||||
impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
|
||||
@ -146,9 +149,16 @@ impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2);
|
||||
|
||||
impl_spis!(TWISPI0, SPIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_spis!(TWISPI1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
impl_spis!(SPI2, SPIS2, SPIM2_SPIS2_SPI2);
|
||||
|
||||
impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
|
||||
impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
|
||||
impl_pwm!(PWM0, PWM0, PWM0);
|
||||
impl_pwm!(PWM1, PWM1, PWM1);
|
||||
impl_pwm!(PWM2, PWM2, PWM2);
|
||||
@ -234,6 +244,8 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5);
|
||||
impl_saadc_input!(P0_30, ANALOG_INPUT6);
|
||||
impl_saadc_input!(P0_31, ANALOG_INPUT7);
|
||||
|
||||
impl_i2s!(I2S, I2S, I2S);
|
||||
|
||||
pub mod irqs {
|
||||
use embassy_cortex_m::interrupt::_export::declare;
|
||||
|
||||
@ -274,6 +286,6 @@ pub mod irqs {
|
||||
declare!(PWM2);
|
||||
declare!(SPIM2_SPIS2_SPI2);
|
||||
declare!(RTC2);
|
||||
declare!(I2S);
|
||||
declare!(FPU);
|
||||
declare!(I2S);
|
||||
}
|
||||
|
@ -161,6 +161,9 @@ embassy_hal_common::peripherals! {
|
||||
|
||||
// PDM
|
||||
PDM,
|
||||
|
||||
// I2S
|
||||
I2S,
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
@ -174,9 +177,16 @@ impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2);
|
||||
impl_spim!(SPI3, SPIM3, SPIM3);
|
||||
|
||||
impl_spis!(TWISPI0, SPIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_spis!(TWISPI1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
impl_spis!(SPI2, SPIS2, SPIM2_SPIS2_SPI2);
|
||||
|
||||
impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
|
||||
impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
|
||||
impl_pwm!(PWM0, PWM0, PWM0);
|
||||
impl_pwm!(PWM1, PWM1, PWM1);
|
||||
impl_pwm!(PWM2, PWM2, PWM2);
|
||||
@ -280,6 +290,8 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5);
|
||||
impl_saadc_input!(P0_30, ANALOG_INPUT6);
|
||||
impl_saadc_input!(P0_31, ANALOG_INPUT7);
|
||||
|
||||
impl_i2s!(I2S, I2S, I2S);
|
||||
|
||||
pub mod irqs {
|
||||
use embassy_cortex_m::interrupt::_export::declare;
|
||||
|
||||
@ -320,10 +332,10 @@ pub mod irqs {
|
||||
declare!(PWM2);
|
||||
declare!(SPIM2_SPIS2_SPI2);
|
||||
declare!(RTC2);
|
||||
declare!(I2S);
|
||||
declare!(FPU);
|
||||
declare!(USBD);
|
||||
declare!(UARTE1);
|
||||
declare!(PWM3);
|
||||
declare!(SPIM3);
|
||||
declare!(I2S);
|
||||
}
|
||||
|
@ -164,6 +164,9 @@ embassy_hal_common::peripherals! {
|
||||
|
||||
// PDM
|
||||
PDM,
|
||||
|
||||
// I2S
|
||||
I2S,
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
@ -177,9 +180,16 @@ impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2);
|
||||
impl_spim!(SPI3, SPIM3, SPIM3);
|
||||
|
||||
impl_spis!(TWISPI0, SPIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_spis!(TWISPI1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
impl_spis!(SPI2, SPIS2, SPIM2_SPIS2_SPI2);
|
||||
|
||||
impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
|
||||
impl_twis!(TWISPI0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
|
||||
impl_twis!(TWISPI1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
|
||||
|
||||
impl_pwm!(PWM0, PWM0, PWM0);
|
||||
impl_pwm!(PWM1, PWM1, PWM1);
|
||||
impl_pwm!(PWM2, PWM2, PWM2);
|
||||
@ -285,6 +295,8 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5);
|
||||
impl_saadc_input!(P0_30, ANALOG_INPUT6);
|
||||
impl_saadc_input!(P0_31, ANALOG_INPUT7);
|
||||
|
||||
impl_i2s!(I2S, I2S, I2S);
|
||||
|
||||
pub mod irqs {
|
||||
use embassy_cortex_m::interrupt::_export::declare;
|
||||
|
||||
@ -325,7 +337,6 @@ pub mod irqs {
|
||||
declare!(PWM2);
|
||||
declare!(SPIM2_SPIS2_SPI2);
|
||||
declare!(RTC2);
|
||||
declare!(I2S);
|
||||
declare!(FPU);
|
||||
declare!(USBD);
|
||||
declare!(UARTE1);
|
||||
@ -333,4 +344,5 @@ pub mod irqs {
|
||||
declare!(CRYPTOCELL);
|
||||
declare!(PWM3);
|
||||
declare!(SPIM3);
|
||||
declare!(I2S);
|
||||
}
|
||||
|
@ -366,11 +366,21 @@ impl_spim!(UARTETWISPI1, SPIM1, SERIAL1);
|
||||
impl_spim!(UARTETWISPI2, SPIM2, SERIAL2);
|
||||
impl_spim!(UARTETWISPI3, SPIM3, SERIAL3);
|
||||
|
||||
impl_spis!(UARTETWISPI0, SPIS0, SERIAL0);
|
||||
impl_spis!(UARTETWISPI1, SPIS1, SERIAL1);
|
||||
impl_spis!(UARTETWISPI2, SPIS2, SERIAL2);
|
||||
impl_spis!(UARTETWISPI3, SPIS3, SERIAL3);
|
||||
|
||||
impl_twim!(UARTETWISPI0, TWIM0, SERIAL0);
|
||||
impl_twim!(UARTETWISPI1, TWIM1, SERIAL1);
|
||||
impl_twim!(UARTETWISPI2, TWIM2, SERIAL2);
|
||||
impl_twim!(UARTETWISPI3, TWIM3, SERIAL3);
|
||||
|
||||
impl_twis!(UARTETWISPI0, TWIS0, SERIAL0);
|
||||
impl_twis!(UARTETWISPI1, TWIS1, SERIAL1);
|
||||
impl_twis!(UARTETWISPI2, TWIS2, SERIAL2);
|
||||
impl_twis!(UARTETWISPI3, TWIS3, SERIAL3);
|
||||
|
||||
impl_pwm!(PWM0, PWM0, PWM0);
|
||||
impl_pwm!(PWM1, PWM1, PWM1);
|
||||
impl_pwm!(PWM2, PWM2, PWM2);
|
||||
|
@ -243,7 +243,9 @@ embassy_hal_common::peripherals! {
|
||||
|
||||
impl_uarte!(UARTETWISPI0, UARTE0, SERIAL0);
|
||||
impl_spim!(UARTETWISPI0, SPIM0, SERIAL0);
|
||||
impl_spis!(UARTETWISPI0, SPIS0, SERIAL0);
|
||||
impl_twim!(UARTETWISPI0, TWIM0, SERIAL0);
|
||||
impl_twis!(UARTETWISPI0, TWIS0, SERIAL0);
|
||||
|
||||
impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||
impl_timer!(TIMER1, TIMER1, TIMER1);
|
||||
|
@ -280,11 +280,21 @@ impl_spim!(UARTETWISPI1, SPIM1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
|
||||
impl_spim!(UARTETWISPI2, SPIM2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
|
||||
impl_spim!(UARTETWISPI3, SPIM3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
|
||||
|
||||
impl_spis!(UARTETWISPI0, SPIS0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
|
||||
impl_spis!(UARTETWISPI1, SPIS1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
|
||||
impl_spis!(UARTETWISPI2, SPIS2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
|
||||
impl_spis!(UARTETWISPI3, SPIS3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
|
||||
|
||||
impl_twim!(UARTETWISPI0, TWIM0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
|
||||
impl_twim!(UARTETWISPI1, TWIM1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
|
||||
impl_twim!(UARTETWISPI2, TWIM2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
|
||||
impl_twim!(UARTETWISPI3, TWIM3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
|
||||
|
||||
impl_twis!(UARTETWISPI0, TWIS0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
|
||||
impl_twis!(UARTETWISPI1, TWIS1, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
|
||||
impl_twis!(UARTETWISPI2, TWIS2, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
|
||||
impl_twis!(UARTETWISPI3, TWIS3, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
|
||||
|
||||
impl_pwm!(PWM0, PWM0, PWM0);
|
||||
impl_pwm!(PWM1, PWM1, PWM1);
|
||||
impl_pwm!(PWM2, PWM2, PWM2);
|
||||
|
@ -2,7 +2,7 @@ use core::convert::Infallible;
|
||||
use core::future::{poll_fn, Future};
|
||||
use core::task::{Context, Poll};
|
||||
|
||||
use embassy_hal_common::{impl_peripheral, Peripheral, PeripheralRef};
|
||||
use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef};
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
use crate::gpio::sealed::Pin as _;
|
||||
@ -148,7 +148,7 @@ impl Iterator for BitIter {
|
||||
|
||||
/// GPIOTE channel driver in input mode
|
||||
pub struct InputChannel<'d, C: Channel, T: GpioPin> {
|
||||
ch: C,
|
||||
ch: PeripheralRef<'d, C>,
|
||||
pin: Input<'d, T>,
|
||||
}
|
||||
|
||||
@ -162,7 +162,9 @@ impl<'d, C: Channel, T: GpioPin> Drop for InputChannel<'d, C, T> {
|
||||
}
|
||||
|
||||
impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
|
||||
pub fn new(ch: C, pin: Input<'d, T>, polarity: InputChannelPolarity) -> Self {
|
||||
pub fn new(ch: impl Peripheral<P = C> + 'd, pin: Input<'d, T>, polarity: InputChannelPolarity) -> Self {
|
||||
into_ref!(ch);
|
||||
|
||||
let g = regs();
|
||||
let num = ch.number();
|
||||
|
||||
@ -215,7 +217,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
|
||||
|
||||
/// GPIOTE channel driver in output mode
|
||||
pub struct OutputChannel<'d, C: Channel, T: GpioPin> {
|
||||
ch: C,
|
||||
ch: PeripheralRef<'d, C>,
|
||||
_pin: Output<'d, T>,
|
||||
}
|
||||
|
||||
@ -229,7 +231,8 @@ impl<'d, C: Channel, T: GpioPin> Drop for OutputChannel<'d, C, T> {
|
||||
}
|
||||
|
||||
impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
|
||||
pub fn new(ch: C, pin: Output<'d, T>, polarity: OutputChannelPolarity) -> Self {
|
||||
pub fn new(ch: impl Peripheral<P = C> + 'd, pin: Output<'d, T>, polarity: OutputChannelPolarity) -> Self {
|
||||
into_ref!(ch);
|
||||
let g = regs();
|
||||
let num = ch.number();
|
||||
|
||||
@ -470,71 +473,49 @@ mod eh1 {
|
||||
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
mod eha {
|
||||
use futures::FutureExt;
|
||||
|
||||
use super::*;
|
||||
|
||||
impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Input<'d, T> {
|
||||
type WaitForHighFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> {
|
||||
self.wait_for_high().map(Ok)
|
||||
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.wait_for_high().await)
|
||||
}
|
||||
|
||||
type WaitForLowFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> {
|
||||
self.wait_for_low().map(Ok)
|
||||
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.wait_for_low().await)
|
||||
}
|
||||
|
||||
type WaitForRisingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> {
|
||||
self.wait_for_rising_edge().map(Ok)
|
||||
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.wait_for_rising_edge().await)
|
||||
}
|
||||
|
||||
type WaitForFallingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> {
|
||||
self.wait_for_falling_edge().map(Ok)
|
||||
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.wait_for_falling_edge().await)
|
||||
}
|
||||
|
||||
type WaitForAnyEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> {
|
||||
self.wait_for_any_edge().map(Ok)
|
||||
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.wait_for_any_edge().await)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: GpioPin> embedded_hal_async::digital::Wait for Flex<'d, T> {
|
||||
type WaitForHighFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_high<'a>(&'a mut self) -> Self::WaitForHighFuture<'a> {
|
||||
self.wait_for_high().map(Ok)
|
||||
async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.wait_for_high().await)
|
||||
}
|
||||
|
||||
type WaitForLowFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_low<'a>(&'a mut self) -> Self::WaitForLowFuture<'a> {
|
||||
self.wait_for_low().map(Ok)
|
||||
async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.wait_for_low().await)
|
||||
}
|
||||
|
||||
type WaitForRisingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_rising_edge<'a>(&'a mut self) -> Self::WaitForRisingEdgeFuture<'a> {
|
||||
self.wait_for_rising_edge().map(Ok)
|
||||
async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.wait_for_rising_edge().await)
|
||||
}
|
||||
|
||||
type WaitForFallingEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_falling_edge<'a>(&'a mut self) -> Self::WaitForFallingEdgeFuture<'a> {
|
||||
self.wait_for_falling_edge().map(Ok)
|
||||
async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.wait_for_falling_edge().await)
|
||||
}
|
||||
|
||||
type WaitForAnyEdgeFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn wait_for_any_edge<'a>(&'a mut self) -> Self::WaitForAnyEdgeFuture<'a> {
|
||||
self.wait_for_any_edge().map(Ok)
|
||||
async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
|
||||
Ok(self.wait_for_any_edge().await)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1141
embassy-nrf/src/i2s.rs
Normal file
1141
embassy-nrf/src/i2s.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,11 @@
|
||||
//! mutable slices always reside in RAM.
|
||||
|
||||
#![no_std]
|
||||
#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))]
|
||||
#![cfg_attr(
|
||||
feature = "nightly",
|
||||
feature(type_alias_impl_trait, async_fn_in_trait, impl_trait_projections)
|
||||
)]
|
||||
#![cfg_attr(feature = "nightly", allow(incomplete_features))]
|
||||
|
||||
#[cfg(not(any(
|
||||
feature = "nrf51",
|
||||
@ -74,6 +78,8 @@ pub mod buffered_uarte;
|
||||
pub mod gpio;
|
||||
#[cfg(feature = "gpiote")]
|
||||
pub mod gpiote;
|
||||
#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))]
|
||||
pub mod i2s;
|
||||
pub mod nvmc;
|
||||
#[cfg(any(
|
||||
feature = "nrf52810",
|
||||
@ -95,10 +101,12 @@ pub mod rng;
|
||||
#[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))]
|
||||
pub mod saadc;
|
||||
pub mod spim;
|
||||
pub mod spis;
|
||||
#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
|
||||
pub mod temp;
|
||||
pub mod timer;
|
||||
pub mod twim;
|
||||
pub mod twis;
|
||||
pub mod uarte;
|
||||
#[cfg(any(
|
||||
feature = "_nrf5340-app",
|
||||
@ -266,5 +274,12 @@ pub fn init(config: config::Config) -> Peripherals {
|
||||
#[cfg(feature = "_time-driver")]
|
||||
time_driver::init(config.time_interrupt_priority);
|
||||
|
||||
// Disable UARTE (enabled by default for some reason)
|
||||
#[cfg(feature = "_nrf9160")]
|
||||
unsafe {
|
||||
(*pac::UARTE0::ptr()).enable.write(|w| w.enable().disabled());
|
||||
(*pac::UARTE1::ptr()).enable.write(|w| w.enable().disabled());
|
||||
}
|
||||
|
||||
peripherals
|
||||
}
|
||||
|
@ -477,45 +477,34 @@ mod eh1 {
|
||||
|
||||
#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
|
||||
mod eha {
|
||||
use core::future::Future;
|
||||
|
||||
use super::*;
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spim<'d, T> {
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
async move { Ok(()) }
|
||||
async fn flush(&mut self) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::SpiBusRead<u8> for Spim<'d, T> {
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, words: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.read(words)
|
||||
async fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
|
||||
self.read(words).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::SpiBusWrite<u8> for Spim<'d, T> {
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.write(data)
|
||||
async fn write(&mut self, data: &[u8]) -> Result<(), Error> {
|
||||
self.write(data).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_async::spi::SpiBus<u8> for Spim<'d, T> {
|
||||
type TransferFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::TransferFuture<'a> {
|
||||
self.transfer(rx, tx)
|
||||
async fn transfer(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> {
|
||||
self.transfer(rx, tx).await
|
||||
}
|
||||
|
||||
type TransferInPlaceFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Self::TransferInPlaceFuture<'a> {
|
||||
self.transfer_in_place(words)
|
||||
async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
|
||||
self.transfer_in_place(words).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
539
embassy-nrf/src/spis.rs
Normal file
539
embassy-nrf/src/spis.rs
Normal file
@ -0,0 +1,539 @@
|
||||
#![macro_use]
|
||||
use core::future::poll_fn;
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::task::Poll;
|
||||
|
||||
use embassy_embedded_hal::SetConfig;
|
||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
|
||||
|
||||
use crate::chip::FORCE_COPY_BUFFER_SIZE;
|
||||
use crate::gpio::sealed::Pin as _;
|
||||
use crate::gpio::{self, AnyPin, Pin as GpioPin};
|
||||
use crate::interrupt::{Interrupt, InterruptExt};
|
||||
use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut};
|
||||
use crate::{pac, Peripheral};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
TxBufferTooLong,
|
||||
RxBufferTooLong,
|
||||
/// EasyDMA can only read from data memory, read only buffers in flash will fail.
|
||||
DMABufferNotInDataMemory,
|
||||
}
|
||||
|
||||
/// Interface for the SPIS peripheral using EasyDMA to offload the transmission and reception workload.
|
||||
///
|
||||
/// For more details about EasyDMA, consult the module documentation.
|
||||
pub struct Spis<'d, T: Instance> {
|
||||
_p: PeripheralRef<'d, T>,
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct Config {
|
||||
pub mode: Mode,
|
||||
pub orc: u8,
|
||||
pub def: u8,
|
||||
pub auto_acquire: bool,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mode: MODE_0,
|
||||
orc: 0x00,
|
||||
def: 0x00,
|
||||
auto_acquire: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Spis<'d, T> {
|
||||
pub fn new(
|
||||
spis: impl Peripheral<P = T> + 'd,
|
||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||
cs: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
sck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
miso: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
mosi: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(cs, sck, miso, mosi);
|
||||
Self::new_inner(
|
||||
spis,
|
||||
irq,
|
||||
cs.map_into(),
|
||||
sck.map_into(),
|
||||
Some(miso.map_into()),
|
||||
Some(mosi.map_into()),
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_txonly(
|
||||
spis: impl Peripheral<P = T> + 'd,
|
||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||
cs: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
sck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
miso: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(cs, sck, miso);
|
||||
Self::new_inner(
|
||||
spis,
|
||||
irq,
|
||||
cs.map_into(),
|
||||
sck.map_into(),
|
||||
Some(miso.map_into()),
|
||||
None,
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_rxonly(
|
||||
spis: impl Peripheral<P = T> + 'd,
|
||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||
cs: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
sck: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
mosi: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(cs, sck, mosi);
|
||||
Self::new_inner(
|
||||
spis,
|
||||
irq,
|
||||
cs.map_into(),
|
||||
sck.map_into(),
|
||||
None,
|
||||
Some(mosi.map_into()),
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
fn new_inner(
|
||||
spis: impl Peripheral<P = T> + 'd,
|
||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||
cs: PeripheralRef<'d, AnyPin>,
|
||||
sck: PeripheralRef<'d, AnyPin>,
|
||||
miso: Option<PeripheralRef<'d, AnyPin>>,
|
||||
mosi: Option<PeripheralRef<'d, AnyPin>>,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
into_ref!(spis, irq, cs, sck);
|
||||
|
||||
let r = T::regs();
|
||||
|
||||
// Configure pins.
|
||||
sck.conf().write(|w| w.input().connect().drive().h0h1());
|
||||
r.psel.sck.write(|w| unsafe { w.bits(sck.psel_bits()) });
|
||||
cs.conf().write(|w| w.input().connect().drive().h0h1());
|
||||
r.psel.csn.write(|w| unsafe { w.bits(cs.psel_bits()) });
|
||||
if let Some(mosi) = &mosi {
|
||||
mosi.conf().write(|w| w.input().connect().drive().h0h1());
|
||||
r.psel.mosi.write(|w| unsafe { w.bits(mosi.psel_bits()) });
|
||||
}
|
||||
if let Some(miso) = &miso {
|
||||
miso.conf().write(|w| w.dir().output().drive().h0h1());
|
||||
r.psel.miso.write(|w| unsafe { w.bits(miso.psel_bits()) });
|
||||
}
|
||||
|
||||
// Enable SPIS instance.
|
||||
r.enable.write(|w| w.enable().enabled());
|
||||
|
||||
// Configure mode.
|
||||
let mode = config.mode;
|
||||
r.config.write(|w| {
|
||||
match mode {
|
||||
MODE_0 => {
|
||||
w.order().msb_first();
|
||||
w.cpol().active_high();
|
||||
w.cpha().leading();
|
||||
}
|
||||
MODE_1 => {
|
||||
w.order().msb_first();
|
||||
w.cpol().active_high();
|
||||
w.cpha().trailing();
|
||||
}
|
||||
MODE_2 => {
|
||||
w.order().msb_first();
|
||||
w.cpol().active_low();
|
||||
w.cpha().leading();
|
||||
}
|
||||
MODE_3 => {
|
||||
w.order().msb_first();
|
||||
w.cpol().active_low();
|
||||
w.cpha().trailing();
|
||||
}
|
||||
}
|
||||
|
||||
w
|
||||
});
|
||||
|
||||
// Set over-read character.
|
||||
let orc = config.orc;
|
||||
r.orc.write(|w| unsafe { w.orc().bits(orc) });
|
||||
|
||||
// Set default character.
|
||||
let def = config.def;
|
||||
r.def.write(|w| unsafe { w.def().bits(def) });
|
||||
|
||||
// Configure auto-acquire on 'transfer end' event.
|
||||
if config.auto_acquire {
|
||||
r.shorts.write(|w| w.end_acquire().bit(true));
|
||||
}
|
||||
|
||||
// Disable all events interrupts.
|
||||
r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
|
||||
|
||||
irq.set_handler(Self::on_interrupt);
|
||||
irq.unpend();
|
||||
irq.enable();
|
||||
|
||||
Self { _p: spis }
|
||||
}
|
||||
|
||||
fn on_interrupt(_: *mut ()) {
|
||||
let r = T::regs();
|
||||
let s = T::state();
|
||||
|
||||
if r.events_end.read().bits() != 0 {
|
||||
s.waker.wake();
|
||||
r.intenclr.write(|w| w.end().clear());
|
||||
}
|
||||
|
||||
if r.events_acquired.read().bits() != 0 {
|
||||
s.waker.wake();
|
||||
r.intenclr.write(|w| w.acquired().clear());
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
|
||||
slice_in_ram_or(tx, Error::DMABufferNotInDataMemory)?;
|
||||
// NOTE: RAM slice check for rx is not necessary, as a mutable
|
||||
// slice can only be built from data located in RAM.
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
let r = T::regs();
|
||||
|
||||
// Set up the DMA write.
|
||||
let (ptr, len) = slice_ptr_parts(tx);
|
||||
r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
|
||||
r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
|
||||
|
||||
// Set up the DMA read.
|
||||
let (ptr, len) = slice_ptr_parts_mut(rx);
|
||||
r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
|
||||
r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
|
||||
|
||||
// Reset end event.
|
||||
r.events_end.reset();
|
||||
|
||||
// Release the semaphore.
|
||||
r.tasks_release.write(|w| unsafe { w.bits(1) });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn blocking_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(usize, usize), Error> {
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
let r = T::regs();
|
||||
|
||||
// Acquire semaphore.
|
||||
if r.semstat.read().bits() != 1 {
|
||||
r.events_acquired.reset();
|
||||
r.tasks_acquire.write(|w| unsafe { w.bits(1) });
|
||||
// Wait until CPU has acquired the semaphore.
|
||||
while r.semstat.read().bits() != 1 {}
|
||||
}
|
||||
|
||||
self.prepare(rx, tx)?;
|
||||
|
||||
// Wait for 'end' event.
|
||||
while r.events_end.read().bits() == 0 {}
|
||||
|
||||
let n_rx = r.rxd.amount.read().bits() as usize;
|
||||
let n_tx = r.txd.amount.read().bits() as usize;
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
Ok((n_rx, n_tx))
|
||||
}
|
||||
|
||||
fn blocking_inner(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(usize, usize), Error> {
|
||||
match self.blocking_inner_from_ram(rx, tx) {
|
||||
Ok(n) => Ok(n),
|
||||
Err(Error::DMABufferNotInDataMemory) => {
|
||||
trace!("Copying SPIS tx buffer into RAM for DMA");
|
||||
let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..tx.len()];
|
||||
tx_ram_buf.copy_from_slice(tx);
|
||||
self.blocking_inner_from_ram(rx, tx_ram_buf)
|
||||
}
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
async fn async_inner_from_ram(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(usize, usize), Error> {
|
||||
let r = T::regs();
|
||||
let s = T::state();
|
||||
|
||||
// Clear status register.
|
||||
r.status.write(|w| w.overflow().clear().overread().clear());
|
||||
|
||||
// Acquire semaphore.
|
||||
if r.semstat.read().bits() != 1 {
|
||||
// Reset and enable the acquire event.
|
||||
r.events_acquired.reset();
|
||||
r.intenset.write(|w| w.acquired().set());
|
||||
|
||||
// Request acquiring the SPIS semaphore.
|
||||
r.tasks_acquire.write(|w| unsafe { w.bits(1) });
|
||||
|
||||
// Wait until CPU has acquired the semaphore.
|
||||
poll_fn(|cx| {
|
||||
s.waker.register(cx.waker());
|
||||
if r.events_acquired.read().bits() == 1 {
|
||||
r.events_acquired.reset();
|
||||
return Poll::Ready(());
|
||||
}
|
||||
Poll::Pending
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
self.prepare(rx, tx)?;
|
||||
|
||||
// Wait for 'end' event.
|
||||
r.intenset.write(|w| w.end().set());
|
||||
poll_fn(|cx| {
|
||||
s.waker.register(cx.waker());
|
||||
if r.events_end.read().bits() != 0 {
|
||||
r.events_end.reset();
|
||||
return Poll::Ready(());
|
||||
}
|
||||
Poll::Pending
|
||||
})
|
||||
.await;
|
||||
|
||||
let n_rx = r.rxd.amount.read().bits() as usize;
|
||||
let n_tx = r.txd.amount.read().bits() as usize;
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
Ok((n_rx, n_tx))
|
||||
}
|
||||
|
||||
async fn async_inner(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(usize, usize), Error> {
|
||||
match self.async_inner_from_ram(rx, tx).await {
|
||||
Ok(n) => Ok(n),
|
||||
Err(Error::DMABufferNotInDataMemory) => {
|
||||
trace!("Copying SPIS tx buffer into RAM for DMA");
|
||||
let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..tx.len()];
|
||||
tx_ram_buf.copy_from_slice(tx);
|
||||
self.async_inner_from_ram(rx, tx_ram_buf).await
|
||||
}
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads data from the SPI bus without sending anything. Blocks until `cs` is deasserted.
|
||||
/// Returns number of bytes read.
|
||||
pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<usize, Error> {
|
||||
self.blocking_inner(data, &[]).map(|n| n.0)
|
||||
}
|
||||
|
||||
/// Simultaneously sends and receives data. Blocks until the transmission is completed.
|
||||
/// If necessary, the write buffer will be copied into RAM (see struct description for detail).
|
||||
/// Returns number of bytes transferred `(n_rx, n_tx)`.
|
||||
pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
|
||||
self.blocking_inner(read, write)
|
||||
}
|
||||
|
||||
/// Same as [`blocking_transfer`](Spis::blocking_transfer) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
|
||||
/// Returns number of bytes transferred `(n_rx, n_tx)`.
|
||||
pub fn blocking_transfer_from_ram(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
|
||||
self.blocking_inner_from_ram(read, write)
|
||||
}
|
||||
|
||||
/// Simultaneously sends and receives data.
|
||||
/// Places the received data into the same buffer and blocks until the transmission is completed.
|
||||
/// Returns number of bytes transferred.
|
||||
pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<usize, Error> {
|
||||
self.blocking_inner_from_ram(data, data).map(|n| n.0)
|
||||
}
|
||||
|
||||
/// Sends data, discarding any received data. Blocks until the transmission is completed.
|
||||
/// If necessary, the write buffer will be copied into RAM (see struct description for detail).
|
||||
/// Returns number of bytes written.
|
||||
pub fn blocking_write(&mut self, data: &[u8]) -> Result<usize, Error> {
|
||||
self.blocking_inner(&mut [], data).map(|n| n.1)
|
||||
}
|
||||
|
||||
/// Same as [`blocking_write`](Spis::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
|
||||
/// Returns number of bytes written.
|
||||
pub fn blocking_write_from_ram(&mut self, data: &[u8]) -> Result<usize, Error> {
|
||||
self.blocking_inner_from_ram(&mut [], data).map(|n| n.1)
|
||||
}
|
||||
|
||||
/// Reads data from the SPI bus without sending anything.
|
||||
/// Returns number of bytes read.
|
||||
pub async fn read(&mut self, data: &mut [u8]) -> Result<usize, Error> {
|
||||
self.async_inner(data, &[]).await.map(|n| n.0)
|
||||
}
|
||||
|
||||
/// Simultaneously sends and receives data.
|
||||
/// If necessary, the write buffer will be copied into RAM (see struct description for detail).
|
||||
/// Returns number of bytes transferred `(n_rx, n_tx)`.
|
||||
pub async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
|
||||
self.async_inner(read, write).await
|
||||
}
|
||||
|
||||
/// Same as [`transfer`](Spis::transfer) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
|
||||
/// Returns number of bytes transferred `(n_rx, n_tx)`.
|
||||
pub async fn transfer_from_ram(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
|
||||
self.async_inner_from_ram(read, write).await
|
||||
}
|
||||
|
||||
/// Simultaneously sends and receives data. Places the received data into the same buffer.
|
||||
/// Returns number of bytes transferred.
|
||||
pub async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<usize, Error> {
|
||||
self.async_inner_from_ram(data, data).await.map(|n| n.0)
|
||||
}
|
||||
|
||||
/// Sends data, discarding any received data.
|
||||
/// If necessary, the write buffer will be copied into RAM (see struct description for detail).
|
||||
/// Returns number of bytes written.
|
||||
pub async fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
|
||||
self.async_inner(&mut [], data).await.map(|n| n.1)
|
||||
}
|
||||
|
||||
/// Same as [`write`](Spis::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
|
||||
/// Returns number of bytes written.
|
||||
pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<usize, Error> {
|
||||
self.async_inner_from_ram(&mut [], data).await.map(|n| n.1)
|
||||
}
|
||||
|
||||
/// Checks if last transaction overread.
|
||||
pub fn is_overread(&mut self) -> bool {
|
||||
T::regs().status.read().overread().is_present()
|
||||
}
|
||||
|
||||
/// Checks if last transaction overflowed.
|
||||
pub fn is_overflow(&mut self) -> bool {
|
||||
T::regs().status.read().overflow().is_present()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Drop for Spis<'d, T> {
|
||||
fn drop(&mut self) {
|
||||
trace!("spis drop");
|
||||
|
||||
// Disable
|
||||
let r = T::regs();
|
||||
r.enable.write(|w| w.enable().disabled());
|
||||
|
||||
gpio::deconfigure_pin(r.psel.sck.read().bits());
|
||||
gpio::deconfigure_pin(r.psel.csn.read().bits());
|
||||
gpio::deconfigure_pin(r.psel.miso.read().bits());
|
||||
gpio::deconfigure_pin(r.psel.mosi.read().bits());
|
||||
|
||||
trace!("spis drop: done");
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct State {
|
||||
pub waker: AtomicWaker,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
waker: AtomicWaker::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Instance {
|
||||
fn regs() -> &'static pac::spis0::RegisterBlock;
|
||||
fn state() -> &'static State;
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static {
|
||||
type Interrupt: Interrupt;
|
||||
}
|
||||
|
||||
macro_rules! impl_spis {
|
||||
($type:ident, $pac_type:ident, $irq:ident) => {
|
||||
impl crate::spis::sealed::Instance for peripherals::$type {
|
||||
fn regs() -> &'static pac::spis0::RegisterBlock {
|
||||
unsafe { &*pac::$pac_type::ptr() }
|
||||
}
|
||||
fn state() -> &'static crate::spis::sealed::State {
|
||||
static STATE: crate::spis::sealed::State = crate::spis::sealed::State::new();
|
||||
&STATE
|
||||
}
|
||||
}
|
||||
impl crate::spis::Instance for peripherals::$type {
|
||||
type Interrupt = crate::interrupt::$irq;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// ====================
|
||||
|
||||
impl<'d, T: Instance> SetConfig for Spis<'d, T> {
|
||||
type Config = Config;
|
||||
fn set_config(&mut self, config: &Self::Config) {
|
||||
let r = T::regs();
|
||||
// Configure mode.
|
||||
let mode = config.mode;
|
||||
r.config.write(|w| {
|
||||
match mode {
|
||||
MODE_0 => {
|
||||
w.order().msb_first();
|
||||
w.cpol().active_high();
|
||||
w.cpha().leading();
|
||||
}
|
||||
MODE_1 => {
|
||||
w.order().msb_first();
|
||||
w.cpol().active_high();
|
||||
w.cpha().trailing();
|
||||
}
|
||||
MODE_2 => {
|
||||
w.order().msb_first();
|
||||
w.cpol().active_low();
|
||||
w.cpha().leading();
|
||||
}
|
||||
MODE_3 => {
|
||||
w.order().msb_first();
|
||||
w.cpol().active_low();
|
||||
w.cpha().trailing();
|
||||
}
|
||||
}
|
||||
|
||||
w
|
||||
});
|
||||
|
||||
// Set over-read character.
|
||||
let orc = config.orc;
|
||||
r.orc.write(|w| unsafe { w.orc().bits(orc) });
|
||||
|
||||
// Set default character.
|
||||
let def = config.def;
|
||||
r.def.write(|w| unsafe { w.def().bits(def) });
|
||||
|
||||
// Configure auto-acquire on 'transfer end' event.
|
||||
let auto_acquire = config.auto_acquire;
|
||||
r.shorts.write(|w| w.end_acquire().bit(auto_acquire));
|
||||
}
|
||||
}
|
@ -841,39 +841,31 @@ mod eh1 {
|
||||
mod eha {
|
||||
use super::*;
|
||||
impl<'d, T: Instance> embedded_hal_async::i2c::I2c for Twim<'d, T> {
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.read(address, buffer)
|
||||
async fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Result<(), Error> {
|
||||
self.read(address, buffer).await
|
||||
}
|
||||
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.write(address, bytes)
|
||||
async fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Result<(), Error> {
|
||||
self.write(address, bytes).await
|
||||
}
|
||||
|
||||
type WriteReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write_read<'a>(
|
||||
async fn write_read<'a>(
|
||||
&'a mut self,
|
||||
address: u8,
|
||||
wr_buffer: &'a [u8],
|
||||
rd_buffer: &'a mut [u8],
|
||||
) -> Self::WriteReadFuture<'a> {
|
||||
self.write_read(address, wr_buffer, rd_buffer)
|
||||
) -> Result<(), Error> {
|
||||
self.write_read(address, wr_buffer, rd_buffer).await
|
||||
}
|
||||
|
||||
type TransactionFuture<'a, 'b> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a, 'b: 'a;
|
||||
|
||||
fn transaction<'a, 'b>(
|
||||
async fn transaction<'a, 'b>(
|
||||
&'a mut self,
|
||||
address: u8,
|
||||
operations: &'a mut [embedded_hal_async::i2c::Operation<'b>],
|
||||
) -> Self::TransactionFuture<'a, 'b> {
|
||||
) -> Result<(), Error> {
|
||||
let _ = address;
|
||||
let _ = operations;
|
||||
async move { todo!() }
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
759
embassy-nrf/src/twis.rs
Normal file
759
embassy-nrf/src/twis.rs
Normal file
@ -0,0 +1,759 @@
|
||||
#![macro_use]
|
||||
|
||||
//! HAL interface to the TWIS peripheral.
|
||||
//!
|
||||
//! See product specification:
|
||||
//!
|
||||
//! - nRF52832: Section 33
|
||||
//! - nRF52840: Section 6.31
|
||||
use core::future::{poll_fn, Future};
|
||||
use core::sync::atomic::compiler_fence;
|
||||
use core::sync::atomic::Ordering::SeqCst;
|
||||
use core::task::Poll;
|
||||
|
||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
#[cfg(feature = "time")]
|
||||
use embassy_time::{Duration, Instant};
|
||||
|
||||
use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
|
||||
use crate::gpio::Pin as GpioPin;
|
||||
use crate::interrupt::{Interrupt, InterruptExt};
|
||||
use crate::util::slice_in_ram_or;
|
||||
use crate::{gpio, pac, Peripheral};
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct Config {
|
||||
pub address0: u8,
|
||||
pub address1: Option<u8>,
|
||||
pub orc: u8,
|
||||
pub sda_high_drive: bool,
|
||||
pub sda_pullup: bool,
|
||||
pub scl_high_drive: bool,
|
||||
pub scl_pullup: bool,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
address0: 0x55,
|
||||
address1: None,
|
||||
orc: 0x00,
|
||||
scl_high_drive: false,
|
||||
sda_pullup: false,
|
||||
sda_high_drive: false,
|
||||
scl_pullup: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
enum Status {
|
||||
Read,
|
||||
Write,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
TxBufferTooLong,
|
||||
RxBufferTooLong,
|
||||
DataNack,
|
||||
Bus,
|
||||
DMABufferNotInDataMemory,
|
||||
Overflow,
|
||||
OverRead,
|
||||
Timeout,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Command {
|
||||
Read,
|
||||
WriteRead(usize),
|
||||
Write(usize),
|
||||
}
|
||||
|
||||
/// Interface to a TWIS instance using EasyDMA to offload the transmission and reception workload.
|
||||
///
|
||||
/// For more details about EasyDMA, consult the module documentation.
|
||||
pub struct Twis<'d, T: Instance> {
|
||||
_p: PeripheralRef<'d, T>,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> Twis<'d, T> {
|
||||
pub fn new(
|
||||
twis: impl Peripheral<P = T> + 'd,
|
||||
irq: impl Peripheral<P = T::Interrupt> + 'd,
|
||||
sda: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
scl: impl Peripheral<P = impl GpioPin> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
into_ref!(twis, irq, sda, scl);
|
||||
|
||||
let r = T::regs();
|
||||
|
||||
// Configure pins
|
||||
sda.conf().write(|w| {
|
||||
w.dir().input();
|
||||
w.input().connect();
|
||||
if config.sda_high_drive {
|
||||
w.drive().h0d1();
|
||||
} else {
|
||||
w.drive().s0d1();
|
||||
}
|
||||
if config.sda_pullup {
|
||||
w.pull().pullup();
|
||||
}
|
||||
w
|
||||
});
|
||||
scl.conf().write(|w| {
|
||||
w.dir().input();
|
||||
w.input().connect();
|
||||
if config.scl_high_drive {
|
||||
w.drive().h0d1();
|
||||
} else {
|
||||
w.drive().s0d1();
|
||||
}
|
||||
if config.scl_pullup {
|
||||
w.pull().pullup();
|
||||
}
|
||||
w
|
||||
});
|
||||
|
||||
// Select pins.
|
||||
r.psel.sda.write(|w| unsafe { w.bits(sda.psel_bits()) });
|
||||
r.psel.scl.write(|w| unsafe { w.bits(scl.psel_bits()) });
|
||||
|
||||
// Enable TWIS instance.
|
||||
r.enable.write(|w| w.enable().enabled());
|
||||
|
||||
// Disable all events interrupts
|
||||
r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
|
||||
|
||||
// Set address
|
||||
r.address[0].write(|w| unsafe { w.address().bits(config.address0) });
|
||||
r.config.write(|w| w.address0().enabled());
|
||||
if let Some(address1) = config.address1 {
|
||||
r.address[1].write(|w| unsafe { w.address().bits(address1) });
|
||||
r.config.modify(|_r, w| w.address1().enabled());
|
||||
}
|
||||
|
||||
// Set over-read character
|
||||
r.orc.write(|w| unsafe { w.orc().bits(config.orc) });
|
||||
|
||||
// Generate suspend on read event
|
||||
r.shorts.write(|w| w.read_suspend().enabled());
|
||||
|
||||
irq.set_handler(Self::on_interrupt);
|
||||
irq.unpend();
|
||||
irq.enable();
|
||||
|
||||
Self { _p: twis }
|
||||
}
|
||||
|
||||
fn on_interrupt(_: *mut ()) {
|
||||
let r = T::regs();
|
||||
let s = T::state();
|
||||
|
||||
if r.events_read.read().bits() != 0 || r.events_write.read().bits() != 0 {
|
||||
s.waker.wake();
|
||||
r.intenclr.modify(|_r, w| w.read().clear().write().clear());
|
||||
}
|
||||
if r.events_stopped.read().bits() != 0 {
|
||||
s.waker.wake();
|
||||
r.intenclr.modify(|_r, w| w.stopped().clear());
|
||||
}
|
||||
if r.events_error.read().bits() != 0 {
|
||||
s.waker.wake();
|
||||
r.intenclr.modify(|_r, w| w.error().clear());
|
||||
}
|
||||
}
|
||||
|
||||
/// Set TX buffer, checking that it is in RAM and has suitable length.
|
||||
unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> {
|
||||
slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?;
|
||||
|
||||
if buffer.len() > EASY_DMA_SIZE {
|
||||
return Err(Error::TxBufferTooLong);
|
||||
}
|
||||
|
||||
let r = T::regs();
|
||||
|
||||
r.txd.ptr.write(|w|
|
||||
// We're giving the register a pointer to the stack. Since we're
|
||||
// waiting for the I2C transaction to end before this stack pointer
|
||||
// becomes invalid, there's nothing wrong here.
|
||||
//
|
||||
// The PTR field is a full 32 bits wide and accepts the full range
|
||||
// of values.
|
||||
w.ptr().bits(buffer.as_ptr() as u32));
|
||||
r.txd.maxcnt.write(|w|
|
||||
// We're giving it the length of the buffer, so no danger of
|
||||
// accessing invalid memory. We have verified that the length of the
|
||||
// buffer fits in an `u8`, so the cast to `u8` is also fine.
|
||||
//
|
||||
// The MAXCNT field is 8 bits wide and accepts the full range of
|
||||
// values.
|
||||
w.maxcnt().bits(buffer.len() as _));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set RX buffer, checking that it has suitable length.
|
||||
unsafe fn set_rx_buffer(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
// NOTE: RAM slice check is not necessary, as a mutable
|
||||
// slice can only be built from data located in RAM.
|
||||
|
||||
if buffer.len() > EASY_DMA_SIZE {
|
||||
return Err(Error::RxBufferTooLong);
|
||||
}
|
||||
|
||||
let r = T::regs();
|
||||
|
||||
r.rxd.ptr.write(|w|
|
||||
// We're giving the register a pointer to the stack. Since we're
|
||||
// waiting for the I2C transaction to end before this stack pointer
|
||||
// becomes invalid, there's nothing wrong here.
|
||||
//
|
||||
// The PTR field is a full 32 bits wide and accepts the full range
|
||||
// of values.
|
||||
w.ptr().bits(buffer.as_mut_ptr() as u32));
|
||||
r.rxd.maxcnt.write(|w|
|
||||
// We're giving it the length of the buffer, so no danger of
|
||||
// accessing invalid memory. We have verified that the length of the
|
||||
// buffer fits in an `u8`, so the cast to the type of maxcnt
|
||||
// is also fine.
|
||||
//
|
||||
// Note that that nrf52840 maxcnt is a wider
|
||||
// type than a u8, so we use a `_` cast rather than a `u8` cast.
|
||||
// The MAXCNT field is thus at least 8 bits wide and accepts the
|
||||
// full range of values that fit in a `u8`.
|
||||
w.maxcnt().bits(buffer.len() as _));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn clear_errorsrc(&mut self) {
|
||||
let r = T::regs();
|
||||
r.errorsrc
|
||||
.write(|w| w.overflow().bit(true).overread().bit(true).dnack().bit(true));
|
||||
}
|
||||
|
||||
/// Returns matched address for latest command.
|
||||
pub fn address_match(&self) -> u8 {
|
||||
let r = T::regs();
|
||||
r.address[r.match_.read().bits() as usize].read().address().bits()
|
||||
}
|
||||
|
||||
/// Returns the index of the address matched in the latest command.
|
||||
pub fn address_match_index(&self) -> usize {
|
||||
T::regs().match_.read().bits() as _
|
||||
}
|
||||
|
||||
/// Wait for read, write, stop or error
|
||||
fn blocking_listen_wait(&mut self) -> Result<Status, Error> {
|
||||
let r = T::regs();
|
||||
loop {
|
||||
if r.events_error.read().bits() != 0 {
|
||||
r.events_error.reset();
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
while r.events_stopped.read().bits() == 0 {}
|
||||
return Err(Error::Overflow);
|
||||
}
|
||||
if r.events_stopped.read().bits() != 0 {
|
||||
r.events_stopped.reset();
|
||||
return Err(Error::Bus);
|
||||
}
|
||||
if r.events_read.read().bits() != 0 {
|
||||
r.events_read.reset();
|
||||
return Ok(Status::Read);
|
||||
}
|
||||
if r.events_write.read().bits() != 0 {
|
||||
r.events_write.reset();
|
||||
return Ok(Status::Write);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait for stop, repeated start or error
|
||||
fn blocking_listen_wait_end(&mut self, status: Status) -> Result<Command, Error> {
|
||||
let r = T::regs();
|
||||
loop {
|
||||
// stop if an error occured
|
||||
if r.events_error.read().bits() != 0 {
|
||||
r.events_error.reset();
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
return Err(Error::Overflow);
|
||||
} else if r.events_stopped.read().bits() != 0 {
|
||||
r.events_stopped.reset();
|
||||
return match status {
|
||||
Status::Read => Ok(Command::Read),
|
||||
Status::Write => {
|
||||
let n = r.rxd.amount.read().bits() as usize;
|
||||
Ok(Command::Write(n))
|
||||
}
|
||||
};
|
||||
} else if r.events_read.read().bits() != 0 {
|
||||
r.events_read.reset();
|
||||
let n = r.rxd.amount.read().bits() as usize;
|
||||
return Ok(Command::WriteRead(n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait for stop or error
|
||||
fn blocking_wait(&mut self) -> Result<usize, Error> {
|
||||
let r = T::regs();
|
||||
loop {
|
||||
// stop if an error occured
|
||||
if r.events_error.read().bits() != 0 {
|
||||
r.events_error.reset();
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
let errorsrc = r.errorsrc.read();
|
||||
if errorsrc.overread().is_detected() {
|
||||
return Err(Error::OverRead);
|
||||
} else if errorsrc.dnack().is_received() {
|
||||
return Err(Error::DataNack);
|
||||
} else {
|
||||
return Err(Error::Bus);
|
||||
}
|
||||
} else if r.events_stopped.read().bits() != 0 {
|
||||
r.events_stopped.reset();
|
||||
let n = r.txd.amount.read().bits() as usize;
|
||||
return Ok(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait for stop or error with timeout
|
||||
#[cfg(feature = "time")]
|
||||
fn blocking_wait_timeout(&mut self, timeout: Duration) -> Result<usize, Error> {
|
||||
let r = T::regs();
|
||||
let deadline = Instant::now() + timeout;
|
||||
loop {
|
||||
// stop if an error occured
|
||||
if r.events_error.read().bits() != 0 {
|
||||
r.events_error.reset();
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
let errorsrc = r.errorsrc.read();
|
||||
if errorsrc.overread().is_detected() {
|
||||
return Err(Error::OverRead);
|
||||
} else if errorsrc.dnack().is_received() {
|
||||
return Err(Error::DataNack);
|
||||
} else {
|
||||
return Err(Error::Bus);
|
||||
}
|
||||
} else if r.events_stopped.read().bits() != 0 {
|
||||
r.events_stopped.reset();
|
||||
let n = r.txd.amount.read().bits() as usize;
|
||||
return Ok(n);
|
||||
} else if Instant::now() > deadline {
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
return Err(Error::Timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait for read, write, stop or error with timeout
|
||||
#[cfg(feature = "time")]
|
||||
fn blocking_listen_wait_timeout(&mut self, timeout: Duration) -> Result<Status, Error> {
|
||||
let r = T::regs();
|
||||
let deadline = Instant::now() + timeout;
|
||||
loop {
|
||||
if r.events_error.read().bits() != 0 {
|
||||
r.events_error.reset();
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
while r.events_stopped.read().bits() == 0 {}
|
||||
return Err(Error::Overflow);
|
||||
}
|
||||
if r.events_stopped.read().bits() != 0 {
|
||||
r.events_stopped.reset();
|
||||
return Err(Error::Bus);
|
||||
}
|
||||
if r.events_read.read().bits() != 0 {
|
||||
r.events_read.reset();
|
||||
return Ok(Status::Read);
|
||||
}
|
||||
if r.events_write.read().bits() != 0 {
|
||||
r.events_write.reset();
|
||||
return Ok(Status::Write);
|
||||
}
|
||||
if Instant::now() > deadline {
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
return Err(Error::Timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait for stop, repeated start or error with timeout
|
||||
#[cfg(feature = "time")]
|
||||
fn blocking_listen_wait_end_timeout(&mut self, status: Status, timeout: Duration) -> Result<Command, Error> {
|
||||
let r = T::regs();
|
||||
let deadline = Instant::now() + timeout;
|
||||
loop {
|
||||
// stop if an error occured
|
||||
if r.events_error.read().bits() != 0 {
|
||||
r.events_error.reset();
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
return Err(Error::Overflow);
|
||||
} else if r.events_stopped.read().bits() != 0 {
|
||||
r.events_stopped.reset();
|
||||
return match status {
|
||||
Status::Read => Ok(Command::Read),
|
||||
Status::Write => {
|
||||
let n = r.rxd.amount.read().bits() as usize;
|
||||
Ok(Command::Write(n))
|
||||
}
|
||||
};
|
||||
} else if r.events_read.read().bits() != 0 {
|
||||
r.events_read.reset();
|
||||
let n = r.rxd.amount.read().bits() as usize;
|
||||
return Ok(Command::WriteRead(n));
|
||||
} else if Instant::now() > deadline {
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
return Err(Error::Timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait for stop or error
|
||||
fn async_wait(&mut self) -> impl Future<Output = Result<usize, Error>> {
|
||||
poll_fn(move |cx| {
|
||||
let r = T::regs();
|
||||
let s = T::state();
|
||||
|
||||
s.waker.register(cx.waker());
|
||||
|
||||
// stop if an error occured
|
||||
if r.events_error.read().bits() != 0 {
|
||||
r.events_error.reset();
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
let errorsrc = r.errorsrc.read();
|
||||
if errorsrc.overread().is_detected() {
|
||||
return Poll::Ready(Err(Error::OverRead));
|
||||
} else if errorsrc.dnack().is_received() {
|
||||
return Poll::Ready(Err(Error::DataNack));
|
||||
} else {
|
||||
return Poll::Ready(Err(Error::Bus));
|
||||
}
|
||||
} else if r.events_stopped.read().bits() != 0 {
|
||||
r.events_stopped.reset();
|
||||
let n = r.txd.amount.read().bits() as usize;
|
||||
return Poll::Ready(Ok(n));
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
})
|
||||
}
|
||||
|
||||
/// Wait for read or write
|
||||
fn async_listen_wait(&mut self) -> impl Future<Output = Result<Status, Error>> {
|
||||
poll_fn(move |cx| {
|
||||
let r = T::regs();
|
||||
let s = T::state();
|
||||
|
||||
s.waker.register(cx.waker());
|
||||
|
||||
// stop if an error occured
|
||||
if r.events_error.read().bits() != 0 {
|
||||
r.events_error.reset();
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
return Poll::Ready(Err(Error::Overflow));
|
||||
} else if r.events_read.read().bits() != 0 {
|
||||
r.events_read.reset();
|
||||
return Poll::Ready(Ok(Status::Read));
|
||||
} else if r.events_write.read().bits() != 0 {
|
||||
r.events_write.reset();
|
||||
return Poll::Ready(Ok(Status::Write));
|
||||
} else if r.events_stopped.read().bits() != 0 {
|
||||
r.events_stopped.reset();
|
||||
return Poll::Ready(Err(Error::Bus));
|
||||
}
|
||||
Poll::Pending
|
||||
})
|
||||
}
|
||||
|
||||
/// Wait for stop, repeated start or error
|
||||
fn async_listen_wait_end(&mut self, status: Status) -> impl Future<Output = Result<Command, Error>> {
|
||||
poll_fn(move |cx| {
|
||||
let r = T::regs();
|
||||
let s = T::state();
|
||||
|
||||
s.waker.register(cx.waker());
|
||||
|
||||
// stop if an error occured
|
||||
if r.events_error.read().bits() != 0 {
|
||||
r.events_error.reset();
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
return Poll::Ready(Err(Error::Overflow));
|
||||
} else if r.events_stopped.read().bits() != 0 {
|
||||
r.events_stopped.reset();
|
||||
return match status {
|
||||
Status::Read => Poll::Ready(Ok(Command::Read)),
|
||||
Status::Write => {
|
||||
let n = r.rxd.amount.read().bits() as usize;
|
||||
Poll::Ready(Ok(Command::Write(n)))
|
||||
}
|
||||
};
|
||||
} else if r.events_read.read().bits() != 0 {
|
||||
r.events_read.reset();
|
||||
let n = r.rxd.amount.read().bits() as usize;
|
||||
return Poll::Ready(Ok(Command::WriteRead(n)));
|
||||
}
|
||||
Poll::Pending
|
||||
})
|
||||
}
|
||||
|
||||
fn setup_respond_from_ram(&mut self, buffer: &[u8], inten: bool) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
|
||||
compiler_fence(SeqCst);
|
||||
|
||||
// Set up the DMA write.
|
||||
unsafe { self.set_tx_buffer(buffer)? };
|
||||
|
||||
// Clear events
|
||||
r.events_stopped.reset();
|
||||
r.events_error.reset();
|
||||
self.clear_errorsrc();
|
||||
|
||||
if inten {
|
||||
r.intenset.write(|w| w.stopped().set().error().set());
|
||||
} else {
|
||||
r.intenclr.write(|w| w.stopped().clear().error().clear());
|
||||
}
|
||||
|
||||
// Start write operation.
|
||||
r.tasks_preparetx.write(|w| unsafe { w.bits(1) });
|
||||
r.tasks_resume.write(|w| unsafe { w.bits(1) });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn setup_respond(&mut self, wr_buffer: &[u8], inten: bool) -> Result<(), Error> {
|
||||
match self.setup_respond_from_ram(wr_buffer, inten) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(Error::DMABufferNotInDataMemory) => {
|
||||
trace!("Copying TWIS tx buffer into RAM for DMA");
|
||||
let tx_ram_buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()];
|
||||
tx_ram_buf.copy_from_slice(wr_buffer);
|
||||
self.setup_respond_from_ram(&tx_ram_buf, inten)
|
||||
}
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_listen(&mut self, buffer: &mut [u8], inten: bool) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
compiler_fence(SeqCst);
|
||||
|
||||
// Set up the DMA read.
|
||||
unsafe { self.set_rx_buffer(buffer)? };
|
||||
|
||||
// Clear events
|
||||
r.events_read.reset();
|
||||
r.events_write.reset();
|
||||
r.events_stopped.reset();
|
||||
r.events_error.reset();
|
||||
self.clear_errorsrc();
|
||||
|
||||
if inten {
|
||||
r.intenset
|
||||
.write(|w| w.stopped().set().error().set().read().set().write().set());
|
||||
} else {
|
||||
r.intenclr
|
||||
.write(|w| w.stopped().clear().error().clear().read().clear().write().clear());
|
||||
}
|
||||
|
||||
// Start read operation.
|
||||
r.tasks_preparerx.write(|w| unsafe { w.bits(1) });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn setup_listen_end(&mut self, inten: bool) -> Result<(), Error> {
|
||||
let r = T::regs();
|
||||
compiler_fence(SeqCst);
|
||||
|
||||
// Clear events
|
||||
r.events_read.reset();
|
||||
r.events_write.reset();
|
||||
r.events_stopped.reset();
|
||||
r.events_error.reset();
|
||||
self.clear_errorsrc();
|
||||
|
||||
if inten {
|
||||
r.intenset.write(|w| w.stopped().set().error().set().read().set());
|
||||
} else {
|
||||
r.intenclr.write(|w| w.stopped().clear().error().clear().read().clear());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Wait for commands from an I2C master.
|
||||
/// `buffer` is provided in case master does a 'write' and is unused for 'read'.
|
||||
/// The buffer must have a length of at most 255 bytes on the nRF52832
|
||||
/// and at most 65535 bytes on the nRF52840.
|
||||
/// To know which one of the addresses were matched, call `address_match` or `address_match_index`
|
||||
pub fn blocking_listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
|
||||
self.setup_listen(buffer, false)?;
|
||||
let status = self.blocking_listen_wait()?;
|
||||
if status == Status::Write {
|
||||
self.setup_listen_end(false)?;
|
||||
let command = self.blocking_listen_wait_end(status)?;
|
||||
return Ok(command);
|
||||
}
|
||||
Ok(Command::Read)
|
||||
}
|
||||
|
||||
/// Respond to an I2C master READ command.
|
||||
/// Returns the number of bytes written.
|
||||
/// The buffer must have a length of at most 255 bytes on the nRF52832
|
||||
/// and at most 65535 bytes on the nRF52840.
|
||||
pub fn blocking_respond_to_read(&mut self, buffer: &[u8]) -> Result<usize, Error> {
|
||||
self.setup_respond(buffer, false)?;
|
||||
self.blocking_wait()
|
||||
}
|
||||
|
||||
/// Same as [`blocking_respond_to_read`](Twis::blocking_respond_to_read) but will fail instead of copying data into RAM.
|
||||
/// Consult the module level documentation to learn more.
|
||||
pub fn blocking_respond_to_read_from_ram(&mut self, buffer: &[u8]) -> Result<usize, Error> {
|
||||
self.setup_respond_from_ram(buffer, false)?;
|
||||
self.blocking_wait()
|
||||
}
|
||||
|
||||
// ===========================================
|
||||
|
||||
/// Wait for commands from an I2C master, with timeout.
|
||||
/// `buffer` is provided in case master does a 'write' and is unused for 'read'.
|
||||
/// The buffer must have a length of at most 255 bytes on the nRF52832
|
||||
/// and at most 65535 bytes on the nRF52840.
|
||||
/// To know which one of the addresses were matched, call `address_match` or `address_match_index`
|
||||
#[cfg(feature = "time")]
|
||||
pub fn blocking_listen_timeout(&mut self, buffer: &mut [u8], timeout: Duration) -> Result<Command, Error> {
|
||||
self.setup_listen(buffer, false)?;
|
||||
let status = self.blocking_listen_wait_timeout(timeout)?;
|
||||
if status == Status::Write {
|
||||
self.setup_listen_end(false)?;
|
||||
let command = self.blocking_listen_wait_end_timeout(status, timeout)?;
|
||||
return Ok(command);
|
||||
}
|
||||
Ok(Command::Read)
|
||||
}
|
||||
|
||||
/// Respond to an I2C master READ command with timeout.
|
||||
/// Returns the number of bytes written.
|
||||
/// See [`blocking_respond_to_read`].
|
||||
#[cfg(feature = "time")]
|
||||
pub fn blocking_respond_to_read_timeout(&mut self, buffer: &[u8], timeout: Duration) -> Result<usize, Error> {
|
||||
self.setup_respond(buffer, false)?;
|
||||
self.blocking_wait_timeout(timeout)
|
||||
}
|
||||
|
||||
/// Same as [`blocking_respond_to_read_timeout`](Twis::blocking_respond_to_read_timeout) but will fail instead of copying data into RAM.
|
||||
/// Consult the module level documentation to learn more.
|
||||
#[cfg(feature = "time")]
|
||||
pub fn blocking_respond_to_read_from_ram_timeout(
|
||||
&mut self,
|
||||
buffer: &[u8],
|
||||
timeout: Duration,
|
||||
) -> Result<usize, Error> {
|
||||
self.setup_respond_from_ram(buffer, false)?;
|
||||
self.blocking_wait_timeout(timeout)
|
||||
}
|
||||
|
||||
// ===========================================
|
||||
|
||||
/// Wait asynchronously for commands from an I2C master.
|
||||
/// `buffer` is provided in case master does a 'write' and is unused for 'read'.
|
||||
/// The buffer must have a length of at most 255 bytes on the nRF52832
|
||||
/// and at most 65535 bytes on the nRF52840.
|
||||
/// To know which one of the addresses were matched, call `address_match` or `address_match_index`
|
||||
pub async fn listen(&mut self, buffer: &mut [u8]) -> Result<Command, Error> {
|
||||
self.setup_listen(buffer, true)?;
|
||||
let status = self.async_listen_wait().await?;
|
||||
if status == Status::Write {
|
||||
self.setup_listen_end(true)?;
|
||||
let command = self.async_listen_wait_end(status).await?;
|
||||
return Ok(command);
|
||||
}
|
||||
Ok(Command::Read)
|
||||
}
|
||||
|
||||
/// Respond to an I2C master READ command, asynchronously.
|
||||
/// Returns the number of bytes written.
|
||||
/// The buffer must have a length of at most 255 bytes on the nRF52832
|
||||
/// and at most 65535 bytes on the nRF52840.
|
||||
pub async fn respond_to_read(&mut self, buffer: &[u8]) -> Result<usize, Error> {
|
||||
self.setup_respond(buffer, true)?;
|
||||
self.async_wait().await
|
||||
}
|
||||
|
||||
/// Same as [`respond_to_read`](Twis::respond_to_read) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
|
||||
pub async fn respond_to_read_from_ram(&mut self, buffer: &[u8]) -> Result<usize, Error> {
|
||||
self.setup_respond_from_ram(buffer, true)?;
|
||||
self.async_wait().await
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Instance> Drop for Twis<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
trace!("twis drop");
|
||||
|
||||
// TODO: check for abort
|
||||
|
||||
// disable!
|
||||
let r = T::regs();
|
||||
r.enable.write(|w| w.enable().disabled());
|
||||
|
||||
gpio::deconfigure_pin(r.psel.sda.read().bits());
|
||||
gpio::deconfigure_pin(r.psel.scl.read().bits());
|
||||
|
||||
trace!("twis drop: done");
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
use super::*;
|
||||
|
||||
pub struct State {
|
||||
pub waker: AtomicWaker,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
waker: AtomicWaker::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Instance {
|
||||
fn regs() -> &'static pac::twis0::RegisterBlock;
|
||||
fn state() -> &'static State;
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static {
|
||||
type Interrupt: Interrupt;
|
||||
}
|
||||
|
||||
macro_rules! impl_twis {
|
||||
($type:ident, $pac_type:ident, $irq:ident) => {
|
||||
impl crate::twis::sealed::Instance for peripherals::$type {
|
||||
fn regs() -> &'static pac::twis0::RegisterBlock {
|
||||
unsafe { &*pac::$pac_type::ptr() }
|
||||
}
|
||||
fn state() -> &'static crate::twis::sealed::State {
|
||||
static STATE: crate::twis::sealed::State = crate::twis::sealed::State::new();
|
||||
&STATE
|
||||
}
|
||||
}
|
||||
impl crate::twis::Instance for peripherals::$type {
|
||||
type Interrupt = crate::interrupt::$irq;
|
||||
}
|
||||
};
|
||||
}
|
@ -986,7 +986,7 @@ mod eha {
|
||||
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
async move { Ok(()) }
|
||||
}
|
||||
}
|
||||
@ -1000,7 +1000,7 @@ mod eha {
|
||||
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
async move { Ok(()) }
|
||||
}
|
||||
}
|
||||
@ -1012,4 +1012,26 @@ mod eha {
|
||||
self.read(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Read for UarteWithIdle<'d, U, T> {
|
||||
type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn read<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
self.read(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, U: Instance, T: TimerInstance> embedded_hal_async::serial::Write for UarteWithIdle<'d, U, T> {
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn write<'a>(&'a mut self, buffer: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
self.write(buffer)
|
||||
}
|
||||
|
||||
type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
|
||||
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
async move { Ok(()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![macro_use]
|
||||
|
||||
use core::future::{poll_fn, Future};
|
||||
use core::future::poll_fn;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering};
|
||||
@ -28,11 +28,7 @@ static READY_ENDPOINTS: AtomicU32 = AtomicU32::new(0);
|
||||
/// here provides a hook into determining whether it is.
|
||||
pub trait UsbSupply {
|
||||
fn is_usb_detected(&self) -> bool;
|
||||
|
||||
type UsbPowerReadyFuture<'a>: Future<Output = Result<(), ()>> + 'a
|
||||
where
|
||||
Self: 'a;
|
||||
fn wait_power_ready(&mut self) -> Self::UsbPowerReadyFuture<'_>;
|
||||
async fn wait_power_ready(&mut self) -> Result<(), ()>;
|
||||
}
|
||||
|
||||
pub struct Driver<'d, T: Instance, P: UsbSupply> {
|
||||
@ -102,8 +98,7 @@ impl UsbSupply for PowerUsb {
|
||||
regs.usbregstatus.read().vbusdetect().is_vbus_present()
|
||||
}
|
||||
|
||||
type UsbPowerReadyFuture<'a> = impl Future<Output = Result<(), ()>> + 'a where Self: 'a;
|
||||
fn wait_power_ready(&mut self) -> Self::UsbPowerReadyFuture<'_> {
|
||||
async fn wait_power_ready(&mut self) -> Result<(), ()> {
|
||||
poll_fn(move |cx| {
|
||||
POWER_WAKER.register(cx.waker());
|
||||
let regs = unsafe { &*pac::POWER::ptr() };
|
||||
@ -116,6 +111,7 @@ impl UsbSupply for PowerUsb {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,8 +143,7 @@ impl UsbSupply for &SignalledSupply {
|
||||
self.usb_detected.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
type UsbPowerReadyFuture<'a> = impl Future<Output = Result<(), ()>> + 'a where Self: 'a;
|
||||
fn wait_power_ready(&mut self) -> Self::UsbPowerReadyFuture<'_> {
|
||||
async fn wait_power_ready(&mut self) -> Result<(), ()> {
|
||||
poll_fn(move |cx| {
|
||||
POWER_WAKER.register(cx.waker());
|
||||
|
||||
@ -160,6 +155,7 @@ impl UsbSupply for &SignalledSupply {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,61 +285,52 @@ pub struct Bus<'d, T: Instance, P: UsbSupply> {
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
|
||||
type EnableFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a;
|
||||
type DisableFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a;
|
||||
type PollFuture<'a> = impl Future<Output = Event> + 'a where Self: 'a;
|
||||
type RemoteWakeupFuture<'a> = impl Future<Output = Result<(), Unsupported>> + 'a where Self: 'a;
|
||||
async fn enable(&mut self) {
|
||||
let regs = T::regs();
|
||||
|
||||
fn enable(&mut self) -> Self::EnableFuture<'_> {
|
||||
async move {
|
||||
let regs = T::regs();
|
||||
errata::pre_enable();
|
||||
|
||||
errata::pre_enable();
|
||||
regs.enable.write(|w| w.enable().enabled());
|
||||
|
||||
regs.enable.write(|w| w.enable().enabled());
|
||||
|
||||
// Wait until the peripheral is ready.
|
||||
regs.intenset.write(|w| w.usbevent().set_bit());
|
||||
poll_fn(|cx| {
|
||||
BUS_WAKER.register(cx.waker());
|
||||
if regs.eventcause.read().ready().is_ready() {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await;
|
||||
regs.eventcause.write(|w| w.ready().clear_bit_by_one());
|
||||
|
||||
errata::post_enable();
|
||||
|
||||
unsafe { NVIC::unmask(pac::Interrupt::USBD) };
|
||||
|
||||
regs.intenset.write(|w| {
|
||||
w.usbreset().set_bit();
|
||||
w.usbevent().set_bit();
|
||||
w.epdata().set_bit();
|
||||
w
|
||||
});
|
||||
|
||||
if self.usb_supply.wait_power_ready().await.is_ok() {
|
||||
// Enable the USB pullup, allowing enumeration.
|
||||
regs.usbpullup.write(|w| w.connect().enabled());
|
||||
trace!("enabled");
|
||||
// Wait until the peripheral is ready.
|
||||
regs.intenset.write(|w| w.usbevent().set_bit());
|
||||
poll_fn(|cx| {
|
||||
BUS_WAKER.register(cx.waker());
|
||||
if regs.eventcause.read().ready().is_ready() {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
trace!("usb power not ready due to usb removal");
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await;
|
||||
regs.eventcause.write(|w| w.ready().clear_bit_by_one());
|
||||
|
||||
errata::post_enable();
|
||||
|
||||
unsafe { NVIC::unmask(pac::Interrupt::USBD) };
|
||||
|
||||
regs.intenset.write(|w| {
|
||||
w.usbreset().set_bit();
|
||||
w.usbevent().set_bit();
|
||||
w.epdata().set_bit();
|
||||
w
|
||||
});
|
||||
|
||||
if self.usb_supply.wait_power_ready().await.is_ok() {
|
||||
// Enable the USB pullup, allowing enumeration.
|
||||
regs.usbpullup.write(|w| w.connect().enabled());
|
||||
trace!("enabled");
|
||||
} else {
|
||||
trace!("usb power not ready due to usb removal");
|
||||
}
|
||||
}
|
||||
|
||||
fn disable(&mut self) -> Self::DisableFuture<'_> {
|
||||
async move {
|
||||
let regs = T::regs();
|
||||
regs.enable.write(|x| x.enable().disabled());
|
||||
}
|
||||
async fn disable(&mut self) {
|
||||
let regs = T::regs();
|
||||
regs.enable.write(|x| x.enable().disabled());
|
||||
}
|
||||
|
||||
fn poll<'a>(&'a mut self) -> Self::PollFuture<'a> {
|
||||
async fn poll(&mut self) -> Event {
|
||||
poll_fn(move |cx| {
|
||||
BUS_WAKER.register(cx.waker());
|
||||
let regs = T::regs();
|
||||
@ -401,6 +388,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
|
||||
|
||||
Poll::Pending
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -493,42 +481,40 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn remote_wakeup(&mut self) -> Self::RemoteWakeupFuture<'_> {
|
||||
async move {
|
||||
let regs = T::regs();
|
||||
async fn remote_wakeup(&mut self) -> Result<(), Unsupported> {
|
||||
let regs = T::regs();
|
||||
|
||||
if regs.lowpower.read().lowpower().is_low_power() {
|
||||
errata::pre_wakeup();
|
||||
if regs.lowpower.read().lowpower().is_low_power() {
|
||||
errata::pre_wakeup();
|
||||
|
||||
regs.lowpower.write(|w| w.lowpower().force_normal());
|
||||
regs.lowpower.write(|w| w.lowpower().force_normal());
|
||||
|
||||
poll_fn(|cx| {
|
||||
BUS_WAKER.register(cx.waker());
|
||||
let regs = T::regs();
|
||||
let r = regs.eventcause.read();
|
||||
poll_fn(|cx| {
|
||||
BUS_WAKER.register(cx.waker());
|
||||
let regs = T::regs();
|
||||
let r = regs.eventcause.read();
|
||||
|
||||
if regs.events_usbreset.read().bits() != 0 {
|
||||
Poll::Ready(())
|
||||
} else if r.resume().bit() {
|
||||
Poll::Ready(())
|
||||
} else if r.usbwuallowed().bit() {
|
||||
regs.eventcause.write(|w| w.usbwuallowed().allowed());
|
||||
if regs.events_usbreset.read().bits() != 0 {
|
||||
Poll::Ready(())
|
||||
} else if r.resume().bit() {
|
||||
Poll::Ready(())
|
||||
} else if r.usbwuallowed().bit() {
|
||||
regs.eventcause.write(|w| w.usbwuallowed().allowed());
|
||||
|
||||
regs.dpdmvalue.write(|w| w.state().resume());
|
||||
regs.tasks_dpdmdrive.write(|w| w.tasks_dpdmdrive().set_bit());
|
||||
regs.dpdmvalue.write(|w| w.state().resume());
|
||||
regs.tasks_dpdmdrive.write(|w| w.tasks_dpdmdrive().set_bit());
|
||||
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await;
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await;
|
||||
|
||||
errata::post_wakeup();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
errata::post_wakeup();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,9 +580,7 @@ impl<'d, T: Instance, Dir: EndpointDir> driver::Endpoint for Endpoint<'d, T, Dir
|
||||
&self.info
|
||||
}
|
||||
|
||||
type WaitEnabledFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a;
|
||||
|
||||
fn wait_enabled(&mut self) -> Self::WaitEnabledFuture<'_> {
|
||||
async fn wait_enabled(&mut self) {
|
||||
let i = self.info.addr.index();
|
||||
assert!(i != 0);
|
||||
|
||||
@ -608,6 +592,7 @@ impl<'d, T: Instance, Dir: EndpointDir> driver::Endpoint for Endpoint<'d, T, Dir
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -712,34 +697,26 @@ unsafe fn write_dma<T: Instance>(i: usize, buf: &[u8]) {
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
|
||||
type ReadFuture<'a> = impl Future<Output = Result<usize, EndpointError>> + 'a where Self: 'a;
|
||||
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
|
||||
let i = self.info.addr.index();
|
||||
assert!(i != 0);
|
||||
|
||||
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||
async move {
|
||||
let i = self.info.addr.index();
|
||||
assert!(i != 0);
|
||||
self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?;
|
||||
|
||||
self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?;
|
||||
|
||||
unsafe { read_dma::<T>(i, buf) }
|
||||
}
|
||||
unsafe { read_dma::<T>(i, buf) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
|
||||
type WriteFuture<'a> = impl Future<Output = Result<(), EndpointError>> + 'a where Self: 'a;
|
||||
async fn write(&mut self, buf: &[u8]) -> Result<(), EndpointError> {
|
||||
let i = self.info.addr.index();
|
||||
assert!(i != 0);
|
||||
|
||||
fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||
async move {
|
||||
let i = self.info.addr.index();
|
||||
assert!(i != 0);
|
||||
self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?;
|
||||
|
||||
self.wait_data_ready().await.map_err(|_| EndpointError::Disabled)?;
|
||||
unsafe { write_dma::<T>(i, buf) }
|
||||
|
||||
unsafe { write_dma::<T>(i, buf) }
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -749,136 +726,120 @@ pub struct ControlPipe<'d, T: Instance> {
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
|
||||
type SetupFuture<'a> = impl Future<Output = [u8;8]> + 'a where Self: 'a;
|
||||
type DataOutFuture<'a> = impl Future<Output = Result<usize, EndpointError>> + 'a where Self: 'a;
|
||||
type DataInFuture<'a> = impl Future<Output = Result<(), EndpointError>> + 'a where Self: 'a;
|
||||
type AcceptFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a;
|
||||
type RejectFuture<'a> = impl Future<Output = ()> + 'a where Self: 'a;
|
||||
|
||||
fn max_packet_size(&self) -> usize {
|
||||
usize::from(self.max_packet_size)
|
||||
}
|
||||
|
||||
fn setup<'a>(&'a mut self) -> Self::SetupFuture<'a> {
|
||||
async move {
|
||||
async fn setup(&mut self) -> [u8; 8] {
|
||||
let regs = T::regs();
|
||||
|
||||
// Reset shorts
|
||||
regs.shorts.write(|w| w);
|
||||
|
||||
// Wait for SETUP packet
|
||||
regs.intenset.write(|w| w.ep0setup().set());
|
||||
poll_fn(|cx| {
|
||||
EP0_WAKER.register(cx.waker());
|
||||
let regs = T::regs();
|
||||
if regs.events_ep0setup.read().bits() != 0 {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await;
|
||||
|
||||
// Reset shorts
|
||||
regs.shorts.write(|w| w);
|
||||
regs.events_ep0setup.reset();
|
||||
|
||||
// Wait for SETUP packet
|
||||
regs.intenset.write(|w| w.ep0setup().set());
|
||||
poll_fn(|cx| {
|
||||
EP0_WAKER.register(cx.waker());
|
||||
let regs = T::regs();
|
||||
if regs.events_ep0setup.read().bits() != 0 {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await;
|
||||
let mut buf = [0; 8];
|
||||
buf[0] = regs.bmrequesttype.read().bits() as u8;
|
||||
buf[1] = regs.brequest.read().brequest().bits();
|
||||
buf[2] = regs.wvaluel.read().wvaluel().bits();
|
||||
buf[3] = regs.wvalueh.read().wvalueh().bits();
|
||||
buf[4] = regs.windexl.read().windexl().bits();
|
||||
buf[5] = regs.windexh.read().windexh().bits();
|
||||
buf[6] = regs.wlengthl.read().wlengthl().bits();
|
||||
buf[7] = regs.wlengthh.read().wlengthh().bits();
|
||||
|
||||
regs.events_ep0setup.reset();
|
||||
|
||||
let mut buf = [0; 8];
|
||||
buf[0] = regs.bmrequesttype.read().bits() as u8;
|
||||
buf[1] = regs.brequest.read().brequest().bits();
|
||||
buf[2] = regs.wvaluel.read().wvaluel().bits();
|
||||
buf[3] = regs.wvalueh.read().wvalueh().bits();
|
||||
buf[4] = regs.windexl.read().windexl().bits();
|
||||
buf[5] = regs.windexh.read().windexh().bits();
|
||||
buf[6] = regs.wlengthl.read().wlengthl().bits();
|
||||
buf[7] = regs.wlengthh.read().wlengthh().bits();
|
||||
|
||||
buf
|
||||
}
|
||||
buf
|
||||
}
|
||||
|
||||
fn data_out<'a>(&'a mut self, buf: &'a mut [u8], _first: bool, _last: bool) -> Self::DataOutFuture<'a> {
|
||||
async move {
|
||||
async fn data_out(&mut self, buf: &mut [u8], _first: bool, _last: bool) -> Result<usize, EndpointError> {
|
||||
let regs = T::regs();
|
||||
|
||||
regs.events_ep0datadone.reset();
|
||||
|
||||
// This starts a RX on EP0. events_ep0datadone notifies when done.
|
||||
regs.tasks_ep0rcvout.write(|w| w.tasks_ep0rcvout().set_bit());
|
||||
|
||||
// Wait until ready
|
||||
regs.intenset.write(|w| {
|
||||
w.usbreset().set();
|
||||
w.ep0setup().set();
|
||||
w.ep0datadone().set()
|
||||
});
|
||||
poll_fn(|cx| {
|
||||
EP0_WAKER.register(cx.waker());
|
||||
let regs = T::regs();
|
||||
if regs.events_ep0datadone.read().bits() != 0 {
|
||||
Poll::Ready(Ok(()))
|
||||
} else if regs.events_usbreset.read().bits() != 0 {
|
||||
trace!("aborted control data_out: usb reset");
|
||||
Poll::Ready(Err(EndpointError::Disabled))
|
||||
} else if regs.events_ep0setup.read().bits() != 0 {
|
||||
trace!("aborted control data_out: received another SETUP");
|
||||
Poll::Ready(Err(EndpointError::Disabled))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
regs.events_ep0datadone.reset();
|
||||
|
||||
// This starts a RX on EP0. events_ep0datadone notifies when done.
|
||||
regs.tasks_ep0rcvout.write(|w| w.tasks_ep0rcvout().set_bit());
|
||||
|
||||
// Wait until ready
|
||||
regs.intenset.write(|w| {
|
||||
w.usbreset().set();
|
||||
w.ep0setup().set();
|
||||
w.ep0datadone().set()
|
||||
});
|
||||
poll_fn(|cx| {
|
||||
EP0_WAKER.register(cx.waker());
|
||||
let regs = T::regs();
|
||||
if regs.events_ep0datadone.read().bits() != 0 {
|
||||
Poll::Ready(Ok(()))
|
||||
} else if regs.events_usbreset.read().bits() != 0 {
|
||||
trace!("aborted control data_out: usb reset");
|
||||
Poll::Ready(Err(EndpointError::Disabled))
|
||||
} else if regs.events_ep0setup.read().bits() != 0 {
|
||||
trace!("aborted control data_out: received another SETUP");
|
||||
Poll::Ready(Err(EndpointError::Disabled))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
unsafe { read_dma::<T>(0, buf) }
|
||||
}
|
||||
unsafe { read_dma::<T>(0, buf) }
|
||||
}
|
||||
|
||||
fn data_in<'a>(&'a mut self, buf: &'a [u8], _first: bool, last: bool) -> Self::DataInFuture<'a> {
|
||||
async move {
|
||||
async fn data_in(&mut self, buf: &[u8], _first: bool, last: bool) -> Result<(), EndpointError> {
|
||||
let regs = T::regs();
|
||||
regs.events_ep0datadone.reset();
|
||||
|
||||
regs.shorts.write(|w| w.ep0datadone_ep0status().bit(last));
|
||||
|
||||
// This starts a TX on EP0. events_ep0datadone notifies when done.
|
||||
unsafe { write_dma::<T>(0, buf) }
|
||||
|
||||
regs.intenset.write(|w| {
|
||||
w.usbreset().set();
|
||||
w.ep0setup().set();
|
||||
w.ep0datadone().set()
|
||||
});
|
||||
|
||||
poll_fn(|cx| {
|
||||
cx.waker().wake_by_ref();
|
||||
EP0_WAKER.register(cx.waker());
|
||||
let regs = T::regs();
|
||||
regs.events_ep0datadone.reset();
|
||||
|
||||
regs.shorts.write(|w| w.ep0datadone_ep0status().bit(last));
|
||||
|
||||
// This starts a TX on EP0. events_ep0datadone notifies when done.
|
||||
unsafe { write_dma::<T>(0, buf) }
|
||||
|
||||
regs.intenset.write(|w| {
|
||||
w.usbreset().set();
|
||||
w.ep0setup().set();
|
||||
w.ep0datadone().set()
|
||||
});
|
||||
|
||||
poll_fn(|cx| {
|
||||
cx.waker().wake_by_ref();
|
||||
EP0_WAKER.register(cx.waker());
|
||||
let regs = T::regs();
|
||||
if regs.events_ep0datadone.read().bits() != 0 {
|
||||
Poll::Ready(Ok(()))
|
||||
} else if regs.events_usbreset.read().bits() != 0 {
|
||||
trace!("aborted control data_in: usb reset");
|
||||
Poll::Ready(Err(EndpointError::Disabled))
|
||||
} else if regs.events_ep0setup.read().bits() != 0 {
|
||||
trace!("aborted control data_in: received another SETUP");
|
||||
Poll::Ready(Err(EndpointError::Disabled))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
if regs.events_ep0datadone.read().bits() != 0 {
|
||||
Poll::Ready(Ok(()))
|
||||
} else if regs.events_usbreset.read().bits() != 0 {
|
||||
trace!("aborted control data_in: usb reset");
|
||||
Poll::Ready(Err(EndpointError::Disabled))
|
||||
} else if regs.events_ep0setup.read().bits() != 0 {
|
||||
trace!("aborted control data_in: received another SETUP");
|
||||
Poll::Ready(Err(EndpointError::Disabled))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
fn accept<'a>(&'a mut self) -> Self::AcceptFuture<'a> {
|
||||
async move {
|
||||
let regs = T::regs();
|
||||
regs.tasks_ep0status.write(|w| w.tasks_ep0status().bit(true));
|
||||
}
|
||||
async fn accept(&mut self) {
|
||||
let regs = T::regs();
|
||||
regs.tasks_ep0status.write(|w| w.tasks_ep0status().bit(true));
|
||||
}
|
||||
|
||||
fn reject<'a>(&'a mut self) -> Self::RejectFuture<'a> {
|
||||
async move {
|
||||
let regs = T::regs();
|
||||
regs.tasks_ep0stall.write(|w| w.tasks_ep0stall().bit(true));
|
||||
}
|
||||
async fn reject(&mut self) {
|
||||
let regs = T::regs();
|
||||
regs.tasks_ep0stall.write(|w| w.tasks_ep0stall().bit(true));
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user