Basic performance of FreeRTOS on a PIC24

armag1234 wrote on Friday, August 20, 2010:

I was wondering if anybody has measured instruction cycle counts for basic operations in FreeRTOS for a PIC24F.  I would do this myself, but the demo application requires a development board that I don’t have at the moment, so it’s easier to ask.   I’m specifically looking for the typical cycles between the time one task calls the equilivant of the Win32 “SetEvent” and the other task wakes up and runs to the point that it leaves OS code and can do it’s own work.

I have one more question.  In my application I need to manage an RF module in an extrememly time dependent way so I think it needs to be interrupt driven with a priority higher then the FreeRTOS scheduler/dispatcher priority.   Is it possible for this interrupt based code to wakeup normal FreeRTOS tasks from time to time such as when data is available?   I think in Microsoft Windows OS driver programing, this is solved with DPCs which allows the interrupt routes to post a callback that gets run by the OS back at the scheduler IRQ level.  Does FreeRTOS have anything like this or possibly even a solution to this problem?

danlhenry wrote on Friday, August 20, 2010:

You don’t need a development board.  The instructions for that port include how to run using MPLAB’s MPSIM component.

richard_damon wrote on Friday, August 20, 2010:

I haven’t done a detail timing analysis like what you are asking, but as been said, that can be done with the simulator.

As to higher speed interrupts waking up tasks, yes that is very possible. What is normally done is the task wait on a semaphore take, and a high speed interrupt does a semaphore give, or if a little bit of data needs to be sent, use a queue, interrupt puts into the queue, task pops data out of the queue.

One thing to note, is that interrupt that interact with FreeRTOS can not nest, so if the RF module needs to signal a task with FreeRTOS operations, it will be disable during the tick interrupt.

armag1234 wrote on Friday, August 20, 2010:

Thanks, I found the instructions for the PIC24F port and I’m playing with the simulator now to see some of the timing info.

As for my second questions, this is what I understand of the FreeRTOS architure.

Interrupts <= Scheduler IRQ(including tasks) can call into the scheduler
Scheduler IRQ - This is the IRQ most of the FreeRTOS APIs run at( this includes IRQs running at the scheduler IRQ )
Interrupt > Scheduler IRQ can’t interact with FreeRTOS

I need my RF IRQs to run at a higher priority then the scheduler so that it can’t be interrupted( or disabled ) at all by FreeRTOS, yet be able to unblock FreeRTOS tasks when data is received.  As I understand it, this is not possible with FreeRTOS as it is implemented today because higher priority IRQ can not interact with FreeRTOS tasks or objects.  Correct?

armag1234 wrote on Friday, August 20, 2010:

BTW, like I said I think the way this is solved in the Microsoft Windows Driver programming model is that high priority routine queues a callback that runs after the interrupt finshing that runs at the scheduler IRQ.    This callback can then set the semaphore that you refer to. I’m not sure how Linux solves this problem.

The problem is that I don’t see a clean way to add this to the FreeRTOS programming model.  The best solution I can think of is to burn a microcontroller resource like a hardware timer set to a very small value that can be armed inside the high priority interrupt that runs at the scheduler priority.   This interrupt could call functions on the semaphore and then call yield.  No nesting would occure.

danlhenry wrote on Friday, August 20, 2010:

Isn’t that what is discussed in here in the “configKERNEL_INTERRUPT_PRIORITY” bullet item?

armag1234 wrote on Saturday, August 21, 2010:


“ISR’s running above the kernel priority are never masked out by the kernel itself, so their responsiveness is not effected by the kernel functionality. However, such ISR’s cannot use the API functions. The fast timer interrupt test within this demo demonstrates this configuration.”

This limitiation is too much for my application so I need to find a work around.  Either by changes in my application or changes to the FreeRTOS source code.   I want to be able trigger calls to API functions due to events that happen during the higher priority interrupts.

richard_damon wrote on Saturday, August 21, 2010:

The PIC processors tend to have a lot of interrupt vectors, and it is easy to “force” an interrupt (you just set the corresponding IF register). A good solution is to use one of the interrupt vectors for a peripheral you are not using, set its priority to configKERNEL_INTERRUPT_PRIORITY and have the high priority interrupt set the IF for that vector. This lower priority vector can then call the FromISR API.

danlhenry wrote on Saturday, August 21, 2010:

However, such ISR’s cannot use the API functions.

No, I’m referring to the the paragraph (a.) immediately above what you quoted, that describes an interrupt returning to a kernel priority level handler that it had just awakened.

richard_damon wrote on Saturday, August 21, 2010:

I think you are misunderstanding what the topic is describing. The Interrupt handling ‘tasks’ that is described is a normal task, that is assigned a very high FreeRTOS priority, so that when the interrupt wakes it up, it will execute immediately upon return from the ISR (after the context switch that happens at the end of that ISR).

It is NOT returning to a ‘kernel priority level handler’, but to a (non-interrupt level) handler task to continue to process the effects of the interrupt. The idea is to have a very small ISR, that does the minimal work required, as fast as possible, to service the interrupt, and that then passes control (via a synchronizing primitive) to a handler TASK to complete the longer parts of the servicing.

The PIC24 currently (as far as I know) does not implement the configMAX_SYSCALL_INTERRUPT_PRIORITY option yet, so all interrupt that use the FromISR API are at configKERNEL_INTERRUPT_PRIORITY, so do not have nesting.

danlhenry wrote on Saturday, August 21, 2010:

I think you are misunderstanding what the topic is describing.

Very well then.  Please forgive the interruptions.

armag1234 wrote on Saturday, August 21, 2010:

I’ve tested the idea of the “forced” KERNEL_INTERRUPT_PRIORITY interrupt from a higher priority interrupt(>KERNEL_INTERRUPT_PRIORITY) and it appears to work, at least in the simulator.  So I will probably use this for my application.

It would be nice though if some portable mechanism were available for doing this.     Ive been trying to think of ASM code that could wrap the (>KERNEL_INTERRUPT_PRIORITY) interrupt to do this without resorting to undocumented tricks and I can’t quite see how to do it.

Is this a common mechanism on other CPU archetectures to be able to manually set an interrupt flag to force an interrupt?

richard_damon wrote on Sunday, August 22, 2010:

Forcing interrupts like this is hardly “undocumented”, the Microchip manuals clearly talk about this as an valid operation. I would also say that it is fairly common on this scale of processors to have some way to “simulate” an interrupt of some sort (the mechanism may vary though). Somehow “portable” and dealing this close to the hardware doesn’t really happen.  The whole structure is ISR’s is fairly loaded with device dependencies (there are a number of common aspects, but there is always a core of device dependencies around).

For the PIC24, you don’t need to “wrap” anything. The high level interrupt is written just like any normal interrupt routine. If you want to trigger the configKERNEL_INTERRUPT_PRIORITY isr, you just use a line like _xxIF = 1; to request the interrupt (xx being the device you are using to for this), so you actually don’t need to drop into ANY asm code.

armag1234 wrote on Sunday, August 22, 2010:

Thanks for the info.  Like I said, I’ve confirmed on both the simulator and a real PIC that the _xxIF = 1 works.  It’s too bad Microchip didn’t dedicate a few of those 100 some interrupt sources specifically for this.  It’s appears the _xxIF needs to be for a real peripheral that isn’t used by the firmware.

I also realized I don’t need any ASM for the _xxIF =1 solution.   I was simply trying to think of an alternative through ASM that would give the same result by pushing and poping items from the stack without using the _xxIF = 1 trick.

Anyway, thanks for everyone’s help.

richard_damon wrote on Sunday, August 22, 2010:

The problem with trying to “fake” the interrupt with asm code, would be that if you are in a critical section or a configKERNEL_INTERRUPT_PRIORITY interrupt, you don’t want to actually go straight to your low level isr, but need to hold off until that critical section or interrupt is over.

I suppose one option would be to put a test at the end of the critical section and interrupt, to see if you should do something and go to it. This of course has a cost of doing this test all the time, and needing to special code for your case (or building some framework to handle a general case here).