cancel
Showing results for 
Search instead for 
Did you mean: 

LWIP Socket API, TCP and UDP connection on the same STM32 MCU

voyvoda .
Senior

Hello,

I am trying to implement TCP and UDP server connection on my STM32F407-Discovery Board. I use Socket API with FreeRTOS.

I am able to run TCP or UDP seperately. Single server or client works fine.

When I combine TCP and UDP server tasks at the same code. None of them work. I can not even PING my STM32 board. I created different two tasks for each TCP and UDP server.

I tried to increase HEAP size of LWIP above 32KB. However, it did not resolved my issue.

Are the any solution to my issue ?

Thank you in advance for your help. Best Regards

17 REPLIES 17
Ozone
Lead

Do resource acquisition functions (socket, bind, etc.) return errors during combined operation, or does it just silently fail ?

What does wireshark say ?

no function returns error. I have check returns and if it fails, I know it.

I have not checked it by wireshark.

Ozone
Lead

I would check how far the communication proceeds, perhaps the core is occasionally overloaded (interrupts), and drops ethernet packages.

In my experience, this is a very common problem with IoT projects.

I think there is a memory allocation problem

/* USER CODE BEGIN 4 */
void udp_client_task()
{
	char payload[] = "Message from STM32\r\n";
 
    while (1) {
 
        struct sockaddr_in dest_addr_udp;
        dest_addr_udp.sin_addr.s_addr = inet_addr("192.168.0.100");
        dest_addr_udp.sin_family = AF_INET;
        dest_addr_udp.sin_port = htons(5555);
 
        int sock_udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
        if (sock_udp < 0) {
            break;
        }
 
        while (1) {
 
            int err = sendto(sock_udp, payload, strlen(payload), 0, (struct sockaddr *)&dest_addr_udp, sizeof(dest_addr_udp));
            if (err < 0) {
                break;
            }
 
            osDelay(1000);
        }
 
        close(sock_udp);
    }
 
}
 
void tcp_client_task()
{
	char payload[] = "Message from STM32\r\n";
 
    while (1) {
 
        struct sockaddr_in dest_addr_tcp;
        dest_addr_tcp.sin_addr.s_addr = inet_addr("192.168.0.100");
        dest_addr_tcp.sin_family = AF_INET;
        dest_addr_tcp.sin_port = htons(5000);
 
        int sock_tcp =  socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
        if (sock_tcp < 0) {
 
            break;
        }
 
 
        int err = connect(sock_tcp, (struct sockaddr *)&dest_addr_tcp, sizeof(struct sockaddr_in));
        if (err != 0) {
        	osDelay(1000);
            continue;
        }
 
        while (1) {
            int err = send(sock_tcp, payload, strlen(payload), 0);
            if (err < 0) {
 
                break;
            }
 
            osDelay(1000);
        }
 
        close(sock_tcp);
    }
 
}
/* USER CODE END 4 */
 
/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* init code for LWIP */
  MX_LWIP_Init();
  /* USER CODE BEGIN 5 */
  tcp_client_task();
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END 5 */
}
 
/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the myTask02 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void const * argument)
{
  /* USER CODE BEGIN StartTask02 */
	udp_client_task();
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END StartTask02 */
}

0693W000007ZnazQAC.png 

Piranha
Chief II

As you are using ST's broken bloatware... Take a note that, while netconn and socket APIs are inherently thread-safe, Ethernet link status and DHCP processing code by ST are still broken in this regard. These and other issues are documented here:

https://community.st.com/s/question/0D50X0000BOtfhnSQB/how-to-make-ethernet-and-lwip-working-on-stm32

​In the link below, it is suggested about multi-treading. I need to apply this to my code.

https://www.nongnu.org/lwip/2_1_x/multithreading.html 

In short: Copy the functions sys_mark_tcpip_thread() and sys_check_core_locking() to your port and modify them to work with your OS. Then let LWIP_ASSERT_CORE_LOCKED() and LWIP_MARK_TCPIP_THREAD() point to these functions.

If you use LWIP_TCPIP_CORE_LOCKING, you also need to copy and adapt the functions sys_lock_tcpip_core() and sys_unlock_tcpip_core(). Let LOCK_TCPIP_CORE() and UNLOCK_TCPIP_CORE() point to these functions.

Ivan Pletnev
Associate II

Hello!

First, your clients are using same local port . You should use differents ports for udp and tcp clients at least.

Second. Every new connection should use another port for prevent tcp errors like "Reusing port" and so on.

Third. While your tcp client trying to connect to server in loop, it take all availible memory in tcp_pcb memory pool.

I,m highly recommend to use traffic analyzer like Wireshark to undestand, whats going on.

> Second. Every new connection should use another port for prevent tcp errors like "Reusing port" and so on.

Servers usually have a "linger period" assigned to ports that are not explicitly closed, sometimes up to 15 minutes.

> I,m highly recommend to use traffic analyzer like Wireshark to undestand, whats going on.

I second that - as mentioned initially.

Ivan Pletnev
Associate II

0693W000008w2BYQAY.pngThis is a my tcp client. It is works fine together with tcp server on the same mcu.

void tcp_client_socket_thread(void *arg) {
 
	serverParams *pSrvParams = (serverParams*) arg;
	portSettingsType *pPortSettings =
			&eepromSettings.portSettings[pSrvParams->number];
	volatile uint8_t currentPortNumber = 0;
	int socket, newconn = 0;
	struct ip4_addr tempIp;
	struct sockaddr_in addr, localhost;
	osThreadId socketReceiveTaskHandle;
	osThreadId socketSendTaskHandle;
	uint16_t localPort = 0;
	uint8_t i = 0;
 
	currentPortNumber = pSrvParams->number;
 
	memset(&localhost, 0, sizeof (localhost));
	localhost.sin_family = AF_INET;
	localhost.sin_len = sizeof(struct sockaddr_in);
	localhost.sin_addr.s_addr = INADDR_ANY;
	localhost.sin_port = 0;
 
	memset(&addr, 0, sizeof(addr));
	addr.sin_len = sizeof(addr);
	addr.sin_family = AF_INET;
	IP4_ADDR(&tempIp, pPortSettings->remoteIpAddress[0],
			pPortSettings->remoteIpAddress[1],
			pPortSettings->remoteIpAddress[2],
			pPortSettings->remoteIpAddress[3]);
	addr.sin_addr.s_addr = tempIp.addr;
	addr.sin_port = htons(pPortSettings->remoteTcpPort);
 
	osDelay(3000);
 
	for (;;){
		if (pSrvParams->connCounter < MAX_SOCKET_CONN){
			localPort = (uint16_t)(HAL_RNG_GetRandomNumber(&hrng)%16383+49152);
			for (i=0; i<NO_OF_PORTS; i++){
				if (localPort == eepromSettings.portSettings[i].localTcpPort){
					localPort +=10+i;
					if (localPort < 49152){
						localPort = 49152+i;
					}
				}
			}
			localhost.sin_port = htons (localPort);
			socket = socket (AF_INET, SOCK_STREAM, 0);
			if (socket < 0){
				puts ("Create client socket failed\r\n");
				return;
			} else {
				printf ("1. TCP client socket # %i for Port # %u has been created\r\n", socket, pSrvParams->number);
				if (bind (socket, (struct sockaddr*)&localhost, sizeof (struct sockaddr)) < 0){
							puts("Bind failed\r\n");
							return;
				} else {
					puts("Bind socket to localhost OK\r\n");
					newconn = connect(socket, (struct sockaddr*)&addr, sizeof (addr));
					if (newconn < 0){
						printf("2. Unable to connect to remote server, newconn = %i\r\n\r\n", newconn);
						osDelay(10000);
					} else {
						printf("Connection to remote server established. Socket No %i \r\n\r\n", newconn);
						pSrvParams->currentFd = socket;
						pSrvParams->connCounter++;
						switch (pSrvParams->number) {
						case 0:
							HAL_GPIO_WritePin(SOCK1_GPIO_Port, SOCK1_Pin, GPIO_PIN_SET);
							break;
						case 1:
							HAL_GPIO_WritePin(SOCK2_GPIO_Port, SOCK2_Pin, GPIO_PIN_SET);
							break;
						}
						socketReceiveTaskHandle = sys_thread_new(
								pSrvParams->receiveTaskName, socketReceiveTask,
								(void*) &srvParams[currentPortNumber], 256,
								osPriorityNormal);
						pSrvParams->receiveTaskHandle = &socketReceiveTaskHandle;
						socketSendTaskHandle = sys_thread_new(pSrvParams->sendTaskName,
								socketSendTask, (void*) &srvParams[currentPortNumber],
								256, osPriorityNormal);
						pSrvParams->sendTaskHandle = &socketSendTaskHandle;
					}
				}//connect
			}//bind
		}//if (connCounter)
		osDelay(10);
	} //infinite loop
}//tcp_client_socket_thread