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.

[参考译文] AM2432:DLR Sign_On 溢出测试 (CT22)-处理单播连续 Sign_On 帧

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1646485/am2432-dlr-sign_on-overflow-test-ct22---handling-of-unicast-continuous-sign_on-frame

器件型号: AM2432

问题

我们目前正在研究 DLR 一致性 (ODVA CT22)、我们有关于 Sign_On 溢出方案(特别是单播连续 Sign_On 帧)的正确处理的问题。


背景

在执行期间:

  • CT22 DLR 仿真测试 2.3:
    Sign_On 帧–溢出

我们的 DUT 在以下情况下失败:

  • 分析 Sign_On 单播结果

根据测试结果:

“观察到序列 ID 0x15 的 1 个 Sign_on 帧;预计至少 2 个 Sign_on 帧“  


观察到的行为

从数据包捕获:

  1. CT 工具首先发送 超过最大大小 (~1512 字节)的多播 Sign_On 帧。
  2. 然后、它 向 DUT(~60 字节)发送单播 Sign_On 帧(连续 Sign_On)。
  3. 但是、DUT 不传输任何响应帧

当前的实施问题

从我们对 TI SDK (EIP_processProtocolFrames) 的分析可以看出、DLR 帧检测是根据以下标准执行的:

Destination MAC == 01:21:6C:00:00:02 (DLR multicast)

因此:

  • 单播 Sign_On(连续 Sign_On)帧 不被识别为 DLR 帧
  • 这些帧 在 EIP_processProtocolFrames() 中被丢弃

CIP 规范参考

根据 CIP 规范第 2 卷第 9-5.5.4 节(Sign_On 工艺)

  • 当 Sign_On 帧超过最大大小时:

    • 节点 不附加其地址
    • 相反、它会 将 Sign_On 帧直接发送到活动监控器(单播)
  • 收到此单播 Sign_On 后:

    • 主管 重新启动 Sign_On 进程
    • 直接向节点发送新的 Sign_On 帧(单播)
    • 节点应:
      • 添加其地址
      • 再次转发 Sign_On 帧(多播)

这意味着 必须将单播 Sign_On 帧处理为有效的 DLR 帧、而不是丢弃。


问题

我们尝试了以下修改、测试通过、但我们不相信这些是正确的实现。

(1) DLR 帧检测

我们修改了代码、以便:

  • 单播 Sign_On 帧也由处理 EIP_DLR_processDLRFrame()

问题: 在这种情况下、识别 DLR 帧的正确方法是什么?
是否有任何推荐的方法(例如 EtherType、DLR 帧类型)?


(2) 目标 MAC 处理

为避免 CT 故障:

  • 在转发之前、我们将目的 MAC 地址修改为 DLR 多播地址

问题: 将目的 MAC 地址重写为多播是否具有正确的行为?
或者是否应保留原始单播目的地?


(3) signOnRcvdFlag 处理

在 SDK 实现中:

  • EIP_DLR_processDLRFrame() 返回而不处理 IF signOnRcvdFlag == FALSE

我们注意到:

  • 即使接受单播 Sign_On 帧后 signOnRcvdFlag 、仍然为 false
  • 作为一种变通方法、我们暂时删除此检查以通过测试

问题:

设置 signOnRcvdFlag 为 true 的正确条件和时间是什么?

  • 如果在接收到以下数据时设置该位:
    • 多播 Sign_On?
    • 单播 Sign_On(连续)?
    • 两者都有?

存在许多风险

  • SDK:适用于 AM243x 的工业通信 SDK 11.00.00.08

摘要

我们主要关注的是:

  • 正确处理 单播连续 Sign_On 帧
  • 符合 CIP Sign_On 上溢行为
  • 目标实现保持一致

非常感谢有关正确设计或参考实现的任何指导。

 

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

    田村明弘 

    在继续进行问题分析之前(有一件事我想确认)、这里使用的 ENIP 协议栈是什么?  

    它是 TI 的 ENIP 协议栈吗?

    同时,我将从驱动程序/固件 POV 进行所需的分析。

    此致
    Archit

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

    您好 Archit Dev 

    感谢您的答复。

    我们未使用 TI 提供的 ENIP 协议栈。
    相反、我们使用的是 TI SDK 之上集成的第三方 EtherNet/IP 协议栈。

    此致、

    田村明弘

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

     :

    从 PRU 固件和 ICSS DLR 驱动程序的角度来看、该问题应在即将发布的版本中得到解决。
    我附上了测试结果(使用 TI 的 EIP 堆栈)、以供您参考。

    e2e.ti.com/.../DLR_5F00_EmulatedTest.7z

    此致、
    Pourya

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

    尊敬的 Pourya:

    因此、下一个版本似乎能够通过 DLR 一致性测试。

    1. 您能帮助回答他的以下问题吗?
    2. 如果增补程序可用、是否可以共享它?

    【问题】

    [引述 userid=“617515“ url=“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1646485/am2432-dlr-sign_on-overflow-test-ct22---handling-of-unicast-continuous-sign_on-frame

    问题

    我们尝试了以下修改、测试通过、但我们不相信这些是正确的实现。

    (1) DLR 帧检测

    我们修改了代码、以便:

    • 单播 Sign_On 帧也由处理 EIP_DLR_processDLRFrame()

    问题: 在这种情况下、识别 DLR 帧的正确方法是什么?
    是否有任何推荐的方法(例如 EtherType、DLR 帧类型)?


    (2) 目标 MAC 处理

    为避免 CT 故障:

    • 在转发之前、我们将目的 MAC 地址修改为 DLR 多播地址

    问题: 将目的 MAC 地址重写为多播是否具有正确的行为?
    或者是否应保留原始单播目的地?


    (3) signOnRcvdFlag 处理

    在 SDK 实现中:

    • EIP_DLR_processDLRFrame() 返回而不处理 IF signOnRcvdFlag == FALSE

    我们注意到:

    • 即使接受单播 Sign_On 帧后 signOnRcvdFlag 、仍然为 false
    • 作为一种变通方法、我们暂时删除此检查以通过测试
    [/报价]

    谢谢你。

    此致、

    Kasai

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

    (1) DLR 帧检测

    我们修改了代码、以便:

    • 单播 Sign_On 帧也由处理  EIP_DLR_processDLRFrame()

    问题: 在这种情况下、识别 DLR 帧的正确方法是什么?
    是否有任何推荐的方法(例如 EtherType、DLR 帧类型)?

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    在我们方面、我们通过几个步骤来确定:

    1. EtherType (0x80E1)-第一步、比较任何 DLR EtherType 帧

    2.比较多播 MAC — 第二步比较 MAC 地址是否为 DLR 多播地址。

    • 检查是否存在 确切的多播 MAC 地址 (0121:6C00:00:02) Sign_On 帧未处理其他多播地址
    • 如果 MAC =01 216C00:00:02、则检查 DLR 帧类型的 Sign_On 类型 (7)、并通过 EIP_DLR_processDLRFrame 调用进行处理
         

    3. 比较单播 MAC — 在第三步比较 MAC 地址是否为设备的地址、Sign_On 帧不处理其他单播 MAC

    • 如果 MAC =“MAC of your device“、请检查 DLR 帧类型是否为 Sign_On 类型 (7)、并通过 EIP_DLR_processDLRFrame 调用处理

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    (2) 目标 MAC 处理

    为避免 CT 故障:

    • 在转发之前、我们将目的 MAC 地址修改为 DLR 多播地址

    问题: 将目的 MAC 地址重写为多播是否具有正确的行为?
    或者是否应保留原始单播目的地?

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    不需要修改、但应仅处理与第一个答案中所述的设备 MAC 相等的单播 MAC。

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    (3) signOnRcvdFlag 处理

    在 SDK 实现中:

    • EIP_DLR_processDLRFrame() 返回而不处理 IF  signOnRcvdFlag == FALSE

    我们注意到:

    • 即使接受单播 Sign_On 帧后 signOnRcvdFlag 、仍然为 false
    • 作为一种变通方法、我们暂时删除此检查以通过测试

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    不确定使用这一个、因为在实际实现中 、signOnRcvdFlag 没有 IF 条件。 但我建议首先删除权变措施、仅处理器件的单播 MAC 地址。 如果问题仍然存在、请再次提问、我会将其转发给负责的同事。

    此致
    Jiri Biel

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

    您好、  

    只需在此处添加几个要点:  

    • 在工业通信 SDK 11.00 中、PRU 固件不会在最高优先级队列中发送 DLR 单播信号帧。 最新固件中将修复此问题、该固件将包含在即将发布的 Industrial Comms SDK 2026 版本中。
      • 关于在发布前共享文件 — 我正在内部与团队进行检查。
      • 但是,作为一种即时的权变措施 — 可以在登录帧的接收回调中添加检查并调用 ICSS DLR 驱动程序函数。
    [报价 userid=“540505“ url=“~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1646485/am2432-dlr-sign_on-overflow-test-ct22---handling-of-unicast-continuous-sign_on-frame/6348716

    (2) 目标 MAC 处理

    为避免 CT 故障:

    • 在转发之前、我们将目的 MAC 地址修改为 DLR 多播地址

    问题: 将目的 MAC 地址重写为多播是否具有正确的行为?
    或者是否应保留原始单播目的地?

    [/报价]

    根据规范:

    环中的节点数可能足够大、以至于所有节点的地址都不适合 Sign_On 帧。 当节点接收到 Sign_On 帧时、如果添加节点的地址会超过最大帧大小、则节点不添加其地址、而是保存接收帧的端口、并将 Sign_On 帧直接发送到活动环形监控器。


    当环形监控器接收到发送到其单播 MAC 地址的 Sign_On 帧时、它假定这是由于 Sign_On 帧大小达到其最大值。 主管通过直接向其接收单播 Sign_On 帧的节点发送新的 Sign_On 帧(单播)来重新启动登录过程。


    从振铃监控器接收到新的 Sign_On 帧后、振铃节点会将其地址添加到 Sign_On 帧中。 然后、节点通过保存的端口以外的另一个端口发送 Sign_On 帧(多播)。

    将此逻辑转换为代码后、节点端处理的参考代码可能如下所示:

    uint32_t gSignOnOverflowDetectedPort;
    
    void EIP_DLR_processSignOnFrameAsNode(EIP_DLRHandle dlrHandle, uint8_t *pktBuffer,
                                          uint8_t portNum, uint16_t size)
    {
        ICSS_EMAC_Handle dlricssEmacHandle = dlrHandle->emacHandle;
        PRUICSS_HwAttrs const *pruicssHwAttrs = (PRUICSS_HwAttrs const *)(dlrHandle->pruicssHandle->hwAttrs);
        activeSuperAddr *actSupAddrPtr = &(dlrHandle->dlrObj->addr);
        uint8_t *ifMacID = (uint8_t *)(&(dlrHandle->macId[0]));
        uint16_t numNodes, offset;
        uint8_t txPort;
        uint8_t dstMac[6];
        uint8_t isUnicast;
        ICSS_EMAC_TxArgument txArg;
        /* Create a local array of MAX_MTU size - aligned to 4 bytes */
        uint8_t newSignOnFrame[ICSS_EMAC_MAXMTU] __attribute__((aligned(4))) = {0};
    
        /* Check if this is a unicast frame (destination MAC = own MAC) */
        EIP_DLR_getMACId(pktBuffer + DLR_DST_MAC_OFFSET, dstMac);
        if(DLR_FALSE == memcmp(dstMac, ifMacID, ETHERNET_MAC_ADDR_LEN))
        {
            isUnicast = DLR_TRUE;
        }
        else
        {
            isUnicast = DLR_FALSE;
        }
    
        /* Calculate next port for forwarding */
        if(portNum == ICSS_EMAC_PORT_1)
        {
        	txPort = ICSS_EMAC_PORT_2;
        }
        else
        {
        	txPort = ICSS_EMAC_PORT_1;
        }
    
        /* Get current number of nodes */
        numNodes = EIP_DLR_convBigEndianToLittleEndianHalfWord(pktBuffer + DLR_SIGNON_NUM_NODES_OFFSET);
    
        /* Calculate offset where new address would be added */
        offset = (DLR_SIGNON_SUP_MAC_ADD_OFFSET + (numNodes * 10));
    
        /* Check if adding own address (4 bytes for IP Address and 6 bytes for MAC Address = 10 bytes) would exceed max frame size */
        if ((offset + ETHERNET_IP_ADDR_LEN + ETHERNET_MAC_ADDR_LEN) > ICSS_EMAC_MAXMTU)
        {
            /* Frame is too large - save receiving port to shared RAM and send unicast to supervisor */
            gSignOnOverflowDetectedPort = portNum;
    
            /* Modify source MAC to own MAC */
            EIP_DLR_addMACID(pktBuffer + DLR_SRC_MAC_OFFSET, ifMacID);
    
            /* Set destination to supervisor MAC (unicast) */
            EIP_DLR_addMACID(pktBuffer + DLR_DST_MAC_OFFSET, actSupAddrPtr->supMACAddress);
    
            /* Send unicast to supervisor on the other port */
            txArg.icssEmacHandle = dlricssEmacHandle;
            txArg.lengthOfPacket = size;
            txArg.portNumber = txPort;
            txArg.queuePriority = ICSS_EMAC_QUEUE1;
            txArg.srcAddress = pktBuffer;
    
            ICSS_EMAC_txPacket(&txArg, NULL);
        }
        else if (isUnicast == DLR_TRUE)
        {
            /* This is a unicast Sign_On from supervisor (after overflow detection) */
            /* Copy old data from the frame */
            memcpy(newSignOnFrame, pktBuffer, size);
            /* Add own address to the frame */
            EIP_DLR_addMACID(newSignOnFrame + offset, ifMacID);
            EIP_DLR_addWord(newSignOnFrame + offset + ETHERNET_MAC_ADDR_LEN, dlrHandle->deviceIP);
            offset += (ETHERNET_IP_ADDR_LEN + ETHERNET_MAC_ADDR_LEN);
            numNodes++;
    
            /* Update number of nodes in frame */
            EIP_DLR_addSignOnNumNodes(newSignOnFrame, numNodes);
    
            /* Restore multicast destination MAC */
            EIP_DLR_addMACID(newSignOnFrame + DLR_DST_MAC_OFFSET, EIP_DLR_signOnMacID);
    
            /* Modify source MAC to own MAC */
            EIP_DLR_addMACID(newSignOnFrame + DLR_SRC_MAC_OFFSET, ifMacID);
    
            /* send on OTHER port */
            if((ICSS_EMAC_PORT_1 == gSignOnOverflowDetectedPort)
            {
                txPort = ICSS_EMAC_PORT_2;
            }
            else
            {
                txPort = ICSS_EMAC_PORT_1;
            }
    
            if(offset < DEFAULT_DLR_PACKET_SIZE)
            {
                txArg.lengthOfPacket = DEFAULT_DLR_PACKET_SIZE;
            }
            else
            {
                txArg.lengthOfPacket = offset;
            }
    
            txArg.icssEmacHandle = dlricssEmacHandle;
            txArg.portNumber = txPort;
            txArg.queuePriority = ICSS_EMAC_QUEUE1;
            txArg.srcAddress = newSignOnFrame;
    
            ICSS_EMAC_txPacket(&txArg, NULL);
        }
        else
        {
            /* Normal processing: add own address and forward multicast */
            /* Copy old data from the frame */
            memcpy(newSignOnFrame, pktBuffer, size);
            /* Modify source MAC to own MAC */
            EIP_DLR_addMACID(newSignOnFrame + DLR_SRC_MAC_OFFSET, ifMacID);
    
            /* Add own address */
            EIP_DLR_addMACID(newSignOnFrame + offset, ifMacID);
            EIP_DLR_addWord(newSignOnFrame + offset + ETHERNET_MAC_ADDR_LEN, dlrHandle->deviceIP);
            offset += (ETHERNET_IP_ADDR_LEN + ETHERNET_MAC_ADDR_LEN);
            numNodes++;
    
            /* Update number of nodes */
            EIP_DLR_addSignOnNumNodes(newSignOnFrame, numNodes);
    
            if(offset < DEFAULT_DLR_PACKET_SIZE)
            {
                txArg.lengthOfPacket = DEFAULT_DLR_PACKET_SIZE;
            }
            else
            {
                txArg.lengthOfPacket = offset;
            }
            /* Send multicast on other port */
            txArg.icssEmacHandle = dlricssEmacHandle;
            txArg.portNumber = txPort;
            txArg.queuePriority = ICSS_EMAC_QUEUE1;
            txArg.srcAddress = newSignOnFrame;
    
            ICSS_EMAC_txPacket(&txArg, NULL);
        }
    }
    

    如果这里有任何疑问或问题、请告诉我们。

    此致
    Archit

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

    你(们)好  

    我强烈建议使用最新的 ICSS DLR 驱动程序和来自工业通信 SDK AM243x 的 EIP 固件: https://www.ti.com/tool/download/INDUSTRIAL-COMMUNICATIONS-SDK AM243X/2026.00.00.06 

    这包括针对 DLR 节点和监控器测试用例的 CT22 DLR 仿真测试通过情况。

    如果您有任何疑问、请随时与我们联系。

    此致
    Archit