Faster context switching

nobody wrote on Tuesday, March 06, 2007:


I’m trying to implement faster context switching version of FreeRTOS using LPC2138 (ARM-architecture). So far, I modified such that the tick interrupt is generated as FIQ, and memory map the interrupt vector to RAM. However the ISR, vPreemptiveTick() is still running from ROM.

I could rewrite the whole ISR at FIQ address, but that’s not really neat.

Anyone knows how to write relocatable code with GCC or Keil?

Next, I understand that global variable ulCriticalNesting also needs to be saved along with task context when switching. This is extra load, I plan to remove it. I understand that the earlier version of FreeRTOS didnt have this ulCriticalNesting. What was the problem with that necessitated it?

Finally any advice how can I create the fastest context switching FreeRTOS? This is a study, I dont really care if application programmers will have tougher time due to lack of features.

Thank you.

Eddy Zawaki.

nobody wrote on Tuesday, March 06, 2007:

WRT ulCriticalNesting.

Each task has its own interrupt status as part of its context.  You therefore need to save the interrupt status when context switching.  This can be done easily by saving and then restoring the ulCriticalNesting variable. 

Older versions of the ARM port did not do this because the critical section implementation was different. 

To enter a critical section the old version would push the status register onto the stack then disable interrupts.
To exit a critical section the old version would simply pop the status registers from the stack.

This method takes care of nesting automatically using the stack and therefore does not need the ulCriticalNesting variable.  The problem was it only worked at certain optimization levels.  Low optimization you can modify the stack without upsetting access to stack variables, the same is not true at high optimization.

The AVR/GCC port still uses the old method because the compiler does not care for that processor.


jra01 wrote on Wednesday, March 07, 2007:

For Keil, if using Realview compiler, there is a check under linker: "Make RO sections position independent". Maybe that is what you are looking for.

I have run code copied to RAM (for program of internal flash), without checking this, but that maybe depends on what the code does?


nobody wrote on Friday, March 09, 2007:

You managed to create RealView port for FreeRTOS? I’ve been researching and trying for weeks without result.

Did you write a lot of codes in assembly?

rtel wrote on Friday, March 09, 2007:

Send me an email to r ++dot barry --at and I can send you Joakims port.


nobody wrote on Sunday, April 08, 2007:

I’ve looked at portISR.c for LPC2129 Keil ARM port and I dont understand one thing.

#define portNO_CRITICAL_NESTING        ( ( unsigned portLONG ) 0 )
volatile unsigned portLONG ulCriticalNesting = 9999UL;

Why is ulCriticalNesting initialised to 9999UL ? Why not 0 since I guess the RTOS starts with no entering critical section.

Please help. Anyway I am going to be around this forum a lot for awhile, please dont get bored of my silly questions. Many thanks.

Eddy Zawaki.

embeddedc wrote on Sunday, April 08, 2007:

Some API functions can be called before the scheduler is started.  These API functions may use critical nesting.  Initializing the critical nesting count to non zero ensure interrupts don’t mistakenly get enabled prior to the scheduler starting.

The critical nesting count is stored as part of the context of each task and therefore is automatically cleared to zero when the first task starts.

nobody wrote on Sunday, April 08, 2007:

"automatically cleared to zero … " ?
That means there is no explicit statement ulCriticalNesting = 0 ? No wonder I couldnt find it. How actually does this clearing happen?

Questions. Since inside critical section, there is no context switching why does ulCriticalNesting need to be saved as part of task context? Cant we just assume that it’s zero every time context switching happens?

I apologize for so many trivial questions.

Eddy Zawaki.

nobody wrote on Monday, April 09, 2007:

The nesting count is stored as part of the task context.  The initial context of the task has the count set to zero so when the context is restored zero is written into the nesting count.


adarkar9 wrote on Monday, April 09, 2007:

You might be laboring under the same false assumption that I made a while ago.  Just because you are in a “critical section” does not guarantee that a context switch won’t occur.  For more details, check out the thread “Yield in critical section?” in this forum (dated 2006-05).  In a nutshell, the kernel sometimes does yield from within “critical sections” and expects to continue execution with interrupts disabled.  Therefore you cannot assume that ulCriticalNesting is zero when a context switch occurs.