I2C Delay between ACK and Data from slave

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

I2C Delay between ACK and Data from slave

4,848 次查看
ellenlin
Contributor III

Dear NXP , 

   Now I am using KL43Z I2C as Slave Device , and I need to read data from KL43Z ( I2C Slave ) , and i found a delay ( about 16us between ACK & DATA ( Slave ) . as below CLOCK setting and LA Picture , Why this happen ? how to modify to solve this , i want to slave response quickly . The Situation as below , 

 

IDE : MCUXpresso

SDK Project : reference "frdmkl43z_i2c_interrupt_b2b_transfer_slave"

I2C Slave : FRDM-KL43Z

Setting : At 125KHz, SCK should be Hi 4us and low 4us 

and there are some delay (about 2 clocks = 16us) before slave mode out to master.

pastedImage_1.png

pastedImage_3.png

Thanks a lot !!

标签 (1)
标记 (5)
0 项奖励
回复
13 回复数

3,972 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi eLin,

Thank you for your updated information.
Customer can use the optimize, actually optimize will decrease the code size, just decrease the code execute time.
On my side, I modify the SDK interrupt handler, and change it to the register control mode, then the ACK&Data time is also decreased.
From my attached code, you can find if don't modify, the executed time is about 12us, but if I use the register control, the time is about 6.8us.
Actually, it is relate to the Handler execute time.
I modify the SDK code in folder: SDK_2.4.1_FRDM-KL43Z\boards\frdmkl43z\driver_examples\i2c\interrupt_b2b_transfer\slave\iar
fsl_i2c.c void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) like this:

void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
{
    volatile unsigned char Dummy;
    if (I2C0->FLT & (I2C_FLT_STOPF_MASK)) //stop
    {                                         
        I2C0->FLT    |= (I2C_FLT_STOPF_MASK);                                 
        I2C0->S      |= (I2C_S_IICIF_MASK);                                     
        return;                                                     
    }  
    
    if(I2C0->S & I2C_S_IICIF_MASK)        
    {
       I2C0->S |= I2C_S_IICIF_MASK;         //clear interrupt flag                                 
       if (I2C0->S & I2C_S_ARBL_MASK)       //clear ARBL                                    
       {
          I2C0->S |= (I2C_S_ARBL_MASK);
          if (!(I2C0->S & (I2C_S_IAAS_MASK)))                                      
          {
        return ;
          }    
       }        
    }        
    
    if (I2C0->S & I2C_S_IAAS_MASK)          //ADDRESS                                   
    {
    I2C0->C1 &= ~I2C_C1_TXAK_MASK;                                               
        if (I2C0->S & I2C_S_SRW_MASK)        //send mode               
    {                                  
            I2C0->C1 |= I2C_C1_TX_MASK;                                                
            I2C0->D = 0x55;
        }
    else   //receive mode
    {    
            I2C0->C1 &= ~I2C_C1_TX_MASK;                                                 
            Dummy = I2C0->D ;                                              
                    
        }
        
    }
    else  //date range
    {            
        if (I2C0->S & I2C_S_SRW_MASK) //send mode
    {
        if(I2C0->S & I2C_S_RXAK_MASK)  //nack
        {
            I2C0->C1 &= ~I2C_C1_TX_MASK; //change to receive mode
            Dummy = I2C0->D;
        }
        else  
        {
                       I2C0->D = 0x55;
        }
                      
        }
    else
    {    
            I2C0->C1 &= ~I2C_C1_TX_MASK;          //receive mode                                                                       
            //Rec_data[I2C_S_Recindex++] = I2C0_D ;   
            Dummy = I2C0->D;
        }            
              
    }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


This time should meet the customer's demand.
If the customer still want to minimize the time, they need to modify the .s file, just use I2C0_IRQHandler as the Interrupt handler directly.
Don't copy the to I2C0_DriverIRQHandler, then I2C_TransferCommonIRQHandler, then  I2C_SlaveTransferHandleIRQ
As you know, enter deep function also need the code execute time, just simplify the code method.
But if the time already meet the customer's demand, it's better use the SDK directly, becuase that code structure is more better, just a little complicated to the code execute time.
I also attached my modified code for your reference.

This picture is SDK code without modification:

pastedImage_1.jpg

This picture is using the register controlled interrupt handler:

pastedImage_2.jpg
Wish it helps you!


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 项奖励
回复

3,972 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi e Lin,

      From my own view point, I don't think it is the slave's problem. Because the slave already give the ACK to master, this delay should caused by the master, when the master receive the ACK, it is not send the data clock quickly.

    Just from your picture:

pastedImage_1.png

Bit 9 is the ACK point, you can find the slave already give ACK, it is low during 9th clock.

So, maybe you also need to check the master side.

Could you also tell me what the I2C master you are using? You can check that master code, when the master enter read mode, and get the ACK, the wait time between receive ACK and the next Clock sending. As you know, all the clock in the I2C bus is sent by the I2C master.

Wish it helps you!

If you still have question about it, please kindly let me know.

Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 项奖励
回复

3,972 次查看
john_wang1
Contributor I

Hello Kerry,

    My environment is using the MCUXpresso v10.2.1 build and SDK_2.x_MKL27Z256xxx4(Ver:2.4.1 / Manifest Ver:3.3.0).

    I check the SDK driver, fsl_i2c.c. There is no ACK control (TXAK) in "I2C_SlaveTransferHandleIRQ()" when getting the address match status. So the ACK of ID_Read should be the response automatically. Maybe it comes from the SMB FACK function, but I'm not sure. (SMB didn't configure in initial function and the default is 0x00.)

    After I test with changing the code in "I2C_SlaveTransferHandleIRQ()", the delay time can be shorter. So, I believe the delay is caused by the slave code.

0 项奖励
回复

3,972 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi John,

   Thank you for your updated information, you said:"changing the code in "I2C_SlaveTransferHandleIRQ()", the delay time can be shorter."

  Could you tell me what the detail code you have changed? After the change, could you also share the test I2C bus wave? 


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 项奖励
回复

3,972 次查看
john_wang1
Contributor I

Hi Kerry,

   I try to reduce the call function layers, change to access static buffer(not to ptr) for reducing setup time, even to reduce not necessary branch(if/else).

   Project: frdmkl43z_i2c_interrupt_b2b_transfer_slave

   File: fsl_i2c.c

   Function: I2C_SlaveTransferHandleIRQ

   I add some code to approach my I2C master device.

   I will check the input data after addr+w, then to decide output data when addr+r.

0 项奖励
回复

3,972 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi John Wang,

    Thank you for your updated information.

    Today, I have tested the sdk code directly, this is the I2C bus wave:

pastedImage_2.png

  You can find each byte have a little delay, actually, this also relate to the code, as you know, SDK code have called a lot of API.

  This small delay won't influence the I2C usage.

  But if you still want to shorten it, I think, you can use use the register control directly, instead of the API code, register control will save time.

 


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 项奖励
回复

3,972 次查看
ellenlin
Contributor III

Dear Kerry Zhou 員工 ,, 

   Thanks for your checking ~

   Could you help to provide code about " register control directly " Method to test ?

   Thanks a lot !!

0 项奖励
回复

3,972 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi e Lin,

    We don't have the direct official register control I2C slave code.

    But I have finished some code based on the KL26 series by myself, you also can refer to it.

   Just attach some driver for your reference.

 I also attach the interrupt handler for the slave

void I2C1_IRQHandler(void)
{
     volatile unsigned char Dummy;

     
    if(I2C1_S & I2C_S_IICIF_MASK)          
    {
                I2C1_S |= I2C_S_IICIF_MASK;                                             /* ÇåÁãÖжϱêÖ¾                 */  
       if (I2C1_S & I2C_S_ARBL_MASK)                                             /* Çå³ýARBL                     */
       { 
                    I2C1_S |= (I2C_S_ARBL_MASK);
        if (!(I2C1_S & (I2C_S_IAAS_MASK)))                                      /* IAAS ·Ç 1                    */ 
        {
                         return ;
        }    
       }          
          }          
    
    if (I2C1_S & I2C_S_IAAS_MASK)                                             /* µØÖ·´«Êä½×¶Î                 */
    {
                 I2C1_C1 &= ~I2C_C1_TXAK_MASK;                                               
        I2C_S_Sendindex       = 0;                         // ·¢ËͲÎÊýÇåÁã                    
        if (I2C1_S & I2C_S_SRW_MASK)                       //´Ó»ú·¢ËÍģʽ ÓɵØÖ·ºóÃæµÄR/W¾ö¶¨
                    {                                  
            I2C1_C1 |= I2C_C1_TX_MASK;                                        /* ·¢ËÍģʽ                     */  
            I2C1_D = Sensor_Data[I2C_S_Sendindex++];                         /* ·¢Ë͵ÚÒ»¸öÊý¾Ý               */
   
        } 
                    else //´Ó»ú½ÓÊÕģʽ
                    {    
            I2C1_C1 &= ~I2C_C1_TX_MASK;                                       /* ½ÓÊÕģʽ                     */              
            Dummy = I2C1_D ;                                               /* ¶ÁÒ»´Î                       */        
        }
        
    } 
          else 
          {               
        if (I2C1_S & I2C_S_SRW_MASK) // ´Ó»ú·¢ËÍģʽ
                    {
                         if(I2C1_S & I2C_S_RXAK_MASK) //¼ì²âµ½NACK
                         {
                           I2C1_C1 &= ~I2C_C1_TX_MASK; //תΪ½ÓÊÕģʽ
                              Dummy = I2C1_D;
                         }
                         else  //Èç¹ûÖ÷»úACK£¬Ôò¼ÌÐø½ÓÊÕ
                         {
                           I2C1_D = Sensor_Data[I2C_S_Sendindex++]; //·¢ËÍÊ£ÓàÊý¾Ý
                         }
                           
        } 
                    else 
                    {    
            I2C1_C1 &= ~I2C_C1_TX_MASK;                                       /* ½ÓÊÕģʽ                     */
            //GulCounter = 0;                
            Dummy = I2C1_D ;                                               /* ¶ÁÒ»´Î                       */        
        }               
                 
    }    

}     ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Just for your reference, you'd better to refer to the KL43 reference manual check it again.


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 项奖励
回复

3,972 次查看
ellenlin
Contributor III

Dear Kerry Zhou 員工 , 

   Thanks for your help !! we'll try it to solve issue , thanks a lot !!

0 项奖励
回复

3,972 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

Hi e Lin,

   Do you meet any problem with the register control mode?

   Today, I receive you create a case about it, I already take it, actually, it is the same question.

   Do you have tried it? If you meet any problem, just let me know, just as I have told you, we don't have the register control mode directly, just have the SDK sample code.

   If you want I provide the according project, I need time to write the code and do the testing.:)


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 项奖励
回复

3,972 次查看
ellenlin
Contributor III

Dear Kerry Zhou 員工 , 

   ok , i' ll test example code with 2 board , One is I2C Interrupt Master , another one is I2C Interrupt Slave . To check the issue will happen on FSL_I2C_Master sample code or not , Update i ' ll let you know , thanks a lot !!!!

0 项奖励
回复

3,972 次查看
kerryzhou
NXP TechSupport
NXP TechSupport

OK, any updated information is welcome!


Have a great day,
Kerry

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 项奖励
回复

3,972 次查看
ellenlin
Contributor III

Dear Kerry Zhou 員工 , 

   As John Wang Says , Could you provide some advice to help him ?

   I 'll check Example code the same time ~ thanks a lot !!

0 项奖励
回复