cancel
Showing results for 
Search instead for 
Did you mean: 

i2c busy flag

spa2
Associate II
Posted on March 17, 2010 at 08:02

i2c busy flag

16 REPLIES 16
davidwalker9
Associate II
Posted on May 17, 2011 at 13:43

The statement ''I2C_Cmd(..., ENABLE)'' sets the PE bit to 1. You then write to the I2C_CCR register through the ''I2C_Init'' statement. The reference manual says you have to write I2C_CCR with PE clear so you may want to swap the order of those two statements.

tran2
Associate II
Posted on May 17, 2011 at 13:43

Hello,

   I have the same problem as yours. There was a another thread in this forum, and its probaly a problem from your device I2C Slave.

   The communication I2C is a little stupid, when you lost a data or a bit in your transfer, the I2C Slave counter stop and wait for a bit who will never come, that's why the slave device hang up the line and keep SDA pull down, SCL up ( so busy bus).

   The best way to get out of this problem is make a power reset on the slave device ( impossible to me).

   The second solution is : clock out the slave device buy BIT-BANGING, but i don't know how to do it.

    Does somebody here can tell us about the GPIO config, and the sequency that we have to make to clock out this problem, pls?

    I tried to pull the SCL up and down, but the communication is still hang up.

Great thank,

damh
Associate II
Posted on May 17, 2011 at 13:43

First problem is the command sequence as said above.

The hangup problem can be solved in my case by:

I2C_DeInit

I2C_Init

I2C_ITConfig

...

=> a complete local reset! In my case not the slave is the problem, but the STM itself.

To avoid the hang in many cases, use DMA.

EDIT:

>>The second solution is : clock out the slave device buy BIT-BANGING, but i don't know how to do it.<<

You can try to send a stop sequence, but you have to change the pin configuration to do this. Every normal slave should release the bus on this sequence. The stm libary code won't help, because you have to break the rules of I2C communication (you are not allowed to send a stop sequence, if you are not the master (or in your case, the master forgot to be the master ;-)).
tran2
Associate II
Posted on May 17, 2011 at 13:43

Thank for your answer,

The init of STM32 ( as you said) doesn't work for me.

My device is M24C02 and he is really hanged-up.

I don't understand about the STOP that i have to make, that's why i post my question here :d.

My SDA was pulled down because the ODrain of slave device was pulled down to the ground. So what ever i do from the STM32, the SDA won't never pulled up.

How do you do in this case a STOP : because a STOP for me is a pull up of SDA when the SCL is in a Hight Level.

Thx
hbliek2
Associate II
Posted on May 17, 2011 at 13:43

You need to feed clock pulses on the line until the slave device releases the SDA line. No device can hold SDA for more than 9 clock cycles. Once SDA is free again, you can issue a new start.

Personally I have quit trying to get the hardware I2C controller to work. It seem rather unstable or very critical to init/command sequences, even in a straightforward master-only configuration. And it requires an insane amount of coding to get transfers going. So I simply went back to old-skool bit-banging I2C transfers. Most of the time I need to wait for the resulting data anyway, so there is hardly any performance penalty either.

Anyway; this is how my I2C_address function starts; it just feeds SCL cycles until the SDA checks high. Afer that it continues by sending the normal I2C start and address.

 /* Check if the bus is stuck and act accordingly */

 while(GPIO_ReadInputDataBit(SDA1) == RESET)

 {

  if(i++ > 10)

  {

   break;

  }

  GPIO_WriteBit(SCL1, 0);

  Delay(vI2cDelay);

  GPIO_WriteBit(SCL1, 1);

  Delay(vI2cDelay);

 }

tran2
Associate II
Posted on May 17, 2011 at 13:43

Thanks,

It seems to work.

But i have another question, when you fake the clock ( when the SDA is Low), so the Slave will see an octet ''0x00''.

Is it possible, by a chance, in a Write Cycle ( where the EEPROM was stuck), there are a 0x00 who will be written in my EEPROM?==> it means that i will lost my data ? :( , its was an experience when i toggle the line SCL manual by connecting it directly to the ground :d.

Quyen
spa2
Associate II
Posted on May 17, 2011 at 13:43

Hi.

just an update, if I init. the I2C controller before the GPIO I don't get the BUSY flag, so that will be my solution.

Tthanks

Tomas DRESLER
Senior II
Posted on May 17, 2011 at 13:43

The only issue with all your code is, that you don't follow EXACTLY the state machines described in the reference manual and in CORRECT time (see notes below them, and errata sheet).

NEVER try to make more than written in the EVx events, parse flag by flag, not the whole words.

I2C works well, however is very critical on flag handling. That's why DMA is recommended... The last version of I2C AN for STM32 should have a well working code. But please don't use I2C examples from the FW library, they may fail sometimes.

My last comment is to the bit bashing and troubles around - the line is usually pulled down by STM32, if you don't follow the proper flag handling (by improper testing and clearing flags, you can ''hide'' one event followed by another, and I2C gets stuck in the previous state, holding the SCL down). The peripherals like memories don't usually show this behavior, if you gave them proper amount of clocks.

Btw. if, by toggling the CLK line, you enter some data into the memory, depending on the issued command and protocol, you can write whatever was on SDA line - be careful about that.
bogao3037
Associate II
Posted on May 17, 2011 at 13:43

I tried your code and and just could bring the SDA to 0. I checked with Logic Analyzer and still see the SDA is hold to ''1'' all the time. Do I need to change the pin configuration  from OPEN_DRAIN to AF_PUSH_PULL before the code starts?