|
|
View previous topic :: View next topic |
Author |
Message |
frank_the_programmer
Joined: 05 Feb 2024 Posts: 7
|
Reset I2C On Lockup? |
Posted: Wed Aug 28, 2024 7:26 pm |
|
|
Hey all. I've been using the CCS C Compiler for a while now and I have some nice looking code, but I can't figure how to make my I2C routines fool proof. I'm putting this dsPIC33FJ128GP204 through its paces trying to find edge cases.
I've been able to consistently recreate an I2C lockup by shorting the clock or data lines. If anyone knows a way to reset the I2C or reboot the device on a detected error send your ideas this way! Thanks. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1351
|
|
Posted: Wed Aug 28, 2024 8:28 pm |
|
|
I'm sure others will have good tips for making it stable.
For resetting, did you try:
Setting the I2C PMD bit to 1
Setting the I2C PMD bit to 0
redo the setup of the I2C |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Thu Aug 29, 2024 4:09 am |
|
|
The key thing on i2C, is to handle the situation where a peripheral
has not completed a read transaction.
Imagine you are talking to a peripheral, and something happens. The chip
restarts. You now have a device that is part way through a transaction,
and potentially expecting clocks. If you then wake up your I2C driver,
and start trying to talk to it, it won't work...
Quote: |
Details: It is generally known that the I2C bus can hang if an I2C master is removed from the bus
in the middle of a data read. This can occur because the I2C protocol does not mandate
a minimum clock rate. Therefore, if a master is reset in the middle of a read while a
slave is driving the data line low, the slave will continue driving the data line low while it
waits for the next clock edge. This prevents bus masters from initiating transfers. If this
condition is detected, the following three steps will clear the bus hang condition:
1. An I2C master must generate up to 9 clock cycles.
2. After each clock cycle, the data pin must be observed to determine whether it has
gone high while the clock is high.
3. As soon as the data pin is observed high, the master can initiate a start condition.
|
In this situation, since the data line is being held low by the slave, the
master device cannot send an I2C start. Result disaster....
What has to happen is that you have to send I2C clock pulses to the
device till it completes it's transaction. This then releases the bus, and
you can start correctly. Now the PIC I2C peripheral won't do this, since it
won't receive a correct response to an I2C start being sent.
So:
1) Setup the I2C using #use I2C, with NOINIT.
2) At the start of the main, read the I2C data line.
3) If this is low, the bus is being held be a peripheral. If so, simply operate
the clock line yourself in code.
Remember not too fast. 5uSec low, then 5uSec 'float'. Then back to
testing the data line.
4) Once the SDA line releases, simply call i2c_init for the bus.
This releases the device that is driving the bus.
As a further comment to this using the NOINIT, and I2C_init option, also
allows you at any time to reset the master device. You can just use:
I2C_INIT(YourStreamName, FALSE);
to turn ff the I2C peripheral, and:
I2C_INIT(YourStreamName, TRUE);
To re-initialise the I2C peripheral and re-enable it. |
|
|
frank_the_programmer
Joined: 05 Feb 2024 Posts: 7
|
|
Posted: Mon Sep 02, 2024 8:08 am |
|
|
Thanks for the speed replies. I took a few days to test the suggested methods and I think I got something that works! Adding NOINIT on the #use i2c worked great after initializing in main.
Using your methods I was able to add an i2c activity monitor. if the i2c slave interrupt doesn't see any activity for 2 seconds it restarts the i2c with i2c_init(0) and shortly after i2c_init(1). This works great and now the bus fully recovers. Thanks again everyone. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Mon Sep 02, 2024 10:30 am |
|
|
A critical thing you did not mention. That you were dealing with being a
slave device.
The 'check the line' part is for the master device.
If you are losing packets from a master, resetting the bus is sensible, but
does suggest you may be not correctly handling one of the bus errors.
Is it possible you are getting a buffer overrun, or a bus collision?. Both
will be flagged and can be tested for in your handler. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|