Problem in switch context

naomihochberg wrote on Sunday, March 20, 2011:

I use FreeRTOS with PIC24F15KA102. My application includes only one task (except the idle task) and I work with  non nested interrupts and total disable interrupts for portDISABLE_INTERRUPTS(). In ISRs messages are entered to Q. Messages are received and  handled by the task. Sometimes I reach the point where msg Q is full,but  the task is not running although it is ready.

Problem is caused by the fact that in vTaksSwitchContext  scanning the ready lists and decrementing the global variable uxTopReadyPriority is not protected from interrupts.  It may be changed by ISR that enters the message to Q during the following loop and than be  overwritten in the loop.

/* Find the highest priority queue that contains ready tasks. */
while( listLIST_IS_EMPTY( &( pxReadyTasksLists ) ) )

When I put the scanning loop under disable interrupts  problem is solved.

davedoors wrote on Sunday, March 20, 2011:

It sounds like you are doing something very wrong. Are you calling API functions that do not end in FromISR from inside an ISR? Are you enabling interrupts in the ISR in the wrong way, etc, etc. If it is being used correctly, the problem you describe will not happen.

naomihochberg wrote on Thursday, March 24, 2011:

I call xQueueSendToBackFromISR() that calls xTaskRemoveFromEventList() that calls prvAddTaskToReadyQueue()
that modifies uxTopReadyPriority  (in ISR).

vTaskSwitchContext()  is call by  portYIELD()   called by the Idle task.

rtel wrote on Thursday, March 24, 2011:

In that port, portYIELD() disables interrupts up to the priority set by configKERNEL_INTERRUPT_PRIORITY, and there is a documented restriction that interrupts that call ISR safe API functions cannot use a priority above configKERNEL_INTERRUPT_PRIORITY - therefore, if the usage instructions are being followed, it should not be possible for the two code sections you highlight (one inside an interrupt, and one outside of the interrupt) to interfere with each other.

That is the intention anyway - I’m always happy to be proven wrong.


naomihochberg wrote on Sunday, March 27, 2011:

In  PIC24F15KA102 none nested interrupt mode it is impossible to write to IPL bits of SR register.  ISR will always run in higher priority than none ISR routines.
Does that mean that it is impossible to use FreeRTOS in none nested interrupts mode ?

naomihochberg wrote on Thursday, March 31, 2011:

I use nested interrupts and configure all interrupts to configKERNEL_INTERRUPT_PRIORITY. It is actually the same as working in none nested interrupts mode. This way portYIELD()  disable interrupts before vTaskSwitchContext() is called
and my application is working OK.

Thanks to richarfbarry for the explanation.

anonymous wrote on Tuesday, April 12, 2011:

Hello naomihochberg,
I had the same problem on my LPC2468 (ARM7TDMI-S) and FreeRTOS 6.1.1. I have implemented nested interrupts by re-enabling all IRQs on entrance in a wrapper ISR. I mask out from configKERNEL_INTERRUPT_PRIORITY to configMAX_SYSCALL_INTERRUPT_PRIORITY and I have to mask out before calling vTaksSwitchContext.

Your denoted loop in vTaksSwitchContext isn’t safe using xFromISR functions if the CSW can be preempted by that syscall-level IRQs with xfromISR calls. If using any other traps that cannot interrupt IRQs everything is safe again .

I think this behavior should be considered in one of the next releases or should be mentioned correctly in the documentation as it only denotes

To utilize this scheme your application design must adhere to the following rule: Any interrupt that uses the FreeRTOS API must be set to the same priority as the kernel (as configured by the configKERNEL_INTERRUPT_PRIORITY macro), or at or below** configMAX_SYSCALL_INTERRUPT_PRIORITY** for ports that include this functionality