2025-01-10 03:08 AM - last edited on 2025-01-10 08:00 AM by Andrew Neil
Dear ST Support Team,
I am working on the STM32H7S78-DK board and have successfully implemented a TouchGFX-based project. However, I am facing issues when trying to add Ethernet support to the project while using FreeRTOS.
When I call MX_LWIP_Init(), the code gets stuck after entering this function. If I comment out or disable MX_LWIP_Init(), the TouchGFX functionality works perfectly. The same Ethernet code works without any issues in a standalone project (without FreeRTOS and TouchGFX).
I have verified the Ethernet GPIO configuration and settings, and everything appears to be correct. The Ethernet code has been tested successfully without FreeRTOS. However, integrating the same code into the TouchGFX project with FreeRTOS results in the issue described above.
Could you please help me identify the cause of this behaviour and provide guidance on resolving it?
Here I attached some code for reference.
#include "main.h"
#include "FreeRTOS.h"
#include "cmsis_os2.h"
#include "app_touchgfx.h"
#include "lwip.h"
#include "stdio.h"
#include <string.h>
#include "udpClientRAW.h"
extern struct netif gnetif;
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for TouchGFXTask */
osThreadId_t TouchGFXTaskHandle;
const osThreadAttr_t TouchGFXTask_attributes = {
.name = "TouchGFXTask",
.stack_size = 4096 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_HPDMA1_Init(void);
static void MX_LTDC_Init(void);
static void MX_CRC_Init(void);
static void MX_DMA2D_Init(void);
static void MX_JPEG_Init(void);
static void MX_FLASH_Init(void);
static void MX_I2C1_Init(void);
static void MX_GPU2D_Init(void);
static void MX_ICACHE_GPU2D_Init(void);
static void MX_UART4_Init(void);
void StartDefaultTask(void *argument);
extern void TouchGFX_Task(void *argument);
osThreadId_t uartTaskHandle;
const osThreadAttr_t uartTask_attributes =
{
.name = "uartTask",
.priority = (osPriority_t)osPriorityNormal,
.stack_size = 512 * 4,
};
void UART_Task(void *argument)
{
for (;;)
{
printf("UART_Task\n\r");
// Wait for 5 seconds
osDelay(2000); // Delay in milliseconds
UH_SendUDPData();
}
}
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* Enable the CPU Cache */
/* Enable I-Cache---------------------------------------------------------*/
SCB_EnableICache();
/* Enable D-Cache---------------------------------------------------------*/
SCB_EnableDCache();
/* MCU Configuration--------------------------------------------------------*/
/* Update SystemCoreClock variable according to RCC registers values. */
SystemCoreClockUpdate();
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_HPDMA1_Init();
MX_LTDC_Init();
MX_CRC_Init();
MX_DMA2D_Init();
MX_JPEG_Init();
MX_FLASH_Init();
MX_I2C1_Init();
MX_GPU2D_Init();
MX_ICACHE_GPU2D_Init();
MX_UART4_Init();
UART_Print("Start...TouchGFX...Project\n\r");
printf("Hello_STM32H7S78-DK!\n\r");
MX_TouchGFX_Init();
/* Call PreOsInit function */
MX_TouchGFX_PreOSInit();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize();
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* creation of TouchGFXTask */
TouchGFXTaskHandle = osThreadNew(TouchGFX_Task, NULL, &TouchGFXTask_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
uartTaskHandle = osThreadNew(UART_Task, NULL, &uartTask_attributes);
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN 5 */
printf("StartDefaultTask\n\r");
MX_LWIP_Init();
udpClient_connect();
/* Infinite loop */
for(;;)
{
osDelay(1);
ethernetif_input(&gnetif);
sys_check_timeouts();
}
/* USER CODE END 5 */
}
void MX_LWIP_Init(void)
{
/* IP addresses initialization */
IP_ADDRESS[0] = 169;
IP_ADDRESS[1] = 254;
IP_ADDRESS[2] = 250;
IP_ADDRESS[3] = 70;
NETMASK_ADDRESS[0] = 255;
NETMASK_ADDRESS[1] = 255;
NETMASK_ADDRESS[2] = 0;
NETMASK_ADDRESS[3] = 0;
GATEWAY_ADDRESS[0] = 169;
GATEWAY_ADDRESS[1] = 254;
GATEWAY_ADDRESS[2] = 250;
GATEWAY_ADDRESS[3] = 1;
/* USER CODE BEGIN IP_ADDRESSES */
/* USER CODE END IP_ADDRESSES */
/* Initialize the LwIP stack with RTOS */
tcpip_init( NULL, NULL );
/* IP addresses initialization without DHCP (IPv4) */
IP4_ADDR(&ipaddr, IP_ADDRESS[0], IP_ADDRESS[1], IP_ADDRESS[2], IP_ADDRESS[3]);
IP4_ADDR(&netmask, NETMASK_ADDRESS[0], NETMASK_ADDRESS[1] , NETMASK_ADDRESS[2], NETMASK_ADDRESS[3]);
IP4_ADDR(&gw, GATEWAY_ADDRESS[0], GATEWAY_ADDRESS[1], GATEWAY_ADDRESS[2], GATEWAY_ADDRESS[3]);
/* add the network interface (IPv4/IPv6) with RTOS */
netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
/* Registers the default network interface */
netif_set_default(&gnetif);
ethernet_link_status_updated(&gnetif);
/* Set the link callback function, this function is called on change of link status*/
netif_set_link_callback(&gnetif, ethernet_link_status_updated);
/* Create the Ethernet link handler thread */
/* USER CODE BEGIN H7_OS_THREAD_NEW_CMSIS_RTOS_V2 */
memset(&attributes, 0x0, sizeof(osThreadAttr_t));
attributes.name = "EthLink";
attributes.stack_size = INTERFACE_THREAD_STACK_SIZE;
attributes.priority = osPriorityBelowNormal;
osThreadNew(ethernet_link_thread, &gnetif, &attributes);
/* USER CODE END H7_OS_THREAD_NEW_CMSIS_RTOS_V2 */
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
}
/*
***************************************************************************************************************
***************************************************************************************************************
***************************************************************************************************************
File: udpClientRAW.c
Author: ControllersTech.com
Updated: Jul 23, 2021
***************************************************************************************************************
Copyright (C) 2017 ControllersTech.com
This is a free software under the GNU license, you can redistribute it and/or modify it under the terms
of the GNU General Public License version 3 as published by the Free Software Foundation.
This software library is shared with public for educational purposes, without WARRANTY and Author is not liable for any damages caused directly
or indirectly by this software, read more about this on the GNU General Public License.
***************************************************************************************************************
*/
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "stdio.h"
#include "string.h"
#include "udpClientRAW.h"
void udp_receive_callback_client(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
static void udpClient_send(void);
struct udp_pcb *upcb;
char buffer[100];
int counter = 0;
extern TIM_HandleTypeDef htim1;
void UH_SendUDPData(void)
{
printf("UH_SendUDPData\n\r");
udpClient_send();
}
/* IMPLEMENTATION FOR UDP CLIENT : source:https://www.geeksforgeeks.org/udp-server-client-implementation-c/
1. Create UDP socket.
2. Send message to server.
3. Wait until response from server is received.
4. Process reply and go back to step 2, if necessary.
5. Close socket descriptor and exit.
*/
void udpClient_connect(void)
{
printf("udpClient_connect\n\r");
err_t err;
/* 1. Create a new UDP control block */
upcb = udp_new();
/* Bind the block to module's IP and port */
ip_addr_t myIPaddr;
IP_ADDR4(&myIPaddr, 169, 254, 250, 70);
err = udp_bind(upcb, &myIPaddr, 49152);
if (err == ERR_OK)
{
printf("udp_bind successfully \n\r");
printf("Bound to IP: %s, Port: %d\n\r", ip4addr_ntoa(&upcb->local_ip), upcb->local_port);
}
/* configure destination IP address and port */
ip_addr_t DestIPaddr;
IP_ADDR4(&DestIPaddr, 169, 254, 250, 76);
err = udp_connect(upcb, &DestIPaddr, 49153);
if (err == ERR_OK)
{
printf("udpClient_send\n\r");
/* 2. Send message to server */
udpClient_send ();
/* 3. Set a receive callback for the upcb */
udp_recv(upcb, udp_receive_callback_client, NULL);
}
}
static void udpClient_send(void)
{
struct pbuf *txBuf;
char data[100];
err_t err;
printf("udpClient_send to IP: %s, Port: %d\n\r", ip4addr_ntoa(&upcb->remote_ip), upcb->remote_port);
int len = sprintf(data, "sending UDP client message %d\n\r", counter);
/* allocate pbuf from pool*/
txBuf = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if (txBuf != NULL)
{
/* copy data to pbuf */
pbuf_take(txBuf, data, len);
/* send udp data */
err = udp_send(upcb, txBuf);
if(err != ERR_OK)
{
printf("udp_send fails with err : %d\n\r",err);
}
else
{
printf("udpClient_send (%s)\n\r",(char *)data);
}
/* free pbuf */
pbuf_free(txBuf);
}
}
void udp_receive_callback_client(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
printf("udp_receive_client_callback_\n\r");
/* Copy the data from the pbuf */
strncpy (buffer, (char *)p->payload, p->len);
/*increment message count */
counter++;
/* Free receive pbuf */
pbuf_free(p);
}
Your support will be greatly appreciated.
Best regards,
Mehul