1
votes

I'm using FreeRTOS for a project of mine and I'm reading the documentation and there's something I can't understand. I know that context switching happens as the tick interrupt is triggered, so the scheduler performs its work and unblocks tasks that were waiting for an event and chooses the higher priority task that's in the ready state. But what happens when a task blocks before the tick interrupt? The documentation seems to hint that a context switch takes immediately place (for example,two task with different priorities each calling vTaskDelay() to free the CPU time slice). How does it happen? I searched but I couldn't find any answer to my question.

EDIT in my port of FreeRTOS (SAMD21 Cortex-M0+) the portYIELD() macro is used that simply request a SVCall exception, so is this the mechanism that is used to perform context switching (aside from the scheduler running on tick interrupts)?

4
Not sure exactly what you're asking, but if a thread relinquishes the processor before it's time slice is over, an RTOS should run the scheduler immediately.Fiddling Bits
@FiddlingBits yes, that's what I suppose, but there's no trace of it in the documentation. It only talks about the ISR running on every periodic tick, but what about context switching occurring between ticks? Does the scheduler take over and perform context switching? if so, does a interrupt (software) fires in order to do it?Luca
The SVC is no longer used in the latest M0 ports. However I expect the SVC interrupt is triggering a PendSV interrupt to do the actual context switching.Realtime Rik

4 Answers

5
votes

There is documentation about taskYIELD. This function can be used to request context switch so no need to wait for the tick. Context switching is privileged operation so it is often done by software interrupt. In your case by PendSV and SVCall.

If all tasks are blocked (e.g by vTaskDelay) then FreeRTOS is running Idle Task. vTaskDelay uses portYIELD internally to request context switch, because there is no way how to continue current task.

You also need some knowledge about Preemptive multitasking to understand FreeRTOS in that mode.

Edit 2016-01-29:

  • Calling delay function causes calling taskYIELD/portYIELD internally. So your current task is blocked and FreeRTOS reschedule to highest priority task, that can run (is not also blocked) or to Idle task if there is no task able to run.
  • Calling e.g. xQueueReceive can have two possibilities. There is some element in the queue, so it is POPed. There is no element in the queue, so the task is switched to blocked state and YIELD is called for you, so FreeRTOS reshedule to another task.
  • Calling e.g. xQueueSend can have two possibilities. There is no room in the queue, so the task is blocked until there is some space. There is at least one free element, so you can push to the queue.

Receiving element from the queue or sending element to the queue can wake other higher priority task, that is doing oposite but is currently blocked. FreeRTOS will reschedule it immediately.

This can be also done from interrupt handler. You can have handler task, that is waiting on some queue. From the interrupt, you put some element to the queue. After the interrupt ends, FreeRTOS reschedules to the task waiting on that queue. There is just prerequisite to have enough high priority on that task. This has benefit, that you are not doing much in the interrupt - just some cleanup and sending item to the queue - which is short operation. Handling interrupt can be also done by xTimerPendFunctionCallFromISR, which is another interresting way how to handle interrupts.

Please also read about FreeRTOS fundamentals. There are several chapters about it and it is interresting reading.

1
votes

Whenever a OS call such as TaskDelay or sending an item to a queue or freeing a resource occurs the OS works out if another any other task become ready to run, if a higher priority task is ready to run, it will pre-empt the current task. Basically whatever is the highest priority task that is ready to run will run. The time slicing only occurs when two or more task of equal and highest priority are ready to run.

Yes an interrupt runs. On a cortex-m the PENDSV interrupt carries out the context switch.

1
votes

Are you asking what you have to do to switch to another task when the currently running task blocks? Or are you asking about the mechanics of how a context switch is performed? Its really not clear.

If you are asking how to switch to another task when one task blocks then the answer is nothing, that is the fundamentals of what the RTOS does for you. If you call vTaskDelay() for example, or xQueueReceive() with blocking time specified, then the task enters the Blocked state. When the task is Blocked, it cannot run, so the scheduling algorithm in the RTOS selects the next task to run AND starts that task running.

0
votes

A little late to the party. I believe an implicit taskYield is called inside a xQueueReceive.

Inside an ISR, a call to xQueueSend doesn't call taskYield. It must be called explicitly (& at end of Function). This gives the ISR a bit of control whether to do a context switch or not. So if a task is blocked on a xQueueReceive and hence say in the Idle task, and an ISR is called the performs a xQueueSendFromISR. If NO taskYield is called it will return to the Idle task until the next timer tick. Even though xQueueReceive could unblock. If taskYield is called within the ISR, the scheduler will get called and the xQueueReceive will unblock and postentially run right after ISR.