0
0
FreeRTOSprogramming~15 mins

Multiple tasks running concurrently in FreeRTOS - Deep Dive

Choose your learning style9 modes available
Overview - Multiple tasks running concurrently
What is it?
Multiple tasks running concurrently means that a system can handle several jobs at the same time by switching between them quickly. In FreeRTOS, tasks are like small programs that run independently but share the same processor. The system manages these tasks so they appear to run together, even if the processor can only do one thing at a time. This helps devices do many things without waiting for one job to finish before starting another.
Why it matters
Without running multiple tasks concurrently, devices would be slow and unresponsive because they would have to finish one job completely before starting another. This would make things like reading sensors, controlling motors, and communicating over networks inefficient. By running tasks concurrently, devices can react faster and handle complex jobs smoothly, improving user experience and system reliability.
Where it fits
Before learning about multiple tasks running concurrently, you should understand basic programming concepts like functions and loops. Knowing what an operating system does helps too. After this, you can learn about task synchronization, inter-task communication, and advanced scheduling techniques in FreeRTOS.
Mental Model
Core Idea
Multiple tasks run by sharing processor time so each gets a turn, making it seem like they run at the same time.
Think of it like...
Imagine a single cook in a kitchen preparing several dishes by working on each dish a little bit at a time, switching between them quickly so all dishes progress together.
┌───────────────┐
│   Processor   │
└──────┬────────┘
       │
┌──────▼───────┐
│ Task Scheduler│
└──────┬───────┘
       │
┌──────▼───────┐   ┌──────▼───────┐   ┌──────▼───────┐
│   Task 1     │   │   Task 2     │   │   Task 3     │
└──────────────┘   └──────────────┘   └──────────────┘
Build-Up - 7 Steps
1
FoundationWhat is a Task in FreeRTOS
🤔
Concept: A task is a small program or function that runs independently in FreeRTOS.
In FreeRTOS, a task is like a mini-program that does a specific job. You create tasks by writing functions and telling FreeRTOS to run them. Each task has its own stack and state, so it can run without interfering with others.
Result
You can create multiple tasks that FreeRTOS will manage separately.
Understanding that tasks are independent units of work is key to grasping how FreeRTOS manages multiple jobs.
2
FoundationHow FreeRTOS Switches Between Tasks
🤔
Concept: FreeRTOS switches tasks by saving and restoring their states quickly, giving each a slice of processor time.
The processor can only do one thing at a time. FreeRTOS switches between tasks by saving the current task's information (like where it stopped) and loading another task's information to continue it. This happens so fast that tasks seem to run at the same time.
Result
Multiple tasks appear to run concurrently even on a single processor.
Knowing that task switching is about saving and restoring states helps understand how concurrency works without multiple processors.
3
IntermediateTask Priorities and Scheduling
🤔Before reading on: do you think higher priority tasks always run before lower priority ones, or can lower priority tasks run first? Commit to your answer.
Concept: Tasks have priorities that influence which task runs next, but lower priority tasks can run when higher priority ones are waiting.
Each task has a priority number. The scheduler picks the highest priority task that is ready to run. If a high priority task is waiting (for example, for a delay or event), lower priority tasks get a chance to run. This way, important tasks get more attention, but others still make progress.
Result
Tasks run in an order that respects their importance but allows all to run when possible.
Understanding priority-based scheduling explains why some tasks run more often and how FreeRTOS balances work.
4
IntermediateCreating and Starting Multiple Tasks
🤔Before reading on: do you think tasks start running immediately after creation, or only after the scheduler starts? Commit to your answer.
Concept: Tasks are created with specific functions and start running only after the scheduler begins.
You create tasks using xTaskCreate(), giving each a function to run and a priority. However, tasks do not run until you call vTaskStartScheduler(), which starts the task switching process. Before that, tasks exist but do not execute.
Result
Multiple tasks are ready and start running concurrently once the scheduler is active.
Knowing that the scheduler controls task execution timing helps avoid confusion about when tasks actually run.
5
IntermediateTask States and Blocking
🤔Before reading on: do you think a blocked task uses processor time or not? Commit to your answer.
Concept: Tasks can be in different states; blocked tasks do not use processor time until unblocked.
Tasks can be running, ready, blocked, or suspended. A blocked task waits for something (like a timer or event) and does not run or use processor time. This allows other tasks to run while it waits.
Result
Efficient use of processor time by running only tasks that are ready.
Understanding task states explains how FreeRTOS manages processor time efficiently.
6
AdvancedContext Switching Overhead and Optimization
🤔Before reading on: do you think context switching is free or does it cost processor time? Commit to your answer.
Concept: Switching tasks takes time and resources, so minimizing switches improves performance.
Each time FreeRTOS switches tasks, it saves and restores registers and stack info. This takes processor time called context switch overhead. Writing tasks that run longer or block properly reduces unnecessary switches and improves system speed.
Result
Better system performance by reducing wasted time on switching.
Knowing the cost of context switches helps write efficient multitasking programs.
7
ExpertPreemptive vs Cooperative Multitasking in FreeRTOS
🤔Before reading on: do you think FreeRTOS always forces task switches, or can tasks control when to switch? Commit to your answer.
Concept: FreeRTOS supports both preemptive (forced) and cooperative (voluntary) multitasking modes.
In preemptive mode, the scheduler interrupts tasks to switch to higher priority ones automatically. In cooperative mode, tasks must yield control voluntarily. Preemptive mode is common for responsiveness, but cooperative mode can simplify some designs and reduce context switches.
Result
Flexible multitasking behavior depending on system needs.
Understanding these modes helps choose the right multitasking style for your application.
Under the Hood
FreeRTOS uses a scheduler that manages a list of tasks with their states and priorities. It uses a timer interrupt (tick) to decide when to switch tasks. When switching, it saves the current task's CPU registers and stack pointer, then loads the next task's saved state. This process is called context switching. The scheduler picks the highest priority ready task to run next, ensuring real-time responsiveness.
Why designed this way?
FreeRTOS was designed for small, resource-limited devices needing real-time control. The lightweight scheduler and context switching minimize overhead and complexity. Preemptive scheduling ensures critical tasks run promptly, while cooperative mode offers simplicity. Alternatives like full OS kernels were too heavy for embedded systems, so FreeRTOS balances power and efficiency.
┌───────────────┐
│   Timer Tick  │
└──────┬────────┘
       │ triggers
┌──────▼───────┐
│   Scheduler  │
├──────────────┤
│ Task List    │
│ (states,    │
│ priorities) │
└──────┬───────┘
       │
┌──────▼───────┐       ┌───────────────┐
│ Save Current │       │ Load Next     │
│ Task Context │──────▶│ Task Context  │
└──────────────┘       └───────────────┘
       │                      │
       └──────────────┬───────┘
                      ▼
               ┌───────────────┐
               │  CPU Runs     │
               │  Next Task    │
               └───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Do tasks in FreeRTOS truly run at the exact same time on a single-core processor? Commit to yes or no.
Common Belief:Tasks run exactly at the same time simultaneously.
Tap to reveal reality
Reality:On a single-core processor, tasks do not run simultaneously but share processor time by switching rapidly.
Why it matters:Believing tasks run simultaneously can lead to confusion about timing and resource conflicts.
Quick: Does a higher priority task always run immediately, even if a lower priority task is running? Commit to yes or no.
Common Belief:Higher priority tasks always interrupt lower priority tasks immediately.
Tap to reveal reality
Reality:Higher priority tasks run immediately only in preemptive mode; in cooperative mode, tasks must yield control voluntarily.
Why it matters:Misunderstanding this can cause bugs where high priority tasks don't run as expected.
Quick: Do blocked tasks consume processor time while waiting? Commit to yes or no.
Common Belief:Blocked tasks still use processor time while waiting.
Tap to reveal reality
Reality:Blocked tasks do not use processor time until they become ready again.
Why it matters:Thinking blocked tasks consume CPU can lead to inefficient task design.
Quick: Is context switching free and has no impact on system performance? Commit to yes or no.
Common Belief:Context switching is free and does not affect performance.
Tap to reveal reality
Reality:Context switching takes processor time and resources, impacting performance if overused.
Why it matters:Ignoring context switch cost can cause slow or unresponsive systems.
Expert Zone
1
Task stack size must be carefully chosen; too small causes crashes, too large wastes memory.
2
Using task notifications is a lightweight way to communicate between tasks, more efficient than queues in some cases.
3
The tick rate affects responsiveness and power consumption; higher tick rates improve responsiveness but use more CPU.
When NOT to use
Running multiple tasks concurrently is not ideal for very simple applications where a single loop suffices. In such cases, adding multitasking adds unnecessary complexity. Also, for hard real-time systems requiring guaranteed timing, specialized real-time kernels or hardware solutions might be better.
Production Patterns
In real-world systems, tasks are often grouped by function (e.g., sensor reading, communication, control). Priority levels reflect task importance. Developers use synchronization tools like semaphores and queues to avoid conflicts. Power management is handled by blocking tasks when idle. Debugging tools monitor task states and CPU usage to optimize performance.
Connections
Threading in General-Purpose Operating Systems
Builds-on similar ideas of multitasking but with more resources and complexity.
Understanding FreeRTOS tasks helps grasp how threads work in bigger OSes like Windows or Linux, showing the core idea of time-sharing.
Cooperative Board Games
Shares the idea of players taking turns voluntarily to progress the game.
Knowing how players yield turns in cooperative games helps understand cooperative multitasking where tasks must yield control.
Project Management with Multiple Workers
Same pattern of dividing work into tasks and scheduling them efficiently.
Seeing how managers assign and prioritize tasks among workers clarifies how FreeRTOS schedules tasks by priority and readiness.
Common Pitfalls
#1Creating tasks but forgetting to start the scheduler.
Wrong approach:xTaskCreate(task1, "Task1", 1000, NULL, 1, NULL); // No call to vTaskStartScheduler()
Correct approach:xTaskCreate(task1, "Task1", 1000, NULL, 1, NULL); vTaskStartScheduler();
Root cause:Not understanding that tasks only run after the scheduler starts.
#2Using the same priority for all tasks without considering importance.
Wrong approach:xTaskCreate(task1, "Task1", 1000, NULL, 1, NULL); xTaskCreate(task2, "Task2", 1000, NULL, 1, NULL);
Correct approach:xTaskCreate(task1, "Task1", 1000, NULL, 2, NULL); xTaskCreate(task2, "Task2", 1000, NULL, 1, NULL);
Root cause:Not recognizing how priorities affect task scheduling and responsiveness.
#3Writing tasks that never block or yield, causing system freeze.
Wrong approach:void task1(void *pvParameters) { while(1) { // Busy loop without delay or yield } }
Correct approach:void task1(void *pvParameters) { while(1) { // Do work vTaskDelay(pdMS_TO_TICKS(10)); } }
Root cause:Not understanding the need for tasks to block or yield to allow others to run.
Key Takeaways
Multiple tasks in FreeRTOS run by sharing processor time through fast switching, not true simultaneous execution on single-core processors.
Task priorities guide which task runs next, but tasks must be designed to block or yield to allow multitasking to work smoothly.
The scheduler starts task execution; creating tasks alone does not run them.
Context switching has a cost, so efficient task design minimizes unnecessary switches for better performance.
FreeRTOS supports both preemptive and cooperative multitasking, offering flexibility for different application needs.