UltimaSerial lwIP UDP Echo Broadcaster Example using Raw API, Socket or Netconn approaches
 

Data logger
UltimaSerial

 

Windaq add-ons
Windaq Add-ons

 

Spectrogram
UltimaWaterfall

 

Ultimaserial XChart
XChart

 

FFT1024
FFT1024

 

Ultimaserial Classroom
Lessons

lwIP is a popular free TCP/IP stack for many embedded processors. The following workshop builds an UDP echo broadcaster on lwIP.

Here we pick a real piece of hardware from Atmel:  EVK1100. Its processor is 32UC3A0512, but the codes below should work in other hardware.

Software Development Platform: AVR32 with lwIP and FreeRTOS. 

To write an UDP broadcaster on EVK1100, using lwIP on FreeRTOS, under AVR32

  1. AVR32->File->New->Example, select EVK1100-SERVICES-LWIP example
  2. Give a Project Name: MyTestFromLwIP, then click Finish. This will create a new project under the Project Explorer pane.
  3. Open MyTestFromLwIP->src->CONFIG->conf-eth.h, and change ETHERNET_CONF_IPADDR0..3 to whatever IP address you wish to use. For example, 192.168.0.223. If you wish to change the MAC also, it is just a few lines up 
  4. Instead of create a new thread, which will require better understanding of FreeRTOS, we will modify an existing thread to an UDP broadcaster.
  5. Open MyTestFromLwIP->src->NETWORK->BasicTFTP-> BasicTFTP.c
  6. The program will broadcast "testing" to port 1234, and broadcast/echo whatever comes in to port 1235.
  7. All roads lead to Rome: There are three approaches to get the job done
    1. Raw API programming
      • Reference about raw API can be found under MyTestFromLwIP->src->SOFTWARE_FRAMWORK->lwip-1.3.0->doc->rawapi.txt
      • Replace  portTASK_FUNCTION( vBasicTFTPServer, pvParameters ) with this:

        void udp_echo_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port){
              if (p != NULL) {
                    udp_sendto(pcb, p, IP_ADDR_BROADCAST, 1234); //dest port
                    pbuf_free(p);
              }
        }

        portTASK_FUNCTION( vBasicTFTPServer, pvParameters )
        {
               
        struct udp_pcb *ptel_pcb;
                char msg[]="testing";
                struct pbuf *p;

                ptel_pcb = udp_new();

                udp_bind(ptel_pcb, IP_ADDR_ANY, 1235);
                udp_recv(ptel_pcb, udp_echo_recv, NULL);

                while (1){
                       //Allocate packet buffer
                        p = pbuf_alloc(PBUF_TRANSPORT,sizeof(msg),PBUF_RAM);
                        memcpy (p->payload, msg, sizeof(msg));
                        udp_sendto(ptel_pcb, p, I
        P_ADDR_BROADCAST, 1234);
                        pbuf_free(p); //De-allocate packet buffer
                        vTaskDelay( 200 );
        //some delay!
                }       
        }

    2. Network connection programming 
      • Reference for these functions can be found in "Design and Implemention of the lwIP TCP/IP Stack" by Adam Dunkels
      • Replace portTASK_FUNCTION( vBasicTFTPServer, pvParameters ) with this:

        portTASK_FUNCTION( vBasicTFTPServer , pvParameters ){
               
        struct netconn *conn;
                char msg[]="testing" ;
                struct netbuf *buf;
                char * data;

                conn = netconn_new( NETCONN_UDP );
                netconn_bind(conn, IP_ADDR_ANY, 1234 ); //local port

                netconn_connect(conn, IP_ADDR_BROADCAST, 1235 );
                for( ;; ){
                        buf = netbuf_new();
                        data =netbuf_alloc(buf, sizeof(msg));
                        memcpy (data, msg, sizeof (msg));
                        netconn_send(conn, buf);
                        netbuf_delete(buf); // De-allocate packet buffer

                        vTaskDelay( 200 ); //some delay!
                }
        }

    3. Socket programming:
      • Replace  portTASK_FUNCTION( vBasicTFTPServer, pvParameters ) with this :

        portTASK_FUNCTION( vBasicTFTPServer, pvParameters ){
               int lSocket;
               struct sockaddr_in sLocalAddr, sDestAddr;
               char reply[]="testing";
               char buffer[1024];
               int nbytes;
               int i;

               lSocket = lwip_socket(AF_INET, SOCK_DGRAM, 0);
               
               memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr));
               memset((char *)&sDestAddr, 0, sizeof(sDestAddr));

               /*Destination*/
               sDestAddr.sin_family = AF_INET;
               sDestAddr.sin_len = sizeof(sDestAddr);
               sDestAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
               sDestAddr.sin_port = 1234;
               
               /*Source*/
               sLocalAddr.sin_family = AF_INET;
               sLocalAddr.sin_len = sizeof(sLocalAddr);
               sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
               sLocalAddr.sin_port = 1235;

               lwip_bind(lSocket, (struct sockaddr *)&sLocalAddr, sizeof(sLocalAddr));

               while (1) {
                     nbytes=lwip_recv(lSocket, buffer, sizeof(buffer),8);
                     if (nbytes>0){
                            lwip_sendto(lSocket, buffer, nbytes, 0, (struct sockaddr *)&sDestAddr, sizeof(sDestAddr));
                     }

                      lwip_sendto(lSocket, reply, sizeof(reply), 0, (struct sockaddr *)&sDestAddr, sizeof(sDestAddr));
                      vTaskDelay( 200 );  //some delay!
               }
               lwip_close(lSocket);
        }

  8. Pick one of the approaches above, build and run it, then you can use WireShark to capture the UDP packets
  9. Watch out, due to the way FreeRTOS handles priority, make sure you either keep all threads in the same priority or make sure the higher priority thread goes into blocked state periodically, such as vTaskDelay( 1 ), or the highest priority thread will never let the lower ones to run.

  Click here for more lwIP examples

Find out how to upgrade to the latest lwIP

 

 Last update: 12/18/14