Jump to main content

##

# 3.9.22 Serial Communication Interface (SERCOM)

A SERCOM can be configured in USART, SPI or I2C mode

USART Mode

This section provides interface to use the SERCOM peripheral in USART mode. The SERCOM USART PLIB can be configured in blocking, non-blocking or ring buffer mode.

Blocking mode

In blocking mode, the transfer APIs block until the requested data is transferred.

Non-blocking mode

In non-blocking mode the peripheral interrupt is enabled. The transfer API initiates the transfer and returns immediately. The transfer is then completed from the peripheral interrupt. Application can either use a callback to get notified when the transfer is complete or can use the IsBusy API to check the completion status.

Ring buffer mode

In ring buffer mode, the receiver is always enabled, and the received data is saved in the internal receive ring buffer, size of which can be configured using MCC. The application can use the API calls to read the data out from the ring buffer. APIs are provided to query the number of (unread) bytes available in the receive buffer, free space in the receive buffer and size of the receive buffer. Similarly, during transmission, the application data is deep copied into the internal transmit ring buffer, size of which can be configured using MCC. This allows the use of local buffers for data transmission. APIs are provided to query the free space in the transmit buffer, number of bytes pending transmission and the size of the transmit buffer. Additionally, application can enable notifications to get notified when n bytes are available in the receive buffer or when n bytes of free space is available in the transmit buffer. The APIs allow application to set the threshold levels for notification in both receive and transmit buffers. Further, application can also choose to enable persistent notifications, whereby the application is notified until the threshold condition is met.

In all the modes, library provides API to change the baud, parity, data width and the number of stop bits at run time.

## Using The Library

Blocking Mode

    #define RX_BUFFER_SIZE 10
    char message[] = "SERCOM Example in blocking mode";
    char receiveBuffer[RX_BUFFER_SIZE] = {0};
    USART_ERROR errorStatus;
    char rxData = 0;

    int main ( void )
    {
        /* Initialize all modules */
        SYS_Initialize ( NULL );

        /* Transmit buffer*/
        SERCOM0_USART_Write(message, sizeof(message));

    	/* Wait for a character to be received */
    	while(SERCOM0_USART_ReceiverIsReady() == false);

    	if(SERCOM0_USART_ErrorGet() == USART_ERROR_NONE)
    	{
    		/* Read a byte */
    		rxData = SERCOM0_USART_ReadByte();
    	}

    	/* Receive buffer */
        if (SERCOM0_USART_Read(receiveBuffer, RX_BUFFER_SIZE)) == false)
    	{
    		/* Read failed, get the error */
    		errorStatus SERCOM0_USART_ErrorGet();

    		/* Handle the error */
    	}
        else
    	{
    		/* Transmit the received buffer*/
    		SERCOM0_USART_Write(receiveBuffer, RX_BUFFER_SIZE);
    	}

        /* Execution should not come here during normal operation */

        return ( EXIT_FAILURE );
    }

Non-blocking Mode

    #define RX_BUFFER_SIZE 10

    char message[] = "**** Non-blocking Transfer with the interrupt  ****\r\n\
    **** Type 10 characters. The received characters are echoed back ****\r\n";

    char messageError[] = "**** USART error occurred ****\r\n";

    char receiveBuffer[RX_BUFFER_SIZE] = {0};
    char echoBuffer[RX_BUFFER_SIZE+4] = {0};

    bool errorStatus = false;
    bool writeStatus = false;
    bool readStatus = false;

    void APP_WriteCallback(uintptr_t context)
    {
        writeStatus = true;
    }

    void APP_ReadCallback(uintptr_t context)
    {
        if(SERCOM0_USART_ErrorGet() != USART_ERROR_NONE)
        {
            /* ErrorGet clears errors, set error flag to notify console */
            errorStatus = true;
        }
        else
        {
            readStatus = true;
        }
    }

    int main ( void )
    {
        /* Initialize all modules */
        SYS_Initialize ( NULL );

        /* Register callback functions and send start message */
        SERCOM0_USART_WriteCallbackRegister(APP_WriteCallback, 0);
        SERCOM0_USART_ReadCallbackRegister(APP_ReadCallback, 0);
        SERCOM0_USART_Write(&message[0], sizeof(message));

        while ( true )
        {
            if(errorStatus == true)
            {
                /* Send error message to console */
                errorStatus = false;
                SERCOM0_USART_Write(&messageError[0], sizeof(messageError));
            }
            else if(readStatus == true)
            {
                /* Echo back received buffer and Toggle LED */
                readStatus = false;

                echoBuffer[0] = '\n';
                echoBuffer[1] = '\r';
                memcpy(&echoBuffer[2], receiveBuffer,sizeof(receiveBuffer));
                echoBuffer[RX_BUFFER_SIZE+2] = '\n';
                echoBuffer[RX_BUFFER_SIZE+3] = '\r';

                SERCOM0_USART_Write(&echoBuffer[0], sizeof(echoBuffer));
            }
            else if(writeStatus == true)
            {
                /* Submit buffer to read user data */
                writeStatus = false;
                SERCOM0_USART_Read(&receiveBuffer[0], sizeof(receiveBuffer));
            }
            else
            {
                /* Repeat the loop */
                ;
            }
        }

        /* Execution should not come here during normal operation */

        return ( EXIT_FAILURE );
    }

Ring buffer Mode

    uint8_t txBuffer[50];
    uint8_t rxBuffer[10];
    volatile uint32_t nBytesRead = 0;
    volatile bool txThresholdEventReceived = false;
    volatile bool rxThresholdEventReceived = false;

    void usartReadEventHandler(SERCOM_USART_EVENT event, uintptr_t context )
    {
        uint32_t nBytesAvailable = 0;

        if (event == SERCOM_USART_EVENT_READ_THRESHOLD_REACHED)
        {
            /* Receiver should atleast have the thershold number of bytes in the ring buffer */
            nBytesAvailable = SERCOM0_USART_ReadCountGet();

            nBytesRead += SERCOM0_USART_Read((uint8_t*)&rxBuffer[nBytesRead], nBytesAvailable);
        }
    }

    void usartWriteEventHandler(SERCOM_USART_EVENT event, uintptr_t context )
    {
        txThresholdEventReceived = true;
    }

    int main ( void )
    {
        uint32_t nBytes = 0;

        /* Initialize all modules */
        SYS_Initialize ( NULL );

        /* Register a callback for write events */
        SERCOM0_USART_WriteCallbackRegister(usartWriteEventHandler, (uintptr_t) NULL);

        /* Register a callback for read events */
        SERCOM0_USART_ReadCallbackRegister(usartReadEventHandler, (uintptr_t) NULL);

        /* Print the size of the read buffer on the terminal */
        nBytes = sprintf((char*)txBuffer, "RX Buffer Size = %d\r\n", (int)SERCOM0_USART_ReadBufferSizeGet());

        SERCOM0_USART_Write((uint8_t*)txBuffer, nBytes);

        /* Print the size of the write buffer on the terminal */
        nBytes = sprintf((char*)txBuffer, "TX Buffer Size = %d\r\n", (int)SERCOM0_USART_WriteBufferSizeGet());

        SERCOM0_USART_Write((uint8_t*)txBuffer, nBytes);

        SERCOM0_USART_Write((uint8_t*)"Adding 10 characters to the TX buffer - ", sizeof("Adding 10 characters to the TX buffer - "));

        /* Wait for all bytes to be transmitted out */
        while (SERCOM0_USART_WriteCountGet() != 0);

        SERCOM0_USART_Write((uint8_t*)"0123456789", 10);

        /* Print the amount of free space available in the TX buffer. This should be 10 bytes less than the configured write buffer size. */
        nBytes = sprintf((char*)txBuffer, "\r\nFree Space in Transmit Buffer = %d\r\n", (int)SERCOM0_USART_WriteFreeBufferCountGet());

        SERCOM0_USART_Write((uint8_t*)txBuffer, nBytes);

        /* Let's enable notifications to get notified when the TX buffer is empty */
        SERCOM0_USART_WriteThresholdSet(SERCOM0_USART_WriteBufferSizeGet());

        /* Enable notifications */
        SERCOM0_USART_WriteNotificationEnable(true, false);

        /* Wait for the TX buffer to become empty. Flag "txThresholdEventReceived" is set in the callback. */
        while (txThresholdEventReceived == false);

        txThresholdEventReceived = false;

        /* Disable TX notifications */
        SERCOM0_USART_WriteNotificationEnable(false, false);

        SERCOM0_USART_Write((uint8_t*)"Enter 10 characters. The received characters are echoed back. \r\n>", sizeof("Enter 10 characters. The received characters are echoed back. \r\n>"));

        /* Wait till 10 (or more) characters are received */
        while (SERCOM0_USART_ReadCountGet() < 10);

        /* At-least 10 characters are available in the RX buffer. Read out into the application buffer */
        SERCOM0_USART_Read((uint8_t*)rxBuffer, 10);

        /* Echo the received data */
        SERCOM0_USART_Write((uint8_t*)rxBuffer, 10);

        /* Now demonstrating receiver notifications */
        SERCOM0_USART_Write((uint8_t*)"\r\n Now turning on RX notifications \r\n>", sizeof("\r\n Now turning on RX notifications \r\n>"));

        /* For demonstration purpose, set a threshold value to receive a callback after every 5 characters are received */
        SERCOM0_USART_ReadThresholdSet(5);

        /* Enable RX event notifications */
        SERCOM0_USART_ReadNotificationEnable(true, false);

        while(1)
        {
            /* Wait until at-least 10 characters are entered by the user */
            while (nBytesRead < 10);

            /* Echo the received data */
            SERCOM0_USART_Write((uint8_t*)rxBuffer, nBytesRead);

            SERCOM0_USART_Write((uint8_t*)"\r\n>", 3);

            nBytesRead = 0;
        }

        /* Execution should not come here during normal operation */

        return ( EXIT_FAILURE );
    }

SPI Mode

This section provides interface to use the SERCOM peripheral in SPI mode. The SERCOM SPI PLIB can be configured in master or slave mode.

SPI master mode

In SPI master mode, the PLIB can be configured to run in blocking mode or non-blocking mode. In blocking mode the peripheral interrupt is disabled and the transfer API blocks until the transfer is complete. In non-blocking mode, the peripheral interrupt is enabled. The transfer API initiates the transfer and returns immediately. The transfer is completed from the peripheral interrupt. Application can either use a callback to get notified when the transfer is complete or can use the IsBusy API to check the completion status.

SPI slave mode

SPI slave mode enables peripheral interrupt for data transfers. The PLIB uses internal receive and transmit buffers. The receive buffer is used to hold the data received from the SPI master while the application data to be transmitted out is copied into the transmit buffer. The size of the transmit and receive buffers is configurable in MCC. Application must register a callback with the PLIB to receive event notifications. A callback is given when the chip select is de-asserted by the SPI master. The application must read out the received data in the callback, thereby clearing the PLIB's internal RX buffer.

The PLIB optionally supports busy signalling from SPI slave to SPI master. This option can be enabled to provide an indication to the SPI master on when the SPI slave will be ready to respond. In a typical implementation, to read data from SPI slave, the SPI master asserts the chip select line and then sends a SPI packet informing the slave about the memory address to read from and the number of bytes to read and then de-asserts the chip select line. The SPI master must then wait for the SPI slave to frame the response by waiting on the busy line. Once the SPI slave drives the busy signal to ready state, the SPI master can start reading the actual data by asserting the chip select line and sending dummy writes for the number of bytes to read. Finally, after the intended bytes are read, the chip select must be de-asserted by the SPI master.

If the busy signalling is not enabled, the SPI master must wait for sufficient duration to allow the SPI slave to become ready with the response.

SPI Master in blocking (peripheral interrupt disabled) mode

    // Following code demonstrates SPI self loopback with the PLIB configured in blocking mode
    uint8_t txData[]  = "SELF LOOPBACK FOR SPI!";
    uint8_t rxData[sizeof(txData)];

    int main ( void )
    {
        /* Initialize all modules */
        SYS_Initialize ( NULL );

        /* SPI Write Read */
        SERCOM0_SPI_WriteRead(&txData[0], sizeof(txData), &rxData[0], sizeof(rxData));

        /* Compare received data with the transmitted data */
        if ((memcmp(txData, rxData, sizeof(txData)) == 0))
        {
            /* Pass: Received data is same as transmitted data */
        }
        else
        {
            /* Fail: Received data is not same as transmitted data */
        }

        while ( true )
        {
        }

        /* Execution should not come here during normal operation */

        return ( EXIT_FAILURE );
    }

SPI Master in non-blocking (peripheral interrupt enabled) mode

    // Following code demonstrates SPI self loopback with the PLIB configured in non-blocking mode

    uint8_t txData[]  = "SELF LOOPBACK FOR SPI!";
    uint8_t rxData[sizeof(txData)];
    volatile bool transferStatus = false;

    /* This function will be called by SPI PLIB when transfer is completed */
    void APP_SPI_Callback(uintptr_t context )
    {
        transferStatus = true;
    }

    int main ( void )
    {
        /* Initialize all modules */
        SYS_Initialize ( NULL );

        /* Register callback function   */
        SERCOM0_SPI_CallbackRegister(APP_SPI_Callback, 0);

        /* SPI Write Read */
        SERCOM0_SPI_WriteRead(&txData[0], sizeof(txData), &rxData[0], sizeof(rxData));

    	while (1)
    	{
    		/* Perform other tasks here ...*/

    		/* Check if transfer has completed */
    		if(transferStatus == true)
    		{
    			/* Compare received data with the transmitted data */
    			if(memcmp(txData, rxData, sizeof(txData)) == 0)
    			{
    				/* Pass: Received data is same as transmitted data */
    			}
    			else
    			{
    				/* Fail: Received data is not same as transmitted data */
    			}
    		}
    	}

    }

SPI slave mode

This example uses the SERCOM SPI peripheral library in slave mode and allows reading and writing data from/to its internal buffer by a SPI master. The SPI master writes data by sending a write command followed by two bytes of memory address followed by the data to be written.

< WR_CMD > < ADDR_MSB > < ADDR_LSB > < DATA0 > ... < DATA n >

The SPI slave asserts the Busy line to indicate to the SPI master that it is busy. Once ready, the SPI slave de-asserts the Busy line. Once the SPI slave is ready, the SPI master reads the data by sending read command followed by two bytes of memory address and the number of bytes to read.

< RD_CMD > < ADDR_MSB > < ADDR_LSB > < NUM_BYTES >

The SPI slave responds by sending the data at the requested memory address.

    typedef enum
    {
        APP_STATE_INITIALIZE,
        APP_STATE_READ,
        APP_STATE_WRITE,
        APP_STATE_IDLE,

    } APP_STATES;

    /* Commands */
    #define APP_CMD_WRITE                       0x02
    #define APP_CMD_READ                        0x03

    #define APP_MEM_BUFFER_SIZE                 512
    #define APP_RX_BUFFER_SIZE                  256
    #define APP_TX_BUFFER_SIZE                  256

    typedef struct
    {
        uint8_t busy        :1;
        uint8_t reserved    :7;
    }STATUS;

    typedef struct
    {
        volatile APP_STATES          state;
        volatile STATUS              status;
        volatile uint8_t             nBytesRead;
        volatile uint8_t             nBytesToWrite;
        volatile uint8_t             nBytesReadRequest;
        volatile uint16_t            memAddr;
    }APP_DATA;

    APP_DATA appData;

    uint8_t APP_MemoryBuffer[APP_MEM_BUFFER_SIZE] =
    {
        0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
        0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
        0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
        0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
        0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
        0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
        0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
        0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
        0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
        0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
        0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
        0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
        0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
        0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
        0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
        0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,

        0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
        0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
        0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
        0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
        0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
        0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
        0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
        0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
        0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
        0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
        0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
        0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
        0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
        0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
        0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
        0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
    };

    uint8_t APP_RxData[APP_RX_BUFFER_SIZE];
    uint8_t APP_TxData[APP_TX_BUFFER_SIZE];

    void delay(uint32_t count)
    {
        uint32_t i;

        // 1 loop roughly provides 1us delay at 32MHz CPU frequency
        for (i = 0; i < count; i++)
        {
            asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");
            asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");
            asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");
            asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");
        }
    }

    void SPIEventHandler(uintptr_t context )
    {
        if (SERCOM0_SPI_ErrorGet() == SPI_SLAVE_ERROR_NONE)
        {
            appData.nBytesRead = SERCOM0_SPI_Read(APP_RxData, SERCOM0_SPI_ReadCountGet());

            switch(APP_RxData[0])
            {
                case APP_CMD_WRITE:
                    if (appData.status.busy == 0)
                    {
                        appData.status.busy = 1;
                        appData.memAddr = ((APP_RxData[1] << 8) | (APP_RxData[2]));
                        appData.nBytesToWrite = (appData.nBytesRead - 3);
                        appData.state = APP_STATE_WRITE;
                    }
                    break;

                case APP_CMD_READ:

                    appData.memAddr = ((APP_RxData[1] << 8) | (APP_RxData[2]));
                    appData.nBytesReadRequest = APP_RxData[3];

                    if ((appData.memAddr + appData.nBytesReadRequest) <= APP_TX_BUFFER_SIZE)
                    {
                        memcpy(APP_TxData, &APP_MemoryBuffer[appData.memAddr], appData.nBytesReadRequest);
                        SERCOM0_SPI_Write(APP_TxData, appData.nBytesReadRequest);
                    }
                    break;
            }

            if (appData.status.busy == 0)
            {
                /* Indicate to SPI Master that slave is ready for data transfer */
                SERCOM0_SPI_Ready();
            }
        }
    }

    int main ( void )
    {
        /* Initialize all modules */
        SYS_Initialize ( NULL );

        appData.state = APP_STATE_INITIALIZE;

        while(1)
        {
            /* Check the application's current state. */
            switch (appData.state)
            {
                case APP_STATE_INITIALIZE:

                    SERCOM0_SPI_CallbackRegister(SPIEventHandler, (uintptr_t) 0);

                    /* Wait for instructions from SPI master */
                    appData.state = APP_STATE_IDLE;

                    break;

                case APP_STATE_WRITE:

                    /* Adding delay to simulate busy condition */
                    delay(1000);

                    /* Copy received data into Application memory buffer */
                    if ((appData.memAddr + appData.nBytesToWrite) <= APP_MEM_BUFFER_SIZE)
                    {
                        memcpy(&APP_MemoryBuffer[appData.memAddr], &APP_RxData[3], appData.nBytesToWrite);
                    }

                    appData.status.busy = 0;

                    appData.state = APP_STATE_IDLE;

                    /* Indicate to SPI Master that slave is ready for data transfer */
                    SERCOM0_SPI_Ready();

                    break;

                case APP_STATE_IDLE:
                    break;

                default:
                    break;
            }
        }
    }

I2C Mode

This section provides interface to use the SERCOM peripheral in I2C mode. The SERCOM I2C PLIB can be configured in master or slave mode.

I2C master mode The SERCOM I2C peripheral library supports the following I2C transfers:

Master Write: The master writes a block of data to the slave Master Read: The master reads a block of data from the slave Master Write/Read: The master writes and then reads back a block of data from slave.

The block of data is transferred in a non-blocking manner using a peripheral interrupt. Application can either use a callback or IsBusy API to check for completion of data transfer.

I2C slave mode

I2C slave PLIB can be configured with peripheral interrupt enabled or disabled. When peripheral interrupt is enabled, application must register a callback, to get notified of the I2C events such as address match, transmitter ready, receiver ready etc. When peripheral interrupt is disabled, PLIB provides APIs to read the interrupt status flags. Application can call this API to determine the I2C event and then use the ReadByte/WriteByte APIs to read/write over the I2C bus.

I2C Master mode

    // Following code demonstrates I2C write operation using polling method

    #define APP_SLAVE_ADDR 0x0057
    #define NUM_BYTES      10

    uint8_t myWriteData [NUM_BYTES] = {'1', '0', ' ', 'B', 'Y', 'T', 'E', 'S', '!', '!',};

    int main(void)
    {
    	/* Initialize all modules */
        SYS_Initialize ( NULL );

        /* Write data to the I2C Slave */
        SERCOM0_I2C_Write(APP_SLAVE_ADDR, &myWriteData[0], NUM_BYTES);

        /* Poll and wait for the transfer to complete */
        while(SERCOM0_I2C_IsBusy());

        /* Check if any error occurred */
        if(SERCOM0_I2C_ErrorGet() == SERCOM_I2C_ERROR_NONE)
        {
            //Transfer is completed successfully
        }
        else
        {
            //Error occurred during transfer.
        }
    }

    // Following code demonstrates I2C write operation using callback method

    #define APP_SLAVE_ADDR 0x0057
    #define NUM_BYTES      10

    uint8_t myWriteData [NUM_BYTES] = {'1', '0', ' ', 'B', 'Y', 'T', 'E', 'S', '!', '!',};

    void SERCOM0_I2C_Callback(uintptr_t context)
    {
        if(SERCOM0_I2C_ErrorGet() == SERCOM_I2C_ERROR_NONE)
        {
            //Transfer is completed successfully
        }
        else
        {
            //Error occurred during transfer.
        }
    }

    int main(void)
    {
    	/* Initialize all modules */
        SYS_Initialize ( NULL );

        /* Register Callback function */
        SERCOM0_I2C_CallbackRegister(SERCOM0_I2C_Callback, (uintptr_t)NULL);

        /* Submit Write Request */
        SERCOM0_I2C_Write(APP_SLAVE_ADDR, &myWriteData[0], NUM_BYTES);
    }

I2C Slave mode

This example uses the I2C peripheral library in slave mode and emulates an EEPROM of 512 bytes. There are two pages each of size 256 bytes. I2C slave expects two bytes of memory address from the I2C master and the memory address can range from 0x00 to 0x1FF.

    #define EEPROM_PAGE_SIZE_BYTES                  256
    #define EEPROM_PAGE_SIZE_MASK                   0xFF
    #define EEPROM_SIZE_BYTES                       512

    typedef enum
    {
        EEPROM_CMD_WRITE,
        EEPROM_CMD_IDLE,
    }EEPROM_CMD;

    typedef struct
    {
        /* currentAddrPtr - to allow for sequential read (from the current address) */
        uint16_t                    currentAddrPtr;
        /* addrIndex - used to copy 2 bytes of EEPROM memory address */
        uint8_t                     addrIndex;
        /* wrBuffer - holds the incoming data from the I2C master */
        uint8_t                     wrBuffer[EEPROM_PAGE_SIZE_BYTES];
        /* wrBufferIndex - Index into the wrBuffer[] */
        uint16_t                    wrBufferIndex;
        /* wrAddr - indicates the starting address of the EEPROM emulation memory to write to */
        volatile uint16_t           wrAddr;
        /* nWrBytes - indicates the number of bytes to write to EEPROM emulation buffer */
        volatile uint8_t            nWrBytes;
        /* internalWriteInProgress - indicates that EEPROM is busy with internal writes */
        bool                        internalWriteInProgress;
        /* eepromCommand - used to trigger write to the EEPROM emulation buffer */
        EEPROM_CMD                  eepromCommand;
    }EEPROM_DATA;

    EEPROM_DATA         eepromData;

    uint8_t EEPROM_EmulationBuffer[EEPROM_SIZE_BYTES] =
    {
        0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
        0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
        0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
        0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
        0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
        0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
        0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
        0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
        0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
        0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
        0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
        0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
        0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
        0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
        0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
        0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,

        0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
        0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
        0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
        0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
        0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
        0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
        0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
        0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
        0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
        0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
        0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
        0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
        0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
        0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
        0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
        0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
    };

    bool APP_SERCOM_I2C_Callback ( SERCOM_I2C_SLAVE_TRANSFER_EVENT event, uintptr_t contextHandle )
    {
        bool isSuccess = true;

        switch(event)
        {
            case SERCOM_I2C_SLAVE_TRANSFER_EVENT_ADDR_MATCH:
                if ((SERCOM0_I2C_TransferDirGet() == SERCOM_I2C_SLAVE_TRANSFER_DIR_WRITE) && (eepromData.internalWriteInProgress == true))
                {
                    /* EEPROM is busy. Send NAK */
                    isSuccess = false;
                }
                else
                {
                    /* Reset the indexes */
                    eepromData.addrIndex = 0;
                    eepromData.wrBufferIndex = 0;
                }
                break;

            case SERCOM_I2C_SLAVE_TRANSFER_EVENT_RX_READY:
                /* Read the data sent by I2C Master */
                if (eepromData.addrIndex < 2)
                {
                    ((uint8_t*)&eepromData.currentAddrPtr)[eepromData.addrIndex++] = SERCOM0_I2C_ReadByte();
                }
                else
                {
                    eepromData.wrBuffer[(eepromData.wrBufferIndex & EEPROM_PAGE_SIZE_MASK)] = SERCOM0_I2C_ReadByte();
                    eepromData.wrBufferIndex++;
                }
                break;

            case SERCOM_I2C_SLAVE_TRANSFER_EVENT_TX_READY:
                /* Provide the EEPROM data requested by the I2C Master */
                SERCOM0_I2C_WriteByte(EEPROM_EmulationBuffer[eepromData.currentAddrPtr++]);
                if (eepromData.currentAddrPtr >= EEPROM_SIZE_BYTES)
                {
                    eepromData.currentAddrPtr = 0;
                }
                break;

            case SERCOM_I2C_SLAVE_TRANSFER_EVENT_STOP_BIT_RECEIVED:
                if (eepromData.wrBufferIndex > 0)
                {
                    if (eepromData.wrBufferIndex > EEPROM_PAGE_SIZE_BYTES)
                    {
                        eepromData.wrBufferIndex = EEPROM_PAGE_SIZE_BYTES;
                    }
                    eepromData.wrAddr = eepromData.currentAddrPtr;
                    eepromData.nWrBytes = eepromData.wrBufferIndex;

                    /* Update the current address pointer to allow for sequential read */
                    eepromData.currentAddrPtr += eepromData.wrBufferIndex;

                    /* Reset the indexes */
                    eepromData.addrIndex = 0;
                    eepromData.wrBufferIndex = 0;

                    /* Set busy flag to send NAK for any write requests */
                    eepromData.internalWriteInProgress = true;
                    eepromData.eepromCommand = EEPROM_CMD_WRITE;
                }
                break;
            default:
                break;
        }

        return isSuccess;
    }

    void EEPROM_StateMachine(void)
    {
        switch(eepromData.eepromCommand)
        {
            case EEPROM_CMD_WRITE:
                memcpy(&EEPROM_EmulationBuffer[eepromData.wrAddr], &eepromData.wrBuffer[0], eepromData.nWrBytes);
                eepromData.internalWriteInProgress = false;
                eepromData.eepromCommand = EEPROM_CMD_IDLE;
                break;
            case EEPROM_CMD_IDLE:
                /* Do Nothing */
                break;
        }
    }

    int main ( void )
    {
        /* Initialize all modules */
        SYS_Initialize ( NULL );

        eepromData.eepromCommand = EEPROM_CMD_IDLE;

        SERCOM0_I2C_CallbackRegister(APP_SERCOM_I2C_Callback, 0);

        while ( true )
        {
            EEPROM_StateMachine();
        }

        /* Execution should not come here during normal operation */

        return ( EXIT_FAILURE );
    }

## Library Interface

SERCOM peripheral library provides the following interfaces:

USART Mode

Functions

Name | Description | Blocking mode | Non-blocking mode | Ring buffer mode
--- | --- | --- | --- | ---
SERCOMx_USART_Initialize | Initializes given instance of the USART peripheral | Yes | Yes | Yes
SERCOMx_USART_SerialSetup | Sets up serial configurations for USART peripheral | Yes | Yes | Yes
SERCOMx_USART_Write | Writes data to the given USART peripheral instance | Yes | Yes | Yes
SERCOMx_USART_Read | Reads data from the given USART peripheral instance | Yes | Yes | Yes
SERCOMx_USART_WriteIsBusy | Returns the write request status associated with the given USART peripheral instance | No | Yes | No
SERCOMx_USART_ReadIsBusy | Returns the read request status associated with the given USART peripheral instance | No | Yes | No
SERCOMx_USART_WriteCountGet | Gets the byte count of processed bytes for a given USART read operation in non-blocking mode. Returns the number of bytes pending to be transmitted out in the transmit buffer in ring buffer mode. | No | Yes | Yes
SERCOMx_USART_ReadCountGet | Gets the byte count of processed bytes for a given USART read operation in non-blocking mode. Returns the number of bytes available in the internal receive buffer of the PLIB in ring buffer mode. | No | Yes | Yes
SERCOMx_USART_TransmitterIsReady | Returns the hardware status of the USART Transmitter | Yes | No | No
SERCOMx_USART_TransmitComplete | Returns the hardware status of the USART Transmit Shift Register | Yes | No | No
SERCOMx_USART_ReceiverIsReady | Returns the hardware status of the USART Receiver | Yes | No | No
SERCOMx_USART_ErrorGet | Gets the error of the given USART peripheral instance | Yes | Yes | Yes
SERCOMx_USART_WriteCallbackRegister | Sets the pointer to the function (and it's context) to be called when the given USART's write events occur | No | Yes | Yes
SERCOMx_USART_ReadCallbackRegister | Sets the pointer to the function (and it's context) to be called when the given USART's read events occur | No | Yes | Yes
SERCOMx_USART_ReadByte | Submits request to read a byte of data to the given USART peripheral | Yes | No | No
SERCOMx_USART_WriteByte | Submits a byte of data to the given USART peripheral to transfer | Yes | No | No
SERCOMx_USART_FrequencyGet | Provides the given SERCOM peripheral frequency | Yes | Yes | Yes
SERCOMx_USART_ReadAbort | Aborts the ongoing read request | No | Yes | No
SERCOMx_USART_WriteFreeBufferCountGet | Returns the number of bytes of free space available in the internal transmit buffer | No | No | Yes
SERCOMx_USART_WriteBufferSizeGet | Returns the size of the internal transmit ring buffer | No | No | Yes
SERCOMx_USART_WriteNotificationEnable | This API lets the application turn the transmit notifications on/off | No | No | Yes
SERCOMx_USART_WriteThresholdSet | This API allows the application to set a threshold level on the number of free space available in the transmit buffer | No | No | Yes
SERCOMx_USART_ReadFreeBufferCountGet | Returns the number of bytes of free space available in the internal receive buffer | No | No | Yes
SERCOMx_USART_ReadBufferSizeGet | Returns the size of the receive ring buffer | No | No | Yes
SERCOMx_USART_ReadNotificationEnable | This API lets the application turn the receive notifications on/off | No | No | Yes
SERCOMx_USART_ReadThresholdSet | This API allows the application to set a threshold level on the number of bytes of data available in the receive buffer | No | No | Yes
SERCOMx_USART_LIN_CommandSet | This API lets the application to select between automatic transmission of the complete LIN header or software controlled transmission of LIN header in LIN master mode | Yes | Yes | Yes
SERCOMx_ISO7816_Card_Detect | This API allows the application to detect the physical card available status. | Yes | No | No
SERCOMx_ISO7816_Vcc_Enable | This API enables the Vcc power supply input to ISO7816 Smartcard. | Yes | No | No
SERCOMx_ISO7816_Vcc_Disable | This API disables the Vcc power supply input to ISO7816 Smartcard. | Yes | No | No
SERCOMx_ISO7816_Icc_Power_On | This API enables the reset signal to ISO7816 Smartcard. | Yes | No | No
SERCOMx_ISO7816_Icc_Power_Off | This API disables the reset signal to ISO7816 Smartcard. | Yes | No | No
SERCOMx_ISO7816_Cold_Reset | This API allows the application to cold reset the device. | Yes | No | No
SERCOMx_ISO7816_Warm_Reset | This API allows the application to warm reset the device. | Yes | No | No
SERCOMx_ISO7816_Data_Read_Atr | This API allows the application to read the answer to reset (ATR) response from device. | Yes | No | No
SERCOMx_ISO7816_Decode_Atr | This API allows the application to decode the answer to reset (ATR) response from device. | Yes | No | No
SERCOMx_ISO7816_Xfr_Block_Tpdu | This API allows the application to send commands and read back its response. | Yes | No | No

Data types and constants

Name | Type | Description | Blocking mode | Non-blocking mode | Ring buffer mode
--- | --- | --- | --- | --- | ---
USART_ERROR | Macros and Typedef | Defines the macros and typedefs associated with the USART peripheral errors | Yes | Yes | Yes
USART_DATA | Enum | Defines the data width types for the USART peripheral | Yes | Yes | Yes
USART_PARITY | Enum | Defines the parity types for the USART peripheral | Yes | Yes | Yes
USART_STOP | Enum | Defines the data type for the USART peripheral stop bits | Yes | Yes | Yes
USART_LIN_MASTER_CMD | Enum | Defines the enumeration constants for the LIN Master commands | Yes | Yes | Yes
USART_SERIAL_SETUP | Struct | Defines the data structure which is used to configure USART serial parameters at run time | Yes | Yes | Yes
SERCOM_USART_CALLBACK | Typedef | Defines the data type and function signature of the USART peripheral library callback function | Yes | Yes | No
SERCOM_USART_EVENT | Enum | Defines the enums associated with the USART events in the ring buffer mode | Yes | Yes | Yes
SERCOM_USART_RING_BUFFER_CALLBACK | Typedef | Defines the data type and function signature for the SERCOM_USART peripheral callback function in the ring buffer mode | No | No | Yes

SPI Mode

Functions

Name | Description | Master (blocking/interrupt disabled) mode | Master (non-blocking/interrupt enabled) mode | Slave mode
--- | --- | --- | --- | ---
SERCOMx_SPI_Initialize | Initializes instance x of the SERCOM module operating in SPI master or slave mode | Yes | Yes | Yes
SERCOMx_SPI_TransferSetup | Configure SERCOM SPI operational parameters at run time | Yes | Yes | No
SERCOMx_SPI_WriteRead | Write and Read data on SERCOM SPI peripheral | Yes | Yes | No
SERCOMx_SPI_Write | Writes data to SERCOM x SPI peripheral | Yes | Yes | Yes
SERCOMx_SPI_Read | Reads data on the SERCOM SPI peripheral in SPI master mode. Reads data from the PLIB's internal buffer to the application buffer in SPI slave mode | Yes | Yes | Yes
SERCOMx_SPI_CallbackRegister | Allows application to register a callback with the PLIB | No | Yes | Yes
SERCOMx_SPI_IsBusy | Returns transfer status of SERCOM SPI | No | Yes | Yes
SERCOMx_SPI_ReadCountGet | Returns the number of bytes pending to be read out from the PLIB's internal buffer | No | No | Yes
SERCOMx_SPI_ReadBufferSizeGet | Returns the size of the PLIB's internal receive buffer | No | No | Yes
SERCOMx_SPI_WriteBufferSizeGet | Returns the size of the PLIB's internal transmit buffer | No | No | Yes
SERCOMx_SPI_ErrorGet | Returns the error status of SPI transfer | No | No | Yes
SERCOMx_SPI_Ready | Drives the SPI slave busy line to ready (not busy) state | No | No | Yes

Data types and constants

Name | Description | Master (blocking/interrupt disabled) mode | Master (non-blocking/interrupt enabled) mode | Slave mode
--- | --- | --- | --- | ---
SPI_CLOCK_PHASE | Enum | Identifies SPI Clock Phase Options | Yes | Yes
SPI_CLOCK_POLARITY | Enum | Identifies SPI Clock Polarity Options | Yes | Yes
SPI_DATA_BITS | Enum | Identifies SPI bits per transfer | Yes | Yes
SPI_TRANSFER_SETUP | Struct | Data structure containing the SPI parameters which can be changed at run time | Yes | Yes
SERCOM_SPI_CALLBACK | Typedef | Defines the data type and function signature for the SERCOM SPI peripheral callback function | No | Yes
SPI_SLAVE_ERROR | Macros and Typedef | Defines the macros and typedef associated with SPI slave mode errors | No | No
SERCOM_SPI_SLAVE_CALLBACK | Typedef | Pointer to a SPI Call back function when SPI is configured in slave mode | No | No

I2C Mode

Functions

Name | Description | Master mode | Slave mode (interrupt disabled) | Slave mode (interrupt enabled)
--- | --- | --- | --- | ---
SERCOMx_I2C_Initialize | Initializes the instance of the SERCOM peripheral in either master or slave mode | Yes | Yes | Yes
SERCOMx_I2C_Read | Reads data from the slave | Yes | No | No
SERCOMx_I2C_Write | Writes data to the slave | Yes | No | No
SERCOMx_I2C_WriteRead | Write and Read data from Slave | Yes | No | No
SERCOMx_I2C_IsBusy | Returns the Peripheral busy status | Yes | No | Yes
SERCOMx_I2C_ErrorGet | Returns the I2C error that occurred on the bus | Yes | Yes | Yes
SERCOMx_I2C_TransferSetup | Dynamic setup of I2C Peripheral | Yes | No | No
SERCOMx_I2C_CallbackRegister | Sets the pointer to the function (and it's context) to be called when the given SERCOM I2C's transfer events occur | Yes | No | Yes
SERCOMx_I2C_Read_HighSpeed | Reads data from the slave in high speed mode | Yes | No | No
SERCOMx_I2C_Write_HighSpeed | Writes data to the slave in high speed mode | Yes | No | No
SERCOMx_I2C_WriteRead_HighSpeed | Write and Read data from Slave in high speed mode | Yes | No | No
SERCOMx_I2C_InterruptFlagsGet | Returns the SERCOM I2C slave interrupt flags | No | Yes | No
SERCOMx_I2C_InterruptFlagsClear | Clears the specified SERCOM I2C slave interrupt flags | No | Yes | No
SERCOMx_I2C_ReadByte | Read the received I2C byte | No | Yes | Yes
SERCOMx_I2C_WriteByte | Write a data byte to I2C master | No | Yes | Yes
SERCOMx_I2C_TransferDirGet | Returns the I2C transfer direction | No | Yes | Yes
SERCOMx_I2C_LastByteAckStatusGet | Returns the ACK status of the last byte written to the I2C master | No | Yes | Yes
SERCOMx_I2C_AckActionSet | Sets the ACK action for the next byte that will be received from the I2C master | No | Yes | Yes
SERCOMx_I2C_CommandSet | Sets I2C slave command | No | Yes | Yes
SERCOMx_I2C_BusScan Function | Scans and reports the target devices found on the bus | Yes | No | No |

Data types and constants

Name | Type | Description | Master mode | Slave mode (interrupt disabled) | Slave mode (interrupt enabled)
--- | --- | --- | --- | --- | ---
SERCOM_I2C_ERROR | Enum | Defines the possible errors that the SERCOM I2C peripheral can generate in I2C master mode | Yes | No | No
SERCOM_I2C_TRANSFER_SETUP | Struct | I2C transfer setup data structure | Yes | No | No
SERCOM_I2C_CALLBACK | Typedef | Defines the data type and function signature for the SERCOM I2C peripheral callback function in I2C master mode | Yes | No | No
SERCOM_I2C_SLAVE_TRANSFER_DIR | Enum | Defines the enum for I2C data transfer direction | No | Yes | Yes
SERCOM_I2C_SLAVE_ACK_ACTION_SEND | Enum | Defines the enum for the I2C slave acknowledgement type | No | Yes | Yes
SERCOM_I2C_SLAVE_INTFLAG | Enum | Defines the enum for the I2C slave interrupt flags | No | Yes | No
SERCOM_I2C_SLAVE_ACK_STATUS | Enum | Defines the enum for the I2C acknowledgement | No | Yes | Yes
SERCOM_I2C_SLAVE_TRANSFER_EVENT | Enum | Defines the enum for the I2C slave transfer event | No | No | Yes
SERCOM_I2C_SLAVE_COMMAND | Enum | Defines the enum for the I2C slave commands | No | Yes | Yes
SERCOM_I2C_SLAVE_ERROR | Macros and Typedef | Defines macros and typedefs associated with I2C slave error | No | Yes | Yes
SERCOM_I2C_SLAVE_CALLBACK | Typedef | Defines the data type and function signature for the SERCOM I2C Slave callback function | No | No | Yes