FreeRTOS IP doesn't answer ARP frame

I have integrated FreeRTOS and FReeRTOS-IP.

I’ve created a task that implements a TCP echo server.
I have a TCP client that sends a string to the TCP echo server written in Python, which I know it’s working with a LwIP TCP echo server.

The Nucleo-144 is programmed with an IP address of 192.168.0.10 (mac address 0x00, 0x11, 0x22, 0x33, 0x44, 0x55) and the Windows machine is 192.168.0.100.
I’m using port 80.

I can see with wireShark that the ARP is sent:
11 61.282383 Dell_43:e4:58 Broadcast ARP 42 Who has 192.168.0.10? Tell 192.168.0.100

But no answer is coming back.
Any ideas on how to find out what is going on?

thanks

In stm32fxx_ahl_eth.h the MAC address is defined as:

#define ETH_MAC_ADDRESS0    ( ( uint32_t ) 0x00000000U )

Which of the MAC address is used? The one define is this file or the one defined upon calling FreeRTOS_IPInit() ?

Does anyone know what is the interrupt routine that receives a Ethernet frame?
I would like to know if this is properly enabled…

It’s the ETH peripheral with ETH_Handler as default ISR.
If using stm32f4xx_hal_eth.c you can step into the init code HAL_ETH_Init to see what’s going on.

HAL_Eth_Init() returns HAL_OK.
xNetworkInterfaceInitialise() return pdFAIL but it seems normal…

        /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
         * and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */
        xResult = pdFAIL;

The prvEMACHandlerTask is running but this if never comes true.

    if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )
    {
        /* Something has changed to a Link Status, need re-check. */
        prvEthernetUpdateConfig( pdFALSE );
    }

I guess ETH_Handler() is:

void ETH_IRQHandler( void )
{
HAL_ETH_IRQHandler( &xETH );
}

but it’s never hit.

Remember your earlier question on MII vs. RMII? Ever got that resolved? Might be the key…

I’m using a Nucleo-144 with a STM32F767ZI.
I was told by other colleagues that it’s a RMII. I’ll do some extra checks…

NetworkInterface.c initialises as RMII
xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;

also make sure that the strapped PHY address matches your code. Or vice versa… :kissing_closed_eyes:

The MAC address has reported by FreeRTOS_GetMACAddress() in xNetworkInterfaceInitialise is
00:11:22:33:44:55 which is the one presented to FreeRTOS_IPInit().

What is “the strapped PHY address” ?
Is there any other MAC address defined? Is there any unique ID IC on Nucleo-144?

You mean FreeRTOS_IPInit() right ?

You should be able to step through your ethernet interface initialization in HAL_ETH_Init which among other things should program the provided MAC address into the ETH hardware.
Also when in doubt check that the PHY is found at it’s fixed address (boot-strapped by external resistors) and verify that the PHY then detects ethernet link up with the expected mode and speed (e.g. 100MBit full-duplex). Watch the LEDs on your RJ45 plug and/or check the link state on the peer PC/machine.
Finally link-up is signaled to the network stack and the real fun starts :wink:

Yes FreeRTOS_IPInit.

HAL_ETH_Init return HAL_OK.
xNetworkInterfaceInitialise() return pdFAIL but it seems normal…

        /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
         * and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */
        xResult = pdFAIL;

The prvEMACHandlerTask is running but this if never comes true.

if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )
{
    /* Something has changed to a Link Status, need re-check. */
    prvEthernetUpdateConfig( pdFALSE );
}

Both leds in the RJ45 connector are on.

I think the thing missing here in that the link never goes up!
What would be the reason for that?

If both LEDs are ON than the the PHY has detected a 100 MBit-FD link-up. Then step through xPhyCheckLinkStatus and/or check the returned pxPhyObject members like ulLinkStatusMask as defined in phyHandling.h (I guess) to verify that it’s reported properly and prvEthernetUpdateConfig gets invoked.

1 Like

That is correct Hartmut, about phyHandling.h.

It will automatically detect on what addresses ( 0 … 31 ) a PHY chip is found. It recognises most types of PHY’s.

It works with a simple configuration: either auto-nego, or using a manual set-up. 99% of the projects will use the auto-negotiation and go for the maximum speed, auto-DMX, and full duplex.

The STM32F and STM32H drivers come with a copy of the ST-supplied driver files: stm32fxx_hal_eth.c and stm32hxx_hal_eth.c.

Please make sure that you use one of these files, and exclude the ETH file and header files from your HAL distribution.

xPhyCheckLinkStatus keeps being called, but it seems to return pdFALSE.

Also strangely so does xNetworkInterfaceInitialise().

in xPhyCheckLinkStatus()

if( xHadReception > 0 ) is always false

the else if is true

the for loop however does not seem to run since pxPhyObject->xPortCount is 0.

and the final outcome is:

    else
    {
        /* The link status is low, polling may be done more frequently. */
        pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS );
    }

I don’t think pxPhyObject->xPortCount should be 0, since the assignment of pxPhyObject->ulLinkStatusMask happens inside the for loop…
Why is pxPhyObject->xPortCount equal to 0?

In xPhyDiscover() phyHandling.c the if

    /* A valid PHY id can not be all zeros or all ones. */
    if( ( ulLowerID != ( uint16_t ) ~0U ) && ( ulLowerID != ( uint16_t ) 0U ) )

is never true.

and pxPhyObject->xPortCount comes out as 0.

I’m using stm32fxx_hal_eth.c and stm32fxx_hal_eth.h provided by FreeRTOS-IP

/**


  • @file stm32fxx_hal_eth.c
  • @author MCD Application Team
  • @version V1.3.2
  • @date 26-June-2015
  • @brief ETH HAL module driver.

The ST HAL files for ethernet have been deleted.

Have you stepped through xPhyDiscover() already?
As you probably know, switching off compiler optimisation makes stepping a lot easier.

Does the fnPhyRead() function return any other number than all ones (0xffff)?

Is your implementation of HAL_ETH_MspInit() correct? It defines clocks and the direction and function of GPIO pins involved.

I am attaching a version that I use for tests with an STM32F7x: HAL_ETH_MspInit.c (2.0 KB)
It is just an example, your hardware might be different from my STM32F746 Discovery board.

You wrote:

#define ETH_MAC_ADDRESS0 ( ( uint32_t ) 0x00000000U )

FreeRTOS+TCP doesn’t use these defines.

In the FreeRTOS demo applications, FreeRTOSConfig.h will define them as e.g.:

#define configMAC_ADDR0    0x00
#define configMAC_ADDR1    0x11
#define configMAC_ADDR2    0x22
#define configMAC_ADDR3    0x33
#define configMAC_ADDR4    0x44
#define configMAC_ADDR5    0x60

and apply them in main.c before calling FreeRTOS_IPInit().

You wrote:

I was told by other colleagues that it’s a RMII. I’ll do some extra checks…

My STM32F746 board is also wired with the RMII scheme.

The problem seems that:

for( xPhyAddress = phyMIN_PHY_ADDRESS; xPhyAddress <= phyMAX_PHY_ADDRESS; xPhyAddress++ )
{
    uint32_t ulLowerID;

    pxPhyObject->fnPhyRead( xPhyAddress, phyREG_03_PHYSID2, &ulLowerID );

    /* A valid PHY id can not be all zeros or all ones. */
    if( ( ulLowerID != ( uint16_t ) ~0U ) && ( ulLowerID != ( uint16_t ) 0U ) )
    {
              ...
    }
}

Never hits the if code. ulLowerID always returns 0.

fnPhyRead always returns ulLowerID with 0! I’ve checked the 32 returns.

It’s RMII wired.

My HAL_ETH_MspInit() seems to be much simpler than yours :rofl:

    __weak void HAL_ETH_MspInit( ETH_HandleTypeDef * heth )
    {
        /* NOTE : This function Should not be modified, when the callback is needed,
         * the HAL_ETH_MspInit could be implemented in the user file
         */
        ( void ) heth;
    }

But I have copied the files from:
FreeRTOSv202012.00\FreeRTOS-Plus\Source\FreeRTOS-Plus-TCP\portable\NetworkInterface\STM32Fxx

This seems to be the problem.
Where should I get the correct file?
They are dated 15/12/2020

The HAL_ETH_MspInit() function is not part of the FreeRTOS distribution, because each board may be different.
Have you looked up the schemes of a Nucleo-144, regarding the ETH and PHY? Try to get a list of all pins involved and compose a HAL_ETH_MspInit().

Or, alternatively, try to find an Ethernet project for Nucleo-144, which may also be a lwIP project. The pinnings are the same.

It is good to use the following github locations to find the latests drivers:

FreeRTOS-Kernel for the latest kernel.
FreeRTOS-Plus-TCP for the latest +TCP software.

You can either clone these repos ( preferable ), or download them as a big ZIP file.

I have copied the HAL_ETH_MspInit() routine from LwIP and…

Hooray :slight_smile: I’m receiving data. Many thanks.

Now, when sending data is falling into the vApplicationMallocFailedHook()
I have a 32 Kbytes heap and I’m using BufferAllocation_2.c and heap4.c.

call stack:
FreeRTOS_send
xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
( void ) prvTCPCreateStream( pxSocket, pdFALSE );
pxBuffer = ipCAST_PTR_TO_TYPE_PTR( StreamBuffer_t, pvPortMallocLarge( uxSize ) );
vApplicationMallocFailedHook

What could be the justification for this?

Hooray :slight_smile: I’m receiving data. Many thanks.

Very good!

32 KB of heap is not too much, can you still increase configTOTAL_HEAP_SIZE?

Where has the 32KB gone?

Do you have ipconfigREPLY_TO_INCOMING_PINGS defined in your FreeRTOSIPConfig.h? If so, does your device respond to a simple PING?

Do you see any EMAC_IF_TX_EVENT, as in :

if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )

One TX event should always occur after a packet has been sent. When the even comes, a network buffer can be released ( zero-copy transmission ).