SAM D21 SERCOM I²C Slave Configuration

Last modified by Microchip on 2023/11/10 11:09


This page provides a more detailed description of how to configure the SAM D21 MCU SERCOM peripheral into an I²C slave. We cover the key registers to be configured to implement a simple I²C slave application where an I²C master can read and write to the slave register map on the MCU.

The very first thing to consider when configuring an I²C slave driver is to decide which of the two interrupt strategies will be picked for the application (they can be changed in run mode if necessary). The strategies are controlled by the SCL Stretch Mode bit (CTRLA.SCLSM).

The default strategy is CTRLA.SCLSM = 0, where the SCL line is stretched before or after the acknowledge bit. In this mode, the I²C slave operates according to the following behavioral diagram:

I2C Slave behavioral diagram

The circles labeled Sn (S1, S2..) indicate the nodes the bus logic can jump to based on software or hardware interaction.

The second strategy is CTRLA.SCLSM = 1, where interrupts will only occur after the ACK bit is sent. This strategy can be used when it is not necessary to check DATA before acknowledging. For master reads, an address and data interrupt will be issued simultaneously after the address acknowledge. However, for master writes, the first data interrupt will be seen after the first data byte has been received by the slave and the acknowledge bit has been sent to the master.

We will focus on the default operation of the SCLSM bit (CTRLA.SCLSM = 0) so that the application firmware can have control over clock stretching and acknowledgment.

Back to top

Configuration Steps

The following instructions should be used when configuring the SERCOM peripheral to work as an I²C slave. This section explores a simple and basic configuration. More advanced applications might use extra functionalities from the peripheral, but the basic principle remains the same.

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

  1. Configure the pins to work as SERCOM I/Os using the PMUX
  2. Provide a bus clock to the SERCOM peripheral using the Power Manager
  3. Provide a generic clock to the SERCOM peripheral using GCLK
  4. Configure the SERCOM I²CS control registers
  5. Configure the SERCOM interrupts

Configure the SERCOM I²C Pins Using the PMUX

Use the “I/O Multiplexing and Considerations” section of the "SAM D21 Family Datasheet" to determine which pins can be used and for which SERCOM. For the example application that will follow this page, PA08 and PA09 are used, along with SERCOM2.

For the configuration selected above, PA08 and PA09 PMUX functionality must be configured to setting D, from the datasheet PMUX table section, as shown in the accompanying image.

PORT Function multiplexing for A, B, and C variant devices

The following is a code example that performs this assignment:

PORT->Group[0].WRCONFIG.reg =
       PORT_WRCONFIG_PMUX(PORT_PMUX_PMUXE_D_Val) |     //Config for PMUX
       PORT_WRCONFIG_PINMASK(PORT_PA08|PORT_PA09);     //Config PA08 and PA09

Provide a Bus Clock to the SERCOM Peripheral Using the Power Manager

The SERCOM peripheral is implemented on the Advanced Peripheral Bus (APB) C. To communicate with the register set, we enable the synchronous clock to the peripheral using the Power Manager (PM) register set. The following is example code for enabling SERCOM2:

PM->APBCMASK.reg |= PM_APBCMASK_SERCOM2; //Enable the SERCOM2 under the PM

Provide a Generic Clock to the SERCOM Peripheral Using GCLK

The following is an example of SERCOM2 being configured to use generic clock source 0 (GCLK 0 - same clock source as used for the CPU):


This is only valid for the SAMD Arm® Cortex®-M0+ devices. On the SAML, the configuration for the clocks will be different!

Configure the SERCOM I²CS Control Registers

To configure the actual SERCOM operation, the following control registers will be configured:

  1. CTRLA: Set the MODE bits to configure the I²C Slave mode.
  2. CTRLB: Set the SMART mode bit, which will help to automate the ACK/NACK issuing on the I²C operation.
  3. ADDR: Add here what will be the 7-bit Slave address to which the peripheral will reply to.

The following is example code that performs these actions:

SERCOM2->I2CS.CTRLB.reg = SERCOM_I2CS_CTRLB_SMEN;            //Configure I2C in SMART mode
SERCOM2->I2CS.ADDR.reg = SERCOM_I2CS_ADDR_ADDR(I2C_SLAVE_ADDR);    //I2C Slave address (7-bit address)

Configure the SERCOM Interrupts

Finally, in most I²C applications in Slave mode, you will enable interrupts so that each frame can be processed using such functionality, instead of polling from a loop. The following is an example of enabling interrupts under Slave Address Match, Data Ready Match, and STOP Condition for the SERCOM2:

       SERCOM_I2CS_INTENSET_PREC |        //Enable interrupt on STOP condition
       SERCOM_I2CS_INTENSET_AMATCH |    //Enable interrupt on ADD MATCH condition
       SERCOM_I2CS_INTENSET_DRDY;        //Enable interrupt on DAT READY condition

NVIC_EnableIRQ(SERCOM2_IRQn);    //Enable the global interrupt for the peripheral

After all the steps of this configuration are done, the system is ready to receive I²C commands, which causes the interrupt into the SERCOM vector when one of the conditions set for interrupt happens. Note that this configuration sequence is basic and can be expanded for applications of higher complexity.

Back to top

Learn More

Back to top