heinbali01 wrote on Thursday, September 01, 2016:
The name “+TCP stack” can be misleading, because it includes both +UDP ( the former version of FreeRTOS’ IP-stack ) and +TCP.
A UDP packet travels on its own from end-point to end-point. And as +TCP doesn’t implement Ethernet fragmentation, there will be single Ethernet message per UDP packet ( Fragmentation would make it possible to transmit larger datagrams ).
Only TCP sockets have a stream buffer.
UDP sockets are much simpler. A UDP socket puts the received Network Buffers into a List. As Richard wrote, UDP packets can travel zero-copy, all the way from DMA-reception in the EMAC until the user application.
In FreeRTOS_DHCP.c you find an example of zero-copy reception:
lBytes = FreeRTOS_recvfrom( xDHCPData.xDHCPSocket, ( void * ) &pucUDPPayload,
0ul, FREERTOS_ZERO_COPY, &xClient, &xClientLength );
if( lBytes > 0 )
/* Use the 'lBytes' UDP payload data. */
FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayload );
pucUDPPayload is a bit of a special pointer. It points somewhere halfway in the
pucEthernetBuffer of a
The Ethernet Header, the IP-header and UDP-header are skipped.
pucUDPPayload points to the first data-byte of the UDP-payload.
FreeRTOS_ReleaseUDPPayloadBuffer() will find the
pucEthernetBuffer and it will release the original
Does that make sense?
I think that the
FREERTOS_ZERO_COPY flag is exactly what you are looking for.
I am expecting a “group” of these messages being received back-to-back
with little time between them.
Normally when you receive N packets, the network driver will queue N messages for the IP-task. When packets are received in a burst, the driver can link them together in a chain and put a single message into the queue. You can reach quite a performance gain with this technique:
#define ipconfigUSE_LINKED_RX_MESSAGES 1
Find an example at the bottom of this post.
Since the stack is running at a higher priority than my task calling
FreeRTOS_recvfrom, will the stack drop or “queue” another incoming
message if I have not finished initial processing of the previous
message and gotten back to issue another FreeRTOS_recvfrom call?
As Richard wrote: the driver will queue-up packets as long as there are Network Buffers available.
Example of using linked RX messages:
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
NetworkBufferDescriptor_t *pxHead = NULL;
NetworkBufferDescriptor_t *pxTail = NULL;
for( ;; )
/* driver_receive() returns the next available packet.
It may not block. When nothing has arrived, it returns
pxNetworkBuffer = driver_receive();
if( pxNetworkBuffer == NULL )
/* That's it for now. */
if( pxHead == NULL )
/* Remember the first packet. */
pxHead = pxNetworkBuffer;
if( pxTail != NULL )
/* Make the link */
pxTail->pxNextBuffer = pxNetworkBuffer;
/* Remember the last packet. */
pxTail = pxNetworkBuffer;
if( pxHead != NULL )
/* Just make sure that the last item has no next buffer: */
pxTail->pxNextBuffer = NULL;
xRxEvent.eEventType = eNetworkRxEvent;
xRxEvent.pvData = ( void * )pxHead;
/* Send a linked list of packets. */
if( xSendEventStructToIPTask( &xRxEvent, ( portTickType ) 1000 ) != pdPASS )
/* Sending failed, make sure to release every linked Network Buffer! */
#endif /* ipconfigUSE_LINKED_RX_MESSAGES != 0 */