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.

[参考译文] App_shutdownNetworkStack 函数未正常运行。MCU-PLUS-SDK - AM243X:App_shutdownNetworkStack 函数。

Guru**** 2686715 points

Other Parts Discussed in Thread: SYSCONFIG, AM2431

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1570007/mcu-plus-sdk-am243x-the-app_shutdownnetworkstack-function-is-not-functioning-properly

器件型号: AM243X - MCU-PLUS-SDK
Thread 中讨论的其他器件: SysconfigAM2431

工具/软件:AM243X-EVM

您好:

我目前正在使用 AM243x EVM 测试 icssg 的双 MAC 功能。

两个以太网端口都在使用中、系统基于 FreeRTOS。

在最简单的示例 icssg tcpserver 中、app_main.c 文件内的 App_shutdownNetworkStack () 函数存在于 appMain 函数内。

但是、它位于一个无限循环之下、因此实际上永远不会执行。

对于我正在开发的功能、在某些情况下、我需要关闭 lwip 栈。

我修改了代码以在特定条件下退出 while (1) 循环、然后执行 App_shutdownNetworkStack ()。

static void App_shutdownNetworkStack()
{
    for (uint32_t netifIdx = 0U; netifIdx < ENET_SYSCFG_NETIF_COUNT; netifIdx++)
    {
        LwipifEnetApp_netifClose(hlwipIfApp, NETIF_INST_ID0 + netifIdx);
    }
    return;
}

但是、此功能存在以下问题:

1.在此函数中调用的 LwipifEnetApp_netifClose 函数调用 nettif_remove。

netif_remove 函数检查 LWIP 的核心锁。

因此、直接调用该函数会使 MCU 根据置位进入无限循环。

因此、我按如下方式修改了该函数。

static void App_shutdownNetworkStack()
{
    sys_lock_tcpip_core();  // Add for netif_remove
    
    for (uint32_t netifIdx = 0U; netifIdx < ENET_SYSCFG_NETIF_COUNT; netifIdx++)
    {
        LwipifEnetApp_netifClose(hlwipIfApp, NETIF_INST_ID0 + netifIdx);
    }
    
    sys_unlock_tcpip_core();    // Add for netif_remove
    return;
}

2.调用修改后的函数后,两个函数中的第一个元素似乎被正常删除。

然而,当删除第二个嵌套时,由于断言,它会进入一个无限循环。

第二个 netiF_remove 进入无限循环的原因可以在 MCU+SDK lwip2enet.c 文件内的 Lwip2enet_close 函数中找到。

此函数的第一部分如下所示。

void Lwip2Enet_close(Lwip2Enet_Handle hLwip2Enet, struct netif *netif)
{
    Lwip2Enet_assert(NULL != hLwip2Enet);

    /* Stop and delete the tick timer */
    ClockP_stop(&hLwip2Enet->pacingClkObj);
    ClockP_destruct(&hLwip2Enet->pacingClkObj);

    Lwip2Enet_netif_t* pInterface = Lwip2Enet_getInterfaceObj(hLwip2Enet, netif);
    
    .....
}

此函数停止和释放与 hLwip2enet 句柄关联的 pacingClkObj 的时钟。

问题是 hLwip2enet 句柄不是按每个子句分配的。 此句柄在 LWIP 中显示为单个实例。

**如果已经分配了 hLwip2enet、Lwip2enet_allocateObj 函数不会分配额外的句柄。

`,第二个` netiF_remove `在第一个` netiF_remove `期间已删除` pacingClkObj `hLwip2enet`的 pacingClkObj 时调用。

此时、由于 pacingClkObj 不再有效、因此断言会导致无限循环。

请修复此器件。

此外、如果在下一个 SDK 版本中反映此问题之前可以实施权变措施、请告知我。

此致、

Jinwon Jang

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

    尊敬的  Jinwon Jang:

    这是我们在 LwIP 接口的功能集中发现的一个已知问题。 我们正在努力解决这个问题。 目前有部分实现可供您在设置中进行测试以处理此问题。 我附加了一个补丁文件来实现相同的目标。

    请注意、与 正确处理标志相关的补丁中仍然存在一些问题。 这只是一个参考设计、就是这样 不是生产就绪型产品 集成到最终产品中的 TI 控制器代码。

    如果您在验证此实施时遇到任何问题、请告知我们。

    e2e.ti.com/.../0001_2D00_all_2D00_socs_2D00_LwIP_2D00_Enet_2D00_Fix_2D00_LwIP_2D00_close_2D00_sequence.patch

    此致、
    Teja。

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

    尊敬的 Teja:

    感谢您的及时回复。

    我正在编写、因为我在应用您附加的修补程序文件时遇到问题。

    在 appmain.c 中、有对 killFlag 函数的调用。

    但是、找不到 killFlag 函数、从而导致编译错误。

    您能解释一下这个函数的作用吗?

    此致、
    Jinwon Jang

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

    尊敬的  Jinwon Jang:

    请让我在我的最后检查一下,并发送给你更新的补丁。 由于接下来的 2 天是在印度度假、请在星期一或之前回复。

    感谢您的耐心等待、

    此致、
    Teja。

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

    尊敬的 Teja:

    我仍然没有收到您上次说您会发送的更新补丁。

    请告诉我何时可以期待它。

    感谢您的帮助。

    此致、

    Jinwon Jang

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

    尊敬的  Jinwon Jang:

    首先、对拖延表示歉意。 我在另一个内部承诺中工作。  

    进入 Killflag 函数后、它会设置轮询功能的关闭功能。 您可以通过在$(MCU_PLUS_SDK)/source/networking/enet/core/sysconfig/networking/.meta/enet_cpsw/templates/enet_lwipif.c.xdt 中(就在 LwipifEnetApp_析 构 PollTask 函数之前)添加以下代码来启用它。

    void KillFlag (LwipifEnetApp_Handle handle)
    {
        LwipifEnetApp_Object* pObj = (LwipifEnetApp_Object*) handle;
        pObj->task.pollTask.shutDownFlag = true;
    }

    这将解决编译问题并启用功能。 如有任何其他疑问、请告知我。

    此致、
    Teja。

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

    尊敬的 Teja:

    感谢您的答复。

    即使在应用您提供的补丁后、结果也保持不变。
    删除第二个主题时、问题仍然发生在之前遇到问题的同一位置。

    要再次总结问题的原因:

    1. App_shutdownNetworkStack() 函数调用 LwipifEnetApp_netifClose() 传递函数 Netif 通过 for 循环打开、并尝试全部关闭。
    2. LwipifEnetApp_netifClose() 函数调用 netif_remove() 测量输出。
    3. netif_remove() 函数可删除 Netif 最后调用在中注册的函数 Remove_callback ( LWIPIF_LWIP_stop() 功能)。
    4. LWIPIF_LWIP_stop() 函数调用 lwip2enet_close () 测量输出。
    5. lwip2enet_close () 函数停止和析构 hLwip2enet->pacingClkObj (计时器)。
    6. hLwip2enet 不会为每个单独分配 Netif 。 即使有两个也是如此 netifs 仅添加一个 hLwip2enet (处理程序)已分配。 (请参阅 Lwip2enet_allocateObj ()  功能)
    7.因此,当 lwip2enet_close () 函数的初始化函数来关闭第二个函数 Netif 、它将尝试停止 hLwip2enet->pacingClkObj
    8.不过、 hLwip2enet->pacingClkObj 就已经删除了 Netif 从而导致发生断言。

    虽然只使用一个角子应该没问题,但使用两个角子时,这个序列显然有问题。

    请查看并修复此器件。

    谢谢你。

    此致、
    Jinwon Jang

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

    尊敬的 Teja:

    打开调试程序 Lwip2 Enet_Close () 我在代码中发现了一个严重错误。
    此误差源于 LWIPIF_LWIP_stop() 函数将错误的句柄传递给 Lwip2 Enet_Close () 测量输出。

    static void LWIPIF_LWIP_stop(struct netif *netif)
    {
        Lwip2Enet_Handle hLwip2Enet;
    
        /* Get the pointer to the private data */
        hLwip2Enet = (Lwip2Enet_Handle)netif->state;
    
        /* Call low-level close function */
        Lwip2Enet_close(hLwip2Enet, netif);
    
        /* Enet controller has been stopped. */
    }
    

    在此代码中、 netif->state  表示 a Lwip2enet_netif_t *
    但是、此变量被转换为 Lwip2 Enet_Handle


    IF Netif  是第一个接口、本节正常运行。
    但是、如果 Netif  是第二个接口、 hLwip2enet  映射到错误的地址。

    我尝试修复这部分、但在中 lwip2enet.c 、唯一的方法是直接指定的地址 gLwip2EnetObj  全局变量。
    但是、我认为这不是一个好办法。


    由于采用了 LWIPIF_LWIP_stop() 函数是的回调函数 netif_remove() ,它应该只处理接口的闭合操作是合理的。

    因此、我认为它将更加一致 Lwip2 Enet_Close () 采用 Lwip2enet_netif_t * 而不是 A Lwip2 Enet_Handle、  并且 最好处理下冲 Lwip2 Enet_Handle 意味着什么。

    请查看此器件。

    谢谢你。

    最棒的酒廊

    Jinwon Jang

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

    尊敬的  Jinwon Jang:

    在此代码中、 netif->state  表示 a Lwip2enet_netif_t *
    但是、此变量被转换为 Lwip2 Enet_Handle .

    Lwip2 Enet_Handle 中的第一个成员 是 Lwip2enet_netif_t、它是库对象 Lwip2 Enet_Obj 的指针  因此、我们可以使用相同的指针访问这两者。 无论使用多少个 netifs,都只有一个 hLwip2enet,这是在第一个 netif 的关闭序列之前关闭的。

    我再次在内部针对单网用例测试了该补丁。 我会将此请求转发给我们的开发团队、以便将此实施扩展到双线性用例中。 我将 在 2 天内更新 ETA 的详细信息。  

    此致、
    Teja。

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

    尊敬的 Teja:

    感谢您的评分

    如所示 lwip2enet_open () 下面的函数代码、打开两个 netifs 时、每个 netifs netif->state 指向 不同的 Lwip2enet_netif_t 成正比。

    Lwip2Enet_Handle Lwip2Enet_open(Enet_Type enetType, uint32_t instId, struct netif *netif, uint32_t netifIdx)
    {
        uint32_t txChIdList[LWIPIF_MAX_TX_CHANNELS_PER_PHERIPHERAL];
        uint32_t rxChIdList[LWIPIF_MAX_RX_CHANNELS_PER_PHERIPHERAL];
        EnetApp_GetMacAddrOutArgs          macAddr;
        EnetApp_HandleInfo                 handleInfo;
        Lwip2Enet_Handle    hLwip2Enet = Lwip2Enet_allocateObj();
        Lwip2Enet_netif_t*  pInterface = &(hLwip2Enet->interfaceInfo[hLwip2Enet->numOpenedNetifs++]);
        gInterface = pInterface;
        uint32_t txChIdCount = 0, rxChIdCount = 0;
    
        /* .... */
        
    
        /* Updating the netif params */
        Lwip2Enet_assert(netif->hwaddr_len == ENET_MAC_ADDR_LEN);
        netif->state = (void *)pInterface;
        
        if (hLwip2Enet->isInitDone == false)
        {
            /* Enable polling mode only when interrupt mode is disabled */
            if((pInterface->hRx[0]->disableEvent) && (pInterface->hTx[0]->disableEvent)){
                
                hLwip2Enet->isInitDone = true;
                Lwip2Enet_createTimer(hLwip2Enet);
                ClockP_start(&hLwip2Enet->pacingClkObj);
                /* assert if clk period is not valid  */
                Lwip2Enet_assert(0U != hLwip2Enet->appInfo.timerPeriodUs);
            }
        }
        
        return hLwip2Enet;
    }
    
    

    它实际上按如下方式映射。

    • 第一个 netif->state 指向 hLwip2enet->interfaceInfo[0]
    • 第二个 netif->state 指向 hLwip2enet->interfaceInfo[1]

    因此、第一个 netif->state 匹配的地址 hLwip2enet ,正如你提到的,但第二个 netif->state 与的地址不匹配 hLwip2enet

    所以、移除第二个时 Netif 、不正确 hLwip2enet 地址传递给 lwip2enet_close () 测量输出。


    此致、

    Jinwon Jang

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

    尊敬的  Jinwon Jang:

    我已经理解了这里的问题。 为了更好地处理这一问题、我们需要对序列进行一些根本性的更改。 开发团队表示、至少在 2026 年第 1 季度之前、关闭序列修复将不可用。 我将计划参加此活动。 由于我已经做出了一些承诺,并且由于印度的节假日,团队将离开下周,我将需要大约 3 周 来完成这一实施。  

    如果您对时间表有疑问、请告诉我。 感谢您的耐心。

    此致、
    Teja。

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

    尊敬的 Teja:

    我同意你的意见、认为有必要作出根本性的改变。

    我目前正在处理 SDK 的一些修复程序、但由于我仍在了解这部分代码、
    我希望您的解决方案在逻辑上更加清晰。

    谢谢你。

    此致、

    Jinwon Jang

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

    尊敬的  Jinwon Jang:

    内部会跟踪该要求、至少在 2026 年 Q1 结束之前、该要求才会作为标准 SDK 的一部分提供。 请告知我们此时间表是否适合您。 如果没有、我们必须检查后续可能采取的步骤。

    谢谢。此致、
    Teja。

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

    尊敬的 Teja:

    我了解您的情况。

    但是、由于我们的发展计划、我们已经发生了重大延误、而明年第二季度太迟了。

    我们的产品验证测试计划在明年第一季度进行、因此实施应在 1 月底前完成。

    尽管存在挑战、但请考虑可行的解决方案以满足我们的日程安排。

    “谢谢你。

    此致、

    Jinwon Jang

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

    尊敬的  Jinwon Jang:

    请让我与我们的团队核实、然后进行可行性分析。 我们将检查是否可以在您需要的时间范围内处理该问题、例如、在 1 月底之前完成的实施。

    敬请期待明天 EOD 的响应。

    谢谢。此致、
    Teja。

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

    尊敬的 Jinwong Jang:

    您能否提供有关您需要此功能的项目的更多详细信息、以及为什么您需要此功能用于应用? 这为我们提供了更多的背景,并在我们的规划中考虑到这些。 我仍然无法确认此功能将在 1 月前可用。 我正在与内部团队讨论相同的问题。

    谢谢。此致、
    Teja。

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

    尊敬的 Teja:

    我提前表示歉意、因为法规原因、我无法详细解释我们的项目内容。

    为了进行大致说明、需要具备以下功能:

    • 该器件设计使用 R5 单核处理器 AM2431。
      • 使用这个平台的模型约有十几个。
    • 有些型号使用两个 1Gb 光纤以太网端口实现冗余。
      • 两个以太网端口使用 AM2431 的 icssg0 的双 MAC 功能连接到单独的 PHY IC。
    •  固件管理需要在引导加载程序和固件之间进行切换、类似于 DOS。
      • 当固件退出时、它必须保存现有输出的最后值(包括模拟和数字)。
      • 由于输出的最后一个值保持特性、固件必须切换到引导加载程序而无需复位 MCU。
      • 由于此功能、使用以太网的型号需要 LWIP 平稳退出才能重新进入固件。

    由于旧型号中的处理器过时问题、我们正在开发的模型正在向新平台转变。

    因此、要在旧模型和新模型之间交叉使用、用户体验必须尽可能相同。

    SDK LWIP 最重要的方面是以下两点:

    • 使用两个以太网端口的通信稳定性
    • LWIP 初始化和取消初始化操作的稳定性

    我们请求您对这些要点进行审查。

    谢谢你。

    此致、

    Jinwon Jang

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

    尊敬的 Jinwong Jang:

    请不要误会我、您还能介绍一些有关终端 设备和项目规模的见解吗? 这有助于我们了解卷并相应地进行规划。  

    谢谢。此致、
    Teja。