CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Reset I2C On Lockup?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
frank_the_programmer



Joined: 05 Feb 2024
Posts: 7

View user's profile Send private message

Reset I2C On Lockup?
PostPosted: Wed Aug 28, 2024 7:26 pm     Reply with quote

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: 1349

View user's profile Send private message

PostPosted: Wed Aug 28, 2024 8:28 pm     Reply with quote

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: 19520

View user's profile Send private message

PostPosted: Thu Aug 29, 2024 4:09 am     Reply with quote

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... Sad
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. Very Happy

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

View user's profile Send private message

PostPosted: Mon Sep 02, 2024 8:08 am     Reply with quote

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: 19520

View user's profile Send private message

PostPosted: Mon Sep 02, 2024 10:30 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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