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.

RTOS/PROCESSOR-SDK-AM437X: PRP application fails

Part Number: PROCESSOR-SDK-AM437X
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI-RTOS

Hi,

I'm working on PRP example app with processor_sdk_rtos_am437x_3_03_00_04 on idkAM437x.

Application after initialization fail with :

Exception occurred in ThreadType_Task.
Task handle: 0x80132bc0.
Task stack base: 0x80132c10.
Task stack size: 0x2000.
R0 = 0x80134554 R8 = 0x80123e00
R1 = 0x00000000 R9 = 0xffffffff
R2 = 0x54402000 R10 = 0x80123e70
R3 = 0x54403e94 R11 = 0x00000003
R4 = 0xffffffff R12 = 0x80124088
R5 = 0xffffffff SP(R13) = 0x8004e314
R6 = 0xffffffff LR(R14) = 0x80123cf4
R7 = 0xffffffff PC(R15) = 0x80008c98
PSR = 0x80008c98
DFSR = 0x00000005 IFSR = 0x00001004
DFAR = 0x0000000c IFAR = 0xbbb9b7e8
ti.sysbios.family.arm.exc.Exception: line 205: E_dataAbort: pc = 0x80008c98, lr = 0x80123cf4.
xdc.runtime.Error.raise: terminating execution


Aplication is build with Debug option.

As far I succeeded with step debugging, it look like something go wrong in NC_NetStart function. (stack: ti_ndk_config_Global_stackThread -> NC_NetStart)

I'm surprised with problem because is "original" app provided from TI.
What should be reason?

Best Regards,
Mare

  • The RTOS team have been notified. They will respond here.
  • How can i build (setup make rule) for compiling ndk with debug flag?
    Now is hard to determent where app fail because code is optimized.

    Regards,
    Mare
  • Mare,

    Which PRU-ICSS industrial software release you are referring to? And how does your network topology look like when the exception occurs?

    Without any network cable connected, are you able to see the log "Network Added: If-1:255.255.255.255" in CCS?

    With regard to NDK debug flag, see

    2. If you want to build NDK in debug mode, you have to uncomment a couple of lines in ndk.bld

    /* Uncomment the following lines to build libraries for debug mode: */

    // Pkg.attrs.profile = "debug";

    // c6xOpts += " -g -o0 ";

    // armOpts += " -g -o0 ";

    // gnuOpts += " -g ";

    Regards, Garrett

  • Garrett,

    Which PRU-ICSS industrial software release you are referring to? 
    PRU-ICSS-HSR-PRP-DAN_01.00.02.00


    And how does your network topology look like when the exception occurs?
    For test I connect idkAm437 PRUETH0 to the local network (My PC and idkAM437 are connected to office switcher).

    Without any network cable connected, are you able to see the log "Network Added: If-1:255.255.255.255" in CCS?
    YES! 

    [CortexA9] 00000.000 
    InterNiche Portable TCP/IP, v4.01 (TI SYS/BIOS)
    
    00000.000 Copyright 1996-2013 by InterNiche Technologies. All rights reserved.
    
    Network Added: If-1:255.255.255.255


    ON SERIAL CONSOLE:

    boardName: AM43_IDK
    Version - HSR/PRP 1.0.2.0
    Board name : AM43_IDK
    Chip Revision : 1.4A
    SYS/BIOS PRP Sample application running
    Assigned IP : 255.255.255.255
    Mac Id : c4:be:84:cc:fd:c2
    
    
    IP Address : 255.255.255.255
    Mac Id : c4:be:84:cc:fd:c2
    Device config : PRP
    
    HSR/PRP Application Menu Options. Press key (Upper/Lower)
    *******************************************
    S : Show Statistics
    C : Show HSR/PRP Configuration
    N : Show Ring members/Node Table
    I : Assign IP address
    P : Show PTP/1588 status
    R : Run Rx/Tx test
    H : Help menu. Shows details on all the options
    ********************************************

    When I connect cable it fail immediately...
    If I don't connect cable it fail after 2 min but I not sure if is maybe reason my exploring in console...

     

  • I think it fail after :

    packetLength =  ((((ICSS_EmacObject*)hEMAC->object)->callBackHandle)->rxCallBack)->callBack(&rxArgs, NULL);

    line in uint32_t NIMU_ICSS_rxServiceCheck(ICSS_EmacHandle hEMAC,int32_t prioQueue) (nimu_icssSwitchEmac.c) called by NIMU_ICSS_rxServiceCheck.

    What could be reason?

    Best Regards

    Mare

  • Disassembly view of RedRxPktGet function:

    
    
     395                     hsrPrphandle->icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_0]);
    80008c98:   E591E00C            ldr        lr, [r1, #0xc]


    hsrPrphandle is NULL defined from beginning of function:
    hsrPrpHandle *hsrPrphandle = (hsrPrpHandle *) userArg ;

    userArg = null (FROM packetLength =  ((((ICSS_EmacObject*)hEMAC->object)->callBackHandle)->rxCallBack)->callBack(&rxArgs, NULL);)


    So here program file and jump to ti_sysbios_family_arm_exc_Exception_excHandlerDataAsm__I:

    Or I debug inside wrong file???

    Did I miss/forgot to setup something in project?

  • Mare,

    Have you patched pdk_am437x_1_0_6 with the files from PRU-ICSS-HSR-PRP-DAN_01.00.02.00\protocols\pdk_patches\03.03.00 and rebuild PDK? see HSR/PRP release note: processors.wiki.ti.com/.../PRU_ICSS_HSR_PRP_Release_Notes

    Note, you need to run unix2dos.exe to the patch files for icss_emac and nimu_icss before applying them to PDK, and you can individually build the modules with the option LIMIT_BOARDS="idkAM437x", see processors.wiki.ti.com/.../Rebuilding_The_PDK

    Regards, Garrett
  • Hi Garrett.

    Sorry for delay, but I was working on other issues. Now I'm back on this issue and it seems that we still have similar problem.

    I patch all files and re-build ("all")... I check source of .patch file and compare with changes of files and it seems it is done as it should be.

    Exception occurred in ThreadType_Task.
    Task handle: 0x80140cc0.
    Task stack base: 0x80140d10.
    Task stack size: 0x2000.
    R0 = 0x00000000  R8  = 0x80131f00
    R1 = 0x403048c0  R9  = 0x00000000
    R2 = 0x0000003c  R10 = 0x80131f70
    R3 = 0x00000000  R11 = 0x00000003
    R4 = 0x0000003c  R12 = 0x403048c0
    R5 = 0xffffffff  SP(R13) = 0x8005c408
    R6 = 0x80131f70  LR(R14) = 0x80131df4
    R7 = 0x0000003c  PC(R15) = 0x80087ef4
    PSR = 0x80087ef4
    DFSR = 0x00000805  IFSR = 0x00001008
    DFAR = 0x00000000  IFAR = 0x68824554
    ti.sysbios.family.arm.exc.Exception: line 205: E_dataAbort: pc = 0x80087ef4, lr = 0x80131df4.
    xdc.runtime.Error.raise: terminating execution
    

    when I step trough code it seems it fail on memcpy on 581 line in "hsrPrp_red.c" (It seems that hsrPrp_red.c is build with optimization.... don't know hot to turn off.. all other source in project is compiled as debug..??)

    memcpy((int32_t *)destAddress, (int32_t *)rd_buffer_l3_addr, rd_packet_length);

    If I start device with unplugged eth I see that IP is set on 255.255.255.255 (in .cfg was set different)
    When I assign new IP and plug eth it seems I can ping device....


    Any idea what is going on??

    Best Regards, Mare

  • Mare,

    With the PDK patch applied, you should not see any exception, can you also check if the library under pdk_am437x_1_0_6\packages\ti\drv\icss_emac\lib is re-built? note PRSDK-2475_fix_* has 3 files patched.

    Regards,
    Garrett
  • Hi Garrett!

    Double check, re-build....
    The same problem.

    If idk437x has unplugged ETH cable it starts normally. Otherwise I get known exception...
    When I start device with unplugged ETH cable and then later connect ETH and run Rx/Tx test....

    ************************End of Help Menu***************************
    
    
    
    IP Address      : 193.2.205.9
    Mac Id          : c4:be:84:cc:fd:c2
    Device config : PRP
    
    HSR/PRP Application Menu Options. Press key (Upper/Lower)
    *******************************************
    S : Show Statistics
    C : Show HSR/PRP Configuration
    N : Show Ring members/Node Table
    I : Assign IP address
    P : Show PTP/1588 status
    R : Run Rx/Tx test
    H : Help menu. Shows details on all the options
    ********************************************
    
    To configure device as Transmitter enter T or t. To configure as receiver enter R or r :
    Device configured as transmitter, sending packets now
    

    Get exception :

    Network Added: If-1:193.2.205.9
    Exception occurred in ThreadType_Task.
    Task handle: 0x8013cc00.
    Task stack base: 0x8013cc50.
    Task stack size: 0x2000.
    R0 = 0x8013b058  R8  = 0x00000064
    R1 = 0x00000064  R9  = 0x00000064
    R2 = 0x00000000  R10 = 0x801090a0
    R3 = 0x0000a05c  R11 = 0x8013b040
    R4 = 0x0000006a  R12 = 0x2000015f
    R5 = 0x8013b040  SP(R13) = 0x8005c408
    R6 = 0x800a8364  LR(R14) = 0x80131df4
    R7 = 0x00000000  PC(R15) = 0x80009900
    PSR = 0x80009900
    DFSR = 0x00000005  IFSR = 0x00001004
    DFAR = 0x00000000  IFAR = 0xbfb99fe8
    ti.sysbios.family.arm.exc.Exception: line 205: E_dataAbort: pc = 0x80009900, lr = 0x80131df4.
    xdc.runtime.Error.raise: terminating execution
    

    Where should I start looking for solution?

    nimu_icssSwitchEmac.c
    /**
     *   @file nimu_icssSwitchEmac.c
     *   @brief
     *      Contains helper functions used to implement NDK NIMU transport driver interface for ICSS
     */
    
    /* Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ 
     *
     *  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 <stdint.h>
    #include <ti/csl/hw_types.h>
    #if defined (SOC_AM335x) || defined (SOC_AM437x)
    #include <ti/csl/src/ip/mdio/V2/cslr_mdio.h>
    #include <ti/csl/src/ip/mdio/V2/csl_mdio.h>
    #include <ti/csl/src/ip/mdio/V2/csl_mdioAux.h>
    #else
    #include <ti/csl/csl_mdioAux.h>
    #endif
    
    #include "ti/transport/ndk/nimu_icss/src/nimu_icss_transport_log.h"
    #include "ti/transport/ndk/nimu_icss/src/nimu_icssSwitchEmac.h"
    #include "ti/transport/ndk/nimu_icss/nimu_icssIoctl.h"
    #include "ti/drv/icss_emac/icss_emacStatistics.h"
    #include "ti/drv/icss_emac/icss_emacStormControl.h"
    #include "ti/transport/ndk/nimu_icss/nimu_icssEth.h"
    
    #include <ti/ndk/inc/stkmain.h>
    #include <ti/ndk/inc/os/osif.h>
    
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    
    
    void NIMU_ICSS_packetInit(NIMU_IcssEmacPkt* pNimuPacket)
    {
        PBM_Handle hPkt;
        hPkt = PBM_alloc(1522U);
        if (hPkt != NULL)
        {
            PBM_setDataOffset( hPkt, 0 );
        
            pNimuPacket->AppPrivate = (uint32_t)hPkt;
            pNimuPacket->pDataBuffer  = PBM_getDataBuffer(hPkt);
            pNimuPacket->BufferLen    = PBM_getBufferLen(hPkt);
            pNimuPacket->DataOffset =  PBM_getDataOffset(hPkt);
        }
    }
    
    /**
    * @brief The function free Rx packet buffer
    * @internal
    * @param pi pointer to EMAC object
    *
    * @retval none
    */
    void NIMU_ICSS_packetShutdown(NIMU_IcssPdInfo *pi); /* misra warning */
    void NIMU_ICSS_packetShutdown(NIMU_IcssPdInfo *pi)
    {
    
        NIMU_IcssDevice* nimuDevice = (NIMU_IcssDevice*)(((ICSS_EmacObject*)((pi->nimuDrvHandle)->object))->pvtInfo);
        PBM_free( (PBM_Handle)((nimuDevice->nimuPktRx)->AppPrivate));
    }
    
    /**
    * @brief Update our local copy of the statistics
    * @internal
    * @param pd pointer to EMAC object
    *
    * @retval none
    *
    * @pre EMAC peripheral instance must be opened
    */
    static void NIMU_ICSS_updateStats(NIMU_IcssPdInfo *pd, uint8_t portNo); /* misra warning */
    static void NIMU_ICSS_updateStats(NIMU_IcssPdInfo *pd, uint8_t portNo)
    {
        uint8_t	i = 0;
        ICSS_EmacHandle icssEmacHandle = pd->nimuDrvHandle;
        NIMU_IcssDevice *nimuDevice = ((ICSS_EmacObject*)icssEmacHandle->object)->pvtInfo;
        NIMU_IcssStatistics* nimuStats = nimuDevice->nimuStat;
    	ICSS_EmacPruStatistics_t *pruStatsPtr;
    	ICSS_EmacHostStatistics_t * hostStatsPtr;
    	ICSSEMAC_IoctlCmd ioctlParams;
    
    	/*Separate logic to get Switch and Mac statistics*/
    	if(ICSS_EMAC_MODE_SWITCH == ((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg->portMask)
    	{
    		/*IOCTL Command to read Statistics to ICSSEMAC handle*/
    		ioctlParams.command = ICSS_EMAC_IOCTL_STAT_CTRL_GET;
    		ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_STATS_CTRL, ICSS_EMAC_PORT_1, (void*)&ioctlParams);
    		ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_STATS_CTRL, ICSS_EMAC_PORT_2, (void*)&ioctlParams);
    
    		pruStatsPtr = (ICSS_EmacPruStatistics_t*)(((ICSS_EmacObject*)icssEmacHandle->object)->pruStat);
    		hostStatsPtr = (ICSS_EmacHostStatistics_t*)(((ICSS_EmacObject*)icssEmacHandle->object)->hostStat);
    
    		/*Getting Host statistics*/
    		(nimuStats)->txUcast += ((hostStatsPtr)->txUcast + (hostStatsPtr + 1)->txUcast);
    		(nimuStats)->txBcast += ((hostStatsPtr)->txBcast + (hostStatsPtr + 1)->txBcast);
    		(nimuStats)->txMcast += ((hostStatsPtr)->txMcast + (hostStatsPtr + 1)->txMcast);
    		(nimuStats)->txGoodFrames += ((hostStatsPtr)->txUcast + (hostStatsPtr)->txBcast + (hostStatsPtr)->txMcast);
    		(nimuStats)->txNetOctets += ((hostStatsPtr)->txOctets + (hostStatsPtr + 1)->txOctets);
    		(nimuStats)->rxUcast+= ((hostStatsPtr)->rxUcast + (hostStatsPtr + 1)->rxUcast);
    		(nimuStats)->rxBcast += ((hostStatsPtr)->rxBcast + (hostStatsPtr + 1)->rxBcast);
    		(nimuStats)->rxMcast += ((hostStatsPtr)->rxMcast + (hostStatsPtr + 1)->rxMcast);
    		(nimuStats)->rxGoodFrames += ((hostStatsPtr)->rxUcast + (hostStatsPtr)->rxBcast + (hostStatsPtr)->rxMcast);
    		(nimuStats)->rxNetOctets += ((hostStatsPtr)->rxOctets + (hostStatsPtr + 1)->rxOctets);
            (nimuStats)->rxUnknownProtocol += ((hostStatsPtr)->rxUnknownProtocol + (hostStatsPtr + 1)->rxUnknownProtocol);
            (nimuStats)->droppedPackets = 0U;
    
    
            for( i = 0U; i < NIMU_ICSS_NUM_MAC_PORTS; i++) {
    
                (nimuStats + i + 1U)->txUcast += (pruStatsPtr + i)->txUcast;
                (nimuStats + i + 1U)->txBcast += (pruStatsPtr + i)->txBcast;
                (nimuStats + i + 1U)->txMcast += (pruStatsPtr + i)->txMcast;
                (nimuStats + i + 1U)->txGoodFrames += ((pruStatsPtr + i)->txUcast + (pruStatsPtr + i)->txBcast \
                                                 + (pruStatsPtr + i)->txMcast);
                (nimuStats + i + 1U)->txNetOctets += (pruStatsPtr + i)->txOctets;
    
                (nimuStats + i + 1U)->rxUcast += (pruStatsPtr + i)->rxUcast;
                (nimuStats + i + 1U)->rxBcast += (pruStatsPtr + i)->rxBcast;
                (nimuStats + i + 1U)->rxMcast += (pruStatsPtr + i)->rxMcast;
    
                (nimuStats + i + 1U)->rxGoodFrames += ((pruStatsPtr + i)->rxUcast + (pruStatsPtr + i)->rxBcast \
                                                  + (pruStatsPtr + i)->rxMcast);
                (nimuStats + i + 1U)->rxNetOctets += (pruStatsPtr + i)->rxOctets;
                (nimuStats + i + 1U)->rxErrorFrames += ((pruStatsPtr + i)->rxCRCFrames + (pruStatsPtr + i)->rxOverSizedFrames + (pruStatsPtr + i)->rxUnderSizedFrames
                                                    + (pruStatsPtr + i)->rxMisAlignmentFrames);
                (nimuStats + i + 1U)->rxUnknownProtocol += (hostStatsPtr + i)->rxUnknownProtocol;
                (nimuStats + i + 1U)->droppedPackets += ((pruStatsPtr + i)->stormPrevCounter + (pruStatsPtr + i)->droppedPackets);
    
                (nimuStats + i + 1U)->lateColl     += (pruStatsPtr + i)->lateColl;
                (nimuStats + i + 1U)->excessColl     += (pruStatsPtr + i)->excessColl;
                (nimuStats + i + 1U)->singleColl     += (pruStatsPtr + i)->singleColl;
                (nimuStats + i + 1U)->multiColl     += (pruStatsPtr + i)->multiColl;
                (nimuStats + i + 1U)->defTx         += (pruStatsPtr + i)->defTx;
                (nimuStats + i + 1U)->macRxError     += ((pruStatsPtr + i)->macRxError + (pruStatsPtr + i)->SFDError);
    
                }
    
            /*IOCTL Command to Clear Statistics to ICSSEMAC handle.The nimu structure holds the stat */
    		/* Increment the nimu structure values in next read */
    		ioctlParams.command = ICSS_EMAC_IOCTL_STAT_CTRL_CLEAR;
    		ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_STATS_CTRL, ICSS_EMAC_PORT_1, (void*)&ioctlParams);
    		ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_STATS_CTRL, ICSS_EMAC_PORT_2, (void*)&ioctlParams);
    	}
        else
        {
            /*IOCTL Command to read Statistics to ICSSEMAC handle*/
            ioctlParams.command = ICSS_EMAC_IOCTL_STAT_CTRL_GET;
            ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_STATS_CTRL, portNo, (void*)&ioctlParams);
    
            pruStatsPtr = (ICSS_EmacPruStatistics_t*)(((ICSS_EmacObject*)icssEmacHandle->object)->pruStat);
            hostStatsPtr = (ICSS_EmacHostStatistics_t*)(((ICSS_EmacObject*)icssEmacHandle->object)->hostStat);
    
            /*Getting Host statistics*/
            (nimuStats)->txUcast += (hostStatsPtr)->txUcast;
            (nimuStats)->txBcast += (hostStatsPtr)->txBcast;
            (nimuStats)->txMcast += (hostStatsPtr)->txMcast;
            (nimuStats)->txGoodFrames += ((hostStatsPtr)->txUcast + (hostStatsPtr)->txBcast + (hostStatsPtr)->txMcast);
            (nimuStats)->txNetOctets += (hostStatsPtr)->txOctets ;
            (nimuStats)->rxUcast+= (hostStatsPtr)->rxUcast ;
            (nimuStats)->rxBcast += (hostStatsPtr)->rxBcast ;
            (nimuStats)->rxMcast += (hostStatsPtr)->rxMcast ;
            (nimuStats)->rxGoodFrames += ((hostStatsPtr)->rxUcast + (hostStatsPtr)->rxBcast + (hostStatsPtr)->rxMcast); /* NA */
            (nimuStats)->rxNetOctets += (hostStatsPtr)->rxOctets ;
            (nimuStats)->rxUnknownProtocol += (hostStatsPtr)->rxUnknownProtocol;
            (nimuStats)->droppedPackets = 0;
    
            /*Getting Port statistics*/
            (nimuStats + 1)->txUcast += (pruStatsPtr)->txUcast;
            (nimuStats + 1)->txBcast += (pruStatsPtr)->txBcast;
            (nimuStats + 1)->txMcast += (pruStatsPtr)->txMcast;
            (nimuStats + 1)->txGoodFrames += ((pruStatsPtr)->txUcast + (pruStatsPtr)->txBcast \
                                             + (pruStatsPtr)->txMcast);
            (nimuStats + 1)->txNetOctets += (pruStatsPtr)->txOctets;
    
            (nimuStats + 1)->rxUcast += (pruStatsPtr)->rxUcast;
            (nimuStats + 1)->rxBcast += (pruStatsPtr)->rxBcast;
            (nimuStats + 1)->rxMcast += (pruStatsPtr)->rxMcast;
    
            (nimuStats + 1)->rxGoodFrames += ((pruStatsPtr)->rxUcast + (pruStatsPtr)->rxBcast \
                                              + (pruStatsPtr)->rxMcast);
            (nimuStats + 1)->rxNetOctets += (pruStatsPtr)->rxOctets;
            (nimuStats + 1)->rxErrorFrames += ((pruStatsPtr)->rxCRCFrames + (pruStatsPtr)->rxOverSizedFrames + (pruStatsPtr)->rxUnderSizedFrames
                                                + (pruStatsPtr)->rxMisAlignmentFrames);
            (nimuStats + 1)->rxUnknownProtocol += (hostStatsPtr)->rxUnknownProtocol;
            (nimuStats + 1)->droppedPackets += ((pruStatsPtr)->stormPrevCounter + (pruStatsPtr)->droppedPackets);
    
            (nimuStats + 1)->lateColl     += (pruStatsPtr)->lateColl;
            (nimuStats + 1)->excessColl     += (pruStatsPtr)->excessColl;
            (nimuStats + 1)->singleColl     += (pruStatsPtr)->singleColl;
            (nimuStats + 1)->multiColl     += (pruStatsPtr)->multiColl;
            (nimuStats + 1)->defTx         += (pruStatsPtr)->defTx;
            (nimuStats + 1)->macRxError     += ((pruStatsPtr)->macRxError + (pruStatsPtr)->SFDError);
    
    
    		/*IOCTL Command to Clear Statistics to ICSSEMAC handle.The nimu structure holds the stat */
    		/* Increment the nimu structure values in next read */
    		ioctlParams.command = ICSS_EMAC_IOCTL_STAT_CTRL_CLEAR;
    		ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_STATS_CTRL, portNo, (void*)&ioctlParams);
    	}
    }
    
    
    /**********************************************************************
     ***************** Switch Configuration Functions *********************
     **********************************************************************/
    
    
    /**
    * @internal
    * @brief Configures Address lookup engine (ALE) of EMAC.
    *
    * @param hPort       pointer to port object
    *
    * @retval none
    *
    */
    static void NIMU_ICSS_setAleCfg(ICSS_EmacHandle handle); /* misra warning */
    static void NIMU_ICSS_setAleCfg(ICSS_EmacHandle handle)
    {
        ICSSEMAC_IoctlCmd ioctlParams;
        ioctlParams.command = ICSS_EMAC_LEARN_CTRL_INIT_TABLE;
        if(ICSS_EMAC_MODE_SWITCH == (((ICSS_EmacObject*)handle->object)->emacInitcfg)->portMask)
        {
            if((((ICSS_EmacObject*)handle->object)->emacInitcfg)->learningEn)
            {
                ICSS_EmacIoctl(handle, ICSS_EMAC_IOCTL_LEARNING_CTRL, 0, (void*)&ioctlParams);
            }
        }
    }
    
    
    /**
    * @internal
    * @brief Configures Address lookup engine (ALE) of EMAC.
    *
    * @param hPort       pointer to port object
    *
    * @retval none
    *
    */
    static void NIMU_ICSS_setRateControlCfg(ICSS_EmacHandle handle); /* misra warning */
    static void NIMU_ICSS_setRateControlCfg(ICSS_EmacHandle handle)
    {
        ICSSEMAC_IoctlCmd ioctlParams;
        ioctlParams.command = ICSS_EMAC_STORM_PREV_CTRL_INIT;
    
    
        switch ((((ICSS_EmacObject*)handle->object)->emacInitcfg)->portMask)
        {
            case ICSS_EMAC_MODE_SWITCH:
            {
                ICSS_EmacIoctl(handle, ICSS_EMAC_IOCTL_STORM_PREV_CTRL, ICSS_EMAC_PORT_1, (void*)&ioctlParams);
                ICSS_EmacIoctl(handle, ICSS_EMAC_IOCTL_STORM_PREV_CTRL, ICSS_EMAC_PORT_2, (void*)&ioctlParams);
                break;
            }
            case ICSS_EMAC_MODE_MAC1:
            {
                ICSS_EmacIoctl(handle, ICSS_EMAC_IOCTL_STORM_PREV_CTRL, ICSS_EMAC_PORT_1, (void*)&ioctlParams);
                break;
            }
            case ICSS_EMAC_MODE_MAC2:
            {
                ICSS_EmacIoctl(handle, ICSS_EMAC_IOCTL_STORM_PREV_CTRL, ICSS_EMAC_PORT_2, (void*)&ioctlParams);
                break;
            }
            default:
            {
                break;
            }
        }
    
    }
    
    /**
    * @internal
    * @brief Configures Address lookup engine (ALE) of EMAC.
    *
    * @param hPort       pointer to port object
    *
    * @retval none
    *
    */
    static void NIMU_ICSS_setStatisticsCfg(ICSS_EmacHandle handle); /* misra warning */
    static void NIMU_ICSS_setStatisticsCfg(ICSS_EmacHandle handle)
    {
        ICSSEMAC_IoctlCmd ioctlParams;
        ioctlParams.command = ICSS_EMAC_IOCTL_STAT_CTRL_CLEAR;
    
    
        switch ((((ICSS_EmacObject*)handle->object)->emacInitcfg)->portMask)
        {
            case ICSS_EMAC_MODE_SWITCH:
            {
                ICSS_EmacIoctl(handle, ICSS_EMAC_IOCTL_STATS_CTRL, ICSS_EMAC_PORT_1, (void*)&ioctlParams);
                ICSS_EmacIoctl(handle, ICSS_EMAC_IOCTL_STATS_CTRL, ICSS_EMAC_PORT_2, (void*)&ioctlParams);
                break;
            }
            case ICSS_EMAC_MODE_MAC1:
            {
                ICSS_EmacIoctl(handle, ICSS_EMAC_IOCTL_STATS_CTRL, ICSS_EMAC_PORT_1, (void*)&ioctlParams);
                break;
            }
            case ICSS_EMAC_MODE_MAC2:
            {
                ICSS_EmacIoctl(handle, ICSS_EMAC_IOCTL_STATS_CTRL, ICSS_EMAC_PORT_2, (void*)&ioctlParams);
                break;
            }
            default:
            {
                break;
            }
        }
    }
    
    
    
    /**
    * @internal
    * @brief This function opens and sets up a MAC port for communication.
    *
    * @param hPort               Handle to the Port object to setup
    *
    * @retval none
    *
    */
    static void NIMU_ICSS_macOpen(uint32_t hPort,NIMU_IcssPdInfo * pi); /* misra warning */
    static void NIMU_ICSS_macOpen(uint32_t hPort,NIMU_IcssPdInfo * pi)
    {
    
        uint32_t instId = hPort ;
        ICSS_EmacHandle icssEmacHandle = pi->nimuDrvHandle;
        uint32_t phyNum = (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->phyAddr[instId];
        uint32_t phyinst = (hPort + pi->PhysIdx);
        uint32_t PhySel;
    
    
        PhySel=phyNum;
        PhySel = PhySel | (0x40U);
    
        uint32_t baseAddr = (((const ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs;
    
        baseAddr = baseAddr + CSL_MDIO_USER_PHY_SEL_REG(0U);
    
        baseAddr = baseAddr + (phyinst*8U);
    
         HWREG(baseAddr) = PhySel;
    }
    
    
    static void NIMU_ICSS_macClose(uint32_t hPort,NIMU_IcssPdInfo * pi); /* misra warning */
    static void NIMU_ICSS_macClose(uint32_t hPort,NIMU_IcssPdInfo * pi)
    {
    
        uint32_t instId = hPort ;
        ICSS_EmacHandle icssEmacHandle = pi->nimuDrvHandle;
        uint32_t phyNum = (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->phyAddr[instId];
        uint32_t phyinst = (hPort + pi->PhysIdx);
        uint32_t PhySel;
    
        PhySel=phyNum;
        PhySel = PhySel & ~((uint32_t)0x40U);
    
        uint32_t baseAddr = (((const ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs;
    
        baseAddr = baseAddr + CSL_MDIO_USER_PHY_SEL_REG(0U);
        baseAddr = baseAddr + (phyinst*8U);
    
         HWREG(baseAddr) = PhySel;
    
    }
    
    void NIMU_ICSS_openPeripheral(NIMU_IcssPdInfo *pi)
    {
        uint32_t              i;
        uint32_t numPorts=0U;
    
        if(ICSS_EMAC_MODE_SWITCH == (uint32_t)((((ICSS_EmacObject*)(pi->nimuDrvHandle)->object)->emacInitcfg)->portMask))
        {
            numPorts = 2U;
        }
        else
        {
            numPorts = 1U;
        }
        if(ICSS_EMAC_MODE_MAC2 != (((ICSS_EmacObject*)(pi->nimuDrvHandle)->object)->emacInitcfg)->portMask)
        {
            CSL_MDIO_init((((ICSS_EmacHwAttrs*)(pi->nimuDrvHandle)->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs,
                                     NIMU_ICSS_DEFAULT_MDIOCLOCKFREQ,NIMU_ICSS_DEFAULT_MDIOBUSFREQ);
        }
    
        /* Open all ports */
        for(i=0;i<numPorts; i++)
        {
            NIMU_ICSS_macOpen(i,pi);
        }/* end of for loop over PORTS */
    
        NIMU_ICSS_setAleCfg(pi->nimuDrvHandle);
    
        NIMU_ICSS_setRateControlCfg(pi->nimuDrvHandle);
    
        NIMU_ICSS_setStatisticsCfg(pi->nimuDrvHandle);
    
    }
    
    uint32_t NIMU_ICSS_closePeripheral(NIMU_IcssPdInfo *pi)
    {
        uint32_t i;
        uint32_t numPorts;
    
        if(ICSS_EMAC_MODE_SWITCH == (((ICSS_EmacObject*)(pi->nimuDrvHandle)->object)->emacInitcfg)->portMask)
        {
            numPorts =2U;
        }
        else
        {
            numPorts = 1U;
        }
        /* Close all ports */
        for(i=0U;i<numPorts; i++)
        {
            NIMU_ICSS_macClose(i,pi);
        }/* end of for loop over PORTS */
    
        NIMU_ICSS_packetShutdown(pi);
    
        /* Exit with interrupts still disabled in the wrapper */
        return (NIMU_ICSS_SUCCESS);
    }
    /**
    * @brief 	Called to get the current device statistics. The statistics structure
    *     		contains a collection of event counts for various packet sent and
    *     		receive properties. Reading the statistics also clears the current
    *     		statistic counters, so the values read represent a delta from the last
    *     		call.
    * @details  The statistics information is copied into the structure pointed to
    *     			by the pStatistics argument.
    *     			The function returns zero on success, or an error code on failure.
    *     			Possible error code include:
    *      			NIMU_ICSS_INVALID_PARAM   - A calling parameter is invalid
    * @internal
    * @param  hEMAC       handle to the opened EMAC device
    * @param  pStatistics Pointer to the device statistics
    * @param  portNo   port number
    *
    * @retval 	Success (0)
    *			NIMU_ICSS_INVALID_PARAM   - A calling parameter is invalid
    * @pre      EMAC peripheral instance must be opened before calling this API
    *
    */
    uint32_t NIMU_ICSS_getStatistics(NIMU_IcssPdInfo *pi, NIMU_IcssStatistics *pStatistics,uint8_t portNo)
    {
        uint32_t retVal;
        NIMU_IcssDevice *nimuDevice = ((ICSS_EmacObject*)(pi->nimuDrvHandle)->object)->pvtInfo;
        NIMU_IcssStatistics* nimuStats = nimuDevice->nimuStat;
    
        if(portNo > NIMU_ICSS_NUM_MAC_PORTS)
        {
                retVal =  NIMU_ICSS_INVALID_PORT;
        }
        else
        {
            /* Update the stats */
            NIMU_ICSS_updateStats(pi, portNo);
            /* Copy the updated stats to the application */
            *pStatistics = *(nimuStats + portNo);
            retVal = NIMU_ICSS_SUCCESS;
        }
        return (retVal);
    }
    /**
    * @brief 	Called to clear the current device statistics for a particular port
    * @internal
    * @param  pi       handle to the opened EMAC device
    * @param  portNo   port to clear statistics
    *
    * @retval 	Success (0)
    *			NIMU_ICSS_INVALID_PARAM   - A calling parameter is invalid
    * @pre      EMAC peripheral instance must be opened before calling this API
    *
    */
    uint32_t NIMU_ICSS_clearStatistics(NIMU_IcssPdInfo *pi,uint8_t portNo)
    {
        uint32_t retVal;
        NIMU_IcssDevice *nimuDevice = ((ICSS_EmacObject*)(pi->nimuDrvHandle)->object)->pvtInfo;
        NIMU_IcssStatistics* nimuStats = nimuDevice->nimuStat;
        if(portNo > NIMU_ICSS_NUM_MAC_PORTS)
        {
                retVal =  NIMU_ICSS_INVALID_PORT;
        }
        else
        {
            NIMU_ICSS_updateStats(pi, portNo);
            memset((nimuStats + portNo),0,sizeof(NIMU_IcssStatistics));
            retVal = NIMU_ICSS_SUCCESS;
        }
        return (retVal);
    }
    
    
    uint32_t NIMU_ICSS_setConfig(NIMU_IcssPdInfo *pi, void* pBuf, uint32_t size)
    {
        uint32_t  ret_val = NIMU_ICSS_SUCCESS;
        uint32_t port;
        NIMU_IcssConsCmd * swConsCommand = (NIMU_IcssConsCmd *)pBuf;
        ICSS_EmacHandle emachandle = pi->nimuDrvHandle;
        uint8_t mode =0;
        uint32_t mdioBaseAdd;
        uint32_t phyAddr;
        uint16_t regStatus = 0U;
        mdioBaseAdd= (((ICSS_EmacHwAttrs*)emachandle->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs;
        uint8_t macMode = (((ICSS_EmacObject*)emachandle->object)->emacInitcfg)->portMask;
    
        switch(swConsCommand->opcode)
        {
            case ICSS_IOCTL_SET_PORT_CONFIG:
            {
                NIMU_IcssPortCmd *lpPortCmd = &swConsCommand->PortCmd;
                uint8_t port = lpPortCmd->port;
                if( (lpPortCmd->port < 2) && (lpPortCmd->EnDis < 2))
                {
                    switch(lpPortCmd->value)
                    {
                        case 0:
                        {
                            mode=PHY_CONFIG_AUTONEG;
                            break;
                        }
                        case 10:
                        {
                            if(lpPortCmd->EnDis ==1)
                            {
                                mode=PHY_CONFIG_10FD;
                            }
                            else
                            {
                                mode=PHY_CONFIG_10HD;
                            }
                            break;
                        }
                        case 100:
                        {
                            if(lpPortCmd->EnDis ==1)
                            {
                                mode=PHY_CONFIG_100FD;
                            }
                            else
                            {
                                mode=PHY_CONFIG_100HD;
                            }
                             break;
                        }
                        default:
                        {
                            mode=PHY_CONFIG_AUTONEG;
                            break;
                        }
                    }/* end of switch construct  */
    
                    if(macMode == ICSS_EMAC_MODE_SWITCH)
                    {
                        if(port > 0U)
                        {
                            phyAddr =(((ICSS_EmacObject*)emachandle->object)->emacInitcfg)->phyAddr[port-1U];
                        }
                        else
                        {
                            ret_val = NIMU_ICSS_INVALID_PORT;
                         }
                    }
                    else
                    {
                        phyAddr = (((ICSS_EmacObject*)emachandle->object)->emacInitcfg)->phyAddr[0U];
                    }
                    if (ret_val == NIMU_ICSS_SUCCESS)
                    {
                        regStatus = 0;
                        CSL_MDIO_phyRegRead(mdioBaseAdd, phyAddr, NIMU_ICSS_PHY_BMCR_REG, &regStatus);
                        switch(mode)
                        {
                             case PHY_CONFIG_AUTONEG:
                                  regStatus = regStatus | NIMU_ICSS_MII_AUTO_NEGOTIATE_EN;
                                 break;
                             case PHY_CONFIG_100FD:
                                 regStatus = regStatus & (uint16_t)(~(NIMU_ICSS_MII_AUTO_NEGOTIATE_EN));
                                 regStatus = regStatus | NIMU_ICSS_MII_SPEEDSEL_100;
                                 regStatus = regStatus | NIMU_ICSS_MII_DUPLEXMODE_FULL;
    
                                 
                                 break;
                             case PHY_CONFIG_10FD:
                                 regStatus = regStatus & (uint16_t)(~(NIMU_ICSS_MII_AUTO_NEGOTIATE_EN));
                                 regStatus = regStatus & (uint16_t)(~(NIMU_ICSS_MII_SPEEDSEL_100));
                                 regStatus = regStatus | NIMU_ICSS_MII_DUPLEXMODE_FULL;
                                 break;
                             case PHY_CONFIG_100HD:
                                 regStatus = regStatus & (uint16_t)(~(NIMU_ICSS_MII_AUTO_NEGOTIATE_EN));
                                 regStatus = regStatus | NIMU_ICSS_MII_SPEEDSEL_100;
                                 regStatus = regStatus & (uint16_t)(~(NIMU_ICSS_MII_DUPLEXMODE_FULL));
                                 break;
                             case PHY_CONFIG_10HD:
                                 regStatus = regStatus & (uint16_t)(~(NIMU_ICSS_MII_AUTO_NEGOTIATE_EN));
                                 regStatus = regStatus & (uint16_t)(~(NIMU_ICSS_MII_SPEEDSEL_100));
                                 regStatus = regStatus & (uint16_t)(~(NIMU_ICSS_MII_DUPLEXMODE_FULL));
                                 break;
                             default:
                                 regStatus = regStatus | NIMU_ICSS_MII_AUTO_NEGOTIATE_EN;
                                 break;
                        }
                    CSL_MDIO_phyRegWrite(mdioBaseAdd, phyAddr, NIMU_ICSS_PHY_BMCR_REG, regStatus);
                        }
                }
                else
                {
                    NIMU_ICSS_transport_log("SET_PORT_CONFIG:Invalid Arguments\n");
                    ret_val = NIMU_ICSS_INVALID_PORT;
                }
    
                break;
            }
            case ICSS_IOCTL_GET_PORT_CONFIG:
            {
                NIMU_IcssPortCmd *lpPortCmd = &swConsCommand->PortCmd;
                uint8_t i;
                if(lpPortCmd->port == 0)        /*HOST Port*/
                {
                    port  = lpPortCmd->port;
                    lpPortCmd->ml    = port;
                    lpPortCmd->port  = ((uint8_t)1U);
                    lpPortCmd->value = ((uint32_t)0U);
                    lpPortCmd->EnDis = ((uint8_t)1U);
                    lpPortCmd->phyMode = 0;
                    for(i=0U;i<6U;i++)
                    {
                        lpPortCmd->add[i]= ((((ICSS_EmacObject*)(pi->nimuDrvHandle)->object)->emacInitcfg)->macId)[i];
                    }
                }
                else if(lpPortCmd->port < ((uint8_t)3U))
                {
                    port  = lpPortCmd->port;
                    if(macMode == ICSS_EMAC_MODE_SWITCH)
                    {
                        phyAddr = (((ICSS_EmacObject*)emachandle->object)->emacInitcfg)->phyAddr[port-1U];
                    }
                    else
                    {
                        phyAddr = (((ICSS_EmacObject*)emachandle->object)->emacInitcfg)->phyAddr[0U];
                    }
    
                    CSL_MDIO_phyRegRead(mdioBaseAdd, phyAddr, NIMU_ICSS_PHY_BMCR_REG, &regStatus);
    
                    if(regStatus & NIMU_ICSS_MII_AUTO_NEGOTIATE_EN)
                    {
                        lpPortCmd->value =0;
                    }
                    switch(lpPortCmd->value)
                    {
                        case PHY_CONFIG_10FD:
                        {
                            lpPortCmd->EnDis =((uint8_t)1);
                            lpPortCmd->value =10;
                            break;
                        }
                        case PHY_CONFIG_10HD:
                         {
                            lpPortCmd->EnDis =((uint8_t)0U);
                            lpPortCmd->value =((uint32_t)10U);
                             break;
                         }
                        case PHY_CONFIG_100FD:
                         {
                            lpPortCmd->EnDis =((uint8_t)1U);
                            lpPortCmd->value =((uint32_t)100U);
                              break;
                         }
                         case PHY_CONFIG_100HD:
                         {
                            lpPortCmd->EnDis =((uint8_t)0U);
                            lpPortCmd->value =((uint32_t)100U);
                              break;
                         }
                         default:
                         {
                            break;
                         }
                    }
                    port  = lpPortCmd->port;
                    lpPortCmd->ml    = port - 1U;
                    lpPortCmd->port  = CSL_MDIO_phyLinkStatus(mdioBaseAdd,phyAddr);
                }
                else
                {
                    NIMU_ICSS_transport_log("GET_PORT_CONFIG:Invalid Arguments\n");
                     ret_val = NIMU_ICSS_INVALID_PORT;
                }
    
                break;
            }
            default:
            {
                break;
            }
        }/* end of switch construct */
    
        swConsCommand->ret_type = ret_val;
    
        return ret_val;
    }
    
    uint32_t NIMU_ICSS_sendPacket(Handle hEMAC, NIMU_IcssEmacPkt *pPkt)
    {
        uint32_t retVal = NIMU_ICSS_SUCCESS;
        uint32_t          fragcnt,pktlen;
        NIMU_IcssEmacPkt        *pPktLast;
        uint32_t txPort;
        ICSS_EmacHandle handle = (ICSS_EmacHandle)hEMAC;
        int32_t ret;
       ICSS_EmacTxArgument txArgs;
    
        /* Count the number of frags in this packet */
        fragcnt =1U;
        pktlen  = pPkt->PktLength;
    
        pPktLast = pPkt;
        while ((((pPktLast->Flags & NIMU_ICSS_EMAC_PKT_FLAGS_EOP) != NIMU_ICSS_EMAC_PKT_FLAGS_EOP)) && (retVal == NIMU_ICSS_SUCCESS))
        {
            if (pPktLast->pNext == NULL)
            {
                retVal = NIMU_ICSS_INVALID_PARAM;
            }
            else
            {
                pktlen -= pPktLast->ValidLen;
                pPktLast = pPktLast->pNext;
                fragcnt++;
                /* At this point we can't have another SOP */
                if (pPktLast->Flags & NIMU_ICSS_EMAC_PKT_FLAGS_SOP)
                {
                    retVal = NIMU_ICSS_INVALID_PARAM;
                }
            }
        }
        if (retVal == NIMU_ICSS_SUCCESS)
        {
            /* Make sure PktLength and ValidLen agree */
            if (pktlen != pPktLast->ValidLen)
            {
                retVal = NIMU_ICSS_ERR_BADPACKET;
            }
            else
            {
                /* The frag count must be correct */
                if (fragcnt != pPkt->PktFrags)
                {
                    retVal = NIMU_ICSS_ERR_BADPACKET;
                }
                else
                {
                    /* Now pad for 60 byte min size. We only pad the last fragment */
                    if (pPkt->PktLength < 60U)
                    {
                        pktlen = 60U - pPkt->PktLength;
                        pPkt->PktLength = 60U;
                        pPktLast->ValidLen += pktlen;
                    }
                
                
                    if(ICSS_EMAC_MODE_SWITCH == (((ICSS_EmacObject*)handle->object)->emacInitcfg)->portMask)
                    { /*Switch Mode*/
                        txPort = ICSS_EMAC_PORT_0;
                    } 
                    else if(ICSS_EMAC_MODE_MAC1 == (((ICSS_EmacObject*)handle->object)->emacInitcfg)->portMask)
                    {
                        txPort = ICSS_EMAC_PORT_1;
                    } 
                    else if(ICSS_EMAC_MODE_MAC2 == (((ICSS_EmacObject*)handle->object)->emacInitcfg)->portMask) 
                    {
                        txPort = ICSS_EMAC_PORT_2;
                    }
                    else
                    {
                        txPort = ICSS_EMAC_PORT_0;
                    }
                    txArgs.icssEmacHandle = handle;
                    txArgs.lengthOfPacket = pPkt->PktLength;
                    txArgs.portNumber = txPort;
                    txArgs.queuePriority = ICSS_EMAC_QUEUE4;
                    txArgs.srcAddress = (const uint8_t *)(pPkt->pDataBuffer + pPkt->DataOffset);
                
                    ret = ((((ICSS_EmacObject*)handle->object)->callBackHandle)->txCallBack)->callBack(&txArgs, ((((ICSS_EmacObject *)
           handle->object)->callBackHandle)->txCallBack)->userArg);
                    if(ret != 0)
                    {
                        retVal = NIMU_ICSS_ERR_TX_OUT_OF_BD;
                    }
                }
            }
        }
        return (retVal);
    }
    
    /**
    * @internal
    * @brief     This function should be called every time there is an EMAC device Rx
    *             interrupt to process the packet
    * @details  Note that the application has the responsibility for mapping the
    *             physical device index to the correct EMAC_serviceCheck() function. If
    *             more than one EMAC device is on the same interrupt, the function must be
    *             called for each device.
    *
    * @param  hEMAC       handle to the opened EMAC device
    *
    * @retval     NIMU_ICSS_SUCCESS (0)
    *                NIMU_ICSS_INTERNAL_FAILURE   - Packet provided by firmware has invalid length
    * @pre     NIMU_ICSS_openPeripheral function must be called before calling this API.
    *
    */
    uint32_t NIMU_ICSS_rxServiceCheck(ICSS_EmacHandle hEMAC,int32_t prioQueue)
    {
        uint32_t retVal = NIMU_ICSS_SUCCESS;
        NIMU_IcssEmacPkt    *pPkt;
        int32_t        packetLength;
        ICSS_EmacRxArgument rxArgs;
        uint32_t dataBufTemp;
    
        NIMU_IcssDevice* lclDevice = (NIMU_IcssDevice*)(((ICSS_EmacObject*)hEMAC->object)->pvtInfo);
    
        rxArgs.icssEmacHandle = hEMAC;
        
        rxArgs.queueNumber = prioQueue;
        rxArgs.more = 1;
        rxArgs.port = 0;
    
        while ((retVal == NIMU_ICSS_SUCCESS) && (rxArgs.more == 1U))
        {
            pPkt = lclDevice->nimuPktRx;
            if (pPkt != NULL)
            {
                dataBufTemp = ((uint32_t)pPkt->pDataBuffer);
                rxArgs.destAddress =  dataBufTemp + pPkt->DataOffset;
                packetLength =  ((((ICSS_EmacObject*)hEMAC->object)->callBackHandle)->rxCallBack)->callBack(&rxArgs, ((((ICSS_EmacObject *)
           hEMAC->object)->callBackHandle)->rxCallBack)->userArg);
    
                if (packetLength > 0)
                {
                    /* Fill in the necessary packet header fields */
                    pPkt->ValidLen = pPkt->PktLength = (uint32_t)(packetLength) & (0xFFFFU);
                    pPkt->PktChannel = (uint32_t)rxArgs.port;
                    pPkt->PktFrags = (1U);
                    (lclDevice->pfcbRxPacket)(hEMAC,pPkt);
                }
                else
                {
                    retVal = NIMU_ICSS_INTERNAL_FAILURE;
                }
            }
            else
            {
                retVal = NIMU_ICSS_INTERNAL_FAILURE;
            }
    
        }
    
        return(retVal);
    }
    
    
    icss_emacFwInit.c
    icss_emacLearning.c
    /**
    * @file icss_emacLearning.c
    *
    * @brief Main file for Learning/FDB implementation
    *        Contains hash functions and other routines used to implement a Learning/FDB implementation
    *
    */
    
    /* Copyright (C) {2016} Texas Instruments Incorporated - http://www.ti.com/ 
    *
    *   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 Files                                  */
    /* ========================================================================== */
    #include <ti/drv/icss_emac/icss_emacLearning.h>
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    static uint8_t hashFuncGPMAC(const uint8_t* macId);
    
    static uint8_t checkDuplicateMAC(uint8_t key, const uint8_t* macId, uint8_t portNum, HashTable_t *tablePtr);
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    static uint8_t hashFuncGPMAC(const uint8_t* macId) {
        uint8_t key;
        /*get the key*/
        key = macId[0] ^ macId[1] ^ macId[2] ^ macId[3] ^ macId[4] ^ macId[5];
        return key;
    }
    
    void updateHashTable(uint8_t* macId, uint8_t portNum, HashTable_t *tablePtr,const ICSS_EmacCallBackConfig* exceptionCallBack) {
        uint8_t key = 0;
        uint8_t i, oldestTimestamp, index = 0, macFound;
        HashBucket_t * bucket;
        HashTable_t *table;
        ICSS_EmacCallBack protException;
        void * protExceptionuser = exceptionCallBack->userArg;
        protException = exceptionCallBack->callBack;
    
        if((tablePtr == NULL) || (macId == NULL)) {
            return;
        }
    
        if((macId[0] & 0x01U) > 0U) { /* MAC reversed - lowest bit indicates MC  */
            return;
        }
    
        table = tablePtr + portNum - 1U;
    
        /* don't do anything for wrong port num  */
        if(portNum > (uint8_t)ICSS_EMAC_LEARNING_PORT_2) {
            return;
        }
    
        /*Call back for Protocol specific adaption*/
        if(protException != NULL) {
            if(protException(macId, protExceptionuser) == 0U) {
                return;
            }
        }
    
        /*get the key*/
        key = hashFuncGPMAC(macId);
    
        if((table->state == locked) || (table->state == notLearning)){
            return; /*not allowed to make any changes in cases table is locked or if learning is disabled  */
        }
    
        /*go to first hash entry in the table*/
        bucket = &(table->entries[key]);
        macFound = 0; /*set to false*/
    
        /*If bucket is empty update the first entry else run through the bucket*/
        if (bucket->numEntries == 0) {
            /* make sure the SLT has no entry for this MAC on the other port  */
            checkDuplicateMAC(key, macId, portNum, tablePtr);
    
            /* add entry  */
            copyMAC((bucket->mac[0].macId), macId);
    
            bucket->timerCount[0] = 0;
            bucket->numEntries++;
            table->totalNumEntries++;
    
    
    
        } else {
            oldestTimestamp = bucket->timerCount[0];
    
            for(i = 0; i < bucket->numEntries; i++) {
                /*Update all timer counts, for ageing*/
                if (COMPARE_MAC(macId, bucket->mac[i].macId)) {
                    bucket->timerCount[i] = 0;
                    macFound = 1u;
    
                    /*early exit  */
                    break;
                }
    
                /*if multiple MAC ID's hash to the same bucket, timer count is used to resolve the conflict*/
                if (oldestTimestamp <=  bucket->timerCount[i]) {
                    oldestTimestamp = bucket->timerCount[i];
                    index = i;
                }
    
            }
            if (macFound == 0U) {
    
                /* make sure the SLT has no entry for this MAC on the other port  */
                checkDuplicateMAC(key, macId, portNum, tablePtr);
    
                if(bucket->numEntries == MAX_NUM_ENTRIES) {
                    /*replace an existing entry(the least hit)*/
                    copyMAC(bucket->mac[index].macId, macId);
    
    
                    bucket->timerCount[index] = 0;
                } else {
                    copyMAC(bucket->mac[bucket->numEntries].macId, macId);
    
                    bucket->timerCount[bucket->numEntries] = 0;
                    bucket->numEntries++;
                    table->totalNumEntries++;
                }
    
            }
        }
    
    
    
    }
    
    void purgeTable(uint8_t portNum, HashTable_t *tablePtr) {
        int32_t i;
        /*don't do anything for wrong port num*/
        if(portNum <= (uint8_t)ICSS_EMAC_LEARNING_PORT_2)
        { 
            HashTable_t *table;
            table = tablePtr;
    
             /*not allowed to make any changes in cases table is locked  */
            if(table->state != locked) 
            {
                /*make total entries to 0*/
                table->totalNumEntries = 0;
                /*Do a dirty deletion*/
                for(i=0; i<NUMBUCKETS;i++) {
                    table->entries[i].numEntries = 0;
                }
            }
        }
        return;
    }
    
    void ageingRoutine(uint8_t portNum, HashTable_t *tablePtr) {
    
        int32_t i, a, j = 0;
        int32_t size, numEntriesRemoved;
    
        /*structure definitions, see header file*/
        HashTable_t *table;
        HashBucket_t * bucket;
        /*Right now this is hardcoded, modified only at compile time, can be added as an option later*/
        uint8_t ageingTime = AGEING_COUNT;
    
        /* don't do anything for wrong port num  */
        if(portNum <= (uint8_t)ICSS_EMAC_LEARNING_PORT_2)
        {
            /*get the table for the corresponding port*/
            table  = tablePtr;
    
            if(table->state != locked) 
            {
                for(i=0; i < NUMBUCKETS; i++) 
                {
                bucket = &(table->entries[i]);
                size = bucket->numEntries;
                numEntriesRemoved = size;
                a = 0;
                while(a < size) {
                    if(ageingTime <= bucket->timerCount[a])
                    {
                        j = a;
                        /*as we find hits, we decrement the size of the bucket*/
                        size--;
                        while(j < size) {
                            /*copy the data from below once a hole is created in the bucket due to retiring an entry*/
                            bucket->timerCount[j] = bucket->timerCount[j+1];
                            copyMAC(bucket->mac[j].macId, bucket->mac[j+1].macId);
                            j++;
                        }
                    } else {
                        a++;
                    }
                }
                /*Number of entries left*/
                bucket->numEntries = size;
                numEntriesRemoved -= size;
    
                /*Update the total number of entries removed  */
                table->totalNumEntries -= numEntriesRemoved;
                }
            }
        }
        return;
    }
    
    uint8_t findMAC(const uint8_t * macId, HashTable_t *tablePtr) {
    
        uint8_t j;
        uint8_t key;
        uint8_t macFound[NUM_PORTS] = {0};
        uint8_t numPorts = 0;
        HashTable_t *table;
        HashBucket_t * bucket;
    
        uint8_t ret_val = 0U;
    
    
        /*get the key to lookup in the hash table*/
        key = hashFuncGPMAC(macId);
    
        /*Look in all port entries, break if found*/
        for(numPorts = 0; numPorts < NUM_PORTS; numPorts++){
            table = tablePtr + numPorts;
            bucket = &(table->entries[key]);
            for (j = 0; j < bucket->numEntries; j++ ) {
                if (COMPARE_MAC(bucket->mac[j].macId, macId)) {
                    /*set the flag and exit*/
                    macFound[numPorts] = (uint8_t)1U;
                    break;
                }
    
            }
    
        }
        /*since a return val of 0 means MAC Id not found 1 is added to distinguish port 0 from mac id not found,
         user to subtract 1 to get port number*/
        /*If MAC ID moves from port 1 to port 2, both ports will return false*/
    
        for(numPorts = 0; numPorts < NUM_PORTS; numPorts++) 
        {
            if(macFound[numPorts]) 
            {
                ret_val = numPorts + 1U;
                break;
            }
        }
    
        return ret_val;
    }
    
    uint8_t removeMAC(const uint8_t * macId, HashTable_t *tablePtr) {
        uint8_t j = 0;
        uint8_t key = 0;
        uint8_t macFound[NUM_PORTS] = {0};
        uint8_t macIndex[NUM_PORTS] = {0};
        uint8_t numPorts = 0;
        HashTable_t *table;
        HashBucket_t * bucket;
        key = hashFuncGPMAC(macId);
    
        uint8_t ret_val = 0U;
    
    
        /*Look in all port entries, exit if true*/
        for(numPorts = 0; numPorts < NUM_PORTS; numPorts++){
            table = tablePtr + numPorts;
            if(table->state != locked) 
            {
                bucket = &(table->entries[key]);
                for (j = 0; j < bucket->numEntries; j++ ) 
                {
                    if (COMPARE_MAC(bucket->mac[j].macId, macId)) 
                    {
                        macFound[numPorts] = (uint8_t)1U;
                        macIndex[numPorts] = j;
                        break;
                    }
                }
            }
        }
    
        for(numPorts = 0; numPorts < NUM_PORTS; numPorts++){
    
            if(macFound[numPorts]) {
                    /*Remove for PORT 0*/
                    table = tablePtr + numPorts;
                    bucket = &(table->entries[key]);
    
                    for(j = macIndex[numPorts]; j < (bucket->numEntries - ((uint8_t)1U)); j++) {
                        bucket->timerCount[j] = bucket->timerCount[j+1U];
                        copyMAC(bucket->mac[j].macId, bucket->mac[j+1U].macId);
                    }
                    bucket->numEntries--;
                    table->totalNumEntries--;
                    ret_val = 1U;
                    break;
                }
        }
    
        return ret_val;
    
    }
    
    static uint8_t checkDuplicateMAC(uint8_t key, const uint8_t* macId, uint8_t portNum, HashTable_t *tablePtr) {
    
        HashBucket_t * bucket;
        HashTable_t *table;
        uint8_t i, j, macFound = 0;
        uint8_t port = 0;
    
        uint8_t ret_val = 0U;
    
    
        /*don't do anything for wrong port num*/
        if(portNum <= (uint8_t)ICSS_EMAC_LEARNING_PORT_2) 
        {
            /*Look in all other port tables for duplicates*/
            for(port = 0; port < NUM_PORTS; port++) 
            {
                /*Skip the current port, look in other ports*/
                if((portNum-1U) != port) 
                {
                    table = tablePtr + port;
                    bucket = &(table->entries[key]);
    
                    for (j = 0; j < bucket->numEntries; j++ ) 
                    {
                        if (COMPARE_MAC(bucket->mac[j].macId, macId)) 
                        {
                            macFound = 1U;
                            for(i = j; i < (bucket->numEntries - ((uint8_t)1U)); i++) 
                            {
                                bucket->timerCount[i] = bucket->timerCount[i+1U];
                                copyMAC(bucket->mac[i].macId, bucket->mac[i+1U].macId);
                            }
                            bucket->numEntries--;
                            table->totalNumEntries--;
                            break;
                        }
                
                    }
                    /*MAC Found, no need to look in other ports*/
                    if(macFound == 1U) {
                        break;
                    }
                }
            }
            ret_val = macFound;
        }
        return ret_val;
    }
    
    void incrementCounter(HashTable_t *tablePtr) {
        int32_t i,j;
        HashTable_t *table;
        HashBucket_t * bucket;
        uint8_t port;
    
        /*Do for All ports*/
        for(port = 0; port < NUM_PORTS; port++) {
            table = tablePtr + port;
            if(table->state == locked) {
                break; /*not allowed to make any changes in cases table is locked  */
            }
            for(i=0; i<NUMBUCKETS;i++) {
                bucket = &(table->entries[i]);
                for(j=0; j < bucket->numEntries; j++) {
                    if(bucket->timerCount[j] <= AGEING_COUNT) {
                        bucket->timerCount[j]++;
                    }
                }
            }
    
        }
        return;
    }
    
    void initLearningTable(HashTable_t *tablePtr) {
        HashTable_t *table;
        uint8_t ports = 0;
    
        /*Initialize all ports*/
        for(ports = 0; ports < NUM_PORTS; ports++) {
            table = tablePtr + ports;
            purgeTable(ports, table);
            table->state = learning;
        }
    }
    
    void changePortState(portState state, HashTable_t *tablePtr) {
    
        tablePtr->state = state;
    
    }
    
    void copyMAC(uint8_t *dst, const uint8_t *src) {
        uint8_t i;
        for(i = 0; i < 6U; i++) {
            *(dst) = *(src);
            dst++;
            src++;
        }
    }
    
    icss_emacStormControl.hicss_emacDrv.c
    icss_emacStormControl.c
    /**
    * @file icss_emacStormControl.c
    *
    * @brief Storm prevention implementation
    * @details      Contains functions for implementing a storm prevention scheme for
    *               the ICSS based ethernet switch. This is done through a credit based
    *               scheme where only a particular number of packets are allowed in a
    *               given amount of time, this is specified through a credit which expires
    *               at the end of a time period.
    */
    
    /* Copyright (C) {2016} Texas Instruments Incorporated - http://www.ti.com/ 
    *
    *   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 Files                                  */
    /* ========================================================================== */
    
    
    #include <ti/drv/icss_emac/icss_emacDrv.h>
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    /**Storm prevention control information*/
    /*stormPrevention controlBMcast[2];*/
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    
    void ICSS_EmacInitStormPreventionTable(uint8_t portnum, ICSS_EmacHandle icssEmacHandle) {
    
        stormPrevention_t* stormPrevPtr;
    
        if(ICSS_EMAC_MODE_SWITCH != ((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg->portMask) {
            portnum = 1U;
        }
    
        stormPrevPtr = (stormPrevention_t*)(((ICSS_EmacObject*)icssEmacHandle->object)->stormPrevPtr);
        stormPrevPtr += (portnum - 1U);
    
        setCreditValue(DEFAULT_CREDITS, stormPrevPtr);
        ICSS_EmacEnableStormPrevention(portnum, icssEmacHandle);
    }
    
    void setCreditValue(uint16_t creditValue, stormPrevention_t* stormPrevPtr) {
    
        stormPrevPtr->credits = creditValue;
    }
    
    void ICSS_EmacDisableStormPrevention(uint8_t portnum, ICSS_EmacHandle icssEmacHandle) {
        uint16_t *controlPointer;
        stormPrevention_t* stormPrevPtr;
        ICSS_EmacFwStaticMmap *pStaticMMap = (&((ICSS_EmacObject*)icssEmacHandle->object)->fwStaticMMap);
    
        uint32_t temp_addr = 0U;
    
        if (portnum <= (uint8_t)ICSS_EMAC_PORT_2) 
        {
            if(ICSS_EMAC_MODE_SWITCH != ((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg->portMask) {
                portnum = 1U;
            }
    
            stormPrevPtr = (stormPrevention_t*)(((ICSS_EmacObject*)icssEmacHandle->object)->stormPrevPtr);
            stormPrevPtr += (portnum - 1U);
    
            stormPrevPtr->suppressionEnabled = 0;
    
            if(portnum == (uint8_t)ICSS_EMAC_PORT_1) {
                temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr + pStaticMMap->stormPreventionOffset);
                controlPointer = (uint16_t*)(temp_addr);
            } else {
                temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + pStaticMMap->stormPreventionOffset);
                controlPointer = (uint16_t*)(temp_addr);
            }
            *(controlPointer) = stormPrevPtr->suppressionEnabled;
        }
        return;
    }
    
    void ICSS_EmacEnableStormPrevention(uint8_t portnum, ICSS_EmacHandle icssEmacHandle) {
    
        uint16_t *controlPointer;
        stormPrevention_t* stormPrevPtr;
        uint32_t temp_addr = 0U;
        ICSS_EmacFwStaticMmap *pStaticMMap = (&((ICSS_EmacObject*)icssEmacHandle->object)->fwStaticMMap);
    
    
        if (portnum <= (uint8_t)ICSS_EMAC_PORT_2) 
        {
            if(ICSS_EMAC_MODE_SWITCH != ((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg->portMask) {
                portnum = 1u;
            }
    
            /*get the pointer to the correct port*/
            stormPrevPtr = (stormPrevention_t*)(((ICSS_EmacObject*)icssEmacHandle->object)->stormPrevPtr);
            stormPrevPtr += (portnum - 1u);
    
            stormPrevPtr->suppressionEnabled = 1;
    
            if(portnum == (uint8_t)ICSS_EMAC_PORT_1) {
                temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr + pStaticMMap->stormPreventionOffset);
                controlPointer = (uint16_t*)(temp_addr);
            } else {
                temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr +  pStaticMMap->stormPreventionOffset);
                controlPointer = (uint16_t*)(temp_addr);
            }
            *(controlPointer) = stormPrevPtr->suppressionEnabled;
        }
        return;
    }
    
    void ICSS_EmacResetStormPreventionCounter(ICSS_EmacHandle icssEmacHandle){
        uint32_t *controlPointer;
        uint32_t controlWord;
    
        uint32_t temp_addr = 0U;
        uint16_t temp_var1 = 0u;
        stormPrevention_t* stormPrevPtr = (stormPrevention_t*)(((ICSS_EmacObject*)icssEmacHandle->object)->stormPrevPtr);
        ICSS_EmacFwStaticMmap *pStaticMMap = (&((ICSS_EmacObject*)icssEmacHandle->object)->fwStaticMMap);
    
        if(stormPrevPtr->suppressionEnabled) {
            temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr +  pStaticMMap->stormPreventionOffset);
            controlPointer = (uint32_t*)(temp_addr);
            temp_var1 = (((uint16_t)(stormPrevPtr->suppressionEnabled)) | ((uint16_t)((stormPrevPtr->credits) << 8U)));
            controlWord = ((uint32_t)(temp_var1));
            *(controlPointer) = controlWord;
        }
    
        if(ICSS_EMAC_MODE_SWITCH == ((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg->portMask) 
        {
            /*Access next port member*/
            stormPrevPtr += 1;
    
            if(stormPrevPtr->suppressionEnabled) {
                temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr +  pStaticMMap->stormPreventionOffset);
                controlPointer = (uint32_t*)(temp_addr);
                temp_var1 = (((uint16_t)(stormPrevPtr->suppressionEnabled)) | ((uint16_t)((stormPrevPtr->credits) << 8U)));
                controlWord = ((uint32_t)(temp_var1));
                *(controlPointer) = controlWord;
            }
        }
        return;
    }
    /**
    * @brief   returns true if storm prevention is enabled
    *
    * @param stormPrevPtr Pointer to Storm Prevention member instance for that port
    *
    * @retval Status. 1 if storm prevention is enabled on any port else 0
    */
    inline uint8_t ifStormPreventionEnabled(const stormPrevention_t* stormPrevPtr); /* for misra warning */ 
    inline uint8_t ifStormPreventionEnabled(const stormPrevention_t* stormPrevPtr) 
    {
        return stormPrevPtr->suppressionEnabled;
    }
    
    

    Hope we solve the problem... thanks!

    Regards, Mare

  • Mare,

    This may be related to non-aligned memory access. hsrPrp_red.c is built into prp_lib (projectCreate.bat AM437x arm) with -O2 optimization. Can you try to add hsrPrp_red.c into your prp_app project and step into the RedRxPktGet() to see if destAddress and rd_buffer_l3_addr that pass to memcpy is odd address?

    Regards,
    Garrett
  • Garrett,

    destAddress is 0. Also rxArg->destAddress is 0.

    Regards,
    Mare
  • Garrett,

    hsrPrp_red.c:

    destAddress is 0. Also rxArg->destAddress is 0.

            else
            {
    
                memcpy((int32_t *)destAddress, (int32_t *)rd_buffer_l3_addr, rd_packet_length);
                typeProt = (uint16_t *)destAddress + 6;
                typeProt1 = ((uint16_t)((*typeProt) << 8U));
                typeProt2 = ((uint16_t)((*typeProt) >> 8U));
                typeProt1 = typeProt1 | typeProt2;
            }

    inside NIMU_ICSS_rxServiceCheck() line 869 pPkt = lclDevice->nimuPktRx;:

    All pPkt members  are 0:

    NIMU_IcssDevice* lclDevice = (NIMU_IcssDevice*)(((ICSS_EmacObject*)hEMAC->object)->pvtInfo):

    -  nimuPdInfo struct NIMU_IcssPdInfo_s * 0x800F9D04 {PhysIdx=0,hEther=0x00000000,hEvent=0x80332B40,bMacAddr=[196 '\xc4',190 '\xbe',...,Filter=... 0x800FA7C4
    - aleTicks unsigned long 3000 0x800FA7C8
    - aleTimerActive unsigned long 0 0x800FA7CC
    - RxFilter unsigned long 0 0x800FA7D0
    - PktMTU unsigned long 1518 0x800FA7D4
    - FatalError unsigned long 0 0x800FA7D8
    - nimuStat struct NIMU_IcssStatistics_s * 0x800FCB04 {txUcast=0,txBcast=0,txMcast=0,txGoodFrames=0,txNetOctets=0...} 0x800FA7DC (all members 0)
    - nimuPktRx struct NIMU_IcssEmacPkt_s * 0x800FA7F4 {AppPrivate=0,pPrev=0x00000000 {AppPrivate=???,pNext=0x00000000 {AppPrivate=...,pDataBuffer=... 0x800FA7E0 (all members 0)
    - nimuPktTx struct NIMU_IcssEmacPkt_s * 0x800FA824 {AppPrivate=0,pPrev=0x00000000 {AppPrivate=???,pNext=0x00000000 {AppPrivate=...,pDataBuffer=... 0x800FA7E4 (all members 0)
    - pfcbRxPacket NIMU_IcssEmacPkt_s* (*)(void**,NIMU_IcssEmacPkt_s*) 0x80068414 0x800FA7E8

    icssEmacHandle is not prepared for service!!?

    Regards,

    Mare

  • Mare,

    Can you upload your .out file and .map file here?

    Regards,
    Garrett
  • MarePrpForGarrett.zip

    Hi,

    in file is .out, .map, .bin and .cfg file.

  • Mare,

    Your .out file runs fine on my idkAM437x. Do you have another IDK to try? and do you see the exception constantly?

    Regards,
    Garrett
  • Hi Garrett,

    Somehow your post is good news but also bad in my current state. I dont't have another IDK...and YES, exception is constantly if ETH cable is plugged in on startup!

    I'm digging in.. so any suggestions are welcome.
    I compare flow of program in case ETH plugged/unplugged.

    Plugged ETH:

    Unplugged:

    It seems ICSS_EmacRxInterruptHandler() prevent NC_NetStart() to finish operations...
    I dont't know for real...Step-by-step analyse will be done tomorow...
    If you have any tip or proposal what to check...please let me know.

    Best Regards, Mare

  • Mare,

    Attached is the snapshot with your .out file when I step around NIMU_ICSS_rxServiceCheck() line 869 you mentioned above, hope it helps.

  • one more thing to check - try to erase QSPI flash:
    processors.wiki.ti.com/.../AM437x
  • It works as expected at our AM437x IDKs as well. Pinging it shows replies from the PRP app, with no crash over 10 minutes of run. PFA Mare_PRP_capture.zip containing capture for ping test for reference.

    Mare_PRP_capture.zip

  • Mare,

    Additionally, can you confirm if your are using the GEL script for AM437x IDK from CCS v7.x?

    Regards,
    Garrett
  • Hi Garrett,

    1) I get from Garvit Jain reply post on email but is not visible on e2e.ti forum. Message is:

    This points to the issue fixed by the patch available at pdk_patches/03.03.00/PRSDK-2445_UserArg.patch


    This patch is done.

    2.) I didn't try erase QSPI flash... but how can QSPI flash impact on current application? APP is loaded & run with debuger.

    3.)GEL on load/debug:

    CortexA9: Output: ****  AM437x IDK EVM Initialization is in progress .......... 
    CortexA9: Output:  **** Device Type: GP
    CortexA9: GEL Output: System input clock is 24MHz
    CortexA9: GEL Output: ****  AM43xx OPP100 with CLKIN=24MHz is in progress ......... 
    CortexA9: GEL Output: 	 ****  Going to Bypass... 
    CortexA9: GEL Output: 	 ****  Bypassed, changing values... 
    CortexA9: Output: 	 ****  Locking PLL
    CortexA9: GEL Output: 	 ****  MPU PLL locked
    CortexA9: GEL Output: 	 ****  Core Bypassed
    CortexA9: GEL Output: 	 ****  Now locking Core...
    CortexA9: GEL Output: 	 ****  Core locked
    CortexA9: GEL Output: 	 ****  Calculated PER SD Divisor=4
    CortexA9: GEL Output: 	 ****  PER DPLL Bypassed
    CortexA9: GEL Output: 	 ****  PER DPLL Locked
    CortexA9: GEL Output: 	 ****  Calculated EXTDEV SD Divisor=4
    CortexA9: GEL Output: 	 ****  EXTDEV DPLL Bypassed
    CortexA9: GEL Output: 	 ****  EXTDEV DPLL Locked
    CortexA9: GEL Output: 	 ****  DISP PLL Config is in progress .......... 
    CortexA9: GEL Output: 	 ****  DISP PLL Locked 
    CortexA9: GEL Output: 	 ****  DDR DPLL Bypassed
    CortexA9: GEL Output: 	 ****  DDR DPLL Locked
    CortexA9: GEL Output: ****  Setting DDR3  = 400MHz
    CortexA9: GEL Output: ****  AM43xx OPP100 configuration is done ......... 
    CortexA9: GEL Output: Starting DDR3 configuration...
    CortexA9: Output: EMIF PRCM is in progress ....... 
    CortexA9: Output: EMIF PRCM Done 
    CortexA9: GEL Output: EMIF CLK enabled... 
    CortexA9: GEL Output: Waiting for VTP Ready ....... 
    CortexA9: GEL Output: VTP is Ready! 
    CortexA9: GEL Output: VTP controller enabled
    CortexA9: GEL Output: Checking if DLL is ready...
    CortexA9: GEL Output: DLL is ready
    CortexA9: GEL Output: Configuring DDR IOs and Control Module registers...
    CortexA9: GEL Output: Configuration of Control Module registers complete
    CortexA9: GEL Output: Setting up DDR3 H/W leveling configuration...
    CortexA9: GEL Output: Starting EMIF controller configuration...
    CortexA9: GEL Output: 
    
    DDR3 Hardware leveling complete... Outputing all the leveling results !!!
    
    CortexA9: GEL Output: PHY_STATUS_12=0x070000BC
    CortexA9: GEL Output: PHY_STATUS_13=0x070000B4
    CortexA9: GEL Output: PHY_STATUS_14=0x070000D9
    CortexA9: GEL Output: PHY_STATUS_15=0x070000D9
    CortexA9: GEL Output: PHY_STATUS_16=0x00000000
    CortexA9: GEL Output: PHY_STATUS_7 =0x00000047
    CortexA9: GEL Output: PHY_STATUS_8 =0x00000048
    CortexA9: GEL Output: PHY_STATUS_9 =0x00000045
    CortexA9: GEL Output: PHY_STATUS_10=0x00000044
    CortexA9: GEL Output: PHY_STATUS_11=0x00000000
    CortexA9: GEL Output: PHY_STATUS_17=0x002E00DC
    CortexA9: GEL Output: PHY_STATUS_18=0x02AD00DC
    CortexA9: GEL Output: PHY_STATUS_19=0x030A00E8
    CortexA9: GEL Output: PHY_STATUS_20=0x003900E7
    CortexA9: GEL Output: PHY_STATUS_21=0x00000000
    CortexA9: GEL Output: PHY_STATUS_22=0x03EE009C
    CortexA9: GEL Output: PHY_STATUS_23=0x026D009C
    CortexA9: GEL Output: PHY_STATUS_24=0x02CA00A8
    CortexA9: GEL Output: PHY_STATUS_25=0x03F900A7
    CortexA9: GEL Output: PHY_STATUS_26=0x00000000
    CortexA9: GEL Output: 
    
    DDR3 configuration is complete!!!
    
    CortexA9: GEL Output: Turning on EDMA...  
    CortexA9: GEL Output: EDMA is turned on...  
    CortexA9: Output: ****  AM437x IDK EVM Initialization is Done ****************** 

    4.)

    I make step-by-step debugging to learn about APP implementation...
    On beginning:
     taskPruss() --(priority = 15)
    So first task is "taskPruss". TaskPruss finish and scheduler run ICSS_EMacOsRxTaskFnc
    4.a.)
    Should run ti_ndk_config_Global_stackThread?.

    .cfg file -> "Global.kernTaskPriLevel = 12; 
    Has ti_ndk_config_Global_stackThread priority 12?

    Any way back to topic.
    ICSS_EMacOsRxTaskFnc() has priority = 10
    Program flow:

    ICSS_EMacOsRxTaskFnc() --(priority = 10)
    line:445: ICSS_EMAC_Pend(icssEmacHandle, ICSS_EMAC_INTR_SRC_RX);

    ICSS_EMAC_Pend()
    line:255: ICSS_EMAC_osalPendLock(((ICSS_EmacObject*)icssEmacHandle->object)->rxSemaphoreHandle, SemaphoreP_WAIT_FOREVER);

    SemaphoreP_pend()
    line:133: flag = Semaphore_pend((Semaphore_Handle)handle, timeout);

    Semaphore_pend()

    Because on current state rxSempahore is 0, so task is put on hold/the end of queue. 

    line:258: task wait for rxSempahore is post? So other tasks are started (ti_ndk_config_Global_stackThread).

    ti_ndk_config_Global_stackThread() 
    line:3386: rc = NC_NetStart(hCfg, ti_ndk_config_Global_NetworkOpen,
    ti_ndk_config_Global_NetworkClose,
    ti_ndk_config_Global_NetworkIPAddr);

    NC_NetStart()
    line:181: NIMUInit (&stkEvent);

    NIMUInit()
    line:1199: NIMUDeviceTable[index].init (hEvent); (NIMU_ICSS_EmacInit)

    NIMU_ICSS_EmacInit()
    line:374: if (NIMURegister (pNimuIcssEmacDevice) < 0)

    NIMURegister()
    line:692: if (ptr_netif_device->start (ptr_netif_device) < 0)

    NIMU_ICSS_start()
    line:97: if (NIMU_ICSS_open(&pNimuIcssEmacPrivData->pdi) == 0)

    NIMU_ICSS_open()
    line:396: retVal = NIMU_ICSS_interruptInit(pi);

    On line:400 missing DDR address is initialized for RedRxPktGet() (where exception is made, because memcpy try to copy packet from L3 on DDR, but DDR address is NULL) which will be executed when ICSS_EMacOsRxTaskFnc task will go on....

    But after executing NIMU_ICSS_interruptInit() function, Hwi - ICSS_EmacRxInterruptHandler is made which post rxSempahore.

    Executing of ti_ndk_config_Global_stackThread() is interrupted (and NIMU_ICSS_packetInit(nCfg->nimuPktRx); is not executed) and scheduler run ICSS_EMacOsRxTaskFnc. Resoult is that task run RedRxPktGet function where rxArg->destAddress == 0!

    Any idea?

    5.) I running this example on local office network whit one port connected with cable... I don't have "for real" just prp devices on network... should this matters?

    I'm really glad and I appreciate your help!

    Best Regards,

    Mare

  • Hi Mare

    The GEL file initialization log provided by you seem to differ from the one we have. Below is the sections that differs.

    DDR3 Hardware leveling complete... Outputing all the leveling results !!!

    CortexA9: GEL Output: PHY_STATUS_12=0x0700003D
    CortexA9: GEL Output: PHY_STATUS_13=0x0700003B
    CortexA9: GEL Output: PHY_STATUS_14=0x07000056
    CortexA9: GEL Output: PHY_STATUS_15=0x07000056
    CortexA9: GEL Output: PHY_STATUS_16=0x00000000
    CortexA9: GEL Output: PHY_STATUS_7 =0x00000047
    CortexA9: GEL Output: PHY_STATUS_8 =0x00000047
    CortexA9: GEL Output: PHY_STATUS_9 =0x00000047
    CortexA9: GEL Output: PHY_STATUS_10=0x00000045
    CortexA9: GEL Output: PHY_STATUS_11=0x00000000
    CortexA9: GEL Output: PHY_STATUS_17=0x0377004D
    CortexA9: GEL Output: PHY_STATUS_18=0x034F0053
    CortexA9: GEL Output: PHY_STATUS_19=0x0268006D
    CortexA9: GEL Output: PHY_STATUS_20=0x01370063
    CortexA9: GEL Output: PHY_STATUS_21=0x00000000
    CortexA9: GEL Output: PHY_STATUS_22=0x0337000D
    CortexA9: GEL Output: PHY_STATUS_23=0x030F0013
    CortexA9: GEL Output: PHY_STATUS_24=0x0228002D
    CortexA9: GEL Output: PHY_STATUS_25=0x00F70023
    CortexA9: GEL Output: PHY_STATUS_26=0x00000000

    Kindly make sure that the GEL file in use is pointing to <ccs_base_folder>\ccs_base\emulation\boards\idk_am437x\gel\idk_am437x.gel . Steps are provided at : 

    Kindly note CCS version shouldn't affect any behavior. We are aligned with CCSv7.

  • Hi Garvit,

    It seems path for gel is OK. But I can't get equal PHY_STATUSx as you have.
    Where I can found documentation what is PHY_STATUSx or give me hint witch or what setups are you using... Bypass? Slave Processor? ...
    I'm using CCSv7

    Any comment / answers on my previews post?

    Best Regards, Mare 

  • Mare,

    It appears that I forgot to click 'Reply' button yesterday. Below was what I tried to update you:

    1) OK
    2) was thinking of any difference between your board and ours.
    3) There are some difference on PHY_STATUS registers, but those are probably 'don't care' bits. If you didn't modify any GEL files under idk_am437x\gel\, it should be OK.
    CortexA9: GEL Output: PHY_STATUS_12=0x070000BE
    CortexA9: GEL Output: PHY_STATUS_13=0x070000BD
    CortexA9: GEL Output: PHY_STATUS_14=0x070000D0
    CortexA9: GEL Output: PHY_STATUS_15=0x070000D1
    CortexA9: GEL Output: PHY_STATUS_16=0x00000000
    CortexA9: GEL Output: PHY_STATUS_7 =0x00000048
    CortexA9: GEL Output: PHY_STATUS_8 =0x00000048
    CortexA9: GEL Output: PHY_STATUS_9 =0x00000046
    CortexA9: GEL Output: PHY_STATUS_10=0x00000044
    CortexA9: GEL Output: PHY_STATUS_11=0x00000000
    CortexA9: GEL Output: PHY_STATUS_17=0x00CB00D1
    CortexA9: GEL Output: PHY_STATUS_18=0x023000D2
    CortexA9: GEL Output: PHY_STATUS_19=0x018600E7
    CortexA9: GEL Output: PHY_STATUS_20=0x018300E7
    CortexA9: GEL Output: PHY_STATUS_21=0x00000000
    CortexA9: GEL Output: PHY_STATUS_22=0x008B0091
    CortexA9: GEL Output: PHY_STATUS_23=0x01F00092
    CortexA9: GEL Output: PHY_STATUS_24=0x014600A7
    CortexA9: GEL Output: PHY_STATUS_25=0x014300A7
    CortexA9: GEL Output: PHY_STATUS_26=0x00000000

    4) haven't dived into it yet. But as your .out file works on our boards, it doesn't seem to be prp software issue.
    4) no, it doesn't matter whether the port connects to an office network or real prp device. The exception should not happen in any case.

    Regards,
    Garrett
  • Hi Garrett,

    I think that successful problem solving is related with deep-understanding of the program flow and priority settings.
    Until you dive into program flow, I can try run PRP APP on custom board, but this will probably take a lot of time because I never did this before.
    I see that in PRP packet has also some extra HW source placed in PRU-ICSS-HSR-PRP-DAN_01.00.02.00\examples\board.
    pdk_am437x_1_0_6\packages\ti\starterware\board\am43xx for pinmux is needed...what else?

    Regards,
    Mare

  • Hi Garrett,

    another issue: When I start APP with unplugged cable (with plugged cable startup fail and this issue remains)  Run Rx/Tx test fail. I already mention it in previews post. Exception is on line:92 in "hsrPrp_red_prp.c"

        /* Fill in the PRP RCT */
        PRP_RCT_WRITE(prpRct, PRP_LAN_A_MAGIC, lsduSize, hsrPrphandle->redSeqNr);

    If I check program flow from stack it is clear that hsrPrphandle == 0x0 !
    NULL value came from "hsr_prp_menu.c" line:719:

                    status = ((((ICSSEMAC_Object *)
                                emachandle->object)->callBackHandle)->txCallBack)->callBack(&txArg,
                                        NULL);

    Please tell me if in your case Rx/Tx test working.

    Thanks.

    Regards, Mare

  • Hi Garrett,

    short update.

    I made nasty hack in "nimu_icssEthDriver.c"

    After lin:140: in NIMU_ICSS_interruptInit() I add:

                ((ICSS_EmacObject*)icssEmacHandle->object)->rxintHandle = rxHwiHandle;
                ((ICSS_EmacObject*)icssEmacHandle->object)->linkintHandle = linkHwiHandle;
    			HwiP_disableInterrupt(rxIntrN);//just testing....nasty hack

    Now it survive NIMU startup cuse rxInterrupt is enabled after packet address init.

    Can someone comment this solution?

    Best Regards, Mare

  • Mare,

    I was sidetracked and now get back to the issue.
    In the beginning of NIMU_ICSS_interruptInit(), there is ICSS_EMAC_osalHardwareIntDisable(). I can't explain why the HwiP_disableInterrupt() helps here. With the hack, everything works fine?
    For Rx/Tx testing, you need two IDKs (transmitter and receiver). The null pointer you observed is very likely the same root cause as APP starts with cable plug in.

    One question - have you tried to flash the pre-built app binary from software-dl.ti.com/.../index_FDS.html

    Regards,
    Garrett
  • Garrett,

    In the beginning of NIMU_ICSS_interruptInit(), there is ICSS_EMAC_osalHardwareIntDisable().

    This is global HWI disable.
    Then in function Handler function are registered, so when ICSS_EMAC_osalHardwareIntRestore(cookie) is executed RXinterrupt is generated.
    Cuse RxInterrupt is made before NIMU_ICSS_packetInit() is called exception is made (NIMU packet - address for packet storage is not init.)

    It seems Sys event rxIntrN is already enabled. It should be enabled in EnableEMACInterrupts() but is already before... This is bug.. I think...

    With the hack, everything works fine?
    ping work so far...

    For Rx/Tx testing, you need two IDKs (transmitter and receiver). 
    I know that I need two IDK's for testing TX and RX... but any way example should not make exception's!

    The null pointer you observed is very likely the same root cause as APP starts with cable plug in.
    Disagree!

    -Please put brak point on line:719 in "hsr_prp_menu.c" ( txHSRPRPTestFrame ).
    -Run Tx test from usart console.
    -from line 719 status = ((((ICSSEMAC_Object *)
    emachandle->object)->callBackHandle)->txCallBack)->callBack(&txArg,
    NULL);
    step into function.

    - it should be RedTxPacket(). Step on line:273
    ret = RedFrameSend(hsrPrphandle, icssEmacHandle, redFrame, packetData,
    packetLength,
    queuePriority, portNum);
    Tell me if "hsrPrphandle" is NULL ?!? This null come from callBack(&txArg,
    NULL);

    Step program forwad in the RedFrameSend() and confirm that exception is made on RedFrameFill(hsrPrphandle, pRedFrame, pFrame, frameSize);

    One question - have you tried to flash the pre-built app binary from software-dl.ti.com/.../index_FDS.html
    No I did not. I already spend to much time on solving issues. 
    My next step will be porting prp on custom board and adding TCP and UDP layer on! Please help me with information and tips, to compensate lost time.


    Regards, Mare

  • Mare,

    >>Step program forwad in the RedFrameSend() and confirm that exception is made on RedFrameFill(hsrPrphandle, pRedFrame, pFrame, frameSize);

    I can confirm the exception happens with the Tx test, will find out why this is not covered in our test case. Thanks for your diligent work!

    We will review your fix for rxIntrN disabling, and update you along with the info on porting PRP to custom board.

    Regards,
    Garrett
  • Mare,

    Regarding the 'porting prp on custom board and adding TCP and UDP layer', you may find the following info useful:

    1. Application Development Using Processor SDK RTOS training, section Processor SDK RTOS: Port. training.ti.com/application-development-using-processor-sdk-rtos
    2. Processor SDK HSR PRP developer guide, processors.wiki.ti.com/.../Processor_SDK_HSR_PRP
    3. TCP/UDP in general please look into NDK user guide. Note snmp and ptp in third_party\protocols use TCP, UDP respectively.

    Regards,
    Garrett
  • I am able to reproduce the exception during startup with the following steps. It appeared the exception depending on the packets from link partner as you have discovered. The port of your office network must generate more traffic than the dedicated ethernet card in our PCs.

    I set a breakpoint at BIOS_start(). As the PHY initialization has been done at this point and link is up, so I can start to inject packets from an external traffic generator, right after I resume to run from BIOS_start, the exception occurs.

    I have submitted an internal ticket to track the issue, will update you as soon as possible.

    Thanks,
    Garrett
  • 1. Application Development Using Processor SDK RTOS training, section Processor SDK RTOS: Port. training.ti.com/application-development-using-processor-sdk-rtos 
    2. Processor SDK HSR PRP developer guide, processors.wiki.ti.com/.../Processor_SDK_HSR_PRP



    This is not useful.
    I try with .

    But no lack...
    Do you have any dedicated guide for am437x soc?

  • Mare,

    'no luck...' - do you mean you are not able to build your custom board library or you can't get emac work with your custom board library?
    For better tracking/supporting the custom board library issue, would you mind to open a new thread? The wiki you referred to actually contains the most detailed instructions so far.

    Regards,
    Garrett
  • Hi Garrett.

    I agree! I will start for custom board lib new thread. I just need to discover some parts in pdk.... wiki do not cover starterware part and this is problem.
    Link to new thread will be posted here.

    Please use this thread for PRP issues updating.

    p.s. BTW is anything new on PRP?

    Regards, 
    Mare 

  • Mare,

    Please try the attached the one line patch that fixes the Tx/Rx test exception. We have added a new test case to ensure this incident won't happen in later releases. Thank you for your testing.

    Regards,

    GarrettMare.patch

  • Mare,

    Did you have chance to verify the patch for Tx/Rx test fix?

    For the startup exception while cable is plugged in, we are not certain if the 'breakpoint' approach for reproducing the issue will resolve the problem you observed. We tried to start the application with high traffic on the link ( & no breakpoint at BIOS_start()), but this issue is not seen. If you could test your setup with our release binary then we would have a baseline for debug.

    Thanks,
    Garrett

  • Hi Garret!

    Sorry for delay, working on custom board port....

    Can you give me hint how to run with CCS prebuild app?
    File "app" (pru_icss_hsr-prp-dan_prebuilt_01.00.02.00\pru_icss_hsr-prp-dan_prebuilt_01.00.02.00\applications\prp_app_arm\AM437x_release) is not .bin or .hex.

    Tx/Rx test now run without exception, but I did not test with 2 nodes. I will get another IDK so it will be tested soon.
    I don't know why breakpoint on BIOS_start will effect behavior. How I understand problem is that HW interrupt is enabled by default or is not well defined on startup so it produce random behavior.

    Regards, Mare 

  • Mare,

    The pre-built app needs to be run from SD card, please refer to the section "Booting Via SD Card" - processors.wiki.ti.com/.../AM437x. Essentially you need to format a SD card with the processor_sdk_rtos_am437x_4_00_00_04\prebuilt-sdcards\evmAM437x\sd_card_img, then replace the MLO and app. The MLO (bootloader_boot_mmcsd_a9host_release_ti.bin) is at at pdk_am437x_1_0_7\packages\ti\starterware\binary\bootloader\bin\am43xx-evm\gcc.

    Regards,
    Garrett
  • Garrett,

    great explanation/guide for SD!

    Prebuild image doesn't have issues with pluged cable on the startup! It's working fine until TX test. Ping is "Request time out" after TX test is executed.
    hm.... prebuild work fine on startup....my build faill (without fix on rx interrupt)... my build on your network don't fail. I'm confused....


    Best Regards, Mare

  • Mare,

    Have you tried to build your image with RELEASE (not DEBUG) build configuration and without rx interrupt fix?
    Also ensure the components in your build is from PRSDK 3.3 as listed here: processors.wiki.ti.com/index.php

    Tx test is a bug that has been planed to be fixed in next release.

    Regards,
    Garrett
  • Hi Garrett

    Garrett Ding said:

    Also ensure the components in your build is from PRSDK 3.3 as listed here: processors.wiki.ti.com/index.php 

    Everything OK.

    Garrett Ding said:

    Have you tried to build your image with RELEASE (not DEBUG) build configuration and without rx interrupt fix?
     

    ***********************************
    1.)I rebuild pdk to "relise"
    2.) app build as "debug"

    Resoult:
    Every time fail with exception. 

    ***********************************

    1.)I rebuild pdk to "relise"
    2.) app build as "relise"

    Resoult:
    Some times it pass normally on startup, but most of the time the exception is produced.

    At beginning it looked like the system shows the pattern where it doesn't make exception if debug configuration is run for first time (erase configuration -> make new and run), but now I think is just random effect.

    Garrett Ding said:


    Tx test is a bug that has been planed to be fixed in next release.

    Also extended example with TCP and UDP will be usefull.

    Regards, Mare

  • Garrett,

    I know that there is some documentation where is describe how to make boot SD... but can you point me (to save time on exploring)?!
    I wish to make boot SD with this app/build to confirm that debugger doesn't have any influence on code.

    Thanks!

    Regards, Mare
  • Mare,

    Are you looking for this:

    The pre-built app needs to be run from SD card, please refer to the section "Booting Via SD Card" - processors.wiki.ti.com/.../AM437x Essentially you need to format a SD card with the processor_sdk_rtos_am437x_4_00_00_04\prebuilt-sdcards\evmAM437x\sd_card_img, then replace the MLO and app. The MLO (bootloader_boot_mmcsd_a9host_release_ti.bin) is at at pdk_am437x_1_0_7\packages\ti\starterware\binary\bootloader\bin\am43xx-evm\gcc.

    Regards,
    Garrett
  • Garrett,

    I think you miss understood...
    This is already clear....

    I would like made "app" file from my project. So I can run IDK with my SDimage and see differences in my build and prebuild (TI relise) image. Also I would like to see if debuger has any influence on how program run. Point is that TI .bin image work OK...my build not...so I would like to run my image with SD to avoid debuger..
  • Oh.... is app file already made uder AM437x_relise folder???

    Sorry for that...
  • Got it. Yes, the app is made by the post-build script: ${PDK_INSTALL_PATH}/pdkAppImageCreate.bat ${PDK_INSTALL_PATH} ${CG_TOOL_ROOT} ${PROJECT_LOC}/${ConfigName} ${ProjName} AM437x arm, see Properties -> CCS build -> Steps -> Post build steps.

    No problem. The step/app location may need noted in UG wiki.
  • Hi garrett,

    Maybe my thinking about debugger/init debug session issues at least make some sense...
    If I load image as debug session, app fail. App loaded buy bootloader from SD work....
    Is possible that on debug session some values in RAM or periphery become random or previous set values (are not erased or set before load).... and in this case RX interrupt flag is set or whatever ???

    I think this behavioral with SD boot point closer to solution!

    Regards, Mare
  • Is possible to "force" debuger to erase/reset/set periphery/memory... ?
    Any suggestion how to test theory from previous post?

    Regards, Mare