Xilinx ultrascale A53 Free RTOS + TCP /UDP

Hi

Sorry I’m new to TCP.
I’m trying to setup FREE RTOS + TCP on a custom board using xilinx ultrascale + TI DP83822 PHY.
The application runs on A53 core 0.
My starting point was the Free RTOS example we can generate using the SDK to set up the OS.
Once working I imported the the FREE RTOS + TCP package specific to xilinx ultrascale. I took one matching my OS version / version 180821.
I modified the PHY init to match my device (which is only capable of 100Mbds).
The board is using GEM3 controller.

The IP stack seems initialize OK then go to process a network down event were it initialize the PHY.
From there , when Link is detected up by the PHY, a UDP socket is created and bound to port 0x8000.
Every second a message is sent by the application.
I can see the code going to the emacps_send_message wich triggers emacps_send_message interrupt.
I cannot see any signal at PHY input.
Same on the receive side, the PHY RX signals seem valid but not receive interrupt event is generated.

Checking HW with HW team, all looks ok…

Did somebody already had this combination of GEM / PHY ?

Most interesting post so far was FreeRTOS + TCP/IP on Arm Cortexa53
Still seems most of the changes are in the package I imported.
I’ve been stuck on it for a week now looking at a lot resource I could find on internet but I could not figure out what is the problem.

Any pointer would be greatly appreciated.

Thanks

Seb

Am I correct in thinking this sounds like a hardware configuration/hardware setup issue at this point rather than a FreeRTOS+TCP issue? If so, can you set the MAC into loopback mode and then do some low level test? Xilinx often provide a test routine for their peripherals.

Hi Richard

Thanks for your answer. Well I cam across while searching and it seems I need to connect 2 GEMs together (externally) to be able to do so.
On my board, I have only one GEM “going” out.
I’ll dig further on this topic.

Would have experience with PHY errors and what they are actually meaning from a hardware perspective ?
For example reading the RxErr conter of the device it increments to max then back to 0 and max again.
Been checking the wiring it seems all ok …

From HW perspective I’m not too sure what to look at.

thanks

Seb

The interesting post that you referred to resulted in a new driver for the Xilinx Ultrascale, which you can find here. I assume you found that driver already?

Hi Hein

Thanks a lot for sending the link over. I think what I’ve got is older. I give that a proper look.
I’ve been testing with a ZCU106 eval board and observed that even with no code running the PC could detect the cable.
Somewhat that narrows down the problem to something related to HW.
I’m trying now to get the code running on this eval board to check that code is OK.
I’ll try with what I’ve got now but will move to the latest driver.
Thanks a lot for your help.

Regards

Seb

Hi

Quick question though, does the OS version I’m using has to match the TCP stack ?
I’m using kernel version 10.1.1 currently.
Thanks

Seb

I’m not aware of any dependencies between the TCP and kernel versions.

Hi
OK that’s great !
I can see traffic now between my eval board and the PC with WireShark.
FREE RTOS does not show up any error but I can’t ping the board.
So probably I will move to the latest driver.
Any particular point I need to check specially ?
Thanks

Seb

Hi

I spotted that line in the new driver which different from mine:
NetworkInterface.c / line202 / XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );

The Zynq 7020 was supporting divisions up to that level but I believe the ultrascale only supports division up to 48 with the MAC fed by 100MHz clock.
Am I wrong ?

Regards

Seb

I’ve now moved to the latest driver.
I can see traffic from PC only in wireshark and can’t ping the board still.
The application will try to send a message every second or so. I can see the code going to the emacps_send_message function.
It goes successfully down to :
/* Make STARTTX high /
uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET );
/
Start transmit */
xemacpsif->txBusy = pdTRUE;
It’s looking the dma works ok.
but emacsps_send_handler is never triggered nor the receive handler by the way.
I’ll double check the state of interrupt enable …
Could you point me in the direction of what could be wrong ?

Thanks

Seb

PS. I uploaded the testing project that I used when developing the network driver for Ultrascale here.
I used this FZ3 Card.

I’ve been testing with a ZCU106 eval board and observed that even with no code running the PC could detect the cable.

Yes, in my experience also: all PHY’s have auto negotiating enabled by default, and they tend to connect full-duplex at the highest available speed. That happens without running any software.

does the OS version I’m using has to match the TCP stack ?
I’m using kernel version 10.1.1 currently.

That is OK. FreeRTOS+TCP was developed when the kernel was around V8.2.0. So yes, 10.x.x is perfect.

Could you point me in the direction of what could be wrong?

That is difficult to say from a distance.
In general, I think of:

  • A miss configuration in the FPGA logic
    ( don’t ask me because I always ask advice to other people about this )
  • DMA problems because of using cached memory
  • Some clock not enabled, or running at the wrong speed.
  • Interrupt handler not installed or not enabled
  • I/O pins not correctly configured

Hi

Here is the the checks I’ve been making :

  • FPGA Config OK . GEM3 fed by clock / pin assignment to signals consistent with schematic.
  • Clock seems ok
  • Interrupt handler working

Interrupt handler is working but goes into the error handler emacps_error_handler twice. Seems after that interrupts get disabled hence I did not see them in first place.
the 2 errors I get are:

  • in receive : “Receive DMA error” (direction = 0x02 / ErrorWord = 0x08)
  • in transmit : ErrorWord = 0x0110
    -> “Transmit DMA error” and “Transmit buffer exhausted”

I’m not sure why I get this as all init seems to go OK. Not sure what I’m missing.

Regards

Seb

Hi Hein

Thanks for sharing the code.
Finally the issue about the DMA errors was coming from the fact that Isolation was enabled into the FPGA / HW setup. The area reserved for DMA was not matching what FREE RTOS was allocating for uncached memory at DMA init.
I’ve turned off isolation in my test setup. All is working pretty well now.
It would probably be necessary for us to enable isolation again. In that case I’m not too sure how I should modify the following lines in uncached_memory.c to set the start of pucUncachedMemory at the correct location without breaking anything.

#if ( ipconfigULTRASCALE == 1 )
/* Reserve 2 MB of memory. /
#define uncMEMORY_SIZE 0x200000U
#define DDR_MEMORY_END ( XPAR_PSU_DDR_0_S_AXI_HIGHADDR )
#define uncMEMORY_ATTRIBUTE NORM_NONCACHE | INNER_SHAREABLE
#else

#endif /
( ipconfigULTRASCALE == 1 ) */

static uint8_t pucUncachedMemory[ uncMEMORY_SIZE ] attribute( ( aligned( uncMEMORY_SIZE ) ) );

In any case, many thanks for your help. That was really appreciated.

Regards

Seb

Hello Seb, in the Zynq driver, the location of the uncached memory block is set at runtime here. It is placed after the last data and bss declarations, using _end.
Likewise you can change it to use a different segment.

I just investigated the possibility of working with cached memory only:

The network driver shares these objects with DMA:

  • RX descriptors
  • TX descriptors
  • Packet buffers ( pxBuffer->pucEthernetBuffer )

The RX and TX descriptors are declared in uncached memory.
For the Packet buffers, it depends on the macro nicUSE_UNCACHED_MEMORY, when set the buffers will be obtained by calling pucGetUncachedMemory().

When nicUSE_UNCACHED_MEMORY is 0, then the packet buffers (as in pxBuffer->pucEthernetBuffer) are declared statically and thus cached. In that case, the functions Xil_DCacheFlushRange() and Xil_DCacheInvalidateRange() will be called when necessary.

If you want to avoid all use of uncached memory, you’ll have to add a few more calls to Xil_DCacheFlushRange() and Xil_DCacheInvalidateRange().

That is a possibility.

Hi

Your explanations are very clear.
Now that I have a code that runs well on the eval board, I’ll try to crack what’s happening to our custom board.
Thanks a lot for your help.

Regards

Seb