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.

HERCULES_SAFETY_MCU_DEMOS: LwIP best practices to handle reception of UDP data

Part Number: HERCULES_SAFETY_MCU_DEMOS

Hello all,

I'm using the LwIP stack to implement UDP communication using the Raw API and no OS.  What is the best practice to extract and and handle received UDP data?  Below is a short code snippet that initializes the UDP socket, and sets the reception callback.  The callback copies the data from the pbuf to a local buffer, and then the idea is to process the data from the buffer from a loop called in main by getting a pointer to the rxData buffer.  I am worried that:

A. The data may not be processed fast enough before new data arrives

B. Once new data arrives, it will overwrite the buffer before it's fully processed, this will cause my data to be all mixed up (I can put a mutex on the receive buffer, but I'm worried I'll be loosing some received data)

In general, it is a good idea to process the data outside of the callback, correct? Since it's technically part of the ISR... correct me if I am wrong, otherwise I can do all I need to do inside the callback

How's this typically handled? Is there a better way of doing what I'm trying to do? Any examples?

static uint16_t rxLength = 0;
static uint8_t rxData[4096];


void EMAC_LwIP_Main (uint8_t * macAddress)
{
    unsigned int 	ipAddr;
	
	/* Enable the interrupt generation in CPSR register */
	IntMasterIRQEnable();
	_enable_FIQ();

   

	/* Initialze the lwIP library, using static address.*/
	uint8 ip_addr[4] = { 192, 168, 2, 44 };
	uint8 netmask[4] = { 255, 255, 255, 0 };
	uint8 gateway[4] = { 192, 168, 2, 254 };
	ipAddr = lwIPInit(0, macAddress,
			*((uint32_t *)ip_addr),
			*((uint32_t *)netmask),
			*((uint32_t *)gateway),
			IPADDR_USE_STATIC);

	struct udp_pcb * mypcb;
	mypcb = udp_new();


	if (udp_bind(mypcb, IP_ADDR_ANY, 8760) == ERR_OK)
    {
	    /* Set a receive callback for the pcb */
        udp_recv(mypcb, udp_receive_callback, NULL);
    }
	else
	{
        return;
	}

	/* Loop forever.  All the work is done in interrupt handlers. */
	while(1)
	{
		ProcessRxData();
	}
}

void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
{

    /* Copy data to local buffer */
    if (p != NULL && p->tot_len != 0)
    {
        rxLength = pbuf_copy_partial(p, rxData, p->tot_len, 0);
    }
}

void ProcessRxData(void)
{
	// Process RX data here... may be a long routine
}

  • Hello G89,

    Unfortunately, we don't have any explicit examples of this other than the LWIP example provided with Halcogen. Since this is a open source developed stack, I would really suggest you might find better answers and deeper experience with it in the open source community here savannah.nongnu.org/.../.

    However, from a embedded programming best practices point of view, I can tell you it is always best to do as little as possible inside your ISR and do most of you processing in a middle layer between the HAL and the application. Have you considered use of the DMA to move data from the receive buffer to a processing buffer where you could keep a queue of packets to be processed? If this method is used, you still need to be careful not to overrun your processing buffer or, in the case where a ring buffer is used, not to overwrite data from a prior message.
  • Thank you for the informative reply, Chuck.   To use the DMA it sounds like I would have to modify the LwIP core, is this correct or am I missing something?  Because once the raw API callback executes, it is assumed that the data is already available in the pbufs... I guess you're suggesting to continuously receive data through hardware registers and process that data through the main loop?  Any pointers on how to start doing that?

    I have found a lot of information out there on LwIP, unfortunately however, everything I'm seeing are more fundamental examples .  If anyone could provide an example, not necessarily from on TI products, that can achieve what I'm trying to do, that would be greatly appreciated!

  • Hi G89,

    As I mentioned, Ethernet protocols and, in particular, the LWIP stack is not a particular expertise of mine. I will forward your post to one of my colleagues that has a bit more proficiency with it to see if maybe they might be able to offer some additional suggestions. You may also want to search through this E2E to see if other posts/threads may have more details or examples that can be used as learning tools.

    Also as mentioned previously, the LWIP web page for the open source community may be a good resource. I believe they also have a community page were you can post questions and request help with the application.