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.

TMS320F28388D: The contents of the descriptor and data buffer do not match(Again)

Part Number: TMS320F28388D
Other Parts Discussed in Thread: C2000WARE, TMDSCNCD28388D

Tool/software:

I'm reposting this thread as it may have gotten buried.

Hi experts,

When processing received data from Ethernet, the information indicated by the descriptor may not match the contents of the data buffer.

Q:Could you tell me how to avoid this? If the current information is not enough, please let me know what points I should check.

My customer is using Ethernet with F28388D and evaluating LWIP. This is a continuation of this thread.

This phenomenon occurs when the PC and F28388D are connected with a LAN cable. In particular, when the PC links up, many packets flow, so the processing may not be able to keep up and the memory may be rewritten.

They are using a switch called KSZ8794 as the Ethernet PHY. This switch has multiple ports and adds one byte of identification information (TailTag) to the received data from the outside. This identification information needs to be removed, but the data is added to the end of the received data (before the FCS). Therefore, it is necessary to identify the position of the data from the data length (pPacket->validLength) information of the received data and extract it. However, sometimes the location indicated by the data length (pPacket->validLength) contains content that differs from the actual data.

The results of a WireShark log investigation show that when the data length (pPacket->validLength) is processed by the receive function, the data sent later is stored in memory, resulting in the incorrect TailTag being extracted. When the same log is checked with Wireshark, it is confirmed that the correct TailTag is present at the location indicated by the data contents.

The sample code below is used as the base, and interrupts are disabled immediately after an interrupt occurs, and are released once buffer processing is complete.
:<C2000Ware Install Path>\libraries\communications\Ethernet\third_party\lwip\examples\enet_lwip

They copied the contents of the receive buffer during interrupt processing(f2838xif_receive()), then set a BreakPoint after copying and compared the results.
The contents of the copy buffer were different from the receive buffer at the moment it stopped at the BreakPoint, and specifically the contents of the copy buffer were several times older.

Best regards,
O.H

  • Hi experts,

    Is there any update?

    Best regards,
    O.H

  • Hi experts,

    Sorry for rush you. Could you tell me the situation?

    If it's difficult for you to answer here, we can discuss it in private chat.

    Best regards,
    O.H

  • Hi O.H,

    1.  I would like to reproduce this on the EVM. Can you please share how to reproduce this issue locally, without using KSZ8794 , if possible?

    2.  Can you please share the C2000Ware Version that you are using?

    3.  Can you please share the wireshark dump/snippet to show the error in the packet.

    With regards,
    Pradeep

  • Hi Pradeep,

    Thank you for your reply. And sorry for late reply. Below are some comments from customers.

    1.  I would like to reproduce this on the EVM. Can you please share how to reproduce this issue locally, without using KSZ8794 , if possible?

    I tested it with TMDSCNCD28388D.
    I tried saving to memory twice in the receive function and comparing the differences.
    In the example I checked, when packets with a length of 110 came in succession (at intervals of about 100us), I was able to confirm that the contents of Buf changed during the receive interrupt function.
    When received data comes in succession, it seems that we can confirm a condition similar to the symptom where the contents of Desc and Buf are different.
    This is more noticeable when a TailTag is added with KSZ, but seems to be less likely to occur without a TailTag.

    I have attached the source file (f2838xif.c).
    I will send the verification materials and the entire project in a private chat.
    I tried replacing only f2838xif.c in the examples/enet_lwip_udp project, but I was unable to confirm any memory mismatch.

    2.  Can you please share the C2000Ware Version that you are using?

    C2000Ware has also checked 5.04, but the actual source reference was 5.01.

    3.  Can you please share the wireshark dump/snippet to show the error in the packet.

    I will send the materials in a private chat.

    Best regards,
    O.H

    //###########################################################################
    //
    // FILE:   f2838xif.c
    //
    // TITLE:  F2838x interface port file.
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    // $Copyright:
    // Copyright (C) 2022 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.
    // $
    //###########################################################################
    
    /**
     * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice,
     *    this list of conditions and the following disclaimer.
     * 2. 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.
     * 3. The name of the author may not be used to endorse or promote products
     *    derived from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
     *
     * This file is part of the lwIP TCP/IP stack.
     *
     * Author: Adam Dunkels <adam@sics.se>
     *
     */
    
    /**
     * Copyright (c) 2018 Texas Instruments Incorporated
     *
     * This file is dervied from the ``ethernetif.c'' skeleton Ethernet network
     * interface driver for lwIP.
     *
     */
    
    #include <string.h>
    /**
     * lwIP specific header files
     */
    #include "lwip/opt.h"
    #include "lwip/def.h"
    #include "lwip/mem.h"
    #include "lwip/pbuf.h"
    #include "lwip/sys.h"
    #include <lwip/stats.h>
    #include <lwip/snmp.h>
    #include "netif/etharp.h"
    #include "netif/ppp/pppoe.h"
    #include "netif/f2838xif.h"
    
    /**
     * f2838x device specific header files
     */
    #include "inc/hw_emac.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib_cm/ethernet.h"
    #include "driverlib_cm/interrupt.h"
    #include "driverlib_cm/sysctl.h"
    
    #include "utils/lwiplib.h"
    /**
     * Sanity Check:  This interface driver will NOT work if the following defines
     * are incorrect.
     *
     */
    #if (PBUF_LINK_HLEN != 16)
    #error "PBUF_LINK_HLEN must be 16 for this interface driver!"
    #endif
    #if (ETH_PAD_SIZE != 0)
    #error "ETH_PAD_SIZE must be 0 for this interface driver!"
    #endif
    #if (!SYS_LIGHTWEIGHT_PROT)
    #error "SYS_LIGHTWEIGHT_PROT must be enabled for this interface driver!"
    #endif
    
    /**
     * Number of pbufs supported in low-level tx/rx pbuf queue.
     *
     */
    #ifndef F2838X_NUM_PBUF_QUEUE
    #define F2838X_NUM_PBUF_QUEUE    20
    #endif
    
    #define EMAC_BASE                   0x400C0000U //EMAC
    #define EMAC_SS_BASE                0x400C2000U //EMACSS
    
    /* Define those to better describe your network interface. */
    #define IFNAME0 't'
    #define IFNAME1 'i'
    
    /* Helper struct to hold a queue of pbufs for transmit and receive. */
    struct pbufq
    {
        struct pbuf *pbuf[F2838X_NUM_PBUF_QUEUE];
        unsigned long qwrite;
        unsigned long qread;
        unsigned long overflow;
    };
    
    /* Helper macros for accessing pbuf queues. */
    #define PBUF_QUEUE_EMPTY(q) \
        (((q)->qwrite == (q)->qread) ? true : false)
    
    #define PBUF_QUEUE_FULL(q) \
        ((((((q)->qwrite + 1) % F2838X_NUM_PBUF_QUEUE)) == (q)->qread) ? \
        true : false )
    
    /**
     * Helper struct to hold private data used to operate your ethernet interface.
     * Keeping the ethernet address of the MAC in this struct is not necessary
     * as it is already kept in the struct netif.
     * But this is only an example, anyway...
     */
    struct f2838xif
    {
        struct eth_addr *ethaddr;
        /* Add whatever per-interface state that is needed here. */
        struct pbufq txq;
        Ethernet_Pkt_Desc *pktDesc;
    };
    
    /**
     * A structure used to keep track of driver state and error counts.
     */
    typedef struct {
        uint32_t ui32TXCount;
        uint32_t ui32TXCopyCount;
        uint32_t ui32TXCopyFailCount;
        uint32_t ui32TXNoDescCount;
        uint32_t ui32TXBufQueuedCount;
        uint32_t ui32TXBufFreedCount;
        uint32_t ui32RXBufReadCount;
        uint32_t ui32RXPacketReadCount;
        uint32_t ui32RXPacketErrCount;
        uint32_t ui32RXPacketCBErrCount;
        uint32_t ui32RXNoBufCount;
    }
    tDriverStats;
    
    tDriverStats g_sDriverStats = {0};
    
    #define DRIVER_STATS_INC(x) do{ g_sDriverStats.ui32##x++; } while(0)
    #define DRIVER_STATS_DEC(x) do{ g_sDriverStats.ui32##x--; } while(0)
    #define DRIVER_STATS_ADD(x, inc) do{ g_sDriverStats.ui32##x += inc; } while(0)
    #define DRIVER_STATS_SUB(x, dec) do{ g_sDriverStats.ui32##x -= dec; } while(0)
    
    /*
     * Creating a queue that maps an ethernet packet descriptor with
     * the corresponding pbuf. It is useful to free up the allocated pbuf memory
     * after the packet has been sent.
     */
    #ifndef F2838X_INTERFACE_NUM_PKT_DESC_QUEUE
    #define F2838X_INTERFACE_NUM_PKT_DESC_QUEUE    20
    #endif
    
    /**
     * Global variable for this interface's private data.  Needed to allow
     * the interrupt handlers access to this information outside of the
     * context of the lwIP netif.
     *
     */
    static struct f2838xif f2838xif_data;
    
    Ethernet_Handle emac_handle;
    
    /**
     * A macro which determines whether a pointer is within the SRAM address
     * space and, hence, points to a buffer that the Ethernet MAC can directly
     * DMA from.
     */
    #define PTR_SAFE_FOR_EMAC_DMA(ptr) (((uint32_t)(ptr) >= 0x2000800) &&   \
                                        ((uint32_t)(ptr) < 0x2000FFFF))
    
    
    /*
    	for test
    */
    #define DBG_ENET_RCV_TEST
    #ifdef DBG_ENET_RCV_TEST
    //#include <string.h> //memcpy
    int32_t dbg_enet_rcv_cnt = 0;
    int32_t dbg_enet_rcv_len = 0;
     //#define _USE_TIMESTAMP_
     #ifdef _USE_TIMESTAMP_
     #include "timer_cm.h" //GetTimer() : 100us inc
     #else
     #define GetTimer() (0x12345678)
     #endif
    int16_t dbg_enet_rcv_head192_idx = 0;
    #define NofHead192Buf (20)
    #define MaxBufLengthHead192	(192)
    typedef struct{
    	int16_t len; //2
    	uint16_t idx; //2
    	uint32_t tim; //4
    	uint8_t pad[7]; //7
    	uint8_t tail; // 1
    	uint8_t bufHead192[MaxBufLengthHead192];
    }tDBG_ENET_HEAD192;
    tDBG_ENET_HEAD192 dbg_enet_rcv_head192[ NofHead192Buf ] = {0};
    static int16_t cpylen;//=0;
    static uint8_t *pTail; // Top of FCS when TailTag is not used
    int32_t dbg_enet_missmatch = 0;
    int16_t dbg_enet_missmatch_idx = 0xFFFF;
    #endif
    
    /**
     * In this function, the hardware should be initialized.
     * Called from f2838xif_init().
     *
     * @param netif the already initialized lwip network interface structure
     *        for this ethernetif
     */
    static void
    f2838xif_hwinit(struct netif *netif)
    {
        uint32_t mac_low,mac_high;
        uint8_t *pucTemp;
    
        /* set MAC hardware address length */
        netif->hwaddr_len = ETHARP_HWADDR_LEN;
    
        /* set MAC address */
        Ethernet_getMACAddr(EMAC_BASE, 0, &mac_high, &mac_low);
    
        pucTemp = (uint8_t *)&mac_low;
        netif->hwaddr[0] = pucTemp[0];
        netif->hwaddr[1] = pucTemp[1];
        netif->hwaddr[2] = pucTemp[2];
        netif->hwaddr[3] = pucTemp[3];
    
        pucTemp = (uint8_t *)&mac_high;
        netif->hwaddr[4] = pucTemp[0];
        netif->hwaddr[5] = pucTemp[1];
    
        /* maximum transfer unit */
        netif->mtu = 1500;
    
        /* device capabilities */
        /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
        netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_IGMP;
    }
    
    /**
     * This function should do the actual transmission of the packet. The packet is
     * contained in the pbuf that is passed to the function. This pbuf might be
     * chained.
     *
     * @param netif the lwip network interface structure for this ethernetif
     * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
     * @return ERR_OK if the packet could be sent
     *         an err_t value if the packet couldn't be sent
     * @note This function MUST be called with interrupts disabled or with the
     *       F2838x Ethernet transmit fifo protected.
     */
    static err_t
    f2838xif_transmit(struct netif *netif, struct pbuf *p)
    {
        struct pbuf *q;
    
        /* No of pbufs (if chained)*/
        int n=0;
        int i=0;
        Ethernet_Pkt_Desc *pktDescOrigPtr, *pktDescPtr;
    
        /* ENTER CRITICAL SECTION
         * This is to protect the forming of packetc descriptor chain using pbufs
         * passed to the function.
         */
        Interrupt_disable(INT_EMAC_TX0);
        Interrupt_disable(INT_EMAC_RX0);
    
        /*
         * Make sure we still have a valid buffer (it may have been copied)
         */
        if(!p)
        {
            LINK_STATS_INC(link.memerr);
    
            /* EXIT CRITICAL SECTION */
            Interrupt_enable(INT_EMAC_TX0);
            Interrupt_enable(INT_EMAC_RX0);
    
            return(ERR_MEM);
        }
    
        /*
         * Count the number of the pbufs in the chain that we are passed with.
         */
        for(q = p; q != NULL; q = q->next)
                n++;
    
        /*
         * Get the head of the packet descriptor chain that will be passed to
         * the driver for sending.
         */
        pktDescOrigPtr = mem_malloc(sizeof(Ethernet_Pkt_Desc));
        #if 0
        if(pktDescOrigPtr == NULL)
        {
            __asm("   bkpt #0");
        }
        #else // UPD sample
        if(pktDescOrigPtr == NULL)
        {
            pbuf_free(p);
            LINK_STATS_INC(link.memerr);
            __asm("   bkpt #0");
            return (ERR_MEM);
        }
        #endif
    
        /*
         * Go over the pbufs present in the chain and allot a packet descriptor for
         * each pbuf. The descriptors will also be chained in the same order as
         * pbufs before passing the head of the chain to the driver.
         */
        for(q = p, pktDescPtr = pktDescOrigPtr; // Initialization
            q != NULL; // Condition evaluation
            q = q->next, pktDescPtr = pktDescPtr->nextPacketDesc) // Manipulation
        {
            /*
             * Initializing this data structure, otherwise garbage values will
             * result in rogue results while running.
             */
            memset(pktDescPtr,0,sizeof(Ethernet_Pkt_Desc));
    
            pktDescPtr->dataOffset = 0;
            pktDescPtr->dataBuffer = q->payload;
            pktDescPtr->pktChannel = ETHERNET_DMA_CHANNEL_NUM_0;
            pktDescPtr->pktLength = q->tot_len;
            pktDescPtr->bufferLength = q->len;
            pktDescPtr->validLength = q->len;
    
              if(i==0)
              {
                    if(n!=1)
                    {
                        /*
                         * Prepare the next ethernet packet descriptor holder if
                         * there is a pbuf next in the chain.
                         */
                        pktDescPtr->nextPacketDesc =
                                mem_malloc(sizeof(Ethernet_Pkt_Desc));
                        if(pktDescPtr->nextPacketDesc == NULL)
                            {
    							#if 0
                                __asm("   bkpt #0");
                            	#else
    	                        pbuf_free(p);
    	                        LINK_STATS_INC(link.memerr);
    	                        __asm("   bkpt #0");
    	                        return (ERR_MEM);
                            	#endif
                            }
                        pktDescPtr->flags = ETHERNET_PKT_FLAG_SOP ;
                    }
                    else
                    {
                        pktDescPtr->nextPacketDesc = 0;
                        pktDescPtr->flags = ETHERNET_PKT_FLAG_SOP |
                                            ETHERNET_PKT_FLAG_EOP;
                    }
              }
              else
              {
                  if(q->next != NULL)
                  {
                      /*
                       * Prepare the next ethernet packet descriptor holder if
                       * there is a pbuf next in the chain.
                       */
                      pktDescPtr->nextPacketDesc =
                              mem_malloc(sizeof(Ethernet_Pkt_Desc));
                      if(pktDescPtr->nextPacketDesc == NULL)
                          {
    							#if 0
                                __asm("   bkpt #0");
                            	#else
    	                        pbuf_free(p);
    	                        LINK_STATS_INC(link.memerr);
    	                        __asm("   bkpt #0");
    	                        return (ERR_MEM);
                            	#endif
                          }
                      pktDescPtr->flags = 0;
                  }
                  else
                  {
                      pktDescPtr->nextPacketDesc = 0;
                      pktDescPtr->flags = ETHERNET_PKT_FLAG_EOP;
                  }
              }
    
              i++;
        }
    
        /* EXIT CRITICAL SECTION */
        Interrupt_enable(INT_EMAC_TX0);
        Interrupt_enable(INT_EMAC_RX0);
    
        /*
         * Hand over the packet descriptor to the driver.
         */
        pktDescOrigPtr->numPktFrags = n;
        Ethernet_sendPacket(emac_handle,pktDescOrigPtr);
    
        LINK_STATS_INC(link.xmit);
    
        return(ERR_OK);
    }
    
    /**
     * This function will process all transmit descriptors and free pbufs attached
     * to any that have been transmitted since we last checked.
     *
     * This function is called only from the Ethernet interrupt handler.
     *
     * @param netif the lwip network interface structure for this ethernetif
     * @return None.
     */
    int descriptorFreeErr=0;
    static void
    f2838xif_process_transmit(struct netif *netif, Ethernet_Pkt_Desc *pPacket)
    {
        Ethernet_Pkt_Desc *pktDescPtr, *pktDescPtrShadow;
    
        /*
         * Free the packet descriptor memory.
         */
        if (pPacket == 0)
            return;
    
        pktDescPtr = pPacket;
    
        /* ENTER CRITICAL SECTION */
        Interrupt_disable(INT_EMAC_TX0);
        //Interrupt_disable(INT_EMAC_RX0);
    
    #if 0
        do
        {
            pktDescPtrShadow = pktDescPtr->nextPacketDesc;
            mem_free(pktDescPtr);
            pktDescPtr = pktDescPtrShadow;
        }
        while(pktDescPtr != 0);
    #else //Referenced by TI Forum (E2E)
        //do
        //{
            pktDescPtrShadow = pktDescPtr->nextPacketDesc;
            mem_free(pktDescPtr);
            pktDescPtr = pktDescPtrShadow;
        //}
        //while(pktDescPtr != 0);
    #endif
        /* EXIT CRITICAL SECTION */
        Interrupt_enable(INT_EMAC_TX0);
        //Interrupt_enable(INT_EMAC_RX0);
    }
    
    /**
     * This function with either place the packet into the F2838x transmit fifo,
     * or will place the packet in the interface PBUF Queue for subsequent
     * transmission when the transmitter becomes idle.
     *
     * @param netif the lwip network interface structure for this ethernetif
     * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
     * @return ERR_OK if the packet could be sent
     *         an err_t value if the packet couldn't be sent
     *
     */
    
    static err_t
    f2838xif_output(struct netif *netif, struct pbuf *p)
    {
        f2838xif_transmit(netif, p);
    
        return ERR_OK;
    }
    
    /**
     * This function will read a single packet from the F2838x ethernet
     * interface, if available, and return a pointer to a pbuf.  The timestamp
     * of the packet will be placed into the pbuf structure.
     *
     * @param netif the lwip network interface structure for this ethernetif
     * @return pointer to pbuf packet if available, NULL otherswise.
     */
    Ethernet_Pkt_Desc*
    f2838xif_receive( struct netif *netif, Ethernet_Pkt_Desc *pPacket )
    {
        struct pbuf *p;
        
    #ifdef DBG_ENET_RCV_TEST
    dbg_enet_rcv_cnt++;
    #endif
    
    #if LWIP_PTPD
        u32_t time_s, time_ns;
        /* Get the current timestamp if PTPD is enabled */
        lwIPHostGetTime(&time_s, &time_ns);
    #endif
    
        p = pbuf_alloc(PBUF_RAW, sizeof(struct pbuf), PBUF_POOL);
        if(p)
        {
    		
    #ifdef DBG_ENET_RCV_TEST
    
    	dbg_enet_rcv_len = pPacket->validLength;
    	pTail = (pPacket->dataBuffer) + dbg_enet_rcv_len - 4;	//4 = FCS length,
    	
    	//if (dbg_enet_rcv_head192_idx < NofHead192Buf){
    	if ((dbg_enet_rcv_head192_idx < NofHead192Buf)&&(dbg_enet_rcv_len!=0x40/*64*/)){
    		dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx].len = dbg_enet_rcv_len;
    		dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx].idx = dbg_enet_rcv_head192_idx;
    		dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx].tim = GetTimer();
    		dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx].tail = *pTail;
    		
    		cpylen = (dbg_enet_rcv_len>MaxBufLengthHead192)?MaxBufLengthHead192:(dbg_enet_rcv_len<0)?0:dbg_enet_rcv_len;	//
    		memcpy(
    			dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx].bufHead192,
    			pPacket->dataBuffer,
    			cpylen
    		);
    		dbg_enet_rcv_head192_idx++;
    	}
    	
    #endif
            p->payload = pPacket->dataBuffer;
    
            p->len = 1538U; //Max possible length of received packet.
            p->tot_len = p->len;
    
        #if LWIP_PTPD
            /* Place the timestamp in the PBUF */
            p->time_s = time_s;
            p->time_ns = time_ns;
        #endif
    
    #ifdef DBG_ENET_RCV_TEST
    	
    	dbg_enet_rcv_len = pPacket->validLength;
    	pTail = (pPacket->dataBuffer) + dbg_enet_rcv_len - 4;	//4=FCSlength,
    	
    	//if (dbg_enet_rcv_head192_idx < NofHead192Buf){
    	if ((dbg_enet_rcv_head192_idx < NofHead192Buf)&&(dbg_enet_rcv_len!=0x40/*64*/)){
    		dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx].len = dbg_enet_rcv_len;
    		dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx].idx = dbg_enet_rcv_head192_idx;
    		dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx].tim = GetTimer();
    		dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx].tail = *pTail;
    		
    		cpylen = (dbg_enet_rcv_len>MaxBufLengthHead192)?MaxBufLengthHead192:(dbg_enet_rcv_len<0)?0:dbg_enet_rcv_len;	//
    		memcpy(
    			dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx].bufHead192,
    			pPacket->dataBuffer,
    			cpylen
    		);
    		dbg_enet_rcv_head192_idx++;
    		
    		#if 1
    		if( 
    			memcmp(
    				dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx -2].bufHead192,
    				dbg_enet_rcv_head192[dbg_enet_rcv_head192_idx -1].bufHead192,
    				cpylen) != 0 ){
    			dbg_enet_missmatch++;
    			dbg_enet_missmatch_idx = dbg_enet_rcv_head192_idx -2;
    		}
    		#endif
    	}
    #endif
    
    		#if 0
            if(ethernet_input(p, netif)!=ERR_OK)
            #else //
            if(netif->input(p, netif)!=ERR_OK)
            #endif
            {
                /* drop the packet */
                LWIP_DEBUGF(NETIF_DEBUG, ("f2838xif_input: input error\n"));
                pbuf_free(p);
                p = NULL;
                /* Adjust the link statistics */
                LINK_STATS_INC(link.memerr);
                LINK_STATS_INC(link.drop);
            }
        }
    
        LINK_STATS_INC(link.recv);
    
        return(pPacket);
    }
    
    Ethernet_Pkt_Desc *f2838xif_newbuffcallback(void)
    {
        Ethernet_Pkt_Desc *newPacket = mem_calloc(1, sizeof(Ethernet_Pkt_Desc));
    
        if(newPacket)
        {
            newPacket->dataBuffer= memp_malloc(MEMP_PBUF_POOL);
        }
        return newPacket;
    }
    
    /**
     * Should be called at the beginning of the program to set up the
     * network interface. It calls the function f2838xif_hwinit() to do the
     * actual setup of the hardware.
     * This function should be passed as a parameter to netif_add().
     *
     * @param netif the lwip network interface structure for this ethernetif
     * @return ERR_OK if the loopif is initialized
     *         ERR_MEM if private data couldn't be allocated
     *         any other err_t on error
     */
    err_t
    f2838xif_init(struct netif *netif)
    {
        LWIP_ASSERT("netif != NULL", (netif != NULL));
    
    #if LWIP_NETIF_HOSTNAME
        /* Initialize interface hostname */
        netif->hostname = "lwip";
    #endif /* LWIP_NETIF_HOSTNAME */
    
        /*
         * Initialize the snmp variables and counters inside the struct netif.
         * The last argument should be replaced with your link speed, in units
         * of bits per second.
         */
        NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 1000000);
    
        netif->state = &f2838xif_data;
        netif->name[0] = IFNAME0;
        netif->name[1] = IFNAME1;
    
        /* We directly use etharp_output() here to save a function call.
         * You can instead declare your own function an call etharp_output()
         * from it if you have to do some checks before sending (e.g. if link
         * is available...) */
        netif->output = etharp_output;
        netif->linkoutput = f2838xif_output;
    
        f2838xif_data.ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
        f2838xif_data.txq.qread = f2838xif_data.txq.qwrite = 0;
        f2838xif_data.txq.overflow = 0;
    
        /* initialize the hardware */
        f2838xif_hwinit(netif);
    
        return ERR_OK;
    }
    
    /**
     * Process tx and rx packets at the low-level interrupt.
     *
     * Should be called from the F2838x Ethernet Interrupt Handler.  This
     * function will read packets from the F2838x Ethernet fifo and place them
     * into a pbuf queue.  If the transmitter is idle and there is at least one packet
     * on the transmit queue, it will place it in the transmit fifo and start the
     * transmitter.
     *
     */
    
    Ethernet_Pkt_Desc*
    f2838xif_interrupt(struct netif *netif, Ethernet_Pkt_Desc *pPacket)
    {
        Ethernet_Pkt_Desc *sPacket = NULL;
    
        /**
         * Based on the flags we get from pPacket, we should decide whether
         * to trasnmit or receive. Currently, it works for only incoming
         * ICMP ping requests.
         */
    
        /* ENTER CRITICAL SECTION
         * This is to protect the forming of packetc descriptor chain using pbufs
         * passed to the function.
         */
        Interrupt_disable(INT_EMAC_TX0);
        Interrupt_disable(INT_EMAC_RX0);
    
        if(pPacket->flags & ETHERNET_INTERRUPT_FLAG_RECEIVE)
            sPacket = f2838xif_receive(netif, pPacket);
    
        if(pPacket->flags & ETHERNET_INTERRUPT_FLAG_TRANSMIT)
            f2838xif_process_transmit(netif, pPacket);
    
        /* EXIT CRITICAL SECTION */
        Interrupt_enable(INT_EMAC_TX0);
        Interrupt_enable(INT_EMAC_RX0);
    
        return (sPacket);
    }
    

  • Hi,

    May I know what are the values of genericISRCustomcount and genericISRCustomRBUcount?

  • Hi,

    Below are some customer comments.

    May I know what are the values of genericISRCustomcount and genericISRCustomRBUcount?

    We confirmed this when continuous data was received on the ControlCard and the values ​​saved in the buffer were different (a mismatch) before and after the receive processing function.
    This mismatch seems to have occurred when data was sent with an interval of about 81 us or 85 us.

    At this time, "genericISRCustomcount" and "genericISRCustomRBUcount" remain zero. ("genericISRCustomROVcount" and "genericISRCustomRIcount" also remain zero.)
    When no mismatch occurred, "genericISRCustomcount" and "genericISRCustomRBUcount" would occasionally become 1.

    The same results were obtained when using KSZ8794.

    Best regards,
    O.H

  • Hi Pradeep,

    Could you please accept my friend request so I can send you the contents of the error packet?

    Best regards,
    O.H

  • Hi,

    I was not able to reproduce the same issue. Since you are mentioning about buffer corruption, I suggest you increase the number of buffers so that each

    diff --git a/examples/enet_lwip/cm/enet_lwip.c b/examples/enet_lwip/cm/enet_lwip.c
    index 5dc6a36..42b3af9 100644
    --- a/examples/enet_lwip/cm/enet_lwip.c
    +++ b/examples/enet_lwip/cm/enet_lwip.c
    @@ -70,7 +70,7 @@ extern uint16_t constRunSize;
     //
     //*****************************************************************************
     
    -#define ETHERNET_NO_OF_RX_PACKETS   2U
    +#define ETHERNET_NO_OF_RX_PACKETS   8U      //2U
     #define ETHERNET_MAX_PACKET_LENGTH 1538U
     #define NUM_PACKET_DESC_RX_APPLICATION 8
     
    @@ -163,19 +163,24 @@ SysTickIntHandler(void)
     //  Rewrite this API for custom use case.
     //
     //*****************************************************************************
    +uint32_t Ethernet_numGetPacketBufferCallbackCustom = 0;
     Ethernet_Pkt_Desc* Ethernet_getPacketBufferCustom(void)
     {
         //
         // Get the next packet descriptor from the descriptor pool
         //
    -    uint32_t shortIndex = (Ethernet_numGetPacketBufferCallback + 3)
    +    uint32_t shortIndex = (Ethernet_numGetPacketBufferCallbackCustom + 3)
                     % NUM_PACKET_DESC_RX_APPLICATION;
     
         //
         // Increment the book-keeping pointer which acts as a head pointer
         // to the circular array of packet descriptor pool.
         //
    -    Ethernet_numGetPacketBufferCallback++;
    +    Ethernet_numGetPacketBufferCallbackCustom++;
    +    if(Ethernet_numGetPacketBufferCallbackCustom == NUM_PACKET_DESC_RX_APPLICATION)
    +    {
    +        Ethernet_numGetPacketBufferCallbackCustom = 0;
    +    }
     
         //
         // Update buffer length information to the newly procured packet
    @@ -446,7 +451,7 @@ Ethernet_init(const unsigned char *mac)
         // Receive packet callback on Receive packet completion interrupt
         //
         pInitCfg->pfcbRxPacket = &Ethernet_receivePacketCallbackCustom;
    -    pInitCfg->pfcbGetPacket = &Ethernet_getPacketBuffer;
    +    pInitCfg->pfcbGetPacket = &Ethernet_getPacketBufferCustom;
         pInitCfg->pfcbFreePacket = &Ethernet_releaseTxPacketBufferCustom;
     
         //
    @@ -454,6 +459,7 @@ Ethernet_init(const unsigned char *mac)
         //Packets. This should be accessible by the Ethernet DMA
         //
         pInitCfg->rxBuffer = Ethernet_rxBuffer;
    +    pInitCfg->numChannels = 1U;
     
         //
         // The Application handle is not used by this application
    diff --git a/examples/enet_lwip/cm/lwipopts.h b/examples/enet_lwip/cm/lwipopts.h
    index 845ca58..3b30f21 100644
    --- a/examples/enet_lwip/cm/lwipopts.h
    +++ b/examples/enet_lwip/cm/lwipopts.h
    @@ -69,7 +69,7 @@
     //#define MEMP_NUM_NETCONN                4
     //#define MEMP_NUM_TCPIP_MSG_API          8
     //#define MEMP_NUM_TCPIP_MSG_INPKT        8
    -#define PBUF_POOL_SIZE                    24    // Default 16, was 36
    +#define PBUF_POOL_SIZE                    10    //24    // Default 16, was 36
     buffer will be held by a single DMA descriptor and test the same issue is reproducible.

  • Hi Gouri Siva M,

    Thank you for your supports.

    The following is a customer's comment.

    I was not able to reproduce the same issue. Since you are mentioning about buffer corruption, I suggest you increase the number of buffers so that each
    buffer will be held by a single DMA descriptor and test the same issue is reproducible.

    I have checked the buffer size before, and checked it again, but it doesn't seem to have any effect.
    In the attached comment file, "pInitCfg->numChannels = 1U;" was added, so I checked that too, but it had no effect.
    (I sent the details in a private chat.)

    I was not able to reproduce the same issue.

    I think this happens if continuous packets come in close succession.
    Also, can you check if the first time it's empty?
    For verification purposes, we are storing a suitable amount of data in the confirmation buffer. However, if we don't limit the data length when storing data in the buffer, I think the first time it will contain empty data.

    Q: I believe that essentially it is caused by a discrepancy between when the interrupt is called and when the data is stored in the buffer, but what is your opinion on this?
    The following post is a similar case.
    It appears that data was being missed during continuous reception, and that the interrupt was not enough to handle it, so it switched to polling.
    :https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1292322/tms320f28388d-ethernet-issues---tx-missing-interrupt-and-delayed-tx-packet-transmission/4936233

    Best regards,
    O.H

  • Patch have been provided to customer in Private chat.

  • Inorder to use 8 Buffers , modified Ethernet_getPacketBufferCustom should be used and assign it to pInitCfg->pfcbGetPacket as given in the patch. It will ensure that each DMA descriptor will hold a unique buffer. In this patch we are using only a single DMA channel