AM263P4-Q1: Regarding the operation when multiple I2C communications are performed simultaneously

Part Number: AM263P4-Q1
Other Parts Discussed in Thread: SYSCONFIG

A timeout is occurring during I2C communication with an external EEPROM (when I2C_transfer() is executed). The situation is summarized below:

* AM263Px MCU, SDK version 09.02.00 is being used.

* I2C3 is used for communication with the EEPROM.

* To enable the timeout, the SDK's EEPROM_write() and EEPROM_read() functions are not used for communication with the EEPROM. Instead, custom functions with added timeout settings are used.

* The timeout duration is set with a margin based on the estimated communication time derived from the bit rate and data transfer volume.

* A separate task is using I2C1 and I2C2 to communicate with devices other than the EEPROM.

* The bit rate is the same for all I2C1, I2C2, and I2C3 settings, and interrupts are disabled.

* We have confirmed that I2C1 and I2C2 communication (execution of I2C_transfer()) was occurring in a separate task while communication with the EEPROM was taking place.

* The timeout during communication with the EEPROM no longer occurred after making the following changes:
** Disable I2C1 and I2C2 communication, or significantly extend the timeout period during communication with the EEPROM.

Based on the above situation, we believe that simultaneous I2C communication is having an effect that prolongs the communication time.
Please tell us the cause of this phenomenon and recommended countermeasures (such as a correct method for estimating the time until communication is completed when simultaneous I2C communication occurs).

Desired response date: 2026/5/17

  • Hi Imaoka,

    The key detail in your setup is that interrupts are disabled, meaning all three I2C instances (I2C1, I2C2, I2C3) are operating in polling mode. In polling mode, the I2C driver blocks the CPU while actively polling hardware registers to complete each transfer [1][2].

    Since I2C1 and I2C2 are being serviced in a separate task, here is what happens:

    1. Your EEPROM task initiates I2C_transfer() on I2C3 in polling/blocking mode.
    2. The RTOS scheduler allows the other task (handling I2C1/I2C2) to run.
    3. That task also calls I2C_transfer() in polling mode, which monopolizes CPU cycles while polling I2C1 or I2C2 to completion.
    4. During this time, the I2C3 hardware peripheral continues its bus transaction, but the software cannot service it (read FIFO, advance state machine, acknowledge bytes) because the CPU is occupied polling another instance.
    5. This extends the effective completion time of the I2C3 transfer well beyond the theoretical bit-rate calculation, causing your timeout to expire.

    Each I2C instance (I2C0–I2C3) is independent hardware [3], so there is no bus-level arbitration conflict. The contention is purely at the CPU/software level — multiple polling transfers competing for the same processor.


    Recommended Countermeasures

    Option 1 (Strongly Recommended): Switch to Interrupt Mode

    Enable interrupt mode for all I2C instances via SysConfig [2]. In interrupt mode:

    • The hardware generates an interrupt when data is ready or a transfer completes.
    • The CPU is not blocked polling registers, so multiple I2C instances can proceed concurrently without starving each other.
    • Transfer completion time will closely match the theoretical bit-rate-based estimate.

    This is the architecturally correct solution for concurrent multi-instance I2C operation.

    Option 2: Serialize I2C Operations

    Use a mutex or semaphore to ensure only one I2C transfer executes at a time across all tasks. This eliminates CPU contention but reduces throughput.

    Option 3: Adjust Task Priorities

    If the EEPROM task has higher priority than the I2C1/I2C2 task, and preemption is enabled, the EEPROM polling transfer will not be interrupted. However, this only works if the lower-priority task cannot preempt — verify your RTOS scheduling configuration.

    Option 4: Extend Timeout (Workaround Only)

    As you discovered, extending the timeout works but is not a robust solution. If you must use this approach, the timeout should account for:

    Effective timeout = (I2C3 transfer time based on bit rate)
    + (worst-case blocking time from other I2C polling transfers)
    + margin

    Where worst-case blocking time = sum of maximum transfer durations on I2C1 and I2C2 that could execute during your I2C3 transfer window.


    Correct Estimation Method

    When using polling mode with multiple concurrent I2C instances, the theoretical transfer time formula:

    T = (number_of_bits) / (bit_rate)

    is insufficient. You must add the worst-case CPU unavailability time — i.e., the maximum time the CPU could be occupied polling other I2C instances before returning to service yours. This depends on task priorities, transfer sizes on other instances, and scheduling behavior.

    With interrupt mode, the theoretical formula becomes valid again because the hardware drives completion independently of CPU availability.


    To help refine this recommendation, it would be helpful to know:

    • The RTOS task priority levels for the task handling I2C1/I2C2 versus the EEPROM task
    • Whether all I2C instances are serviced from the same task/thread or different execution contexts
    • The data transfer sizes on I2C1 and I2C2 (to quantify worst-case blocking)
    • Whether your custom timeout implementation accounts for OS task-switching overhead
    • The specific EEPROM device timing (page write time, clock stretching behavior)

    Resources

    1. I2C LLD API Guide - AM263Px
    2. I2C HLD API Guide - AM263Px
    3. SOC Module - I2C Base Address Definitions
    4. I2C HLD Module API
    Best Regards,
    Zackary Fleenor