From my understanding, not all processors support a mechanism to determine what context given code is called from, which prohibits a generic solution. This has been discussed many times before, I am surprised you are not aware of it?..
In addition to not all processors having a method to decide, just requiring the API TO decide, means the more normal case, where you know the context is slower.
There are also fundamental differences in what you can and need to do based on the context, as the ISR can not “block” and wait for something, so needs some active handling of a “busy” condition.
When you do the normal things, ISRs tend to be very small and quick and what happens in them is clearly in an ISR. If you are going into a larger routine that is going to be used in both an interrupt context and a task context, normally using it in the interrupt context is NOT the right thing to do, but the ISR should have done some smaller operation, and kicked of a task, perhaps of high priority, to finish the operations, so it doesn’t interfear with other interrupts.
If the operation is actually fairly short, making an ISR version and a task-based version isn’t normally that hard.
Just to add to what @richard-damon and @RAc said, it is a design decision taken to ensure that the ISR code is kept as short as possible. Otherwise, the code to determine context would always execute in the ISR context.
Thank you all for your quick and helpful replies. Here is my summary (kind of). Maybe some more bullets could be added to the FAQ?
Q:
• Why do we have a separate API (FromISR/FROM_ISR) used in interrupts?
• Wouldn’t it be possible to make a wrapper, that understands whether it is called from interrupt or task context and call the appropriate functions?
A:
• not all processors support a mechanism to determine whether code is called from an ISR
• in case the processor has a way to distinguish interrupt and non-interrupt context one could try xPortIsInsideInterrupt() but
– just requiring the API to decide, means the more normal case, where you know the interrupt/task context is slower
• there are also fundamental differences in what you can and need to do based on the context
– the ISR can not “block” and wait for something, so it needs some active
handling of a “busy” condition
• it’s a design decision to have a clear distinction between FreeRTOS API calls from ISR and task context taken to ensure that the ISR code is kept as short as possible (code to determine context would always execute in the ISR context) and to prevent large routines shared between task and interrupt context
– when you do the normal things, ISRs tend to be very small and quick and what happens in them is clearly in an ISR
– having the possibility to easily write a larger routine that will be used in both in interrupt context and a task context, normally using it in the interrupt context is NOT the right thing to do!
– deferred processing should be preferred: i.e. the ISR should have done some smaller operation, and kicked off a task, perhaps of high priority, to finish the operations, so it doesn’t interfere with other interrupts
• if the operation is fairly short, making an ISR version and a task-based version isn’t normally that hard
• (from FreeRTOS FAQ) - having separate APIs means:
• API functions designed for use in interrupts are optimized for that use case;
– they do not need to check programmatically if they are being called from an interrupt
– they do not need to take different actions depending on whether they are being called from an interrupt or task context
– and they do not need parameters (such as block times) that are required when they are called from a task context but are obsolete when they are called from an interrupt context