PSOC E8XXGP Device Support Library

General Description

Driver API for I2C Bus Peripheral.

I2C - The Inter-Integrated Circuit (I2C) bus is an industry-standard.

The functions and other declarations used in this part of the driver are in cy_scb_i2c.h. You can also include cy_pdl.h to get access to all functions and declarations in the PDL.

The I2C peripheral driver provides an API to implement I2C slave, master, or master-slave devices based on the SCB hardware block. I2C devices based on SCB hardware are compatible with I2C Standard-mode, Fast-mode, and Fast-mode Plus specifications as defined in the I2C-bus specification.

Features:

Note
I2C supports clock stretching. This occurs when a slave device is not capable of processing data, it holds the SCL line by driving a '0'. The master device monitors the SCL line and detects it when it cannot generate a positive clock pulse ('1') on the SCL line. It then reacts by delaying the generation of a positive edge on the SCL line, effectively synchronizing with the slave device that is stretching the clock. Clock stretching can occur in the case of externally clocked address matching until the internally clocked logic takes over. The largest reason for clock stretching is when the master tries to write to the slave and the slave's RX FIFO is full, the slave will then clock stretch until the FIFO is no longer full. For more information on FIFO size and clock stretching see the architecture TRM.

Configuration Considerations

The I2C driver configuration can be divided to number of sequential steps listed below:

Note
I2C driver is built on top of the SCB hardware block. The SCB3 instance is used as an example for all code snippets. Modify the code to match your design.

Configure I2C

To set up the I2C driver, provide the configuration parameters in the cy_stc_scb_i2c_config_t structure. Provide i2cMode to the select operation mode slave, master or master-slave. The useRxFifo and useTxFifo parameters specify if RX and TX FIFO is used during operation. Typically, both FIFOs should be enabled to reduce possibility of clock stretching. However, using RX FIFO has side effects that needs to be taken into account (see useRxFifo field description in cy_stc_scb_i2c_config_t structure). For master modes, parameters lowPhaseDutyCycle, highPhaseDutyCycle and enableDigitalFilter can be used to define output data rate (refer to section Configure Data Rate for more information). For slave mode, provide the slaveAddress and slaveAddressMask. The other parameters are optional for operation.
To initialize the driver, call Cy_SCB_I2C_Init function providing a pointer to the populated cy_stc_scb_i2c_config_t structure and the allocated cy_stc_scb_i2c_context_t structure.

/* Allocate context for I2C operation */
/* Populate configuration structure */
#if (USE_I2C_SLAVE)
/* Slave configuration */
const cy_stc_scb_i2c_config_t i2cConfig =
{
.useRxFifo = false,
.useTxFifo = true,
.slaveAddress = 0x08U,
.slaveAddressMask = 0xFEU,
.acceptAddrInFifo = false,
.ackGeneralAddr = false,
.enableWakeFromSleep = false,
.enableDigitalFilter = false,
.lowPhaseDutyCycle = 0U,
.highPhaseDutyCycle = 0U,
};
#else /* USE_I2C_MASTER */
/* Master configuration */
const cy_stc_scb_i2c_config_t i2cConfig =
{
.useRxFifo = false,
.useTxFifo = true,
.slaveAddress = 0U,
.slaveAddressMask = 0U,
.acceptAddrInFifo = false,
.ackGeneralAddr = false,
.enableWakeFromSleep = false,
.enableDigitalFilter = false,
.lowPhaseDutyCycle = 8U,
.highPhaseDutyCycle = 8U,
};
#endif
/* Configure I2C to operate */
(void) Cy_SCB_I2C_Init(SCB3, &i2cConfig, &i2cContext);
cy_en_scb_i2c_mode_t i2cMode
Specifies the mode of operation.
Definition: cy_scb_i2c.h:439
I2C configuration structure.
Definition: cy_scb_i2c.h:437
I2C context structure.
Definition: cy_scb_i2c.h:562
@ CY_SCB_I2C_SLAVE
Configures SCB for I2C Slave operation.
Definition: cy_scb_i2c.h:387
@ CY_SCB_I2C_MASTER
Configures SCB for I2C Master operation.
Definition: cy_scb_i2c.h:388
cy_en_scb_i2c_status_t Cy_SCB_I2C_Init(CySCB_Type *base, cy_stc_scb_i2c_config_t const *config, cy_stc_scb_i2c_context_t *context)
Initializes the SCB for the I2C operation.
Definition: cy_scb_i2c.c:80

Set up I2C slave read and write buffer before enabling its operation using Cy_SCB_I2C_SlaveConfigReadBuf and Cy_SCB_I2C_SlaveConfigWriteBuf appropriately. Note that the master reads data from the slave read buffer and writes data into the slave write buffer.

/* Allocate buffers for I2C slave operation */
#define BUFFER_SIZE (128UL)
uint8_t i2cReadBuffer[BUFFER_SIZE];
uint8_t i2cWriteBuffer[BUFFER_SIZE];
/* Configure write and read buffers for communication with master */
Cy_SCB_I2C_SlaveConfigReadBuf (SCB3, i2cReadBuffer, BUFFER_SIZE, &i2cContext);
Cy_SCB_I2C_SlaveConfigWriteBuf(SCB3, i2cWriteBuffer, BUFFER_SIZE, &i2cContext);
void Cy_SCB_I2C_SlaveConfigReadBuf(CySCB_Type const *base, uint8_t *buffer, uint32_t size, cy_stc_scb_i2c_context_t *context)
Configures the buffer pointer and the read buffer size.
Definition: cy_scb_i2c.c:840
void Cy_SCB_I2C_SlaveConfigWriteBuf(CySCB_Type const *base, uint8_t *buffer, uint32_t size, cy_stc_scb_i2c_context_t *context)
Configures the buffer pointer and size of the write buffer.
Definition: cy_scb_i2c.c:1019

Assign and Configure Pins

Only dedicated SCB pins can be used for I2C operation. The HSIOM register must be configured to connect dedicated SCB I2C pins to the SCB block. Also the I2C pins must be configured in Open-Drain, Drives Low mode (this pins configuration implies usage of external pull-up resistors):

/* Assign pins for I2C on SCB0: P8[0] and P8[1] */
#define I2C_PORT (P8_0_PORT)
#define I2C_SCL_NUM (P8_0_NUM)
#define I2C_SDA_NUM (P8_1_NUM)
/* Connect SCB0 I2C function to pins */
Cy_GPIO_SetHSIOM(I2C_PORT, I2C_SCL_NUM, P8_0_SCB0_I2C_SCL);
Cy_GPIO_SetHSIOM(I2C_PORT, I2C_SDA_NUM, P8_1_SCB0_I2C_SDA);
/* Configure pins for I2C operation */
#define CY_GPIO_DM_OD_DRIVESLOW
Open Drain, Drives Low.
Definition: cy_gpio.h:518
__STATIC_INLINE void Cy_GPIO_SetDrivemode(GPIO_PRT_Type *base, uint32_t pinNum, uint32_t value)
Configures the pin output buffer drive mode and input buffer enable.
Definition: cy_gpio.h:1284
__STATIC_INLINE void Cy_GPIO_SetHSIOM(GPIO_PRT_Type *base, uint32_t pinNum, en_hsiom_sel_t value)
Configures the HSIOM connection to the pin.
Definition: cy_gpio.h:923
Note
The alternative pins configuration is Resistive Pull-ups which implies usage internal pull-up resistors. This configuration is not recommended because resistor value is fixed and cannot be used for all supported data rates. Refer to the device datasheet parameter RPULLUP for resistor value specifications.

Assign Clock Divider

A clock source must be connected to the SCB block to oversample input and output signals, in this document this clock will be referred as clk_scb. You must use one of the 8-bit or 16-bit dividers. Use the SysClk (System Clock) driver API to do this.

/* Assign divider type and number for I2C */
#define I2C_CLK_DIV_TYPE (CY_SYSCLK_DIV_8_BIT)
#define I2C_CLK_DIV_NUMBER (0U)
/* Connect assigned divider to be a clock source for I2C */
Cy_SysClk_PeriphAssignDivider(PCLK_SCB3_CLOCK_SCB_EN, I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUMBER);
cy_en_sysclk_status_t Cy_SysClk_PeriphAssignDivider(en_clk_dst_t ipBlock, cy_en_divider_types_t dividerType, uint32_t dividerNum)
Assigns a programmable divider to a selected IP block, such as a TCPWM or SCB.
Definition: cy_sysclk_v2.c:2175

Configure Data Rate

To get I2C slave operation with the desired data rate, the clk_scb must be fast enough to provide sufficient oversampling. Use the SysClk (System Clock) driver API to do this.

/* I2C slave desired data rate is 400 kbps.
* To support this data rate the clk_scb frequency must be in range 7.82 – 15.38 MHz.
* Find clk_scb valid ranges in TRM section I2C sub-section Oversampling and Bit Rate.
* For clk_peri = 50 MHz, select divider value 4 and get clk_scb = (50 MHz / 4) = 12.5 MHz.
* This clock frequency meets requirements above.
*/
Cy_SysClk_PeriphSetDivider (I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUMBER, 3u);
Cy_SysClk_PeriphEnableDivider(I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUMBER);
cy_en_sysclk_status_t Cy_SysClk_PeriphEnableDivider(cy_en_divider_types_t dividerType, uint32_t dividerNum)
Enables the selected divider.
Definition: cy_sysclk_v2.c:2189
cy_en_sysclk_status_t Cy_SysClk_PeriphSetDivider(cy_en_divider_types_t dividerType, uint32_t dividerNum, uint32_t dividerValue)
Sets one of the programmable clock dividers.
Definition: cy_sysclk_v2.c:2142

To get I2C master operation with the desired data rate, the source clock frequency and SCL low and high phase duration must be configured. Use the SysClk (System Clock) driver API to configure source clock frequency. Then call Cy_SCB_I2C_SetDataRate to set the SCL low, high phase duration and digital filter. This function sets SCL low and high phase settings based on source clock frequency.

uint32_t dataRate;
/* I2C master desired data rate in Hz */
#define I2C_DESIRED_DATA_RATE_HZ (100000U)
/* I2C master desired data rate is 100 kbps.
* To support this data rate the clk_scb frequency must be in range 1.55 – 3.2 MHz.
* Find clk_scb valid ranges in TRM section I2C sub-section Oversampling and Bit Rate.
* For clk_peri = 50 MHz, select divider value 32 and get clk_scb = (50 MHz / 32) = 1.563 MHz.
* This clock frequency meets requirements above.
*/
Cy_SysClk_PeriphSetDivider (I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUMBER, 31u);
Cy_SysClk_PeriphEnableDivider(I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUMBER);
/* Configure master to operate with desired data rate */
dataRate = Cy_SCB_I2C_SetDataRate(SCB3, I2C_DESIRED_DATA_RATE_HZ, Cy_SysClk_PeriphGetFrequency(I2C_CLK_DIV_TYPE, I2C_CLK_DIV_NUMBER));
if ((dataRate > I2C_DESIRED_DATA_RATE_HZ) || (dataRate == 0U))
{
/* Can not reach desired data rate */
CY_ASSERT(0U);
}
uint32_t Cy_SCB_I2C_SetDataRate(CySCB_Type *base, uint32_t dataRateHz, uint32_t scbClockHz)
Configures the SCB to work at the desired data rate.
Definition: cy_scb_i2c.c:541
uint32_t Cy_SysClk_PeriphGetFrequency(cy_en_divider_types_t dividerType, uint32_t dividerNum)
Reports the frequency of the output of a given peripheral divider.
Definition: cy_sysclk_v2.c:2132

Alternatively, the low, high phase and digital filter can be set directly using configuration structure cy_stc_scb_i2c_config_t fields lowPhaseDutyCycle, highPhaseDutyCycle and enableDigitalFilter appropriately.
Refer to the technical reference manual (TRM) section I2C sub-section Oversampling and Bit Rate to get information how to configure I2C to run with the desired data rate.

Note
For I2C slave, the analog filter is used for all supported data rates.
For I2C master, the analog filter is used for Standard and Fast modes and the digital filter for Fast Plus mode.

Configure Interrupt

The interrupt is mandatory for I2C operation. The exception is the when only the Master Low-Level functions are used. The driver provides three interrupt functions: Cy_SCB_I2C_Interrupt, Cy_SCB_I2C_SlaveInterrupt, and Cy_SCB_I2C_MasterInterrupt. One of these functions must be called in the interrupt handler for the selected SCB instance. Call Cy_SCB_I2C_SlaveInterrupt when I2C is configured to operate as a slave, Cy_SCB_I2C_MasterInterrupt when I2C is configured to operate as a master and Cy_SCB_I2C_Interrupt when I2C is configured to operate as master and slave. Using the slave- or master-specific interrupt function allows reducing the flash consumed by the I2C driver. Also this interrupt must be enabled in the NVIC otherwise it will not work.

Note
The I2C driver documentation refers to the Cy_SCB_I2C_Interrupt function when interrupt processing is mandatory for the operation. This is done to simplify the readability of the driver's documentation. The application should call the slave- or master-specific interrupt functions Cy_SCB_I2C_SlaveInterrupt or Cy_SCB_I2C_MasterInterrupt, when appropriate.
void I2C_Isr(void)
{
Cy_SCB_I2C_Interrupt(SCB3, &i2cContext);
}
void Cy_SCB_I2C_Interrupt(CySCB_Type *base, cy_stc_scb_i2c_context_t *context)
This is the interrupt function for the SCB configured in the I2C mode.
Definition: cy_scb_i2c.c:2161
/* Assign I2C interrupt number and priority */
#define I2C_INTR_NUM scb_3_interrupt_IRQn
#define I2C_INTR_PRIORITY (7UL)
/* Populate configuration structure (code specific for CM4) */
const cy_stc_sysint_t i2cIntrConfig =
{
.intrSrc = I2C_INTR_NUM,
.intrPriority = I2C_INTR_PRIORITY,
};
/* Hook interrupt service routine and enable interrupt */
(void) Cy_SysInt_Init(&i2cIntrConfig, &I2C_Isr);
NVIC_EnableIRQ(I2C_INTR_NUM);
IRQn_Type intrSrc
Interrupt source.
Definition: cy_sysint.h:227
Initialization configuration structure for a single interrupt channel.
Definition: cy_sysint.h:225
cy_en_sysint_status_t Cy_SysInt_Init(const cy_stc_sysint_t *config, cy_israddress userIsr)
Initializes the referenced interrupt by setting the priority and the interrupt vector.
Definition: cy_sysint_v2.c:80

Enable I2C

Finally, enable the I2C operation by calling Cy_SCB_I2C_Enable. Then I2C slave starts respond to the assigned address and I2C master ready to execute transfers.

/* Enable I2C to operate */
/* Enable global interrupts */
__enable_irq();
__STATIC_INLINE void Cy_SCB_I2C_Enable(CySCB_Type *base)
Enables the SCB block for the I2C operation.
Definition: cy_scb_i2c.h:1139

Common Use Cases

Master Operation

The master API is divided into two categories: Master High-Level and Master Low-Level. Therefore, there are two methods for initiating I2C master transactions using either Low-Level or High-Level API. These two methods are described below. Only one method should be used at a time. They should not be mixed.

Use High-Level Functions

Call Cy_SCB_I2C_MasterRead or Cy_SCB_I2C_MasterWrite to communicate with the slave. These functions do not block and only start a transaction. After a transaction starts, the Cy_SCB_I2C_Interrupt handles further data transaction until its completion (successfully or with error occurring). To monitor the transaction, use Cy_SCB_I2C_MasterGetStatus or register callback function using Cy_SCB_I2C_RegisterEventCallback to be notified about I2C Callback Events.

uint8_t readBuffer [5UL];
uint8_t writeBuffer[2UL] = {0U, 5U};
/* Configure write transaction */
transfer.slaveAddress = 0x08U;
transfer.buffer = writeBuffer;
transfer.bufferSize = sizeof(writeBuffer);
transfer.xferPending = true; /* Do not generate Stop condition at the end of transaction */
/* Initiate write transaction.
* The Start condition is generated to begin this transaction.
*/
(void) Cy_SCB_I2C_MasterWrite(SCB3, &transfer, &i2cContext);
/* Wait for transaction completion */
while (0UL != (CY_SCB_I2C_MASTER_BUSY & Cy_SCB_I2C_MasterGetStatus(SCB3, &i2cContext)))
{
}
/* Configure read transaction */
transfer.buffer = readBuffer;
transfer.bufferSize = sizeof(readBuffer);
transfer.xferPending = false; /* Generate Stop condition the end of transaction */
/* Initiate read transaction.
* The ReStart condition is generated to begin this transaction because
* previous transaction was completed without Stop.
*/
(void) Cy_SCB_I2C_MasterRead(SCB3, &transfer, &i2cContext);
/* Wait for transaction completion */
while (0UL != (CY_SCB_I2C_MASTER_BUSY & Cy_SCB_I2C_MasterGetStatus(SCB3, &i2cContext)))
{
}
/* Process received data */
uint8_t * buffer
The pointer to the buffer for data to read from the slave or data to write into the slave.
Definition: cy_scb_i2c.h:616
bool xferPending
The transfer operation is pending - the stop condition will not be generated.
Definition: cy_scb_i2c.h:635
uint32_t bufferSize
The size of the buffer.
Definition: cy_scb_i2c.h:619
uint8_t slaveAddress
The 7-bit right justified slave address to communicate with.
Definition: cy_scb_i2c.h:610
The I2C Master transfer structure.
Definition: cy_scb_i2c.h:608
#define CY_SCB_I2C_MASTER_BUSY
The master is busy executing operation started by Cy_SCB_I2C_MasterRead or Cy_SCB_I2C_MasterWrite.
Definition: cy_scb_i2c.h:822
uint32_t Cy_SCB_I2C_MasterGetStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
Returns the current I2C master status.
Definition: cy_scb_i2c.c:1184
cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterRead(CySCB_Type *base, cy_stc_scb_i2c_master_xfer_config_t *xferConfig, cy_stc_scb_i2c_context_t *context)
This function configures the master to automatically read an entire buffer of data from the slave dev...
Definition: cy_scb_i2c.c:1244
cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterWrite(CySCB_Type *base, cy_stc_scb_i2c_master_xfer_config_t *xferConfig, cy_stc_scb_i2c_context_t *context)
This function configures the master to automatically write an entire buffer of data to a slave device...
Definition: cy_scb_i2c.c:1472

Use Low-Level Functions

Call Cy_SCB_I2C_MasterSendStart to generate a start, send an address with the Read/Write direction bit, and receive acknowledgment. After the address is ACKed by the slave, the transaction can be continued by calling Cy_SCB_I2C_MasterReadByte or Cy_SCB_I2C_MasterWriteByte depending on its direction. These functions handle one byte per call. Therefore, they should be called for each byte in the transaction. Note that for the Read transaction, the last byte must be NAKed. To complete the current transaction, call Cy_SCB_I2C_MasterSendStop or call Cy_SCB_I2C_MasterSendReStart to complete the current transaction and start a new one. Typically, do a restart to change the transaction direction without releasing the bus from the master control. The Low-Level functions are blocking and do not require calling Cy_SCB_I2C_Interrupt inside the interrupt handler. Using these functions requires extensive knowledge of the I2C protocol to execute transactions correctly.

Master Write Operation

/* Buffer to write to the slave */
uint8_t buffer[] = {0x55, 0x44, 0x33};
/* Wait 100 ms until operation completion */
uint32_t timeout = 100UL;
/* Send Start condition, address and receive ACK/NACK response from slave */
status = Cy_SCB_I2C_MasterSendStart(SCB3, 0x08U, CY_SCB_I2C_WRITE_XFER, timeout, &i2cContext);
if (CY_SCB_I2C_SUCCESS == status)
{
uint32_t cnt = 0UL;
/* Write data into the slave from the buffer */
do
{
/* Write byte and receive ACK/NACK response */
status = Cy_SCB_I2C_MasterWriteByte(SCB3, buffer[cnt], timeout, &i2cContext);
++cnt;
}
while((status == CY_SCB_I2C_SUCCESS) && (cnt < sizeof(buffer)));
}
/* Check status of transaction */
if ((status == CY_SCB_I2C_SUCCESS) ||
{
/* Send Stop condition on the bus */
status = Cy_SCB_I2C_MasterSendStop(SCB3, timeout, &i2cContext);
if (status == CY_SCB_I2C_SUCCESS)
{
/* Stop was successfully executed on the bus after a non-acknowledged address,
a NAK during transfer, or a successful slave transaction */
}
}
else
{
/* Other statuses do not require any actions */
}
cy_en_scb_i2c_status_t
I2C status codes.
Definition: cy_scb_i2c.h:332
@ CY_SCB_I2C_WRITE_XFER
Current transaction is Write.
Definition: cy_scb_i2c.h:395
@ CY_SCB_I2C_MASTER_MANUAL_ADDR_NAK
The slave NACKed the address.
Definition: cy_scb_i2c.h:355
@ CY_SCB_I2C_SUCCESS
Operation completed successfully.
Definition: cy_scb_i2c.h:334
@ CY_SCB_I2C_MASTER_MANUAL_NAK
The slave NACKed the data byte.
Definition: cy_scb_i2c.h:360
cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterSendStart(CySCB_Type *base, uint32_t address, cy_en_scb_i2c_direction_t bitRnW, uint32_t timeoutMs, cy_stc_scb_i2c_context_t *context)
Generates a Start condition and sends a slave address with the Read/Write bit.
Definition: cy_scb_i2c.c:1744
cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterSendStop(CySCB_Type *base, uint32_t timeoutMs, cy_stc_scb_i2c_context_t *context)
Generates a Stop condition to complete the current transaction.
Definition: cy_scb_i2c.c:1942
cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterWriteByte(CySCB_Type *base, uint8_t byte, uint32_t timeoutMs, cy_stc_scb_i2c_context_t *context)
Sends one byte to a slave.
Definition: cy_scb_i2c.c:2108

Master Read Operation

/* Buffer to write to the slave */
uint8_t buffer[5U];
/* Wait 100 ms until operation completion */
uint32_t timeout = 100UL;
/* Send Start condition, address and receive ACK/NACK response from slave */
status = Cy_SCB_I2C_MasterSendStart(SCB3, 0x08U, CY_SCB_I2C_WRITE_XFER, timeout, &i2cContext);
if (CY_SCB_I2C_SUCCESS == status)
{
uint32_t cnt = 0UL;
/* Read data from the slave into the buffer */
do
{
if (cnt == (sizeof(buffer) - 1UL))
{
/* The last byte must be NACKed */
}
/* Read byte and generate ACK / or prepare for NACK */
status = Cy_SCB_I2C_MasterReadByte(SCB3, cmd, &buffer[cnt], timeout, &i2cContext);
++cnt;
}
while((status == CY_SCB_I2C_SUCCESS) && (cnt < sizeof(buffer)));
}
/* Check status of transaction */
if ((status == CY_SCB_I2C_SUCCESS) ||
{
/* Send Stop condition on the bus */
status = Cy_SCB_I2C_MasterSendStop(SCB3, timeout, &i2cContext);
if (status == CY_SCB_I2C_SUCCESS)
{
/* Process received data */
}
}
else
{
/* Other statuses do not require any actions.
* The received data should dropped.
*/
}
cy_en_scb_i2c_command_t
I2C Command ACK / NAK.
Definition: cy_scb_i2c.h:401
@ CY_SCB_I2C_NAK
Send NAK to current byte.
Definition: cy_scb_i2c.h:403
@ CY_SCB_I2C_ACK
Send ACK to current byte.
Definition: cy_scb_i2c.h:402
cy_en_scb_i2c_status_t Cy_SCB_I2C_MasterReadByte(CySCB_Type *base, cy_en_scb_i2c_command_t ackNack, uint8_t *byte, uint32_t timeoutMs, cy_stc_scb_i2c_context_t *context)
Reads one byte from a slave and generates an ACK or prepares to generate a NAK.
Definition: cy_scb_i2c.c:2016

Slave Operation

Slave operation requires the Cy_SCB_I2C_Interrupt be called inside the interrupt handler. The read and write buffers must be provided for the slave to enable communication with the master. Use Cy_SCB_I2C_SlaveConfigReadBuf and Cy_SCB_I2C_SlaveConfigWriteBuf for this purpose. Note that after transaction completion the buffer must be configured again. Otherwise, the same buffer is used starting from the point where the master stopped a previous transaction. For example: The read buffer is configured to be 10 bytes and the master reads 8 bytes. If the read buffer is not configured again, the next master read will start from the 9th byte. To monitor the transaction status, use Cy_SCB_I2C_SlaveGetStatus or use Cy_SCB_I2C_RegisterEventCallback to register a callback function to be notified about I2C Callback Events.

Get Slave Events Notification

/* Register callback for event notification.
* It is better to do this during initialization before I2C is enabled.
*/
Cy_SCB_I2C_RegisterEventCallback(SCB3, I2C_SlaveEventHandler, &i2cContext);
__STATIC_INLINE void Cy_SCB_I2C_RegisterEventCallback(CySCB_Type const *base, cy_cb_scb_i2c_handle_events_t callback, cy_stc_scb_i2c_context_t *context)
Registers a callback function that notifies that I2C Callback Events occurred in the Cy_SCB_I2C_Inter...
Definition: cy_scb_i2c.h:1345
/* Callback implementation */
void I2C_SlaveEventHandler(uint32_t events)
{
/* Slave sent data to master */
if (0UL != (events & CY_SCB_I2C_SLAVE_RD_CMPLT_EVENT))
{
if (0UL == (events & CY_SCB_I2C_SLAVE_ERR_EVENT))
{
/* Read complete without errors: update buffer content */
}
/* Setup read buffer for the next read transaction */
Cy_SCB_I2C_SlaveConfigReadBuf(SCB3, i2cReadBuffer, BUFFER_SIZE, &i2cContext);
}
/* Slave received data from master */
if (0UL != (events & CY_SCB_I2C_SLAVE_WR_CMPLT_EVENT))
{
if (0UL == (events & CY_SCB_I2C_SLAVE_ERR_EVENT))
{
/* Write complete without errors: process received data */
}
/* Setup buffer for the next write transaction */
Cy_SCB_I2C_SlaveConfigWriteBuf(SCB3, i2cWriteBuffer, BUFFER_SIZE, &i2cContext);
}
/* Ignore all other events */
}
#define CY_SCB_I2C_SLAVE_ERR_EVENT
Indicates the I2C hardware detected an error.
Definition: cy_scb_i2c.h:900
#define CY_SCB_I2C_SLAVE_WR_CMPLT_EVENT
Indicates the master completed writing to the slave (set by the master Stop or Restart)
Definition: cy_scb_i2c.h:894
#define CY_SCB_I2C_SLAVE_RD_CMPLT_EVENT
Indicates the master completed reading from the slave (set by the master NAK or Stop)
Definition: cy_scb_i2c.h:888

Polling Slave Completion Events

/* Disable I2C Interrupt: protect code from interruption */
NVIC_DisableIRQ(I2C_INTR_NUM);
/* Check if write transaction completed */
if (0UL != (CY_SCB_I2C_SLAVE_WR_CMPLT & Cy_SCB_I2C_SlaveGetStatus(SCB3, &i2cContext)))
{
/* Process received data */
/* Configure buffer for the next write */
Cy_SCB_I2C_SlaveConfigWriteBuf(SCB3, i2cWriteBuffer, BUFFER_SIZE, &i2cContext);
/* Clear slave write status to capture following updates */
}
/* Enable I2C interrupt */
NVIC_EnableIRQ(I2C_INTR_NUM);
#define CY_SCB_I2C_SLAVE_WR_CMPLT
The master has finished writing data into the slave.
Definition: cy_scb_i2c.h:791
uint32_t Cy_SCB_I2C_SlaveClearWriteStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t *context)
Clears the write status flags and error condition flags and returns their values.
Definition: cy_scb_i2c.c:1140
uint32_t Cy_SCB_I2C_SlaveGetStatus(CySCB_Type const *base, cy_stc_scb_i2c_context_t const *context)
Returns the current I2C slave status.
Definition: cy_scb_i2c.c:791
Note
All slave API (except Cy_SCB_I2C_SlaveAbortRead and Cy_SCB_I2C_SlaveAbortWrite) are not interrupt-protected and to prevent a race condition, they should be protected from the I2C interruption in the place where they are called. The code snippet Polling Slave Completion Events above shows how to prevent a race condition when detect transfer completion and update I2C slave write buffer. The simple example of race condition is: application updates slave read buffer the I2C master starts read transfer. The I2C interrupts read buffer update and I2C interrupt loads current read buffer content in the TX FIFO . After I2C interrupt returns the application updates remaining part of the read buffer. As a result the mater read partly updated buffer.

Low Power Support

The I2C driver provides callback functions to handle power mode transition. The callback Cy_SCB_I2C_DeepSleepCallback must be called during execution of Cy_SysPm_CpuEnterDeepSleep Cy_SCB_I2C_HibernateCallback must be called during execution of Cy_SysPm_SystemEnterHibernate. To trigger the callback execution, the callback must be registered before calling the power mode transition function. Refer to SysPm (System Power Management) driver for more information about power mode transitions and callback registration.

API Reference

 Macros
 
 Functions
 
 Data Structures
 
 Enumerated Types