Preemption in FreeRTOS - c

I am starting to use FreeRTOS and I would like a interrupt to preempt whatever task was about to run and run the task I need to run critically.
Is there a way to do this in FreeRTOS? (Is this achieved through task priority?)

NO! Both the above answers are DANGEROUS.
Do NOT use taskENTER_CRITICAL() or taskEXIT_CRITICAL() inside an ISR - it is unusual to need a critical section in an ISR but if you do then use taskENTER_CRITICAL_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR(). (possible the AVR32 port is an exception to that rule?)
Do NOT use xTaskResumeFromISR() to synchronise a task with an interrupt. The link already posted to the documentation for that function even says this.
If my understanding of your question is correct you want the ability to have an interrupt unblock a task, and then if that task is the highest priority task in that is able to run, have the interrupt return directly to the unblocked task. If my understanding is right then there is an example of how to do that in an efficient way on the following page: http://www.freertos.org/RTOS_Task_Notification_As_Counting_Semaphore.html

The short answer would be: Yes, this is achieved through task priority.
The FreeRTOS kernel will consider swapping in any task in ready-state after an ISR has completed so it would preempt the current running task if a higher priority task is now ready.
It should be mentioned that this is really only true if the handler is called through FreeRTOS. On a Cortex-A processor there is a common IRQ entry-point in the IRQ or FIQ exception handler which is most likely handled by FreeRTOS or otherwise by an IRQ dispatcher which is easily wrapped by FreeRTOS, usually by a function in the port-layer called vApplicationIRQHandler().
On a Cortex-M this is not necessarily the case as the vector is usually manipulated by the vendor's MCU API. On a Cortex-M I'd safe-guard against this using portYIELD_FROM_ISR() in the ISR which should be implemented to provide the kernel with an opportunity to perform a context switch.

You can use xTaskResumeFromISR to do this.
There is a number of conditions to be met for the yielded task not to be interrupted by other tasks (like it's priority must be high enough) and a number of other conditions to be met to ensure that no interrupt can go un-serviced (like the yielded task must guarantee to be done before the next interrupt)

1. enable preemption:
This is very simple to do.
All the configuration options of FreeRTOS are under "FreeRTOSConfig.h"
#define configUSE_PREEMPTION 1
You can set this to 1 to use the preemptive RTOS scheduler, or 0 to use the cooperative RTOS scheduler.
Check this link for more info
2. Use critical section inside ISR
void taskENTER_CRITICAL( void );
//action
void taskEXIT_CRITICAL( void );
RTOS wont do anythis extra inside this critical part
ref: here

Related

How can I determin if execution takes place in thread mode or if an exception is active? (ARMv7-A architecture)

I am using FreeRTOS on an ARM Cortex A9 CPU und I'm desperately trying to find out if it is possible to determin if the processor is executing a normal thread or an interrupt service routine. It is implemented in V7-a architecture.
I found some promising reference hinting the ICSR register (-> VECTACTIVE bits), but this only exist in the cortex M family. Is there a comparable register in the A family as well? I tried to read out the processor modes in the current processor status register (CPSR), but when read during an ISR I saw that the mode bits indicate supervisor mode rather than IRQ or FIQ mode.
Looks a lot like there is no way to determine in which state the processor is, but I wanted to ask anyway, maybe I missed something...
The processor has a pl390 General Interrupt Controller. Maybe it is possible to determine the if an interrupt has been triggered by reading some of it's registers?
If anybody can give me a clue I would be very greatfull!
Edit1:
The IRQ Handler of FreeRTOS switches the processor to Superviser mode:
And subsequently switches back to system mode:
Can I just check if the processor is in supervisor mode and assume that this means that the execution takes place in an ISR, or are there other situations where the kernel may switches to supervisor mode, without being in an ISR?
Edit2:
On request I'll add an overal background description of the solution that I want to achieve in the first place, by solving the problem of knowing the current execution context.
I'm writing a set of libraries for the CortexA9 and FreeRTOS that will access periphery. Amongst others I want to implement a library for the available HW timer from the processor's periphery.
In order to secure the access to the HW and to avoid multiple tasks trying to access the HW resource simultaneously I added Mutex Semaphores to the timer library implementation. The first thing the lib function does on call is to try to gain the Mutex. If it fails the function returns an error, otherwise it continouses its execution.
Lets focus on the function that starts the timer:
static ret_val_e TmrStart(tmr_ctrl_t * pCtrl)
{
ret_val_e retVal = RET_ERR_DEF;
BaseType_t retVal_os = pdFAIL;
XTtcPs * pHwTmrInstance = (XTtcPs *) pCtrl->pHwTmrInstance;
//Check status of driver
if(pCtrl == NULL)
{
return RET_ERR_TMR_CTRL_REF;
}else if(!pCtrl->bInitialized )
{
return RET_ERR_TMR_UNINITIALIZED;
}else
{
retVal_os = xSemaphoreTake(pCtrl->osSemMux_Tmr, INSTANCE_BUSY_ACCESS_DELAY_TICKS);
if(retVal_os != pdPASS)
{
return RET_ERR_OS_SEM_MUX;
}
}
//This function starts the timer
XTtcPs_Start(pHwTmrInstance);
(...)
Sometimes it can be helpful to start the timer directly inside an ISR. The problem that appears is that while the rest of function would support it, the SemaphoreTake() call MUST be changed to SemaphoreTakeFromISR() - moreover no wait ticks are supported when called from ISR in order to avoid a blocking ISR.
In order to achieve code that is suitable for both execution modes (thread mode and IRQ mode) we would need to change the function to first check the execution state and based on that invokes either SemaphoreTake() or SemaphoreTakeFromISR() before proceeding to access the HW.
That's the context of my question. As mentioned in the comments I do not want to implement this by adding a parameter that must be supplied by the user on every call which tells the function if it's been called from a thread or an ISR, as I want to keep the API as slim as possible.
I could take FreeRTOS approch and implement a copy of the TmrStart() function with the name TmrStartFromISR() which contains the the ISR specific calls to FreeRTOS's system resources. But I rather avoid that either as duplicating all my functions makes the code overall harder to maintain.
So determining the execution state by reading out some processor registers would be the only way that I can think of. But apparently the A9 does not supply this information easily unfortunately, unlike the M3 for example.
Another approch that just came to my mind could be to set a global variable in the assembler code of FreeRTOS that handles exeptions. In the portSAVE_CONTEXT it could be set and in the portRESTORE_CONTEXT it could be reset.
The downside of this solution is that the library then would not work with the official A9 port of FreeRTOS which does not sound good either. Moreover you could get problems with race conditions if the variable is changed right after it has been checked by the lib function, but I guess this would also be a problem when reading the state from a processor registers directly... Probably one would need to enclose this check in a critical section that prevents interrupts for a short period of time.
If somebody sees some other solutions that I did not think of please do not hesitate to bring them up.
Also please feel free to discuss the solutions I brought up so far.
I'd just like to find the best way to do it.
Thanks!
On a Cortex-A processor, when an interrupt handler is triggered, the processor enters IRQ mode, with interrupts disabled. This is reflected in the state field of CPSR. IRQ mode is not suitable to receive nested interrupts, because if a second interrupt happened, the return address for the first interrupt would be overwritten. So, if an interrupt handler ever needs to re-enable interrupts, it must switch to supervisor mode first.
Generally, one of the first thing that an operating system's interrupt handler does is to switch to supervisor mode. By the time the code reaches a particular driver, the processor is in supervisor mode. So the behavior you're observing is perfectly normal.
A FreeRTOS interrupt handler is a C function. It runs with interrupts enabled, in supervisor mode. If you want to know whether your code is running in the context of an interrupt handler, never call the interrupt handler function directly, and when it calls auxiliary functions that care, pass a variable that indicates who the caller is.
void code_that_wants_to_know_who_called_it(int context) {
if (context != 0)
// called from an interrupt handler
else
// called from outside an interrupt handler
}
void my_handler1(void) {
code_that_wants_to_know_who_called_it(1);
}
void my_handler2(void) {
code_that_wants_to_know_who_called_it(1);
}
int main(void) {
Install_Interrupt(EVENT1, my_handler1);
Install_Interrupt(EVENT2, my_handler1);
code_that_wants_to_know_who_called_it(0);
}

STM32 RTOS timer interrupt and threads

I am working on a project where I need to execute 2 pieces of code off TIM interrupts. One of them has a slightly higher priority than the other, and both will be running on 2 different timers (of course not at the same time interval). Due to both timers being proportional to another (one is 1KHz, one is 8Khz) both will trigger at the same time.
Since I am already using the RTOS middle-ware for another purposes (threads of a much lower priority than these too), I was thinking of creating one thread of each these routines.
However, looking at how cubeMX is generating code, I am even wondering if this is possible.
I can start/stop these timers from any thread, but there is only one HAL_TIM_PeriodElapsedCallback which you usually fill with if statements like so:
if (htim->Instance == TIM2)
Am I correct to assume, regardless of which thread the timers are started from, the TIM callback will always occur "outside" of the RTOS environment?
if so, what would be a better strategy to achieve something close to what I need?
Cheers
Interrupts will triger. But remember:
Its priority (not the RTOS priority as they are unrelated) must be lower the SVC interrupt if you want to use any ...fromISR RTOS functions
They will not happen at the same time (as you have only one core)
I am working on a project where I need to execute 2 pieces of code off
TIM interrupts. One of them has a slightly higher priority than the
other, and both will be running on 2 different timers...
What exactly do you mean by "one of them has a [..] higher priority" - the HW timer events will occur just when the timer underflows occur. I think you mean, the handler code servicing the timeout events.
... (of course not at the same time interval). Due to both timers being proportional to another (one is 1KHz, one is 8Khz) both will trigger at the same time.
In embedded realtime programming, you should never build on the assumption that IRQ events are not occurring at the same time: Your ISR handlers may be suppressed at the moment when a trigger event occurs. This way, even if two concurrent events trigger closely after each other, it may look for your software code as if they had triggered at the same time. The solution is what your question points at: Context priorities (of tasks (= "threads") and ISRs (= "Interrupt handlers")) let you avoid the question which event came earlier and control which event to treat first.
Since I am already using the RTOS middle-ware for another purposes (threads of a much lower priority than these too), I was thinking of creating one thread of each these routines.
You are free to deploy code to an RTOS task or to an ISR, but keep in mind that any ISR will have a higher priority than any task. Your TIM event will trigger an ISR (= interrupt context), but you can (and often should) use the ISR to send a notification (or event, or semaphore, or queue message) to a task in order to have the main part of the timer event processed at the lower priority of a task.
However, looking at how cubeMX is generating code, I am even wondering if this is possible.
CubeMX is not limiting you to use or not use tasks. The question is rather how far CubeMX will generate the code you need, and how much you have to add manually. Please note that you don't have to use the CubeMX feature to generate tasks through its configuration, but this can be done by your own C code, too.
I can start/stop these timers from any thread, but there is only one HAL_TIM_PeriodElapsedCallback which you usually fill with if statements like so:
if (htim->Instance == TIM2)
Am I correct to assume, regardless of which thread the timers are started from, the TIM callback will always occur "outside" of the RTOS environment?
Yes, you are. The question who started the timer is not relevant to the context type/selection triggered by the timer. In any case, the TIM will trigger its ISR (at the interrupt priority configured for that interrupt).
If you use the CubeHAL library, it will implement the root of that ISR, check which of the TIMs related to that ISR have elapsed, and invoke the code you printed. Here, you can insert your user code to the different TIM instances (like TIM2 in your case).
if so, what would be a better strategy to achieve something close to what I need?
Re-check your favourite textbook on RTOS and microcontrollers. Any SO answer cannot include all the theory to solve the problem properly.
Decide whether there will be any more urgent reaction on your system than treating the timeout events. If no, you may implement the timeout reaction in the ISR handler. If yes (or in cases of doubt), implement the ISR with a task notification that goes to a task where you do what the timeout event requires. This may be the task from where you started the timer, or another one.

What happens when a interrupt occurs in RTOS while currently in any task or another ISR?

I have read this question, It is not a valid answer when one interrupt is executing it will not disable all the other interrupts always. It is based on the interrupt type (in some case we need to do manually in our program).
My Question is what happens when a interrupt occurs while executing a
interrupt ??? If Low priority interrupt is executing then High
priority interrupt occurs the what will happen ?
It depends on the system. If the microcontroller/interrupt controller supports nested interrupts and the application enables that feature then a higher priority interrupt will interrupt a lower priority interrupt. In this case the lower priority interrupt will resume when the higher priority interrupt is complete. But if the system does not support nested interrupts then the subsequent interrupt request will pend and be serviced when the active interrupt service routine is complete.
It is too broad for SO, I think and it is arch based.
I try to give you a brief overview, expecting some DV on it. ;)
Mainly, if the arch allow nested interrupts, the interrupt with lower priority is interrupted while executing to jump to the ISR of high level interrupt.
But you can have NMI (Non Maskable Interrupt) that have priority on all other interrupts and cannot be disable.
Usually (all I think) archs have also a global interrupt enable flag, so it must be enabled to allow other interrupts to be served. Also means that an ISR, when is executing, can disable other interrupts during its job.
You can think, for example, on an RTOS implementation: the scheduler can be easily developed using a Timer within its interrupt. This interrupt must have the lower priority and mustn't stops other interrupts (usually): this grant that interrupts are served a soon as possible not considering context switch of RTOS scheduler.
The question was
What happens when a interrupt occurs in RTOS while currently in any task or another ISR?
I have written two commercial RTOS's and there is no answer that satisfies all of the criteria. However, I CAN answer as broadly as the question:
Depending on what is allowed, it will act as a normal interrupt. The problem with this question is that "what happens" is a little broad - some RTOS's do work behind the scenes with interrupts. So, the problem is that the question is not specific enough.
"What happens" in regards to a task is that NOTHING happens in regards to a task. An interrupt is an interrupt and what the relation to a task is depends on the programming. Since I don't read minds, again, the question is not specific enough.
The BEST answer is 42 (HHGTTG)
There is no one answer, sometimes nothing happens the lower prio interrupt continues to completion, sometimes the higher one interrupts the lower. It depends first on the chip/system design, second it depends on the individual programmers across the board RTOS and application folks.
Or another way to say it is, what happens is what those individuals desired to happen in their design and implementation.

'Usage fault exception' in ARM Cortex M

I attended a lecture on FreeRtos and Cortex M where the instructor advised that if ISR safe version of API is not used from ISR it can lead to Usage fault exception in Cortex M processors.This would happen because this can involve going from interrupt context(interrupt handler) to task context(thread handler)
My question is why this task switch would be considered illegal and what would be the repercussions of such a switch?
On a Cortex-M (some of) the current context will be stored on stack in use before the interrupt (on interrupt entry), so if you were in a task and it was interrupted some of the current context would be stored on the task stack (via the PSP). The interrupt itself always runs on the MSP. If the interrupt does not return to the task which it interrupted then the interrupted task will have a messed up stack (as it restores the stored context on exit) as well as trying to restore an incorrect context for the task which was switched to.
On a context switch(which happens in an interrupt) again some of the context is automatically stored on the task stack, but the OS also stores the rest of the context on the task stack as well. When it does the switch and exits the interrupt, the OS restores the context it stored itself for the task and then the rest of the context is automatically restored by exiting the interrupt. This works as it is ensured that the stack is left in the correct format. Look at interrupt entry / exit in the Cortex-M4 Generic User Guide.
Not all processors work like this.
This answer is generic and not FreeRTOS nor Cortex-M specific - it applies to any typical RTOS on any platform:
RTOS API calls that cause the scheduler to run cannot be called from the interrupt service routine. For example, if you give a semaphore, normally the scheduler runs to switch to any task pending on that semaphore; this is inappropriate in an ISR, where the scheduler must run once when the interrupt context exits; obviously you do not want a context switch before the interrupt has completed and there may be other API calls or preemption by higher priority interrupts that cause a different task to become runable; making that assessment only once when the context switch will occur maintains deterministic behaviour.
The ISR specific versions of functions do not invoke the scheduler immediately; instead they set a flag to indicate that the scheduler must run on exit from the interrupt context.
Typically an ISR that makes RTOS API calls must have a prologue and epilogue; specific enter/exit interrupt calls or macros. This prologue, increments a counter that is decremented in the epilogue; if the counter is zero and the schedule flag is set, the scheduler will run. The counter is to prevent the scheduler from running on exit from a nested interrupt. This ensures that the scheduler only runs once on exit form the lowest priority pending interrupt.
Whether or why a "uasge fault" would occur is a FreeRTOS specific implementation detail, and largely academic. An RTOS could equally trap the usage of a non-ISR safe call in an ISR and run a more specific error handler, if it does not bother to do so, then the resulting behaviour might trigger a usage fault; it seems a somewhat crude mechanism to rely on; Usage Fault is a very broad trap and could happen for a number of reasons:
Usage Fault: detects execution of undefined instructions, unaligned
memory access for load/store multiple. When enabled, divide-by-zero
and other unaligned memory accesses are also detected.
Some RTOS do not have ISR specific functions, instead the API calls that cause scheduling detect internally the ISR context and behave differently in that context - this is simpler and safer for the programmer, but carries a small overhead to test the context on every such call. An API that handles ISR safety internally also means that calling functions that may themselves make OS API calls is simpler since those functions themselves need not be ISR specific.

Is spinlock required for every interrupt handler?

In Chapter 5 of ULK the author states as follows:
"...each interrupt handler is serialized with respect to itself-that is, it cannot execute more than one concurrently. Thus, accessing the data struct does not require synchronization primitives"
I don't quite understand why interrupt handlers is "serialized" on modern CPUs with multiple cores. I'm thinking it could be possible that a same ISR can be run on different cores simultaneously, right? If that's the case, if you don't use spinlock to protect your data it can come to a race condition.
So my question is, on a modern system with multi-cpus, for every interrupt handler you are going to write that will read & write some data, is spinlock always needed?
While executing interrupt handlers, the kernel explicitly disables that particular interrupt line at the interrupt controller, so one interrupt handler cannot be executed more than once concurrently. (The handlers of other interrupts can run concurrently, though.)
Clarification: as per CL. remark below - the kernel makes sure not to fire the interrupt handler for the same interrupt but if you have multiple registrations of the same interrupt handler for multiple interrupts than the below answer is, I believe, correct.
You are right that the same interrupt handler can run concurrently on multiple cores and that shared data needs to be protected. However, a spinlock is not the only and certainly not always the recommended way to achieve this.
A multitude of other synchronization methods, from per-CPU data, accessing shared data only using atomic operations and even Read-Copy-Update variants may be used to protect the shared data.
No spinlock is not always needed in interrupt handler.
Please note one thing first -
When an interrupt of a particular device occur on interrupt controller, that interrupt is disabled at interrupt controller and hence on all the cores for that particular device. So, the interrupt of same device cannot come on all the CPU simultaneously.
So in normal case there wont be any spin lock required as the code would not be re-entrant.
Though there are 2 cases below in which spinlock is needed in interrupt handler.
Please note, when an interrupt comes from a device and IRQ line, that cores disables all other interrupt on that core and also for that device interrupt on other core also. Interrupt from other devices can comes on other core.
So there can be a case in which, same interrupt handler is registered for different devices.
for eg:-
request_irq(A,func,..);
reqest_irq(B,func,..);
for device A interrupt handler func is called.
for device B same interrupt handler func is called.
So, a spinlock should be used in this case to prevent raise condition.
When same resource is being used in interrupt handler and also some other code which runs in process context.
For eg:- there is resource A
So there can be a case in which one cores runs in interrupt mode, the interrupt handler and is modifying the resource A and other core runs in process context and is also modifying the same resource in some other place.
So to present raise condition for that resource we should use spin lock.
section 4.6 of Understanding the Linux Kernel, 3rd Edition by Marco Cesati, Daniel P. Bovet told you the answer.
Actual interrupt handler is process by handle_IRQ_event. irq_desc[irq].lock prevent concurrently access to handle_IRQ_event by any other CPU.
If the critical data is shared b/w the interrupt handler and your process (may be a kernel thread) then you need to protect your data and hence spinlock is required.A common Kernel api for spinlock is : spin_lock().
There are also variants of these api e.g. spin_lock_irqsave() which can help avoiding the deadlock problems which one can face while acquiring/holding the spin locks.Please go through the below link to find details of the subject:
http://www.linuxjournal.com/article/5833

Resources