Module 5/5 · Weeks 13–15 · 27 h

RTOS and embedded AI

UAT 204 Microcontrollers and Embedded Systems

About 80 minDraft, awaiting reviewLast updated 27 September 2026

Lesson

By the end of this module you will be able to

  1. Explain tasks, priority and preemption in a real-time operating system (RTOS)
  2. Check whether a task set is rate-monotonic schedulable using the Liu and Layland bound and simulation
  3. Identify the RTOSs used in PX4 and ArduPilot and the licences of NuttX, ChibiOS and FreeRTOS
  4. Explain running small AI models on MCUs (TinyML) and their limits

Prerequisites: UAT 204 modules 1–4

Why this matters

A flight controller must do many jobs at once: read the IMU a thousand times a second, compute attitude, receive GPS, write logs and talk to the ground station. If logging runs so long that an IMU read misses its time, control degrades immediately. A real-time operating system (RTOS) orders the work so important tasks always run on time. The final topic leads on to running small AI models on MCUs.

Tasks, priority and preemption

  • A task is work repeated periodically, with period and computation time
  • Priority is the task’s importance
  • Preemption lets a more important task interrupt a running one at once

Rate-monotonic scheduling gives higher priority to shorter periods. Liu and Layland (1973) proved that if total utilisation does not exceed for tasks, every task meets its deadline. This bound falls towards about 69% for many tasks. It is a sufficient condition: exceeding it does not necessarily mean failure, and needs a closer check.

Example 1 A hypothetical flight controller’s task set

Time units are 0.1 ms (integers, to avoid floating-point error). Simulate one second, with shorter periods at higher priority.

def check(tasks, horizon=10_000):
    n = len(tasks)
    u = sum(c / t for _, t, c in tasks)
    bound = n * (2 ** (1 / n) - 1)
    order = sorted(tasks, key=lambda x: x[1])            # shorter period = higher priority
    remaining = {name: 0 for name, _, _ in order}
    missed = {name: 0 for name, _, _ in order}
    for t in range(horizon):
        for name, period, cost in order:
            if t % period == 0:
                if remaining[name] > 0:
                    missed[name] += 1                    # previous job unfinished = missed deadline
                remaining[name] = cost
        for name, _, _ in order:
            if remaining[name] > 0:
                remaining[name] -= 1
                break
    return u, bound, missed


base = [("IMU", 10, 2), ("attitude", 25, 5), ("logging", 200, 40), ("GPS", 1000, 50)]
for label, tasks in (("base", base), ("+ AI 6 ms/20 ms", base + [("AI", 2000, 600)]),
                     ("+ AI 8 ms/20 ms", base + [("AI", 2000, 800)])):
    u, bound, missed = check(tasks)
    print(f"{label:<16} U = {u:.2f}, bound = {bound:.3f}, missed deadlines = {sum(missed.values())}")
base             U = 0.65, bound = 0.757, missed deadlines = 0
+ AI 6 ms/20 ms  U = 0.95, bound = 0.743, missed deadlines = 0
+ AI 8 ms/20 ms  U = 1.05, bound = 0.743, missed deadlines = 4

The base set uses 65% of the CPU, below the 75.7% bound, so it is guaranteed to meet deadlines. Adding an AI task brings to 0.95, above the bound, yet the simulation shows every task still on time, because these periods divide into each other almost exactly; this is why the bound is only sufficient. But once the AI task grows so that exceeds 1, deadlines are certainly missed. All numbers are hypothetical, not real PX4 or ArduPilot timings.

A 0 to 10 ms timeline of four tasks. IMU runs briefly every 1 ms, attitude every 2.5 ms, logging runs in the gaps and is repeatedly preempted, and GPS runs near the end when the others are idle
Figure 1 Rate-monotonic schedule for the first 10 ms

RTOSs in flight stacks

  • PX4 uses NuttX as its primary RTOS on flight-control boards. NuttX is an Apache project under the Apache 2.0 licence
  • ArduPilot on STM32 boards uses ChibiOS through the AP_HAL_ChibiOS layer. ChibiOS/RT is GPL3 or commercial, while ChibiOS/HAL is Apache 2.0
  • FreeRTOS is popular on general MCU boards, including the ESP32; its kernel is MIT-licensed

Besides scheduling, a safe embedded system needs a watchdog, which resets the system if the program hangs and fails to check in on time.

From MCU to AI

Four levels from left to right: MCU for real-time control; MCU plus TinyML with kilobyte models; edge AI SoCs such as Jetson and Pi; and the cloud with large models. An arrow below runs from low power and fast response to more compute and more latency
Figure 2 From MCU to edge AI and the cloud

TinyML runs small machine-learning models on MCUs, for example classifying abnormal motor sounds or vibration patterns. Google calls its tool LiteRT for Microcontrollers (formerly TensorFlow Lite for Microcontrollers); it runs without an operating system, and its core runtime fits in about 16 KB on a Cortex-M3. Larger tasks, such as detecting objects in images, need a companion computer as in UAT 322, and the knowledge hub’s deep dive on embedded AI and ROS builds on this module.

Module lab

Lab: tasks on FreeRTOS

  1. Create a FreeRTOS project on the Pico 2 (following the SDK guide) with three tasks: read a sensor every 10 ms, send a UART frame every 100 ms and blink an LED every 500 ms.
  2. Assign rate-monotonic priorities and measure each task’s real timing by toggling GPIO pins and using a logic analyzer.
  3. Add a simulated heavy load (a busy computation) in a low-priority task and check that sensor reading stays on time.
  4. Put the measured values into the code in Example 1 and compare calculation with measurement.
  5. Enable the watchdog, simulate a hung task and observe the reset.

Common mistakes

Watch out

  • Setting priorities by feel rather than by period and timing importance
  • Assuming exceeding the Liu–Layland bound always means unschedulable
  • Busy-waiting in tasks instead of using RTOS delays
  • No watchdog in systems that must run continuously
  • Expecting an MCU to run large image models

Summary

  • An RTOS orders tasks with priority and preemption so important work meets its deadlines
  • Rate-monotonic gives shorter periods higher priority; the bound is a sufficient condition
  • PX4 uses NuttX, ArduPilot uses ChibiOS, and FreeRTOS is popular on general MCUs
  • TinyML runs small models on MCUs, while larger AI needs a companion computer

Check your understanding

  1. A task with a 10 ms period takes 2 ms and one with a 20 ms period takes 5 ms. What is the total utilisation?
  2. What is the rate-monotonic bound for 2 tasks?
  3. Is the task set in question 1 guaranteed to meet its deadlines?
  4. Which RTOS does PX4 use on flight-control boards?
  5. What is a watchdog for?
Answers
  1. Yes, because
  2. NuttX
  3. To reset the system when the program hangs and fails to check in on time

Key formulas

CPU utilisation
Rate-monotonic bound

Key references

  1. Liu, C. L., & Layland, J. W. (1973). Scheduling algorithms for multiprogramming in a hard-real-time environment. Journal of the ACM, 20(1), 46–61. link
  2. PX4 Autopilot. PX4 architectural overview. PX4 user guide (main). link
  3. Apache Software Foundation. Apache NuttX real-time operating system. link
  4. ArduPilot Dev Team. Porting to a new flight controller board (ChibiOS). ArduPilot developer documentation. link
  5. ChibiOS. Licensing (ChibiOS/RT and ChibiOS/HAL). link
  6. FreeRTOS. FreeRTOS kernel (MIT license). link
  7. Google. LiteRT for Microcontrollers (TensorFlow Lite for Microcontrollers). link
  8. Warden, P., & Situnayake, D. (2020). TinyML: Machine learning with TensorFlow Lite on Arduino and ultra-low-power microcontrollers. O'Reilly Media.

Further reading

Study the assigned knowledge units in advance, review media and take the module quiz

In class / field

Lab or field practice from worksheets with a safety checklist

Learning evidence: Checked worksheets and quiz results

Module quiz

This is a formative self-check, not a graded exam

Knowledge domain: Sensors and embedded systems · Automation, robotics and swarms · Artificial intelligence and computer vision