ABONAMENTE VIDEO REDACȚIA
RO
EN
×
▼ LISTĂ EDIȚII ▼
Numărul 30
Abonament PDF

Utilizarea sistemelor de operare compatibile cu OSEK/VDX în sistemele embedded

Mircea Pătraș-Ciceu
C++ Developer
@Arobs
PROGRAMARE


Sistemele embedded au la bază microcontrolere care procesează datele primite ca intrare și execută acțiunile corespunzătoare conform rutinelor programate. Porturile I/O facilitează interfațarea cu lumea exterioară, iar rularea rutinelor/algoritmilor proiectului aplicației este efectuată de către unitatea CPU.

Proiectul software trebuie să conțină, pe lângă fișierele de configurație adaptate tipului de microcontroler folosit, un programator de activități (eng.: task scheduler), rutine pentru controlul unităților periferice (_driver-_e) și rutinele aplicației. Proiectul poate să mai conțină și servicii de comunicație, librării și altele. În continuare vom menționa două metode comune de programare a activităților: „super loop” și mașini de stare; apoi vom prezenta mai detaliat algoritmii de programare, utilizați în sistemele de operare OSEK/VDX și vom evidenția pe scurt avantajele și dezavantajele folosirii fiecăruia dintre ele.

Ne vom referi mai jos la OSEK/VDX în mod simplificat: OSEK.

Algoritmi de programare a activităților

Algoritmul de programare a activităților într-un proiect embedded reprezintă modalitatea în care se apelează funcțiile aplicației. Această secvență de apelare a activităților poate fi configurată în mod explicit (cum e cazul sistemelor de operare compatibile OSEK) sau poate fi o consecință directă a modului de implementare a aplicației (în cazul „super loop”). Prin configurarea explicită a secvenței de execuție a activităților înțelegem conectarea acestora la câte un eveniment și definirea clasei și priorității lor (OSEK).

Continuăm cu prezentarea metodelor de programare a activităților:

Super loop

E un mod simplist, dar „la îndemână” de a executa activitățile unei aplicații embedded. Funcționarea e simplă: într-o buclă WHILE(1) sunt verificate secvențial și periodic (cu o perioadă nedeterminată ce depinde mult de activitatea care rulează la un moment dat) toate condițiile de rulare a activităților. Atunci când o condiție este îndeplinită, activitatea corespunzătoare este executată. În acest timp celelalte activități sunt blocate și nu se verifică nici condițiile de executare a lor.

Pro: implementarea e simplă (dar și simplistă);

Contra: resursele CPU sunt folosite ineficient, activitățile sunt executate în mod necontrolat, mentenanța codului sursă e anevoioasă.

Mașini de stare

Folosind această metodă, aplicația este mai bine structurată decât în cazul „super loop”. Activitățile sunt executate în funcție de starea curentă a mașinii de stări. Activități de o complexitate mai mare pot fi implementate folosind mașini de stare imbricate.

Pro: pregătirea și mentenanța codului sursă este facilă;

Contra: resursele CPU nu sunt folosite într-un mod optim, algoritmul de programare a activităților este puternic integrat în aplicație astfel că el este practic creat de la zero de la o aplicație la alta.

Programatoarele de activități OSEK:

OSEK oferă un standard pentru proiectarea sistemelor embedded în domeniul automotive. Unele din ariile de acoperire OSEK sunt sistemele de operare folosite în aplicațiile embedded. Există două tipuri de sisteme de operare propuse de standardul OSEK: OSEK OS cu programatorul de activități condus de evenimente și OSEKtime OS cu programatorul de activități periodic. Configurarea sistemelor de operare OSEK se realizează cu fișiere .oil (ce includ definirea activităților și proprietăților acestora) și alte elemente specifice sistemelor de operare: rutine „hook”, „resurse”, alarme, evenimente, mesaje, moduri de rulare a aplicației, rutine pentru tratarea erorilor.

OSEK

Următoarele elemente sunt disponibile în OSEK OS: activități, evenimente, API-uri pentru controlul resurselor și al întreruperilor, alarme, mesaje. Activitățile sunt programate în funcție de prioritate, astfel încât o activitate va fi întreruptă dacă alta, cu prioritate mai mare, a primit semnalul de activare. După terminarea acestei activități, vechea activitate este reluată dacă are cea mai mare prioritate. O activitate poate fi lansată prin mai multe moduri: direct din altă activitate, la expirarea contorului unei alarme, dintr-o întrerupere configurată sau de către un mesaj. Activitățile extinse pot intra în modul de așteptare al unui eveniment, eliberând astfel resursele CPU și permițând rularea unei alte activități. La apariția evenimentului, activitatea care rulează este întreruptă și se reia execuția activității extinse (dacă prioritatea acesteia este mai mare). Resursele utilizate de activități pot fi și ele blocate, astfel încât alte activități ce necesită accesul la aceeași resursă să nu o poată întrerupe pe prima, chiar dacă are o prioritate mai mare.

Sistemul de operare poate rula în mai multe moduri de aplicație (definite static în fișierele .oil). Practic, fiecare mod diferit al aplicației are un set distinct de activități (ex.: modul normal, modul de diagnosticare, bootloader). Aplicația decide în timpul rulării când se trece de la un mod la altul.

Rutinele de tip „hook” pentru tratarea erorilor sunt rulate de sistemul de operare la apariția acestora. Aceste rutine pot fi adaptate aplicației.

Pașii utilizării OSEK OS

Primul pas este configurarea elementelor sistemului de operare (definite mai sus) în fișierele .oil. Editarea acestor fișiere se poate face manual sau utilizând unelte de configurare de nivel înalt specifice (dacă sunt disponibile). Fișierele .oil sunt apoi interpretate de generatorul de sistem care creează fișiere sursă. Aceste fișiere sursă, împreună cu restul modulelor aplicației formează proiectul software compilabil. Acest mecanism înlesnește procesul de portare a aplicațiilor pe mai multe sisteme de operare compatibile OSEK și pe mai multe tipuri de microcontrolere (suportate de OS).

Fig. 1 - Pașii dezvoltării / configurării aplicației

Rularea aplicației

În orice moment, programatorul de activități o rulează pe cea cu prioritatea mai mare dintre cele în starea „ready”. Dintre două activități cu aceeași prioritate, cea activată prima va fi reactivată întâi, după o întrerupere cauzată de o altă activitate mai importantă (principiul FIFO). Cealaltă activitate va fi activată după terminarea sau intrarea în așteptare a celei curente. Terminarea „benevolă” a unui task se face prin apelul programatorului de activități. În funcție de nevoile aplicației se pot activa mai multe moduri de programare a activităților care permit sau nu prezența activităților extinse și permit sau nu întreruperea lor. Activitățile care pot fi întrerupte sunt utile, de exemplu, atunci când, într-o aplicație, sunt activități atât cu timp mare cât și mic de execuție.

Activități

Cum am amintit și mai sus, există două tipuri de activități: simple și extinse. Cele extinse au în plus starea de așteptare a unui eveniment față de stările activităților comune: suspendată, pregătită de rulare și în execuție. La nivelul OS implementarea este semnificativ mai complexă atunci când sunt acceptate și task-uri extinse: necesitatea controlului unui stack suplimentar pentru fiecare activitate extinsă față de un stack unic pentru activitățile simple. Consumul de memorie este astfel crescut.

Activitățile mai au o proprietate: disponibilitatea de a fi întrerupte. Astfel, ele pot fi întrerupte sau cooperative (adică nu pot fi întrerupte).

Mecanisme de sincronizare

OSEK este un OS „condus” de evenimente ce oferă variate metode de sincronizare (obiecte și servicii). Fiecare obiect generează un eveniment specific transmițând o anumită informație:

Obiectul eveniment: orice activitate poate genera un „eveniment”. Totuși, doar activitățile extinse le pot consuma.

Alarma: este reprezentată de obiecte atașate unui contor (software sau hardware) care numără anumite evenimente (pot fi intervale de timp, apăsări de butoane, impulsuri de la un encoder etc.). Contorul este comparat cu valoarea predefinită în obiect la fiecare incrementare. La atingerea valorii dorite, alarma este activată și una din următoarele acțiuni este posibilă: activarea unei activități, activarea unui obiect „event”, execuția unei funcții callback.

Întreruperi hardware: OSEK oferă servicii de control al întreruperilor care au rolul (în general) de a sincroniza activitățile cu evenimentele hardware.

Fig. 2 - OSEK/VDX task state

Mecanisme de comunicație/mesaje. Mesajele pot fi vehiculate între activitățile din același procesor sau între activități din procesoare diferite. Mesajele sunt configurate static (la dezvoltarea proiectului) în fișierul *.oil: se configurează, printre altele, modul de transmitere a mesajului, sursa și destinația lui.

Pro: resursele CPU sunt folosite în mod optim, implementarea software a activităților este facilă;

Contra: configurarea OS este laborioasă.

OSEKtime

Resursele puse la dispoziție în aplicațiile embedded compatibile OSEKtime sunt: întreruperile și activitățile. OSEKtime programează activitățile în mod periodic conform configurației din tabela de programare. Programatorul de activități are capacitatea de a întrerupe activitatea curentă pentru a rula o alta, care este pregătită de rulare. După terminarea rulării acesteia, programatorul reia execuția celei întrerupte (dacă există una). Totuși, o activitate nu se poate întrerupe pe ea însăși, această condiție fiind considerată o anomalie. În acest caz programatorul de activități va rula o rutină specifică de tratare a erorii, configurabilă de către aplicație (ex.: repornirea SO sau chiar resetarea microcontroler-ului).

Pașii utilizării OSEKtime OS

La dezvoltarea proiectului, primul pas este configurarea uneia sau mai multor tabele de activități. Mai multe astfel de tabele permit rularea aplicației în mai multe moduri (ex.: inițializare, mod de funcționare normală etc.). În fiecare din aceste tabele, activitățile sunt configurate prin definirea „offset-ului”, perioadei de activare, timpului de monitorizare a execuției și adresa activității (un pointer la funcția care implementează activitatea).

Utilizatorul mai configurează și timpul de „tick” al sistemului de operare. Regula calculării acestuia este următoarea: valoarea lui trebuie să fie cel puțin egală cu cel mai mare divizor comun al perioadelor activităților configurate. Cu cât valoarea „tick-ului” este mai mare, cu atât sistemul de operare va aloca mai mult timp CPU pentru activități și mai puțin pentru rularea rutinei de programare a activităților.

Rulare aplicație

Sistemul de operare va începe executarea activităților din tabela implicită. În aplicație, utilizatorul poate cere schimbarea tabelei de activități folosind un serviciu OS dedicat. Schimbarea va avea loc efectiv doar la sfârșitul parcurgerii tabelei curente (când toate activitățile sunt oprite).

Stările activităților

Activitățile sunt activate la expirarea „timer”-ului asignat. Acest „timer” este reîncărcat, în momentul startului activității, cu perioada configurată în tabela de activități. Dacă activitatea curentă (A) se termină înainte de expirarea „timer-ului” altei activități (B), atunci starea ei trece din activă în inactivă. Dacă nu, atunci A este întreruptă și B devine activă și se execută. La terminarea activității B, se reia activitatea A de unde a fost întreruptă.

Notă: la fel se întâmplă și când „timer-ul” activității A expiră înainte de terminarea execuției lui B. Astfel observăm că nu este definit, implicit sau explicit, un mecanism de prioritizare a activităților.

Detecția erorilor

Timpul de execuție a activităților este comparat cu timpul de monitorizare predefinit în tabela de activități. La depășirea acestui timp, sistemul de operare va rula rutina corespunzătoare de tratare a erorii. Ulterior este inițiată procedura de oprire a OS și se va rula o nouă rutină utilizator pentru acțiuni specifice la oprirea sistemului de operare. După rularea acestei rutine OS va reporni.

Rutine de întrerupere

Utilizatorul configurează timpul minim de recurență a rutinelor de întrerupere pe lângă implementarea efectivă a acestora. După activarea unei întreruperi, aceasta va fi dezactivată până expiră timpul minim de recurență. Astfel se asigură un timp procesor minim pentru rularea activităților chiar în cazurile activărilor repetate și rapide a întreruperilor.

Activitatea „idle”

Prima activitate rulată de OS este cea „idle”, al cărei conținut este definit de utilizator. Activitatea „idle” rulează doar atunci când toate celelalte sunt inactive. Astfel, ea este întreruptă de oricare din celelalte activități. O metodă de utilizare a activității „idle” este de a apela instrucțiunea de trecere a microcontroler-ului în modul „sleep” astfel încât, atunci când nicio activitate periodică nu rulează, procesorul să consume mai puțin curent.

Pro: resursele CPU sunt folosite într-un mod optim și se asigură un comportament previzibil al aplicației în toate situațiile;

Contra: utilizatorul trebuie să țină cont de limitările acestui tip de programator de activități când implementează funcțiile aplicației: suma funcțiilor din orice activitate trebuie să determine un timp de execuție mai mic decât timpul de monitorizare. Metoda de implementare a activităților este constrânsă de faptul că acestea se execută periodic.

COM

OSEK oferă specificații standardizate și pentru serviciile de comunicație. Mesajele configurate pot fi vehiculate între activități din același CPU sau din microcontroler-e diferite.

REFERINȚE

http://www.osek-vdx.org/

Conferință

Sponsori

  • ntt data
  • 3PillarGlobal
  • Betfair
  • Telenav
  • Accenture
  • Siemens
  • Bosch
  • FlowTraders
  • MHP
  • Connatix
  • UIPatj
  • MetroSystems
  • Globant
  • Colors in projects