Realtidsoperativsystem (RTOS) och deras tillämpningar

Av Lim Jia Zhi, Senior Embedded Software Engineer

Bidraget med av DigiKeys nordamerikanska redaktörer

Vad är RTOS

Ett realtidsoperativsystem (RTOS) är ett lättvikts-OS som används för att underlätta multitasking och uppgiftsintegrering i resurs- och tidsbegränsade konstruktioner, vilket normalt är fallet i inbäddade system. Dessutom indikerar termen "realtid" förutsägbarhet/determinism i exekveringstid snarare än rå hastighet, så ett RTOS kan vanligtvis bevisas uppfylla hårda realtidskrav till följd av sin determinism.

Nyckelbegrepp för RTOS är:

Uppgift

Uppgifter (kan även kallas processer/trådar) är oberoende funktioner som körs i oändliga slingor, där var och en vanligen är ansvarig för en funktion. Uppgifterna körs oberoende i sin egen tid (tidsmässig isolering) och minnesstack (rumslig isolering). Rumslig isolering mellan uppgifter kan säkerställas med hjälp av en MPU (Hardware Memory Protection Unit), som begränsar tillgängligt minnesområde och utlöser felundantag vid brott mot åtkomstreglerna. Normalt är interna kringkretsar minnesmappade, så en MPU kan också användas för att begränsa åtkomsten till kringkretsar.

Uppgifterna kan befinna sig i olika tillstånd:

  • Blockerad - uppgiften väntar på en händelse (t.ex. tidsfördröjning, tillgänglighet av data/resurser)
  • Redo - uppgiften är redo att köras på processorn men körs inte eftersom processorn används av en annan uppgift
  • Körs - uppgiften är tilldelad för körning på processorn

Schemaläggare

Schemaläggare i RTOS styr vilken uppgift som ska köras på processorn och olika schemaläggningsalgoritmer finns tillgängliga. Normalt är de:

  • Förebyggande - uppgiften kan avbrytas om en annan uppgift med högre prioritet är redo
  • Kooperativ - uppgiftsbyte kommer bara ske om den för närvarande aktiva uppgiften själv lämnar företräde

Förebyggande schemaläggning tillåter högre prioriterade uppgifter att avbryta en lägre uppgift för att uppfylla realtidsbegränsningar, men det resulterar i förbrukning av overheadresurser vid kontextväxling.

Kommunikation mellan uppgifter (ITC)

Flera uppgifter behöver normalt dela information eller händelser med varandra. Det enklaste sättet att dela är att direkt läsa/skriva till delade globala variabler i RAM, men detta är inte önskvärt på grund av risken för dataskada som orsakas av ett s.k. race condition. Ett bättre sätt är att läsa/skriva filgemensamma statiska variabler som är tillgängliga med setter- och getterfunktioner, och race conditions kan förhindras genom att inaktivera interrupt eller använda ett ömsesidigt uteslutningsobjekt (mutex) inuti setter/getter-funktionen. Det renaste sättet är att använda trådsäkra RTOS-objekt som en meddelandekö för att skicka information mellan uppgifter.

Förutom att dela information kan RTOS-objekt också synkronisera uppgiftsexekveringen, eftersom uppgifter kan blockeras för att vänta på att RTOS-objekt är tillgängliga. De flesta RTOS har objekt som:

  • Meddelandekö
    • First-in-first-out-kö (FIFO) för att skicka data
    • Data kan skickas med kopia eller genom referens (pekare)
    • Används för att skicka data mellan uppgifter eller mellan interrupt och uppgift
  • Semafor
    • Kan behandlas som en referensräknare för att registrera tillgängligheten för en specifik resurs
    • Kan vara en binär eller räknande semafor
    • Används för att skydda resursanvändningen eller synkronisera uppgiften
  • Mutex
    • Liknar binär semafor, och används vanligtvis för att skydda användningen av en viss resurs (MUTual EXClusion)
    • FreeRTOS mutex har en prioriterad arvsmekanism för att undvika prioritetsinversion (villkor när uppgift med hög prioritet slutar vänta på uppgift med lägre prioritet).
  • Brevlåda
    • Enkel lagringsplats för att dela en specifik variabel
    • Kan betraktas som en specifik elementkö
  • Händelsegrupp
    • Grupp av villkor (tillgänglighet av semafor, kö, händelseflagga etc.)
    • Uppgiften kan blockeras och kan vänta tills ett specifikt kombinationsvillkor uppfylls
    • Finns i Zephyr som API för pollning, i FreeRTOS som QueueSets

System Tick

RTOS behöver en tidsbas för att mäta tid, normalt i form av en systemtidräknarvariabel som inkrementeras med ett periodiskt hårdvaruinterrupt. Med systemtidräkningen kan en applikation köra mer än tidsbaserade tjänster (uppgiftsexekveringsintervall, väntetid, tidsuppdelning) med bara en hårdvarutimer. En högre räkningshastighet kommer dock bara att öka upplösningen på RTOS-tidsbasen; det gör inte att programvaran går snabbare.

Varför använda RTOS

Organisering

Applikationer kan alltid skrivas direkt mot maskinvaran, men när kodkomplexiteten ökar, underlättar det att ha någon form av struktur för att hantera olika delar av applikationen och hålla dem åtskilda. Dessutom kan en ny teammedlem förstå koden och börja bidra snabbare om det fins ett strukturerat sätt att utveckla och ett välbekant utvecklingsspråk. RFCOM Technologies har utvecklat applikationer med olika microcontrollers somTexas Instruments Hercules, Renesas RL78 och RX och STMicroelectronics STM32 på ett annat RTOS. Liknande utvecklingsmönster gör det möjlig att utveckla applikationer på olika microcontrollers och till och med ett annat RTOS.

Modularitet

Söndra och härska. Genom att separera funktioner i olika uppgifter kan nya funktioner enkelt läggas till utan att andra funktioner störs, förutsatt att den nya funktionen inte överbelastar gemensamma resurser som processor och kringkretsar. Utveckling utan RTOS kommer normalt resultera i en stor oändlig slinga där alla funktioner utgör en del av slingan. En ändring av någon funktion i slingan kommer att påverka andra funktioner, vilket gör programvaran svår att modifiera och underhålla.

Kommunikationsstackar och drivrutiner

Många extra drivrutiner eller stackar som TCP/IP, USB, BLE-stackar och grafikbibliotek är utvecklade/portade för/till befintliga RTOS. En applikationsutvecklare kan fokusera på ett applikationslager av programvaran och avsevärt minska tiden till marknad.

Tips

Statisk tilldelning

Användning av statisk allokering av minne för RTOS-objekt betyder att man reserverar plats i minnesstacken i RAM för varje RTOS-objekt under kompileringen. Ett exempel på en statisk allokeringsfunktion i freeRTOS är xTaskCreateStatic (). Detta säkerställer att ett RTOS-objekt kan skapas, vilket undviker besvär med att hantera en eventuell misslyckad allokering och gör tillämpningen mer deterministisk.

När det gäller att bestämma vilken stackstorlek som behövs för en uppgift kan uppgiften köras med en större (mer än tillräcklig) stackstorlek och sedan kan stackanvändningen kontrolleras under körtiden för att avgöra hur stor högbelastningen blir. Det finns också ett analysverktyg för statiska stackar.

Operativsystemets abstraktionsskikt (OSAL) och meningsfull abstraktion

Precis som för ett HAL (Hardware Abstraction Layer), möjliggör användning av RTOS-abstraktionsskiktet enkel migrering av applikationsprogramvara till andra RTOS. Funktionerna i RTOS är tämligen liknande, så att skapa ett OSAL bör inte vara för komplicerat. Exempelvis:

Använda freeRTOS API direkt:

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

Packa in RTOS API i OSAL:

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

genom att använda abstraktionslagret på kommunikationen mellan uppgifter för att göra koden mer läsbar och minimera omfattningen av ett RTOS-objekt:

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

Dessutom möjliggör abstraktionen också en programmerare att ändra det underliggande RTOS-objektet (t.ex. från mutex till att räknarsemafor) om det finns mer än en SPI-modul tillgänglig. OSAL och andra abstraktionsskikt hjälper också till med mjukvarutestning genom att förenkla införing av skenfunktioner under produkttestning.

Val av räknarintervall

Idealiskt ska räknarhastigheten vara lägre till följd av pga. en lägre förbrukning av overheadresurser. För att välja en lämplig räknarhastighet, kan utvecklaren lista tidsbegränsningar för moduler i en applikation (upprepningsintervall, tidsgräns, etc.). Om det finns några ytterlighetsmoduler som behöver ett litet intervall, kan ett dedikerat timerinterrupt övervägas för ytterlighetsmoduler snarare än att öka RTOS:ets räknarhastighet. Om högfrekvensfunktionen är mycket kort (t.ex. skrivning till register för att slå på/stänga av en lysdiod) kan den göras inuti en Interrupt Service Routine (ISR), annars kan uppskjuten interrupthantering användas. Uppskjuten interrupt-hantering är en teknik för att hänskjuta en interruptberäkning till en RTOS-uppgift; ISR:n genererar bara en händelse genom RTOS-objektet, sedan avblockeras RTOS-uppgiften av händelsen och gör beräkningen.

Räkningspausering för strömsnåla applikationer

Räknarlös tomgång inaktiverar räkneinterrupt när systemet går på tomgång under en längre tid. Ett viktigt sätt för inbyggd firmware att minska strömförbrukningen är att sätta systemet i lågeffektläge så länge som möjligt. Räknarlös tomgång implementeras genom att inaktivera det periodiska räknarinterruptet och sedan ställa in en nedräkningstimer till att göra ett interrupt när en blockerad uppgift ska utföras. Om det inte finns någon uppgift som väntar på en timeout, kan räknarinterruptet inaktiveras på obestämd tid tills ett nytt räknarinterruptet inträffar (t.ex. att knappen trycks ned). I fallet med exempelvis Bluetooth Low Energy (BLE) kan microcontrollern sättas i djupsömn mellan självannonseringsintervallen. Som visas i figur 1 sätts fyren i djupsömn under merparten av tiden och förbrukar effekt i storleksordningen tiotals µA.

Diagram över aktuell förbrukning av en BLE-fyr (klicka för att förstora)Figur 1: Strömförbrukning för en BLE-fyr (Bildkälla: RFCOM)

Slutsats

Ett RTOS erbjuder funktionsbegrepp som schemaläggare, uppgifter och RTOS-objekt för kommunikation mellan uppgifter, samt kommunikationsstackar och drivrutiner. Det gör det möjligt för utvecklare att fokusera på applikationslagret för den inbäddade programvaran och utveckla multitasking-programvara snabbt och med lätthet. Men precis som alla andra verktyg måste det användas på rätt sätt för att få ut mesta möjliga nytta. För att skapa säker och effektiv inbäddad programvara behöver utvecklare veta när de ska använda RTOS-funktioner och även hur man konfigurerar RTOS.

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 skribenten

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 utgivaren

DigiKeys nordamerikanska redaktörer