I2C hot plugging issue

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

I2C hot plugging issue

Jump to solution
1,201 Views
laszlomonda
Contributor IV

Hi there,

 

I'm working on an unusually complicated keyboard, the Ultimate Hacking Keyboard.

 

The keyboard halves are connected via I2C, driven at 100 kHz. The right keyboard half (K22) is the master device and it talks to the left keyboard half (KL03) all the time in order to keep the state up-to-date as much as possible.

 

This is working well, except when I disconnect the keyboard halves and reconnect them. I want to make the communication resume then which doesn't always happen.

 

I use `I2C_MasterTransferNonBlocking()` to kickstart the communication between the keyboard halves, then I use it again at the end of my I2C callback to keep the communication going. The problematic part is when the keyboard halves get separated.

 

This is my simplified callback:

 

 

static void i2cCallback(I2C_Type *base, i2c_master_handle_t *handle, status_t status, void *userData)

{

    if (status != kStatus_Success) {
        I2C_MasterDeinit(I2C_MAIN_BUS_BASEADDR);
        I2C_MasterInit(I2C_MAIN_BUS_BASEADDR, &masterConfig, sourceClock);
        I2C_MasterTransferCreateHandle(I2C_MAIN_BUS_BASEADDR, &masterHandle, i2cCallback, NULL);

    }
    status_t status2 = I2C_MasterTransferNonBlocking(I2C_ADDRESS, &masterHandle, &masterXfer);

}

 

As you can see above, I check the status variable of the callback and try to reset the state of the I2C peripherial to keep the communication going. If the status is not success, I deinitialize, then reinitialize I2C, then recreate the handle.

 

I've already spent hours on making this reliable but even the current code is not good enough. The communication stops after a couple disconnects, and sometimes the state of the master gets screwed too, to the point that the right keyboard half doesn't scan the keyboard matrix anymore, which is weird because it's totally unrelated to the I2C callback.

 

I'd really appreciate any help on this issue.

 

Thank you,

- Laci

Labels (1)
1 Solution
861 Views
laszlomonda
Contributor IV

Hi Jorge,

Thank you very much for your answer, and sorry for noticing it so lately!

I think your suggested solutions could haved worked for us, but we ended up implementing an alternative solution in the meantime.

We basically implemented an I2C watchdog which reinitializes the I2C peripherial when no bus activity is detected for a second. This seems to work pretty well. You can check out our code on GitHub. We have also slighly modified the KSDK to update the I2C_Watchdog variable.

Thanks again, and have a nice day!

- Laci

View solution in original post

2 Replies
861 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Laci,

I am sorry that your question went unattended.

What is the status of your issue?

I believe in a disconnection the slave could hang and stay in a state where it holds the bus, so when the cable is reconnected the Master is not able to recover control over the I2C bus. You can confirm this situation with a scope, most probably the SDA line will be held low by the slave.

There is a good explanation by Mark Butcher to workaround such issue in the next document:

I2C device dead-lock recovery 

Basically it consists in configuring the I2C pins as GPIOs and sending clock pulses until the slave releases the SDA line.

More or less the same approach is described in the application note AN4803, by sending 9 clock pulses followed by NACK and a STOP signal (search in the document for " I2C_Restore"):

http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4803.pdf 

Best Regards!

Jorge Gonzalez

862 Views
laszlomonda
Contributor IV

Hi Jorge,

Thank you very much for your answer, and sorry for noticing it so lately!

I think your suggested solutions could haved worked for us, but we ended up implementing an alternative solution in the meantime.

We basically implemented an I2C watchdog which reinitializes the I2C peripherial when no bus activity is detected for a second. This seems to work pretty well. You can check out our code on GitHub. We have also slighly modified the KSDK to update the I2C_Watchdog variable.

Thanks again, and have a nice day!

- Laci