Module grand_central_m4::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 peripheral pads, but only
certain Pin
combinations are acceptable. In particular, all Pin
s must be
mapped to the same Sercom
and IoSet
(see section 6.2.8.1 of 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 up to six type parameters. The first two specify the
Sercom
and IoSet
, 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};
use atsamd_hal::sercom::v2::{Sercom0, spi};
use atsamd_hal::sercom::v2::pad::IoSet1;
use atsamd_hal::typelevel::NoneT;
type Miso = Pin<PA08, AlternateC>;
type Sclk = Pin<PA09, AlternateC>;
type Pads = spi::Pads<Sercom0, IoSet1, 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::sercom::v2::pad::IoSet1;
use atsamd_hal::typelevel::NoneT;
type Pads = spi::PadsFromIds<Sercom0, IoSet1, PA08, NoneT, PA09>;
Instances 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. The builder methods automatically convert each
pin to the correct PinMode
.
Note that the CK
Pin
must map to Pad1
, and if specified, the SS
Pin
must map to Pad2
. The DI
and DO
Pin
s can vary in PadNum
based on the Dipo
and Dopo
values.
use atsamd_hal::pac::Peripherals;
use atsamd_hal::gpio::v2::Pins;
use atsamd_hal::sercom::v2::{Sercom0, spi};
use atsamd_hal::sercom::v2::pad::IoSet1;
let mut peripherals = Peripherals::take().unwrap();
let pins = Pins::new(peripherals.PORT);
let pads = spi::Pads::<Sercom0, IoSet1>::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:
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
transaction Length
, in bytes, represented at the type level using the
[typenum
] crate. Valid transaction lengths are provided in the lengths
sub-module. The default Length
is U1
.
use atsamd_hal::gpio::v2::{PA08, PA09};
use atsamd_hal::sercom::v2::{Sercom0, spi};
use atsamd_hal::sercom::v2::spi::{Master, lengths::U2};
use atsamd_hal::sercom::v2::pad::IoSet1;
use atsamd_hal::typelevel::NoneT;
type Pads = spi::PadsFromIds<Sercom0, IoSet1, PA08, NoneT, PA09>;
type Config = spi::Config<Pads, Master, U2>;
The SPI peripheral has two different ways to control the transaction length, the character size and the length counter. The character size can be set to 8-bit or 9-bit transactions. The length counter can be set to produce transactions of any length from 1-255 bytes. For simplicity, this module ignores character size. Instead, the SPI peripheral is always configured to use 32-bit extension mode and the length counter.
Upon creation, the Config
takes ownership of both the Pads
and the
PAC Sercom
struct. It takes a reference to the MCLK, 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 mclk = peripherals.MCLK;
let sercom = peripherals.SERCOM0;
// Configure GCLK for 10 MHz
let freq = 10.mhz();
let config = spi::Config::new(&mclk, 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;
let spi = spi::Config::new(&mclk, sercom, pads, freq)
.baud(1.mhz())
.length::<U2>()
.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 Config
, and it has only one
type parameter, the corresponding config.
use atsamd_hal::gpio::v2::{PA08, PA09};
use atsamd_hal::sercom::v2::{Sercom0, spi};
use atsamd_hal::sercom::v2::spi::{Master, lengths::U2};
use atsamd_hal::sercom::v2::pad::IoSet1;
use atsamd_hal::typelevel::NoneT;
type Pads = spi::PadsFromIds<Sercom0, IoSet1, PA08, NoneT, PA09>;
type Config = spi::Config<Pads, Master, U2>;
type Spi = spi::Spi<Config>;
Only Spi
s 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 transaction Length
and Pads
. For instance,
FullDuplex
is only implemented if the Pads
are both Tx
and
Rx
and if the transaction Length
is less than U4
.
use nb::block;
use embedded_hal::spi::FullDuplex;
block!(spi.send(0xAA55));
let rcvd: u16 = block!(spi.read());
Modules
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
Enums
Error enum
for SPI transactions
OpMode
variant for Master mode
OpMode
variant for Master mode with hardware-controlled slave select
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
Marker trait for transactions that are performed atomically
Control the DIPO
field as a function of the PadNum
type
Control the DOPO
field as a function of the PadNum
type
Marker trait for transaction Length
s greater than four
Type-level enum representing the SPI transaction length, in bytes
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 statically known transaction Length
s
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
Type Definitions
Marker type for a run-time dynamic Length