Hello.
I am creating an application for a board based on MCU STM32H743, ethernet phy Microchip lan8742A in Keil (compiler version 6) + CubeMX (initialization of peripherals) using FREERTOS and FREERTOS plus TCP libraries. The board and PC are connected via a switch.
I was able to successfully build the application. It allows you to ping the board, creates a TCP echo server on the board, and also sends packets to the client by timer and works correctly in normal mode. However, there are several questions and problems.
I do not know if I should create separate topics or I can ask all the questions in this one. Correct me if I am wrong.
If you do not connect the network cable to the port, then after initialization of the application and the network stack in the callback vApplicationIPNetworkEventHook is called with the eNetworkDown parameter approximately every 3 seconds, as it should be. When connecting the network cable, the eNetworkUp message comes and everything works as it should (ping, tcp server). But if you now disconnect the network cable, then eNetworkDown never comes.
Also, if you start the board with the network cable connected, then after initializing the application and the network stack, eNetworkUp comes, but when disconnecting the network cable, eNetworkDown never comes. What could be the reason?
Question about clearing the TCP connection. When the TCP server is working correctly, disconnect occurs as described in the manual: FreeRTOS_recv and FreeRTOS_send return a value less than 0 and clearing occurs.
Size = FreeRTOS_recv( xConnectedSocket, IN_Array, sizeof( IN_Array ), 0 );
/* If data was received, echo it back. */
if( Size > 0 )
{
vTaskResume(RTOS_Handle_Write);
}
else
{
if(Size==0)
{
}
else
{
/* Socket closed? */
break;
}
}
FreeRTOS_shutdown( xConnectedSocket, FREERTOS_SHUT_RDWR );
/* Wait for the shutdown to take effect, indicated by FreeRTOS_recv()
returning an error. */
xTimeOnShutdown = xTaskGetTickCount();
do
{
if( FreeRTOS_recv( xConnectedSocket, cReceivedString, ipconfigTCP_MSS, 0 ) < 0 )
{
break;
}
} while( ( xTaskGetTickCount() - xTimeOnShutdown ) < tcpechoSHUTDOWN_DELAY );
/* Finished with the socket and the task. */
FreeRTOS_closesocket( xConnectedSocket );
vTaskDelete( NULL );
If during operation the cable is disconnected from the board or from the PC, then after about 15 seconds FreeRTOS_recv returns with a value less than 0. However, FreeRTOS_send returns with positive values all this time, as if the transfer is taking place.
What determines the time after which an obviously lost connection will lead to the return of FreeRTOS_recv with a negative value and why FreeRTOS_send does not return an error, although there is clearly no packet transmission.
Is it possible to clear the connection if there is certainty that the connection is lost, without waiting for about 15 seconds for the stack to detect this itself (see point 2)?
My attempts to do this either do not lead to anything or disrupt the stack and lead to its malfunction.
Have you enabled ipconfigSUPPORT_NETWORK_DOWN_EVENT in the FreeRTOSIPConfig.h?
If that is enabled and is still not working, please share what version of FreeRTOS+TCP you are using. If its V4.3.0 or above, then there are 2 possible network interface implementations that support STM32H7 legacy and the unified, please state which one.
However, FreeRTOS_send returns with positive values all this time, as if the transfer is taking place.
FreeRTOS_send called from the application tasks only adds the data to the TCP sockets stream buffer (uxStreamBufferAdd) it doesn’t really send the data from through the network interface, it’s the IP task that does that. So as long as you call FreeRTOS_send with a valid socket and valid data, it keeps adding data to the stream buffer.
Is it possible to clear the connection if there is certainty that the connection is lost, without waiting for about 15 seconds for the stack to detect this itself (see point 2)?
My attempts to do this either do not lead to anything or disrupt the stack and lead to its malfunction.
You can take a look at the ipconfigPHY_LS_HIGH_CHECK_TIME_MS configuration. It defines the time interval (in milliseconds) for checking if the Physical Layer (PHY) link status remains high (i.e., a connection is established) after a period of inactivity, i.e., no packet reception. This mechanism is to prevent frequent checking of PHY registers, which could impact performance.
The default value is 15000 ms (15 seconds); you can try lowering it.
Just to add, if you are using the older network (Legacy) interface prior to V4.3.0 then the support for network down event is not present for STM32H7. You might consider updating to a newer version.
I am using the latest version of the FreeRTOSv202406.01-LTS library.
I took the implementation of the network interface from …\FreeRTOSv202406.01-LTS\FreeRTOS-LTS\FreeRTOS\FreeRTOS-Plus-TCP\source\portable\NetworkInterface\STM32Hxx.
Yes, I have the ipconfigSUPPORT_NETWORK_DOWN_EVENT option enabled in FreeRTOSIPConfig.h. As I said, the vApplicationIPNetworkEventHook event with the NetworkDown flag occurs approximately every 3 seconds if you start the board with the cable disconnected. But it does not happen if you start the board with the cable connected and disconnect it, or turn on the board with the cable disconnected, connect the cable, receive the vApplicationIPNetworkEventHook connection event with the eNetworkUp flag and disconnect it again.
I understood your answer about FreeRTOS_send.
I understood the advice about ipconfigPHY_LS_HIGH_CHECK_TIME_MS and I will try it. But is there a correct way to clear the connection before the stack itself detects the fault (I understand that you can reset the MCU, but this is not a very beautiful solution). Is it possible to clear it or “force” the stack to clear, as if it itself detected that everything is bad?
Unfortunately I can’t test your practical advice until next week, but I will definitely try and write about the results.
I checked the version of FreeRTOS-Plus-TCP here is v4.2.2. Just like @tony-josi-aws mentioned, new driver is provided from v4.3.0. Would you like to try latest released version 202406.03-LTS? It might provide the capability of eNetworkDown event you want.
In reality, the issue on network interface might be recoverable. If the stack clear when it’s down even for just 1ms, the application needs to re-establish the socket connection in this case. It’d be exhaused to handle this kind of re-connection issue. And it also waste network bandwidth. The current design decouples network interface event and the application by the +TCP stack. If the network interface back by itself in short, then user doesn’t need to take care of it.
I would like to know what exactly clearing the connection means for you. Is it closing the TCP connection? Or is it restarting the TCP connection when the ethernet cable is connected back again after a long time (assuming the connection with other peer has been shut down)?