Astra SRSDK Peripheral Driver Library
 
Loading...
Searching...
No Matches

Topics

 Enumerated Types
 Enumerated types for I2C driver.
 
 Data Structures
 Data structures for I2C driver.
 
 General Functions
 General functions for I2C driver.
 

Detailed Description

The I²C driver provides a high-level, easy-to-use API for configuring and operating the I²C hardware block on Synaptics MCUs It supports both Controller (formerly “Master”) and Target (formerly “Slave”) roles, in blocking and non-blocking modes, with full control over timing, addressing, and error handling.

Key Features

API Organization

Typical Usage

  1. Configure the I2C-related pins using the pinmux driver (e.g., set SDA/SCL to I2C function).
  2. Call i2c_init() to reset the block and enable its clock.
  3. Configure timing and addressing via i2c_controller_set_config(), i2c_target_set_config()
  4. Register a callback for non-blocking transfers.
  5. Enable the I²C block with i2c_enable().
  6. Perform transfers via blocking or non-blocking APIs.
  7. When finished, disable the block via i2c_disable() and call i2c_deinit().

I2C Initialization and Pinmux Configuration

This snippet handles the initialization of I2C modules (Controller 0, Controller 1, and Target) and configures the corresponding pinmux settings based on enabled configuration macros.

i2c_init(I2C_INST_M);
i2c_init(I2C_INST_S);

I2C Enable

This snippet enables the required I2C controllers and targets after pinmux configuration.

/* Enable interfaces */
i2c_enable(I2C_INST_M);
i2c_enable(I2C_INST_S);

Controller Configuration

This snippet shows how to define a structure to configure the I2C controller.

/* Controller Configuration */
i2c_controller_config_t i2c_con_config = {
.ten_bit_addr = false,
.speed = I2C_SPEED_FAST,
.enable_bus_clear = false,
.clear_stuck_sda = false,
.scl_stuck_timeout_ms = 1,
.sda_stuck_timeout_ms = 1
};

Target Configuration

This snippet demonstrates how to define a structure for configuring the I2C target.

i2c_target_config_t i2c_t_config = {
.ten_bit_addr = false,
.speed = I2C_SPEED_FAST,
.target_address = I2C_TARGET_ADDRESS,
.general_call_response = false,
.scl_stuck_timeout_ms = 1,
.sda_stuck_timeout_ms = 1
};

Setting Target Address

This snippet demonstrates how to set and retrieve the I2C controller's target address.

/* Set target addresses */
i2c_controller_set_target_address(I2C_INST_M, I2C_TARGET_ADDRESS);
if (i2c_controller_get_target_address(I2C_INST_M, &address) == I2C_OK) {
LOG_INFO(LOG_MOD_GENERIC, "Controller target address: 0x%02X\n", address);
} else {
LOG_ERROR(LOG_MOD_GENERIC, "Failed to get I2C target address\n");
}

Blocking Controller Write and Read

This snippet shows how to perform blocking write and read operations.

/* Enable interfaces */
i2c_enable(I2C_INST_M);
i2c_enable(I2C_INST_S);
LOG_INFO(LOG_MOD_GENERIC, "I2C controller write blocking started\n");
ret = i2c_controller_write_blocking(I2C_INST_M, &config);
if (ret == I2C_OK) {
LOG_INFO(LOG_MOD_GENERIC, "Controller write success with status code:%d\n", ret);
}
else {
LOG_ERROR(LOG_MOD_GENERIC, "Controller write failed with status code:%d\n", ret);
}
/* Blocking Read */
ret = i2c_controller_read_blocking(I2C_INST_M, &read_config);
if (ret == I2C_OK) {
LOG_INFO(LOG_MOD_GENERIC, "Blocking read success with status code: %d\n", ret);
for (int i = 0; i < read_config.size; i++) {
LOG_INFO(LOG_MOD_GENERIC, "Read byte [%d]: 0x%02X\n", i, read_config.buf[i]);
if (read_config.buf[i] == target_tx_buf[i]) {
match_count++;
} else {
mismatch_count++;
}
}
}
else {
LOG_ERROR(LOG_MOD_GENERIC, "Blocking read failed with status code: %d\n", ret);
}

Non-Blocking Controller Write and Read

This snippet shows how to perform non-blocking write and read operations.

/*Non-Blocking Write */
LOG_INFO(LOG_MOD_GENERIC, "Controller: Sending data...\n");
for (int i = 0; i < 10; ++i) {
if (i2c_controller_write_non_blocking(I2C_INST_M, &write_cfg) == I2C_OK)
{
LOG_INFO(LOG_MOD_GENERIC,"Write is completed\n");
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
if (xSemaphoreTake(i2c_controller_semaphore, pdMS_TO_TICKS(SEMAPHORE_TIMEOUT)) == pdTRUE) {
LOG_INFO(LOG_MOD_GENERIC, "Controller semaphore taken!");
} else {
LOG_INFO(LOG_MOD_GENERIC, "Controller semaphore TIMEOUT!");
}
if (i2c_event_master_type == I2C_EVENT_WRITE_COMPLETE || i2c_event_master_type == I2C_EVENT_STOP_DET) {
LOG_INFO(LOG_MOD_GENERIC, "Controller: Write completed with event: 0x%X\n",i2c_event_master_type);
} else {
LOG_ERROR(LOG_MOD_GENERIC, "Controller: Write failed. Event: 0x%X\n", i2c_event_master_type);
}
/*Non-Blocking Read */
i2c_controller_read_non_blocking(I2C_INST_M, &read_non_block);
if (xSemaphoreTake(i2c_controller_semaphore, pdMS_TO_TICKS(SEMAPHORE_TIMEOUT)) == pdTRUE) {
LOG_INFO(LOG_MOD_GENERIC, "Controller semaphore taken!");
} else {
LOG_INFO(LOG_MOD_GENERIC, "Controller semaphore TIMEOUT!");
}
if (i2c_event_master_type == I2C_EVENT_ABORT) {
LOG_ERROR(LOG_MOD_GENERIC, "Non-Blocking read failed due to NACK/invalid address\n");
} else if (i2c_event_master_type == I2C_EVENT_READ_COMPLETE) {
LOG_INFO(LOG_MOD_GENERIC, "Non-Blocking read success with event type: %d\n", i2c_event_master_type);
for (int i = 0; i < read_non_block.size; i++) {
LOG_INFO(LOG_MOD_GENERIC, "Read byte [%d]: 0x%02X\n", i, read_non_block.buf[i]);
if (read_non_block.buf[i] == target_tx_buf[i]) {
match_count++;
} else {
mismatch_count++;
}
}
} else {
LOG_INFO(LOG_MOD_GENERIC, "Non-Blocking read with event type: %d\n", i2c_event_master_type);
}

Non-Blocking Target Read

This snippet shows how to perform non-blocking read operation.

LOG_INFO(LOG_MOD_GENERIC,"Target: Reading Starts...\n");
/* Prepare to receive */
ret = i2c_target_prep_controller_write(I2C_INST_S, target_rx_buf, sizeof(target_rx_buf));
if (ret != I2C_OK) {
LOG_ERROR(LOG_MOD_GENERIC, "Target: Failed to prep controller write: %d", ret);
vTaskDelete(NULL);
}

Non-Blocking Target Read

This snippet shows how to perform non-blocking write operation.

ret = i2c_target_prep_controller_read(I2C_INST_S, target_tx_buf, sizeof(target_tx_buf));
if (ret != I2C_OK) {
LOG_ERROR(LOG_MOD_GENERIC, "Target: Failed to prep controller read: %d", ret);
vTaskDelete(NULL);
}

Callback Handler

This callback function is registered with the I2C driver and gets invoked asynchronously when an I2C event occurs. The function handles events such as transmission completion, reception, or error conditions.

static void i2c_event_cb(i2c_instance_en id, i2c_event_en event_mask, void* user_data)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (id == I2C_INST_M) {
i2c_event_master_type = event_mask;
i2c_event_master_flag = 1;
LOG_INFO(LOG_MOD_GENERIC, "[Controller] I2C Event: 0x%X\n", event_mask);
if (xPortIsInsideInterrupt()) {
xSemaphoreGiveFromISR(i2c_controller_semaphore, &xHigherPriorityTaskWoken);
} else {
xSemaphoreGive(i2c_controller_semaphore);
}
} else {
i2c_event_type = event_mask;
i2c_event_flag = 1;
LOG_INFO(LOG_MOD_GENERIC, "[Target] I2C Event: 0x%X\n", event_mask);
if (xPortIsInsideInterrupt()) {
xSemaphoreGiveFromISR(i2c_target_semaphore, &xHigherPriorityTaskWoken);
} else {
xSemaphoreGive(i2c_target_semaphore);
}
}
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

I2C Disable

This snippet disables the required I2C controllers and targets.

/* Disable interfaces */
i2c_disable(I2C_INST_M);
i2c_disable(I2C_INST_S);
Note
For complete register listings and detailed descriptions, refer to the Technical Reference Manual of your device.