FreeRTOS + lwIP TCP cannot receive large packages at high rates

That is what I am doing. I first read the header so I get the total size. Then with the inner loop I keep reading until I get that number of bytes. If I do that I get a full buffer

Ahh, right.
What means full buffer ?
You steadily (blocking ?) recv data from the socket. That should work as long the peer keeps sending the image data until done.
However, check the return code of recv. It might get -1 on error…

It might be something else…it does a couple of loops and then goes into port_asm_vector.S, line:

.org (FREERTOS_VBAR + 0x200)
	b	FreeRTOS_SWI_Handler

recv will block until it receives the number of bytes that I specify, right? If so, there would be no need to write it in two loops but two consecutive recv calls. One for the header and then to read all the bytes that it says

I hope there is a free paired with malloc :wink:
And no, recv returns whatever it can. The given number of bytes is the desired amount of data. So you have to collect all needed data in application code counting recv’d bytes, adjusting the recv buffer offset accordingly until you got all data from the peer.
And this also applies even to the reception of the 4 byte header !

There wasn’t :smiley: I forgot to copy it to make this new task.
Ok, seems to be solved. The issue then we could say was the combination of selectand recvthen? If so, the solution would be to use one task per incoming socket and a mutex for the DMA.

Thank you very much @hs2 for your huge help.

Yes, exactly. The recv events signaled by select are not coupled with/directly related to the number of bytes available in the socket. It only tells you there is something new to read. User code has to take care to handle all recv data available when getting signaled. Even if it’s already the beginning of the next image block…

One more hint: You might tune your send/recv behavior setting a socket option e.g.

int Size = 64 * 1024;
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &Size, sizeof(Size)) < 0) ... error...

resp. SO_SNDBUF to increase the network stack internal socket buffer.
The size depends on your expected data blocks/traffic.
Increasing it helps to have less send/recv calls because usually they can handle more data per call.

Well that is what I had. Only to wait for socket activity with select and then with those 2 loops with recv checking the correct amount of that to receive.

That also has a limit, right? How can I set it or check it?

That’s not exactly what you had since you recv’d just the number of expected bytes and not all bytes from the socket.
As mentioned the mechanism is getting signaled by select and recv(..., MSG_DONTWAIT) i.e. non-blocking until recv returns an error (-1) with errno set to EWOULDBLOCK. There might be the last part of an image data block and already the 1st part of the next one available in the socket (buffer) !

The socket buffer size is limited by the available heap. So if you have plenty of heap you can set it e.g. to the size of a complete image or size of the data you want to transfer at once.

Ok, I get it now…I was only reading the expected amount and there could have been more data in the buffer…

:+1:
I forgot to mention that setsockopt returns an error with errno being set accordingly also if the requested size is too big.

Where should setsockopt be called? after creating it, before the while(1)is ok?

Yes, that’s ok. I usually setup this kind of options right after connect resp. accept when they are going to be used for data traffic.

If I have other tasks handling DMA and I leave individual tasks for incoming socket, I should set the priorities of TCP-related sockets to be higher so as soon as there is something on any socket all other tasks that could be executing will be preemted so I can quickly read the TCP buffer to avoid getting it full, right?

Sure if fast and smooth data streaming to/from FPGA has high prio for your application it’s good to give the handler tasks high prio. On the other hand it’s not a problem if you don’t fetch incoming data as they arrive. Sometimes you want a certain (lower) data rate (e.g. 30 FPS in your case) or the embedded system can’t handle ethernet wire speed but a multi-core PC as sending peer can, just let TCP flow control handle that for you.
Receive data flow is throttled by the TCP stack (by shrinking the receive window) automatically as the socket buffer fills up.
A maybe useful side effect of having a handler task per socket/FPGA data stream could be that you can prioritize the different data streams. That’s obviously not possible if all streams would be handled by 1 task.

PS: A final word regarding the common pitfall with TCP send/recv returning an arbitrary number of bytes less than or equal to the desired size.
Remember it can also happen that you want to receive 4 bytes and you just get 3 byte.
I’d recommend to add a wrapper function doing the socket send/recv in a loop that guarantees that you really send/receive the requested number of bytes which is a common use case. Similar to your code fetching the image data.
Use this wrappers for all socket send/receives with a required number of bytes.