SAM C21 SERCOM SPI Slave Configuration

Overview

This page provides a more detailed description of how to configure the SAM C21 SERCOM peripheral into an SPI Slave. It will cover the key registers to be configured to implement a simple SPI Slave application where the SAM C21 accepts and responds to SPI commands sent by an SPI Host Application running on a PC.

The SPI Slave has several configuration possibilities that need to be considered when interfacing to external SPI Master devices.

Data Transfer Modes

The SPI Slave of the SAM C21 supports all four data transfer modes.

table27-3.png
figure27-3-1.png
figure27-3-2.png

Module Block Diagram (SPI Slave)

samc21-spi-slave-block-diagram.png

Data Interface

There is only a single register interface for the SERCOM in SPI Slave mode, the DATA register. The block diagram above shows these as two separate paths but they share a common register address.

Data to be transmitted by the SPI Slave is written to the DATA register.

Data to be received by the SPI Slave is read from the DATA register.

Clock Interface

The external clock provided via the SCK pin function provides the necessary module clocks. There is no need to configure the BAUD register in SPI Slave mode.

Slave Select (SS) Operation

Per the previous diagrams, an SPI transaction is started with the SS line being asserted by the Master. This detection is automatically detected by the SERCOM module. However, there is an option to allow the device to be woken up when the SS line is asserted by enabling the CTRLB.SSDE bit.

Interrupts

In SPI Slave mode, there are five interrupt sources:

Data Register Empty (DRE) Set when the DATA register is empty
NOTE — flag is cleared by writing to the DATA register
Transmission Complete (TXC) Set when a rising edge is detected on SS
Reception Complete (RXC) Set when unread data is in the DATA register
NOTE — flag is cleared by reading the DATA register
Slave Select Low (SSL) Set when a falling edge is detected on SS
Error (ERR) Set when an error is detected — the only error in SPI Slave mode is the buffer overflow, found at the STATUS.BUFOVF

Addressing Modes

In SPI Slave mode, there are three optional slave addressing modes. These modes work by performing the desired address comparison on the first data byte received by the SERCOM module after SS is asserted.

Enabling Addressing is selected via the CTRLA.FORM register bits.

The desired addressing mode is selected by the CTRLB.AMODE register bits.

MODE FUNCTION
Mask ADDRMASK[n] removes bit n from the address mask comparison
2 Addresses ADDRMASK contains the first match address
ADDR contains the second match address
Address Range ADDRMASK contains the lower limit of the address range
ADDR contains the higher limit of the address range
NOTE — Address ranges are inclusive of the ADDRMASK and ADDR register values
addressing-mode-30-4.png
addressing-mode-30-5.png
addressing-mode-30-6.png

Configuration Steps

Use the following instructions when configuring the SERCOM peripheral to work as an SPI Slave. This section explores a simple and basic configuration, where the SAM C21 is connected as an SPI Slave to an MCP2210 SPI Master device, which issues commands from a PC Terminal Application.

spi-slave-demo-connection-diagram.png

This application uses:

  • SERCOM5 in SPI Slave mode, with Address Range slave addressing mode enabled
  • PB01 (SCK), PB00 (MOSI), PB02 (MISO), PB03 (SS)


More advanced applications might use extra functionalities from the peripheral, but the basic principle remains the same.

Below is a high-level step list to configure the peripheral:

  1. Configure the SERCOM pins using the PMUX
  2. Provide a Bus Clock to the peripheral using MCLK
  3. Provide a Generic Clock to the peripheral using GCLK
  4. Configure the SERCOM SPI control registers for SPI Slave operation
  5. Configure Interrupts
  6. Enable Module

Step 1. Configure the SERCOM pins using the PMUX

Use the “I/O Multiplexing and Considerations” section of the "SAM C21 Family Datasheet" to determine what pins can be used and for which SERCOM. For the example application that follows this page, PB00, PB01, PB02 and PB03 are used, along with SERCOM5.

For the configuration selected above, PB00, PB01, PB02, and PB03 PMUX functionality must be configured to use setting D, from the datasheet PMUX table section, as shown:

config-step1-table6-2.png

The following is a code example which performs this assignment:

#define PORTB (1ul)
#define SPI_SCK_PIN 1
#define SPI_MOSI_PIN 0
#define SPI_MISO_PIN 2
#define SPI_nSS_PIN 3

//    SPI-MOSI
//    PB00 (SERCOM5-PAD2)
PORT->Group[PORTB].PINCFG[SPI_MOSI_PIN].bit.PMUXEN   = 1;
PORT->Group[PORTB].PMUX[0].bit.PMUXE                 = GPIO_PIN_FUNCTION_D;
PORT->Group[PORTB].DIRCLR.reg                        = (0x00000001 << SPI_MOSI_PIN);

//    SPI-CLK
//    PB01 (SERCOM5-PAD3)
PORT->Group[PORTB].PINCFG[SPI_SCK_PIN].bit.PMUXEN    = 1;
PORT->Group[PORTB].PMUX[0].bit.PMUXO                 = GPIO_PIN_FUNCTION_D;
PORT->Group[PORTB].DIRCLR.reg                        = (0x00000001 << SPI_SCK_PIN);

//    SPI-MISO
//    PB02 (SERCOM5-PAD0)
PORT->Group[PORTB].PINCFG[SPI_MISO_PIN].bit.PMUXEN   = 1;
PORT->Group[PORTB].PMUX[1].bit.PMUXE                 = GPIO_PIN_FUNCTION_D;
PORT->Group[PORTB].DIRSET.reg                        = (0x00000001 << SPI_MISO_PIN);

//    SPI-nSS
//    PB03 (SERCOM5-PAD1)
PORT->Group[PORTB].PINCFG[SPI_nSS_PIN].bit.PMUXEN    = 1;
PORT->Group[PORTB].PMUX[1].bit.PMUXO                 = GPIO_PIN_FUNCTION_D;
PORT->Group[PORTB].DIRCLR.reg                        = (0x00000001 << SPI_nSS_PIN);

Note – in addition to configuring the PORT registers, the SERCOM module must also correctly assign the PADS to the SPI input and output pin functions in the SERCOM control registers. For SPI Slave, CTRLA.DIPO is used to assign the MOSI pin location and CTRL.DOPO is used to assign the MISO, SCK and SS pin locations:
dipo-dopo.png

If these are not configured correctly, the module will not operate properly with the pins assigned. See Step 4 below for a code example that initializes these bit-fields.

Step 2. Provide a Bus Clock to the peripheral using MCLK

The SERCOM peripheral is implemented on the Advanced Peripheral Bus C (APBC). To communicate with the register set, we enable the synchronous clock to the peripheral using the Main Clock Controller (MCLK) register set.

Here is a code example for enabling the bus clock for SERCOM5:

MCLK->APBCMASK.reg |= MCLK_APBCMASK_SERCOM5;        //enable SERCOM5 bus clock

Step 3. Provide a Generic Clock to the peripheral using GCLK

The Generic Clock for a peripheral must be configured by writing to the respective Peripheral Channel Control register PCHCTRLm. The Generator used as the source for the Peripheral Clock must be written to the GEN bit field in the Peripheral Channel Control register PCHCTRLm.GEN.

For SERCOM5, there are two clock input selections, a Main clock and a Slow clock. Table 16-9 in the SAM C21 datasheet outlines the PCHCTRLm register-to-peripheral-channel mapping as shown:

table16-9.png

The following code snippet assigns the GCLK to these peripheral channels:

GCLK->PCHCTRL[24].reg    = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; // Slow clock
GCLK->PCHCTRL[25].reg    = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; // Main clock

Each SERCOM module has two clock input selections, a Main clock and a Slow clock. Only the Main clock needs to be assigned for SPI Slave operation.

Step 4. Configure the SERCOM SPI control registers for SPI Slave operation

The following code example enables SPI Slave mode operation, with Address Range addressing mode enabled (addresses between 0x01 and 0x07 will be detected). 8-bit data size is selected, and the SERCOM PADS are assigned to the appropriate SPI pin functions via CTRLA.DIPO and CTRLA.DOPO bit-fields:

SERCOM5->SPI.DBGCTRL.reg              = 0;
SERCOM5->SPI.ADDR.bit.ADDR            = 0x07;                // High address limit
SERCOM5->SPI.ADDR.bit.ADDRMASK        = 0x01;                // Low address limit
SERCOM5->SPI.BAUD.reg                 = 0x00;

SERCOM5->SPI.CTRLB.reg |= SERCOM_SPI_CTRLB_RXEN
                        | SERCOM_SPI_CTRLB_AMODE(2)      // Address Range addressing mode
                        | SERCOM_SPI_CTRLB_SSDE
                        | SERCOM_SPI_CTRLB_CHSIZE(0);    // 8-bit data

while (SERCOM5->SPI.SYNCBUSY.bit.CTRLB);

SERCOM5->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_RUNSTDBY     
                        | SERCOM_SPI_CTRLA_DOPO(3)        // SERCOM5 Data Out Pinout
                        | SERCOM_SPI_CTRLA_DIPO(2)        // SERCOM5 Data In Pinout
                        | SERCOM_SPI_CTRLA_FORM(2)        // Format: SPI frame with address
                        | SERCOM_SPI_CTRLA_MODE(2);       // SPI Slave mode operation
                                                          // Do not enable module yet

while (SERCOM5->SPI.SYNCBUSY.bit.ENABLE);

Note that the module is not enabled until interrupts are configured.

Step 5. Configure Interrupts

For this example application, the following SPI interrupts will be enabled:

  • TXC (TRANSMIT COMPLETE)
  • RXC (RECEIVE COMPLETE)
  • SSL (SLAVE SELECT LOW)
  • ERROR (BUFFER OVERFLOW ERROR HAS OCCURRED)


The following code example enables these interrupt sources, and set the interrupt priority level to "3" (lowest priority):

SERCOM5->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC 
                            | SERCOM_SPI_INTFLAG_RXC 
                            | SERCOM_SPI_INTFLAG_SSL 
                            | SERCOM_SPI_INTFLAG_ERROR;    // clear all flags

SERCOM5->SPI.INTENSET.reg = SERCOM_SPI_INTFLAG_TXC 
                            | SERCOM_SPI_INTFLAG_RXC 
                            | SERCOM_SPI_INTFLAG_SSL 
                            | SERCOM_SPI_INTFLAG_ERROR;    // enable interrupts

NVIC_SetPriority(SERCOM5_IRQn, 3);        // set priority
NVIC_EnableIRQ(SERCOM5_IRQn);            // enable SERCOM5 NVIC interrupt line

Step 6. Enable Module

Finally, we enable the module:

SERCOM5->SPI.CTRLA.bit.ENABLE = 1;
while (SERCOM5->SPI.SYNCBUSY.bit.ENABLE);


After all the steps of this configuration are done, the system is ready to receive commands/data. Visit the SAM C21 SERCOM SPI Slave Example Project page to see the complete working demo.

 Learn More

 
SERCOM SPI Slave Overview
Learn more >
 
SERCOM SPI Slave Example Project
Learn more >
© 2019 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.