Introduction to RTOS Part 3 - Task Scheduling | Digi-Key Electronics
Understanding the FreeRTOS Scheduler
Overview of Multi-threaded Programming
- The discussion begins with a recap on using an RTOS and running multiple tasks in FreeRTOS, leading into a deeper exploration of how the scheduler operates.
- In multi-threaded programs, tasks appear to run independently and simultaneously, especially when hardware interrupts are utilized for events like timer overflows or pin changes.
Processor Utilization and Time Slicing
- With a single core processor, time must be divided among various tasks. Most RTOS implementations use time slicing, where hardware timers interrupt the processor at regular intervals (commonly one millisecond in FreeRTOS).
- A diagram illustrates priority slots for tasks; the scheduler runs every tick (one millisecond) to determine which task to execute based on priority.
Task Scheduling Mechanics
- If only one low-priority task (Task A) is ready to run, it will continue until its time slice ends. If it calls
vTaskDelay, it enters a blocked state while waiting for ticks.
- Once Task A's delay expires, it becomes ready again. Higher priority tasks (Tasks B and C) can enter the ready state but must wait for their turn during the next tick.
Preemptive Scheduling Explained
- The scheduler prioritizes higher-priority tasks (B and C), executing them in a round-robin manner if they share equal priority. This method is known as preemptive scheduling.
- Preemptive scheduling allows CPU time to be reallocated from lower-priority tasks to higher-priority ones without needing explicit code intervention.
Interrupt Handling Considerations
- Hardware interrupts have higher priority than software processes unless explicitly disabled. Nested interrupts depend on specific hardware configurations.
- It’s recommended to limit active interrupt service routines (ISRs), keeping them short to ensure efficient task switching back to previously running tasks.
Multi-core System Dynamics
- In multi-core systems, schedulers may allocate different tasks across cores for simultaneous execution; however, this discussion focuses on single-core operation for simplicity.
- When created, each task enters a ready state indicating its availability for execution unless blocked by higher-priority tasks.
Task States Management
- Tasks transition between states: ready when available for execution and running when actively using the processor. Only one task can be in the running state at any moment on a single-core system.
- Tasks can enter blocked states through API functions like
vTaskDelay, pausing their execution until certain conditions are met (e.g., timer expiration).
Suspending Tasks Effectively
- FreeRTOS provides an API function (
vTaskSuspend) that allows developers to suspend tasks intentionally. These suspended tasks cannot run until explicitly resumed viavTaskResume.
Understanding Context Switching in RTOS
What is Context Switching?
- When switching tasks, the scheduler must remember where each task left off, including all working variables and values stored in RAM and CPU registers.
- The saved information about a task's state is referred to as its "context," and the process of saving and restoring this context for different tasks is known as context switching.
- FreeRTOS documentation provides valuable resources on context switching, including graphics and detailed examples for AVR microcontrollers.
Example of Task Preemption
- An Arduino example demonstrates task preemption by creating two tasks: one that counts characters in a string and another that prints an asterisk every 100 milliseconds.
- To avoid blocking output from the second task, the first task prints one character at a time instead of sending the entire string to the serial buffer.
- After completing its character count, the first task enters a blocked state for one second, allowing RTOS to manage its return to ready state after delay.
Task Management in Setup
- A slow serial baud rate is used during setup to visualize real-time outputs; faster rates may cause missed outputs.
- The setup function initializes two tasks with different priorities: priority 1 for counting characters (task 1), and priority 2 for printing asterisks (task 2).
- A third control task manages suspending and resuming task two while ensuring proper handling of task deletion using
vTaskDelete.
Observing Task Behavior
- Upon uploading code to ESP32, users should set baud rate to 300. Resetting ESP32 helps start fresh execution.
- Users will observe that both setup and loop functions run independently as separate tasks with defined priorities.
- As tasks are suspended or resumed, users will see interruptions in output—asterisks appearing amidst printed sentences from the first task.
Challenge & Next Steps
- The challenge presented involves creating a program with two tasks controlling an LED's blinking rate based on user input via serial terminal.
- This exercise aims to develop an independent user interface that updates LED behavior without interfering with hardware operations.