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.

[参考译文] AM2434:I2C 超时-繁忙位卡住-如何清除?

Guru**** 2439560 points
Other Parts Discussed in Thread: AM2434

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1232331/am2434-i2c-timeout---busy-bit-stuck---how-to-clear

器件型号:AM2434

您好!

我正在 LP-AM2434上使用 I2C0在 延迟环路中读取 I2C 外设(AD9542)的状态。

I2C 传输定期超时:看似会检查 I2C Busy 位的 I2CControllerBusBusBusy 函数始终返回 BUSY 状态。

如何清除此位和/或复位总线? 我不在乎之前的交易-我只是想进行一笔新的交易。

仅供参考、我将调用 I2C_RecoverBus、然后在循环开始时执行100us 的延迟、但这没有帮助。

谢谢、Steve

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Steve、您好!

    此 I2C 句柄卡在忙模式下的行为不是预期行为。 如果操作不正确、可能会导致 I2C 配置出现一些问题。

    您能否通过共享您所处的示例和 MCU_PLUS_SDK 版本来帮助我在最终重现问题。

     I2C_IRQSTATUS_RAW 的第12位提供总线忙状态、但它是只读类型、对其进行写入将不产生影响、因此该位不能直接清零

    此外、您是否可以尝试将延迟时间增加到250-500us 之类。

    此致。

    ~Shaunak

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shaunak:

    我使用的是 SDK 8.06和 clang 3.0.0 (尽管 SDK 8.04和8.05中存在该问题)。

    (简化的)伪代码为:

    device.I2cHandle = I2cHandle;
    I2C_Transaction_init (&device.i2cTransaction);
    device.i2cTransaction.targetAddress = targetAddress;

    device.i2cTransaction.TIMEOUT = 10000U;

    while (1)

    {

    I2C_RecoverBus (I2cHandle、I2C_DELAY_SMALL);

    ClockP_usleep (500);

    pdocity->i2cTransaction.writeBuf =&txBytes[0U];
    pdocity->i2cTransaction.writeCount = 2u;
    pdocity->i2cTransaction.readBuf = pValue;
    pdocity->i2cTransaction.ReadCount = 1U;

    I2C_TRANSMIT (PDevice->I2cHandle、&PDevice->i2cTransaction);

    ClockP_usleep (10000);

    我已经增加了睡眠后恢复到500 us。

    仅供参考、 因为我们知道 AM 的 I2C 边沿与 I2C 不兼容("太快")、所以我已经在 AM2434 I2C0和 AD9542之间添加了一个 PCA9517A I2C 缓冲器。 下面是 模拟和数字信号完整性的典型 I2C 事务跟踪(PCA9517A 的任一端)。  

    谢谢、Steve

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Steve、您好!

    根据伪代码、我尝试 在最终重现此问题、但无法观察到相同的行为、您能否共享 debug.out 文件?  

    同时、您可以尝试执行 I2C 软件复位吗?

     /*将 i2c 置于复位/禁用状态*/
      I2CControllerDisable (object->baseAddr);

     /*执行软件复位*/
      I2CSoftReset (object->baseAddr);

     /*启用 i2c 模块*/
     I2CControllerEnable (object->baseAddr);

    此致、

    Shaunak

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shaunak:

    可悲的是、添加这些调用导致了"仲裁丢失"错误。

    史蒂夫

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Steve、您好!

    您能否共享 project.c 文件? 由于没有直接的方法来清除总线繁忙位、我想尝试找到一个解决方案。

    此致、

    Shaunak

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shaunak:

    不幸的是、出于复杂性和机密性的原因、我无法分享来源。

    什么因素会导致 I2C 控制器的 BUSY 位卡滞?

    谢谢、Steve

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Steve、您好!

    不再现问题很难得出可靠结论、我尝试根据伪代码进行再现、但找不到总线忙位卡住。

    如果您只关心接下来的交易、您可以采用更安全的方法。

    if(I2CControllerBusBusy(baseAddr) == 1) /* check if bus is busy */
    {
        /* If busy, Wait for the transaction to complete */
        status = I2C_waitForBb(baseAddr, timeout);
    }
    else
    {
        /* If timeout, then reset the I2C IP */
        status = I2C_resetCtrl(I2C_Handle)
    }

    我仍在研究可能导致该位卡在繁忙模式的原因。 如果有任何更新、我会回复给您。

    此致、
    Shaunak

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Steve、您好!

    1.当发生故障条件时、您可以分享 I2C 总线的示波器屏幕截图吗?

    2.您能 将该电路板和 AD9542引脚相连吗?这能帮助我们更好地理解设置吗?

    3.您使用的是什么版本的 AM243x LP、比如 E3A 或者 E3B?

    4.如果您可以删除代码的专有部分、并仅将其减少为有助于我重现问题的 I2C 代码、我将能够为您提供更好的支持。

    此致、
    Shaunak

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shaunak:

    哦、我的代码基于 SDK 文档:

    但是、我现在已将其分解、并将重试:

    int32_t AD9542_ReadRegister(AD9542_Device *pDevice, uint16_t registerAddress, uint8_t *pValue)
    {
        int32_t         status = SystemP_SUCCESS;
        int32_t         count = 5; // If there is an I2C Transfer error then retry 5 times
        uint8_t         txBytes[sizeof(registerAddress)];
    
        // address is high byte, low byte order
        txBytes[1U] = registerAddress & 0xFF;
        txBytes[0U] = registerAddress >> 8;
    
        // prepare to write
        pDevice->i2cTransaction.writeBuf = &txBytes[0U];
        pDevice->i2cTransaction.writeCount = sizeof(registerAddress);
        pDevice->i2cTransaction.readCount = 0U;
    
        // write
        status = I2C_transfer(pDevice->I2cHandle, &pDevice->i2cTransaction);
    
        if (SystemP_SUCCESS == status)
        {
            // prepare to read
            pDevice->i2cTransaction.writeCount = 0U;
            pDevice->i2cTransaction.readBuf = pValue;
            pDevice->i2cTransaction.readCount = sizeof(*pValue);
    
            // read
            status = I2C_transfer(pDevice->I2cHandle, &pDevice->i2cTransaction);
        }
    
        if (SystemP_SUCCESS != status)
        {
            // I2C not successful, print error
            AD9542_DebugPrintI2CStatus("AD9542_ReadRegister", registerAddress, status);
        }
    
        return status;
    }
    

    史蒂夫

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Steve、您好!

    上述重构是否解决了此问题?

    如果没有,请回答我上一次答复中的问题。

    此致
    Shaunak

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shaunak:

    重构代码整夜运行(大约每秒30-40次交易)。 虽然这不是决定性的,但这是最长的时间,没有 超时一个数量级,所以 这是非常令人鼓舞的。

    但是、我只是这样做、因为这是"SDK 告诉我要做的"。 请按要求修改。

    谢谢。

    史蒂夫