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);
}