2023-02-01 00:48:33 +01:00
//! Serial Peripheral Instance in master mode (SPIM) driver.
2021-05-11 03:04:59 +02:00
#![ macro_use ]
2022-09-22 16:42:49 +02:00
use core ::future ::poll_fn ;
2023-03-05 22:00:52 +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 ;
2022-07-23 14:00:19 +02:00
use embassy_hal_common ::{ into_ref , PeripheralRef } ;
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 } ;
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 } ;
2023-06-01 02:22:46 +02:00
use crate ::interrupt ::{ self , Interrupt } ;
2022-06-12 22:15:44 +02:00
use crate ::util ::{ slice_in_ram_or , slice_ptr_parts , slice_ptr_parts_mut } ;
2022-07-23 14:00:19 +02:00
use crate ::{ pac , Peripheral } ;
2021-01-18 14:22:55 +01:00
2023-02-01 00:48:33 +01:00
/// SPIM error
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 {
2023-02-01 00:48:33 +01:00
/// TX buffer was too long.
2021-01-18 14:22:55 +01:00
TxBufferTooLong ,
2023-02-01 00:48:33 +01:00
/// RX buffer was too long.
2021-01-18 14:22:55 +01:00
RxBufferTooLong ,
/// EasyDMA can only read from data memory, read only buffers in flash will fail.
2023-02-01 00:48:33 +01:00
BufferNotInRAM ,
2021-01-18 14:22:55 +01:00
}
2023-02-01 00:48:33 +01:00
/// SPIM configuration.
2021-05-11 03:04:59 +02:00
#[ non_exhaustive ]
2021-01-18 14:22:55 +01:00
pub struct Config {
2023-02-01 00:48:33 +01:00
/// Frequency
2021-01-18 14:22:55 +01:00
pub frequency : Frequency ,
2023-02-01 00:48:33 +01:00
/// SPI mode
2021-01-18 14:22:55 +01:00
pub mode : Mode ,
2023-02-01 00:48:33 +01:00
/// Overread character.
///
/// When doing bidirectional transfers, if the TX buffer is shorter than the RX buffer,
/// this byte will be transmitted in the MOSI line for the left-over bytes.
2021-01-18 14:22:55 +01:00
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 ,
}
}
}
2023-03-05 22:00:52 +01:00
/// Interrupt handler.
pub struct InterruptHandler < T : Instance > {
_phantom : PhantomData < T > ,
}
impl < T : Instance > interrupt ::Handler < T ::Interrupt > for InterruptHandler < T > {
unsafe fn on_interrupt ( ) {
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 ( ) ) ;
}
}
}
/// SPIM driver.
pub struct Spim < ' d , T : Instance > {
_p : PeripheralRef < ' d , T > ,
}
2021-03-19 04:08:44 +01:00
impl < ' d , T : Instance > Spim < ' d , T > {
2023-02-01 00:48:33 +01:00
/// Create a new SPIM driver.
2021-03-19 04:08:44 +01:00
pub fn new (
2022-07-23 14:00:19 +02:00
spim : impl Peripheral < P = T > + ' d ,
2023-03-05 22:00:52 +01:00
_irq : impl interrupt ::Binding < T ::Interrupt , InterruptHandler < T > > + ' d ,
2022-07-23 14:00:19 +02:00
sck : impl Peripheral < P = impl GpioPin > + ' d ,
miso : impl Peripheral < P = impl GpioPin > + ' d ,
mosi : impl Peripheral < P = impl GpioPin > + ' d ,
2022-02-12 01:04:01 +01:00
config : Config ,
) -> Self {
2022-07-23 14:27:45 +02:00
into_ref! ( sck , miso , mosi ) ;
Self ::new_inner (
spim ,
sck . map_into ( ) ,
Some ( miso . map_into ( ) ) ,
Some ( mosi . map_into ( ) ) ,
config ,
)
2022-02-12 01:04:01 +01:00
}
2023-02-01 00:48:33 +01:00
/// Create a new SPIM driver, capable of TX only (MOSI only).
2022-02-12 01:04:01 +01:00
pub fn new_txonly (
2022-07-23 14:00:19 +02:00
spim : impl Peripheral < P = T > + ' d ,
2023-03-05 22:00:52 +01:00
_irq : impl interrupt ::Binding < T ::Interrupt , InterruptHandler < T > > + ' d ,
2022-07-23 14:00:19 +02:00
sck : impl Peripheral < P = impl GpioPin > + ' d ,
mosi : impl Peripheral < P = impl GpioPin > + ' d ,
2022-02-12 01:04:01 +01:00
config : Config ,
) -> Self {
2022-07-23 14:27:45 +02:00
into_ref! ( sck , mosi ) ;
2023-03-05 22:00:52 +01:00
Self ::new_inner ( spim , sck . map_into ( ) , None , Some ( mosi . map_into ( ) ) , config )
2022-02-12 01:04:01 +01:00
}
2023-02-01 00:48:33 +01:00
/// Create a new SPIM driver, capable of RX only (MISO only).
2022-02-12 01:04:01 +01:00
pub fn new_rxonly (
2022-07-23 14:00:19 +02:00
spim : impl Peripheral < P = T > + ' d ,
2023-03-05 22:00:52 +01:00
_irq : impl interrupt ::Binding < T ::Interrupt , InterruptHandler < T > > + ' d ,
2022-07-23 14:00:19 +02:00
sck : impl Peripheral < P = impl GpioPin > + ' d ,
miso : impl Peripheral < P = impl GpioPin > + ' d ,
2022-02-12 01:04:01 +01:00
config : Config ,
) -> Self {
2022-07-23 14:27:45 +02:00
into_ref! ( sck , miso ) ;
2023-03-05 22:00:52 +01:00
Self ::new_inner ( spim , sck . map_into ( ) , Some ( miso . map_into ( ) ) , None , config )
2022-02-12 01:04:01 +01:00
}
fn new_inner (
2022-07-23 15:13:47 +02:00
spim : impl Peripheral < P = T > + ' d ,
2022-07-23 14:00:19 +02:00
sck : PeripheralRef < ' d , AnyPin > ,
miso : Option < PeripheralRef < ' d , AnyPin > > ,
mosi : Option < PeripheralRef < ' d , AnyPin > > ,
2021-03-19 04:08:44 +01:00
config : Config ,
) -> Self {
2023-03-05 22:00:52 +01:00
into_ref! ( spim ) ;
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 ) } ) ;
2023-06-01 02:22:46 +02:00
T ::Interrupt ::unpend ( ) ;
unsafe { T ::Interrupt ::enable ( ) } ;
2021-04-14 16:37:10 +02:00
2022-07-23 15:13:47 +02:00
Self { _p : spim }
2021-01-18 14:22:55 +01:00
}
2021-04-14 16:37:10 +02:00
2022-01-13 20:00:33 +01:00
fn prepare ( & mut self , rx : * mut [ u8 ] , tx : * const [ u8 ] ) -> Result < ( ) , Error > {
2023-02-01 00:48:33 +01:00
slice_in_ram_or ( tx , Error ::BufferNotInRAM ) ? ;
2022-01-13 19:27:10 +01:00
// 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 ( ( ) ) ,
2023-02-01 00:48:33 +01:00
Err ( Error ::BufferNotInRAM ) = > {
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 ( ( ) ) ,
2023-02-01 00:48:33 +01:00
Err ( Error ::BufferNotInRAM ) = > {
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 {
2022-08-22 21:46:09 +02:00
use embassy_sync ::waitqueue ::AtomicWaker ;
2021-09-11 01:53:53 +02:00
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
}
2023-02-01 00:48:33 +01:00
/// SPIM peripheral instance
2022-07-23 14:00:19 +02:00
pub trait Instance : Peripheral < P = Self > + sealed ::Instance + 'static {
2023-02-01 00:48:33 +01:00
/// Interrupt for this peripheral.
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 ,
2023-02-01 00:48:33 +01:00
Self ::BufferNotInRAM = > embedded_hal_1 ::spi ::ErrorKind ::Other ,
2022-01-13 23:56:25 +01:00
}
}
}
impl < ' d , T : Instance > embedded_hal_1 ::spi ::ErrorType for Spim < ' d , T > {
type Error = Error ;
}
2022-09-29 11:02:43 +02:00
impl < ' d , T : Instance > embedded_hal_1 ::spi ::SpiBusFlush for Spim < ' d , T > {
2022-02-16 03:54:39 +01:00
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-09-29 11:02:43 +02:00
impl < ' d , T : Instance > embedded_hal_1 ::spi ::SpiBusRead < u8 > for Spim < ' d , T > {
2022-02-16 03:54:39 +01:00
fn read ( & mut self , words : & mut [ u8 ] ) -> Result < ( ) , Self ::Error > {
self . blocking_transfer ( words , & [ ] )
2022-01-13 23:56:25 +01:00
}
}
2022-09-29 11:02:43 +02:00
impl < ' d , T : Instance > embedded_hal_1 ::spi ::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-09-29 11:02:43 +02:00
impl < ' d , T : Instance > embedded_hal_1 ::spi ::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-08-31 02:46:52 +02:00
#[ cfg(all(feature = " unstable-traits " , feature = " nightly " )) ]
mod eha {
2022-01-13 23:56:25 +01:00
2022-08-31 02:46:52 +02:00
use super ::* ;
2022-01-13 23:56:25 +01:00
2022-08-31 02:46:52 +02:00
impl < ' d , T : Instance > embedded_hal_async ::spi ::SpiBusFlush for Spim < ' d , T > {
2022-11-21 23:31:31 +01:00
async fn flush ( & mut self ) -> Result < ( ) , Error > {
Ok ( ( ) )
2022-01-13 23:56:25 +01:00
}
2022-08-31 02:46:52 +02:00
}
2022-01-13 23:56:25 +01:00
2022-08-31 02:46:52 +02:00
impl < ' d , T : Instance > embedded_hal_async ::spi ::SpiBusRead < u8 > for Spim < ' d , T > {
2022-11-21 23:31:31 +01:00
async fn read ( & mut self , words : & mut [ u8 ] ) -> Result < ( ) , Error > {
self . read ( words ) . await
2022-01-13 23:56:25 +01:00
}
2022-08-31 02:46:52 +02:00
}
2022-01-13 23:56:25 +01:00
2022-08-31 02:46:52 +02:00
impl < ' d , T : Instance > embedded_hal_async ::spi ::SpiBusWrite < u8 > for Spim < ' d , T > {
2022-11-21 23:31:31 +01:00
async fn write ( & mut self , data : & [ u8 ] ) -> Result < ( ) , Error > {
self . write ( data ) . await
2022-01-13 23:56:25 +01:00
}
2022-08-31 02:46:52 +02:00
}
2022-01-13 23:56:25 +01:00
2022-08-31 02:46:52 +02:00
impl < ' d , T : Instance > embedded_hal_async ::spi ::SpiBus < u8 > for Spim < ' d , T > {
2022-11-21 23:31:31 +01:00
async fn transfer ( & mut self , rx : & mut [ u8 ] , tx : & [ u8 ] ) -> Result < ( ) , Error > {
self . transfer ( rx , tx ) . await
2022-08-31 02:46:52 +02:00
}
2022-01-13 23:56:25 +01:00
2022-11-21 23:31:31 +01:00
async fn transfer_in_place ( & mut self , words : & mut [ u8 ] ) -> Result < ( ) , Error > {
self . transfer_in_place ( words ) . await
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 ) } ) ;
}
}