xSemaphoreTake/Give from ISR

alsaleem wrote on Sunday, July 30, 2017:

I have a resource to be synchronized on task accesses. I made a code (in the resource driver) to use xSemaphoreTake/Give for this synchronization.
I now have a case that this resource needs to be accessed from ISR. This requires that the lock process take/give be done in the calling function (instead of the driver) since it might be the task or isr. This adds a little complexity.

My question: Is there away in FreeRTOS to know if the code being executed is from a task or isr?
If yes, is it going to take too much cpu time?

Thanks.

richard_damon wrote on Sunday, July 30, 2017:

FreeRTOS exposes no portable way to detect if yoou are in an ISR or not (and it may not be an easy thing to determine on all platforms it has been ported to). If you look in port.c, inside vPortEnterCritical there may be code to test this as part of a configASSERT statement, that code being very port specific.

Sometimes I do wonder if it would make sense for poort.c/portmacro.h to export this code as a callable function for those ports where it is something reasonable to test. I do find that there are a few cases where it could be useful.

One thing you are going need to watch out the way you are describing things, if a task has locked the resource, and an ISR that needs it gets invoked, there is no way for the ISR to do the equivalent of a block till available, so you may need to rethink your program structure. I rarely find that this sort of access can be made to look mostly the same between the ISR context and the Task Context, so the resource driver needs different code for the two cases, so the ISR can just call the FromISR version of the driver.

The point where having the test could be helpful is if the ISR needs to use a middle layer of code that then access the driver, and duplicating the middle layer may be a bit awkward. (But if the middle layer has much code, it probably shouldn’t be called in the ISR anyway).

alsaleem wrote on Sunday, July 30, 2017:

if a task has locked the resource, and an ISR that needs it gets invoked, there is no way for the ISR to do the equivalent of a block till available,

yes. good point. However, if the isr is of a lower priority than systick, then it should be able to wait.

I will look into the code you mentioned and also see if i could do a work-around.

Thanks.

richard_damon wrote on Sunday, July 30, 2017:

First, I beleive SysTick needs to be the lowest priority of interrupt. (That is an assumption in most ports)

Second, if the ISR does try to wait, all it can do is spin its wheels, which means the task that has the lock will NEVER run, and never finish its operation and your program dies in a deadlock.

If your ISR tried to wait by going back to the task, nothing will ever resume the ISR, so it will never do its action.

Like I said, ISR access to shared resources is different than task level access.

One option is you could put the code that needs to accerss the resource into a Pended function, which will then mean it will run at ‘Task Level’ and is written very much like task code (uses non-FromISR routines).

Remember, xSemaphoreTakeFromISR does NOT block, and thus doesn’t provide the same sort of exclusion that xSemaphoreTake does.

alsaleem wrote on Sunday, July 30, 2017:

I was confusing

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   0xf

and

#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5

yes, systick has the lowest.

If your ISR tried to wait by going back to the task, nothing will ever resume the ISR, so it will never do its action.

Thanks for the explanation as it contains facts.
What if the sysytick has mid-priority (e.g. 8 in 16-level)? Is there away to push isr’s PC/SP into top of FreeRTOS’s TCB list?

I managed to do work around, in my current case. I created a high priority task and used (xTaskNotifyFromISR/portYIELD_FROM_ISR → xTaskNotifyWait) to continue the work.

Thanks.

richard_damon wrote on Sunday, July 30, 2017:

The Tick Processing code assumes it is on the lowest priority interrupt, so moving it up is likely to cause problems.

Trying to add the ISR to the TCB list is basically trying to make it a task, actually making a task avoids a lot of problems, which is a good solution. I was suggesting using xTimerPendFunctionFromISR() which is a slightly lighter weight option (but might add some undesired interactions depending on who long some other task might be holding the resource).

hs2sf wrote on Monday, July 31, 2017:

I’d propose to rethink your design. It’s not the best idea trying to block in an ISR and also this is not supported by any other OS I’m aware of for a reason.

alsaleem wrote on Tuesday, August 01, 2017:

Thanks. I already made a separate high priority task to continue the work.
Maybe FreeRTOS team may think of this scenario. There might be a case to do that.

rtel wrote on Tuesday, August 01, 2017:

Thanks. I already made a sepeare high priority task to continue the work.
Maybe FreeRTOS team may think of this scenario. There might be a case to
do that.

That is what xTimerPendFunctionFromISR() does, it takes the function you
pass it as a parameter and runs it in the RTOS daemon task (also known
as the timer service task) - the priority of which is set by the
application writer.

Going back to answer the question at the top of the thread, if you are
using a Cortex-M then there is a function xPortIsInsideInterrupt() that
tells you if you are in an interrupt or not - but that would not help
you in any case.

alsaleem wrote on Tuesday, August 01, 2017:

Yes, indeed xTimerPendFunctionCallFromISR does exactly the work I wanted, although it adds a separate task (xTimer task) same as i did.
Unfortunately, i am running V8.2.1, and could not find xPortIsInsideInterrupt in this version’s code.

Is upgrade a seamless process? I mean, do I need to re-write some code to upgrade?

Thanks.

rtel wrote on Tuesday, August 01, 2017:

The upgrade should be a drop in replacement.

richard_damon wrote on Tuesday, August 01, 2017:

xTimerPendFunctinCallFromISR adds a single task, that allows you to create a number of ISR callbacks and/or Timer Call back routines. If you have no other use for the TImer/Service task, then it is extra overhead. Knowing it is there, can often simplify code and save tasks.

RTE can make a more diffinative comment, but I don’t remember any incompatibility issues between v8 and v9 of FreeRTOS (lots of new features, but I don’t remember anything breaking.

alsaleem wrote on Wednesday, August 02, 2017:

Thanks. I assume it is 100% drop-in.