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.

[参考译文] CC3235MODSF:I2C 从设备+睡眠模式唤醒会破坏总线流量

Guru**** 2558250 points
Other Parts Discussed in Thread: SYSCONFIG

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

https://e2e.ti.com/support/wireless-connectivity/wi-fi-group/wifi/f/wi-fi-forum/1050087/cc3235modsf-i2c-slave-sleep-mode-wake-up-corrupts-the-bus-traffic

器件型号:CC3235MODSF
Thread 中讨论的其他器件:SysConfig

在努力解决和克服一系列 CPU 错误后、我们认为我们终于解决了与 I2C 从设备外设相关的所有问题。

现在出现了一个新问题:当 CC3235被唤醒并且正在进行传输(我们有一个 I2C 显示屏需要~30ms 更新)时、出于某种原因、它似乎通过拉低 SDA 线路来破坏传输。

在我们的设置中、我们不使用 SysConfig 初始化对应于 SDA 和 SCL 的引脚(它们保留为输入 HIGHZ)、I2C 外设初始化后、我使用 MAP_PinTypeI2C 将引脚分配给 I2C 外设。

此时、我使用专用 GPIO、该 GPIO 在我们处于唤醒状态时配置了上拉电阻、在睡眠期间可看到下拉电阻->睡眠进入/退出。  

问题是、当 WiFi 芯片唤醒主设备和 LCD 之间的 I2C 通信时、偶尔(也很少)会受到干扰。

下面是400s 的记录、其中包含一个测试软件、用于强调 LCD 更新、CC3235除了由 NWP 精心编排的通信外、不处理任何其他通信:

放大有问题的部分

使用示波器检查信号后发现无硬件问题。

当我保持 WiFi 处于唤醒状态(禁用睡眠策略)时、错误永远不会发生。
当我启用睡眠模式但未在 postNotify 回调中初始化 I2C 时、永远不会发生错误。

因此、在这种状态下、我们将问题缩小到仅作为 CC3235问题、并与唤醒时的 I2C 初始化相关。
请注意、当我们唤醒时、我们不会启动传输、也不会期望接收到传输。
我们只是将 I2C 初始化为从器件(清空 FIFO、复位 DMA 等)。

现在、这对我们来说是一个障碍。 我们在该器件和 I2C 从器件上遇到了很多问题、这是我们最后一次尝试使用该器件。

是否有人可以向我们指出正确的方向、说明如何将 I2C 从设备与 GPIO 一起正确初始化?

或者、在这种情况下、在唤醒期间会发生什么可能的错误?

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

    您好!

    请详细说明以下内容:

    • 谁是主人,谁是奴隶?
    • 您是否意味着您从 SDA 上获取的一些数据会断开、因为 CC3235会在从 LPDS 唤醒期间将该引脚拉至高电平?
    • I2CCC32XX_postNotify 在唤醒期间被调用并且不执行任何  MAP_PinTypeI2C 设置、这是 I2C_Open()的一部分完成的。 您是否正在使用 postNotify 回叫进行呼叫? "当我启用睡眠模式但不在 postNotify 回调中初始化 I2C 时"到底意味着什么?

    Shlomi

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

    我们有一个 STM32、它是 I2C 主设备。 CC3235显然是从器件。 LCD 显然也是从设备。

    CC3235无法将 SDA 拉至高电平? I2C 总线是一条开漏总线。 当线路唤醒时、它似乎会在某个时间点将其拉低。

    CC3235没有 I2C 从设备驱动程序。 很遗憾、我不得不编写自己的代码。 在此论坛上、您可以找到我提供的几个"已关闭并已解决"论坛条目、其中报告了过去1.5年中与此相关的几个 CPU 错误(非现有 FIFO 空触发器、错误 DMA 触发器、完成时双 DMA 中断等)。

    不管怎样、在这种情况下、大部分时间都能正常工作、但我们在系统中添加了 LCD、很明显、我们再次遇到了问题。
    这是 init 函数:

    static void I2CCC32XX_initHw_test(I2C_Handle handle)
    {
        uint32_t ulRegVal;
        uint32_t key;
    
        key = HwiP_disable();
    
        Power_setDependency(PowerCC32XX_PERIPH_I2CA0);
    
        //Take I2C hardware semaphore to prevent NWP from accessing I2C.
        //
        //This is done in initHw() instead of postNotify(), so the
        //hardware sempahore is also taken during open().
        ulRegVal = HWREG(COMMON_REG_BASE + COMMON_REG_O_I2C_Properties_Register);
        ulRegVal = (ulRegVal & ~0x3) | 0x1;
        HWREG(0x400F7000) = ulRegVal;
    
        PRCMPeripheralReset(PRCM_I2CA0);
    
        // In case of app restart: disable I2C module, clear interrupt at NVIC
        MAP_I2CMasterDisable(I2CA0_BASE);
        MAP_I2CSlaveDisable(I2CA0_BASE);
    
        // Flush the FIFOs. They must be empty before re-assignment
        MAP_I2CTxFIFOFlush(I2CA0_BASE);
        MAP_I2CRxFIFOFlush(I2CA0_BASE);
    
        I2CMasterGlitchFilterConfigSet(I2CA0_BASE, I2C_MASTER_GLITCH_FILTER_32);
    
        // Set TX and RX FIFOs to slave mode
        MAP_I2CTxFIFOConfigSet(I2CA0_BASE, I2C_FIFO_CFG_TX_SLAVE_DMA);
        MAP_I2CRxFIFOConfigSet(I2CA0_BASE, I2C_FIFO_CFG_RX_SLAVE_DMA);
    
        // Clear ALL interrupts
        MAP_I2CSlaveIntClearEx(I2CA0_BASE, 0xFFFFFFFF);
    
        // Don't change the sequence of these 2 function calls. They operate on SCSR and it is write only!
        MAP_I2CSlaveInit(I2CA0_BASE, SLAVE_I2C_ADDR);
        MAP_I2CSlaveFIFOEnable(I2CA0_BASE, I2C_SCSR_TREQ | I2C_SCSR_FBR);
    
        //MAP_I2CSlaveIntEnable(I2CA0_BASE);    // slave int data
        //MAP_I2CSlaveIntEnableEx(I2CA0_BASE, I2C_SLAVE_INT_STOP);
        //MAP_I2CSlaveIntEnableEx(I2CA0_BASE, I2C_SLAVE_INT_RX_FIFO_REQ);
        //MAP_I2CSlaveIntEnableEx(I2CA0_BASE, I2C_SLAVE_INT_TX_FIFO_EMPTY);
    
        MAP_I2CSlaveIntEnableEx(I2CA0_BASE, I2C_SLAVE_INT_TX_DMA_DONE);
        MAP_I2CSlaveIntEnableEx(I2CA0_BASE, I2C_SLAVE_INT_RX_DMA_DONE);
    
        dma_rx_irq_clear();
        dma_rx_setup();
    
        dma_tx_disable();
        dma_tx_irq_clear();
    
        uint8_t pin, mode;
    
        pin = I2CCC32XX_PIN_04_I2C_SDA & 0xff;
        mode = (I2CCC32XX_PIN_04_I2C_SDA >> 8) & 0xff;
        MAP_PinTypeI2C((unsigned long)pin, (unsigned long)mode);
    
        pin = I2CCC32XX_PIN_03_I2C_SCL & 0xff;
        mode = (I2CCC32XX_PIN_03_I2C_SCL >> 8) & 0xff;
        MAP_PinTypeI2C((unsigned long)pin, (unsigned long)mode);
    
        HwiP_restore(key);
    }

    通知回调函数已注册到电源驱动程序、并根据 I2C 主设备和 SPI 示例调用此函数。

    int I2CCC32XX_postNotify_test(unsigned int eventType, uintptr_t eventArg, uintptr_t clientArg)
    {
            I2CCC32XX_initHw_test((I2C_Handle) 0);
    
        return (Power_NOTIFYDONE);
    }

    因此、这2个函数足以重现问题。

    我的意思是"当我启用睡眠模式但不在 postNotify 回调中初始化 I2C 时":
    1) 1)在应用程序开始时调用 Power_enablePolicy
    2) 2)在 notify_test 函数中对"I2CCC32XX_iniHW_test"的上述调用未添加注释(调用从编译中删除)

    因此、当启用睡眠策略且没有对 I2C 的调用时、一切正常。
    当我重新添加函数调用并且 CC3235被唤醒时(同样、不通过 I2C 与 CC3235进行通信时、它会被唤醒!) 然后总线受到干扰、似乎是由于发生了 SDA 低拉电流。

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

    您好!

    那么、为了在这里对齐、您是否声明从 LPDS 唤醒后、CC3235 I2C 从设备将处理 SDA 线路并中断 LCD 从设备?

    这种中间/瞬时电流是否 使 I2C 初始化完成后一切恢复正常?

    Shlomi

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

    是的、WAKEUP / i2c 初始化会导致通信中断。 大多数时候 LCD 受到影响的原因是它需要大约30ms 的连续数据传输。 在某些情况下、当无线网络在传输过程中唤醒时、似乎会将 SDA 线路拉低。 但并非总是如此、因此一定会出现问题。

    在大多数情况下、拉线后似乎恢复正常、但我需要进一步测试、我认为我们看到一些情况下、它不 返回、但我不确定问题是否是由从器件未完成传输和拉时钟线引起的 或主器件中的异常将线路保持为低电平。

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

    将 GPIO 12和13作为 GPIO 的输入类型添加到 SysConfig 中、现在我们观察到的问题不会发生。

    是否有人能够重现此问题?

    是否需要 GPIO 电源依赖性( 调用 Power_setDependency (PowerCC32XX_Periph_GPIOA0)),并且 GPIO 驱动程序在器件唤醒时实际上会执行该操作?
    如果是、为什么这在任何 I2C SPI TI 驱动程序中都不存在/或者是否在后台执行了进一步的操作、我可能会错过?

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

    您好!

    当您通过 SysConfig 设置 GPIO 时、I2C 是否正常工作? 因为这些 GPIO 用于您的 I2C。

    如果答案是肯定的、那么可能是当芯片唤醒时、在很短的时间内、只有在您将其实际设置为 I2C 时、才会设置芯片。

    power_setDependency()用作 I2C_Open ()的一部分,但与 PowerCC32XX_Periph_I2CA0搭配使用。

    可能是将其设置为 GPIO 输入会使其工作、直到 I2C 再次初始化。

    当然、这只是一种缓解或权变措施。

    再深入了解一下、我注意到生成了一个文件 ti_drivers_config.c

    在此文件中、您可以找到 作为电源域一部分的 parkInfo 初始化。

    查看我一侧的示例:

    PowerCC32XX_ParkInfo parkInfo[]={
    /* PIN 暂留状态引脚别名
    -------- ---------------------- -------- *

    {PowerCC32XX_PIN01、PowerCC32XX_weak 下拉_STD}、// GP10 *
    {PowerCC32XX_PIN02、PowerCC32XX_weak 下拉_STD}、// GP11 *
    {PowerCC32XX_PIN03、PowerCC32XX_weak 下拉_STD}、// GP12 *
    {PowerCC32XX_PIN04、PowerCC32XX_weak 下拉_STD}、// GP13 *
    {PowerCC32XX_PIN05、PowerCC32XX_weak 下拉_STD}、// GP14 *
    {PowerCC32XX_PIN06、PowerCC32XX_weak 下拉_STD}、// GP15 *
    {PowerCC32XX_PIN07、PowerCC32XX_weak 下拉_STD}、// GP16 *
    {PowerCC32XX_PIN08、PowerCC32XX_weak 下拉_STD}、// GP17 *
    {PowerCC32XX_PIN13、PowerCC32XX_weak 下拉_STD}、
    {PowerCC32XX_PIN15、PowerCC32XX_weak 下拉_STD}、// GP22 *
    {PowerCC32XX_PIN16、PowerCC32XX_weak 下拉_STD}、/* TDI */
    {PowerCC32XX_PIN17、PowerCC32XX_weak 下拉_STD}、/* TDO */
    {PowerCC32XX_PIN18、PowerCC32XX_weak 下拉_STD}、// GP28 *
    {PowerCC32XX_PIN19、PowerCC32XX_weak 下拉_STD}、/* TCK *
    {PowerCC32XX_PIN20、PowerCC32XX_weak 下拉_std}、/* TMS *
    {PowerCC32XX_PIN21、PowerCC32XX_weak 下拉_STD}、// SOP2 *
    {PowerCC32XX_PIN29、PowerCC32XX_weak 下拉_STD}、
    {PowerCC32XX_PIN30、PowerCC32XX_weak 下拉_STD}、
    {PowerCC32XX_PIN45、PowerCC32XX_weak 下拉_STD}、// GP31 *
    {PowerCC32XX_PIN50、PowerCC32XX_weak 下拉_STD}、// GP00 *
    {PowerCC32XX_PIN52、PowerCC32XX_weak 下拉_STD}、// GP32 *
    {PowerCC32XX_PIN53、PowerCC32XX_weak 下拉_STD}、// GP30 *
    {PowerCC32XX_PIN55、PowerCC32XX_weak 上拉_std}、/* GP01 */
    {PowerCC32XX_PIN57、PowerCC32XX_weak 上拉_std}、// GP02 *
    {PowerCC32XX_PIN58、PowerCC32XX_weak 下拉_STD}、// GP03 *
    {PowerCC32XX_PIN59、PowerCC32XX_weak 下拉_STD}、// GP04 *
    {PowerCC32XX_PIN60、PowerCC32XX_weak 下拉_STD}、// GP05 *
    {PowerCC32XX_PIN61、PowerCC32XX_weak 下拉_STD}、// GP06 *
    {PowerCC32XX_PIN62、PowerCC32XX_weak 下拉_STD}、// GP07 *
    {PowerCC32XX_PIN63、PowerCC32XX_weak 下拉_STD}、// GP08 *
    {PowerCC32XX_PIN64、PowerCC32XX_weak 下拉_STD}、// GP09 *
    };

    如您所见、默认值为  PowerCC32XX_weak pull_down_STD、它可以解释您在案例中看到的 PD。

    您一侧的 GPIO12和 GPIO13设置是什么?

    如果您将其修改为 PowerCC32XX_weak PULL_UP_OPENDRAIN 会怎样?

    Shlomi

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

    是的、I2C 正常工作、实际上只有使它正常工作。 从技术上讲、它将重新配置引脚、因为我的驱动程序通知回调(恢复 LPDS)在 GPIO 恢复后被调用、因此初始化 I2C 外设的 INIT 函数也将重新配置相应的 GPIO 并将其映射到 I2C 外设。

    在我们的案例中、这些引脚上的 GPIO 停驻是"未使用"的(它们保留在 PowerCC32XX_NO_PULL_HIZ 配置中)。 是否建议将其用于驻车总线引脚?

    我尝试为相应的 GPIO 端口添加 setDependency 调用、但这没有帮助。 到目前为止、只有 GPIO 配置实现了这一目的。
    在大多数情况下、更令人困扰的是什么? 我有一个压力测试、其中主器件不断更新 LCD、在 I2C 总线上施加80%的负载、因此 CC3235唤醒会破坏流量的可能性很高、但当发生此问题时、很少发生、需要几分钟时间 (使用逻辑分析仪检查)在 LCD 更新传输过程中有数千次 CC3235唤醒事件没有任何问题。

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

    我认为值得尝试将这两条特定的线路与 I2C (PU 和 OD)放起来。 当平台进入 LPDS 时、这些应该会生效。 如果其他 I2C 客户端也是以 pu 为单位、则不应消耗电流、但让我们将功耗从公式中抽出一分钟、然后检查其是否正常工作。

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

    刚刚尝试过。 驻车设置不是解决方案。 删除 了 SysConfig 中 GPIO 的初始化、并将其设置为仅停在上拉代码中(当然在应用程序中 、我的驱动程序会初始化 GPIO)。 遗憾的是、问题会发生。 因此、这与进入睡眠或处于睡眠状态无关。 它与唤醒相关。

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

    您好!

    我对它进行了更多的研究。

    可能是在 LPDS 退出期间至少需要3mSec、尽管引脚的默认状态为 HiZ、但该特定 GPIO 显示为 PD。 我想知道时钟引脚 GPIO12上是否也会发生这种情况?

    如果不是、这可能与 GPIO13也是一个可能的唤醒引脚这一事实有关。

    我将测试的最终选项:

    • 移除所有可能的唤醒源 GPIO、查看其是否有用
    • 如果可能、将 I2C 引脚更改为#1和#2 (GPIO10/11)、并查看其是否起作用(这些不是唤醒源)

    如果这些仍然不起作用、您是否可以将建议的缓解措施用作工作站?

    此致、

    Shlomi

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

    我不记得在时钟引脚上看到过它、可能还存在它。 我认为、上述代码和3个 Launchpad (每100ms 1个主设备1个从设备和1个进入/退出睡眠模式)可以重现此问题。

    据我所知、模块只能将1个引脚配置为唤醒引脚、我们目前正在使用 GPIO2。

    测试听起来很棒、 请随时向我们更新您发现的内容!

    目前、我们还没有处于可以将引脚更改为不同 GPIO 的设计阶段、并且由于不了解导致问题的原因、也不了解 TexasInstruments 支持的明确陈述、如果其他引脚上不能发生这种情况、我就没有什么意见了 尝试更改我们的设计。

    建议的变通办法似乎至少现在起作用,直到我们有进一步的问题,我将保持不变。