I'm using FreeRTOS+UDP stack and I have encountered two problems (maybe connected).
As the subject says one of them is freeing already free buffer. I'm using BufferAllocation1 and zero copy principle. Buffer is taken in the defferedRxTask by the function pxNetworkBufferGet() swapped with the buffer from the rx descriptor and propagated to the IP stack trough xNetworkEventQueue. On the other side, I'm using FreeRTOSselect() and FreeRTOSrecvfrom() to get data from the socket. The only place where I'm freeing buffers (execpt the frees caused by IP stack) is after getting data from a socket. And every now and then configASSERT( xListItemAlreadyInFreeList == pdFALSE ); in the vNetworkBufferRelease() called after receiving data from a socket fails. Looks like problem occurs only in high ethernet traffic conditions.
Trying to debug that I have encountered another problem and that is configASSERT( ( listCURRENTLISTLENGTH( &( pxSocket->xWaitingPacketsList ) ) > 0U ) ); in the FreeRTOSrecvfrom(); waitingPacketSemaphore has been successfully obtained but the socket list was actually empty...
I don't know if two problems are connected but I'm having really hard time dealing with them.
Has anyone had similar experience or idea how to deal with it?
I'm using STM32F207 uC.
Both symptoms could possibly be concurrency related - I would recommend
scrutinising the driver code, especially if buffers are being used in
both interrupts and tasks. For example, where are the DMA buffers being
swapped. Is that within the ISR? If so, how is the new buffer obtained
from inside the ISR?
I also believe it is concurrency related problem but I'm having really hard time tracking it down, even with the trace macros defined...
Buffers are swapped (and obtained) in a dedicated deferred Rx thread. I'm only giving notifications from the ISR to trigger the Rx thread, but whole memory process is done outside of the ISR.
With trace macros defined what I can see is:
and then the same buffer again released without being obtained first. And as I mentioned in the previous post the only place where I'm releasing buffers is after receiving data from the socket. And I have no idea how the socket is passing buffer which was not obtained before, nor how to trace that...
You possibly know that FreeRTOS+UDP now has a successor that includes many more protocols? It's called FreeRTOS+TCP. It is based on the same principles and methods.
But your problem ( double releasing of a network buffer ) should not occur of course.
When it happens to me that network buffers are not properly released, I temporarily add the parameter
"pcWhere" to these functions:
const char *pcWhere, sizet xRequestedSizeBytes, TickType_t xBlockTimeTicks )
const char *pcWhere, xNetworkBufferDescriptor_t * const pxNetworkBuffer )
It forces me to write a description of the calling location, e.g. :
pxNetworkBufferGet( "deferredRx", xSize, xBlockTimeTicks );
vNetworkBufferRelease( "myTask2", pxNetworkBuffer );
Make sure that the logging of these events ( "get" / "release" ) is reliable. I normally use a cyclic buffer which can be inspected by the debugger.
Also in FreeRTOS+TCP, BufferAllocation_1 contains some helping code if
ipconfigTCP_IP_SANITY is defined:
BaseTypet prvIsFreeBuffer( const NetworkBufferDescriptort *pxDescr );
UBaseTypet bIsValidNetworkDescriptor( const NetworkBufferDescriptort * pxDesc );
Crashes with Network buffers are nasty, and these functions help to avoid crashes by checking the validity of pointers.
I bet that the cause of your problem is a simple one. Once found, you will say: ah yes, of course :-)
Please let us know. Hein
No progress so far. If/when I find the problem I let you know.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.