cancel
Showing results for 
Search instead for 
Did you mean: 

Error interrupt I2C Example1

jordi
Associate II
Posted on September 04, 2009 at 17:24

Error interrupt I2C Example1

11 REPLIES 11
guyvo67
Associate II
Posted on May 17, 2011 at 12:31

Quote:

I can't offer you a solution, but I had lots of problems with I2C with STM32 in the past. After discussions with ST support, I realized that the events defined on the libraries (the ones used on the examples) do not cover all the possible cases, just the ''ideal cases''.

Yes the value of the events I get you can not even make them with combining or oring the bits together with those defined in ST header. That makes it very strange. Maybe the people of ST could modify the i2c firmware in order to give the developers a honest change to catch all events and interrupts.

Quote:

The best way to work with I2C is to read the reference manual RM0008, and treat the events as described in figures 232 to 235. These figures on the same time define exactly the possible events (keep in mind that in the real world one can have combinations of different events, so take care when implementing, I wouldn't follow the way the examples implement it with switch and case ).

Well I think that STs firmware lib should cover all the possible event cases anyway. Sure if you write your own handler totally in assembler I'm pretty sure these bugs will not appear but it's only I2C even not SPI or ethernet so I think you can drive this totally in C. eg with 300k you only have ca 3µs on period given a cortex at 72M this is still 250 cycles. Besides the I2C is done in hardware without bit banging so I expect this to be fast and accurate.

Quote:

Ah, and try to use DMA, because when a I2C DMA transfer is started, one doesn't have to bother with interrupts and events until a STOP is received or has to be sent!

Also here a bit overkill to use DMA on I2C. But I will give it try anyway. Indeed you reduce the number events which will have a good influence on timings. Again, this should not be last resort solution as it's only I2C and with clock stretching enabled you are pretty sure the protocol can be handled even with servicing other interrupts at the same time.

-G

guyvo67
Associate II
Posted on May 17, 2011 at 12:31

GOOD NEWS:

system running :

core = 72M

I2C = 400k ( don't forget the I2C_DutyCycle_16_9 )

I2C1/2 at int0

freeRTOS running with 8 tasks

So as you probably could read in this thread it's all about the capturing of the right events at the right moment. Well in fact it is believe me.

I introduced a new event:

I2C_EVENT_SLAVE_BYTE_RECEIVED_AND_STOP ((u32)0x00000050)

Which means that there's a byte received and also a stop condition. These two together are never captured when you follow the ST examples. You need to capture this state when the cortex is very busy. Apparently the I2C hardware is faster than the software can handle and misses the last byte recieved in the I2C_EVENT_SLAVE_BYTE_RECEIVED. So two events are signalled together at the hardware level and this is not proper handled by the ST examples.

This was only the slave side and of course this can happen on the master side too. But my program is running now with the extra event simply as:

case I2C_EVENT_SLAVE_BYTE_RECEIVED_AND_STOP:

buffer[idx++] = I2C_ReceiveData(I2C2);

(void)(I2C_GetITStatus(I2C2, I2C_IT_STOPF));

I2C_Cmd(I2C2, ENABLE);

break;

I don't know which states on the master that suffers from this timing issue yet because I haven't seen it so far. But I keep you all posted of tests. ( over night run with full charge )

Strange thing is that ST didn't provide this dual state in the event list. Maybe they think that the examples are only meant to run once ;)

Sequel of testing:

I had to add one more event case at the receiver:

I2C_EVENT_SLAVE_BYTE_RECEIVED_WITH_BTF ((u32)0x00020044)

This is to handle the clock stretching. In fact you can put the same code in this case as you do for I2C_EVENT_SLAVE_BYTE_RECEIVED which is reading the byte in your buffer so it's out of the shift register and ready to receive another byte.

At the master I also had to add :

I2C_EVENT_MASTER_BYTE_TRANSMITTED ( declared in ST header )

This also covers the clock stretching but at the master. You just send you data byte in the case as you do with I2C_EVENT_MASTER_BYTE_TRANSMITTING.

My tests ran for hours without any problems now.

 

Resume and things to keep in mind:

 

 

1. At slave foresee I2C_EVENT_SLAVE_BYTE_RECEIVED_AND_STOP to capture EV2/EV4 when they are signalled together

 

 

2. At slave foresee I2C_EVENT_SLAVE_BYTE_RECEIVED_WITH_BTF to handle clock stretching if enabled.

 

 

3. At master foresee I2C_EVENT_MASTER_BYTE_TRANSMITTED to handle slock stretching if enabled

 

 

4. Analyse your own application on a state diagram level and try to port this out to the available events. Don't hesitate to make your own combinations

 

 

5. Be aware that I2C hardware level is sometimes faster than your software layer can handle.

 

 

6. ST didn't make events in the header to capture the clock stretching on the slave receiver.

 

 

Important notes in rm0008:

 

 

SLAVE:

 

 

If RxNE is set and the data in the DR register is not read before the end of the next data

 

reception, the BTF bit is set and the interface waits until BTF is cleared by a read from

 

I2C_SR1 followed by a read from the I2C_DR register, stretching SCL low

 

 

MASTER:

 

 

If TxE is set and a data byte was not written in the DR register before the end of the last data

 

transmission, BTF is set and the interface waits until BTF is cleared by a read from I2C_SR1

 

followed by a write to I2C_DR, stretching SCL low.

 

 

Concerning my case this topic is closed. Thanks for the reactions it gave me some food for thoughts and ideas.

Cheers

-G

[ This message was edited by: guyvo67 on 06-09-2009 13:16 ]