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: PRU Referencing Wrong Port Register in MII Mode

Part Number: AM2432
Other Parts Discussed in Thread: SYSCONFIG, DP83869

Hello,

We are experiencing an issue on a custom board using the AM2432 where the 100M Ethernet IPG is set to 480 ns. I had asked about this before, but I’ve discovered new information, so I’d like to add that and ask again.

The custom board has two ports, which I’ll refer to as Port 1 and Port 2. We modified the sample “enet_layer2_icssg” to run on the custom board so that when it receives an ARP frame, it returns two ARP frames. We measure the IPG between the two frames sent from the custom board after sending an ARP frame from the PC.

Here’s what we found during testing:

1-1. Connect a LAN cable to Port 1. The IPG register for Port 1 is set to a value (0x17).
1-2. Send an ARP frame from the PC to the custom board.
1-3. When replying with two frames from Port 1 to the PC, the PRU refers to Port 2’s register value (0x0B). The IPG becomes 480 ns.

2-1. Connect a LAN cable to Port 2. The IPG register for Port 2 is set to a value (0x17).
2-2. Send an ARP frame from the PC to the custom board.
2-3. When replying with two frames from Port 2 to the PC, the PRU refers to Port 1’s register value (0x0B). The IPG becomes 480 ns.

3-1. Connect a LAN cable to Port 1. The IPG register for Port 1 is set to a value (0x17).
3-2. Disconnect the LAN cable from Port 1.
3-3. Connect a LAN cable to Port 2. The IPG register for Port 2 is set to a value (0x17).
3-4. Send an ARP frame from the PC to the custom board.
3-5. The PC receives an ARP frame from Port 2. The IPG is 960 ns. Presumably, Port 1’s register value (0x17) is being referenced.
(The same phenomenon occurs if you reverse Port 1 and Port 2.)

From this, I suspect there might be a bug where the register referenced during actual frame transmission is somehow reversed between Port 1 and Port 2.

I’ve confirmed that this does not occur on the AM243xEVM evaluation board. Investigating the differences, I found that in SysConfig under Enet(ICSS), the evaluation board uses RGMII, while the custom board uses MII. Could this difference cause the PRU to incorrectly reference IPG0 and IPG1 in reverse? Could you please check this?

Best Regards,
Kazushige.

  • Hi Kazushige,

    This seems to be an issue with the Tx pins of the MII interface. Can you please give some details if you have followed the TI evm schematics or the soc spec to design your custom board? I remember there being an issue with the MII Tx pins. Please share the details on your reference, and I'll check the details based on that. 

    Thanks and regards,
    Teja.

  • I downloaded the design files for AM64x/AM243x from TI’s website.
    The attached file was used as a reference for the circuit.
    In particular, I referred to pages P17, P18, and P27.


    The actual circuit of the custom board has been presented in the related previous threads.

    Regards

    PROC101D(004)_SCH.pdf

  • Hi Kazushige,

    We will check this configuration internally, and get back with the analysis. Please give us 3 working days to verify this.

    Thank you for your patience,

    Regards,
    Teja.

  • Hi Kazushige,

    AM243xEVM evaluation board. Investigating the differences, I found that in SysConfig under Enet(ICSS), the evaluation board uses RGMII, while the custom board uses MII.

    Is this the same case on AM243x EVM evaluation board in MII mode - you need to change the option in SYSCONFIG enet-ICSS to MII mode? Can you give a try if you haven't tested it?

    BR
    JC

  • Hi,

    I tested the AM243xEVM environment with the enet-ICSS option set to MII.
    As a result, the IPG was 480 ns, just like in the initial question.
    I also ran the same tests as before: 1-1 to 1-3, 2-1 to 2-3, and 3-1 to 3-5, and obtained the same results.

    I’m sending the sample project I used.
    There are two changes from the original “enet_layer2_icssg” project:

    • Changed the enet-ICSS option in syscfg to MII
    • Modified EnetMp_rxTask in enet_layer2_icssg.c to respond with two frames

    IPGtestproject.zip

    Regards,
    Kazushige.

  • Hi Kazushige,

    1-3. When replying with two frames from Port 1 to the PC, the PRU refers to Port 2’s register value (0x0B). The IPG becomes 480 ns.

    How are you confirming IPG value? Can you share me the wireshark capture?

    BR
    JC

  • Hi,

    How are you confirming

    I am using a logic analyzer to measure the Tx_EN signal on the AM243xEVM.

    Can you share me the wireshark capture?

    Attached is the Wireshark capture for tests similar to 3-1 through 3-5.

    wireshark_data.zip
    No. 1–10:
    Connected a LAN cable to Port 1, and sent 5 ARP packets from the PC to the AM243xEVM.
    The AM243xEVM responds with 2 frames each time, for a total of 10 ARP frames of 1072 bytes.
    (Some frames cannot be captured because the IPG is 480 ns.)

    No. 11–14:
    Disconnected Port 1 and connected to Port 2.

    No. 15–29:
    Sent 5 ARP packets from the PC to the AM243xEVM.
    The AM243xEVM responds with 2 frames each time, for a total of 10 ARP frames of 1072 bytes.
    (All frames can be captured because the IPG is 980 ns.)

    Configuration:
    PC --- PROFISHARK (packet capture) --- AM243xEVM

    Regards,
    Kazushige.

  • Hi Kazushige, 

    Could you please navigate to the following path:

    File: source/networking/enet/core/src/per/icssg_utils.c

    Function: IcssgUtils_fwConfig

    In this function, please negate the condition as shown below:

    if (!EnetMacPort_isRgmii(&cfg->mii))
    {
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TXCFG0, 0x1803U);
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TXCFG1, 0x1903U);
    }
    else
    {
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TXCFG0, 0x1903U);
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TXCFG1, 0x1803U);
    }

    After making the change, rebuild the ENET ICSSG library using the following commands from SDK root directory, then re-build the example

    gmake -s -f makefile.am243x enet-icssg_r5f.ti-arm-clang PROFILE=debug
    gmake -s -f makefile.am243x enet-icssg_r5f.ti-arm-clang PROFILE=release

    BR,
    JC

  • Hi,

    As instructed, I modified the file icssg_utils.c in the SDK, rebuilt it, and performed testing.
    However, the issue has not been resolved.

    Test details:

    • Connected a LAN cable to Port 1, then sent an ARP frame from the PC.
      → The AM243xEVM responded to the ARP frame from Port 2, which had nothing connected. (The orange LED on the LAN port was blinking.)
    • Disconnected the LAN cable from Port 1 and connected it to Port 2.
    • Sent an ARP frame from the PC.
      → The AM243xEVM responded to the ARP frame from Port 1, which had nothing connected. (The orange LED on the LAN port was blinking.)

    The IPG was 9.6 ns, so it seems the AM243xEVM internally assumes a 1 Gbps connection.
    The PC’s Ethernet port is configured for 100 Mbps.

    wireshark_data2.zip

    Regards,
    Kazushige.

  • Hi Kazushige,

    The IPG was 9.6 ns, so it seems the AM243xEVM internally assumes a 1 Gbps connection.

    I believe this measurement is 9.6µs rather than ns, which would correspond to 10M speed. I don't currently have boards with the TX_EN pins probed, but I'll look into the possibility to set that up.

    I also have another question: In your default test scenario (before applying the change below) where you observed 480ns, what was the value of the MII_G_RT register? For reference: ICSSG0 is at 0x30033004, and ICSSG1 is at 0x300B3004.

    if (!EnetMacPort_isRgmii(&cfg->mii))
    {
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TXCFG0, 0x1803U);
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TXCFG1, 0x1903U);
    }
    else
    {
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TXCFG0, 0x1903U);
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TXCFG1, 0x1803U);
    }

    BR
    JC

  • Hi,

    what was the value of the MII_G_RT register? For reference: ICSSG0 is at 0x30033004, and ICSSG1 is at 0x300B3004.

    Since I am using ICSSG1, I checked 0x300B3004.

    1. After powering on and connecting a LAN cable to Port 1, the value became 0x00640000.
      Then, after disconnecting from Port 1 and connecting to Port 2, it became 0x00440000.
      (After that, repeated connect/disconnect operations did not cause any change.)



    2. After powering on and connecting a LAN cable to Port 2, the value became 0x00460000.
      Then, after disconnecting from Port 2 and connecting to Port 1, it became 0x00440000.
      (After that, repeated connect/disconnect operations did not cause any change.)


    Regards,
    Kazushige.

  • For completeness, which SDK version are you using here?

  • I am using mcu_plus_sdk_am243x_11_00_00_18.
    Regards,
    Kazushige.
  • Hi Kazushige, 

    Just to clarify—are you referring to version 11.00.00.15 (Apr 4, 2025)?

    Regarding packet generation: could you clarify how you're generating packets from the R5F host? Upon reviewing your application, it appears to be using the default application loopback method similar to out-of-box example release SDK. The attached project is hitting an assert - looks like no packets are initialized in the enqueue API, is there any changes to the project you've shared?

    I've set up testing on my end and completed some RGMII measurements (ref below), which align with expectations. I'm currently testing MII and will share those results tomorrow. Meantime can you clarify above questions?

     

    BR
    JC

  • Hi Kazushige,

    1-1. Connect a LAN cable to Port 1. The IPG register for Port 1 is set to a value (0x17).
    1-2. Send an ARP frame from the PC to the custom board.
    1-3. When replying with two frames from Port 1 to the PC, the PRU refers to Port 2’s register value (0x0B). The IPG becomes 480 ns.

    I tested the scenario you described above.
    The registers are indeed configured as you mentioned: TX_IPG0 = 0x17 and TX_IPG1 = 0x0B, which is expected.
    However, I was unable to reproduce the issue you reported. Please refer to the attached screenshot for my measurement results

    The logic analyzer capture shows the Inter-Packet Gap (IPG) measurement between two consecutive frames transmitted from Port 1:

    M0 (Green region): Δ960 ns – IPG between first and second packet
    M1 (Red region): Δ960 ns – Confirms consistent IPG timing
    M2 (Blue region): Δ6.88 µs – This represents the actual frame/packet duration

    My test setup:

    Board revision PROC101C(005) - AM243x EVM
    SDK version Public version 11.00.00.15 (April 4, 2025)
    Example project from SDK (default, no changes) icssg_layer2_dualmac_am243x-evm_r5fss0-0_freertos_ti-arm-clang
    PHY mode MII (100 Mbps)

    BR
    JC

  • Hi,

    Thank you for your investigation.

    Just to clarify—are you referring to version 11.00.00.15 (Apr 4, 2025)?

    When I checked www.ti.com/.../, version 11.0.0.18 was available, but it seems to be gone now. Since the issue can be reproduced with 11.0.0.15, using 11.0.0.15 is fine.

    The attached project is hitting an assert - looks like no packets are initialized in the enqueue API, is there any changes to the project you've shared?

    There are no changes in the IPGtestproject I shared. However, since I haven’t tested with a large number of frames, an assert due to memory exhaustion could occur.
    I only want to verify the IPG, so as long as two frames of about 1000 bytes are queued and transmitted from the AM243x EVM, any implementation should be fine.

    However, I was unable to reproduce the issue you reported

    Are you queuing two frames for transmission inside the AM243x EVM?
    If your setup measures the IPG for frames returned by the AM243x EVM in response to two consecutive frames sent from the PC, that doesn’t really provide meaningful results.
    The sample project
    (default, no changes) icssg_layer2_dualmac_am243x-evm_r5fss0-0_freertos_ti-arm-clang
    returns one frame for each received frame, so I’m curious whether you’re actually queuing and sending two frames.

    For reference, I’ve attached the Python script used to send ARP packets from the PC.
    Enter the PC’s MAC address on line 7 and the NIC name in line 21 (replace "eth7"), and it will work.
    This code sends 5 ARP packets.

    sendARP.zip
    On the AM243x EVM side, I’m using CCS 12.8.1.

    Regards,
    Kazushige.

  • Hi Kazushige,

    Are you queuing two frames for transmission inside the AM243x EVM?

    I'm using a dedicated external traffic generator that operates at true line rate. This ensures the AM243x EVM receives traffic at precise 100Mbps, which properly saturates the R5F's packet processing and creates backpressure on the TX path and starts to queue the packet. This situation is exactly the packet queueing mechanism you mentioned above without manual packet queueing from R5F.

    By the way which PHY chip are you tapping in the EVM when the cable is connected in Port-1?

    BR
    JC 

  • Hi,

    By the way which PHY chip are you tapping in the EVM when the cable is connected in Port-1?

    We are using the DP83869.


    I understand that the sample icssg_layer2_dualmac_am243x-evm_r5fss0-0_freertos_ti-arm-clang is designed to return a frame to its sender upon receiving it.
    I also understand that you are trying to create a similar situation by continuously sending packets to the AM243x EVM beyond its processing capacity. However, could you please apply the following modification to the sample code and test it in the same environment where this bug occurs?
    The change is simply to modify EnetMp_rxTask in enet_layer_icssg.c as shown below.

    static void EnetMp_rxTask(void *args)
    {
        EnetMp_PerCtxt *perCtxt = (EnetMp_PerCtxt *)args;
        EnetDma_PktQ rxReadyQ;
        EnetDma_PktQ rxFreeQ;
        EnetDma_PktQ txSubmitQ;
        EnetDma_Pkt *rxPktInfo;
        EnetDma_Pkt *txPktInfo;
        EnetDma_Pkt *txPktInfo2;
        EthFrame *rxFrame;
        EthFrame *txFrame;
        Enet_IoctlPrms prms;
        bool semStatus;
    #if DEBUG
        uint32_t totalRxCnt = 0U;
    #endif
        uint32_t flowIdx, prioMap[ENETMP_MAX_TX_CHANNEL_NUM];
        int32_t status = ENET_SOK;
    
    
        for(flowIdx = 0; flowIdx< ENETMP_MAX_TX_CHANNEL_NUM; flowIdx++)
        {
            prioMap[flowIdx] =  flowIdx;
        }
    
        status = set_priority_queue_mapping(perCtxt, ENET_MAC_PORT_1, prioMap);
        status = set_priority_queue_mapping(perCtxt, ENET_MAC_PORT_2, prioMap);
    
        status = EnetMp_waitForLinkUp(perCtxt);
        if (status != ENET_SOK)
        {
            EnetAppUtils_print("%s: Failed to wait for link up: %d\n", perCtxt->name, status);
        }
    
        /* Open DMA for peripheral/port */
        if (status == ENET_SOK)
        {
            uint32_t perCtxtIndex;
    
            EnetAppUtils_print("%s: Open DMA\r\n", perCtxt->name);
    
            status = EnetMp_mapPerCtxt2Idx(perCtxt, &perCtxtIndex);
            EnetAppUtils_assert(status == ENET_SOK);
            status = EnetMp_openDma(perCtxt, perCtxtIndex);
            if (status != ENET_SOK)
            {
                EnetAppUtils_print("%s: failed to open DMA: %d\r\n", perCtxt->name, status);
            }
        }
    
        /* Add port MAC entry */
        if ((status == ENET_SOK) && (Enet_isIcssFamily(perCtxt->enetType)))
        {
            EnetAppUtils_print("%s: Set MAC addr: ", perCtxt->name);
            EnetAppUtils_printMacAddr(&perCtxt->macAddr[0U][0U]);//[flowIdx][MAC addr length]
    
            if (perCtxt->enetType == ENET_ICSSG_DUALMAC)
            {
                IcssgMacPort_SetMacAddressInArgs inArgs;
    
                memset(&inArgs, 0, sizeof(inArgs));
                inArgs.macPort = perCtxt->macPort[0U];
                EnetUtils_copyMacAddr(&inArgs.macAddr[0U], &perCtxt->macAddr[0U][0U]);//[flowIdx][MAC addr length]
                ENET_IOCTL_SET_IN_ARGS(&prms, &inArgs);
    
                ENET_IOCTL(perCtxt->handleInfo.hEnet, gEnetMp.coreId, ICSSG_MACPORT_IOCTL_SET_MACADDR, &prms, status);
            }
            else
            {
                Icssg_MacAddr addr; // FIXME Icssg_MacAddr type
    
                /* Set host port's MAC address */
                EnetUtils_copyMacAddr(&addr.macAddr[0U], &perCtxt->macAddr[0U][0U]);//[flowIdx][MAC addr length]
                ENET_IOCTL_SET_IN_ARGS(&prms, &addr);
    
                ENET_IOCTL(perCtxt->handleInfo.hEnet, gEnetMp.coreId, ICSSG_HOSTPORT_IOCTL_SET_MACADDR, &prms, status);
            }
    
            if (status != ENET_SOK)
            {
                    EnetAppUtils_print("%s: Failed to set MAC address entry: %d\n", perCtxt->name, status);
            }
        }
    
    
        while ((ENET_SOK == status) && (gEnetMp.run))
        {
            /* Wait for packet reception */
            SemaphoreP_pend(&perCtxt->rxSemObj, SystemP_WAIT_FOREVER);
    
            /* All peripherals have single hardware RX channel, so we only need to retrieve
             * packets from a single flow.  But ICSSG Switch has two hardware channels, so
             * we need to retrieve packets from two flows, one flow per channel */
    
                for (flowIdx = 0; flowIdx < perCtxt->rxChCount; flowIdx++)
                {
                    EnetQueue_initQ(&rxReadyQ);
                    EnetQueue_initQ(&rxFreeQ);
                    EnetQueue_initQ(&txSubmitQ);
    
                    /* Get the packets received so far */
                    status = EnetDma_retrieveRxPktQ(perCtxt->hRxCh[flowIdx], &rxReadyQ);
                    if (status != ENET_SOK)
                    {
                        /* Should we bail out here? */
                        EnetAppUtils_print("Failed to retrieve RX pkt queue: %d\r\n", status);
                        continue;
                    }
    #if DEBUG
                    EnetAppUtils_print("%s: Received %u packets\r\n", perCtxt->name, EnetQueue_getQCount(&rxReadyQ));
                    totalRxCnt += EnetQueue_getQCount(&rxReadyQ);
    #endif
                    reqTs = 0U;
                    count[0][flowIdx] += EnetQueue_getQCount(&rxReadyQ);
    
                    /* Consume the received packets and send them back */
                    rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ);
                    while (rxPktInfo != NULL)
                    {
                        rxFrame = (EthFrame *)rxPktInfo->sgList.list[0].bufPtr;
                        EnetDma_checkPktState(&rxPktInfo->pktState,
                                              ENET_PKTSTATE_MODULE_APP,
                                              ENET_PKTSTATE_APP_WITH_DRIVER,
                                              ENET_PKTSTATE_APP_WITH_READYQ);
    
                        /* Retrieve TX packets from driver and recycle them */
                        EnetMp_retrieveFreeTxPkts(perCtxt);
    
                        /* Dequeue one free TX Eth packet */
                        txPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&gEnetMp.txFreePktInfoQ);
                        txPktInfo2 = (EnetDma_Pkt *)EnetQueue_deq(&gEnetMp.txFreePktInfoQ);
    
                        if (txPktInfo != NULL)
                        {
                            /* Fill the TX Eth frame with test content */
                            txFrame = (EthFrame *)txPktInfo->sgList.list[0].bufPtr;
                            memcpy(txFrame->hdr.dstMac, rxFrame->hdr.srcMac, ENET_MAC_ADDR_LEN);
                            memcpy(txFrame->hdr.srcMac, &perCtxt->macAddr[0U], ENET_MAC_ADDR_LEN);
                            txFrame->hdr.etherType = rxFrame->hdr.etherType;
    
                            memcpy(&txFrame->payload[0U],
                                   &rxFrame->payload[0U],
                                   rxPktInfo->sgList.list[0].segmentFilledLen - sizeof(EthFrameHeader));
    
                            txPktInfo->sgList.list[0].segmentFilledLen = rxPktInfo->sgList.list[0].segmentFilledLen+1000;
                            txPktInfo->sgList.numScatterSegments = 1;
                            txPktInfo->chkSumInfo = 0U;
                            txPktInfo->appPriv = &gEnetMp;
    
                            txFrame = (EthFrame *)txPktInfo2->sgList.list[0].bufPtr;
                            memcpy(txFrame->hdr.dstMac, rxFrame->hdr.srcMac, ENET_MAC_ADDR_LEN);
                            memcpy(txFrame->hdr.srcMac, &perCtxt->macAddr[0U], ENET_MAC_ADDR_LEN);
                            txFrame->hdr.etherType = rxFrame->hdr.etherType;
    
                            memcpy(&txFrame->payload[0U],
                                   &rxFrame->payload[0U],
                                   rxPktInfo->sgList.list[0].segmentFilledLen - sizeof(EthFrameHeader));
    
                            txPktInfo2->sgList.list[0].segmentFilledLen = rxPktInfo->sgList.list[0].segmentFilledLen+1000;
                            txPktInfo2->sgList.numScatterSegments = 1;
                            txPktInfo2->chkSumInfo = 0U;
                            txPktInfo2->appPriv = &gEnetMp;
    
                            /* Set timestamp info in DMA packet.
                             * Packet timestamp currently enabled only for ICSSG. */
                            if (gEnetMp.enableTs &&
                                Enet_isIcssFamily(perCtxt->enetType))
                            {
                                /* Save the timestamp of received packet that we are about to send back,
                                 * so we can calculate the RX-to-TX time diffence in TX timestamp callback */
                                perCtxt->rxTs[perCtxt->txTsSeqId % ENET_SYSCFG_TOTAL_NUM_RX_PKT] = rxPktInfo->tsInfo.rxPktTs;
    
                                txPktInfo->tsInfo.enableHostTxTs = true;
                                txPktInfo->tsInfo.txPktSeqId     = perCtxt->txTsSeqId++;
                                txPktInfo->tsInfo.txPktMsgType   = 0U; /* Don't care for ICSSG */
                                txPktInfo->tsInfo.txPktDomain    = 0U; /* Don't care for ICSSG */
                                reqTs++;
                            }
                            else
                            {
                                txPktInfo->tsInfo.enableHostTxTs = false;
                            }
    
                            EnetDma_checkPktState(&txPktInfo->pktState,
                                                  ENET_PKTSTATE_MODULE_APP,
                                                  ENET_PKTSTATE_APP_WITH_FREEQ,
                                                  ENET_PKTSTATE_APP_WITH_DRIVER);
    
    
                            EnetDma_checkPktState(&txPktInfo2->pktState,
                                                  ENET_PKTSTATE_MODULE_APP,
                                                  ENET_PKTSTATE_APP_WITH_FREEQ,
                                                  ENET_PKTSTATE_APP_WITH_DRIVER);
    
                            /* Enqueue the packet for later transmission */
                            EnetQueue_enq(&txSubmitQ, &txPktInfo->node);
                            EnetQueue_enq(&txSubmitQ, &txPktInfo2->node);
                        }
                        else
                        {
                            EnetAppUtils_print("%s: Drop due to TX pkt not available\r\n", perCtxt->name);
                        }
    
                        EnetDma_checkPktState(&rxPktInfo->pktState,
                                              ENET_PKTSTATE_MODULE_APP,
                                              ENET_PKTSTATE_APP_WITH_READYQ,
                                              ENET_PKTSTATE_APP_WITH_FREEQ);
    
                        /* Release the received packet */
                        EnetQueue_enq(&rxFreeQ, &rxPktInfo->node);
                        rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ);
                    }
    
                    /* Transmit all enqueued packets */
    #if ENET_SYSCFG_DUAL_MAC
                    const uint32_t txChIdx = flowIdx;
    #else
                    const uint32_t txChIdx = flowIdx % ENET_SYSCFG_TX_CHANNELS_NUM;
    #endif
                    status = EnetDma_submitTxPktQ(perCtxt->hTxCh[txChIdx], &txSubmitQ);
                    if (status != ENET_SOK)
                    {
                        EnetAppUtils_print("%s: Failed to submit TX pkt queue: %d\r\n", perCtxt->name, status);
                    }
    
                    EnetAppUtils_validatePacketState(&rxFreeQ,
                                                     ENET_PKTSTATE_APP_WITH_FREEQ,
                                                     ENET_PKTSTATE_APP_WITH_DRIVER);
    
                    /* Wait for TX timestamp */
                    while (gEnetMp.run && (reqTs != 0U))
                    {
                        Enet_MacPort macPort = perCtxt->macPort[0];
    
                        Enet_poll(perCtxt->handleInfo.hEnet, ENET_EVT_TIMESTAMP_TX, &macPort, sizeof(macPort));
                        semStatus = SemaphoreP_pend(&perCtxt->txTsSemObj, 1U);
                        if (semStatus == SystemP_SUCCESS)
                        {
                            continue;
                        }
                    }
    
                    /* Submit now processed buffers */
                    EnetDma_submitRxPktQ(perCtxt->hRxCh[flowIdx], &rxFreeQ);
                    if (status != ENET_SOK)
                    {
                        EnetAppUtils_print("%s: Failed to submit RX pkt queue: %d\r\n", perCtxt->name, status);
                    }
                }
    
        }
    
    #if DEBUG
        EnetAppUtils_print("%s: Received %u packets\r\n", perCtxt->name, totalRxCnt);
    #endif
    
    
        SemaphoreP_post(&perCtxt->rxDoneSemObj);
        TaskP_exit();
    }
    

    The diagram illustrates the changes as follows.

    Regards,
    Kazushige.

  • Hi Kazushige,

    I've applied the suggested changes and tested the same scenario you described on both ports. Unfortunately, I'm still unable to reproduce the issue. As seen in the screenshot, the IPG measurements (M0, M3) consistently show 960 ns. Additionally, I've verified that the IPG values in the registers are set as expected, matching the values you mentioned.

    BR
    JC

  • Thank you.

    I have confirmed that the waveform with two packets is similar to what we observe in our environment.
    In our environment, this issue occurs 100% of the time, so I would like to investigate where the differences lie.

    Below are the detailed test steps. Please check if they match your procedure:

    1. Disconnect all cables from every port of the AM243xEVM.
    2. Turn on the power of the AM243xEVM.
    3. From the PC, start debugging in CCS, load the project, and run it (the issue occurs with both Debug and Release builds).
    4. Connect a LAN cable only to Port 1 (the lower port of the two stacked LAN ports).
    5. Execute sendARP(send an ARP frame from the PC).
    6. Measure the Tx_EN pin using a logic analyzer.

    Regards,
    Kazushige.

  • Kazushige, 

    I was able to reproduce this issue following the test steps you described.

    Root Cause
    This is a driver bug related to the TX Inter-Packet Gap (IPG) configuration. The current driver uses 0x0B for the TX_IPG register value, which is only compatible with 1G speed (96ns) in RGMII mode.

    For MII mode (10M or 100M), the correct value should be 0x17.

    Recommendation: For mixed link speed modes, we recommend configuring both ports as RGMII regardless of the actual link speed, rather than using MII for one port and RGMII for another.

    Fix
    This fix will be included in a future SDK release. In the meantime, please apply the following fix in driver.

    1. In source/networking/enet/core/src/per/icssg_utils.c - API: IcssgUtils_fwConfig() 

    Remove the following code:

    // Program TX_IPG0/IPG1
    /* Workaround: Due to hardware bug, the following sequence has to be followed:
     * - For port 0, write as is.
     * - For port 1, write value, and then do a dummy read-then-write operation on port 0 */
    Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG1, 0xBU);
    Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG0, 0xBU);

    Replace the EnetMacPort_isRgmii(&cfg->mii)) section with:

    /* Init RGMII config for ICSSG: TXL2, TXPRU enable, etc */
    // Program TX_IPG0/IPG1
    /* Workaround: Due to hardware bug, the following sequence has to be followed:
     * - For port 0, write as is.
     * - For port 1, write value, and then do a dummy read-then-write operation on port 0 */
    if (EnetMacPort_isRgmii(&cfg->mii))
    {
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG1, 0x17U);
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG0, 0x17U);
        Icssg_wr32(hIcssg, cfgRegs + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_G_CFG_REGS_G_ICSS_G_CFG, 0x1082FU);
    }
    else
    {
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG1, 0xBU);
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG0, 0xBU);
        Icssg_wr32(hIcssg, cfgRegs + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_G_CFG_REGS_G_ICSS_G_CFG, 0x10807U);
    }

    2. In IcssgUtils_configSwtFw function 

    Replace the following code:

    /* Note that it is important to update TX_IPG1 before TX_IPG0 as in WIRE_CLK mode TX_IPG0 write
     * is required to load the IPG value to hardware */
    Icssg_wr32(hIcssg,
               baseAddr +
               CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE +
               CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG1,
               0xBU); /* Wire CLK @ 125 MHz : 8ns */
    Icssg_wr32(hIcssg,
               baseAddr +
               CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE +
               CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG0,
               0xBU);  /* Wire CLK @ 125 MHz : 8ns */

    With:

    if (EnetMacPort_isRgmii(&cfg->mii))
    {
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG1, 0x17U);
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG0, 0x17U);
    }
    else
    {
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG1, 0xBU);
        Icssg_wr32(hIcssg, baseAddr + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_REGS_BASE + CSL_ICSS_G_PR1_MII_RT_PR1_MII_RT_CFG_TX_IPG0, 0xBU);
    }

    Rebuild the ENET ICSS library before testing.

    BR
    JC

  • Hi,

    Thank you for confirming and providing the fix.

    This resolves the issue, but I have one last question:

    When is the release of the SDK with the bug fix scheduled?
    Please let me know if you have any information on this, even an approximate timeline.

    Regards,
    Kazushige.

  • Hi Kazushige,

    Next release planned for 2Q'26 tentative (start/mid)

    BR
    JC

  • Hi JC,

    All my questions have been resolved. Thank you very much.

    Best Regards,
    Kazushige.