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: ETHERNET TRASMIT - RECEIVE ISSUE

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

Hi all,

Our company is working on ethernet module on TMS320f28388d microcontroller. We are trying to use enet lwip module to send and receive the data between the controller and application in pc. For reference following are the steps taken so far in the process: -

Step 1. We have taken two example projects: - Ethernet_c28_config project and enet_lwip project.

Step 2. We first debug cm_common_config file and then the other one.

Step 3. By using cmd window and Hercules.exe tool we were able to ping and establish the connection.

Step 4. The same is also verified by using http webserver.

Step 5. Now we want to send and receive the data, but we don’t know in which buffer we can write or read the data from. Also, we can see some random data coming in watch window in ethernet_rx_buffer.

Step 6. To try out communication we try to use IPC send command in cm_common_config file and tried its communication with ethernet_ipc_ex1_basic_cm, the pass flag variable is raised, confirming that IPC is acknowledging, but we are unable to see any data we have send in both watch window and Hercules app.

Kindly rectify the problem and guide us how to start data transmission between controller and app and which buffers we need to modify, and how to see our data in watch window.

Also tell us , how to do socket programming through enet_lwip.

Thanks & Regards

  • hi,

    I  have  also  tried  to incorporate the tcp  functions given in lwiperf.c file in lwip file without using ipc , There is a arguement  which I  am unable to understand i.e void * arg . Kindly explain which of the two approaches are correct to implement tcp ip stack send and receive through internet & also provide the steps involved

  • Hi, 

    Will take a look at this early next week and respond to you.

    Best Regards

    Siddharth

  • Hi Siddharth , 

    Thankyou  so  much  for replying , so  far we have  tried the  following method:-

    1.testpcb = tcp_new();

    2.err=tcp_bind(testpcb, &src, LocalIPPort);
    3.tcp_arg(testpcb,&data);

    4.tcp_listen_with_backlog(testpcb,0xff);//0xff
    // tcp_accept(testpcb,accept);

    These  steps are followed to  implement  tcp server  in lwip  stack example . We are unable to trace the  second argument passed in tcp_accept .  Kindly guide us how to trace the function and also how to transmit and receive the data further.

  • Hi Udita, 

    The second argument to the tcp_accept is the callback function which gets called when a new connection arrives for a listening TCP PCB.  When an incoming connection is accepted, the function specified with the tcp_accept() function will be called.

    You can take a look at the following link as reference.

    https://github.com/MCUapps/lwip-gnu/blob/master/STM32F4DIS-BB/tcp_echo_server/src/tcp_echoserver.c

    Best Regards

    Siddharth

  • Hi  Siddharth,

    Thankyou for replying ,we are working  on f28388d  module. Will this callback  function work for that as well as server example is  not provided for F28388 microcontroller.

    Thanks &  Regards

  • Hi Siddharth,

    We have tested the tcp echo server functions on F28388D and it is working well , but kindly tell us how to send the data from our side .Right now we are able to send the data from Hercules to server and echo it back to Hercules.

    Thanks & Regards 

  • Hi Udita, 

    What do you mean by send data from our side? Pls clarify.  

    Also, by Hercules do you mean https://www.hw-group.com/software/hercules-setup-utility tool?

    Best Regards

    Siddharth

  • Hi Siddharth , 

    Yes by Hercules we mean the very same utility tool only . 

    We are working as a server and right now , Hercules is sending some data and we are responding by echo , instead of echo we want to respond by the buffer containing our data .Kindly guide us .

    Thanks & Regards

  • Hi Udita, 

    Are you using the tcpEchoF2838X example? If so, you can update the tcpworker function and update the send() commands with its own data buffer. 

    Best Regards

    Siddharth

  • Hi Siddharth  ,

    Actually  , we  are using  enet_lwip.c , we have embed the tcpechoserver example with this and it is working fine to echo the data. Is there anything we can do to share our data instead of echo the received one back

  • Udita, 

    Is it possible for you to share the updated code ? I can take a look at it and let you know the changes that need to be done.

    Best Regards

    Siddharth

  • Hi Siddharth,

    Kindly find the updated code.

    //###########################################################################
    //
    // 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"
    #define lwiperf_report_type LWIPERF_TCP_DONE_SERVER
    #define Port 5001
    #define LWIP_CALLBACK_API               1
    //#define  TCP_LISTEN_BACKLOG 1
    void tcp_echoserver_init(void);
    //void tcp_echoserver_send(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es);
    struct tcp_pcb *tcp_echoserver_pcb;
    int LocalIPPort=Port;
    int ServerPort ;
    int err,pcb,ret_val;
    
    
    
    #include "driverlib_cm/ethernet.h"
    #include "driverlib_cm/gpio.h"
    #include "driverlib_cm/interrupt.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 unsigned long RamfuncsLoadStart;
    extern unsigned long RamfuncsLoadSize;
    extern unsigned long RamfuncsRunStart;
    ip4_addr_t src;
    //*****************************************************************************
    //
    // Driver specific initialization code and macro.
    //
    //*****************************************************************************
    #define ETHERNET_NO_OF_RX_PACKETS   8U
    #define ETHERNET_MAX_PACKET_LENGTH 500
    #define NUM_PACKET_DESC_RX_APPLICATION 8
    
    Ethernet_Handle emac_handle;
    Ethernet_InitConfig *pInitCfg;
    uint32_t Ethernet_numRxCallbackCustom = 0;
    uint32_t releaseTxCount = 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];
    
    extern Ethernet_Pkt_Desc*
    lwIPEthernetIntHandler(Ethernet_Pkt_Desc *pPacket);
    
    //*****************************************************************************
    //
    // 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);
    }
    
    
    //callback function for accept
    
    
    //*****************************************************************************
    //
    //  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
    }
    
    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.eqos_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_getPacketBufferCustom;
        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);
    
        //
        //Do global Interrupt Enable
        //
        (void)Interrupt_enableInProcessor();
    
        //
        //Assign default ISRs
        //
        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);
    
        //
        // 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);
    }
    
    void acceptcallback(void)
    {
        //tcprecved();
    }
    
    //*****************************************************************************
    //
    // This example demonstrates the use of the Ethernet Controller.
    //
    //*****************************************************************************
    int
    main(void)
    {//buffer->arr[0]=50;
        unsigned long ulUser0, ulUser1;
        unsigned char pucMACArray[8];
        //uint32_t data=0xdeadbeef;
    
        src.addr=IP4_ADDR(&src,4,0,168,192);
        //
        // 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;
    
        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(pucMACArray);
    
        //
        // Initialze the lwIP library, using DHCP.
        //
        lwIPInit(0, pucMACArray, IPAddr, NetMask, GWAddr, IPADDR_USE_STATIC);
    
        //
        // Initialize the HTTP webserver daemon.Da
        //
        //httpd_init();
    
        tcp_echoserver_init();
    
        //tcp_echoserver_send(tcp_echoserver_pcb,buffer);
    
        //testpcb = tcp_new();
    
        // err=tcp_bind(testpcb, &src, LocalIPPort);
       //tcp_arg(testpcb,&data);
    
        //tcp_listen_with_backlog(testpcb,0xff);//0xff
        //tcp_echoserver_accept(NULL,testpcb,err);
    
    
        //void *lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void *report_arg);
    
       // lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
       // lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
       // err_t  lwiperf_tx_start_impl(const ip_addr_t *remote_ip, u16_t remote_port, lwiperf_settings_t *settings, lwiperf_report_fn report_fn,
                              ///void *report_arg, lwiperf_state_base_t *related_master_state, lwiperf_state_tcp_t **new_conn);
    
    
        //
        // 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)
    {
    
    }
    

  • Udita, 

    You can refer to the file C:\ti\c2000\C2000Ware_3_04_00_00\libraries\communications\Ethernet\third_party\lwip\lwip-2.1.2\src\core\tcp.c , it mentions the functions for setting up the TCP connection, sending and receiving TCP data. 

    You will have to create a TCP PCB and implement the callback functions to  send the data using the tcp_write and tcp_send functions.

    I will try to create such and example and share with you.

    Best Regards

    Siddharth

  • Hi Siddharth,

    Thankyou so much for replying . We have sort out that issue and now we can send and receive via  tcp  ip  server  .  The  new  issue we are  facing is we want to build an independent application and we are unable to copy enet_lwip  project in any other workspace . We have to import it every time and make required changes . Kindly look into the issue.

    Thanks & Regards

  • Udita, 

    Glad that you got it working. 

    By independent application , do you mean that you want to create a new CCS project that can be shared and built without any changes?

    If so, you can refer the following link

    https://software-dl.ti.com/ccs/esd/documents/ccs_sharing-projects.html

    Let me know if you have any other queries related to it.

    Best Regards

    Siddharth