Task switch time after xSemaphoreGiveFromISR

I am using xSemaphoreGiveFromISR() and portEND_SWITCHING_ISR() to activate a task from a ISR. I have some timing issues, and wish to know what time I could expect from the ISR til my task starts to run from where it was waiting with xSemaphoreTake(). The MCU I am using has a Cortex M3 core and is running at 80 MHz.

Task switch time after xSemaphoreGiveFromISR

Assuming there are no other interrupts pending, and assuming there is no interrupt nesting, then portEND_SWITCHING_ISR() on the Cortex M3 will just set a bit in the register.  Then when your interrupt exits the software interrupt will run (with tail chaining) and select a new task.  When the software interrupt exits your new task will be running. I’m not going to provide the exact details (there are 26 architectures supported, with 55 ports, that would be a full time job) but can recommend that you either measure using a scope (or something similar) or that you just count the cycles used by the output asm instructions. Regards.

Task switch time after xSemaphoreGiveFromISR

Then I suppose the scheduler is not my problem. I am using a semaphore to delay a task, as described above. However, often the time from the ISR til the task gets unblocked may be as long as 150 ms (!). And this is when I am testing with the highest priority task, and no other tasks that have any work to do. Is this a known behavior to you? I am confident that I am doing something wrong, but am not able to find out what it is.

Task switch time after xSemaphoreGiveFromISR

150ms is an astronimically long time – probably 600 times what I would expect it to be in the region of. What is your tick rate?
Are you using any function such as printf() that take a long time to complete?
Do you have any critical sections that could take a long time complete?
Most importantly of all – how are you measuring the time?  Sorry to say that normally when people complain of timing issues the problem lies in how they are measuring it – normally because of incorrect assumptions. Regards.

Task switch time after xSemaphoreGiveFromISR

Currently I am using a tick rate of 10000, but I have experimented with several different numbers. Also, I notice that the scheduler ISR xPortPendSVHandler is in fact executed  is called every tick (and presumably whenever i call portEND_SWITCHING_ISR), so I am lead to think that the problem is related to the semaphore/queue and/or how the scheduler decides that the task that was waiting for the semaphore is ready to run. Initially I measured the delay with a timer on the MCU, but I also checked using GPIO’s. I intended to measure on them using a logical analyzer, but in fact the delay on such a magnitude that it is easy to see without the analyzer, as the GPIO’s have LED’s attached to them.

Task switch time after xSemaphoreGiveFromISR

> Currently I am using a tick rate of 10000, but I have experimented with several
> different numbers. The demos use 1KHz by default, and that is too fast. 10KHz is extremely fast. I doubt the kernel is doing much other than executing itself. > Also, I notice that the scheduler ISR xPortPendSVHandler
> is in fact executed  is called every tick If configUSE_PREEMPTION is set to 1 then that is correct behavior. > (and presumably whenever i call
> portEND_SWITCHING_ISR), No, it will never be called when portEND_SWITCHING_ISR is called, but portEND_SWITCHING_ISR will cause it to execute. This is described in post 2 of this thread. Also, if you look at the implementation of these functions and macros you will see that this assumption is not right. > so I am lead to think that the problem is related to
> the semaphore/queue and/or how the scheduler decides that the task that was
> waiting for the semaphore is ready to run. It works for everybody else, so either you have discovered a latent bug or the problem is in your own code. If you are using 10KHz and don’t understand how the macros work I think it is the later but am ok with you proving me wrong. > Initially I measured the delay with a timer on the MCU, but I also checked using
> GPIO’s. I intended to measure on them using a logical analyzer, but in fact
> the delay on such a magnitude that it is easy to see without the analyzer, as
> the GPIO’s have LED’s attached to them. I think the delay is likely to be because of the 10KHz tick. Do you have stack overflow trapping turned on?

Task switch time after xSemaphoreGiveFromISR

The demos use 1KHz by default, and that is too fast. 10KHz is extremely fast.
I doubt the kernel is doing much other than executing itself.
It is also worth pointing out that, although the scheduler will run with a tick rate above 1KHz, if you go above 1KHz then the constant portTICK_RATE_MS will not work.  If you are using portTICK_RATE_MS then that could be the cause of the described behaviour. Regards.

Task switch time after xSemaphoreGiveFromISR

Thank you for your feedback, richardbarry and davedoors. As I mentioned in my second post, I am confident that I am doing something wrong, and not insinuating that the problem is related to a bug in FreeRTOS. What I am describing is the symptoms I see, hoping that some of you have experienced similar symptoms previously, and have ideas on what could cause such a behavior. After reading what you said, I will deficiently use less that 1 kHz tick rate. However, changing this (actually to as low as 10 Hz), did not help my problem. I also set configCHECK_FOR_STACK_OVERFLOW to 0. Also, I did use portTICK_RATE_MS, but as you said, that caused division by zero, so I stopped using that. Regarding the way I described portEND_SWITCHING_ISR(), it was with a unprecise language, but still the practical effect will be that, after a (very) short time, the scheduler executes (triggered by the software interrupt) – or have I totally misunderstood things?

Task switch time after xSemaphoreGiveFromISR

Hi,
after a (very) short time, the scheduler executes
As already described in Post 2, the scheduler executes immediatly after your isr-routine. I’m using a Cortex M3 too at 72 MHz and ~1kHz tick rate. The delay between the interrupt event and the waiting task switching in is around 11 µs. configCHECK_FOR_STACK_OVERFLOW is 2 and tracing enabled. Unfortunately i don’t know where your problem is. I can only show you my implementation: void isr(void) {
  signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
  xSemaphoreGiveFromISR(semaphore, &xHigherPriorityTaskWoken);
  portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
} Hope it helps you.