Multitask-Scheduler und Prioritätsdesign über 11 Lese-Stift-SKUs, mit Latenztabellen, Vermeidung von Prioritätsinversion und Preemption-Diagrammen für OEMs.

Veröffentlicht am: Jul 24, 2024 - 72 Aufrufe

Lese-Stift Multitask-Scheduler und Priorität: FreeRTOS, Zephyr, AliOS und Linux CFS im Vergleich

Zielgruppe: Dieser Leitfaden richtet sich an Firmware-Ingenieure, RTOS-Architekten und OEM-Programmmanager, die verstehen müssen, wie ein Lesestift seinen Audioplayer, OID-Decoder, Tasten-Handler, BLE-Stack und OTA-Agenten einplant – und wie sich diese Planung auf die für den Nutzer sichtbare Latenz, die Akkulaufzeit und Field-Service-Tickets auswirkt. Er setzt voraus, dass Sie wissen, was ein Thread oder Task ist, erfordert jedoch keine RTOS-Expertise.

Jeder Lesestift führt mehrere Tasks gleichzeitig aus, selbst der kleinste P2 mit seinen 64 KB Flash. Auf einem typischen T2 finden Sie 24–38 aktive Tasks: einen OID-Decoder-Task, einen Audio-Mixer-Task, einen UI-Task, einen Wi-Fi-Supervisor-Task, einen BLE-GATT-Server-Task, einen OTA-Staging-Task, einen Akku-Mess-Task, einen Power-Management-Task und mehrere Sensor-Polling-Tasks. Der Scheduler entscheidet in jeder Mikrosekunde, welcher davon auf der CPU läuft.

Dieser Artikel führt Sie durch die vier Scheduler-Familien, die wir über unsere 11 SKUs (B1, B2, F8, K7, KF1, L5, P2, Q6, Q8, T2, Y6) hinweg einsetzen – FreeRTOS, Zephyr, AliOS Things und Linux CFS – und zeigt die Prioritätszuweisung, Preemption-Latenz, Prioritätsinversions-Mitigation und Load-Shedding-Strategie, die wir jeweils verwenden.

1. Was ein Lesestift-Scheduler tatsächlich tut

Ein Scheduler hat drei Aufgaben:

  1. In jedem Moment entscheiden, welcher Task auf der CPU läuft.
  2. Priorität durchsetzen – höher priorisierte Tasks verdrängen niedriger priorisierte.
  3. Die Latenz zwischen einem Ereignis (Interrupt, Signal) und dem Aufwachen des zuständigen Tasks begrenzen.

Bei einem Lesestift ist die dritte Aufgabe am wichtigsten. Ein Nutzer tippt mit dem Stift auf einen OID-Punkt, der OID-Sensor löst einen DMA-Complete-Interrupt aus, der OID-Decoder-Task muss innerhalb von 1–4 ms aufwachen, um die Seite zu decodieren, und der Audioplayer-Task muss innerhalb von 50 ms mit dem Streaming beginnen. Wenn der Scheduler diese Latenz nicht begrenzen kann, hört der Nutzer eine Verzögerung.

2. Die vier Scheduler-Familien, die wir ausliefern

Scheduler OS SKUs, die ihn nutzen Preemption-Modell Tick-Rate
FreeRTOS tickbasiert FreeRTOS 10.4 B1, B2, P2 Prioritätsbasiert preemtiv 1 kHz
Zephyr tickless Zephyr 3.4 LTS K7, KF1 Priorität + Deadline 100 Hz Baseline, tickless idle
AliOS Things AliOS Things 3.3 Q6, Q8 Prioritätsbasiert preemtiv 1 kHz
Linux CFS Linux 5.10 / 5.15 F8, L5, T2, Y6 Completely Fair Scheduler mit RT-Gruppe 250 Hz / 1 kHz

Die Aufteilung von zwei Dritteln RTOS zu einem Drittel Linux spiegelt den breiteren Lesestift-Markt wider. Die Scheduler-Wahl folgt auf die in TC-097 diskutierte OS-Wahl, die Prioritätspolitik folgt hingegen aus dem Feature-Set des jeweiligen SKU.

3. FreeRTOS-Scheduler auf B1, B2, P2

FreeRTOS verwendet einen Fixed-Priority-Preemptive-Scheduler mit optionalem Time-Slicing. Jeder Task hat eine Priorität von 0 (niedrigste) bis configMAX_PRIORITIES - 1 (höchste, typischerweise 32 oder 56). Der Scheduler führt stets den bereiten Task mit der höchsten Priorität aus; Gleichstände werden per Time-Slice aufgelöst.

Auf der B2-Firmware 2.4.7 lautet unsere Prioritätstabelle:

Priorität Task Zweck Stack
7 (höchste) audio_dma_isr DMA-Complete-Handler (ISR-deferred) 256 Bytes
6 oid_decode OID-Seite decodieren 1.024 Bytes
5 audio_player MP3-Decode + DAC-Feed 2.048 Bytes
4 button_handler Button-Debounce + Long-Press 512 Bytes
3 battery_monitor Batterieanzeige-Abfrage 512 Bytes
2 led_pattern RGB-LED-Animation 256 Bytes
1 idle_hook Tickless-Idle-Eintritt 128 Bytes
0 ota_staging OTA-Empfang + Schreiben 1.024 Bytes

Der ISR wird über xQueueSendFromISR + taskNOTIFY an einen hochprioren Task zurückgestellt, sodass der Audiostream niemals durch langen ISR-Code blockiert wird. Priorität 7 bedeutet, dass der Audio-DMA-Handler 200 µs vor dem OID-Decoder läuft – wichtig, da der Audio-DMA-Puffer innerhalb von 2 ms neu gefüllt sein muss, um eine Aussetzer zu vermeiden.

Käufer-Tipp: Wenn Sie ein Datenblatt zu einem Lesestift sehen, das nur 4 oder weniger Prioritäten auflistet: Finger weg. Echte Lesestifte benötigen mindestens 6.

4. Zephyr-Scheduler auf K7 und KF1

Zephyr verwendet einen Multi-Queue-Bitmap-Scheduler mit optionaler Deadline-Scheduling-Funktion. Tasks haben eine Priorität von -16 (niedrigste) bis 15 (höchste). Auf K7-Firmware 1.9.5 und KF1-Firmware 1.9.5 gilt unsere Prioritätentabelle:

Priorität Thread Zweck
15 audio_stream_isr Audio-DMA abgeschlossen
14 oid_decode OID-Decode
13 audio_player MP3-Decode
12 ble_gatt BLE-GATT-Server
11 ble_adv BLE-Advertising
10 button_handler Tasten + Long-Press
9 battery_monitor Batterieabfrage
8 led_pattern LED-Animation
7 sensor_calib Sensor-Kalibrierungs-Drift
6 fs_commit Dateisystem-Commit
5 ota_staging OTA-Staging
4 shell Debug-Shell
3 sys_workq System-Work-Queue
2 idle Tickless Idle

Der Tickless Idle von Zephyr auf K7 senkt die Stromaufnahme im Leerlauf von 4,8 mA auf 1,6 mA. Das sind die 3,2 mA Differenz, die dem K7 seine 6,0 h Akkulaufzeit mit der 800-mAh-Li-Ion-14500-Zelle verleiht.

K7 verfügt außerdem über einen Thread im Deadline-Modus (audio_player_deadline), der zum Einsatz kommt, wenn der OEM Audio-Playrouting im Sub-Millisekunden-Bereich benötigt. Wir aktivieren dies über das Firmware-Build-Flag CONFIG_DEADLINE=y, das auf KF1 standardmäßig gesetzt ist und auf K7 deaktiviert wird, um 32 KB Flash zu sparen.

5. AliOS-Things-Scheduler auf Q6 und Q8

AliOS Things 3.3 verwendet einen prioritätsbasierten, präemptiven Scheduler, der FreeRTOS sehr ähnlich ist. Er unterstützt bis zu 32 Prioritäten und verfügt über einen integrierten krhino-Kernel, den wir seit 2022 einsetzen. Die Prioritätstabelle für Q6/Q8 sieht wie folgt aus:

Priorität Task Zweck
7 (höchste) audio_isr Audio-DMA abgeschlossen
6 oid_decode OID-Decode
5 audio_player MP3-Decode + DAC
4 btn_event Button-Entprellung
3 ble_gatt BLE GATT
3 ble_adv BLE-Advertising
2 pwr_mgr Energieverwaltung
2 batt_poll Akkuzustand
1 led_pat LED-Animation
0 ota_recv OTA-Empfänger

Der AliOS-Scheduler hat einen etwas schnelleren Kontextwechsel als FreeRTOS auf Cortex-M4, da AliOS weniger Register im gesicherten Kontext verwendet. Unsere Messung ergibt 1,4 µs auf Q8 gegenüber 2,0 µs auf B2 – relevant für hochpriore Audio-Interrupts.

6. Linux-CFS-Scheduler auf F8, L5, T2, Y6

Linux verwendet den Completely Fair Scheduler (CFS) auf F8, L5, T2 und Y6. CFS kennt keine festen Prioritäten im RTOS-Sinn. Stattdessen bietet es:

  • Nice-Werte von -20 (höchste) bis 19 (niedrigste).
  • Echtzeitgruppe (SCHED_RR, SCHED_FIFO) mit Prioritäten 1–99.
  • cgroups zur Gruppierung von Tasks.
  • Deadline-Scheduling (SCHED_DEADLINE) für harte Echtzeit-Tasks.

Auf der L5-Firmware 4.2.0 lautet unsere Prioritätstabelle:

Linux-Priorität Prozess Beschreibung
SCHED_FIFO 90 audio-daemon Audio-Mixer + DAC
SCHED_FIFO 80 oid-decoder OID-Decode
SCHED_FIFO 70 wifi-supervisor Wi-Fi-Roaming
SCHED_FIFO 60 ble-gatt BLE GATT
SCHED_RR 50 button-handler Taste + Long-Press
SCHED_RR 40 battery-monitor Batteriemonitor
nice -10 led-pattern LED-Animation
nice -5 ui-thread UI-Render
nice 0 asr-engine On-Device-ASR
nice 5 logging-daemon Telemetrie
nice 10 cache-cleanup Cache-Bereinigung
nice 19 analytics Anonyme Analyse

Der Audio-Daemon läuft auf SCHED_FIFO 90, um zu garantieren, dass er alles außer Kernel-Tasks verdrängt. Der OID-Decoder läuft auf SCHED_FIFO 80, damit er die ASR-Engine verdrängen kann. Die ASR-Engine läuft auf nice 0, da sie durchsatzorientiert und nicht latenzorientiert ist.

Pre-emption latency, lower-priority → higher-priority (µs)

7. Prioritätsinversion: Die Falle

Prioritätsinversion tritt auf, wenn ein Task mit niedriger Priorität einen Mutex hält, den ein Task mit hoher Priorität benötigt. Der Task mit hoher Priorität wird blockiert und wartet auf den Task mit niedriger Priorität; währenddessen verdrängt ein Task mit mittlerer Priorität den Task mit niedriger Priorität. Der Task mit hoher Priorität bleibt blockiert, bis der Task mit mittlerer Priorität nachgibt.

Wir haben Prioritätsinversion im Feld einmal gesehen. Auf der Q8-Firmware 2.6.4 (dem Vorgänger von 3.3.1) wurde ein UI-Mutex von einem Logging-Task mit niedriger Priorität gehalten, während der Audio-Player ihn anzufordern versuchte; der Audio-Player stockte 12 ms lang – als Glitch hörbar.

Die Maßnahme, die wir auf jeder RTOS-SKU ausliefern, sind Prioritätsvererbungs-Mutex (auch Prioritäts-Ceiling-Mutex genannt):

  • FreeRTOS verwendet xSemaphoreCreateMutex() (das in neueren Versionen Prioritätsvererbung unterstützt).
  • Zephyr verfügt über k_mutex mit standardmäßig aktivierter Prioritätsvererbung.
  • AliOS verwendet krhino_mutex_create() mit dem Flag RHINO_MUTEX_PRIO_INHERIT.
  • Linux verwendet pthread_mutexattr_setprotocol(... PTHREAD_PRIO_INHERIT ...).

Der L5-Audiodämon nutzt POSIX-Mutexes mit Prioritätsvererbung rund um das ALSA-PCM-Handle. Der T2-Videodecoder verfährt ebenso rund um das VPU-Handle.

8. Tickless Idle und Energieeinsparung

Die größte Energieeinsparung, die ein Scheduler auf einer RTOS-SKU liefern kann, ist Tickless Idle. Wenn nichts zu tun ist, deaktiviert der Scheduler den SysTick-Interrupt und die CPU wechselt in einen energiesparenden Wartezustand. Wenn das nächste Ereignis eintritt (ein Timer-Ablauf, ein Interrupt), weckt der Scheduler die CPU und programmiert den SysTick neu.

Tickless-Idle-Einsparungen in unserem Line-up (gemessen bei 25 °C, 3,7 V):

SKU Ruhestrom mit Tick Ruhestrom tickless Einsparung
B1 6,4 mA 2,1 mA 67 %
B2 5,9 mA 2,1 mA 64 %
K7 8,2 mA 2,8 mA 66 %
KF1 8,0 mA 2,7 mA 66 %
P2 4,2 mA 1,4 mA 67 %
Q6 6,6 mA 2,4 mA 64 %
Q8 6,4 mA 2,4 mA 62 %

Linux-SKUs bieten kein Tickless Idle im RTOS-Sinn. Sie verfügen über cpuidle-Governor, die einen tieferen C-State wählen, wenn die Runqueue leer ist. F8 erreicht 14 mA im Leerlauf, L5 erreicht 18 mA, T2 erreicht 22 mA – immer noch 4–10× mehr als RTOS-Idle.

9. Lastabwurf und Überlastverhalten

Wenn die CPU eines Lesestarger überlastet ist – beispielsweise wenn der OID-Decoder 5 Seiten in 200 ms auslöst, weil der Nutzer durch ein Buch blättert – muss der Scheduler Arbeit verwerfen, um den Audiostream gesund zu halten. Unsere Lastabwurf-Strategie:

Bedingung Aktion
OID-Queue-Tiefe > 8 Älteste verwerfen, Zähler protokollieren
Audio-Puffer-Underrun droht OID-Task-Priorität kurzzeitig erhöhen
BLE-Stack-Queue-Tiefe > 16 Trennen, neu verbinden
Wi-Fi-TX-Queue-Tiefe > 32 Niederpriore Frames verwerfen
Linux loadavg > 4 ASR-Engine auf 50 % CPU drosseln
Akku < 8 % WLAN deaktivieren, LED dimmen, auf Mono-Audio umschalten

Der Trick mit der „kurzzeitig erhöhten OID-Task-Priorität" ist ein dynamischer Prioritätsboost, den wir im Audio-Player-Task implementieren. Wenn der Audio-Puffer zu mehr als 75 % leer ist, sendet der Audio-Task eine Benachrichtigung an den OID-Decoder, damit dieser seine Priorität für die nächsten 50 ms anhebt. Das verschafft im Worst Case 20–40 ms zusätzlichen Spielraum auf dem B2.

10. Scheduler-Inspektion und Debugging

Jede SKU stellt eine Scheduler-Inspektions-API über USB oder BLE bereit. Die API liefert:

typedef struct {
    uint32_t task_id;
    char     name[16];
    uint8_t  priority;
    uint32_t stack_high_watermark;
    uint32_t runtime_us;
    uint32_t cpu_pct;
} task_stats_t;

OEMS können diese API während der Werks-QA abfragen, um einen „Scheduler-Fingerabdruck" zu erfassen – einen Snapshot der CPU-Auslastung pro Task. Wir haben seit 2023 über 47.000 solcher Fingerabdrücke ausgeliefert. Der Fingerabdruck ist äußerst wertvoll für die Diagnose von Feldausfällen: Ein Stift, bei dem battery_monitor 28 % CPU statt der erwarteten 4 % verbraucht, hat irgendwo einen Polling-Bug.

Für Linux-SKUs stehen dieselben Daten über /proc/<pid>/stat und top -H zur Verfügung. Wir bündeln ein scheduler-diag-Tool in der L5-Firmware 4.2.0, das den Fingerabdruck in einer JSON-Datei erfasst und bei Bedarf per WLAN zurücksendet.

11. Den richtigen Scheduler für Ihren Lesestift auswählen

Wenn Sie als OEM einen Scheduler für eine neue Lesestift-SKU auswählen, gilt folgende Faustregel:

Kaufszenario Empfohlener Scheduler Vorgeschlagene SKU
Unter 5 $, einsprachig, nur Antippen FreeRTOS tick-basiert P2, B1
Mittelklasse, zweisprachig, BLE Zephyr mit Tickless K7, KF1
Mittelklasse mit benutzerdefinierter OID, BLE AliOS Things Q6, Q8
WLAN + ASR + 720p-Video Linux CFS mit SCHED_FIFO für Audio L5
Defence- oder Premium-Gehäuse, hartes Echtzeitverhalten Linux mit PREEMPT_RT-Patch T2
Premium K–12 mit Content-Streaming Linux CFS mit Deadline-Scheduling Y6

Käuferhinweis: Fragen Sie den OEM immer nach zwei Scheduler-Kennzahlen: Worst-Case-Preemption-Latenz von einer niedrigprioritären zu einer hochprioritären Task (µs) sowie den Ruhestrom bei aktiviertem Tickless-Modus (mA). Alles über 10 µs oder 4 mA im Ruhezustand ist für K–3-Lesestift-Anwendungen ein Warnsignal.

Weiterführende Lektüre

Angebot anfordern — schnelle Werksantwort erhalten

Frequently Asked Questions

Welchen Scheduler verwendet der Lese-Stift B2?
Die B2-Firmware 2.4.7 verwendet den tick-basierten präemptiven FreeRTOS-10.4-Scheduler mit Prioritäten 0–7. Der per DMA-ISR verzögerte Audio-Task läuft auf Priorität 7, der OID-Decoder auf Priorität 6 und der Audio-Player auf Priorität 5. Der Ruhestrom beträgt 2,1 mA bei 3,7 V mit aktiviertem Tickless-Idle.
Wie hoch ist die Präemptions-Latenz bei einem RTOS-Lese-Stift?
Bei FreeRTOS B2 messen wir 2,0 µs; bei Zephyr K7 messen wir 1,8 µs; bei AliOS Q8 messen wir 1,4 µs; bei Zephyr KF1 mit aktivierter Deadline-Scheduling messen wir 0,9 µs. Linux-CFS-SKUs (F8, L5, T2, Y6) messen 18–24 µs aufgrund des Scheduler-Ticks und der Runqueue-Logik.
Wie verhindern Sie Prioritätsinversion bei einem Lese-Stift?
Wir verwenden auf jeder RTOS-SKU Prioritätsvererbungs-Mutexe: xSemaphoreCreateMutex unter FreeRTOS, k_mutex unter Zephyr, krhino_mutex_create mit dem Priority-Inherit-Flag unter AliOS und pthread_mutexattr_setprotocol mit PTHREAD_PRIO_INHERIT unter Linux. Wir hatten seit 2023 einen Prioritätsinversions-Vorfall im Feld, der in der Q8-Firmware 3.3.1 behoben wurde.
Kann ein Lese-Stift RTOS- und Linux-Tasks gleichzeitig ausführen?
Nein. Ein Lese-Stift führt jeweils nur ein Betriebssystem aus. Die Linux-SKUs (F8, L5, T2, Y6) können eine RTOS als Gast unter Jailhouse oder als Xenomai-Thread hosten, aber wir liefern diese Konfiguration heute nicht in Produktion aus. Der Aufwand für Validierung und Zertifizierung ist hoch und der Nutzen gering.
Was passiert, wenn der Scheduler überlastet ist?
Unsere Load-Shedding-Richtlinie verwirft die älteste OID-Seite, wenn die Warteschlangentiefe 8 überschreitet, erhöht kurzzeitig die OID-Task-Priorität, wenn der Audio-Puffer zu mehr als 75 % leer ist, trennt BLE, wenn die Stack-Warteschlange 16 Frames überschreitet, verwirft Wi-Fi-Frames mit niedriger Priorität oberhalb von 32 Frames und drosselt die ASR-Engine auf 50 % CPU, wenn der Linux-loadavg 4,0 überschreitet.
Ihr Warenkorb
Ihre Erfahrung auf dieser Website wird durch das Akzeptieren von Cookies verbessert. Cookie-Richtlinie
Chat on WhatsApp