2023-02-01 00:48:33 +01:00
//! Serial Peripheral Instance in slave mode (SPIS) driver.
2022-11-05 00:15:43 +01:00
#![ macro_use ]
use core ::future ::poll_fn ;
2023-03-05 22:05:02 +01:00
use core ::marker ::PhantomData ;
2022-11-05 00:15:43 +01:00
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 _ ;
2022-11-13 01:49:55 +01:00
use crate ::gpio ::{ self , AnyPin , Pin as GpioPin } ;
2023-06-08 16:08:40 +02:00
use crate ::interrupt ::typelevel ::Interrupt ;
2022-11-05 00:15:43 +01:00
use crate ::util ::{ slice_in_ram_or , slice_ptr_parts , slice_ptr_parts_mut } ;
2023-06-08 16:08:40 +02:00
use crate ::{ interrupt , pac , Peripheral } ;
2022-11-05 00:15:43 +01:00
2023-02-01 00:48:33 +01:00
/// SPIS error
2022-11-05 00:15:43 +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.
2022-11-05 00:15:43 +01:00
TxBufferTooLong ,
2023-02-01 00:48:33 +01:00
/// RX buffer was too long.
2022-11-05 00:15:43 +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 ,
2022-11-05 00:15:43 +01:00
}
2023-02-01 00:48:33 +01:00
/// SPIS configuration.
2022-11-05 00:15:43 +01:00
#[ non_exhaustive ]
pub struct Config {
2023-02-01 00:48:33 +01:00
/// SPI mode
2022-11-05 00:15:43 +01:00
pub mode : Mode ,
2023-02-01 00:48:33 +01:00
/// Overread character.
///
/// If the master keeps clocking the bus after all the bytes in the TX buffer have
/// already been transmitted, this byte will be constantly transmitted in the MISO line.
2022-11-05 00:15:43 +01:00
pub orc : u8 ,
2023-02-01 00:48:33 +01:00
/// Default byte.
///
/// This is the byte clocked out in the MISO line for ignored transactions (if the master
/// sets CSN low while the semaphore is owned by the firmware)
2022-11-05 00:15:43 +01:00
pub def : u8 ,
2023-02-01 00:48:33 +01:00
/// Automatically make the firmware side acquire the semaphore on transfer end.
2022-11-05 00:15:43 +01:00
pub auto_acquire : bool ,
}
impl Default for Config {
fn default ( ) -> Self {
Self {
mode : MODE_0 ,
orc : 0x00 ,
def : 0x00 ,
auto_acquire : true ,
}
}
}
2023-03-05 22:05:02 +01:00
/// Interrupt handler.
pub struct InterruptHandler < T : Instance > {
_phantom : PhantomData < T > ,
}
2023-06-08 16:08:40 +02:00
impl < T : Instance > interrupt ::typelevel ::Handler < T ::Interrupt > for InterruptHandler < T > {
2023-03-05 22:05:02 +01:00
unsafe fn on_interrupt ( ) {
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 ( ) ) ;
}
}
}
/// SPIS driver.
pub struct Spis < ' d , T : Instance > {
_p : PeripheralRef < ' d , T > ,
}
2022-11-05 00:15:43 +01:00
impl < ' d , T : Instance > Spis < ' d , T > {
2023-02-01 00:48:33 +01:00
/// Create a new SPIS driver.
2022-11-05 00:15:43 +01:00
pub fn new (
spis : impl Peripheral < P = T > + ' d ,
2023-06-08 16:08:40 +02:00
_irq : impl interrupt ::typelevel ::Binding < T ::Interrupt , InterruptHandler < T > > + ' d ,
2022-11-05 00:15:43 +01:00
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 ,
cs . map_into ( ) ,
sck . map_into ( ) ,
Some ( miso . map_into ( ) ) ,
Some ( mosi . map_into ( ) ) ,
config ,
)
}
2023-02-01 00:48:33 +01:00
/// Create a new SPIS driver, capable of TX only (MISO only).
2022-11-05 00:15:43 +01:00
pub fn new_txonly (
spis : impl Peripheral < P = T > + ' d ,
2023-06-08 16:08:40 +02:00
_irq : impl interrupt ::typelevel ::Binding < T ::Interrupt , InterruptHandler < T > > + ' d ,
2022-11-05 00:15:43 +01:00
cs : impl Peripheral < P = impl GpioPin > + ' d ,
sck : impl Peripheral < P = impl GpioPin > + ' d ,
2022-11-22 00:55:05 +01:00
miso : impl Peripheral < P = impl GpioPin > + ' d ,
2022-11-05 00:15:43 +01:00
config : Config ,
) -> Self {
2022-11-22 02:13:03 +01:00
into_ref! ( cs , sck , miso ) ;
2023-03-05 22:05:02 +01:00
Self ::new_inner ( spis , cs . map_into ( ) , sck . map_into ( ) , Some ( miso . map_into ( ) ) , None , config )
2022-11-05 00:15:43 +01:00
}
2023-02-01 00:48:33 +01:00
/// Create a new SPIS driver, capable of RX only (MOSI only).
2022-11-05 00:15:43 +01:00
pub fn new_rxonly (
spis : impl Peripheral < P = T > + ' d ,
2023-06-08 16:08:40 +02:00
_irq : impl interrupt ::typelevel ::Binding < T ::Interrupt , InterruptHandler < T > > + ' d ,
2022-11-05 00:15:43 +01:00
cs : impl Peripheral < P = impl GpioPin > + ' d ,
sck : impl Peripheral < P = impl GpioPin > + ' d ,
2022-11-22 00:55:05 +01:00
mosi : impl Peripheral < P = impl GpioPin > + ' d ,
2022-11-05 00:15:43 +01:00
config : Config ,
) -> Self {
2022-11-22 02:13:03 +01:00
into_ref! ( cs , sck , mosi ) ;
2023-03-05 22:05:02 +01:00
Self ::new_inner ( spis , cs . map_into ( ) , sck . map_into ( ) , None , Some ( mosi . map_into ( ) ) , config )
2022-11-05 00:15:43 +01:00
}
fn new_inner (
spis : impl Peripheral < P = T > + ' d ,
cs : PeripheralRef < ' d , AnyPin > ,
sck : PeripheralRef < ' d , AnyPin > ,
miso : Option < PeripheralRef < ' d , AnyPin > > ,
mosi : Option < PeripheralRef < ' d , AnyPin > > ,
config : Config ,
) -> Self {
2022-11-13 01:49:55 +01:00
compiler_fence ( Ordering ::SeqCst ) ;
2023-03-05 22:05:02 +01:00
into_ref! ( spis , cs , sck ) ;
2022-11-05 00:15:43 +01:00
let r = T ::regs ( ) ;
2022-11-05 01:12:25 +01:00
// Configure pins.
2022-11-05 00:15:43 +01:00
sck . conf ( ) . write ( | w | w . input ( ) . connect ( ) . drive ( ) . h0h1 ( ) ) ;
2022-11-13 01:49:55 +01:00
r . psel . sck . write ( | w | unsafe { w . bits ( sck . psel_bits ( ) ) } ) ;
2022-11-05 00:15:43 +01:00
cs . conf ( ) . write ( | w | w . input ( ) . connect ( ) . drive ( ) . h0h1 ( ) ) ;
2022-11-13 01:49:55 +01:00
r . psel . csn . write ( | w | unsafe { w . bits ( cs . psel_bits ( ) ) } ) ;
2022-11-05 00:15:43 +01:00
if let Some ( mosi ) = & mosi {
mosi . conf ( ) . write ( | w | w . input ( ) . connect ( ) . drive ( ) . h0h1 ( ) ) ;
2022-11-13 01:49:55 +01:00
r . psel . mosi . write ( | w | unsafe { w . bits ( mosi . psel_bits ( ) ) } ) ;
2022-11-05 00:15:43 +01:00
}
if let Some ( miso ) = & miso {
miso . conf ( ) . write ( | w | w . dir ( ) . output ( ) . drive ( ) . h0h1 ( ) ) ;
2022-11-13 01:49:55 +01:00
r . psel . miso . write ( | w | unsafe { w . bits ( miso . psel_bits ( ) ) } ) ;
2022-11-05 00:15:43 +01:00
}
// 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
} ) ;
2022-11-05 01:12:25 +01:00
// Set over-read character.
2022-11-05 00:15:43 +01:00
let orc = config . orc ;
r . orc . write ( | w | unsafe { w . orc ( ) . bits ( orc ) } ) ;
2022-11-05 01:12:25 +01:00
// Set default character.
2022-11-05 00:15:43 +01:00
let def = config . def ;
r . def . write ( | w | unsafe { w . def ( ) . bits ( def ) } ) ;
2022-11-05 01:12:25 +01:00
// Configure auto-acquire on 'transfer end' event.
if config . auto_acquire {
r . shorts . write ( | w | w . end_acquire ( ) . bit ( true ) ) ;
}
// Disable all events interrupts.
2022-11-05 00:15:43 +01:00
r . intenclr . write ( | w | unsafe { w . bits ( 0xFFFF_FFFF ) } ) ;
2023-06-01 02:22:46 +02:00
T ::Interrupt ::unpend ( ) ;
unsafe { T ::Interrupt ::enable ( ) } ;
2022-11-05 00:15:43 +01:00
Self { _p : spis }
}
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-11-05 00:15:43 +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 _ ) } ) ;
2022-11-13 01:49:55 +01:00
// Reset end event.
2022-11-05 00:15:43 +01:00
r . events_end . reset ( ) ;
2022-11-05 01:12:25 +01:00
// Release the semaphore.
2022-11-05 00:15:43 +01:00
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 > {
2022-11-05 01:34:52 +01:00
compiler_fence ( Ordering ::SeqCst ) ;
2022-11-05 00:15:43 +01:00
let r = T ::regs ( ) ;
2022-11-05 01:34:52 +01:00
// 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 ) ? ;
2022-11-05 00:15:43 +01:00
// 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 ) ,
2023-02-01 00:48:33 +01:00
Err ( Error ::BufferNotInRAM ) = > {
2022-11-05 00:15:43 +01:00
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 ( ) ;
2022-11-05 01:12:25 +01:00
// Clear status register.
r . status . write ( | w | w . overflow ( ) . clear ( ) . overread ( ) . clear ( ) ) ;
2022-11-05 01:34:52 +01:00
// Acquire semaphore.
2022-11-05 00:15:43 +01:00
if r . semstat . read ( ) . bits ( ) ! = 1 {
2022-11-05 01:12:25 +01:00
// Reset and enable the acquire event.
2022-11-05 00:15:43 +01:00
r . events_acquired . reset ( ) ;
r . intenset . write ( | w | w . acquired ( ) . set ( ) ) ;
2022-11-05 01:12:25 +01:00
// Request acquiring the SPIS semaphore.
2022-11-05 00:15:43 +01:00
r . tasks_acquire . write ( | w | unsafe { w . bits ( 1 ) } ) ;
2022-11-05 00:19:52 +01:00
2022-11-05 01:34:52 +01:00
// Wait until CPU has acquired the semaphore.
2022-11-05 00:15:43 +01:00
poll_fn ( | cx | {
2022-11-14 11:39:55 +01:00
s . waker . register ( cx . waker ( ) ) ;
2022-11-14 16:24:21 +01:00
if r . events_acquired . read ( ) . bits ( ) = = 1 {
2022-11-14 16:18:11 +01:00
r . events_acquired . reset ( ) ;
2022-11-05 00:15:43 +01:00
return Poll ::Ready ( ( ) ) ;
}
Poll ::Pending
} )
. await ;
}
self . prepare ( rx , tx ) ? ;
// Wait for 'end' event.
2022-11-13 01:49:55 +01:00
r . intenset . write ( | w | w . end ( ) . set ( ) ) ;
2022-11-05 00:15:43 +01:00
poll_fn ( | cx | {
2022-11-14 11:39:55 +01:00
s . waker . register ( cx . waker ( ) ) ;
2022-11-05 00:15:43 +01:00
if r . events_end . read ( ) . bits ( ) ! = 0 {
2022-11-14 16:18:11 +01:00
r . events_end . reset ( ) ;
2022-11-05 00:15:43 +01:00
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 ) ,
2023-02-01 00:48:33 +01:00
Err ( Error ::BufferNotInRAM ) = > {
2022-11-05 00:15:43 +01:00
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 ) ,
}
}
2022-11-22 00:55:05 +01:00
/// Reads data from the SPI bus without sending anything. Blocks until `cs` is deasserted.
2022-11-05 01:12:25 +01:00
/// Returns number of bytes read.
2022-11-05 00:15:43 +01:00
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).
2022-11-05 01:12:25 +01:00
/// Returns number of bytes transferred `(n_rx, n_tx)`.
2022-11-05 00:15:43 +01:00
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.
2022-11-05 01:12:25 +01:00
/// Returns number of bytes transferred `(n_rx, n_tx)`.
2022-11-05 00:15:43 +01:00
pub fn blocking_transfer_from_ram ( & mut self , read : & mut [ u8 ] , write : & [ u8 ] ) -> Result < ( usize , usize ) , Error > {
2022-11-22 00:55:05 +01:00
self . blocking_inner_from_ram ( read , write )
2022-11-05 00:15:43 +01:00
}
/// Simultaneously sends and receives data.
/// Places the received data into the same buffer and blocks until the transmission is completed.
2022-11-05 01:12:25 +01:00
/// Returns number of bytes transferred.
2022-11-05 00:15:43 +01:00
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).
2022-11-05 01:12:25 +01:00
/// Returns number of bytes written.
2022-11-05 00:15:43 +01:00
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.
2022-11-05 01:12:25 +01:00
/// Returns number of bytes written.
2022-11-05 00:15:43 +01:00
pub fn blocking_write_from_ram ( & mut self , data : & [ u8 ] ) -> Result < usize , Error > {
2022-11-22 00:55:05 +01:00
self . blocking_inner_from_ram ( & mut [ ] , data ) . map ( | n | n . 1 )
2022-11-05 00:15:43 +01:00
}
/// Reads data from the SPI bus without sending anything.
2022-11-05 01:12:25 +01:00
/// Returns number of bytes read.
2022-11-05 00:15:43 +01:00
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).
2022-11-05 01:12:25 +01:00
/// Returns number of bytes transferred `(n_rx, n_tx)`.
2022-11-05 00:15:43 +01:00
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.
2022-11-05 01:12:25 +01:00
/// Returns number of bytes transferred `(n_rx, n_tx)`.
2022-11-05 00:15:43 +01:00
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.
2022-11-05 01:12:25 +01:00
/// Returns number of bytes transferred.
2022-11-05 00:15:43 +01:00
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).
2022-11-05 01:12:25 +01:00
/// Returns number of bytes written.
2022-11-05 00:15:43 +01:00
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.
2022-11-05 01:12:25 +01:00
/// Returns number of bytes written.
2022-11-05 00:15:43 +01:00
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 )
}
2022-11-05 01:12:25 +01:00
/// 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 ( )
}
2022-11-05 00:15:43 +01:00
}
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 {
2022-11-14 11:39:55 +01:00
pub waker : AtomicWaker ,
2022-11-05 00:15:43 +01:00
}
impl State {
pub const fn new ( ) -> Self {
Self {
2022-11-14 11:39:55 +01:00
waker : AtomicWaker ::new ( ) ,
2022-11-05 00:15:43 +01:00
}
}
}
pub trait Instance {
fn regs ( ) -> & 'static pac ::spis0 ::RegisterBlock ;
fn state ( ) -> & 'static State ;
}
}
2023-02-01 00:48:33 +01:00
/// SPIS peripheral instance
2022-11-05 00:15:43 +01:00
pub trait Instance : Peripheral < P = Self > + sealed ::Instance + 'static {
2023-02-01 00:48:33 +01:00
/// Interrupt for this peripheral.
2023-06-08 16:08:40 +02:00
type Interrupt : interrupt ::typelevel ::Interrupt ;
2022-11-05 00:15:43 +01:00
}
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 {
2023-06-08 16:08:40 +02:00
type Interrupt = crate ::interrupt ::typelevel ::$irq ;
2022-11-05 00:15:43 +01:00
}
} ;
}
// ====================
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
} ) ;
2022-11-05 01:12:25 +01:00
// Set over-read character.
2022-11-05 00:15:43 +01:00
let orc = config . orc ;
r . orc . write ( | w | unsafe { w . orc ( ) . bits ( orc ) } ) ;
2022-11-05 01:12:25 +01:00
// Set default character.
2022-11-05 00:15:43 +01:00
let def = config . def ;
r . def . write ( | w | unsafe { w . def ( ) . bits ( def ) } ) ;
2022-11-05 01:12:25 +01:00
// Configure auto-acquire on 'transfer end' event.
2022-11-05 00:15:43 +01:00
let auto_acquire = config . auto_acquire ;
r . shorts . write ( | w | w . end_acquire ( ) . bit ( auto_acquire ) ) ;
}
}