Jump to content
43oh

I2C hangs at Wire.endtransmission() after running for a while


Recommended Posts

Hello,

 

I just received a TM4C1294XL connected launchpad. I'm trying to get it working with L3G4200D gyroscope  (it's a module from Parallax with pull-ups). The program runs as expected for a while and then freezes and I have to long press the reset button to get it working again. By importing the Energia sketch into CCSv6, I was able to find the program hangs at the Wire.endtrsmission(), in particular at line

 

  //Wait for any previous transaction to complete
  while(ROM_I2CMasterBusBusy(MASTER_BASE));
 
in the Wire library. I tried with another sensor and experience the same problem. Could somebody help me out?
 
The related code is attached below (sorry for not knowing how to format the code in the post):
 
void setup()
{
// Start the Ethernet and UDP
Ethernet.begin(mac,ip);
udp.begin(localPort);
 
// Start I2C
Wire.setModule(0);
Wire.begin();
// Initilize the L3G4200D gyro
gyro.init();
}

 

void loop()
{
currentTime = millis();
interval = currentTime - lastTime;
if (currentTime - lastTime >= 100)
{
// Serial.println(interval);
lastTime = currentTime;
// Get sensor data
gyro.getRawData();
 
compseTxPacket();
 
IPAddress remoteIP(192,168,1,10);
uint16_t remoteLocalPort = 13000;
udp.beginPacket(remoteIP, remoteLocalPort);
udp.write(txPacketBuffer, TX_PACKET_SIZE);
udp.endPacket();
 
}
}

 

void L3G4200D::getRawData()
{
while((i2cReadReg(L3G4200D_REGISTER_STATUS_REG) & 0x08) == 0);
 
Wire.beginTransmission(L3G4200D_ADDRESS);
Wire.write(L3G4200D_REGISTER_OUT_X_INC); // first register to start read from
Wire.endTransmission();
Wire.requestFrom(L3G4200D_ADDRESS, 6);
while(Wire.available() < 6);
 
byte raw_low;
byte raw_high;
raw_low = Wire.read();
raw_high = Wire.read();
data.xRawDPS = (raw_high << 8) | raw_low;
raw_low = Wire.read();
raw_high = Wire.read();
data.yRawDPS = (raw_high << 8) | raw_low;
raw_low = Wire.read();
raw_high = Wire.read();
data.zRawDPS = (raw_high << 8) | raw_low;
}
Link to post
Share on other sites

Do you have a logic analyzer?

 

Can you tell what state the SDA and SCL lines are in?

 

Is the SCL being held low?

Is the SDA toggling still?

 

If yes to both above then the slave device is having trouble with your communication sequence.

 

If this is the case then you will need to consult the datasheet for the slave device and see what it expects for a communication sequence for each command that you are sending to it.

 

For example, if you want to read the sensor repeatedly, are you sending the correct sequence?

That datasheet may say do this:

1. Write(TakeAReadingPlease)

2. Read(GiveMeTheReadingPlease)

 

But you do this instead:

1. Write(TakeAReadingPlease)

2. Read(GiveMeTheReadingPlease)

3. Read(GiveMeTheReadingPlease)
 
Then you can expect step 3 to fail. 
 
Why?
 
Because the state machine inside the sensor is confused and probably in an unresponsive state until it receives one of its predetermined commands.
 
Does that make sense?

 

Link to post
Share on other sites

Hi zeke,

 

thanks for the quick response. When it hangs, the SCL line stays HIGH and SDA line stays low. Do you have any comment on that?

 

The strange thing is I'm able to get correct data for the first 2 minutes (maybe a bit longer). I checked on other's code for the same chip, I'm pretty sure the code to get raw data is OK.

 

Any suggestions from anybody would be appreciated.

 

Thanks!

Link to post
Share on other sites

Hi zeke,

 

thanks for the quick response. When it hangs, the SCL line stays HIGH and SDA line stays low. Do you have any comment on that?

 

The strange thing is I'm able to get correct data for the first 2 minutes (maybe a bit longer). I checked on other's code for the same chip, I'm pretty sure the code to get raw data is OK.

 

Any suggestions from anybody would be appreciated.

 

Thanks!

 

you sure there are pull-ups in your module? The lm4c1294 doesn't have internal pull-ups (altough i think it has in the SCL line).

 

i find the lm4c1294 I2C very picky. I have yet to get it to work with TivaWare. But with energia i had no problem with it.

 

What i do for srf08 sensors to avoid errors is i ask for software revision over and over, istead of just resquesting data and just wait until data comes in (wich it may never come a hang in there forever), until it gives me a clear reading, then i know i can ask the correct sensor data. 

Link to post
Share on other sites

I'm sure this is no a problem with pull-ups. I tried to add two 4.7k pull-ups to SDA and SCL lines. Same thing happens.

 

And I used the following line to check if new data is available too.

 

while((i2cReadReg(L3G4200D_REGISTER_STATUS_REG) & 0x08) == 0);

 

It seems CCS works fine to me, but not Energia. 

Link to post
Share on other sites

Intuitively, I want to say that there is a problem with the Master side in its interrupt service routine - assuming the I2C Master is running with interrupts.

 

If the Master isn't programmed to handle a  specific interrupt flag that occurs then the Master will hang.

 

Here's some troubleshooting ideas for you:

 

1. Check out the I2C Bus Primer. It has plenty of authoritative information on the operation of the I2C bus. 

2. Compare the waveforms they present there to the waveforms that you see on your I2C bus.

3. Do you get consistent START and STOP conditions on all of your bus transactions?

4. Are you handling all Slave side interrupts for START, STOP, Receive and Transmit conditions?

5. Are you handling all Master side interrupts for START, STOP, Receive and Transmit conditions?

6. Can you sanity check your Master code by using a bit bang I2C Master rather than an interrupt driven Master?

7. Are you using a logic analyzer that can interpret I2C thus visually showing you what is happening on the bus?

Link to post
Share on other sites

Thanks again for your guide. I'll look into that.

 

However, I found that using Wire library, the read of 6 bytes takes almost 6ms. This is way too slow that I got from using modified CCS example which takes under 0.5ms. Is this a issue with the library or I did something wrong?

Link to post
Share on other sites

I have heard from others that it is slow but I personally do not use Energia so I cannot comment on the performance of its implementation of the Wire routines. 

 

From the Slave's point of view, the speed of the CLK signal is unimportant because the Master is in control.

 

I have worked with systems where the Master bit banged out the proper I2C protocol only it was super slow (less than 15kHz) and it worked just fine.

 

For reference, a 100kHz CLK signal is a normal speed.

 

I took a look at your getRawData routine and I might be inclined to rewrite it like this:

void L3G4200D::getRawData()
{
	byte rawData[6];
	byte i;
	
	while((i2cReadReg(L3G4200D_REGISTER_STATUS_REG) & 0x08) == 0);
 
	Wire.beginTransmission(L3G4200D_ADDRESS);
	Wire.write(L3G4200D_REGISTER_OUT_X_INC); // first register to start read from
	Wire.endTransmission();
	Wire.requestFrom(L3G4200D_ADDRESS, 6);
	while(Wire.available() < 6);
	
	for( i=0; i<6; i++)
	{
	    rawData[i++] = Wire.read();
	}
	
	data.xRawDPS = (rawData[1] << 8) | rawData[0];
	data.yRawDPS = (rawData[3] << 8) | rawData[2];
	data.zRawDPS = (rawData[5] << 8) | rawData[4];
}

The idea is to read the I2C bus as quickly as possible and do the data processing afterwards - not in between reads.

 

 

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...