FreeRTOS+TCP slow to accept TCP connections

@mark03 I remove the HAL in my personal code as well. I started to make a register based network interface in this repo but had to turn my attention to other things and never got back to it

@mark03 wrote:

It defaults to HSI48 but I didn’t have that oscillator turned on. As a consequence, I was returning zero from that function, causing prvHandleListen() (in FreeRTOS_TCP_State_Handling_IPv4.c) to fail silently.

A failure to create a random number should not pass silently. It costed us a lot of time and investigation this week.

In trying to understand your issue, I discovered a problem in the function prvAcceptPacket(), depending on the macro ipconfigETHERNET_DRIVER_FILTERS_PACKETS.
It stops all incoming ARP messages from being processed.

Great debugging! Thank you for sharing your solution.

Yes, sorry @htibosch, if I’d had a better understanding of the FreeRTOS+TCP code structure to begin with, I would have started debugging from the top down instead of from the bottom up, which would have quickly revealed that the “lost” packets were not really lost at all, but making it quite far up the stack. I have a new appreciation for the sheer number of code paths involved in the packet processing.

My other problem is that this is (1) my first time using ST’s new VSCode plugin for debugging, which has some issues; and (2) my first project on the STM32H7. So, yes, not the most efficient process.

Of course, the nondeterministic behavior I was seeing may yet indicate a different problem, which is merely hidden by other fixes. Hope not :slight_smile:

EDIT: I just looked at your sample project on github, and I think it suffers from the same issue, if I’m not mistaken? xApplicationGetRandomNumber returns pdFAIL if the HAL RNG call fails, and pdFAIL is defined as zero. This will then be returned as the initial sequence number… Of course, the “bug” may never show up because the RNG is correctly initialized.

Many years ago, we introduced these functions:

UBaseType_t uxRand();

uint32_t ulApplicationGetNextSequenceNumber(
    uint32_t ulSourceAddress,
    uint16_t usSourcePort,
    uint32_t ulDestinationAddress,
    uint16_t usDestinationPort );

Both functions return a random number, or when it fails it will return 0. Users objected that 0 is also a possible random number and should not be treated as an error.

So we had to split up the success-bit and the random value:

BaseType_t xApplicationGetRandomNumber( uint32_t *pulValue );

This function returns pdPASS in case a random number is returned, otherwise pdFAIL.
We can also assume that returning an error should be a fatal thing: randomness has a lot to do with security.

As for the RNG in an STM32, I think that the peripheral either works or it does not.

This starting code includes initialisation of the RNG:

static void vStartRandomGenerator( void )
{
    /* Enable the clock for the RNG. */
    __HAL_RCC_RNG_CLK_ENABLE();
    RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN;
    RNG->CR |= RNG_CR_RNGEN;

    hrng.Instance = RNG;
    hrng.Init.ClockErrorDetection = RNG_CED_ENABLE;
    if (HAL_RNG_Init(&hrng) != HAL_OK)
    {
    	Error_Handler();
    }
    /* Get random numbers. */
    HAL_RNG_GenerateRandomNumber( &hrng, &ulSeed );
}

Aha, you are right of course. I was skimming too quickly.