SPI choices for D21-based Arduino boards
On Arduino models with the Atmel SAMD21G18A(D21 for short) processor such as the Tian and the M0 Pro, it is possible to implement Serial Peripheral Interface(SPI) protocol on
any of several different combinations of Arduino pins.
On those models, the SPIClass
class in the Arduino libraries supports a SPI bus
over the ICSP connector as it does on other Arduino models.
But that processor has circuits to support several SPI buses. You can write a subclass of SPIClass
.
In that class, you can configure your own SPI bus to use a different set of digital pins for an SPI bus.
To do this, you need to learn a little about what is inside the D21
Hardware
The D21
Inside this ARM processor is a
collection of configurable peripheral interface devices.
The D21 Datasheet
describes the chip in great detail. It is the source for information in this document.
Connecting to the D21
The signals follow this path from connected SPI device to program running on the D21:
- from Arduino pins to processor pins
- from processor pins to multiplexors
- from multiplexors to SERCOM pads
- from SERCOM pads to SPI roles
The sections below follow this path in more detail.
Processor Pins, Arduino Pins
D21 processor pins are labeled A00 through A31 and B00 through B31.
On the Arduino boards, I/O pins D0 through D13 and A0 through A5, SDA and SCL are each connected
to a processor pin.
Serial Communications Interfaces
A Serial Communications Interface(a SERCOM
) is a circuit inside the D21 for serial communications. Each SERCOM
can be configured
to support one of several different
serial protocols such as USART, SPI and I2C. There are six SERCOM
s : SERCOM0
, ..., SERCOM5
.
Each of them has four signal lines called PAD[0]
, PAD[1]
, PAD[2]
, PAD[3]
.
Some of the serial interfaces are already assigned to Serial, Serial5 and SPI classes. Those
are SERCOM0, SERCOM5 and SERCOM4. This leaves SERCOM1, SERCOM2, and SERCOM3 available for SPI–as long
as you don't need those serial interfaces to support other serial protocols.
A sketch can configure the mapping between the SPI signals: MISO
, MOSI
, SCK
, _SS
and the SERCOM lines: PAD[0]
, PAD[1]
, PAD[2]
, PAD[3]
within limits.
Multiplexing
Each of the processor pins can be configured to perform one of many possible functions. A pin is
assigned to a function named with a single letter A through H. These are described in the datasheet
in the chapter on multiplexing. Functions C
and D
are of interest here because they are used to
connect to SERCOMs. The table shows the connections for functions C
and D
for the processor pins
that are connected to Arduino pins.
A program assigns one of these functions to a pin. When it assigns function D
to pin D2, the pin becomes, effectively, a
connection to the PAD[0] of SERCOM2 as you can see in this table.
Arduino | Processor | C | | D | |
Pin | Pin | SERCOM | | SERCOM_ALT | |
D0 | PA11 | SERCOM0 | PAD[3] | SERCOM2 | PAD[3] |
D1 | PA10 | SERCOM0 | PAD[2] | SERCOM2 | PAD[2] |
D2 | PA08 | SERCOM0 | PAD[0] | SERCOM2 | PAD[0] |
D3 | PA09 | SERCOM0 | PAD[1] | SERCOM2 | PAD[1] |
D4 | PA14 | SERCOM2 | PAD[2] | SERCOM4 | PAD[2] |
D5 | PA15 | SERCOM2 | PAD[3] | SERCOM4 | PAD[3] |
D6 | PA20 | SERCOM5 | PAD[2] | SERCOM3 | PAD[2] |
D7 | PA21 | SERCOM5 | PAD[3] | SERCOM3 | PAD[3] |
D8 | PA06 | | | SERCOM0 | PAD[2] |
D9 | PA07 | | | SERCOM0 | PAD[3] |
D10 | PA18 | SERCOM1 | PAD[2] | SERCOM3 | PAD[2] |
D11 | PA16 | SERCOM1 | PAD[0] | SERCOM3 | PAD[0] |
D12 | PA19 | SERCOM1 | PAD[3] | SERCOM3 | PAD[3] |
D13 | PA17 | SERCOM1 | PAD[1] | SERCOM3 | PAD[1] |
A0 | PA02 | | | | |
A1 | PB08 | | | SERCOM4 | PAD[0] |
A2 | PB09 | | | SERCOM4 | PAD[1] |
A3 | PA04 | | | SERCOM0 | PAD[0] |
A4 | PA05 | | | SERCOM0 | PAD[1] |
A5 | PB02 | | | SERCOM5 | PAD[0] |
SDA | PA22 | SERCOM3 | PAD[0] | SERCOM5 | PAD[0] |
SCL | PA23 | SERCOM3 | PAD[1] | SERCOM5 | PAD[1] |
Software
Libraries
There are a few library files that you need to look at to follow how the example works:
- /Applications/Arduino-1.7.10.app/Contents/Java/hardware/arduino/samd/libraries/SPI/SPI.h
- /Applications/Arduino-1.7.10.app/Contents/Java/hardware/arduino/samd/cores/arduino/SERCOM.h
- /Applications/Arduino-1.7.10.app/Contents/Java/hardware/arduino/samd/cores/arduino/SERCOM.cpp
- /Applications/Arduino-1.7.10.app/Contents/Java/hardware/arduino/samd/variants/arduino_zero/variant.h
- /Applications/Arduino-1.7.10.app/Contents/Java/hardware/arduino/samd/variants/arduino_zero/variant.cpp
- /Applications/Arduino-1.7.10.app/Contents/Java/hardware/arduino/sam/system/libsam/include/pio.h
These paths are typical for Macintosh. Note that, in order to see the files in the finder, you
need to right click on the application and select Show Package Contents.
Pin assignments
In the example, Arduino pins are assigned to custom SPI roles:
- SDA - MOSI
- SCL - SCK
- D10 - SS
- D7 - MISO
The choice of pins and signals is entirely arbitrary within limits. This figure shows the target
configuration.
Multiplexers
In the multiplexing table above, we can see that our goal can be reached. In the row for Arduino pin
D7, in the SERCOM-ALT column, D, is SERCOM3
, PAD[3]
. When software assigns
function D to that pin, it makes a connection to the pad of SERCOM3
.
DOPO and DIPO
Data out pinout and data in pinout. These are fields in hardware control registers. A sketch can set the values when initializing a SERCOM.
For SPI master, possible DOPO values are:
SPI_PAD_0_SCK_1
MOSI=PAD[0], SCK=PAD[1]
SPI_PAD_2_SCK_3
MOSI=PAD[2], SCK=PAD[3]
SPI_PAD_3_SCK_1
MOSI=PAD[3], SCK=PAD[1]
SPI_PAD_0_SCK_3
MOSI=PAD[0], SCK=PAD[3]
For SPI master, possible DIPO values are:
SERCOM_RX_PAD_0
MISO=PAD[0]
SERCOM_RX_PAD_1
MISO=PAD[1]
SERCOM_RX_PAD_2
MISO=PAD[2]
SERCOM_RX_PAD_3
MISO=PAD[3]
Example sketch
Sketches have been run on Arduino IDE 1.7.11.
When this sketch is loaded, the user can enter a command to
tell the sketch to send a short text message to the slave. The sketch displays the response
from the slave in the Serial Monitor.
To send and receive a message, the sketch will:
- turn on SPI
- set _SS to LOW(active)
- using a library function send and receive bytes one at a time
- shut down SPI
- set _SS to HIGH(inactive)/li>
- write the data received from the slave onto the serial port
Before running the sketch, the SPI pins should be connected to another SPI device configured as slave. Don't forget
to attach GND as well.
Moving on to your own SPI bus
To build your own custom SPI connections on the Tian or other Arduino based on a SAMD21 processor:
- Decide which pins are available.
- Choose a SERCOM that connects to three of those pins for
MISO
,MOSI
and SCK
.
- Choose a pin for
_SS
.
- Decide which of the SERCOM connections will be used for which SPI connection
- Once you have determined a configuration that works, you can replace the values in the sample sketch
to run it.
Available pins
Consider the other requirements for your sketch. Which pins do you need? Which pins are take by
other uses such as serial for the console?
Choose a SERCOM
Given the available pins, search the table in the multiplexing section above for a SERCOM device.
It should be one that isn't already in use and connects to at least 3 of the pins that are
available. Use this information to setup a MySpiPadSet
structure like the one in the
sample sketch. The MySpiPadSet
and sercom device are parameters for a MySPI
constructor.
A pin for _SS
It is your master mode program that will control the _SS
output.
The MySpiPadSet
structure in MySpi.h
includes an member for slave select.
This is not used in this example but included for future expansion of MySPI
.
The digital pin that you use for _SS
does not need to be connected to a SERCOM.
Connections between SERCOM and SPI signals
The choices for which of the SERCOM connections, PAD[0]
through PAD[3]
are
listed in the section above on DIPO
and DIPI[0]
. These values are
passed as parameters to begin()
in MySPI
class.
Go
The software configuration is complete ready to run.