cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7, LWIP and multi threading done right ?

Manu Abraham
Senior

Hi,

The more I am reading LWIP documentation, the more I get confused.

The entire LWIP codebase is scattered with #ifdefs making it look like a minefield and nightmare regarding maintainability. At least that's what I feel, maybe it is because I have not worked with LWIP before.

I see @Piranha​  citing clearly documented issues regarding CubeH7 package and multi threading regarding LWIP.

So, I have taken some interest to implement the code, the best possible way possible by me, based on LWIP documentation. But the more I look into it, I get even more confused.

To begin with, https://www.nongnu.org/lwip/2_1_x/multithreading.html

"How to get threading done right"

Did a search within the CubeH7 package regarding "LWIP_MARK_TCPIP_THREAD"

Searching 42199 files for "LWIP_MARK_TCPIP_THREAD" (case sensitive)

0 matches

@Amel NASRI​ @Imen DAHMEN​ After a few night outs, I have a splitting headache trying to sort things out. It appears as though the Cube H7 package is not really stable as far as Ethernet/LWIP is concerned.

I cant find even a single example, which properly implements LWIP guidelines, not even LWIP has sample code to describe the stack usage properly. It looks like a very poor stack regarding proper documentation too, forget maintainability and readability.

@Piranha​ Can you please point to at least a single properly implemented LWIP sample application code base ?

If anyone else has any pointers on this subject, please chime in even if it is 2c. I am all ears.

Thanks,

Manu

3 REPLIES 3
Pavel A.
Evangelist III

ST's clone of LwIP repo is here.

LwIP has a mailing list: https://lists.nongnu.org/archive/html/lwip-users https://lists.nongnu.org/mailman/listinfo/lwip-users

If you're looking how to write asynchronously to a socket from which another thread reads,

see this question: https://lists.nongnu.org/archive/html/lwip-users/2020-04/msg00087.html

Note that FreeRTOS has their own TCP/IP stack, you may try it instead.

-- pa

EmbeddedVito
Associate II

If yuu want to make your application thread safe you have to implement lwip multithreading.

The list of what to do that im going to show helped me resolving this problem: i wanted 5 thread calling the same function UDP_Server() (an UDP client created by me) every 1s. I always ended up in Hard Fault or problem related with memory in the LWIP library.

What to do:

  • here you can read "See the example sys_arch.c files in unix and Win32 port in the contrib repository". the mentioned repository can be found here. You have to search for the file sys_arch.c inside the port folder. Choose the folder freertos. Inside this file you will see all the 4 functions mentioned about multithreading: sys_marc_tcpip_thread(), sys_check_core_locking(), sys_lock_tcpip_core() and sys_unlock_tcpip_core(). if you are working with CSIS RTOS you have to change the functions and put them inside your sys_arch.c file:
static osThreadId lwip_tcpip_thread;
static u8_t lwip_core_lock_count;
static osThreadId lwip_core_lock_holder_thread;
extern sys_mutex_t lock_tcpip_core;
 
void sys_lock_tcpip_core(void)
{
   if (lwip_core_lock_count == 0) {
     lwip_core_lock_holder_thread = osThreadGetId();
   }
   lwip_core_lock_count++;
   sys_mutex_lock(&lock_tcpip_core); //spostato sotto perchè in questa funzione si aspetta
}
 
void sys_unlock_tcpip_core(void)
{
	lwip_core_lock_count--;
	if (lwip_core_lock_count == 0) {
		lwip_core_lock_holder_thread = 0;
	}
	sys_mutex_unlock(&lock_tcpip_core);
}
 
void sys_mark_tcpip_thread(void)
{
	lwip_tcpip_thread = osThreadGetId();
}
 
void sys_check_core_locking(void)
{
	taskENTER_CRITICAL();
	taskEXIT_CRITICAL();
 
	if(lwip_tcpip_thread != 0)
	{
		osThreadId current_thread = osThreadGetId();
		LWIP_ASSERT("Function called without core lock",
				current_thread == lwip_core_lock_holder_thread && lwip_core_lock_count > 0);
	}

after doing this you have to put the declarations of these functions in your sys_arch.h and make LWIP_ASSERT_CORE_LOCKED and LWIP_MARK_TCPIP_THREAD (these macros are inside opt.h) points to sys_check_core_locked() and sys_mark_tcpip_thread()

  • You have to declare the mutex lock_tcpip_core external inside your sys_arch.c (see line 4 of the previous code)
  • you finally have to make LOCK_TCPIP_CORE and UNLOCK_TCPIP_CORE (inside tcpip.h file) pointing to sys_lock_tcpip_core() and sys_unlock_tcpip_core()
  • the last thing you have to implement is a semaphore or mutex that will protect the ethernet to send a packet at time (ask if you want a detailed explanation)

Hello, EmbeddedVito!

Can you give an example of using a mutex when sending a packet?

This is about the last point in your message: "the last thing you have to implement is a semaphore or mutex that will protect the ethernet to send a packet at time"

 

Thanks!