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.

AM263P4-Q1: Ethernet CPSW Policer configuration

Part Number: AM263P4-Q1
Other Parts Discussed in Thread: AM263P4, SYSCONFIG

I am using the AM263P4 LaunchPad with MCU+ SDK 10.02.15.
I am currently debugging the enet_layer2_cpsw_example and trying to configure the CPSW policer to filter frames based on a specific Source MAC address.

To achieve this, I used the function EnetApp_setCpswPolicer() function present in the l2_cpsw_cfg.c file.
I have configured it to accept frames only from a particular Source MAC address.

However, during testing, I am still receiving frames from different MAC addresses as well, not just from the configured source.

Could you please help me understand:

  1. Whether any additional configuration is needed to make the policer work as a source-based filter?

  2. If there are any known limitations or specific register settings required to ensure that only frames from the given MAC address are accepted?

Additionally, I find it difficult to understand the CPSW configuration structures and parameters used in the example. Because of this, it’s challenging to write my own simplified application that performs basic frame transmission and reception using CPSW.

If there are any simple examples or documentation that explain how to perform basic CPSW frame transmission and reception (without the complex configuration structures)?

Regards

Sravanthi R.

  • Hi Team,

    Can we please help the customer out on this?

    Best Regards,

    madhurya 

  • Also could you please suggest how to receive raw ethernet frames and explain about the below registers, when the interrupt will be triggered.

    Whether the interrupt is triggered after some packets are received which is mentioned in  CPSW_REGS_INT_SS_C0_TH_THRESH_PULSE_EN_REG Register  as threshold level or Number of packets we mention in system config for one DMA Tx channel. 

    Regards

    Sravanthi R.

  • Just a remainder for the above queries.

    Regards

    Sravanthi R.

  • Hi Sravanthi,

      I believe that you are trying to receive the packets with specific MAC address that corresponds to unicast packets.
    If so, please implement the below function in your application and call it after 'EnetApp_open'.

    void EnetApp_addUnicastMacAddr(EnetApp_PerCtxt *perCtxt, uint8_t* pUnicastMacAddr)
    {
        CpswAle_SetUcastEntryInArgs setUcastInArgs;
        uint32_t entryIdx;
        /* ALE entry with "secure" bit cleared is required for loopback */
        setUcastInArgs.addr.vlanId  = 0U;
        setUcastInArgs.info.portNum = CPSW_ALE_HOST_PORT_NUM;
        setUcastInArgs.info.blocked = false;
        setUcastInArgs.info.secure  = true;
        setUcastInArgs.info.super   = false;
        setUcastInArgs.info.ageable = false;
        setUcastInArgs.info.trunk   = false;
        EnetUtils_copyMacAddr(&setUcastInArgs.addr.addr[0U], pUnicastMacAddr);
        ENET_IOCTL_SET_INOUT_ARGS(&prms, &setUcastInArgs, &entryIdx);
    
        ENET_IOCTL(perCtxt->hEnet,  gEnetApp.coreId, CPSW_ALE_IOCTL_ADD_UCAST, &prms, status);
        if (status != ENET_SOK)
        {
            EnetAppUtils_print("Failed to add ucast entry: %d\r\n", status);
        }
    }

    Again, the above one is only for unicast MAC address. However, if you are trying to add multi-cast MAC address, it is different IOCTL (CPSW_ALE_IOCTL_ADD_MCAST).

    Thanks and regards,

    Pradeep

  • Additionally, I find it difficult to understand the CPSW configuration structures and parameters used in the example. Because of this, it’s challenging to write my own simplified application that performs basic frame transmission and reception using CPSW.

    Hi Sravanthi,
     We can help here. What is your usecase? What are the functionalites that you want to realize using CPSW? Based on this, we can provide the exact examples and details that you need.

    With regards,

    Pradeep

  • how to receive raw ethernet frames

    Hi Sravanthi,
     About above query, you do not need use work with the above low level registers to send and receive raw ethernet frames. There are easily usable driver wrappers. Please share the details on the usecase/ application. We can provide the guidelines.

    With regards,

    Pradeep

  • Hii Pradeep,

    I am trying to transmit and receive raw Ethernet frames using the CPSW peripheral on the AM263P4 in NORTOS .To start, I used the "CPSW Loopback Example(PHY End)" from the MCU+SDK 10.02.15 and the made the following configuration and code level changes.

    SysConfig Modifications

    1. Loopback Mode Disabled

      • I disabled the internal CPSW loopback mode in SysConfig to allow external frame transmission and reception via the PHY.

    2. DMA Channel Configuration

      • Configured 4 TX packets and 32 RX packets under the DMA channel settings.

    3. MAC Address Allocation

      • Selected Manual MAC address allocation instead of automatic.

    4. RTOS Variant

      • Set the RTOS variant to NoRTOS (bare-metal mode).

    5. File Generation Control

      • Disabled the automatic generation of  ti_enet_open_close.c and manually added it to the project.

      • This was required because I modified the logic to remove the PHY handler task and handle periodic PHY ticks differently. 

    Code-Level Changes

    1. Removed Task Creation

      • The original example created RTOS tasks for handling the PHY state machine and link monitoring.

      • I removed all task creation and task loop functions, since this is a NoRTOS environment.

    2. Periodic Tick Handling

      • Instead of using a separate PHY task, I call  Enet_periodicTick()  directly from a timer callback function to periodically service the CPSW/PHY, where the timer intilialization is in EnetApp_initPhyStateHandlerTask() function.

    3. Polling-Based RX/TX Logic

      • In the receive ISR callback, I set a flag (rcvd_isr = 1) whenever data is received.

      • In the main loop, I continuously poll this flag to process received frames.

      • Similarly, I set flags for TX and statistics display, which are handled based on user choice.

    4. Printf Replacement

      • After removing RTOS dependencies, the example’s EnetAppUtils_printf() function started triggering assert failures .

      • To fix this, I replaced all EnetAppUtils_printf() calls with standard printf() statements.

    After making the above changes and debugging the NoRTOS version, I found that:

    • The code gets stuck inside the following function call chain during driver initialization:

    EnetApp_driverOpen()
        ↓
        EnetAppUtils_initResourceConfig()
            ↓
            EnetAppUtils_updateMacResPart()
                ↓
                EnetAppUtils_reduceCoreMacAllocation()  ← Execution stuck here

    Attached the main.c , loopback_test.c , loopback_main.c , ti_enet_open_close.c files which i have changed.

    /*
     *  Copyright (C) 2023-2024 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    #include <stdlib.h>
    #include <kernel/dpl/DebugP.h>
    #include "ti_drivers_config.h"
    #include "ti_board_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    #include "FreeRTOS.h"
    #include "task.h"
    
    #define MAIN_TASK_PRI  (2)
    
    #define MAIN_TASK_SIZE (8192U/sizeof(configSTACK_DEPTH_TYPE))
    StackType_t gMainTaskStack[MAIN_TASK_SIZE] __attribute__((aligned(32)));
    
    StaticTask_t gMainTaskObj;
    TaskHandle_t gMainTask;
    
    void EnetLpbk_mainTask(void *args);
    
    
    int main()
    {
        /* init SOC specific modules */
        System_init();
        Board_init();
        /* Open drivers */
        Drivers_open();
        /* Open flash and board drivers */
        status = Board_driversOpen();
        DebugP_assert(status==SystemP_SUCCESS);
    
        EnetLpbk_mainTask(NULL);
    
        /* Close board and flash drivers */
        Board_driversClose();
        /* Close drivers */
        Drivers_close();
        
    
        return 0;
    }
    
    /*
     *  Copyright (c) Texas Instruments Incorporated 2020
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*!
     * \file  loopback_main.c
     *
     * \brief This file contains the main task of the Enet loopback example.
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    #include "loopback_common.h"
    #include "loopback_cfg.h"
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /* ========================================================================== */
    /*                         Structure Declarations                             */
    /* ========================================================================== */
    
    /* None */
    
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    /* None */
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    /* None */
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    void EnetLpbk_mainTask(void *args)
    {
        uint32_t i;
        int32_t status;
        Enet_MacPort macPortList[ENET_MAC_PORT_NUM];
        uint8_t numMacPorts;
    
        /* Initialize loopback test config */
        memset(&gEnetLpbk, 0, sizeof(gEnetLpbk));
        gEnetLpbk.exitFlag = false;
    
        EnetApp_getEnetInstInfo(CONFIG_ENET_CPSW0, &gEnetLpbk.enetType,
                                    &gEnetLpbk.instId);
    
        EnetApp_getEnetInstMacInfo(gEnetLpbk.enetType,
                                    gEnetLpbk.instId,
                                    macPortList,
                                    &numMacPorts);
    
        EnetAppUtils_assert(numMacPorts == 1);
        gEnetLpbk.macPort          = macPortList[0];
    
        for (i = 0U; i < ENETLPBK_NUM_ITERATION; i++)
        {
            /* Note: Clock create/delete must be done per iteration to account for
             * memory allocation (from heap) done in snprintf for code reentrancy.
             * Moving this out will result in heap memory leak error in external
             * loopback mode on A72. */
    
            printf("=============================\r\n");
            printf(" Enet Loopback: Iteration %u \r\n", i + 1);
            printf("=============================\r\n");
    
            /* Run the loopback test */
            status = EnetApp_loopbackTest();
    
            /* Sleep at end of each iteration to allow idle task to delete all terminated tasks */
            ClockP_usleep(1000);
        }
    
        return;
    }
    
    /*
     *  Copyright (c) Texas Instruments Incorporated 2022
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*!
     * \file  loopback_test.c
     *
     * \brief This file contains the loopback test implementation.
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    #include "loopback_common.h"
    #include "loopback_cfg.h"
    #include "FreeRTOS.h"
    
    /* ========================================================================== */
    /*                           Macros & Typedefs                                */
    /* ========================================================================== */
    
    /* None */
    
    /* ========================================================================== */
    /*                         Structure Declarations                             */
    /* ========================================================================== */
    
    /* None */
    
    /* ========================================================================== */
    /*                          Function Declarations                             */
    /* ========================================================================== */
    
    static void EnetApp_createRxTxTasks(void);
    
    static uint32_t EnetApp_retrieveFreeTxPkts(void);
    
    static void EnetApp_txTask(void *args);
    
    static uint32_t EnetApp_receivePkts(void);
    
    static void EnetApp_rxTask(void *args);
    
    static void EnetApp_initCpswCfg(Cpsw_Cfg *cpswCfg);
    
    static int32_t EnetApp_setupCpswAle(void);
    
    static void EnetApp_closeEnet(void);
    
    static int32_t EnetApp_showAlivePhys(void);
    
    static int32_t EnetApp_waitForLinkUp(void);
    
    static void EnetApp_showCpswStats(void);
    
    static int32_t EnetApp_macMode2PhyMii(emac_mode macMode,
                                           EnetPhy_Mii *mii);
    
    static void EnetApp_macMode2MacMii(emac_mode macMode,
                                        EnetMacPort_Interface *mii);
    
    static void EnetApp_rxIsrFxn(void *appData);
    
    static void EnetApp_txIsrFxn(void *appData);
    
    static void EnetApp_initTxFreePktQ(void);
    
    static void EnetApp_initRxReadyPktQ(void);
    
    static int32_t EnetApp_openDma(void);
    
    static void EnetApp_closeDma(void);
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    /* Test application stack */
    static uint8_t gEnetLpbkTaskStackTx[ENETLPBK_TASK_STACK_SZ] __attribute__ ((aligned(32)));
    static uint8_t gEnetLpbkTaskStackRx[ENETLPBK_TASK_STACK_SZ] __attribute__ ((aligned(32)));
    extern EnetLpbk_Obj gEnetLpbk;
    uint8_t BcastADD[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,};
    uint64_t rxPktCnt;
    uint64_t NumPktmissess;
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    int32_t EnetApp_loopbackTest(void)
    {
        int32_t status;
        EnetApp_HandleInfo handleInfo;
        Enet_IoctlPrms prms;
    
        if (gEnetLpbk.enetType == ENET_CPSW_2G)
        {
            printf("CPSW_2G Test\r\n");
        }
        if (gEnetLpbk.enetType == ENET_CPSW_3G)
        {
            printf("CPSW_3G Test\r\n");
        }
    
        EnetAppUtils_enableClocks(gEnetLpbk.enetType, gEnetLpbk.instId);
    
        /* Local core id */
        gEnetLpbk.coreId = EnetSoc_getCoreId();
    
        EnetApp_driverInit();
    
        if (status == ENET_SOK)
        {
            status = EnetApp_driverOpen(gEnetLpbk.enetType, gEnetLpbk.instId);
    
            if (status != ENET_SOK)
            {
                printf("Failed to open ENET: %d\r\n", status);
            }
        }
        gEnetLpbk.exitFlag     = false;
        gEnetLpbk.exitFlagDone = false;
    
        EnetApp_acquireHandleInfo(gEnetLpbk.enetType, gEnetLpbk.instId, &handleInfo);
        gEnetLpbk.hEnet = handleInfo.hEnet;
    
        /* Attach the core with RM */
        if (status == ENET_SOK)
        {
            EnetPer_AttachCoreOutArgs attachCoreOutArgs;
    
            EnetApp_coreAttach(gEnetLpbk.enetType, gEnetLpbk.instId, gEnetLpbk.coreId, &attachCoreOutArgs);
            gEnetLpbk.coreKey = attachCoreOutArgs.coreKey;
        }
    
        /* Open DMA driver */
        if (status == ENET_SOK)
        {
            status = EnetApp_openDma();
            if (status != ENET_SOK)
            {
                printf("Failed to open DMA: %d\r\n", status);
            }
        }
    
        if (status == ENET_SOK)
        {
            CpswAle_SetMcastEntryInArgs setMcastInArgs;
            uint32_t entryIdx;
            
            EnetUtils_copyMacAddr(&setMcastInArgs.addr.addr[0U], BcastADD);
            setMcastInArgs.info.super = false;
            setMcastInArgs.info.numIgnBits = 0;
            setMcastInArgs.info.fwdState = CPSW_ALE_FWDSTLVL_BLK_FWD_LRN;
            ENET_IOCTL_SET_INOUT_ARGS(&prms, &setMcastInArgs, &entryIdx);
    
            ENET_IOCTL(gEnetLpbk.hEnet, gEnetLpbk.coreId, CPSW_ALE_IOCTL_ADD_MCAST, &prms, status);
            if (status != ENET_SOK)
            {
                printf("Failed to add ucast entry: %d\r\n", status);
            }
        }
    
        /* Wait for link up */
        if (status == ENET_SOK)
        {
            status = EnetApp_waitForLinkUp();
        }
    
        while(1)
        {
            while(rcvdISR == 1)
            {
                EnetApp_rxTask(NULL);
    
            }
            if(tx_choice == 1)
            {
                EnetApp_txTask(NULL)
                tx_choice = 0;
            }
            if(portStatus == 1)
            {
                 EnetApp_showCpswStats();
                 portStatus = 0;
            }
            if(channelStatus == 1)
            {
                EnetAppUtils_showRxChStats(gEnetLpbk.hRxCh);
                EnetAppUtils_showTxChStats(gEnetLpbk.hTxCh);
                channelStatus = 0;
            }
        }
    
    
        /* Close Enet DMA driver */
        EnetApp_closeDma();
    
        /*Detach Core*/
        EnetApp_coreDetach(gEnetLpbk.enetType, gEnetLpbk.instId, gEnetLpbk.coreId, gEnetLpbk.coreKey);
    
        /*Release Handle Info*/
        EnetApp_releaseHandleInfo(gEnetLpbk.enetType, gEnetLpbk.instId);
        gEnetLpbk.hEnet = NULL;
    
        EnetApp_driverDeInit();
    
        /* Disable peripheral clocks */
        EnetAppUtils_disableClocks(gEnetLpbk.enetType, gEnetLpbk.instId);
    
        return status;
    }
    
    /* ========================================================================== */
    /*                   Static Function Definitions                              */
    /* ========================================================================== */
    
    
    static uint32_t EnetApp_retrieveFreeTxPkts(void)
    {
        EnetDma_PktQ txFreeQ;
        EnetDma_Pkt *pktInfo;
        int32_t status;
        uint32_t txFreeQCnt = 0U;
    
        EnetQueue_initQ(&txFreeQ);
    
        /* Retrieve any CPSW packets that may be free now */
        status = EnetDma_retrieveTxPktQ(gEnetLpbk.hTxCh, &txFreeQ);
        if (status == ENET_SOK)
        {
            txFreeQCnt = EnetQueue_getQCount(&txFreeQ);
    
            pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ);
            while (NULL != pktInfo)
            {
                EnetDma_checkPktState(&pktInfo->pktState,
                                      ENET_PKTSTATE_MODULE_APP,
                                      ENET_PKTSTATE_APP_WITH_DRIVER,
                                      ENET_PKTSTATE_APP_WITH_FREEQ);
    
                EnetQueue_enq(&gEnetLpbk.txFreePktInfoQ, &pktInfo->node);
                pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ);
            }
        }
        else
        {
            printf("retrieveFreeTxPkts() failed to retrieve pkts: %d\r\n",
                               status);
        }
    
        return txFreeQCnt;
    }
    
    static void EnetApp_txTask(void *args)
    {
        EnetDma_PktQ txSubmitQ;
        EnetDma_Pkt *pktInfo;
        EthFrame *frame;
        uint32_t txRetrievePktCnt;
        uint32_t loopCnt, pktCnt;
        int32_t status = ENET_SOK;
        uint8_t bcastAddr[ENET_MAC_ADDR_LEN] = {0xffU, 0xffU, 0xffU, 0xffU, 0xffU, 0xffU};
        uint8_t payload[20] = {0x00 , 0x01 ,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14};
    
    
        gEnetLpbk.totalTxCnt = 0U;
        for (loopCnt = 0U; loopCnt < ENETLPBK_NUM_ITERATION; loopCnt++)
        {
            pktCnt = 0U;
            
                /* Transmit a single packet */
                EnetQueue_initQ(&txSubmitQ);
    
                /* Dequeue one free TX Eth packet */
                pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&gEnetLpbk.txFreePktInfoQ);
    
                while (NULL != pktInfo)
                {
                    pktCnt++;
                    /* Fill the TX Eth frame with test content */
                    frame = (EthFrame *)pktInfo->sgList.list[0].bufPtr;
                    memcpy(frame->hdr.dstMac, bcastAddr, ENET_MAC_ADDR_LEN);
                    memcpy(frame->hdr.srcMac, &gEnetLpbk.hostMacAddr[0U], ENET_MAC_ADDR_LEN);
                    frame->hdr.etherType = Enet_htons(ETHERTYPE_EXPERIMENTAL1);
                    memset(&frame->payload[0U], (uint8_t)(0xA5 + pktCnt), ENETLPBK_TEST_PKT_LEN);
    
                    pktInfo->sgList.list[0].segmentFilledLen = ENETLPBK_TEST_PKT_LEN + sizeof(EthFrameHeader);
                    pktInfo->sgList.numScatterSegments = 1;
                    pktInfo->chkSumInfo = 0U;
                    pktInfo->appPriv    = &gEnetLpbk;
                    EnetDma_checkPktState(&pktInfo->pktState,
                                          ENET_PKTSTATE_MODULE_APP,
                                          ENET_PKTSTATE_APP_WITH_FREEQ,
                                          ENET_PKTSTATE_APP_WITH_DRIVER);
    
                    /* Enqueue the packet for later transmission */
                    EnetQueue_enq(&txSubmitQ, &pktInfo->node);
    
                    /* Dequeue one free TX Eth packet */
                    pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&gEnetLpbk.txFreePktInfoQ);
                }
    
                while (0U != EnetQueue_getQCount(&txSubmitQ))
                {
                    uint32_t txCnt = EnetQueue_getQCount(&txSubmitQ);
                    status = EnetDma_submitTxPktQ(gEnetLpbk.hTxCh,
                                                  &txSubmitQ);
        
                    /* Retrieve TX free packets */
                    if (status == ENET_SOK)
                    {
                        txCnt            = txCnt - EnetQueue_getQCount(&txSubmitQ);
                        txRetrievePktCnt = 0U;
                        while (txRetrievePktCnt != txCnt)
                        {
                            /* This is not failure as HW is busy sending packets, we
                             * need to wait and again call retrieve packets */
                            ClockP_usleep(1000);
                            txRetrievePktCnt += EnetApp_retrieveFreeTxPkts();
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            
    
            gEnetLpbk.totalTxCnt += pktCnt;
        
        }
        printf("Transmitted %d packets \r\n", gEnetLpbk.totalTxCnt);
    
    }
    
    
    static void EnetApp_rxTask(void *args)
    {
        EnetDma_Pkt *pktInfo;
        EnetDma_PktQ rxFreeQ;
        EthFrame *frame;
        int32_t status = ENET_SOK;
    
        EnetQueue_initQ(&rxFreeQ);
        EnetDma_retreiveRxPkt(gEnetLpbk.hRxCh,&pktInfo);
        while(pktInfo != NULL)
        {
            frame = (*EthFrame)pktInfo->sgList.list[0].bufPtr;
            rxPktCnt++;
            if(frame != NULL)
            {
                for(int i = 0;i<2;i++)
                {
                    printf("source mac : %d and dest mac %d",frame->hdr.srcMac[i],frame->hdr.dstMac[i]); // to know the frame source mac and dest mac
                }
    
            }
            EnetQueue_enq(&rxFreeQ,&pktInfo->node)
            EnetDma_retrieveRxPkt(gEnetLpbk.hRxCh,&pktInfo);
    
            if(pktInfo != NULL) NumPktmissess++;
    
    
        }
        rcvdISR = 0;
        EnetDma_submitRxPktQ(gEnetLpbk.hRxCh,&gEnetLpbk.rxFreeQ);
        EnetAppUtils_validatePacketState(&gEnetLpbk.rxFreeQ,ENET_PKTSTATE_APP_WITH_FREEQ,ENET_PKTSTATE_APP_WITH_DRIVER);
    }
    
        
    
    void EnetApp_updateCpswInitCfg(Enet_Type enetType,  uint32_t instId, Cpsw_Cfg *cpswCfg)
    {
        CpswHostPort_Cfg *hostPortCfg = &cpswCfg->hostPortCfg;
        CpswAle_Cfg *aleCfg = &cpswCfg->aleCfg;
        CpswCpts_Cfg *cptsCfg = &cpswCfg->cptsCfg;
    
        /* Set Enet global runtime log level */
        Enet_setTraceLevel(ENET_TRACE_DEBUG);
    
        /* Peripheral config */
        cpswCfg->vlanCfg.vlanAware = false;
    
        /* Host port config */
        hostPortCfg->removeCrc      = true;
        hostPortCfg->padShortPacket = true;
        hostPortCfg->passCrcErrors  = true;
    
        /* ALE config */
        aleCfg->modeFlags                          = CPSW_ALE_CFG_MODULE_EN;
        aleCfg->agingCfg.autoAgingEn               = true;
        aleCfg->agingCfg.agingPeriodInMs           = 1000;
        aleCfg->nwSecCfg.vid0ModeEn                = true;
        aleCfg->vlanCfg.aleVlanAwareMode           = false;
        aleCfg->vlanCfg.cpswVlanAwareMode          = false;
        aleCfg->vlanCfg.unknownUnregMcastFloodMask = CPSW_ALE_ALL_PORTS_MASK;
        aleCfg->vlanCfg.unknownRegMcastFloodMask   = CPSW_ALE_ALL_PORTS_MASK;
        aleCfg->vlanCfg.unknownVlanMemberListMask  = CPSW_ALE_ALL_PORTS_MASK;
    
        /* CPTS config */
        /* Note: Timestamping and MAC loopback are not supported together because of
         * IP limitation, so disabling timestamping for this application */
        cptsCfg->hostRxTsEn = false;
    
    }
    
    static void EnetApp_closeEnet(void)
    {
        Enet_IoctlPrms prms;
        int32_t status;
    
        /* Close port link */
        ENET_IOCTL_SET_IN_ARGS(&prms, &gEnetLpbk.macPort);
    
        ENET_IOCTL(gEnetLpbk.hEnet, gEnetLpbk.coreId, ENET_PER_IOCTL_CLOSE_PORT_LINK, &prms, status);
        if (status != ENET_SOK)
        {
            printf("Failed to close port link: %d\r\n", status);
        }
    
        /* Close Enet driver */
        Enet_close(gEnetLpbk.hEnet);
    
        gEnetLpbk.hEnet = NULL;
    }
    
    
    
    static int32_t EnetApp_waitForLinkUp(void)
    {
        Enet_IoctlPrms prms;
        bool linked = false;
        int32_t status = ENET_SOK;
    
        ENET_IOCTL_SET_INOUT_ARGS(&prms, &gEnetLpbk.macPort, &linked);
    
        while (!linked)
        {
            ENET_IOCTL(gEnetLpbk.hEnet, gEnetLpbk.coreId, ENET_PER_IOCTL_IS_PORT_LINK_UP, &prms, status);
            if (status != ENET_SOK)
            {
                printf("Failed to get port %u's link status: %d\r\n",
                                ENET_MACPORT_ID(gEnetLpbk.macPort), status);
                linked = false;
                break;
            }
    
            if (!linked)
            {
                /* wait for 50 ms and poll again*/
                ClockP_usleep(50000);
            }
        }
    
        return status;
    }
    
    static void EnetApp_showCpswStats(void)
    {
        Enet_IoctlPrms prms;
        CpswStats_PortStats portStats;
        int32_t status;
    
        /* Show host port statistics */
        ENET_IOCTL_SET_OUT_ARGS(&prms, &portStats);
        ENET_IOCTL(gEnetLpbk.hEnet, gEnetLpbk.coreId, ENET_STATS_IOCTL_GET_HOSTPORT_STATS, &prms, status);
        if (status == ENET_SOK)
        {
            printf("\r\n Port 0 Statistics\r\n");
            printf("-----------------------------------------\r\n");
            EnetAppUtils_printHostPortStats2G((CpswStats_HostPort_2g *)&portStats);
            printf("\r\n");
        }
        else
        {
            printf("Failed to get host stats: %d\r\n", status);
        }
    
        /* Show MAC port statistics */
        if (status == ENET_SOK)
        {
            ENET_IOCTL_SET_INOUT_ARGS(&prms, &gEnetLpbk.macPort, &portStats);
            ENET_IOCTL(gEnetLpbk.hEnet, gEnetLpbk.coreId, ENET_STATS_IOCTL_GET_MACPORT_STATS, &prms, status);
            if (status == ENET_SOK)
            {
                printf("\r\n Port 1 Statistics\r\n");
                printf("-----------------------------------------\r\n");
                printf((CpswStats_MacPort_2g *)&portStats);
                printf("\r\n");
            }
            else
            {
                printf("Failed to get MAC stats: %d\r\n", status);
            }
        }
    }
    
    static int32_t EnetApp_macMode2PhyMii(emac_mode macMode,
                                        EnetPhy_Mii *mii)
    {
        int32_t status = ENET_SOK;
    
        switch (macMode)
        {
            case MII:
                *mii = ENETPHY_MAC_MII_MII;
                break;
            case RMII:
                *mii = ENETPHY_MAC_MII_RMII;
                break;
    
            case RGMII:
                *mii = ENETPHY_MAC_MII_RGMII;
                break;
            default:
                status = ENET_EFAIL;
                printf("Invalid MAC mode: %u\r\n", macMode);
                EnetAppUtils_assert(false);
                break;
        }
    
        return status;
    }
    
    static void EnetApp_macMode2MacMii(emac_mode macMode,
                                        EnetMacPort_Interface *mii)
    {
        switch (macMode)
        {
            case MII:
                mii->layerType    = ENET_MAC_LAYER_MII;
                mii->sublayerType = ENET_MAC_SUBLAYER_STANDARD;
                mii->variantType  = ENET_MAC_VARIANT_NONE;
            break;
            case RMII:
                mii->layerType    = ENET_MAC_LAYER_MII;
                mii->sublayerType = ENET_MAC_SUBLAYER_REDUCED;
                mii->variantType  = ENET_MAC_VARIANT_NONE;
                break;
    
            case RGMII:
                mii->layerType    = ENET_MAC_LAYER_GMII;
                mii->sublayerType = ENET_MAC_SUBLAYER_REDUCED;
                mii->variantType  = ENET_MAC_VARIANT_FORCED;
                break;
            default:
                printf("Invalid MAC mode: %u\r\n", macMode);
                EnetAppUtils_assert(false);
                break;
        }
    }
    
    static void EnetApp_rxIsrFxn(void *appData)
    {
       rcvdISR = 1;
    }
    
    static void EnetApp_txIsrFxn(void *appData)
    {
        printf("No. of packets transmitted %d",gEnetLpbk.totalTxCnt);
    }
    
    static void EnetApp_initTxFreePktQ(void)
    {
        EnetDma_Pkt *pPktInfo;
        uint32_t i;
        uint32_t scatterSegments[] =
        {
           ENET_MEM_LARGE_POOL_PKT_SIZE,
        };
    
        /* Initialize all queues */
        EnetQueue_initQ(&gEnetLpbk.txFreePktInfoQ);
    
        /* Initialize TX EthPkts and queue them to txFreePktInfoQ */
        for (i = 0U; i < ENET_SYSCFG_TOTAL_NUM_TX_PKT; i++)
        {
            pPktInfo = EnetMem_allocEthPkt(&gEnetLpbk,
                                           ENETDMA_CACHELINE_ALIGNMENT,
                                           ENET_ARRAYSIZE(scatterSegments),
                                           scatterSegments);
            EnetAppUtils_assert(pPktInfo != NULL);
            ENET_UTILS_SET_PKT_APP_STATE(&pPktInfo->pktState, ENET_PKTSTATE_APP_WITH_FREEQ);
    
            EnetQueue_enq(&gEnetLpbk.txFreePktInfoQ, &pPktInfo->node);
        }
    
        EnetAppUtils_print("initQs() txFreePktInfoQ initialized with %d pkts\r\n",
                           EnetQueue_getQCount(&gEnetLpbk.txFreePktInfoQ));
    }
    
    static void EnetApp_initRxReadyPktQ(void)
    {
        EnetDma_PktQ rxReadyQ;
        EnetDma_Pkt *pPktInfo;
        int32_t status;
        uint32_t i;
        uint32_t scatterSegments[] =
        {
           ENET_MEM_LARGE_POOL_PKT_SIZE,
        };
    
        EnetQueue_initQ(&gEnetLpbk.rxFreeQ);
        EnetQueue_initQ(&gEnetLpbk.rxReadyQ);
        EnetQueue_initQ(&rxReadyQ);
    
        for (i = 0U; i < ENET_SYSCFG_TOTAL_NUM_RX_PKT; i++)
        {
            pPktInfo = EnetMem_allocEthPkt(&gEnetLpbk,
                                            ENETDMA_CACHELINE_ALIGNMENT,
                                            ENET_ARRAYSIZE(scatterSegments),
                                            scatterSegments);
            EnetAppUtils_assert(pPktInfo != NULL);
            ENET_UTILS_SET_PKT_APP_STATE(&pPktInfo->pktState, ENET_PKTSTATE_APP_WITH_FREEQ);
            EnetQueue_enq(&gEnetLpbk.rxFreeQ, &pPktInfo->node);
        }
    
        /* Retrieve any CPSW packets which are ready */
        status = EnetDma_retrieveRxPktQ(gEnetLpbk.hRxCh, &rxReadyQ);
        EnetAppUtils_assert(status == ENET_SOK);
        /* There should not be any packet with DMA during init */
        EnetAppUtils_assert(EnetQueue_getQCount(&rxReadyQ) == 0U);
    
        EnetAppUtils_validatePacketState(&gEnetLpbk.rxFreeQ,
                                         ENET_PKTSTATE_APP_WITH_FREEQ,
                                         ENET_PKTSTATE_APP_WITH_DRIVER);
    
        EnetDma_submitRxPktQ(gEnetLpbk.hRxCh,
                             &gEnetLpbk.rxFreeQ);
    
        /* Assert here as during init no. of DMA descriptors should be equal to
         * no. of free Ethernet buffers available with app */
    
        EnetAppUtils_assert(0U == EnetQueue_getQCount(&gEnetLpbk.rxFreeQ));
    }
    
    static int32_t EnetApp_openDma(void)
    {
        int32_t status = ENET_SOK;
    
        /* Open the CPSW TX channel  */
        if (status == ENET_SOK)
        {
            EnetApp_GetDmaHandleInArgs     txInArgs;
            EnetApp_GetTxDmaHandleOutArgs  txChInfo; 
    
            txInArgs.cbArg   = &gEnetLpbk;
            txInArgs.notifyCb = EnetApp_txIsrFxn;
    
            EnetApp_getTxDmaHandle(ENET_DMA_TX_CH0,
                                   &txInArgs,
                                   &txChInfo);
    
            gEnetLpbk.hTxCh   = txChInfo.hTxCh;
    
    
            EnetApp_initTxFreePktQ();
    
            if (NULL != gEnetLpbk.hTxCh)
            {
                status = ENET_SOK;
                if (ENET_SOK != status)
                {
                    printf("EnetUdma_startTxCh() failed: %d\r\n", status);
                    status = ENET_EFAIL;
                }
            }
            else
            {
                printf("EnetDma_openTxCh() failed to open: %d\r\n",
                                   status);
                status = ENET_EFAIL;
            }
        }
    
        /* Open the CPSW RX flow  */
        if (status == ENET_SOK)
        {
            EnetApp_GetRxDmaHandleOutArgs  rxChInfo;
            EnetApp_GetDmaHandleInArgs     rxInArgs;
    
            rxInArgs.notifyCb = EnetApp_rxIsrFxn;
            rxInArgs.cbArg   = &gEnetLpbk;
    
            EnetApp_getRxDmaHandle(ENET_DMA_RX_CH0,
                                  &rxInArgs,
                                  &rxChInfo);
            gEnetLpbk.hRxCh  = rxChInfo.hRxCh;
            EnetAppUtils_assert(rxChInfo.numValidMacAddress == 1);
            EnetUtils_copyMacAddr(gEnetLpbk.hostMacAddr, &rxChInfo.macAddr[rxChInfo.numValidMacAddress-1][0]);
            if (NULL == gEnetLpbk.hRxCh)
            {
                printf("EnetDma_openRxCh() failed to open: %d\r\n",
                                   status);
                EnetAppUtils_assert(NULL != gEnetLpbk.hRxCh);
            }
            else
            {
                /* Submit all ready RX buffers to DMA.*/
                EnetApp_initRxReadyPktQ();
            }
        }
    
        return status;
    }
    
    static void EnetApp_closeDma(void)
    {
        EnetDma_PktQ fqPktInfoQ;
        EnetDma_PktQ cqPktInfoQ;
    
        EnetQueue_initQ(&fqPktInfoQ);
        EnetQueue_initQ(&cqPktInfoQ);
    
        /* There should not be any ready packet */
        EnetAppUtils_assert(0U == EnetQueue_getQCount(&gEnetLpbk.rxReadyQ));
    
        /* Close RX channel */
        EnetApp_closeRxDma(ENET_DMA_RX_CH0,
                           gEnetLpbk.hEnet,
                           gEnetLpbk.coreKey,
                           gEnetLpbk.coreId,
                           &fqPktInfoQ,
                           &cqPktInfoQ);
    
        EnetAppUtils_freePktInfoQ(&fqPktInfoQ);
        EnetAppUtils_freePktInfoQ(&cqPktInfoQ);
    
        /* Close TX channel */
        EnetQueue_initQ(&fqPktInfoQ);
        EnetQueue_initQ(&cqPktInfoQ);
    
        EnetApp_closeTxDma(ENET_DMA_TX_CH0,
                           gEnetLpbk.hEnet,
                           gEnetLpbk.coreKey,
                           gEnetLpbk.coreId,
                           &fqPktInfoQ,
                           &cqPktInfoQ);
    
        EnetAppUtils_freePktInfoQ(&fqPktInfoQ);
        EnetAppUtils_freePktInfoQ(&cqPktInfoQ);
    
        EnetAppUtils_freePktInfoQ(&gEnetLpbk.rxFreeQ);
        EnetAppUtils_freePktInfoQ(&gEnetLpbk.txFreePktInfoQ);
    
    }
    
    /*
     *  Copyright (c) Texas Instruments Incorporated 2024
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*!
     * \file ti_enet_open_close.c
     *
     * \brief This file contains enet driver memory allocation related functionality.
     */
    
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    #include <string.h>
    #include <stdint.h>
    #include <stdarg.h>
    
    #include <enet.h>
    #include "enet_appmemutils.h"
    #include "enet_appmemutils_cfg.h"
    #include "enet_apputils.h"
    #include <enet_board.h>
    #include <enet_cfg.h>
    #include <include/core/enet_per.h>
    #include <include/core/enet_utils.h>
    #include <include/core/enet_dma.h>
    #include <include/common/enet_utils_dflt.h>
    #include <include/per/cpsw.h>
    #include <priv/per/cpsw_cpdma_priv.h>
    #include <include/core/enet_soc.h>
    #include <kernel/dpl/SemaphoreP.h>
    #include <kernel/dpl/TaskP.h>
    #include <kernel/dpl/EventP.h>
    #include <kernel/dpl/ClockP.h>
    #include <kernel/dpl/QueueP.h>
    
    #include "ti_enet_config.h"
    #include "ti_drivers_config.h"
    #include "ti_enet_open_close.h"
    #include "ti_board_config.h"
    #include <utils/include/enet_appsoc.h>
    
    #if defined(SOC_AM275X)
    #include <drivers/pinmux.h>
    void EnetApp_fixPinmux();
    #endif
    
    #define ENETAPP_PHY_STATEHANDLER_TASK_PRIORITY        (7U)
    #define ENETAPP_PHY_STATEHANDLER_TASK_STACK     (3 * 1024)
    #define AppEventId_CPSW_PERIODIC_POLL    (1 << 3)
    #define ENETAPP_NUM_IET_VERIFY_ATTEMPTS               (20U)
    
    
    
    typedef struct EnetAppTxDmaSysCfg_Obj_s
    {
        /* TX channel handle */
        EnetDma_TxChHandle hTxCh;
        /* TX channel number */
        uint32_t txChNum;
    } EnetAppTxDmaSysCfg_Obj;
    
    typedef struct EnetAppRxDmaSysCfg_Obj_s
    {
        /* RX channel handle */
        EnetDma_RxChHandle hRxCh;
        /* RX channel number */
        uint32_t rxChNum;
        /* mac Address valid */
        uint32_t numValidMacAddress;
        /* MAC address. It's port/ports MAC address in Dual-MAC or
         * host port MAC address in Switch */
        uint8_t macAddr[ENET_MAX_NUM_MAC_PER_PHER][ENET_MAC_ADDR_LEN];
    } EnetAppRxDmaSysCfg_Obj;
    
    
    static void EnetAppUtils_openTxCh(Enet_Handle hEnet,
                                      uint32_t coreKey,
                                      uint32_t coreId,
                                      uint32_t *pTxChNum,
                                      EnetDma_TxChHandle *pTxChHandle,
                                      EnetCpdma_OpenTxChPrms *pCpswTxChCfg);
    
    static void EnetAppUtils_openRxCh(Enet_Handle hEnet,
                                      uint32_t coreKey,
                                      uint32_t coreId,
                                      uint32_t *pRxChNum,
                                      EnetDma_RxChHandle *pRxChHandle,
                                      EnetCpdma_OpenRxChPrms *pCpswRxChCfg,
                                      uint32_t allocMacAddrCnt,
                                      uint8_t macAddr[ENET_MAX_NUM_MAC_PER_PHER][ENET_MAC_ADDR_LEN]);
    
    static void EnetAppUtils_setCommonRxChPrms(EnetCpdma_OpenRxChPrms *pRxChPrms);
    
    static void EnetAppUtils_setCommonTxChPrms(EnetCpdma_OpenTxChPrms *pTxChPrms);
    
    static void EnetApp_openRxDma(EnetAppRxDmaSysCfg_Obj *rx,
                                  uint32_t numRxPkts,
                                  Enet_Handle hEnet, 
                                  uint32_t coreKey,
                                  uint32_t coreId,
                                  uint32_t allocMacAddrCnt);
    
    static void EnetApp_openTxDma(EnetAppTxDmaSysCfg_Obj *tx,
                                  uint32_t numTxPkts,
                                  Enet_Handle hEnet, 
                                  uint32_t coreKey,
                                  uint32_t coreId);
    
    static void EnetAppUtils_closeTxCh(Enet_Handle hEnet,
                                       uint32_t coreKey,
                                       uint32_t coreId,
                                       EnetDma_PktQ *pFqPktInfoQ,
                                       EnetDma_PktQ *pCqPktInfoQ,
                                       EnetDma_TxChHandle hTxChHandle,
                                       uint32_t txChNum);
    
    static void EnetAppUtils_closeRxCh(Enet_Handle hEnet,
                                       uint32_t coreKey,
                                       uint32_t coreId,
                                       EnetDma_PktQ *pFqPktInfoQ,
                                       EnetDma_PktQ *pCqPktInfoQ,
                                       EnetDma_RxChHandle hRxChHandle,
                                       uint32_t rxChNum,
                                       uint32_t freeHostMacAddrCount,
                                       uint8_t macAddr[ENET_MAX_NUM_MAC_PER_PHER][ENET_MAC_ADDR_LEN]);
    
    
    
    
    typedef struct EnetAppDmaSysCfg_Obj_s
    {
        EnetAppTxDmaSysCfg_Obj tx[ENET_SYSCFG_TX_CHANNELS_NUM];
        EnetAppRxDmaSysCfg_Obj rx[ENET_SYSCFG_RX_FLOWS_NUM];
    } EnetAppDmaSysCfg_Obj;
    
    
    typedef struct EnetAppSysCfg_Obj_s
    {
    
        Enet_Handle hEnet;
    
        EnetAppDmaSysCfg_Obj dma;
    
        ClockP_Object timerObj;
    
        volatile bool timerTaskShutDownFlag;
    
        TaskP_Object task_phyStateHandlerObj;
    
        SemaphoreP_Object timerSemObj;
    
        volatile bool timerTaskShutDownDoneFlag;
    
        uint8_t appPhyStateHandlerTaskStack[ENETAPP_PHY_STATEHANDLER_TASK_STACK] __attribute__ ((aligned(32)));
    }EnetAppSysCfg_Obj;
    
    static EnetAppSysCfg_Obj gEnetAppSysCfgObj;
    
    static void EnetApp_initLinkArgs(const Enet_Type enetType,
                              const uint32_t instId,
                              const Enet_MacPort macPort,
                              const bool isInNoPhyMode,
                              EnetPer_PortLinkCfg *linkArgs);
    
    static int32_t EnetApp_enablePorts(Enet_Handle hEnet,
                                       Enet_Type enetType,
                                       uint32_t instId,
                                       uint32_t coreId,
                                       Enet_MacPort macPortList[ENET_MAC_PORT_NUM],
                                       uint8_t numMacPorts);
    
    static void EnetApp_getCpswInitCfg(Enet_Type enetType,
                                       uint32_t instId,
                                       Cpsw_Cfg *cpswCfg);
    
    static void EnetApp_getMacPortInitConfig(CpswMacPort_Cfg *pMacPortCfg, const Enet_MacPort portIdx);
    
    void EnetApp_getMacPortLinkCfg(EnetMacPort_LinkCfg *pMacPortLinkCfg, const Enet_MacPort portIdx);
    
    static void EnetApp_openDmaChannels(EnetAppDmaSysCfg_Obj *dma,
                                        Enet_Type enetType,
                                        uint32_t instId,
                                        Enet_Handle hEnet,
                                        uint32_t coreKey,
                                        uint32_t coreId);
    
    static void EnetApp_openAllRxDmaChannels(EnetAppDmaSysCfg_Obj *dma,
                                             Enet_Handle hEnet,
                                             uint32_t coreKey,
                                             uint32_t coreId);
    
    static void EnetApp_openAllTxDmaChannels(EnetAppDmaSysCfg_Obj *dma,
                                             Enet_Handle hEnet,
                                             uint32_t coreKey,
                                             uint32_t coreId);
    
    static void EnetApp_ConfigureDscpMapping(Enet_Type enetType,
                                             uint32_t instId,
                                             uint32_t coreId,
                                             Enet_MacPort macPortList[ENET_MAC_PORT_NUM],
                                             uint8_t numMacPorts);
    
    
    void EnetApp_phyStateHandler(void * appHandle);
    
    static Enet_Handle EnetApp_doCpswOpen(Enet_Type enetType, uint32_t instId, const Cpsw_Cfg *cpswCfg)
    {
        void *perCfg = NULL_PTR;
        uint32_t cfgSize;
        Enet_Handle hEnet;
    
        EnetAppUtils_assert(true == Enet_isCpswFamily(enetType));
    
        perCfg = (void *)cpswCfg;
        cfgSize = sizeof(*cpswCfg);
    
        hEnet = Enet_open(enetType, instId, perCfg, cfgSize);
        if(hEnet == NULL_PTR)
        {
            EnetAppUtils_print("Enet_open failed\r\n");
            EnetAppUtils_assert(hEnet != NULL_PTR);
        }
    
        return hEnet;
    }
    
    
    static void EnetApp_timerCb(ClockP_Object *clkInst, void * appHandle)
    {
       EnetAppSysCfg_Obj *hEnetAppObj = (EnetAppSysCfg_Obj *)appHandle;
       Enet_periodicTick(hEnetAppObj->hEnet);
    }
    
    static int32_t EnetApp_createPhyStateHandlerTask(EnetAppSysCfg_Obj *hEnetAppObj) // FREERTOS
    {
        
            ClockP_Params clkParams;
            const uint32_t timPeriodTicks = ClockP_usecToTicks((ENETPHY_FSM_TICK_PERIOD_MS)*1000U);  // Set timer expiry time in OS ticks
    
            ClockP_Params_init(&clkParams);
            clkParams.start     = TRUE;
            clkParams.timeout   = timPeriodTicks;
            clkParams.period    = timPeriodTicks;
            clkParams.args      = &hEnetAppObj;
            clkParams.callback  = &EnetApp_timerCb;
    
            /* Creating timer and setting timer callback function*/
            status = ClockP_construct(&hEnetAppObj->timerObj ,
                                      &clkParams);
            if (status == SystemP_SUCCESS)
            {
                hEnetAppObj->timerTaskShutDownFlag = false;
            }
            else
            {
                EnetAppUtils_print("EnetApp_createClock() failed to create clock\r\n");
            }
        }
        return status;
    
    }
    
    void EnetApp_driverInit()
    {
    /* keep this implementation that is generic across enetType and instId.
     * Initialization should be done only once.
     */
        int32_t status = ENET_SOK;
        EnetOsal_Cfg osalPrms;
        EnetUtils_Cfg utilsPrms;
    
        /* Initialize Enet driver with default OSAL, utils */
        Enet_initOsalCfg(&osalPrms);
        Enet_initUtilsCfg(&utilsPrms);
        Enet_init(&osalPrms, &utilsPrms);
    
        status = EnetMem_init();
        EnetAppUtils_assert(ENET_SOK == status);
        #if defined(SOC_AM275X)
        EnetApp_fixPinmux();
        #endif
    }
    
    void EnetApp_driverDeInit()
    {
    /* keep this implementation that is generic across enetType and instId.
     * Denitialization should be done only once.
     */
    
        EnetMem_deInit();
        Enet_deinit();
    }
    
    int32_t EnetApp_driverOpen(Enet_Type enetType, uint32_t instId)
    {
        int32_t status = ENET_SOK;
        Cpsw_Cfg cpswCfg;
        Enet_MacPort macPortList[ENET_MAC_PORT_NUM];
        uint8_t numMacPorts;
        uint32_t selfCoreId;
        EnetRm_ResCfg *resCfg = &cpswCfg.resCfg;
        EnetApp_HandleInfo handleInfo;
        EnetPer_AttachCoreOutArgs attachInfo;
    
        EnetCpdma_Cfg dmaCfg;
        
        EnetAppUtils_assert(Enet_isCpswFamily(enetType) == true);
        EnetApp_getEnetInstMacInfo(enetType, instId, macPortList, &numMacPorts);
    
        /* Set configuration parameters */
        selfCoreId   = EnetSoc_getCoreId();
        cpswCfg.dmaCfg = (void *)&dmaCfg;
        Enet_initCfg(enetType, instId, &cpswCfg, sizeof(cpswCfg));
        cpswCfg.dmaCfg = (void *)&dmaCfg;
    
        EnetApp_getCpswInitCfg(enetType, instId, &cpswCfg);
    
        resCfg = &cpswCfg.resCfg;
        EnetAppUtils_initResourceConfig(enetType, instId, selfCoreId, resCfg);
    
        dmaCfg.maxTxChannels = ENET_SYSCFG_TX_CHANNELS_NUM;
        dmaCfg.maxRxChannels = ENET_SYSCFG_RX_FLOWS_NUM;
    
        EnetApp_updateCpswInitCfg(enetType, instId, &cpswCfg);
    
    
        gEnetAppSysCfgObj.hEnet = EnetApp_doCpswOpen(enetType, instId, &cpswCfg);
        EnetAppUtils_assert(NULL != gEnetAppSysCfgObj.hEnet);
    
        EnetApp_enablePorts(gEnetAppSysCfgObj.hEnet, enetType, instId, selfCoreId, macPortList, numMacPorts);
    
        EnetApp_ConfigureDscpMapping(enetType, instId, selfCoreId, macPortList, numMacPorts);
        status = EnetApp_createPhyStateHandlerTask(&gEnetAppSysCfgObj);
        EnetAppUtils_assert(status == SystemP_SUCCESS);
        /* Open all DMA channels */
        EnetApp_acquireHandleInfo(enetType,
                                  instId,
                                  &handleInfo);
    
        (void)handleInfo; /* Handle info not used. Kill warning */
        EnetApp_coreAttach(enetType,
                           instId,
                           selfCoreId,
                           &attachInfo);
        EnetApp_openDmaChannels(&gEnetAppSysCfgObj.dma,
                                enetType,
                                instId,
                                gEnetAppSysCfgObj.hEnet,
                                attachInfo.coreKey,
                                selfCoreId);
        return status;
    }
    
    static void EnetApp_ConfigureDscpMapping(Enet_Type enetType,
                                             uint32_t instId,
                                             uint32_t coreId,
                                             Enet_MacPort macPortList[ENET_MAC_PORT_NUM],
                                             uint8_t numMacPorts)
    {
        Enet_IoctlPrms prms;
        int32_t status;
        EnetMacPort_SetIngressDscpPriorityMapInArgs setMacDscpInArgs;
        EnetPort_DscpPriorityMap setHostDscpInArgs;
        CpswAle_DfltThreadCfg dfltThreadCfg;
        uint32_t pri;
        uint8_t i;
    
        Enet_Handle hEnet = Enet_getHandle(enetType, instId);
        memset(&setMacDscpInArgs, 0, sizeof(setMacDscpInArgs));
        /* Each Port can have different dscp priority mapping values */
        for (i = 0U; i < numMacPorts; i++)
        {
            setMacDscpInArgs.macPort = macPortList[i];
            setMacDscpInArgs.dscpPriorityMap.dscpIPv4En = true;
            /* Example Mapping: 0 to 7  dscp values are mapped to 0 priority
             *                  8 to 15 dscp values are mapped to 1 priority
             *                  and so on
             *                  56 to 63 dscp values are mapped to 7 priority
             */
            for (pri = 0U; pri < 64U; pri++)
            {
                setMacDscpInArgs.dscpPriorityMap.tosMap[pri] = pri/8;
            }
            ENET_IOCTL_SET_IN_ARGS(&prms, &setMacDscpInArgs);
            ENET_IOCTL(hEnet, coreId, ENET_MACPORT_IOCTL_SET_INGRESS_DSCP_PRI_MAP, &prms, status);
            if (status != ENET_SOK)
            {
                EnetAppUtils_print("Failed to set dscp Priority map for Port %u - %d \r\n", macPortList[i], status);
            }
        }
    
        /* Fill the dscp priority mapping reg of host port */
        memset(&setHostDscpInArgs, 0, sizeof(setHostDscpInArgs));
        setHostDscpInArgs.dscpIPv4En = true;
        for (pri = 0U; pri < 64U; pri++)
        {
            setHostDscpInArgs.tosMap[pri] = pri/8;
        }
        ENET_IOCTL_SET_IN_ARGS(&prms, &setHostDscpInArgs);
        ENET_IOCTL(hEnet, coreId, ENET_HOSTPORT_IOCTL_SET_INGRESS_DSCP_PRI_MAP, &prms, status);
        if (status != ENET_SOK)
        {
            EnetAppUtils_print("Failed to set dscp Priority map for Host Port - %d\r\n", status);
        }
        /* Enable the p0_rx_remap_dscp_ipv4 in CPPI_P0_Control for host port, This is done through syscfg */
    
        /* Enable Channel override (in EnetApp_updateCpswInitCfg)*/
        /* Configure the default threadId */
        memset(&dfltThreadCfg, 0, sizeof(dfltThreadCfg));
        dfltThreadCfg.dfltThreadEn = true;
        dfltThreadCfg.threadId = 0;
        ENET_IOCTL_SET_IN_ARGS(&prms, &dfltThreadCfg);
        ENET_IOCTL(hEnet,
                   coreId,
                   CPSW_ALE_IOCTL_SET_DEFAULT_THREADCFG,
                   &prms,
                   status);
    }
    
    void EnetApp_macMode2MacMii(emac_mode macMode, EnetMacPort_Interface *pMii)
    {
        switch (macMode)
        {
            case MII:
            {
                pMii->layerType    = ENET_MAC_LAYER_MII;
                pMii->sublayerType = ENET_MAC_SUBLAYER_STANDARD;
                pMii->variantType  = ENET_MAC_VARIANT_NONE;
                break;
            }
            case RMII:
            {
                pMii->layerType    = ENET_MAC_LAYER_MII;
                pMii->sublayerType = ENET_MAC_SUBLAYER_REDUCED;
                pMii->variantType  = ENET_MAC_VARIANT_NONE;
                break;
            }
            case RGMII:
            {
                pMii->layerType    = ENET_MAC_LAYER_GMII;
                pMii->sublayerType = ENET_MAC_SUBLAYER_REDUCED;
                pMii->variantType  = ENET_MAC_VARIANT_FORCED;
                break;
            }
            default:
            {
                EnetAppUtils_print("Invalid MAC mode: %u\r\n", macMode);
                EnetAppUtils_assert(false);
            }
        }
    }
    
    static void EnetApp_initLinkArgs(const Enet_Type enetType,
                              const uint32_t instId,
                              const Enet_MacPort macPort,
                              const bool isInNoPhyMode,
                              EnetPer_PortLinkCfg *pLinkArgs)
    {
        EnetMacPort_LinkCfg *pLinkCfg = &pLinkArgs->linkCfg;
        int32_t status = ENET_SOK;
        EnetAppUtils_print("Open MAC port %u\r\n", ENET_MACPORT_ID(macPort));
    
        /* Set port link params */
        pLinkArgs->macPort = macPort;
        EnetBoard_getMiiConfig(&pLinkArgs->mii);
        EnetApp_getMacPortLinkCfg(pLinkCfg, macPort);
    
        /* Setup board for requested Ethernet port */
        EnetBoard_EthPort ethPort =
        {
           .enetType = enetType,
           .instId   = instId,
           .macPort  = macPort,
           .boardId  = EnetBoard_getId(),
           .mii      = pLinkArgs->mii,
        };
        status = EnetBoard_setupPorts(&ethPort, 1U);
        if (status != ENET_SOK)
        {
            EnetAppUtils_print("Failed to setup MAC port %u\r\n", ENET_MACPORT_ID(macPort));
            EnetAppUtils_assert(false);
        }
    
        EnetPhy_Cfg *pPhyCfg = &pLinkArgs->phyCfg;
        EnetPhy_initCfg(pPhyCfg);
    
        if (isInNoPhyMode)
        {
            /* In No-PHY MODE, speed and duplexity can not be in AUTO */
    
            /* In No-PHY mode, speed of 10M is not possible to operate,
             * as 10M needs in-band isignalling from PHY to set MAC port clock speed.
             * Hence, only 100M and 1G is supported in No-PHY mode */
    
            pPhyCfg->phyAddr    = ENETPHY_INVALID_PHYADDR;
            pLinkCfg->speed     = (pLinkArgs->mii.layerType == ENET_MAC_LAYER_GMII) ? ENET_SPEED_1GBIT : ENET_SPEED_100MBIT;
            pLinkCfg->duplexity = ENET_DUPLEX_FULL;
            EnetAppUtils_print("Setting in NO-PHY mode for MAC port %u\r\n", ENET_MACPORT_ID(macPort));
        }
        else
        {
            const EnetBoard_PhyCfg* pBoardPhyCfg = EnetBoard_getPhyCfg(&ethPort);
            if (pBoardPhyCfg != NULL)
            {
                pPhyCfg->phyAddr     = pBoardPhyCfg->phyAddr;
                pPhyCfg->isStrapped  = pBoardPhyCfg->isStrapped;
                pPhyCfg->loopbackEn  = true;
                pPhyCfg->skipExtendedCfg = pBoardPhyCfg->skipExtendedCfg;
                pPhyCfg->extendedCfgSize = pBoardPhyCfg->extendedCfgSize;
                memcpy(pPhyCfg->extendedCfg, pBoardPhyCfg->extendedCfg, pPhyCfg->extendedCfgSize);
            }
            else
            {
                EnetAppUtils_print("No PHY configuration found for MAC port %u\r\n", ENET_MACPORT_ID(macPort));
                EnetAppUtils_assert(false);
            }
        }
    
    }
    
    static int32_t EnetApp_enablePorts(Enet_Handle hEnet,
                                       Enet_Type enetType,
                                       uint32_t instId,
                                       uint32_t coreId,
                                       Enet_MacPort macPortList[ENET_MAC_PORT_NUM],
                                       uint8_t numMacPorts)
    {
        int32_t status = ENET_SOK;
        Enet_IoctlPrms prms;
        uint8_t i;
    
        for (i = 0U; i < numMacPorts; i++)
        {
            EnetPer_PortLinkCfg linkArgs;
            CpswMacPort_Cfg cpswMacCfg;
    
            linkArgs.macCfg = &cpswMacCfg;
            CpswMacPort_initCfg(&cpswMacCfg);
            EnetPhy_initCfg(&linkArgs.phyCfg);
    
            linkArgs.macPort = macPortList[i];
            EnetApp_getMacPortInitConfig(linkArgs.macCfg, macPortList[i]);
    
            /* in MAC loopback mode, we should not configure PHYs. It shall be treated as NO-PHY system */
            EnetApp_initLinkArgs(enetType, instId, macPortList[i], cpswMacCfg.loopbackEn, &linkArgs);
    
            ENET_IOCTL_SET_IN_ARGS(&prms, &linkArgs);
            ENET_IOCTL(hEnet,
                       coreId,
                       ENET_PER_IOCTL_OPEN_PORT_LINK,
                       &prms,
                       status);
            if (status != ENET_SOK)
            {
                EnetAppUtils_print("EnetApp_enablePorts() failed to open MAC port: %d\r\n", status);
            }
    
        }
    
        if ((status == ENET_SOK) && (Enet_isCpswFamily(enetType)))
        {
            CpswAle_SetPortStateInArgs setPortStateInArgs;
    
            setPortStateInArgs.portNum   = CPSW_ALE_HOST_PORT_NUM;
            setPortStateInArgs.portState = CPSW_ALE_PORTSTATE_FORWARD;
            ENET_IOCTL_SET_IN_ARGS(&prms, &setPortStateInArgs);
            prms.outArgs = NULL_PTR;
            ENET_IOCTL(hEnet,
                       coreId,
                       CPSW_ALE_IOCTL_SET_PORT_STATE,
                       &prms,
                       status);
            if (status != ENET_SOK)
            {
                EnetAppUtils_print("EnetApp_enablePorts() failed CPSW_ALE_IOCTL_SET_PORT_STATE: %d\r\n", status);
            }
            if (status == ENET_SOK)
            {
                ENET_IOCTL_SET_NO_ARGS(&prms);
                ENET_IOCTL(hEnet,
                           coreId,
                           ENET_HOSTPORT_IOCTL_ENABLE,
                           &prms,
                           status);
                if (status != ENET_SOK)
                {
                    EnetAppUtils_print("EnetApp_enablePorts() Failed to enable host port: %d\r\n", status);
                }
            }
        }
    
        /* Show alive PHYs */
        if (status == ENET_SOK)
        {
            Enet_IoctlPrms prms;
            bool alive;
            uint32_t i;
    
            for (i = 0U; i < ENET_MDIO_PHY_CNT_MAX; i++)
            {
                ENET_IOCTL_SET_INOUT_ARGS(&prms, &i, &alive);
                ENET_IOCTL(hEnet,
                           coreId,
                           ENET_MDIO_IOCTL_IS_ALIVE,
                           &prms,
                           status);
    
                if (status == ENET_SOK)
                {
                    if (alive == true)
                    {
                        EnetAppUtils_print("PHY %d is alive\r\n", i);
                    }
                }
                else
                {
                    EnetAppUtils_print("Failed to get PHY %d alive status: %d\r\n", i, status);
                }
            }
        }
    
        return status;
    }
    
    static void EnetApp_deleteClock(EnetAppSysCfg_Obj *hEnetAppObj)
    {
    
        hEnetAppObj->timerTaskShutDownFlag = true;
    
        ClockP_stop(&hEnetAppObj->timerObj);
    
        /* Post Timer Sem once to get the Periodic Tick task terminated */
        SemaphoreP_post(&hEnetAppObj->timerSemObj);
    
        do
        {
            ClockP_usleep(ClockP_ticksToUsec(1));
        } while (hEnetAppObj->timerTaskShutDownDoneFlag != true);
    
        ClockP_destruct(&hEnetAppObj->timerObj);
        SemaphoreP_destruct(&hEnetAppObj->timerSemObj);
    
    }
    void EnetApp_driverClose(Enet_Type enetType, uint32_t instId)
    {
        Enet_IoctlPrms prms;
        int32_t status;
        uint32_t selfCoreId;
        uint32_t i;
        Enet_MacPort macPortList[ENET_MAC_PORT_NUM];
        uint8_t numMacPorts;
        Enet_Handle hEnet = Enet_getHandle(enetType, instId);
    
        EnetAppUtils_assert(Enet_isCpswFamily(enetType) == true);
        selfCoreId   = EnetSoc_getCoreId();
        EnetApp_getEnetInstMacInfo(enetType, instId, macPortList, &numMacPorts);
        EnetApp_deleteClock(&gEnetAppSysCfgObj);
        /* Disable host port */
    	ENET_IOCTL_SET_NO_ARGS(&prms);
    	ENET_IOCTL(hEnet,
                   selfCoreId,
                   ENET_HOSTPORT_IOCTL_DISABLE,
                   &prms,
                   status);
    	if (status != ENET_SOK)
    	{
    	    EnetAppUtils_print("Failed to disable host port: %d\r\n", status);
    	}
    
        for (i = 0U; i < numMacPorts; i++)
        {
            Enet_MacPort macPort = macPortList[i];
    
            ENET_IOCTL_SET_IN_ARGS(&prms, &macPort);
            ENET_IOCTL(hEnet,
                       selfCoreId,
                       ENET_PER_IOCTL_CLOSE_PORT_LINK,
                       &prms,
                       status);
            if (status != ENET_SOK)
            {
                EnetAppUtils_print("close() failed to close MAC port: %d\r\n", status);
            }
        }
    
        Enet_close(hEnet);
    }
    
    
    
    
    static uint32_t EnetApp_retrieveFreeTxPkts(EnetDma_TxChHandle hTxCh, EnetDma_PktQ *txPktInfoQ)
    {
        EnetDma_PktQ txFreeQ;
        EnetDma_Pkt *pktInfo;
        uint32_t txFreeQCnt = 0U;
        int32_t status;
    
        EnetQueue_initQ(&txFreeQ);
    
        /* Retrieve any packets that may be free now */
        status = EnetDma_retrieveTxPktQ(hTxCh, &txFreeQ);
        if (status == ENET_SOK)
        {
            txFreeQCnt = EnetQueue_getQCount(&txFreeQ);
    
            pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ);
            while (NULL != pktInfo)
            {
                EnetDma_checkPktState(&pktInfo->pktState,
                                        ENET_PKTSTATE_MODULE_APP,
                                        ENET_PKTSTATE_APP_WITH_DRIVER,
                                        ENET_PKTSTATE_APP_WITH_FREEQ);
    
                EnetQueue_enq(txPktInfoQ, &pktInfo->node);
                pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ);
            }
        }
        else
        {
            EnetAppUtils_print("retrieveFreeTxPkts() failed to retrieve pkts: %d\r\n", status);
        }
    
        return txFreeQCnt;
    }
    
    
    
    static void EnetApp_openDmaChannels(EnetAppDmaSysCfg_Obj *dma,
                                        Enet_Type enetType,
                                        uint32_t instId,
                                        Enet_Handle hEnet,
                                        uint32_t coreKey,
                                        uint32_t coreId)
    {
        EnetApp_openAllTxDmaChannels(dma,
                                     hEnet,
                                     coreKey,
                                     coreId);
        EnetApp_openAllRxDmaChannels(dma,
                                     hEnet,
                                     coreKey,
                                     coreId);
    }
    
    
    
    static void EnetApp_setPortTsEventPrms(CpswMacPort_TsEventCfg *tsPortEventCfg)
    {
        memset(tsPortEventCfg, 0, sizeof(CpswMacPort_TsEventCfg));
    
        tsPortEventCfg->txAnnexFEn = true;
        tsPortEventCfg->rxAnnexFEn = true;
        tsPortEventCfg->txHostTsEn = true;
        /* Enable ts for SYNC, PDELAY_REQUEST, PDELAY_RESPONSE */
        tsPortEventCfg->messageType = 13;
        tsPortEventCfg->seqIdOffset = 30;
        tsPortEventCfg->domainOffset = 4;
    }
    
    int32_t EnetApp_enablePortTsEvent(Enet_Handle hEnet, uint32_t coreId, uint32_t macPort[], uint32_t numPorts)
    {
        int32_t status = ENET_SOK;
        Enet_IoctlPrms prms;
        CpswMacPort_EnableTsEventInArgs enableTsEventInArgs;
        uint8_t i = 0U;
    
        EnetApp_setPortTsEventPrms(&(enableTsEventInArgs.tsEventCfg));
        for (i = 0U; i < numPorts; i++)
        {
            enableTsEventInArgs.macPort = (Enet_MacPort)macPort[i];
            ENET_IOCTL_SET_IN_ARGS(&prms, &enableTsEventInArgs);
            ENET_IOCTL(hEnet, coreId, CPSW_MACPORT_IOCTL_ENABLE_CPTS_EVENT, &prms, status);
            if (status != ENET_SOK)
            {
                EnetAppUtils_print("Enet_ioctl ENABLE_CPTS_EVENT failed %d port %d\n", status, macPort[i]);
            }
        }
    
        return status;
    }
    
    int32_t EnetApp_getRxTimeStamp(Enet_Handle hEnet, uint32_t coreId, EnetTimeSync_GetEthTimestampInArgs* inArgs, uint64_t *ts)
    {
        int32_t status = ENET_SOK;
        Enet_IoctlPrms prms;
    
        ENET_IOCTL_SET_INOUT_ARGS(&prms, inArgs, ts);
        ENET_IOCTL(hEnet, coreId, ENET_TIMESYNC_IOCTL_GET_ETH_RX_TIMESTAMP, &prms, status);
    
        return status;
    }
    
    int32_t EnetApp_setTimeStampComplete(Enet_Handle hEnet, uint32_t coreId)
    {
        int32_t status = ENET_SOK;
        /* Not supported for CPSW, the completion ioctl is only vaild for ICSSG */
        /* Need this funtion definition to align CPSW and ICSSG for TSN libs */
        return status;
    }
    
    
    
    
    
    #define ENET_SYSCFG_DEFAULT_NUM_TX_PKT                                     (16U)
    #define ENET_SYSCFG_DEFAULT_NUM_RX_PKT                                     (32U)
    
    
    
    static void EnetAppUtils_setCommonRxChPrms(EnetCpdma_OpenRxChPrms *pRxChPrms)
    {
        pRxChPrms->numRxPkts           = ENET_SYSCFG_DEFAULT_NUM_RX_PKT;
    }
    
    static void EnetAppUtils_setCommonTxChPrms(EnetCpdma_OpenTxChPrms *pTxChPrms)
    {
        pTxChPrms->numTxPkts           = ENET_SYSCFG_DEFAULT_NUM_TX_PKT;
    }
    
    static void EnetAppUtils_openTxCh(Enet_Handle hEnet,
                                      uint32_t coreKey,
                                      uint32_t coreId,
                                      uint32_t *pTxChNum,
                                      EnetDma_TxChHandle *pTxChHandle,
                                      EnetCpdma_OpenTxChPrms *pCpswTxChCfg)
    {
        EnetDma_Handle hDma = Enet_getDmaHandle(hEnet);
        int32_t status;
    
        EnetAppUtils_assert(hDma != NULL);
    
        pCpswTxChCfg->hEnet = hEnet;
        status = EnetAppUtils_allocTxCh(hEnet,
                                        coreKey,
                                        coreId,
                                        pTxChNum);
        EnetAppUtils_assert(ENET_SOK == status);
    
        pCpswTxChCfg->chNum = *pTxChNum;
    
        *pTxChHandle = EnetDma_openTxCh(hDma, (void *)pCpswTxChCfg);
        EnetAppUtils_assert(NULL != *pTxChHandle);
    }
    
    static void EnetAppUtils_closeTxCh(Enet_Handle hEnet,
                                       uint32_t coreKey,
                                       uint32_t coreId,
                                       EnetDma_PktQ *pFqPktInfoQ,
                                       EnetDma_PktQ *pCqPktInfoQ,
                                       EnetDma_TxChHandle hTxChHandle,
                                       uint32_t txChNum)
    {
        int32_t status;
    
        EnetQueue_initQ(pFqPktInfoQ);
        EnetQueue_initQ(pCqPktInfoQ);
    
        EnetDma_disableTxEvent(hTxChHandle);
        status = EnetDma_closeTxCh(hTxChHandle, pFqPktInfoQ, pCqPktInfoQ);
        EnetAppUtils_assert(ENET_SOK == status);
    
        status = EnetAppUtils_freeTxCh(hEnet,
                                       coreKey,
                                       coreId,
                                       txChNum);
        EnetAppUtils_assert(ENET_SOK == status);
    }
    
    static void EnetAppUtils_openRxCh(Enet_Handle hEnet,
                                      uint32_t coreKey,
                                      uint32_t coreId,
                                      uint32_t *pRxChNum,
                                      EnetDma_RxChHandle *pRxChHandle,
                                      EnetCpdma_OpenRxChPrms *pCpswRxChCfg,
                                      uint32_t allocMacAddrCnt,
                                      uint8_t macAddr[ENET_MAX_NUM_MAC_PER_PHER][ENET_MAC_ADDR_LEN])
    {
        EnetDma_Handle hDma = Enet_getDmaHandle(hEnet);
        int32_t status;
        uint32_t rxFlowStartIdx;
        uint32_t rxFlowIdx;
    
        EnetAppUtils_assert(hDma != NULL);
    
        pCpswRxChCfg->hEnet = hEnet;
        status = EnetAppUtils_allocRxFlow(hEnet,
                                          coreKey,
                                          coreId,
                                          &rxFlowStartIdx,
                                          &rxFlowIdx);
        EnetAppUtils_assert(status == ENET_SOK);
        pCpswRxChCfg->chNum = rxFlowIdx;
    	*pRxChNum = rxFlowIdx;
    
        *pRxChHandle = EnetDma_openRxCh(hDma, (void *)pCpswRxChCfg);
        EnetAppUtils_assert(NULL != *pRxChHandle);
    
        for (uint32_t i = 0; i < allocMacAddrCnt; i++)
        {
            status = EnetAppUtils_allocMac(hEnet,
                                           coreKey,
                                           coreId,
                                           macAddr[i]);
            EnetAppUtils_assert(ENET_SOK == status);
            EnetAppUtils_addHostPortEntry(hEnet, coreId, macAddr[i]);
        }
    }
    
    static void EnetAppUtils_closeRxCh(Enet_Handle hEnet,
                                       uint32_t coreKey,
                                       uint32_t coreId,
                                       EnetDma_PktQ *pFqPktInfoQ,
                                       EnetDma_PktQ *pCqPktInfoQ,
                                       EnetDma_RxChHandle hRxChHandle,
                                       uint32_t rxChNum,
                                       uint32_t freeHostMacAddrCount,
                                       uint8_t macAddr[ENET_MAX_NUM_MAC_PER_PHER][ENET_MAC_ADDR_LEN])
    {
        int32_t status;
    
        EnetQueue_initQ(pFqPktInfoQ);
        EnetQueue_initQ(pCqPktInfoQ);
    
        status = EnetDma_closeRxCh(hRxChHandle, pFqPktInfoQ, pCqPktInfoQ);
        EnetAppUtils_assert(ENET_SOK == status);
        for (uint32_t macAdrIdx = 0;  macAdrIdx < freeHostMacAddrCount; macAdrIdx++)
        {
            EnetAppUtils_delAddrEntry(hEnet, coreId, macAddr[macAdrIdx]);
            EnetAppUtils_freeMac(hEnet,
                                 coreKey,
                                 coreId,
                                 macAddr[macAdrIdx]);
        }
    }
    
    
    static void EnetApp_openTxDma(EnetAppTxDmaSysCfg_Obj *tx,
                                  uint32_t numTxPkts,
                                  Enet_Handle hEnet, 
                                  uint32_t coreKey,
                                  uint32_t coreId)
    {
        EnetCpdma_OpenTxChPrms txChCfg;
    
        memset(tx, 0, sizeof(*tx));
        /* Open the TX channel for Regular traffic */
        EnetDma_initTxChParams(&txChCfg);
    
        txChCfg.cbArg    = NULL;
        txChCfg.notifyCb = NULL;
    
        EnetAppUtils_setCommonTxChPrms(&txChCfg);
    
        txChCfg.numTxPkts = numTxPkts;
        EnetAppUtils_openTxCh(hEnet,
                              coreKey,
                              coreId,
                              &tx->txChNum,
                              &tx->hTxCh,
                              &txChCfg);
        return;
    }
    
    static void EnetApp_openRxDma(EnetAppRxDmaSysCfg_Obj *rx,
                                  uint32_t numRxPkts,
                                  Enet_Handle hEnet, 
                                  uint32_t coreKey,
                                  uint32_t coreId,
                                  uint32_t allocMacAddrCnt)
    {
        EnetCpdma_OpenRxChPrms rxChCfg;
    
        memset(rx, 0, sizeof(*rx));
        /* Open the TX channel for Regular traffic */
        EnetDma_initRxChParams(&rxChCfg);
    
        rxChCfg.cbArg    = NULL;
        rxChCfg.notifyCb = NULL;
    
        EnetAppUtils_setCommonRxChPrms(&rxChCfg);
    
        rxChCfg.numRxPkts = numRxPkts;
        EnetAppUtils_openRxCh(hEnet,
                              coreKey,
                              coreId,
                              &rx->rxChNum,
                              &rx->hRxCh,
                              &rxChCfg,
                              allocMacAddrCnt,
                              rx->macAddr);
    
        rx->numValidMacAddress = allocMacAddrCnt;
        return;
    }
    
    static void EnetApp_openAllTxDmaChannels(EnetAppDmaSysCfg_Obj *dma,
                                             Enet_Handle hEnet, 
                                             uint32_t coreKey,
                                             uint32_t coreId)
    {
        uint32_t txNumPkts[ENET_SYSCFG_TX_CHANNELS_NUM] = 
                               {
                                16   
                               };
        uint32_t i;
        
        for (i = 0; i < ENET_SYSCFG_TX_CHANNELS_NUM;i++)
        {
            EnetApp_openTxDma(&dma->tx[i], txNumPkts[i], hEnet, coreKey, coreId);
        }
    }
    
    static void EnetApp_openAllRxDmaChannels(EnetAppDmaSysCfg_Obj *dma,
                                             Enet_Handle hEnet, 
                                             uint32_t coreKey,
                                             uint32_t coreId)
    {
        const uint32_t rxNumPkts[ENET_SYSCFG_RX_FLOWS_NUM] =
                               {
                                32
                               };
        const uint32_t allocMacAddrCnt[ENET_SYSCFG_RX_FLOWS_NUM] = 
                               {
                                1
                               };
    
    
        for (uint32_t i = 0; i < ENET_SYSCFG_RX_FLOWS_NUM;i++)
        {
            EnetApp_openRxDma(&dma->rx[i], rxNumPkts[i], hEnet, coreKey, coreId, allocMacAddrCnt[i]);
        }
    }
    
    void EnetApp_closeTxDma(uint32_t enetTxDmaChId,
                            Enet_Handle hEnet, 
                            uint32_t coreKey,
                            uint32_t coreId,
                            EnetDma_PktQ *fqPktInfoQ,
                            EnetDma_PktQ *cqPktInfoQ)
    {
        EnetAppTxDmaSysCfg_Obj *tx;
    
        EnetAppUtils_assert(enetTxDmaChId < ENET_ARRAYSIZE(gEnetAppSysCfgObj.dma.tx));
        tx = &gEnetAppSysCfgObj.dma.tx[enetTxDmaChId];
        EnetQueue_initQ(fqPktInfoQ);
        EnetQueue_initQ(cqPktInfoQ);
        EnetApp_retrieveFreeTxPkts(tx->hTxCh, cqPktInfoQ);
        EnetAppUtils_closeTxCh(hEnet,
                               coreKey,
                               coreId,
                               fqPktInfoQ,
                               cqPktInfoQ,
                               tx->hTxCh,
                               tx->txChNum);
    
        memset(tx, 0, sizeof(*tx));
    }
    
    void EnetApp_closeRxDma(uint32_t enetRxDmaChId,
                            Enet_Handle hEnet, 
                            uint32_t coreKey,
                            uint32_t coreId,
                            EnetDma_PktQ *fqPktInfoQ,
                            EnetDma_PktQ *cqPktInfoQ)
    {
        EnetAppRxDmaSysCfg_Obj *rx;
    
        EnetAppUtils_assert(enetRxDmaChId < ENET_ARRAYSIZE(gEnetAppSysCfgObj.dma.rx));
        rx = &gEnetAppSysCfgObj.dma.rx[enetRxDmaChId];
        /* Close RX channel */
        EnetQueue_initQ(fqPktInfoQ);
        EnetQueue_initQ(cqPktInfoQ);
    
    	EnetAppUtils_closeRxCh(hEnet,
                               coreKey,
                               coreId,
                               fqPktInfoQ,
                               cqPktInfoQ,
                               rx->hRxCh,
                               rx->rxChNum,
                               rx->numValidMacAddress,
                               rx->macAddr);
    
        EnetAppSoc_releaseMacAddrList(rx->macAddr, rx->numValidMacAddress);
        memset(rx, 0, sizeof(*rx));
    }
    
    void EnetApp_getTxDmaHandle(uint32_t enetTxDmaChId,
                                const EnetApp_GetDmaHandleInArgs *inArgs,
                                EnetApp_GetTxDmaHandleOutArgs *outArgs)
    {
        int32_t status;
        EnetAppTxDmaSysCfg_Obj *tx;
        uint32_t txNumPkts[ENET_SYSCFG_TX_CHANNELS_NUM] = 
                               {
                                16   
                               };
    
        EnetAppUtils_assert(enetTxDmaChId < ENET_ARRAYSIZE(gEnetAppSysCfgObj.dma.tx));
        tx = &gEnetAppSysCfgObj.dma.tx[enetTxDmaChId];
    
        EnetAppUtils_assert(tx->hTxCh != NULL);
        status = EnetDma_registerTxEventCb(tx->hTxCh, inArgs->notifyCb, inArgs->cbArg);
        EnetAppUtils_assert(status == ENET_SOK);
        
        outArgs->hTxCh = tx->hTxCh;
        outArgs->txChNum = tx->txChNum;
        EnetAppUtils_assert(enetTxDmaChId < ENET_ARRAYSIZE(txNumPkts));
        outArgs->maxNumTxPkts = txNumPkts[enetTxDmaChId];
        return;
    }
    
    void EnetApp_getMacAddress(uint32_t enetRxDmaChId,
                                EnetApp_GetMacAddrOutArgs *outArgs)
    {
    
        EnetAppUtils_assert(enetRxDmaChId < ENET_ARRAYSIZE(gEnetAppSysCfgObj.dma.rx));
        EnetAppRxDmaSysCfg_Obj* rx = &gEnetAppSysCfgObj.dma.rx[enetRxDmaChId];
    
        outArgs->macAddressCnt = rx->numValidMacAddress;
        EnetAppUtils_assert(outArgs->macAddressCnt <= ENET_MAX_NUM_MAC_PER_PHER);
        for (uint32_t i = 0; i < outArgs->macAddressCnt; i++)
        {
            EnetUtils_copyMacAddr(outArgs->macAddr[i], rx->macAddr[i]);
        }
    
    }
    
    void EnetApp_getRxDmaHandle(uint32_t enetRxDmaChId,
                                const EnetApp_GetDmaHandleInArgs *inArgs,
                                EnetApp_GetRxDmaHandleOutArgs *outArgs)
    {
        int32_t status;
        EnetAppRxDmaSysCfg_Obj *rx;
        uint32_t rxNumPkts[ENET_SYSCFG_RX_FLOWS_NUM] = 
                               {
                                32   
                               };
    
        EnetAppUtils_assert(enetRxDmaChId < ENET_ARRAYSIZE(gEnetAppSysCfgObj.dma.rx));
        rx = &gEnetAppSysCfgObj.dma.rx[enetRxDmaChId];
    
        EnetAppUtils_assert(rx->hRxCh != NULL);
        status = EnetDma_registerRxEventCb(rx->hRxCh, inArgs->notifyCb, inArgs->cbArg);
        EnetAppUtils_assert(status == ENET_SOK);
        
        outArgs->hRxCh = rx->hRxCh;
        outArgs->rxChNum = rx->rxChNum;
        outArgs->numValidMacAddress = rx->numValidMacAddress;
        for (uint32_t i = 0; i < outArgs->numValidMacAddress; i++)
        {
            EnetUtils_copyMacAddr(outArgs->macAddr[i], rx->macAddr[i]);
        }
    
        EnetAppUtils_assert(enetRxDmaChId < ENET_ARRAYSIZE(rxNumPkts));
        outArgs->maxNumRxPkts = rxNumPkts[enetRxDmaChId];
        return;
    }
    
    
    
    #if defined(SOC_AM275X) /* This is a workaround, will be removed. */
    void EnetApp_fixPinmux()
    {
        Pinmux_PerCfg_t gPinMuxRGMII[] = {
            /* MDIO0 pin config */
            /* MDIO0_MDC -> MDIO0_MDC (V11) */
            {
                PIN_MDIO0_MDC,
                ( PIN_MODE(0) | PIN_PULL_DISABLE )
            },
            /* MDIO0_MDIO -> MDIO0_MDIO (U11) */
            {
                PIN_MDIO0_MDIO,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2 pin config */
            /* RGMII2_RD0 -> RGMII2_RD0 (U15) */
            {
                PIN_RGMII2_RD0,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_RD1 -> RGMII2_RD1 (V15) */
            {
                PIN_RGMII2_RD1,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_RD2 -> RGMII2_RD2 (W14) */
            {
                PIN_RGMII2_RD2,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_RD3 -> RGMII2_RD3 (T15) */
            {
                PIN_RGMII2_RD3,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_RXC -> RGMII2_RXC (W15) */
            {
                PIN_RGMII2_RXC,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_RX_CTL -> RGMII2_RX_CTL (V14) */
            {
                PIN_RGMII2_RX_CTL,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_TD0 -> RGMII2_TD0 (V16) */
            {
                PIN_RGMII2_TD0,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_TD1 -> RGMII2_TD1 (W16) */
            {
                PIN_RGMII2_TD1,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_TD2 -> RGMII2_TD2 (V17) */
            {
                PIN_RGMII2_TD2,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_TD3 -> RGMII2_TD3 (W18) */
            {
                PIN_RGMII2_TD3,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_TXC -> RGMII2_TXC (W17) */
            {
                PIN_RGMII2_TXC,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII2_TX_CTL -> RGMII2_TX_CTL (U16) */
            {
                PIN_RGMII2_TX_CTL,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1 pin config */
            /* RGMII1_RD0 -> RGMII1_RD0 (W11) */
            {
                PIN_RGMII1_RD0,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_RD1 -> RGMII1_RD1 (T11) */
            {
                PIN_RGMII1_RD1,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_RD2 -> RGMII1_RD2 (T12) */
            {
                PIN_RGMII1_RD2,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_RD3 -> RGMII1_RD3 (U12) */
            {
                PIN_RGMII1_RD3,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_RXC -> RGMII1_RXC (W12) */
            {
                PIN_RGMII1_RXC,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_RX_CTL -> RGMII1_RX_CTL (V12) */
            {
                PIN_RGMII1_RX_CTL,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_TD0 -> RGMII1_TD0 (U13) */
            {
                PIN_RGMII1_TD0,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_TD1 -> RGMII1_TD1 (W13) */
            {
                PIN_RGMII1_TD1,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_TD2 -> RGMII1_TD2 (T14) */
            {
                PIN_RGMII1_TD2,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_TD3 -> RGMII1_TD3 (U14) */
            {
                PIN_RGMII1_TD3,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_TXC -> RGMII1_TXC (V13) */
            {
                PIN_RGMII1_TXC,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
            /* RGMII1_TX_CTL -> RGMII1_TX_CTL (T13) */
            {
                PIN_RGMII1_TX_CTL,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DISABLE )
            },
    
            {PINMUX_END, 0U}
        };
    
        Pinmux_PerCfg_t i2cPinmuxConfig[] =
        {
            /* I2C0 pin config */
            /* I2C0_SCL -> I2C0_SCL (M3) */
            {
                PIN_I2C0_SCL,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DIRECTION  )
            },
                    /* I2C0_SDA -> I2C0_SDA (N3) */
            {
                PIN_I2C0_SDA,
                ( PIN_MODE(0) | PIN_INPUT_ENABLE | PIN_PULL_DIRECTION  )
            },
    
    
            {PINMUX_END, 0U}
        };
        Pinmux_config(gPinMuxRGMII, PINMUX_DOMAIN_ID_MAIN);
        Pinmux_config(i2cPinmuxConfig, PINMUX_DOMAIN_ID_MAIN);
    }
    #endif
    
    
    
    #include <string.h>
    
    #include <enet.h>
    #include <include/core/enet_utils.h>
    
    #include <include/core/enet_dma.h>
    #include <include/per/cpsw.h>
    
    #include "enet_appmemutils.h"
    #include "enet_appmemutils_cfg.h"
    #include "enet_apputils.h"
    
    
    
    
    static void EnetApp_initEnetLinkCbPrms(Cpsw_Cfg *cpswCfg)
    {
        cpswCfg->mdioLinkStateChangeCb     = NULL;
        cpswCfg->mdioLinkStateChangeCbArg  = NULL;
    
        cpswCfg->portLinkStatusChangeCb    = NULL;
        cpswCfg->portLinkStatusChangeCbArg = NULL;
    }
    
    static const CpswAle_Cfg enetAppCpswAleCfg =
    {
        .modeFlags = (CPSW_ALE_CFG_MODULE_EN),
        .policerGlobalCfg =
        {
            .policingEn         = false,
            .yellowDropEn       = false,
            .redDropEn          = false,
            .yellowThresh       = CPSW_ALE_POLICER_YELLOWTHRESH_DROP_PERCENT_100,
            .policerNoMatchMode = CPSW_ALE_POLICER_NOMATCH_MODE_GREEN,
            .noMatchPolicer     = {
                                      .peakRateInBitsPerSec   = 0,
                                      .commitRateInBitsPerSec = 0,
                                  }
        },
        .agingCfg =
        {
            .autoAgingEn        = true,
            .agingPeriodInMs    = 1000,
        },
        .vlanCfg =
        {
            .aleVlanAwareMode   = true,
            .cpswVlanAwareMode  = false,
            .autoLearnWithVlan  = false,
            .unknownVlanNoLearn = false,
            .unknownForceUntaggedEgressMask = (0),
            .unknownRegMcastFloodMask       = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
            .unknownUnregMcastFloodMask     = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
            .unknownVlanMemberListMask      = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
        },
        .nwSecCfg =
        {
            .hostOuiNoMatchDeny  = false,
            .vid0ModeEn          = true,
            .malformedPktCfg     = {
                                       .srcMcastDropDis = false,
                                       .badLenPktDropEn = false,
                                   },
            .ipPktCfg            = {
                                       .dfltNoFragEn          = false,
                                       .dfltNxtHdrWhitelistEn = false,
                                       .ipNxtHdrWhitelistCnt  =  0,
                                       .ipNxtHdrWhitelist     = {
                                                                  
                                                                },
                                   },
    
    
            .macAuthCfg          = {
                                       .authModeEn           = false,
                                       .macAuthDisMask       = (0 | CPSW_ALE_HOST_PORT_MASK),
                                   },
        },
        .portCfg =
        {
            [CPSW_ALE_HOST_PORT_NUM] =
            {
                .learningCfg =
                {
                    .noLearn         = false,
                    .noSaUpdateEn    = false,
                },
                .vlanCfg =
                {
                    .vidIngressCheck = false,
                    .dropUntagged    = false,
                    .dropDualVlan    = false,
                    .dropDoubleVlan  = false,
                },
                .macModeCfg =
                {
                    .macOnlyCafEn    = false,
                    .macOnlyEn       = false,
                },
                .pvidCfg =
                {
                    .vlanIdInfo      =
                    {
                        .vlanId   = 0,
                        .tagType  = ENET_VLAN_TAG_TYPE_INNER,
                    },
                    .vlanMemberList          = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
                    .unregMcastFloodMask     = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
                    .regMcastFloodMask       = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
                    .forceUntaggedEgressMask = (0),
                    .noLearnMask             = (0),
                    .vidIngressCheck         = false,
                    .limitIPNxtHdr           = false,
                    .disallowIPFrag          = false,
                },
            },
            [CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_1)] =
            {
                .learningCfg =
                {
                    .noLearn         = false,
                    .noSaUpdateEn    = false,
                },
                .vlanCfg =
                {
                    .vidIngressCheck = false,
                    .dropUntagged    = false,
                    .dropDualVlan    = false,
                    .dropDoubleVlan  = false,
                },
                .macModeCfg =
                {
                    .macOnlyCafEn    = false,
                    .macOnlyEn       = false,
                },
                .pvidCfg =
                {
                    .vlanIdInfo      =
                    {
                        .vlanId   = 0,
                        .tagType  = ENET_VLAN_TAG_TYPE_INNER,
                    },
                    .vlanMemberList          = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
                    .unregMcastFloodMask     = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
                    .regMcastFloodMask       = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
                    .forceUntaggedEgressMask = (0),
                    .noLearnMask             = (0),
                    .vidIngressCheck         = false,
                    .limitIPNxtHdr           = false,
                    .disallowIPFrag          = false,
                },
            },
            [CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_2)] =
            {
                .learningCfg =
                {
                    .noLearn         = false,
                    .noSaUpdateEn    = false,
                },
                .vlanCfg =
                {
                    .vidIngressCheck = false,
                    .dropUntagged    = false,
                    .dropDualVlan    = false,
                    .dropDoubleVlan  = false,
                },
                .macModeCfg =
                {
                    .macOnlyCafEn    = false,
                    .macOnlyEn       = false,
                },
                .pvidCfg =
                {
                    .vlanIdInfo      =
                    {
                        .vlanId   = 0,
                        .tagType  = ENET_VLAN_TAG_TYPE_INNER,
                    },
                    .vlanMemberList          = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
                    .unregMcastFloodMask     = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
                    .regMcastFloodMask       = (0 | CPSW_ALE_HOST_PORT_MASK | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) | CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_2)),
                    .forceUntaggedEgressMask = (0),
                    .noLearnMask             = (0),
                    .vidIngressCheck         = false,
                    .limitIPNxtHdr           = false,
                    .disallowIPFrag          = false,
                },
            },
        }
    
    };
    
    static const Mdio_Cfg enetAppCpswMdioCfg =
    {
        .mode               = MDIO_MODE_STATE_CHANGE_MON,
        .mdioBusFreqHz      = 2200000,
        .phyStatePollFreqHz = 22000,
        .pollEnMask         = -1,
        .c45EnMask          = 0,
        .isMaster           = true,
        .disableStateMachineOnInit = false,
    };
    
    
    static const CpswCpts_Cfg enetAppCpswCptsCfg =
    {
        .hostRxTsEn     = false,
        .tsCompPolarity = true,
        .tsRxEventsDis  = false,
        .tsGenfClrEn    = true,
        .cptsRftClkFreq = CPSW_CPTS_RFTCLK_FREQ_200MHZ,
    };
    
    static const CpswHostPort_Cfg enetAppCpswHostPortCfg =
    {
        .crcType           = ENET_CRC_ETHERNET,
        .removeCrc         = false,
        .padShortPacket    = true,
        .passCrcErrors     = false,
        .rxMtu             = 1518,
        .passPriorityTaggedUnchanged = false,
        .rxCsumOffloadEn   = true,
        .txCsumOffloadEn   = true,
        .rxVlanRemapEn     = false,
        .rxDscpIPv4RemapEn = true,
        .rxDscpIPv6RemapEn = false,
        .vlanCfg           =
        {
            .portPri = 0,
            .portCfi = false,
            .portVID = 0,
        },
        .rxPriorityType    = ENET_INGRESS_PRI_TYPE_FIXED,
        .txPriorityType    = ENET_EGRESS_PRI_TYPE_FIXED,
    };
    
    static const EnetMacPort_LinkCfg enetAppMacPortLinkCfg[] =
    {
        [ENET_MAC_PORT_1] =
        {
            ENET_SPEED_100MBIT,
            ENET_DUPLEX_FULL,
        },
        [ENET_MAC_PORT_2] =
        {
            ENET_SPEED_AUTO,
            ENET_DUPLEX_AUTO,
        }
    };
    
    static const CpswMacPort_Cfg enetAppCpswMacPortCfg[] =
    {
        [ENET_MAC_PORT_1] =
        {
            .loopbackEn = false,
            .crcType    = ENET_CRC_ETHERNET,
            .rxMtu      = 1518,
            .passPriorityTaggedUnchanged = false,
            .vlanCfg =
            {
                .portPri = 0,
                .portCfi = false,
                .portVID = 0,
            },
            .txPriorityType = ENET_EGRESS_PRI_TYPE_FIXED,
            .sgmiiMode      = ENET_MAC_SGMIIMODE_INVALID, // INVALID as SGMII is not supported in MCU+ devices
    
        },
        [ENET_MAC_PORT_2] =
        {
            .loopbackEn = false,
            .crcType    = ENET_CRC_ETHERNET,
            .rxMtu      = 1518,
            .passPriorityTaggedUnchanged = false,
            .vlanCfg =
            {
                .portPri = 0,
                .portCfi = false,
                .portVID = 0,
            },
            .txPriorityType = ENET_EGRESS_PRI_TYPE_FIXED,
            .sgmiiMode      = ENET_MAC_SGMIIMODE_INVALID, // INVALID as SGMII is not supported in MCU+ devices
    
        },
    };
    
    static void EnetApp_initAleConfig(CpswAle_Cfg *pAleCfg)
    {
        *pAleCfg = enetAppCpswAleCfg;
    }
    
    static void EnetApp_initMdioConfig(Mdio_Cfg *pMdioCfg)
    {
        *pMdioCfg = enetAppCpswMdioCfg;
    }
    
    static void EnetApp_initCptsConfig(CpswCpts_Cfg *pCptsCfg)
    {
        *pCptsCfg = enetAppCpswCptsCfg;
    }
    
    static void EnetApp_initHostPortConfig(CpswHostPort_Cfg *pHostPortCfg)
    {
        *pHostPortCfg = enetAppCpswHostPortCfg;
    }
    
    static void EnetApp_initCpdmaConfig(EnetCpdma_Cfg *pCpdmaCfg)
    {
        pCpdmaCfg->enHostRxTsFlag = false;
    
    }
    
    static void EnetApp_getCpswInitCfg(Enet_Type enetType,
                                       uint32_t instId,
                                       Cpsw_Cfg *cpswCfg)
    {
        cpswCfg->vlanCfg.vlanAware          = false;
        cpswCfg->hostPortCfg.removeCrc      = true;
        cpswCfg->hostPortCfg.padShortPacket = true;
        cpswCfg->hostPortCfg.passCrcErrors  = true;
        EnetApp_initEnetLinkCbPrms(cpswCfg);
        EnetApp_initAleConfig(&cpswCfg->aleCfg);
        EnetApp_initMdioConfig(&cpswCfg->mdioCfg);
        EnetApp_initCptsConfig(&cpswCfg->cptsCfg);
        EnetApp_initHostPortConfig(&cpswCfg->hostPortCfg);
        EnetApp_initCpdmaConfig((EnetCpdma_Cfg *)cpswCfg->dmaCfg);
    }
    
    static void EnetApp_getMacPortInitConfig(CpswMacPort_Cfg *pMacPortCfg, const Enet_MacPort portIdx)
    {
        EnetAppUtils_assert(portIdx < ENET_ARRAYSIZE(enetAppCpswMacPortCfg));
        *pMacPortCfg = enetAppCpswMacPortCfg[portIdx];
    }
    
    void EnetApp_getMacPortLinkCfg(EnetMacPort_LinkCfg *pMacPortLinkCfg, const Enet_MacPort portIdx)
    {
        EnetAppUtils_assert(portIdx < ENET_ARRAYSIZE(enetAppMacPortLinkCfg));
        *pMacPortLinkCfg = enetAppMacPortLinkCfg[portIdx];
    }
    
    static bool IsMacAddrSet(uint8_t *mac)
    {
        return ((mac[0]|mac[1]|mac[2]|mac[3]|mac[4]|mac[5]) != 0);
    }
    
    static int AddVlan(Enet_Handle hEnet, uint32_t coreId, uint32_t vlanId)
    {
        CpswAle_VlanEntryInfo inArgs;
        uint32_t outArgs;
        Enet_IoctlPrms prms;
        int32_t status = ENET_SOK;
    
        inArgs.vlanIdInfo.vlanId        = vlanId;
        inArgs.vlanIdInfo.tagType       = ENET_VLAN_TAG_TYPE_INNER;
        inArgs.vlanMemberList           = CPSW_ALE_ALL_PORTS_MASK;
        inArgs.unregMcastFloodMask      = CPSW_ALE_ALL_PORTS_MASK;
        inArgs.regMcastFloodMask        = CPSW_ALE_ALL_PORTS_MASK;
        inArgs.forceUntaggedEgressMask  = 0U;
        inArgs.noLearnMask              = 0U;
        inArgs.vidIngressCheck          = false;
        inArgs.limitIPNxtHdr            = false;
        inArgs.disallowIPFrag           = false;
    
        ENET_IOCTL_SET_INOUT_ARGS(&prms, &inArgs, &outArgs);
        ENET_IOCTL(hEnet, coreId, CPSW_ALE_IOCTL_ADD_VLAN, &prms, status);
        if (status != ENET_SOK)
        {
            EnetAppUtils_print("%s():CPSW_ALE_IOCTL_ADD_VLAN failed: %d\r\n",
                               __func__, status);
        }
        else
        {
            EnetAppUtils_print("CPSW_ALE_IOCTL_ADD_VLAN: %d\r\n", vlanId);
        }
    
        return status;
    }
    
    int32_t EnetApp_applyClassifier(Enet_Handle hEnet, uint32_t coreId, uint8_t *dstMacAddr,
                                    uint32_t vlanId, uint32_t ethType, uint32_t rxFlowIdx)
    {
        Enet_IoctlPrms prms;
        CpswAle_SetPolicerEntryOutArgs setPolicerEntryOutArgs;
        CpswAle_SetPolicerEntryInArgs setPolicerEntryInArgs;
        int32_t status;
    
        if (IsMacAddrSet(dstMacAddr) == true)
        {
            status = EnetAppUtils_addAllPortMcastMembership(hEnet, dstMacAddr);
            if (status != ENET_SOK)
            {
                EnetAppUtils_print("%s:EnetAppUtils_addAllPortMcastMembership failed: %d\r\n",
                                   "sitara-cpsw", status);
            }
        }
        memset(&setPolicerEntryInArgs, 0, sizeof (setPolicerEntryInArgs));
    
        if (ethType > 0)
        {
            setPolicerEntryInArgs.policerMatch.policerMatchEnMask |=
                CPSW_ALE_POLICER_MATCH_ETHERTYPE;
            setPolicerEntryInArgs.policerMatch.etherType = ethType;
        }
        setPolicerEntryInArgs.policerMatch.portIsTrunk = false;
        setPolicerEntryInArgs.threadIdEn = true;
        setPolicerEntryInArgs.threadId = rxFlowIdx;
    
        ENET_IOCTL_SET_INOUT_ARGS(&prms, &setPolicerEntryInArgs, &setPolicerEntryOutArgs);
        ENET_IOCTL(hEnet, coreId,
                CPSW_ALE_IOCTL_SET_POLICER, &prms, status);
    
        if (status != ENET_SOK)
        {
            EnetAppUtils_print("%s():CPSW_ALE_IOCTL_ADD_VLAN failed: %d\r\n",
                               __func__, status);
        }
        else
        {
            if (vlanId > 0)
            {
                status = AddVlan(hEnet, coreId, vlanId);
            }
        }
        return status;
    }
    
    int32_t EnetApp_filterPriorityPacketsCfg(Enet_Handle hEnet, uint32_t coreId)
    {
        EnetMacPort_SetPriorityRegenMapInArgs params;
        Enet_IoctlPrms prms;
        int32_t retVal = ENET_SOK;
    
        params.macPort = ENET_MAC_PORT_1;
    
        params.priorityRegenMap.priorityMap[0] =0U;
        for (uint32_t i = 1; i < 8U; i++)
        {
            params.priorityRegenMap.priorityMap[i] =1U;  // Map all priorities from (1 to 7) to priority 1, these packets will be received on DMA channel 1.
        }
    
        ENET_IOCTL_SET_IN_ARGS(&prms, &params);
    
        ENET_IOCTL(hEnet, coreId, ENET_MACPORT_IOCTL_SET_PRI_REGEN_MAP, &prms, retVal);
    
        return retVal;
    }
    
    
    
    

    I also observed an irregular pattern in how the RX interrupt callback is triggered during frame reception.
    Specifically, the RX ISR callback is not invoked after every single frame reception — instead, it gets triggered after a random number of received frames.

    So, I wanted to understand after how many received frames the RX interrupt is actually triggered? and why it doesn’t occur consistently for every incoming frame.

    Regards

    Sravanthi R.

  • Hii pradeep,

    Is there any update for the above query.

    Regards

    Sravanthi R.

  • Hi Sravanthi,
    Thank you very much for the details!

    Currently in SDK there is one example that demonstrates baremetal (NORTOS) for ethernet application.
    Please refer to https://software-dl.ti.com/mcu-plus-sdk/esd/AM263X/11_00_00_19/exports/docs/api_guide_am263x/EXAMPLES_ENET_LWIP_CPSW_HTTPSERVER.html example to desing the baremetal application

    Bellow are the suggestion to implement baremetal (NORTOS) application.

    1. Change in SysConfig GUI tool to select the RTOS variant as NORTOS ( I see that you have done this correctly).
    2. Bellow changes are correct:

      About:

      EnetAppUtils_reduceCoreMacAllocation()  ← Execution stuck here

      What is the exact line where Execution is stuck? Can you please give more details on 'execution' stuck - Do you see this as assert getting hit? or execption calls or it is stuck in any loop?

      With regards,

      Pradeep

  • Hii Pradeep

    In the application (loopbacktest.c), periodically call  EnetApp_phyStateHandler() at every 100 ms. 

    EnetApp_phyStateHandler() doesnt contain any code . Why to add this function ? Is there anything i have to add in the function and include it.

    And what is the purpose of the function Enet_periodicTick(). This function is defined enet.h file.

    What is the exact line where Execution is stuck? Can you please give more details on 'execution' stuck - Do you see this as assert getting hit? or execption calls or it is stuck in any loop?

    In the EnetAppUtils_reduceCoreMacAllocation()  function after the execution of EnetAppUtils_printf() statement it is asserting at an infinite while loop.

    Regards

    Sravanthi R.

  • Hii pradeep,

    Is there any update for the above queries.

    Regards

    Sravanthi R.

  • Hi Sravanthi,

    EnetApp_phyStateHandler() doesnt contain any code . Why to add this function ?

    This function is there in the sysconfig generated code. It is there in ti_enet_open_close.c Let me explain what this function does.

    It waits for a timer semaphore. This semaphore is posted by a function called EnetApp_timerCb(). This function is a call back and it registered as a callback in the function EnetApp_createPhyStateHandlerTask(). This happens as a part of enet app driver open. 

    So when the timer callback is triggered Enet_periodicTick() is called. This function calls another function called Cpsw_periodicTick(). This function checks the phy link status.

    So basically the flow is like,

    Clock timer → Callback → Posts Semaphore → Pends Semaphore by EnetApp_phyStateHandler → Calls Enet_periodicTick → Calls Cpsw_periodicTick().

    Please see the function Cpsw_periodicTick() to understand more.

    Regards,

    Aswin

  • In the EnetAppUtils_reduceCoreMacAllocation()  function after the execution of EnetAppUtils_printf() statement it is asserting at an infinite while loop.

    Apologies, I could not point out the Assert condition describes here. Is it this condition 

    EnetAppUtils_assert(reduceCount == 0); ?
  • Hi Sravanthi,


    EnetApp_phyStateHandler() doesnt contain any code . Why to add this function ? Is there anything i have to add in the function and include it.

    And what is the purpose of the function Enet_periodicTick(). This function is defined enet.h file.


    Enet Driver expects to application to call Enet_periodicTick() periodically (atleast once every 100 ms - no issues if you call it more frequently).

    In NO_RTOS case,  below is the expected generation of EnetApp_phyStateHandler() implementation.

    in generated/ti_enet_open_close.c :
    
    ...
    void EnetApp_phyStateHandler()
    {
        Enet_periodicTick(gEnetAppSysCfgObj.hEnet);
    }
    ...

    Please check this and correct.

    About,

    In the EnetAppUtils_reduceCoreMacAllocation()  function after the execution of EnetAppUtils_printf() statement it is asserting at an infinite while loop.


    I guess, EnetAppUtils_printf() would have been resulting into stack corruption. Please increase the stack size in linker.cmd application and check if the crash goes away.


    With regards,

    Pradeep

  • Hi,

    The .c files I posted earlier also include ti_enet_open_close.c. I disabled auto-generation of this file, applied my modifications manually, and added it to the project. The change I made in ti_enet_open_close.c is:

    • In EnetApp_createPhyStateHandlerTask(), I removed the PHY task creation.

    • Instead, I moved Enet_periodicTick() into the timer callback function EnetApp_timerCb().

    I guess, EnetAppUtils_printf() would have been resulting into stack corruption. Please increase the stack size in linker.cmd application and check if the crash goes away.

    However, I am using EnetAppUtils_printf() in a NORTOS implementation, and I noticed that it still gets routed to a FreeRTOS source file during execution of print statement. All the includes and compiler settings also appear to be in FreeRTOS mode, even though System Config is set to NORTOS. This makes me suspect that this mismatch may be contributing to the crash.

    Considering this, I took the main.c, loopback_main.c, and loopback_test.c files posted above and copied them into the enet_cpsw_rawhttpserver project(which is NORTOS) , replacing the existing source files of the project.

    But during debugging, I noticed that the PHY never links up.
    The function EnetApp_waitForLinkUp() always reports the PHY link as false, meaning the PHY is not getting linked at all.

    Regards

    Sravanthi R.

  • Hi Sravanthi,

    Is the nortos version of enet libs used underneath ? If you see the makefile for the example, you can see the libs are based on nortos. Is this the same for you as well ? 

    This is from the makefile of enet_cpsw_rawhttpserver example.

    Regards,

    Aswin

  • Hi Aswin,

    Considering this, I took the main.c, loopback_main.c, and loopback_test.c files posted above and copied them into the enet_cpsw_rawhttpserver project(which is NORTOS) , replacing the existing source files of the project.

    After following this method i.e replacing the .c files of the enet_cpsw_rawhttpserver example with .main.c, loopback_main.c, and loopback_test.c  files posted above. The makefile generated contains the same posted above by you.

    Problem i noticed here PHY is not getting linked.

    Regards

    Sravanthi R.

  • Hi Sravanthi,


    about-

    Problem i noticed here PHY is not getting linked.

    In no-rtos side, you have to call Enet_periodicTick();

    ```

    void EnetApp_phyStateHandler()
    {
          Enet_periodicTick(gEnetAppSysCfgObj.hEnet);
    }

    ```
    The link status is updated only with the above function call.

    So, please ensure to call this while you are waiting for linkup.

    With regards,

    Pradeep

  • Hii Pradeep,

    Thanks for the reply.

    Actually both the functions  Enet_periodicTick(gEnetAppSysCfgObj.hEnet) and  EnetApp_waitForLinkUp() checks for PHY link status right? Then i have confusion why on calling the function  Enet_periodicTick(gEnetAppSysCfgObj.hEnet) only the lnik status gets updated.

    And which function actually establishes the phy link?

    Regards

    Sravanthi R.

  • Sravanthi,

    I'm reviewing some long running e2e threads to experiment with an internal AI model to review your last questions.  I have not done any QC of the results since I'm not familiar with this topic.  Please review if it is helpful, and if not please let us know on that as well.

    Key Difference Between the Functions

    Enet_periodicTick() and EnetApp_waitForLinkUp() serve different purposes:

    1. Enet_periodicTick() - Updates PHY Status

    This function actively polls the PHY hardware and updates the internal driver state. The call chain is:

    Enet_periodicTick()
    → Cpsw_periodicTick()
    → EnetPhy_tick()
    → Reads PHY registers (e.g., MII_BMSR)
    → Updates link status in driver

    This function must be called periodically (every 100ms) to:

    • Read the actual PHY hardware registers
    • Detect link state changes (up/down)
    • Update the driver's internal link status
    • Handle PHY state machine transitions

    2. EnetApp_waitForLinkUp() - Reads Cached Status

    This function only reads the already-cached link status from the driver. It does NOT poll the PHY hardware itself. It just checks what Enet_periodicTick() last discovered.

    Which Function Establishes PHY Link?

    Neither function "establishes" the link. The physical link establishment happens automatically in hardware when:

    1. PHY is initialized (during EnetApp_driverOpen())

      • PHY registers are configured
      • Auto-negotiation is started (if enabled)
    2. Cable is connected between two devices

    3. Both sides negotiate speed/duplex settings

    4. Enet_periodicTick() detects the link is up by reading PHY status registers

    Your Issue - Why Link Doesn't Come Up

    In your NORTOS implementation, you need to call Enet_periodicTick() while waiting for link up:

    static void EnetApp_waitForLinkUp(void)
    {
    bool linkUp = false;
    while (!linkUp)
    {
    // CRITICAL: Poll PHY to update link status
    Enet_periodicTick(gEnetAppSysCfgObj.hEnet);
    // Small delay between polls
    ClockP_usleep(100000); // 100ms
    // Now check if link is up
    linkUp = EnetApp_isPortLinkUp(gEnetAppSysCfgObj.hEnet);
    }
    }

    Without calling Enet_periodicTick() in the loop, the driver never reads the PHY registers, so it never knows the link came up - even if it's physically connected!

    Summary

    • Enet_periodicTick() = Active polling of PHY hardware (updates status)
    • EnetApp_waitForLinkUp() = Passive reading of cached status
    • Link establishment = Happens in PHY hardware automatically
    • Link detection = Requires periodic calls to Enet_periodicTick()
  • Hi Sravanthi, 

    Adding on to Jason's reply, Basically EnetApp_waitForLinkUp() will check if link is obtained. This api does not directly check the phy status.

    The status of phy is checked via the phy state machine. Please see the PHY driver section in the below link,

    https://software-dl.ti.com/mcu-plus-sdk/esd/AM263PX/latest/exports/docs/api_guide_am263px/enetphy_guide_top.html

    Regrads,

    Aswin

  • Thank you for the reply. I have reviewed the above suggestions and understood them.

    Currently, the PHY is linking successfully and I am able to receive data. However, I am facing issues with transmission.

    When I submit a TX packet to DMA, the EnetApp_txIsrFxn() interrupt function is triggered as expected, but I do not see any transmitted frames in Wireshark. I have also configured the system for loopback mode, and even in this case, although the TX ISR is triggered, no data is received back.

    Additionally, I have implemented a function to block a specific unicast MAC address, but I am still receiving frames from that MAC address. This behavior is unexpected.

    I also observed that the RX interrupt is triggered for  random number of received frames. I would like to clarify whether this behavior is expected, since i am using EnetDma_retreiveRxPkt() which is called in rx ISR ,this API retrieves only one packet at a time from the buffer descriptor queue, then it may be possible that some RX frames are being overwritten or missed before they are retrieved in the application?

    Another question I have is whether it is possible to view the actual Ethernet frame data that a buffer descriptor points to, directly in the CCS memory browser, in order to verify whether data is written correctly to memory.

    Test setup and modifications performed

    To perform this test in NoRTOS (instead of FreeRTOS), I made the following changes:

    • I used the enetCpswRawHttpServer example as the base.

    • I removed the following files:

      • app_main.c

      • app_httpserver.c

      • app_cpswconfighandler.h

      • app_cpswconfighandler.c

    • I replaced them with files from the CPSW loopback example:

      • main.c

      • loopback_main.c

      • loopback_test.c

      • loopback_cfg.c

      • loopback_cfg.h

      • loopback_common.h

    • I also removed the loopback configuration in the MAC port settings from SysConfig.

    • After these changes, I built and debugged the code in CCS.

    Despite these steps, I am still facing the TX visibility issue and inconsistent RX behavior as described above.

    I have attached the above files. Please review them and suggest if any changes are required.

    Regardsproject .c files.zip

    Sravanthi R.

  • Hi Sravanthi,

    Aplogies for the delay as I was OOO. Let me check the queries and get back to you.

    When I submit a TX packet to DMA, the EnetApp_txIsrFxn() interrupt function is triggered as expected, but I do not see any transmitted frames in Wireshark. I have also configured the system for loopback mode, and even in this case, although the TX ISR is triggered, no data is received back.

    For a start, can you check the CPSW stats. How is it behaving ? Are you able to see packets going out og Mac Port and Host Port ?

    Regards,

    Aswin

  • Hi Sravanthi,

    Additionally, I have implemented a function to block a specific unicast MAC address, but I am still receiving frames from that MAC address. This behavior is unexpected.

    May I know if you are trying to block pacetts based on Destination or Source Unicast Address ?

    Regards,

    Aswin

  • Hi Aswin,

    May I know if you are trying to block pacetts based on Destination or Source Unicast Address ?

    I am trying to blockpackets based on Source Address(i.e while receiving the packets).

    For a start, can you check the CPSW stats. How is it behaving ? Are you able to see packets going out og Mac Port and Host Port ?

    No I cannot see any packets going out of Mac port/ host port.

    Regards

    Sravanthi R.

  • Hi Sravanthi,

    Is it possible for you to share the full project so that I can try it here. Would I be able to run it on a luanchpad or control card?

    Regards,

    Aswin

  • Hi Aswin,

    Actually we executes the code in systems which does not have extranet access. So thats why i have made the changes what i have executed in the .c files in CCS cloud and shared those files with system configuration also. You just need to take enetcpsw_rawhttpserver and delete the .c files present in the project and add the files which i have attached. 6747.project .c files.zip

    Regards

    Sravanthi R.,

  • Hi Sravanthi, 
    Thank you. Let me try this on my side.

    Regards,

    Aswin

  • Hi Sravanthi,

    I will check this on my side

    Also, can you once cross verify the files in the zip folder. I am getting some compilation errors.

    Regards,

    Aswin

  • Hi Aswin,

    Since these are not the exact files that I debugged  (I made the modifications needed in CCS Cloud), you are encountering compilation errors.

    I will check this once again from my side also.

    Regards

    Sravanthi R.

  • Hii Aswin,

    I am using AM263P4 LaunchPad with MCU+ SDK 10.02.15 and system configuration : 1.23.0

    Regards

    Sravanthi R.

  • Hi Sravanthi,

    I see that in the sysconfig timer is not enabled. Also the RTOS Variant is chosen as nortos.

    Is the requirement you have is to enable phy loopback on nortos? 

    Regards,

    Aswin

  • Hi Sravanthi,

    When running the example in your case, can you please get me the following details,

    Can you run the gel script cpsw_3g_statsprint_nonzero. This is in Scripts > CPSW Statistics print > cpsw_3g_statsprint_nonzero.

    Regards,

    Aswin

  • Hi Aswin,

    I have seen the cpswtx and cpswrx status they are showing as zero number of packets transmitted.

    I have attached the project file that i executed.

    CCS version used is 12.8
    MCU+SDK 10.02.15
    System Config 1.23.0

    Regards

    Sravanthi R.enet_cpsw_testing(NO_RTOS)_am263px-lp_r5fss0-0_nortos_ti-arm-clang.zip

  • Hii Aswin,

    My requirement is to operate Ethernet in a No-RTOS environment, with loopback disabled. The system should be able to transmit and receive frames simultaneously without any disturbance or interference.

    Additionally, I want to receive Ethernet frames only from a specific source MAC address, and frames from any other source should be rejected.

    Regards

    Sravanthi 

  • I have seen the cpswtx and cpswrx status they are showing as zero number of packets transmitted.

    So my understanding is that STAT_0_RXGOODFRAMES is seens as 0 ?

  • TXGOODFRAMES as zero. I am receiving some frames initially irrespective of filter of source address. But whenever i am trying to transmit the frames then receving of frames also stopped.

  • Hi Sravanthi,

    I was able to convert the enet_layer2_cpsw example to nortos. The example will receive a packet and will transmit the same packet out. May I share this example with you. I assume this will suffice the requirement.

    Regards,

    Aswin

  • Hii Aswin,

    Yes, please share the example.
    Also, could you please let me know what mistake I might have made in the project that i have shared.

    Regards

    Sravanthi

  • Hi Sravanthi,

    Plese run the example attached in the zip file. The example is a will receive a packet send from PC and will transmit it back.

    Please use the debug configuration. I have configured only debug mode.

    The expect log should be as below,

    Once the example is running, when sending some packets from PC to the device it will send it back. Please see the wireshark logs.

    In the wiresahrk logs, the packet with source Realtek comes from PC and packets with source Texas Ins are the ones returned from the device.

    I am also attaching the .outfile that I used for testing.

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/908/enet_5F00_l2_5F00_cpsw_5F00_am263px_2D00_lp_5F00_r5fss0_2D00_0_5F00_nortos_5F00_ti_2D00_arm_2D00_clang.out

    Regards,

    Aswin

  • Also, could you please let me know what mistake I might have made in the project that i have shared.

    Let me completely review the project and get back.

    Regards,

    Aswin

  • enet_l2_cpsw_am263px-lp_r5fss0-0_nortos_ti-arm-clang.zip

    Attaching the zip file of the project. Can you please run this and let me know.

    Regards,

    Aswin

  • Hi Sravanthi,

    For blocking packets with particular mac address, you can call this API and check

    void blockUniCast(void)
    {
        CpswAle_SetUcastEntryInArgs setUcastInArgs;
        uint32_t entryIdx;
        Enet_IoctlPrms prms;
        int32_t status = ENET_SOK;
        uint8_t uniCastMacAddr[6] = {0x00, 0xe0, 0x4c, 0x32, 0x79, 0x68};
    
        setUcastInArgs.addr.vlanId = 0;
        setUcastInArgs.info.portNum = CPSW_ALE_HOST_PORT_NUM;
        setUcastInArgs.info.blocked = true;
        setUcastInArgs.info.secure = false;
        setUcastInArgs.info.super = false;
        setUcastInArgs.info.ageable = false;
        setUcastInArgs.info.trunk = false;
    
        EnetUtils_copyMacAddr(&setUcastInArgs.addr.addr[0U], &uniCastMacAddr[0]);
    
        ENET_IOCTL_SET_INOUT_ARGS(&prms, &setUcastInArgs, &entryIdx);
    
        ENET_IOCTL(gEnetApp.perCtxt[0].hEnet, gEnetApp.coreId, CPSW_ALE_IOCTL_ADD_UCAST, &prms, status);
        if (status != ENET_SOK)
        {
            printf("Failed to add ucast entry: %d\r\n", status);
        }
    }

     

    You can call this under EnetApp_addMCastEntry() function in EnetApp_open().

    Please see my ALE table entry after adding this

    Cortex_R5_0: GEL Output: ---------------------------------------------
    Cortex_R5_0: GEL Output: -------CPSW3G ALE TABLE----------------------
    Cortex_R5_0: GEL Output: ---------------------------------------------
    Cortex_R5_0: GEL Output: ---------------------------------------------
    Cortex_R5_0: GEL Output: Entry 0 - Unicast
    Cortex_R5_0: GEL Output: ---------------------------------------------
    Cortex_R5_0: GEL Output: PORT_NUMBER = 0
    Cortex_R5_0: GEL Output: BLOCK = 0
    Cortex_R5_0: GEL Output: SECURE = 1
    Cortex_R5_0: GEL Output: UNICAST_TYPE = 0
    Cortex_R5_0: GEL Output: ENTRY_TYPE = 1
    Cortex_R5_0: GEL Output: UNICAST_ADDR = 0x000070FF 0x761F68EA
    Cortex_R5_0: GEL Output: ---------------------------------------------
    Cortex_R5_0: GEL Output: Entry 1 - Multicast
    Cortex_R5_0: GEL Output: ---------------------------------------------
    Cortex_R5_0: GEL Output: PORT_MASK = 0x00000007
    Cortex_R5_0: GEL Output: SUPER = 0
    Cortex_R5_0: GEL Output: MCAST_FWD_STATE = 0
    Cortex_R5_0: GEL Output: ENTRY_TYPE = 1
    Cortex_R5_0: GEL Output: MULTICAST_ADDR = 0x0000FFFF 0xFFFFFFFF
    Cortex_R5_0: GEL Output: ---------------------------------------------
    Cortex_R5_0: GEL Output: Entry 2 - Unicast
    Cortex_R5_0: GEL Output: ---------------------------------------------
    Cortex_R5_0: GEL Output: PORT_NUMBER = 0
    Cortex_R5_0: GEL Output: BLOCK = 1
    Cortex_R5_0: GEL Output: SECURE = 0
    Cortex_R5_0: GEL Output: UNICAST_TYPE = 0
    Cortex_R5_0: GEL Output: ENTRY_TYPE = 1
    Cortex_R5_0: GEL Output: UNICAST_ADDR = 0x000000E0 0x4C327968

    Please see the CPSW stats after adding this

    Cortex_R5_0: GEL Output: STATS
    Cortex_R5_0: GEL Output: --------------------------------
    Cortex_R5_0: GEL Output: PORT0 STATS
    Cortex_R5_0: GEL Output: --------------------------------
    Cortex_R5_0: GEL Output: --------------------------------
    Cortex_R5_0: GEL Output: PORT1 STATS
    Cortex_R5_0: GEL Output: --------------------------------
    Cortex_R5_0: GEL Output: STAT_1_RXGOODFRAMES = 0x00000040
    Cortex_R5_0: GEL Output: STAT_1_RXBROADCASTFRAMES = 0x0000000C
    Cortex_R5_0: GEL Output: STAT_1_RXMULTICASTFRAMES = 0x0000001A
    Cortex_R5_0: GEL Output: STAT_1_ALE_DROP = 0x00000040
    Cortex_R5_0: GEL Output: STAT_1_RXOCTETS = 0x00001A2F
    Cortex_R5_0: GEL Output: STAT_1_OCTETFRAMES64 = 0x00000026
    Cortex_R5_0: GEL Output: STAT_1_OCTETFRAMES65T127 = 0x0000000B
    Cortex_R5_0: GEL Output: STAT_1_OCTETFRAMES128T255 = 0x0000000C
    Cortex_R5_0: GEL Output: STAT_1_OCTETFRAMES256T511 = 0x00000003
    Cortex_R5_0: GEL Output: STAT_1_NETOCTETS = 0x00001A2F
    Cortex_R5_0: GEL Output: STAT_1_PORTMASK_DROP = 0x00000040
    Cortex_R5_0: GEL Output: STAT_1_ALE_BLOCK_DROP = 0x00000040
    Cortex_R5_0: GEL Output: --------------------------------
    Cortex_R5_0: GEL Output: PORT2 STATS
    Cortex_R5_0: GEL Output: --------------------------------

    This API is used only for unicast addresses and not multicast or broadcast addresses.

    Regards,

    Aswin

  • Hi Sravanthi,

        uint8_t mCastAddr[6] = {0x01,0x00,0x5E,0x00,0x00,0x01};
        EnetApp_addMCastEntry(gEnetApp.perCtxt[0].enetType, gEnetApp.perCtxt[0].instId, gEnetApp.coreId, mCastAddr, 0);

    Multicast packets can be dropped based on port mask. Please try this for blocking multicast packets. This will work for broadcast packets as well.

    Please check the cpsw stats to see the packet drops.

    Here the concept is to drop packets based on port mask. Port mask dicates to which all ports it should go to. If given as 0, it means the packet will not be forwarded to any ports.

    Regards,

    Aswin

  • Hi Sravanthi,

    Sorry for the delay, regarding rx descriptors, once the data is read from them, the desc is not expected to be set to zero. 

    Regards,

    Aswin