Quality RTOS & Embedded Software

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


tick ISR curiosity

Posted by *anonymous on January 11, 2007

FreeRTOS 4.1.1, GCC, LPC2...

In an attempt to eliminate round-robin scheduling of tasks of equal priority, I wrote my own tick ISR. It calls vTaskIncrementTick(), but then it calls vTaskSwitchContext() only if a task of higher priority gets scheduled. To do this, it exits the ISR with


where NeedTickSwitch() answers the question regarding relative priorities (I put it in tasks.c so it can compare uxTopReadyPriority to pxCurrentTCB->uxPriority).

This trick didn't work. But I can't quite get a handle on what is going wrong. My testing seems to imply vTaskSwitchContext() must always be called after vTaskIncrementTick(). I don't see why, but is this true?

tick ISR curiosity

Posted by embeddedc on January 12, 2007

How about this, leave all other stuff unmodified and just change vTaskSwitchContext() as follows:

void vTaskSwitchContext( void ) { static unsigned portBASE_TYPE uxLastTopReadyPriority = 0;

____if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) ____{ ________xMissedYield = pdTRUE; ________return; ____}

____while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) ____{ ________--uxTopReadyPriority; ____}

____if( uxTopReadyPriority > uxLastTopReadyPriority ) ____{ ________listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); ________uxLastTopReadyPriority = uxTopReadyPriority; ____} }

Would that do what you want?  I have not actually tried it, but the idea is to only select a new task to run if the top priority ready task is higher than the last time the selection function was called.

tick ISR curiosity

Posted by *anonymous on January 12, 2007

I think that would mean taskYIELD() would not perform as expected. I don't know what other ill effects it might have. In fact, it was this explicit control between tasks of equal priority that I was looking for.

My understanding is that ISRs are supposed to have the capability to determine whether or not they trigger a context switch using portEXIT_SWITCHING_ISR(). I would rather use a prescibed mechanism than change the kernel. But portEXIT_SWITCHING_ISR() doesn't seem to work with the tick ISR.

Richard, can you shed any light?

tick ISR curiosity

Posted by richardbarry on January 12, 2007

I think you are right about the not yielding with the suggested code.

I could not think of a reason why vTaskSwitchContext() would have to be called after incrementing the tick, in fact when running with configUSE_PREEMPTION set to 0 it is not.  So your results are suprising.

+ What do you find happens?  The system crashes or just still round robins when you don't want it to? + What are you calling when you enter the tick ISR?  portSAVE_CONTEXT() of portENTER_SWITCHING_ISR()?

Some of the other ARM7 ports have a different IRQ handling mechanism where the context is saved automatically prior to vectoring to the handler.  This prevents you having to use the ENTER/EXIT_SWITCHING_ISR() macros.


tick ISR curiosity

Posted by *anonymous on January 12, 2007


I have a common ISR that handles all (VIC default vector) IRQs, including the tick interrrupt.

extern void  __attribute__ ((naked)) PortIRQDispatch(void);

void PortIRQDispatch(void) { __portENTER_SWITCHING_ISR();


__portEXIT_SWITCHING_ISR(NeedTaskSwitch()); }

ISRDispatch() does a table lookup to properly dispatch to the correct ISR. NeedTaskSwitch() is implemented in tasks.c as:

short    NeedTaskSwitch(void) { __static portTickType lastCount; __short               didTick = lastCount!=xTickCount;

__lastCount = xTickCount;

__return didTick || uxTopReadyPriority>pxCurrentTCB->uxPriority; }

The above version works as I had hoped. The 'didTick' trick ensures that true is returned whenever vTaskIncrementTick() is called in the ISR. The following version does not work as expected.

short    NeedTaskSwitch(void) { __return uxTopReadyPriority>pxCurrentTCB->uxPriority; }

The test has a lower priority task in an infinite loop. A higher priority task delays for a certain period. It never appears to run after the delay period. But then I have some difficulty with debugging. I see NeedTaskSwitch() return true at the appropriate time, but I can't seem to properly step out of the restoring of the context to see what is happening. I don't know if the stepping out issue is an artifact of the actual problem, or if it is just an artifact of my debugging tools. Visually, during the final __SUBS    PC, LR, #4 the LR has the same value as the PC, so it just steps back 1 instruction and appears to be looping infinitely. But this is inconsistent with the free-running behaviour so I tend to suspect the debug tools rather than think this is the actual problem. Free-running, a breakpoint after the delay in the higher priority task never triggers, and the lower priority task continues looping.

The truth be told, I never examined the registers of the restored context to try to figure out which of the 2 tasks was being restored. I may take some time to do this some time in the future. Or, if you are willing to look at it...


tick ISR curiosity

Posted by richardbarry on January 14, 2007

Not 100% sure about this but I think it might be to do with a mismatch between the IRQ and SWI stack frames.

Could you give this a go.

void __attribute__ ((naked)) PortIRQDispatch(void);

void PortIRQDispatch(void) { __portSAVE_CONTEXT(); __{


____if( NeedTaskSwitch()) ____{ ________vTaskSwitchContext(); ____} __} __portRESTORE_CONTEXT(); }

Keep the brackets between the SAVE/RESTORE to start with, I don't think they are needed unless you declare a stack variable in the function, but they won't do any harm.



tick ISR curiosity

Posted by *anonymous on January 14, 2007


I have absolutely no idea why this has solved the problem nor how what you have suggested differs in any significant way from the original, but it does seem to have solved the problem. And no, the extra brackets are not required.

Does this mean that there is something not quite right about the ARM port that we should be aware of?

Thanks, Richard. I'll maybe look it more closely tomorrow.

tick ISR curiosity

Posted by richardbarry on January 15, 2007

The portENTER_SWITCHING_ISR() macro contains one extra line (to change the stack frame) when compared to the portSAVE_CONTEXT() macro as they are intended for use in slightly different situations.  The code I suggested matched the way the original tick ISR was written.


tick ISR curiosity

Posted by *anonymous on January 15, 2007

Sorry about continuing to beat this dead horse, but I would like to understand the implications of this for my future use of FreeRTOS.

1. Is the only downside of using the portSAVE_CONTEXT()/portRESTORE_CONTEXT() version the fact that the main ISR function can't have local variables?

2. Does the fact that the tick ISR had a problem with the portENTER_SWITCHING_ISR()/portEXIT_SWITCHING_ISR() version mean that other ISRs could also have problems with these macros, or is this problem specifically related to the use of vTaskIncrementTick() in the ISR?


tick ISR curiosity

Posted by richardbarry on January 16, 2007

Not sure - I need to look into this in more detail.

I recently updated the demo makefiles in the download to include the -fomit-fame-pointer options.  Are you using this?  I am wondering if it has caused a problem.


tick ISR curiosity

Posted by *anonymous on January 16, 2007

Oh... no, I found the -fomit-fame-pointer interfered too much much with debugging, so I 'fixed' the GCC problem within FreeRTOS. Could that be the problem? Have you actually reproduced the my ISR problem, or have you just been relying on my description?

Here is what I did for the problem of GCC emitting ARM/Thumb code incompatible with context switching:


____"SUB    SP, SP, #4                            ____"LDMIA  SP!,{R0}                                                                    /*gb - step over possible GCC stacked items (GCC bug)*/ ____"SUB    R0, R0, #8           

        /* Push the return address onto the stack. */ ____"STMDB  R0!, {LR}

tick ISR curiosity

Posted by richardbarry on January 16, 2007

Glen - would it be possible for you to send me a zip file containing a mini project that exhibits the behaviour?  It does not really have to do anything.  I will then merge your FreeRTOS specific files into an LPC2000 demo project and run it in CrossWorks so I can step through the code to see exactly what is what.  You can send the file to the email address on the WEB site rather than SourceForge as the latter strips off binary attachments (r +++dot+++ barry !!!at!!! freertos.org).


tick ISR curiosity

Posted by *anonymous on January 17, 2007

Sorry, I won't be able put together a mini app for some time. I'll get back to you. Thanks for the time you have put on it so far.


tick ISR curiosity

Posted by *anonymous on January 17, 2007

Oh, oh. I have discovered the problem was mine. The actual strategy I was using is fine. My blunder was misinterpreting what I was seeing.

My deepest apologies , Richard. As I trimmed things down I discovered my blunder. (Good strategy on your part!) I even got it wrong when I said that the change you suggested fixed the problem. Well, in fact there was no problem.

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

Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.

Free TCP/IP and file system demos for the RTOS

Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑

FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

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

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

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

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists