FreeRTOS + TCP/IP on Arm Cortexa53

I’ve got this:
uint64 = 0706050403020100
uint32 = 03020100 07060504
uint16 = 0100 0302 0504 0706

Thank you. That is exactly the same, so no doubt that your UltraScale is configured little-endian.

@Maxim.Vechkanov wrote:

I am finally able to ping the board. But getting CRC errors: “CRC error: 1234 location 3”

Actually it is not a CRC- but a length-error:

    usLength = pxIPPacket->xIPHeader.usLength;
    usLength = FreeRTOS_ntohs( usLength );

    if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
    {
        usChecksum = ipINVALID_LENGTH;
        location = 3;
        goto error_exit;
    }

Now I would be very curious to see the contents of the struct pxIPPacket->xIPHeader.
That represents the IP-header of a packet.
Als the value of uxBufferLength, which is the number of bytes received.

pxIPPacket->xIPHeader .

ucVersionHeaderLength=0x00
ucDifferentiatedServicesCode=0x01
usLength=0x0008
usIdentification=0x0406
usFragmentOffset=0x0100
ucTimeToLive=0x00
ucProtocol=0x00u
sHeaderChecksum=0x0000
ulSourceIPAddress=0xa8c00000
ulDestinationIPAddress=0x0000c750

uxBufferLength = 0x000000000000002a

Contents of the IP header:

pxIPPacket->xIPHeader .
ucVersionHeaderLength=0x00        Should be 0x45, or at least 0x4.
ucDifferentiatedServicesCode=0x01
usLength=0x0008                   Should be at least 20
usIdentification=0x0406
usFragmentOffset=0x0100
ucTimeToLive=0x00                  Should not be zero
ucProtocol=0x00u                   Expected 1, 2, 6, 17  
sHeaderChecksum=0x0000
ulSourceIPAddress=0xa8c00000       168.192.0.0
ulDestinationIPAddress=0x0000c750  0.0.199.80

uxBufferLength = 0x2a     42 bytes received, that is possible

I can not make much of it.
I have only seen these kind of problems in case the memory shared with DMA was cached.

What does a received packet look like when it is just received, in x_emacpsif_dma.c around the macro iptraceNETWORK_INTERFACE_RECEIVE()?

As a test, could you change ucIsCachedMemory() to always return pdTRUE? just to see if the memories are still cached?

pxBuffer looks like this:

- xBufferListItem = {xItemValue=0x0000000000000000 
                                   pxNext=0x00000000001d7e28
                                   pxPrevious=0x00000000001d7dc0
                                   pvOwner=0x00000000001d7de0
                                   pvContainer=0x0000000000000000}
- ulIPAddress=0x00000000
- pucEthernetBuffer=0x00000000001ff4ca
- xDataLength=0x000000000000003c
- usPort=0x0000
- usBoundPort=0x0000
uint8_t ucIsCachedMemory( const uint8_t *pucBuffer )
{
uint8_t ucReturn;

	if( ( pucStartOfMemory != NULL ) &&
		( pucBuffer >= pucStartOfMemory ) &&
		( pucBuffer < ( pucStartOfMemory + uncMEMORY_SIZE ) ) )
	{
		ucReturn = pdFALSE;
	}
	else
	{
		ucReturn = pdTRUE;
	}

	return ucReturn;
}

ucReturn = pdFALSE is never invoked.

That is as expected.
Now just as a test, could you temporarily change it to:

uint8_t ucIsCachedMemory( const uint8_t *pucBuffer )
{
    return pdTRUE;
}

and then run the application?

pucEthernetBuffer=0x00000000001ff4ca

I would be curious to see a memory-dump of the contents of this pointer pucEthernetBuffer, just the first 42 bytes.

Now i’ve got no CRC or length error.

Where can i find this?

and then run the application?

Now i’ve got no CRC or length error.

Good to hear, but this would mean that the memory provided by uncached_memory.c in fact is cached memory.

Does it mean that you can communicate now? Can you ping the board?

pucEthernetBuffer=0x00000000001ff4ca

I would be curious to see a memory-dump of the contents of this pointer pucEthernetBuffer , just the first 42 bytes.

Where can i find this?

Well, if it works now for you, i don’t need to look this up anymore.

One of the many windows in Eclipse is called “memory”, it can show you the contents of the RAM. Fill in the value of the pointer pucEthernetBuffer, and you will see the packet.

I’d have to start it again with

uint8_t ucIsCachedMemory( const uint8_t *pucBuffer )
{
    return pdTRUE;
}

Yesterday, my software code was not built properly.

It still shows the CRC or rather length error.

Yes i can communicate and ping the board. That works fine.

this is how it looks like in the memory area for pucEthernetBuffer.

image

It looks like the CRC/length error is a false alarm. It is shown when xNetworkInterfaceOutput() calls usGenerateProtocolChecksum() with an ARP packet. It should only call it for IPv4 ICMP packets.

Could you make the following change in xNetworkInterfaceOutput() in NetworkInterface.c, around line 234:

-    if( ( pxPacket->xICMPPacket.xIPHeader.ucProtocol != ipPROTOCOL_UDP ) &&
+    if( ( pxPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) &&
+        ( pxPacket->xICMPPacket.xIPHeader.ucProtocol != ipPROTOCOL_UDP ) &&
         ( pxPacket->xICMPPacket.xIPHeader.ucProtocol != ipPROTOCOL_TCP ) )
     {
         /* The EMAC will calculate the checksum of the IP-header.
         It can only calculate protocol checksums of UDP and TCP,
         so for ICMP and other protocols it must be done manually. */
         usGenerateProtocolChecksum( (uint8_t*)&( pxPacket->xUDPPacket ), pxBuffer->xDataLength, pdTRUE );
     }

That will stop the error messages.

It works thank you Hein!

So i can say, the Network Driver for the UltraScale+ finally works.

Very good! Congratulations!

Have you already tried to make a TCP connection? Or exchange UDP packets? Have you tried to enabled DHCP?

I work on that.

I succesfully build a socket, and can connect through an test app.
May you have already a test for this? with some random data?

DHCP is still deactivated

I always find telnet an easy tool for testing TCP.
Here is a simple example: telnet.zip (2.8 KB)

In telnet_usage.c you see an example of how to use it.
The default port number is 23 ( see TELNET_PORT_NUMBER ).

A more complex tools is IPERF, which measures performance.
iperf_task_v3_0d.zip (7.3 KB)
Please see iperf_config.h for an example of configuration parameters.

Can anyone advice me on the following: I want to buy a Xilinx Ultrascale board in order to finish and test the FreeRTOS+TCP driver.

There is an affordable Ultra96-V2, would that be good enough to do the job?

@Maxim.Vechkanov, any suggestion?

Thanks, Hein

@htibosch ,
As far as I know, the only major difference in PS part between Xilinx MPSoC chips is that CG devices have Dual-Core A53 MPCore. The others have Quad-core.
I’m afraid, Ultra96-V2 does not have Ethernet (rj-45) port. I doubt that WiFi uses GEM.
I found this one in the list on Xilinx site: FZ3 Kit, with similar price. But it seems to require external JTAG like this JTAG-HS2.

I also asked Avnet and they offered to use SOM approach:
Carrier + Processor
But is looks quite expensive

Thank you for this answer, Maxim. I will study it and try to decide.
Hein

I ordered a FZ3 Kit. I will let you know how it goes.

I have started exploring my new FZ3 board with an Ultrascale, with 4 x Cortex-A53.

Thanks a lot to @Maxim.Vechkanov because he helped me to get started much quicker than I would have done on my own. He seems very experienced with Xilinx FPGA’s.

Here are some things that I found, just for your interest:

#define ipconfigNIC_N_TX_DESC ( 100 )
#define ipconfigNIC_N_RX_DESC ( 1000 )

That is much more than necessary. These are the number of descriptors that are reserved for the DMA. In a very fast sytem like UltraScale the following should be enough:

#define ipconfigNIC_N_TX_DESC ( 5 )
#define ipconfigNIC_N_RX_DESC ( 16 )

And then:

#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS \
      ( ipconfigNIC_N_RX_DESC + ipconfigNIC_N_TX_DESC )

This defines the total number of available network packets. That should be at least the sum of the DMA descriptors, let’s say:

#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS \
      ( ipconfigNIC_N_RX_DESC + ipconfigNIC_N_TX_DESC + 32U )

Note that received UDP packets are stored in a list of network packets, which belongs to a UDP socket. And then there may be packets traveling from the network interface to the IP-task.

The project uses BufferAllocation_2, which allocates network buffers by using pvPortMalloc(), whereas we wanted to use the uncached memory, BufferAllocation_1.c.
The latter allocates all necessary network buffers statically, at start-up.

I have an application running now, and the PHY is recognised as a Marvell. So I am as far as Philipp last reported.

Hello Guys,

I see you are working with tcp/ip stack on zynq ultrascale board. I m working in similar project, I use a ZYNQ ULTRASCALE XCZU7CG MCU ( precisely we use the R5 cortex ). I can’t send an UDP frame or receive it. In Tx mode , Stack try to send an arp frame but i don’t see any frame sent in wireshark. I use a freeRtos 10.2.1 stack. this is my dump memory for GEM register and PL390 below.
0x101004 frame status and length
0x0002CDEA frame buffer adresse frame length is 60 byte

Any Idea why the frame didn’t be sent and seen by wireshark ?
Any valid example was always welcome !
I suspect that the not alignment of our buffer can cause this issue. the buffer shifter by 2 bytes. can this be the source of our issue ?
other suspicion is that the dma don’t send all data or the phy doesn’t send the data, any way to debug this two module.

best regards

Hello khalil, yes I am working on a FreeRTOS+TCP driver for UltraScale+. And I need co-testers.

It needs a small adaptation to have UDP work on a 64-bit platform.
ARP, ICMP(echo), and TCP work fine already.
I will get UDP to work and post the driver (as it is) on this forum.