FreeRTOS+TCP Xil_DCache usage in zynq port

Hello. I’m writing application on Zynq involving AXI Ethernet with DMA. I’m using Zynq port as an example of working with DMA. If Ethernet buffers are in cached memory we need to flush and invalidate cache (x_emacpsif_dma.c). The question is: why is invalidation region shifted by 2 bytes?

Xil_DCacheFlushRange( ( INTPTR ) pxBuffer->pucEthernetBuffer, ( u32 ) pxBuffer->xDataLength );

Xil_DCacheInvalidateRange( ( ( uint32_t ) pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, ( uint32_t ) dmaRX_TX_BUFFER_SIZE );

I know that pucEthernetBuffer has special alignment to provide easy access to its fields but does it matter here? What about last 2 bytes which now are not included?

And another question here. It is related but separate question. There is a recommendation somewhere to use BufferAllocation_2.c for beginners. So I used it. My guess is that it should not be used with caching even with cache invalidation function because thouse buffers are not chache aligned? Or am I supposed to edit BufferAllocation_2.c to make them chache aligned?

Hello @Ddiimmaann,

Thank you for your interest in FreeRTOS, and thanks for taking the effort to report these irregularities.

Normally, I think that most developers will have the GMAC driver use non-cached memory, using BufferAllocation_1. I think that that is the fastest and safest solution.

Just tested BufferAllocation_2 with cached memory. I saw that the L1-DCache is on at start-up.
The function ucIsCachedMemory() returns true, unless the memory object is part of the 1 MB block pucUncachedMemory[], and uncached_memory.c is being used.

This indeed doesn’t look logical:

Xil_DCacheFlushRange( pxBuffer->pucEthernetBuffer, xLength );

Xil_DCacheInvalidateRange( pxBuffer->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE, xLength );

although it won’t make a difference if ipconfigPACKET_FILLER_SIZE is subtracted or not. I would propose to leave it out:

-    Xil_DCacheInvalidateRange( pxBuffer->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE, xLength );
+    Xil_DCacheInvalidateRange( pxBuffer->pucEthernetBuffer, xLength );

The two Xil_DCache functions will round down the starting address to a multiple of 32 bytes, ie. the start of a cache line. The 2 bytes won’t make a difference.

When using BufferAllocation_1, the network buffers are 32-bits aligned.

When your platform has a 32-bits CPU, the pvPortMalloc() will return 32-bit aligned pointers:

~~~

#define portBYTE_ALIGNMENT 32
#define portBYTE_ALIGNMENT_MASK 0x001f

~~~

So the buffers will align with the cash lines.

So far the DCache and the GMAC driver.

Thank you for the answer!