Expand description
Implement Embedded HAL (v0.2 and nb) traits for
Spi structs
As noted in the spi module documentation, the embedded-hal trait
implementations vary by both Size and Capability. Each
implementation is optimized to take advantage of all information known at
compile-time, so it is importatnt to carefully read the documentation in
this module.
§Variations by Size
Remember that SAMx5x chips operate in 32-bit extension mode and use the
hardware LENGTH counter to set the number of bytes in each transaction.
The transaction Length is usually tracked at compile-time using
type-level integers from the typenum crate, but it can also be tracked
at run-time when using a DynLength.
The transaction Lengths can be sub-divided into three groups:
Lengths of 1-4 bytes can be completed in a single read/write of theDATAregister. TheseLengths are marked asAtomicSizes.LengthsGreaterThan4are known at compile-time but cannot be completed atomically.- A
DynLengthcan be any length, but the value is only known at run-time.
In general, transaction lengths with an AtomicSize implement embedded HAL
traits with the corresponding Word type. For example, Spi structs
using a transaction Length of 2 bytes implement FullDuplex<u16>. These
lengths implement both the blocking and non-blocking traits from embedded
HAL. The non-blocking traits are found in the spi and
serial modules, while the blocking traits are found
in the embedded HAL v0.2 blocking module.
Transaction lengths GreaterThan4 cannot be completed in a single read or
write of the DATA register, so these lengths do NOT implement the
non-blocking traits from the embedded HAL spi and serial modules.
Instead, they only implement traits from the blocking module. These traits
are implemented for u8 types, e.g. blocking::spi::Transfer<u8>, and
operate on [u8] slices. The length of the slice is checked to ensure it
matches the transaction Length.
Because a DynLength is not guaranteed to be an AtomicSize, the
corresponding Spi structs only implement the blocking traits as well.
For a non-blocking alternative that can be used to transfer arbitrary-length
slices, you could use either
DMA
.
§Variations by Capability
The implementations in this module also seek to optimize as much as possible
based on the Capability of the Spi struct. They follow a few general
rules:
Txstructs can never receive data, so their corresponding trait implementations never read theDATAregister and can never return anError::Overflow.Rxstructs in aMasterModemust initiate all transactions, so their implementations of non-blocking traits must track the state of on-going transactions.Duplexstructs must always read as many bytes as they send, even when implementingWrite-only traits, to ensure they never introduce anError::Overflow.
§Notes on individual embedded HAL traits
§spi::FullDuplex
spi::FullDuplex is only implemented for structs with Duplex
Capability. Although the embedded HAL documentation assumes a
MasterMode, this module also implements it for the Slave OpMode.
§serial::Read
serial::Read is only implemented for structs with Rx Capability. When
in a MasterMode, it initiates and tracks the state of the on-going
transactions. But this is not required when acting as a Slave.
§serial::Write
serial::Write is only implemented for structs with Tx Capability.
These implementations never read the DATA register and ignore all
instances of Error::Overflow.
§blocking::serial::Write
This trait uses the blocking::serial::write::Default implementation for
implementers of serial::Write.
§blocking::spi traits
These traits are implemented following all of the rules outlined above for
the different Size and Capability options.