In the Micrium uC/OS-II, which is the RTOS I used to work in my previous work, there is a pair of API functions OSIntEnter and OSIntExit intended to notify the Kernel about the interrupt being processed, I think in order to prevent Scheduler switching to some task during the interrupt and also to keep track of interrupt nesting. This example is taken from the Micrium web-site:
MyISR:
Save CPU registers;
OSIntEnter(); /* Or, OSIntNestingCtr++ */
:
Process ISR;
:
OSIntExit();
Restore CPU registers;
Return from interrupt;
The same approach exists in the Segger’s embOS. They have a similar API: OS_INT_Enter() and OS_INT_Exit()
I don’t see a similar API in the FreeRTOS (checked in the User Manual). If it is indeed true, would one here be so kind as to explain me why in the FreeRTOS I don’t need to notify the Scheduler about the interrupt being processed?
The interrupt is declared as naked, i.e. without the usual save and restore context. In stead, the two macro’s take care of this.
Note that in this case, the return value of handler_spi() determines if a task switch is required ( register r0 ).
For platforms using ARM, the interrupt handlers are simpler: they look like ordinary functions.
In all cases, within an interrupt handler, you can only use a subset of the FreeRTOS API’s, i.e. the ones that end with FromISR
Thank you very much for spending your time to answer my question.
For most ports ( platforms ), FreeRTOS does not have an equivalent of OSIntEnter()/OSIntExit()
So the question is how the Scheduler knows the code is running from interrupt? Isn’t there a danger that it will switch the interrupt to some task ? Doesn’t the scheduler run from PendSV , so seemingly it can do this unwanted context switching.
The interrupt is declared as naked, i.e. without the usual save and restore context. In stead, the two macro’s take care of this.
Actually I found the function portENTER_SWITCHING_ISR(); on the web, but by some reason I didn’t find it in the User Guide, therefore I didn’t understand what is the function intended for. I also didn’t find this function in my FreeRTOS project (FreeRTOS 9.0 for now). Did you mean to say that I have to always call portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR inside my ISR?
Also can I assume that this specific ISR API takes care to prevent the context switching while an ISR running is ongoing?
So the question is how the Scheduler knows the code is running from interrupt?
Isn’t there a danger that it will switch the interrupt to some task?
Doesn’t the scheduler run from PendSV , so seemingly it can do this unwanted context switching.
You do not have to worry about this. You just write the ISR code, keeping it as short as possible. If a context switch becomes necessary, it will take place after your ISR is ready.
Did you mean to say that I have to always call portENTER_SWITCHING_ISR()
and portEXIT_SWITCHING_ISR inside my ISR?
No, that is not necessary, unless you’re using a platform like Atmel UC3.
Also can I assume that this specific ISR API takes care to prevent the context
switching while an ISR running is ongoing?
As for ARM: this has to do with priorities: the priority of your ISR’s should higher than the priority of PendSV. If you have configASSERT(), the CPU priority will be checked in every API you call from an ISR.
About configASSERT() : it is a macro that will halt your program in case an expression can not be asserted ( i.e. evaluates to zero ). Read more about configASSERT() here.
But PendSV does have a higher priority…
The higher the number, the lower the priority
As I understand the priority of PendSV is configurable
Sure it is. You can use ISR’s with a lower priority as long as they do nothing with the FreeRTOS kernel.
but… doesn’t kernel itself takes care for that ?
Like I said, the kernel can check the current ISR priority during every FromISR() API.
This is being done for instance in xQueueGenericSendFromISR() when it calls the macro portASSERT_IF_INTERRUPT_PRIORITY_INVALID().
The page you mention is indeed very clear and helpful
Given the mentioned above OSIntEnter()/OSIntExit() do not exist in FreeRTOS, may I assume that the RTOS Interrupt Latency is zero in the FreeRTOS? So far, I used to think that the overhead of the OSIntEnter()/OSIntExit() is the “Interrupt Latency” added by RTOS. Am i mistaken?
In FreeRTOS there is a separate API for use in interrupts - namely the
functions with “FromISR” in their name. There are pros and cons to any
approach of course, but FreeRTOS’s approach here means:
You do not need to tell the kernel you are in an interrupt, you just
have to use the right API functions when you are.
The API functions can be tuned for use when inside interrupts - for
example you can’t block inside an interrupt so there is no block time
parameter to pass into an ISR safe function and no logic in the
implementation of the ISR function to handle blocking.
The non ISR functions can also be tuned as they do not need to check
to see if you are inside an interrupt before deciding what to do.