FreeRTOS+TCP: STM32H7 Support

PS. which DHCP option number do you propose to use for this?
DHCP option 50 (“Requested IP Address”) I assume?

Correct

Are you sure that option 50 may be used along with a DHCP DISCOVER message?
I just tried it, but it doesn’t seem to be honoured.

See in this PCAP file:
dhcp_discover.zip (316 Bytes)
My device asks for 192.168.2.16, but it gets x.x.x.15 offered.

EDIT : maybe we should try a REQUEST first, along with option 50. If that fails, start with a new DISCOVER ?

In our case, initialization dependency must wait for the blocked Ethernet before proceeding. It would be nice if we could tell Ethernet initialization to “please initialize and let me know when you’re done”

But this is FreeRTOS: while the IP-task is busy initialising the hardware and the IP-stack, you can initialise the LCD and show a splash screen. phyHandling will mostly be sleeping.

Have you studied phyHandling.c already?

It’s been so long that I don’t recall. I do recall, however, ST’s stm32F7xx_hal_eth.c file required certain modification relative to phy-specific calls, and it does have blocking delay loops. These are what I was referring to with respect to being “abysmal” :slight_smile:

In that case, I think that you will like the approach taken in phyHandling.c.

I do in fact allow the IP task to have a very high priority, and I suspected the sockets are actually getting closed. The example code on how to properly close a socket, however, states one should first call FreeRTOS_shutdown(.), where subsequent calls to FreeRTOS_recv(…) should eventually return FREERTOS_EINVAL ( a negative value ),

Ah yes, this is about the graceful closured of TCP sockets. Many developers get confused by shutdown() and write code llike this:

    if( recv() < 0 )
	{
	    /* The following call is useless because the
         * connection has already been shut down. */
	    shutdown( xSocket, SHUT_RDWR);
		close( xSocket );
		return;
	}

There are two situations:

  1. your device is a HTTP server, and it receives clients on port 80. It serves the client for ever until FreeRTOS_recv() tells that the connection is broken:
   BaseType_t rc = FreeRTOS_recv( xSocket, message, sizeof message, 0 );
   if( ( rc < 0 ) && ( rc != -pdFREERTOS_ERRNO_EWOULDBLOCK ) )
   {
       printf( "The connection is closed: %d\n", ( int ) rc );
       FreeRTOS_closesocket( xSocket );
       return;
   }
  1. Your device is connecting to a web site to store or to retrieve some data. When you are done you can just close your socket, or do a graceful closure of the connection. The latter is far preferred, because it cleans up resources at the peers’ system.
    Here is an example:
    /* Set the socket in shut-down-mode: */
    FreeRTOS_shutdown( xSocket, 0 );

    TickType_t xStartTime = xTaskGetTickCount();
    for( ;; )
    {
    TickType_t xEndTime = xTaskGetTickCount();

        if( ( xEndTime - xStartTime ) > pdMS_TO_TICKS( 1000U ) )
        {
    		/* Time-out waiting for the FIN+ACK. */
            break;
        }
        BaseType_t rc = FreeRTOS_recv( xSocket, ( const void * ) pcBuffer, sizeof pcBuffer, 0 );
        if( ( rc < 0 ) && ( rc != -pdFREERTOS_ERRNO_EWOULDBLOCK ) )
        {
            printf( "Connection gracefully closed\n" );
            break;
        }
    }

Make sure that the socket blocks in FreeRTOS_recv().

IP task to have a very high priority

I always recommend to assign:

  • higher : the task handling the EMAC
  • medium : the IP-task
  • lower : all tasks that make use of the IP-stack.

Tasks that do not use the IP-stack are free to choose any priority.

If you still find that the start-up splash screen is not fast enough, you can temporarily raise the priority of the task handling that. But the EMAC and PHY initialisation should not take too much CPU time.