- Kako deluje RTOS?
- Pogosto uporabljeni izrazi v RTOS
- Namestitev knjižnice Arduino FreeRTOS
- Shema vezja
- Primer Arduino FreeRTOS - Ustvarjanje nalog FreeRTOS v Arduino IDE
- Izvajanje naloge FreeRTOS v Arduino IDE
OS, ki je prisoten v vgrajenih napravah, se imenuje RTOS (Real-Time Operacijski sistem). V vdelanih napravah so opravila v realnem času ključnega pomena, kjer ima čas zelo pomembno vlogo. Realnočasovne naloge so časovno deterministične, kar pomeni, da je odzivni čas na kateri koli dogodek vedno stalen, tako da lahko zagotovimo, da se bo določen dogodek zgodil ob določenem času. RTOS je zasnovan za izvajanje aplikacij z zelo natančnim časovnim razporedom in visoko stopnjo zanesljivosti. RTOS pomaga tudi pri večopravilnosti z enim jedrom.
Že smo zajeli vadnico o uporabi RTOS-a v vgrajenih sistemih, kjer lahko veste več o RTOS-u, o razliki med splošnimi operacijskimi sistemi in RTOS-om, različnih vrstah RTOS-a itd.
V tej vadnici bomo začeli z FreeRTOS. FreeRTOS je razred RTOS za vgrajene naprave, ki je dovolj majhen, da se lahko izvaja na 8/16-bitnih mikrokrmilnikih, čeprav njegova uporaba ni omejena na te mikrokrmilnike. Je popolnoma odprtokodna in koda je na voljo na githubu. Če poznamo nekaj osnovnih pojmov RTOS, je FreeRTOS zelo enostaven za uporabo, saj ima dobro dokumentirane API-je, ki jih je mogoče neposredno uporabiti v kodi, ne da bi poznal zadnji del kodiranja. Popolno dokumentacijo FreeRTOS najdete tukaj.
Kot FreeRTOS lahko deluje na 8-bitnem MCU, tako da se lahko izvaja tudi na plošči Arduino Uno. Prenesti moramo knjižnico FreeRTOS in nato začeti izvajati kodo z uporabo API-jev. Ta vadnica je namenjena popolnemu začetniku, spodaj so teme, ki jih bomo obravnavali v tej vadnici za Arduino FreeRTOS:
- Kako deluje RTOS
- Nekateri pogosto uporabljeni izrazi v RTOS
- Namestitev FreeRTOS v Arduino IDE
- Kako na primeru ustvariti naloge FreeRTOS
Kako deluje RTOS?
Preden začnemo z delom RTOS, poglejmo, kaj je naloga. Opravilo je del kode, ki ga je na CPU mogoče načrtovati za izvajanje. Torej, če želite izvesti neko nalogo, jo je treba razporediti z uporabo zakasnitve jedra ali z uporabo prekinitev. To delo opravi načrtovalec, ki je prisoten v jedru. V enojedrnem procesorju načrtovalnik pomaga opravilom, da se izvajajo v določenem časovnem rezu, vendar se zdi, da se različna opravila izvajajo hkrati. Vsaka naloga se izvaja glede na prednostno nalogo, ki ji je dana.
Zdaj pa poglejmo, kaj se zgodi v jedru RTOS, če želimo ustvariti nalogo za utripanje LED z enosekundnim intervalom in to nalogo dati na najvišjo prioriteto.
Poleg naloge LED bo še ena naloga, ki jo ustvari jedro, znana kot nedejavna naloga. Neaktivna naloga se ustvari, ko nobena naloga ni na voljo za izvajanje. Ta naloga se vedno izvaja z najnižjo prioriteto, tj. 0 prioriteto. Če analiziramo časovni graf, naveden zgoraj, je razvidno, da se izvajanje začne z LED-nalogo in deluje določen čas, nato pa preostali čas, medtem ko se nedejavna naloga izvaja, dokler ne pride do prekinitve s kljukico. Nato se jedro odloči, katero nalogo je treba izvesti glede na prioriteto naloge in skupni pretečeni čas naloge LED. Ko je 1 sekunda končana, jedro znova izbere vodeno nalogo za izvedbo, ker ima večjo prednost kot nedejavna naloga, lahko rečemo tudi, da naloga LED prevzame nedejavno nalogo. Če obstaja več kot dve nalogi z enako prednostjo, se bosta določen čas izvajala v krožnem načinu.
Pod diagramom stanja je prikazano preklapljanje nedelujoče naloge v delujoče stanje.
Vsako novo ustvarjeno opravilo gre v stanje pripravljenosti (del stanja, ki se ne izvaja). Če ima ustvarjena naloga (Task1) največjo prednost kot druge naloge, se bo preusmerila v stanje delovanja. Če to nalogo, ki se izvaja, prepreči druga naloga, se bo spet vrnila v stanje pripravljenosti. V nasprotnem primeru, če je task1 blokiran z API-jem za blokiranje, se CPU s to nalogo ne bo ukvarjal do časovne omejitve, ki jo določi uporabnik.
Če je Task1 onemogočen v delujočem stanju z uporabo API-jev za zaustavitev, bo Task1 prešel v stanje Suspended in razporejevalniku znova ni na voljo. Če nadaljujete z opravilom 1 v stanju mirovanja, se bo vrnil v stanje pripravljenosti, kot lahko vidite v blokovnem diagramu.
To je osnovna ideja, kako se opravila izvajajo in spreminjajo svoja stanja. V tej vadnici bomo v programu Arduino Uno izvedli dve nalogi z uporabo FreeRTOS API.
Pogosto uporabljeni izrazi v RTOS
1. Naloga: To je del kode, ki jo je na CPU mogoče načrtovati za izvajanje.
2. Načrtovalnik: odgovoren je za izbiro naloge s seznama pripravljenega stanja v stanje, ki se izvaja. Načrtovalci se pogosto uporabljajo, tako da zasedajo vse računalniške vire (kot pri uravnoteženju obremenitve).
3. Prednost: Gre za dejanje začasne prekinitve že izvršene naloge z namenom odstranitve iz stanja, ki je v teku, brez njenega sodelovanja.
4. Preklapljanje konteksta: pri prednostnem prednastavitvi načrtovalnik primerja prednost izvajanja nalog s prednostjo seznama pripravljenih opravil na vsaki prekinitvi systic . Če je na seznamu katera naloga, katere prednost je večja od izvajanja opravila, pride do preklopa konteksta. V bistvu se v tem postopku vsebina različnih nalog shrani v njihov pomnilnik skladov.
5. Vrste pravilnikov o načrtovanju:
- Preventivno razporejanje: pri tej vrsti razporejanja se naloge izvajajo z enakim časovnim rezom, ne da bi upoštevali prioritete.
- Prednostna prednostna naloga : Naloga z visoko prioriteto se bo zagnala prva.
- Razporejanje sodelovanja: Preklop konteksta se bo zgodil le s sodelovanjem tekočih nalog. Opravilo se bo izvajalo neprekinjeno, dokler ne pokličete donosa.
6. Predmeti jedra: Za signaliziranje naloge za izvedbo dela se uporablja postopek sinhronizacije. Za izvajanje tega postopka se uporabljajo objekti jedra. Nekateri objekti jedra so Dogodki, Semaforji, Čakalne vrste, Mutex, Nabiralniki itd. Kako jih bomo uporabljali, bomo videli v prihodnjih vajah.
Iz zgornje razprave smo dobili nekaj osnovnih idej o konceptu RTOS in zdaj lahko izvajamo projekt FreeRTOS v Arduinu. Začnimo z namestitvijo knjižnic FreeRTOS v Arduino IDE.
Namestitev knjižnice Arduino FreeRTOS
1. Odprite Arduino IDE in pojdite na Sketch -> Include Library -> Manage Libraries . Poiščite FreeRTOS in namestite knjižnico, kot je prikazano spodaj.
Knjižnico lahko prenesete iz github in dodate datoteko.zip v Sketch-> Include Library -> Add.zip datoteko.
Zdaj znova zaženite Arduino IDE. Ta knjižnica vsebuje nekaj primerov kode, ki jo lahko najdete tudi v Datoteka -> Primeri -> FreeRTOS, kot je prikazano spodaj.
Tu bomo napisali kodo iz nič, da bomo razumeli delovanje, kasneje lahko preverite primere kod in jih uporabite.
Shema vezja
Spodaj je diagram vezja za ustvarjanje naloge utripajočih LED z uporabo FreeRTOS na Arduinu:
Primer Arduino FreeRTOS - Ustvarjanje nalog FreeRTOS v Arduino IDE
Poglejmo osnovno strukturo za pisanje projekta FreeRTOS.
1. Najprej vključite glavo datoteke Arduino FreeRTOS kot
#include
2. Dajte prototip funkcije vseh funkcij, ki jih pišete za izvajanje, ki so zapisane kot
void Task1 (void * pvParameters); void Task2 (void * pvParameters); .. ….
3. Zdaj v funkciji void setup () ustvarite naloge in zaženite načrtovalnik opravil.
Za ustvarjanje naloge je v nastavitveni funkciji z določenimi parametri / argumenti poklican API xTaskCreate () .
xTaskCreate (TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void * pvParameters, UBaseType_t uxPriority, TaskHandle_t * pxCreatedTask);
Med ustvarjanjem katere koli naloge je treba navesti 6 argumentov. Poglejmo, kakšni so ti argumenti
- pvTaskCode: To je preprosto kazalec na funkcijo, ki izvaja nalogo (v resnici samo ime funkcije).
- pcName: opisno ime za nalogo. Tega FreeRTOS ne uporablja. Vključen je izključno za odpravljanje napak.
- usStackDepth: Vsaka naloga ima svoj unikatni sklad, ki ga jedro dodeli opravilu, ko je naloga izdelana. Vrednost določa število besed, ki jih lahko vsebuje sklad, ne število bajtov. Na primer, če je sklad širok 32 bitov in se usStackDepth preda kot 100, bo v RAM-u dodeljenih 400 bajtov prostora sklada (100 * 4 bajtov). Uporabite to pametno, ker ima Arduino Uno samo 2Kbajta RAM-a.
- pvParameters: Vhodni parameter naloge (lahko NULL).
- uxPriority: Prednost naloge (0 je najnižja prednost).
- pxCreatedTask: Uporablja se lahko za predajo ročice nalogi, ki jo ustvarjate. Ta ročaj se lahko nato uporabi za sklicevanje na nalogo v klicih API, ki na primer spremenijo prednostno nalogo ali izbrišejo nalogo (lahko NULL).
Primer izdelave naloge
xTaskCreate (task1, "task1", 128, NULL, 1, NULL); xTaskCreate (task2, "task2", 128, NULL, 2, NULL);
Tu ima naloga 2 večjo prioriteto in se zato najprej izvede.
4. Po izdelavi naloge zaženite načrtovalnik v nastavitvi void z uporabo vTaskStartScheduler (); API.
5. Funkcija Void loop () bo ostala prazna, saj nobene naloge ne želimo izvajati ročno in neskončno. Ker izvršitev naloge zdaj ureja razporejevalnik.
6. Zdaj moramo implementirati funkcije nalog in v te funkcije zapisati logiko, ki jo želite izvajati. Ime funkcije mora biti enako prvemu argumentu API-ja xTaskCreate () .
void task1 (void * pvParameters) { while (1) { .. ..//vaša logika } }
7. Večina kode potrebuje funkcijo zakasnitve, da ustavi tekoče opravilo, vendar v RTOS-u ni priporočljivo uporabljati funkcije Delay (), saj ustavi CPU in s tem tudi RTOS preneha delovati. Torej ima FreeRTOS jedrni API, ki za določen čas blokira nalogo.
vTaskDelay (const TickType_t xTicksToDelay);
Ta API se lahko uporablja za zamudo. Ta API zakasni opravilo za določeno število klopov. Dejanski čas, za katerega je naloga še vedno blokirana, je odvisen od stopnje tikov. Stalni portTICK_PERIOD_MS se lahko uporablja za izračun realnega časa iz hitrosti odkljuka.
To pomeni, da če želite zamudo 200 ms, preprosto zapišite to vrstico
vTaskDelay (200 / portTICK_PERIOD_MS);
Za to vadnico bomo uporabili te API-je FreeRTOS za izvajanje treh nalog.
API-ji, ki jih bomo uporabili:
- xTaskCreate ();
- vTaskStartScheduler ();
- vTaskDelay ();
Naloga, ki jo je treba ustvariti za to vadnico:
- Utripa LED na digitalnem zatiču 8 s frekvenco 200 ms
- Utripa LED na digitalnem zatiču 7 s frekvenco 300 ms
- Natisnite številke na serijski monitor s frekvenco 500 ms.
Izvajanje naloge FreeRTOS v Arduino IDE
1. Iz zgornje razlage osnovne strukture vključite datoteko glave Arduino FreeRTOS. Nato naredite prototipe funkcij. Ker imamo tri naloge, naredite tri funkcije in to so prototipi.
#include void TaskBlink1 (void * pvParameters); void TaskBlink2 (void * pvParameters); void Taskprint (void * pvParameters);
2. V funkciji void setup () inicializirajte serijsko komunikacijo s hitrostjo 9600 bitov na sekundo in z API-jem xTaskCreate () ustvarite vse tri naloge. Sprva določite prednostne naloge vseh nalog kot »1« in zaženite načrtovalnik.
void setup () { Serial.begin (9600); xTaskCreate (TaskBlink1, "Task1", 128, NULL, 1, NULL); xTaskCreate (TaskBlink2, "Task2", 128, NULL, 1, NULL); xTaskCreate (Taskprint, "Task3", 128, NULL, 1, NULL); vTaskStartScheduler (); }
3. Zdaj izvedite vse tri funkcije, kot je prikazano spodaj za LED-utripanje task1.
void TaskBlink1 (void * pvParameters) { pinMode (8, IZHOD); while (1) { digitalWrite (8, HIGH); vTaskDelay (200 / portTICK_PERIOD_MS); digitalWrite (8, LOW); vTaskDelay (200 / portTICK_PERIOD_MS); } }
Podobno izvedite funkcijo TaskBlink2. Funkcija Task3 bo zapisana kot
void Taskprint (void * pvParameters) { int counter = 0; medtem ko (1) { števec ++; Serial.println (števec); vTaskDelay (500 / portTICK_PERIOD_MS); } }
To je to. Uspešno smo zaključili projekt FreeRTOS Arduino za Arduino Uno. Celotno kodo lahko najdete skupaj z videoposnetkom na koncu te vadnice.
Na koncu na digitalni nožici 7 in 8 priključite dve LED in naložite kodo na ploščo Arduino in odprite serijski monitor. Videli boste, da števec teče enkrat v 500 ms z imenom naloge, kot je prikazano spodaj.
Upoštevajte tudi LED-diode, ki utripajo v različnih časovnih intervalih. Poskusite se igrati s prednostnim argumentom v funkciji xTaskCreate . Spremenite številko in opazujte obnašanje na serijskem monitorju in LED.
Zdaj lahko razumete prva dva primera kod, v katerih se ustvarjajo naloge analognega branja in digitalnega branja. Na ta način lahko naredite več naprednih projektov z uporabo samo Arduino Uno in FreeRTOS API-jev.