Struct grand_central_m4::sercom::v2::spi::Spi [−][src]
pub struct Spi<C> where
C: ValidConfig, { /* fields omitted */ }
Expand description
An enabled SPI peripheral that can perform transactions
As noted in the OpMode
and Length
traits, this module chooses to
always operate in 32-bit extension mode and uses the LENGTH counter to set
the number of bytes in each transaction, from 1 to 255. In 32-bit extension
mode, transaction Length
s of four bytes or fewer can be completed in a
single read or write of the DATA register. Longer transactions require
multiple reads or writes of the DATA register.
Embedded HAL traits
The embedded HAL FullDuplex
trait is non-blocking, which has
consequences for different transaction Length
s. Transaction Length
s
of 1-4 bytes fit the FullDuplex
model well, because they can return
WouldBlock
until it is possible to perform a single read or write that
completes the transaction. The FullDuplex
word type is u8
for 1-byte
transactions, u16
for 2-byte transactions and u32
for 3- and 4-byte
transactions.
For half-duplex, non-blocking transactions, this type implements the
serial
Read
and Write
traits. They are only implemented for
transaction Length
s <= 4
and only when the Pads
are not
Tx
+
Rx
, so they don’t compete with FullDuplex
.
Longer Length
s require multiple reads or writes, which does not fit the
FullDuplex
model very well. When returning WouldBlock
, the
implementation would have to store some sort of internal state to track the
progress of an on-going transaction. As a consequence, FullDuplex
is
only implemented for Length
s of 1-4.
However, the blocking::spi
traits are different, because they can always
execute a transaction to completion before returning. For Length
s of
1-4 bytes, these traits are implemented using an approach very similar to
the Default
implementations. Longer Length
s use a custom
implementation of Transfer
and Write
and
accept slices of u8
with a length matching the transaction Length
.
When using a DynLength
, Spi
only implements Transfer
and
Write
, using the same approach as long transaction
Length
s.
For a non-blocking alternative that can be used to transfer slices, see the
SpiFuture
type.
Further documentation
The individual implementations of the embedded HAL traits are well
documented. Unfortunately, however, rustdoc does not produce the most
visually scannable documentation, especially when using typenum
. Here are
some tips for finding more information in the impl
blocks below:
FullDuplex
uses a single blanket implementation forLength
s of 1-4Read
has two different implementations, one forSlave
OpMode
and another forMasterMode
sWrite
uses a single blanket implementation, likeFullDuplex
. However, watch out for ambiguity betweenserial::Write
,blocking::serial::Write
andblocking::spi::Write
.blocking::serial::Write
uses theblocking::serial::write::Default
implementationblocking::spi::Transfer
uses custom implementations. The implementations forLength
s of 1-4 are generated by macro, so there are four different implementations forU1
-U4
. This is responsible for most of the visual noise in the docs.Length
s greater than four use a blanket implementation.DynLength
uses its own implementation with an added run-time check of the transaction length.blocking::spi::Write
takes the same approach asTransfer
.blocking::spi::WriteIter
is implemented via macro forLength
s 1-4, but it is not implemented for longerLength
s orDynLength
.
Implementations
Obtain a reference to the PAC SERCOM
struct
Directly accessing the SERCOM
could break the invariants of the
type-level tracking in this module, so it is unsafe.
Update the SPI configuration.
Calling this method will temporarily disable the SERCOM peripheral, as some registers are enable-protected. This may interrupt any ongoing transactions.
Enable interrupts for the specified flags
Disable interrupts for the specified flags
Read the interrupt status flags
Clear interrupt status flags
Setting the ERROR, SSL or TXC flag will clear the interrupt. Clearing any flag will have no effect. This function has no effect on the DRE or RXC flags.
Warning: The implementation of of Write::flush
waits on and
clears the TXC
flag. Manually clearing this flag could cause it to
hang indefinitely.
Read the error status flags
Clear error status flags
Setting a flag will clear the error. Clearing any flag will have no effect.
Read from the DATA register
Reading from the data register directly is unsafe
, because it will
clear the RXC flag, which could break assumptions made elsewhere in
this module.
Write to the DATA register
Writing to the data register directly is unsafe
, because it will clear
the DRE flag, which could break assumptions made elsewhere in this
module.
Return the current transaction length
Read the LENGTH register to determine the current transaction length
Set the transaction length
Write the LENGTH register to set the transaction length. Panics if the length is zero.
Safety
If you have sent any data at the current transaction length, you
must wait for TXC
before changing the length.
Trait Implementations
impl<P, M, L> CheckBufLen for Spi<Config<P, M, L>> where
P: TxOrRx,
M: OpMode,
L: StaticLength,
Config<P, M, L>: ValidConfig,
impl<P, M, L> CheckBufLen for Spi<Config<P, M, L>> where
P: TxOrRx,
M: OpMode,
L: StaticLength,
Config<P, M, L>: ValidConfig,
impl<P, M> CheckBufLen for Spi<Config<P, M, UTerm>> where
P: TxOrRx,
M: OpMode,
Config<P, M, UTerm>: ValidConfig,
impl<P, M> CheckBufLen for Spi<Config<P, M, UTerm>> where
P: TxOrRx,
M: OpMode,
Config<P, M, UTerm>: ValidConfig,
Implement FullDuplex
for short Spi
transaction Length
s
[FullDuplex
is only implemented when Pads
is both Tx
and Rx
,
the OpMode
is a MasterMode
, and the transaction Length
is <= 4
bytes. When the Length
is <= 4
, the Word
is a primitive
integer, with a size that depends on the Length
(u8
, u16
or u32
).
Implement Read
for MasterMode
s
Read
is only implemented when the Pads
are Rx
but NotTx
.
If the Pads
are both Rx
and Tx
, then use FullDuplex
.
In a MasterMode
, Read
has to initiate transactions and receive the
responses. To do so, it uses a static
allocation to keep track of the
transaction state. If a transaction is in progress, it will wait on RXC
.
If not, it will wait on DRE
and then send 0
.
It should not be possible for the tracked state to become invalid using only
safe code. However, if using unsafe
, the state could fall out of sync. In
that case, the Spi::reset_serial_read_state
method can be used to reset
the state. After reset, a transaction is assumed to NOT be in progress.
If a transaction is already in progress, wait for an RXC
flag, then
read the word. If not, wait for a DRE
flag, then write 0
.
Track the transaction state with an internal static
. It should not be
possible for the state to get out of sync with the hardware using only
safe code. If using unsafe
and the state does get out of sync, use
Spi::reset_serial_read_state
to reset it.
impl<'a, P, M, L> Transfer<u8> for Spi<Config<P, M, L>> where
P: Rx,
M: OpMode,
L: GreaterThan4,
Config<P, M, L>: ValidConfig,
impl<'a, P, M, L> Transfer<u8> for Spi<Config<P, M, L>> where
P: Rx,
M: OpMode,
L: GreaterThan4,
Config<P, M, L>: ValidConfig,
Implement Write
for short Spi
transaction Length
s
The Spi
Pads
must be Tx
but NotRx
and the
transaction Length
must be <= 4
. The transfer accepts a
slice of primitive integers, depending on the Length
(u8
,
u16
or u32
).
Because Write
is only implemented when the Pads
are
NotRx
, this implementation never reads the DATA register and
ignores all buffer overflow errors.
Implement Write
for short Spi
transaction Length
s
The Spi
Pads
must be Tx
but NotRx
and the
transaction Length
must be <= 4
. The transfer accepts a
slice of primitive integers, depending on the Length
(u8
,
u16
or u32
).
Because Write
is only implemented when the Pads
are
NotRx
, this implementation never reads the DATA register and
ignores all buffer overflow errors.
Implement Write
for short Spi
transaction Length
s
The Spi
Pads
must be Tx
but NotRx
and the
transaction Length
must be <= 4
. The transfer accepts a
slice of primitive integers, depending on the Length
(u8
,
u16
or u32
).
Because Write
is only implemented when the Pads
are
NotRx
, this implementation never reads the DATA register and
ignores all buffer overflow errors.
Implement Write
for short Spi
transaction Length
s
The Spi
Pads
must be Tx
but NotRx
and the
transaction Length
must be <= 4
. The transfer accepts a
slice of primitive integers, depending on the Length
(u8
,
u16
or u32
).
Because Write
is only implemented when the Pads
are
NotRx
, this implementation never reads the DATA register and
ignores all buffer overflow errors.
impl<P, M, L> Write<u8> for Spi<Config<P, M, L>> where
P: Tx,
M: OpMode,
L: GreaterThan4,
Config<P, M, L>: ValidConfig,
impl<P, M, L> Write<u8> for Spi<Config<P, M, L>> where
P: Tx,
M: OpMode,
L: GreaterThan4,
Config<P, M, L>: ValidConfig,
Implement Write
for longer Spi
transaction Length
s
The Spi
Pads
must be Tx
but NotRx
and the transaction
Length
must be > 4
. The transfer accepts a slice of u8
with a length
equal to the transfer Length
. If the slice length is incorrect, it will
panic.
Because Write
is only implemented when the Pads
are NotRx
, this
implementation never reads the DATA register and ignores all buffer overflow
errors.
Implement Write
for Spi
types with DynLength
The Spi
Pads
must be Tx
. The transfer accepts a slice of u8
with a length equal to the run-time dynamic transaction length. If the slice
length does not match the result of Spi::get_dyn_length
, it will panic.
Because Write
is only implemented when the Pads
are NotRx
, this
implementation never reads the DATA register and ignores all buffer overflow
errors.
Implement WriteIter
for short Spi
transaction Length
s
The Spi
Pads
must be Tx
but NotRx
and the
transaction Length
must be <= 4
. The transfer accepts an
iterator that yields primitive integers, depending on the
Length
(u8
, u16
or u32
).
Because WriteIter
is only implemented when the Pads
are
NotRx
, this implementation never reads the DATA register and
ignores all buffer overflow errors.
Implement WriteIter
for short Spi
transaction Length
s
The Spi
Pads
must be Tx
but NotRx
and the
transaction Length
must be <= 4
. The transfer accepts an
iterator that yields primitive integers, depending on the
Length
(u8
, u16
or u32
).
Because WriteIter
is only implemented when the Pads
are
NotRx
, this implementation never reads the DATA register and
ignores all buffer overflow errors.
Implement WriteIter
for short Spi
transaction Length
s
The Spi
Pads
must be Tx
but NotRx
and the
transaction Length
must be <= 4
. The transfer accepts an
iterator that yields primitive integers, depending on the
Length
(u8
, u16
or u32
).
Because WriteIter
is only implemented when the Pads
are
NotRx
, this implementation never reads the DATA register and
ignores all buffer overflow errors.
Implement WriteIter
for short Spi
transaction Length
s
The Spi
Pads
must be Tx
but NotRx
and the
transaction Length
must be <= 4
. The transfer accepts an
iterator that yields primitive integers, depending on the
Length
(u8
, u16
or u32
).
Because WriteIter
is only implemented when the Pads
are
NotRx
, this implementation never reads the DATA register and
ignores all buffer overflow errors.