cancel
Showing results for 
Search instead for 
Did you mean: 

Networking issues for LwIP/FreeRTOS code generated via STM32CubeMX [NUCLEO-F746ZG]

KR1
Associate III

After a few somewhat fruitless attempts to run Ethernet error-free on the H7 development board, I have decided to switch back to the somewhat more established F7 series (which I am a bit more familiar with). Nonetheless, I am still experiencing some weird Ethernet connectivity behavior from the code generated via STM32CubeMX. The LwIP_HTTP_Server_Netconn_RTOS example from STM32Cube_FW_F7_V1.14.0 works just fine. The operation of LwIP_HTTP_Server_Netconn_RTOS is stable and I can send HTTP GET commands to the development board at a rapid pace. Essentially, I can send them every few milliseconds, and the devboard transmits a proper response without any unnecessary lag.

If I try to recreate the same conditions using STM32CubeMX I begin to experience periodic lag. The continuous stream of HTTP GET commands is actually sent as a burst after which the devboard seemingly crashes and I am kept waiting for a timeout. After a small halt, this communication is reestablished once again and I can send another burst of messages. If I inspect the Ethernet traffic, I can see that each crash is followed by a bunch of TCP Retransmission, TCP Previous segment not captured or TCP Dup ACK errors:

0690X000006D0MsQAK.png 

As I've mentioned before, the LwIP_HTTP_Server_Netconn_RTOS example does not behave in this kind of segmented fashion - I can continuously send and receive TCP packets to/from the board.

The code in STMCubeMX was generated in the following way:

  1. In the RCC tab HSE was set to Crystal/Ceramic Resonator (8 MHz) and the HCLK was set to 216 MHz in the Clock Configuration window.
  2. SYS timebase source was set to TIM6.
  3. Ethernet (RMII) was enabled in Connectivity->ETH.
  4. PHY address was set to 0.
  5. Pins PG13 and PG11 were set to, accordingly, ETH_TXD0 and ETH_TX_EN.
  6. FreeRTOS was enabled with all the default settings.
  7. LwIP was enable with all the default settings.
  8. Code was generated for SW4STM32.

To get some response out of the device, I’ve copied the httpserver-netconn.h and httpserver-netconn.c files and added them to my project. Since I’m only interested in very basic connectivity, I’ve commented out most of the code there (see the attached files), leaving the http server responsive only to the “GET /STM32F7xx_files/logo.jpg�? command. The http_server_netconn_init(); function was added to the StartDefaultTask thread.

A couple of things to note:

  1. I think that a similar issue has been reported earlier: https://community.st.com/s/question/0D50X00009XkYKOSA3/problem-with-slow-response-from-lwip-to-incoming-data-on-stm32f7 but this particular solution did not improve the behavior of my code.
  2. The LwIP_HTTP_Server_Netconn_RTOS example enables ICache, DCache, and MPU (also it uses a dedicated linker script for RAM reallocation). The above-described code doesn’t. I’ve tried to implement these features into the CubeMX-generated code, albeit they did not seem to fix the issue.
  3. The LwIP/FreeRTOS parameters in the LwIP_HTTP_Server_Netconn_RTOS example are (most likely) fine-tuned. I’ve looked through the lwiopts.h and FreeRTOSConfig.h files to determine the discrepancies between the CubeMX-generated code and the properly working example. I tried to set a good portion of them to match (the attached project does not implement these changes), but this did not improve the Ethernet behavior. The lwiopts.h and FreeRTOSConfig.h in the LwIP_HTTP_Server_Netconn_RTOS example are somewhat messy – they seem to be generated manually (since their structure is much different from the code generated via CubeMX), therefore it can be rather hard to track all the differences.

Now I realize that it is possible just to write my own code using the LwIP_HTTP_Server_Netconn_RTOS example as a basis. Nonetheless, this kind of approach lacks the functionality provided by CubeMX. So my questions are:

  1. Why is the LwIP_HTTP_Server_Netconn_RTOS example running properly, whereas an equivalent code generated via CubeMX is buggy?
  2. What LwIP/FreeRTOS/system parameters need to be changed to run Ethernet properly (i.e., without the windows of lag and/or TCP errors)?

I guess my end goal is to be able to generate a networking example using CubeMX that works just as well as the LwIP_HTTP_Server_Netconn_RTOS example.

4 REPLIES 4
KR1
Associate III

To illustrate my point, this is how the CubeMX-generated code responds to a “GET /STM32F7xx_files/logo.jpg�? query:

0690X000006D0PhQAK.png

And a zoomed in version:

0690X000006D0PwQAK.png

x axis represents the absolute time when the query was issued (since the beginning of the measurement). y axis represents the time it takes for the devboard to respond to the said query. When all is OK, each query is transmitted and the answer is received in a manner of few ms (therefore we get these thick, densely-packed regions of transmission/reception). The sharp spikes with the huge gaps in x-axis in-between them represent the time when the said TCP issues take place.

Contrarily, these are the results that I get from the LwIP_HTTP_Server_Netconn_RTOS example:

0690X000006D0RsQAK.png

Essentially, I always get response on average in about 2.66 ms (with a standard deviation of 3.5 ms).

KR1
Associate III

So I spent almost two days trying to unravel this mysterious behavior and I think that I have found the cause (or at least I am 95% certain). I will share my findings because I think that this issue is important to anyone who is doing any networking on the STM32 microcontrollers. There are quite a few differences between the STM32CubeMX-generated code and the LwIP_HTTP_Server_Netconn_RTOS example from STM32Cube_FW_F7_V1.14.0 (mostly in the FreeRTOS and LwIP setup). In a desperate attempt to find which parameters cause the Ethernet issues I have tried to:

  1. Apply the FreeRTOS/LwIP parameters from the STM32CubeMX-generated code to the LwIP_HTTP_Server_Netconn_RTOS example (in order to make it crash);
  2. Apply the FreeRTOS/LwIP parameters from LwIP_HTTP_Server_Netconn_RTOS example to the STM32CubeMX-generated code (in order to make it work);

Nonetheless, all the imposed changes did not seem to bring any results. Despite all the code changes STM32CubeMX-generated code was always working improperly, whereas the LwIP_HTTP_Server_Netconn_RTOS example always seemed to execute mostly fine.

After a careful examination of all the project files, I have noticed that the Ethernet configuration in stm32f7xx_hal_conf.h is actually different:

/* Section 2: PHY configuration section */
/* LAN8742A PHY Address*/
#define LAN8742A_PHY_ADDRESS            0x00U
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
#define PHY_RESET_DELAY                 ((uint32_t)0x00000FFFU)
/* PHY Configuration delay */
#define PHY_CONFIG_DELAY                ((uint32_t)0x00000FFFU)
 
#define PHY_READ_TO                     ((uint32_t)0x0000FFFFU)
#define PHY_WRITE_TO                    ((uint32_t)0x0000FFFFU)
 
/* Section 3: Common PHY Registers */
 
#define PHY_BCR                         ((uint16_t)0x00U)    /*!< Transceiver Basic Control Register   */
#define PHY_BSR                         ((uint16_t)0x01U)    /*!< Transceiver Basic Status Register    */
 
#define PHY_RESET                       ((uint16_t)0x8000U)  /*!< PHY Reset */
#define PHY_LOOPBACK                    ((uint16_t)0x4000U)  /*!< Select loop-back mode */
#define PHY_FULLDUPLEX_100M             ((uint16_t)0x2100U)  /*!< Set the full-duplex mode at 100 Mb/s */
#define PHY_HALFDUPLEX_100M             ((uint16_t)0x2000U)  /*!< Set the half-duplex mode at 100 Mb/s */
#define PHY_FULLDUPLEX_10M              ((uint16_t)0x0100U)  /*!< Set the full-duplex mode at 10 Mb/s  */
#define PHY_HALFDUPLEX_10M              ((uint16_t)0x0000U)  /*!< Set the half-duplex mode at 10 Mb/s  */
#define PHY_AUTONEGOTIATION             ((uint16_t)0x1000U)  /*!< Enable auto-negotiation function     */
#define PHY_RESTART_AUTONEGOTIATION     ((uint16_t)0x0200U)  /*!< Restart auto-negotiation function    */
#define PHY_POWERDOWN                   ((uint16_t)0x0800U)  /*!< Select the power down mode           */
#define PHY_ISOLATE                     ((uint16_t)0x0400U)  /*!< Isolate PHY from MII                 */
 
#define PHY_AUTONEGO_COMPLETE           ((uint16_t)0x0020U)  /*!< Auto-Negotiation process completed   */
#define PHY_LINKED_STATUS               ((uint16_t)0x0004U)  /*!< Valid link established               */
#define PHY_JABBER_DETECTION            ((uint16_t)0x0002U)  /*!< Jabber condition detected            */
  
/* Section 4: Extended PHY Registers */
 
#define PHY_SR                          ((uint16_t)0x1FU)    /*!< PHY special control/ status register Offset     */
 
#define PHY_SPEED_STATUS                ((uint16_t)0x0004U)  /*!< PHY Speed mask                                  */
#define PHY_DUPLEX_STATUS               ((uint16_t)0x0010U)  /*!< PHY Duplex mask                                 */
 
 
#define PHY_ISFR                        ((uint16_t)0x1DU)    /*!< PHY Interrupt Source Flag register Offset       */
#define PHY_ISFR_INT4                   ((uint16_t)0x0010U)  /*!< PHY Link down inturrupt                         */

in LwIP_HTTP_Server_Netconn_RTOS example, and:

/* Section 2: PHY configuration section */
 
/* LAN8742A_PHY_ADDRESS Address*/ 
#define LAN8742A_PHY_ADDRESS           0
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ 
#define PHY_RESET_DELAY                 ((uint32_t)0x000000FFU)
/* PHY Configuration delay */
#define PHY_CONFIG_DELAY                ((uint32_t)0x00000FFFU)
 
#define PHY_READ_TO                     ((uint32_t)0x0000FFFFU)
#define PHY_WRITE_TO                    ((uint32_t)0x0000FFFFU)
 
/* Section 3: Common PHY Registers */
 
#define PHY_BCR                         ((uint16_t)0x00U)    /*!< Transceiver Basic Control Register   */
#define PHY_BSR                         ((uint16_t)0x01U)    /*!< Transceiver Basic Status Register    */
 
#define PHY_RESET                       ((uint16_t)0x8000U)  /*!< PHY Reset */
#define PHY_LOOPBACK                    ((uint16_t)0x4000U)  /*!< Select loop-back mode */
#define PHY_FULLDUPLEX_100M             ((uint16_t)0x2100U)  /*!< Set the full-duplex mode at 100 Mb/s */
#define PHY_HALFDUPLEX_100M             ((uint16_t)0x2000U)  /*!< Set the half-duplex mode at 100 Mb/s */
#define PHY_FULLDUPLEX_10M              ((uint16_t)0x0100U)  /*!< Set the full-duplex mode at 10 Mb/s  */
#define PHY_HALFDUPLEX_10M              ((uint16_t)0x0000U)  /*!< Set the half-duplex mode at 10 Mb/s  */
#define PHY_AUTONEGOTIATION             ((uint16_t)0x1000U)  /*!< Enable auto-negotiation function     */
#define PHY_RESTART_AUTONEGOTIATION     ((uint16_t)0x0200U)  /*!< Restart auto-negotiation function    */
#define PHY_POWERDOWN                   ((uint16_t)0x0800U)  /*!< Select the power down mode           */
#define PHY_ISOLATE                     ((uint16_t)0x0400U)  /*!< Isolate PHY from MII                 */
 
#define PHY_AUTONEGO_COMPLETE           ((uint16_t)0x0020U)  /*!< Auto-Negotiation process completed   */
#define PHY_LINKED_STATUS               ((uint16_t)0x0004U)  /*!< Valid link established               */
#define PHY_JABBER_DETECTION            ((uint16_t)0x0002U)  /*!< Jabber condition detected            */
  
/* Section 4: Extended PHY Registers */
#define PHY_SR                          ((uint16_t)0x10U)    /*!< PHY status register Offset                      */
 
#define PHY_SPEED_STATUS                ((uint16_t)0x0002U)  /*!< PHY Speed mask                                  */
#define PHY_DUPLEX_STATUS               ((uint16_t)0x0004U)  /*!< PHY Duplex mask                                 */
 
#define PHY_ISFR                        ((uint16_t)0x000BU)    /*!< PHY Interrupt Source Flag register Offset   */
#define PHY_ISFR_INT4                   ((uint16_t)0x000BU)  /*!< PHY Link down inturrupt       */  

in STM32CubeMX-generated code.

So it appears that the default Ethernet settings (ETH->Advanced Parameters) are not suitable for the LAN8742A driver. After changing the Ethernet parameters for the STM32CubeMX-generated code and the LwIP_HTTP_Server_Netconn_RTOS example I have managed to get former code running and the latter code to crash. Now in truth the default STM32CubeMX-generated code can still crash once every few minutes, but that most likely has to do with not optimized memory management for FreeRTOS/Lwip. Nonetheless, it is quite an improvement from crashes every 2-3 seconds.

It would be great if someone from STM32 (or soeone who has more experience with STM32 networking) could verify if these findings are in fact correct.

HKim.101
Associate

Hi,

I downloaded your attached file and compiled. I also download it. How can I check it works? I want to make sure ethernet is working.

Do I have to use cmd or any tool?

How can I select LwIP_HTTP_Server_Netconn_RTOS in STM32CubeMX? Now I'm using STM32Cube FW_F7 V1.15.0.

Piranha
Chief II