Module serpente::sercom::v2::spi [−][src]
Expand description
Use the SERCOM peripheral for SPI transactions
Configuring an SPI peripheral occurs in three steps. First, you must create
a set of Pads
for use by the peripheral. Next, you assemble pieces into
a Config
struct. After configuring the peripheral, you then enable
it, yielding a functional Spi
struct. Transactions are performed using
the spi
and serial
traits
from embedded HAL.
Pads
A Sercom
can use up to four Pin
s as configured as SERCOM pads, but
only certain Pin
combinations are acceptable. In particular, all Pin
s
must be mapped to the same Sercom
(see the datasheet). This HAL makes it
impossible to use invalid Pin
combinations, and the Pads
struct is
responsible for enforcing these constraints.
A Pads
type takes five type parameters. The first specifies the Sercom
,
while the remaining four, DI
, DO
, CK
and SS
, represent the Data In,
Data Out, Sclk and SS pads respectively. Each of the remaining type
parameters is an OptionalPad
and defaults to NoneT
. Aliases defining
the pad types can be provided by the bsp_pins!
macro.
use atsamd_hal::gpio::v2::{PA08, PA09, AlternateC, AlternateD};
use atsamd_hal::sercom::v2::{Sercom0, spi};
use atsamd_hal::typelevel::NoneT;
type Miso = Pin<PA08, AlternateC>;
type Sclk = Pin<PA09, AlternateC>;
type Pads = spi::Pads<Sercom0, Miso, NoneT, Sclk>;
Alternatively, you can use the PadsFromIds
alias to define a set of
Pads
in terms of PinId
s instead of Pin
s. This is useful when you
don’t have Pin
aliases pre-defined.
use atsamd_hal::gpio::v2::{PA08, PA09};
use atsamd_hal::sercom::v2::{Sercom0, spi};
use atsamd_hal::typelevel::NoneT;
type Pads = spi::PadsFromIds<Sercom0, PA08, NoneT, PA09>;
Instaces of Pads
are created using the builder pattern. Start by creating
an empty set of Pads
using Default
. Then pass each respective Pin
using the corresponding methods. Both v1::Pin
and v2::Pin
types are
accepted here.
On SAMD21 chips, the builder methods automatically convert each
pin to the correct PinMode
. But for SAMD11 chips, users must manually
convert each pin before calling the builder methods. This is a consequence
of inherent ambiguities in the SAMD11 SERCOM pad definitions. Specifically,
the same PinId
can correspond to two different PadNum
s for the same
Sercom
.
use atsamd_hal::pac::Peripherals;
use atsamd_hal::gpio::v2::Pins;
use atsamd_hal::sercom::v2::{Sercom0, spi};
let mut peripherals = Peripherals::take().unwrap();
let pins = Pins::new(peripherals.PORT);
let pads = spi::Pads::<Sercom0>::default()
.sclk(pins.pa09)
.data_in(pins.pa08)
.data_out(pins.pa11);
To be accepted as ValidPads
, a set of Pads
must do two things:
- Specify a type for
CK
and at least one ofDI
orDO
- Satisfy the
DipoDopo
trait
Config
Next, create a Config
struct, which represents the SPI peripheral in its
disabled state. A Config
is specified with three type parameters: the
Pads
type; an OpMode
, which defaults to Master
; and a
CharSize
, which defaults to EightBit
.
use atsamd_hal::gpio::v2::{PA08, PA09};
use atsamd_hal::sercom::v2::{Sercom0, spi};
use atsamd_hal::sercom::v2::spi::{Master, NineBit};
use atsamd_hal::typelevel::NoneT;
type Pads = spi::PadsFromIds<Sercom0, PA08, NoneT, PA09>;
type Config = spi::Config<Pads, Master, NineBit>;
Upon creation, the Config
takes ownership of both the Pads
struct
and the PAC Sercom
struct. It takes a reference to the PM, so that it
can enable the APB clock, and it takes a frequency to indicate the GCLK
configuration. Users are responsible for correctly configuring the GCLK.
use atsamd_hal::time::U32Ext;
let pm = peripherals.PM;
let sercom = peripherals.SERCOM0;
// Configure GCLK for 10 MHz
let freq = 10.mhz();
let config = spi::Config::new(&pm, sercom, pads, freq);
The Config
struct uses the builder pattern to configure the peripheral,
ending with a call to enable
, which consumes the Config
and returns
an enabled Spi
peripheral.
use embedded_hal::spi::MODE_1;
use atsamd_hal::sercom::v2::spi::NineBit;
let spi = spi::Config::new(&mclk, sercom, pads, freq)
.baud(1.mhz())
.char_size::<NineBit>()
.msb_first(false)
.spi_mode(MODE_1)
.enable();
To be accepted as a ValidConfig
, the Config
must have all the
necessary pads for its OpMode
.
Spi
An Spi
struct can only be created from a ValidConfig
, and it has
only one type parameter, the corresponding Config
uration.
use atsamd_hal::gpio::v2::{PA08, PA09};
use atsamd_hal::sercom::v2::{Sercom0, spi};
use atsamd_hal::sercom::v2::spi::{Master, NineBit};
use atsamd_hal::typelevel::NoneT;
// Assuming SAMD21
type Pads = spi::PadsFromIds<Sercom0, PA08, NoneT, PA09>;
type Config = spi::Config<Pads, Master, NineBit>;
type Spi = spi::Spi<Config>;
Only the Spi
struct can actually perform transactions. To do so, use the
embedded HAL traits, like spi::FullDuplex
,
serial::Read
and serial::Write
. See the Spi
documentation for more information about the trait implementations, which
vary based on the CharSize
and Pads
. For instance, FullDuplex
is
only implemented if the Pads
are both Tx
and Rx
, and its word
size varies between u8
and u16
, depending on CharSize
.
use nb::block;
use embedded_hal::spi::FullDuplex;
block!(spi.send(0x0155));
let rcvd: u16 = block!(spi.read());
Structs
A configurable, disabled SPI peripheral
Error bit flags for SPI transactions
Interrupt bit flags for SPI transactions
Container for a set of SERCOM pads
An enabled SPI peripheral that can perform transactions using the embedded HAL traits
Enums
CharSize
variant for 8-bit transactions
Error enum
for SPI transactions
OpMode
variant for Master mode
OpMode
variant for Master mode with hardware-controlled slave select
CharSize
variant for 9-bit transactions
Clock phase
Clock polarity
OpMode
variant for Slave mode
Constants
Helper for CPOL = 0, CPHA = 0
Helper for CPOL = 0, CPHA = 1
Helper for CPOL = 1, CPHA = 0
Helper for CPOL = 1, CPHA = 1
Traits
Type class for all possible Config
types
Type class for all possible Spi
types
Type-level enum representing the SPI character size
Configure the DIPO
and DOPO
fields based on a set of Pads
Marker trait for Master operating modes
Marker trait for a set of Pads
that cannot receive
Marker trait for a set of Pads
that cannot transmit
Type-level enum representing the SPI operating mode
Type-level function to recover the OptionalPad
types from a generic set
of Pads
Marker trait for a set of Pads
that can receive
Marker trait for a set of Pads
that can transmit
Marker trait for a set of Pads
that can transmit OR receive
Marker trait for valid SPI Config
urations
Marker trait for valid sets of Pads