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.

[参考译文] TMS320F28386D:CM-I2C 配置为从器件在 SCL 中出现干扰后将 SDA 线路保持为低电平。 如何恢复?

Guru**** 2445440 points
Other Parts Discussed in Thread: TMS320F28386D

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1508123/tms320f28386d-cm-i2c-config-as-slave-holds-the-sda-line-low-after-glitches-in-scl-how-to-recover

部件号:TMS320F28386D

工具/软件:

您好:

我使用的是 TMS320F28386D(下文称为“DSP")“)、该器件在共享总线上配置为 I2C 从器件。 连接管理器 (CM) 通过 I2C (CM-I2C) 接收命令、而 C28x 内核在运行逆变器 (PWM) 的控制环路。

问题:

当逆变器运行时、会将噪声引入环境中。 该噪声有时会耦合到 I2C 总线上。 虽然噪声水平不是很高、但如果噪声尖峰与时钟 (SCL) 的上升沿相一致、则可能会产生错误的时钟边沿。 这些错误边沿有时会被识别为错误数据包、我的软件会检测这些数据包并向主器件报告、从而继续正常运行。

但是、有时 CM 中的 I2C 外设会卡住、从而将 SDA 线路保持为低电平。 发生这种情况时、如果不复位 DSP、系统就无法恢复。

我的问题:
如何在不复位器件的情况下从该卡滞状态恢复 I2C 外设?

我尝试过的方法:

  • 在 SCL 上发送 9 个时钟脉冲(这是释放从器件卡滞的标准)不会恢复总线。

  • 使用调试器 (XDS110 和 CCS)、我切换了 I2C 外设中的“Master Enabled“和“Slave Enabled“位、但这并未释放这些行。

  • 将引脚 104 和 105 的 GPIO 多路复用器配置更改为其默认功能后、会释放 SDA 线路、但将它们切换回 I2C-CM 会再次使 SDA 保持低电平、从而确认外设是问题的根源。

  • 在 I2C 外设上启用主模式并将抗干扰滤波器设置为 8 个时钟似乎可以防止我当前测试中出现问题、但我担心、如果最终产品中环境变得更大、这并不是一种稳健的解决方案。

启用主模式后、我可以监控 SDA/SCL 的繁忙位或状态、并实施看门狗作为权变措施、但不知道如何在应该的看门狗触发时复位外设。

附件是一条逻辑分析仪布线:

  • 蓝色矩形突出显示了带有干扰的放大区域。

  • 顶部迹线是数字采集、底部是模拟采集。

  • 在干扰发生后、SDA 保持在低电平。 多个后续时钟边沿不会导致 CM(从器件)释放 SDA 线。

提前感谢

如果您需要更多信息或测量值、请告诉我。

此致

Agustin J. Gomez

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

    尊敬的 Agustin:

    让我再深入研究一下、明天再联系您。 在此期间、请参阅论坛中有关此主题的类似主题、以获得帮助。  

    此致、

    Aishwarya

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

    尊敬的 Aishwarya:

    我已经检查了多个涉及类似问题的主题、但没有一个与我的具体案例完全匹配。

    我的设置中的主要差异:
    CM-I2C 配置为从模式、并主动将 SDA 线路保持为低电平 元件引起的

    例如、在此主题中: TMS320F28386D:I2C BUS 挂起(SDA 挂起)- C2000 微控制器论坛 — C2000Tm︎ 微控制器 — TI E2E 支持论坛

    在这种情况下、DSP 充当主器件、从器件保持 SDA 线路(根据我的理解)。 如我的初始消息中所述、建议的将 SCL 线切换 9 次的解决方案在我尝试时未能解决问题。

    这是我检查的另一个线程: TMS320F280025:F280025 I2C 从器件 SDA 突然拉至低电平、然后在主机向 F280025 I2C 从器件发送命令期间 SCL 拉至高电平? - C2000 微控制器论坛 — C2000Tm μ︎ 微控制器 — TI E2E 支持论坛

    在此线程中、问题与此类似、因为 DSP 配置为从器件。 但是、它涉及 C28x I2C(而不是 CM-I2C)、我们私下讨论了该解决方案。

    我找不到任何涉及此确切场景的线程。 此时、我怀疑 CM-I2C 硬件(勘误表)中可能有具体错误、不过我希望事实并非如此。

    此致、

    Agustin J. Gomez

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

    Agustin、

    进行 I2C 模块软复位(仅复位外设而不是器件)通常是恢复总线的最佳解决方案。 您是否尝试过此方法而不是复位整个器件?

    您是否还研究了 在发生此干扰时手动发送停止条件来结束事务、然后利用 您前面提到的逻辑来结束 操作并报告给控制器相应地进行处理? 从技术上讲、当 SDA 从低电平变为 高电平且 SCL 为高电平时、这是停止条件。 在产生停止条件后、总线被视为空闲。 不是在这里发生的事情,而是一个尝试的建议。

    我认为、一般来说、您应该考虑 在硬件设置中添加 I2C 干扰滤波器、以保护电路免受外部噪声的影响。  

    此时、我怀疑这可能是 CM-I2C 硬件中的特定错误(勘误表)–不过我希望情况并非如此。

    您指的是勘误表中的哪个错误?  

    此致、

    Aishwarya

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

    尊敬的 Aishwarya:

    进行 I2C 模块软复位(仅复位外设而非器件)通常是恢复总线的最佳解决方案[/报价]

    请告诉我如何复位外设。 我在 CM-I2C 中找不到正确的位。

    您是否也已检查过 在发生此干扰时手动发送停止条件以结束事务

    在这种状态下、在外设已锁定的情况下、我切换了用于控制 ACK 位的位、即寄存器 I2CSACKCTL、位 ACKOVAL 和 ACKOEN、并且没有更改外设的状态。  

    一般来说、您应该考虑 在硬件设置中添加 I2C 干扰滤波器、以保护电路免受外部噪声的影响。  [/报价]

    谢谢、我们将对此进行检查。 我们已经考虑在必要时添加一些电容器。 如前所述、主器件的内部抗干扰滤波器确实有所帮助、但希望为外设再次死亡的情况做好准备。

    这是我的权变措施、因此很明显:

        // Configure as master to use the glitch filter to protect the SCL/SDA lines
        // and avoid I2C peripheral to get stuck
        // The master functionality itself is not used.
        I2C_enableMaster(I2C0_BASE);
        I2C_initMaster(I2C0_BASE,I2C_CLK_FREQ,false);
        I2C_setSlaveAddress(I2C0_BASE,slaveAddress,I2C_MASTER_WRITE);
        I2C_configureMasterGlitchFilter(I2C0_BASE, I2C_MASTER_GLITCH_FILTER_8);
        // Configure as slave - actual use-case:
        I2C_registerInt(INT_I2C0, I2CSlaveISR);
        I2C_enableSlave(I2C0_BASE);
        I2C_setOwnSlaveAddress(I2C0_BASE, I2C_SLAVE_ADDR_PRIMARY, slaveAddress);

    您提到勘误表中的哪个错误?  [/报价]

    我的意思是、一个新错误仍然没有包含在其中。 但是、我希望它不会。

    总结:

    如何对 CM-I2C 进行软复位?

    再次感谢您。

    此致

    Agustin

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

    尊敬的 Agustin:

    对不起,延误,请再给我一天回来给你。

    此致、

    Aishwarya

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

    尊敬的 Rajesh:

    没有问题,它不是紧急的,但重要的。

    当您有解决方案或解决方法时、请告诉我。

    谢谢你。

    此致、

    Agustin

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

    Agustin、

    在硬件方面、您可以考虑在 SDA 和 SCL 线路上添加串联电阻、以帮助滤除串联电阻之外的噪声。  

    在软件方面、您可以实现一个用于监控 I2C 外设状态的软件看门狗。  这也是有关检查 CM I2C BB 的相关主题: TMS320F28388D:CM I2C 读取错误数据。  

    此致、

    Aishwarya

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

    Aishwarya,

    该问题需要的是如何复位外设 CM-I2C。

    不要担心硬件,我们可以处理,我们将添加那些你以前推荐我的扼流圈.

    我总结了解决方法、直到现在、您不会迷路:

    我的应用程序需要从器件配置、但为了避免挂起或从中恢复:

    *我启用主配置以使用干扰滤波器。

    *启用主器件后,我还可以检查总线状态 (BB ),如果它很长时间忙...

    选项 1:我们对 CM-I2C 进行软复位(如何?)

    选项 2:我们重置整个处理器(最差的解决方案)

    现在请记住的主要问题是如何复位 CM-I2C。

    提前感谢

    此致、

    Agustin

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

    Agustin、

    您是否已经尝试使用 driverlib 函数 (I2C_enableSlave、I2C_disableSlave ) 启用和禁用 CM I2C?  这肯定会复位器件。 此外、还有相同的功能可用于启用/禁用控制器。

    上面提供的其他信息是 用于帮助确定何时需要复位的逻辑、不过您似乎已经弄清楚了。

    此致、

    Aishwarya

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

    Aishwarya,  

    这似乎很有趣。 我使用调试器切换了寄存器中的主器件和从器件使能位、但没有任何帮助。 现在我检查了您提到的 driverlib 函数、它们看起来似乎有所不同、它们也会从从控制状态切换“器件激活“位。 让我为此创建一个测试、然后在接下来的几天内回到这个问题上来。 也许是一周的结束。 我会让你知道的。

    再次感谢您、

    此致

    Agustin

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

    Aishwarya,

    今天我花了一些时间来测试它。 这不起作用。

    我移除了干扰滤波器以重现问题。

    void I2CSlave_config (uint8_t slaveAddress){
      //配置为主器件以使用干扰滤波器来保护 SCL/SDA 线路
      //并避免 I2C 外设卡住
       //不使用主功能本身。
       I2C_enableMaster (I2C0_BASE);
       I2C_initMaster (I2C0_BASE、I2C_CLK_FREQ、FALSE);
       I2C_setSlaveAddress (I2C0_BASE、slaveAddress、I2C_MASTER_WRITE);
       // I2C_configureMasterGlitchFilter (I2C0_BASE、I2C_MASTER_glitch_8);
       //配置为从器件 — 实际用例:
       I2C_REGISTERINT (INT_I2C0、I2CSlaveISR);
       I2C_enableSlave (I2C0_BASE);
       I2C_setOwnSlaveAddress (I2C0_BASE、I2C_SLAVE_ADDR_PRIMARY、slaveAddress);
    }

    void I2CSlave_reset (){
       I2C_disableSlave (I2C0_BASE);
       I2C_disableMaster (I2C0_BASE);
       I2C_enableMaster (I2C0_BASE);
       I2C_enableSlave (I2C0_BASE);
    }

    /******************************************************* /

    //在 main.c 中,在一个任务中各有几毫秒

    Volatile bool reset_i2c = false;//使用调试器切换

    作废任务(作废){

    (...)

      if (reset_i2c){
       Reset_i2c = false;
       I2CSlave_reset ();
      }

    (...)

    }

    我只使用从器件配置和主器件配置进行测试、如代码中所示。

    关于如何重置它的另一个建议?

    我在 driverlib 中注意到了新内容:在 i2c.h 中存在寄存器“_write",“,其、其地址与其他寄存器相同、但位含义不同。

    例如:

    #define I2C_O_MCS_WRITE 0x4U // I2C 主器件控制/状态
    #define I2C_O_SCSR_WRITE 0x804U // I2C 从器件控制/状态

    我在 TRM 中未找到它们。 他们在哪里解释?  

    此致、

    Agustin

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

    Agustin、

    很奇怪、我可以联系设计专家。 感谢您的耐心!

    此致、

    Aishwarya

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

    Agustin、

    对延迟表示歉意、仍在等待其他专家的反馈。  

    I2C_enableSlave (I2C0_BASE);

    对延迟表示歉意、仍在等待其他专家的反馈。 可以帮助解决的一件事是在这之后添加延迟(尽管硬件应负责处理)。 另外尝试清除中断状态/标志。  

    此致、

    Aishwarya

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

    尊敬的 Agustin:

    SYSCTL 具有以下可用于复位外设的寄存器。 请尝试一下、让我知道。  

    此致、

    Aishwarya

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

    尊敬的 Aishwarya:

    谢谢你。 这似乎很有希望。 我将尝试 在接下来的几天或几周进行测试、因为我现在正在执行另一项任务。

    我一知道就让你知道了。

    再次感谢。

    此致、

    Agustin

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

    Agustin、

    请随时更新、感谢您的耐心。

    此致、

    Aishwarya

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

    尊敬的 Aishwarya:

    我进行了快速检查、可以确认复位功能正常工作。 谢谢!

    为了完整起见、我在这里留下完整的解决方案。

    首先、问题:

    SDA 线路会卡住、这仍然是 CM 上的 I2C 外设存在的问题。我认为数据表中应明确说明这一点、至少应在勘误表中提及、因为它在实际应用中非常重要。

    当通信期间干扰进入时钟线时、会发生此问题、如我第一个问题的图中所示。 在我的例子中、这些干扰是由电源逆变器开关时的噪声引起的。

    主要问题是、保持 SDA 线不是总线上从器件的预期行为。 如果确实发生了这种情况、发送额外的时钟应该会解决该问题。 在多主系统中、保持 SDA 线将被解释为仲裁丢失、但在这里并非如此、并且系统没有为这种情况做好准备。

    在简单的主器件实现中、当主器件进行写入时、它在最后一个时钟读取总线、需要 ACK/NACK 响应。 如果 SDA 保持低电平、它将被解释为 ACK、因此主器件继续工作、就好像没有任何错误一样。


    预防:
    软件:
    在启用干扰滤波器并在 I2C 外设中启用主器件后、我看到了巨大的改进。 我不将外设用作主器件、但使用它的特性。 在实验室条件下、我无法在启用滤波器的情况下再次重现错误。

    硬件:
    您建议添加与 I2C 输入串联的铁氧体磁珠 (100MHz 处的 1kΩ)。 这也应该有助于防止噪声进入。 也可以添加小电容器、但应将其与总线的其余部分一起进行分析、因为您不希望过多地增加总线电容并降低其速度。


    建议的解决方案:看门狗(计时器)

    1. 如果错误仅在 DSP 被寻址时发生:

      • 在第一个字节中断得到处理后启用计时器、配置为下一个字节到达所需的最长时间(这定义了最小总线频率)。

      • 在每个新字节到达后复位计时器。

      • 检测到停止条件时停止计时器。

      • 在计时器 ISR 中、放入 I2C 复位函数。
    2. 如果在一般性写入总线时发生错误:

      • 启用主器件后、可以检查 BUSY 位、并且可以观察 SDA 和 SCL 的状态。

      • 简单的解决方案是完成一项计算总线繁忙时间的任务。 如果时间超过系统中最长数据包所需的时间、请尝试复位 I2C、以防外设本身保持线路。

      • 这是一个基本的解决办法、所以我希望第一个解决办法就足够了。


    测试:
    我仍然需要通过打开逆变器(产生噪声)并写入总线上的其他器件来测试这些条件。 如果总线没有卡住、则可以实现解决方案 1。
    但是、我担心在寻址阶段、每个器件都会监听错误。 在这种情况下、可能不会触发中断、解决方案 1 不起作用。 也许这两种解决方案应该并行实施。


    以下是初始化和复位函数:

    void I2CSlave_config(uint8_t slaveAddress) {
        // Configure as master to use the glitch filter to protect the SCL/SDA lines
        // and avoid I2C peripheral to get stuck
        // The master functionality itself is not used.
        I2C_enableMaster(I2C0_BASE);
        I2C_initMaster(I2C0_BASE,I2C_CLK_FREQ,false);
        self.slaveAddress = slaveAddress;
        I2C_setSlaveAddress(I2C0_BASE,slaveAddress,I2C_MASTER_WRITE);
        // Remove this for testing.
        // I2C_configureMasterGlitchFilter(I2C0_BASE, I2C_MASTER_GLITCH_FILTER_8);
        // Configure as slave - actual use-case:
        I2C_registerInt(INT_I2C0, I2CSlaveISR);
        I2C_enableSlave(I2C0_BASE);
        I2C_setOwnSlaveAddress(I2C0_BASE, I2C_SLAVE_ADDR_PRIMARY, slaveAddress);
        // (...)
    }
    
    void I2CSlave_reset() {
        SysCtl_resetPeripheral(SYSCTL_PERIPH_RES_I2C0);
        NOP;
        I2CSlave_config(self.slaveAddress);
    }

    我不确定是否需要 NOP、我只是怀疑复位后需要执行一些周期。

    感谢你的帮助。

    此致、
    Agustin J. Gomez