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 support@ccsinfo.com

PIC24EP512 - Exiting from i2c lock-up on faulty sensor
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
benoitstjean



Joined: 30 Oct 2007
Posts: 543
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PIC24EP512 - Exiting from i2c lock-up on faulty sensor
PostPosted: Tue Oct 10, 2023 7:05 am     Reply with quote

Device: PIC24EP512GP806
Compiler: 5.026

Hi guys,

I know this topic may have already somewhat addressed in the past, including an older post from myself, but I've gone through what I could find and I think I still need help because what I thought was working ended-up not completely working now that I got this new batch of circuits made.

Situation: I have a FW version that I use throughout a few different circuits, some with I2C sensors, some without. When the device boots-up, if it does not find the I2C device due to it either not being present on this version or being faulty on the version with the sensor, then it should just mark-it as 'fail' and continue.

What I have so far is that as the PIC boots, when it reaches the code for the initialization of the I2C devices, it starts a 1 second timer then attempts to initialize the I2C sensor. In an ideal world, if the sensor initialization is successful, then it is marked as PASS then the code continues. But if it is not present or faulty, the timer will eventually expire and i2c_init( SENSORS, FALSE ); is called.... but this doesn't appear to do anything.

What happens during initialization is that the code first attempts to read the I2C device ID by calling an I2C read at the proper device address / memory location on the device. The problem is that it hangs somewhere in the read function:

Code:

unsigned int8 Read_I2C( unsigned int8 DeviceAddress, unsigned int8 MemoryAddress )
{
   unsigned int8 Data;
                                                                                 
   i2c_start();
   i2c_write( DeviceAddress );
   i2c_write( MemoryAddress );
                               
   i2c_start();
   i2c_write( DeviceAddress | 0x01 );

   Data = i2c_read( 0 );

   output_float( PIN_G2 );
   output_float( PIN_G3 );

   return( Data );
}


This code has been working for years for all my boards since they all have sensors and they never failed. But then this new batch of PCBs doesn't have the sensors but I want it to use the same code as the rest of the circuit is the same.

So my question is I need to know if there's a way / how to "release" CCS's I2C code so that it exits that Read_I2C() function. I haven't identified at which line it hangs specifically since I know it's that function due to fprintfs to TeraTerm before and after the function whereas the one after never prints therefore it hangs in that function...

When the 1 second timer expires, that's where I should have that I2C exit condition to make sure that this Read_I2C unblocks. So isn't there anything I can send like toggling one of the lines a number of times or something to release the internal I2C code?

Thanks!

Ben

[EDIT] In the Read_I2C(), at the first I2c_write( DeviceAddress ), I added a check for what is returned to see if it's an ACK or NACK since I figured that perhaps a NACK would be returned if there's nothing but the function appears to return 0 which is an ACK....


Last edited by benoitstjean on Tue Oct 10, 2023 7:28 am; edited 1 time in total
gaugeguy



Joined: 05 Apr 2011
Posts: 288

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 7:27 am     Reply with quote

Why aren't you checking for an acknowledge from the sensor and stopping if that is not returned?
The i2c_write function returns the state of the ACK bit but you aren't checking it.
benoitstjean



Joined: 30 Oct 2007
Posts: 543
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 7:29 am     Reply with quote

I guess we wrote at the same time. I modified the function to check what i2c_write( DEVICE_ADDRESS ) returns and it returns a 0 when there's no sensor.... and 0 means ACK.... the circuit does not have anything on I2C therefore I havn't put any pull-up resistors on there. The pins are just unconnected.
Ttelmah



Joined: 11 Mar 2010
Posts: 19225

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 7:34 am     Reply with quote

Multiple separate things.

First, you can use the no_init option in the i2c setup. Read the SCL & SDA
pins. If these are not high the i2c device is hung. If the SDA line is high
You can repeatedly clock the SCL line yourself and hopefully the SDA line
will release. This is the specified i2c way of unlocking a hung bus.
So:
Code:

      if (input(SDA)==0) //If SDA is not high
      {
         //Now need to try clocking SCL to release bus
         for (int temp8=0;temp8<9;temp8++)
         {
            output_low(SCL);
            delay_us(5);
            output_float(SCL);
            delay_us(5);
         } //9*100KHz clocks
      }
      i2c_init(I2CBUS,1); //physically initialise bus


Then look at how PCM_programmer tests for the device acknowledging
in the I2C scanner program in the code library. The device should always
return a zero as an acknowledgement when you send it it's address byte
if it doesn't the device is either not there or not working. This is your
first write after the start. Test this and if you don't get this acknowledge
then you know not to proceed.... Sad

Do this test before trying to i2c_read.
Ttelmah



Joined: 11 Mar 2010
Posts: 19225

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 7:39 am     Reply with quote

Everybody pointed out the same thing. That the test to do is for the
acknowledge when you send the address, _before_ ever trying to read. Smile

I was trying to handle the other possibility of a hung sensor as well.

Best Wishes
benoitstjean



Joined: 30 Oct 2007
Posts: 543
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 7:42 am     Reply with quote

I guess I should be more specific as this may change the way to approach this: on the board with the sensors, I have two I2C devices. On the board without, then there's none obviously.

Therefore on the board with sensors, one can fail while the other works. So reading the SCL and SDA lines may not be the best solution since one device may work while the other does not.

[EDIT] And I do have the NOINIT flag set in #use i2c.
Ttelmah



Joined: 11 Mar 2010
Posts: 19225

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 8:06 am     Reply with quote

No, you should do the read on SDA first. The point is that I2C devices
can hang, where they have missed a clock, or received a clock during
boot. In that state, trying to send a read or a write will still result in
the bus staying hung. Manually clocking if the bus is high is the way to
release this.
Then before the reads, if you test the acknowledge whenever you send
the device address, you can tell whether a device is hung.
benoitstjean



Joined: 30 Oct 2007
Posts: 543
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 8:19 am     Reply with quote

Alrighty.... so at the moment at boot time, I do input( PIN_G3 ) - which is my SDA pin on the version with sensors - and it appears to return 1... but that pin is not connected since there's no sensor!

I guess I should tie both SCL and SDA to low with a resistor on the version without sensors. This will ensure that both pins are forced low.

It appears that at the moment, since they are untied / floating, I guess they are detecting a high state? That's what it seems to be anyhow since reading the pin returns 1 and doing an i2c_write( DeviceAddress ) returns ACK (0)....

[EDIT] So definitely, I should tie SDA and SCL to GND with resistors because at the moment, they are floating and reading them returns 1.
gaugeguy



Joined: 05 Apr 2011
Posts: 288

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 8:29 am     Reply with quote

Trying to test a floating pin can be done, but it is very tricky. Best to make sure the pin has a known state for both pass and fail.
benoitstjean



Joined: 30 Oct 2007
Posts: 543
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 8:36 am     Reply with quote

What's your 'trick' to test the floating pin? Is it to force it let's say to low as an output then make it an input and read it? What delays do you suggest in-between? For now this would save me lots of headaches (I can't add the resistors to the circuit unless I dismantle everything and I really don't want to do this).
gaugeguy



Joined: 05 Apr 2011
Posts: 288

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 8:38 am     Reply with quote

You can test for a floating pin or pullup present by:
driving the pin low
wait a short time
let the pin float
wait a time dependent on your hardware
test the pin

If the timing is done correctly you should reliably get a high for a pullup present or a low for floating.
gaugeguy



Joined: 05 Apr 2011
Posts: 288

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 8:44 am     Reply with quote

Further details:
The high test is dependent on the time constant of the pullup and circuit capacitance.
The low test (floating) is dependent on the pin and circuit capacitance holding the low level.
The time the pin is held low is to make sure any pin/stray capacitance is discharged.
You will need to use a scope to watch the pin response in your circuit with both a pullup present and floating to determine the timing.
benoitstjean



Joined: 30 Oct 2007
Posts: 543
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 8:50 am     Reply with quote

Oh! I tried it with 10ms after pulling low then 10ms after setting floating and now when I read both pins, they are low.... so this appears to work with the circuit without sensors. I will test a bit later with the circuit that does have sensors to see how that reacts... I expect the pins to be high since they both have a pull-up resistors on the bus.

Now it's a matter of figuring a way to make the sensors appear as failing to see what code will bypass them in the eventuality of a failure.

More to come.

Thanks!

Ben
gaugeguy



Joined: 05 Apr 2011
Posts: 288

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 9:21 am     Reply with quote

It would probably work with 10us and 10us but that depends on your hardware. If you need to handle a possible disconnect during operation you may need to repeat this test before each read/write begins.
Ttelmah



Joined: 11 Mar 2010
Posts: 19225

View user's profile Send private message

PostPosted: Tue Oct 10, 2023 9:49 am     Reply with quote

I'd say no.

The I2C bus should always be resistively pulled up. Then the input pin will
read high _reliably_
Clocking the version without sensors won't matter.
Then when you do the i2c_write of the address, you won't get an ack,
so you know the sensor is not there.
Simple and reliable.

Pulling high can be done simply by turning on the internal pull up resistors
in the chip. Most PIC24's have these individually settable on the pins.
The current drawn by these is tiny, so will have no effect on the versions
where the sensors are present.

I don't like having pins shorted to ground. Doing so could result in a massive
overload if something drives the line high... Sad

You are getting the ACK, because the line is not pulled up.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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