Realtidsoperativsystemer (RTOS) og deres applikationer

Af Lim Jia Zhi, Senior Embedded Software Engineer

Bidraget af DigiKeys nordamerikanske redaktører

Hvad er RTOS

Et realtidsoperativsystem (RTOS) er et letvægts OS, der bruges til at lette multitasking og opgaveintegration i ressource- og tidsbegrænsede designs, hvilket normalt er tilfældet i embedded systemer. Desuden indikerer udtrykket "realtid" forudsigelighed/determinisme i udførselstid snarere end rå hastighed, og derfor kan et RTOS normalt bevises at tilfredsstille strenge realtidskrav på grund af dens determinisme.

Nøglekoncepter i RTOS er:

Opgave

Opgaver (kan også kaldes processer/tråde) er uafhængige funktioner, der kører i uendelige løkker, som normalt, hver er ansvarlige for en funktion. Opgaver kører uafhængigt i deres egen tid (tidsmæssig isolation) og hukommelsesstak (memory isolation). Isolering mellem opgaver kan garanteres ved brug af en MPU (Hardware Memory Protection), som beskytter tilgængelig hukommelse og udløser en fejl-exception hvis flere opgaver forsøger at tilgå den samme hukommelse på samme tid. Normalt mappes interne perifere enheder, så en MPU også kan bruges til at begrænse adgangen til perifert udstyr.

Opgaver kan være i forskellige tilstande:

  • Blokeret - opgaven venter på et event (f.eks. forsinket timeout, tilgængelighed af data/ressourcer)
  • Klar - opgaven er klar til at køre på CPU,'en men kører ikke, fordi CPU'en bruges af en anden opgave
  • Kører - opgaven køre på CPU'en

Scdulering

Schedulering i RTOS styrer, hvilken opgave der skal køres på CPU'en og har forskellige schduleringssalgoritmer tilrådighed. Normalt er de:

  • Preemptiv - udførelse af opgaven kan afbrydes, hvis en anden opgave med højere prioritet er klar
  • Kooperativ - opgaveskift finder kun sted, hvis den aktuelle kørende opgave tillader det

Preemptiv schedulering gør det muligt for opgaver med højere prioritet at afbryde en opgave med lavere prioritet for at opfylde realtidskrav, men det koster yderligere ressourcer at foretage kontekstskift.

ITC (Inter task kommunikation)

Flere opgaver skal normalt dele data eller events med hinanden. Den enkleste måde at dele data på er ved at direkte læse/skrive delte globale variabler i RAM, men dette er uønsket på grund af risikoen for datakorruption forårsaget af en race-tilstand (opdatering fra flere opgaver på samme tid). En bedre måde er at læse/skrive til statiske variabler med setter- og getter-funktioner, hvorved race-tilstande kan forhindres ved at deaktivere interrupts eller bruge et gensidigt ekskluderingsobjekt (mutex) i setter/getter-funktionen. Den renere måde er at bruge trådsikre RTOS-objekter som meddelelseskø til at videregive data mellem opgaver.

Udover deling af data er RTOS-objekter også i stand til at synkronisere udførelse af opgaver, da opgaver kan blokeres for at vente på tilgængelighed af andre RTOS-objekter. De fleste RTOS har objekter som:

  • Meddelelseskø
    • FIFO (First-in-first-out) kø for at videregive data
    • Data kan sendes som kopi eller ved henvisning (pointer)
    • Bruges til at sende data mellem opgaver eller mellem afbrydelse (interrupts) og opgave
  • Semafor
    • Kan behandles som en referencetæller til registrering af tilgængelighed af en bestemt ressource
    • Kan være en binær- eller tællesemafor
    • Bruges til at beskytte ressourceforbruget eller synkronisere udførelse af en opgave
  • Mutex
    • Svarende til binær semafor, der generelt bruges til at beskytte brugen af en enkelt ressource (MUTual EXClusion)
    • FreeRTOS mutex leveres med en prioriteret mekanisme til arv for at undgå prioritetsinversion (tilstand, når opgave med høj prioritet ender med at vente på opgave med lavere prioritet).
  • Postkasse
    • Enkel lagerplacering til deling af en enkelt variabel
    • Kan betragtes som en enkelt elementkø
  • Eventgruppe
    • Gruppe af betingelser (tilgængelighed af semafor, kø, event-flag osv.)
    • Opgaven kan blokeres og kan vente på, at en bestemt kombination af betingelser er opfyldt
    • Tilgængelig i Zephyr som Polling API, i FreeRTOS som QueueSets

System-tick

RTOS har brug for en tidsbase til at måle tid, normalt i form af en system-tick-tællervariabel, der er inkrementeres vha. et periodisk hardware-timer-interrupt. Med system-tick kan en applikation opretholde flere tidsbaserede tjenester (interval for opgaveudførelse, ventetid, tidsopdeling) vha. en enkelt hardware-timer. En højere tick-frekvens vil dog kun øge opløsningen af RTOS-tidsbasen men det får ikke softwaren til at køre hurtigere.

Hvorfor bruge RTOS

Organisation

Applikationer kan altid skrives på den rå måde, men efterhånden som kodens kompleksitet øges, vil en eller anden form for struktur hjælpe med at administrere forskellige dele af applikationen og holde dem adskilt. Desuden, med en struktureret måde at udvikle på og ved at benytte et velkendt designsprog, kan et nyt teammedlem forstå koden og begynde at bidrage hurtigere. RFCOM Technologies har udviklet applikationer vha. forskellige mikrocontrollere som f.eks Texas Instruments' Hercules, Renesas' RL78 og RX samt STMicroelectronics'STM32 på en anden RTOS. Lignende designmønstre giver os mulighed for at udvikle applikationer på forskellige mikrocontrollere og endda en anden RTOS.

Modularitet

Divide and conquer. Ved at adskille funktioner i forskellige opgaver kan nye funktioner let tilføjes uden at forstyrre andre funktioner; forudsat at den nye funktion ikke overbelaster delte ressourcer som CPU og perifert udstyr. Udvikling uden RTOS vil normalt være i en stor uendelig løkke, hvor alle funktioner er en del af løkken. En ændring af en hvilken som helst funktion inden for løkken vil have indflydelse på andre funktioner, hvilket gør softwaren svær at ændre og vedligeholde.

Kommunikationsstakke og drivere

Mange ekstra drivere eller stakke som TCP/IP, USB, BLE-stakke og grafikbiblioteker er udviklet/konverteret fra/til eksisterende RTOS'er. En applikationsudvikler kan derved fokusere på et applikationslag af softwaren og reducere time-to-market betydeligt.

Tips

Statisk fordeling

Brug af statisk allokering af hukommelse til RTOS-objekter betyder at reservere hukommelsesstak i RAM til hvert RTOS-objekt under kompileringstiden. Et eksempel på en statisk allokeringsfunktion i freeRTOS er xTaskCreateStatic(). Dette sikrer, at et RTOS-objekt kan oprettes med succes, hvilket sparer besværet med at håndtere en mulig mislykket allokering og gøre applikationen mere deterministisk.

Med hensyn til at beslutte stakstørrelse, der er nødvendig for en opgave, kan opgaven køres med en større stakstørrelse end nødvendig, og derefter kan stakforbruget kontrolleres under kørsel for at bestemme den maksimale stakbehov. Der er også et statisk stakanalyseværktøj tilgængeligt.

Operativsystemets abstraktionslag (OSAL) og meningsfuld abstraktion

Hardware Abstraction Layer (HAL) gør anvendelse af RTOS-abstraktionslaget som gør det muligt at applikationssoftware let kan migreres til andre RTOS'er. Funktionerne i RTOS'er er ret ens, så oprettelse af OSAL bør ikke være kompliceret. For eksempel:

Brug af freeRTOS API direkte:

if( xSemaphoreTake( spiMutex, ( TickType_t ) 10 ) == pdTRUE ) { //dosomething }

Indpakning af RTOS API i OSAL:

if( osalSemTake( spiMutex, 10 ) == true) { //dosomething }

vha. abstraktionslaget på inter-task kommunikation for at gøre koden mere læsbar og minimere antallet af et RTOS-objekter:

if( isSpiReadyWithinMs( 10 ) ) { //doSomething }

Derudover gør abstraktion det muligt for en programmør at ændre det anvendte RTOS-objekt (f.eks. Fra mutex til at tælle semafor), hvis der er mere end et SPI-modul til rådighed. OSAL og andre abstraktionslag hjælper også med softwaretest ved at forenkle indsættelse af mock-funktion under enhedstest.

Valg af tick-interval

Ideelt set er en lavere tick-frekvens bedre på grund af mindre overhead. For at vælge en passende tick-frekvens kan udvikleren angive tidsbegrænsninger for moduler i en applikation (gentagelsesinterval, varighed af timeout osv.). Hvis der er specielle moduler, der har brug for et lille interval, kan det overvejes at have et dedikeret timer-interrupt for disse specielle moduler i stedet for at øge RTOS-tickfrekvenen. Hvis højfrekvensfunktionen er meget kort (f.eks. skrivning til registre for at tænde/slukke for en LED), kan dette gøres inde i en ISR (Interrupt Service Routine); alternativt kan der anvendes udskudt interrupt-håndtering. Udskudt interrupt-håndtering er en teknik til udskydelse af interrupt-beregning til en RTOS-opgave ved at ISR genererer et event igennem RTOS-objektet, hvorefter RTOS-opgaven bliver frigives fra eventet og udfører beregningen.

Tick-undertrykkelse ved applikationer med lavt strømforbrug

Opdaterings-inaktivitet (tickless idle) deaktiverer tick-interrupts, når systemet bliver inaktiv i længere tid. En væsentlig måde for embeddede firmware at reducere strømforbruget på er at sætte systemet i lav strømtilstand så længe som muligt. Tickless idle implementeres ved deaktivering af periodiske tick-interrupt og derefter indstille en nedtællingstimer til at afbryde, når en blokeret opgave skal udføres. Hvis der ikke er nogen opgave, der venter på et timeout, kan tick-interruptet deaktiveres på ubestemt tid, indtil der opstår et andet interrupt (f.eks. Tryk på en knap). For eksempel i tilfælde af et BLE (Bluetooth Low Energy)-beacon kan en MCU sættes i dyb dvale (deep sleep) mellem beacon broadcasts. Som vist i figur 1 sættes BLE'en i dyb dvaletilstand det meste af tiden og forbruger meget lidt strøm (µA størrelse).

Graf over det strømforbrug af et BLE-beacon (klik for at forstørre)Figur 1: Strømforbrug af et BLE-beacon (billedkilde: RFCOM)

Konklusion

En RTOS indeholder funktioner som schedulerer opgaver og inter-task kommunikation mellem RTOS-objekter samt kommunikationsstakke og drivere. Det giver udviklere mulighed for at fokusere på applikationslaget i den embeddede software og designe multitasking-software med lethed og hastighed. Men ligesom alle andre værktøjer skal det bruges korrekt for at få mest mulig værdi. For at skabe sikker og effektiv embedded software skal udviklere vide, hvornår de skal bruge RTOS-funktioner og hvordan man konfigurerer RTOS'en.

DigiKey logo

Disclaimer: The opinions, beliefs, and viewpoints expressed by the various authors and/or forum participants on this website do not necessarily reflect the opinions, beliefs, and viewpoints of DigiKey or official policies of DigiKey.

Om denne forfatter

Image of Lim Jia Zhi

Lim Jia Zhi, Senior Embedded Software Engineer

Lim Jia Zhi is an embedded software engineer, holds a degree in Electrical and Electronics Engineering. He has developed software for devices in IoT solution covering edge gateway and battery-powered edge devices, and also involved in developing safety-critical embedded software. Actively learning ways to design efficient and reliable embedded system, like using design pattern and tools, and having software development lifecycle. (jia.zhi.lim@rfcom-tech.com (+65) 6635 4217)

Om udgiveren

DigiKeys nordamerikanske redaktører