- Kako RTOS radi?
- Pojmovi koji se često koriste u RTOS-u
- Instaliranje Arduino FreeRTOS knjižnice
- Kružni dijagram
- Primjer Arduino FreeRTOS - Stvaranje zadataka FreeRTOS u Arduino IDE-u
- Implementacija FreeRTOS zadatka u Arduino IDE
OS koji se nalazi unutar ugrađenih uređaja naziva se RTOS (operativni sustav u stvarnom vremenu). U ugrađenim uređajima zadaci u stvarnom vremenu presudni su kad mjerenje vremena igra vrlo važnu ulogu. Zadaci u stvarnom vremenu vremenski su deterministički znači da je vrijeme odziva na bilo koji događaj uvijek konstantno, tako da se može jamčiti da će se bilo koji određeni događaj dogoditi u određeno vrijeme. RTOS je dizajniran za pokretanje aplikacija s vrlo preciznim vremenom i visokim stupnjem pouzdanosti. RTOS također pomaže u obavljanju više zadataka s jednom jezgrom.
Već smo obradili tutorial o tome kako koristiti RTOS u ugrađenim sustavima gdje možete znati više o RTOS-u, razlici između OS-a i RTOS-a opće namjene, različitim vrstama RTOS-a itd.
U ovom uputstvu započet ćemo s FreeRTOS-om. FreeRTOS je klasa RTOS-a za ugrađene uređaje koja je dovoljno mala da se može izvoditi na 8/16-bitnim mikrokontrolerima, iako njegova upotreba nije ograničena na ove mikrokontrolere. Potpuno je otvoren izvor i njegov je kôd dostupan na githubu. Ako znamo neke osnovne koncepte RTOS-a, tada je vrlo jednostavno koristiti FreeRTOS jer ima dobro dokumentirane API-je koji se mogu izravno koristiti u kodu bez poznavanja pozadinskog dijela kodiranja. Kompletnu FreeRTOS dokumentaciju možete pronaći ovdje.
Kao što FreeRTOS može raditi na 8-bitnom MCU-u, tako se može pokretati i na ploči Arduino Uno. Moramo samo preuzeti knjižnicu FreeRTOS, a zatim započeti s implementacijom koda pomoću API-ja. Ovaj je vodič namijenjen potpunom početniku, u nastavku su teme koje ćemo obraditi u ovom Arduino FreeRTOS vodiču:
- Kako RTOS radi
- Neki često korišteni pojmovi u RTOS-u
- Instaliranje FreeRTOS-a u Arduino IDE
- Kako stvoriti FreeRTOS zadatke na primjeru

Kako RTOS radi?
Prije početka rada s RTOS-om, pogledajmo što je zadatak. Zadatak je dio koda koji se može izvršiti na CPU-u. Dakle, ako želite izvršiti neki zadatak, onda ga treba zakazati pomoću kašnjenja jezgre ili pomoću prekida. Ovaj posao obavlja Planer prisutan u jezgri. U jednojezgrenom procesoru, planer pomaže izvršavanju zadataka u određenom vremenskom odsječku, ali čini se da se različiti zadaci izvršavaju istovremeno. Svaki zadatak radi prema prioritetu koji mu je dan.
Sada, pogledajmo što će se dogoditi u RTOS jezgri ako želimo stvoriti zadatak za LED koji trepće s intervalom od jedne sekunde i staviti ovaj zadatak na najveći prioritet.

Osim LED zadatka, postojat će još jedan zadatak koji stvara jezgra, poznat je kao neaktivan zadatak. Neaktivni zadatak stvara se kada nijedan zadatak nije dostupan za izvršenje. Ovaj se zadatak uvijek izvodi s najmanjim prioritetom, tj. S 0 prioriteta. Ako analiziramo gore dani vremenski graf, može se vidjeti da izvršavanje započinje LED zadatkom i radi određeno vrijeme, a zatim preostalo vrijeme, dok se neaktivni zadatak izvršava sve dok se ne dogodi prekid krpelja. Tada kernel odlučuje koji zadatak treba izvršiti u skladu s prioritetom zadatka i ukupnim proteklim vremenom LED zadatka. Kada se završi 1 sekunda, jezgra ponovno bira vodeći zadatak za izvršenje jer ima veći prioritet od neaktivnog zadatka, možemo također reći da LED zadatak preuzima neaktivni zadatak. Ako postoji više od dva zadatka s istim prioritetom, tada će se izvršavati u krugu određeno vrijeme.
Ispod dijagrama stanja jer prikazuje prebacivanje neizvršenog zadatka u pokrenuto stanje.

Svaki novostvoreni zadatak ide u stanje pripravnosti (dio stanja koje nije pokrenuto). Ako stvoreni zadatak (Zadatak1) ima najveći prioritet od ostalih zadataka, tada će se prebaciti u pokrenuto stanje. Ako ovaj izvršeni zadatak preuzme drugi zadatak, tada će se opet vratiti u stanje pripravnosti. Inače ako je task1 blokiran upotrebom API-ja za blokiranje, tada se CPU neće uključiti u ovaj zadatak sve dok ne istekne vremensko ograničenje koje je definirao korisnik.
Ako je Task1 suspendiran u aktivnom stanju pomoću suspendiranih API-ja, tada će Task1 preći u suspendirano stanje i nije ponovo dostupan planeru. Ako Task1 nastavite u suspendiranom stanju, vratit će se u stanje pripravnosti kao što vidite na blok dijagramu.
To je osnovna ideja kako se zadaci pokreću i mijenjaju svoja stanja. U ovom uputstvu implementirat ćemo dva zadatka u Arduino Uno koristeći FreeRTOS API.
Pojmovi koji se često koriste u RTOS-u
1. Zadatak: To je dio koda koji se može izvršiti na CPU.
2. Planer: On je odgovoran za odabir zadatka s popisa spremnih stanja u stanje u kojem se izvodi. Planeri se često implementiraju tako da zauzimaju sve računalne resurse (kao kod uravnoteženja opterećenja).
3. Prevencija: Čin je privremenog prekida već izvršenog zadatka s namjerom da se ukloni iz aktivnog stanja bez njegove suradnje.
4. Prebacivanje konteksta: U prevenciji temeljenoj na prioritetu, planer uspoređuje prioritet izvršenih zadataka s prioritetom spremnog popisa zadataka na svakom prekidu systicka . Ako na popisu postoji bilo koji zadatak čiji je prioritet veći od izvršavanja zadatka, tada se događa prebacivanje konteksta. U osnovi, u ovom se procesu sadržaj različitih zadataka sprema u njihovu memoriju steka.
5. Vrste politika zakazivanja:
- Preventivno raspoređivanje: U ovoj vrsti raspoređivanja zadaci se izvode s jednakim vremenskim odsječkom bez razmatranja prioriteta.
- Prednost na temelju prioriteta : Prvo će se pokrenuti zadatak s visokim prioritetom.
- Zakazivanje suradnje: Prebacivanje konteksta dogodit će se samo uz suradnju izvršenih zadataka. Zadatak će se izvoditi kontinuirano dok se ne pozove prinos zadatka.
6. Objekti jezgre: Za signaliziranje zadatka za izvođenje nekog posla koristi se postupak sinkronizacije. Za izvođenje ovog postupka koriste se Kernel objekti. Neki su objekti jezgre događaji, semafori, redovi čekanja, mutex, poštanski sandučići itd. Vidjet ćemo kako ih koristiti u sljedećim vodičima.
Iz gornje rasprave dobili smo nekoliko osnovnih ideja o konceptu RTOS-a i sada možemo implementirati projekt FreeRTOS u Arduinu. Dakle, krenimo s instaliranjem FreeRTOS knjižnica u Arduino IDE.
Instaliranje Arduino FreeRTOS knjižnice
1. Otvorite Arduino IDE i idite na Skica -> Uključi biblioteku -> Upravljanje knjižnicama . Potražite FreeRTOS i instalirajte knjižnicu kao što je prikazano dolje.

Knjižnicu možete preuzeti s github-a i dodati.zip datoteku u Sketch-> Include Library -> Add.zip datoteku.
Sada ponovno pokrenite Arduino IDE. Ova knjižnica nudi neki primjer koda, koji se također može naći u Datoteka -> Primjeri -> FreeRTOS, kao što je prikazano dolje.

Ovdje ćemo napisati kod ispočetka kako bismo razumjeli rad, kasnije možete provjeriti primjere kodova i koristiti ih.
Kružni dijagram
Ispod je shema spojeva za stvaranje zadatka Trepćuća LED pomoću FreeRTOS-a na Arduinu:

Primjer Arduino FreeRTOS - Stvaranje zadataka FreeRTOS u Arduino IDE-u
Pogledajmo osnovnu strukturu za pisanje FreeRTOS projekta.
1. Prvo uključite datoteku zaglavlja Arduino FreeRTOS kao
#include
2. Dajte prototip funkcije svih funkcija koje pišete za izvršenje, a koji su zapisani kao
void Task1 (void * pvParameters); void Task2 (void * pvParameters); .. ...
3. Sada, u funkciji void setup () , kreirajte zadatke i pokrenite planer zadataka.
Za stvaranje zadatka poziva se xTaskCreate () API u funkciji postavljanja s određenim parametrima / argumentima.
xTaskCreate (TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void * pvParameters, UBaseType_t uxPriority, TaskHandle_t * pxCreatedTask);
Postoji 6 argumenata koje treba proslijediti tijekom stvaranja bilo kojeg zadatka. Da vidimo koji su to argumenti
- pvTaskCode: To je jednostavno pokazivač na funkciju koja implementira zadatak (zapravo samo ime funkcije).
- pcName: opisni naziv zadatka. Ovo ne koristi FreeRTOS. Uključen je isključivo u svrhu uklanjanja pogrešaka.
- usStackDepth: Svaki zadatak ima svoj jedinstveni stog koji jezgra dodijeljuje zadatku kada se zadatak kreira. Vrijednost određuje broj riječi koje stek može sadržavati, a ne broj bajtova. Na primjer, ako je stog širok 32 bita i usStackDepth se preda kao 100, tada će se u RAM-u dodijeliti 400 bajtova prostora stoga (100 * 4 bajta). Koristite to pametno jer Arduino Uno ima samo 2 KB bajta.
- pvParameters: Ulazni parametar zadatka (može biti NULL).
- uxPriority: Prioritet zadatka (0 je najniži prioritet).
- pxCreatedTask: Može se koristiti za prosljeđivanje hvataljke zadatku koji se izrađuje. Ova se ručka tada može koristiti za referenciranje zadatka u API pozivima koji, na primjer, mijenjaju prioritet zadatka ili brišu zadatak (može biti NULL).
Primjer izrade zadatka
xTaskCreate (zadatak1, "zadatak1", 128, NULL, 1, NULL); xTaskCreate (zadatak2, "zadatak2", 128, NULL, 2, NULL);
Ovdje Task2 ima veći prioritet i stoga se izvršava prvi.
4. Nakon kreiranja zadatka, pokrenite planer u void postavci pomoću vTaskStartScheduler (); API.
5. Funkcija Void loop () ostat će prazna jer ne želimo ručno i beskonačno pokretati nijedan zadatak. Jer izvršavanjem zadataka sada se bavi Planer.
6. Sada moramo implementirati funkcije zadataka i napisati logiku koju želite izvršiti unutar tih funkcija. Naziv funkcije trebao bi biti jednak prvom argumentu API-ja xTaskCreate () .
void task1 (void * pvParameters) { while (1) { .. ..//vasa logika } }
7. Većini koda je potrebna funkcija odgode da bi se zaustavio izvršeni zadatak, ali u RTOS-u se ne preporučuje upotreba funkcije Delay () jer zaustavlja CPU, a time i RTOS prestaje raditi. Dakle, FreeRTOS ima kernel API koji blokira zadatak na određeno vrijeme.
vTaskDelay (const TickType_t xTicksToDelay);
Ovaj se API može koristiti za kašnjenje. Ovaj API odgađa zadatak za zadani broj krpelja. Stvarno vrijeme za koje zadatak ostaje blokiran ovisi o stopi krpelja. Stalni portTICK_PERIOD_MS može se koristiti za izračunavanje stvarnog vremena iz stope krpelja.
To znači da ako želite kašnjenje od 200 ms, samo napišite ovaj redak
vTaskDelay (200 / portTICK_PERIOD_MS);
Dakle, za ovaj tutorial koristit ćemo ove FreeRTOS API-je za provedbu tri zadatka.
API-ji koji će se koristiti:
- xTaskCreate ();
- vTaskStartScheduler ();
- vTaskDelay ();
Zadatak koji će se stvoriti za ovaj vodič:
- LED trepće na digitalnom pinu 8 s frekvencijom 200 ms
- LED trepće na digitalnom pinu 7 s frekvencijom 300 ms
- Ispis brojeva u serijski monitor s frekvencijom od 500 ms.
Implementacija FreeRTOS zadatka u Arduino IDE
1. Iz gornjeg objašnjenja osnovne strukture, dodajte datoteku zaglavlja Arduino FreeRTOS. Zatim napravite prototipove funkcija. Kako imamo tri zadatka, tako izradite tri funkcije i to su prototipovi.
#include void TaskBlink1 (void * pvParameters); void TaskBlink2 (void * pvParameters); void Taskprint (void * pvParameters);
2. U funkciji void setup () , inicijalizirajte serijsku komunikaciju brzinom od 9600 bita u sekundi i stvorite sve tri zadatke pomoću xTaskCreate () API-ja. U početku postavite prioritete svih zadataka kao '1' i pokrenite planer.
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. Sada implementirajte sve tri funkcije kao što je prikazano dolje za treptanje LED diode task1.
void TaskBlink1 (void * pvParameters) { pinMode (8, OUTPUT); while (1) { digitalWrite (8, HIGH); vTaskDelay (200 / portTICK_PERIOD_MS); digitalWrite (8, LOW); vTaskDelay (200 / portTICK_PERIOD_MS); } }
Slično tome, implementirajte funkciju TaskBlink2. Funkcija Task3 bit će zapisana kao
void Taskprint (void * pvParameters) { int counter = 0; while (1) { brojač ++; Serial.println (brojač); vTaskDelay (500 / portTICK_PERIOD_MS); } }
To je to. Uspješno smo završili FreeRTOS Arduino projekt za Arduino Uno. Puni kôd možete pronaći zajedno s videozapisom na kraju ovog vodiča.
Napokon, spojite dvije LED diode na digitalni pin 7 i 8 i prenesite kôd na svoju Arduino ploču i otvorite serijski monitor. Vidjet ćete da brojač radi jednom u 500 ms s nazivom zadatka kao što je prikazano dolje.


Također, promatrajte LED diode, koje trepere u različitim vremenskim intervalima. Pokušajte se igrati s argumentom prioriteta u funkciji xTaskCreate . Promijenite broj i promatrajte ponašanje serijskog monitora i LED-a.
Sada možete razumjeti prva dva primjera kodova u kojima se stvaraju zadaci analognog čitanja i digitalnog čitanja. Na taj način možete napraviti više naprednih projekata koristeći samo Arduino Uno i FreeRTOS API-je.
