cancel
Showing results for 
Search instead for 
Did you mean: 

[BUG] STM32CubeMX generates a dysfunctional lwIP application without RTOS

Piranha
Chief II

With RTOS the CubeMX generated code creates threads, which do the reception of packets and link state management. Without RTOS the example code does the lwIP processing in the main infinite loop. But, when CubeMX generates lwIP application without RTOS, the main infinite loop is left empty and therefore the network code is completely dysfunctional. The issue seems to be present for all series with lwIP support.

4 REPLIES 4
JMarq.1
Associate III

I manually add MX_LWIP_Process(); inside the main while(1) to do LWIP stack processing.

/* Infinite loop */
  /* USER CODE BEGIN WHILE */
  Init_AppLoop();
  while (1)
  {
    /* USER CODE END WHILE */
    MX_USB_HOST_Process();
 
    /* USER CODE BEGIN 3 */
    MX_LWIP_Process();
    Do_AppLoop();
  }
  /* USER CODE END 3 */

I apply this after searching in the whole project the old code being called in ST examples (because they are based in older versions of IDE not including MX). I mean the following lines that appear in the old UM1713 from ST:

ethernetif_input(&gnetif);
sys_check_timeouts();

I don't know whether there is any other routine to be called in the while loop...

Adding it manually lets us to call LWIP stack processing only if needed. We have a custom hardware where Ethernet must be activated from a configuration menu after applying for a license fee. Thus, not being included automatically by CubeMX, we can write something like that:

if (config.ethernet_enabled)
  MX_LWIP_Process();

BTW, is there any better way of achiving this?

Obviously, this implies that on a new MX release, we would need to check whether there's any change on how to call LWIP processing. This should be mentioned in some official documentation (AN or release notes) from ST.

If MX generates the required code automatically, it will be a good idea. There is always the possibility to remove/modify it manually based on your needs, but at least I also see your point in getting functional code at the first time and showing what needs to be called exaclty.

Piranha
Chief II

In your code example CubeMX generated a call to MX_USB_HOST_Process(), but did not generate a call to MX_LWIP_Process(). As a minimum it's an inconsistent behavior. Either it should generate processing calls for all software components, which need it, or don't do it for any and document the necessity of adding those calls manually. But the second case conflicts with the whole purpose of code generation, which supposedly is generating a working examples.

> we can write something like that

When you start writing your own code, the question becomes why do you still need CubeMX. One can use the HAL drivers without it. But in a serious project one shouldn't use any of ST's broken bloatware at all.

> BTW, is there any better way of achiving this?

Interrupts should trigger a task, which processes Rx frames. Independently of that the sys_check_timeouts() should be called by a periodic software timer. I recommend a period of 50 ms or less. No offence, but in my opinion the typical superloop with a useless polling/execution of all tasks is a beginner level code. Any serious project even with a cooperative scheduling should have an event-triggered tasks and a software timer system implemented anyway. And, to be completely honest, the lack of a well-defined APIs and implementations for these concepts clearly shows that the whole software industry is terribly stagnating.

JMarq.1
Associate III
/* lwip.c */
 
/**
 * ----------------------------------------------------------------------
 * Function given to help user to continue LwIP Initialization
 * Up to user to complete or change this function ...
 * Up to user to call this function in main.c in while (1) of main(void)
 *-----------------------------------------------------------------------
 * Read a received packet from the Ethernet buffers
 * Send it to the lwIP stack for handling
 * Handle timeouts if LWIP_TIMERS is set and without RTOS
 * Handle the llink status if LWIP_NETIF_LINK_CALLBACK is set and without RTOS
 */
void MX_LWIP_Process(void)
{
/* USER CODE BEGIN 4_1 */
/* USER CODE END 4_1 */
  ethernetif_input(&gnetif);
 
/* USER CODE BEGIN 4_2 */
/* USER CODE END 4_2 */
  /* Handle timeouts */
  sys_check_timeouts();
 
/* USER CODE BEGIN 4_3 */
/* USER CODE END 4_3 */
}

I think I'm just doing what ST environment suggests to do and not reinventing the wheel. If ST code is bloatware, the solution for serious projects I think is to move to another platform and not wasting time diving in how to write what is already provided by ST.

why do you still need CubeMX

CubeMX is a great tool in my opinion and it is supposed to be good. It absolutely does a lot of work in order to get a quick skeleton not having to dive into low level details that only wastes time in your daily job at application level programming. If it is there, I see no point for not using it.

Yes, I'm at beginner level. I hope to not regret having choosed the popular STM32 as MCU platform for our projects.

> CubeMX is a great tool in my opinion and it is supposed to be good. It absolutely does a lot of

> work in order to get a quick skeleton not having to dive into low level details

And that's about it, you should not see it as the 3-clicks-solution for any projects.

HAL is different, there are some good HAL sources, and some very bad. But as Piranha always complains: almost always unnecessarily "bloated".

>  I hope to not regret having choosed the popular STM32 as MCU platform for our projects.

The hardware is very good and reliable, sometimes documentation is ... lacking.