Hello. I am experiencing an issue using FreeRTOS with LwIP that I am having a hard time understanding. For what is worth, I am not an experienced C developer, nor FreeRTOS user, so I apologize if I am doing something obviously incorrect. I am developing my application on a MicroBlaze processor on an Xilinx Artix7 device.
The application receives data via two interfaces: UART and Ethernet, but only one is in use at any time (if UART is in use, the threads used by LwIP are not started and vice versa). For the latter I am using TCP/IP LwIP with DMA. Messages that arrive to the unit are of varying size, and for that reason I am using dynamically allocated memory as the size of these messages are not known before-hand. In the thread that receives data, I allocate memory to buffer a complete message once the size is known using pvPortMalloc. The message is stored using this memory, and a pointer to the memory sent to the thread that processes the message via a queue. Once processing is complete, the memory is freed using vPortFree. This seems to work perfectly fine for the UART, but this procedure results in an assertion error after only a few packets (somewhere around 40 bytes in total) have been handled this way in the thread that receives data from a socket via LwIP.
I am using heap4 and the actual assertion error is on line 236, which states:
configASSERT( ( ( ( sizet ) pxNewBlockLink ) & portBYTEALIGNMENTMASK ) == 0 );
I have plenty of RAM (several MBs), so the error does not seem related to lack of memory. I also checked this and there's plenty of heap-space remaining.
The code leading up to this is equal for both the UART- and LwIP receiving threads, and follows this format:
...--After receiving a complete message--...
u8 msgBuffer = (u8)pvPortMalloc((LENGTH)*sizeof(u8));
xQueueSendToBack(ctrlQueue, &msgBuffer,(TickType_t) 10);
u8 msg = 0;
if(xQueueReceive(ctrlQueue, &msg, portMAXDELAY ) == pdTRUE)
With the queue being created like so:
ctrlQueue = xQueueCreate(5, sizeof(u8));
I would be grateful if anyone could shine some light on this, or maybe there is a smoother way of passing varying-size packets of data between two threads. Thanks.
That is a very odd assert to fail. The heap allocater should always
ensure the proper byte alignment is maintained - no matter the size of
the block you request, internally within heap4.c it will make any
adjustments necessary. If that assert fails then I'm going to guess
variables used by heap4.c has simply become corrupted by something
stomping on them.
lwIP has certain requirements for use in multi-threaded environments.
Perhaps it is not configured correctly. I'm afraid I can't advice on
the configuration options actually required though. Did you add lwIP a
multithreaded project yourself? Or was it provided already configured
for multi-threading? It also depends on the API you are calling as lwIP
as three APIs, raw, netcon and sockets. I think sockets is the only one
that can be called from more than one task, but that information might
be out of date.
The assert is indeed very odd.
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUMBLOCKSIZE )
pxBlock is being dereferenced, and therefore I would think that it is well aligned.
The value of
xWantedSize has been tested: there is enough free space and it is also well aligned.
Can you confirm that the following defines are OK :
define portBYTE_ALIGNMENT 4
define portBYTEALIGNMENTMASK ( 0x0003 )
The routines in heap_x have sanity checks at certain points. In
configASSERT() statements the validity of data is being checked.
heap_4 asserts, I would try to check if some function is writing out of defined memory. Maybe
N bytes were claimed and
N+ bytes were being written to? Or, by mistake, data is written to memory that has been freed by
vPortFree(). Or some task has a stack overflow?
How did you create the queue, with an element size equal to
sizeof( char * )?
By the way, this might interest you: FreeRTOS has its own TCP/IP stack called FreeRTOS+TCP, which you can find here. It has a demo for the Xilinx Zynq processor.
Hello again and thank you both for the response (did not really expect it on a sunday). I have solved the problem, it seems. It turned out the error was not related to the LwIP thread at all, although this was the only place where it showed itself. The data arriving to the unit is encoded, and on decoding, two additional bytes following that which was malloced was being written to. Rewriting the part that does the decoding solved the problem.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.