Switching context optimization

asv60 wrote on Friday, November 16, 2018:

I use a simple RTOS of my own design in my project.
Now I want to switch to FreeRtos.
The peculiarity of my project is that in order to optimize
I, when interrupting the timer, save at first a small amount registers.
I increment the counter. Then I check if the time of activation of the nearest
task has expired. If not, I restore registers and return from interrupt.
If yes, I save the remaining registers and transfer control to the scheduler.
Timer interrupts occur at a frequency of 1 kHz. The maximum frequency of activation tasks is 50 Hz.
Thus, I get significant savings on switching context.
Is this interrupt handling mode possible on FreeRtos and, if so,
how best to do it?

Below for clarity, a pseudocode algorithm is given:
-------- Portable layer (assembler) ------------------
timer interrupt:
saveRegistersLite(4 registers);
timerCount++;
if(timerCount < ticksBeforeActivate){
restoreRegistersLite(4 registers);
returnFromInterrupt();
}else{
saveRegistersFull(26 registers);
callScheduler();
}

Best regards

rtel wrote on Friday, November 16, 2018:

Which architecture are you using?

richarddamon wrote on Friday, November 16, 2018:

You don’t say what processor/complier you are using so how easy that would be to do is hard to say.

First, FreeRTOS is written mostly in C, with possibly just a bit of assembly code in the thin porting layer. At first glance, I would say that you likely wrote your timer interrupt in assembly so you could make that first quick check with mininal register saving. Using assembly you can do some tricks that are just not possible in portable C code. The FreeRTOS tick increment function is slightly more complicated than your example, but not horibally more.

One big point that I will make is that it seems unneccessary in general to have a 1 ms tick period when your periodic periods are much longer (20 ms minimum), unless you actually need 1 ms resoultion for your timings, which in my experiance is unusual. I typically run with a tick period more like 5-10 ms / tick which is normally more than enough for my heeds. Dropping the tick rate will save you enough CPU usage that doing the full save every tick is no more expensive than what you are currently doing.

asv60 wrote on Friday, November 16, 2018:

Many thanks for your replies.
I use architecture MIPS32, I thought it does not matter.
Thanks for advice on reducing the frequency of interruptions,
but unfortunately this cannot be done.
For now, I intend to implement something like this:
BaseType_t xTaskIncrementTick (BaseType_t ticksJump);

Is it realizable?

rtel wrote on Friday, November 16, 2018:

Our MIPS implementation uses a separate interrupt for context switching,
and that interrupt is only ever pended when it has already been
determined that a context switch is necessary. See vPortYieldISR here.

https://sourceforge.net/p/freertos/code/HEAD/tree/trunk/FreeRTOS/Source/portable/MPLAB/PIC32MZ/port_asm.S

Entry to the timer interrupt is therefore governed by the requirements
of the MIPS ABI with regards to which registers are caller saved and
which callee saved. If the timer interrupt pends a context switch then
the context switch interrupt executes in accordance with the configure
interrupt priorities.

ldb wrote on Saturday, November 17, 2018:

What you are doing isn’t unusual and if your interrupt vector isn’t ROM there is a much faster way of doing that which is to have a tick interrupt and a scheduler interrupt.

The tick interrupt just advances the tick if the next tick needs to go to the scheduler it rewrites the interrupt vector to it. The scheduler just sets the interrupt vector back to the tick version and then runs. You can actually allow the interrupts to immediately start counting ticks again even while the scheduler is running if you want really accurate quantums.

asv60 wrote on Saturday, November 17, 2018:

It seems to me that in general this is like what I am doing. Only the decision to call the scheduler is made one tick before.
But the main question for me is: which function should I call in the scheduler?

rtel wrote on Sunday, November 18, 2018:

I’m not sure I understand this question. You just need to add the files
that implement the scheduler to your project - you don’t need to call
anything yourself from the scheduler as it is written already.