2021-05-11 03:04:59 +02:00
#![ macro_use ]
2021-03-19 04:08:44 +01:00
use core ::marker ::PhantomData ;
2021-01-18 14:22:55 +01:00
use core ::sync ::atomic ::{ compiler_fence , Ordering } ;
use core ::task ::Poll ;
2022-06-12 22:15:44 +02:00
2022-07-08 15:47:47 +02:00
use embassy_embedded_hal ::SetConfig ;
2021-07-29 13:44:51 +02:00
use embassy_hal_common ::unborrow ;
2022-06-12 22:15:44 +02:00
pub use embedded_hal_02 ::spi ::{ Mode , Phase , Polarity , MODE_0 , MODE_1 , MODE_2 , MODE_3 } ;
2021-01-18 14:22:55 +01:00
use futures ::future ::poll_fn ;
2022-06-12 22:15:44 +02:00
pub use pac ::spim0 ::frequency ::FREQUENCY_A as Frequency ;
2021-01-18 14:22:55 +01:00
2022-02-23 23:38:18 +01:00
use crate ::chip ::FORCE_COPY_BUFFER_SIZE ;
2021-03-27 03:20:58 +01:00
use crate ::gpio ::sealed ::Pin as _ ;
2022-06-12 22:15:44 +02:00
use crate ::gpio ::{ self , AnyPin , Pin as GpioPin , PselBits } ;
use crate ::interrupt ::{ Interrupt , InterruptExt } ;
use crate ::util ::{ slice_in_ram_or , slice_ptr_parts , slice_ptr_parts_mut } ;
use crate ::{ pac , Unborrow } ;
2021-01-18 14:22:55 +01: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 22:51:59 +01:00
/// Interface for the SPIM peripheral using EasyDMA to offload the transmission and reception workload.
///
2022-03-08 16:42:46 +01:00
/// For more details about EasyDMA, consult the module documentation.
2021-03-19 04:08:44 +01:00
pub struct Spim < ' d , T : Instance > {
phantom : PhantomData < & ' d mut T > ,
2021-01-18 14:22:55 +01:00
}
2021-05-11 03:04:59 +02:00
#[ non_exhaustive ]
2021-01-18 14:22:55 +01:00
pub struct Config {
pub frequency : Frequency ,
pub mode : Mode ,
pub orc : u8 ,
}
2021-05-11 03:04:59 +02:00
impl Default for Config {
fn default ( ) -> Self {
Self {
frequency : Frequency ::M1 ,
mode : MODE_0 ,
orc : 0x00 ,
}
}
}
2021-03-19 04:08:44 +01:00
impl < ' d , T : Instance > Spim < ' d , T > {
pub fn new (
2022-02-12 01:04:01 +01: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 19:59:52 +02:00
irq : impl Unborrow < Target = T ::Interrupt > + ' d ,
sck : impl Unborrow < Target = impl GpioPin > + ' d ,
2022-02-12 01:04:01 +01: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 04:08:44 +01:00
config : Config ,
) -> Self {
2022-02-12 01:04:01 +01:00
unborrow! ( irq ) ;
2021-03-19 04:08:44 +01:00
2021-04-14 16:37:10 +02:00
let r = T ::regs ( ) ;
2021-01-18 14:22:55 +01:00
2021-03-19 04:08:44 +01:00
// Configure pins
2021-03-21 20:52:20 +01:00
sck . conf ( ) . write ( | w | w . dir ( ) . output ( ) . drive ( ) . h0h1 ( ) ) ;
2022-02-12 01:04:01 +01:00
if let Some ( mosi ) = & mosi {
2021-03-27 03:20:58 +01:00
mosi . conf ( ) . write ( | w | w . dir ( ) . output ( ) . drive ( ) . h0h1 ( ) ) ;
}
2022-02-12 01:04:01 +01:00
if let Some ( miso ) = & miso {
2021-03-27 03:20:58 +01:00
miso . conf ( ) . write ( | w | w . input ( ) . connect ( ) . drive ( ) . h0h1 ( ) ) ;
}
2021-03-19 04:08:44 +01:00
match config . mode . polarity {
Polarity ::IdleHigh = > {
sck . set_high ( ) ;
2022-02-12 01:04:01 +01:00
if let Some ( mosi ) = & mosi {
2021-03-27 03:20:58 +01:00
mosi . set_high ( ) ;
}
2021-03-19 04:08:44 +01:00
}
Polarity ::IdleLow = > {
sck . set_low ( ) ;
2022-02-12 01:04:01 +01:00
if let Some ( mosi ) = & mosi {
2021-03-27 03:20:58 +01:00
mosi . set_low ( ) ;
}
2021-03-19 04:08:44 +01:00
}
}
2021-01-18 14:22:55 +01:00
// Select pins.
2021-03-21 20:52:20 +01: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 14:22:55 +01:00
// Enable SPIM instance.
r . enable . write ( | w | w . enable ( ) . enabled ( ) ) ;
// Configure mode.
let mode = config . mode ;
r . config . write ( | w | {
2021-06-03 11:38:25 +02: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 14:22:55 +01:00
}
2021-06-03 11:38:25 +02:00
2021-01-18 14:22:55 +01: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 20:00:33 +01:00
r . orc . write ( | w | unsafe { w . orc ( ) . bits ( orc ) } ) ;
2021-01-18 14:22:55 +01:00
// Disable all events interrupts
r . intenclr . write ( | w | unsafe { w . bits ( 0xFFFF_FFFF ) } ) ;
2021-04-14 16:37:10 +02:00
irq . set_handler ( Self ::on_interrupt ) ;
irq . unpend ( ) ;
irq . enable ( ) ;
2022-06-12 22:15:44 +02:00
Self { phantom : PhantomData }
2021-01-18 14:22:55 +01:00
}
2021-04-14 16:37:10 +02: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 19:27:10 +01:00
2022-01-13 20:00:33 +01:00
fn prepare ( & mut self , rx : * mut [ u8 ] , tx : * const [ u8 ] ) -> Result < ( ) , Error > {
2022-01-13 19:27:10 +01: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 22:51:59 +01:00
fn blocking_inner_from_ram ( & mut self , rx : * mut [ u8 ] , tx : * const [ u8 ] ) -> Result < ( ) , Error > {
2022-01-13 20:00:33 +01:00
self . prepare ( rx , tx ) ? ;
2022-01-13 19:27:10 +01:00
// Wait for 'end' event.
while T ::regs ( ) . events_end . read ( ) . bits ( ) = = 0 { }
compiler_fence ( Ordering ::SeqCst ) ;
Ok ( ( ) )
}
2022-02-23 22:51:59 +01: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 23:27:12 +01:00
trace! ( " Copying SPIM tx buffer into RAM for DMA " ) ;
2022-03-02 22:48:58 +01:00
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 )
2022-02-23 22:51:59 +01:00
}
Err ( error ) = > Err ( error ) ,
}
}
async fn async_inner_from_ram ( & mut self , rx : * mut [ u8 ] , tx : * const [ u8 ] ) -> Result < ( ) , Error > {
2022-01-13 20:00:33 +01:00
self . prepare ( rx , tx ) ? ;
2022-01-13 19:27:10 +01: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 20:00:33 +01:00
2022-02-23 22:51:59 +01: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 23:27:12 +01:00
trace! ( " Copying SPIM tx buffer into RAM for DMA " ) ;
2022-03-02 22:48:58 +01:00
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
2022-02-23 22:51:59 +01:00
}
Err ( error ) = > Err ( error ) ,
}
}
/// Reads data from the SPI bus without sending anything. Blocks until the buffer has been filled.
2022-01-13 20:00:33 +01:00
pub fn blocking_read ( & mut self , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
self . blocking_inner ( data , & [ ] )
}
2022-02-23 22:51:59 +01: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 20:00:33 +01:00
pub fn blocking_transfer ( & mut self , read : & mut [ u8 ] , write : & [ u8 ] ) -> Result < ( ) , Error > {
self . blocking_inner ( read , write )
}
2022-03-08 16:42:46 +01:00
/// Same as [`blocking_transfer`](Spim::blocking_transfer) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
2022-06-12 22:15:44 +02:00
pub fn blocking_transfer_from_ram ( & mut self , read : & mut [ u8 ] , write : & [ u8 ] ) -> Result < ( ) , Error > {
2022-02-23 22:51:59 +01:00
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 20:00:33 +01:00
pub fn blocking_transfer_in_place ( & mut self , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
2022-02-23 22:51:59 +01:00
self . blocking_inner_from_ram ( data , data )
2022-01-13 20:00:33 +01:00
}
2022-02-23 22:51:59 +01: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 20:00:33 +01:00
pub fn blocking_write ( & mut self , data : & [ u8 ] ) -> Result < ( ) , Error > {
self . blocking_inner ( & mut [ ] , data )
}
2022-03-08 16:42:46 +01:00
/// Same as [`blocking_write`](Spim::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
2022-02-23 22:51:59 +01:00
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 20:00:33 +01:00
pub async fn read ( & mut self , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
self . async_inner ( data , & [ ] ) . await
}
2022-02-23 22:51:59 +01:00
/// Simultaneously sends and receives data.
/// If necessary, the write buffer will be copied into RAM (see struct description for detail).
2022-01-13 20:00:33 +01:00
pub async fn transfer ( & mut self , read : & mut [ u8 ] , write : & [ u8 ] ) -> Result < ( ) , Error > {
self . async_inner ( read , write ) . await
}
2022-03-08 16:42:46 +01:00
/// Same as [`transfer`](Spim::transfer) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
2022-02-23 22:51:59 +01:00
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 20:00:33 +01:00
pub async fn transfer_in_place ( & mut self , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
2022-02-23 22:51:59 +01:00
self . async_inner_from_ram ( data , data ) . await
2022-01-13 20:00:33 +01:00
}
2022-02-23 22:51:59 +01: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 20:00:33 +01:00
pub async fn write ( & mut self , data : & [ u8 ] ) -> Result < ( ) , Error > {
self . async_inner ( & mut [ ] , data ) . await
}
2022-02-23 22:51:59 +01:00
2022-03-08 16:42:46 +01:00
/// Same as [`write`](Spim::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
2022-02-23 22:51:59 +01:00
pub async fn write_from_ram ( & mut self , data : & [ u8 ] ) -> Result < ( ) , Error > {
self . async_inner_from_ram ( & mut [ ] , data ) . await
}
2021-03-18 01:27:30 +01:00
}
2021-05-26 18:22:44 +02:00
impl < ' d , T : Instance > Drop for Spim < ' d , T > {
fn drop ( & mut self ) {
2021-12-23 13:43:14 +01:00
trace! ( " spim drop " ) ;
2021-05-26 18:22:44 +02: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 13:43:14 +01:00
trace! ( " spim drop: done " ) ;
2021-05-26 18:22:44 +02:00
}
}
2021-05-11 03:04:59 +02:00
pub ( crate ) mod sealed {
2021-09-11 01:53:53 +02:00
use embassy ::waitqueue ::AtomicWaker ;
2021-03-18 20:56:10 +01:00
use super ::* ;
2021-04-14 16:37:10 +02:00
pub struct State {
pub end_waker : AtomicWaker ,
}
impl State {
pub const fn new ( ) -> Self {
Self {
end_waker : AtomicWaker ::new ( ) ,
}
}
}
2021-03-18 20:56:10 +01:00
pub trait Instance {
2021-04-14 16:37:10 +02:00
fn regs ( ) -> & 'static pac ::spim0 ::RegisterBlock ;
fn state ( ) -> & 'static State ;
2021-03-18 20:56:10 +01:00
}
2021-01-18 14:22:55 +01:00
}
2021-05-15 00:05:32 +02:00
pub trait Instance : Unborrow < Target = Self > + sealed ::Instance + 'static {
2021-01-18 14:22:55 +01:00
type Interrupt : Interrupt ;
}
2021-05-11 03:04:59 +02:00
macro_rules ! impl_spim {
( $type :ident , $pac_type :ident , $irq :ident ) = > {
impl crate ::spim ::sealed ::Instance for peripherals ::$type {
2021-04-14 16:37:10 +02:00
fn regs ( ) -> & 'static pac ::spim0 ::RegisterBlock {
2021-05-11 03:04:59 +02:00
unsafe { & * pac ::$pac_type ::ptr ( ) }
2021-03-18 20:56:10 +01:00
}
2021-05-11 03:04:59 +02:00
fn state ( ) -> & 'static crate ::spim ::sealed ::State {
static STATE : crate ::spim ::sealed ::State = crate ::spim ::sealed ::State ::new ( ) ;
2021-04-14 16:37:10 +02:00
& STATE
}
2021-03-18 20:56:10 +01:00
}
2021-05-11 03:04:59 +02:00
impl crate ::spim ::Instance for peripherals ::$type {
type Interrupt = crate ::interrupt ::$irq ;
2021-03-18 20:56:10 +01:00
}
} ;
2021-01-18 14:22:55 +01:00
}
2022-01-13 23:56:25 +01: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 ;
}
2022-02-16 03:54:39 +01:00
impl < ' d , T : Instance > embedded_hal_1 ::spi ::blocking ::SpiBusFlush for Spim < ' d , T > {
fn flush ( & mut self ) -> Result < ( ) , Self ::Error > {
Ok ( ( ) )
2022-01-13 23:56:25 +01:00
}
2022-02-16 03:54:39 +01:00
}
2022-01-13 23:56:25 +01:00
2022-02-16 03:54:39 +01:00
impl < ' d , T : Instance > embedded_hal_1 ::spi ::blocking ::SpiBusRead < u8 > for Spim < ' d , T > {
fn read ( & mut self , words : & mut [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . blocking_transfer ( words , & [ ] )
2022-01-13 23:56:25 +01:00
}
}
2022-02-16 03:54:39 +01:00
impl < ' d , T : Instance > embedded_hal_1 ::spi ::blocking ::SpiBusWrite < u8 > for Spim < ' d , T > {
2022-01-13 23:56:25 +01:00
fn write ( & mut self , words : & [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . blocking_write ( words )
}
}
2022-02-16 03:54:39 +01:00
impl < ' d , T : Instance > embedded_hal_1 ::spi ::blocking ::SpiBus < u8 > for Spim < ' d , T > {
2022-01-13 23:56:25 +01:00
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 )
}
}
2022-02-12 00:24:04 +01:00
}
2022-02-16 03:54:39 +01:00
cfg_if ::cfg_if! {
if #[ cfg(all(feature = " unstable-traits " , feature = " nightly " )) ] {
use core ::future ::Future ;
2022-01-13 23:56:25 +01:00
2022-02-16 03:54:39 +01:00
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 ;
2022-01-13 23:56:25 +01:00
2022-02-16 03:54:39 +01:00
fn flush < ' a > ( & ' a mut self ) -> Self ::FlushFuture < ' a > {
async move { Ok ( ( ) ) }
2022-01-13 23:56:25 +01:00
}
}
2022-02-16 03:54:39 +01:00
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 ;
2022-01-13 23:56:25 +01:00
2022-02-16 03:54:39 +01:00
fn read < ' a > ( & ' a mut self , words : & ' a mut [ u8 ] ) -> Self ::ReadFuture < ' a > {
self . read ( words )
2022-01-13 23:56:25 +01:00
}
}
2022-02-16 03:54:39 +01:00
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 ;
2022-01-13 23:56:25 +01:00
2022-02-16 03:54:39 +01:00
fn write < ' a > ( & ' a mut self , data : & ' a [ u8 ] ) -> Self ::WriteFuture < ' a > {
self . write ( data )
}
2022-01-13 23:56:25 +01:00
}
2022-02-16 03:54:39 +01:00
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 ;
2022-01-13 23:56:25 +01:00
2022-02-16 03:54:39 +01:00
fn transfer < ' a > ( & ' a mut self , rx : & ' a mut [ u8 ] , tx : & ' a [ u8 ] ) -> Self ::TransferFuture < ' a > {
self . transfer ( rx , tx )
}
2022-01-13 23:56:25 +01:00
2022-02-16 03:54:39 +01:00
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 )
2022-01-13 23:56:25 +01:00
}
}
}
}
2022-07-08 15:47:47 +02:00
2022-07-09 00:00:55 +02:00
impl < ' d , T : Instance > SetConfig for Spim < ' d , T > {
type Config = Config ;
fn set_config ( & mut self , config : & Self ::Config ) {
2022-07-08 15:47:47 +02:00
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
} ) ;
// Configure frequency.
let frequency = config . frequency ;
r . frequency . write ( | w | w . frequency ( ) . variant ( frequency ) ) ;
// Set over-read character
let orc = config . orc ;
r . orc . write ( | w | unsafe { w . orc ( ) . bits ( orc ) } ) ;
}
}