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.

TM4C129ENCPDT: Bug in Port to LWIP for TIVA Processor

Part Number: TM4C129ENCPDT

I was having issues when running LWIP portfor TIRTOS where the pBuf would run out , it took some tracking down but I found the issue in the Ethernet driver port.

There is a bug in the LWIP port example for TM4C129ENCPDT

"C:\ti\TivaWare_C_Series-2.2.0.295\third_party\lwip-1.4.1\ports\tiva-tm4c129\netif\tiva-tm4c129.c"

The bug is in the "tivaif_receive" function and occurs when the last descriptor list contains part of an incomplete frame.

If the following check fails for the last descriptor to be processed (DES0_RX_STAT_LAST_DESC is not set)

          if (pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32CtrlStatus &
             DES0_RX_STAT_LAST_DESC)

The code automatically allocates a new pBuff to this descriptor (even though the current one hasn't been handled).

My work around was to have the function check if the last pBuf was handled before allocating a new on to the descriptor.

		// Find the next descriptor in the chain, taking care to wrap.
		ui32NextDescriptor = pDescList->ui32Read + 1;
		if (ui32NextDescriptor == pDescList->ui32NumDescs)
		{
			ui32NextDescriptor = 0;
		}

		// We didn't finish with the last buffer, frame wasn't complete
		if (pBuf && (ui32NextDescriptor == ui32DescEnd))
		{
			// Let DMA get the data next time
			DRIVER_STATS_DEC(RXBufReadCount);
			break;
		}
		else
		{
			// Allocate a new buffer for this descriptor
			pDescList->pDescriptors[pDescList->ui32Read].pBuf = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL);
			pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32Count = DES1_RX_CTRL_CHAINED;
			if (pDescList->pDescriptors[pDescList->ui32Read].pBuf)
			{
				// We got a buffer so fill in the payload pointer and size.
				pDescList->pDescriptors[pDescList->ui32Read].Desc.pvBuffer1 =	pDescList->pDescriptors[pDescList->ui32Read].pBuf->payload;
				pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32Count |= (pDescList->pDescriptors[pDescList->ui32Read].pBuf->len <<
								DES1_RX_CTRL_BUFF1_SIZE_S);

				// Give this descriptor back to the hardware
				pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32CtrlStatus = DES0_RX_CTRL_OWN;
			}
			else
			{
				LWIP_DEBUGF(NETIF_DEBUG, ("tivaif_receive: pbuf_alloc error\n"));
				pDescList->pDescriptors[pDescList->ui32Read].Desc.pvBuffer1 = 0;
				// Update the stats to show we couldn't allocate a pbuf.
				DRIVER_STATS_INC(RXNoBufCount);
				LINK_STATS_INC(link.memerr);

				// Stop parsing here since we can't leave a broken descriptor in the chain.
				break;
			}
			// Move on to the next descriptor in the chain, taking care to wrap.
			pDescList->ui32Read = ui32NextDescriptor;
		}

This works well for me, with no more lost pBuf, but may not be the ideal way, would value feedback.

  • Hi Barry,

    Barry Andrews said:
    I was having issues when running LWIP portfor TIRTOS

      Let me try to understand your environment here. You mentioned TIRTOS. You seem to suggest you are using LwIP in the socket or netconn API mode using TIRTOS. Is this a correct understanding? If this is the case, you might be the first one to do so. Is there any reason you would not use the NDK that comes with the TI-RTOS? The NTK is TI's version of the TCP/IP stack. I wonder if you have seen this problem if you use LwIP in RAW API mode. 

      In any case, much appreciated your finding and I will bookmark this post if anyone comes across the same issue. Thank you again.

  • Thanks for the response.

    I have changed from NDK to LWIP because I am using multiple PPP devices as well as the Ethernet and needed to be able to ensure data from a socket binds to the specific interface. I had used a work around by adding a route to the interface, but this doesn't work when both PPP ports are targeting the same host address and need to send at the same time. The LWIP stack has this capability as a simple socket option, the NDK does not have this capability and looking at the code, I couldn't see an easy way to add this capability.

    I was also concerned that the NDK has no new releases for many years and doesn't seem to be actively supported, LWIP is actively supported.

    The issue I have found was in the Tivaware examples and includes freertos, the bug exists regardless of the RTOS and regardless of the LWIP mode as it is in the Ethernet receive function which is the lowest level.

  • HI Barry,

      Is your finding only applicable when you are in PPP? Not that I'm an expert in the driver code but personally, I have not come across anyone reporting an issue like yours until now.  

  • Hello Charles

    The bug is in the Ethernet driver receive, and nothing to do with PPP.

    The bug only happens when the Ethernet frame is split across multiple pBuf and the whole frame isn't received in the one burst of DMA.

    It would depend very much on what the Ethernet MTU is set to and what the pBuf size is set to and what tasks are running in the application.

    If the pBuf is bigger than the MTU then there would be no splitting of frames across buffers and hence the bug would not occur.

    However, the code is designed to allow for the case where an Ethernet frame is split across multiple pBuf which implies pBuf size can be smaller than the ethernet frames, and hence the receive function should handle this condition.

    In my case it would lose 1 pBuf every hour or two, so it was happening very infrequently, I would handle millions of pBuf descriptors before my available 64 pBuf pool would be exhausted.

    We had two units running and one failed every 2 or 3 days, whilst the other ran for more than a month, so it very much depends upon the Ethernet traffic where the device is as well as other factors.

    Regards

    Barry.

  • Hi Barry,

      Thanks for the clarification. I wonder if you have tried to configure the pBuf size equal to one MTU (I think the default is 1500) and see if any different results. 

      Do you mind to share the modified tiva-tm4c129.c you have?