cancel
Showing results for 
Search instead for 
Did you mean: 

Hardware I2C buffering question

peter239955
Associate II
Posted on September 23, 2013 at 16:39

I am working with an STM32L151xC, and I'm building a bridging between an USB and an I2C interface.

Since they have different time constraints, I came up with some issues I'm not familiar with.

To read out data from my I2C device, I first send the address (and read bit) and wait for an ACK from the device. Then I want to read out the rest of the data.

However, since there is USB communication involved, there is a 1ms delay between the address, and the reading of the data.

The thing I've been seeing, is that after I send the address with read bit, the controller immediately starts reading two bytes, then 1ms later, when I ask for it, it reads out the rest.

Oddly enough, the two bytes that were read out earlier come up correctly 1ms later, so it is working allight.

Is this behaviour normal? Why are those two bytes read out automaticly, and why exactly two?

Can this be dangerous for stability, and is there a way to prevent this from happening?

Sincerely,

Peter

#stm32 #i2c
12 REPLIES 12
Posted on September 23, 2013 at 16:52

> However, since there is USB communication involved, there is a 1ms delay between the address, and the reading of the data.

How is the USB communication involved and why would there be the 1ms delay?

Is you I2C interrupt-driven, or DMA-driven, or...?

> The thing I've been seeing, is that after I send the address with read bit, the controller immediately starts reading two bytes, then 1ms later, when I ask for it, it reads out the rest.

How do you know that? Looking at the waveforms using a LA, possibly? Or any other means?

> Oddly enough, the two bytes that were read out earlier come up correctly 1ms later, so it is working allight.

How do they ''come up correctly... later''?

Do you see two bytes to be transmitter repeatedly on the bus? Or...?

JW

peter239955
Associate II
Posted on September 24, 2013 at 09:09

>How is the USB communication involved and why would there be the 1ms delay?

>Is you I2C interrupt-driven, or DMA-driven, or...?

The bridging between USB and I2C is meant to give controll over the I2C protocol over the USB bus to the interface.

First there is a USB command to send an I2C start signal, with the address and write bit. Then the data is send in a new USB command, thus 1ms later at least, an I2C stop command is also generated.

Another USB command is then send to generate another I2C start signal, and the address with the read bit set.

After that, another USB command has to trigger reading back the response.

This is visible in ''png'' that I attached.

I do not use I2C or DMA, I just use the I2C functions from stm32l1xx_i2c.h.

>How do you know that? Looking at the waveforms using a LA, possibly? Or any other means?

I attached an oscilloscope to check the SDA and SCL signals, as seen on the prints I attached.

>How do they ''come up correctly... later''?

>Do you see two bytes to be transmitter repeatedly on the bus? Or...?

This is visible in ''png'' that I attached, you can see the two bytes that are being read, after wich there is a 1ms delay until the USB issues to start reading the data.

They come up correctly means when I read out the response 1ms later, I receive these two bytes as well as the rest of the response correctly after the last USB command.

________________

Attachments :

01.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I18Y&d=%2Fa%2F0X0000000bjU%2FFJElWA58paXYPgqjF36N1sDgfOpn0v2rWoYPAcvdO5g&asPdf=false

02.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I1A0&d=%2Fa%2F0X0000000bjR%2Fy.xo1oqFJE9j9.2ixZLk9Lb7ED91KzmyjJmHWuWAu_0&asPdf=false
Posted on September 24, 2013 at 10:00

>>Is you I2C interrupt-driven, or DMA-driven, or...?

> I do not use I2C

What?

(I understand of course 😉 )

>>How do they ''come up correctly... later''?

>>Do you see two bytes to be transmitter repeatedly on the bus? Or...?

> This is visible in ''02.png'' that I attached, you can see the two bytes that are being read, after > wich there is a 1ms delay until the USB issues to start reading the data.

Show us the code which produced 02.png (i.e. what is called at the moment when USB ''issues to start reding the data'').

JW

peter239955
Associate II
Posted on September 24, 2013 at 10:40

I mean ofcourse that I don't use interrupt driven I2C, my bad.

The code that is called to what leads to 02.png is his:

    i2c_start();

    I2C_TimeOut_Var = 0;

    register_callback_i2c_error(i2c_timeout_callback, TimeOut);  //Will set I2C_TimeOut_Var = 1 after TimeOut ms

    I2C_ClearFlag(I2C1, I2C_FLAG_AF);

    I2C_Send7bitAddress(I2C1, DeviceAddress<<1, I2C_Direction_Receiver);

    do{

         if( I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) )

        {

                return 0x80;

        }

        if( I2C_TimeOut_Var )

        {

            I2C_TimeOut_Var = 0;

            register_callback_i2c_error(0, 0);

            return 0x80;

        }

    }while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

    register_callback_i2c_error(0, 0);

Posted on September 24, 2013 at 13:35

This looks reasonable.

What if you'd start a new, very simple project, just going through all those steps without the involvement of USB, making a delay between the consecutive steps e.g. using a simple delay loop? This shouldn't take up much time and maybe looking at the resulting waveform on the scope might trigger some ideas...

JW

peter239955
Associate II
Posted on September 24, 2013 at 15:05

As I said, the functionality is already working, so a behvioural study for idea's to fix it isn't needed.

I'm trying to find out if this is normal behaviour and why.

If this could cause a problem to stability, I also like to know how to prevent this from happening. For instance if I would like to read out only one or two bytes, I missed the chance to call I2C_AcknowledgeConfig to NACK the last byte.

Posted on September 25, 2013 at 10:01

Yes, it's normal. The I2C module is a bit weird in this respect, probably in attempt to maintain a high pace transmission on the hardware and making use of double-buffered receiver, allowing for sloppier software handling. After the ADDR bit is cleared by reading both status registers (which is what happens in 

I2C_CheckEvent

() - I don't use the ''library'' so I didn't realize that) the receiver reads in the next two bytes. It's your software which checks for them only 1ms later.

It's about time to read thoroughly the ''Master receiver'' chapter in the manual, including the description of POS bit in I2C_CR1. It will answer you the question on how to perform a single/two byte read, in details.

JW

peter239955
Associate II
Posted on September 27, 2013 at 12:57

The POS bit retermines if the current of the next byte is answered with ACK, but this does not help me. Both bytes are already received (one in the data register, the other in the shift register) when I know if they should be ACK'd.

I seem unable to find in the datasheet how I can induce SCL stretching manually. As I understand it, SCL stretching is completely controlled by hardware, based on RxNE and BTF, wich both can not be set by software.

Maybe I'm missing something.
Posted on September 27, 2013 at 13:16

The module transmits the address, sets the ADDR bit, and then waits until both I2C_SR1 and I2C_SR2 registers are read. That's the time when you set the bit(s) determining whether to ACK or not, and which of the following 2 bytes (POS and ACK in I2C_CR1).

To poll for ADDR, it's enough to read I2C_SR1, so don't read I2C_SR2 at that moment. In other words, as I said above, don't use the

I2C_CheckEvent

() function.

JW