Hello,
Summary:
- Environnement
- What I want to do
- What I have done
- What my problem is
- Questions
- Code sample
##### ENVIRONMENT #####
Card : STM32H723ZG
PC : Computer with Windows 10
IDE : stm32cubeIDE
Compiler : GCC 9.2.0
FreeRTOS : 202212.01
##### What I want to do #####
I want to ping my STM32 and later set it as a client (in this question I tried maing a server, not a client).
You can get more informations about my project here : STM32H7 TCP DMATxDscrTab double declaration in main.c and NetworkInterface.c, if I remove it from one of the files it becomes undeclared
##### What I have done #####
I was able to make a simple FreeRTOS project with 2 tasks. I then moved to to initializing FreeRTOS plus TCP.
##### What my problem is #####
I started trying to make a TCP server.
I am following the tutorial here : TCP Networking Tutorial - Creating, Configuring and Binding TCP Client and Server Sockets
I also need to choose between reading or sending data, so I decided to receive data following this tutorial : TCP Networking Tutorial - Receiving Data Using a TCP Socket
When I run, I get stuck in the
configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
on line 140.
This is because
FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP);
returns FREERTOS_INVALID_SOCKET.
In the file FreeRTOS_Sockets.c, in the function FreeRTOS_socket, this âifâ statement is entered :
if( prvDetermineSocketSize( xDomain, xType, xProtocolCpy, &uxSocketSize ) == pdFAIL )
{
/* MISRA Ref 11.4.1 [Socket error and integer to pointer conversion] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-114 */
/* coverity[misra_c_2012_rule_11_4_violation] */
xReturn = FREERTOS_INVALID_SOCKET;
}
So prvDetermineSocketSize returns pdFail.
in the function prvDetermineSocketSize, this âifâ statement is entered :
/* Asserts must not appear before it has been determined that the network
* task is ready - otherwise the asserts will fail. */
if( xIPIsNetworkTaskReady() == pdFALSE )
{
xReturn = pdFAIL;
}
And finaly, in the file FreeRTOS_IP.c, xIPIsNetworkTaskReady is defined as:
BaseType_t xIPIsNetworkTaskReady( void )
{
return xIPTaskInitialised;
}
So xIPTaskInitialised is set to pdFALSE.
In file FreeRTOS_IP.c, we can see the declaration of xIPTaskInitialised set to pdFALSE on line 227.
The only way for xIPTaskInitialised to be set to psTRUE is in the same file on line 295 inside the function prvIPTask.
I did a global researche and prvIPTask is not mentionned (called) in any file other than FreeRTOS_IP.c.
It mention in the brief
The IP task handles all requests from the user application and the network interface. It receives messages through a FreeRTOS queue called âxNetworkEventQueueâ.
So I donât know when and how this function is called as it is not one of the âhook/callback APIâ mentionned in the website.
##### Question #####
- What do I have to change in my program to make it work
- When and where is prvIPTask called?
- Should I manually set xTasksAlreadyCreated to pdTRUE ?
##### Code sample #####
The main:
/* Standard includes. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <ctype.h>
//#include <winsock.h>
/*
#ifdef __linux__ // include the socket library
#include <sys/socket.h>
#elif _WIN32
#include <Winsock2.h>
#else
#include "socket.h"
#endif
*/
/* cubeMX/HAL includes */
#include "main.h"
#include "string.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "phyHandling.h"
#if( ipconfigMULTI_INTERFACE != 0 )
#include "FreeRTOS_Routing.h"
#include "FreeRTOS_ND.h"
#endif
ETH_TxPacketConfig TxConfig;
#define usUsedStackSize 128
#define BUFFER_SIZE 512
/* cube mx generated handler */
ETH_HandleTypeDef heth;
UART_HandleTypeDef huart3;
/* task handlers */
/* The MAC address array is not declared const as the MAC address will
normally be read from an EEPROM and not hard coded (in real deployed applications).*/
static uint8_t ucMACAddress[ 6 ] = { 0x00, 0x80, 0xE1, 0x00, 0x00, 0x00 };
/* Define the network addressing. These parameters will be used if either
ipconfigUDE_DHCP is 0 or if ipconfigUSE_DHCP is 1 but DHCP auto configuration failed. */
static const uint8_t ucIPAddress[ 4 ];
static const uint8_t ucNetMask[ 4 ];
static const uint8_t ucGatewayAddress[ 4 ];
/* The following is the address of the DNS server. */
static const uint8_t ucDNSServerAddress[ 4 ] = { 192, 168, 73, 220 };
/* Random Number Generator variable. */
static RNG_HandleTypeDef hrng;
/* cube MX generated function definitions */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_USB_OTG_HS_USB_Init(void);
/* TCP function definition */
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );
BaseType_t xApplicationGetRandomNumber( uint32_t *pulValue );
void vCreateTCPServerSocket(void);
void prvProcessData(char *cRxedData, BaseType_t lBytesReceived);
/* task function definitions (the ones that doens't do tcp thing */
static void prvEchoClientRxTask(void *pvParameters);
int main(void)
{
/* cube mx generated */
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART3_UART_Init();
MX_USB_OTG_HS_USB_Init();
uint8_t buffer[20];
sprintf((char*)buffer, "Entered main\r\n\n");
HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
/* TCP init */
FreeRTOS_IPInit(ucIPAddress,
ucNetMask,
ucGatewayAddress,
ucDNSServerAddress,
ucMACAddress );
vCreateTCPServerSocket(); //allocate and initialise a socket
/* task creation */
/* starting rtos scheduler */
vTaskStartScheduler();
for(;;);
}
void vCreateTCPServerSocket(void)
{
struct freertos_sockaddr xClient, xBindAddress;
Socket_t xListeningSocket, xConnectedSocket;
socklen_t xSize = sizeof( xClient );
static const TickType_t xReceiveTimeOut = portMAX_DELAY;
const BaseType_t xBacklog = 20;
/* Attempt to open the socket. */
xListeningSocket = FreeRTOS_socket(FREERTOS_AF_INET,
FREERTOS_SOCK_STREAM, /* SOCK_STREAM for TCP. */
FREERTOS_IPPROTO_TCP);
/* Check the socket was created. */
configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET ); //block here because xListeningSocket return FREERTOS_INVALID_SOCKET
/* If FREERTOS_SO_RCVBUF or FREERTOS_SO_SNDBUF are to be used with
FreeRTOS_setsockopt() to change the buffer sizes from their default then do
it here!. (see the FreeRTOS_setsockopt() documentation. */
/* If ipconfigUSE_TCP_WIN is set to 1 and FREERTOS_SO_WIN_PROPERTIES is to
be used with FreeRTOS_setsockopt() to change the sliding window size from
its default then do it here! (see the FreeRTOS_setsockopt()
documentation. */
/* Set a time out so accept() will just wait for a connection. */
FreeRTOS_setsockopt( xListeningSocket,
0,
FREERTOS_SO_RCVTIMEO,
&xReceiveTimeOut,
sizeof( xReceiveTimeOut ) );
/* Set the listening port to 10000. */
xBindAddress.sin_port = ( uint16_t ) 10000;
xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
/* Bind the socket to the port that the client RTOS task will send to. */
FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
/* Set the socket into a listening state so it can accept connections.
The maximum number of simultaneous connections is limited to 20. */
FreeRTOS_listen( xListeningSocket, xBacklog );
for( ;; )
{
/* Wait for incoming connections. */
xConnectedSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize );
configASSERT( xConnectedSocket != FREERTOS_INVALID_SOCKET );
/* Spawn a RTOS task to handle the connection. */
xTaskCreate( prvEchoClientRxTask,
"EchoServer",
usUsedStackSize,
( void * ) xConnectedSocket,
tskIDLE_PRIORITY,
NULL );
}
}
static void prvEchoClientRxTask( void *pvParameters )
{
Socket_t xSocket;
static char cRxedData[ BUFFER_SIZE ];
BaseType_t lBytesReceived;
/* It is assumed the socket has already been created and connected before
being passed into this RTOS task using the RTOS task's parameter. */
xSocket = ( Socket_t ) pvParameters;
for( ;; )
{
/* Receive another block of data into the cRxedData buffer. */
lBytesReceived = FreeRTOS_recv( xSocket, &cRxedData, BUFFER_SIZE, 0 );
if( lBytesReceived > 0 )
{
/* Data was received, process it here. */
prvProcessData(cRxedData, lBytesReceived);
}
else if( lBytesReceived == 0 )
{
/* No data was received, but FreeRTOS_recv() did not return an error.
Timeout? */
}
else
{
/* Error (maybe the connected socket already shut down the socket?).
Attempt graceful shutdown. */
FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );
break;
}
}
/* The RTOS task will get here if an error is received on a read. Ensure the
socket has shut down (indicated by FreeRTOS_recv() returning a -pdFREERTOS_ERRNO_EINVAL
error before closing the socket). */
while( FreeRTOS_recv( xSocket, &cRxedData, BUFFER_SIZE, 0 ) >= 0 )
{
/* Wait for shutdown to complete. If a receive block time is used then
this delay will not be necessary as FreeRTOS_recv() will place the RTOS task
into the Blocked state anyway. */
vTaskDelay(pdMS_TO_TICKS(250));
/* Note - real applications should implement a timeout here, not just
loop forever. */
}
/* Shutdown is complete and the socket can be safely closed. */
FreeRTOS_closesocket( xSocket );
/* Must not drop off the end of the RTOS task - delete the RTOS task. */
vTaskDelete( NULL );
}
void prvProcessData(char *cRxedData, BaseType_t lBytesReceived)
{
}
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
{
static BaseType_t xTasksAlreadyCreated = pdFALSE;
//static BaseType_t xIPTaskInitialised = pdFALSE;
uint8_t buffer[20];
sprintf((char*)buffer, "Entered eNetwork\r\n");
HAL_UART_Transmit(&huart3, buffer, strlen((char*)buffer), HAL_MAX_DELAY);
/* Both eNetworkUp and eNetworkDown events can be processed here. */
if( eNetworkEvent == eNetworkUp )
{
/* Create the tasks that use the TCP/IP stack if they have not already
been created. */
if( xTasksAlreadyCreated == pdFALSE )
{
/*
* For convenience, tasks that use FreeRTOS-Plus-TCP can be created here
* to ensure they are not created before the network is usable.
*/
xTasksAlreadyCreated = pdTRUE;
//xIPTaskInitialised = pdTRUE;
}
}
}
BaseType_t xApplicationGetRandomNumber( uint32_t *pulValue )
{
HAL_StatusTypeDef xResult;
BaseType_t xReturn;
uint32_t ulValue;
xResult = HAL_RNG_GenerateRandomNumber( &hrng, &ulValue );
if( xResult == HAL_OK )
{
xReturn = pdPASS;
*pulValue = ulValue;
}
else
{
xReturn = pdFAIL;
}
return xReturn;
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 275;
RCC_OscInitStruct.PLL.PLLP = 1;
RCC_OscInitStruct.PLL.PLLQ = 4;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
}
static void MX_USART3_UART_Init(void)
{
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
{
Error_Handler();
}
}
static void MX_USB_OTG_HS_USB_Init(void)
{
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOB, LED_GREEN_Pin|LED_RED_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(USB_FS_PWR_EN_GPIO_Port, USB_FS_PWR_EN_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_YELLOW_GPIO_Port, LED_YELLOW_Pin, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = B1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LED_GREEN_Pin|LED_RED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = USB_FS_PWR_EN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(USB_FS_PWR_EN_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = USB_FS_OVCR_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(USB_FS_OVCR_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = USB_FS_VBUS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(USB_FS_VBUS_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = USB_FS_ID_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_HS;
HAL_GPIO_Init(USB_FS_ID_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LED_YELLOW_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_YELLOW_GPIO_Port, &GPIO_InitStruct);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1) {
HAL_IncTick();
}
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
The FreeRTOSIPConfig.h :
#ifndef FREERTOS_IP_CONFIG_H
#define FREERTOS_IP_CONFIG_H
#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN
#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 64
#define ipconfigZERO_COPY_RX_DRIVER 1
#define ipconfigZERO_COPY_TX_DRIVER 1
#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 1
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1
#define ipconfigUSE_NETWORK_EVENT_HOOK 1
#endif /* FREERTOS_IP_CONFIG_H */
Thanks in advance for your help!
If you have any questions to make the post clearer, donât hesitate.