Skip to main content
Graduate
June 10, 2025
Question

Ethernet/LWIP Problems on the STM32H755ZIQ nucleo-board

  • June 10, 2025
  • 4 replies
  • 995 views

Hello,

I am currently attempting to get the ethernet set up on my eval board. The project goal is to use a timer on the eval board to trigger the board to call out to a PLC on my network to receive 8 values every 1 second. Those values will then be stored in specific corresponding variables in the main.c file to be used in another function later on. I have attempted to follow several examples and use some AI to help me debug but I have hit a wall. I have zero errors when building out the project and running the debugger. It appears to flash onto the device but then nothing happens.

List of the places that I have tried to debug with a simple toggle GPIO command on one of the user LEDs

-user code section 2 : did toggle successfully on

-main while loop : does not work

-user code section 4 with in my modbus request : does not work

I have had several cases where it appears when the debugger asks me to resume the process it sends me to the hard fault handler in stm32H7xx_it.c, but this leaves me even more confused as to where to begin my debug process as I am so new to this. I at one point could ping the STM32 on my network but now I unfortunately get destination host unreachable. However, all of the hardware lights on the ethernet port do work!

 

The following are the components in the hardware config that I have activated and their settings:

System Core: GPIO / set USER LEDs to GPIO output on the M7 core only, no other changes

Timers: TIM2 activated on M7 / Counter period to 240000000 / TRGO set to Reset / NVIC TIM2 global interrupt checked

Connectivity: ETH activated on M7 only / NVIC global interrupt checked

Connectivity: USART3 Activated for Asynchronous mode

Middleware: FREERTOS_M7 on / API set to CMSIS v1 / USE_NEWLIB_REENTRANT Enabled / Default Task Enabled

Middleware: LWIP Enabled for M7 / DHCP disabled and static IP set / Platform settings to LAN8742

 

The following is the code I have implemented in my main.c ----------------------

 
#include "cmsis_os.h"

#include "lwip.h"

/* USER CODE BEGIN Includes */

#include "lwip/api.h"

#include "lwip/netbuf.h"

#include "lwip/ip_addr.h"

#include "lwip/tcp.h"

#include <string.h>

#include <stdio.h>



/* USER CODE END Includes */

/* USER CODE BEGIN PV */

/* Ethernet Packet Buffer */

uint8_t modbus_tx_buffer[12]; // Modbus Request Frame

uint8_t modbus_rx_buffer[1024];



/* Variables to store received Modbus values */

float phase_set_point, amplitude_set_point;

float phase_p, phase_i, phase_d;

float amp_p, amp_i, amp_d;



/* UART Debug Buffer */

uint8_t uart_msg[100];

extern UART_HandleTypeDef huart3;

/* USER CODE END PV */

/* USER CODE BEGIN 2 */

/* Initialize LWIP and Ethernet */

MX_LWIP_Init();



/* Start TIM2 for Modbus updates */

MX_TIM2_Init();

HAL_TIM_Base_Start_IT(&htim2);

/* USER CODE END 2 */

/* USER CODE BEGIN 4 */

void modbus_send_request(void)

{

struct netconn *conn;

struct netbuf *buf;

ip_addr_t server_ip;



IP4_ADDR(&server_ip, 000, 000, 000, 000);

conn = netconn_new(NETCONN_TCP);



if (conn != NULL)

{

if (netconn_connect(conn, &server_ip, 502) == ERR_OK)

{

modbus_tx_buffer[0] = 0x00;

modbus_tx_buffer[1] = 0x01;

modbus_tx_buffer[2] = 0x00;

modbus_tx_buffer[3] = 0x00;

modbus_tx_buffer[4] = 0x00;

modbus_tx_buffer[5] = 0x06;

modbus_tx_buffer[6] = 0x01;

modbus_tx_buffer[7] = 0x03;

modbus_tx_buffer[8] = 0xD4;

modbus_tx_buffer[9] = 0xDC;

modbus_tx_buffer[10] = 0x00;

modbus_tx_buffer[11] = 0x10;



netconn_write(conn, modbus_tx_buffer, 12, NETCONN_NOCOPY);



if (netconn_recv(conn, &buf) == ERR_OK && buf != NULL)

{

memcpy(modbus_rx_buffer, buf->p->payload, buf->p->len);

netbuf_delete(buf);



phase_set_point = (modbus_rx_buffer[9] << ‌‌ | modbus_rx_buffer[10];

amplitude_set_point = (modbus_rx_buffer[11] << ‌‌ | modbus_rx_buffer[12];

phase_p = (modbus_rx_buffer[13] << ‌‌ | modbus_rx_buffer[14];

phase_i = (modbus_rx_buffer[15] << ‌‌ | modbus_rx_buffer[16];

phase_d = (modbus_rx_buffer[17] << ‌‌ | modbus_rx_buffer[18];

amp_p = (modbus_rx_buffer[19] << ‌‌ | modbus_rx_buffer[20];

amp_i = (modbus_rx_buffer[21] << ‌‌ | modbus_rx_buffer[22];

amp_d = (modbus_rx_buffer[23] << ‌‌ | modbus_rx_buffer[24];



sprintf((char*)uart_msg, "Modbus Data: PSet=%.2f, ASet=%.2f\n", phase_set_point, amplitude_set_point);

HAL_UART_Transmit(&huart3, uart_msg, strlen((char*)uart_msg), HAL_MAX_DELAY);

}



netconn_close(conn);

netconn_delete(conn);

}

}

}



void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

if (htim->Instance == TIM2)

{

modbus_send_request();

HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14);

}

}

/* USER CODE END 4 */

I have left the IP address blank on purpose

I will also say that I have tried to click through every line and over things in the main.c file, it appeared that it was breaking after osKernelStart but I am unsure at this time.

/* Create the thread(s) */

/* definition and creation of defaultTask */

osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);

defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);



/* USER CODE BEGIN RTOS_THREADS */

/* add threads, ... */

/* USER CODE END RTOS_THREADS */



/* Start scheduler */

osKernelStart();



/* We should never get here as control is now taken by the scheduler */

 

Any help or ideas of where to go from here would be greatly appreciated or tutorials that you might know of, thank you!

 

    This topic has been closed for replies.

    4 replies

    Technical Moderator
    June 11, 2025

    Hello,

    Sorry, the code is not clear. Especially, nothing tells where main program starts!

    "-main while loop : does not work" -> where that "main while loop" is located?

    How to debug a HardFault on an Arm® Cortex®-M STM32

    kyleg4032Author
    Graduate
    June 11, 2025

    I apologize for the confusion! I will attach the main.c file in its entirety with this message.

    Thank you!

    Technical Moderator
    June 11, 2025

    1- "user code section 2 : did toggle successfully on"

    -> what line are you referring to in the attached main.c?

    2- "main while loop : does not work"

    -> which line? 

    3- Are you reaching HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14) in HAL_TIM_PeriodElapsedCallback()?

     

    Technical Moderator
    June 12, 2025

    Hello @kyleg4032

    In addition to what @mƎALLEm suggested, and after reviewing the code you shared, I believe that LWIP and FreeRTOS might be misconfigured.

    Firstly, the stack size you’re using (128 words) appears to be smaller than the recommended size mentioned in our knowledge base article and other similar projects. Additionally, it looks like LWIP is being initialized twice—once in main and again in a FreeRTOS task. Finally, in the default task, the initialization task hasn’t been deleted after completing the setup.

    I suggest reviewing your project configuration and cross-checking it with this KB article:

    Once you’ve made the necessary adjustments, we can return to debugging and work towards resolving your issue.

     

    Best regards,

    kyleg4032Author
    Graduate
    June 12, 2025

    Hi @STackPointer64,

    So after reading through that KB article you linked, I decided to start again from scratch. I saved my user code in visual studio for later once I can get the ethernet actually up and running. I therefore created a new CubeIDE project and followed along exactly with the article. I then added breakpoints and a GPIO toggle just before the osKernalStart and after. Unfortunately, my code still does not leave the osKernalStart. However, this time it is getting stuck in a different place, specifically memp.c. I will provide a screenshot of the location and code:

    /* create a linked list of memp elements */
    
    for (i = 0; i < desc->num; ++i) {
    
    memp->next = *desc->tab;
    
    *desc->tab = memp;
    
    #if MEMP_OVERFLOW_CHECK
    
    memp_overflow_init_element(memp, desc);
    
    #endif /* MEMP_OVERFLOW_CHECK */
    
    /* cast through void* to get rid of alignment warnings */
    
    memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size
    
    #if MEMP_OVERFLOW_CHECK
    
    + MEM_SANITY_REGION_AFTER_ALIGNED
    
    #endif
    
    );
    
    }
    
    #if MEMP_STATS
    
    desc->stats->avail = desc->num;
    
    #endif /* MEMP_STATS */
    
    #endif /* !MEMP_MEM_MALLOC */
    
    
    
    #if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY)
    
    desc->stats->name = desc->desc;
    
    #endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */
    
    }
    
    
    
    /**
    
    * Initializes lwIP built-in pools.
    
    * Related functions: memp_malloc, memp_free
    
    *
    
    * Carves out memp_memory into linked lists for each pool-type.
    
    */
    
    void
    
    memp_init(void)
    
    {
    
    u16_t i;
    
    
    
    /* for every pool: */
    
    for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) {
    
    memp_init_pool(memp_pools[i]);
    
    
    
    #if LWIP_STATS && MEMP_STATS
    
    lwip_stats.memp[i] = memp_pools[i]->stats;
    
    #endif
    
    }

    If you were to open memp.c, this would be lines 193-235. I am almost positive I followed the article to a T.

     

    I appreciate the help!

    kyleg4032Author
    Graduate
    June 12, 2025

    I realize I should have specified, it creates an endless loop and never leaves!

    Technical Moderator
    June 13, 2025

    Hello @kyleg4032,

    You are currently working in a Real-Time Operating System (RTOS) environment, which operates differently from a traditional bare-metal or non-RTOS environment. In an RTOS, tasks are managed and scheduled by the operating system, ensuring that each task gets the CPU time it needs based on priority and timing requirements. This means you cannot rely on traditional infinite while loops to handle your application's logic, as this would block the CPU and prevent other tasks from running.

    Instead, you should create a thread (or task) in the RTOS in STM32CubeMX, to define your application's behavior. Each thread runs independently and cooperatively with other threads, allowing the RTOS to manage task scheduling efficiently. This approach ensures that your application remains responsive and adheres to real-time constraints.

    Thread creation and configuration can be done in STM32CubeMX FreeRTOS settings under Tasks and Queues. Leave the default task as it is, and create a new task that will handle the execution of your Modbus program flow.

    To better understand these concepts, I highly recommend exploring the following:

    1. FreeRTOS Documentation: Learn how to create and manage tasks, use synchronization primitives (e.g., semaphores, queues), and understand task priorities.

    2. RTOS Tutorials: Look for beginner-friendly guides or video tutorials on RTOS concepts to grasp task scheduling, preemption, and inter-task communication.

    3. LwIP Documentation: Familiarize yourself with how LwIP works in an RTOS environment. This will help you understand how to integrate networking into your application.

    By studying these resources, you’ll gain a solid understanding of how to design and implement applications in an RTOS environment effectively.

    Best regards,

    Technical Moderator
    June 25, 2025

    Hello once again @kyleg4032,

    Have you managed to resolve your problem? If so, please click Accept as Solution on the reply that helped you. This will assist other users who may have the same issue in the future.

    Best regards,

    kyleg4032Author
    Graduate
    June 30, 2025

    Hi @STackPointer64 ,

    I apologize for the late reply, I so far have not come up with a way to resolve my problem and due to time constraints on what I am doing, I have decided to forgo the use of Ethernet in my project at this time. I have had the USB communication running for quite some time and created a python code that will work in tandem with the microcontroller so it will receive the values it requires to function over that USB communication.

     

    In the future though, I might return to try and get the Ethernet capabilities up and running but not for this initial design I am working on.

     

    Thank you again though for taking the time to reply and provide resources to help me, I truly appreciate it!

     

    -Kyle

    Technical Moderator
    June 30, 2025

    Hello,

    Thank you for your update @kyleg4032. You’re very welcome! It’s great to hear you’ve made progress with the USB communication and Python integration. Prioritizing your project timeline is important, and returning to Ethernet later sounds like a solid plan. If you need any help in the future, don’t hesitate to ask.

    Best regards,