Professional Documents
Culture Documents
The task that is actually running (using processing time) is in the Running state.
On a single core processor there can only be one task in the Running state at any given time.
Created tasks that are not actually running, but are not in the Blocked state or the Suspended state, are in the
Ready state.
Tasks that are in the Ready state are available to be selected by the scheduler as the task to enter the
Running state.
The scheduler will always choose the highest priority Ready state task to enter the Running
state.
Tasks can wait in the Blocked state for an event and are automatically moved back to the Ready
state when the event occurs.
Temporal events occur at a particular time, for example, when a block time expires, and are normally used to implement
periodic or timeout behavior. We saw many examples of this type.
Synchronization events occur when a task or interrupt service routine sends information using a task notification, queue,
event group, or one of the many types of semaphore. They are generally used to signal asynchronous activity, such as data
arriving at a peripheral. We will see many examples of this type later in the course.
Question 2
Read the section "Configuring the Scheduling Algorithm" on Page 91 of the FreeRTOS Tutorial to answer the following!
The scheduling algorithm is the software routine that decides which Ready state task to transition into the Running state.
The FreeRTOS scheduling algorithm can be changed using two configuration constants in FreeRTOSConfig.h:
configUSE_PREEMPTION
configUSE_TIME_SLICING
In all possible configurations the FreeRTOS scheduler, ensures that the tasks that have the same priority are selected to
enter the Running state in turn.
This policy is referred to as
Round Robin
scheduling (RR).
The RR scheduling algorithm does not guarantee that the time is shared equally between tasks of equal priority.
A third configuration constant, configUSE_TICKLESS_IDLE, also affects the scheduling algorithm by turning off the tick
interrupt for extended periods.
Read the section "Prioritized Pre-emptive Scheduling with Time Slicing" starting on Page 92 in the FreeRTOS Tutorial to
answer the following!
All the examples we saw in the last chapter used the default setting of the configuration constants:
configUSE_PREEMPTION =
1
configUSE_TIME_SLICING =
1
In this configuration, the algorithm is called Fixed Priority Pre-emptive Scheduling with Time Slicing.
Fixed Priority: The algorithm does not change the priority assigned to the tasks being scheduled. However, it
does not prevent the tasks themselves from changing their own priority, or that of other tasks.
Preemptive: The algorithm preempts the Running task when a task with higher priority enters the Ready state
immediately .
Time Slicing: Time slicing is used to share processing time between tasks of equal priority, even when the tasks do not
explicitly yield or enter the Blocked state. A time slice is equal to the time between
2
The figure illustrates an example for Fixed Priority Pre-emptive Scheduling with Time Slicing.
The 4 tasks have four different priority levels.
Task 1 and Task 3 are event-driven.
Task 2 is periodic.
ms.
Task 3 gets
3
The last event can have occurred any time between t9 and t12
Idle Task
The idle task is running at the lowest priority, so gets pre-empted every time a higher priority task enters the Ready state
—for example, at times t3, t5 and t9.
Task 3
Task 3 is an event-driven task that executes with a relatively low priority, but above the Idle priority. It spends most of its
time in the Blocked state waiting for its event of interest, transitioning from the Blocked state to the Ready state each
time the event occurs. All FreeRTOS inter-task communication mechanisms (task notifications, queues, semaphores, event
groups, etc.) can be used to signal events and unblock tasks in this way.
Events occur at times t3 and t5, and also somewhere between t9 and t12. The events occurring at times t3 and t5 are
processed immediately as, at these times, Task 3 is the highest priority task that is able to run. The event that occurs
4/4/2021 LQ 6-1: Attempt review
somewhere between times t9 and t12 is not processed until t12 because, until then, the higher priority tasks Task 1 and
Task 2 are still executing. It is only at time t12 that both Task 1 and Task 2 are in the Blocked state, making Task 3 the
highest priority Ready state task.
Task 2
Task 2 is a periodic task that executes at a priority above the priority of Task 3, but below the priority of Task 1. The task’s
period interval means Task 2 wants to execute at times t1, t6, and t9.
At time t6, Task 3 is in the Running state, but Task 2 has the higher relative priority so pre-empts Task 3 and starts
executing immediately. Task 2 completes its processing and re-enters the Blocked state at time t7, at which point Task 3
can re-enter the Running state to complete its processing. Task 3 itself Blocks at time t8.
Task 1
Task 1 is also an event-driven task. It executes with the highest priority of all, so can pre-empt any other task in the
system. The only Task 1 event shown occurs at time t10, at which time Task 1 pre-empts Task 2. Task 2 can complete its
processing only after Task 1 has re-entered the Blocked state at time t11.
Question 5
The figure illustrates another example for Fixed Priority Pre-emptive Scheduling with Time Slicing.
Task 2 has same priority as the Idle task (0).
Task 1 is event-driven and has higher priority.
The Fixed Priority Pre-emptive Scheduling with Time Slicing causes same-priority tasks to enter the Running state in an
alternating way, even if any of these tasks was preempted and did not consume its time slice fully.
Assume that Task 1 has re-entered the Blocked state at t8, instead of t7.
The previous example (above) showed that the Idle task is sharing processing time with an application task. Allocating
that much processing time to the Idle task might not be desirable if the application task with the same priority as the idle
task has work to do, but the Idle task does not.
There is a compile time configuration constant that can be used to control this. It is called configIDLE_SHOULD_YIELD.
This parameter can be used to change how the Idle task is scheduled:
configIDLE_SHOULD_YIELD = 0: The Idle task will remain in the Running state for the entirety of its time slice, unless it is
preempted by a higher priority task. See the example above.
configIDLE_SHOULD_YIELD = 1: The Idle task will yield (voluntarily give up whatever remains of its allocated time slice)
on each iteration of its loop if there are other Idle priority tasks in the Ready state.
As you can see the rule of strict alternating between same-priority tasks does not apply here for idle-priority tasks. This is
why Task 2 continues execution at time point
t7
When configIDLE_SHOULD_YIELD is set to 1, the task selected to enter the Running state after the Idle task does not
execute for an entire time slice, but instead executes for whatever remains of the time slice during which the Idle task
yielded.
Question 7
Read the section "Prioritized Pre-emptive Scheduling (without Time Slicing)" starting on Page 96 in the FreeRTOS Tutorial
to answer the following!
configUSE_TIME_SLICING =
0
The following table shows the similarities and differences between both algorithms:
Fixed Priority Pre-emptive Scheduling with Time Slicing Prioritized Pre-emptive Sch
Priority Task can have different priorities Same
PreemptionHigher-priority tasks preempt lower priority tasks Same
Time Uses time slicing to share processing time between tasks of equal priority Does not use time slicing to share proce
Slicing
Time slicing:
If there is more than one ready state task at the highest priority that is able to run, then the scheduler will select a new
task to enter the Running state during each RTOS tick interrupt (a tick interrupt marking the end of a time slice).
No time slicing:
The scheduler will only select a new task to enter the Running state when either:
A higher priority task enters the Ready state.
The task in the Running state enters the Blocked or Suspended state.
Question 8
Turning time slicing off results in a reduction in the scheduler’s processing Yes because there are less
overhead. context switches.
Turning time slicing off can results can be unfair. Yes, because tasks of equal priority can receive
greatly different amounts of processing time.
22
Question 9
.
The Idle task and Task 2 are both continuous processing tasks of priority 0 (the idle priority).
Until this time point, the Idle task has spent more than four complete tick periods in the Running state.
Task 2 starts running at time t7, where Task 1 re-enters the Blocked state.
.
At time
t10
Tick interrupts occur at times t1, t2, t3, t4, t5, t8, t11, t12 and t13.
2 events happen to Task 1 at t6 and t9.
Question 10
Read the section "Co-operative Scheduling" starting on Page 98 in the FreeRTOS Tutorial to answer the following!
configUSE_TIME_SLICING = 0 or 1
When the co-operative scheduler is used, a context switch will only occur when the Running state task:
enters the Blocked state, or
explicitly yields (manually requests a re-schedule) by calling taskYIELD().
The figure shows the Gantt chart for three tasks using a co-operative scheduling scheme.
Later we will learn about queues and semaphore (for now think of them as events like the one caused by vTaskDelay();).
Between t3 and t4, both Task 1 and Task
2
are ready for execution. But they cannot start since Task3 cannot be preempted .
In a multi-tasking application the programmer should make sure that a resource is not accessed by more than one task
simultaneously.
Simultaneous access could corrupt the resource.
Example:
Two tasks are writing strings to the UART (serial port);
Task 1 is writing “abcdefghijklmnop”
Task 2 is writing “123456789”
Task 1 is in the Running state and starts to write its string. It writes “abcdefg” to the UART, but leaves the Running state
before writing any further characters.
Task 2 enters the Running state and writes “123456789” to the UART, before leaving the Running state.
Task 1 re-enters the Running state and writes the remaining characters of its string to the UART.
In this scenario what is actually written to the UART is “abcdefg123456789hijklmnop”, a corrupted sequence.
Co-operative scheduling solves this problem:
The programmer controls when a switch to another task should occur.
In the UART example, the programmer can ensure that Task 1 does not leave the Running state until its entire string has
been written to the UART.
However, systems will be less responsive when the co-operative scheduler is used and this can very problematic
for real-time systems that must respond to high priority events within a defined time period.
Question 13
Run the following code under default setting for the scheduling: (Preemptive with Time Slicing).
#include <Arduino_FreeRTOS.h>
void setup() {
Serial.begin(9600);
xTaskCreate(PrintCharcters, "A", 128, NULL, 1, &Handle_of_PrintCharcters_task);
xTaskCreate(PrintNumbers, "B", 128, NULL, 1, &Handle_of_PrintNumbers_task);
}
void loop() {}
void PrintCharcters (void *pvParameters) {
while (1) {
Serial.println("ABCDEFGHIGKLMNOP");}
}
void PrintNumbers (void *pvParameters) {
while (1) {
Serial.println("123456789123456789");}
}
Question 14
#define configUSE_PREEMPTION 0
#include <Arduino_FreeRTOS.h>
void setup() {
Serial.begin(9600);
xTaskCreate(PrintCharcters, "A", 128, NULL, 1, NULL);
xTaskCreate(PrintNumbers, "B", 128, NULL, 1, NULL);
}
void loop() {}
void PrintCharcters (void *pvParameters) {
while (1) {
Serial.println("ABCDEFGHIGKLMNOP");
taskYIELD()
;}
}
void PrintNumbers (void *pvParameters) {
while (1) {
Serial.println("123456789123456789");
taskYIELD()
;}
}