ES: Task Management

Task management in FreeRTOS controls how tasks are created, scheduled, executed, and deleted while managing their states, priorities, and individual stacks.Understanding TCB internals, stack handling, idle behavior, and starvation is essential to design deterministic, safe, and efficient embedded systems.

Task Management (Deep Dive)

In any Real-Time Operating System (RTOS), task management is the core

mechanism that enables deterministic behavior. If the scheduler decides

who runs, task management defines *how tasks live, transition, and

terminate inside the kernel*.

This deep dive explains task management in a **generic RTOS

architecture**, independent of any specific implementation.


Understanding a Task in an RTOS

A task (or thread) is an independent execution context that contains:

  • Its own stack memory
  • Its own CPU register snapshot
  • Its own priority level
  • Its own execution state

Unlike a bare‑metal super loop:

c
int main()
{
    while(1)
    {
        taskA();
        taskB();
        taskC();
    }
}

An RTOS isolates execution contexts:

txt
			  Scheduler
				  |
	---------------------------------
	|               |               |
  Task A          Task B          Task C
 (Stack A)        (Stack B)       (Stack C)

Each task has its own stack and saved CPU state. This isolation enables

preemptive multitasking.


Task Creation and Deletion

When a task is created, the kernel performs:

  • Allocation of a Task Control Block (TCB)
  • Allocation of stack memory
  • Initialization of the initial stack frame
  • Insertion into the Ready queue

Internal conceptual flow:

txt
+-----------------------------+
| Allocate TCB                |
+-----------------------------+
| Allocate Stack              |
+-----------------------------+
| Initialize Stack Frame      |
| (Simulated interrupt frame) |
+-----------------------------+
| Insert into Ready Queue     |
+-----------------------------+

Task deletion reverses the process:

  • Removal from scheduling queues
  • Stack memory release
  • TCB release

Proper lifecycle management prevents memory leaks and scheduling

corruption.


Task States

A task continuously transitions between defined states:

txt
			 +------------+
			 |  Running   |
			 +------------+
					|
					| Preempted
					v
			 +------------+
			 |   Ready    |
			 +------------+
					|
	 +--------------+---------------+
	 |                              |
 Wait / Delay                    Resume
	 v                              ^
+------------+                      |
|  Blocked   |----------------------+
+------------+

+------------+
| Suspended  |
+------------+

Running

Only one task per CPU core can execute at a time.

Ready

Task is eligible to run but waiting for CPU allocation.

Blocked

Task is waiting for:

  • Time delay expiration
  • Semaphore
  • Queue message
  • Event flag
  • Notification

Suspended

Task is explicitly paused and invisible to the scheduler until resumed.

All state information is stored in the Task Control Block.


Task Control Block (TCB) Internals

The TCB is the kernel's internal representation of a task.

Conceptual structure:

txt
+---------------------------+
| Task Identifier           |
+---------------------------+
| Priority                  |
+---------------------------+
| Top of Stack Pointer      |
+---------------------------+
| Stack Base Address        |
+---------------------------+
| State List Links          |
+---------------------------+
| Event List Links          |
+---------------------------+
| Task Flags / Attributes   |
+---------------------------+

The most critical field is the Top of Stack Pointer.

During a context switch:

txt
Context Switch Flow

Save CPU Registers
		|
		v
Store into Current TCB->Stack
		|
		v
Load Next TCB->Stack
		|
		v
Restore CPU Registers

This mechanism allows seamless switching between tasks.


Stack Management per Task

Each task owns a private stack region.

Typical memory layout:

txt
RAM
+----------------------------------+
| Stack Task A                     |
+----------------------------------+
| Stack Task B                     |
+----------------------------------+
| Stack Task C                     |
+----------------------------------+
| Heap                             |
+----------------------------------+

The stack stores:

  • Local variables
  • Function call frames
  • CPU registers during context switches
  • Interrupt nesting frames

Proper stack sizing is critical for system stability.


Stack Overflow Detection

Stack overflow is a severe failure because it can corrupt:

  • Neighboring stacks
  • Kernel structures
  • Heap memory

Two common detection mechanisms:

Stack Pointer Boundary Check

Verify the stack pointer remains within its allocated limits.

Pattern Fill Technique

Initialize stack with known pattern:

txt
| AA AA AA AA |
| AA AA AA AA |
| AA AA AA AA |
| Used Region |

If pattern corruption is detected → overflow handler is triggered.

Best practice:

  • Measure maximum stack usage
  • Maintain safety margin (25--30%)
  • Avoid deep recursion in RTOS tasks

Task Priorities

Each task has a priority level.

Scheduler rule:

txt
    Select highest priority Ready task
    Execute it

Preemption example:

txt
    Time →
    Low Low Low Low
            ^
            High becomes Ready
            High High High

If multiple tasks share same priority:

txt
    Round Robin Scheduling

    T1 T1 T2 T2 T1 T1 T2 T2

Priority design directly impacts determinism.


Idle Task and Background Processing

Every RTOS contains an internal Idle task.

Characteristics:

  • Lowest priority
  • Always Ready
  • Executes when no other task is Ready

Conceptual behavior:

If Ready Queue is empty

Execute Idle Task

Idle task responsibilities may include:

  • Power management entry
  • Memory cleanup
  • Background maintenance

Efficient systems use the Idle period to reduce power consumption.


Task Starvation

Starvation occurs when a lower-priority task never executes.

Example:

txt
    Time →
    High High High High High
    Low never runs

Causes:

  • High-priority task never blocks
  • Poor priority distribution
  • Busy polling loops

Incorrect design:

c
while(1)
{
    pollHardware();
}

Correct event-driven design:

c
while(1)
{
    waitForEvent();
    processEvent();
}

Golden rule:

High-priority tasks must block quickly.


Final Architectural View

txt
				 +--------------------+
				 |     Scheduler      |
				 +--------------------+
						 |
	-------------------------------------------------
	|              |              |                |
 Control        Comms          Logging           Idle
 (High Pri)    (Medium)        (Low)           (Lowest)
	|              |              |
  Blocks         Blocks         Blocks

Professional RTOS task management is:

  • Event-driven
  • Stack-monitored
  • Priority-balanced
  • Deterministic
  • Free from starvation