FreeRTOS + LwIP ATSAME70 Lock up

Hi all,

I’m using FreeRTOS + LwIP on a Microchip ATSAME70 MCU, and I’m facing a long-standing issue where the system eventually locks up, but only after using TCP sockets.

Here’s what I’ve tried and observed:

If I keep a TCP socket open continuously, the system locks up faster — sometimes within minutes or hours.

To work around this, I changed the design to only open a TCP socket briefly when I need to send data, and then immediately close and delete it (connect → send → close).

This extends the time before the lockup occurs, but it still eventually happens after enough TCP activity over time.

I’m seeing errors like:

memp_malloc: out of memory in pool TCP_PCB

memp_malloc: out of memory in pool NETCONN

I increased MEMP_NUM_TCP_PCB and MEMP_NUM_NETCONN which cleared the errors but my system is still locking up after a certain amount of time.

My TCP THREAD is:

/********************* TCP Thread Function *********************/
S8 res; 
void TCP_THREAD(struct _tcp_descriptor* TCP)
{
	portTASK_USES_FLOATING_POINT();

	//Set handle for thread
	TCP->handle = xTaskGetCurrentTaskHandle();
	//Force close on start
	TCP->sockFlags |= TCP_FORCE_CLOSE_FLAG;
	TCP->txBuf.flags = 0;

	//Wait until low level is ready for a connection
	TCP_PHY_WAIT(TCP);
	
	//Enter TCP state machine
	while (1)
	{
		//wait until woken, or timeout
		TCP->state = TCP_STATE_WAIT;
		ulTaskNotifyTake(pdTRUE, 10);
		//vTaskDelay(10);
		//Monitor PHY and NETIF status
		if (*(TCP->netifStatus) == false || *(TCP->phyStatus) == false){
			TCP_PHY_WAIT(TCP);
		}

		//If not connected, attempt to connect
		if (TCP->linkStatus == false){
			TCP->linkStatus = TCP_CONNECT(TCP);
			TCP->tcpLastRx = sysGetMs() + 5000;
		}else if (TCP->sockFlags & TCP_FORCE_CLOSE_FLAG){
				TCP_CLOSE_SOCK(TCP);
				xSemaphoreGive(*(TCP->lwipMtx));
				TCP_PHY_WAIT(TCP);
		}else{
			//receive data if mailbox is not empty
			res = TCP_READ(TCP);
			//Add downtime between io events
			vTaskDelay(10);
			//Forward data if we have any
			if(!(TCP->txBuf.flags & TCP_BUF_DONE)){
				res = TCP_WRITE_FROM_BUF(TCP);	
			}
		}
		
		if ((sysGetMs() > socketTimer + 180000) && TCP->linkStatus == true ) { // close socket every ...
           printf("Idle timeout, Closing socket... \n");
           TCP_FORCE_CLOSE_SOCK(TCP);
		   socketTimer = sysGetMs(); 
  
		}
       		
		//get high water mark
		RTOS.TCP.hwMark = uxTaskGetStackHighWaterMark( NULL );
	}
}

I am fairly new at this so my understanding of the issue might be completely off.
Has anyone else run into a similar issue? Or any insight on how to deal with it would be greatly appreciated.

Thanks in advance.

For LWIP related support, I would suggest reaching out to the LWIP forum/mailing list.

Here are a couple of things I noted while taking a quick look:

  • The return value of ulTaskNotifyTake not checked here: Refer to these docs to see how task notifications can be used correctly: RTOS task notifications - FreeRTOS™
  • The fields in the struct _tcp_descriptor pointer (TCB) seems to be updated from a different thread/callback/ISR. If thats the case those fields are accessed concurrently from TCP_THREAD thread, you need mutexes to protect them from race conditions.
  • Verify the implementation of printf for your platform is thread safe.
2 Likes

Hi Tony,

thank you so much for your response. I have made some changes to my code based on your notes. So far it seems to be working fine but then it could take longer before it locks up. I will keep monitoring it and if it fails again I will try my luck on the LWIP forum as you suggested.

Thanks.