This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28388D: C2000 microcontrollers forum

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

Hi,

I want to implement Ethernet loopback between Laptop and TMS320F28388D.
I would like to know how to start to realize this.
The board is ready, and the PHY device is DP83822I.

For reference, here's what I've tried so far.

1.Connect the PC and the board with LAN cable. supply power to the MS320F28388D and DP83822I.
At this time, LED_1 of PHY device is ON.

2. Load ethernet_c28x_config.out to CPU1.

3. Load ethernet_ex2_phy_loopback.out to M4.

4.Set CPU1 to Run. At this time, LED_0 of the PHY device changes from OFF to ON, and LED_1 changes from ON to OFF. laptop recognizes Ethernet.

5.Set M4 to Run. At this time, LED_0 changes from OFF to ON, and the PC no longer recognizes the Ethernet. LED_1 is still OFF.

(I don't know why the Ethernet is not recognized after running M4.)

  • Hi,

    The ethernet_ex2_phy_loopback is an internal loopback example in which the packets are transmitted by the device and the phy loops it back to f28388d.

    In order to communicate with your laptop you can use TCP/IP stack based examples such as enet_lwip.

    You can find the project here <C2000Ware>\libraries\communications\Ethernet\third_party\lwip\examples\enet_lwip\cm\

    You can follow the steps in the readme.txt in the project to get started. 

    By this use you should be able to ping the device from your host pc (given all the network configurations like ip address are set properly which are given in readme.txt).

    Reards,

    Yashwant

  • HI, 

    Using the routine you mentioned, can the data in 28388D be sent to the laptop through the ethernet port? Has there been a successful case?

  • Yes, the example is meant for that. Go through the reader.txt to understand what data is sent through web server application.

    Regards,

    Yashwant

  • HI,Yashwant Temburu1

    The reader.txt did not explain clearly how to proceed on CCS10.0.

    My current operation is to burn the enet_lwip project directly into 28388D, and then set the computer's IP to: 192.168.0.5. Then use a network cable to connect to J4 of TMDSCNCD28388D and the network port of the computer. Next, on the computer, ping 192.168.0.4 under cmd, and the message returned is that the target host cannot be accessed.

    Is there any problem with my operation?

    thanks!

    vince

  • HI,Yashwant Temburu1

    In CCS, I first debug ethernet_c28x_config.out into CPU1, then load enet_lwip into CM4, and then click to run CPU1 and CM4 respectively. After that, the IP of the computer was changed to: 192.168.0.5. Connect J4 to the computer's network port with a network cable. Then, under cmd, ping 1922.168.0.4 to get the effect shown in the figure below. This result is correct, right? But how to operate so that the data in the development board can be sent to the computer, and the data can be seen in real time on the computer?

    This picture can already show that the sender device can see the ping reply from the IP address of the f2838x device, right?

    thanks

    vince

  • HI, 

    I would like to ask, the next purpose is to send the data of the CPU1 core of the development board to the computer through the ethernet port.

    The next task is to change the program in the enet_lwip.c file. Also under the ethernet_c28x_config project, modify the pins corresponding to ethernet.

    After completing the above operations, it should be possible to send the data of the development board from the cpu1 core to the CM4 core, and then send it to the computer through the ethernet port, so as to realize the real-time changes of the data on the computer side, right?

    But in this case, IPC issues are involved, so the routine should be changed.
    Replace with: C:\ti\c2000\C2000Ware_3_04_00_00\driverlib\f2838x\examples\c28x_cm\ethernet

    Then under the ethernet_ipc_ex1_basic_cm.c routine, modify the code to realize that the data of the development board (in the CPU1 core) is sent to the computer for display.

    The model of the development board used is: TMDSCNCD28388D.

    thanks!

    vince

  • Vince,

    By your previous message we can confirm that the connection between your host pc and f28388d was successfully setup as there was ping reply.

    Now if you open a browser and load 192.168.0.4 you should be able to see data on the browser.

    It is difficult to modify C:\ti\c2000\C2000Ware_3_04_00_00\driverlib\f2838x\examples\c28x_cm\ethernet\ethernet_ipc_ex1_basic_cm.c to support data transfer between laptop and f28388d as communication would require tcp/ip stack.

    I would suggest you to modify the enet_lwip example to include IPC and modify the webserver html files at C2000Ware_3_04_00_00\libraries\communications\Ethernet\third_party\lwip\lwip-2.1.2\src\apps\http\fs\fs to transfer required element data.

    You can also refer to https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/952362/tms320f28388d-how-to-change-html-file-for-lwip-example/3519732?tisearch=e2e-sitesearch&keymatch=lwip%2520http%2520files#3519732 on how to update http files.

    Regards,

    Yashwant

  • Yes, enter the IP on the web page, the interface is as above.

  • HI, 

    You mean, let me add the IPC code in the enet_lwip example, and then go to the following path: C2000Ware_3_04_00_00 \ libraries \ communications \ Ethernet \ third_party \ lwip \ lwip-2.1.2 \ src \ apps \ http \ fs \ fs , Change the html file of the web server.

    Add the IPC code in the enet_lwip example, the source of the IPC code, is it from the file in the following path:
    C: \ ti \ c2000 \ C2000Ware_3_04_00_00 \ driverlib \ f2838x \ examples \ c28x_cm \ ethernet \ ethernet_ipc_ex1_basic_cm.c

    Regarding the modification of the html file, a link given by the engineer of the English forum, the modification inside is really incomprehensible, please tell me more about it.

    thanks

    vince

  • Vince,

    You mean, let me add the IPC code in the enet_lwip example, and then go to the following path: C2000Ware_3_04_00_00 \ libraries \ communications \ Ethernet \ third_party \ lwip \ lwip-2.1.2 \ src \ apps \ http \ fs \ fs , Change the html file of the web server.

    You are right that is what i meant. 

    Regarding html file updates you may want to spend some time understanding the data flow of the enet_lwip example starting from how the intermediate stack data are handled by lwip and sent to the upper layers. lwip is an open source stack so we wont be able to help much on how to use the stack.

    You can try finding lwip support on some opensource forums online.

    Regards,

    Yashwant

  • Hi

    Sorry for the late reply.

    I was able to send and receive packet using ping.

    My final purpose is to change the value of a variable in the DSP from the laptop.
    Can you tell me how to that?
    As for the user interface, you can create it yourself.
    thank you
  • We are looking into this and will get back to you in a day or so.

    Thanks,

    Yashwant

  • Thank you.
    I am waiting for your reply.

    For your information, the data transfer protocol is UDP.

  • My final purpose is to change the value of a variable in the DSP from the laptop.

    This is possible using the existing http_webserver enet_lwip example by following changes.

    As mentioned in my previous post the html, javascript files that are displayed on the host side are at location C2000Ware_3_04_00_00\libraries\communications\Ethernet\third_party\lwip\lwip-2.1.2\src\apps\http\fs\fs.

    In the index.html get_data() method is called when the button is pressed. This is defined in the javascript.js where the line req.open("GET", "/param?id=" + Math.random(), true);  is used to access the variable from the device memory.

    The device side code which is responding to the request is at C2000Ware_3_04_00_00\libraries\communications\Ethernet\third_party\lwip\lwip-2.1.2\src\apps\http\fs.c  . In fs.c at line 82 usnprintf(pcBuf, 10, "%d", httpHit); is transmitting the variable value "httpHit" to the host.

    Similarly you can add a custom function send_data() like get_data() and use req.open("PUT") type method to send a new value to the device.

    Regards,

    Yashwant

  • 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

  • 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 addres

    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

  • Dear  Yashwant Temburu1

    I have 2 questions.

    1.  What does second program parameter mean in req.open ("GET", "/ param?id =" + Math.random(), true) ?

         It seems to point to a location, if so where is it?

    2.I have checked the two examples in \ driverlib \ f2838x \ examples \ c28x_cm \ ethernet).

      What you have written here seems to be a one-way data exchange from C28 to CM, is that correct?

      If so, is there a code somewhere that shows the exchange of data from the CM to the C28?

    Thank you

    - Matsu

  • What does second program parameter mean in req.open ("GET", "/ param?id =" + Math.random(), true) ?

         It seems to point to a location, if so where is it

    /param is the key to message object to be read from the device side application. It is used in line 79 of the file fs.c at wip-2.1.2\src\apps\http\fs.c.

    You could use a different key to read a different variable form the device memory. 

    Below is a comment in fs.c for your reference

    /*
    * This is a placeholder where custom functions can be executed based on the
    * params received in the url from the http client.
    */

    If so, is there a code somewhere that shows the exchange of data from the CM to the C28

    There is a similar IPC_sendCommand() api for the CM driverlib. 

    Go through the IPC examples at C2000Ware_3_04_00_00\driverlib\f2838x\examples\c28x_cm\ipc for more understanding.

    Regards,

    Yashwant

  • HI,

    On your side, have you been able to communicate with the computer through the ethernet on the 28388D?

    If it is convenient, I would like to ask.

    e2e.ti.com/.../3706211

    thanks

    vince

  • Hi  vince

    I have been able to confirm sending and receiving using Ping.
    However, I haven't been able to do anything else yet.

    Thank you

    -Matsu

  • HI,Matsu

    I can currently implement IPC inter-core communication. I am thinking about how to send data to the Ethernet chip.

    If it is convenient, we can add contact information and exchange it.

    thanks

    vince

  • Dear  Yashwant

    I used the user interface here to send the data to the device side.
    I checked using the wire shark and it seems to be transmitting.
    Which register should I refer to check this data on the device side?

    * Sorry, I want to use my user interface to send and receive data, so I am not using html.

    //#############################################################################
    //
    // 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.
    //!
    //
    //#############################################################################
    // $TI Release: F2838x Support Library v2.00.00.02 $
    // $Release Date: Mon May 27 06:55:11 CDT 2019 $
    // $Copyright:
    // Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //#############################################################################
    
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    
    void main(void)
    {
    
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pull-ups.
        //
        Device_initGPIO();
    
    #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_121_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_120_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(107, GPIO_DIR_MODE_OUT); //  119->107
        GPIO_setPadConfig(107, GPIO_PIN_TYPE_PULLUP);  //  119->107
        GPIO_writePin(107,1);                          //  119->107
    #endif
    
    #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_setMasterCore(85, GPIO_CORE_CPU1);
        GPIO_setPinConfig(GPIO_85_CMUARTRXA);
        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_setMasterCore(84, GPIO_CORE_CPU1);
        GPIO_setPinConfig(GPIO_84_CMUARTTXA);
        GPIO_setDirectionMode(84, GPIO_DIR_MODE_OUT);
        GPIO_setPadConfig(84, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(84, GPIO_QUAL_ASYNC);
    #endif
    
    #ifdef USB
    
        //
        // Set the clocking to run from the PLL at 60MHz
        //
        SysCtl_setAuxClock(SYSCTL_AUXPLL_OSCSRC_XTAL |
                           SYSCTL_AUXPLL_IMULT(24) |
                           SYSCTL_REFDIV(2U) | SYSCTL_ODIV(4U) |
                           SYSCTL_AUXPLL_DIV_1 |
                           SYSCTL_AUXPLL_ENABLE |
                           SYSCTL_DCC_BASE_0);
    
        //
        // 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_setPinConfig(GPIO_120_USB0PFLT);
    
        //
        // Configure the External Power Signal Enable.
        //
        GPIO_setPinConfig(GPIO_121_USB0EPEN);
    
        //
        // Set the CM Clock.
        //
        SysCtl_setCMClk(SYSCTL_CMCLKOUT_DIV_2, SYSCTL_SOURCE_AUXPLL);
    #endif
    }
    


  • Hi Matsu,

    You can read the following global variable - Ethernet_rxBuffer in the expression window or memory browser which stores the complete received packet from the MAC.

    Regards,

    Yashwant

  • Hi Yashwant 

    Found it.
    Thank you for your support.

    thank you 

    -Matsu

  • Dear Yashwant

    I have question about Ethernet_rxBuffer.

    I sent 52 bytes of data and checked the array and it seems to be sending the correct values.
    However, the values after the 52nd array have also changed.
    Is this correct?

    I don't know much about communication.
    Please give me some advice.

     

    Thank you

    -Matsu

  • They could be CRC checksum bytes or updated by the transmit side code.  

    We cant comment much without your setup knowledge.

  • If you use the ping command, the values of up to the 255th element will also change. After the 256th element, the value remains 0.

    The code used is enet_lwip and ethernet_c28_config.

    I did not make any drastic changes to the code.
    I just changed the pin number of ethenet_c28_config to match the device.

    Can you tell me why this is happening?

  • The ping command also sends some payload on top of ICMP header which the device has to reply with the same payload.

    So that payload which is just series of number or alphabets could be that long.

    -Yashwant

  • Hi Yashwant 

    I was able to confirm that the data sent from the laptop is written to rxbuffur, but after a few seconds it changes to other values. Is this the correct behavior? I have not sent any data after confirming that it is written.

  • Hi Matsu,

    There could be other packets on the same network like ARP, DHCP request packets which may not be sent by your ping command which could be received by the device and so the Ethernet_rxBuffer is getting changed.

    Can you paste the wireshark log of the network when you send 1 ping and the data is overwritten.  We can confirm if whether device is overwriting or something else.

    -Yashwant

  • Hi Yashwant

    I send you the wireshark results when we run the ping command.

    At the timing of wireshark No. 8 or 9, the value of rx_buffer was rewritten as shown in the capture.

    Please let me know if there is any further information you need.

    After_ping.zip

    Thank you

    -Matsu

  • I see there are other broadcast packets(.255) in your wireshark log which are also captured/read by the deivce. So based on ETHERNET_NO_OF_RX_PACKETS  value in the code, after every that may number of packets, that memory location is going to get updated. 

    You can increase the interpacket delay in your software so that you can process those packets before rewrite.

    Regards,

    Yashwant

  • Can you tell me what are changes need to do for the change interpacket delay?

    The code are enet_lwip and ethernet_c28_config.
  • Can you tell me what are changes need to do for the change interpacket delay?

    This has to be done in the transmit side which is the software that you are using. There should some setting to change the delay.

    -Yashwant

  • There are other broadcast packets (.255) in wireshark as you mentioned.
    However, the IP address of the device is (192.168.0.4).

    Is this the correct behavior for the packet to be rewritten?

    -Matsu

  • The English may be difficult to understand, so I will supplement it.


    Is it the correct behavior to capture packets for the destination (.255)?
    Is there any way to prevent the capture?

    -Matsu

  • .255 is a broadcast address, so every device on the sub network will receive the packet. 

    Yes it is correct behaviour.

  • Thank you for reply

    I have two questions.


    1. I was able to stop the NBNS broadcast packets by changing the settings on my laptop.
    However, UDP broadcast packets are still being sent. Can you tell me the cause?


    2. There is an array element whose value does not change no matter how many times I send data from my laptop as shown below.
    For example, I think the first 6 bytes are the dst address, but the value does not change. Can you tell me the cause?

    This is also the case when using ping.

  • I have two questions, but you may reply to the one you can answer first.

    -Matsu

  • Hi Yashwant

    I would like to add a supplement to No.2 above.
    If you use C2000Ware_3_04_00_00, the value of rx_buffer will be updated correctly.

    However, if you use C2000Ware_2_00_00_02, the value of rx_buffer will not be updated or will change to a value that is not displayed by wireshark.

    Since we are using C2000Ware_2_00_00_02 to create software for all parts except Ethernet, we would like to implement Ethernet communication using C2000Ware_2_00_00_02 if possible.

    Do you know why the results are different when using C2000Ware_3_04_00_00 and when using C2000Ware_2_00_00_02?

    Also, in the past I reported to you that the value of rx_Buffer was updated correctly, but this time I was using C2000Ware_2_00_00_02. I am not sure why it did not work. Does this happen when you make an unintended change?

    -Matsu

  • There are some updated to the example and the low level driver for C2000Ware_3_04_00_00 Ethernet module. This is more stable when the device is attacked with multiple packets with less interpacket delay. 

    I would recommend you to use v3.4 instead of v3.2.

    Regards,

    Yashwant

  • Hi Yashwant

    I know that it has been updated.
    I am wondering if v3.4 has completed the communication.
    Is it safe to assume that there will be no significant changes in the future?

    -Matsu

  • There are few small updates to v3.4 as well. I have attached the updated files that will be released for next release. In our tests we have verified its use case but cannot guarantee that it is complete. 

    But there wont be any significant changes to v3.4

    //###########################################################################
    //
    // 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)
    {
    
    }
    
    //###########################################################################
    //
    // 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);
    }
    
    8712.ethernet.c5751.ethernet.h

    Regards,

    Yashwant

  • Hi Yashwant

    Thank you for sharing information.

    We have some concerns, but we have made progress on data transmission from laptop to CM.
    The next step is to send data from the CM to the laptop.
    Can you give me some code to refer to and functions to use?

    -Matsu

  • Hi

    Would anyone be willing to respond to my request?

    -Matsu

  • There are multiple ways to transfer data from CM (using HTTP, UDP socket, just TCP payload). Make sure that data to be transmitted has correct headers like the ip address, protocols flags for the laptop to be able to receive and creation connection.

    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.

    We dont have exact example that you are looking for but in the below reply i hinted a way to update the http variables to transfer that data.

    This is possible using the existing http_webserver enet_lwip example by following changes.

    As mentioned in my previous post the html, javascript files that are displayed on the host side are at location C2000Ware_3_04_00_00\libraries\communications\Ethernet\third_party\lwip\lwip-2.1.2\src\apps\http\fs\fs.

    In the index.html get_data() method is called when the button is pressed. This is defined in the javascript.js where the line req.open("GET", "/param?id=" + Math.random(), true);  is used to access the variable from the device memory.

    The device side code which is responding to the request is at C2000Ware_3_04_00_00\libraries\communications\Ethernet\third_party\lwip\lwip-2.1.2\src\apps\http\fs.c  . In fs.c at line 82 usnprintf(pcBuf, 10, "%d", httpHit); is transmitting the variable value "httpHit" to the host.

    Similarly you can add a custom function send_data() like get_data() and use req.open("PUT") type method to send a new value to the device.

    Regards,

    Yashwant

  • Hi Yashwant

    Thank you for response.  

    Transfer way is Udp socket. 

    Is there any documentation on TCP_output or TCP_new that might be helpful?

    I find it quite difficult to understand them from the code.

     -Matsu

  • You can find the documentation for lwIP stack in the official lwIP site. https://www.nongnu.org/lwip/2_1_x/index.html

    Thanks,

    Yashwant