Understanding the Three Major Task Scheduling Mechanisms in Microcontrollers: Preemptive, Round-Robin, and Coroutines

Here, I will explain these three concepts from a simple and microcontroller engineer’s perspective, ensuring you understand them at a glance.

๐Ÿš€ 1. Preemptive Scheduler

Core: Tasks can be “forcefully interrupted”, and the CPU’s control can be taken away by higher priority tasks at any time.

โœ” Features

  • Uses interrupts + priority to control task switching
  • When a high-priority task arrives โ†’ immediately interrupts the current task
  • RTOS (FreeRTOS, RTX) all use this mechanism
  • Each task has its own stack and context switching

โœ” Applicable Scenarios

  • Strong real-time requirements
  • Multiple tasks running in parallel without blocking each other
  • Complex logic projects (e.g., communication + control + interface)

โœ” Example

PWM interrupt needs to execute every 20ยตs โ†’ it can interrupt the main loop at any time, which is “preemption”.

โ†’ The essence: relies on hardware interrupts to preempt the CPU

โฑ 2. Time Slice Round-Robin / Time Polling

Core: The CPU will not be interrupted; tasks can only “queue and take turns executing”, each running a little bit.

โœ” Features

  • Non-preemptive
  • Different tasks are executed in order
  • Each task runs for a short period (time slice), then switches to the next
  • No interrupts means no task switching (except SysTick)

โœ” Typical Performance in Microcontrollers

Like this:

while (1) {
    Task_A();
    Task_B();
    Task_C();
}

Or:

if (Sched_Every(&t1, 1)) Task_A();
if (Sched_Every(&t2, 5)) Task_B();

Both are polling style.

โœ” Advantages / Disadvantages

  • Simple structure, very stable
  • Delays rely on “queuing” โ†’ not real-time enough
  • If one task gets stuck โ†’ all other tasks get stuck

โ†’ The essence: queuing to do things in a big loop, will not be forcefully interrupted.

๐ŸŒฑ 3. Coroutines

Core: Tasks voluntarily yield the CPU, not preempted, but “voluntary switching”.

โœ” Features

  • Lightweight, does not require an independent stack (there are stack coroutines, but the overhead is much less)
  • Does not rely on interrupts, will not preempt
  • Tasks execute to a certain point and then yield() / await() to yield the CPU
  • When continuing execution, it resumes from the last paused point

โœ” Essential Differences

  • Coroutines: I pause voluntarily
  • Time slice round-robin: The CPU tells me to pause (when the time slice is up)
  • Preemptive: Interrupts directly take the CPU

โœ” Example in Microcontrollers (State Machine + Segmented Execution)

Like this:

switch(state) {
    case 0: ... state=1; break;
    case 1: ... state=2; break;
    case 2: ... state=0; break;
}

This is actually a manual coroutine โ€” executing a little bit each time, using state to save the “pause point”.

๐Ÿ”ฅ Comparison of the Three (Microcontroller Perspective)

Feature Preemptive Scheduling (RTOS) Time Slice Round-Robin Coroutines
CPU Control Can be interrupted and taken at any time Cannot be taken Task voluntarily yields
Real-time Performance โญโญโญโญโญ โญโญ โญโญโญ
Deadlock Risk Yes (needs locking) Very low Low
Overhead Maximum Minimum Very small
Number of Tasks Many Medium Many
Suitable For Complex systems Small systems Lightweight multitasking, logical flow

๐Ÿ“Œ The Simplest Summary in One Sentence

Preemptive Scheduling

๐Ÿ‘‰ “I don’t care what you’re doing, high priority needs to use it, yield immediately!

Time Slice Round-Robin

๐Ÿ‘‰ “Everyone comes one by one, queue and take turns on the CPU.

Coroutines

๐Ÿ‘‰ “I do it halfway, pause for a moment, let others go first.

Leave a Comment