i2c waiting for ever

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

i2c waiting for ever

974 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dragilla on Sun Jan 29 07:58:15 MST 2012
Hello again

I fixed all my hard faults, and other silly errors and now I faced another behavior of my hardware which I don't understand.
I have an IMU 6DOF board (accelerometer and gyroscope) connected to my lpcxpresso 1769 board through i2c. The whole set works 100% ok... for a while Last time it run for almost 3 hours with no fault. But if I wait long enough the program always gets stuck in one line:
static uint32_t I2C_Start (LPC_I2C_TypeDef *I2Cx)
{
I2Cx->I2CONSET = I2C_I2CONSET_STA;
I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;

// Wait for complete
while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI)); // <--- HERE IT GETS STUCK
I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
}

And it stops here from the function that reads data from the gyroscope (ITG3200) - never the accelerometer. 3 hours is kind of long... my loop reading data from this IMU board runs at 100hz... so I don't have much idea of what can happen. Do you?

I tried changing clock speeds for the I2C - the default was 100khz, I tried 120khz as my core clock is 120mhz, then I tried 60khz - same result.
The itg3200 can run on frequencies from 0 to 400khz.

I even tried rearranging the code, to put the accelerometer reading before the gyroscope. I tried putting some other commands between the two reads, to make a time gap between using the i2c - nothing.

Please give me an idea what can I try. Maybe I should try to do something with my hardware, or something?
0 Kudos
Reply
17 Replies

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by atomicdog on Thu Feb 02 12:31:31 MST 2012

Quote: dragilla
I changed the order, removed my 'safety code' and again I get the same infinite loop, waiting for interrupt flag forever.
So it must be something else than just the order.

Check the hardware.
If the SCL line is low when the STA is sent it will wait until the SCL line goes high.
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by yoko on Thu Feb 02 12:31:00 MST 2012
Hi,

    You might want to check the I/O pin config.  I2C requires open drain with pullups.   

Hoan
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dragilla on Wed Feb 01 14:21:06 MST 2012
I changed the order, removed my 'safety code' and again I get the same infinite loop, waiting for interrupt flag forever.
So it must be something else than just the order.
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dragilla on Wed Feb 01 06:14:12 MST 2012
It makes sense of course. Why is the cmsis example constructed the other way around? Maybe there is a reason for that? Anyone?

Wow. Now I look in the original cmsis file and it is like this: first clear SI, then set STA. Some evil gnomes must have changed it in my code ;) I'm closing the thread :)
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by atomicdog on Wed Feb 01 00:48:00 MST 2012

Quote: dragilla
Ok. So clearing the interrupt flag. How else would I check the interrupt flag if it's not cleared first?
Or maybe you mean, that I clear it after setting STA, so the interrupt flag actually may be set first, then I clear it? Hm...

But it works now, another night of flawless operation... Only I added those checks, which actually don't do anything since it just works now. I don't get it.

Clear it before you set STA. Before you try to start a new transaction you should have the I2C peripheral in a know good state.
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dragilla on Tue Jan 31 01:04:05 MST 2012
Ok. So clearing the interrupt flag. How else would I check the interrupt flag if it's not cleared first?
Or maybe you mean, that I clear it after setting STA, so the interrupt flag actually may be set first, then I clear it? Hm...

But it works now, another night of flawless operation... Only I added those checks, which actually don't do anything since it just works now. I don't get it.
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by atomicdog on Mon Jan 30 13:59:09 MST 2012

Quote:
Well the manual says that after sending the start flag the SI flag is set.

I agree.

Quote:
So checking for this flag after setting the STA bit makes perfect sense to me. I just check if I2C is started this way...

I agree.

I never said either of those things were the problem.
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by atomicdog on Mon Jan 30 10:33:39 MST 2012

Quote: dragilla
Besides, reading the manual, I think the order is ok (first set start, then clear interrupt, then wait for interrupt - not check the interrupt flag as you mentioned).
From the UM10360:
The master transmitter mode may now be entered by setting the STA bit. The I2C logic will
now test the I2C-bus and generate a START condition as soon as the bus becomes free.
When a START condition is transmitted, the serial interrupt flag (SI) is set ...
So, any idea what's going on here? Why adding my code (which only adds some checks) prevents the problem?


:confused::confused::confused:
...then wait for interrupt == ..check the interrupt flag
Why doe you think their different?

You quoted the user manual but where do you see it saying to clear the interrupt flag right after setting the start flag? :confused:
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dragilla on Mon Jan 30 09:00:00 MST 2012
But I don't add any code between setting the start flag, clearing the interrupt and then checking. The order and timing of these 3 operations should stay the same?
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ex-kayoda on Mon Jan 30 07:05:50 MST 2012

Quote: dragilla
Why adding my code (which only adds some checks) prevents the problem?



Doesn't your question include the answer? You're changing the timing :eek:

Probably adding a few nops would do the same :rolleyes:
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dragilla on Mon Jan 30 06:42:53 MST 2012
Besides, reading the manual, I think the order is ok (first set start, then clear interrupt, then wait for interrupt - not check the interrupt flag as you mentioned).
From the UM10360:
The master transmitter mode may now be entered by setting the STA bit. The I2C logic will
now test the I2C-bus and generate a START condition as soon as the bus becomes free.
When a START condition is transmitted, the serial interrupt flag (SI) is set ...


So, any idea what's going on here? Why adding my code (which only adds some checks) prevents the problem?
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dragilla on Mon Jan 30 02:06:52 MST 2012

Quote: atomicdog
This sequence is incorrect. I'm actually surprised you say it works.
  I2Cx->I2CONSET = I2C_I2CONSET_STA;   
  I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;


You don't want to clear the interrupt flag until you're ready for the next state.
The code [U]should[/U] get stuck there since you're clearing the INT flag right before you check if it's set.



This is not my code, this is cmsis1.3
Anyway... what's really odd (especially after what you say) is: I added the global counter to the code from my previous post, to count how many times retry is substracted and guess what - it worked the whole night and the global counter (global_retries) still shows 0 ...
The code now looks like this:
static uint32_t I2C_Start (LPC_I2C_TypeDef *I2Cx)
{
int i = 10000, retry = 3;

// Wait for complete
while (retry){
i = 10000;
I2Cx->I2CONSET = I2C_I2CONSET_STA;
I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
while(!(I2Cx->I2CONSET & I2C_I2CONSET_SI) && i --);
if(i) break;
global_retries ++;
retry --;
}
// if retry == 0 create infinite loop
if(!retry) while(1);
I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
}
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by atomicdog on Sun Jan 29 16:07:41 MST 2012
This sequence is incorrect. I'm actually surprised you say it works.
  I2Cx->I2CONSET = I2C_I2CONSET_STA;   
  I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;


You don't want to clear the interrupt flag until you're ready for the next state.
The code [U]should[/U] get stuck there since you're clearing the INT flag right before you check if it's set.
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dragilla on Sun Jan 29 09:20:33 MST 2012

Quote: kayoda
Could be useful to add a global retry counter to control how often this effect occurs  :rolleyes:



Good idea... for starters...
But the real question is why it happens? And how to prevent it? You think it's normal?
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ex-kayoda on Sun Jan 29 09:01:12 MST 2012
Could be useful to add a global retry counter to control how often this effect occurs  :rolleyes:
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dragilla on Sun Jan 29 08:38:17 MST 2012

Quote: kayoda
Timeout counter :eek:


Could you be more precise?

I will try something like this:
static uint32_t I2C_Start (LPC_I2C_TypeDef *I2Cx)
{
int i = 10000, retry = 3;

// Wait for complete
while (retry){
i = 10000;
I2Cx->I2CONSET = I2C_I2CONSET_STA;
I2Cx->I2CONCLR = I2C_I2CONCLR_SIC;
while(!(I2Cx->I2CONSET & I2C_I2CONSET_SI) && i --);
if(i) break;
retry --;
}
// if retry == 0 create infinite loop
if(!retry) while(1);
I2Cx->I2CONCLR = I2C_I2CONCLR_STAC;
return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK);
}

What do you think?
0 Kudos
Reply

776 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ex-kayoda on Sun Jan 29 08:33:46 MST 2012

Quote: dragilla
Please give me an idea what can I try.



Timeout counter :eek:
0 Kudos
Reply