Caspar Westerberg
Caspar Westerberg

Reputation: 11

How to receive data over Ethernet using LWIP, UDP

I'm trying to send data to and from my computer and an STM32H745 over Ethernet using LwIP and UDP. I have successfully configured the card and right now I can send data from the card to a Python script running on the computer. However, I don't understand how udp_recv works <udp,lwip> or how to receive data with UDP on LwIP in general, and I can't find examples that do just that. Where is the data being received? Should I even use udp_recv?

In the main loop I run MX_LWIP_Process, which runs ethernetif_input which somehow handles the received data, but I don't understand where it puts it.

Below is the main code, just for reference.

const char* message = "a";

HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1); // orange

ip_addr_t PC_IPADDR;
IP_ADDR4(&PC_IPADDR, 192, 168, 1, 200);

u16_t port = 8000;

struct udp_pcb* my_udp = udp_new();

struct pbuf* udp_buffer = NULL;

/* Infinite loop */
for (;; )
{
    MX_LWIP_Process();
    HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1); // orange
    HAL_Delay(1000);

    udp_buffer = pbuf_alloc(PBUF_TRANSPORT, strlen(message), PBUF_RAM);
    if (udp_buffer != NULL)
    {
        memcpy(udp_buffer->payload, message, strlen(message));
        udp_sendto(my_udp, udp_buffer,&PC_IPADDR, port);
        pbuf_free(udp_buffer);
    }

    //udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
}

Upvotes: 1

Views: 12668

Answers (1)

Clifford
Clifford

Reputation: 93556

udp_recv() does not actually receive UDP datagrams (despite its name). It registers a callback function that will then be called by MX_LWIP_Process() when a datagram has been buffered. It would better be called udp_set_recv_callback(), but it is what it is.

To that end you should call it once before your executive loop:

    udp_bind( my_udp, IP_ADDR_ANY, port ) ;
    udp_recv( my_udp, udp_receive_callback, NULL ) ;

    /* Infinite loop */
    for (;; )
    {
         // Run the CubeMX LwIP stack
         MX_LWIP_Process() ;

         ...
    }

Where udp_receive_callback is a function that will be invoked on receipt of a datagram:

void udp_receive_callback( void* arg,              // User argument - udp_recv `arg` parameter
                           struct udp_pcb* upcb,   // Receiving Protocol Control Block
                           struct pbuf* p,         // Pointer to Datagram
                           const ip_addr_t* addr,  // Address of sender
                           u16_t port )            // Sender port 
{

  // Process datagram here (non-blocking code)
  ...
  
  // Must free receive pbuf before return
  pbuf_free(p);
}

Examples include:

Documentation can be found at https://www.nongnu.org/lwip/2_0_x/group__udp__raw.html

Upvotes: 4

Related Questions