This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/AM5726: I2C timing issue

Part Number: AM5726

Tool/software: TI-RTOS

Hi Champs,

We would like to confirm AM5726 I2C driver code.

We have some I2C tlow time shortage issue when we use I2C Fs mode.

Software :\ti\pdk_am57xx_1_0_9\packages\ti\csl\src\ip\i2c\V2\priv\ i2c.c I2CMasterInitExpClk function

document:  [Table 24-7. HS I2C Register Values for Maximum I2C Bit Rates in I2C F/S, I2C HS Modes]

F/S mode must be output 400khz.To getting this value, we have to set sysClk=96Mhz, internalclk=9.6Mhz,outputclk=400khz. 

In this case , divisor on the I2CMasterInitExpClk value is 24.

However, when we use this divisor value =24, register setting area code will be bellow.

   HW_WR_REG32(baseAddr + I2C_SCLL, 5U);

  HW_WR_REG32(baseAddr + I2C_SCLH, 7U)

According to above TRM, when we use Fs mode , I2C_SCLL must be 7U, I2C_SCLH must be 5U. So, SCLL register value is lower as theoritical value.

So, this tlow term is lower as expect.

Could you please this I2C source code if our understand is correct ?

/*******************************************************************************

*                       API FUNCTION DEFINITIONS

*******************************************************************************/

/*TI_INSPECTED 8 D : MISRAC_2012_R_2.2

*"No problem in redefining variable without being referenced after it's

* definition" */

void I2CMasterInitExpClk(uint32_t baseAddr,

                         uint32_t sysClk,

                        uint32_t internalClk,

                         uint32_t outputClk)

{

   uint32_t prescalar;

   uint32_t divisor;

   uint32_t div_h, div_l;

   uint32_t actIntClk = 0U;

 

   /* Iterate through the valid pre-scalar values until one is found that is

     * the closest match to the desired internal clock speed

     */

   for (prescalar = 0U; prescalar < I2C_MAX_CLK_PRESCALAR; prescalar++)

   {

       /* Calculate the actual speed that would be used for the current

         * pre-scalar value, and if it is within 1 MHz of the desired value then

         * we have a match

         */

       actIntClk = sysClk / (prescalar + 1U);

 

       if (actIntClk <= (internalClk + I2C_INTERNAL_CLK_STEP))

       {

           break;

       }

   }

 

   HW_WR_REG32(baseAddr + I2C_PSC, prescalar);

 

   /* Calculate the divisor to be used based on actual internal clock speed

     * based on pre-scalar value used

     */

   divisor = actIntClk / outputClk;

   if ((outputClk * divisor) != actIntClk)

   {

       /* Round up the divisor so that output clock never exceeds the

         * requested value if it is not exact

         */

       divisor += 1U;

   }

 

   /* Split into SCK HIGH and LOW time to take odd numbered divisors

     * into account and avoid reducing the output clock frequency

     */

   div_h = divisor / 2U;

   div_l = divisor - div_h;

 

   HW_WR_REG32(baseAddr + I2C_SCLL, div_l - 7U);

 

   HW_WR_REG32(baseAddr + I2C_SCLH, div_h - 5U);

}

  • The RTOS team have been notified. They will respond here.
  • Hi,

    I looked at the code you mentioned:

    void I2CMasterInitExpClk(uint32_t baseAddr,
    uint32_t sysClk,
    uint32_t internalClk,
    uint32_t outputClk)

    Where you have sysClk = 96,000,000 (96M), internalClk = 9,600,000 (9.6M) and outputClk = 400,000 (400K). The first round of the code search from 0 to 255 for the pre-scalar, and this is 9 to be programmed into I2C_PSC field. So 96M/(9+1) = 9.6M. This is OK.

    Then, divisor = 9.6M/400K = 24, so div_h = 12 and div_l = 12 as well. For programming them into SCLH and SCLL, if you look at the registers in Table 24-74. I2C_SCLH:

    7:0 SCLH Fast/standard mode SCL high time RW 0x00
    The value of the bit field is automatically increased by 5.

    And Table 24-72. I2C_SCLL
    7:0 SCLL Fast/standard mode SCL low time RW 0x00
    The value of the bit field is automatically increased by 7.

    So, we program SCLH = 12-5 = 7. SCLL = 12-7 = 5. This is also what the code does. From Table 24-6. HS I2C tLOW and thighValues of the I2C Cloc, you can see that when calculate Tlow, this "7" is added back: (I2Ci.I2C_SCLL[7:0] SCLLbit field value + 7) x I2Ci_INTERNAL_CLK period

    Going back to the Table 24-7, I thought they made a typo. The SCLL should be 5 and SCLH should be 7.

    Regards, Eric
  • Hi
    Thanks for your reply. I understand this is TRM typo. Could you please update new TRM ?
    However, "Tlow" period seems short when we see scope. Do you think this is another reason ?

    If this is not "typo", above phenomenon can explain. but, if this is "typo" on the TRM, I can't understand this phenomenon.

    Regards,
    Kz777
  • Hi,

    The issue is discussed offline. "Based on what I’m seeing in the I2C IP spec, I agree that Table 12-329 appears to have an error for the Fast Mode settings. SCLL should be 5, and SCLH should be 7. However, I am also confirming this with our documentation team, who would have created the table."

    Regards, Eric