Ping not working. Trouble getting started w/ FreeRTOS+TCP on Zynq (Zedboard)

Currently I’m using FreeRTOS10 on the Zedboard dev board (Zynq).
This is the FreeRTOS that comes with Vitis 2022.1.0 IDE.

I’m having trouble getting FreeRTOS+TCP library to work.
Eventually I’d like to set up two static IP (IPv4) on the Ethernet interface on the Zedboard:
One IP address as a TCP server, and the other as a UDP client.
However, for now I’m just trying to get one static IP address on my interface.

I started with the Tutorial. For example:
https://www.freertos.org/Documentation/03-Libraries/02-FreeRTOS-plus/02-FreeRTOS-plus-TCP/04-Tutorial/04-Initialization

A couple issues I’ve noticed so far:
(1) After doing the initialization (see link above), when I use my Windows or Linux computer to ping the zedboard at the static IP address I set up, I get a “Request Time out”
indicating to me that the static IP address either didn’t get setup correctly, or the Zynq is not responding to pings.
However, I do get this message on the console:
FreeRTOS_AddEndPoint: MAC: 44-55 IPv4: a6464a0ip
(a6464a0 Converted to IPv4 format is 10.100.100.160. This is what I want)

(2) If the ipconfigIP_TASK_PRIORITY is a higher priority than my other FreeRTOS tasks, then those other tasks never run.
I had to make the other tasks equal or higher priority to have them run.

(3) I tried to use the Zynq as a TCP client and connect to a Server running on my PC.
When I ran my application in debug mode, it never returned from FreeRTOS_connect().
(Investigating further I followed down the rabbit hole of FreeRTOS_connect()-> prvTCPConnectStart()-> FreeRTOS_bind() → xEventGroupWaitBits().
At this point I stopped following the hole.)

Below is some of my configuration settings:

For the FreeRTOSConfig.h, I just used the default one that FreeRTOS created for me.
Only change I made was adding
#define INCLUDE_xTaskGetCurrentTaskHandle 1

For the FreeRTOSIPConfig.h, I started with the one included in one of the demos
(the demo called “FreeRTOS_Plus_TCP_Echo_Posix”)
and then made a few changes.

Here are the changes from the demo version
#define ipconfigUSE_IPv6 ( 0 )
#define ipconfigUSE_LLMNR ( 0 )
#define ipconfigUSE_NBNS ( 0 )
#define ipconfigUSE_DHCP ( 0 )
#define ipconfigUSE_DNS ( 0 )
#define ipconfigSUPPORT_OUTGOING_PINGS ( 1 )

In order to build the project I also had to add the following:
#define ipconfigZERO_COPY_TX_DRIVER ( 1 )
#define ipconfigZERO_COPY_RX_DRIVER ( 1 )

#ifndef pdFREERTOS_ERRNO_EAFNOSUPPORT
#define pdFREERTOS_ERRNO_EAFNOSUPPORT 97
#endif

As well as this
// Taken from amazon-freertos/vendors/xilinx/boards/microzed/aws_demos/config_files/FreeRTOSIPConfig.h at main · aws/amazon-freertos · GitHub
#define ipconfigNIC_N_TX_DESC ( 32 )
#define ipconfigNIC_N_RX_DESC ( 32 )

I also created a .c file that defined a bunch of stubs I needed.
I can provide the definitions I filled out if anyone asks. (Trying to keep this initial post as short as I can).
void vApplicationPingReplyHook( ePingReplyStatus_t eStatus,
uint16_t usIdentifier )

BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
uint16_t usSourcePort,
uint32_t ulDestinationAddress,
uint16_t usDestinationPort )
UBaseType_t uxRand( void )
void vApplicationIPNetworkEventHook_Multi( eIPCallbackEvent_t eNetworkEvent,
struct xNetworkEndPoint * pxEndPoint )

eDHCPCallbackAnswer_t xApplicationDHCPHook_Multi( eDHCPCallbackPhase_t eDHCPPhase,
struct xNetworkEndPoint * pxEndPoint,
IP_Address_t * pxIPAddress )

BaseType_t xApplicationDNSQueryHook_Multi( struct xNetworkEndPoint * pxEndPoint,
const char * pcName )

uint64_t ullGetHighResolutionTime( void )

Hi @svgarcia,
Welcome to FreeRTOS community!

Could you help check if ipconfigREPLY_TO_INCOMING_PINGS is set to enable in your FreeRTOSIPConfig.h? That config must be set to reply the ping request from remote.

Feel free to adjust the priority yourself. Refer to ipconfigIP_TASK_PRIORITY for some introduction. Note that please ensure that the IP task still has the opportunity to run, even if it has been assigned a lower priority.

This process requires the IP task to bind the socket and then wake up the executing task. Would you kindly check if the IP task is running when entering the xEventGroupWaitBits function?

Thank you.

@ActoryOu Thanks for replying to my post.
Regarding the ping
(1) In my FreeRTOSIPConfig.h file I already had the following set:
#define ipconfigREPLY_TO_INCOMING_PINGS 1
#define ipconfigSUPPORT_OUTGOING_PINGS 1

(2) My other tasks have a vTaskDelay() in the while loop so I’m sure that I should have no problem with my other tasks starving the +TCP task.

(3) Perhaps I should solve the ping issue before I even attempt to do a TCP Client/Server example?

Thanks.

Hi @svgarcia,
To help isolate the issue with +TCP on your platform, please:

  1. Try removing all other tasks you’ve created and attempt the ping again.
  2. If the issue persists, please enable ipconfigHAS_DEBUG_PRINTF and FreeRTOS_debug_printf in your configuration.
  3. Once you’ve enabled the debug logging, could you please run the ping test again and share the resulting logs with us?

Thank you.

Hi @ActoryOu,
Thanks again for your reply.
I’m still having issues with getting a ping to work:

(1) I went ahead and removed the other tasks.
So right now the only thing I’m doing is the following:

In main() function I am doing the following:

pxZynq_FillInterfaceDescriptor( 0, &( xInterfaces[ 0 ] ) );
FreeRTOS_FillEndPoint( &( xInterfaces[ 0 ] ), 
                       &( xEndPoints[ 0 ] ), ucIPAddress,
                            ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress );
FreeRTOS_IPInit_Multi();

For reference, in that same file I used the following global variables:

static const uint8_t ucIPAddress[ 4 ] = { 10, 100, 100, 160 };
static const uint8_t ucNetMask[ 4 ] = { 255, 255, 255, 0 };
static const uint8_t ucGatewayAddress[ 4 ] = { 10, 100, 100, 1 };
static const uint8_t ucDNSServerAddress[ 4 ] = { 208, 67, 222, 222 };

static NetworkInterface_t xInterfaces[ 1 ];
static NetworkEndPoint_t xEndPoints[ 2 ];

(2) In my FreeRTOSIPConfig.h I have the following defined:

#define ipconfigHAS_DEBUG_PRINTF    1
#define FreeRTOS_debug_printf( X )    vLoggingPrintf X

(3) This is the console output when running my application:

FreeRTOS_AddEndPoint: MAC: 44-55 IPv4: a6464a0ip
prvIPTask started
link speed: 0

Notice that 0xa6464a0 is 10.100.100.160 according to online tools like Convert an IP Address to Hex – Online Hex Tools
So it appears as if the endpoint I desired was added.
However, when I try to ping that address from my host computer I get
“Destination Host Unreachable” as always.

Hi @svgarcia,
It seems the issue might be related to your environment or network driver.

  1. Could you please verify the network environment between your device and computer? In particular:
    • The IP address settings are correct.
    • If there’s a router in between, could you check if it’s properly configured?
      • Please ensure that the router recognizes the IP address “10.100.100.160” as being assigned to your device.
  2. Could you check the link status by examining the registers on the network interface to know if link is successfully established?

Thank you.

Hi @ActoryOu,
(1) Regarding the network environment I have the Zynq / Zedboard and my host computer hooked up via an ethernet hub.
When I used LWIP on the Zynq I had no problems communicating between the Zynq and host computer.

For FreeRTOS+TCP I used the same IP Address, Netmask, and Gateway address I used when using LWIP.

The only thing different I did on FreeRTOS+TCP was specify a DNS Server Address. Although I’m using static IP address (I disabled DNS), so hoping that’s not an issue.
I’m using

static const uint8_t ucDNSServerAddress[ 4 ] = { 208, 67, 222, 222 };

(2) What are the names of the registers on the network interface you recommend I examine? I’m using the Zynq 7020, so when including FreeRTOS+TCP I added the files in the directory
portable->NetworkInterface->Zynq

Is that all you get on the console?

Hi @aggarg,
That is correct. When running the application I only get those three lines on the console.

Can you step through the code inside the pfInitialise() [initialized here] function and see if it’s able to initialize and set up the network interface correctly?

The console logs seem to indicate that there is something wrong with the ethernet driver initialization, probably incorrect GPIO configurations or PHY settings.

Hi @tony-josi-aws,
I’m not exactly sure what to look for during the pfInitialise() function to make sure that the network interface is set up correctly.
Did you mean examine the pxEMAC_PS and pxEndPoint structures?

The XEmacPs_CfgInitialize() function returns 0 (i.e. XST_SUCCESS)
After this function the pxEMAC_PS is the following:

{Config={DeviceId=0x0000, BaseAddress=0xe000b000, IsCacheCoherent=0x00, S1GDiv0=0x0000, S1GDiv1=0x00, S100MDiv0=0x0000, S100MDiv1=0x00, S10MDiv0=0x0000, S10MDiv1=0x00}, IsStarted=0x00000000, IsReady=0x11111111, Options=0x000037f0, TxBdRing={PhysBaseAddr=0x00000000, BaseBdAddr=0x00000000, HighBdAddr=0x00000000, Length=0x00000000, RunState=0x00000000, Separation=0x00000000, FreeHead=0x00000000, PreHead=0x00000000, HwHead=0x00000000, HwTail=0x00000000, PostHead=0x00000000, BdaRestart=0x00000000, HwCnt=0x00000000, PreCnt=0x00000000, FreeCnt=0x00000000, PostCnt=0x00000000, AllCnt=0x00000000}, RxBdRing={PhysBaseAddr=0x00000000, BaseBdAddr=0x00000000, HighBdAddr=0x00000000, Length=0x00000000, RunState=0x00000000, Separation=0x00000000, FreeHead=0x00000000, PreHead=0x00000000, HwHead=0x00000000, HwTail=0x00000000, PostHead=0x00000000, BdaRestart=0x00000000, HwCnt=0x00000000, PreCnt=0x00000000, FreeCnt=0x00000000, PostCnt=0x00000000, AllCnt=0x00000000}, SendHandler=0x0011bfc4, RecvHandler=0x0011bfc4, SendRef=0x00000000, RecvRef=0x00000000, ErrorHandler=0x0011bfc4, ErrorRef=0x00000000, Version=0x00000002, RxBufMask=0x00001fff, MaxMtuSize=0x000005dc, MaxFrameSize=0x000005ee, MaxVlanFrameSize=0x00000600}

pxEMAC_PS after XEmacPs_SetMacAddress() appears to not change any of the above.
pxEMAC_PS after XEmacPs_SetMdioDivisor() appears to not change any of the above.
pxEMAC_PS after Phy_Setup() appears to not change any of the above.

Perhaps I did an incorrect copy and paste, so if you could perhaps help me hone in one which structure element(s) to look at, I can take a second look.

pxEndPoint before calling FreeRTOS_FirstEndPoint()

{ipv4_settings={ulIPAddress=0xe1a03000, ulNetMask=0xe3530000, ulGatewayAddress=0x0a000003, ulDNSServerAddresses=[0xe51b2010, 0xe5d23000], ulBroadcastAddress=0xe3833002, ucDNSIndex=0x00}, ipv4_defaults={ulIPAddress=0xe51b3010, ulNetMask=0xe5d33000, ulGatewayAddress=0xe2033002, ulDNSServerAddresses=[0xe6ef3073, 0xe3530000], ulBroadcastAddress=0x0a000007, ucDNSIndex=0x10}, xMACAddress={ucBytes=[0x10, 0x30, 0x93, 0xe5, 0x03, 0x10]}, bits={bIsDefault=?, bWantRA=?, bIPv6=?, bCallDownHook=?, bEndPointUp=?}, usDNSType=0x69, xDHCP_RATimer={bActive=?, bExpired=?, xTimeOut={xOverflowCount=-452251640, xTimeOnEntering=0xea000001}, ulRemainingTime=0xe3a03000, ulReloadTime=0xe50b3008}, xRAData={bits={bRouterReplied=?, bIPAddressInUse=?}, ulPreferredLifeTime=0xe1a00003, uxRetryCount=0xe24bd004, eRAState=0}, pxNetworkInterface=0xe52db004, pxNext=0xe28db000}

pxEndPoint after calling FreeRTOS_FirstEndPoint()

{ipv4_settings={ulIPAddress=0x00000000, ulNetMask=0x00ffffff, ulGatewayAddress=0x0164640a, ulDNSServerAddresses=[0xdede43d0, 0x00000000], ulBroadcastAddress=0xff64640a, ucDNSIndex=0x00}, ipv4_defaults={ulIPAddress=0xa064640a, ulNetMask=0x00ffffff, ulGatewayAddress=0x0164640a, ulDNSServerAddresses=[0xdede43d0, 0x00000000], ulBroadcastAddress=0xff64640a, ucDNSIndex=0x00}, xMACAddress={ucBytes=[0x00, 0x11, 0x22, 0x33, 0x44, 0x55]}, bits={bIsDefault=?, bWantRA=?, bIPv6=?, bCallDownHook=?, bEndPointUp=?}, usDNSType=0x00, xDHCP_RATimer={bActive=?, bExpired=?, xTimeOut={xOverflowCount=0, xTimeOnEntering=0x00000000}, ulRemainingTime=0x00000000, ulReloadTime=0x00000000}, xRAData={bits={bRouterReplied=?, bIPAddressInUse=?}, ulPreferredLifeTime=0x00000000, uxRetryCount=0x00000000, eRAState=0}, pxNetworkInterface=0x004010f0, pxNext=0x00000000}

@tony-josi-aws @aggarg @ActoryOu Wanted to see if anyone has any ideas of what to look at next to see why I can’t get ping to work.

Which version of +TCP are you using? Have you enabled logging? If so please share the console logs.

The XEmacPs_CfgInitialize() function returns 0 (i.e. XST_SUCCESS )

What about the rest of the functions related to PHY setup? (Phy_Setup)

Hi @tony-josi-aws
Looking at History.txt it appears that I have v4.1.0

I have enabled logging:
#define ipconfigHAS_DEBUG_PRINTF 1
#define ipconfigHAS_PRINTF 1

Console Output:
FreeRTOS_AddEndPoint: MAC: 44-55 IPv4: a6464a0ip
prvIPTask started
link speed: 0

Inside the function xZynqNetworkInterfaceInitialise() there is a call to Phy_Setup()
See link_1

Inside Phy_Setup() none of the #ifdef are triggered.
And since conv_present remains at 0,
the only line that gets executed in Phy_Setup() is:
FreeRTOS_printf( ( “link speed: %d\n”, link_speed ) );
return link_speed;
See link_2

-Sam

@svgarcia

Try defining the required link speed macro [ipconfigNIC_LINKSPEED1000 or ipconfigNIC_LINKSPEED100] in your FreeRTOSIPConfig.h file.

Hi @tony-josi-aws

In my FreeRTOSIPConfig.h I added the following:
#define ipconfigNIC_LINKSPEED_AUTODETECT

Now my console output gets a lot further than before:

FreeRTOS_AddEndPoint: MAC: 44-55 IPv4: a6464a0ip
prvIPTask started
XEmacPs detect_phy: PHY detected at address 0.
Start PHY autonegotiation
Waiting for PHY to complete autonegotiation.
autonegotiation complete
link speed: 1000
prvEMACHandlerTask[ 0 ] started running
Network buffers: 28 lowest 28
END POINT created vApplicationIPNetworkEventHook_Multi
Network buffers: 28 lowest 27

However, ping still doesn’t work.
When I try pinging the zynq, the console outputs the following multiple times:

vApplicationMallocFailedHook() called
emacps_check_rx: unable to allocate a Network Buffer

Seems like now the PHY negotiation succeeded and the network endpoint is up.

vApplicationMallocFailedHook will be called when memory allocation fails, usually when there isn’t enough heap memory available (probably while requesting more network buffers to handle incoming packets).

Try modifying the configTOTAL_HEAP_SIZE macro to increase the heap size.
For example:

#define configTOTAL_HEAP_SIZE                     ( ( size_t )( 192 * 1024 ) )

Hi @tony-josi-aws

I went into FreeRTOSConfig.h and changed the configTOTAL_HEAP_SIZE as you mentioned.

I now have something interesting.
From my Windows machine I can ping the Zynq.
However, when I ping from my Raspberry Pi (Rpi) it doesn’t appear to work correctly. It just sort of hangs:

$ ping 10.100.100.160
PING 10.100.100.160 (10.100.100.160) 56(84) bytes of data.

This doesn’t happen when the Rpi pings the Windows machine or the other Rpi I have on my LAN. So there is something still a little weird about the ping.
Any thoughts?

Thanks,
-Sam

Once the ping from Rpi does not work, are you able to ping the device from your PC? Does it happen on both the Rpis? Please share the device console logs also.

As @aggarg suggested please make sure the Zynq is still running after the un replied pings.

However, when I ping from my Raspberry Pi (Rpi) it doesn’t appear to work correctly. It just sort of hangs

Also, one other reason this could happen could be that the MAC addresses have a conflict. Can you compare the MAC addresses of both Raspberry Pi (Rpi) and Zynq (if its configured)?