- Kaip veikia RTOS?
- RTOS dažnai vartojami terminai
- Diegiama „Arduino FreeRTOS“ biblioteka
- Grandinės schema
- „Arduino FreeRTOS“ pavyzdys - „FreeRTOS“ užduočių kūrimas „Arduino IDE“
- „FreeRTOS“ užduoties įgyvendinimas „Arduino IDE“
Įterptųjų įrenginių viduje esanti OS vadinama RTOS (realaus laiko operacine sistema). Įterptuosiuose įrenginiuose realiojo laiko užduotys yra labai svarbios, kai laikas turi labai svarbų vaidmenį. Realaus laiko užduotys yra laiko nustatymo priemonės, tai reiškia, kad atsakymo laikas į bet kurį įvykį visada yra pastovus, kad būtų galima garantuoti, jog bet kuris konkretus įvykis įvyks nustatytu laiku. RTOS yra sukurtas paleisti programas su labai tiksliu laiku ir aukštu patikimumo laipsniu. RTOS taip pat padeda atlikti daug užduočių su vienu branduoliu.
Mes jau apėmė pamoką, kaip naudoti RTOS įterptosiose sistemose, kur galite sužinoti daugiau apie RTOS, skirtumą tarp bendrosios paskirties OS ir RTOS, skirtingų tipų RTOS ir kt.
Šioje pamokoje pradėsime nuo „ FreeRTOS“. „FreeRTOS“ yra įterptųjų įrenginių RTOS klasė, kuri yra pakankamai maža, kad ją būtų galima paleisti su 8/16 bitų mikrovaldikliais, nors jos naudojimas neapsiriboja tik šiais mikrovaldikliais. Tai yra visiškai atviro kodo kodas, kurį galima rasti „github“. Jei mes žinome kai kurias pagrindines RTOS sąvokas, tada labai lengva naudoti „FreeRTOS“, nes ji turi gerai dokumentuotas API, kurias galima tiesiogiai naudoti kode, nežinant užpakalinės kodavimo dalies. Išsamią „FreeRTOS“ dokumentaciją galite rasti čia.
„FreeRTOS“ gali veikti 8 bitų MCU, todėl jį galima paleisti ir „Arduino Uno“ plokštėje. Turime tiesiog atsisiųsti „FreeRTOS“ biblioteką ir tada pradėti diegti kodą naudodami API. Ši pamoka skirta visiškai pradedantiesiems, toliau pateikiamos temos, kurias aptarsime šioje „ Arduino FreeRTOS“ pamokoje:
- Kaip veikia RTOS
- Kai kurie RTOS dažnai vartojami terminai
- „FreeRTOS“ diegimas „Arduino IDE“
- Kaip sukurti „FreeRTOS“ užduotis su pavyzdžiu
Kaip veikia RTOS?
Prieš pradėdami dirbti su RTOS, pažiūrėkime, kas yra užduotis. Užduotis yra kodo dalis, kurią CPU gali suplanuoti vykdyti. Taigi, jei norite atlikti tam tikrą užduotį, ji turėtų būti suplanuota naudojant branduolio uždelsimą arba pertraukimus. Šį darbą atlieka suplanuotojas, esantis branduolyje. Vieno branduolio procesoriuje tvarkaraštis padeda užduotims atlikti tam tikrą laiko dalį, tačiau atrodo, kad skirtingos užduotys vykdomos vienu metu. Kiekviena užduotis vykdoma pagal jai teikiamą prioritetą.
Pažiūrėkime, kas vyksta RTOS branduolyje, jei norime sukurti užduotį, skirtą mirksi šviesos diodams su vienos sekundės intervalu, ir nustatyti šią užduotį didžiausiam prioritetui.
Be LED užduoties, bus dar viena užduotis, kurią sukuria branduolys, ji vadinama nenaudojama užduotimi. Nenaudojama užduotis sukuriama, kai negalima vykdyti jokios užduoties. Ši užduotis visada vykdoma pagal mažiausią prioritetą, ty 0 prioritetą. Jei išanalizuosime aukščiau pateiktą laiko grafiką, galima pastebėti, kad vykdymas prasideda nuo LED užduoties ir jis veikia nurodytą laiką, o likusį laiką - neveikos užduotis vykdoma tol, kol įvyksta varnelės pertraukimas. Tada branduolys nusprendžia, kuri užduotis turi būti vykdoma, atsižvelgiant į užduoties prioritetą ir bendrą praeitą LED užduoties laiką. Kai bus baigta 1 sekundė, branduolys vėl pasirenka vykdyti užduotį, nes ji turi didesnį prioritetą nei tuščiąja eiga, mes taip pat galime pasakyti, kad šviesos diodo užduotis užkerta kelią neveikiančiai užduočiai. Jei yra daugiau nei dvi užduotys, turinčios tą patį prioritetą, jos nustatytą laiką bus vykdomos pirmyn.
Žemiau būsenos diagramos, nes ji rodo nevykdomos užduoties perjungimą į veikimo būseną.
Kiekviena naujai sukurta užduotis eina parengties būsena (neveikiančios būsenos dalis). Jei sukurta užduotis (1 užduotis) turi didžiausią prioritetą nei kitos užduotys, ji pereis į veikiančią būseną. Jei šiai vykdomai užduočiai pasirenkama kita užduotis, ji vėl grįš į parengties būseną. Kitaip, jei „task1“ yra užblokuotas naudojant blokavimo API, tada procesorius nevykdys šios užduoties iki vartotojo nustatyto skirtojo laiko.
Jei „Task1“ bus sustabdytas veikiančioje būsenoje naudojant „Suspend API“, tada „Task1“ pereis į „Suspended“ būseną ir jos vėl nebus planuotojui. Jei atnaujinsite „Task1“ sustabdytoje būsenoje, ji grįš į parengties būseną, kaip matote blokinėje diagramoje.
Tai yra pagrindinė užduočių vykdymo ir jų būsenų keitimo idėja. Šioje pamokoje įgyvendinsime dvi „Arduino Uno“ užduotis naudodami „FreeRTOS“ API.
RTOS dažnai vartojami terminai
1. Užduotis: Tai yra kodo dalis, kurią CPU gali suplanuoti vykdyti.
2. Tvarkaraštis: Jis yra atsakingas už užduoties pasirinkimą iš parengties būsenos sąrašo į veikiančią būseną. Tvarkaraščiai dažnai įgyvendinami, kad jie užimtų visus kompiuterio išteklius (kaip ir apkrovos balansavimo metu).
3. Priemonė: tai laikinai nutraukiama jau vykdoma užduotis, siekiant ją pašalinti iš veikiančios valstybės be jos bendradarbiavimo.
4. Konteksto perjungimas: Prioritetu pagrįstame išankstiniame nustatyme planuotojas lygina vykdomų užduočių prioritetą su paruoštų užduočių sąrašo prioritetu kiekviename sistemos mygtuko pertraukime. Jei sąraše yra kokia nors užduotis, kurios prioritetas yra didesnis nei vykdomos užduoties, įvyksta konteksto perjungimas. Iš esmės šiame procese skirtingų užduočių turinys išsaugomas atitinkamoje kamino atmintyje.
5. Planavimo politikos rūšys:
- Prevencinis planavimas: Šio tipo planavime užduotys vykdomos vienodu laiko tarpu, neatsižvelgiant į prioritetus.
- Prioritetu pagrįstas prevencinis: Pirmiausia bus vykdoma aukšto prioriteto užduotis.
- Bendradarbiavimo planavimas: konteksto perjungimas įvyks tik bendradarbiaujant vykdomoms užduotims. Užduotis vykdoma nuolat, kol bus iškviestas užduoties derlius.
6. Branduolio objektai: norint nurodyti užduotį atlikti tam tikrą darbą, naudojamas sinchronizavimo procesas. Šiam procesui atlikti naudojami branduolio objektai. Kai kurie branduolio objektai yra įvykiai, semaforai, eilės, „Mutex“, pašto dėžutės ir kt. Mes pamatysime, kaip šiuos objektus naudoti būsimose mokymo programose.
Iš minėtos diskusijos mes turime keletą pagrindinių idėjų apie RTOS koncepciją ir dabar galime įgyvendinti „FreeRTOS“ projektą „Arduino“. Taigi, pradėkime įdiegdami „ FreeRTOS“ bibliotekas „Arduino IDE“.
Diegiama „Arduino FreeRTOS“ biblioteka
1. Atidarykite „Arduino IDE“ ir eikite į „ Sketch -> Include Library -> Manage Libraries“ . Ieškokite „FreeRTOS“ ir įdiekite biblioteką, kaip parodyta žemiau.
Galite atsisiųsti biblioteką iš „github“ ir pridėti.zip failą sketch-> įtraukti biblioteką -> pridėti.zip failą.
Dabar iš naujo paleiskite „Arduino IDE“. Šioje bibliotekoje yra keletas kodo pavyzdžių, kuriuos taip pat galite rasti Failas -> Pavyzdžiai -> FreeRTOS, kaip parodyta žemiau.
Čia mes parašysime kodą nuo nulio, kad suprastume veikiantį, vėliau galite patikrinti kodų pavyzdžius ir juos naudoti.
Grandinės schema
Žemiau pateikiama „Blinking LED“ užduoties kūrimo schema naudojant „FreeRTOS“ sistemoje „Arduino“:
„Arduino FreeRTOS“ pavyzdys - „FreeRTOS“ užduočių kūrimas „Arduino IDE“
Pažiūrėkime apie pagrindinę „FreeRTOS“ projekto rašymo struktūrą.
1. Pirmiausia įtraukite „Arduino FreeRTOS“ antraštės failą kaip
# įtraukti
2. Pateikite visų funkcijų, kurias rašote vykdyti, prototipą, kuris parašytas taip
void Task1 (negaliojantis * pvParameters); void Task2 (negaliojantis * pvParameters); .. ….
3. Dabar, naudodamiesi „ void setup ()“ funkcija, sukurkite užduotis ir paleiskite užduočių planavimo priemonę.
Kuriant užduotį, xTaskCreate () API iškviečiama sąrankos funkcijoje su tam tikrais parametrais / argumentais.
xTaskCreate (TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void * pvParameters, UBaseType_t uxPriority, TaskHandle_t * pxCreatedTask);
Kuriant bet kokią užduotį, reikia pateikti 6 argumentus. Pažiūrėkime, kokie yra šie argumentai
- pvTaskCode: Tai tiesiog funkcijos, kuri įgyvendina užduotį, rodyklė (iš tikrųjų tik funkcijos pavadinimas).
- pcName: aprašomas užduoties pavadinimas. To nenaudoja „FreeRTOS“. Jis įtrauktas tik derinimo tikslais.
- usStackDepth: Kiekviena užduotis turi savo unikalų kaminą, kurį branduolys skiria užduočiai kuriant užduotį. Vertė nurodo žodžių, kuriuos gali laikyti rietuvėje, skaičių, o ne baitų skaičių. Pvz., Jei kamino plotis yra 32 bitai, o „ usStackDepth “ perduodamas kaip 100, tada RAM bus skirta 400 baitų kamino vietos (100 * 4 baitų). Naudokite tai išmintingai, nes „Arduino Uno“ turi tik 2Kbaitų RAM.
- pvParameters: užduoties įvesties parametras (gali būti NULL).
- uxPriority: užduoties prioritetas (0 yra žemiausias prioritetas).
- pxCreatedTask: Jis gali būti naudojamas perduodant kuriamos užduoties rankeną. Tada šią rankeną galima naudoti nurodant užduotį API kvietimuose, kurie, pavyzdžiui, keičia užduoties prioritetą arba ištrina užduotį (gali būti NULL).
Užduoties kūrimo pavyzdys
„xTaskCreate“ (task1, „task1“, 128, NULL, 1, NULL); „xTaskCreate“ (task2, „task2“, 128, NULL, 2, NULL);
Čia „Task2“ turi didesnį prioritetą ir todėl pirmiausia vykdo.
4. Sukūrę užduotį, paleiskite tvarkaraštį tuščioje sąrankoje naudodami vTaskStartScheduler (); API.
5. Void loop () funkcija liks tuščia, nes mes nenorime vykdyti jokių užduočių rankiniu būdu ir be galo. Nes užduočių vykdymą dabar tvarko planuotojas.
6. Dabar turime įgyvendinti užduočių funkcijas ir užrašyti logiką, kurią norite vykdyti šiose funkcijose. Funkcijos pavadinimas turėtų būti toks pats kaip pirmasis xTaskCreate () API argumentas.
void task1 (void * pvParameters) { while (1) { .. ..//your logic } }
7. Daugumai kodo reikia uždelsimo funkcijos, kad sustabdytumėte vykdomą užduotį, tačiau RTOS sistemoje nerekomenduojama naudoti uždelsimo () funkcijos, nes ji sustabdo procesorių ir todėl RTOS taip pat nustoja veikti. Taigi „FreeRTOS“ turi branduolio API, kad blokuotų užduotį konkrečiam laikui.
vTaskDelay (const TickType_t xTicksToDelay);
Ši API gali būti naudojama atidėjimo tikslais. Ši API atideda užduotį tam tikram erkių skaičiui. Faktinis laikas, per kurį užduotis lieka užblokuota, priklauso nuo varnelės rodiklio. Nuolatinis portTICK_PERIOD_MS gali būti naudojamas realiuoju laiku apskaičiuoti pagal pažymėjimo greitį.
Tai reiškia, kad jei norite 200ms vėlavimo, tiesiog parašykite šią eilutę
„vTaskDelay“ (200 / portTICK_PERIOD_MS);
Taigi šiai pamokai mes naudosime šias „ FreeRTOS“ API, kad įgyvendintume tris užduotis.
Naudojamos API:
- xTaskCreate ();
- „vTaskStartScheduler“ ();
- vTaskDelay ();
Šios pamokos sukurta užduotis:
- Šviesos diodas mirksi esant 8 skaitmeniniam kaiščiui su 200 ms dažniu
- Šviesos diodas mirksi prie skaitmeninio kaiščio 7 su 300 ms dažniu
- Spausdinkite numerius serijiniame monitoriuje 500 ms dažniu.
„FreeRTOS“ užduoties įgyvendinimas „Arduino IDE“
1. Iš aukščiau pateikto pagrindinio struktūros paaiškinimo įtraukite „Arduino FreeRTOS“ antraštės failą. Tada sukurkite funkcijų prototipus. Kadangi turime tris užduotis, atlikite tris funkcijas ir jos prototipus.
#include void „TaskBlink1“ (negaliojantis * pvParameters); negaliojantis „TaskBlink2“ (negaliojantis * pvParameters); void Taskprint (void * pvParameters);
2. Naudodami „ void setup ()“ funkciją, pradėkite nuoseklųjį ryšį 9600 bitų per sekundę greičiu ir sukurkite visas tris užduotis naudodami „ xTaskCreate () API“. Iš pradžių nustatykite visų užduočių prioritetus kaip „1“ ir paleiskite tvarkaraštį.
negaliojanti sąranka () { 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. Dabar įgyvendinkite visas tris funkcijas, kaip parodyta žemiau 1 užduoties šviesos diodui.
negaliojantis „TaskBlink1“ (negaliojantis * „pvParameters“) { pinMode (8, OUTPUT); o (1) { digitalWrite (8, HIGH); „vTaskDelay“ (200 / portTICK_PERIOD_MS); „digitalWrite“ (8, LOW); „vTaskDelay“ (200 / portTICK_PERIOD_MS); } }
Panašiai įgyvendinkite „ TaskBlink2“ funkciją. „Task3“ funkcija bus parašyta taip
void Taskprint (void * pvParameters) { int skaitiklis = 0; o (1) { skaitiklis ++; Serial.println (skaitiklis); „vTaskDelay“ (500 / portTICK_PERIOD_MS); } }
Viskas. Mes sėkmingai užbaigėme „Arduino Uno“ „ FreeRTOS Arduino“ projektą. Šios instrukcijos pabaigoje rasite visą kodą kartu su vaizdo įrašu.
Galiausiai prie skaitmeninio kaiščio 7 ir 8 prijunkite du šviesos diodus ir įkelkite kodą į savo „Arduino“ plokštę ir atidarykite „Serial“ monitorių. Pamatysite, kad skaitiklis veikia kartą per 500 ms su užduoties pavadinimu, kaip parodyta žemiau.
Taip pat stebėkite šviesos diodus, jie mirksi skirtingais laiko intervalais. Pabandykite žaisti su prioriteto argumentu funkcijoje „ xTaskCreate“ . Pakeiskite numerį ir stebėkite serijinio monitoriaus ir šviesos diodų veikimą.
Dabar galite suprasti pirmuosius du kodų pavyzdžius, kuriuose kuriamos analoginio skaitymo ir skaitmeninio skaitymo užduotys. Tokiu būdu galite atlikti daugiau išankstinių projektų naudodami tik „Arduino Uno“ ir „FreeRTOS“ API.