FreeRTOS hangs in vListInsert
Hi,
since some days I am stuck in a very indeterministic problem. I am working on an LM3S8962 evaluation board. Using the arm-none-eabi-gcc (Sourcery G++ Lite 2008q1-126) 4.2.3 and arm-none-eabi-g++. I wrote a c++ wrapper for FreeRTOS which is working fine (I did a test running several tasks using semaphore and queues to communicate and the UART1 for output, which is running stable since a week).
However, I have a serious problem with receiving from the UART. I implemented an interrupt handle for my UART that is sending a message to a queue when a string has been send to the uart ending with a newline or escape char.
The message is received in a task that I stripped so much down, that it is basically doing nothing but receiving this message. This works for some seconds sometimes several minutes up to over half an hour (I am continously sending a message of 8 bytes to the UART and the frequency of the message or the baud rate does not matter, I tested several setups). But than it stops in an endless loop trying to add the task to the eventlist. Here the debug trace:
Thread [0] (Suspended: Signal ‘SIGINT’ received. Description: Interrupt.)
6 vListInsert() /home/szymansk/workspace/SymbricatorRTOS/FreeRTOS503/list.c:130 0x00012334
5 vTaskPlaceOnEventList() /home/szymansk/workspace/SymbricatorRTOS/FreeRTOS503/tasks.c:1494 0x0001392a
4 xQueueGenericReceive() /home/szymansk/workspace/SymbricatorRTOS/FreeRTOS503/queue.c:930 0x000126c0
3 UART0IOStreamTask::task() /home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/src/tasks/UART0IOStreamTask.cpp:271 0x000035ac
2 __thread_main_dispatcher() /home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/src/core/Task.cpp:114 0x000092b4
1 <symbol is not available> 0x00000000
The endless loop is caused by the problem that the pxIterator in vListInsert() is the same as pxNewListItem pointing with pxIterator->next to itself. Therefor is pxIterator->pxNext->xItemValue <= xValueOfInsertion always true and causes the endless loop.
pxList 0x2000646c
uxNumberOfItems 2
pxIndex 0x20006474
xItemValue 4294967295
pxNext 0x200064f4
pxPrevious 0x200064f4
pvOwner 0x0000000a
pvContainer 0x0000000a
xListEnd {…}
pxNewListItem 0x200064f4
xItemValue 6
pxNext 0x200064f4
pxPrevious 0x200064f4
pvOwner 0x200064dc
pvContainer 0x2000646c
pxIterator 0x200064f4
xItemValue 6
pxNext 0x200064f4
pxPrevious 0x200064f4
pvOwner 0x200064dc
pvContainer 0x2000646c
"pxCurrentTCB" = 0x200064dc
pxTopOfStack = 0x20006780
xGenericListItem = {…}
xEventListItem = {…}
xItemValue = 6
pxNext = 0x200064f4
pxPrevious = 0x200064f4
pvOwner = 0x200064dc
pvContainer = 0x2000646c
uxPriority = 5
pxStack = 0x20006520
*pxStack = 2779096485
pcTaskName = 0x20006510
I also implemented the vApplicationStackOverflowHook as an infinite loop and put a breakpoint in it (using configCHECK_FOR_STACK_OVERFLOW 2) . But it has never been called. As far as I can say seems the stack of the task to be ok after I had a look at the memory.
Does anyone have a clue why this doesn’t work? What am I doing wrong?
Many thanks in advance and best regards,
Marc.
void UART0IOStreamTask::task( )
{
static portCHAR buf[UARTIOStream::LINELENGTH];
for( ;; )
{
// Wait for a uart message to arrive.
if (xQueueReceive( uart0Queue, buf, 50 ) == pdTRUE)
UARTCharPut(UART1_BASE, ‘.’);
}
}
//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
extern "C"
void
UART0IntHandler(void)
{
unsigned long ulStatus;
char cChar;
static char bLastWasCR = 0;
static unsigned long ulCount = 0;
portBASE_TYPE xHigherPriorityTaskWoken;
unsigned long ulLen = UARTIOStream::TXBUFFERSIZE;
char pcBuf[]={’1’};
//
// Adjust the length back by 1 to leave space for the trailing
// null terminator.
//
ulLen–;
//
// Get the interrrupt status.
//
ulStatus = UARTIntStatus(UART0_BASE, true);
//
// Clear the asserted interrupts.
//
UARTIntClear(UART0_BASE, ulStatus);
//
// Loop while there are characters in the receive FIFO.
//
/* We have not woken a task at the start of the ISR. */
xHigherPriorityTaskWoken = pdFALSE;
//
// Read the next character from the UART and write it back to the queue
//
/* Was an Rx interrpt pending? */
if( ulStatus & UART_INT_RX || ulStatus & UART_INT_RT)
{
/* Loop until the buffer is empty. */
do
{
/* Obtain a byte from the buffer. */
cChar = UARTCharGetNonBlocking(UART0_BASE);
//
// See if the backspace key was pressed.
//
if(cChar == ‘b’)
{
//
// If there are any characters already in the buffer, then delete
// the last.
//
if(ulCount)
{
//
// Rub out the previous character.
//
if (UART0IOStreamTask::verbose == 1) {
UARTCharPutNonBlocking(UART0_BASE, ‘b’);
UARTCharPutNonBlocking(UART0_BASE, ‘ ‘);
UARTCharPutNonBlocking(UART0_BASE, ‘b’);
}
//
// Decrement the number of characters in the buffer.
//
ulCount–;
}
//
// Skip ahead to read the next character.
//
continue;
}
//
// If this character is LF and last was CR, then just gobble up the
// character because the EOL processing was taken care of with the CR.
//
if((cChar == ‘n’) && bLastWasCR)
{
bLastWasCR = 0;
continue;
}
//
// See if a newline or escape character was received.
//
if((cChar == ‘r’) || (cChar == ‘n’) || (cChar == 0x1b))
{
//
// If the character is a CR, then it may be followed by a LF which
// should be paired with the CR. So remember that a CR was
// received.
//
if(cChar == ‘r’)
{
bLastWasCR = 1;
if (UART0IOStreamTask::verbose == 1) {
UARTCharPutNonBlocking(UART0_BASE, ‘n’);
UARTCharPutNonBlocking(UART0_BASE, ‘r’);
}
}
//
// Stop processing the input and end the line.
//
break;
}
//
// Process the received character as long as we are not at the end of
// the buffer. If the end of the buffer has been reached then all
// addiT0IOnal characters are ignored until a newline is received.
//
if(ulCount < ulLen)
{
//
// Store the character in the caller supplied buffer.
//
UART0IOStreamTask::uart0RXBuffer[ulCount] = cChar;
//
// Increment the count of characters received.
//
ulCount++;
//
// Reflect the character back to the user.
//
if (UART0IOStreamTask::verbose == 1)
UARTCharPutNonBlocking(UART0_BASE, cChar);
}
} while(UARTCharsAvail(UART0_BASE));
//
// Add a null terminaT0IOn to the string.
//
UART0IOStreamTask::uart0RXBuffer[ulCount] = ‘