I2C SPI USB CAN eSPI Cable Testing View All Quick Start Guides User Manuals Software Downloads Knowledge Base Videos Case Studies App Notes White Papers Sales Support About Us
Products Blog Sales Support Contact Search
Clearing a Stuck I2C Bus Using an Aardvark Adapter or Promira Serial Platform
Chris

Stuck I2C Bus

Sometimes a fault can cause an I2C bus to get stuck. This happens when a slave device is driving a low/logic-0 state on the bus while waiting for another clock pulse, but the master has already aborted a transaction, rebooted, become confused by bus noise, or some other fault.

Resolving a Stuck I2C Bus

A bus stuck in this way can be cleared by cycling 9 clock pulses on the bus, causing any device holding the bus to release its low state drive.

The Aardvark I2C/SPI Host Adapter and Promira Serial Platform can be used to clear the bus by putting the appropriate pins into GPIO mode.  Pullups should then be enabled and the pins set to inputs.  The output buffers should be set to low/0. Then toggle between input/output mode to do the bus cycling.

This process must be initiated by the host software. With systems where this problem occurs frequently, it may be recommended to include this sequence as part of a normal initialization process, or it may be part of an error recovery process.

On the other hand, when the bus is entirely powered by the Aardvark adapter or Promira Serial Platform and all devices are certainly reset by the controlling software, this type of recovery is generally not necessary.

Recovery Process Example

Screenshot of the recovery process on the bus:

Example of Clear I2C Bus

Channel 1: SCL (Yellow)

Channel 2: SDA (Blue)

Sample Code for Aardvark Adapter and Promira Serial Platform

Below are sample codes using Python that allow the host software to perform the actions needed to clear the stuck I2C bus:

Aardvark I2C/SPI Host Adapter

def i2c_clear_bus (handle):

old_config = aa_configure(handle, AA_CONFIG_QUERY)

assert old_config in (AA_CONFIG_GPIO_ONLY, AA_CONFIG_SPI_GPIO,

AA_CONFIG_GPIO_I2C, AA_CONFIG_SPI_I2C), \

aa_status_string(ret)

ret = aa_configure(handle, AA_CONFIG_GPIO_ONLY)

assert ret == AA_CONFIG_GPIO_ONLY, aa_status_string(ret)

ret = aa_gpio_pullup(handle, AA_GPIO_SCL | AA_GPIO_SDA)

assert ret == AA_OK, aa_status_string(ret)

ret = aa_gpio_direction(handle, 0) # inputs

assert ret == AA_OK, aa_status_string(ret)

ret = aa_gpio_set(handle, 0)

assert ret == AA_OK, aa_status_string(ret)

for i in range(9):

ret = aa_gpio_direction(handle, AA_GPIO_SCL)

assert ret == AA_OK, aa_status_string(ret)

ret = aa_gpio_direction(handle, 0)

assert ret == AA_OK, aa_status_string(ret)

ret = aa_configure(handle, old_config)

assert ret == old_config, aa_status_string(ret)

Full Aardvark example file.

Promira Serial Platform

def i2c_clear_bus (channel):

old_config = ps_app_configure(channel, PS_APP_CONFIG_QUERY)

assert old_config in (PS_APP_CONFIG_GPIO, PS_APP_CONFIG_I2C,

PS_APP_CONFIG_SPI,

PS_APP_CONFIG_SPI | PS_APP_CONFIG_I2C), \

ps_app_status_string(ret)

ret = ps_app_configure(channel, PS_APP_CONFIG_GPIO)

assert ret == PS_APP_CONFIG_GPIO, ps_app_status_string(ret)

ret = ps_gpio_direction(channel, 0) # inputs

assert ret == PS_APP_OK, ps_app_status_string(ret)

ret = ps_gpio_set(channel, 0)

assert ret == PS_APP_OK, ps_app_status_string(ret)

for i in range(9):

ret = ps_gpio_direction(channel, 1)

assert ret == PS_APP_OK, ps_app_status_string(ret)

ret = ps_gpio_direction(channel, 0)

assert ret == PS_APP_OK, ps_app_status_string(ret)

ret = ps_app_configure(channel, old_config)

assert ret == old_config, ps_app_status_string(ret)

Full Promira example file.

For any questions on using the Aardvark I2C/SPI Host Adapter or Promira Serial Platform for this use case, please email us sales@totalphase.com.