AM625-Q1: I2C exception causes RTOS crash

Part Number: AM625-Q1

Preface: External watchdog is used to feed dogs in RTOS tasks. During troubleshooting the issue of abnormal reset, it was found that I2C communication abnormalities can cause reset. The following is detailed information on simulation debugging.
I2C communication exception caused program crash, interrupt continues to I2C_lld_targetIsr, unable to enter task function, all tasks starved to death.

As shown in the above figure, there is another strange thing, why does the value of object ->current Transaction ->controller Mode equal 0x96 enter the else branch?

and then

The software is configured as a controller and the code has not been modified to a target anywhere.
Why is it that the value bit of I2C_CON register [10] MST becomes 0 and the device becomes the target?

  • 您好,

    已经收到了您的案例,调查需要些时间,感谢您的耐心等待。

  • 更新信息。

    发现编译器开启优化功能后会导致以上问题,编译器优化设置如图:

    把编译器优化关掉后,没有复现问题,关编译器设置如图:

    但是我们的项目工程不开优化的话,栈会溢出,请问有没有解决办法。

  • 您好,

         从上面看,似乎在使用 -O1 优化级别时会失败。或者这是因为 -flto 优化?

         你能尝试不同的优化级别,比如 -O2 吗?

         1.3.7. Optimization Options — TI Arm Clang Compiler Tools User's Guide

  • 我们换了一块新板子进行测试,发现无论哪种优化等级都复现不了上述内容。

    但是程序偶发i2c通信异常在i2c_v0_lld.c的2176行里一直循环,等不到总线busy释放。用逻辑分析仪看,SDA和SCL均已拉高。

    图示在等bbtimeout减到为0。

    请问有无方法规避这个问题。

    CCS版本为12.7.0,sdk版本为mcu_plus_sdk_am62x_10_00_00_14。

  • 您好,

    但是程序偶发i2c通信异常在i2c_v0_lld.c的2176行里一直循环,等不到总线busy释放。

    您是否配置了I2C的超时值?超时的默认值是永远等待。因此,它将等待直到中断原始寄存器中的BB位被清除或超时发生。

  • 这里的超时时间不是我能配置的,是sdk代码里面写死的。sdk版本是mcu_plus_sdk_am62x_10_00_00_14。

    在最新版本的sdk这个地方并没有改动,如下图:

  • 这里的问题我重新更新下状态,这里是直接XDS110 debug去看的,配置成了主机但是复现故障异常的时候一直进从机的中断,最后定位为定义了NUL的宏值为0#define NULL         ((void) 0),也许某个地方指针越界了。屏蔽以后没有复现过上述问题。但是在I2C_waitForBb函数里面死等总线释放busy的状态这里,帮我看下有没有办法规避,因为SDA和SCL我用逻辑分析仪看都为高了,但是总线busy没释放。

  • 补充上述,最新mcu sdk版本是mcu_plus_sdk_am62x_11_01_00_16

  • 您好,

    但是在I2C_waitForBb函数里面死等总线释放busy的状态这里,帮我看下有没有办法规避,因为SDA和SCL我用逻辑分析仪看都为高了,但是总线busy没释放。

    在配置I2C参数时,您还可以配置此超时值。

    请参考以下代码。

    尝试一下在配置超时值,并更新结果。

  •  您好,这里的超时时间一直都有配置的,值为0x100。

    这里的超时值作用不在上述问题那里,而是在i2c_v0.c第506行,如下图:

  • 您好,

          是的,可以看到在 I2C_waitforbb() API 中超时设置没有效。

          I2C_lld_primeTransferIntr() API 内部调用了 I2C_waitforbb() API,并传入了 I2C_WAIT_FOREVER 的超时值

          您能试着用 I2C_DELAY_MED 值来设置超时并更新结果吗?

           请参见下面的图片。

           

  • 这样的话,得自己改sdk代码了。

  • 您好,

    我使用例程ipc_rpmsg_echo_linux_am62x-sk-lp_m4fss0-0_freertos_ti-arm-clang修改的代码如图所示:

    SDK版本:mcu_plus_sdk_am62x_10_00_00_14,CCS版本:Code Composer Studio 12.7.0。

    发现I2C异常时,会偶发进来HwiP_hardFault_handler函数:

    想请教下,哪些条件会进来HwiP_hardFault_handler函数。

  • 您好,

         那么,代码现在不再卡在总线忙位以进行清除。相反,它会引发异常。

         您能逐步调试,并检查在调用哪个函数后会引发异常吗?

  • 您好,

         那么,代码现在不再卡在总线忙位以进行清除。相反,它会引发异常。

        您能逐步调试,并检查在调用哪个函数后会引发异常吗?

  • 太难定位了,代码如上述截图,已经相当简单了,我断点打在sdk的函数里面几乎复现不了问题,单步调试也不复现。可能需要一个完整的连续的过程,而不是断断续续的过程,才好复现。

  • 我封装了一个很简单的i2c写函数如下图,在其他.c定义,main函数里面调用。

    i2c异常时候还是会进入I2C_lld_targetIsr,此时没开优化,还是在例程ipc_rpmsg_echo_linux_am62x-sk-lp_m4fss0-0_freertos_ti-arm-clang上做的修改。配置时选择的是主机。想请教一下是什么原因,

    我查看了芯片手册如下图,译文是:当传输器检测到它在总线上呈现的高信号被低信号推翻时,它会切换到目标接收机模式。不清楚是不是这个原因。

    If two or more controller transmitters start a transmission on the same bus almost simultaneously, an arbitration procedure is invoked. The arbitration procedure uses the data presented on the serial bus by the competing transmitters. When a transmitter senses that a high signal it has presented on the bus has been overruled by a low signal, it switches to the target receiver mode, sets the arbitration lost (I2C_IRQSTATUS_RAW[0] AL) flag, and generates the arbitration lost interrupt. I2C Arbitration Between Controller Transmitters shows the arbitration procedure between two devices. The arbitration procedure gives priority to the device that transmits the serial data stream with the lowest binary value. If two or more devices send identical first bytes, arbitration continues on the subsequent bytes.

  • 您好,I2C的问题,在I2C_transfer函数不返回I2C_STS_SUCCESS的时候,我是先调用Drivers_i2cClose再调用Drivers_i2cOpen后,其实异常可以恢复,暂时解决问题了。只要之后不会进HwiP_hardFault_handler和一直进I2C_lld_targetIsr,就OK了。进HwiP_hardFault_handler和一直进I2C_lld_targetIsr的可能原因还麻烦帮分析一下。

  • 您好,

    进HwiP_hardFault_handler和一直进I2C_lld_targetIsr的可能原因还麻烦帮分析一下。

    当控制器在目标模式而不是控制器模式下操作时,会调用 I2C_lld_targetIsr API。您是否正在配置 I2C 以在目标模式下操作?     

  • 您好,没有配置成目标模式,看我之前的截图(如下),我是在例程ipc_rpmsg_echo_linux_am62x-sk-lp_m4fss0-0_freertos_ti-arm-clang上做的修改。截图已经是完整的代码了。默认配置如下,全是控制模式(主机)不是目标模式。

    另外,我使用的ide的版本是Code Composer Studio 12.7.0,Call Stack View在哪里可以看?对了,我想看优化后和未优化生成固件的差异,请问有没有生成汇编文件的方法,看看优化后和未优化生成的汇编代码的差异。

  • 您好,

    默认配置如下,全是控制模式(主机)不是目标模式。

    配置是正确的,并且I2C以控制器模式运行。

    仍然不确定为什么CPU正在执行I2C_lld_targetIsr,因为这个API应该在I2C处于目标模式时被调用。

    你可以通过在I2C_lld_targetIsr API处暂停CPU来重新确认,如果MST位的值被设置,那么I2C就是在控制器模式,否则是在目标模式。

    调用堆栈视图可以在 CCS 的调试视图中查看,一旦核心停止运行。

    您可以比较优化和未优化固件的 *map 文件以查看差异。

    您可以启用选项以保留编译期间生成的所有文件。要启用此选项,请导航至项目属性 -> 构建 -> Arm 编译器 -> 高级选项 -> 控制选项。

  • 您好,

    默认配置成主机,我交替把sda和scl短接到地,模拟故障现场,会进来从机的中断,配置也变为了从机。

     另外,*map 文件只是看内存的分布,看不出实际逻辑的差异,又该怎么比较。

    周一我看看把工程的应用代码删了,上传工程,给你看看代码,程序只配置成了主机的。没有地方改为从机。

  • 您好,

    默认配置成主机,我交替把sda和scl短接到地,模拟故障现场,会进来从机的中断,配置也变为了从机。

     另外,*map 文件只是看内存的分布,看不出实际逻辑的差异,又该怎么比较。

    周一我看看把工程的应用代码删了,上传工程,给你看看代码,程序只配置成了主机的。没有地方改为从机。

  • 6661.ipc_rpmsg_echo_linux_am62x-sk-lp_m4fss0-0_freertos_ti-arm-clang.zip

    上传工程使用SDK的版本为:mcu_plus_sdk_am62x_10_00_00_14

    IDE版本:Code Composer Studio 12.7.0

    调试器:XDS110

    以上工程,配置成主机(控制模式),交替把I2C的SDA和SCL短接到GND(模拟故障),会自动变为从机(目标模式)。

    工程是开了优化的。

    没开优化是进来HwiP_hardFault_handler,如下图片所示:

  • 您好,

    调查需要些时间,感谢您的耐心等待。