Quality RTOS & Embedded Software

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




Loading

Idle task stack overflow

Posted by ARMinator on December 31, 2010
Hi,

I'm running the latest version of freeRTOS on an LPC2000 and I am getting a stack overflow error with the idle task.

This only occurs after I enable the processing of interrupts for UART0 (RX data available and receive data timeout interrupts enabled only), and after about half a dozen interrupts are serviced.
What is most likely to generate a stack overflow on the idle task? Is this a general corruption of memory, which is reported as a stack overflow for the idle task?

This is how the UART0 isr is implemented (C wrapper for C++ UART driver). No call to the freeRTOS API is made in the m_Uart0.Isr() method.

void Uart0Isr( void ) __attribute__((naked));
void Uart0Isr( void )
{
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();

m_Uart0.Isr();

/* Restore the context of the new task. */
portRESTORE_CONTEXT();
}

Happy New Year,
JS

RE: Idle task stack overflow

Posted by ARMinator on December 31, 2010
Oups, looks like this has already been handled here:

https://sourceforge.net/projects/freertos/forums/forum/382005/topic/3301950

Sorry for the double post...

RE: Idle task stack overflow

Posted by ARMinator on January 4, 2011
Hi,

I am still getting this error and it seems this happens exclusively when both the tick interrupts and the UART interrupts are enabled and serviced. I use a tick hook.

I do not get this error when the tick interrupts are enabled and my tick hook is called. I do not get this error when the tick hook is not called and UART ISRs are serviced. Somehow it looks like the tick hook and the UART ISR are not compatible...
I have increased the size of the interrupt stack in the linker script but I still get this error.

Here is the code I use in the tick hook:

void CScheduler::Scheduler(
const uint32_t tick // in
)
{
CScheduler::sEntry_t * p_Entry = mp_EntryList;
signed portBASE_TYPE xHigherPriorityTaskWoken;
static CSubsystem::sActivation_t activationPacket;

m_Tick = tick;

while(0 != p_Entry)
{
if( 0 != p_Entry->clkDivider &&
0 == (m_Tick % p_Entry->clkDivider)
)
{
activationPacket.type = CSubsystem::ACTIVATION_TYPE_SCHEDULER;
activationPacket.p_Cmd = CSubsystem::CommandGet();
if(0 != activationPacket.p_Cmd)
{
activationPacket.p_Cmd->id = 0;
activationPacket.p_Cmd->dataLen = 0;
// Activating
xQueueSendFromISR(*(p_Entry->p_ActivationQueue), &activationPacket, &xHigherPriorityTaskWoken);
}
else
{}
}
else
{
// Skipping
}

p_Entry = p_Entry->p_Next;
} // while
} // CScheduler::Scheduler

Here is the UART ISR:


void Uart1ISR( void ) __attribute__((naked));
void Uart1ISR( void )
{
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();
lpc21xxUart1.Isr();
VICVectAddr = 0;
/* Restore the context of the new task. */
portRESTORE_CONTEXT();
}

And the actual method

void CLpc21xxUartDev::Isr(void)
{
uint32_t intStatus = LPC214x_REG_READ_8(UxIIR);
uint8_tdata= 0;
portBASE_TYPE higherPriorityTaskWoken = pdFALSE;

intStatus = (intStatus >> 1) & 0x07;

if(0x03 == (intStatus & 0x03))
{
// receive line status
LPC214x_REG_READ_8(UxLSR);
}
else
{}

if((0x02 == (intStatus & 0x02)) ||
(0x06 == (intStatus & 0x06))
)
{
// data received or cti
// cleared by reading all the data
while(LPC214x_REG_READ_8(UxLSR) & 0x01)
{
data = LPC214x_REG_READ_8(UxRBR);
xQueueSendFromISR(m_RxQueue, &data, &higherPriorityTaskWoken);
}
}
else
{}

if(0x01 == (intStatus & 0x01))
{
uint32_t cnt = 0;
while(cnt < LPC214x_HW_FIFO_SIZE)
{
if(pdTRUE == xQueueReceiveFromISR (m_TxQueue, &data, &higherPriorityTaskWoken))
{
LPC214x_REG_WRITE_8(UxTHR, data);
cnt++;
}
else
{
m_TxEmpty = true;
break;
}
} // while
}
else
{}

if(higherPriorityTaskWoken)
portYIELD_FROM_ISR ();
}

Does anybody see something obvious that would generate this error?

As a side note, could somebody clarify when portYIELD_FROM_ISR () should be called?
I realize the 2 pieces of code I provide here are not consistent: the tick hook never bothers to call the method even if a higher level task is woken up.
In the UART ISR, I only call it at the end of the ISR, while it's possible that xQueueReceiveFromISR could be called many times. In that case I also overwrite the value of higherPriorityTaskWoken...

RE: Idle task stack overflow

Posted by ARMinator on January 5, 2011
I fixed this by removing a call to xTaskGetTickCount() from the tick hook. Doesn't seem to bother anything if only the tick interrupt is enabled. But generates task overflows when other interrupts are serviced.

RE: Idle task stack overflow

Posted by Richard Damon on January 5, 2011
getTickHook is called from within an ISR (the timer interrupt), so it can only call FreeRTOS functions with FromISR in their name. xTaskGetTickCount uses an ISR to access the count, and those don't work inside of ISR routines, it can allow improper interrupt nesting.

RE: Idle task stack overflow

Posted by Richard on January 5, 2011
ISRs must not call any FreeRTOS API functions that do not end in "FromISR". Latest versions of FreeRTOS include an xTaskGetTickCountFromISR() function (although this is mentioned in the change history, it has not made it into the documentation yet).

Regards.


[ 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