Since I have a lot of problems to get the TCP IP stack running on the CortexA53, I wanted to ask if there is someone who also uses it and has managed to get the TCP IP stack running.
What have you tried? What problems have you encountered? Is the Ethernet MAC on the UltraScale different to that on the Zynq as there is a driver for the Zynq already?
The first problem I had was that an error occurred when creating the uncached memory area. I have fixed this with the following. Therefore I had to change the following:
the following change must be made to uncached_memory.c
the defined size of
“UNCACHED_MEMORY_SIZE”
must be changed from 1MB to 2MB, because the minimum block size in MMU is 2MB.
of: #define UNCACHED_MEMORY_SIZE 0x100000ul
on: #define UNCACHED_MEMORY_SIZE 0x200000ul
and as a further point the attribute must be changed.
must be changed from 1MB to 2MB, because the minimum block size in MMU is 2MB.
of: #define UNCACHED_MEMORY_SIZE 0x100000ul
on: #define UNCACHED_MEMORY_SIZE 0x200000ul
Thanks for this, we will change that with an #ifdef
and as a further point the attribute must be changed.
This module xemacps.c is not part of the +TCP Network Interface.
That would be useless to write zero’s to that Status Register. Bits in this register are cleared by writing a 1.
in xemacps_hw.h:
UltraScale+:
#define XEMACPS_SR_ALL_MASK 0xFFFFFFFFU /**< Mask for full register */
ZYNQ 7000:
no definition of XEMACPS_SR_ALL_MASK 0xFFFFFFFFU
I think that the same macro applies to the ZYNQ 7000 : writing ones clear the bits.
Hello @Mulle
I faced the same and managed to make it work. I wanted to share it, but I deleted the code, cause I did not write it a good way and the task was rejected.
What I remember is:
I used lwIP port provided with Xilinx SDK as a reference.
Ethernet MACs on US+ and 7000 are different. One of the differences is in buffer descriptor structure. The structure for US+ takes into accout a possible 64-bit addressing, so some fields are shifted from where they were in 7000
Hello Maxim Vechkanov, thank you very much for responding to this thread.
Unfortunately, I don’t have such a board my self, I hope that @mulle finds time to check it.
Thanks, Hein
Assuming there is no other bug it’s a matter of tuning/limit memory consumption of the stack.
FreeRTOSIPConfig.h contains a number of parameters related to that and also the forum contains some posts regarding this configuration for different scenarios.
Tuning strongly depends on your use case. A rather slow control connection with very few simultaneously opened sockets requires less reserved network buffers, smaller sliding window sizes etc.
I had a surprising effect with a bunch of ARP requests from a Windows peer PC during startup consuming more buffers than expected and had to bump some parameters…
Wireshark helped me to find out what’s going on.
So try to estimate the requirements of your application and tweak FreeRTOSIPConfig.h accordingly and maybe have a look at the wire.
Looks like the MAC driver runs out of ethernet frame rx-DMA buffer descriptors. There must be a configuration for the (array)size of the rx/tx DMA descriptor rings. Or check the source of the driver where these arrays are defined.
Unfortunately I’m not familiar with the Zynq port…
Have you corrected the buffer descriptors (BD) related code?
As you said, APU core code is compiled by aarch64. According to UG1085 and Xilinx BSP code, in that case BD is 128 bits wide and BD alignment restriction is 64 bytes
It means that
Maxim, thanks for your input. I have no experience with UltraScale yet.
Would the following declaration solve it?
struct xBD_TYPE {
uint32_t address;
uint32_t flags;
/* Fill it up so the struct gets a size of 16 bytes. */
uint32_t filler[ XEMACPS_BD_NUM_WORDS - 2 ];
};
PS the first xBD struct already has a alignment of 4 KByte in un-cached memory ( see uncached_memory.c ).
Hein, I hope so.
Thought it requires the alignment for each BD, but you are right, only aligment of the start of BD ring is required.
I think it is better to put it under __aarch64__ symbol definition, like:
struct xBD_TYPE {
uint32_t address;
uint32_t flags;
#ifdef __aarch64__
/* Fill it up so the struct gets a size of 16 bytes. */
uint32_t address_high;
uint32_t reserved;
#endif
};
I am not sure what is better: rename “address” to “address_low” or keep it as is.
Someone might need 64-bit addressing support. And for RPU cores of US+, 32-bit addressing still required to be used, according to Xilinx’s driver.
Regarding the uncached memory. US+ baremetal uses 2 MB MMU sections, so I believe 2 MB uncached memory aligned to 2 MB boundary should be used.
I think you can use the code you provided, if uncached memory is addressable by 32-bit word.
I would propose you to add some verbose debugging print to emacps_check_rx to see more details about the received descriptor.
I beleive this case is normal:
( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0
Because as far as I understand emacps_check_rx tries to read out all the messages which have been received from the previous call. So it stops once reaches the descriptor which is not yet filled by HW.
The bad thing is if you see "emacps_check_rx: unable to allocate a Network Buffer\n". I beleive it means lack of memory in TCP/IP stack. Have you tried to increase memory for TCP/IP stack buffers? You can start from very big values just to be sure that they are enough.
And another thing I would propose to check is this piece of code:
if( ethMsg != NULL )
{
passEthMessages( );
}
If ehMsg is NULL after the loop, it means that an rx IRQ is received, but on RX frames can be passed to the stack, what is a bad situation in my opinion.
I think you can use the code you provided, if uncached memory is addressable by 32-bit word.
How can I make sure that this is true?
( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0
i mean this leads that ethMsg is NULL.
emacps_check_rx: unable to allocate a Network Buffer\n
This does not occur because the ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 condition is true and therefore a break occurs.
Have you tried to increase memory for TCP/IP stack buffers?
The Zynq 7000 driver has been around for a long time and has been thoroughly tested. Maybe we should concentrate on the differences between the Zynq and UltraScale.