- Hvordan fungerer RTOS?
- Ofte anvendte udtryk i RTOS
- Installation af Arduino FreeRTOS-bibliotek
- Kredsløbsdiagram
- Arduino FreeRTOS Eksempel - Oprettelse af FreeRTOS-opgaver i Arduino IDE
- FreeRTOS opgaveimplementering i Arduino IDE
Operativsystemet til stede inde i de indlejrede enheder kaldes et RTOS (realtidsoperativsystem). I indlejrede enheder er realtidsopgaver kritiske, hvor timing spiller en meget vigtig rolle. Realtidsopgaver er tid Deterministisk betyder, at responstiden til enhver begivenhed altid er konstant, så det kan garanteres, at en bestemt begivenhed finder sted på et fast tidspunkt. RTOS er designet til at køre applikationer med meget præcis timing og en høj grad af pålidelighed. RTOS hjælper også med multitasking med en enkelt kerne.
Vi har allerede dækket en tutorial om, hvordan du bruger RTOS i indlejrede systemer, hvor du kan vide mere om RTOS, forskellen mellem OS og RTOS til almindelige formål, forskellige typer RTOS osv.
I denne vejledning starter vi med FreeRTOS. FreeRTOS er en klasse af RTOS til indlejrede enheder, som er lille nok til at køre på 8/16-bit mikrokontrollere, selvom brugen ikke er begrænset til disse mikrokontroller. Det er en fuldstændig open source, og dens kode er tilgængelig på github. Hvis vi kender nogle grundlæggende begreber i RTOS, er det meget nemt at bruge FreeRTOS, fordi det har veldokumenterede API'er, som kan bruges direkte i koden uden at kende backend-delen af kodningen. Komplet FreeRTOS-dokumentation kan findes her.
Da FreeRTOS kan køre på 8-bit MCU, så det også kan køres på Arduino Uno-kort. Vi skal bare downloade FreeRTOS-biblioteket og derefter begynde at implementere koden ved hjælp af API'er. Denne vejledning er beregnet til en komplet begynder, nedenunder er emnerne, vi vil dække i denne Arduino FreeRTOS-tutorial:
- Sådan fungerer RTOS
- Nogle ofte anvendte udtryk i RTOS
- Installation af FreeRTOS i Arduino IDE
- Sådan oprettes FreeRTOS-opgaver med eksempel
Hvordan fungerer RTOS?
Før vi begynder med RTOS-arbejde, lad os se, hvad der er en opgave. Opgave er et stykke kode, der kan planlægges på CPU'en at udføre. Så hvis du vil udføre en opgave, skal den planlægges ved hjælp af kerneforsinkelse eller ved hjælp af afbrydelser. Dette arbejde udføres af Scheduler til stede i kernen. I en enkeltkerneprocessor hjælper planlæggeren opgaver med at udføre i en bestemt tidsskive, men det ser ud til, at forskellige opgaver udføres samtidigt. Hver opgave kører i henhold til den prioritet, den får.
Lad os nu se, hvad der sker i RTOS-kernen, hvis vi vil oprette en opgave til LED, der blinker med et sekunders interval og sætte denne opgave på højeste prioritet.
Bortset fra LED-opgaven vil der være endnu en opgave, der oprettes af kernen, den er kendt som en inaktiv opgave. Tomgangsopgaven oprettes, når ingen opgave er tilgængelig til udførelse. Denne opgave kører altid med den laveste prioritet, dvs. 0 prioritet. Hvis vi analyserer timinggrafen, der er angivet ovenfor, kan det ses, at udførelsen starter med en LED-opgave, og den kører i et bestemt tidsrum, og derefter for den resterende tid kører tomgangsopgaven, indtil der opstår en krydsafbrydelse. Derefter beslutter kernen, hvilken opgave der skal udføres i henhold til opgavens prioritet og den samlede forløbne tid for LED-opgaven. Når 1 sekund er afsluttet, vælger kernen den ledede opgave igen til at udføre, fordi den har en højere prioritet end tomgangsopgaven, vi kan også sige, at LED-opgaven forhindrer tomgangsopgaven. Hvis der er mere end to opgaver med samme prioritet, kører de i rund-robin mode i et bestemt tidsrum.
Under tilstandsdiagrammet, da det viser skiftet af den ikke-kørende opgave til kørende tilstand.
Hver nyoprettede opgave går i klar tilstand (del af tilstanden kører ikke). Hvis den oprettede opgave (Task1) har den højeste prioritet end andre opgaver, flyttes den til kørende tilstand. Hvis denne kørende opgave forhindrer den anden opgave, går den tilbage til klar tilstand igen. Ellers hvis task1 er blokeret ved hjælp af blokerende API, vil CPU ikke engagere sig i denne opgave før timeout defineret af brugeren.
Hvis Opgave1 er suspenderet i kørende tilstand ved hjælp af Suspend API'er, går Opgave1 til Suspenderet tilstand, og den er ikke tilgængelig for planlæggeren igen. Hvis du genoptager opgave1 i suspenderet tilstand, går den tilbage til klar tilstand, som du kan se i blokdiagrammet.
Dette er den grundlæggende idé om, hvordan Opgaver kører og ændrer deres tilstande. I denne vejledning implementerer vi to opgaver i Arduino Uno ved hjælp af FreeRTOS API.
Ofte anvendte udtryk i RTOS
1. Opgave: Det er et stykke kode, der kan planlægges på CPU'en at udføre.
2. Planlægning: Den er ansvarlig for at vælge en opgave fra listen over klar tilstand til den kørende tilstand. Planlægningsprogrammer implementeres ofte, så de holder alle computerressourcer optaget (som ved belastningsafbalancering).
3. Indfrielse: Det handler om midlertidigt at afbryde en allerede udførende opgave med det formål at fjerne den fra den kørende tilstand uden dens samarbejde.
4. Kontekstskift: I prioritetsbaseret forudindstilling sammenligner planlæggeren prioriteten for kørende opgaver med en prioritet for klar opgaveliste på hver systickafbrydelse . Hvis der er nogen opgave på listen, hvis prioritet er højere end at køre opgave, forekommer kontekstskift. Dybest set bliver indholdet af forskellige opgaver i denne proces gemt i deres respektive stakhukommelse.
5. Typer af planlægningspolitikker:
- Forebyggende planlægning: I denne type planlægning kører opgaver med samme tidsskive uden at overveje prioriteterne.
- Prioritetsbaseret præemptiv: Opgave med høj prioritet køres først.
- Kooperativ planlægning: Skift af kontekst sker kun med samarbejde om løbende opgaver. Opgaven kører kontinuerligt, indtil opgaveudbyttet kaldes.
6. Kernel Objects: Synkroniseringsprocessen bruges til at signalere opgaven om at udføre noget arbejde. For at udføre denne proces anvendes kernelobjekter. Nogle Kernel-objekter er begivenheder, semaforer, køer, Mutex, postkasser osv. Vi vil se, hvordan man bruger disse objekter i kommende tutorials.
Fra ovenstående diskussion har vi fået nogle grundlæggende ideer om RTOS-konceptet, og nu kan vi implementere FreeRTOS-projektet i Arduino. Så lad os komme i gang med at installere FreeRTOS-biblioteker i Arduino IDE.
Installation af Arduino FreeRTOS-bibliotek
1. Åbn Arduino IDE, og gå til Skitse -> Inkluder bibliotek -> Administrer biblioteker . Søg efter FreeRTOS, og installer biblioteket som vist nedenfor.
Du kan downloade biblioteket fra github og tilføje.zip-filen i Sketch-> Inkluder bibliotek -> Tilføj.zip- fil.
Genstart nu Arduino IDE. Dette bibliotek indeholder nogle eksempler på kode, som også findes i File -> Eksempler -> FreeRTOS som vist nedenfor.
Her skriver vi koden fra bunden for at forstå funktionen, senere kan du kontrollere eksemplets koder og bruge dem.
Kredsløbsdiagram
Nedenfor er kredsløbsdiagrammet til oprettelse af blinkende LED-opgave ved hjælp af FreeRTOS på Arduino:
Arduino FreeRTOS Eksempel - Oprettelse af FreeRTOS-opgaver i Arduino IDE
Lad os se en grundlæggende struktur til at skrive et FreeRTOS-projekt.
1. Inkluder først Arduino FreeRTOS header-fil som
#omfatte
2. Giv funktionsprototypen for alle funktioner, som du skriver til udførelse, der er skrevet som
ugyldig opgave1 (ugyldig * pvParameters); ugyldig opgave2 (ugyldig * pvParameters); .. ….
3. Opret nu opgaver i tomrumsopsætning () -funktionen og start opgaveplanlæggeren.
Til oprettelse af en opgave kaldes xTaskCreate () API i installationsfunktionen med visse parametre / argumenter.
xTaskCreate (TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void * pvParameters, UBaseType_t uxPriority, TaskHandle_t * pxCreatedTask);
Der er 6 argumenter, der skal sendes, mens du opretter en opgave. Lad os se, hvad disse argumenter er
- pvTaskCode: Det er simpelthen en markør til den funktion, der gennemfører opgaven (faktisk bare navnet på funktionen).
- pcName: Et beskrivende navn til opgaven. Dette bruges ikke af FreeRTOS. Det medtages udelukkende til fejlfindingsformål.
- usStackDepth: Hver opgave har sin egen unikke stak, der tildeles af kernen til opgaven, når opgaven oprettes. Værdien angiver antallet af ord, som stakken kan rumme, ikke antallet af byte. For eksempel, hvis stakken er 32 bit bred, og usStackDepth sendes ind som 100, tildeles 400 byte stakplads (100 * 4 byte) i RAM. Brug dette klogt, fordi Arduino Uno kun har 2Kbytes RAM.
- pvParameters: Parameter for opgaveinput (kan være NULL).
- uxPriority: Opgavens prioritet (0 er den laveste prioritet).
- pxCreatedTask: Det kan bruges til at give et håndtag til opgaven, der oprettes. Dette håndtag kan derefter bruges til at henvise til opgaven i API-opkald, der f.eks. Ændrer opgaveprioriteten eller sletter opgaven (kan være NULL).
Eksempel på oprettelse af opgaver
xTaskCreate (opgave1, "opgave1", 128, NULL, 1, NULL); xTaskCreate (task2, "task2", 128, NULL, 2, NULL);
Her har Task2 højere prioritet og udføres derfor først.
4. Efter oprettelsen af opgaven skal du starte planlæggeren i en ugyldig opsætning ved hjælp af vTaskStartScheduler (); API.
5. Void loop () -funktionen forbliver tom, da vi ikke vil køre nogen opgave manuelt og uendeligt. Fordi udførelse af opgave nu håndteres af planlæggeren.
6. Nu skal vi implementere opgavefunktioner og skrive den logik, som du vil udføre inden for disse funktioner. Funktionsnavnet skal være det samme som det første argument for API til xTaskCreate () .
ugyldig opgave1 (ugyldig * pvParameters) { mens (1) { …. din logik } }
7. Det meste af koden har brug for forsinkelsesfunktion for at stoppe den kørende opgave, men i RTOS anbefales det ikke at bruge Delay () -funktionen, da den stopper CPU'en, og derfor stopper RTOS også med at arbejde. Så FreeRTOS har en kerne-API til at blokere opgaven i et bestemt tidspunkt.
vTaskDelay (const TickType_t xTicksToDelay);
Denne API kan bruges til forsinkelsesformål. Denne API forsinker en opgave for et givet antal kryds. Den aktuelle tid, for hvilken opgaven forbliver blokeret, afhænger af krydsraten. Den konstante portTICK_PERIOD_MS kan bruges til at beregne realtid ud fra krydsraten .
Dette betyder, at hvis du vil have en forsinkelse på 200 ms, skal du bare skrive denne linje
vTaskDelay (200 / portTICK_PERIOD_MS);
Så til denne vejledning bruger vi disse FreeRTOS API'er til at implementere tre opgaver.
API'er, der skal bruges:
- xTaskCreate ();
- vTaskStartScheduler ();
- vTaskDelay ();
Opgave, der skal oprettes til denne vejledning:
- LED blinker ved Digital pin 8 med 200 ms frekvens
- LED blinker ved Digital pin 7 med 300 ms frekvens
- Udskriv numre i seriel skærm med 500 ms frekvens.
FreeRTOS opgaveimplementering i Arduino IDE
1. Fra ovenstående grundlæggende strukturforklaring skal du inkludere Arduino FreeRTOS header-fil. Lav derefter funktionsprototyper. Da vi har tre opgaver, så lav tre funktioner, og det er prototyper.
#include void TaskBlink1 (void * pvParameters); ugyldig TaskBlink2 (ugyldig * pvParameters); ugyldigt Taskprint (ugyldigt * pvParameters);
2. I tomrumsopsætning () -funktionen skal du initialisere seriel kommunikation med 9600 bits per sekund og oprette alle tre opgaver ved hjælp af xTaskCreate () API. Oprindeligt skal du prioritere alle opgaver som '1' og starte planlæggeren.
ugyldig opsætning () { 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. Implementér nu alle tre funktioner som vist nedenfor for opgave1 LED blinker.
ugyldig TaskBlink1 (ugyldig * pvParameters) { pinMode (8, OUTPUT); mens (1) { digitalWrite (8, HIGH); vTaskDelay (200 / portTICK_PERIOD_MS); digitalWrite (8, LAV); vTaskDelay (200 / portTICK_PERIOD_MS); } }
På samme måde implementerer du TaskBlink2-funktionen. Task3-funktion skrives som
void Taskprint (void * pvParameters) { int counter = 0; mens (1) { tæller ++; Serial.println (tæller); vTaskDelay (500 / portTICK_PERIOD_MS); } }
Det er det. Vi har gennemført et FreeRTOS Arduino- projekt til Arduino Uno. Du kan finde fuld kode sammen med en video i slutningen af denne vejledning.
Tilslut til sidst to lysdioder ved den digitale pin 7 og 8, og upload koden på dit Arduino-kort, og åbn den serielle skærm. Du vil se, at en tæller kører en gang i 500 ms med opgavens navn som vist nedenfor.
Overhold også lysdioderne, de blinker med forskellige tidsintervaller. Prøv at lege med prioritetsargumentet i xTaskCreate- funktionen. Skift nummeret og følg opførslen på seriel skærm og lysdioder.
Nu kan du forstå de to første eksempelkoder, hvor analoge læsning og digitale læseopgaver oprettes. På denne måde kan du lave flere forhåndsprojekter ved hjælp af kun Arduino Uno og FreeRTOS API'er.