2021-05-11 01:04:59 +00:00
#![ macro_use ]
2021-03-19 03:08:44 +00:00
use core ::marker ::PhantomData ;
2021-01-18 13:22:55 +00:00
use core ::sync ::atomic ::{ compiler_fence , Ordering } ;
use core ::task ::Poll ;
2021-04-14 14:37:10 +00:00
use embassy ::interrupt ::InterruptExt ;
2021-09-10 23:53:53 +00:00
use embassy ::util ::Unborrow ;
2021-07-29 11:44:51 +00:00
use embassy_hal_common ::unborrow ;
2021-01-18 13:22:55 +00:00
use futures ::future ::poll_fn ;
2022-02-23 22:38:18 +00:00
use crate ::chip ::FORCE_COPY_BUFFER_SIZE ;
2021-03-27 02:20:58 +00:00
use crate ::gpio ::sealed ::Pin as _ ;
2022-02-12 00:04:01 +00:00
use crate ::gpio ::{ self , AnyPin } ;
use crate ::gpio ::{ Pin as GpioPin , PselBits } ;
2021-05-17 09:48:58 +00:00
use crate ::interrupt ::Interrupt ;
2022-01-13 18:27:10 +00:00
use crate ::util ::{ slice_ptr_parts , slice_ptr_parts_mut } ;
2021-05-17 09:48:58 +00:00
use crate ::{ pac , util ::slice_in_ram_or } ;
2021-01-18 13:22:55 +00:00
2022-01-13 22:56:25 +00:00
pub use embedded_hal_02 ::spi ::{ Mode , Phase , Polarity , MODE_0 , MODE_1 , MODE_2 , MODE_3 } ;
2021-03-19 03:08:44 +00:00
pub use pac ::spim0 ::frequency ::FREQUENCY_A as Frequency ;
2021-01-18 13:22:55 +00:00
#[ 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 ,
}
2022-02-23 21:51:59 +00:00
/// Interface for the SPIM peripheral using EasyDMA to offload the transmission and reception workload.
///
/// ## Data locality requirements
///
/// On nRF chips, EasyDMA requires the buffers to reside in RAM. However, Rust
/// slices will not always do so. Take the following example:
///
/// ```no_run
/// // As we pass a slice to the function whose contents will not ever change,
/// // the compiler writes it into the flash and thus the pointer to it will
/// // reference static memory. Since EasyDMA requires slices to reside in RAM,
/// // this function call will fail.
/// let result = spim.write_from_ram(&[1, 2, 3]);
/// assert_eq!(result, Error::DMABufferNotInDataMemory);
///
/// // The data is still static and located in flash. However, since we are assigning
/// // it to a variable, the compiler will load it into memory. Passing a reference to the
/// // variable will yield a pointer that references dynamic memory, thus making EasyDMA happy.
/// // This function call succeeds.
/// let data = [1, 2, 3];
/// let result = spim.write_from_ram(&data);
/// assert!(result.is_ok());
/// ```
///
/// Each function in this struct has a `_from_ram` variant and one without this suffix.
/// - Functions with the suffix (e.g. [`write_from_ram`](Spim::write_from_ram), [`transfer_from_ram`](Spim::transfer_from_ram)) will return an error if the passed slice does not reside in RAM.
/// - Functions without the suffix (e.g. [`write`](Spim::write), [`transfer`](Spim::transfer)) will check whether the data is in RAM and copy it into memory prior to transmission.
///
/// Since copying incurs a overhead, you are given the option to choose from `_from_ram` variants which will
/// fail and notify you, or the more convenient versions without the suffix which are potentially a little bit
/// more inefficient.
///
/// Note that the [`read`](Spim::read) and [`transfer_in_place`](Spim::transfer_in_place) methods do not have the corresponding `_from_ram` variants as
/// mutable slices always reside in RAM.
2021-03-19 03:08:44 +00:00
pub struct Spim < ' d , T : Instance > {
phantom : PhantomData < & ' d mut T > ,
2021-01-18 13:22:55 +00:00
}
2021-05-11 01:04:59 +00:00
#[ non_exhaustive ]
2021-01-18 13:22:55 +00:00
pub struct Config {
pub frequency : Frequency ,
pub mode : Mode ,
pub orc : u8 ,
}
2021-05-11 01:04:59 +00:00
impl Default for Config {
fn default ( ) -> Self {
Self {
frequency : Frequency ::M1 ,
mode : MODE_0 ,
orc : 0x00 ,
}
}
}
2021-03-19 03:08:44 +00:00
impl < ' d , T : Instance > Spim < ' d , T > {
pub fn new (
2022-02-12 00:04:01 +00:00
spim : impl Unborrow < Target = T > + ' d ,
irq : impl Unborrow < Target = T ::Interrupt > + ' d ,
sck : impl Unborrow < Target = impl GpioPin > + ' d ,
miso : impl Unborrow < Target = impl GpioPin > + ' d ,
mosi : impl Unborrow < Target = impl GpioPin > + ' d ,
config : Config ,
) -> Self {
unborrow! ( sck , miso , mosi ) ;
Self ::new_inner (
spim ,
irq ,
sck . degrade ( ) ,
Some ( miso . degrade ( ) ) ,
Some ( mosi . degrade ( ) ) ,
config ,
)
}
pub fn new_txonly (
spim : impl Unborrow < Target = T > + ' d ,
2021-04-14 17:59:52 +00:00
irq : impl Unborrow < Target = T ::Interrupt > + ' d ,
sck : impl Unborrow < Target = impl GpioPin > + ' d ,
2022-02-12 00:04:01 +00:00
mosi : impl Unborrow < Target = impl GpioPin > + ' d ,
config : Config ,
) -> Self {
unborrow! ( sck , mosi ) ;
Self ::new_inner ( spim , irq , sck . degrade ( ) , None , Some ( mosi . degrade ( ) ) , config )
}
pub fn new_rxonly (
spim : impl Unborrow < Target = T > + ' d ,
irq : impl Unborrow < Target = T ::Interrupt > + ' d ,
sck : impl Unborrow < Target = impl GpioPin > + ' d ,
miso : impl Unborrow < Target = impl GpioPin > + ' d ,
config : Config ,
) -> Self {
unborrow! ( sck , miso ) ;
Self ::new_inner ( spim , irq , sck . degrade ( ) , Some ( miso . degrade ( ) ) , None , config )
}
fn new_inner (
_spim : impl Unborrow < Target = T > + ' d ,
irq : impl Unborrow < Target = T ::Interrupt > + ' d ,
sck : AnyPin ,
miso : Option < AnyPin > ,
mosi : Option < AnyPin > ,
2021-03-19 03:08:44 +00:00
config : Config ,
) -> Self {
2022-02-12 00:04:01 +00:00
unborrow! ( irq ) ;
2021-03-19 03:08:44 +00:00
2021-04-14 14:37:10 +00:00
let r = T ::regs ( ) ;
2021-01-18 13:22:55 +00:00
2021-03-19 03:08:44 +00:00
// Configure pins
2021-03-21 19:52:20 +00:00
sck . conf ( ) . write ( | w | w . dir ( ) . output ( ) . drive ( ) . h0h1 ( ) ) ;
2022-02-12 00:04:01 +00:00
if let Some ( mosi ) = & mosi {
2021-03-27 02:20:58 +00:00
mosi . conf ( ) . write ( | w | w . dir ( ) . output ( ) . drive ( ) . h0h1 ( ) ) ;
}
2022-02-12 00:04:01 +00:00
if let Some ( miso ) = & miso {
2021-03-27 02:20:58 +00:00
miso . conf ( ) . write ( | w | w . input ( ) . connect ( ) . drive ( ) . h0h1 ( ) ) ;
}
2021-03-19 03:08:44 +00:00
match config . mode . polarity {
Polarity ::IdleHigh = > {
sck . set_high ( ) ;
2022-02-12 00:04:01 +00:00
if let Some ( mosi ) = & mosi {
2021-03-27 02:20:58 +00:00
mosi . set_high ( ) ;
}
2021-03-19 03:08:44 +00:00
}
Polarity ::IdleLow = > {
sck . set_low ( ) ;
2022-02-12 00:04:01 +00:00
if let Some ( mosi ) = & mosi {
2021-03-27 02:20:58 +00:00
mosi . set_low ( ) ;
}
2021-03-19 03:08:44 +00:00
}
}
2021-01-18 13:22:55 +00:00
// Select pins.
2021-03-21 19:52:20 +00:00
r . psel . sck . write ( | w | unsafe { w . bits ( sck . psel_bits ( ) ) } ) ;
r . psel . mosi . write ( | w | unsafe { w . bits ( mosi . psel_bits ( ) ) } ) ;
r . psel . miso . write ( | w | unsafe { w . bits ( miso . psel_bits ( ) ) } ) ;
2021-01-18 13:22:55 +00:00
// Enable SPIM instance.
r . enable . write ( | w | w . enable ( ) . enabled ( ) ) ;
// Configure mode.
let mode = config . mode ;
r . config . write ( | w | {
2021-06-03 09:38:25 +00:00
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 ( ) ;
}
2021-01-18 13:22:55 +00:00
}
2021-06-03 09:38:25 +00:00
2021-01-18 13:22:55 +00:00
w
} ) ;
// Configure frequency.
let frequency = config . frequency ;
r . frequency . write ( | w | w . frequency ( ) . variant ( frequency ) ) ;
// Set over-read character
let orc = config . orc ;
2022-01-13 19:00:33 +00:00
r . orc . write ( | w | unsafe { w . orc ( ) . bits ( orc ) } ) ;
2021-01-18 13:22:55 +00:00
// Disable all events interrupts
r . intenclr . write ( | w | unsafe { w . bits ( 0xFFFF_FFFF ) } ) ;
2021-04-14 14:37:10 +00:00
irq . set_handler ( Self ::on_interrupt ) ;
irq . unpend ( ) ;
irq . enable ( ) ;
2021-01-18 13:22:55 +00:00
Self {
2021-03-19 03:08:44 +00:00
phantom : PhantomData ,
2021-01-18 13:22:55 +00:00
}
}
2021-04-14 14:37:10 +00:00
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 ( ) ) ;
}
}
2022-01-13 18:27:10 +00:00
2022-01-13 19:00:33 +00:00
fn prepare ( & mut self , rx : * mut [ u8 ] , tx : * const [ u8 ] ) -> Result < ( ) , Error > {
2022-01-13 18:27:10 +00:00
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 and enable the event
r . events_end . reset ( ) ;
r . intenset . write ( | w | w . end ( ) . set ( ) ) ;
// Start SPI transaction.
r . tasks_start . write ( | w | unsafe { w . bits ( 1 ) } ) ;
Ok ( ( ) )
}
2022-02-23 21:51:59 +00:00
fn blocking_inner_from_ram ( & mut self , rx : * mut [ u8 ] , tx : * const [ u8 ] ) -> Result < ( ) , Error > {
2022-01-13 19:00:33 +00:00
self . prepare ( rx , tx ) ? ;
2022-01-13 18:27:10 +00:00
// Wait for 'end' event.
while T ::regs ( ) . events_end . read ( ) . bits ( ) = = 0 { }
compiler_fence ( Ordering ::SeqCst ) ;
Ok ( ( ) )
}
2022-02-23 21:51:59 +00:00
fn blocking_inner ( & mut self , rx : & mut [ u8 ] , tx : & [ u8 ] ) -> Result < ( ) , Error > {
match self . blocking_inner_from_ram ( rx , tx ) {
Ok ( _ ) = > Ok ( ( ) ) ,
Err ( Error ::DMABufferNotInDataMemory ) = > {
2022-02-23 22:27:12 +00:00
trace! ( " Copying SPIM tx buffer into RAM for DMA " ) ;
2022-02-23 22:38:18 +00:00
let mut tx_buf = [ 0 u8 ; FORCE_COPY_BUFFER_SIZE ] ;
tx_buf [ .. tx . len ( ) ] . copy_from_slice ( tx ) ;
self . blocking_inner_from_ram ( rx , & tx_buf [ .. tx . len ( ) ] )
2022-02-23 21:51:59 +00:00
}
Err ( error ) = > Err ( error ) ,
}
}
async fn async_inner_from_ram ( & mut self , rx : * mut [ u8 ] , tx : * const [ u8 ] ) -> Result < ( ) , Error > {
2022-01-13 19:00:33 +00:00
self . prepare ( rx , tx ) ? ;
2022-01-13 18:27:10 +00:00
// Wait for 'end' event.
poll_fn ( | cx | {
T ::state ( ) . end_waker . register ( cx . waker ( ) ) ;
if T ::regs ( ) . events_end . read ( ) . bits ( ) ! = 0 {
return Poll ::Ready ( ( ) ) ;
}
Poll ::Pending
} )
. await ;
compiler_fence ( Ordering ::SeqCst ) ;
Ok ( ( ) )
}
2022-01-13 19:00:33 +00:00
2022-02-23 21:51:59 +00:00
async fn async_inner ( & mut self , rx : & mut [ u8 ] , tx : & [ u8 ] ) -> Result < ( ) , Error > {
match self . async_inner_from_ram ( rx , tx ) . await {
Ok ( _ ) = > Ok ( ( ) ) ,
Err ( Error ::DMABufferNotInDataMemory ) = > {
2022-02-23 22:27:12 +00:00
trace! ( " Copying SPIM tx buffer into RAM for DMA " ) ;
2022-02-23 22:38:18 +00:00
let mut tx_buf = [ 0 u8 ; FORCE_COPY_BUFFER_SIZE ] ;
tx_buf [ .. tx . len ( ) ] . copy_from_slice ( tx ) ;
self . async_inner_from_ram ( rx , & tx_buf [ .. tx . len ( ) ] ) . await
2022-02-23 21:51:59 +00:00
}
Err ( error ) = > Err ( error ) ,
}
}
/// Reads data from the SPI bus without sending anything. Blocks until the buffer has been filled.
2022-01-13 19:00:33 +00:00
pub fn blocking_read ( & mut self , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
self . blocking_inner ( data , & [ ] )
}
2022-02-23 21:51:59 +00:00
/// 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).
2022-01-13 19:00:33 +00:00
pub fn blocking_transfer ( & mut self , read : & mut [ u8 ] , write : & [ u8 ] ) -> Result < ( ) , Error > {
self . blocking_inner ( read , write )
}
2022-02-23 21:51:59 +00:00
/// Same as [`blocking_transfer`](Spim::blocking_transfer) but will fail instead of copying data into RAM.
pub fn blocking_transfer_from_ram (
& mut self ,
read : & mut [ u8 ] ,
write : & [ u8 ] ,
) -> Result < ( ) , Error > {
self . blocking_inner ( read , write )
}
/// Simultaneously sends and receives data.
/// Places the received data into the same buffer and blocks until the transmission is completed.
2022-01-13 19:00:33 +00:00
pub fn blocking_transfer_in_place ( & mut self , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
2022-02-23 21:51:59 +00:00
self . blocking_inner_from_ram ( data , data )
2022-01-13 19:00:33 +00:00
}
2022-02-23 21:51:59 +00:00
/// 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).
2022-01-13 19:00:33 +00:00
pub fn blocking_write ( & mut self , data : & [ u8 ] ) -> Result < ( ) , Error > {
self . blocking_inner ( & mut [ ] , data )
}
2022-02-23 21:51:59 +00:00
/// Same as [`blocking_write`](Spim::blocking_write) but will fail instead of copying data into RAM.
pub fn blocking_write_from_ram ( & mut self , data : & [ u8 ] ) -> Result < ( ) , Error > {
self . blocking_inner ( & mut [ ] , data )
}
/// Reads data from the SPI bus without sending anything.
2022-01-13 19:00:33 +00:00
pub async fn read ( & mut self , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
self . async_inner ( data , & [ ] ) . await
}
2022-02-23 21:51:59 +00:00
/// Simultaneously sends and receives data.
/// If necessary, the write buffer will be copied into RAM (see struct description for detail).
2022-01-13 19:00:33 +00:00
pub async fn transfer ( & mut self , read : & mut [ u8 ] , write : & [ u8 ] ) -> Result < ( ) , Error > {
self . async_inner ( read , write ) . await
}
2022-02-23 21:51:59 +00:00
/// Same as [`transfer`](Spim::transfer) but will fail instead of copying data into RAM.
pub async fn transfer_from_ram ( & mut self , read : & mut [ u8 ] , write : & [ u8 ] ) -> Result < ( ) , Error > {
self . async_inner_from_ram ( read , write ) . await
}
/// Simultaneously sends and receives data. Places the received data into the same buffer.
2022-01-13 19:00:33 +00:00
pub async fn transfer_in_place ( & mut self , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
2022-02-23 21:51:59 +00:00
self . async_inner_from_ram ( data , data ) . await
2022-01-13 19:00:33 +00:00
}
2022-02-23 21:51:59 +00:00
/// Sends data, discarding any received data.
/// If necessary, the write buffer will be copied into RAM (see struct description for detail).
2022-01-13 19:00:33 +00:00
pub async fn write ( & mut self , data : & [ u8 ] ) -> Result < ( ) , Error > {
self . async_inner ( & mut [ ] , data ) . await
}
2022-02-23 21:51:59 +00:00
/// Same as [`write`](Spim::write) but will fail instead of copying data into RAM.
pub async fn write_from_ram ( & mut self , data : & [ u8 ] ) -> Result < ( ) , Error > {
self . async_inner_from_ram ( & mut [ ] , data ) . await
}
2021-03-18 00:27:30 +00:00
}
2021-05-26 16:22:44 +00:00
impl < ' d , T : Instance > Drop for Spim < ' d , T > {
fn drop ( & mut self ) {
2021-12-23 12:43:14 +00:00
trace! ( " spim drop " ) ;
2021-05-26 16:22:44 +00:00
// TODO check for abort, wait for xxxstopped
// 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 . miso . read ( ) . bits ( ) ) ;
gpio ::deconfigure_pin ( r . psel . mosi . read ( ) . bits ( ) ) ;
2021-12-23 12:43:14 +00:00
trace! ( " spim drop: done " ) ;
2021-05-26 16:22:44 +00:00
}
}
2021-05-11 01:04:59 +00:00
pub ( crate ) mod sealed {
2021-09-10 23:53:53 +00:00
use embassy ::waitqueue ::AtomicWaker ;
2021-03-18 19:56:10 +00:00
use super ::* ;
2021-04-14 14:37:10 +00:00
pub struct State {
pub end_waker : AtomicWaker ,
}
impl State {
pub const fn new ( ) -> Self {
Self {
end_waker : AtomicWaker ::new ( ) ,
}
}
}
2021-03-18 19:56:10 +00:00
pub trait Instance {
2021-04-14 14:37:10 +00:00
fn regs ( ) -> & 'static pac ::spim0 ::RegisterBlock ;
fn state ( ) -> & 'static State ;
2021-03-18 19:56:10 +00:00
}
2021-01-18 13:22:55 +00:00
}
2021-05-14 22:05:32 +00:00
pub trait Instance : Unborrow < Target = Self > + sealed ::Instance + 'static {
2021-01-18 13:22:55 +00:00
type Interrupt : Interrupt ;
}
2021-05-11 01:04:59 +00:00
macro_rules ! impl_spim {
( $type :ident , $pac_type :ident , $irq :ident ) = > {
impl crate ::spim ::sealed ::Instance for peripherals ::$type {
2021-04-14 14:37:10 +00:00
fn regs ( ) -> & 'static pac ::spim0 ::RegisterBlock {
2021-05-11 01:04:59 +00:00
unsafe { & * pac ::$pac_type ::ptr ( ) }
2021-03-18 19:56:10 +00:00
}
2021-05-11 01:04:59 +00:00
fn state ( ) -> & 'static crate ::spim ::sealed ::State {
static STATE : crate ::spim ::sealed ::State = crate ::spim ::sealed ::State ::new ( ) ;
2021-04-14 14:37:10 +00:00
& STATE
}
2021-03-18 19:56:10 +00:00
}
2021-05-11 01:04:59 +00:00
impl crate ::spim ::Instance for peripherals ::$type {
type Interrupt = crate ::interrupt ::$irq ;
2021-03-18 19:56:10 +00:00
}
} ;
2021-01-18 13:22:55 +00:00
}
2022-01-13 22:56:25 +00:00
// ====================
mod eh02 {
use super ::* ;
impl < ' d , T : Instance > embedded_hal_02 ::blocking ::spi ::Transfer < u8 > for Spim < ' d , T > {
type Error = Error ;
fn transfer < ' w > ( & mut self , words : & ' w mut [ u8 ] ) -> Result < & ' w [ u8 ] , Self ::Error > {
self . blocking_transfer_in_place ( words ) ? ;
Ok ( words )
}
}
impl < ' d , T : Instance > embedded_hal_02 ::blocking ::spi ::Write < u8 > for Spim < ' d , T > {
type Error = Error ;
fn write ( & mut self , words : & [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . blocking_write ( words )
}
}
}
#[ cfg(feature = " unstable-traits " ) ]
mod eh1 {
use super ::* ;
impl embedded_hal_1 ::spi ::Error for Error {
fn kind ( & self ) -> embedded_hal_1 ::spi ::ErrorKind {
match * self {
Self ::TxBufferTooLong = > embedded_hal_1 ::spi ::ErrorKind ::Other ,
Self ::RxBufferTooLong = > embedded_hal_1 ::spi ::ErrorKind ::Other ,
Self ::DMABufferNotInDataMemory = > embedded_hal_1 ::spi ::ErrorKind ::Other ,
}
}
}
impl < ' d , T : Instance > embedded_hal_1 ::spi ::ErrorType for Spim < ' d , T > {
type Error = Error ;
}
impl < ' d , T : Instance > embedded_hal_1 ::spi ::blocking ::Read < u8 > for Spim < ' d , T > {
fn read ( & mut self , words : & mut [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . blocking_transfer ( words , & [ ] )
}
fn read_transaction ( & mut self , words : & mut [ & mut [ u8 ] ] ) -> Result < ( ) , Self ::Error > {
for buf in words {
self . blocking_read ( buf ) ?
}
Ok ( ( ) )
}
}
impl < ' d , T : Instance > embedded_hal_1 ::spi ::blocking ::Write < u8 > for Spim < ' d , T > {
fn write ( & mut self , words : & [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . blocking_write ( words )
}
fn write_transaction ( & mut self , words : & [ & [ u8 ] ] ) -> Result < ( ) , Self ::Error > {
for buf in words {
self . blocking_write ( buf ) ?
}
Ok ( ( ) )
}
fn write_iter < WI > ( & mut self , words : WI ) -> Result < ( ) , Self ::Error >
where
WI : IntoIterator < Item = u8 > ,
{
for w in words {
self . blocking_write ( & [ w ] ) ? ;
}
Ok ( ( ) )
}
}
impl < ' d , T : Instance > embedded_hal_1 ::spi ::blocking ::ReadWrite < u8 > for Spim < ' d , T > {
fn transfer ( & mut self , read : & mut [ u8 ] , write : & [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . blocking_transfer ( read , write )
}
fn transfer_in_place ( & mut self , words : & mut [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . blocking_transfer_in_place ( words )
}
fn transaction < ' a > (
& mut self ,
2022-02-11 23:24:04 +00:00
operations : & mut [ embedded_hal_1 ::spi ::blocking ::Operation < ' a , u8 > ] ,
2022-01-13 22:56:25 +00:00
) -> Result < ( ) , Self ::Error > {
use embedded_hal_1 ::spi ::blocking ::Operation ;
for o in operations {
match o {
Operation ::Read ( b ) = > self . blocking_read ( b ) ? ,
Operation ::Write ( b ) = > self . blocking_write ( b ) ? ,
Operation ::Transfer ( r , w ) = > self . blocking_transfer ( r , w ) ? ,
Operation ::TransferInPlace ( b ) = > self . blocking_transfer_in_place ( b ) ? ,
}
}
Ok ( ( ) )
}
}
2022-02-11 23:24:04 +00:00
}
#[ cfg(all(feature = " unstable-traits " , feature = " nightly " )) ]
mod eh1a {
use super ::* ;
use core ::future ::Future ;
2022-01-13 22:56:25 +00:00
impl < ' d , T : Instance > embedded_hal_async ::spi ::Read < u8 > for Spim < ' d , T > {
type ReadFuture < ' a >
where
Self : ' a ,
= impl Future < Output = Result < ( ) , Self ::Error > > + ' a ;
fn read < ' a > ( & ' a mut self , words : & ' a mut [ u8 ] ) -> Self ::ReadFuture < ' a > {
self . read ( words )
}
type ReadTransactionFuture < ' a >
where
Self : ' a ,
= impl Future < Output = Result < ( ) , Self ::Error > > + ' a ;
fn read_transaction < ' a > (
& ' a mut self ,
words : & ' a mut [ & ' a mut [ u8 ] ] ,
) -> Self ::ReadTransactionFuture < ' a > {
async move {
for buf in words {
self . read ( buf ) . await ?
}
Ok ( ( ) )
}
}
}
impl < ' d , T : Instance > embedded_hal_async ::spi ::Write < u8 > for Spim < ' d , T > {
type WriteFuture < ' a >
where
Self : ' a ,
= impl Future < Output = Result < ( ) , Self ::Error > > + ' a ;
fn write < ' a > ( & ' a mut self , data : & ' a [ u8 ] ) -> Self ::WriteFuture < ' a > {
self . write ( data )
}
type WriteTransactionFuture < ' a >
where
Self : ' a ,
= impl Future < Output = Result < ( ) , Self ::Error > > + ' a ;
fn write_transaction < ' a > (
& ' a mut self ,
words : & ' a [ & ' a [ u8 ] ] ,
) -> Self ::WriteTransactionFuture < ' a > {
async move {
for buf in words {
self . write ( buf ) . await ?
}
Ok ( ( ) )
}
}
}
impl < ' d , T : Instance > embedded_hal_async ::spi ::ReadWrite < u8 > for Spim < ' d , T > {
type TransferFuture < ' a >
where
Self : ' a ,
= impl Future < Output = Result < ( ) , Self ::Error > > + ' a ;
fn transfer < ' a > ( & ' a mut self , rx : & ' a mut [ u8 ] , tx : & ' a [ u8 ] ) -> Self ::TransferFuture < ' a > {
self . transfer ( rx , tx )
}
type TransferInPlaceFuture < ' a >
where
Self : ' a ,
= impl Future < Output = Result < ( ) , Self ::Error > > + ' a ;
fn transfer_in_place < ' a > (
& ' a mut self ,
words : & ' a mut [ u8 ] ,
) -> Self ::TransferInPlaceFuture < ' a > {
self . transfer_in_place ( words )
}
type TransactionFuture < ' a >
where
Self : ' a ,
= impl Future < Output = Result < ( ) , Self ::Error > > + ' a ;
fn transaction < ' a > (
& ' a mut self ,
operations : & ' a mut [ embedded_hal_async ::spi ::Operation < ' a , u8 > ] ,
) -> Self ::TransactionFuture < ' a > {
use embedded_hal_1 ::spi ::blocking ::Operation ;
async move {
for o in operations {
match o {
Operation ::Read ( b ) = > self . read ( b ) . await ? ,
Operation ::Write ( b ) = > self . write ( b ) . await ? ,
Operation ::Transfer ( r , w ) = > self . transfer ( r , w ) . await ? ,
Operation ::TransferInPlace ( b ) = > self . transfer_in_place ( b ) . await ? ,
}
}
Ok ( ( ) )
}
}
}
}