No TCP connection with FreeRTOS+TCP at STM32H7xx

Hi all,

first of all, I would like to describe my problem before going into my development environment.

My problem is that with FreeRTOS+TCP during initialisation on my development kit STM32H735G-DK the socket status does not go beyond eCONNECT_SYN. After a timeout of 3* 500ms the IP stack gives up and changes to eCLOSE_WAIT.

In my development environment I use several libraries. An overview is shown in the schema.

I have already checked the clocks and IOs on the DK. It turned out that the clocks are present on the PHY LAN8742, but no data is coming to the RMII.
The PHY initialisation seems to be successful.

The various examples and demo applications I have looked at do not help me. It feels like looking for a needle in a haystack.

My request:
Does anyone have any ideas and suggestions that I can follow up on?

I’m open to any idea.

Thanks for support.
Best regards
Thomas

Have you made sure that the Ethernet ISRs are enabled, and are getting triggered? You should see something like this in the HAL_ETH_MspInit() or similar ETH init. code:

    HAL_NVIC_SetPriority(ETH_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(ETH_IRQn);
    HAL_NVIC_SetPriority(ETH_WKUP_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(ETH_WKUP_IRQn);

You could also verify if correct IRQ handlers are getting triggered by putting a BP in here.

1 Like

Hi Thomas, did you define ipconfigUSE_NETWORK_EVENT_HOOK and the function vApplicationIPNetworkEventHook()? Does that function get called?

Does ping work well in both directions?

Do you see any activity from your DUT when calling connect() and running Wireshark?

Did you also try to connect without MQTT, directly connecting?

If you want to peek into a simple project in which TCP works well, see my STM32H747 project.

Hi Tony,

my HAL_ETH_MspInit() has following code:

void HAL_ETH_MspInit(ETH_HandleTypeDef* heth) {
    if (heth->Instance == ETH) {
        GPIO_InitTypeDef GPIO_InitStructure = {0};
        /* Ethernett MSP init: RMII Mode */
        /* Ethernet pins configuration */
        /*
        RMII_REF_CLK ----------------------> PA1
        RMII_MDIO -------------------------> PA2
        RMII_MDC --------------------------> PC1
        RMII_MII_CRS_DV -------------------> PA7
        RMII_MII_RXD0 ---------------------> PC4
        RMII_MII_RXD1 ---------------------> PC5
        RMII_MII_RXER ---------------------> PB10
        RMII_MII_TX_EN --------------------> PB11
        RMII_MII_TXD0 ---------------------> PB12
        RMII_MII_TXD1 ---------------------> PB13
        */

        /* Enable GPIOs clocks */
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_GPIOC_CLK_ENABLE();

        /* Configure PA1|RMII_REF_CLK, PA2|RMII_MDIO , PA7|RMII_MII_CRS_DV */
        GPIO_InitStructure.Pin       = RMII_CRS_DV_Pin | RMII_REF_CLK_Pin | RMII_MDIO_Pin;
        GPIO_InitStructure.Speed     = GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStructure.Mode      = GPIO_MODE_AF_PP;
        GPIO_InitStructure.Pull      = GPIO_NOPULL;
        GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

        /* Configure PB10|RMII_MII_RXER,    PB11|RMII_MII_TX_EN,
         *           PB12|RMII_MII_TXD0 and PB13|RMII_MII_TXD1:  */
        GPIO_InitStructure.Pin = RMII_TXD1_Pin | RMII_TXD0_Pin | RMII_RX_ER_Pin | RMII_TX_EN_Pin;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

        /* Configure PC1|RMII_MDC, PC4|RMII_MII_RXD0 and PC5|RMII_MII_RXD1 */
        GPIO_InitStructure.Pin = RMII_MDC_Pin | RMII_RXD1_Pin | RMII_RXD0_Pin;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

        /* Enable Ethernet clocks */
        __HAL_RCC_ETH1MAC_CLK_ENABLE();
        __HAL_RCC_ETH1TX_CLK_ENABLE();
        __HAL_RCC_ETH1RX_CLK_ENABLE();

        /* Enable the Ethernet global Interrupt */
        HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
        HAL_NVIC_EnableIRQ(ETH_IRQn);
        /// @todo EXTI wakeup
        // HAL_NVIC_SetPriority(ETH_WKUP_IRQn, 5, 0);
        // HAL_NVIC_EnableIRQ(ETH_WKUP_IRQn);
    }   // if (heth->Instance == ETH)
}

Ok, I have enabled the IRQ also for wakeup but It was not enough.
See my log:

_I___[LIB rtos]	xPhyReset: phyBMCR_RESET 0 ready

_I___[LIB rtos]	+TCP: advertise: 01E1 config 3100

_I___[LIB rtos]	prvEthernetUpdateConfig: LS mask 00 Force 1

_I___[LIB rtos]	Autonego ready: 00000004: full duplex 100 mbit high status

_I___[LIB rtos]	Network buffers: 56 lowest 56
_I___[LIB rtos]	Link Status is high

_I___[LIB rtos]	IP Address: 192.168.1.230
_I___[LIB rtos]	Subnet Mask: 255.255.0.0
_I___[LIB rtos]	Gateway Address: 192.168.1.1
_I___[LIB rtos]	DNS Server Address: 208.67.222.222
_I___[LIB mqtt]	NW up -> Connect with RTOS.
_I___[LIB mqtt]	Create a TCP connection to 192.168.1.145:1883.
D____[LIB mqtt]	Created new TCP socket.
D____[LIB mqtt]	Creating TCP Connection to 192.168.1.145.
D____[LIB rtos]	FreeRTOS_connect: 63533 to c0a80191ip:1883

D____[LIB rtos]	Socket 63533 -> c0a80191ip:1883 State eCLOSED->eCONNECT_SYN

D____[LIB rtos]	ARP for c0a80191ip (using c0a80191ip): rc=0 00:00:00 00:00:00

D____[LIB rtos]	Connect[c0a80191ip:1883]: next timeout 1: 500 ms

_I___[LIB rtos]	Network buffers: 55 lowest 55
_I___[LIB rtos]	TX descriptors 1/14

D____[LIB rtos]	ARP for c0a80191ip (using c0a80191ip): rc=0 00:00:00 00:00:00

D____[LIB rtos]	Connect[c0a80191ip:1883]: next timeout 2: 500 ms

_I___[LIB rtos]	Network buffers: 54 lowest 54
_I___[LIB rtos]	TX descriptors 2/14

D____[LIB rtos]	ARP for c0a80191ip (using c0a80191ip): rc=0 00:00:00 00:00:00

D____[LIB rtos]	Connect[c0a80191ip:1883]: next timeout 3: 500 ms

_I___[LIB rtos]	Network buffers: 53 lowest 53
_I___[LIB rtos]	TX descriptors 3/14

D____[LIB rtos]	Connect: giving up c0a80191ip:1883

D____[LIB rtos]	Move from eCONNECT_SYN to eCLOSE_WAIT

D____[LIB rtos]	Socket 63533 -> c0a80191ip:1883 State eCONNECT_SYN->eCLOSE_WAIT

D____[LIB rtos]	FreeRTOS_connect() stopped due to an error

___E_[LIB mqtt]	Failed to connect to server: FreeRTOS_Connect failed: ReturnCode=-128, Hostname=192.168.1.145, Port
D____[LIB rtos]	FreeRTOS_closesocket[63533 to c0a80191ip:1883]: buffers 53 socks 0

___E_[LIB mqtt]	Failed to connect to 192.168.1.145 with error -128.
___E_[LIB mqtt]	Connection to broker failed.

Hi Hein,

yes, I have defined ipconfigUSE_NETWORK_EVENT_HOOK.
The called function is defined with:

#if (ipconfigUSE_NETWORK_EVENT_HOOK == 1)
/// @brief application defined hook (or callback) function
/// that is called by the TCP/IP stack when the network either connects or disconnects. As the
/// function is called by the TCP/IP stack the TCP/IP sets sets the value of the function's
/// parameter.
/// @param eNetworkEvent eNetworkUp if network connected, eNetworkDown if network disconnected
/// @remark
/// https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/vApplicationIPNetworkEventHook.html
void vApplicationIPNetworkEventHook(eIPCallbackEvent_t eNetworkEvent) {
    uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress;
    char cBuffer[ 16 ];
    static BaseType_t xTasksAlreadyCreated = pdFALSE;

    /* If the network has just come up...*/
    if( eNetworkEvent == eNetworkUp )
    {
        /* Create the tasks that use the IP stack if they have not already been
         * created. */
        if( xTasksAlreadyCreated == pdFALSE )
        {
            /* See the comments above the definitions of these pre-processor
             * macros at the top of this file for a description of the individual
             * demo tasks. */

            #if ( mainCREATE_TCP_ECHO_TASKS_SINGLE == 1 )
                {
                    vStartTCPEchoClientTasks_SingleTasks( mainECHO_CLIENT_TASK_STACK_SIZE, mainECHO_CLIENT_TASK_PRIORITY );
                }
            #endif /* mainCREATE_TCP_ECHO_TASKS_SINGLE */

            xTasksAlreadyCreated = pdTRUE;
        }

        /* Print out the network configuration, which may have come from a DHCP
         * server. */
        #if defined( FREERTOS_PLUS_TCP_VERSION ) && ( FREERTOS_PLUS_TCP_VERSION >= 10 )
            FreeRTOS_GetEndPointConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress, pxNetworkEndPoints );
        #else
            FreeRTOS_GetAddressConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress );
        #endif
        FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
        FreeRTOS_printf( ( "IP Address: %s", cBuffer ) );

        FreeRTOS_inet_ntoa( ulNetMask, cBuffer );
        FreeRTOS_printf( ( "Subnet Mask: %s", cBuffer ) );

        FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer );
        FreeRTOS_printf( ( "Gateway Address: %s", cBuffer ) );

        FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer );
        FreeRTOS_printf( ( "DNS Server Address: %s", cBuffer ) );
    }
    else
    {
        FreeRTOS_printf( ( "Application idle hook network down\n") );
    }
}
#endif   // ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 )

With Debug I could see that mainCREATE_TCP_ECHO_TASKS_SINGLE is not defined and the function vStartTCPEchoClientTasks_SingleTasks() is not called.
At the moment I do not know if this is necessary.

The function FreeRTOS_connect() is called but the result of xEventGroupWaitBits() returns the event eSOCKET_CLOSED.
At Wireshark I could see no activity from HW STM32H735G-DK, only standard queries from my PC.

Ok, I will disable all my MQTT stuff and test only TCP/IP stack.
Thanks for your link to your project. Maybe it helps.

Best regards
Thomas

Do you have a MQTT broker running on 192.168.1.145?

Yes, my first approach was to set up a point-to-point connection to a local MQTT broker on my Windows PC.
I followed the coreMQTT examples.

Seems like you are not getting any RX packets (assuming the IP address is assigned statically). Can you also share the FreeRTOSIPConfig.h. Also are you using the stm32hxx_hal_eth.c provided in the network interface folder for STM32Hxx in the FreeRTOS+TCP or the default version from the Drivers/STM32H7xx_HAL_Driver/Src?

    /* Configure PB10|RMII_MII_RXER,    PB11|RMII_MII_TX_EN,
     *           PB12|RMII_MII_TXD0 and PB13|RMII_MII_TXD1:  */
    GPIO_InitStructure.Pin = RMII_TXD1_Pin | RMII_TXD0_Pin | RMII_RX_ER_Pin | RMII_TX_EN_Pin;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* Configure PC1|RMII_MDC, PC4|RMII_MII_RXD0 and PC5|RMII_MII_RXD1 */
    GPIO_InitStructure.Pin = RMII_MDC_Pin | RMII_RXD1_Pin | RMII_RXD0_Pin;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

Haven’t checked how HAL_GPIO_Init() is implemented by ST HAL but please make sure if you need to configure the GPIO_InitStructure with right GPIO alternate function, mode, etc before each call to HAL_GPIO_Init.

Ok, I’m a new user and therefore I can’t share files directly. :wink:
My FreeRTOSIPConfig.h is (based on FreeRTOS+TCP V3.1.0):

/*
 * FreeRTOS+TCP V3.1.0
 * Copyright (C) 2022 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * http://aws.amazon.com/freertos
 * http://www.FreeRTOS.org
 */


/*****************************************************************************
*
* See the following URL for configuration information.
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html
*
*****************************************************************************/

#ifndef FREERTOS_IP_CONFIG_H
#define FREERTOS_IP_CONFIG_H

#include <stdlib.h>  // rand()

#define _static

#define ipconfigHAS_DEBUG_PRINTF    1
#if ( ipconfigHAS_DEBUG_PRINTF == 1 )
    #define FreeRTOS_debug_printf( X )    configDEBUGPRINTF( X )
#endif

#define ipconfigHAS_PRINTF    1
#if ( ipconfigHAS_PRINTF == 1 )
    #define FreeRTOS_printf( X )    configPRINTF( X )
#endif

#define ipconfigBYTE_ORDER    pdFREERTOS_LITTLE_ENDIAN

#define FreeRTOS_htons( usIn )    ( ( uint16_t ) ( ( ( usIn ) << 8U ) | ( ( usIn ) >> 8U ) ) )

#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME    ( 5000 )
#define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME       ( 5000 )

#define ipconfigUSE_DNS_CACHE                      ( 1 )
#define ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY      ( 2 )
#define ipconfigDNS_REQUEST_ATTEMPTS               ( 2 )

#define ipconfigDNS_CACHE_NAME_LENGTH              ( 254 )

#define ipconfigIP_TASK_PRIORITY                   ( configMAX_PRIORITIES - 2 )

#define ipconfigIP_TASK_STACK_SIZE_WORDS           ( configMINIMAL_STACK_SIZE * 5 )

#define ipconfigRAND32()    rand()

#define ipconfigUSE_NETWORK_EVENT_HOOK           1

#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS    ( 5000U / portTICK_PERIOD_MS )

#define ipconfigUSE_DHCP                         0
#define ipconfigDHCP_REGISTER_HOSTNAME           1
#define ipconfigDHCP_USES_UNICAST                1

#define ipconfigUSE_DHCP_HOOK                    1

#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD \
    ( 120000U / portTICK_PERIOD_MS )

#define ipconfigARP_CACHE_ENTRIES                 6

#define ipconfigMAX_ARP_RETRANSMISSIONS           ( 5 )

#define ipconfigMAX_ARP_AGE                       150

#define ipconfigINCLUDE_FULL_INET_ADDR            1

#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS    64

#define ipconfigEVENT_QUEUE_LENGTH \
    ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 )

#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND         1

#define ipconfigUDP_TIME_TO_LIVE                       128
#define ipconfigTCP_TIME_TO_LIVE                       128

#define ipconfigUSE_TCP                                ( 1 )

#define ipconfigUSE_TCP_WIN                            ( 1 )

#define ipconfigNETWORK_MTU                            1200U

#define ipconfigUSE_DNS                                1

#define ipconfigREPLY_TO_INCOMING_PINGS                1

#define ipconfigSUPPORT_OUTGOING_PINGS                 1

#define ipconfigSUPPORT_SELECT_FUNCTION                1

#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES      1

#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES    1

#define configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY    ( 20 / portTICK_PERIOD_MS )

#define ipconfigPACKET_FILLER_SIZE                     2U

#define ipconfigTCP_WIN_SEG_COUNT                      240

#define ipconfigTCP_RX_BUFFER_LENGTH                   ( 1000 )

#define ipconfigTCP_TX_BUFFER_LENGTH                   ( 1000 )

#define ipconfigIS_VALID_PROG_ADDRESS( x )    ( ( x ) != NULL )

#define ipconfigTCP_KEEP_ALIVE                   ( 1 )
#define ipconfigTCP_KEEP_ALIVE_INTERVAL          ( 20 ) /* Seconds. */

#define ipconfigSOCKET_HAS_USER_SEMAPHORE        ( 1 )

#define ipconfigSOCKET_HAS_USER_WAKE_CALLBACK    ( 1 )
#define ipconfigUSE_CALLBACKS                    ( 0 )

#define ipconfigUSE_NBNS                         ( 0 )

#define ipconfigUSE_LLMNR                        ( 0 )

#define ipconfigZERO_COPY_RX_DRIVER              ( 1 )
#define ipconfigZERO_COPY_TX_DRIVER              ( 1 )

#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM   1

#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM   1

#define ipconfigDNS_USE_CALLBACKS                0
#define ipconfigUSE_ARP_REMOVE_ENTRY             1
#define ipconfigUSE_ARP_REVERSED_LOOKUP          1

#define ipconfigETHERNET_MINIMUM_PACKET_BYTES    ( 200 )

#define ipconfigARP_STORES_REMOTE_ADDRESSES      ( 1 )

#define ipconfigARP_USE_CLASH_DETECTION          ( 1 )

#define ipconfigDHCP_FALL_BACK_AUTO_IP           ( 1 )

#define ipconfigUDP_MAX_RX_PACKETS               ( 1 )

#define ipconfigSUPPORT_SIGNALS                  ( 1 )

#define ipconfigDNS_CACHE_ENTRIES                ( 2 )

#define ipconfigBUFFER_PADDING                   ( 14 )
#define ipconfigTCP_SRTT_MINIMUM_VALUE_MS        ( 34 )

#define ipconfigTCP_HANG_PROTECTION              ( 1 )

#define ipconfigTCP_MAY_LOG_PORT( xPort )    ( ( xPort ) != 23U )

#endif /* FREERTOS_IP_CONFIG_H */

I have removed all comments.

Yes, I’m using stm32hxx_hal_eth.c
Additionally I had added a function HAL_ETH_SetMDIOClockRange() which is called from NetworkInterface.c, fct. xNetworkInterfaceInitialise(). This I used from FreeRTOS+TCP V3.1.0.

The pins for GPIO handling I have checked for my board.
For alternate function I’m using GPIO_AF11_ETH from stm32h7xx_hal_gpio_ex.h:

#if defined(ETH)
#define GPIO_AF11_ETH           ((uint8_t)0x0B)  /* ETH Alternate Function mapping     */
#endif /* ETH */

The HAL driver I took from stm32h7xx_hal_driver v1.11.1

Additionally I had added a function HAL_ETH_SetMDIOClockRange() which is called from NetworkInterface.c

I believe HAL_ETH_SetMDIOClockRange() is already defined in the STM32Hxx/stm32hxx_hal_eth.c of +TCP V3.1.0.

Where is the ETH_TX_BUF_SIZE and ETH_RX_BUF_SIZE defined and to what value? Can you try using the FreeRTOSIPConfig.h used in the project linked by @htibosch.

Hi Tony,
you are right. The HAL_ETH_SetMDIOClockRange() is defined in this version.

The definitions for buffer size are stored in stm32h7xx_hal_conf.h with:

#define HAL_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED
#define HAL_ETH_MODULE_ENABLED
#define HAL_EXTI_MODULE_ENABLED
#define HAL_FLASH_MODULE_ENABLED
#define HAL_GPIO_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define HAL_TIM_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED
...
/* ########################### Ethernet Configuration ######################### */
#define ETH_TX_DESC_CNT 14U /* number of Ethernet Tx DMA descriptors */
#define ETH_RX_DESC_CNT 8U  /* number of Ethernet Rx DMA descriptors */
#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE
#define ETH_RXBUFNB     ((uint32_t)5U) /*  5 Rx buffers of size ETH_RX_BUF_SIZE */
#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE
#define ETH_TXBUFNB ((uint32_t)5U) /* 5  Tx buffers of size ETH_TX_BUF_SIZE */

...
#ifdef HAL_ETH_MODULE_ENABLED
#include "stm32h7xx_hal_eth.h"
#endif /* HAL_ETH_MODULE_ENABLED */

I am currently working on the example of @htibosch .

I have already discovered one bug. My Wifi IF uses the same IP 192.168.1.x as my LAN IF.
I have changed it to 192.168.5.x. :frowning:

Hi,

Together with a colleague, we were able to find the cause of the problem. The article [Ethernet not working on STM32H7x3] in ST community describes which adjustments are necessary. After moving the Ethernet data to the D2 domain of the SRAM with the MPU active, we could achieve data transfer. The previous configuration for AXI-SRAM on the D1 domain was wrong.

Thanks for support.
BR
Thomas

PS: Maybe the following scheme helps

1 Like

Thank you for reporting back.