Why is there a pause() in I2C routines?

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

Why is there a pause() in I2C routines?

2,231 Views
bonzo
NXP Employee
NXP Employee

I've been working with KL25.

I've need to read I2C data from one of our sensors.  I used the routines provided in the examples (KL25_SC Rev 6).

The i2c.c code has a small delay function called pause() which does about 40 NOP instructions (see below).

This function is called after i2c_Stop() in the I2CWriteRegister and I2CReadRegister functions.

If you don't call pause(), the system will not function.

In looking at the Processor Expert code, there is no delay function.

So what's going on?

thanks,

// this delay is very important, it may cause w-r operation failure.

static void pause(void)

{

    int n;

    for(n=0; n<40; n++);

      #ifndef CMSIS

  asm ("NOP"); // Toggle LED1

  #else

  __nop();

  #endif

}

Tags (1)
4 Replies

916 Views
BlackNight
NXP Employee
NXP Employee

Hi Brad,

I suggest to check with a logic analyzer why it is failing in that case?

not sure if this is still what I saw (and reported) with an early version of the I2C code I saw when the FRDM-KL25Z came out and I tried the I2C code:

My thinking is that the I2C driver code is not correctly checking the flags. The 'workaround' in the code was this delay, which as result made the code 'work'. I realized then as well that the Processor Expert code was doing it the correct way.

I have not checked the Rev6 code, but seems that this 'workaround' is still in place.

Maybe related to this: it might be a problem with the silicon, and depending on which version of the silicon you are using, there could be a problem, documented in the errata. See KL25Z and I2C: Missing Repeated Start Condition | MCU on Eclipse

I hope this helps (somehow).

0 Kudos

916 Views
Mohsin455
Contributor IV

Hi Erich,

               Even I want to know what is the real reason for this delay. We are having some issues running the I2C at 100KHz althought works fine at 300KHz. It is related to the same pause() command. We had to increase this to work for 100KHz but keeps fails occassionally.

Also, we had to add this pause even after completion of read from a device. I think this is required after we send the STOP. But really want to know the reason as at 100KHz, I had to increase this delay to around 15us to get it to work.

I am using K60N512.

Thanks,

Mohsin

0 Kudos

916 Views
mjbcswitzerland
Specialist V

Hi

Since I am presently doing some I2C investigations I have picked up on this old post.

The first thing to note is that I have used the uTasker master I2C driver for a couple of years in interrupt mode without any time delays. However I could imagine that a delay is used in some code to avoid a following I2C message from being started when the stop condition of a previous message has not completed. In the uTasker driver there is a check for the bus busy when a new message is to be sent (but a repeated start can not be used since there is no present activity that the SW "knows" about):

while (*register_ptr & IIC_IBB) {}                           // wait until the stop has actually been sent to avoid a further transmission being started in the mean time

The reason is that a stop condition could have been sent to complete a previous transfer but the stop condition takes (from a SW point of view) quite a long  time to actually take place and complete). For the SW driver the stop has been commanded and there is nothing else to do. When a follow on message is to be sent, checking the bus busy state will show whether a previously commanded stop condition has completed or not. If the bus is still busy due to this a new start can not yet be sent and so one needs to wait a "short time". The time that it takes is of course bus speed depended and also dependent on bus loading (capacitance - number of devices, length etc.) and so if this interval is to be protected by a delay the delay must be a worst case delay for the system.

If the bus busy check is doing effectively the same thing as the delay (waiting a short time for previous activity to complete) it is probably a more suitable solution due to two reasons:

1. it is self timed

2. It only takes place when actually needed. (No delays are required for repeated starts and it is possible to continuously use back-to-back transmissions without any spacing between them).

I haven't checked the code with the delay in it so it may be a different issue. However the uTasker I2C driver is used on all Kl and K devices and there is no knowledge of problems or errate workarounds needed.

Regards

Mark

916 Views
jia_guo
NXP Employee
NXP Employee

Mark:

I totally agree with you.

And I have validated that the pause function can be replaced by the following code:

static void pause(I2C_MemMapPtr p)

{

    while(p->S & I2C_S_BUSY_MASK);

}