- Hogyan működik az RTOS?
- Gyakran használt kifejezések az RTOS-ban
- Az Arduino FreeRTOS könyvtár telepítése
- Kördiagramm
- Arduino FreeRTOS példa - FreeRTOS feladatok létrehozása az Arduino IDE-ben
- FreeRTOS feladat végrehajtása az Arduino IDE-ben
A beágyazott eszközök belsejében lévő operációs rendszert RTOS-nak (Real-Time Operating System) nevezzük. A beágyazott eszközökben a valós idejű feladatok kritikusak, ahol az időzítés nagyon fontos szerepet játszik. A valós idejű feladatok idődeterminisztikusak, vagyis minden eseményre adott válaszidő mindig állandó, így garantálható, hogy egy adott esemény rögzített időpontban következzen be. Az RTOS-t nagyon precíz időzítéssel és nagyfokú megbízhatósággal rendelkező alkalmazások futtatására tervezték. Az RTOS egyetlen feladattal segíti a többfeladatos feladatokat is.
Már bemutattunk egy oktatóanyagot az RTOS használatáról a beágyazott rendszerekben, ahol többet tudhat meg az RTOS-ról, az általános rendeltetésű operációs rendszer és az RTOS közötti különbségről, a különböző típusú RTOS-okról stb.
Ebben az oktatóanyagban a FreeRTOS- szal kezdjük. A FreeRTOS a beágyazott eszközök RTOS-osztálya, amely elég kicsi ahhoz, hogy 8/16-bites mikrovezérlőkön fusson, bár használata nem korlátozódik ezekre a mikrovezérlőkre. Ez egy teljesen nyílt forráskódú és kódja elérhető a github-on. Ha ismerünk néhány alapvető fogalmat az RTOS-ról, akkor nagyon egyszerű használni a FreeRTOS-t, mert jól dokumentált API-kat tartalmaz, amelyek közvetlenül felhasználhatók a kódban anélkül, hogy ismernék a kódolás háttér részét. A FreeRTOS teljes dokumentációja itt található.
Mivel a FreeRTOS 8 bites MCU-n futtatható, így az Arduino Uno táblán is futtatható. Csak le kell töltenünk a FreeRTOS könyvtárat, majd el kell kezdeni a kód implementálását az API-k segítségével. Ez az oktatóanyag egy teljesen kezdő számára készült, az alábbiakban bemutatjuk azokat a témákat, amelyeket ebben az Arduino FreeRTOS oktatóanyagban tárgyalunk:
- Hogyan működik az RTOS
- Néhány gyakran használt kifejezés az RTOS-ban
- A FreeRTOS telepítése az Arduino IDE-be
- Hogyan hozhatunk létre FreeRTOS Tasks-t példával
Hogyan működik az RTOS?
Mielőtt elkezdjük az RTOS működését, nézzük meg, mi a feladat. A Feladat olyan kódrészlet, amelyet a CPU-ra ütemezni lehet a végrehajtásra. Tehát, ha valamilyen feladatot szeretne végrehajtani, akkor azt a kernel delay vagy megszakítások segítségével kell ütemezni. Ezt a munkát a kernelben lévő Scheduler végzi. Az egy magos processzorban az ütemező segíti a feladatokat egy adott szelet végrehajtásában, de úgy tűnik, hogy a különböző feladatok egyidejűleg futnak. Minden feladat a neki adott prioritásnak megfelelően fut.
Most nézzük meg, mi történik az RTOS-kernelben, ha egy másodperc intervallummal szeretnénk létrehozni egy feladatot a LED-ek villogására, és ezt a feladatot helyezzük a legmagasabb prioritásra.
A LED feladaton kívül lesz még egy feladat, amelyet a kern hoz létre, ez egy üresjárati feladat. A tétlen feladat akkor jön létre, amikor nem áll rendelkezésre végrehajtásra alkalmas feladat. Ez a feladat mindig a legalacsonyabb prioritással, azaz 0 prioritással fut. Ha elemezzük a fent megadott időzítési grafikont, akkor látható, hogy a végrehajtás egy LED feladattal kezdődik, és egy meghatározott ideig fut, majd a hátralévő idő alatt a tétlen feladat addig fut, amíg a kullancs megszakítás meg nem történik. Ezután a rendszermag eldönti, hogy melyik feladatot kell végrehajtani a feladat prioritása és a LED feladat teljes eltelt ideje szerint. 1 másodperc befejezése után a kernel ismét kiválasztja a vezetett feladatot a végrehajtáshoz, mert nagyobb prioritással rendelkezik, mint az alapjárati feladat, azt is mondhatjuk, hogy a LED feladat megelőzi az üresjárati feladatot. Ha kettőnél több feladat van azonos prioritással, akkor egy meghatározott ideig körmérkőzéses módon futnak.
Az állapotdiagram alatt látható, amikor a nem futó feladat váltása futási állapotra.
Minden újonnan létrehozott feladat kész állapotba kerül (a nem futó állapot része). Ha a létrehozott feladatnak (1. feladat) a legmagasabb prioritása van, mint a többi feladatnak, akkor futó állapotba kerül. Ha ez a futó feladat megelőzi a másik feladatot, akkor újra visszatér a kész állapotba. Egyébként, ha a task1 blokkolásra kerül az blokkoló API használatával, akkor a CPU csak a felhasználó által megadott időkorlátig vesz részt ezzel a feladattal.
Ha a Task1 futó állapotban van felfüggesztve a Suspend API-k használatával, akkor a Task1 felfüggesztett állapotba kerül, és az ütemező számára nem áll rendelkezésre újra. Ha az 1. feladatot felfüggesztett állapotban folytatja, akkor az visszatér a kész állapotba, amint az a blokkdiagramon látható.
Ez az alapgondolat arról, hogy a Tasks hogyan futtatja és változtatja meg az állapotukat. Ebben az oktatóanyagban két feladatot hajtunk végre az Arduino Uno programban a FreeRTOS API használatával.
Gyakran használt kifejezések az RTOS-ban
1. Feladat: Ez egy olyan kódrészlet, amelyet a CPU ütemezhet végrehajtásra.
2. Ütemező: Feladat kiválasztása a kész állapot listáról a futó állapotra. Az ütemezőket gyakran úgy hajtják végre, hogy az összes számítógépes erőforrást elfoglalják (mint a terheléselosztásban).
3. Előzmény: Ez egy már végrehajtott feladat ideiglenes megszakítása azzal a szándékkal, hogy együttműködése nélkül eltávolítsa a futó állapotból.
4. Környezetváltás: Prioritás-alapú előválogatás esetén az ütemező összehasonlítja a futó feladatok prioritását a kész feladatlista prioritásával minden systick megszakításnál. Ha van olyan feladat a listában, amelynek prioritása magasabb, mint a futó feladat, akkor kontextus váltás történik. Alapvetően ebben a folyamatban a különféle feladatok tartalma a megfelelő verem memóriájába kerül.
5. Ütemezési politikák típusai:
- Megelőző ütemezés: Ebben a típusú ütemezésben a feladatok azonos időszelettel futnak, a prioritások figyelembevétele nélkül.
- Prioritás-alapú megelőző: A kiemelt feladatot kell elsőként lefuttatni.
- Szövetkezeti ütemezés: A kontextusváltás csak a futó feladatok együttműködésével történik. A feladat folyamatosan fut, amíg a feladat hozama meg nem lesz hívva.
6. Kernel objektumok: A feladat jelzésére bizonyos munkák elvégzéséhez a szinkronizálási folyamatot kell használni. A folyamat végrehajtásához a kernelobjektumokat használják. Néhány kernelobjektum: Események, Szemaforák, Sorok, Mutex, Postafiókok stb. Meglátjuk, hogyan kell ezeket az objektumokat használni a következő oktatóanyagok során.
A fenti beszélgetésből kaptunk néhány alapvető ötletet az RTOS koncepcióról, és most megvalósíthatjuk a FreeRTOS projektet Arduinóban. Tehát kezdjük azzal, hogy FreeRTOS könyvtárakat telepítünk az Arduino IDE-be.
Az Arduino FreeRTOS könyvtár telepítése
1. Nyissa meg az Arduino IDE alkalmazást, és lépjen a Sketch -> Könyvtár belefoglalása -> Könyvtárak kezelése elemre . Keresse meg a FreeRTOS-t, és telepítse a könyvtárat az alábbiak szerint.
Letöltheti a könyvtárat a github-ról, és hozzáadhatja a.zip fájlt a Sketch-> Könyvtár belefoglalása ->.zip fájl hozzáadása menüpontba .
Most indítsa újra az Arduino IDE alkalmazást. Ez a könyvtár tartalmaz néhány példakódot, amely megtalálható a Fájl -> Példák -> FreeRTOS alatt is , az alábbiak szerint.
Itt a nulláról írjuk a kódot, hogy megértsük a működést, később ellenőrizheti és felhasználhatja a példakódokat.
Kördiagramm
Az alábbiakban a villogó LED feladat létrehozásának kapcsolási rajza az Arduino FreeRTOS használatával:
Arduino FreeRTOS példa - FreeRTOS feladatok létrehozása az Arduino IDE-ben
Lássuk egy alapvető struktúrát egy FreeRTOS projekt megírásához.
1. Először csatolja az Arduino FreeRTOS fejlécfájlt
#include
2. Adja meg az összes olyan függvény prototípusát, amelyet végrehajtásra ír, és amely így van megírva
void Task1 (void * pvParameters); void 2. feladat (void * pvParameters); .. ….
3. Most a void setup () függvényben hozzon létre feladatokat, és indítsa el a feladatütemezőt.
A feladat létrehozásához az xTaskCreate () API meghívásra kerül a setup függvényben bizonyos paraméterekkel / argumentumokkal.
xTaskCreate (TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void * pvParameters, UBaseType_t uxPriority, TaskHandle_t * pxCreatedTask);
6 argumentumot kell átadni minden feladat létrehozása közben. Lássuk, mik ezek az érvek
- pvTaskCode: Ez egyszerűen egy mutató a függvényre, amely végrehajtja a feladatot (valójában csak a függvény neve).
- pcName: A feladat leíró neve. Ezt a FreeRTOS nem használja. Kizárólag hibakeresési célokra szerepel.
- usStackDepth: Minden feladatnak megvan a maga egyedi vereme, amelyet a kern allokál a feladathoz a feladat létrehozásakor. Az érték meghatározza a veremben tárolható szavak számát, nem a bájtok számát. Például, ha a verem 32 bites szélességű, és az usStackDepth 100- ként kerül átadásra, akkor 400 bájt veremterület kerül kiosztásra (100 * 4 bájt) a RAM-ban. Használja ezt okosan, mert az Arduino Uno csak 2Kbájt RAM-mal rendelkezik.
- pvParameters: Feladat bemeneti paraméter (lehet NULL).
- uxPriority: A feladat prioritása (0 a legalacsonyabb prioritás).
- pxCreatedTask: Használható egy fogantyú átadására a létrehozandó feladat számára. Ez a fogantyú akkor használható a feladat hivatkozására az API hívásokban, amelyek például megváltoztatják a feladat prioritását vagy törlik a feladatot (lehet NULL).
Példa a feladat létrehozására
xTaskCreate (feladat1, "feladat1", 128, NULL, 1, NULL); xTaskCreate (feladat2, "feladat2", 128, NULL, 2, NULL);
Itt a 2. feladat nagyobb prioritással rendelkezik, ezért először hajt végre.
4. A feladat létrehozása után indítsa el az ütemezőt egy érvénytelen beállításban a vTaskStartScheduler () használatával; API.
5. A Void loop () függvény üres marad, mivel nem akarunk semmilyen feladatot manuálisan és végtelenül futtatni. Mivel a feladat végrehajtását most az Ütemező kezeli.
6. Most végre kell hajtanunk a feladatfüggvényeket, és meg kell írnunk a végrehajtani kívánt logikát. A függvény nevének meg kell egyeznie az xTaskCreate () API első argumentumával.
void task1 (void * pvParameters) { while (1) { .. ..// logikád } }
7. A kód nagy részének késleltetési funkcióra van szüksége a futó feladat leállításához, de az RTOS-ban nem javasolt a Delay () függvény használata, mivel leállítja a CPU-t, így az RTOS is leáll. Tehát a FreeRTOS rendelkezik egy kernel API-val, amely egy adott időre blokkolja a feladatot.
vTaskDelay (const TickType_t xTicksToDelay);
Ez az API késleltetési célokra használható. Ez az API késlelteti a feladatot egy adott számú pipa esetén. A tényleges idő, amelyig a feladat blokkolva marad, a pipa arányától függ. Az állandó portTICK_PERIOD_MS használható a valós idejű számításra a kullancssűrűségből.
Ez azt jelenti, hogy 200ms késleltetést szeretne, csak írja be ezt a sort
vTaskDelay (200 / portTICK_PERIOD_MS);
Tehát ehhez az oktatóanyaghoz ezeket a FreeRTOS API-kat fogjuk használni három feladat végrehajtására.
Használandó API-k:
- xTaskCreate ();
- vTaskStartScheduler ();
- vTaskDelay ();
Ehhez az oktatóanyaghoz létrehozandó feladat:
- A LED villog a 8-as digitális tűnél 200 ms frekvenciával
- A LED villog a 7. digitális érintkezőnél 300 ms frekvenciával
- Számok nyomtatása soros monitoron 500 ms frekvenciával.
FreeRTOS feladat végrehajtása az Arduino IDE-ben
1. A fenti alapvető szerkezeti magyarázatból tegye bele az Arduino FreeRTOS fejlécfájlt. Ezután készítsen függvény prototípusokat. Mivel három feladatunk van, készítsünk három függvényt és annak prototípusait.
#include void TaskBlink1 (void * pvParameters); void TaskBlink2 (void * pvParameters); void Taskprint (void * pvParameters);
2. A void setup () függvényben inicializálja a soros kommunikációt 9600 bit / s sebességgel, és az xTaskCreate () API segítségével hozza létre mindhárom feladatot. Kezdetben állítsa az összes feladat prioritását "1" -re, és indítsa el az ütemezőt.
void setup () { Soros.kezdés (9600); xTaskCreate (TaskBlink1, "Task1", 128, NULL, 1, NULL); xTaskCreate (TaskBlink2, "Task2", 128, NULL, 1, NULL); xTaskCreate (Taskprint, "3. feladat", 128, NULL, 1, NULL); vTaskStartScheduler (); }
3. Most hajtsa végre mind a három funkciót az 1. feladat LED-jének villogása szerint.
void TaskBlink1 (void * pvParameters) { pinMode (8, OUTPUT); míg (1) { digitalWrite (8, HIGH); vTaskDelay (200 / portTICK_PERIOD_MS); digitalWrite (8, LOW); vTaskDelay (200 / portTICK_PERIOD_MS); } }
Hasonlóképpen hajtsa végre a TaskBlink2 függvényt is. A Task3 függvényt így írjuk
void Taskprint (void * pvParameters) { int számláló = 0; míg (1) { számláló ++; Soros.println (számláló); vTaskDelay (500 / portTICK_PERIOD_MS); } }
Ez az. Sikeresen befejeztük az Arduino Uno FreeRTOS Arduino projektjét. A bemutató végén megtalálható a teljes kód, valamint a videó.
Végül csatlakoztasson két LED-et a 7. és 8. digitális érintkezőhöz, töltse fel a kódot az Arduino táblára, és nyissa meg a soros monitort. Látni fogja, hogy egy számláló egyszer 500 ms-on fut a feladat nevével, az alábbiak szerint.
Figyelje meg a LED-eket is, ezek különböző időközönként villognak. Próbáljon meg játszani az xTaskCreate függvény prioritás argumentumával. Változtassa meg a számot, és figyelje meg a soros monitoron és a LED-ek viselkedését.
Most már megértheti az első két példakódot, amelyekben analóg olvasási és digitális olvasási feladatok jönnek létre. Ily módon további projekteket készíthet csak Arduino Uno és FreeRTOS API-k használatával.