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/AM4376: PRU-ICSS and PRU-EMAC sometimes drops packets

Part Number: AM4376

Tool/software: TI-RTOS

Hello,

We expirience rare problems with both PRP mode via PRU-ICSS and PRU_EMAC when PRU stops transferring packets for short period of time. I managed to identify that it caused by PRU by taking PRP statistics. Currently it happens on PRU-ICSS-HSR-PRP-DAN_01.00.03.02 package but I do not hope it is fixed in PRU-ICSS-HSR-PRP-DAN_01.00.04.02, though I will try to migrate my code.

The time is around 32.5ms.

We send packets with constant rate (sampled valued data) and this problem sometimes happens once per 10 seconds, sometimes once per half hour. But the the pause in RX (32.5ms) is more or less constant.

For me it looks like internal watchdog reboot of PRU or kind of DDoS protection, but I'm not sure and have no idea of how to proof that theory.

I'm now trying to migrate to 01.00.04.02 to check if fixed already, but I'd like to hear if it is known issue and if this time means something to TI developers.

Thanks, Alexander.

  • Updating to 01.00.04.02 did not resolved the issue. Same or little bit longer (up to 33ms) pauses noticed as well.
  • Alex,

    Is the issue reproducible on AM437x IDK as well? If so, we can try to reproduce the issue and debug. Also can you elaborate your test setup and how you measure the 32.5ms gap?

    Regards,
    Garrett
  • Garrett,

    I'm trying to rebuild it for AM437x IDK, but we have some additional hardware which I need to replace with stubs. I will try to finish porting code ASAP. Also we plan to run the resulting test on AM572x and AM65x boards which we have.

    We have IEC61850 analog merging unit emulator which generates traffic with precise period (4kHz per channel evenly distributed). Each packet individually numbered from 0 to 3999 within given second. We have constant gap if samples are missed of 130 (or 132 on newer edition) which gave us 0.25uS * 130 = 32.5mS.

  • Garrett,

    Finally I was able to reproduce same drops on AM437x IDK, but unlike our board it shows error in statistics:

    ==

    *

    Curr=777,Exp=643

    S T A T I S T I C S

    Lookup error A : 03337694

    Lookup error B : 00000000

         Tx  WrongLan        Rx    Errors     Nodes     Proxy    Unique   Duplic.     Multi     OwnRx

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

    00000474  00000000  00000000  00000399  00000001  00000000  00000000  00000000  00000000  00000000

    00000000  00000000  00000000  00000000                      00000000  00000000  00000000  00000000

    03337694  00000000  00000000  00000000                      00000000  00000000  00000000

    ==

    My app is based on PRP example and I connect SAN device to port A. I attached our changes to PDK, NDK and PRU packages (BTW, it would be great if responsible person from TI finally sync PRU package with current SDK since it not compile from the box over half year at least).

    ndk.diff
    diff -ru ndk_3_40_01_01/packages/ti/ndk/stack/nimu/nimu.c ndk_3_40_09_99/packages/ti/ndk/stack/nimu/nimu.c
    --- ndk_3_40_01_01/packages/ti/ndk/stack/nimu/nimu.c	2018-08-31 19:18:35.000000000 +0300
    +++ ndk_3_40_09_99/packages/ti/ndk/stack/nimu/nimu.c	2019-01-18 16:23:35.084953100 +0300
    @@ -232,6 +232,7 @@
         PBM_Pkt*      ptr_pkt = (PBM_Pkt *)hPkt;
         uint32_t      Type;
         ETHHDR*       ptr_eth_header;
    +    VLANHDR*      ptr_eth_vlanheader;  // vlan patch
     	int			  retVal;
     
     
    @@ -271,7 +272,17 @@
     
         /* Check if the packet type is a VLAN packet. */
         if (Type == 0x8100)
    -        Type = VLANReceivePacket (hPkt);
    +    {
    +        // vlan patch
    +        //do not support VLAN now Type = VLANReceivePacket (hPkt);
    +        //ignore VLAN tag
    +        ptr_eth_vlanheader = (VLANHDR *) (ptr_pkt->pDataBuffer + ptr_pkt->DataOffset);
    +        Type = NDK_ntohs( ptr_eth_vlanheader->EncapProtocol );
    +        ptr_pkt->EtherType = Type;
    +        ptr_pkt->ValidLen   -= VLANHDR_SIZE;
    +        ptr_pkt->DataOffset += VLANHDR_SIZE;
    +        ptr_pkt->L2HdrLen   += VLANHDR_SIZE;
    +    }
     
         /* Dispatch the Packet to the appropriate protocol layer. */
         switch( Type )
    diff -ru ndk_3_40_01_01/packages/ti/ndk/stack/raweth/raweth.c ndk_3_40_09_99/packages/ti/ndk/stack/raweth/raweth.c
    --- ndk_3_40_01_01/packages/ti/ndk/stack/raweth/raweth.c	2018-08-31 19:18:35.000000000 +0300
    +++ ndk_3_40_09_99/packages/ti/ndk/stack/raweth/raweth.c	2019-01-18 17:18:07.379117600 +0300
    @@ -154,7 +154,7 @@
             NDK_raweths.SndNoPacket++;
             return (NDK_EINVAL);
         }
    -
    +    
         /* Configure the length and offsets to accomodate the buffers */
         pPkt->ValidLen    =  len;
     
    @@ -197,7 +197,7 @@
     {
     
         PBM_Pkt*        ptr_pkt = (PBM_Pkt *)hPkt;
    -    uint32_t        Type;
    +//    uint32_t        Type;
         int32_t         len;
         ETHHDR*         ptr_eth_header;
         SOCKRAWETH      *hRawEthSock;
    @@ -216,14 +216,15 @@
         ptr_pkt->DataOffset -= ptr_pkt->L2HdrLen;
     
         /* Get the pointer to the Ethernet Header. */
    -    ptr_eth_header = (ETHHDR *) (ptr_pkt->pDataBuffer + ptr_pkt->DataOffset);
    +//vlan patch    ptr_eth_header = (ETHHDR *) (ptr_pkt->pDataBuffer + ptr_pkt->DataOffset);
     
         /* Use the type field to determine if we have a matching
          * raw ethernet channel open
          */
    -    Type = NDK_ntohs (ptr_eth_header->Type);
    +//vlan patch    Type = NDK_ntohs (ptr_eth_header->Type);
     
    -    hRawEthSock = RawEthSockPcbFind (Type, ptr_pkt->hIFRx);
    +//vlan patch    hRawEthSock = RawEthSockPcbFind (Type, ptr_pkt->hIFRx);
    +    hRawEthSock = RawEthSockPcbFind (ptr_pkt->EtherType, ptr_pkt->hIFRx);
     
         if (!hRawEthSock)
         {
    
    pdk.diff
    diff -ru pdk_am437x_1_0_14.orig/packages/ti/drv/icss_emac/icss_emacDrv.h pdk_am437x_1_0_14/packages/ti/drv/icss_emac/icss_emacDrv.h
    --- pdk_am437x_1_0_14.orig/packages/ti/drv/icss_emac/icss_emacDrv.h	2019-04-06 05:36:51.000000000 +0300
    +++ pdk_am437x_1_0_14/packages/ti/drv/icss_emac/icss_emacDrv.h	2019-04-24 10:50:41.240158700 +0300
    @@ -244,7 +244,7 @@
         *     If packets are in Queue <=ethPrioQueue, they will be forwarded to NRT callback
         *     and others to RT callback
         */
    -    uint8_t ethPrioQueue;
    +    uint8_t ethPrioQueue[4];
         /** Flag to enable learning. Not applicable for Mac mode */
         uint8_t learningEn;
         /**Port Mask. Indication to LLD which ports to be used
    diff -ru pdk_am437x_1_0_14.orig/packages/ti/drv/icss_emac/src/icss_emacDrv.c pdk_am437x_1_0_14/packages/ti/drv/icss_emac/src/icss_emacDrv.c
    --- pdk_am437x_1_0_14.orig/packages/ti/drv/icss_emac/src/icss_emacDrv.c	2019-04-06 05:36:51.000000000 +0300
    +++ pdk_am437x_1_0_14/packages/ti/drv/icss_emac/src/icss_emacDrv.c	2019-04-24 10:52:48.126969500 +0300
    @@ -193,7 +193,13 @@
         if((((ICSS_EmacObject*)icssemacHandle->object)->emacInitcfg)->portMask == ICSS_EMAC_MODE_MAC2) {
             ICSS_EmacClearIrq(icssemacHandle, 21);
         } else {
    -        ICSS_EmacClearIrq(icssemacHandle, 20);
    +        uint32_t intStatus = HW_RD_REG32(((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->prussIntcRegs + CSL_ICSSINTC_SECR0));
    +
    +        if ( intStatus & ( ((uint32_t)1U) << 20 ) )
    +            ICSS_EmacClearIrq(icssemacHandle, 20);
    +
    +        if ( intStatus & ( ((uint32_t)1U) << 21 ) )
    +            ICSS_EmacClearIrq(icssemacHandle, 21);
         }
     }
     
    @@ -2871,7 +2877,7 @@
             if(pLength > 0)
             {
                 /* Invoke  receive packet callback function */
    -            if((rxPktInfo.queueNumber >= ((ICSS_EmacObject*)(icssEmacHandle->object))->emacInitcfg->ethPrioQueue) 
    +            if(( ((ICSS_EmacObject*)(icssEmacHandle->object))->emacInitcfg->ethPrioQueue[rxPktInfo.queueNumber] == 0 ) 
     				&& (((ICSS_EmacObject*)icssEmacHandle->object)->icssEmacHwIntRx != NULL))
                 {
                       ((ICSS_EmacObject*)icssEmacHandle->object)->icssEmacHwIntRx(&rxPktInfo.queueNumber,icssEmacHandle);
    
    pru.diff
    diff -ru PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/board/common/osdrv_ndkdeviceconfig.c PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/common/osdrv_ndkdeviceconfig.c
    --- PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/board/common/osdrv_ndkdeviceconfig.c	2018-06-29 16:39:28.000000000 +0300
    +++ PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/common/osdrv_ndkdeviceconfig.c	2019-04-26 19:13:47.961538800 +0300
    @@ -59,7 +59,7 @@
     /* ========================================================================== */
     static uint32_t nimuDeviceIndex = 0;
     static HANDLE nimuEmacHandle[MAX_ICSSNIMU_TBL_ENTRIES];
    -NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[MAX_ICSSNIMU_TBL_ENTRIES];
    +NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[MAX_ICSSNIMU_TBL_ENTRIES + 1] = {{.init = NULL}};
     
     /*
      * Desc
    @@ -84,7 +84,7 @@
             NIMUDeviceTable[nimuDeviceIndex].init =  initFct ;
             nimuEmacHandle[nimuDeviceIndex++] = emacHandle;
     
    -        if(nimuDeviceIndex < MAX_ICSSNIMU_TBL_ENTRIES)
    +        if(nimuDeviceIndex < MAX_ICSSNIMU_TBL_ENTRIES + 1)
             {
                 NIMUDeviceTable[nimuDeviceIndex].init =  NULL ;
             }
    diff -ru PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/board/include/osdrv_ndkdeviceconfig.h PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/include/osdrv_ndkdeviceconfig.h
    --- PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/board/include/osdrv_ndkdeviceconfig.h	2018-06-29 16:39:28.000000000 +0300
    +++ PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/include/osdrv_ndkdeviceconfig.h	2019-04-24 12:05:11.375313500 +0300
    @@ -52,6 +52,7 @@
     typedef int (*NIMUInitFn)(STKEVENT_Handle hEvent) ;
     
     typedef void       *NimuHandle;
    +typedef void       *HANDLE;
     
     /* ========================================================================== */
     /*                         Structures and Enums                               */
    diff -ru PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/hsr_prp/hsr_prp_menu.c PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_menu.c
    --- PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/hsr_prp/hsr_prp_menu.c	2018-06-29 16:39:28.000000000 +0300
    +++ PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_menu.c	2019-04-29 14:45:36.517534300 +0300
    @@ -64,6 +64,8 @@
     #define RED_HSR_LRE_MODE_M             "MODE M"
     #define RED_HSR_LRE_MODE_UNKNOWN       "UNKNOWN"
     
    +//#define MINIMIZE_STATS
    +
     /**Interface macid index*/
     #define INTERFACE_MAC 0
     /**Port1 macid index*/
    @@ -433,6 +435,7 @@
         char pMsg[1024];
         RED_STATISTICS stats;
     
    +#ifndef MINIMIZE_STATS
     #ifdef ICSS_PROTOCOL_HSR
         char *mode = getHsrLreModePrintStr(emachandle);
         sprintf(pMsg,
    @@ -447,6 +450,7 @@
                 "S T A T I S T I C S\n\r"
                 "\n\r");
         UART_printf(pMsg);
    +#endif
     
         if(RedGetStatistics(&stats, emachandle) != RED_OK)
         {
    @@ -455,6 +459,9 @@
             return;
         }
     
    +#ifdef MINIMIZE_STATS
    +    UART_printf("\n%08d (%08d) - %08d (%08d) - %08d ", (int)stats.cntLookupErrA, (int)stats.cntErrorsA, (int)stats.cntLookupErrB, (int)stats.cntErrorsB, (int)stats.cntTxC);
    +#else
         sprintf(pMsg,
                 "Lookup error A : %08d\n\r"
                 "Lookup error B : %08d\n\r"
    @@ -495,6 +502,7 @@
                 stats.RXB_FWD_FAILACQU_QUEUE);
         UART_printf(pMsg);
     #endif /* RED_STATS_DBG */
    +#endif
     }
     
     void printLreStatistics(ICSSEMAC_Handle emachandle)
    @@ -904,7 +912,7 @@
         HANDLE      hCfgIpAddr;
     
         if(CfgGetImmediate(0, CFGTAG_IPNET, 1, 1, sizeof(NA),
    -                       (UINT8 *)&NA) == sizeof(NA))
    +                       (unsigned char *)&NA) == sizeof(NA))
         {
             /* get the current static IP entry */
             CfgGetEntry(0, CFGTAG_IPNET, 1, 1, &hCfgIpAddr);
    @@ -931,14 +939,14 @@
         bzero(&NA, sizeof(NA));
     
     
    -    NA.IPAddr = (IPN)dwIPAddress;
    +    NA.IPAddr = dwIPAddress;
         NA.IPMask  = inet_addr("255.255.255.0");
         strcpy(NA.Domain, "demo.net");
         NA.NetType = 0;
     
         /* add a new static IP entry */
         CfgAddEntry(0, CFGTAG_IPNET, 1, 0,
    -                sizeof(CI_IPNET), (UINT8 *)&NA, 0);
    +                sizeof(CI_IPNET), (unsigned char *)&NA, 0);
         return TRUE;
     }
     
    diff -ru PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/hsr_prp/hsr_prp_tools.c PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_tools.c
    --- PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/hsr_prp/hsr_prp_tools.c	2018-06-29 16:39:28.000000000 +0300
    +++ PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_tools.c	2019-04-24 15:08:20.204006800 +0300
    @@ -108,7 +108,7 @@
     
     
         src = packet + START_OF_UDP_HEADER;
    -    memcpy(&(pseudoIPHeader[12]), src, DEFAULT_UDP_HEADER_SIZE);
    +    memcpy(&(pseudoIPHeader[12]), src, DEFAULT_UDP_HEADER_SIZE - 2); // minus checksum size
     
         checksum = calcChecksum(pseudoIPHeader, 18);
     

  • I based my test on PRP source since we more interested in it but we saw same effect with EMAC driver as well on our board.
    What is "Errors" counter means?
  • Alex,

    >> we saw same effect with EMAC driver as well
    Do you mean there are packets dropped if increasing the number of packets in icss emac loopback example? And the result is based on the latest PDK 1.0.14 (shown in your diff file) from Processor SDK 5.3.

    The 'Errors' means invalid frames received from the port.

    Regards,
    Garrett
  • We saw exactly same numbers of packets missing in our app with PDK 1.0.12. I have not tried with newer PDK but I don't believe it will change anything.

  • Alex,

    The 1.0.14 shown in your pdk.diff file is already the latest PDK version.

    >>diff -ru pdk_am437x_1_0_14.orig/packages/ti/drv/icss_emac/icss_emacDrv.h pdk_am437x_1_0_14/packages/ti/drv/icss_emac/icss_emacDrv.h

    I will try to run the icss emac loopback example to see if any packets drop in my IDK.

    Regards,
    Garrett
  • Hi Garrett,

    Was your able to reproduce problem? It is very urgent for us (and everyone targeting for iec61850 devices for which Sitara was advertised).

  • A bit more additional information:

    I connected SAN device to IDK via Moxa Redbox in PRP mode. For now I don't see missing frames on the app side but the errors counters are increasing on both interfaces. That means that errors happens on the PRUs in different time.

    ==

    S T A T I S T I C S

    Lookup error A : 15760153
    Lookup error B : 15759354

    Tx WrongLan Rx Errors Nodes Proxy Unique Duplic. Multi OwnRx
    -------- -------- -------- -------- -------- -------- -------- -------- -------- --------
    00000664 00000000 15760153 00000800 00000003 00000000 00000000 00000000 00000000 00000000
    00000664 00000000 15759354 00001597 00000000 00000000 00000000 00000000
    15761558 00000000 00000000 00000000 00002488 15757328 00000004

    ==

    Is there a way to debug exact error reason? If you want any test on my side I'm open to help.

  • Alex,

    I increased the ICSS_EMAC_TEST_PKT_TX_COUNT and ran the ICSS_EMAC_BasicExample_idkAM437x_wSoCLib_armtestproject loopback test for an hour but could not see any packet drop.

    The error statistic from PRU can be CRC count, oversize, undersize frames, Rx Error, and SFD Error. Can you upload a device Ethernet connection topology graph so I can better understand your use case? Have you tried to capture the packets with a netANALYZER to see if any malformed PRP packets on the wire?

    Regards,
    Garrett
  • Garrett,

    We tested this in different environments. Initially we found with the real merging units and Moxa PT-75xx series switches where only PRP LAN A was used. Then we tried same on the table with the merging unit simulator, Cisco SG100D and two different TrendNet switches and finally with the merging unit simulator and Moxa PT-G503-PTP Redbox. The result was the same: sometimes series from 399 to 401 packets goes to trash.

    We don't have netANALYZER but Wireshark doesn't show anything suspicious on missed frames and around them.

    Today I tried to reproduce the problem on IDK based on NIMU_ICSS_BasicExample with PDK 1.0.12 and 1.0.14 and I was not able to reproduce it on the table. Not sure what was wrong when we noticed that on our board, but we use customized NDK and HSR/PRP packages which allows us to switch operation mode at run-time and probably something was wrong there (most likely we loaded PRP firmware by mistake instead of EMAC) or may be we have another issue with our board which looks similar.

    So I suggest to focus on PRP firmware on IDK where the problem is reproducible.

    I noticed there's additional debug statistics in PRU-ICSS-HSR-PRP-DAN_01.00.04.02 under RED_STATS_DBG/LRE_DEBUG_STATS but it doesn't compile. Should I try to fix it or it requires special PRU firmware to operate?

  • Alex,

    RED_STATS_DBG doesn't require special PRU firmware to operate. I will work with our system test team to try to replicate the setup and issue...

    Regards,
    Garrett
  • Garrett,

    Thanks. I added debug fields to LRE stats but all these fields contain zeroes.

    Also, I mixed NIMU_ICSS code with PRP code and was able to reproduce packet drop on EMAC. The operateMode variable located in main() responsible for the mode (0 for EMAC and 1 for PRP). The app is based on prp_app_AM437x_arm, but I removed most of unnecessary code to make code smaller.

    I put project file to archive and changed sources/link script files to src/ directory (in project they are referenced to other directories, I just put them together in the archive). I hope I didn't forgot anything required to build.

    We have holidays till May 13, but I will monitor forum to respond if any questions appear.

    LRE_START 0
    LRE_CNT_TX_A 949
    LRE_CNT_TX_B 0
    LRE_CNT_TX_C 366b867
    LRE_CNT_ERRWRONGLAN_A 0
    LRE_CNT_ERRWRONGLAN_B 0
    LRE_CNT_ERRWRONGLAN_C 0
    LRE_CNT_RX_A 0
    LRE_CNT_RX_B 0
    LRE_CNT_RX_C 0
    LRE_CNT_ERRORS_A 144a
    LRE_CNT_ERRORS_B 0
    LRE_CNT_ERRORS_C 0
    LRE_CNT_NODES 1
    LRE_CNT_PROXY_NODES 0
    LRE_CNT_UNIQUE_RX_A 0
    LRE_CNT_UNIQUE_RX_B 0
    LRE_CNT_UNIQUE_RX_C 0
    LRE_CNT_DUPLICATE_RX_A 0
    LRE_CNT_DUPLICATE_RX_B 0
    LRE_CNT_DUPLICATE_RX_C 0
    LRE_CNT_MULTIPLE_RX_A 0
    LRE_CNT_MULTIPLE_RX_B 0
    LRE_CNT_MULTIPLE_RX_C 0
    LRE_CNT_OWN_RX_A 0
    LRE_CNT_OWN_RX_B 0
    LRE_DUPLICATE_DISCARD 2
    LRE_TRANSPARENT_RECEPTION 1
    LRE_NODE_TABLE_LOOKUP_ERROR_A 366bae3
    LRE_NODE_TABLE_LOOKUP_ERROR_B 0
    LRE_NODE_TABLE_FULL 0
    LRE_MULTICAST_DROPPED 0
    LRE_VLAN_DROPPED 0
    LRE_INTR_TMR_EXP 0
    LRE_TOTAL_RX_A 0
    LRE_TOTAL_RX_B 0
    LRE_OVERFLOW_PRU0 0
    LRE_OVERFLOW_PRU1 0
    LRE_DD_PRU0 0
    LRE_DD_PRU1 0
    LRE_CNT_SUP_PRU0 0
    LRE_CNT_SUP_PRU1 0

    prp_small_AM437x.7z

  • Alex,

    I am seeing several error while building your project, will look into it to see if I can fix it without updated files from you on your holidays.

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

    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_menu.c:907:25: error: 'UINT8' undeclared (first use in this function); did you mean 'UInt8'?
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_menu.c:907:32: error: expected expression before ')' token
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_menu.c:934:18: error: 'IPN' undeclared (first use in this function); did you mean 'IP6N'?
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_menu.c:934:22: error: expected ';' before 'dwIPAddress'
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_menu.c:941:36: error: 'UINT8' undeclared (first use in this function); did you mean 'UInt8'?
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_menu.c:941:43: error: expected expression before ')' token
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_menu.c:940:5: error: too few arguments to function 'CfgAddEntry'
    gmake: *** [hsr_prp_menu.o] Error 1
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/include/osdrv_ndkdeviceconfig.h:79:49: error: unknown type name 'HANDLE'; did you mean '_AND'?
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/include/osdrv_ndkdeviceconfig.h:81:1: error: unknown type name 'HANDLE'; did you mean '_AND'?
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/common/osdrv_ndkdeviceconfig.c:61:8: error: unknown type name 'HANDLE'
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/common/osdrv_ndkdeviceconfig.c:74:49: error: unknown type name 'HANDLE'; did you mean '_AND'?
    C:/ti/PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/common/osdrv_ndkdeviceconfig.c:101:1: error: unknown type name 'HANDLE'; did you mean '_AND'?
    gmake: *** [board_common/osdrv_ndkdeviceconfig.o] Error 1
    gmake: Target 'all' not remade because of errors.

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

    Regards,

    Garrett

  • That also the problem of original example from TI. I forgot that I added these defines to allow app build.

    HANDLE is a pointer to void, IPN is uint32_t, UINT8 is uint8_t.

    Building SMTP support in original app is tricky as well, but I removed all these code.

  • Thanks Alex. I was able to build your project (had to add TimeSync_ParamsHandle_t timeSyncHandle; in small_main.c), but the program crashes immediately after run. What are the patches you added in the NDK and PDK?

    Also I discussed with our team, here is more questions:
    1. What are the conditions for failure ? Packet size, IPG
    2. Type of failure – Packet loss, corruption. Packet loss is mentioned but is there corruption as well ?
    3. As per diagram is it verified that packet is lost at DUT only and not at RedBox ?
    4. Were more tests done on DUT to verify where the packet is lost ? In firmware or in the Host ?

    Regards,
    Garrett
  • I applied patches to PDK shown above and part of NDK patch related to rawsocket support.

    1. Packet size is about 124 bytes IIRC. There's three sampled values sources at my setup, with frame rate 4000 packets per second on each stream. The packets are precisely evenly distributed in time for each channel.

    2. There's no corrupted frames detected at the app level. Only lost frames which are shown at error statistics.

    3. I didn't verified this with Redbox, but with the switch I saw missed frames at Wireshark and I no something special I can tell about these frames.

    4. As long as I see these missed frames in Wireshark and in error statistics of the DUT I'd say error happens on the DUT side. And I used different switches from different manufacturers, so I doubt it is switch related problem.

  • I built app in Release configuration where PTP_TESTING symbol removed and LRE_DEBUG_STATS added. And there's custom hsr_prp_menu.c included in archive though I don't think it is a reason of crash.

    Here are the patches to PDK, NDK and HSR/PRP package I use.

    4048.pdk.diff
    diff -ru pdk_am437x_1_0_14.orig/packages/ti/drv/icss_emac/icss_emacDrv.h pdk_am437x_1_0_14/packages/ti/drv/icss_emac/icss_emacDrv.h
    --- pdk_am437x_1_0_14.orig/packages/ti/drv/icss_emac/icss_emacDrv.h	2019-04-06 05:36:51.000000000 +0300
    +++ pdk_am437x_1_0_14/packages/ti/drv/icss_emac/icss_emacDrv.h	2019-04-24 10:50:41.240158700 +0300
    @@ -244,7 +244,7 @@
         *     If packets are in Queue <=ethPrioQueue, they will be forwarded to NRT callback
         *     and others to RT callback
         */
    -    uint8_t ethPrioQueue;
    +    uint8_t ethPrioQueue[4];
         /** Flag to enable learning. Not applicable for Mac mode */
         uint8_t learningEn;
         /**Port Mask. Indication to LLD which ports to be used
    diff -ru pdk_am437x_1_0_14.orig/packages/ti/drv/icss_emac/src/icss_emacDrv.c pdk_am437x_1_0_14/packages/ti/drv/icss_emac/src/icss_emacDrv.c
    --- pdk_am437x_1_0_14.orig/packages/ti/drv/icss_emac/src/icss_emacDrv.c	2019-04-06 05:36:51.000000000 +0300
    +++ pdk_am437x_1_0_14/packages/ti/drv/icss_emac/src/icss_emacDrv.c	2019-04-24 10:52:48.126969500 +0300
    @@ -193,7 +193,13 @@
         if((((ICSS_EmacObject*)icssemacHandle->object)->emacInitcfg)->portMask == ICSS_EMAC_MODE_MAC2) {
             ICSS_EmacClearIrq(icssemacHandle, 21);
         } else {
    -        ICSS_EmacClearIrq(icssemacHandle, 20);
    +        uint32_t intStatus = HW_RD_REG32(((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->prussIntcRegs + CSL_ICSSINTC_SECR0));
    +
    +        if ( intStatus & ( ((uint32_t)1U) << 20 ) )
    +            ICSS_EmacClearIrq(icssemacHandle, 20);
    +
    +        if ( intStatus & ( ((uint32_t)1U) << 21 ) )
    +            ICSS_EmacClearIrq(icssemacHandle, 21);
         }
     }
     
    @@ -2871,7 +2877,7 @@
             if(pLength > 0)
             {
                 /* Invoke  receive packet callback function */
    -            if((rxPktInfo.queueNumber >= ((ICSS_EmacObject*)(icssEmacHandle->object))->emacInitcfg->ethPrioQueue) 
    +            if(( ((ICSS_EmacObject*)(icssEmacHandle->object))->emacInitcfg->ethPrioQueue[rxPktInfo.queueNumber] == 0 ) 
     				&& (((ICSS_EmacObject*)icssEmacHandle->object)->icssEmacHwIntRx != NULL))
                 {
                       ((ICSS_EmacObject*)icssEmacHandle->object)->icssEmacHwIntRx(&rxPktInfo.queueNumber,icssEmacHandle);
    
    ndk-vlan-raweth.diff
    diff -ru ndk_3_40_01_01/packages/ti/ndk/stack/raweth/raweth.c ndk_3_40_01_01.vlan/packages/ti/ndk/stack/raweth/raweth.c
    --- ndk_3_40_01_01/packages/ti/ndk/stack/raweth/raweth.c	2018-08-31 19:18:35.000000000 +0300
    +++ ndk_3_40_01_01.vlan/packages/ti/ndk/stack/raweth/raweth.c	2019-05-06 17:32:02.752635600 +0300
    @@ -197,7 +197,6 @@
     {
     
         PBM_Pkt*        ptr_pkt = (PBM_Pkt *)hPkt;
    -    uint32_t        Type;
         int32_t         len;
         ETHHDR*         ptr_eth_header;
         SOCKRAWETH      *hRawEthSock;
    @@ -215,15 +214,10 @@
         ptr_pkt->ValidLen   += ptr_pkt->L2HdrLen;
         ptr_pkt->DataOffset -= ptr_pkt->L2HdrLen;
     
    -    /* Get the pointer to the Ethernet Header. */
    -    ptr_eth_header = (ETHHDR *) (ptr_pkt->pDataBuffer + ptr_pkt->DataOffset);
    -
         /* Use the type field to determine if we have a matching
          * raw ethernet channel open
          */
    -    Type = NDK_ntohs (ptr_eth_header->Type);
    -
    -    hRawEthSock = RawEthSockPcbFind (Type, ptr_pkt->hIFRx);
    +    hRawEthSock = RawEthSockPcbFind (ptr_pkt->EtherType, ptr_pkt->hIFRx);
     
         if (!hRawEthSock)
         {
    

    0728.pru.diff
    diff -ru PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/board/common/osdrv_ndkdeviceconfig.c PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/common/osdrv_ndkdeviceconfig.c
    --- PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/board/common/osdrv_ndkdeviceconfig.c	2018-06-29 16:39:28.000000000 +0300
    +++ PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/common/osdrv_ndkdeviceconfig.c	2019-04-26 19:13:47.961538800 +0300
    @@ -59,7 +59,7 @@
     /* ========================================================================== */
     static uint32_t nimuDeviceIndex = 0;
     static HANDLE nimuEmacHandle[MAX_ICSSNIMU_TBL_ENTRIES];
    -NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[MAX_ICSSNIMU_TBL_ENTRIES];
    +NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[MAX_ICSSNIMU_TBL_ENTRIES + 1] = {{.init = NULL}};
     
     /*
      * Desc
    @@ -84,7 +84,7 @@
             NIMUDeviceTable[nimuDeviceIndex].init =  initFct ;
             nimuEmacHandle[nimuDeviceIndex++] = emacHandle;
     
    -        if(nimuDeviceIndex < MAX_ICSSNIMU_TBL_ENTRIES)
    +        if(nimuDeviceIndex < MAX_ICSSNIMU_TBL_ENTRIES + 1)
             {
                 NIMUDeviceTable[nimuDeviceIndex].init =  NULL ;
             }
    diff -ru PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/board/include/osdrv_ndkdeviceconfig.h PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/include/osdrv_ndkdeviceconfig.h
    --- PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/board/include/osdrv_ndkdeviceconfig.h	2018-06-29 16:39:28.000000000 +0300
    +++ PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/board/include/osdrv_ndkdeviceconfig.h	2019-04-24 12:05:11.375313500 +0300
    @@ -52,6 +52,7 @@
     typedef int (*NIMUInitFn)(STKEVENT_Handle hEvent) ;
     
     typedef void       *NimuHandle;
    +typedef void       *HANDLE;
     
     /* ========================================================================== */
     /*                         Structures and Enums                               */
    diff -ru PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/hsr_prp/hsr_prp_tools.c PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_tools.c
    --- PRU-ICSS-HSR-PRP-DAN_01.00.04.02.orig/examples/hsr_prp/hsr_prp_tools.c	2018-06-29 16:39:28.000000000 +0300
    +++ PRU-ICSS-HSR-PRP-DAN_01.00.04.02/examples/hsr_prp/hsr_prp_tools.c	2019-04-24 15:08:20.204006800 +0300
    @@ -108,7 +108,7 @@
     
     
         src = packet + START_OF_UDP_HEADER;
    -    memcpy(&(pseudoIPHeader[12]), src, DEFAULT_UDP_HEADER_SIZE);
    +    memcpy(&(pseudoIPHeader[12]), src, DEFAULT_UDP_HEADER_SIZE - 2); // minus checksum size
     
         checksum = calcChecksum(pseudoIPHeader, 18);
     

  • I think the reason why app crashes is that I put my sources in src directory in the project and I did not expect CCS "automagically" add them to the project. lnk_a8_a9_a15_REV1_2.cmd need to be excluded from build in the project and added via Build->GNU Linker->Libraries->Linker command files.
  • Alex,

    I did miss those patches as you mentioned that you removed most of unnecessary code. Will continue to try to reproduce the issue.
    Also I have forwarded your responses to those questions from team...

    Regards,
    Garrett

  • Alex,

    After applying the patches, I am just able to build and run your application with no more crash. I could assign a IP address to the device, but somehow it's not ping-able. Am I still missing anything? I haven't closely looked into your application. Does the application still need to be run with the test setup C as you described for reproducing the error stats?

    Regards,
    Garrett
  • Garrett,

    For sampled values we don't use IP, so I removed IP stack initialization.

    Here is C# code on top of PCAP which I used for testing. It works on my notebook Win7Pro x64 with Intel card, but caused BSOD on my desktop Win10Pro x64 with Realtek. That seems to be incompatibility with PCAP/Realtek drivers pair, though I'm not sure. The app is looking for interface with address 10.0.1.1 to send packets, you can change it in the code.

    The PC app is sending sampled values packets in group of 3 by default, each group of packet is numbered from 0 to 3999 within a roughly second. The small_main.c in the task taskLedBlink2 checks order of received packets and prints received (Curr) and expected (Exp) counter for the packet.

    Today I run it in few configurations:

    1) PC<-1G->Switch 1G<-100M->IDK, the problem reproduced

    2) PC<-100M->Switch 1G<-100M->IDK, the problem not reproduced but the Windows drops frame rate on unknown reason; there also was noted two big gaps in frames but the PRU statistics were clean, so I'm not sure what caused that

    3) PC<-1G->Switch 1G<-100M->Switch 100M<-100M->IDK, the problem reproduced

    I added printing of interval time in microseconds for which packets not received to small_main.c.

    ==

    *
    Curr=3802,Exp=3668,dT=33535
    *
    Curr=2715,Exp=2581,dT=33510
    *
    Curr=3566,Exp=3431,dT=33780
    *
    Curr=3221,Exp=3086,dT=33774
    *
    Curr=3629,Exp=3494,dT=33763
    *
    Curr=3737,Exp=3603,dT=33476

    ==

    small_main.c
    /**
    * @file main.c
    *
    * @brief Basic example for an HSR PRP device running on AM57xx devices.
    * Requires a full ICSS system (both PRUs) and two external phys connected to
    * ICSS MII/MDIO interfaces
    *
    * \par
    * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
    * \par
    *
    */
    
    #include <stdio.h>
    #include <stdbool.h>
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/ndk/inc/stkmain.h>
    
    #include <examples/osal/TaskP.h>
    
    /* TI-RTOS Header files */
    #include <ti/osal/osal.h>
    #include <ti/drv/uart/UART_stdio.h>
    #include <ti/board/board.h>
    #include <ti/drv/gpio/GPIO.h>
    #include <ti/drv/i2c/I2C.h>
    #include <ti/drv/spi/SPI.h>
    
    #include <stdint.h>
    #include <protocols/hsr_prp/version.h>
    
    #include <ti/drv/icss_emac/icss_emacFwInit.h>
    #include <ti/drv/icss_emac/icss_emacLearning.h>
    #include <ti/drv/icss_emac/icss_emacStatistics.h>
    #include <ti/drv/icss_emac/icss_emacDrv_Def.h>
    #include <ti/drv/icss_emac/icss_emacStormControl.h>
    #include <ti/transport/ndk/nimu_icss/example/src/osdrv_ndkdeviceconfig.h>
    #include <ti/drv/icss_emac/test/src/fw_mem_section.h>
    #include <ti/drv/icss_emac/icss_emacDrv.h>
    #include <ti/drv/icss_emac/soc/icss_emacSoc.h>
    #include <ti/drv/pruss/soc/pruicss_v1.h>
    #include <tiswitch_pruss_intc_mapping.h>
    #include <ti/csl/src/ip/icss/V1/cslr_icss_intc.h>
    #include <ti/csl/src/ip/icss/V1/cslr_icss_cfg.h>
    #if defined(SOC_K2G)
    #include <ti/csl/src/ip/bootcfg/V3/csl_bootcfgAux.h>
    #include <ti/csl/src/ip/bootcfg/V3/csl_bootcfg.h>
    #include <ti/board/src/iceK2G/include/iceK2G_ethernet_config.h>
    #include <ti/csl/src/ip/mdio/V1/cslr_mdio.h>
    #include <ti/csl/src/ip/mdio/V1/csl_mdio.h>
    #include <ti/csl/src/ip/mdio/V1/csl_mdioAux.h>
    #include <ti/csl/src/ip/icss/V1/cslr_icss_pru_ctrl.h>
    #elif defined(SOC_AM572x) || defined(SOC_AM571x) || 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>
    #endif
    #include <ti/transport/ndk/nimu_icss/nimu_icssEth.h>
    #ifdef SOC_AM335x
    #include <ti/csl/src/ip/gpio/V1/gpio_v2.h>
    #include <ti/starterware/include/hw/soc_am335x.h>
    #endif
    #include <ti/drv/spi/SPI.h>
    #include <ti/drv/spi/soc/QSPI_v1.h>
    /* Flash header file */
    #include <ti/drv/spi/SPIver.h>
    
    #include <ti/drv/spi/test/qspi_flash/src/Flash_S25FL/S25FL.h>
    
    #include <examples/board/include/board_i2cLed.h>
    #include <examples/board/include/board_gpioLed.h>
    #include <examples/board/include/board_misc.h>
    #include <examples/board/include/board_phy.h>
    #include <examples/board/include/board_spi.h>
    #include <examples/board/include/board_eeprom.h>
    #include <examples/board/include/delay_us.h>
    #include "hsrPrp_firmware.h"
    #if defined(SOC_AM335x) || defined(SOC_AM437x)
    #include "ti/starterware/include/chipdb.h"
    #include "ti/starterware/include/soc_control.h"
    #endif
    
    #include "hsr_prp_menu.h"
    
    #ifdef ICSS_PROTOCOL_RED
    #include "hsrPrp_red_osBios.h"
    #include "hsrPrp_red_nodeTable.h"
    #include "hsrPrp_red_snmp.h"
    #include "hsrPrp_red_statistics.h"
    #include "hsrPrp_red_config.h"
    #include "hsrPrp_red.h"
    #include "hsrPrp_handle.h"
    #include "hsrPrp_red_multicastTable.h"
    #include "hsrPrp_red_vlanTable.h"
    #endif /* ICSS_PROTOCOL_RED */
    
    #include "hsr_prp_fw_offsets.h"
    
    #ifdef BUILD_HSR_H
    #if defined(SOC_AM335x) || defined(SOC_AM437x)
    #include "protocols/hsr_prp/firmware/hsr/v1.0/icss_hsr_pru0_bin.h"
    #include "protocols/hsr_prp/firmware/hsr/v1.0/icss_hsr_pru1_bin.h"
    #else
    #include "protocols/hsr_prp/firmware/hsr/v2.1/icss_hsr_pru0_bin.h"
    #include "protocols/hsr_prp/firmware/hsr/v2.1/icss_hsr_pru1_bin.h"
    #endif
    #endif
    
    #ifdef BUILD_PRP
    #if defined(SOC_AM335x) || defined(SOC_AM437x)
    #include "protocols/hsr_prp/firmware/prp/v1.0/icss_prp_pru0_bin.h"
    #include "protocols/hsr_prp/firmware/prp/v1.0/icss_prp_pru1_bin.h"
    #else
    #include "protocols/hsr_prp/firmware/prp/v2.1/icss_prp_pru0_bin.h"
    #include "protocols/hsr_prp/firmware/prp/v2.1/icss_prp_pru1_bin.h"
    #endif
    #endif
    
    
    #ifdef SOC_K2G
    #define CSL_ICSSCFG_GPCFG0_PRU0_GP_MUX_SEL_MASK                 (0x3C000000U)
    #define CSL_ICSSCFG_GPCFG0_PRU0_GP_MUX_SEL_SHIFT                (26U)
    #define CSL_ICSSCFG_GPCFG0_PRU0_GP_MUX_SEL_RESETVAL             (0x00000000U)
    #define CSL_ICSSCFG_GPCFG0_PRU0_GP_MUX_SEL_MAX                  (0x00000004U)
    #define CSL_ICSSCFG_GPCFG0_PRU0_GP_MUX_SEL_MII_MODE_VAL         (2u)
    #endif
    
    #define RED_PRINTF_UART
    
    #define RED_REM_NODE_TYPE_STR_DANP     "DANP   "
    #define RED_REM_NODE_TYPE_STR_VDANP    "VDANP  "
    #define RED_REM_NODE_TYPE_STR_REDBOXP  "REDBOXP"
    #define RED_REM_NODE_TYPE_STR_DANH     "DANH   "
    #define RED_REM_NODE_TYPE_STR_VDANH    "VDANH  "
    #define RED_REM_NODE_TYPE_STR_REDBOXH  "REDBOXH"
    #define RED_REM_NODE_TYPE_STR_SANA     "SAN A  "
    #define RED_REM_NODE_TYPE_STR_SANB     "SAN B  "
    #define RED_REM_NODE_TYPE_STR_SANAB    "SAN AB "
    #define RED_REM_NODE_TYPE_STR_UNKNOWN  "UNKNOWN"
    
    #define RED_HSR_LRE_MODE_H             "MODE H"
    #define RED_HSR_LRE_MODE_N             "MODE N"
    #define RED_HSR_LRE_MODE_T             "MODE T"
    #define RED_HSR_LRE_MODE_U             "MODE U"
    #define RED_HSR_LRE_MODE_M             "MODE M"
    #define RED_HSR_LRE_MODE_UNKNOWN       "UNKNOWN"
    
    #include <examples/hsr_prp/hsr_prp_soc.h>
    
    #include <xdc/runtime/Timestamp.h>
    
    extern uint8_t check_ip;
    extern char IPString[20];
    
    /**
     * Default PCP to Q mapping. See description of function initializePCPtoQueueMap below
     */
    uint8_t default_pcp_2_queue_map[8] = {ICSS_EMAC_QUEUE4, ICSS_EMAC_QUEUE4, ICSS_EMAC_QUEUE3, ICSS_EMAC_QUEUE3, \
                                          ICSS_EMAC_QUEUE2, ICSS_EMAC_QUEUE2, ICSS_EMAC_QUEUE1, ICSS_EMAC_QUEUE1
                                         };
    
    
    #define SRC_ADDR    0x81000000
    #define DST_ADDR    0x82000000
    #define DUMMY_PARAM     4
    #define TEST_PARAM      2
    
    #define BOARD_IDKAM571x     1
    #define BOARD_IDKAM572x     2
    
    /*
     *  global data declaration
     */
    /** application version */
    #define APP_VERSION "2.0.0.0"
    
    /* Board specific definitions */
    #ifdef SOC_AM437x
    #define MCSPI_INSTANCE         (2U)
    #else
    #define MCSPI_INSTANCE         (3U)
    #endif
    
    #define QSPI_PER_CNT            (1U)
    #define QSPI_INSTANCE           (1U)
    #define QSPI_OFFSET             (4U)
    
    /*name of the C struct in PRU header file*/
    #define PRU0_FIRMWARE_NAME      PRU0_FIRMWARE
    #define PRU1_FIRMWARE_NAME      PRU1_FIRMWARE
    
    
    /** @brief rotary switch value on ICEv2 */
    Uint8 nodeAddr;                             /**< rotary switch value on ICEv2 */
    
    /**
     * @brief   Initialize the PCP to Queue Map to default value
     *          i.e. Queue 4 or lowest priority queue
     *
     * @param   emachandle Pointer to EMAC handle. Used to fetch shared RAM base address
     *
     * @return  none
     */
    void initializePCPtoQueueMap(ICSS_EmacHandle emachandle);
    
    /**
     * @brief   Load the PCP to Queue Map to shared RAM.
     *          The firmware uses this to
     *
     * @param   emachandle Pointer to EMAC handle. Used to fetch shared RAM base address
     * @param   pcp_2_queue_map pointer to PCP to Q mapping.
     *
     * The mapping is very simple. The memory is an 8 byte char array
     * with each byte containing the queue. The index of the byte corresponds to the
     * PCP value. Here lower value is higher priority queue, see default_pcp_2_queue_map for example
     * So we have as an example (see default_pcp_2_queue_map)
     * PCP         Queue       Mem Offset (QUEUE_2_PCP_MAP_OFFSET is base)
     * 0           Q4          0
     * 1           Q4          1
     * 2           Q3          2
     * ...
     * ...
     * 7           Q1          7
     *
     * @return  none
     */
    void loadPCPtoQueueMap(ICSS_EmacHandle emachandle, uint8_t *pcp_2_queue_map);
    
    void getMacid(char *buf_str);
    
    /** \brief PRU-ICSS LLD handle */
    PRUICSS_Handle prusshandle;
    /** \brief ICSSEmac LLD handle */
    ICSS_EmacHandle emachandle;
    
    
    #if defined(SOC_AM335x)
    Board_flashHandle flashHandle;
    #elif defined(SOC_K2G)
    Board_flashHandle flashHandle;
    extern Board_flashHandle boardFlashHandle;
    #else
    extern S25FL_Handle flashHandle;
    #endif
    
    SPI_Handle handle;
    
    uint8_t lclMac[6];
    Board_IDInfo boardInfo;
    uint32_t ipAddress;
    
    hsrPrpHandle *hsrPrphandle;
    extern int collision_pkt_dropped;
    extern int num_of_collision_occured;
    
    extern void Board_initSPI(void);
    extern void gpioLedPinmuxConfig();
    
    extern PRUICSS_Config pruss_config[2 + 1];
    
    extern ICSS_EmacBaseAddrCfgParams icss_EmacBaseAddrCfgParams[3];
    int rxcalBk = 0;
    
    /**Temporary placeholder to copy packets*/
    uint8_t  tempFrame[ICSS_EMAC_MAXMTU];
    
    /***********************************************************************/
    /* local functions declaration                                         */
    /***********************************************************************/
    
    /**
     * @brief   ICSS EMAC LLD handle init
     *
     * @param   PRU-ICSS LLD configuration
     *
     * @return  E_FAIL on failure, S_PASS on success
     */
    uint8_t ICSSEmacDRVInit(ICSS_EmacHandle handle, uint8_t instance);
    
    #if defined(SOC_AM572x)
    void SOCCtrlGetPortMacAddr(uint32_t portNum, uint8_t *pMacAddr);
    #endif
    /**
     *  @brief  Function to initialize the HSR/PRP driver handle
     *
     *          Implemented to facilitate multi-instance capability.
     *          Moving all global variables across the driver files to this handle in hsrPrp_handle.h file
     *
     *  @param   hsrPrpHandle   [in]  HSR driver handle
     *
     *  @retval  none
     *
     */
    void hsrPrpHandle_init(hsrPrpHandle *hsrPrphandle);
    
    /**
     *  @brief  Function to register the Port 1 LinkReset callback
     *
     *  @param   linkStatus   [in]  link status
     *  @param   arg2         [in]  pointer to a handle
     *
     *  @retval  none
     *
     */
    void hsrPrp_Port1linkResetCallBack(uint8_t linkStatus, void *arg2);
    
    /**
     *  @brief  Function to register the Port 2 LinkReset callback
     *
     *  @param   linkStatus   [in]  link status
     *  @param   arg2         [in]  pointer to a handle
     *
     *  @retval  none
     *
     */
    void hsrPrp_Port2linkResetCallBack(uint8_t linkStatus, void *arg2);
    
    /***********************************************************************/
    /* function definitions                                                */
    /***********************************************************************/
    
    /**
     * \brief main task to initialize all software components and run the stack
     *
     * \param a0 not used
     * \param a1 not used
     * \callgraph
     */
    Void taskPruss(UArg a0, UArg a1)
    {
        uint8_t firmwareLoad_done = 0;
        uint32_t prpMode = (uint32_t)a0;
    
        HSR_PRP_socInit();
    
        UART_printf("\nVersion - ");
        UART_printf(IND_PKG_VERSION);
    
        UART_printf("\nBoard name \t: ");
        UART_printf(boardInfo.boardName);
    
        UART_printf("\n\rChip Revision \t: ");
        UART_printf(boardInfo.version);
        UART_printf("\r\nBuild Timestamp      : %s %s", __DATE__, __TIME__);
    
        /*Initialize the PCP 2 Q map*/
        initializePCPtoQueueMap(emachandle);
    
        PRUICSS_pruDisable(prusshandle, ICSS_EMAC_PORT_1 - 1);
        PRUICSS_pruDisable(prusshandle, ICSS_EMAC_PORT_2 - 1);
    
        if (prpMode)
        {
            if(PRUICSS_pruWriteMemory(prusshandle, PRU_ICSS_IRAM(0) , 0,
                                      (uint32_t *) PRU0_FIRMWARE_NAME,
                                      sizeof(PRU0_FIRMWARE_NAME)))
            {
                if(PRUICSS_pruWriteMemory(prusshandle, PRU_ICSS_IRAM(1) , 0,
                                          (uint32_t *) PRU1_FIRMWARE_NAME,
                                          sizeof(PRU1_FIRMWARE_NAME)))
                {
                    firmwareLoad_done = TRUE;
                }
            }
        }
        else
        {
            if(PRUICSS_pruWriteMemory(prusshandle, PRU_ICSS_IRAM(0) , 0,
                                    (uint32_t *) &pru_imem0_rev1_start,
                                    &pru_imem0_rev1_end - &pru_imem0_rev1_start))
            {
                if(PRUICSS_pruWriteMemory(prusshandle, PRU_ICSS_IRAM(1) , 0,
                                    (uint32_t *) &pru_imem1_rev1_start,
                                    &pru_imem1_rev1_end - &pru_imem1_rev1_start))
                {
                    firmwareLoad_done = TRUE;
                }
            }
        }
    
        if(firmwareLoad_done)
        {
            PRUICSS_pruEnable(prusshandle, ICSS_EMAC_PORT_1 - 1);
            PRUICSS_pruEnable(prusshandle, ICSS_EMAC_PORT_2 - 1);
    
            if (prpMode)
            {
                RedProtocolStart(hsrPrphandle, emachandle);
    
                /*Load the default PCP to Queue mapping*/
                loadPCPtoQueueMap(emachandle, default_pcp_2_queue_map);
            }
        }
    }
    
    #ifdef ICSS_PROTOCOL_RED
    
    /*
     *  ---UART Menu task---
     */
    void taskUartMenu(UArg arg0, UArg arg1)
    {
        ICSSEMAC_Handle emachandle;
        char rxByte;
    
        /* Wait for PRU load complete */
        TaskP_sleep(3000);
        emachandle = (ICSSEMAC_Handle)arg0;
    
        while(1)
        {
            UART_printf("\n\r\n\r");
            printConfig(emachandle);
    
            rxByte = (char) UART_getc();
    
            if((rxByte == 'S') || (rxByte == 's'))
            {
                printStatistics(emachandle);
    
            }
    
            else if((rxByte == 'L') || (rxByte == 'l'))
            {
                printLreStatistics(emachandle);
    
            }
    
            else if((rxByte == 'N') || (rxByte == 'n'))
            {
                if (hsrPrphandle != NULL)
                {
                    printNodeTable(hsrPrphandle);
                }
            }
    
            else if((rxByte == 'M') || (rxByte == 'm'))
            {
                printMulticastFilterSubMenu();
                rxByte = (char) UART_getc();
    
                if((rxByte == 'D') || (rxByte == 'd'))
                {
                    hsrPrp_multicast_filter_config(emachandle, MULTICAST_FILTER_DISABLED);
                }
    
                else if((rxByte == 'E') || (rxByte == 'e'))
                {
                    hsrPrp_multicast_filter_config(emachandle, MULTICAST_FILTER_ENABLED);
                }
    
                else
                {
                    uint8_t bkupMacidString[30];
    
                    UART_gets((char *)bkupMacidString, -2);
    #if DEBUG_MC_FLT
                    UART_puts((char *)bkupMacidString, -2);
    #endif
    
                    if(isValidMacid((char *)bkupMacidString))
                    {
                        if((rxByte == 'M') || (rxByte == 'm'))
                        {
                            hsrPrp_multicast_filter_override_hashmask(emachandle, bkupMacidString);
                            UART_printf("\n\rSuccessfully configured new mask");
                        }
    
                        else if((rxByte == 'A') || (rxByte == 'a'))
                        {
                            hsrPrp_multicast_filter_update_macid(emachandle, bkupMacidString,
                                                                 ADD_MULTICAST_MAC_ID);
                            UART_printf("\n\rSuccessfully added");
                        }
    
                        else if((rxByte == 'R') || (rxByte == 'r'))
                        {
                            hsrPrp_multicast_filter_update_macid(emachandle, bkupMacidString,
                                                                 REMOVE_MULTICAST_MAC_ID);
                            UART_printf("\n\rSuccessfully removed");
                        }
                    }
                }
            }
    
            else if((rxByte == 'V') || (rxByte == 'v'))
            {
                printVlanFilterSubMenu();
                rxByte = (char) UART_getc();
    
                if((rxByte == 'D') || (rxByte == 'd'))
                {
                    vlan_filter_config(emachandle, VLAN_FLTR_DIS);
                }
    
                else if((rxByte == 'E') || (rxByte == 'e'))
                {
                    vlan_filter_config(emachandle, VLAN_FLTR_ENA);
                }
    
                else if((rxByte == 'A') || (rxByte == 'a'))
                {
                    char bkupMacidString[30];
                    UART_gets(bkupMacidString, -2);
    
                    unsigned int vid;
                    sscanf(bkupMacidString, "%u", &vid);
    
                    if(vid <= VLAN_VID_MAX)  /*No need to check for vid >= VLAN_VID_MIN as CWARN.NOEFFECT.UCMP.GE: Comparison of unsigned value against 0 is always true*/
                    {
                        vlan_filter_update_vid(emachandle, (uint16_t)vid, ADD_VLAN_VID);
                    }
                }
    
                else if((rxByte == 'R') || (rxByte == 'r'))
                {
                    char bkupMacidString[30];
                    UART_gets(bkupMacidString, -2);
    
                    unsigned int vid;
                    sscanf(bkupMacidString, "%u", &vid);
    
                    if(vid <= VLAN_VID_MAX)  /*No need to check for vid >= VLAN_VID_MIN as CWARN.NOEFFECT.UCMP.GE: Comparison of unsigned value against 0 is always true*/
                    {
                        vlan_filter_update_vid(emachandle, (uint16_t)vid, REM_VLAN_VID);
                    }
                }
    
                else if((rxByte == 'H') || (rxByte == 'h'))
                {
                    vlan_untagged_frames_config(emachandle,
                                                VLAN_FLTR_UNTAG_HOST_RCV_ALL);
                }
    
                else if((rxByte == 'N') || (rxByte == 'n'))
                {
                    vlan_untagged_frames_config(emachandle,
                                                VLAN_FLTR_UNTAG_HOST_RCV_NAL);
                }
    
                else if((rxByte == 'P') || (rxByte == 'p'))
                {
                    vlan_priotag_frames_config(emachandle,
                                               VLAN_FLTR_PRIOTAG_HOST_RCV_ALL);
                }
    
                else if((rxByte == 'Q') || (rxByte == 'q'))
                {
                    vlan_priotag_frames_config(emachandle,
                                               VLAN_FLTR_PRIOTAG_HOST_RCV_NAL);
                }
    
                else if((rxByte == 'S') || (rxByte == 's'))
                {
                    vlan_sv_frames_config(emachandle,
                                          VLAN_FLTR_SV_VLAN_FLOW_SKIP);
                }
    
                else if((rxByte == 'F') || (rxByte == 'f'))
                {
                    vlan_sv_frames_config(emachandle,
                                          VLAN_FLTR_SV_VLAN_FLOW_TAKE);
                }
            }
    
            else if((rxByte == 'F') || (rxByte == 'f'))
            {
                char bkupMacidString[30];
                UART_gets(bkupMacidString, -2);
    
                unsigned int intrPacStatus;
                sscanf(bkupMacidString, "%u", &intrPacStatus);
                intr_pac_config(emachandle, intrPacStatus);
            }
    
            else if((rxByte == 'I') || (rxByte == 'i'))
            {
                UART_printf("\n\rType IP Address and hit Enter:\t");
    
                if(readAndAssignIPAddress())
                {
                    UART_printf("\n\rSuccessfully assigned new IP address");
                }
    
            }
    
            else if((rxByte == 'R') || (rxByte == 'r'))
            {
                runRxTxTest(emachandle);
    
            }
    
            else if((rxByte == 'C') || (rxByte == 'c'))
            {
                printConfiguration(emachandle);
    
            }
    
            else if((rxByte == 'H') || (rxByte == 'h'))
            {
                printHelpMenu();
    
            }
    
            else
            {
                UART_printf("\n\r\n\rSorry didnt catch that. Unknown input\n\r");
                UART_printf("\n\r");
            }
    
        }
    
    }
    
    #endif /* ICSS_PROTOCOL_RED */
    
    uint32_t asn1ParseLen(const uint8_t **data)
    {
        const uint8_t *ptr = *data;
        uint32_t len = *ptr++;
        if (len != 0)
        {
            if (len & 0x80)
            {
                uint8_t lenLen = len & 0x7f;
                len = 0;
                while (lenLen--)
                {
                    len = (len << 8) | *ptr++;
                }
            }
        }
        *data = ptr;
        return len;
    }
    
    /**
     * @brief LED task for second LED
     *
     * @param arg0 not used
     * @param arg1 not used
     */
    void taskLedBlink2(UArg arg0, UArg arg1)
    {
        SOCKET s;
    
        int32_t pktlen;
        void *pRecvBuf;
        HANDLE hRecvBuf;
    
    #if !defined(SOC_K2G)
        gpioLedPinmuxConfig();
    #endif
        GPIO_init();
    
        /*Give an initial delay to make sure LED's are initialized*/
        TaskP_sleep(1000);
        /**
         * Sequence for LED 1 (Device Status LED)
         * Blink second LED Green color on and off
         */
        Board_setTriColorLED(BOARD_TRICOLOR1_YELLOW, 0);
        Board_setTriColorLED(BOARD_TRICOLOR1_GREEN, 0);
        Board_setTriColorLED(BOARD_TRICOLOR1_RED, 0);
    
        while(GetNdkStatus(0)== NIMU_STAT_PROGRESS || GetNdkStatus(0)==NIMU_STAT_UNKNOWN)
        {
            Task_sleep(100);
        }
    
        fdOpenSession( TaskSelf() );
        int devIndex = 1;
        static uint8_t prio_mapping[MAX_PRIO_VAL];
        int index;
        for (index = 0; index < MAX_PRIO_VAL; index++)
        {
            prio_mapping[index] = index;
        }
    
        NETIF_DEVICE *nd = NIMUFindByName("eth0");
        if (nd == NULL)
        {
            UART_printf("\nCannot find eth0\n");
        }
        else
        {
            devIndex = nd->index;
    #if 1 // VLAN
            /* Use the VLAN API to create a new VLAN device. */
            devIndex = VLANAddDevice (devIndex, 0, 4, prio_mapping);
            if (devIndex < 0)
            {
                UART_printf("\nError VLAN Failed errcode=%d\n", index);
                devIndex = nd->index;
            }
    #endif
        }
        s = socket(AF_RAWETH, SOCK_RAWETH, 0x88ba);
        if (s == INVALID_SOCKET)
        {
            UART_printf("\nFailed to create socket: 0x%x\n", fdError());
        }
        if (setsockopt(s, SOL_SOCKET, SO_IFDEVICE, &devIndex, sizeof(devIndex)) != 0)
        {
            UART_printf("\nFailed to assign SO_IFDEVICE on socket: 0x%x\n", fdError());
        }
        int val;
        int sz = sizeof(val);
        getsockopt(s, SOL_SOCKET, SO_RCVBUF, &val, &sz);
        val = 32768;
        if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) != 0)
        {
            UART_printf("\nFailed to assign SO_RCVBUF on socket: 0x%x\n", fdError());
        }
    #if 0
        uint16_t priority = 4;
        if (NDK_setsockopt(s, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0)
        {
            UART_printf("\nFailed to assign SO_IFDEVICE on socket: 0x%x\n", fdError());
        }
    #endif
        UART_printf("\nSV receiving\n");
    
        uint16_t prevSvId = 0xffff;
        uint32_t cnt = 0;
        uint32_t prev_time = Timestamp_get32();
        xdc_runtime_Types_FreqHz freq;
        Timestamp_getFreq(&freq);
    
        while(1)
        {
            pktlen = recvnc(s, &pRecvBuf, 0, &hRecvBuf);
            if(pktlen > 0)
            {
                uint16_t svId = 0xffff;
                const uint8_t *data;
                ETHHDR *pkt = (ETHHDR *)pRecvBuf;
                uint16_t Type = NDK_ntohs(pkt->Type);
                data = (Type == ETHERTYPE_VLAN) ? ((uint8_t *)pkt + ETHHDR_SIZE + VLANHDR_SIZE) : ((uint8_t *)pkt + ETHHDR_SIZE);
                data += 2 /* appid */ + 2 /* length */ + 4 /* reserved */;
                if (*data++ == 0x60) /* savpdu */
                {
                    uint32_t len = asn1ParseLen(&data);
                    if (*data++ == 0x80) /* noasdu */
                    {
                        len = asn1ParseLen(&data);
                        data += len;
                        if (*data++ == 0xa2)
                        {
                            len = asn1ParseLen(&data);
                            if (*data++ == 0x30)
                            {
                                len = asn1ParseLen(&data);
                                if (*data == 0x80)
                                {
                                    ++data;
                                    len = asn1ParseLen(&data);
                                    data += len;
                                }
                                if (*data == 0x81)
                                {
                                    ++data;
                                    len = asn1ParseLen(&data);
                                    data += len;
                                }
                                if (*data == 0x82)
                                {
                                    ++data;
                                    len = asn1ParseLen(&data);
                                    svId = ((uint16_t)data[0] << 8) | data[1];
                                }
                            }
                        }
                    }
                }
                if (svId != 0xffff)
                {
                    if ((svId != prevSvId) && (svId != ((prevSvId + 1) % 4000)))
                    {
                        UART_printf("*");
                        if (prevSvId != 0xffff)
                        {
                            UART_printf("\nCurr=%d,Exp=%d,dT=%u\n", svId, prevSvId, (Timestamp_get32() - prev_time)/(freq.lo/1000000));
                        }
                    }
                    prevSvId = svId;
                    prev_time = Timestamp_get32();
                }
                if ((cnt % 8000) >= 4000)
                {
                    Board_setTriColorLED(BOARD_TRICOLOR1_GREEN,  0);
                }
                else
                {
                    Board_setTriColorLED(BOARD_TRICOLOR1_GREEN,  1);
                }
                ++cnt;
                /*int i, j;
                UART_printf("\n");
                for (i = 0; i < 123;)
                {
                    int sz = ((123 - i) >= 16) ? 16 : (123 - i);
                    UART_printf("%08x:", i);
                    for (j = 0; j < sz; j++)
                    {
                        UART_printf(" %02x", ((uint8_t *)pkt)[i++]);
                    }
                    UART_printf("\n");
                }*/
                recvncfree(hRecvBuf);
                //break;
            }
            if(pktlen < 0) UART_printf("recvSV fdError %d\n", fdError());
        }
        shutdown(s, SHUT_RDWR);
        fdCloseSession( TaskSelf() );
    }
    
    
    #define PRCM_MODULE_IDLEST_FUNC          (0U)
    #define PRCM_MODULE_IDLEST_TRANS         (1U)
    #define PRCM_MODULE_IDLEST_IDLE          (2U)
    #define PRCM_MODULE_IDLEST_DISABLE       (3U)
    
    
    /**
     * \brief the application entry point - initializes low level hardware, creates tasks and starts SYSBIOS
     *
     */
    
    //extern ICSS_EmacBaseAddrCfgParams icss_EmacBaseAddrCfgParams[2];
    
    void ICSS_EMAC_testDelay(uint32_t delay)
    {
        volatile uint32_t delay1 = delay * 2;
    
        while(delay1--) ;
    }
    
    int main()
    {
        TaskP_Params taskParams;
        uint32_t operateMode = 1; //  0 - EMAC, 1 - PRP
    
        PRUICSS_IntcInitData pruss_intc_initdata = PRUSS_INTC_INITDATA;
    
        HSR_PRP_socHwinit(PRUICSS_INSTANCE);
    
        memset(&boardInfo, 0, sizeof(Board_IDInfo));
        Board_getIDInfo(&boardInfo);
        UART_printf("boardName: %s\n", boardInfo.boardName);
    
    #if !defined(SOC_K2G) && !defined(iceAMIC11x)
        Board_phyReset(2);
    #endif /*SOC_K2G & iceAMIC11x*/
    
        prusshandle = PRUICSS_create((PRUICSS_Config *)pruss_config, PRUICSS_INSTANCE);
        emachandle = (ICSS_EmacHandle)malloc(sizeof(ICSS_EmacConfig));
    
        ICSSEMAC_InitConfig *switchEmacCfg = (ICSSEMAC_InitConfig *)calloc(1, sizeof(ICSSEMAC_InitConfig));
        switchEmacCfg->phyAddr[0] = Board_getPhyAddress(PRUICSS_INSTANCE, 1);
    
        if (operateMode)
        {
            switchEmacCfg->phyAddr[1] = Board_getPhyAddress(PRUICSS_INSTANCE, 2);
            switchEmacCfg->portMask = ICSS_EMAC_MODE_SWITCH;
            switchEmacCfg->halfDuplexEnable = 0;
            switchEmacCfg->learningEn = 1;
        }
        else
        {
            switchEmacCfg->portMask = ICSS_EMAC_MODE_MAC1;
            switchEmacCfg->halfDuplexEnable = 1;
            switchEmacCfg->learningEn = 0;
        }
        switchEmacCfg->ethPrioQueue[ICSS_EMAC_QUEUE1] = 0;
        switchEmacCfg->ethPrioQueue[ICSS_EMAC_QUEUE2] = 0;
        switchEmacCfg->ethPrioQueue[ICSS_EMAC_QUEUE3] = 0;
        switchEmacCfg->ethPrioQueue[ICSS_EMAC_QUEUE4] = 0;
    
        switchEmacCfg->enableIntrPacing = ICSS_EMAC_ENABLE_PACING;
        switchEmacCfg->ICSS_EmacIntrPacingMode = ICSS_EMAC_INTR_PACING_MODE1;
        switchEmacCfg->pacingThreshold = 100;
    
        switchEmacCfg->ICSS_EmacTTSEnableCycPktInterrupt = 0;
    
        HSR_PRP_socgetMACAddress(lclMac);
    
        switchEmacCfg->macId = lclMac;
    
    #ifdef SOC_AM437x
        ICSSEmacDRVInit(emachandle, 1);
    #else
        ICSSEmacDRVInit(emachandle, PRUICSS_INSTANCE);
    #endif
    
        /*Registering Port 1 Link break callback */
        ICSS_EmacRegisterPort0ISRCallback(emachandle,
                                          (ICSS_EmacCallBack)hsrPrp_Port1linkResetCallBack,
                                          0); // callback arg
        /*Registering Port 2 Link break callback */
        ICSS_EmacRegisterPort1ISRCallback(emachandle,
                                          (ICSS_EmacCallBack)hsrPrp_Port2linkResetCallBack,
                                          0);  // callback arg
    
        /*Configure interrupts*/
        HSR_PRP_configureInterrupts(switchEmacCfg);
    
        ((ICSS_EmacObject *)emachandle->object)->pruIcssHandle = prusshandle;
        ((ICSS_EmacObject *)emachandle->object)->emacInitcfg = switchEmacCfg;
    
        ICSS_EmacInit(emachandle, &pruss_intc_initdata, operateMode ? ICSS_EMAC_MODE_SWITCH : (ICSS_EMAC_MODE_MAC1|ICSS_EMAC_MODE_DUALMAC));
    
        if (operateMode)
        {
            hsrPrphandle = (hsrPrpHandle *)malloc(sizeof(hsrPrpHandle));
            hsrPrpHandle_init(hsrPrphandle);  /*  Initializing HSR handle */
        }
        else
        {
            hsrPrphandle = NULL;
        }
    
        TaskP_Params_init(&taskParams);
        //taskParams.stacksize = 8192;
        taskParams.priority = 5;
        taskParams.name = (uint8_t *)"LEDTask";
        TaskP_create(taskLedBlink2, &taskParams);
    
        TaskP_Params_init(&taskParams);
        taskParams.priority = 15;       /* we need stack prio higher than LED I/O*/
        //taskParams.stacksize = 8192;
        taskParams.name = (uint8_t *)"SwitchTask";
        taskParams.arg0 = (void *)operateMode;
        TaskP_create(taskPruss, &taskParams);
    
    #ifdef ICSS_PROTOCOL_RED
    
        TaskP_Params_init(&taskParams);
        taskParams.priority = 1;
        taskParams.name = (uint8_t *)"UARTMenuTask";
        taskParams.arg0 = (void *)emachandle;
        TaskP_create(taskUartMenu, &taskParams);
    
    #endif /* ICSS_PROTOCOL_RED */
    
        if (operateMode)
        {
    #ifdef ICSS_PROTOCOL_RED
            RedProtocolInit();
            RedProtocolConfigure(emachandle);
    
            ICSS_EmacCallBackObject *callBackHandle = ((ICSS_EmacObject *)emachandle->object)->callBackHandle;
    
            callBackHandle->txCallBack->callBack = (ICSS_EmacCallBack)RedTxPacket;
            callBackHandle->txCallBack->userArg = hsrPrphandle;
    
            callBackHandle->rxCallBack->callBack = (ICSS_EmacCallBack)RedRxPktGet;
            callBackHandle->rxCallBack->userArg = hsrPrphandle;
    #endif /* ICSS_PROTOCOL_RED */
    
    #ifdef ICSS_PROTOCOL_RED
            RedInit(emachandle);
    #endif /* ICSS_PROTOCOL_RED */
        }
    
        TaskP_Params_init(&taskParams);
        taskParams.priority = 10;
        taskParams.name = (uint8_t *)"RxTask";
        taskParams.arg0 = (void *)emachandle;
    
        ((ICSS_EmacObject *)emachandle->object)->rxTaskHandle = TaskP_create(
                    (Task_FuncPtr)ICSS_EMacOsRxTaskFnc, &taskParams);
    
        TaskP_Params_init(&taskParams);
        taskParams.priority = 7;
        taskParams.name = (uint8_t *)"LinkTask";
        taskParams.arg0 = (void *)emachandle;
    
        ((ICSS_EmacObject *)emachandle->object)->linkTaskHandle = TaskP_create(
                    (Task_FuncPtr)ICSS_EMacOsLinkTaskFnc, &taskParams);
    
        PRUICSS_pinMuxConfig(prusshandle, 0x0); // PRUSS pinmuxing
    
        if(OSDRV_addNetifEntry((NIMUInitFn)&EmacInit, emachandle) == 0)
        {
            BIOS_exit(0);
        }
    
        BIOS_start();
        return 0;
    }
    
    /**
     * \brief returns interface MAC as a string
     *
     * \retval buf_str return buffer for MAC string (min length x bytes!)
     */
    void getMacid(char *buf_str)
    {
        int i;
        Uint8 bMacAddr[6];
        char *buf_ptr;
        NIMU_IF_REQ if_req;
        if_req.name[0] = 0;
        if_req.index   = 1;
    
        NIMUIoctl(NIMU_GET_DEVICE_MAC, &if_req, &bMacAddr, sizeof(bMacAddr));
    
        buf_ptr = buf_str;
    
        for(i = 0; i < 5; i++)
        {
            if(i != 5)
            {
                buf_ptr += sprintf(buf_ptr, "%02x:", (char)bMacAddr[i]);
            }
        }
    
        buf_ptr += sprintf(buf_ptr, "%02x", (char)bMacAddr[5]);
    }
    
    uint8_t ICSSEmacDRVInit(ICSS_EmacHandle handle, uint8_t instance)
    {
        /* LLD attributes mallocs */
        ICSS_EmacObject *object = (ICSS_EmacObject *)calloc(1, sizeof(ICSS_EmacObject));
    
        /* Callback mallocs */
        ICSS_EmacCallBackObject* callBackObj = (ICSS_EmacCallBackObject*)calloc(1, sizeof(ICSS_EmacCallBackObject));
        callBackObj->learningExCallBack=(ICSS_EmacCallBackConfig*)calloc(1, sizeof(ICSS_EmacCallBackConfig));
        callBackObj->rxRTCallBack=(ICSS_EmacCallBackConfig*)calloc(1, sizeof(ICSS_EmacCallBackConfig));
        callBackObj->rxCallBack=(ICSS_EmacCallBackConfig*)calloc(1, sizeof(ICSS_EmacCallBackConfig));
        callBackObj->txCallBack=(ICSS_EmacCallBackConfig*)calloc(1, sizeof(ICSS_EmacCallBackConfig));
        object->callBackHandle = callBackObj;
    
        /*Allocate memory for learning*/
        object->macTablePtr = (HashTable_t*)calloc(1, NUM_PORTS * sizeof(HashTable_t));
    
        /*Allocate memory for PRU Statistics*/
        object->pruStat = (ICSS_EmacPruStatistics_t*)calloc(1, NUM_PORTS * sizeof(ICSS_EmacPruStatistics_t));
    
        /*Allocate memory for Host Statistics*/
        object->hostStat = (ICSS_EmacHostStatistics_t*)calloc(1, NUM_PORTS * sizeof(ICSS_EmacHostStatistics_t));
    
        /*Allocate memory for Storm Prevention*/
        object->stormPrevPtr = (stormPrevention_t*)calloc(1, NUM_PORTS * sizeof(stormPrevention_t));
    
        /* Base address initialization */
        ICSS_EmacHwAttrs *hwAttrs = (ICSS_EmacHwAttrs *)calloc(1, sizeof(ICSS_EmacHwAttrs));
        hwAttrs->emacBaseAddrCfg = (ICSS_EmacBaseAddressHandle_T)calloc(1, sizeof(ICSS_EmacBaseAddrCfgParams));
    
        /* Initialize hwAttrs->emacBaseAddrCfg */
        ICSS_EmacSocGetInitCfg((instance - 1), hwAttrs->emacBaseAddrCfg);
    
        handle->object = object;
        handle->hwAttrs = hwAttrs;
    
        return 0;
    }
    
    /*Initialize the PCP 2 Q mapping to 0 before starting firmware*/
    void initializePCPtoQueueMap(ICSS_EmacHandle emachandle)
    {
        uint8_t *bytePtr = (uint8_t *)((((ICSS_EmacHwAttrs *)
                                         (emachandle)->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr
                                       + QUEUE_2_PCP_MAP_OFFSET);
        memset(bytePtr, ICSS_EMAC_QUEUE4, 8);
    }
    
    /*Initialize the PCP 2 Q mapping to the required values*/
    void loadPCPtoQueueMap(ICSS_EmacHandle emachandle, uint8_t *pcp_2_queue_map)
    {
        uint8_t *bytePtr = (uint8_t *)((((ICSS_EmacHwAttrs *)
                                         (emachandle)->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr
                                       + QUEUE_2_PCP_MAP_OFFSET);
        memcpy(bytePtr, pcp_2_queue_map, 8);
    }
    
    void hsrPrpHandle_init(hsrPrpHandle *hsrPrphandle)
    {
        hsrPrphandle->redSeqNr = 0;
        hsrPrphandle->supSeqNr = 0;
        hsrPrphandle->collision_pkt_dropped = &collision_pkt_dropped;
        hsrPrphandle->num_of_collision_occured = &num_of_collision_occured;
        hsrPrphandle->redPruCheckTimerHostTableFlag = 0;
        hsrPrphandle->redPruCheckTimerNodeTableClear = 0;
        hsrPrphandle->redPruCheckTimer = NULL;
        hsrPrphandle->redLifeCheckTimer = NULL;
        hsrPrphandle->redSupFrame = NULL;
        hsrPrphandle->redSupTask = NULL;
        hsrPrphandle->hsrPrpNodetableRefreshTask = NULL;
        hsrPrphandle->redLifeCheckSemaphore = NULL;
        hsrPrphandle->nodesTableSemaphore = NULL;
        hsrPrphandle->icssEmacHandle = emachandle;
    
    #if defined(SOC_AM571x) || defined(SOC_AM572x) || defined(SOC_K2G)
        hsrPrphandle->indexArrayBase = (RED_INDEX_ARRAY_ENTRY *)((((
                                           ICSS_EmacHwAttrs *)emachandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr
                                       + INDEX_ARRAY_NT);
    #else
        hsrPrphandle->indexArrayBase = (RED_INDEX_ARRAY_ENTRY *)((((
                                           ICSS_EmacHwAttrs *)emachandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr +
                                       INDEX_ARRAY_NT);
    #endif
    
    #if defined(SOC_AM571x) || defined(SOC_AM572x) || defined(SOC_K2G)
        hsrPrphandle->binArrayBase = (RED_BIN_ARRAY_ENTRY *)((((
                                         ICSS_EmacHwAttrs *)emachandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr
                                     + BIN_ARRAY);
    #else
        hsrPrphandle->binArrayBase = (RED_BIN_ARRAY_ENTRY *)((((
                                         ICSS_EmacHwAttrs *)emachandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr +
                                     BIN_ARRAY);
    #endif
    
        hsrPrphandle->nodeTableBase = (RED_NODE_TABLE_ENTRY *)((((
                                          ICSS_EmacHwAttrs *)emachandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr
                                      + NODE_TABLE_NT);
    }
    
    void hsrPrp_Port1linkResetCallBack(uint8_t linkStatus, void *arg2)
    {
        /*
        Here arg2 already points to timeSyncHandle because of the registered callBack
        Yet, explicit usage of timeSyncHandle keeping futuristic approach wherein we might want to add other callbacks and access to handles other than timeSyncHandle
        */
    }
    
    void hsrPrp_Port2linkResetCallBack(uint8_t linkStatus, void *arg2)
    {
        /*
        Here arg2 already points to timeSyncHandle because of the registered callBack
        Yet, explicit usage of timeSyncHandle keeping futuristic approach wherein we might want to add other callbacks and access to handles other than timeSyncHandle
        */
    }
    

    RawSocket.7z

  • I run same test with 4 SV simulation. The down time increased to 75ms (about 1200 errors block per failure).
    ==
    *
    Curr=846,Exp=545,dT=75217
    *
    Curr=2421,Exp=2119,dT=75474
    *
    Curr=2119,Exp=1818,dT=75192
    *
    Curr=680,Exp=380,dT=74942
    *
    Curr=1654,Exp=1352,dT=75477
    *
    Curr=1653,Exp=1351,dT=75478
    ==
  • And one more test result: 4SV via 100Mbit/s switch. Errors still happens (13 for the 2 cases) but very rare and for the shorter time:
    ==
    *
    Curr=2161,Exp=2158,dT=1207
    *
    Curr=1582,Exp=1580,dT=810
    ==
  • Alex,

    Can you please send me a binary file of your C# project? I don't use Microsoft visual studio for many years : -)

    Regards,
    Garrett
  • Garrett,

    Here it is. I noticed that with increasing number of streams the errors appearance increasing. The RawSocket.exe app took two arguments: first is the repeat timer (250us by default) and the second is number of streams. By calling "RawSocket.exe 250 8" you can simulate 8 SV streams and the problem will appear very quick. If I calcualted correctly it is about 33 Mbit/s load and I may expect random packet drop with 100 Mbit/s interface, but I don't understand why PRU stops receiving for the period of time.

    Though with 8 SV streams I don't see direct correlation between the number of streams and "pause time", but for 3 SV the time is always around 33ms and for 4 SV - 75 ms.

    Release.7z

  • Garrett,

    I ported this test to idk572x using PDK 1.0.14 and I was able to reproduce same issue.

  • Alex,

    sorry I was sidetracked, will try to work on this next Monday.

    Regards,
    Garrett
  • I was able to recover my setup, but the RawSocket.exe crashes.

    I will try to find a win7 PC. With my win10 workstation, I got 'unhandled Exception' as below which could be related to Beckhoff driver installed in my PC too, will continue to look into...Alternatively, can you tell me your SV packet format (header and payload)? I can try to use a PC packet generator...

    hsr_alex\Release>RawSocket.exe 250 8
    ...
    Unhandled Exception: System.InvalidOperationException: Unable to open the adapter. Adapter name: rpcap://\Device\NPF_{}. Error: failed to set hardware filter to promiscuous mode
    at PcapDotNet.Core.LivePacketCommunicator.PcapOpen(SByte* source, Int32 snapshotLength, PacketDeviceOpenAttributes attributes, Int32 ...

    Regards,
    Garrett
  • Garrett,

    I think you don't have https://www.winpcap.org/ driver installed. RawSocket use it to send packets.

  • Alex,

    I turned of TwinCAT switch driver in my PC and able to run your RawSocket. Attached is the log file.prp_sv_log.txt

    and I can see the DT variances, but I am not sure if it's caused by the PRP application/firmware or the NIC driver of PC itself.

    Have you tried to test the application using a hardware packet generator like Ixia?

    Regards,
    Garrett

  • Garrett,

    That's strange for me that you have so frequent problem appearance. In case of 8 SV streams I also saw DT variances but for 3 or 4 simulated streams it mostly constant (and dependent on number of streams).

    No, we don't have special equipment for the network testing but I think the result will be similar with any kind of traffic generator.
  • Garrett,

    Is there any news? We have it very urgent. Were responsible team able to analyze the problem?

    We have around 1000 of Sitara 4 and 1000 of Sitara 5 in stock and our CEO insist to get quick response if problem will be solved in reasonable time or we should consider other device to make product to market.

  • Alex,

    I am working with our team, will update you ASAP if any progress.

    Thanks,
    Garrett

  • Alex,

    We will be reviewing the test results report, specifically to packet stress test for the release tomorrow. We will unfortunately not be able to work on any retest until after end of next week.

    Regards,
    Garrett
  • Alex,

    There are lots of improvements and bug fixes done in firmware as part of Linux HSR/PRP work. The HSR/PRP release 1.0.4 is on ti.com in June 2018, so I replaced the firmware with the latest HSR/PRP release 1.0.5 in our nightly build and re-ran the test, and now with even 33Mbps, the problem goes away.

    FYI, we have Linux HSR/PRP packet benchmarks here -

    Previously with 15Mpbs (RawSocket.exe 250 4) or 13Mbps (RawSocket.exe 250 3), the packet drop issue occured in my setup as well with HSR/PRP 1.0.4 release but just less often as with 33Mbps as you observed.

    Let me check how we can enable you with the latest HSR/PRP 1.0.5...

    Regards,
    Garrett

  • Garrett,

    That sounds great! The only concern I have is that we also saw that with icss_emac firmware, so I expect that emac firmware also will be updated.

    But either way we are ready to help in testing as soon as we receive something fresh.

    Regards,
    Alexander

  • Garrett,

    Is Linux SDK 05.03.00.07 contains same binaries as 1.0.5? May be I can use objcopy to convert ELF files from Linux SDK to TI-RTOS format? Or may be you have NDK on git.ti.com (but I just cannot find it)?

    Regards,
    Alexander

  • Alex,

    Yes, Linux SDK 05.03.00.07 contains same bug fix/feature enhancement in the binaries as 1.0.5. I am not sure if objcopy can convert the binary to .h file for RTOS, but it should work if you dump the program memory using CCS after the binaries are loaded by Linux, save it as raw data and then manipulate it as the PRU header file for RTOS.

    Regards,
    Garrett
  • Garrett,

    I converted Linux PRU binaries to arrays using following command line:

    hexpru.exe --array --array:name_prefix=PRU0_FIRMWARE -exclude=.resource_table am437x-pru0-pruprp-fw.elf 

    Then I corrected array name and replaced them in my project.

    Unfortunately, this does not change anything regarding my problem. I still see same error counters and same delays.

    S T A T I S T I C S
    
    Lookup error A : 00000028
    Lookup error B : 00000000
    
          Tx  WrongLan        Rx    Errors     Nodes     Proxy    Unique   Duplic.     Multi     OwnRx
    --------  --------  --------  --------  --------  --------  --------  --------  --------  --------
    00000003  00000000  00000028  00000000  00000003  00000000  00000000  00000000  00000000  00000000
    00000000  00000000  00000000  00000000                      00000000  00000000  00000000  00000000
    00000028  00000000  00000000  00000000                      00000024  00000000  00000000
    
    
    
    ICSS_EMAC_DRV_VERSION_ID        : 0x100000f
    
    Device config   : PRP
    
    HSR/PRP Application Menu Options. Press key (Upper/Lower)
    *******************************************
    S : Show Statistics
    L : Show LRE Statistics
    C : Show HSR/PRP Configuration
    N : Show Ring members/Node Table
    M : Multicast filter handling
    V : VLAN filter handling
    F : Host Rx Interrupt Config | 0 : Disable | 1. Enable | 2. Enable with Adaptive Logic
    I : Assign IP address
    P : Show PTP/1588 status
    R : Run Rx/Tx test
    H : Help menu. Shows details on all the options
    ********************************************
    **
    Curr=2841,Exp=2706,dT=33785
    *
    Curr=1620,Exp=1486,dT=33536
    *
    Curr=2192,Exp=2058,dT=33668
    *
    Curr=2927,Exp=2793,dT=33526
    *
    Curr=3984,Exp=3849,dT=33775
    *
    Curr=3550,Exp=3415,dT=33773
    
    S T A T I S T I C S
    
    Lookup error A : 23124029
    Lookup error B : 00000000
    
          Tx  WrongLan        Rx    Errors     Nodes     Proxy    Unique   Duplic.     Multi     OwnRx
    --------  --------  --------  --------  --------  --------  --------  --------  --------  --------
    00000972  00000000  23124029  00002409  00000004  00000000  00000000  00000000  00000000  00000000
    00000000  00000000  00000000  00000000                      00000000  00000000  00000000  00000000
    23124029  00000000  00000000  00000000                      23122544  00000000  00000000
    

    Regards,
    Alexander

  • Garrett,

    It looks like the root of problem is storm prevention feature. I run EMAC test and then printed EMAC statistics and in case of missed frames storm prevention counter increased. Unfortunately, I cannot get to work the ICSS_EmacDisableStormPrevention() function. I printed the value under ICSS_EMAC_DEFAULT_FW_STORM_PREVENTION_OFFSET but it increased every time I print it while traffic generator is active.
    Also, I did not found same call for HSR/PRP code.
    Can you please tell how to properly disable storm prevention and is it possible? Note, that SV packets are multicast.

    Regards,
    Alexander
  • Alex,

    Can you please upload your firmware binaries from PLSDK here?

    Regarding the storm control, you may try to enable multicast filter which will bypass the storm control logic for multi-cast packets (SV), ICSS_EmacDisableStormPrevention() is supposed to work though.

    hsrPrp_multicast_filter_config(emachandle, MULTICAST_FILTER_ENABLED);

    Regards,
    Garrett

  • Garrett,

    I'm not sure I understand correctly: what are the PLSDK binaries? Do you mean SD-card binaries I use for testing on IDK?

    I tried to disable storm prevention like this:

        ICSS_EmacInit(emachandle, &pruss_intc_initdata, operateMode ? ICSS_EMAC_MODE_SWITCH : (ICSS_EMAC_MODE_MAC1|ICSS_EMAC_MODE_DUALMAC));
    
        if (operateMode)
        {
            hsrPrphandle = (hsrPrpHandle *)malloc(sizeof(hsrPrpHandle));
            hsrPrpHandle_init(hsrPrphandle);  /*  Initializing HSR handle */
            hsrPrp_multicast_filter_config(emachandle, MULTICAST_FILTER_ENABLED);
        }
        else
        {
            hsrPrphandle = NULL;
            ICSS_EmacDisableStormPrevention(ICSS_EMAC_PORT_1, emachandle);
            ICSS_EmacDisableStormPrevention(ICSS_EMAC_PORT_2, emachandle);
        }
    

    Now trying with PRP and multicast filter enabled.

    Regards,
    Alexander

  • Alex,

    I meant the PRP firmware binaries you converted from PLSDK, wanted to test that on my setup...
    I took the firmware from the nightly build which should be very close to the one from PLSDK v5.3 if it's not identical.

    Regards,
    Garrett
  • Here it is.

    icss_prp_pruX_bin.7z

    Enabling multicast filtration without configuring mask and MAC did not helped. I added the following code:

        ICSS_EmacInit(emachandle, &pruss_intc_initdata, operateMode ? ICSS_EMAC_MODE_SWITCH : (ICSS_EMAC_MODE_MAC1|ICSS_EMAC_MODE_DUALMAC));
    
        if (operateMode)
        {
            hsrPrphandle = (hsrPrpHandle *)malloc(sizeof(hsrPrpHandle));
            hsrPrpHandle_init(hsrPrphandle);  /*  Initializing HSR handle */
            hsrPrp_multicast_filter_config(emachandle, MULTICAST_FILTER_ENABLED);
            hsrPrp_multicast_filter_override_hashmask(emachandle, "255 255 255 0 0 0");
            hsrPrp_multicast_filter_update_macid(emachandle, "1 12 205 0 0 0", ADD_MULTICAST_MAC_ID);
        }
        else
        {
            hsrPrphandle = NULL;
            ICSS_EmacDisableStormPrevention(ICSS_EMAC_PORT_1, emachandle);
            ICSS_EmacDisableStormPrevention(ICSS_EMAC_PORT_2, emachandle);
        }
    
    

    And now continue testing. But original calls hsrPrp_multicast_filter_override_hashmask and hsrPrp_multicast_filter_update_macid sometimes cause crashing. The reason is this code:

        uint8_t multicastAddrTemp[ETHER_ADDR_LEN];
    
        /*extract the hexadecimal values from the incoming multicastAddr*/
        sscanf(multicastAddr, "%u %u %u %u %u %u", &multicastAddrTemp[0],
               &multicastAddrTemp[1], &multicastAddrTemp[2], &multicastAddrTemp[3],
               &multicastAddrTemp[4], &multicastAddrTemp[5]);
    

    sscanf expects unsigned int * and not uint8_t * (which is too short and not aligned). This code needs to be corrected in future releases, though I'd prefer to pass the array instead of decimal string. I never saw MAC address in decimal format anywhere before.

  • Garrett,

    It seems that setting mask and MAC resolved problem for PRP mode.
    There's still a question regarding ICSS_EmacDisableStormPrevention call for EMAC mode. Not sure what I do wrong that it does not work for me. If I can't get it to work I still can remove all those code from EMAC firmware but I'd prefer not to do it.

    Regards,
    Alexander
  • Garrett,

    I found the reason why ICSS_EmacDisableStormPrevention did not worked, I called it before NDK initialized and NDK resetted it. Now it all seems to work.

    Thanks a lot for help.

    Regards,
    Alexander

  • Alex,

    This is awesome! Thanks for your update. You should no need disable storm prevention in next release with enhanced firmware.

    Regards,
    Garrett