Understanding Task Scheduling in FreeRTOS

1. Task Scheduling

Understanding Task Scheduling in FreeRTOS

FreeRTOS is a lightweight real-time operating system kernel, and one of its core functions is task scheduling. Task scheduling is the core mechanism of FreeRTOS, determining which task runs at any given moment, when to switch tasks, and how to handle task priorities.

1.1. Task Definition

Task
  • “Task” is the basic execution unit scheduled by the operating system, equivalent to a “thread” in traditional operating systems. Each task is an independent execution flow, possessing its own program counter, stack space, and context information.
Task States

Tasks in FreeRTOS can be in the following states:

State Name Meaning
Running The task currently running (only one at any moment).
Ready Ready to run, but not currently scheduled.
Blocked Waiting for an event (such as a semaphore, delay, etc.).
Suspended Suspended and not participating in scheduling.
Deleted Deleted and waiting for the system to clean up resources.

1.2. Task Scheduling

In operating systems (including FreeRTOS), Scheduling refers to the process by which the system decides which task (or thread) to execute first, when to execute it, and for how long.

In simple terms: scheduling is about “who gets to use the CPU, for how long, and who uses it next after that.”

Core Objectives

The purpose of scheduling is to reasonably allocate resources when multiple tasks compete for the CPU, achieving the following goals:

  • Improve system response speed (real-time performance)
  • Increase CPU utilization
  • Ensure task fairness or correct priority
  • Meet the demands of real-time systems

Basic Process

  1. Multiple tasks are created and ready
  1. The scheduler selects the highest priority task
  1. The CPU executes that task (in Running state)
  • Calls <span>vTaskDelay()</span> to enter Blocked state
  • Preempted by other higher priority tasks
  • Voluntarily yields the CPU (cooperative)
  1. During task execution, it can be interrupted because:
  1. The scheduler selects an appropriate task to execute again

Scheduler

The “scheduler” in FreeRTOS is one of the core modules, responsible for

  • Managing task states (ready, blocked, suspended, deleted)
  • Implementing task switching (context switching)
  • Triggering events include
    • System tick interrupts (timed triggers)
    • Creating/deleting tasks
    • Suspending/resuming tasks
    • Interrupt service routines waking tasks

Scheduling Strategies

Type Description
Preemptive Scheduling High priority tasks can interrupt low priority tasks at any time
Non-preemptive Scheduling (Cooperative) Tasks must voluntarily yield the CPU for the scheduler to switch
Time-slice Scheduling Tasks of the same priority run in turn, each for a time slice

1.3. Task Switching

System Clock Tick

  • Uses hardware timers to generate interrupts periodically.
  • Each tick triggers the scheduler to check if a task switch is needed.

Context Switch Trigger Conditions

  • A high priority task becomes ready.
  • The current task voluntarily yields the CPU (e.g., calls taskYIELD(), vTaskDelay()).
  • Time slice expires (time rotation for tasks of the same priority).
  • A task is suspended or deleted.
  • Waiting events are satisfied (e.g., semaphore, queue, event group triggers).

Context Switching Process

  • Save the current task’s registers and stack pointer.
  • Load the next task’s registers and stack pointer.
  • Typically implemented in assembly code or bare-metal layer, platform-dependent.

1.4. Scheduling Control

Starting the Scheduler
  • <span>vTaskStartScheduler()</span>;
  • Once the scheduler is started, it will never return (unless it fails due to insufficient memory).
Suspending and Resuming the Scheduler
  • <span>vTaskSuspendAll()</span>: Temporarily suspends the scheduler, no context switching occurs.
  • <span>xTaskResumeAll()</span>: Resumes the scheduler, re-triggers scheduling.

1.5. Priority Inversion

Priority inversion is a potential serious issue in real-time systems, where a high-priority task is “blocked” by a low-priority task, violating scheduling policies and affecting system real-time performance, potentially leading to deadlocks.

Example

A high-priority task needs a resource (e.g., a mutex), but this resource is held by a low-priority task, which is being occupied by other medium-priority tasks for an extended period, causing the high-priority task to be delayed in obtaining the resource, and indirectly blocked by the lowest priority task.

This is called:<span>Priority being "inverted": the high-priority task is suppressed by a lower-priority task and cannot run.</span>

Priority Inheritance Mechanism

FreeRTOS provides a <span>priority inheritance mechanism</span> to alleviate the priority inversion problem:

  • When a low-priority task holds a mutex and a high-priority task is blocked on that lock, the system temporarily raises the priority of the low-priority task to that of the high-priority task, allowing it to complete and release the lock as soon as possible.
  • After releasing the lock, the task’s priority is restored.
  • Enabled by: using <span>xSemaphoreCreateMutex()</span><span> to create a mutex, which supports priority inheritance by default.</span>
Note

Binary semaphores created using <span>xSemaphoreCreateBinary()</span><span> do not support priority inheritance.</span>

2. Cooperative Scheduling

<1>. Principle

  • The current task will not be automatically interrupted, even if a higher-priority task is ready; the current task will continue executing until it voluntarily yields the CPU (e.g., calls taskYIELD(), vTaskDelay(), etc.).
  • Task switching can only occur when the current task “voluntarily” yields.

<2>. Configuration

  • <span>#define configUSE_PREEMPTION 0</span>

<3>. Characteristics

Advantages Disadvantages
Simple implementation, predictable scheduling behavior If tasks do not voluntarily yield, the system can “hang” on one task
Less likely to encounter priority inversion issues Poor real-time performance, easily affected by “malicious” tasks

<4>. Applications

  • Teaching, debugging scenarios
  • Simple system architecture, controlled task behavior, few tasks
  • Applications that do not pursue high real-time performance
Note

Cooperative scheduling is mainly used in resource-constrained devices and is rarely used now; FreeRTOS will no longer maintain this module but will keep it.

3. Preemptive Scheduling

<1>. Principle

  • The default scheduling method; as long as a higher-priority task is in the ready state, the current task will be immediately preempted.
  • Task switching is controlled by the scheduler, usually triggered by interrupts (such as system ticks).

<2>. Configuration

  • <span>#define configUSE_PREEMPTION 1</span>

<3>. Characteristics

Advantages Disadvantages
High real-time performance, faster response Complex system behavior, slightly higher debugging difficulty
Friendly to long tasks, no need to yield voluntarily Potential for priority inversion or frequent preemption issues

<4>. Applications

  • Applications with high real-time requirements
  • Multi-task collaborative operations, such as embedded controllers, industrial automation systems
  • Support for interrupt-driven task waking

4. Time-slice Scheduling

<1>. Principle

  • When multiple ready tasks have the same priority, the system allocates CPU time to them, with each task running in turn for a time slice.
  • The time slice expiration is triggered by the system tick interrupt.

<2>. Configuration

Time-slice scheduling is not an independent scheduling method but an extension mechanism within preemptive scheduling, suitable for “same priority” tasks:

  • <span>#define configUSE_PREEMPTION 1</span>
  • <span>#define configUSE_TIME_SLICING 1 // default is 1, can also be explicitly enabled</span>
  • The length of the time slice is determined by the system tick:<span>#define configTICK_RATE_HZ 1000 // indicates scheduling every 1ms</span>

<3>. Characteristics

Advantages Disadvantages
Fair CPU allocation for tasks of the same priority Frequent scheduling may incur overhead
Improves system responsiveness Real-time performance is not as good as priority-based scheduling

<4>. Applications

  • Many background processing tasks of the same priority need to be executed in turn
  • Systems need to ensure fairness or avoid starvation of certain tasks
Task Example
  1. Run Task1 for one system clock tick, then switch to Task2 through time-slice scheduling.
  2. Run Task2 for one system clock tick, then switch to Task3 through time-slice scheduling.
  3. Task3 calls a blocking API function during its execution; when calling the function, even though the time slice for one system clock tick has not been exhausted, it will still switch to the next task Task4 through time-slice scheduling. (Note that the unused time slice will not be reused; the next time Task3 is executed, it will still run for one system clock tick.)
  4. Run Task4 for one system clock tick, then switch back to Task1 through time-slice scheduling.

Understanding Task Scheduling in FreeRTOS

Previous Recommendations

RECOMMEND

Understanding Task Scheduling in FreeRTOS

[1]. Understanding Memory Management in FreeRTOS

[2]. Core Mechanisms and Important Concepts in FreeRTOS

[3]. How to Create Tasks in FreeRTOS

[4]. Interrupt Management and Configuration in FreeRTOS

I am Aike, an embedded software engineer.

Follow me for more embedded insights.

Remember to like, share, and click “see first,”

Your encouragement is my greatest motivation to keep sharing!

See you next time.

Looking forward to your

sharing

likes

views

NEWS

WeChat IDaike_eureka

Baijiahao|Master Embedded Systems

Leave a Comment