- Sletning af en opgave i FreeRTOS Arduino
- Hvad er køen i FreeRTOS?
- Oprettelse af en kø i FreeRTOS
- Kredsløbsdiagram
- Implementering af FreeRTOS-kø i Arduino IDE
I den foregående vejledning introducerede vi FreeRTOS i Arduino Uno og oprettede en opgave til den blinkende LED. Nu, i denne vejledning, dykker vi mere ind i forhåndskoncepter for RTOS API'er og lærer om kommunikation mellem forskellige opgaver. Her lærer vi også om kø for at overføre data fra en opgave til en anden og demonstrere funktionen af kø-API'er ved at grænseflade 16x2 LCD og LDR med Arduino Uno.
Før vi diskuterer om køer, lad os se en FreeRTOS API mere, som er nyttig til at slette opgaverne, når den er færdig med det tildelte arbejde. Nogle gange skal opgaven slettes for at frigøre den tildelte hukommelse. I forlængelse af den foregående tutorial bruger vi vTaskDelete () API-funktionen i den samme kode til at slette en af opgaverne. En opgave kan bruge vTaskDelete () API-funktionen til at slette sig selv eller enhver anden opgave.
For at bruge denne API skal du konfigurere FreeRTOSConfig.h- filen. Denne fil bruges til at skræddersy FreeRTOS i henhold til applikationen. Det bruges til at ændre planlægningsalgoritmerne og mange andre parametre. Filen findes i Arduino Directory, som generelt er tilgængelig i Dokumenter-mappen på din pc. I mit tilfælde er det tilgængeligt i \ Documents \ Arduino \ biblioteker \ FreeRTOS \ src som vist nedenfor.
Nu skal du åbne denne fil med en teksteditor og søge efter den # define INCLUDE_vTaskDelete og sørg dens værdi er '1' (1 betyder aktivere og 0 betyder deaktivere). Det er som standard 1, men kontrollerer for det.
Vi bruger ofte denne konfigurationsfil i vores næste selvstudier til indstilling af parametrene.
Lad os nu se, hvordan du sletter en opgave.
Sletning af en opgave i FreeRTOS Arduino
For at slette en opgave skal vi bruge vTaskDelete () API-funktionen. Det kræver kun et argument.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Det er håndtaget til opgaven, der skal slettes. Det er det samme som 6 th argument xTaskCreate () API. I den foregående vejledning er dette argument indstillet til NULL, men du kan videregive adressen på opgavens indhold ved hjælp af ethvert navn. Lad os sige, hvis du vil indstille opgavehåndtag til Task2, der erklæres som
TaskHandle_t any_name; Eksempel: TaskHandle_t xTask2Handle;
Nu, i vTaskCreate () API sæt 6 th argument
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1, & xTask2Handle);
Nu kan du få adgang til indholdet af denne opgave ved hjælp af det håndtag, du har givet.
En opgave kan også slette sig selv ved at sende NULL i stedet for et gyldigt opgavehåndtag.
Hvis vi ønsker at slette opgave 3 fra selve opgave 3, skal du skrive vTaskDelete (NULL); inde i Task3-funktionen, men hvis du vil slette opgave 3 fra opgave 2, skal du skrive vTaskDelete (xTask3Handle); inde i task2-funktionen.
I forrige tutorial-kode skal du blot tilføje vTaskDelete (NULL) for at slette Task2 fra selve task2; i ugyldig TaskBlink2 (void * pvParameters) -funktion. Derefter vil ovenstående funktion se sådan ud
ugyldig TaskBlink2 (ugyldig * pvParameters) { Serial.println (“Task2 kører og ved at blive slettet”); vTaskDelete (NULL); pinMode (7, OUTPUT); mens (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LAV); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Upload nu koden, og følg lysdioderne og den serielle skærm. Du vil se, at den anden lysdiode ikke blinker nu, og task2 slettes efter stød på slette-API'et.
Så denne API kan bruges til at stoppe udførelsen af den bestemte opgave.
Lad os starte med køen.
Hvad er køen i FreeRTOS?
Kø er datastrukturen, der kan rumme det endelige antal faste størrelseselementer, og den drives i FIFO-ordningen (First-in First-out). Køer giver en opgave-til-opgave, opgave at afbryde og afbryde-til-opgave kommunikationsmekanisme.
Det maksimale antal elementer, som køen kan indeholde, kaldes dens "længde". Både længden og størrelsen på hvert element indstilles, når køen oprettes.
Et eksempel på, hvordan køen bruges til dataoverførsel, illustreres godt i FreeRTOS-dokumentation, som kan findes her. Du kan let forstå det givne eksempel.
</s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s>Efter at have forstået køerne, lad os prøve at forstå processen med at oprette en kø og prøve at implementere den i vores FreeRTOS-kode.
Oprettelse af en kø i FreeRTOS
Beskriv først problemopgørelsen, der skal implementeres ved hjælp af FreeRTOS-køen og Arduino Uno.
Vi ønsker at udskrive værdien af LDR-sensoren på 16 * 2 LCD. Så der er to opgaver nu
- Opgave1 får analoge værdier for LDR.
- Task2 udskriver den analoge værdi på LCD.
Så her spiller køen sin rolle, fordi de data, der genereres af opgave1, sendes til opgave2. I task1 sender vi analog værdi til køen, og i task2 modtager vi den fra køen.
Der er tre funktioner til at arbejde med køer
- Oprettelse af en kø
- Afsendelse af data til kø
- Modtagelse af data fra kø
Brug xQueueCreate () -funktion API til at oprette kø. Det kræver to argumenter.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: Det maksimale antal elementer, som køen, der oprettes, kan indeholde ad gangen.
uxItemSize: Størrelsen i bytes for hvert dataelement, der kan gemmes i køen.
Hvis denne funktion returnerer NULL, oprettes køen ikke på grund af utilstrækkelig hukommelse, og hvis den returnerer en ikke-NULL-værdi, oprettes køen med succes. Gem denne returværdi i en variabel for at bruge den som et håndtag for at få adgang til køen som vist nedenfor.
KøHåndter_kø1; que1 = xQueueCreate (4, sizeof (int));
Dette opretter en 4-elementskø i heap-hukommelse med int-størrelse (2 bytes af hver blok) og gemmer returværdien til kø1- håndtagsvariablen.
2. Afsendelse af data til kø i FreeRTOS
For at sende værdierne til køen har FreeRTOS 2 varianter af API til dette formål.
- xQueueSendToBack (): Bruges til at sende data til bagsiden (halen) i en kø.
- xQueueSendToFront (): Bruges til at sende data til fronten (hovedet) af en kø.
Nu , xQueueSend () svarer til, og præcis det samme som, xQueueSendToBack ().
Alle disse API'er tager 3 argumenter.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Håndtaget til den kø, som dataene sendes til (skrevet). Denne variabel er den samme som bruges til at gemme returværdien af xQueueCreate API.
pvItemToQueue: En markør til de data, der skal kopieres til køen.
xTicksToWait: Det maksimale tidsrum, som opgaven skal forblive i blokeret tilstand for at vente på, at der bliver plads i køen.
Indstilling af xTicksToWait til portMAX_DELAY får opgaven til at vente på ubestemt tid (uden tidsindstilling), forudsat at INCLUDE_vTaskSuspend er indstillet til 1 i FreeRTOSConfig. Ellers kan du bruge makroen pdMS_TO_TICKS () til at konvertere en tid specificeret i millisekunder til en tid, der er angivet i kryds.
3. Modtagelse af data fra kø i FreeRTOS
For at modtage (læse) et element fra en kø bruges xQueueReceive (). Det element, der modtages, fjernes fra køen.
Denne API tager også tre argumenter.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Første og tredje argument er det samme som at sende API. Kun det andet argument er anderledes.
const pvBuffer: En markør til hukommelsen, hvortil de modtagne data kopieres.
Håber du har forstået de tre API'er. Nu implementerer vi disse API'er i Arduino IDE og forsøger at løse den problemstilling, som vi har beskrevet ovenfor.
Kredsløbsdiagram
Sådan ser det ud på brødbrættet:
Implementering af FreeRTOS-kø i Arduino IDE
Lad os begynde at skrive kode til vores ansøgning.
1. Åbn først Arduino IDE og inkluder Arduino_FreeRTOS.h headerfilen. Nu, hvis der anvendes et kerneobjekt som kø, skal du inkludere headerfilen af det. Da vi bruger 16 * 2 LCD, skal du også medtage biblioteket til det.
# inkluderer # inkluderer
2. Initialiser et køhåndtag for at gemme køens indhold. Initialiser også LCD-pin-numre.
QueueHandle_t que_1; LiquidCrystal lcd (7, 8, 9, 10, 11, 12);
3. I ugyldig opsætning () initialiseres LCD og seriel skærm med 9600 baudrate. Opret en kø og to opgaver ved hjælp af de respektive API'er. Her opretter vi en kø i størrelse 4 med heltalstype. Opret en opgave med lige prioriteter, og prøv senere at lege med dette nummer. Endelig skal du starte planlæggeren som vist nedenfor.
ugyldig opsætning () { Serial.begin (9600); lcd.begin (16, 2); que_1 = xQueueCreate (4, sizeof (int)); hvis (queue_1 == NULL) { Serial.println ("Kø kan ikke oprettes"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Lav nu to funktioner TaskDisplay og TaskLDR . I TaskLDR- funktion skal du læse den analoge pin A0 i en variabel, da vi har LDR tilsluttet A0-stiften i Arduino UNO. Send nu den værdi, der er gemt i variablen, ved at sende den i xQueueSend API og send opgaven til blokeringstilstand efter 1 sekund ved hjælp af vTaskDelay () API som vist nedenfor.
ugyldig TaskLDR (ugyldig * pvParameters) { int nuværende_intensitet; mens (1) { Serial.println ("Task1"); strøm_intensitet = analogRead (A0); Serial.println (nuværende_intensitet); xQueueSend (kø_1, & nuværende_intensitet, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. Tilsvarende lav en funktion til TaskDisplay og modtag værdierne i en variabel, der sendes til xQueueReceive- funktionen. Også xQueueReceive () returnerer pdPASS hvis dataene kan modtages med succes fra køen og returnerer errQUEUE_EMPTY hvis en kø er tom.
Vis nu værdierne på LCD'et ved hjælp af lcd.print () -funktionen.
ugyldigt TaskDisplay (ugyldigt * pvParameters) { int-intensitet = 0; mens (1) { Serial.println ("Task2"); hvis (xQueueReceive (kø_1, & intensitet, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intensitet:"); lcd.setCursor (11, 0); lcd.print (intensitet); } } }
Det er det. Vi har afsluttet kodningsdelen af køimplementering. Komplet kode med en fungerende video kan findes i slutningen.
Tilslut nu LCD og LDR med Arduino UNO i henhold til kredsløbsdiagrammet upload koden. Åbn den serielle skærm, og følg opgaverne. Du vil se, at opgaver skifter, og LDR-værdier ændres i henhold til lysintensiteten.
BEMÆRK: De fleste biblioteker, der er lavet til forskellige sensorer, understøttes ikke af FreeRTOS-kernen på grund af forsinket implementering af funktion inden i bibliotekerne. Forsinkelse får CPU'en til at stoppe fuldstændigt, derfor holder FreeRTOS-kernen også op med at arbejde, og koden udføres ikke længere, og den begynder at opføre sig forkert. Så vi er nødt til at gøre bibliotekerne forsinkelsesfri for at arbejde med FreeRTOS.