Sistemele de operare în timp real (RTOS) și aplicațiile aferente

By Lim Jia Zhi, Senior Embedded Software Engineer

Contributed By DigiKey's North American Editors

Ce este un RTOS

Un sistem de operare în timp real (RTOS) este un sistem de operare simplu, utilizat pentru simplificarea integrării multitaskingului și a sarcinilor în proiectele limitate din punct de vedere al resurselor și al timpului, care este, în mod normal, cazul sistemelor încorporate. În plus, termenul „în timp real” indică predictibilitatea/determinismul în timpul execuției, mai degrabă decât viteza brută, așadar se poate dovedi, de obicei, că, datorită determinismului său, un RTOS realizează cerințele dificile în timp real.

Conceptele cheie ale unui RTOS sunt:

Sarcina

Sarcinile (ar putea fi numite și procese/fire) sunt funcții independente care rulează în bucle infinite, fiecare fiind, de obicei, responsabilă pentru o singură funcție. Sarcinile rulează independent la timpul lor (izolare temporală) și în stiva lor de memorie (izolare spațială). Izolarea spațială între sarcini poate fi garantată prin utilizarea unei unități de protecție a memoriei hardware (MPU), care restricționează regiunea de memorie accesibilă și declanșează excepții de eroare la încălcarea accesului. În mod normal, perifericele interne sunt mapate în memorie, astfel încât un MPU poate fi utilizat și pentru restricționarea accesului la periferice.

Sarcinile pot avea diferite stări:

  • Blocată – sarcina este în așteptarea unui eveniment (de ex., expirare întârziere, disponibilitate date/resurse)
  • Pregătită – sarcina este gata să ruleze pe CPU, dar nu rulează deoarece CPU-ul este utilizat de o altă activitate
  • Rulare – sarcina este atribuită pentru rularea pe CPU

Planificator

Planificatoarele din RTOS controlează ce sarcini vor rula pe CPU și ce algoritmi de planificare diferiți sunt disponibili. În mod normal, acestea sunt:

  • Preventive – executarea sarcinii poate fi întreruptă dacă este pregătită o altă sarcină, cu prioritate mai mare
  • Cooperative – comutarea sarcinilor va avea loc numai dacă sarcina care rulează în prezent este generată automat

Planificarea preventivă le permite sarcinilor cu prioritate mai mare să întrerupă o sarcină cu prioritate mai mică pentru a respecta constrângerile în timp real, dar implică timpi suplimentari consumați pentru operațiile de comutare a contextului.

Comunicarea între sarcini (ITC)

În mod normal, mai multe sarcini vor trebui să facă schimb de informații sau evenimente între ele. Cea mai simplă modalitate de partajare se realizează prin citirea/scrierea directă a variabilelor globale partajate în RAM, dar acest lucru nu este de dorit, din cauza riscului de corupție a datelor cauzat de o condiție de rulare. O modalitate mai bună este citirea/scrierea variabilelor din fișierele statice accesabile prin funcțiile componentei de setare și componentei de obținere, condițiile de rulare putând fi evitate prin dezactivarea întreruperilor sau utilizarea unui obiect de excludere reciprocă (mutex) în cadrul funcției componentei de setare/componentei de obținere. Modul cel mai curat de transmitere a informațiilor între sarcini este utilizarea de obiecte RTOS sigure pentru fire, cum ar fi coada de mesaje.

Pe lângă partajarea informațiilor, obiectele RTOS sunt capabile să sincronizeze executarea sarcinilor, deoarece sarcinile pot fi blocate și puse în așteptare până când obiectele RTOS devin disponibile. Majoritatea RTOS au obiecte precum:

  • Coadă de mesaje
    • Coada primul sosit, primul servit (FIFO) pentru transmiterea datelor
    • Datele pot fi trimise prin copiere sau prin referință (indicator)
    • Se utilizează pentru transmiterea datelor între sarcini sau între întrerupere și sarcină
  • Semafor
    • Poate fi tratat ca un contor de referință pentru înregistrarea disponibilității unei anumite resurse
    • Poate fi un semafor binar sau de numărare
    • Se utilizează pentru protejarea utilizării resurselor sau pentru sincronizarea executării sarcinilor
  • Mutex
    • Similar semaforului binar, se utilizează, în general, pentru protejarea utilizării unei singure resurse (MUTual EXclusion – excludere mutuală)
    • Mutexul FreeRTOS vine cu un mecanism de moștenire prioritară pentru a evita problema inversării priorității (condiția în care o sarcină cu prioritate ridicată ajunge să aștepte executarea uneia cu prioritate mai mică).
  • Cutie poștală
    • Locație de stocare simplă pentru partajarea unei singure variabile
    • Poate fi considerată o coadă pentru un element unic
  • Grup de evenimente
    • Grup de condiții (disponibilitatea semaforului, coada, semnalizarea evenimentului etc.)
    • Sarcina poate fi blocată și poate aștepta îndeplinirea unei anumite condiții a combinației
    • Disponibil în Zephyr ca API de interogare, în FreeRTOS ca QueueSets

Ciclul sistemului

RTOS are nevoie de o bază de timp pentru a măsura timpul, în mod normal sub forma unei variabile de contor de cicluri ale sistemului, incrementată într-o întrerupere periodică a temporizatorului hardware. Cu ciclul sistemului, o aplicație poate menține și alte servicii în afara celor bazate pe timp (intervalul de executare a sarcinilor, expirarea așteptării, divizarea timpului) utilizând doar un singur cronometru hardware. Cu toate acestea, o rată mai mare de cicluri nu va face decât să crească rezoluția bazei de timp a RTOS, nu va produce funcționarea mai rapidă a software-ului.

De ce să utilizați RTOS

Organizare

Aplicațiile pot fi întotdeauna scrise într-un mod foarte simplu, însă, pe măsură ce complexitatea codului crește, existența unei structuri oarecare va ajuta la gestionarea diferitelor părți ale aplicației, păstrându-le separate. Mai mult, cu un mod structurat de dezvoltare și un limbaj de design familiar, un nou membru al echipei poate să înțeleagă mai repede codul și, astfel, să își înceapă contribuția mai repede. RFCOM Technologies a dezvoltat aplicații utilizând diferite microcontrolere, precum cel de la Texas InstrumentsHercules, cele de la RenesasRL78 și RX, precum și cel de la STMicroelectronicsSTM32 pe un RTOS diferit. Modelele de proiectare similare ne permit să dezvoltăm aplicații pe microcontrolere diferite și chiar pe un RTOS diferit.

Modularitate

Dezbină și cucerește. În urma separării funcțiilor în diferite sarcini, pot fi adăugate cu ușurință funcții noi fără ca alte funcții să fie afectate; cu condiția ca noua funcție să nu suprasolicite resursele partajate, cum ar fi CPU-ul și perifericele. Dezvoltarea fără RTOS va ave loc, în mod normal, într-o mare buclă infinită, din care vor face parte toate funcțiile. O modificare a oricărei funcții din buclă va avea impact asupra altor funcții, făcând dificile modificarea și întreținerea software-ului.

Stive de comunicare și drivere

Multe drivere sau stive suplimentare precum TCP/IP, USB, stivele BLE și bibliotecile grafice sunt dezvoltate/portate pentru/către RTOS-urile existente. Un dezvoltator de aplicații se poate concentra asupra unui nivel al aplicației software-ului, reducând în mod semnificativ timpul de introducere pe piață.

Sfaturi

Alocare statică

Utilizarea alocării statice a memoriei pentru obiectele RTOS înseamnă rezervarea stivei de memorie în RAM pentru fiecare obiect RTOS în timpul compilării. Un exemplu de funcție de alocare statică în freeRTOS este xTaskCreateStatic(). Aceasta garantează faptul că un obiect RTOS poate fi creat cu succes, eliminând complicațiile gestionării unei posibile alocări eșuate și făcând aplicația mai deterministă.

În ceea ce privește stabilirea dimensiunii stivei necesare pentru o sarcină, sarcina poate fi rulată cu o dimensiune mai mare (mai mult decât suficientă) a stivei, iar apoi utilizarea stivei poate fi verificată în timpul execuției pentru a se determina inscripționarea înaltă. Este disponibil și un instrument de analiză statică a stivei.

Nivelul de abstractizare a sistemului de operare (OSAL) și abstractizarea relevantă

La fel ca în cazul Nivelului de abstractizare hardware (HAL), utilizarea nivelului de abstractizare RTOS permite migrarea simplă a software-ului aplicației către alte RTOS. Funcțiile RTOS sunt destul de asemănătoare, astfel încât crearea OSAL nu ar trebui să fie prea complicată. De exemplu:

Utilizarea API-ului freeRTOS în mod direct:

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

Încadrarea API-ului RTOS în OSAL:

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

utilizarea nivelului de abstractizare pentru comunicarea inter-sarcini pentru a face codul mai lizibil și pentru a minimiza domeniul de aplicare al unui obiect RTOS:

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

În plus, abstractizarea îi mai permite unui programator să schimbe și obiectul RTOS utilizat în cadrul operației (de ex., din mutex în semaforul de numărare) dacă există mai multe module SPI disponibile. OSAL și alte niveluri de abstractizare ajută și la testarea software-ului, simplificând inserarea funcției simulate în timpul testării unitare.

Selecția intervalului ciclurilor

În mod ideal, o rată mai mică a ciclurilor este mai bună, datorită timpilor suplimentari mai scurți consumați pentru operațiile neproductive. Pentru a selecta o rată adecvată a ciclurilor, dezvoltatorul poate reduce lista constrângerilor de sincronizare ale modulelor dintr-o aplicație (intervalul de repetare, durata de expirare etc.). Dacă există unele module cu valori aberante care necesită un interval scurt, se poate lua în considerare o întrerupere temporizată dedicată pentru modulele cu valori aberante, mai degrabă decât creșterea ratei ciclurilor RTOS. Dacă funcția de înaltă frecvență este foarte scurtă (de ex., scriere pentru înregistrare în vederea aprinderii/stingerii unui led), aceasta poate fi realizată în cadrul unei rutine de serviciu pentru întreruperi (ISR), în caz contrar putându-se utiliza gestionarea întreruperilor amânate. Gestionarea întreruperilor amânate este o tehnică de calcul al întreruperilor amânate într-o sarcină RTOS. ISR va genera un eveniment doar prin obiectul RTOS, după care sarcina RTOS va fi deblocată de eveniment și va efectua calculul.

Suprimarea ciclurilor pentru aplicațiile de joasă putere

Modul de inactivitate fără cicluri dezactivează întreruperea ciclurilor atunci când sistemul rămâne inactiv pentru o perioadă mai lungă de timp. O modalitate semnificativă de reducere a consumului de energie pentru firmware-ul încorporat este setarea sistemului în modul de joasă putere pentru cât mai mult timp posibil. Modul de inactivitate fără cicluri este implementat prin dezactivarea întreruperii periodice a ciclurilor și apoi prin configurarea unui temporizator cu numărătoare inversă pentru întrerupere atunci când urmează să fie executată o sarcină blocată. Dacă nicio sarcină nu este în așteptarea unei expirări, întreruperea ciclurilor poate fi dezactivată pe termen nelimitat, până când apare o altă întrerupere (de ex., un buton apăsat). De exemplu, în cazul unui semnalizator de Energie redusă Bluetooth (BLE), MCU poate fi setat în mod de repaus profund în intervalul dedicat publicității. Așa cum se arată în Figura 1, semnalizatorul este setat în modul de repaus profund în cea mai mare parte a timpului, energia consumată de acesta fiind de zeci de µA.

Graficul consumului curent al unui semnalizator BLE (faceți clic pentru a mări imaginea)Figura 1: Consumul curent al unui semnalizator BLE (Sursă imagine: RFCOM)

Concluzie

Un RTOS oferă funcții precum planificatorul, sarcinile și obiectele RTOS de comunicare între sarcini, precum și stive de comunicare și drivere. Acesta le permite dezvoltatorilor să se concentreze asupra nivelului de aplicație al software-ului încorporat și să proiecteze simplu și rapid software-ul pentru multitasking. Cu toate acestea, la fel ca în cazul oricăror altor instrumente, acesta trebuie utilizat corect pentru a adăuga mai multă valoare. Pentru a crea software încorporat sigur, securizat și eficient, dezvoltatorii trebuie să știe când să utilizeze funcțiile RTOS și, de asemenea, cum să configureze 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.

About this author

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)

About this publisher

DigiKey's North American Editors