Doelgroep: Deze handleiding is geschreven voor firmware-engineers, RTOS-architecten en OEM-programmamanagers die moeten begrijpen hoe een leespen zijn audioplayer, OID-decoder, toetsenhandler, BLE-stack en OTA-agent plant — en hoe die planning de door de gebruiker waargenomen latentie, batterijlevensduur en veldservicetickets beïnvloedt. Er wordt aangenomen dat u weet wat een thread of taak is, maar u hoeft geen expert te zijn in een specifiek RTOS.
Elke leespen voert meer dan één taak tegelijk uit, zelfs de kleinste P2 met zijn 64 KB Flash. Op een typische T2 vindt u mogelijk 24–38 actieve taken: een OID-decodertaak, een audiomixertaak, een UI-taak, een Wi-Fi-supervisor-taak, een BLE GATT-servertask, een OTA-stagingtaak, een batterijmeter-taak, een stroombeheertaak en verschillende sensorpollingstaken. De planner bepaalt welke taak elke microseconde op de CPU draait.
Dit artikel loopt u door de vier plannerfamilies die worden gebruikt in onze 11 SKU's (B1, B2, F8, K7, KF1, L5, P2, Q6, Q8, T2, Y6) — FreeRTOS, Zephyr, AliOS Things en Linux CFS — en toont de prioriteitstoewijzing, pre-emptielatentie, prioriteitsomkering-oplossing en load-shedding-beleid die we op elk gebruiken.
1. Wat een leespenplanner eigenlijk doet
Een planner heeft drie taken:
- Kies welke taak op elke instant op de CPU draait.
- Handhaaf prioriteit — taken met hogere prioriteit preempten taken met lagere prioriteit.
- Beperk de latentie tussen een gebeurtenis (interrupt, signaal) en het ontwaken van de respons-taak.
Bij een leespen is de derde taak het belangrijkst. Een gebruiker tikt met de pen op een OID-punt, de OID-sensor triggert een DMA-complete interrupt, de OID-decodertaak moet binnen 1–4 ms ontwaken om de pagina te decoderen, en de audoplayertaak moet binnen 50 ms beginnen met streamen. Als de planner die latentie niet kan begrenzen, hoort de gebruiker een vertraging.
2. De vier plannerfamilies die wij leveren
| Planner | OS | SKU's die het gebruiken | Pre-emptiemodel | Tickrate |
|---|---|---|---|---|
| FreeRTOS tick-gebaseerd | FreeRTOS 10.4 | B1, B2, P2 | Prioriteitsgebaseerde preemptieve | 1 kHz |
| Zephyr tickless | Zephyr 3.4 LTS | K7, KF1 | Prioriteit + deadline | 100 Hz basislijn, tickless idle |
| AliOS Things | AliOS Things 3.3 | Q6, Q8 | Prioriteitsgebaseerde preemptieve | 1 kHz |
| Linux CFS | Linux 5.10 / 5.15 | F8, L5, T2, Y6 | Completely Fair Scheduler met RT-groep | 250 Hz / 1 kHz |
De tweederde RTOS, eenderde Linux verdeling weerspiegelt de bredere leespenmarkt. De plannerkeuze is downstream van de OS-keuze besproken in TC-097, maar het prioriteitsbeleid is downstream van de SKU's feature set.
3. FreeRTOS Planner op B1, B2, P2
FreeRTOS gebruikt een fixed-priority preemptieve planner met optionele time slicing. Elke taak heeft een prioriteit van 0 (laagste) tot configMAX_PRIORITIES - 1 (hoogste, typisch 32 of 56). De planner draait altijd de taak met de hoogste prioriteit die klaar is; bij gelijke prioriteit wordt gebroken op time slice.
Op B2 firmware 2.4.7 is onze prioriteitstabel:
| Prioriteit | Taak | Doel | Stack |
|---|---|---|---|
| 7 (hoogste) | audio_dma_isr |
DMA-complete handler (ISR-uitgesteld) | 256 bytes |
| 6 | oid_decode |
OID decodeer pagina | 1.024 bytes |
| 5 | audio_player |
MP3 decodeer + DAC-feed | 2.048 bytes |
| 4 | button_handler |
Knopdender + lang indrukken | 512 bytes |
| 3 | battery_monitor |
Batterijmeting pollen | 512 bytes |
| 2 | led_pattern |
RGB LED-animatie | 256 bytes |
| 1 | idle_hook |
Tickless idle-invoer | 128 bytes |
| 0 | ota_staging |
OTA ontvangen + schrijven | 1.024 bytes |
De ISR wordt uitgesteld naar een taak met hoge prioriteit via xQueueSendFromISR + taskNOTIFY zodat de audiostream nooit blokkeert op lange ISR-code. Prioriteit 7 betekent dat de audio DMA-handler vóór de OID-decoder draait voor de komende 200 µs — belangrijk omdat de audio DMA-buffer binnen 2 ms moet worden bijgevuld om een glitch te voorkomen.
Tip voor kopers: Als u ziet dat een leespen-datasheet 4 of minder prioriteiten vermeldt, loop dan weg. Echte leespennen hebben minimaal 6 prioriteiten nodig.
4. Zephyr Scheduler op K7 en KF1
Zephyr gebruikt een multi-queue bitmap scheduler met optionele deadline scheduling. Taken hebben een prioriteit van -16 (laagste) tot 15 (hoogste). Op K7 firmware 1.9.5 en KF1 firmware 1.9.5 is onze prioriteitstabel:
| Prioriteit | Thread | Doel |
|---|---|---|
| 15 | audio_stream_isr |
Audio DMA voltooid |
| 14 | oid_decode |
OID decoderen |
| 13 | audio_player |
MP3 decoderen |
| 12 | ble_gatt |
BLE GATT-server |
| 11 | ble_adv |
BLE-advertenties |
| 10 | button_handler |
Knoppen + lang indrukken |
| 9 | battery_monitor |
Batterij pollen |
| 8 | led_pattern |
LED-animatie |
| 7 | sensor_calib |
Sensorcalibratiedrift |
| 6 | fs_commit |
Bestandssysteem vastleggen |
| 5 | ota_staging |
OTA-staging |
| 4 | shell |
Debug-shell |
| 3 | sys_workq |
Systeemwerkrij |
| 2 | idle |
Tickless ruststand |
De tickless ruststand van Zephyr op K7 verlaagt het stroomverbruik van 4,8 mA naar 1,6 mA in ruststand. Dat is de delta van 3,2 mA die K7 zijn batterijduur van 6,0 uur geeft op de 800 mAh Li-ion 14500-cel.
K7 heeft ook een deadline-modus thread (audio_player_deadline) die wordt gebruikt wanneer de OEM sub-milliseconde audio-planning wenst. We activeren dit in de firmware-build-vlag CONFIG_DEADLINE=y, die standaard aan staat op KF1 en uit op K7 om 32 KB Flash te besparen.
5. AliOS Things Scheduler op Q6 en Q8
AliOS Things 3.3 gebruikt een prioriteitsgebaseerde pre-emptieve scheduler die sterk lijkt op FreeRTOS. Het ondersteunt tot 32 prioriteiten en heeft een ingebouwde krhino-kernel die we sinds 2022 gebruiken. De prioriteitstabel van Q6/Q8 ziet er als volgt uit:
| Prioriteit | Taak | Doel |
|---|---|---|
| 7 (hoogste) | audio_isr |
Audio DMA voltooid |
| 6 | oid_decode |
OID-decode |
| 5 | audio_player |
MP3-decode + DAC |
| 4 | btn_event |
Knop-ontdendering |
| 3 | ble_gatt |
BLE GATT |
| 3 | ble_adv |
BLE-advertising |
| 2 | pwr_mgr |
Energiebeheerder |
| 2 | batt_poll |
Batterijmeting |
| 1 | led_pat |
LED-animatie |
| 0 | ota_recv |
OTA-ontvanger |
De AliOS-scheduler heeft een iets snellere contextwisseling dan FreeRTOS op Cortex-M4 omdat AliOS minder registers gebruikt in de opgeslagen context. Onze meting is 1,4 µs op Q8 vs 2,0 µs op B2 — betekenisvol voor hoogprioritaire audio-interrupts.
6. Linux CFS Scheduler op F8, L5, T2, Y6
Linux gebruikt de Completely Fair Scheduler (CFS) op F8, L5, T2 en Y6. CFS heeft geen vaste prioriteiten in de RTOS-zin. In plaats daarvan heeft het:
- Nice-waarden van -20 (hoogste) tot 19 (laagste).
- Realtime-groep (
SCHED_RR,SCHED_FIFO) met prioriteiten 1-99. - cgroups voor het groeperen van taken.
- Deadline scheduling (
SCHED_DEADLINE) voor harde realtime-taken.
Op L5 firmware 4.2.0 is onze prioriteitstabel:
| Linux prioriteit | Proces | Beschrijving |
|---|---|---|
SCHED_FIFO 90 |
audio-daemon |
Audio mixer + DAC |
SCHED_FIFO 80 |
oid-decoder |
OID decodering |
SCHED_FIFO 70 |
wifi-supervisor |
Wi-Fi roaming |
SCHED_FIFO 60 |
ble-gatt |
BLE GATT |
SCHED_RR 50 |
button-handler |
Knop + lang indrukken |
SCHED_RR 40 |
battery-monitor |
Batterij-indicator |
nice -10 |
led-pattern |
LED-animatie |
nice -5 |
ui-thread |
UI-rendering |
nice 0 |
asr-engine |
On-device ASR |
nice 5 |
logging-daemon |
Telemetrie |
nice 10 |
cache-cleanup |
Cache-opschoning |
nice 19 |
analytics |
Anonieme analyses |
De audio-daemon draait op SCHED_FIFO 90 om te garanderen dat het alles verdringt behalve kernel-taken. De OID-decoder draait op SCHED_FIFO 80 zodat het de ASR-engine kan verdringen. De ASR-engine draait op nice 0 omdat het throughput-gericht is, niet latentie-gericht.
7. Prioriteitsomkering: De Val
Prioriteitsomkering is wat er gebeurt wanneer een taak met lage prioriteit een mutex vasthoudt die een taak met hoge prioriteit nodig heeft. De taak met hoge prioriteit blokkeert en wacht op de taak met lage prioriteit; ondertussen verdringt een taak met gemiddelde prioriteit de taak met lage prioriteit. De taak met hoge prioriteit blijft vastzitten tot de taak met gemiddelde prioriteit zijn beurt opgeeft.
We hebben prioriteitsomkering één keer in het veld gezien. Op Q8 firmware 2.6.4 (de voorganger van 3.3.1) werd een UI-mutex vastgehouden door een taak met lage prioriteit voor logboekregistratie terwijl de audio-speler probeerde deze te verkrijgen; de audio-speler stokte 12 ms — hoorbaar als een glitch.
De mitigatie die we op elke RTOS SKU leveren is mutexes met prioriteitsovererving (ook wel prioriteitsplafond-mutexes genoemd):
- FreeRTOS gebruikt
xSemaphoreCreateMutex()(wat prioriteitsovererving ondersteunt in recente versies). - Zephyr heeft
k_mutexmet prioriteitsovererving standaard ingeschakeld. - AliOS heeft
krhino_mutex_create()met deRHINO_MUTEX_PRIO_INHERITvlag. - Linux gebruikt
pthread_mutexattr_setprotocol(... PTHREAD_PRIO_INHERIT ...).
De L5 audio daemon gebruikt POSIX mutexen met prioriteitsovererving rond de ALSA PCM handle. De T2 video decoder doet hetzelfde rond de VPU handle.
8. Tickless Idle en Energiebesparing
De grootste energiebesparing die een scheduler kan leveren op een RTOS SKU is tickless idle. Als er niets te doen is, schakelt de scheduler de SysTick interrupt uit en gaat de CPU in een laagvermogen wacht. Wanneer het volgende evenement optreedt (een timer aflopen of interrupt), wordt de CPU gewekt en wordt de SysTick opnieuw geprogrammeerd.
Tickless idle besparingen op ons assortiment (gemeten bij 25 °C, 3,7 V):
| SKU | Ruststroom met tick | Ruststroom tickless | Besparing |
|---|---|---|---|
| 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 SKU's hebben geen tickless idle in de RTOS zin. Ze hebben cpuidle governors die een diepere C-state kiezen wanneer de runqueue leeg is. F8 bereikt 14 mA ruststroom, L5 bereikt 18 mA, T2 bereikt 22 mA — nog steeds 4–10× meer dan RTOS ruststroom.
9. Load Shedding en Overbelastingsgedrag
Wanneer de CPU van een leespen overbelast is — bijvoorbeeld, de OID decoder vuurt 5 pagina's in 200 ms omdat de gebruiker door een boek bladert — moet de scheduler werk laten vallen om de audio stream gezond te houden. Ons load-shedding beleid:
| Conditie | Actie |
|---|---|
| OID queue diepte > 8 | Oudste neerzetten, een teller loggen |
| Audio buffer underrun imminent | OID taak prioriteit tijdelijk verhogen |
| BLE stack queue diepte > 16 | Verbinden verbreken, opnieuw verbinden |
| Wi-Fi TX queue diepte > 32 | Lage prioriteit frames neerzetten |
| Linux loadavg > 4 | ASR-engine beperken tot 50% CPU |
| Batterij < 8% | Wi-Fi uitschakelen, LED dimmen, overschakelen naar mono-audio |
De "OID-taakprioriteit kort verhogen"-truc is een dynamische prioriteitsverhoging die we implementeren in de audiotasks. Wanneer de audiobuffer voor meer dan 75% leeg is, stuurt de audiotask een melding naar de OID-decoder om de prioriteit de volgende 50 ms te verhogen. Dit koopt 20–40 ms speelruimte op B2 in worstcasescenario's.
10. Schedulerinspectie en debugging
Elke SKU biedt een schedulerinspectie-API via USB of BLE. De API retourneert:
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;
OEM's kunnen deze API pollen tijdens factory QA om een "scheduler fingerprint" vast te leggen — een momentopname van CPU-gebruik per taak. We hebben sinds 2023 meer dan 47.000 van dergelijke fingerprints verzonden. De fingerprint is van onschatbare waarde voor het diagnosticeren van veldproblemen: een pen die battery_monitor laat zien die 28% CPU verbruikt in plaats van de verwachte 4% heeft ergens een polling-bug.
Voor Linux SKU's zijn dezelfde gegevens beschikbaar via [correctie: html-tag-telling]
/proc/<pid>/stat en top -H. We bundelen een scheduler-diag-tool in de L5-firmware 4.2.0 die de fingerprint vastlegt in een JSON-bestand en het op verzoek terugstuurt via Wi-Fi.
11. Hoe kiest u de juiste scheduler voor uw leespen
Als u een OEM bent die een scheduler selecteert voor een nieuwe leespens SKU, hier is de vuistregel:
| Aankoopscenario | Aanbevolen scheduler | Voorgestelde SKU |
|---|---|---|
| Onder $5, eentalig, alleen tikken | FreeRTOS tick-based | P2, B1 |
| Middenklasse tweetalig, BLE | Zephyr met tickless | K7, KF1 |
| Middenklasse met aangepaste OID, BLE | AliOS Things | Q6, Q8 |
| Wi-Fi + ASR + 720p video | Linux CFS met SCHED_FIFO voor audio |
L5 |
| Defensie of premium bouw, hard real-time | Linux met PREEMPT_RT-patch | T2 |
| Premium K–12 met contentstreaming | Linux CFS met deadline scheduling | Y6 |
Kooptip: Vraag de OEM altijd om twee scheduler-metrieken: worst-case preemptie-latentie van een taak met lage prioriteit naar een taak met hoge prioriteit (µs), en de idle-stroom met tickless modus ingeschakeld (mA). Alles boven 10 µs of 4 mA idle is een rode vlag voor K–3 leespen-use-cases.