2.105 I2C SMBUS

The I2C SMBUS PLIB support I2C Master, I2C Slave, SMBUS Master and SMBUS Slave modes.

Using the Library

I2C Master mode - The below example uses the I2C peripheral library to write an array of values to the I2C Serial EEPROM and verify the value written by reading the values back and comparing it to the value written.
#include <string.h>
#define LED_ON()                       LED5_Set()
#define LED_OFF()                      LED5_Clear()

#define APP_AT24MAC_DEVICE_ADDR             0x0054
#define APP_AT24MAC_MEMORY_ADDR             0x00
#define APP_AT24MAC_MEMORY_ADDR1            0x00
#define APP_TRANSMIT_DATA_LENGTH            6
#define APP_ACK_DATA_LENGTH                 1
#define APP_RECEIVE_DUMMY_WRITE_LENGTH      2
#define APP_RECEIVE_DATA_LENGTH             4

static uint8_t testTxData[APP_TRANSMIT_DATA_LENGTH] =
{
    APP_AT24MAC_MEMORY_ADDR,APP_AT24MAC_MEMORY_ADDR1,
    'M','C','H','P',
};

static uint8_t  testRxData[APP_RECEIVE_DATA_LENGTH];

typedef enum
{
    APP_STATE_EEPROM_STATUS_VERIFY,
    APP_STATE_EEPROM_WRITE,
    APP_STATE_EEPROM_WAIT_WRITE_COMPLETE,
    APP_STATE_EEPROM_CHECK_INTERNAL_WRITE_STATUS,
    APP_STATE_EEPROM_READ,
    APP_STATE_EEPROM_WAIT_READ_COMPLETE,
    APP_STATE_VERIFY,
    APP_STATE_IDLE,
    APP_STATE_XFER_SUCCESSFUL,
    APP_STATE_XFER_ERROR

} APP_STATES;

typedef enum
{
    APP_TRANSFER_STATUS_IN_PROGRESS,
    APP_TRANSFER_STATUS_SUCCESS,
    APP_TRANSFER_STATUS_ERROR,
    APP_TRANSFER_STATUS_IDLE,

} APP_TRANSFER_STATUS;

void APP_I2CCallback(uintptr_t context )
{
    APP_TRANSFER_STATUS* transferStatus = (APP_TRANSFER_STATUS*)context;

    if(I2C0_ErrorGet() == I2C_ERROR_NONE)
    {
        if (transferStatus)
        {
            *transferStatus = APP_TRANSFER_STATUS_SUCCESS;
        }
    }
    else
    {
        if (transferStatus)
        {
            *transferStatus = APP_TRANSFER_STATUS_ERROR;
        }
    }
}

// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    APP_STATES state = APP_STATE_EEPROM_STATUS_VERIFY;
    volatile APP_TRANSFER_STATUS transferStatus = APP_TRANSFER_STATUS_ERROR;
    uint8_t ackData = 0;

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

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

                /* Register the TWIHS Callback with transfer status as context */
                I2C0_CallbackRegister( APP_I2CCallback, (uintptr_t)&transferStatus );

               /* Verify if EEPROM is ready to accept new requests */
                transferStatus = APP_TRANSFER_STATUS_IN_PROGRESS;
                I2C0_Write(APP_AT24MAC_DEVICE_ADDR, &ackData, APP_ACK_DATA_LENGTH);

                state = APP_STATE_EEPROM_WRITE;
                break;

            case APP_STATE_EEPROM_WRITE:

                if (transferStatus == APP_TRANSFER_STATUS_SUCCESS)
                {
                    /* Write data to EEPROM */
                    transferStatus = APP_TRANSFER_STATUS_IN_PROGRESS;
                    I2C0_Write(APP_AT24MAC_DEVICE_ADDR, &testTxData[0], APP_TRANSMIT_DATA_LENGTH);
                    state = APP_STATE_EEPROM_WAIT_WRITE_COMPLETE;
                }
                else if (transferStatus == APP_TRANSFER_STATUS_ERROR)
                {
                    /* EEPROM is not ready to accept new requests. 
                     * Keep checking until the EEPROM becomes ready. */
                    state = APP_STATE_EEPROM_STATUS_VERIFY;
                }
                break;

            case APP_STATE_EEPROM_WAIT_WRITE_COMPLETE:

                if (transferStatus == APP_TRANSFER_STATUS_SUCCESS)
                {
                    /* Read the status of internal write cycle */
                    transferStatus = APP_TRANSFER_STATUS_IN_PROGRESS;
                    I2C0_Write(APP_AT24MAC_DEVICE_ADDR, &ackData, APP_ACK_DATA_LENGTH);
                    state = APP_STATE_EEPROM_CHECK_INTERNAL_WRITE_STATUS;
                }
                else if (transferStatus == APP_TRANSFER_STATUS_ERROR)
                {
                    state = APP_STATE_XFER_ERROR;
                }
                break;

             case APP_STATE_EEPROM_CHECK_INTERNAL_WRITE_STATUS:

                if (transferStatus == APP_TRANSFER_STATUS_SUCCESS)
                {
                    state = APP_STATE_EEPROM_READ;
                }
                else if (transferStatus == APP_TRANSFER_STATUS_ERROR)
                {
                    /* EEPROM's internal write cycle is not complete. Keep checking. */
                    transferStatus = APP_TRANSFER_STATUS_IN_PROGRESS;
                    I2C0_Write(APP_AT24MAC_DEVICE_ADDR, &ackData, APP_ACK_DATA_LENGTH);
                }
                break;

            case APP_STATE_EEPROM_READ:

                transferStatus = APP_TRANSFER_STATUS_IN_PROGRESS;
                /* Read the data from the page written earlier */
                I2C0_WriteRead(APP_AT24MAC_DEVICE_ADDR, &testTxData[0], APP_RECEIVE_DUMMY_WRITE_LENGTH,  &testRxData[0], APP_RECEIVE_DATA_LENGTH);

                state = APP_STATE_EEPROM_WAIT_READ_COMPLETE;

                break;

            case APP_STATE_EEPROM_WAIT_READ_COMPLETE:

                if (transferStatus == APP_TRANSFER_STATUS_SUCCESS)
                {
                    state = APP_STATE_VERIFY;
                }
                else if (transferStatus == APP_TRANSFER_STATUS_ERROR)
                {
                    state = APP_STATE_XFER_ERROR;
                }
                break;

            case APP_STATE_VERIFY:

                if (memcmp(&testTxData[2], &testRxData[0], APP_RECEIVE_DATA_LENGTH) != 0 )
                {
                    /* It means received data is not same as transmitted data */
                    state = APP_STATE_XFER_ERROR;
                }
                else
                {
                    /* It means received data is same as transmitted data */
                    state = APP_STATE_XFER_SUCCESSFUL;
                }
                break;

            case APP_STATE_XFER_SUCCESSFUL:
            {
                LED_ON();
                break;
            }
            case APP_STATE_XFER_ERROR:
            {
                LED_OFF();
                break;
            }
            default:
                break;
        }
    }
}
I2C slave mode - The below example uses the I2C peripheral library in slave mode and emulates an EEPROM of 512 bytes.
#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 ( I2C_SLAVE_TRANSFER_EVENT event, uintptr_t contextHandle )
{
    bool isSuccess = true;

    switch(event)
    {
        case I2C_SLAVE_TRANSFER_EVENT_ADDR_MATCH:
            if ((I2C0_TransferDirGet() == 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 I2C_SLAVE_TRANSFER_EVENT_RX_READY:
            /* Read the data sent by I2C Master */
            if (eepromData.addrIndex < 2)
            {
                ((uint8_t*)&eepromData.currentAddrPtr)[eepromData.addrIndex++] = I2C0_ReadByte();
            }
            else
            {
                eepromData.wrBuffer[(eepromData.wrBufferIndex & EEPROM_PAGE_SIZE_MASK)] = I2C0_ReadByte();
                eepromData.wrBufferIndex++;
            }
            break;

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

        case 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;
    I2C0_CallbackRegister(APP_SERCOM_I2C_Callback, 0);
    while ( true )
    {
        EEPROM_StateMachine();
    }
    /* Execution should not come here during normal operation */
    return ( EXIT_FAILURE );
}
SMBUS Host mode - The below example uses the SMBUS peripheral library and demonstrates how application can use the various APIs available to read and write data when the peripheral is configured in master mode.
#define I2C_SLAVE_ADDR                 0x54

typedef enum
{
    HOST_STATE_WRITE_BYTE = 0,
    HOST_STATE_WRITE_WORD,
    HOST_STATE_WRITE_BLOCK,
    HOST_STATE_READ_BYTE,
    HOST_STATE_READ_WORD,
    HOST_STATE_READ_BLOCK,
    HOST_STATE_WRITE_READ_BLOCK,
    HOST_STATE_WAIT_FOR_TRANSFER_DONE,
    HOST_STATE_ERROR,
    HOST_STATE_SUCCESS,
}HOST_STATE;

typedef enum
{
    HOST_CMD_WRITE_BYTE,
    HOST_CMD_WRITE_WORD,
    HOST_CMD_WRITE_BLOCK,
    HOST_CMD_READ_BYTE,
    HOST_CMD_READ_WORD,
    HOST_CMD_READ_BLOCK,
    HOST_CMD_WRITE_READ_BLOCK,
}HOST_CMD;

volatile bool transferDone = false;
volatile uint32_t nBytesRead = 0;
bool blockRead = false;
uint32_t nBytesRequested = 0;
uint8_t wrBuffer[50] = {0};
uint8_t rdBuffer[50] = {0};

volatile HOST_STATE state = HOST_STATE_WRITE_BYTE;
HOST_STATE nextState;

void i2cSMB0HostEventHandler (I2C_SMB_HOST_TRANSFER_EVENT event, uintptr_t contextHandle)
{
    switch(event)
    {
        case I2C_SMB_HOST_TRANSFER_EVENT_RX_READY:
            nBytesRead = I2CSMB0_HostBufferRead(rdBuffer);
            break;

        case I2C_SMB_HOST_TRANSFER_EVENT_DONE:
            transferDone = true;
            break;

        case I2C_SMB_HOST_TRANSFER_EVENT_ERROR:
            state = HOST_STATE_ERROR;
            break;
            
        default:
            break;
    }
        
}

int main ( void )
{        
    uint32_t i = 0;
    uint32_t data = 1;
    
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    
    I2CSMB0_HostCallbackRegister(i2cSMB0HostEventHandler, 0);
        
    while (1)
    {
        switch(state)
        {
            case HOST_STATE_WAIT_FOR_TRANSFER_DONE:
                if (transferDone == true)
                {
                    transferDone = false;
                    state = nextState;

                    if (nBytesRequested > 0)
                    {
                        i = 0;
                        data = 1;
                        
                        if (blockRead == true)
                        {
                            // for block reads, the first byte indicates the number of bytes transmitted by the slave
                            nBytesRead =  rdBuffer[i++];    
                            blockRead = false;
                        }                        
                        if (nBytesRead != nBytesRequested)
                        {
                            state = HOST_STATE_ERROR;
                            break;
                        }
                        while (nBytesRequested--)
                        {
                            if (rdBuffer[i++] != data++)
                            {
                                state = HOST_STATE_ERROR;
                                break;
                            }                            
                        }

                        nBytesRequested = 0;
                    }
                }
                break;
                
            case HOST_STATE_WRITE_BYTE:
                wrBuffer[0] = 1;
                I2CSMB0_HostWriteByte(I2C_SLAVE_ADDR, HOST_CMD_WRITE_BYTE, wrBuffer);
                state = HOST_STATE_WAIT_FOR_TRANSFER_DONE;
                nextState = HOST_STATE_READ_BYTE;
                break;
                
            case HOST_STATE_READ_BYTE:
                nBytesRequested = 1;
                I2CSMB0_HostReadByte(I2C_SLAVE_ADDR, HOST_CMD_READ_BYTE);
                state = HOST_STATE_WAIT_FOR_TRANSFER_DONE;
                nextState = HOST_STATE_WRITE_WORD;
                break;

            case HOST_STATE_WRITE_WORD:
                wrBuffer[0] = 1;
                wrBuffer[1] = 2;
                I2CSMB0_HostWriteWord(I2C_SLAVE_ADDR, HOST_CMD_WRITE_WORD, wrBuffer);
                state = HOST_STATE_WAIT_FOR_TRANSFER_DONE;
                nextState = HOST_STATE_READ_WORD;
                break;
                
            case HOST_STATE_READ_WORD:
                nBytesRequested = 2;
                I2CSMB0_HostReadWord(I2C_SLAVE_ADDR, HOST_CMD_READ_WORD);
                state = HOST_STATE_WAIT_FOR_TRANSFER_DONE;
                nextState = HOST_STATE_WRITE_BLOCK;
                break;

            case HOST_STATE_WRITE_BLOCK:
                for (uint32_t i = 0; i < 32; i++)
                {
                    wrBuffer[i] = i+1;
                }
                I2CSMB0_HostWriteBlock(I2C_SLAVE_ADDR, HOST_CMD_WRITE_BLOCK, wrBuffer, 32);
                state = HOST_STATE_WAIT_FOR_TRANSFER_DONE;
                nextState = HOST_STATE_READ_BLOCK;
                break;
                
            case HOST_STATE_READ_BLOCK:
                nBytesRequested = 32;
                blockRead = true;
                I2CSMB0_HostReadBlock(I2C_SLAVE_ADDR, HOST_CMD_READ_BLOCK);
                state = HOST_STATE_WAIT_FOR_TRANSFER_DONE;
                nextState = HOST_STATE_WRITE_READ_BLOCK;
                break;
                     
            case HOST_STATE_WRITE_READ_BLOCK:
                nBytesRequested = 32;
                blockRead = true;
                I2CSMB0_HostWriteReadBlock(I2C_SLAVE_ADDR, HOST_CMD_WRITE_READ_BLOCK, wrBuffer, 32);
                state = HOST_STATE_WAIT_FOR_TRANSFER_DONE;
                nextState = HOST_STATE_SUCCESS;
                break;

            case HOST_STATE_SUCCESS:
                break;
                
            case HOST_STATE_ERROR:
                break;
        }
    }
    

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

    return ( EXIT_FAILURE );
}
SMBUS Target mode - The below example uses the SMBUS peripheral library and demonstrates how application can use the various APIs available to read and write data when the peripheral is configured in slave mode.
typedef enum
{
    HOST_CMD_WRITE_BYTE,
    HOST_CMD_WRITE_WORD,
    HOST_CMD_WRITE_BLOCK,
    HOST_CMD_READ_BYTE,
    HOST_CMD_READ_WORD,
    HOST_CMD_READ_BLOCK,
    HOST_CMD_WRITE_READ_BLOCK,
}HOST_CMD;

volatile uint8_t targetRxBuffer[100];
volatile uint8_t targetTxBuffer[100];
volatile uint32_t nBytesRead = 0;
volatile uint32_t nDataBytes = 0;
volatile HOST_CMD command;

bool i2cSMB0TargetEventHandler (I2C_SMB_TARGET_TRANSFER_EVENT event, uintptr_t contextHandle)
{
    switch (event)
    {
        case I2C_SMB_TARGET_TRANSFER_EVENT_RX_READY:
            nBytesRead = I2CSMB0_TargetBufferRead((void*)targetRxBuffer);
            command = targetRxBuffer[1];
            if (command == HOST_CMD_WRITE_BYTE)
            {
                nDataBytes = 1;        
                targetTxBuffer[0] = targetRxBuffer[2];
            }
            else if (command == HOST_CMD_WRITE_WORD)
            {
                nDataBytes = 2;            
                targetTxBuffer[0] = targetRxBuffer[2];
                targetTxBuffer[1] = targetRxBuffer[3];
            }
            else if ((command == HOST_CMD_WRITE_BLOCK) || (command == HOST_CMD_WRITE_READ_BLOCK))
            {
                nDataBytes = targetRxBuffer[2];
                targetTxBuffer[0] = nDataBytes;
                memcpy((void*)&targetTxBuffer[1], (void*)&targetRxBuffer[3], nDataBytes);
                nDataBytes = nDataBytes + 1;
            }                        
            break;
        case I2C_SMB_TARGET_TRANSFER_EVENT_TX_READY:
            I2CSMB0_TargetBufferWrite((void*)targetTxBuffer, nDataBytes);
            break;
        case I2C_SMB_TARGET_TRANSFER_EVENT_ERROR:
            break;
        case I2C_SMB_TARGET_TRANSFER_EVENT_DONE:
            break;
        default:
            break;
    }
    return true;
}

int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    
    I2CSMB0_TargetCallbackRegister(i2cSMB0TargetEventHandler, 0);
    
    I2CSMB0_TargetStart();

    while (1)
    {
        /* Do nothing */
    }

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

    return ( EXIT_FAILURE );
}

Library Interface

I2C SMBUS peripheral library provides the following interfaces:

I2C Mode

Functions

NameDescriptionMaster modeSlave mode
I2CSMBx_InitializeInitializes given instance of I2C SMBUS peripheral.YesYes
I2CSMBx_ReadReads data from the slave.YesNo
I2CSMBx_WriteWrites data to the slave.YesNo
I2CSMBx_WriteReadWrite and Read data from I2C Slave.YesNo
I2CSMBx_IsBusyReturns the Peripheral busy status.YesYes
I2CSMBx_ErrorGetReturns the I2C error that occurred on the bus.YesYes
I2CSMBx_TransferSetupDynamic setup of I2C Peripheral.YesNo
I2CSMBx_CallbackRegisterSets the pointer to the function (and it's context) to be called when the given I2C's transfer events occur.YesYes
I2CSMBx_ReadByteRead the received I2C byteNoYes
I2CSMBx_WriteByteWrite a data byte to I2C masterNoYes
I2CSMBx_TransferDirGetReturns the I2C transfer direction.NoYes
I2CSMBx_LastByteAckStatusGetReturns the ACK status of the last byte written to the I2C master.NoYes
I2CSMBx_StatusFlagsGetReturns the status registerNoYes
I2CSMBx_StatusFlagsResetResets the status register bitsNoYes
I2CSMBx_TransferAbortAborts an ongoing transferYesNo

Data types and constants

NameTypeDescriptionMaster modeSlave mode
I2C_ERROREnumDefines the possible errors that the I2C peripheral can generate in I2C master mode.YesNo
I2C_CALLBACKTypedefDefines the data type and function signature for the I2C peripheral callback function in I2C master mode.YesNo
I2C_SLAVE_TRANSFER_EVENTEnumDefines the enum for the I2C slave transfer eventNoYes
I2C_SLAVE_TRANSFER_DIREnumDefines the enum for I2C data transfer directionNoYes
I2C_SLAVE_ERROREnumDefines errors associated with I2C in slave modeNoYes
I2C_SLAVE_CALLBACK TypedefDefines the data type and function signature for the I2C Slave callback function.NoYes
I2C_SLAVE_ACK_STATUS EnumDefines the enum for the I2C slave acknowledgment.NoYes
I2C_TRANSFER_SETUPStructI2C transfer setup data structureYesNo

SMBUS Mode

Functions
NameDescriptionHost ModeTarget Mode
I2CSMBx_InitializeInitializes given instance of I2C SMBUS peripheral.YesYes
I2CSMBx_HostReadByteReads a data byte from slaveYesNo
I2CSMBx_HostReadWordReads a data word from slaveYesNo
I2CSMBx_HostWriteByteWrites data to the slave.YesNo
I2CSMBx_HostWriteBlockWrites a block of data to the slave.YesNo
I2CSMBx_HostReadBlockReads a block of data from the slaveYesNo
I2CSMBx_HostWriteWordWrites word data to the slave.YesNo
I2CSMBx_HostWriteReadBlockWrites block followed by a read block from the slaveYesNo
I2CSMBx_HostWriteBlockWrites a block of data to the slave.YesNo
I2CSMBx_HostTransferSetupDynamic setup of I2C Peripheral in SMBUS host modeYesNo
I2CSMBx_HostTransferCountGetReturns the transfer count for the last transferYesNo
I2CSMBx_HostIsBusyReturns the Peripheral busy status.YesNo
I2CSMBx_HostErrorGetReturns the I2C error that occurred on the bus.YesNo
I2CSMBx_HostCallbackRegisterSets the pointer to the function (and it's context) to be called when the given I2C's transfer events occur.YesNo
I2CSMBx_HostBufferReadReads data from the internal buffer and into the application bufferYesNo
I2CSMBx_TargetTransferDirGetReturns the I2C transfer direction.NoYes
I2CSMBx_TargetStartConfigures the DMA and starts the target in receive modeNoYes
I2CSMBx_TargetIsBusyReturns the Peripheral busy status.NoYes
I2CSMBx_TargetErrorGetReturns the I2C error that occurred on the bus.NoYes
I2CSMBx_TargetCallbackRegister Sets the pointer to the function (and it's context) to be called when the given I2C's transfer events occur.NoYes
I2CSMBx_TargetBufferWrite Copies the data to be transmitted into the PLIBs internal bufferNoYes
I2CSMBx_TargetBufferRead Reads the received data from internal buffer into the application bufferNoYes

Data types and constants

NameTypeDescriptionHost modeTarget mode
I2C_SMB_HOST_TRANSFER_SETUP StructI2C Transfer Setup Data StructureYesNo
I2C_SMB_HOST_TRANSFER_EVENTEnumDefines the enum for the I2C SMBUS host transfer events.YesNo
I2C_SMB_HOST_ERRORMacro

Defines macros associated with I2C error in SMBUS Host mode

YesNo
I2C_SMB_HOST_CALLBACK TypedefDefines the data type and function signature for the I2C SMBUS host mode callback function.YesNo
I2C_SMB_TARGET_TRANSFER_EVENTEnumDefines the enum for the I2C SMBUS target transfer eventsNoYes
I2C_SMB_TARGET_TRANSFER_DIR EnumDefines the enum for the I2C SMBUS Target mode transfer directionNoYes
I2C_SMB_TARGET_ERROR MacroDefines macros associated with I2C error in SMBUS Target modeNoYes
I2C_SMB_TARGET_CALLBACK TypedefDefines the data type and function signature for the I2C SMBUS Target mode callback function.NoYes
Note: Not all APIs maybe implemented. See the specific device family section for available APIs.