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.

[参考译文] TM4C1294NCPDT:I2C 总线卡滞。 需要在运行时从 I2C 切换到 GPIO,然后再切换回 I2C

Guru**** 2536790 points
Other Parts Discussed in Thread: TM4C1294NCPDT, TCA9535

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1074318/tm4c1294ncpdt-i2c-bus-stuck-need-switch-from-i2c-to-gpio-then-back-to-i2c-during-runtime

部件号:TM4C1294NCPDT
“线程”中讨论的其它部件: TCA9535测试

尊敬的支持团队:

我们使用 TM4C1294NCPDT 作为 I2C 主控制器与 TCA9535 (I2C IO 扩展器) Salve 通信。

我们正在陷入 I2C 总线卡住的境地。

为了让总线“解卡”,我们将在对从设备执行任何 I2C 操作之前切换时钟线路多次(18),以使其确信最后一个事务已完成。

我们遵循以下顺序

  1. 禁用 I2C 外围设备(SystlPeripheralDisable (I2C)),
  2. 启用 GPIO 外设(CtlSysPeripheralEnable(GPIO),
  3. 使用 SCL 和 SD 作为数字输出,
  4. 启用 I2C 外围设备(SystlPeripheralEnable(I2C)

但仍无法与 I2C 从 TCA9535建立连接。 原因可能是什么?

在运行期间,我们可以从 I2C 模式切换到 GPIO 模式,然后再切换回 I2C 模式吗? 这种方法的正确方法是什么?
还是有其他方法来解决这种情况?

谢谢,致以最诚挚的问候。
普拉什特·奈克

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

    普 拉什特您好,

    是的,您可以在它们之间切换您的常规流程似乎正常,但我必须看到您的配置代码才能确定两者。 您可以随意发布它。

    尝试向 I2C 从设备发出启动和停止条件,然后再发出一个停止条件。 这在过去对客户非常有用: https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/954162/tm4c1294ncpdt-problems-resetting-i2c-communication/3541214#3541214

    除此之外,还让我知道公共汽车是如何悬挂的(是奴隶把一根针固定在低位等),这样我就可以看到其他的想法。

    此致,

    拉尔夫·雅各比

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

    这种切换 SCL 以解除 I2C 总线阻塞的方法是否始终有效?

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

    你好,拉尔夫

    感谢您的反馈。

    实际上,我们在 SCL\SDA 较高的健康 I2C 总线上尝试这种方法,因为错误(由于噪音)很少发生。
    这是正确的测试方法吗? 或者我们应该重现错误,然后将虚拟时钟应用到 I2C 从控制器上吗?

    谢谢,致以最诚挚的问候。
    普拉什特·奈克

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

    您好普拉什特,

    我会重现错误来测试它,我看不到在健康的公共汽车上尝试它的相关性,然后假设它可以从从属控制器的 SCL 低的情况中恢复。 使用切换的想法是,当从属设备试图将其拉低时,强制信号偏高,以便看到启动/停止,从而清除挂断,从属设备释放 SCL。 如果没有处于该状态的从属设备,您将无法验证其是否完全适合您的设备。

    此致,

    拉尔夫·雅各比

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

    你好,拉尔夫,

    我是普拉什特的同事。 我们测试健康巴士的目的是确保我们的逻辑运作。 我们需要在复杂的多线程环境中适应比特撞击逻辑。

    正如普拉什特所提到的,错误情形非常罕见,不能经常再现。 一旦我们知道逻辑有效,我们将花足够的时间对其进行验证,以确保它在实际错误情形中的每一次都能正常工作。

    下面是我们在通电时使用的 I2C 配置代码

    /*启用外设*/
    MAP_SystlPeripheralEnable (sysctl_Periph_I2C2);
    MAP_SystlPeripheralReset (sysctl_Periph_I2C2);

    halReturn = CheckI2c 外围设备就绪状态(sysctl_Periph_I2C2);
    IF (HAL_Eok == halReturn)

    MAP_GPIOPinConfigure (GPIO _PN5_I2C2SCL);
    MAP_GPIOPinConfigure (GPIO _PN4_I2C2SDA);
    MAP_GPIOPinTypeI2CSCL (GPIO _PORTN_BASE,GPIO _PIN_5);
    MAP_GPIOPinTypeI2C (GPIO _PORTN_BASE,GPIO _PIN_4);

    MAP_I2CMasterGlitchFilterConfigSet(I2C2_BASE,I2C_MASTER_L闪烁 过滤器_8);

    UINT32 numOfI2cClocks = 0x7D;//当 I2C 以400KHZ 运行时,计算为5ms
    MAP_I2CMasterTimeoutSet(I2C2_BASE,numOfI2cClocks);

    I2C_INIT();

    -----

    哈勒尔
    CheckI2c 外围设备就绪状态(连接 UINT32外围设备)

    HalErr halReturn = HAL_ENOK;
    const UINT32 sleep_Time_in_ticks = 1;
    const UINT8 MAX_TRUST_COUNT = 5;
    UINT8国别指数=1;
    bool readyStatus = MAP_SystlPeripheralReady (外围设备);

    While ((!readyStatus)&&
    (Max_retry_count >条修订国家索引)

    task_Sleep (睡眠时间刻度);
    返修国家索引++;
    readyStatus = MAP_SystlPeripheralReady (外围设备);
    }

    IF (!readyStatus)

    GPIO _log_basic (GPIO _Pack_ID,log_class_warning,
    (“%s:I2C 外围设备未就绪。”,__function__);
    }
    否则

    halReturn = HAL_Eok;
    }
    返回 halReturn;
    }

    -----

    哈勒尔
    HalI2cOpen (const HalI2CBoardIndex 索引,
    科斯特哈利克帕拉姆
    HalI2CHANDLE*手柄)

    OSA_Assert (NULL !=句柄);

    HalErr halReturn = IsValidOpenParameters (索引,
    参数);
    IF (HAL_Eok == halReturn)

    I2C_Params halI2CActualParams;
    I2C_Params_init(&halI2CActualParams);
    halI2CActualParams.transferMode = static_cast<I2C_TransferMode>(param.transferMode);
    halI2CActualParams.bitrate = static_cast<I2C_bitrate_(param.bitrate_);
    halI2CActualParams.transferCallbackFxn = I2cTivaCallbackFxn;

    I2C_HANDLE 实际手柄= I2C_OPEN (索引,
    halI2CActualParams);

    -----

    HalI2CParams i2cParams;
    i2cParams.bitrate = HAL_I2C_400kHz;
    i2cParams.transferMode = HAL_I2C_MODE_callback;
    HalErr halResult = HalI2cOpen (HAL_Board_I2C2,
    i2cParams,
    &m_I2CHandle);

    -----

    感谢您的支持。

    谢谢和问候

    阿希吉

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

    您好,Abhijit,

    [引用 userid="391954" url=~ë/support/icles/arm-based 微处理器-组/基于 ARM 的微控制器/f/arm-based 微控制器- forum/1074318/tm4c1294ncpdt-i2c-bus-stick-need-switch-from-i2c-the-the-the-co-the-back - ip-exvalidation - the-back -我们将在每个运行时的 IPL[3977921-the-vic]中知道,并确保每个运行时错误在每个操作时间内都能在 i79921]3977921[#772c-ipultrat]

    已理解。 我会实施逻辑来禁用 I2C 外设,启用 GPIO 作为数字输出,将 IO 切换为 启动和停止条件的位感叹号,将 GPIO 转回 I2C 配置并重新启动 I2C 外设。

    我只是想清楚一点,我只能肯定这种技术适用于每个 I2C 从设备。 我强烈希望它能起作用,但我无法保证 I2C IO 扩展器将如何响应这种尝试清除错误的方式。 但我绝对建议尝试,就我的经验而言,这是解决此类问题的最佳方法。

    此致,

    拉尔夫·雅各比

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

    你好,拉尔夫,

    感谢您的回复。

    我们在回叫模式下使用 I2C 驱动程序; 在使用位感叹法执行从属重置后,我们观察到写入操作失败,回叫功能中的布尔参数返回 false。 我们如何了解失败的原因? 任何 API 都能让我们了解实际原因吗?

    谢谢和问候

    阿希吉

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

    您好,Abhijit,

    我不完全清楚您使用的是什么 API。 I2C 传输 API 应始终返回成功。 您能否发布存在问题的特定代码段并报告返回 false 的参数? 然后,我可以查看我们的 TI-RTOS 驱动程序文档/源代码,以进一步提供指导。

    此致,

    拉尔夫·雅各比

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

    你好,拉尔夫,

    我们正在回叫模式下使用 TI-RTOS I2C 驱动程序。 我正在谈论 I2C_CallbackFxn。

    谢谢和问候

    阿希吉

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

    您好,Abhijit,

    我知道您正在使用 TI-RTOS API,请发布完整的代码段,以便我可以看到确切的序列和使用的参数等

    I2C_CallbackFxn 不是 TI-RTOS 随附的 TIA-RTOS 用于 TIA-C 的 API,因此它特定于您的系统。  

    此致,

    拉尔夫·雅各比

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

    你好,拉尔夫,

    请查看我之前共享的代码片段。 在 I2C_OPEN 通话期间,我们提供回叫功能(I2ctivaCallbackFxn)。 调用 I2C_TRANSFORT()后,通过回调函数接收到的结果值为 false。

     谢谢和问候

    阿希吉  

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

    您好,Abhijit,

     那么,I2C_OPEN 的回报是什么? 如果其为 NULL,则它不会成功,这将有助于缩小问题的范围。

    如果成功,我看不到 I2ctivaCallbackFxn 的实际代码或任何使用 I2C_TRANSFER 的代码, 因此我 无法更深入地查看。

    此致,

    拉尔夫

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

    你好,拉尔夫,

    下面是 I2C 回调代码;我们有多个软件抽象功能;因此存在一些复杂性。 粗体行中的结果赋值是我们在上面的一个图层所检查的结果,该图层的值为 false。

    /*
    每个 I2C 事务结束时,TIVA 库将调用*
    *
    无效
    I2ctivaCallbackFxn (I2C_HANDLE HANDLE,/*TIC !ORG#011允许在全局范围内使用 C 函数*/
    I2C_Transaction * i2cTransaction,
    布尔结果)

    OSA_Assert (NULL !=句柄);
    OSA_Assert (NULL != i2cTransaction);
    OSA_Assert (NULL != i2cTransaction ->arg);

    HalI2CBoardIndex i2cIndex;
    HalI2CHandle 当前 Handle = reInterl解释_CAST <HalI2CHandle>(句柄);
    HalErr halReturn = GetPeripheralIndex (当前处理器,
    i2c 索引);
    IF (HAL_Eok == halReturn)

    UINT32 currTransactionIndex =*(static_cast<UINT32*>(i2cTransaction ->arg));
    OSA_Assert (DetailedTransactionInfo[i2cIndex].maxTransactionCount > currTransactionIndex);
    DetailedTransactionInfo[i2cIndex].resultPtr[currTransactionIndex]= static_cast<BOOL>(结果);
    IF (!结果)

    GPIO _log_basic (GPIO _Pack_ID,log_class_warning,
    (在事务%u",__function__,i2cIndex,currTransactionIndex 中,I2C 外围设备索引%u 的 I2C 事务失败。);
    }

    /*如果最后一个事务已完成,则调用应用程序回拨*/
    IF(DetailedTransactionInfo[i2cIndex].maxTransactionCount ==(当前 TransactionIndex +1 ))

    OSA_Assert (NULL != DetailedTransactionInfo[i2cIndex].appCallbackFn);
    /*呼叫应用程序回叫*/
    DetailedTransactionInfo[i2cIndex].appCallbackFn(DetailedTransactionInfo[i2cIndex].argine);

    /*清除处理以外的事务详细信息,如果有的话,这些信息对于下一个事务是不需要的*/
    DetailedTransactionInfo[i2cIndex].maxTransactionCount = 0;
    DetailedTransactionInfo[i2cIndex].argument = NULL;
    DetailedTransactionInfo[i2cIndex].appCallbackFn =空;

    /*释放锁定信号*/
    OSA_Assert (NULL != DetailedTransactionInfo[i2cIndex].semHandle);
    semaphore_post (DetailedTransactionInfo[i2cIndex].semHandle);
    }
    }
    否则

    GPIO _log_basic (GPIO _Pack_ID,log_class_warning,
    (“%s:无法获取 I2C 外围设备索引。”,__function__);
    }
    }

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

    您好,Abhijit,

    我看到了软件抽象层的复杂性。 我不是 RTOS 专家,所以这种复杂性使我更难在这里提供任何值得注意的东西。

    也许我们需要朝着另一个方向迈出一步。 在软件方面, I2C_TRANSFER 是了解错误的关键所在,我还没有看到错误是如何使用的,而是试图评估我们可能能够以更简单的方式跟踪这一点。 是否可以使用 o 范围或逻辑分析器查看 I2C 线路?

    然后,我们将能够看到实际的数据传输尝试,并了解未正确发送的内容。 例如,如果未发送任何内容,则表明 I2C 总线未正确重新配置。

    考虑到软件的复杂性,我想或许可以从设备的实际操作中重新回到硬件方面,这将有助于指导您重新访问正确的代码段。

    此致,

    拉尔夫·雅各比