heinbali01 wrote on Friday, November 21, 2014:
While I was typing the response below, Richard was quicker…
But it still adds some information, it’s a bit more specific:
I would like to get a brief information about advantages (or disadvantages)
of FreeRTOS stack vs lwIP. In other words is it worth to pass to native stack
or keep using lwIP?
FreeRTOS+TCP was created with the aim:
- to get a close integration with FreeRTOS
- simple to use, a small configuration file with few items, easy bug-tracking
- fast, low-RAM, configurable memory foot-print
- Compatible with ultra-low-power, tickless kernel
As Richard wrote, +TCP has two ways to allocate network buffers:
- BufferAllocation_1.c : all buffers are allocated in advance
- BufferAllocation_2.c : buffers are allocated using pvPortMalloc() only when needed
The amount of memory needed per TCP socket depends on the buffer-sizes that you assign. These sizes are configurable using sockopt’s, thus yes, they are dynamic.
Once a TCP socket is connected, the buffer size is fixed, reserved, and can not be changed any more. The memory is freed when FreeRTOS_closesocket() is called. This guarantees quality of transmission: you will rarely see a TCP transmission fail half-way because malloc() was running low
The main disadvantages of lwIP stack is lack of ZERO COPY operation and lack of dynamic scale-ability.
I think lwIP does have a possibility for zerocopy if you use the call-back methods?
+TCP also has call-back methods, for instance:
BaseType_t onTcpReceive (xSocket_t xSocket, void * pData, size_t xLength )
/* Here pData is a direct pointer to the internal stream buffer. */
BaseType_t onUdpReceive (xSocket_t xSocket, void * pData, size_t xLength,
const struct freertos_sockaddr *pxFrom,
const struct freertos_sockaddr *pxDest )
/* pData points to the message received. A reply can be sent here */
Such functions can be bound to a socket with sockopts.
Please note that all call-back functions (also within lwIP) are risky because you’re writing code which is executed by the Network task. This task has a different and maybe limited stack, different rights / ownerships etc.
When using TCP, there is a zero-copy possibility while receiving data, not yet documented:
/* The "zero-copy" method for TCP: */
xRc = FreeRTOS_recv( pxClient->xTransferSocket, ( void * ) &pcBuffer,
0x20000u, FREERTOS_ZERO_COPY );
if( xRc <= 0 )
/* pcBuffer points to an internal stream buffer. 'xRc' bytes may be read. */
pxClient->ulRecvBytes += xRc;
/* Use the data, e.g. write them to a file */
/* Tell the driver the data ('xRc' bytes) may be flushed from the buffer. */
FreeRTOS_recv( pxClient->xTransferSocket, ( void * ) NULL, xRc, 0 );
The disadvantage of these call-backs of course is that they are not standard, it will be more difficult to port your code to another platform.
By last I mean that all memory allocation in lwIP are made static
(in compilation time) and I can’t configure specific device without
reprogramming it. I would like to know if this features are implemented
in FreeRTOS stack.
So yes, the sockopt calls will let you configure most of the RAM consumption ‘at runtime’.
NB. Noticed that:
UDP sockets can be nasty: suppose there is some kind of bombing of UDP broadcasts, and suppose that your application doesn’t have time to read the messages immediately. In that case a single UDP socket could grab all available network buffers in a short time and make your device become unreachable for a while.
+TCP will protect against this, with this define:
#define ipconfigUDP_MAX_RX_PACKETS 8
This means that ‘by default’, no more than 8 messages will be stored per UDP socket. The 9th message will be ignored. Again this can be adapted at runtime and per socket, by using the sockopt ‘FREERTOS_SO_UDP_MAX_RX_PACKETS’.
Its hard to be brief about +tcp…