Astra MCU SDK Peripheral Driver Library
Loading...
Searching...
No Matches

Topics

 Enumerated Types
 Enumerated types for I3C driver.
 Data Structures
 Data structures for I3C driver.
 Functions
 Public API functions for I3C driver.

Detailed Description

The I3C driver provides a complete software interface for operating the Synaptics I3C peripheral in both Controller and Target modes.

The driver supports standard I3C and mixed I3C/I2C bus environments, enabling dynamic device management, high-speed data transfers, interrupt-driven communication, and advanced bus arbitration features.

Features:

  • SDR and HDR transfer modes
  • Dynamic Address Assignment (ENTDAA / SETDASA)
  • Direct and Broadcast CCC command support
  • Mixed I3C + I2C device coexistence
  • In-Band Interrupt (IBI) handling
  • Hot-Join detection and processing
  • Master Request arbitration support
  • FIFO-based data buffering with programmable thresholds
  • Blocking and non-blocking transfer models
  • ISR-driven asynchronous operation

The driver is structured around:

  • Controller APIs for device discovery, configuration, and transfers
  • Target APIs for target-mode operation and event generation
  • Unified configuration structures for controller and target modes
  • Callback-based interrupt handling for asynchronous events
Note
I3C APIs are divided into two categories:
  • High-level APIs: Provides structured configuration and transaction-oriented interfaces for operating the I3C peripheral in Controller or Target mode using well-defined configuration structures and transfer descriptors. These APIs abstract queue management, command formatting, and protocol sequencing, and are intended for most application-level use cases.
  • Low-level APIs: Provides direct control over hardware state and protocol behavior, including fine-grained interrupt management, FIFO handling, response queue inspection, and manual Hot-Join or IBI processing.

    This model is intended for system-level software, performance-sensitive applications, protocol validation, or custom arbitration and timing control scenarios.

Warning
Once enabled, core configuration such as operating mode, timing parameters, and dynamic addressing must not be modified until the peripheral is disabled using i3c_disable.

Configuration Considerations

To initialize and operate the I3C driver:

  1. Call i3c_init to initialize the peripheral instance and reset the internal driver context.
  2. Populate either i3c_controller_config_t or i3c_target_config_t depending on the intended operating mode.
  3. Apply configuration using i3c_controller_set_config or i3c_target_set_config. This programs timing, thresholds, addressing behavior, and bus characteristics.
  4. Optionally register an application callback using i3c_register_callback to enable interrupt-driven event handling.
  5. Enable the peripheral using i3c_enable to allow bus participation.

Controller Mode Operation:

  1. Configure controller behavior policy and notifications using i3c_controller_set_policy_config and i3c_controller_set_interrupt_config.
  2. Perform Dynamic Address Assignment using i3c_controller_perform_daa.
  3. Optionally configure HDR behavior using i3c_controller_config_hdr_mode before HDR transfers.
  4. Use i3c_controller_send_ccc for broadcast/direct CCC operations (and response helpers for queued CCC responses).
  5. Build an i3c_transfer_t descriptor with target address, address mode, buffer, length, speed, direction, and flags.
  6. Execute data transfers using blocking or non-blocking APIs: (i3c_controller_write_blocking, i3c_controller_read_blocking, i3c_controller_write_non_blocking, i3c_controller_read_non_blocking).
  7. Optionally enable advanced features such as i3c_controller_enable_ibi or i3c_controller_process_hot_join_and_enumerate.

Using Dynamic Address Assignment (DAA)

DAA is typically used once after bus bring-up, and again when new target devices are introduced (for example after Hot-Join).

Recommended controller-side flow:

  1. Fill an array of i3c_device_config_t with known target capabilities.
  2. Call i3c_controller_perform_daa.
  3. Read discovered devices from the internal list using i3c_controller_get_device_count and i3c_controller_get_device, or from the optional output buffer passed to i3c_controller_perform_daa.
  4. Use the assigned dynamic address or DAT index in i3c_transfer_t for subsequent private transfers.
Note
Legacy I²C targets do not participate in ENTDAA. Configure them with static addressing and use matching transfer speed constraints.

Using Speed Modes (SDR/HDR)

Speed is selected per transfer through i3c_transfer_t.speed.

Practical guidance:

Controller timing can be selected using i3c_controller_config_t.sdr_timing_preset. Choose I3C_SDR_TIMING_PRESET_MANUAL when explicit nanosecond timing values are required in i3c_scl_timing_t.

Using Common Command Codes (CCC)

CCC transactions are initiated with i3c_controller_send_ccc.

Recommended flow:

  1. Select I3C_CCC_BROADCAST for bus-wide commands, or I3C_CCC_DIRECT with a valid DAT index for per-target commands.
  2. Provide request payload in req_buffer/req_length when required by CCC.
  3. Provide resp_buffer/resp_max_length for read/response CCCs.
  4. Read queued response metadata using i3c_controller_ccc_response_get_count and i3c_controller_ccc_response_read.
Note
When using direct CCC, DAT index must refer to a currently enumerated target in the controller internal device list.

Using Hot-Join

Hot-Join allows a new target to request participation after initial bus setup.

Recommended controller-side flow:

  1. Enable policy using i3c_controller_set_policy_config and/or i3c_controller_config_hot_join.
  2. Enable notification via i3c_controller_set_interrupt_config with I3C_EVENT_MASK_IBI_HJ_REQ_RECEIVED.
  3. On event notification, call i3c_controller_process_hot_join_req, or use i3c_controller_process_hot_join_and_enumerate for one-step handling.
  4. Re-run targeted enumeration/DAA as needed and refresh active device descriptors used by transfers.

Target Mode Operation:

  1. After configuration and enable, wait for Dynamic Address Assignment from the controller.
  2. Expect controller-driven CCCs and address changes as part of enumeration and capability negotiation.
  3. Prepare transfer buffers using i3c_target_prep_controller_read or i3c_target_prep_controller_write.
  4. Optionally generate events such as i3c_target_raise_ibi_sir or i3c_target_raise_master_request.
  5. Ensure non-blocking target buffers remain valid until transfer completion/abort is reported through status or callback.
  6. Disable the peripheral using i3c_disable before modifying core configuration parameters or switching operating mode.

i3c_init

Initializes the I3C peripheral and prepares the hardware for configuration.

i3c_init(I3C_INST, I3C_PERIPHERAL);

i3c_controller_set_config

Configures controller timing, thresholds, and bus behavior.

memset(&ctrl_cfg, 0, sizeof(ctrl_cfg));
ctrl_cfg.core_clk = I3C_CORE_CLK_HZ;
ctrl_cfg.op_mode = I3C_MODE_CONTROLLER;
ctrl_cfg.num_of_devices = 1;
/* Configure timing and thresholds as required */
i3c_controller_set_config(I3C_INST, &ctrl_cfg);

i3c_target_set_config

Configures target mode parameters and identification fields.

memset(&tgt_cfg, 0, sizeof(tgt_cfg));
tgt_cfg.core_clk = I3C_CORE_CLK_HZ;
tgt_cfg.op_mode = I3C_MODE_TARGET;
/* Configure identification fields and thresholds */
i3c_target_set_config(I3C_INST, &tgt_cfg);

i3c_enable

Enables the I3C peripheral and allows bus participation.

i3c_enable(I3C_INST);

i3c_controller_perform_daa

Performs Dynamic Address Assignment for connected devices.

i3c_device_config_t device_cfg = {
.device_type = I3C_TARGET_TYPE_I3C,
.static_address = 0,
.dynamic_address = 0
};
i3c_controller_perform_daa(I3C_INST, &device_cfg, 1);

i3c_controller_write_blocking

Executes a blocking write transfer.

blk_cfg.buf = tx_buf;
blk_cfg.size = sizeof(tx_buf);
blk_cfg.timeout = 100;
blk_cfg.send_stop = true;
blk_cfg.is_read = false;
i3c_controller_write_blocking(I3C_INST, &blk_cfg);

i3c_controller_read_blocking

Executes a blocking read transfer.

blk_cfg.buf = rx_buf;
blk_cfg.size = sizeof(rx_buf);
blk_cfg.timeout = 100;
blk_cfg.send_stop = true;
blk_cfg.is_read = true;
i3c_controller_read_blocking(I3C_INST, &blk_cfg);

i3c_controller_write_non_blocking

Starts an interrupt-driven write transfer.

nb_cfg.buf = tx_buf;
nb_cfg.size = sizeof(tx_buf);
nb_cfg.send_stop = true;
nb_cfg.is_read = false;

i3c_controller_read_non_blocking

Starts an interrupt-driven read transfer.

nb_cfg.buf = rx_buf;
nb_cfg.size = sizeof(rx_buf);
nb_cfg.send_stop = true;
nb_cfg.is_read = true;

i3c_disable

Disables the I3C peripheral.

i3c_disable(I3C_INST);

i3c_deinit

Deinitializes the I3C instance and returns hardware to reset state.

i3c_deinit(I3C_INST);