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.

CCS/TM4C129XNCZAD: TM4C129XNCZAD TIVA UDP example

Part Number: TM4C129XNCZAD

Tool/software: Code Composer Studio

I am having a similar problem using static IP.  My computer IP is 192.168.101.11 and the DK board is 192.168.101.10.  I am able to ping 192.168.101.10 from my computer but I can't get the UDP to output.

//*****************************************************************************

//

// This example demonstrates the use of the Ethernet Controller.

//

//*****************************************************************************

main(void)

{

uint32_t ui32User0, ui32User1;

uint8_t pui8MACArray[8];

struct ip_addr ipAddr;

struct ip_addr ipAddr2;

struct ip_addr subnet;

struct ip_addr gateway;

char errorFlag;

struct udp_pcb *UDPSock;

ipAddr.addr = (192u << 24) | (168u << 16) | (101u << 8) | 10u;

ipAddr2.addr = (192u << 24) | (168u << 16) | (101u << 8) | 11u;

subnet.addr = (255u << 24) | (255u << 16) | (255u << 8) | 0;

// gateway = (192u << 24) | (168u << 16) | (0u << 8) | 1;

// IP4_ADDR(&ipAddr, 192, 168, 101, 10);

// IP4_ADDR(&subnet, 255, 255, 255, 0);

IP4_ADDR(&gateway, 0, 0, 0, 0);

 

//

// Run from the PLL at 120 MHz.

//

g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |

SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |

SYSCTL_CFG_VCO_480), 120000000);

//

// Configure the device pins.

//

PinoutSet();

//

// Initialize the display driver.

//

Kentec320x240x16_SSD2119Init(g_ui32SysClock);

//

// Initialize the graphics context.

//

GrContextInit(&g_sContext, &g_sKentec320x240x16_SSD2119);

//

// Draw the application frame.

//

FrameDraw(&g_sContext, "enet-static");

//

// Configure SysTick for a periodic interrupt.

//

ROM_SysTickPeriodSet(g_ui32SysClock / SYSTICKHZ);

ROM_SysTickEnable();

ROM_SysTickIntEnable();

//

// Initialize the file system.

//

fs_init();

//

// Configure the hardware MAC address for Ethernet Controller filtering of

// incoming packets. The MAC address will be stored in the non-volatile

// USER0 and USER1 registers.

//

ROM_FlashUserGet(&ui32User0, &ui32User1);

if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))

{

//

// We should never get here. This is an error if the MAC address has

// not been programmed into the device. Exit the program.

//

GrContextForegroundSet(&g_sContext, ClrRed);

GrStringDrawCentered(&g_sContext, "MAC Address", -1,

GrContextDpyWidthGet(&g_sContext) / 2,

(GrContextDpyHeightGet(&g_sContext) / 2) - 4,

false);

GrStringDrawCentered(&g_sContext, "Not Programmed!", -1,

GrContextDpyWidthGet(&g_sContext) / 2,

(GrContextDpyHeightGet(&g_sContext) / 2) + 16,

false);

while(1)

{

}

}

//

// 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.

//

pui8MACArray[0] = ((ui32User0 >> 0) & 0xff);

pui8MACArray[1] = ((ui32User0 >> 8) & 0xff);

pui8MACArray[2] = ((ui32User0 >> 16) & 0xff);

pui8MACArray[3] = ((ui32User1 >> 0) & 0xff);

pui8MACArray[4] = ((ui32User1 >> 8) & 0xff);

pui8MACArray[5] = ((ui32User1 >> 16) & 0xff);

//

// Initialze the lwIP library, using DHCP.

//

lwIPInit(g_ui32SysClock, pui8MACArray, ipAddr.addr, subnet.addr, gateway.addr, IPADDR_USE_STATIC);

UDPSock = udp_new();

udp_recv(UDPSock, NULL, NULL);

errorFlag = udp_bind(UDPSock, &ipAddr, 7070);

if (errorFlag)

errorFlag = 0;

// errorFlag = udp_connect(UDPSock, IP_ADDR_ANY, 7070);

// if (errorFlag)

// errorFlag = 0;

char buf[500] = "HELLO KITTY";

struct pbuf *p = 0;

//struct ip_addr server;

// IP4_ADDR(&server, 192, 168, 253, 236);

//

//

// Setup the device locator service.

//

//LocatorInit();

//LocatorMACAddrSet(pui8MACArray);

//LocatorAppTitleSet("DK-TM4C129X enet_lwip");

//

// Initialize the sample httpd server.

//

//httpd_init();

//

// Set the interrupt priorities. We set the SysTick interrupt to a higher

// priority than the Ethernet interrupt to ensure that the file system

// tick is processed if SysTick occurs while the Ethernet handler is being

// processed. This is very likely since all the TCP/IP and HTTP work is

// done in the context of the Ethernet interrupt.

//

ROM_IntPrioritySet(INT_EMAC0, ETHERNET_INT_PRIORITY);

ROM_IntPrioritySet(FAULT_SYSTICK, SYSTICK_INT_PRIORITY);

uint32_t ui32Loop;

//

// Loop forever. All the work is done in interrupt handlers.

//

while(1)

{

p=pbuf_alloc(PBUF_TRANSPORT, 500, PBUF_RAM);

memcpy(p->payload, buf, 500);

errorFlag = udp_sendto(UDPSock,p, &ipAddr2, 7070);

if (errorFlag)

errorFlag = 0;

pbuf_free(p);

for(ui32Loop = 0; ui32Loop < 2000000; ui32Loop++)

{}

}

}

  • Hi Robert,

     Can you try this udp_echo example?

    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/flash.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/gpio.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "utils/lwiplib.h"
    #include "utils/ustdlib.h"
    #include "utils/uartstdio.h"
    #include "drivers/pinout.h"
    #include "lwip/udp.h"
    
    
    
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>Ethernet with lwIP (enet_lwip)</h1>
    //!
    //! This example application demonstrates the operation of the Tiva
    //! Ethernet controller using the lwIP TCP/IP Stack.  DHCP is used to obtain
    //! an Ethernet address.  If DHCP times out without obtaining an address,
    //! AutoIP will be used to obtain a link-local address.  The address that is
    //! selected will be shown on the UART.
    //!
    //! UART0, connected to the ICDI virtual COM port and running at 115,200,
    //! 8-N-1, is used to display messages from this application. Use the
    //! following command to re-build the any file system files that change.
    //!
    //!     ../../../../tools/bin/makefsfile -i fs -o enet_fsdata.h -r -h -q
    //!
    //! For additional details on lwIP, refer to the lwIP web page at:
    //! savannah.nongnu.org/.../
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Defines for setting up the system clock.
    //
    //*****************************************************************************
    #define SYSTICKHZ               100
    #define SYSTICKMS               (1000 / SYSTICKHZ)
    
    //*****************************************************************************
    //
    // Interrupt priority definitions.  The top 3 bits of these values are
    // significant with lower values indicating higher priority interrupts.
    //
    //*****************************************************************************
    #define SYSTICK_INT_PRIORITY    0x80
    #define ETHERNET_INT_PRIORITY   0xC0
    
    //*****************************************************************************
    //
    // The current IP address.
    //
    //*****************************************************************************
    uint32_t g_ui32IPAddress;
    
    //*****************************************************************************
    //
    // The system clock frequency.
    //
    //*****************************************************************************
    uint32_t g_ui32SysClock;
    
    //*****************************************************************************
    //
    // Volatile global flag to manage LED blinking, since it is used in interrupt
    // and main application.  The LED blinks at the rate of SYSTICKHZ.
    //
    //*****************************************************************************
    volatile bool g_bLED;
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    
    void udp_echo_init( void );
    
    //*****************************************************************************
    //
    // Display an lwIP type IP Address.
    //
    //*****************************************************************************
    void
    DisplayIPAddress(uint32_t ui32Addr)
    {
        char pcBuf[16];
    
        //
        // Convert the IP Address into a string.
        //
        usprintf(pcBuf, "%d.%d.%d.%d", ui32Addr & 0xff, (ui32Addr >> 8) & 0xff,
                (ui32Addr >> 16) & 0xff, (ui32Addr >> 24) & 0xff);
    
        //
        // Display the string.
        //
        UARTprintf(pcBuf);
    }
    
    //*****************************************************************************
    //
    // Required by lwIP library to support any host-related timer functions.
    //
    //*****************************************************************************
    void
    lwIPHostTimerHandler(void)
    {
        uint32_t ui32NewIPAddress;
    
        //
        // Get the current IP address.
        //
        ui32NewIPAddress = lwIPLocalIPAddrGet();
    
        //
        // See if the IP address has changed.
        //
        if(ui32NewIPAddress != g_ui32IPAddress)
        {
            //
            // See if there is an IP address assigned.
            //
            if(ui32NewIPAddress == 0xffffffff)
            {
                //
                // Indicate that there is no link.
                //
                UARTprintf("Waiting for link.\n");
            }
            else if(ui32NewIPAddress == 0)
            {
                //
                // There is no IP address, so indicate that the DHCP process is
                // running.
                //
                UARTprintf("Waiting for IP address.\n");
            }
            else
            {
                //
                // Display the new IP address.
                //
                UARTprintf("IP Address: ");
                DisplayIPAddress(ui32NewIPAddress);
                UARTprintf("\nEcho Server is ready.\n");
            }
    
            //
            // Save the new IP address.
            //
            g_ui32IPAddress = ui32NewIPAddress;
        }
    
        //
        // If there is not an IP address.
        //
        if((ui32NewIPAddress == 0) || (ui32NewIPAddress == 0xffffffff))
        {
            //
            // Do nothing and keep waiting.
            //
        }
    }
    
    //*****************************************************************************
    //
    // The interrupt handler for the SysTick interrupt.
    //
    //*****************************************************************************
    void
    SysTickIntHandler(void)
    {
        //
        // Call the lwIP timer handler.
        //
        lwIPTimer(SYSTICKMS);
    
        //
        // Tell the application to change the state of the LED (in other words
        // blink).
        //
        g_bLED = true;
    }
    
    //*****************************************************************************
    //
    // This example demonstrates the use of the Ethernet Controller.
    //
    //*****************************************************************************
    int
    main(void)
    {
        uint32_t ui32User0, ui32User1;
        uint8_t pui8MACArray[8];
    
        //
        // Make sure the main oscillator is enabled because this is required by
        // the PHY.  The system must have a 25MHz crystal attached to the OSC
        // pins. The SYSCTL_MOSC_HIGHFREQ parameter is used when the crystal
        // frequency is 10MHz or higher.
        //
        SysCtlMOSCConfigSet(SYSCTL_MOSC_HIGHFREQ);
    
        //
        // Run from the PLL at 120 MHz.
        //
        g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                                 SYSCTL_OSC_MAIN |
                                                 SYSCTL_USE_PLL |
                                                 SYSCTL_CFG_VCO_480), 120000000);
    
        //
        // Configure the device pins.
        //
        //*****************************************************************************
        //
        //! Configures the device pins for the standard usages on the EK-TM4C1294XL.
        //!
        //! \param bEthernet is a boolean used to determine function of Ethernet pins.
        //! If true Ethernet pins are  configured as Ethernet LEDs.  If false GPIO are
        //! available for application use.
        //! \param bUSB is a boolean used to determine function of USB pins. If true USB
        //! pins are configured for USB use.  If false then USB pins are available for
        //! application use as GPIO.
        //
        //*****************************************************************************
        //    void
        // PinoutSet(bool bEthernet, bool bUSB)
        PinoutSet(true, false);
    
        //
        // Configure UART.
        //
        UARTStdioConfig(0, 115200, g_ui32SysClock);
    
        //
        // Clear the terminal and print banner.
        //
        UARTprintf("\033[2J\033[H");
        UARTprintf("Ethernet lwIP udp echo example\n\n");
    
        //
        // Configure Port N1 for as an output for the animation LED.
        //
        MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);
    
        //
        // Initialize LED to OFF (0)
        //
        MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, ~GPIO_PIN_1);
    
        //
        // Configure SysTick for a periodic interrupt.
        //
        MAP_SysTickPeriodSet(g_ui32SysClock / SYSTICKHZ);
        MAP_SysTickEnable();
        MAP_SysTickIntEnable();
    
        //
        // Configure the hardware MAC address for Ethernet Controller filtering of
        // incoming packets.  The MAC address will be stored in the non-volatile
        // USER0 and USER1 registers.
        //
        MAP_FlashUserGet(&ui32User0, &ui32User1);
        if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
        {
            //
            // We should never get here.  This is an error if the MAC address has
            // not been programmed into the device.  Exit the program.
            // Let the user know there is no MAC address
            //
            UARTprintf("No MAC programmed!\n");
            while(1)
            {
            }
        }
    
        //
        // Tell the user what we are doing just now.
        //
        UARTprintf("Waiting for IP.\n");
    
        //
        // 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.
        //
        pui8MACArray[0] = ((ui32User0 >>  0) & 0xff);
        pui8MACArray[1] = ((ui32User0 >>  8) & 0xff);
        pui8MACArray[2] = ((ui32User0 >> 16) & 0xff);
        pui8MACArray[3] = ((ui32User1 >>  0) & 0xff);
        pui8MACArray[4] = ((ui32User1 >>  8) & 0xff);
        pui8MACArray[5] = ((ui32User1 >> 16) & 0xff);
    
        //
        // Initialize the lwIP library, using DHCP.
        //
        
        lwIPInit(g_ui32SysClock, pui8MACArray, 0, 0, 0, IPADDR_USE_DHCP);
    
    
    
        //
        // Initialize the echo server.
        //Run the udpSendReceive Linux or Windows executable that is shipped with TI-RTOS.
        //The executable is found in:
    
          //<tirtos_install_dir>\packages\examples\tools\udpSendReceive
    
          //Usage: ./udpSendReceive <IP-addr> <port> <id> -l[length] -s[sleep in uS]
    
          //<IP-addr> is the IP address
          //<port>    is the UDP port being listened to (23)
          //<id>      is a unique id for the executable. Printed out when 1000 packets are
          //          transmitted. It allows the user to run multiple instances
          //          of udpSendReceive.
    
          //Optional:
          //  -l[length]      size of the packet in bytes. Default is 1024 bytes.
          //  -s[sleep in uS] usleep time to between sends. Default is 1000 uSecs.
    
          //Example:
          //      udpSendReceive 192.168.1.5 23 1 -s100
    
        //Messages such as the following will begin to appear on the terminal window when
        //a UDP packet has been echoed back:
    
        //        Starting test with a 1000 uSec delay between transmits
        //        [id 1] count = 1000, time = 12
        //        [id 1] count = 2000, time = 24
        //        [id 1] count = 3000, time = 36
        //
        udp_echo_init();
    
        //
        // Set the interrupt priorities.  We set the SysTick interrupt to a higher
        // priority than the Ethernet interrupt to ensure that the file system
        // tick is processed if SysTick occurs while the Ethernet handler is being
        // processed.  This is very likely since all the TCP/IP and HTTP work is
        // done in the context of the Ethernet interrupt.
        //
        MAP_IntPrioritySet(INT_EMAC0, ETHERNET_INT_PRIORITY);
        MAP_IntPrioritySet(FAULT_SYSTICK, SYSTICK_INT_PRIORITY);
    
        //
        // Loop forever, processing the LED blinking.  All the work is done in
        // interrupt handlers.
        //
        while(1)
        {
            //
            // Wait till the SysTick Interrupt indicates to change the state of the
            // LED.
            //
            while(g_bLED == false)
            {
            }
    
            //
            // Clear the flag.
            //
            g_bLED = false;
    
            //
            // Toggle the LED.
            //
            MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1,
                             (MAP_GPIOPinRead(GPIO_PORTN_BASE, GPIO_PIN_1) ^
                              GPIO_PIN_1));
        }
    
    
    
    
    }
    
    void udp_echo_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct
    ip_addr *addr, u16_t port)
    {
        if (p != NULL) {
            /* send received packet back to sender */
            udp_sendto(pcb, p, addr, port);
            /* free the pbuf */
            pbuf_free(p);
        }
    }
    
    
    void udp_echo_init(void)
    {
        struct udp_pcb * pcb;
    
        /* get new pcb */
        pcb = udp_new();
        if (pcb == NULL) {
            LWIP_DEBUGF(UDP_DEBUG, ("udp_new failed!\n"));
            return;
        }
    
        /* bind to any IP address on port 23 */
        if (udp_bind(pcb, IP_ADDR_ANY, 23) != ERR_OK) {
            LWIP_DEBUGF(UDP_DEBUG, ("udp_bind failed!\n"));
            return;
        }
    
        /* set udp_echo_recv() as callback function
           for received packets */
        udp_recv(pcb, udp_echo_recv, NULL);
    }

  • Replaced enet_lwip.c contents with what you sent.

    PinoutSet has parameters not defined In pinout.c for enet_lwip example.

    UARTStdioConfig and UARTprintf undefined symbol.  Where do I get these functions?

  • Hi Robert,

     Here is the project.

    udp_echo.zip

  • I am missing the linked files from the project. pinout.c and pinout.h.
  • I used the pinout.c and pinout.h from the C:\ti\TivaWare_C_Series-2.1.4.178\examples\boards\dk-tm4c129x\drivers folder and it now compiles. It is assigned an IP and I can ping it. How do you connect to the ICDI virtual com port?
  • Hi Robert,

      You will need to go to your Windows device manage and look under Ports (COM and LPT) to find out the COM port number the ICDI is enumerated with. The example configures the UART with 115200 baud rate, 1 stop bit and no parity.

      You can use the PC utility <tirtos_install_dir>\packages\examples\tools\udpSendReceive developed for a TI-RTOS UDP example to test out the connection.

  • Do you have WireShark? See: wireshark.org

    That program is quite useful. Also, when I run into network problems with embedded systems, I like to create an isolated network on my desk that is not connected to the rest of the building or the Internet. This helps to diagnose problems because it eliminates other unrelated systems.

    Note a few networking-related caveats to be aware of:

    This sounds really basic but check the network cable! Try different cables if you're not sure.

    If your DK board and PC are connected through an Ethernet switch, and especially if that's part of a larger network of different computers, datagrams from the board will not appear in WireShark on your PC unless they are actually destined for your PC. This is because Ethernet switches reduce/avoid collisions by directing communication only to where it's necessary. If, due to something being misconfigured, the switch thinks it isn't necessary to route some communication to your PC, you won't see it.

    Old-style hubs, as opposed to switches, did not "switch" the communication and you could therefore monitor all computers connected to a hub using WireShark. If you suspect the switch is a problem (unlikely but possible) and you have an old style hub around, you can try that, but then you might run into other problems due to crossover network cables / uplink ports, etc., because a 10 MBit hubs don't support Auto-MDIX as far as I'm aware.

    An even better approach is to connect the DK directly to your PC without a switch or hub. If you are using a TM4C part with a built-in PHY, it supports Auto-MDIX; if using an external PHY you'll have to check if it supports that. Auto-MDIX takes away the need to worry about straight or crossover network cables. If at least one side of a communication link supports Auto-MDIX, it works with either type of cable.

    Note that if your firmware relies on DHCP, you will need a DHCP server available, or you will need to configure lwIP to use Auto-IP. Auto-IP is something that kicks in after DHCP has timed out and assigns a self-assigned IP address. I think the default timeout is about 40 seconds before your board will self-assign itself an IP address. You will need to check control panel on your PC or "ipconfig" to verify that your PC also gave itself a self-assigned IP before beginning your test (or "ifconfig" / "ip addr" or whatever the equivalent is on your OS if using a *nix-style OS).

    If you don't want to mess around with Auto-IP or you think that's not working, but you like the idea of connecting the development board directly to your PC and you need DHCP, you could run a DHCP server on your PC.

    Dual Server is a great program for this: dhcp-dns-server.sourceforge.net

    The nice thing about Dual Server is that you can run it two different ways: as a service which starts automatically with the computer and runs in the background, or -- the mode that is most useful for debugging -- as a standalone program you can start (e.g., from the Windows Start menu) and stop manually at any time. Make sure your computer is not connected to any other network or make sure the configuration is such that your private DHCP server will not interfere with the DHCP server for other networks -- there should only be one DHCP server on a network.

    By connecting the development board directly to your PC and having a DHCP server like this running on the PC, you can create a private network of just your PC and the DK.

    Yet another possibility is to use static IP addresses -- but if you set your PC to a static IP address, then you probably need to remember to set your PC back to DHCP later.
  • Thanks twelve12pm for the info.  After replacing pinout.c and pinout.h from the enet_lwip example I am now seeing the UDP messages using wireshark. I have noticed that importing CCS projects that have linked files do not contain the linked files.

  • Robert Applebee said:

    I have noticed that importing CCS projects that have linked files do not contain the linked files.

    Are you referring to files which install as part of TivaWare? Yes, the CCS Project Explorer makes it look as though all files are "in" the project, but as you found out, that doesn't necessarily mean that a copy of the code ends up in your working directory. The act of importing a project does not cause all of the files to be copied on disk. The way I've dealt with that is to set up an empty TM4C project myself, following the suggestions for a "Portable Project" here: http://processors.wiki.ti.com/index.php/Portable_Projects
    Also I use version control (Subversion) so I followed the advice on a separate Wiki page about which CCS files to version: http://software-dl.ti.com/ccs/esd/documents/sdto_ccs_source-control.html
    After that, I make sure that all files needed by the project are actually in the project directory!