Initial I2C Bus Reset

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
User19852
Level 1
Level 1
It happens that some I2C slave permanently pulls down SDA, after the I2C bus was interrupted during some transmission.
A solution to this is toggling the clock 8 times and sending a stop condition. A similar solution is to perform a Nack Read without Start Condition.
The reference manual describes such a procedure in 18.5.4.2 Valid Master Transmit Data Formats in case of a wrong TDF code.

I would like to perform such a Bus Reset on each boot of my XMC4800. I tried with


XMC_I2C_CH_MasterReceiveNack(channel);
XMC_I2C_CH_MasterStop(channel);


after initialization. Unfortunately, in case of a stuck SDA all what happens is a single clock toggle.
I do not even get an i2c event interrupt. So I need to boot the XMC4800 up to eight times to reset the bus.

Is there a clean way to achieve this bus reset on initialization? Or do I need to configure the Pins as GPIO
first and toggle the clock myself before initializing the I2C module?
0 Likes
6 Replies
jferreira
Employee
Employee
10 sign-ins 5 sign-ins First like received
Hi,

Can you try with the following sequence?
      XMC_I2C_CH_ClearStatusFlag(i2c->i2c, XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION);
// Clear the bus by sending nine clock pulses
XMC_I2C_CH_MasterStart(i2c->i2c, 0xff, XMC_I2C_CH_CMD_READ);
while ((XMC_I2C_CH_GetStatusFlag(i2c->i2c) & XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) == 0U)
;

XMC_I2C_CH_ClearStatusFlag(i2c->i2c, XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION);
XMC_I2C_CH_MasterStop(i2c->i2c);
while ((XMC_I2C_CH_GetStatusFlag(i2c->i2c) & XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) == 0U)
;


Regards,
Jesus
0 Likes
User19852
Level 1
Level 1
Thanks for the reply. Unfortunately the suggested solution does not work for me. In case no slave holds down SDA I can see the clock toggles. But if a slave holds SDA, the clock is not toggled even once and the code remains in the first loop waiting for XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION for ever.
0 Likes
jferreira
Employee
Employee
10 sign-ins 5 sign-ins First like received
Hi,

I cannot check right now, but maybe you could try:

      
XMC_I2C_CH_SetInputSource(i2c->i2c, XMC_I2C_CH_INPUT_SDA, USIC_INPUT_ALWAYS_1);

XMC_I2C_CH_ClearStatusFlag(i2c->i2c, XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION);
// Clear the bus by sending nine clock pulses
XMC_I2C_CH_MasterStart(i2c->i2c, 0xff, XMC_I2C_CH_CMD_READ);
while ((XMC_I2C_CH_GetStatusFlag(i2c->i2c) & XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) == 0U)
;

XMC_I2C_CH_ClearStatusFlag(i2c->i2c, XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION);
XMC_I2C_CH_MasterStop(i2c->i2c);
while ((XMC_I2C_CH_GetStatusFlag(i2c->i2c) & XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) == 0U)
;

XMC_I2C_CH_SetInputSource(i2c->i2c, XMC_I2C_CH_INPUT_SDA, i2c->sda_pin_input);


Regards,
Jesus
0 Likes
jferreira
Employee
Employee
10 sign-ins 5 sign-ins First like received
Hi,

I have being trying it out and finally you need to do something like

  XMC_GPIO_SetMode(SDA_PIN, XMC_GPIO_MODE_INPUT_TRISTATE);
XMC_I2C_CH_SetInputSource(I2C_CHANNEL, XMC_I2C_CH_INPUT_SDA1, USIC0_C0_DX3_DOUT0);

do
{
XMC_I2C_CH_SetInputSource(I2C_CHANNEL, XMC_I2C_CH_INPUT_SDA, USIC0_C0_DX0_DX3INS);

XMC_I2C_CH_ClearStatusFlag(I2C_CHANNEL, XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION);
// Clear the bus by sending nine clock pulses
XMC_I2C_CH_MasterStart(I2C_CHANNEL, 0xff, XMC_I2C_CH_CMD_READ);
while ((XMC_I2C_CH_GetStatusFlag(I2C_CHANNEL) & XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) == 0U);

// Not Acknowledge software recovery since operating in Loop Back Mode
XMC_USIC_CH_TXFIFO_Flush(I2C_CHANNEL);
XMC_USIC_CH_TXFIFO_Flush(I2C_CHANNEL);
XMC_USIC_CH_SetTransmitBufferStatus(I2C_CHANNEL, XMC_USIC_CH_TBUF_STATUS_SET_IDLE);
XMC_I2C_CH_ClearStatusFlag(I2C_CHANNEL, 0x1ffff);

XMC_I2C_CH_SetInputSource(I2C_CHANNEL, XMC_I2C_CH_INPUT_SDA, USIC0_C0_DX0_P2_1);
}
while (XMC_GPIO_GetInput(SDA_PIN) == 0);
0 Likes
User19852
Level 1
Level 1
I just implemented a solution using the GPIO interface before configuring the I2C interface. Thanks anyway for the pure-I2C-interface-solution you just provided.
0 Likes
AntonioG
Level 1
Level 1
First like given First reply posted Welcome!

Hi Jesus,

I just tried your code to implement a well done I2C bus clear.

Unfortunately I still don't understand the connections between peripherals and GPIOs. For this reason I was unable to adapt your code to my application which uses the I2C3 serial with P3.15 as SDA and P0.13 as SCL. Could you help me?

Best regards Antonio

0 Likes