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.

TMDSCNCD28388D: C2000 ETHERNET

Part Number: TMDSCNCD28388D
Other Parts Discussed in Thread: C2000WARE

HI, Yashwant Temburu1


Please tell me. In the above function, the data and address are sent to the CM4 core through IPC. My own data is placed in the following array send_buff[150]. Can I directly replace the packetData in the function with send_buff?

I saw in the comment of the function that packetData corresponds to the address, and PACKET_LENGTH corresponds to the data.

This comment confuses me a bit.

My current progress is that the project that needs to be run by the CPU1 core has been improved, and the project for the CM4 core is also ready. Next, as long as the http file in the web service is changed, the data received by CM4 can be sent to the web page with the computer IP address of 192.168.0.4 via ethernet and displayed in real time?

thanks

vince

  • Hi,

    Yes you can replace the packetData with send_buff. Make sure that this variable is located in shared ram. #pragma DATA_SECTION(send_buff, "MSGRAM_CPU_TO_CM").

    packetData corresponds to the address

    By address it means the pointer to the array. 

    PACKET_LENGTH corresponds to the data

    This means its the length  of data that is being sent from the start of address (send_buff)

    -Yashwant

  • HI,Yashwant Temburu

    I added the IPC code under the enet_lwip project. Please tell me, the data sent from CPU1 through IPC is in the IPC_readCommand function of void IPC_ISR0() under the enet_lwip project. How many bytes are the data format received and sent by the Ethernet fixed? What is the format? How can I send the received data through the ethernet chip on my side?
    On the computer, there is the corresponding host computer software, can it receive the data and display it? What I said before was to use the form of a web page to receive data on the computer and display it. However, the form of this web page is still a bit confused after reading the link given before, and I am not likely to change it.

    Another point is that I am a bit confused to adjust the data communication between the 28388D's ethernet and the computer. Please help me to clarify my ideas. (My data is to receive 150 characters of data from the CAN port of CPU1, and then I want to send it to the computer through the ethernet port, and receive the data on the computer, and it can be displayed and saved in real time)

    The whole process is done in hardware TMDSCNCD28388D (evaluation board of 28388D).

    thanks

    vince

  • HI,Yashwant Temburu

    The data is 150 characters long. How to split it and send it out through the IPC_sendCommand function?
    For the CAN sending function, up to 8 bytes can be sent at a time. My process is to split 150 bytes into 8 bytes of data and send it out. CAN receives data, which is also received in a packet of 8 bytes, and then transferred to a new array.

    Under the enet_lwip project, which function can send data from the ethernet chip?

    thanks

    vince

  • HI,Yashwant Temburu

    The function of Ethernet_sendPacket is to send data to the computer?

    There is a long time between communication with you, so ask a few more questions at a time.

    thanks

    vince

  • HI,Yashwant Temburu

    Ethernet_sendPacket(emac_handle,&pktDesc); is the data in the array pointed to by pktDesc, where is it sent? In what format is it sent?
    The function is in the enet_lwip.c file under the enet_lwip project.

    thanks

    vince

  • Ethernet_sendPacket(emac_handle,&pktDesc)

    This function sends the data to Mac layer. You can visualise the individual packets in host pc through "wireshark" application. 

    As this is a low level driver function it will not append any higher layer stack headers.

    Pktdesc is the pointer to the packet descriptor which has multiple fields including packet size, packet data buffer pointer etc). Based on these field the packet data is transmitted to Mac layer.

    You can go through the structure definition of packet descriptor and update the field of the variable based on your data.

    How many bytes are the data format received and sent by the Ethernet fixed?

    You can define the packet length while transmission. If jumbo packet configured not used max 1500 bytes can be transmitted.

    You can send the whole 150 bytes through ipc. 

    -Yashwant

  • HI,Yashwant Temburu

    Ethernet_sendPacket (emac_handle, & pktDesc)

    This function sends the data to the Mac layer. Can I use the wireshark software to view the data?

    Should still be needed, under the enet_lwip project, modify the following loopback mode to disable it?

    pInitCfg->loopbackMode = ETHERNET_MAC_CONFIGURATION_LM_LOOPBACK_DISABLED;

    Colleagues should also comment out the module code for sending and receiving data verification, right?

    Only after completing the above two operations and filtering your own IP address in the wireshark software, you can observe the data sent by the Ethernet_sendPacket (emac_handle, & pktDesc) function (the IP address has been changed to 219.246.2.1).

    thanks

    vince

  • HI,Yashwant Temburu

    The above figure is the result of capturing the IP:219.246.2.1 packet of the development board after using Wireshark software.

    The following figure is the details of Wireshark software.

    Here's a question:

    I modified the IP address to 219.246.2.1 in the enet_lwip routine, and at the same time, assigned the packetData[PACKET_LENGTH] array in cm_common_config_c28x.c to 132 bits.

    According to common sense, the data packet with the IP address of 219.246.2.1 captured in the wireshark software should be the data assigned below. However, in the wireshark interface, no relevant data was found.

    What went wrong?

    uint8_t  packetData[PACKET_LENGTH]={"123121113111327162412718948863691113111324375127189483699101129011114370110100701101008711010052101000001101013311019957111112345671"};

    thanks

    vince

  • HI,Yashwant Temburu

    After trying to disable the loopback mode, the phenomenon in the wireshark software is no different from before.
    It must be in the enet_lwip routine, and the loopback program is not commented out, or there are other reasons.
    It really didn't find the reason.

    thanks

    vince

  • HI,Yashwant Temburu

    If the entire CPU1 data is sent to the CM4 core, then the CM4 controls the ethernet chip to send the data out, and finally the wireshark software receives the data, and then displays it in what area of the wireshark software?

    thanks

    vince

  • HI,Yashwant Temburu

    uint8_t packetData[PACKET_LENGTH]={"123121113111327162412718948863691113111324375127189483699101129011114370110100701101008711010052101000001101013311019957111112345671"};
    The data composition of this array should be wrong. The first number of bits should be the IP address of the receiving data terminal (laptop), followed by the data to be sent. right?

    There is another problem. The IP address of my laptop is automatically obtained. I use the ipconfig command from cmd to get ipv4, which is the IP address of my laptop (219.246.2.128) (as shown below).

    Then, put the IP address into the above array, and form a complete array with the data. As follows:
    uint8_t packetData[PACKET_LENGTH]={"219.246.2.128.27162412718948863691113111324375127189483699101129011114370110100701101008711010052101000001101013311019957111112345671"};
    This is my idea, please help the engineer to see if there are any problems.
    This is about the development board sending data to the laptop via Ethernet communication. Thinking about the format and composition of the data, please help to see if there is a problem.

    thanks

    vince

  • the data packet with the IP address of 219.246.2.1 captured in the wireshark software should be the data assigned below. However, in the wireshark interface, no relevant data was found.

    You are right. You would have to add necessary header to the data frame (ip header, tcp header etc). 

    We too have limited understanding of the open source lwIP stack and cant help you for individual queries on network stacks. You can ask your queries on some open source lwIP forums.

    Search web for socket communication between devices using lwIP.  It should get you some existing example where your pc can bind to the device and communicate with it.

    -Yashwant

  • hi,Yashwant Temburu

    There is a problem, enet_lwip is a routine, I copy it to the workspace and modify it. It is found that the files on the c drive have also changed. When the system prompts that C2000ware needs to be updated, the update is over, and the enet_lwip routine I saved after modification is updated to the most original state.

    Is there any link file that can be deleted to solve this problem? Or is it necessary to create a new project and put the enet_lwip routine in the past?

    thanks

    vince

  • Currently all the lwip file are linked to the project. 

    You can delete these linked files in CCS GUI. It should delete the links and create a copy of the linked file.

    -Yashwant

  • HI,Yashwant Temburu

    I modified the length of PACKET_LENGTH to 1 in the routine ethernet_c28x_config, and then observed that the bufferlenth in pktDesc also changed to 1 in enet_lwip. However, the databuffer in pktDesc is always 4. No matter how I modify the assignment of packetData[PACKET_LENGTH], the databuffer in pktDesc is always 4.
    Could it be that my IPC code was added incorrectly and did not work?
    However, if IPC does not work, why does the length of PACKET_LENGTH change with the assignment of CPU1?

    I want to send the value in packetData[PACKET_LENGTH] to the CM core. Why does the databuffer in pktDesc never change? What went wrong?

    thanks

    vince

  • HI,Yashwant Temburu

    What is the data frame format of the Ethernet I am using now?

    thanks

    vince

  • hi,Yashwant Temburu

    When we send Ethernet data frames, do we need to pack the data frames ourselves? Or is there a packaged data package in the routine, only need to change the data part of the data package?

    thanks

    vince

  • hi,Yashwant Temburu

    What does the web page shown in the picture below represent?

    In the previous program, there were numbers in the boxes. What do the numbers represent?

    thanks

    vince

  • hi,Yashwant Temburu

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/502741/concerto-enet_lwip-hard-faults

    I saw some posts saying that there are some problems with lwip in the routine? Have these problems been resolved?

    thanks

    vince

  • hi,Yashwant Temburu

    I would like to ask, our lwip protocol, which data packet is used in the following figure?

    thanks

    vince

  • hi,Yashwant Temburu

    Is this place the data captured from the development board? I did not find a place to assign a value to the array in the enet_lwip routine. And there is no place where abcdefghijk... is assigned.
    Where did this data come from?

    thanks

    vince

  • I would like to ask, our lwip protocol, which data packet is used in the following figure?

    The Ethernet module of F28388D supports IEEE 802.3 format. 

    Is this place the data captured from the development board

    Yes this is from the board. It is a reply to ICMP packet so you can assign data to that packet. It is just re transmission of data received in the ICMP request sent by the host pc.

    n the previous program, there were numbers in the boxes. What do the numbers represent?

    These numbers are the global values reflected in the device code.

    I tried to explain about this data in fs.c here https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/998994/tms320f28388d-c2000-microcontrollers-forum. Please refer to each reply.

    I saw some posts saying that there are some problems with lwip in the routine? Have these problems been resolved?

    Yes these problems have been resolved. For the next C2000Ware release these things will be incorporated.

    Regards,

    Yashwant

  • hi,Yashwant Temburu

    The first figure above should indicate that the data has been sent to the CM4 core by CPU1 through the IPC channel?

    It can be explained that the data in the array packetData[PACKET_LENGTH]; in the CPU1 core is successfully written into the CPU1TOCMRAM, right?

    Then from the first picture, you can find pktDesc.dataBuffer = (uint8_t *)addr; in the CM4 core program

    Explain that the data in the array packetData[PACKET_LENGTH] of CPU1 is transferred to the pktDesc.dataBuffer of the CM4 core.


    In this way, it means that the data transmission IPC from CPU1 core to CM4 core in my example is successful?

    Then there is a question, how to send the pktDesc.dataBuffer data of the CM4 core to the computer through the ethernet network port for display?

    My analysis is that the Ethernet_sendPacket(emac_handle,&pktDesc); statement in the second picture above, its function is to send the data received by the IPC channel in the CM4 core to the TX port on the Ethernet chip through the Ethernet_sendPacket function?


    If this is the case, how can I capture the data sent by the Ethernet_sendPacket function on my computer?

    thanks

    vince

  • hi,Yashwant Temburu

    Under the current situation, is it possible to use this software to receive the data sent by the development board? Which protocol to choose in this software?
    Where can I obtain the IP address and port number of the development board?

    thanks

    vince

  • hi,Yashwant Temburu

    How can I send the array pktDesc.dataBuffer received from CPU1, and the wireshark software can also grab the contents of the array pktDesc.dataBuffer.

    The IPC interrupt function in CM4 is as follows:

    void IPC_ISR0()
    {
    uint32_t command, addr, data;
    //
    // Read the command
    //
    IPC_readCommand(IPC_CM_L_CPU1_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,
    &command, &addr, &data);


    if(command == IPC_CMD_READ_MEM)
    {
    status = true;
    //
    //Read the buffer address and Length
    //from the IPC message从IPC信息中读取缓存地址和长度
    //
    pktDesc.dataBuffer = (uint8_t *)addr;
    pktDesc.bufferLength = data;
    pktDesc.pktLength = data;
    pktDesc.validLength = data;
    //
    //Send the packet on receiving Message from C28x side
    //
    Ethernet_sendPacket(emac_handle,&pktDesc);
    }
    }

    In my opinion, the statement Ethernet_sendPacket(emac_handle,&pktDesc); sends out the contents of the array pktDesc.dataBuffer. Is this idea wrong?
    If this idea is ok, is there a problem with my use of the wireshark software? If this is the problem, how should I perform the correct operation to successfully receive the data of the array pktDesc.dataBuffer sent by CPU1 in wireshark?

    thanks

    vince

  • hi,Yashwant Temburu

    The Ethernet_sendPacket(emac_handle, &pktDesc); statement sends the data to the MAC layer. Can I see the data through the wireshark software on my laptop?

    thanks

    vince

  • hi,Yashwant Temburu

    I was wondering whether it was because of the program or the loopback mode that the data was not sent from the CM4, but returned from the CM4 to the CPU1 core.
    If this is the reason, where should I modify the routine?

    Below are the two routines used.

    ethernet_c28x_config.rarenet_CM_lwip.rar

    thanks

    vince

  • hi,Yashwant Temburu

    When pinging the development board from the laptop, the request timeout often occurs. What is the reason?

    thanks

    vince

  • hi,Yashwant Temburu

    However, when I quit the program, it runs. Then power off the development board, power on again, and then run the program of the CPU1 core in order, and then run the program of the CM4 core. At this time, I used cmd to ping, and found that the request timeout situation will be much less, most of which are receiving and sending data normally.

    Can I add your personal contact information? There is very little information about 28388D. I want to transfer ethernet as soon as possible, with your help.

    thanks

    vince

  • Hi Vince,

    Which version of C2000Ware are you using?

    On top of v3.4 please update the attached files in your enet_lwip project and f2838x_cm driverlib.

    //###########################################################################
    //
    // FILE:   f2838xif.c
    //
    // TITLE:  F2838x interface port file.
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    // $Copyright: $
    //###########################################################################
    
    /**
     * 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;
    extern uint32_t sendPacketFailedCount;
    
    /**
     * 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))
    
    /**
     * 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;
        uint32_t Ethernet_sendStatus = 0;
    
        /* 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(pktDescOrigPtr == NULL)
        {
            __asm("   bkpt #0");
        }
    
        /*
         * 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)
                            {
                                __asm("   bkpt #0");
                            }
                        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)
                          {
                              __asm("   bkpt #0");
                          }
                      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_sendStatus = Ethernet_sendPacket(emac_handle,pktDescOrigPtr);
        if(Ethernet_sendStatus != 0)
        {
            sendPacketFailedCount++;
        }
    
        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);
    
        do
        {
            pktDescPtrShadow = pktDescPtr->nextPacketDesc;
            mem_free(pktDescPtr);
            pktDescPtr = pktDescPtrShadow;
            //if((pktDescPtr==0))
            //    break;
        }
        //while((pktDescPtr->flags & ETHERNET_INTERRUPT_FLAG_TRANSMIT) ==
        //      ETHERNET_INTERRUPT_FLAG_TRANSMIT);
        //pktPtr->flags |= ETHERNET_INTERRUPT_FLAG_TRANSMIT
        while((pktDescPtr!=0));
    
        /* 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;
    
    #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)
        {
            p->payload = pPacket->dataBuffer;
    
            p->len = 1538;//pPacket->pktLength;
            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
    
            if(ethernet_input(p, netif)!=ERR_OK)
            {
                /* 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);
            }
        }
    
    
    /*    Ethernet_Pkt_Desc *newPacket = mem_calloc(1, sizeof(Ethernet_Pkt_Desc));
        newPacket->dataBuffer = pPacket->dataBuffer;*/
    /*    if(pPacket != NULL)
            mem_free(pPacket);*/
    /*    Ethernet_Pkt_Desc *newPacket = Ethernet_getPacketBuffer();
        newPacket->dataBuffer = pPacket->dataBuffer;*/
    
        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);
    }
    
    //###########################################################################
    //
    // FILE:   enet_lwip.c
    //
    // TITLE:  lwIP based Ethernet Example.
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    // $Copyright: $
    //###########################################################################
    
    #include <string.h>
    
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_types.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_emac.h"
    
    #include "driverlib_cm/ethernet.h"
    #include "driverlib_cm/gpio.h"
    #include "driverlib_cm/interrupt.h"
    #include "driverlib_cm/flash.h"
    
    #include "driverlib_cm/sysctl.h"
    #include "driverlib_cm/systick.h"
    
    #include "utils/lwiplib.h"
    #include "board_drivers/pinout.h"
    
    #include "lwip/apps/httpd.h"
    //*****************************************************************************
    //
    //! \addtogroup master_example_list
    //! <h1>Ethernet with lwIP (enet_lwip)</h1>
    //!
    //! This example application demonstrates the operation of the F2838x
    //! microcontroller Ethernet controller using the lwIP TCP/IP Stack. Once
    //! programmed, the device sits endlessly waiting for ICMP ping requests. It
    //! has a static IP address. To ping the device, the sender has to be in the
    //! same network. The stack also supports ARP.
    //!
    //! For additional details on lwIP, refer to the lwIP web page at:
    //! http://savannah.nongnu.org/projects/lwip/
    //
    //*****************************************************************************
    
    // These are defined by the linker (see device linker command file)
    extern uint16_t RamfuncsLoadStart;
    extern uint16_t RamfuncsLoadSize;
    extern uint16_t RamfuncsRunStart;
    extern uint16_t RamfuncsLoadEnd;
    extern uint16_t RamfuncsRunEnd;
    extern uint16_t RamfuncsRunSize;
    
    extern uint16_t constLoadStart;
    extern uint16_t constLoadEnd;
    extern uint16_t constLoadSize;
    extern uint16_t constRunStart;
    extern uint16_t constRunEnd;
    extern uint16_t constRunSize;
    
    #define DEVICE_FLASH_WAITSTATES 2
    
    //*****************************************************************************
    //
    // Driver specific initialization code and macro.
    //
    //*****************************************************************************
    
    #define ETHERNET_NO_OF_RX_PACKETS   2U
    #define ETHERNET_MAX_PACKET_LENGTH 1538U
    #define NUM_PACKET_DESC_RX_APPLICATION 16
    
    Ethernet_Handle emac_handle;
    Ethernet_InitConfig *pInitCfg;
    uint32_t Ethernet_numRxCallbackCustom = 0;
    uint32_t releaseTxCount = 0;
    uint32_t genericISRCustomcount = 0;
    uint32_t genericISRCustomRBUcount = 0;
    uint32_t genericISRCustomROVcount = 0;
    uint32_t genericISRCustomRIcount = 0;
    
    uint32_t systickPeriodValue = 15000000;
    Ethernet_Pkt_Desc  pktDescriptorRXCustom[NUM_PACKET_DESC_RX_APPLICATION];
    extern uint32_t Ethernet_numGetPacketBufferCallback;
    extern Ethernet_Device Ethernet_device_struct;
    uint8_t Ethernet_rxBuffer[ETHERNET_NO_OF_RX_PACKETS *
                              ETHERNET_MAX_PACKET_LENGTH];
    uint32_t sendPacketFailedCount = 0;
    
    uint8_t mac_custom[6] = {0xA8, 0x63, 0xF2, 0x00, 0x1D, 0x98};
    
    extern Ethernet_Pkt_Desc*
    lwIPEthernetIntHandler(Ethernet_Pkt_Desc *pPacket);
    
    void CM_init(void)
    {
        //
        // Disable the watchdog
        //
        SysCtl_disableWatchdog();
    
    #ifdef _FLASH
        //
        // Copy time critical code and flash setup code to RAM. This includes the
        // following functions: InitFlash();
        //
        // The RamfuncsLoadStart, RamfuncsLoadSize, and RamfuncsRunStart symbols
        // are created by the linker. Refer to the device .cmd file.
        // Html pages are also being copied from flash to ram.
        //
        memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
        memcpy(&constRunStart, &constLoadStart, (size_t)&constLoadSize);
        //
        // Call Flash Initialization to setup flash waitstates. This function must
        // reside in RAM.
        //
        Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
    #endif
    
        //
        // Sets the NVIC vector table offset address.
        //
    #ifdef _FLASH
        Interrupt_setVectorTableOffset((uint32_t)vectorTableFlash);
    #else
        Interrupt_setVectorTableOffset((uint32_t)vectorTableRAM);
    #endif
    
    }
    //*****************************************************************************
    //
    // HTTP Webserver related callbacks and definitions.
    //
    //*****************************************************************************
    //
    // Currently, this implemented as a pointer to function which is called when
    // corresponding query is received by the HTTP webserver daemon. When more
    // features are needed to be added, it should be implemented as a separate
    // interface.
    //
    void httpLEDToggle(void);
    void(*ledtoggleFuncPtr)(void) = &httpLEDToggle;
    
    //*****************************************************************************
    //
    // The interrupt handler for the SysTick interrupt.
    //
    //*****************************************************************************
    void
    SysTickIntHandler(void)
    {
        //
        // Call the lwIP timer handler.
        //
        lwIPTimer(systickPeriodValue);
    }
    
    //*****************************************************************************
    //
    //  This function is a callback function called by the example to
    //  get a Packet Buffer. Has to return a ETHERNET_Pkt_Desc Structure.
    //  Rewrite this API for custom use case.
    //
    //*****************************************************************************
    Ethernet_Pkt_Desc* Ethernet_getPacketBufferCustom(void)
    {
        //
        // Get the next packet descriptor from the descriptor pool
        //
        uint32_t shortIndex = (Ethernet_numGetPacketBufferCallback + 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++;
    
        //
        // Update buffer length information to the newly procured packet
        // descriptor.
        //
        pktDescriptorRXCustom[shortIndex].bufferLength =
                                      ETHERNET_MAX_PACKET_LENGTH;
    
        //
        // Update the receive buffer address in the packer descriptor.
        //
        pktDescriptorRXCustom[shortIndex].dataBuffer =
                                          &Ethernet_device_struct.rxBuffer [ \
                   (ETHERNET_MAX_PACKET_LENGTH*Ethernet_device_struct.rxBuffIndex)];
    
        //
        // Update the receive buffer pool index.
        //
        Ethernet_device_struct.rxBuffIndex += 1U;
        Ethernet_device_struct.rxBuffIndex  = \
        (Ethernet_device_struct.rxBuffIndex%ETHERNET_NO_OF_RX_PACKETS);
    
        //
        // Receive buffer is usable from Address 0
        //
        pktDescriptorRXCustom[shortIndex].dataOffset = 0U;
    
        //
        // Return this new descriptor to the driver.
        //
        return (&(pktDescriptorRXCustom[shortIndex]));
    }
    
    //*****************************************************************************
    //
    //  This is a hook function and called by the driver when it receives a
    //  packet. Application is expected to replenish the buffer after consuming it.
    //  Has to return a ETHERNET_Pkt_Desc Structure.
    //  Rewrite this API for custom use case.
    //
    //*****************************************************************************
    Ethernet_Pkt_Desc* Ethernet_receivePacketCallbackCustom(
            Ethernet_Handle handleApplication,
            Ethernet_Pkt_Desc *pPacket)
    {
        //
        // Book-keeping to maintain number of callbacks received.
        //
    #ifdef ETHERNET_DEBUG
        Ethernet_numRxCallbackCustom++;
    #endif
    
        //
        // This is a placeholder for Application specific handling
        // We are replenishing the buffer received with another buffer
        //
        return lwIPEthernetIntHandler(pPacket);
    }
    
    void Ethernet_releaseTxPacketBufferCustom(
            Ethernet_Handle handleApplication,
            Ethernet_Pkt_Desc *pPacket)
    {
        //
        // Once the packet is sent, reuse the packet memory to avoid
        // memory leaks. Call this interrupt handler function which will take care
        // of freeing the memory used by the packet descriptor.
        //
        lwIPEthernetIntHandler(pPacket);
    
        //
        // Increment the book-keeping counter.
        //
    #ifdef ETHERNET_DEBUG
        releaseTxCount++;
    #endif
    }
    Ethernet_Pkt_Desc *Ethernet_performPopOnPacketQueueCustom(
                Ethernet_PKT_Queue_T *pktQueuePtr)
    {
        Ethernet_Pkt_Desc *pktDescHdrPtr;
    
        pktDescHdrPtr = pktQueuePtr->head;
    
        if(0U != pktDescHdrPtr)
        {
            pktQueuePtr->head = pktDescHdrPtr->nextPacketDesc;
            pktQueuePtr->count--;
        }
    
        return(pktDescHdrPtr);
    }
    void Ethernet_performPushOnPacketQueueCustom(
            Ethernet_PKT_Queue_T *pktQueuePtr,
            Ethernet_Pkt_Desc *pktDescHdrPtr)
    {
        pktDescHdrPtr->nextPacketDesc = 0U;
    
        if(0U == pktQueuePtr->head)
        {
            //
            // Queue is empty - Initialize it with this one packet
            //
            pktQueuePtr->head = pktDescHdrPtr;
            pktQueuePtr->tail = pktDescHdrPtr;
        }
        else
        {
            //
            // Queue is not empty - Push onto END
            //
            pktQueuePtr->tail->nextPacketDesc = pktDescHdrPtr;
            pktQueuePtr->tail        = pktDescHdrPtr;
        }
        pktQueuePtr->count++;
    }
    void Ethernet_setMACConfigurationCustom(uint32_t base, uint32_t flags)
    {
        HWREG(base + ETHERNET_O_MAC_CONFIGURATION) |= flags;
    }
    void Ethernet_clearMACConfigurationCustom(uint32_t base, uint32_t flags)
    {
        HWREG(base + ETHERNET_O_MAC_CONFIGURATION) &= ~flags;
    
    }
    interrupt void Ethernet_genericISRCustom(void)
    {
        genericISRCustomcount++;
        Ethernet_RxChDesc *rxChan;
        Ethernet_TxChDesc *txChan;
        Ethernet_HW_descriptor    *descPtr;
        Ethernet_HW_descriptor    *tailPtr;
        uint16_t i=0;
        Ethernet_clearMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
        Ethernet_clearMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_TE);
        for(i = 0U;i < Ethernet_device_struct.initConfig.numChannels;i++)
         {
             Ethernet_disableRxDMAReception(
                   Ethernet_device_struct.baseAddresses.enet_base,
                   i);
         }
        if(((ETHERNET_DMA_CH0_STATUS_AIS |
                             ETHERNET_DMA_CH0_STATUS_RBU) ==
                           (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                                  ETHERNET_O_DMA_CH0_STATUS) &
                                  (uint32_t)(ETHERNET_DMA_CH0_STATUS_AIS |
                                             ETHERNET_DMA_CH0_STATUS_RBU))) ||
              (ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS) ==
                                       (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                                              ETHERNET_O_MTL_Q0_INTERRUPT_CONTROL_STATUS) &
                                              (uint32_t)(ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS
                                                         )))
          {
              if((ETHERNET_DMA_CH0_STATUS_AIS |
                                 ETHERNET_DMA_CH0_STATUS_RBU) ==
                               (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                                      ETHERNET_O_DMA_CH0_STATUS) &
                                      (uint32_t)(ETHERNET_DMA_CH0_STATUS_AIS |
                                                 ETHERNET_DMA_CH0_STATUS_RBU)))
              {
              genericISRCustomRBUcount++;
              }
              if((ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS) ==
                      (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                             ETHERNET_O_MTL_Q0_INTERRUPT_CONTROL_STATUS) &
                             (uint32_t)(ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS
                                        )))
              {
                  genericISRCustomROVcount++;
                  Ethernet_enableMTLInterrupt(Ethernet_device_struct.baseAddresses.enet_base,0,
                                              ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS);
              }
    
            /*
                 * Clear the AIS and RBU status bit. These MUST be
                 * cleared together!
                 */
                Ethernet_clearDMAChannelInterrupt(
                        Ethernet_device_struct.baseAddresses.enet_base,
                        ETHERNET_DMA_CHANNEL_NUM_0,
                        ETHERNET_DMA_CH0_STATUS_AIS |
                        ETHERNET_DMA_CH0_STATUS_RBU);
    
                /*
               *Recover from Receive Buffer Unavailable (and hung DMA)
             *
             * All descriptor buffers are owned by the application, and
             * in result the DMA cannot transfer incoming frames to the
             * buffers (RBU condition). DMA has also entered suspend
             * mode at this point, too.
             *
             * Drain the RX queues
             */
    
                /* Upon RBU error, discard all previously received packets */
                if(Ethernet_device_struct.initConfig.pfcbDeletePackets != NULL)
                    (*Ethernet_device_struct.initConfig.pfcbDeletePackets)();
    
                rxChan =
                   &Ethernet_device_struct.dmaObj.rxDma[ETHERNET_DMA_CHANNEL_NUM_0];
                txChan=
                   &Ethernet_device_struct.dmaObj.txDma[ETHERNET_DMA_CHANNEL_NUM_0];
    
        /*
         * Need to disable multiple interrupts, so protect the code to do so within
         * a global disable block (to prevent getting interrupted in between)
         */
    
                if(NULL!= Ethernet_device_struct.ptrPlatformInterruptDisable)
                {
                    (*Ethernet_device_struct.ptrPlatformInterruptDisable)(
                        Ethernet_device_struct.interruptNum[
                            ETHERNET_RX_INTR_CH0 + rxChan->chInfo->chNum]);
    
                    (*Ethernet_device_struct.ptrPlatformInterruptDisable)(
                        Ethernet_device_struct.interruptNum[
                            ETHERNET_GENERIC_INTERRUPT]);
                }
                /* verify we have full capacity in the descriptor queue */
                if(rxChan->descQueue.count < rxChan->descMax) {
                  /* The queue is not at full capacity due to OOM errors.
                  Try to fill it again */
                    Ethernet_addPacketsIntoRxQueue(rxChan);
                }
                Ethernet_initRxChannel(
                        &Ethernet_device_struct.initConfig.chInfo[ETHERNET_CH_DIR_RX][0]);
    
                Ethernet_writeRxDescTailPointer(
                    Ethernet_device_struct.baseAddresses.enet_base,
                    0,
                    (&Ethernet_device_struct.rxDesc[
                     ((uint32_t)ETHERNET_DESCRIPTORS_NUM_RX_PER_CHANNEL) *
                      (0 + (uint32_t)1U)]));
    
                if(NULL!= Ethernet_device_struct.ptrPlatformInterruptEnable)
                {
                    (*Ethernet_device_struct.ptrPlatformInterruptEnable)(
                        Ethernet_device_struct.interruptNum[
                            ETHERNET_RX_INTR_CH0 + rxChan->chInfo->chNum]);
                    (*Ethernet_device_struct.ptrPlatformInterruptEnable)(
                        Ethernet_device_struct.interruptNum[
                            ETHERNET_GENERIC_INTERRUPT]);
                }
    
    
        }
        if(0U != (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                                     ETHERNET_O_DMA_CH0_STATUS) &
                               (uint32_t) ETHERNET_DMA_CH0_STATUS_RI))
        {
            genericISRCustomRIcount++;
            Ethernet_clearDMAChannelInterrupt(
                            Ethernet_device_struct.baseAddresses.enet_base,
                            ETHERNET_DMA_CHANNEL_NUM_0,
                            ETHERNET_DMA_CH0_STATUS_NIS | ETHERNET_DMA_CH0_STATUS_RI);
        }
    
        for(i = 0U;i < Ethernet_device_struct.initConfig.numChannels;i++)
         {
             Ethernet_enableRxDMAReception(
                   Ethernet_device_struct.baseAddresses.enet_base,
                   i);
         }
        Ethernet_setMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
        Ethernet_setMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_TE);
    }
    
    void
    Ethernet_init(const unsigned char *mac)
    {
        Ethernet_InitInterfaceConfig initInterfaceConfig;
        uint32_t macLower;
        uint32_t macHigher;
        uint8_t *temp;
    
        initInterfaceConfig.ssbase = EMAC_SS_BASE;
        initInterfaceConfig.enet_base = EMAC_BASE;
        initInterfaceConfig.phyMode = ETHERNET_SS_PHY_INTF_SEL_MII;
    
        //
        // Assign SoC specific functions for Enabling,Disabling interrupts
        // and for enabling the Peripheral at system level
        //
        initInterfaceConfig.ptrPlatformInterruptDisable =
                                                        &Platform_disableInterrupt;
        initInterfaceConfig.ptrPlatformInterruptEnable =
                                                         &Platform_enableInterrupt;
        initInterfaceConfig.ptrPlatformPeripheralEnable =
                                                        &Platform_enablePeripheral;
        initInterfaceConfig.ptrPlatformPeripheralReset =
                                                         &Platform_resetPeripheral;
    
        //
        // Assign the peripheral number at the SoC
        //
        initInterfaceConfig.peripheralNum = SYSCTL_PERIPH_CLK_ENET;
    
        //
        // Assign the default SoC specific interrupt numbers of Ethernet interrupts
        //
        initInterfaceConfig.interruptNum[0] = INT_EMAC;
        initInterfaceConfig.interruptNum[1] = INT_EMAC_TX0;
        initInterfaceConfig.interruptNum[2] = INT_EMAC_TX1;
        initInterfaceConfig.interruptNum[3] = INT_EMAC_RX0;
        initInterfaceConfig.interruptNum[4] = INT_EMAC_RX1;
    
        pInitCfg = Ethernet_initInterface(initInterfaceConfig);
    
        Ethernet_getInitConfig(pInitCfg);
        pInitCfg->dmaMode.InterruptMode = ETHERNET_DMA_MODE_INTM_MODE2;
    
        //
        // Assign the callbacks for Getting packet buffer when needed
        // Releasing the TxPacketBuffer on Transmit interrupt callbacks
        // Receive packet callback on Receive packet completion interrupt
        //
        pInitCfg->pfcbRxPacket = &Ethernet_receivePacketCallbackCustom;
        pInitCfg->pfcbGetPacket = &Ethernet_getPacketBuffer;
        pInitCfg->pfcbFreePacket = &Ethernet_releaseTxPacketBufferCustom;
    
        //
        //Assign the Buffer to be used by the Low level driver for receiving
        //Packets. This should be accessible by the Ethernet DMA
        //
        pInitCfg->rxBuffer = Ethernet_rxBuffer;
    
        //
        // The Application handle is not used by this application
        // Hence using a dummy value of 1
        //
        Ethernet_getHandle((Ethernet_Handle)1, pInitCfg , &emac_handle);
    
        //
        // Disable transmit buffer unavailable and normal interrupt which
        // are enabled by default in Ethernet_getHandle.
        //
        Ethernet_disableDmaInterrupt(Ethernet_device_struct.baseAddresses.enet_base,
                                     0, (ETHERNET_DMA_CH0_INTERRUPT_ENABLE_TBUE |
                                         ETHERNET_DMA_CH0_INTERRUPT_ENABLE_NIE));
    
        //
        // Enable the MTL interrupt to service the receive FIFO overflow
        // condition in the Ethernet module.
        //
        Ethernet_enableMTLInterrupt(Ethernet_device_struct.baseAddresses.enet_base,0,
                                    ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOIE);
    
        //
        // Disable the MAC Management counter interrupts as they are not used
        // in this application.
        //
        HWREG(Ethernet_device_struct.baseAddresses.enet_base + ETHERNET_O_MMC_RX_INTERRUPT_MASK) = 0xFFFFFFFF;
        HWREG(Ethernet_device_struct.baseAddresses.enet_base + ETHERNET_O_MMC_IPC_RX_INTERRUPT_MASK) = 0xFFFFFFFF;
        //
        //Do global Interrupt Enable
        //
        (void)Interrupt_enableInProcessor();
    
        //
        //Assign default ISRs
        //
        Interrupt_registerHandler(INT_EMAC_TX0, Ethernet_transmitISR);
        Interrupt_registerHandler(INT_EMAC_RX0, Ethernet_receiveISR);
        Interrupt_registerHandler(INT_EMAC, Ethernet_genericISRCustom);
    
        //
        //Enable the default interrupt handlers
        //
        Interrupt_enable(INT_EMAC_TX0);
        Interrupt_enable(INT_EMAC_RX0);
        Interrupt_enable(INT_EMAC);
    
        //
        // Convert the mac address string into the 32/16 split variables format
        // that is required by the driver to program into hardware registers.
        // Note: This step is done after the Ethernet_getHandle function because
        //       a dummy MAC address is programmed in that function.
        //
        temp = (uint8_t *)&macLower;
        temp[0] = mac[0];
        temp[1] = mac[1];
        temp[2] = mac[2];
        temp[3] = mac[3];
    
        temp = (uint8_t *)&macHigher;
        temp[0] = mac[4];
        temp[1] = mac[5];
    
        //
        // Program the unicast mac address.
        //
        Ethernet_setMACAddr(EMAC_BASE,
                            0,
                            macHigher,
                            macLower,
                            ETHERNET_CHANNEL_0);
        Ethernet_clearMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
        Ethernet_setMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
    }
    
    
    //*****************************************************************************
    //
    // This example demonstrates the use of the Ethernet Controller.
    //
    //*****************************************************************************
    int
    main(void)
    {
        unsigned long ulUser0, ulUser1;
        unsigned char pucMACArray[8];
    
        //
        // User specific IP Address Configuration.
        // Current implementation works with Static IP address only.
        //
        unsigned long IPAddr = 0xC0A80004;
        unsigned long NetMask = 0xFFFFFF00;
        unsigned long GWAddr = 0x00000000;
    
        //
        // Initializing the CM. Loading the required functions to SRAM.
        //
        CM_init();
    
        SYSTICK_setPeriod(systickPeriodValue);
        SYSTICK_enableCounter();
        SYSTICK_registerInterruptHandler(SysTickIntHandler);
        SYSTICK_enableInterrupt();
    
        //
        // Enable processor interrupts.
        //
        Interrupt_enableInProcessor();
            
        // Set user/company specific MAC octets
        // (for this code we are using A8-63-F2-00-00-80)
        // 0x00 MACOCT3 MACOCT2 MACOCT1
        ulUser0 = 0x00F263A8;
    
        // 0x00 MACOCT6 MACOCT5 MACOCT4
        ulUser1 = 0x00800000;
    
        //
        // Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
        // address needed to program the hardware registers, then program the MAC
        // address into the Ethernet Controller registers.
        //
        pucMACArray[0] = ((ulUser0 >>  0) & 0xff);
        pucMACArray[1] = ((ulUser0 >>  8) & 0xff);
        pucMACArray[2] = ((ulUser0 >> 16) & 0xff);
        pucMACArray[3] = ((ulUser1 >>  0) & 0xff);
        pucMACArray[4] = ((ulUser1 >>  8) & 0xff);
        pucMACArray[5] = ((ulUser1 >> 16) & 0xff);
    
        //
        // Initialize ethernet module.
        //
        Ethernet_init(mac_custom);
    
        //
        // Initialze the lwIP library, using DHCP.
        //
        lwIPInit(0, mac_custom, IPAddr, NetMask, GWAddr, IPADDR_USE_STATIC);
    
        //
        // Initialize the HTTP webserver daemon.
        //
        httpd_init();
    
        //
        // Loop forever. All the work is done in interrupt handlers.
        //
        while(1);
    }
    
    //*****************************************************************************
    //
    // Called by lwIP Library. Toggles the led when a command is received by the
    // HTTP webserver.
    //
    //*****************************************************************************
    void httpLEDToggle(void)
    {
        //
        // Toggle the LED D1 on the control card.
        //
        GPIO_togglePin(DEVICE_GPIO_PIN_LED1);
    }
    
    
    //*****************************************************************************
    //
    // Called by lwIP Library. Could be used for periodic custom tasks.
    //
    //*****************************************************************************
    void lwIPHostTimerHandler(void)
    {
    
    }
    

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/171/2838x_5F00_flash_5F00_lnk_5F00_cm_5F00_lwip.cmd_5F00_txt

    4265.ethernet.c8168.ethernet.h

    Regards,

    Yashwant

  • I use C2000Ware_3_04_00_00

  • OK,under revision

  • HI,Yashwant Temburu

    I am now under the project and replaced the code you gave to my two files enet_lwip.c and f2838xif.c.
    But you said to update the attachment in f2838x_cm driverlib.
    I did not find this attachment.

    thanks

    vince

  • HI,Yashwant Temburu

    After the two files enet_lwip.c and f2838xif.c were replaced, I replaced the following figure and compiled it. The results are as follows:

    I am also looking for reasons.

    thanks

    vince

  • HI, Yashwant Temburu

    I am now under the project and replaced the code you gave to my three files enet_lwip.c   f2838xif.c and 2838x_flash_lnk_cm_lwip.cmd.

    Then, on my side, I created a new folder, put your ethernet.c and ethernet.h into it, added the header file path, and then added the header file #include "ethernet.h" in enet_lwip.c. Compile again, only a few warnings remain. As shown below:

    thanks

    vince

  • HI,Yashwant Temburu

    After compiling, the ethernet.h file is grayed out as a whole, and it feels a bit unused.
    One more thing I need to ask is how to use wireshark on the computer to capture the data sent by the development board? This example of yours only has the CM4 core to drive the ethernet program. The data on CPU1 is needed later, and the IPC code needs to be added to the routine, right?

    I haven’t tuned Ethernet before, the questions I asked are a bit amateurish, sorry

    thanks

    vince

  • HI,Yashwant Temburu

    If both my development board and laptop are connected to the switch, how can I make the laptop communicate with the development board?

    My process is to modify the IP address in enet_lwip.c.

    Because my laptop is set to automatically recognize the IP, and then I did not use the cmd command ipconfig on the laptop, and found the network segment of the IP address automatically obtained by the laptop. Then change the unsigned long IPAddr = 0xC0A80004; (192.168.0.4) in enet_lwip.c to unsigned long IPAddr = 0xDBF60201; (219.246.2.1) No other changes have been made.

    After that, I used the cmd command to ping the IP address 219.246.2.1 set in the development board program. The results are as follows:

    Summary: The above is my understanding. The development board and the laptop are connected to the switch at the same time and want to communicate. It is necessary to set the development board and the laptop on the same network segment, as set in the figure above. Just need to modify the IP, no need to modify the other, that's it?

    Here to ask

    thanks

    vince

  • HI,Yashwant Temburu

    What are the considerations for the treatment of this place?

    thanks

    vince

  • HI,Yashwant Temburu

    On my side, I want to receive the data sent by the development board through the network debugging assistant. However, when connecting, an error is always reported.

    Is there a problem with the procedure?

    thanks

    vince

  • HI,Yashwant Temburu

    The picture below is the data packet I got by using wireshark to grab the MAC address of the development board in the following connection method

    Connection method:

    The development board uses the network cable to connect to the switch A

    The laptop is connected to the switch A with a network cable

    After connecting, the laptop will change IPV4 to obtain an IP address automatically.

    Then, run the program.

    The results are as follows:

    thanks

    vince

  • Hi Vince,

    First to confirm were you able to successfully build the project with the updated files that were provide? If successfully built, Instead of connecting the board to switch, were you able to communicate to the development board with direct connection to your laptop. 

    The current example uses static ip address which is set using variable IPAddr. 

    For your setup to work with a switch you would have to enable DHCP in the example so that the switch can automatically assign an ip address to your development board. Search for how laptop gets an ipaddress through DHCP by the switch to understand more about the protocol.

    MAC address (mac_custom) is unique to every device but can be requested by the host for communication using ARP.

    Sorry we cannot support for the enhancements you want on the current example but can help with you if there is any issue with existing example.

    Regards,

    Yashwant

  • HI,Yashwant Temburu

    Hello, I have been able to download it successfully. But, don’t know how to use data for communication? At the same time, how should the host computer use the software to grab the data?
    Because my purpose is to send the data of CPU1 to the CM4 core, and then the CM4 core drives the ethernet to send the data to the laptop.
    I see in your reply that our existing routines and technologies do not support the development board to connect to the switch to communicate with the laptop computer?
    Can I only directly connect the development board and the laptop through a network cable, and then perform data communication?

    Currently, my progress is shown in the figure below.

    thanks

    vince

  • I dont know what that software is used for but if it is to transfer packet data to a certain ip address then you can directly use the Ethernet_rxBuffer in the application device code which has the latest packet data sent by the host. This data can then be transferred to C28x using IPC.

    I see in your reply that our existing routines and technologies do not support the development board to connect to the switch to communicate with the laptop computer?

    Yes they dont support router connection using dhcp.

  • HI,Yashwant Temburu

    Hello, it may be that I did not express it clearly. My data is in CPU1, and then it needs to be sent to the CM4 core via IPC, and then CM4 drives the ethernet to send this data to the laptop. The whole process is one-way.
    I have two questions. 1. How to put your own data in the whole process to ensure that the final data is sent out.
    2. How to see the real-time changes of data on the laptop.

    thanks

    vince

  • HI,Yashwant Temburu

    I added IPC to the enet_lwip routine, and also added the IPC program to ethernet_c28x_config. Run these two routines. There is a problem: CPU1 runs the ethernet_c28x_config routine, which is normal. However, when the enet_lwip routine is downloaded to the board and click Run, the program in the enet_lwip routine will run to __asm(" bkpt #0");
    What is the reason for this?

    //#############################################################################
    //
    // FILE:   cm_common_config_c28x.c
    //
    // TITLE:  C28x Common Configurations to be used for the CM Side.
    //
    //! \addtogroup driver_example_list
    //! <h1>C28x Common Configurations</h1>
    //!
    //! This example configures the GPIOs and Allocates the shared peripherals
    //! according to the defines selected by the users.
    
    #include "driverlib.h"
    #include "device.h"
    #include "CANA.h"
    
    #define RX_MSG_OBJ_ID     1
    #define MSG_DATA_LENGTH   8
    #define MSGCOUNT          16
    char send_flag=0;
    #define can_receive_length  3    //*************************
    char send_buf[can_receive_length]; //*************************
    uint16_t  t = 0;
    //************IPC*************
    int i;
    #define IPC_CMD_READ_MEM   0x1001
    #define IPC_CMD_RESP       0x2001
    
    #define TEST_PASS          0x5555
    #define TEST_FAIL          0xAAAA
    
    #define PACKET_LENGTH 132
    #pragma DATA_SECTION(packetData, "MSGRAM_CPU_TO_CM")
    uint8_t  packetData[PACKET_LENGTH];
    //#pragma DATA_SECTION(send_buf, "MSGRAM_CPU_TO_CM")
    uint32_t pass;
    //************IPC*************
    
    void main(void)
    {
        Device_init();
        Device_initGPIO();
        //*********************CANA**************************************
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);
        CAN_initModule(CANA_BASE);
        CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 500000, 20);
        CAN_enableInterrupt(CANA_BASE, CAN_INT_IE0 | CAN_INT_ERROR | CAN_INT_STATUS);
        //*********************CANA**************************************
    //  GPIO_setPadConfig(DEVICE_GPIO_PIN_CANA, GPIO_PIN_TYPE_STD);
    //  GPIO_setDirectionMode(DEVICE_GPIO_PIN_CANA, GPIO_DIR_MODE_OUT);
    //  GPIO_setPadConfig(DEVICE_GPIO_PIN_232, GPIO_PIN_TYPE_STD);
    //  GPIO_setDirectionMode(DEVICE_GPIO_PIN_232, GPIO_DIR_MODE_OUT);
    
        //********************SCIA   TX    232***************************
        GPIO_setMasterCore(8, GPIO_CORE_CPU1);
        GPIO_setPinConfig(GPIO_8_SCIA_TX);
        GPIO_setDirectionMode(8, GPIO_DIR_MODE_OUT);
        GPIO_setPadConfig(8, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(8, GPIO_QUAL_ASYNC);
        //
        // Boot CM core
        //
    #ifdef _FLASH
        Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
    #else
        Device_bootCM(BOOTMODE_BOOT_TO_S0RAM);
    #endif
    
    #ifdef ETHERNET
        //
        // Set up EnetCLK to use SYSPLL as the clock source and set the
        // clock divider to 2.
        //
        // This way we ensure that the PTP clock is 100 MHz. Note that this value
        // is not automatically/dynamically known to the CM core and hence it needs
        // to be made available to the CM side code beforehand.
        SysCtl_setEnetClk(SYSCTL_ENETCLKOUT_DIV_2, SYSCTL_SOURCE_SYSPLL);
        //
        // Configure the GPIOs for ETHERNET.
        //
        // MDIO Signals
        //
        GPIO_setPinConfig(GPIO_105_ENET_MDIO_CLK);
        GPIO_setPinConfig(GPIO_106_ENET_MDIO_DATA);
        //
        // Use this only for RMII Mode
        //GPIO_setPinConfig(GPIO_73_ENET_RMII_CLK);
        //
    
        //
        //MII Signals
        //
        GPIO_setPinConfig(GPIO_109_ENET_MII_CRS);
        GPIO_setPinConfig(GPIO_110_ENET_MII_COL);
        GPIO_setPinConfig(GPIO_75_ENET_MII_TX_DATA0);
        GPIO_setPinConfig(GPIO_122_ENET_MII_TX_DATA1);
        GPIO_setPinConfig(GPIO_123_ENET_MII_TX_DATA2);
        GPIO_setPinConfig(GPIO_124_ENET_MII_TX_DATA3);
        //
        //Use this only if the TX Error pin has to be connected
        //GPIO_setPinConfig(GPIO_46_ENET_MII_TX_ERR);
        //
        GPIO_setPinConfig(GPIO_118_ENET_MII_TX_EN);
        GPIO_setPinConfig(GPIO_114_ENET_MII_RX_DATA0);
        GPIO_setPinConfig(GPIO_115_ENET_MII_RX_DATA1);
        GPIO_setPinConfig(GPIO_116_ENET_MII_RX_DATA2);
        GPIO_setPinConfig(GPIO_117_ENET_MII_RX_DATA3);
        GPIO_setPinConfig(GPIO_113_ENET_MII_RX_ERR);
        GPIO_setPinConfig(GPIO_112_ENET_MII_RX_DV);
        GPIO_setPinConfig(GPIO_44_ENET_MII_TX_CLK);
        GPIO_setPinConfig(GPIO_111_ENET_MII_RX_CLK);
        //
        //Power down pin to bring the external PHY out of Power down
        //
        GPIO_setDirectionMode(108, GPIO_DIR_MODE_OUT);
        GPIO_setPadConfig(108, GPIO_PIN_TYPE_PULLUP);
        GPIO_writePin(108,1);
        //
        //PHY Reset Pin to be driven High to bring external PHY out of Reset
        //
        GPIO_setDirectionMode(119, GPIO_DIR_MODE_OUT);
        GPIO_setPadConfig(119, GPIO_PIN_TYPE_PULLUP);
        GPIO_writePin(119,1);
    #endif
    
        Interrupt_initModule();
        Interrupt_initVectorTable();
        EINT;
        ERTM;
        //*********************CANA**************************************
        Interrupt_register(INT_CANA0,&canaISR);
        Interrupt_enable(INT_CANA0);
        CAN_enableGlobalInterrupt(CANA_BASE, CAN_GLOBAL_INT_CANINT0);
        CAN_setupMessageObject(CANA_BASE, RX_MSG_OBJ_ID, 0x000000,CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0,CAN_MSG_OBJ_USE_ID_FILTER|CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH);
        CAN_startModule(CANA_BASE);
        //*********************CANA**************************************
    
    
    //*************************************************IPC*********************************************************************************
        //
            //Form the unicast Ethernet Packet in Memory
            //在内存中形成单播以太网数据包
            for(i=0;i<PACKET_LENGTH/4;i++)
            {
                //
                //First 6 bytes of the packet are the MAC Destination Address
                //Bytes, the Destination and CRC shall be inserted by the hardware
                //数据包的前6个字节是MAC目标地址字节,目标和CRC必须由硬件插入
                if(i == 0)
                    *((uint32_t *)packetData + i) = 0x01020304;
    //                *((uint32_t *)send_buf + i) = 0x01020304;          //************将 packetData替换成send_buf*********************
                else if(i == 1)
                    *((uint32_t *)packetData + i)  = 0xFFFF0506;
    //                *((uint32_t *)send_buf + i)  = 0xFFFF0506;
                else
                    HWREG((uint32_t *)packetData +i) = i;
    //                HWREG((uint32_t *)send_buf +i) = i;
            }
    
            //
            // Clear any IPC flags if set already
            //
            IPC_clearFlagLtoR(IPC_CPU1_L_CM_R, IPC_FLAG_ALL);
    
            //
            // Synchronize both the cores.同步CPU1和CM内核。
            //
            IPC_sync(IPC_CPU1_L_CM_R, IPC_FLAG31);
            //
            // Send a message without message queue
            // Since C28x and CM does not share the same address space for shared RAM,
            // ADDRESS_CORRECTION is enabled
            // Length of the data to be read is passed as data.
            //
    //        IPC_sendCommand(IPC_CPU1_L_CM_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,
    //                        IPC_CMD_READ_MEM, (uint32_t)packetData, PACKET_LENGTH);
    
            IPC_sendCommand(IPC_CPU1_L_CM_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,IPC_CMD_READ_MEM, (uint32_t)packetData, PACKET_LENGTH);
    
            //
            // Wait for acknowledgment等待CM确认
            //
            IPC_waitForAck(IPC_CPU1_L_CM_R, IPC_FLAG0);
    
            //
            // Read response阅读回应
            //
            if(IPC_getResponse(IPC_CPU1_L_CM_R) == TEST_PASS)
            {
                pass = 1;
            }
            else
            {
                pass = 0;
            }
    //************************************IPC************************************************************
    
    
        while(1)
        {
            //*********************232数据发送************************
            if(send_flag)
            {
                send_flag = 0;
                //GPIO_writePin(DEVICE_GPIO_PIN_232, 0);
                for(t=0;t<150;t++)
                 {
                    if(send_buf[t] == 0)
                     {
                        continue;
                     }
                    SCI_writeCharBlockingNonFIFO(SCIA_BASE, send_buf[t]);
                    if(send_buf[t] == '\n')
                     {
                        send_buf[t] = 0;
                        break;
                     }
                    send_buf[t] = 0;
                 }
              //  GPIO_writePin(DEVICE_GPIO_PIN_232, 1);
            }
            //*********************232数据发送************************
        }
    
    #ifdef MCAN
        //
        // Setting the MCAN Clock.
        //
        SysCtl_setMCANClk(SYSCTL_MCANCLK_DIV_4);
    
        //
        // Configuring the GPIOs for MCAN.
        //
        GPIO_setPinConfig(DEVICE_GPIO_CFG_MCANRXA);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_MCANTXA);
    #endif
    
    #ifdef CANA
        //
        // Configuring the GPIOs for CAN A.
        //
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);
    
        //
        // Allocate Shared Peripheral CAN A to the CM Side.
        //
        SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_CAN_A,0x1U);
    #endif
    
    #ifdef CANB
        //
        // Configuring the GPIOs for CAN B.
        //
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXB);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXB);
    
        //
        // Allocate Shared Peripheral CAN B to the CM Side.
        //
        SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_CAN_B,0x1U);
    #endif
    
    #ifdef UART
        //
        // Configure GPIO85 as the UART Rx pin.
        //
        GPIO_setPinConfig(GPIO_85_UARTA_RX);
        GPIO_setDirectionMode(85, GPIO_DIR_MODE_IN);
        GPIO_setPadConfig(85, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(85, GPIO_QUAL_ASYNC);
    
        //
        // Configure GPIO84 as the UART Tx pin.
        //
        GPIO_setPinConfig(GPIO_84_UARTA_TX);
        GPIO_setDirectionMode(84, GPIO_DIR_MODE_OUT);
        GPIO_setPadConfig(84, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(84, GPIO_QUAL_ASYNC);
    #endif
    
    #ifdef USB
    #ifdef USE_20MHZ_XTAL
        //
        // Set up the auxiliary PLL so a 60 MHz output clock is provided to the USB module.
        // This fixed frequency is required for all USB operations.
        //
        SysCtl_setAuxClock(SYSCTL_AUXPLL_OSCSRC_XTAL |
                           SYSCTL_AUXPLL_IMULT(48) |
                           SYSCTL_REFDIV(2U) | SYSCTL_ODIV(4U) |
                           SYSCTL_AUXPLL_DIV_2 |
                           SYSCTL_AUXPLL_ENABLE |
                           SYSCTL_DCC_BASE_0);
    #else
        //
        // Set up the auxiliary PLL so a 60 MHz output clock is provided to the USB module.
        // This fixed frequency is required for all USB operations.
        //
        SysCtl_setAuxClock(SYSCTL_AUXPLL_OSCSRC_XTAL |
                           SYSCTL_AUXPLL_IMULT(48) |
                           SYSCTL_REFDIV(2U) | SYSCTL_ODIV(5U) |
                           SYSCTL_AUXPLL_DIV_2 |
                           SYSCTL_AUXPLL_ENABLE |
                           SYSCTL_DCC_BASE_0);
    #endif
    
        //
        // Allocate Shared Peripheral USB to the CM Side.
        //
        SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_USBA, 1);
    
        GPIO_setPinConfig(GPIO_0_GPIO0);
        GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
        GPIO_setDirectionMode(0, GPIO_DIR_MODE_OUT);
        GPIO_setMasterCore(0, GPIO_CORE_CM);
    
        //
        // Set the master core of GPIOs to CM.
        //
        GPIO_setMasterCore(42, GPIO_CORE_CM);
        GPIO_setMasterCore(43, GPIO_CORE_CM);
        GPIO_setMasterCore(46, GPIO_CORE_CM);
        GPIO_setMasterCore(47, GPIO_CORE_CM);
        GPIO_setMasterCore(120, GPIO_CORE_CM);
        GPIO_setMasterCore(121, GPIO_CORE_CM);
    
        //
        // Set the USB DM and DP GPIOs.
        //
        GPIO_setAnalogMode(42, GPIO_ANALOG_ENABLED);
        GPIO_setAnalogMode(43, GPIO_ANALOG_ENABLED);
    
        //
        // Set the direction for VBUS and ID.
        //
        GPIO_setDirectionMode(46, GPIO_DIR_MODE_IN);
        GPIO_setDirectionMode(47, GPIO_DIR_MODE_IN);
    
        //
        // Configure the Power Fault.
        //
        GPIO_setMasterCore(120, GPIO_CORE_CM);
        GPIO_setDirectionMode(120, GPIO_DIR_MODE_IN);
    
        //
        // Configure the External Power Signal Enable.
        //
        GPIO_setMasterCore(121, GPIO_CORE_CM);
    	GPIO_setDirectionMode(121, GPIO_DIR_MODE_OUT);
    	GPIO_writePin(121, 1);
    
        //
        // Set the CM Clock to run at 120MHz.
        // The CM Clock is a fractional multiple of the AUXPLL Clock (120 Mhz) from
        // which the USB Clock (60 MHz) is derived.
        //
        SysCtl_setCMClk(SYSCTL_CMCLKOUT_DIV_1, SYSCTL_SOURCE_AUXPLL);
    #endif
    }
    

    //###########################################################################
    //
    // FILE:   enet_lwip.c
    //
    // TITLE:  lwIP based Ethernet Example.
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    // $Copyright: $
    //###########################################################################
    
    #include <string.h>
    
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_types.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_emac.h"
    
    #include "driverlib_cm/ethernet.h"
    #include "driverlib_cm/gpio.h"
    #include "driverlib_cm/interrupt.h"
    #include "driverlib_cm/flash.h"
    
    #include "driverlib_cm/sysctl.h"
    #include "driverlib_cm/systick.h"
    
    #include "utils/lwiplib.h"
    #include "board_drivers/pinout.h"
    
    #include "lwip/apps/httpd.h"
    #include "ethernet.h"
    #include "driverlib_cm.h"
    //#include "ipc_cm.h"
    //*****************************************************************************
    //
    //! \addtogroup master_example_list
    //! <h1>Ethernet with lwIP (enet_lwip)</h1>
    //!
    //! This example application demonstrates the operation of the F2838x
    //! microcontroller Ethernet controller using the lwIP TCP/IP Stack. Once
    //! programmed, the device sits endlessly waiting for ICMP ping requests. It
    //! has a static IP address. To ping the device, the sender has to be in the
    //! same network. The stack also supports ARP.
    //!
    //! For additional details on lwIP, refer to the lwIP web page at:
    //! http://savannah.nongnu.org/projects/lwip/
    //
    //*****************************************************************************
    
    // These are defined by the linker (see device linker command file)
    extern uint16_t RamfuncsLoadStart;
    extern uint16_t RamfuncsLoadSize;
    extern uint16_t RamfuncsRunStart;
    extern uint16_t RamfuncsLoadEnd;
    extern uint16_t RamfuncsRunEnd;
    extern uint16_t RamfuncsRunSize;
    
    extern uint16_t constLoadStart;
    extern uint16_t constLoadEnd;
    extern uint16_t constLoadSize;
    extern uint16_t constRunStart;
    extern uint16_t constRunEnd;
    extern uint16_t constRunSize;
    
    #define DEVICE_FLASH_WAITSTATES 2
    
    //*****************************************************************************
    //
    // Driver specific initialization code and macro.
    //
    //*****************************************************************************
    
    #define ETHERNET_NO_OF_RX_PACKETS   2U
    #define ETHERNET_MAX_PACKET_LENGTH 1538U
    #define NUM_PACKET_DESC_RX_APPLICATION 16
    
    Ethernet_Handle emac_handle;
    Ethernet_InitConfig *pInitCfg;
    uint32_t Ethernet_numRxCallbackCustom = 0;
    uint32_t releaseTxCount = 0;
    uint32_t genericISRCustomcount = 0;
    uint32_t genericISRCustomRBUcount = 0;
    uint32_t genericISRCustomROVcount = 0;
    uint32_t genericISRCustomRIcount = 0;
    
    uint32_t systickPeriodValue = 15000000;
    Ethernet_Pkt_Desc  pktDescriptorRXCustom[NUM_PACKET_DESC_RX_APPLICATION];
    extern uint32_t Ethernet_numGetPacketBufferCallback;
    extern Ethernet_Device Ethernet_device_struct;
    uint8_t Ethernet_rxBuffer[ETHERNET_NO_OF_RX_PACKETS *
                              ETHERNET_MAX_PACKET_LENGTH];
    uint32_t sendPacketFailedCount = 0;
    
    //
    //******IPC*************
    #define IPC_CMD_READ_MEM   0x1001
    #define IPC_CMD_RESP       0x2001
    
    #define TEST_PASS          0x5555
    #define TEST_FAIL          0xAAAA
    #define PACKET_LENGTH 132
    #define ETHERNET_NO_OF_RX_PACKETS   1U
    #define ETHERNET_MAX_PACKET_LENGTH 1538U
    uint8_t pData[PACKET_LENGTH];
    //uint8_t Ethernet_rxBuffer[ETHERNET_NO_OF_RX_PACKETS *ETHERNET_MAX_PACKET_LENGTH];
    Ethernet_Handle emac_handle;
    Ethernet_Pkt_Desc pktDesc;
    extern uint32_t Ethernet_rxInterruptCount;
    bool status = false;
    //
    //**********IPC******************
    uint8_t mac_custom[6] = {0xA8, 0x63, 0xF2, 0x00, 0x1D, 0x98};
    
    extern Ethernet_Pkt_Desc*
    lwIPEthernetIntHandler(Ethernet_Pkt_Desc *pPacket);
    
    void CM_init(void)
    {
        //
        // Disable the watchdog
        //
        SysCtl_disableWatchdog();
    
    #ifdef _FLASH
        //
        // Copy time critical code and flash setup code to RAM. This includes the
        // following functions: InitFlash();
        //
        // The RamfuncsLoadStart, RamfuncsLoadSize, and RamfuncsRunStart symbols
        // are created by the linker. Refer to the device .cmd file.
        // Html pages are also being copied from flash to ram.
        //
        memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
        memcpy(&constRunStart, &constLoadStart, (size_t)&constLoadSize);
        //
        // Call Flash Initialization to setup flash waitstates. This function must
        // reside in RAM.
        //
        Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
    #endif
    
        //
        // Sets the NVIC vector table offset address.
        //
    #ifdef _FLASH
        Interrupt_setVectorTableOffset((uint32_t)vectorTableFlash);
    #else
        Interrupt_setVectorTableOffset((uint32_t)vectorTableRAM);
    #endif
    
    }
    //*****************************************************************************
    //
    // HTTP Webserver related callbacks and definitions.
    //
    //*****************************************************************************
    //
    // Currently, this implemented as a pointer to function which is called when
    // corresponding query is received by the HTTP webserver daemon. When more
    // features are needed to be added, it should be implemented as a separate
    // interface.
    //
    void httpLEDToggle(void);
    void(*ledtoggleFuncPtr)(void) = &httpLEDToggle;
    
    //*****************************************************************************
    //
    // The interrupt handler for the SysTick interrupt.
    //
    //*****************************************************************************
    void
    SysTickIntHandler(void)
    {
        //
        // Call the lwIP timer handler.
        //
        lwIPTimer(systickPeriodValue);
    }
    
    //*****************************************************************************
    //
    //  This function is a callback function called by the example to
    //  get a Packet Buffer. Has to return a ETHERNET_Pkt_Desc Structure.
    //  Rewrite this API for custom use case.
    //
    //*****************************************************************************
    Ethernet_Pkt_Desc* Ethernet_getPacketBufferCustom(void)
    {
        //
        // Get the next packet descriptor from the descriptor pool
        //
        uint32_t shortIndex = (Ethernet_numGetPacketBufferCallback + 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++;
    
        //
        // Update buffer length information to the newly procured packet
        // descriptor.
        //
        pktDescriptorRXCustom[shortIndex].bufferLength =
                                      ETHERNET_MAX_PACKET_LENGTH;
    
        //
        // Update the receive buffer address in the packer descriptor.
        //
        pktDescriptorRXCustom[shortIndex].dataBuffer =
                                          &Ethernet_device_struct.rxBuffer [ \
                   (ETHERNET_MAX_PACKET_LENGTH*Ethernet_device_struct.rxBuffIndex)];
    
        //
        // Update the receive buffer pool index.
        //
        Ethernet_device_struct.rxBuffIndex += 1U;
        Ethernet_device_struct.rxBuffIndex  = \
        (Ethernet_device_struct.rxBuffIndex%ETHERNET_NO_OF_RX_PACKETS);
    
        //
        // Receive buffer is usable from Address 0
        //
        pktDescriptorRXCustom[shortIndex].dataOffset = 0U;
    
        //
        // Return this new descriptor to the driver.
        //
        return (&(pktDescriptorRXCustom[shortIndex]));
    }
    
    //*****************************************************************************
    //
    //  This is a hook function and called by the driver when it receives a
    //  packet. Application is expected to replenish the buffer after consuming it.
    //  Has to return a ETHERNET_Pkt_Desc Structure.
    //  Rewrite this API for custom use case.
    //
    //*****************************************************************************
    Ethernet_Pkt_Desc* Ethernet_receivePacketCallbackCustom(
            Ethernet_Handle handleApplication,
            Ethernet_Pkt_Desc *pPacket)
    {
        //
        // Book-keeping to maintain number of callbacks received.
        //
    #ifdef ETHERNET_DEBUG
        Ethernet_numRxCallbackCustom++;
    #endif
    
        //
        // This is a placeholder for Application specific handling
        // We are replenishing the buffer received with another buffer
        //
        return lwIPEthernetIntHandler(pPacket);
    }
    
    void Ethernet_releaseTxPacketBufferCustom(
            Ethernet_Handle handleApplication,
            Ethernet_Pkt_Desc *pPacket)
    {
        //
        // Once the packet is sent, reuse the packet memory to avoid
        // memory leaks. Call this interrupt handler function which will take care
        // of freeing the memory used by the packet descriptor.
        //
        lwIPEthernetIntHandler(pPacket);
    
        //
        // Increment the book-keeping counter.
        //
    #ifdef ETHERNET_DEBUG
        releaseTxCount++;
    #endif
    }
    Ethernet_Pkt_Desc *Ethernet_performPopOnPacketQueueCustom(
                Ethernet_PKT_Queue_T *pktQueuePtr)
    {
        Ethernet_Pkt_Desc *pktDescHdrPtr;
    
        pktDescHdrPtr = pktQueuePtr->head;
    
        if(0U != pktDescHdrPtr)
        {
            pktQueuePtr->head = pktDescHdrPtr->nextPacketDesc;
            pktQueuePtr->count--;
        }
    
        return(pktDescHdrPtr);
    }
    void Ethernet_performPushOnPacketQueueCustom(
            Ethernet_PKT_Queue_T *pktQueuePtr,
            Ethernet_Pkt_Desc *pktDescHdrPtr)
    {
        pktDescHdrPtr->nextPacketDesc = 0U;
    
        if(0U == pktQueuePtr->head)
        {
            //
            // Queue is empty - Initialize it with this one packet
            //
            pktQueuePtr->head = pktDescHdrPtr;
            pktQueuePtr->tail = pktDescHdrPtr;
        }
        else
        {
            //
            // Queue is not empty - Push onto END
            //
            pktQueuePtr->tail->nextPacketDesc = pktDescHdrPtr;
            pktQueuePtr->tail        = pktDescHdrPtr;
        }
        pktQueuePtr->count++;
    }
    void Ethernet_setMACConfigurationCustom(uint32_t base, uint32_t flags)
    {
        HWREG(base + ETHERNET_O_MAC_CONFIGURATION) |= flags;
    }
    void Ethernet_clearMACConfigurationCustom(uint32_t base, uint32_t flags)
    {
        HWREG(base + ETHERNET_O_MAC_CONFIGURATION) &= ~flags;
    
    }
    interrupt void Ethernet_genericISRCustom(void)
    {
        genericISRCustomcount++;
        Ethernet_RxChDesc *rxChan;
        Ethernet_TxChDesc *txChan;
        Ethernet_HW_descriptor    *descPtr;
        Ethernet_HW_descriptor    *tailPtr;
        uint16_t i=0;
        Ethernet_clearMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
        Ethernet_clearMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_TE);
        for(i = 0U;i < Ethernet_device_struct.initConfig.numChannels;i++)
         {
             Ethernet_disableRxDMAReception(
                   Ethernet_device_struct.baseAddresses.enet_base,
                   i);
         }
        if(((ETHERNET_DMA_CH0_STATUS_AIS |
                             ETHERNET_DMA_CH0_STATUS_RBU) ==
                           (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                                  ETHERNET_O_DMA_CH0_STATUS) &
                                  (uint32_t)(ETHERNET_DMA_CH0_STATUS_AIS |
                                             ETHERNET_DMA_CH0_STATUS_RBU))) ||
              (ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS) ==
                                       (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                                              ETHERNET_O_MTL_Q0_INTERRUPT_CONTROL_STATUS) &
                                              (uint32_t)(ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS
                                                         )))
          {
              if((ETHERNET_DMA_CH0_STATUS_AIS |
                                 ETHERNET_DMA_CH0_STATUS_RBU) ==
                               (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                                      ETHERNET_O_DMA_CH0_STATUS) &
                                      (uint32_t)(ETHERNET_DMA_CH0_STATUS_AIS |
                                                 ETHERNET_DMA_CH0_STATUS_RBU)))
              {
              genericISRCustomRBUcount++;
              }
              if((ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS) ==
                      (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                             ETHERNET_O_MTL_Q0_INTERRUPT_CONTROL_STATUS) &
                             (uint32_t)(ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS
                                        )))
              {
                  genericISRCustomROVcount++;
                  Ethernet_enableMTLInterrupt(Ethernet_device_struct.baseAddresses.enet_base,0,
                                              ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOVFIS);
              }
    
            /*
                 * Clear the AIS and RBU status bit. These MUST be
                 * cleared together!
                 */
                Ethernet_clearDMAChannelInterrupt(
                        Ethernet_device_struct.baseAddresses.enet_base,
                        ETHERNET_DMA_CHANNEL_NUM_0,
                        ETHERNET_DMA_CH0_STATUS_AIS |
                        ETHERNET_DMA_CH0_STATUS_RBU);
    
                /*
               *Recover from Receive Buffer Unavailable (and hung DMA)
             *
             * All descriptor buffers are owned by the application, and
             * in result the DMA cannot transfer incoming frames to the
             * buffers (RBU condition). DMA has also entered suspend
             * mode at this point, too.
             *
             * Drain the RX queues
             */
    
                /* Upon RBU error, discard all previously received packets */
                if(Ethernet_device_struct.initConfig.pfcbDeletePackets != NULL)
                    (*Ethernet_device_struct.initConfig.pfcbDeletePackets)();
    
                rxChan =
                   &Ethernet_device_struct.dmaObj.rxDma[ETHERNET_DMA_CHANNEL_NUM_0];
                txChan=
                   &Ethernet_device_struct.dmaObj.txDma[ETHERNET_DMA_CHANNEL_NUM_0];
    
        /*
         * Need to disable multiple interrupts, so protect the code to do so within
         * a global disable block (to prevent getting interrupted in between)
         */
    
                if(NULL!= Ethernet_device_struct.ptrPlatformInterruptDisable)
                {
                    (*Ethernet_device_struct.ptrPlatformInterruptDisable)(
                        Ethernet_device_struct.interruptNum[
                            ETHERNET_RX_INTR_CH0 + rxChan->chInfo->chNum]);
    
                    (*Ethernet_device_struct.ptrPlatformInterruptDisable)(
                        Ethernet_device_struct.interruptNum[
                            ETHERNET_GENERIC_INTERRUPT]);
                }
                /* verify we have full capacity in the descriptor queue */
                if(rxChan->descQueue.count < rxChan->descMax) {
                  /* The queue is not at full capacity due to OOM errors.
                  Try to fill it again */
                    Ethernet_addPacketsIntoRxQueue(rxChan);
                }
                Ethernet_initRxChannel(
                        &Ethernet_device_struct.initConfig.chInfo[ETHERNET_CH_DIR_RX][0]);
    
                Ethernet_writeRxDescTailPointer(
                    Ethernet_device_struct.baseAddresses.enet_base,
                    0,
                    (&Ethernet_device_struct.rxDesc[
                     ((uint32_t)ETHERNET_DESCRIPTORS_NUM_RX_PER_CHANNEL) *
                      (0 + (uint32_t)1U)]));
    
                if(NULL!= Ethernet_device_struct.ptrPlatformInterruptEnable)
                {
                    (*Ethernet_device_struct.ptrPlatformInterruptEnable)(
                        Ethernet_device_struct.interruptNum[
                            ETHERNET_RX_INTR_CH0 + rxChan->chInfo->chNum]);
                    (*Ethernet_device_struct.ptrPlatformInterruptEnable)(
                        Ethernet_device_struct.interruptNum[
                            ETHERNET_GENERIC_INTERRUPT]);
                }
    
    
        }
        if(0U != (HWREG(Ethernet_device_struct.baseAddresses.enet_base +
                                     ETHERNET_O_DMA_CH0_STATUS) &
                               (uint32_t) ETHERNET_DMA_CH0_STATUS_RI))
        {
            genericISRCustomRIcount++;
            Ethernet_clearDMAChannelInterrupt(
                            Ethernet_device_struct.baseAddresses.enet_base,
                            ETHERNET_DMA_CHANNEL_NUM_0,
                            ETHERNET_DMA_CH0_STATUS_NIS | ETHERNET_DMA_CH0_STATUS_RI);
        }
    
        for(i = 0U;i < Ethernet_device_struct.initConfig.numChannels;i++)
         {
             Ethernet_enableRxDMAReception(
                   Ethernet_device_struct.baseAddresses.enet_base,
                   i);
         }
        Ethernet_setMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
        Ethernet_setMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_TE);
    }
    
    void
    Ethernet_init(const unsigned char *mac)
    {
        Ethernet_InitInterfaceConfig initInterfaceConfig;
        uint32_t macLower;
        uint32_t macHigher;
        uint8_t *temp;
    
        initInterfaceConfig.ssbase = EMAC_SS_BASE;
        initInterfaceConfig.enet_base = EMAC_BASE;
        initInterfaceConfig.phyMode = ETHERNET_SS_PHY_INTF_SEL_MII;
    
        //
        // Assign SoC specific functions for Enabling,Disabling interrupts
        // and for enabling the Peripheral at system level
        //
        initInterfaceConfig.ptrPlatformInterruptDisable =
                                                        &Platform_disableInterrupt;
        initInterfaceConfig.ptrPlatformInterruptEnable =
                                                         &Platform_enableInterrupt;
        initInterfaceConfig.ptrPlatformPeripheralEnable =
                                                        &Platform_enablePeripheral;
        initInterfaceConfig.ptrPlatformPeripheralReset =
                                                         &Platform_resetPeripheral;
    
        //
        // Assign the peripheral number at the SoC
        //
        initInterfaceConfig.peripheralNum = SYSCTL_PERIPH_CLK_ENET;
    
        //
        // Assign the default SoC specific interrupt numbers of Ethernet interrupts
        //
        initInterfaceConfig.interruptNum[0] = INT_EMAC;
        initInterfaceConfig.interruptNum[1] = INT_EMAC_TX0;
        initInterfaceConfig.interruptNum[2] = INT_EMAC_TX1;
        initInterfaceConfig.interruptNum[3] = INT_EMAC_RX0;
        initInterfaceConfig.interruptNum[4] = INT_EMAC_RX1;
    
        pInitCfg = Ethernet_initInterface(initInterfaceConfig);
    
        Ethernet_getInitConfig(pInitCfg);
        pInitCfg->dmaMode.InterruptMode = ETHERNET_DMA_MODE_INTM_MODE2;
    
        //
        // Assign the callbacks for Getting packet buffer when needed
        // Releasing the TxPacketBuffer on Transmit interrupt callbacks
        // Receive packet callback on Receive packet completion interrupt
        //
        pInitCfg->pfcbRxPacket = &Ethernet_receivePacketCallbackCustom;
        pInitCfg->pfcbGetPacket = &Ethernet_getPacketBuffer;
        pInitCfg->pfcbFreePacket = &Ethernet_releaseTxPacketBufferCustom;
    
        //
        //Assign the Buffer to be used by the Low level driver for receiving
        //Packets. This should be accessible by the Ethernet DMA
        //
        pInitCfg->rxBuffer = Ethernet_rxBuffer;
    
        //
        // The Application handle is not used by this application
        // Hence using a dummy value of 1
        //
        Ethernet_getHandle((Ethernet_Handle)1, pInitCfg , &emac_handle);
    
        //
        // Disable transmit buffer unavailable and normal interrupt which
        // are enabled by default in Ethernet_getHandle.
        //
        Ethernet_disableDmaInterrupt(Ethernet_device_struct.baseAddresses.enet_base,
                                     0, (ETHERNET_DMA_CH0_INTERRUPT_ENABLE_TBUE |
                                         ETHERNET_DMA_CH0_INTERRUPT_ENABLE_NIE));
    
        //
        // Enable the MTL interrupt to service the receive FIFO overflow
        // condition in the Ethernet module.
        //
        Ethernet_enableMTLInterrupt(Ethernet_device_struct.baseAddresses.enet_base,0,
                                    ETHERNET_MTL_Q0_INTERRUPT_CONTROL_STATUS_RXOIE);
    
        //
        // Disable the MAC Management counter interrupts as they are not used
        // in this application.
        //
        HWREG(Ethernet_device_struct.baseAddresses.enet_base + ETHERNET_O_MMC_RX_INTERRUPT_MASK) = 0xFFFFFFFF;
        HWREG(Ethernet_device_struct.baseAddresses.enet_base + ETHERNET_O_MMC_IPC_RX_INTERRUPT_MASK) = 0xFFFFFFFF;
        //
        //Do global Interrupt Enable
        //
        (void)Interrupt_enableInProcessor();
    
        //
        //Assign default ISRs
        //
        Interrupt_registerHandler(INT_EMAC_TX0, Ethernet_transmitISR);
        Interrupt_registerHandler(INT_EMAC_RX0, Ethernet_receiveISR);
        Interrupt_registerHandler(INT_EMAC, Ethernet_genericISRCustom);
    
        //
        //Enable the default interrupt handlers
        //
        Interrupt_enable(INT_EMAC_TX0);
        Interrupt_enable(INT_EMAC_RX0);
        Interrupt_enable(INT_EMAC);
    
        //
        // Convert the mac address string into the 32/16 split variables format
        // that is required by the driver to program into hardware registers.
        // Note: This step is done after the Ethernet_getHandle function because
        //       a dummy MAC address is programmed in that function.
        //
        temp = (uint8_t *)&macLower;
        temp[0] = mac[0];
        temp[1] = mac[1];
        temp[2] = mac[2];
        temp[3] = mac[3];
    
        temp = (uint8_t *)&macHigher;
        temp[0] = mac[4];
        temp[1] = mac[5];
    
        //
        // Program the unicast mac address.
        //
        Ethernet_setMACAddr(EMAC_BASE,
                            0,
                            macHigher,
                            macLower,
                            ETHERNET_CHANNEL_0);
        Ethernet_clearMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
        Ethernet_setMACConfigurationCustom(Ethernet_device_struct.baseAddresses.enet_base,ETHERNET_MAC_CONFIGURATION_RE);
    }
    //********************IPC******************
    void IPC_ISR0()
    {
        uint32_t command, addr, data;
        //
        // Read the command
        //
        IPC_readCommand(IPC_CM_L_CPU1_R, IPC_FLAG0, IPC_ADDR_CORRECTION_ENABLE,
                        &command, &addr, &data);
    
    
        if(command == IPC_CMD_READ_MEM)
        {
            status = true;
            //
            //Read the buffer address and Length
            //from the IPC message从IPC信息中读取缓存地址和长度
            //
            pktDesc.dataBuffer = (uint8_t *)addr;
            pktDesc.bufferLength = data;
            pktDesc.pktLength = data;
            pktDesc.validLength = data;
            //
            //Send the packet on receiving Message from C28x side
            //
            Ethernet_sendPacket(emac_handle,&pktDesc);
        }
    }
    
    //********************IPC******************
    
    //*****************************************************************************
    //
    // This example demonstrates the use of the Ethernet Controller.
    //
    //*****************************************************************************
    int
    main(void)
    {
        unsigned long ulUser0, ulUser1;
        unsigned char pucMACArray[8];
    
        //
        // User specific IP Address Configuration.
        // Current implementation works with Static IP address only.
        //
        unsigned long IPAddr = 0xC0A80004;
        unsigned long NetMask = 0xFFFFFF00;
        unsigned long GWAddr = 0x00000000;
    
        //
        // Initializing the CM. Loading the required functions to SRAM.
        //
        CM_init();
    
        SYSTICK_setPeriod(systickPeriodValue);
        SYSTICK_enableCounter();
        SYSTICK_registerInterruptHandler(SysTickIntHandler);
        SYSTICK_enableInterrupt();
        //******************************IPC_CM******************************
            Ethernet_InitInterfaceConfig initInterfaceConfig;
            Ethernet_InitConfig *pInitCfg;
            //
            //Select the MII interface of the module
            //选择模块的MII接口
            initInterfaceConfig.ssbase = EMAC_SS_BASE;
            initInterfaceConfig.enet_base = EMAC_BASE;
            initInterfaceConfig.phyMode = ETHERNET_SS_PHY_INTF_SEL_MII;
            //
            //Assign SoC specific functions for Enabling,Disabling interrupts
            //and for enabling the Peripheral at system level
            //分配SoC特定功能以启用,禁用中断以及在系统级别启用外围设备
            initInterfaceConfig.ptrPlatformInterruptDisable = &Platform_disableInterrupt;
            initInterfaceConfig.ptrPlatformInterruptEnable = &Platform_enableInterrupt;
            initInterfaceConfig.ptrPlatformPeripheralEnable = &Platform_enablePeripheral;
            initInterfaceConfig.ptrPlatformPeripheralReset = &Platform_resetPeripheral;
            //
            //Assign the peripheral number at the SoC
            //在SoC上分配外围设备号
            initInterfaceConfig.peripheralNum = SYSCTL_PERIPH_CLK_ENET;
            //
            //Assign the default SoC specific interrupt numbers of Ethernet interrupts
            //分配以太网中断的默认SoC特定中断号
            initInterfaceConfig.interruptNum[0] = INT_EMAC;
            initInterfaceConfig.interruptNum[1] = INT_EMAC_TX0;
            initInterfaceConfig.interruptNum[2] = INT_EMAC_TX1;
            initInterfaceConfig.interruptNum[3] = INT_EMAC_RX0;
            initInterfaceConfig.interruptNum[4] = INT_EMAC_RX1;
    
            pInitCfg = Ethernet_initInterface(initInterfaceConfig);
    
            //
            // Get an initial configuration of known good parameters
            //获取已知良好参数的初始配置
            Ethernet_getInitConfig(pInitCfg);
    
            //
            //Configure the Loopback mode
            //配置环回模式
            pInitCfg->loopbackMode = ETHERNET_MAC_CONFIGURATION_LM_LOOPBACK_DISABLED;        //***********************禁用回环模式**********************
    
            //
            //Assign the callbacks for Getting packet buffer when needed
            //Releasing the TxPacketBuffer on Transmit interrupt callbacks
            //Receive packet callback on Receive packet completion interrupt
            //在需要时分配用于获取数据包缓冲区的回调在发送中断回调上释放TxPacketBuffer在接收数据包完成中断时接收数据包回调
            pInitCfg->pfcbGetPacket = &Ethernet_getPacketBuffer;
            pInitCfg->pfcbFreePacket = &Ethernet_releaseTxPacketBuffer;
            pInitCfg->pfcbRxPacket = &Ethernet_receivePacketCallback;
            //
            //Assign the Buffer to be used by the Low level driver for receiving
            //Packets. This should be accessible by the Ethernet DMA
            //分配要由低级驱动程序用于接收数据包的缓冲区。 这应该可以通过以太网DMA访问
            pInitCfg->rxBuffer = Ethernet_rxBuffer;
    
            //
            //The Application handle is not used by this application
            //Hence using a dummy value of 1
            //此应用程序未使用应用程序句柄,因此使用虚拟值1
            Ethernet_getHandle((Ethernet_Handle)1,pInitCfg , &emac_handle);
    
        //******************************IPC_CM*********************************
    
    
        //
        // Enable processor interrupts.
        //
        Interrupt_enableInProcessor();
            
        // Set user/company specific MAC octets
        // (for this code we are using A8-63-F2-00-00-80)
        // 0x00 MACOCT3 MACOCT2 MACOCT1
        ulUser0 = 0x00F263A8;
    
        // 0x00 MACOCT6 MACOCT5 MACOCT4
        ulUser1 = 0x00800000;
    
        //
        // Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
        // address needed to program the hardware registers, then program the MAC
        // address into the Ethernet Controller registers.
        //
        pucMACArray[0] = ((ulUser0 >>  0) & 0xff);
        pucMACArray[1] = ((ulUser0 >>  8) & 0xff);
        pucMACArray[2] = ((ulUser0 >> 16) & 0xff);
        pucMACArray[3] = ((ulUser1 >>  0) & 0xff);
        pucMACArray[4] = ((ulUser1 >>  8) & 0xff);
        pucMACArray[5] = ((ulUser1 >> 16) & 0xff);
    
        //
        // Initialize ethernet module.
        //
        Ethernet_init(mac_custom);
    
        //
        // Initialze the lwIP library, using DHCP.
        //
        lwIPInit(0, mac_custom, IPAddr, NetMask, GWAddr, IPADDR_USE_STATIC);
    
        //
        // Initialize the HTTP webserver daemon.
        //
        httpd_init();
        //**********************IPC_CM***********************************
            //Assign default ISRs
            //分配默认ISR
            Interrupt_registerHandler(INT_EMAC_TX0, Ethernet_transmitISR);
            Interrupt_registerHandler(INT_EMAC_RX0, Ethernet_receiveISR);
            //
            //Enable the default interrupt handlers
            //启用默认的中断处理程序
            Interrupt_enable(INT_EMAC_TX0);
            Interrupt_enable(INT_EMAC_RX0);
    
            //
            //Prepare a Packet Descriptor structure to send a packet
            //This contains a single buffer packet
            //The Source address shall be inserted by the MAC
            //Packet CRC is auto computed by the module and appended in the packet
            //准备一个数据包描述符结构以发送一个数据包,其中包含一个缓冲数据包
            //源地址应由MAC数据包插入CRC由模块自动计算并附加在数据包中
    
            pktDesc.dataOffset = 0;
            pktDesc.nextPacketDesc = 0;
            pktDesc.flags = ETHERNET_PKT_FLAG_SOP |ETHERNET_PKT_FLAG_EOP|ETHERNET_PKT_FLAG_SA_INS;
            pktDesc.pktChannel = ETHERNET_DMA_CHANNEL_NUM_0;
    
            pktDesc.numPktFrags = 1;
    
            //
            // Clear any IPC flags if set already
            //清除所有IPC标志(如果已设置)
            IPC_clearFlagLtoR(IPC_CM_L_CPU1_R, IPC_FLAG_ALL);
    
            //
            // Enable IPC interrupts
            //启用IPC中断
            IPC_registerInterrupt(IPC_CM_L_CPU1_R, IPC_INT0, IPC_ISR0);
    
            //
            // Synchronize both the cores.
            //同步两个内核。
            IPC_sync(IPC_CM_L_CPU1_R, IPC_FLAG31);
    
            //
            //At this point the C28x core shall send IPC command
            //which triggers the IPC ISR where the packet is sent
            //With internal loopback the packet is looped back
            //Wait for the packet to be received
            //此时,C28x内核将发送IPC命令,该命令将触发IPC ISR,在该IPC ISR上发送数据包。
    
            while(0 == Ethernet_rxInterruptCount);
    
            //
            //The control data to C28x side can be picked up from Ethernet buffer and
            //Passed to Ethernet
            //可以从以太网缓冲区中提取到C28x侧的控制数据,并传递给以太网
            // Send response to C28x core
            //发送响应到C28x内核
            if(status)
            {
                IPC_sendResponse(IPC_CM_L_CPU1_R, TEST_PASS);
            }
            else
            {
                IPC_sendResponse(IPC_CM_L_CPU1_R, TEST_FAIL);
            }
    
            //
            // Acknowledge the flag
            //确认标志
            IPC_ackFlagRtoL(IPC_CM_L_CPU1_R, IPC_FLAG0);
    
            __asm("   bkpt #0");
    
    
        //**********************IPC_CM************************************
        //
        // Loop forever. All the work is done in interrupt handlers.
        //
        while(1);
    }
    
    //*****************************************************************************
    //
    // Called by lwIP Library. Toggles the led when a command is received by the
    // HTTP webserver.
    //
    //*****************************************************************************
    void httpLEDToggle(void)
    {
        //
        // Toggle the LED D1 on the control card.
        //
        GPIO_togglePin(DEVICE_GPIO_PIN_LED1);
    }
    
    
    //*****************************************************************************
    //
    // Called by lwIP Library. Could be used for periodic custom tasks.
    //
    //*****************************************************************************
    void lwIPHostTimerHandler(void)
    {
    
    }
    

    thanks

    vince

  • HI,Yashwant Temburu

    Hello. On my side, I tried to adjust, but I was a little confused, I don't know how to put the data in it and transmit it.

    thanks

    vince

  • When you say it is hitting asm bpkt, isn't that right. Your CM4 is acknowledging to the IPC request and it completes its wait process. 

    You may want to refer to IPC examples C2000Ware_3_04_00_00\driverlib\f2838x\examples\c28x_cm\ipc for better understanding of IPC.

    Also adding IPC expert to the thread. You may want to wait for the IPC experts reply.

    -Yashwant

  • HI,Yashwant Temburu

    Okay, let's not consider the IPC issue.
    I have only one question now. After the data is sent to the CM4 core through the IPC, how does the CM4 core drive the ethernet to send the data to the laptop. At the same time, how can the laptop receive these data and display the data completely.
    This is my only problem. This problem has bothered me for half a month. I hope it can help me solve it.

    thanks

    vince

  • How to communicate data between 2 devices through TCP/IP is a completely independent problem and has nothing to do with the device.

    To start with you can look at the lwIP APIs tcp_output(), tcp_new() in the enet_lwip example. After correctly configuring the Protocol control block with things like remote ip address and device ip address using tcp_new()  you can update the data pointer of pcb with a new pbuf pointing to the required data that you want to send. You can then call tcp_output() passing that pcb as a parameter which will send the data to the network using the f2838x interface layer.

    For the host side in your laptop you could use tools like python socket package to send or receive packets or just wireshark to tap into the network to check if you have data received.

    Your questions are way too general to be able to answer in this forum. Please try to refer to some books on TCP/IP or UDP based communications or some open source solutions.

    Regards,

    Yashwant