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.

[参考译文] MSPM0L1106:I2C 器件外设访问问题

Guru**** 2553260 points
Other Parts Discussed in Thread: MSPM0L1306

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1565349/mspm0l1106-i2c-device-peripherals-access-issue

器件型号:MSPM0L1106
主题:MSPM0L1306 中讨论的其他器件

工具/软件:

尊敬的团队:

根据 CCS 创建的示例 i2c_controller_rw_multibyte_fifo_poll_LP_MSPM0L1306_nortos_ticlang、我创建了两个 I2C 函数、源代码附加在 i2c.7z 中:

- I2cOperationStatus[t I2C_Read (uint8_t devAddr、uint8_t regAddr、uint8_t *dataBuf、uint8_t length)

- I2cOperationStatus[t I2C_WriteByte ( uint8_t devAddr、uint8_t regAddr、uint8_t dataByte )

我们的产品中有两个具有不同器件地址的 I2C 外设。

当我使用函数 I2C_READ() 从其寄存器中读取芯片 ID 时、可以正确读取芯片 ID。

之后,当我使用函数 I2C_WriteByte () 来初始化寄存器时,它将失败,波形变为:

其中橙色线表示 SDA、蓝色线表示 SCL。

我的问题是:

1.问题的原因是什么?

2.发生这种情况时,如何恢复 I2C 模块以使软件正常工作? 目前、重新引导设备是恢复设备的唯一方法、但问题将再次出现。

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

    尊敬的团队:

    我再次将 i2c 源代码附加到 zip 文件中。

    e2e.ti.com/.../1234.i2c.zip

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

    您好 Alan、

    让我帮您检查一下。

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

    您好 Alan、

    我在您的代码中没有看到任何明显的内容。  实际上、读取和写入函数在发送器件地址和数据方面是相同的、因此工作方式应该相同。  SDA 变为低电平、但 SCL 并不告诉我开始位是生成的、但没有加载目标地址、考虑到它在 I2C_READ () 函数中有效、这真的很奇怪。

    首先,尝试在 I2C_WriteByte () 末尾的 return 语句上设置一个断点。  运行您的代码。  CPU 是否到达 return 语句?  如果不是、请尝试向上移动、在每个 if() 语句中设置断点、并查看 CPU 是否在这些位置停止。

    如果您从未访问过任何这些位置、我们来尝试一下... 打开项目启动文件“startup_mspm01306x..."</s>“ “并在 while () 语句中设置断点。  运行代码、看到失败后、暂停调试器。  可能是那个循环中的代码吗?  如果没有、您能说明它在哪里吗? 请注意、您可能必须设置编译器优化级别= 0、才能在启动文件中设置断点。

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

    1) 我注意到这个代码是它为每个操作启用/禁用 I2C 单元;在我的经验中,这是非常不寻常的。 I2C_ReadByte 也没有真正地等待 Rx 操作完成(停止需要有限的时间)。 erratum I2C_ERR_05 建议在禁用 I2C 单元之前确保 I2C 单元没有执行任何操作;它还描述了  与您观察到的情况相匹配的症状。 [参考勘误表 (SLAZ741D) 第 13 页]

    快速(?) 实验将删除 DL_I2C_disableController () 调用,并查看行为是否发生变化。  

    2) 一般而言、这种情况(SCL 高电平、SDA 卡在低电平)的解决方法是在 SCL 上发送 (8+1) 个时钟脉冲[参考 I2C 规范 (UM10204 修订版 7) 第 3.1.16]节。 它并不总是起作用、但通常会起作用。 否则、唯一的办法是对从器件进行复位或下电上电。

    通常、发生这种情况是因为主器件(无论出于何种原因)之前已停止以中字节向从器件发送器发送时钟(要发送的位为 0);从器件一直将 SDA 保持为低电平、并且在没有更多时钟的情况下无法继续、并且主器件无法发出启动或停止、因为 SDA 保持为低电平。 发送时钟脉冲允许从器件完成字节、然后下一位看起来像 NACK。

    -----

    加上 Dennis 建议的调试。

    ——

    您能告诉我们这是什么从器件吗? 也许有一条线索。

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

    尊敬的 Dennis Lehman:

    感谢您的支持。 在我的测试中、I2C_WriteByte() 将在发生错误时返回、并且不会死循环、因为我用于没有无限循环的循环。

    所以 I2C_WriteByte() 的退出点是 I2C_ERR_DEV_ADDRESS_WR_TIMEOUT、如下所示在我的代码中所示:

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

    您好、Bruce McKenney:

    感谢您的支持。 请允许我回答你的每一句话。

    我注意到这段代码是它为每项操作启用/禁用 I2C 单元;在我的经验中、这种情况非常少见。

    答: 我们的产品由电池供电,禁用 I2C 单元的目的是降低 MCU 功耗,因为 I2C 操作并不频繁。

    I2C_ReadByte 也不会真正等待 Rx 操作完成(Stop 需要有限的时间)。 erratum I2C_ERR_05 建议在禁用 I2C 单元之前确保 I2C 单元没有执行任何操作;它还描述了  与您观察到的情况相匹配的症状。 [参考勘误表 (SLAZ741D) 第 13 页]

    Ans :正如在示例代码中一样,它在每个状态检查上都使用无限 while 循环。 我将这些无限 while 循环更改为有限的 for 循环。 原因是当我们的生产线中的 I2C 硬件出现问题时、我们不希望器件挂起或由于看门狗而继续重新启动。 在此错误中、for 循环的循环计数增加、问题仍然存在。

    a quick(?) 实验将删除 DL_I2C_disableController () 调用,并查看行为是否发生变化。  [/报价]

    ANS : 删除  I2C_READ() 和 I2C_WriteByte() 中的 DL_I2C_disableController() 后、I2C 将正常工作。 此外,我还测试使用回 while 循环,而不是 在 I2C_READ () 和 I2C_WriteByte () 中的 for 循环加上 DL_I2C_disableController (), I2C 也正常工作。 背后的原因是什么?

    2) 一般而言、这种情况(SCL 高电平、SDA 卡在低电平)的解决方法是在 SCL 上发送 (8+1) 个时钟脉冲[参考 I2C 规范 (UM10204 修订版 7) 第 3.1.16]节。 它并不总是起作用、但通常会起作用。 如果没有、唯一的办法是重置从器件或对从器件执行下电上电。

    答:在我们的电路中、2 个 I2C 设备的电源不能断开、即它们不能进行下电上电。 对于 LED 驱动器、它有一个 RESET 引脚、但发生 I2C 问题时器件的复位无法恢复。

    您能告诉我们这是什么从设备吗? 可能有线索。

    - LED 驱动器: Awinic AW9523B.

    - PMIC: Laiyuan ICP1106DA.

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

    1) 删除 disable () 调用 fixed(避免)的事实,该条件确实指向 I2C_ERR_05 作为罪魁祸首。

    I2C_READ() 在读取最后一个字节后禁用 I2C 单元、这(考虑到 CPU 与 I2C 速度的差异)可能是 I2C 单元完成事务之前的“很长时间“。 您可以通过添加来获得良好的结果  

    > while(!(DL_I2C_getControllerStatus(I2C_INST)& DL_I2C_CONTROLLER_STATUS_IDLE));

    disable() 调用前的或等效项。 [我的经验:我没有发现任何 business/busy_bus/idle 完全可靠的完成指示。 I 最终得到 ((RXDONE/TXDONE) 或 (ERR)))、然后是空闲。]

    2) 是否是在 I2C_READ 调用中寻址的 LED 驱动程序? 可能是、由于 I2C_ERR_05 影响主器件侧、因此复位从器件不会完成任何任务。 (I2C_ERR_05 的数量也可能比勘误表文本中显示的数量更多。) 给定的权变措施等同于“不要这样做“。

    【编辑:更正了拼写错误。】

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

    好的、我来看看是否可以在 Launchpad 上进行设置、看看会发生什么情况。

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

    您好 Alan、

    很抱歉、我花了一天左右的时间来完成所有设置。  我从您的同一个 SDK 控制器示例开始、并将其添加到了 I2C.c 代码中。  我不得不填写几个缺少的变量/定义来编译代码(缺少.h 文件)。  在 SDK 示例中,我替换了以下代码段来重复调用你的 I2C_WriteByte ()。  在 I2C 总线的另一端、我有相应的 SDK 目标示例代码、对其进行了修改、仅读取控制器发送的任何内容、以上就是全部内容。  这样得到一个确认来显示一切都是好的。


        reg = 0;
        data = 0;
        while(1)
        {
            I2C_WriteByte(  I2C_TARGET_ADDRESS,  reg++,  data-- );
            DL_Common_delayCycles(1000);
        }

    我运行了一段时间、观察使用逻辑探针的 I2C 总线、我看到“reg"递增“递增和“数据“永远递减... 因此、该函数没有明显的问题。  

    如果有用、我上传了 CCS 项目。

    e2e.ti.com/.../E2E_5F00_I2C_5F00_controller_5F00_MSPM0L1306_5F00_debug.zip

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

    感谢您的设置。 对于我的实验、我:

    1) 重新将启用循环添加到中

    2) 更改了 main 以执行 I2C_READ、然后执行 I2C_WriteByte(中间有 DELAY_CYCLES (100))

    3) 将 I2C 减慢至 50kHz、以增加 CPU 与 I2C 速度比

    4) 使用 Adafruit MPR121 分线板运行(碰巧在我的 gizmo 盒子的顶部)

    ->然后我(立即)看到了原始帖子中显示的症状。 然后、我:

    5) 在 i2c_read () 中的标签 exit_on_err 之后添加了我上面建议的代码行(为空闲旋转)。

    ->现在我看不到症状(可能是跑步 15 分钟)。

    【编辑:轻微澄清】

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

    另一个观察结果:在故障情况下、一旦 I2C_WriteByte ()(重新)启用 I2C 单元、SDA 就会变为低电平、而不是在(下一个)事务启动时。

    勘误表说明使其听起来像是在 SDA 恰好为低电平时“冻结“I2C 单元(此处并非如此)的问题。

    似乎有一些状态、从设备在停止完成和空闲之间的操作来看、 当设备重新启用时、它会卡住并“恢复生命“(脱离上下文)。

    【似乎他们可以这样说。】

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

    谢谢 Bruce 的帮助,在这方面帮助了零;)

    我会尝试你的建议。

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

    如果有用,这是我的 main() 循环:

        while(1)
        {
            errcode = I2C_Read(  I2C_TARGET_ADDRESS,  0x5C, &data,  1 );  // CDT config should be 0x24 after reset
            DL_Common_delayCycles(100);
            errcode = I2C_WriteByte(  I2C_TARGET_ADDRESS,  0x77,  0x00 ); // MPR121 GPIO Enable -> all-0 is benign
            DL_Common_delayCycles(100);
        }

    这是 I2C_READ 的尾端(移除旋转循环以重新引入故障):

    exit_on_err:
    //while ( !(DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE) );
    #if CYCLE
    	DL_I2C_disableController( I2C_INST );
    #endif
    	I2C_FlushFIFO();										// try to flush the FIFO in case of error.
    
    	return status;
    }

    我不会费心使用示波器迹线、因为它们与原始帖子中的迹线无法区分。

    【编辑:轻微澄清】

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

    Bruce — 我还没有机会尝试一下。

    Alan — 禁用 I2C 外设不会像使用适当的电源策略(睡眠模式)那样影响此器件的电流消耗。

    回答: 删除  I2C_READ () 和 I2C_WriteByte () 中的 DL_I2C_disableController () 后、I2C 工作正常

    此时、如果您可以无故障实现 I2C 通信、我建议将 I2C 保持启用状态。  如果您确实感到担心、请使用适当的高分辨率仪表或设备来测量子 uA、并将 M0 置于 STANDBY0 或 1 中(启用 I2C)、但不进行通信并测量电流。  在禁用 I2C 的情况下重复此操作、并比较电流。  “你说什么?

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

    Dennis:谢谢你们的组织。

    Alan:我同意 Dennis 的观点、即让 I2C 保持启用状态可以避免您的症状、并且您仍然可以通过启用/循环来获得太多收益。

    也就是说:我现在相当相信、只要确保(上面的步骤 5)I2C 单元在禁用之前完全空闲、就可以继续执行启用/循环。

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

    您好 Alan、

    让我们知道这是如何为您解决Slight smile

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

    您好、Dennis、Bruce、

    非常感谢您的支持。 我非常感谢你的两项努力。

    由于项目进度紧张、我很抱歉无法及时回复。 是的,在我发现删除  DL_I2C_disableController () 将改善问题后,我立即开始在 I2C 上进行开发和测试。 但我总是跟踪你的答复。

    阅读完所有的回复后,我添加了代码以等待 I2C 的空闲状态 ,然后在 I2C_READ () 和 I2C_WriteByte () 上禁用 I2C 外设,并在昨天重新测试了它们。 他们现在正在工作。  Thumbsupμ s

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

    很棒的消息!

    我们只是想确保它正常工作。

    再次感谢您的帮助 Bruce!

    我会继续标记这个已解决。  如果您对此主题有其他问题或疑问、可以在 30 天内发布新帖子。