Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

FreeRTOS hangs in vListInsert

Posted by szymansk on September 23, 2008
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.

pxList0x2000646c
uxNumberOfItems2
pxIndex0x20006474
xItemValue4294967295
pxNext0x200064f4
pxPrevious0x200064f4
pvOwner0x0000000a
pvContainer0x0000000a
xListEnd{...}

pxNewListItem0x200064f4
xItemValue6
pxNext0x200064f4
pxPrevious0x200064f4
pvOwner0x200064dc
pvContainer0x2000646c

pxIterator0x200064f4
xItemValue6
pxNext0x200064f4
pxPrevious0x200064f4
pvOwner0x200064dc
pvContainer0x2000646c

"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] = '\0';


/* Post the byte. */
if (bLastWasCR) {
bLastWasCR = 0;
UART0IOStreamTask::uart0RXBufferSize = ulCount;
ulCount = 0;
if (xQueueSendFromISR( UART0IOStreamTask::uart0Queue, pcBuf, &xHigherPriorityTaskWoken ) == pdTRUE)
ulMessageCounter++;
}
}

/* Now the buffer is empty we can switch context if necessary. */
if( xHigherPriorityTaskWoken )
{
/* Actual macro used here is port specific. */
taskYIELD();
}
}

C++ wrapper part:
portBASE_TYPE Task::taskCreate() {
TaskManager::instance()->addTask(this);
status = RUNNING;
return xTaskCreate( __thread_main_dispatcher, (SC) pcName, usStackDepth, this, uxPriority, &pvCreatedTask);
}

void __thread_main_dispatcher(void *threadobjptr) {
Task * thread = static_cast< Task * >(threadobjptr);
thread->task_is_running = true;
// call the thread's main() methode;
thread->task();
}

arm-none-eabi-g++
-DGCC_ARMCM3 -DPART_LM3S8962 -I"/home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/include" -I"/home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/src/Maze" -I"/home/szymansk/workspace/SymbricatorRTOS/StellarisDriverLib" -I"/home/szymansk/workspace/SymbricatorRTOS/LM3S8962 Project" -I"/home/szymansk/workspace/SymbricatorRTOS/FreeRTOS503/include" -I"/home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/include/core" -I"/home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/src/MDL2e" -O0 -g3 -pedantic -Wall -mthumb -mcpu=cortex-m3 -MD -c -fno-rtti -fno-exceptions -fcheck-new -fno-enforce-eh-specs -Wabi -Woverloaded-virtual -fomit-frame-pointer

arm-none-eabi-gcc
-DGCC_ARMCM3 -Dgcc -DPART_LM3S8962 -I"/home/szymansk/workspace/SymbricatorRTOS/FreeRTOS503" -I"/home/szymansk/workspace/SymbricatorRTOS/StellarisDriverLib" -I"/home/szymansk/workspace/SymbricatorRTOS/webserver/uip" -I"/home/szymansk/workspace/SymbricatorRTOS/webserver" -I"/home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/src/MDL2e" -I"/home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/include" -I"/home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/include/MDL2e" -I"/home/szymansk/workspace/SymbricatorRTOS/LM3S8962 Project" -I"/home/szymansk/workspace/SymbricatorRTOS/FreeRTOS503/include" -I"/home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/src/MDL2e/decoder" -I"/home/szymansk/workspace/SymbricatorRTOS/SymbricatorOS/src/MDL2e/core" -O0 -g3 -pedantic -Wall -mthumb -mcpu=cortex-m3 -MD -c -fno-exceptions -std=gnu99 -fomit-frame-pointer

Linker:
arm-none-eabi-g++
-L/home/apps/arm-codesourcery/arm-none-eabi/lib/thumb -L/home/apps/arm-codesourcery/arm-none-eabi/lib -T ../LM3S8962\ Project/standalone.ld -mthumb -mcpu=cortex-m3 -fno-rtti -fno-exceptions -fcheck-new

RE: FreeRTOS hangs in vListInsert

Posted by Dave on September 23, 2008
The stack overflow will only detect errors during the context switch. If you corrupt a list structure and hang because of the corruption then it is possible you never get to the next context switch (although the tick should till be running? critical section?).

Is you UART interrupt priority below configMAX_SYSCALL_INTERRUPT_PRIORITY? Remember on the Cotex that 255 is the LOWEST priority not the highest as is a common mistake.

RE: FreeRTOS hangs in vListInsert

Posted by szymansk on September 23, 2008
The configMAX_SYSCALL_INTERRUPT_PRIORITY was set to 191 = 0b10111111 which is equal to 5 as only the first three msb are valid for the priority. The priority of the UART interrupt was set to 0x60 = 01100000 which is 3. If I understood it right it seems to be correct. The priority of the task handling the message coming from the UART interrupt was 5 could this be a problem?

How can I figure out what happens with the list. And when should I use use the critical section stuff?



RE: FreeRTOS hangs in vListInsert

Posted by Dave on September 23, 2008
I think you have it the wrong way around.

As there are only three bits available think of it as 0 being the highest priority and 7 being the lowest priority. The UART interrupt priority must be equal to or lower than configMAX_SYSCALL_INTERRUPT_PRIORITY, so it must have an equal to or higher priority number assigned (higher numbers are lower priorities).

You have assigned configMAX_SYSCALL_INTERRUPT_PRIORITY a priority of 5, so interrupts that use system calls can be assigned priority values of 5, 6 or 7 only. Priortities 5, 6 and 7 are equal to or LOWER than the max syscall priority of 5.

RE: FreeRTOS hangs in vListInsert

Posted by szymansk on September 23, 2008
This is definitely true. Shame on me.

And it seems to work. I also found a typical copy and paste error in an other interrupt which was meant to set the priority of this interrupt but just set the priority of the problematic interrupt back... I'll make a long term test.

Thanks a lot!!!


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS