xSemaphoreGiveFromISR context switch problem

destremps wrote on Friday, June 26, 2009:

AVR32 UC3A0512 port. 200Hz RTOS tick rate.

I have whittled my app down to 1 task and two interrupts during my investigation. One of the interrupts is the FreeRTOS tick. The second interrupt is a 1kHz interrupt into a gpio pin. All the ISR service routine does is raise an IO pin (for the scope), a call to xSemaphoreGiveFromISR, clear the interrupt, and drop the IO pin. Takes about 35usec and we have been very careful to follow the ISR preemption conventions for this port.

The task is also very simple. Its priority is IDLE + 5 (can be idle + anything as it’s the only task). It is blocked on the semaphore. Normally when the ISR finishes (exits) this task runs immediately because it was made ready due to the semaphore give. All the task does is take the semaphore and toggle another IO pin. 99% of the time this task executes within 30usec from the completion of the ISR. Considered a sucessful preemption as we leave the ISR.

The problem is once in a while the preemption does not occur. The task executes 5ms later (think 200hz). I now am generating the 1kHz interrupt with a signal generator and as I vary the interrupt frequency the nature of the mishap changes (happens more or less frequently and pattern varies).

When the preemption is missed 4 or 5 more interrupts happen before the task runs. Those ISRs process much quicker that the 35usec normally observed. About 10usec is all they take. I believe the xSemaphoreGiveFromISR is executing much faster in that mode.

It is interesting that the task always runs exactly 5ms after the GPIO interrupt. I suspect this is a nested interrupt problem with the two interrupts.

UPDATE: I have fixed this problem (I think). And decided to post this anyway as is quite interesting. If you really want to see you RTOS work this simple setup is pretty neat to observe on a scope. THE FIX was to raise the hardware interrupt priority level of the FreeRTOS tick to above that of the GPIO interrupt. The AVR32 will nest interrupts. Apparently it is unacceptable for the tick ISR to be interruptted by the GPIO interrupt (doing the semaphore give and attempting a context switch). BUT it appears to be okay for the GPIO ISR to be interruptted by the tick interrupt. I know this port of FreeRTOS is not supposed to run with nested interrupts but thought by following the ISR conventions laid out for the port all would be good. I’m just happy it all works now!

Any comments appreciated.


richard_damon wrote on Friday, June 26, 2009:

The issue is probably that your GPIO interrupt is calling xSemaphoreGiveFrom|SR when the tick intterupt is in the middle of processing a scheduler operation. This could cause the GPIO to skip the scheduler operation to start up the task and that won’t happen until the next time the tick operation has happened. FreeRTOS assume that interrupts that access the kernel do not nest, so it doesn’t implement critical sections inside routines run inside interrupt routine. In some ways you are luck that it is sort of behaving, as by letting the this happen, you run the risk of corrupting some of the data structures used by FreeRTOS.

Reversing the priority levels just swaped which problems could occur. If the tic interrupt preempts the GPIO interrupt, and some task higher than the task started by the GPIO task get reactivate by the tick, it won’t start until the next scheduler action, probably when the GPIO task block on the semaphore. Not long in you case, but it could be.

destremps wrote on Monday, June 29, 2009:

Well then as I feared we are still exposed. At the very least to a task starting one tick late - which I think is okay for me. The bigger fear is the possiblity of trashed behaviour that potentially brings the kernel down.

So has anyone addressed this on the ARV32 UC3 series of microcontrollers? Nested interrupts are happening. Is a solution to run all interrupts at the same hardware priority level? (there are 4 levels in the part)

How about this thought: to avoid the nesting that happens with this part shouldn’t the portENTER_SWITCHING_ISR macro mask higher priority interrupts?

Appreciate it.

destremps wrote on Monday, June 29, 2009:

After giving this some more thought and finding this message


my conclusion for the AVR32 UC3 port is as follows:

All interrupt service routines that make FreeRTOS system calls, including the OS tick, must be at the same interrupt level.

I don’t know where the correct place is for this all important statement to sit, but probably not buried in this thread. Maybe it’s already stated and tied to the port and I’ve missed it.

Well that’s where I’ve gotten to.