- Slette en oppgave i FreeRTOS Arduino
- Hva er køen i FreeRTOS?
- Opprette en kø i FreeRTOS
- Kretsdiagram
- Implementering av FreeRTOS-kø i Arduino IDE
I forrige opplæring introduserte vi FreeRTOS i Arduino Uno og opprettet en oppgave for den blinkende LED-en. Nå, i denne veiledningen, vil vi dykke mer i forhåndskonsepter for RTOS APIer og lære om kommunikasjon mellom forskjellige oppgaver. Her lærer vi også om kø for å overføre data fra en oppgave til en annen og demonstrere hvordan API-programmer fungerer ved å koble 16x2 LCD og LDR til Arduino Uno.
Før vi diskuterer om køer, la oss se en FreeRTOS API til som er nyttig for å slette oppgavene når den er ferdig med det tildelte arbeidet. Noen ganger må oppgaven slettes for å frigjøre det tildelte minnet. I fortsettelse av forrige opplæring vil vi bruke vTaskDelete () API-funksjon i samme kode for å slette en av oppgavene. En oppgave kan bruke vTaskDelete () API-funksjonen til å slette seg selv, eller en hvilken som helst annen oppgave.
For å bruke denne API-en, må du konfigurere FreeRTOSConfig.h- filen. Denne filen brukes til å skreddersy FreeRTOS i henhold til applikasjonen. Den brukes til å endre planleggingsalgoritmene og mange andre parametere. Filen finnes i Arduino-katalogen, som vanligvis er tilgjengelig i Dokumenter-mappen på din PC. I mitt tilfelle er den tilgjengelig i \ Documents \ Arduino \ biblioteker \ FreeRTOS \ src som vist nedenfor.
Nå åpner denne filen med et tekstredigeringsprogram og søk etter den #define INCLUDE_vTaskDelete og sørge for at verdien er '1' (1 betyr aktivere og 0 betyr deaktivere). Det er 1 som standard, men ser etter det.
Vi bruker denne konfigurasjonsfilen ofte i de neste veiledningene våre for å sette parametrene.
La oss nå se hvordan du sletter en oppgave.
Slette en oppgave i FreeRTOS Arduino
For å slette en oppgave, må vi bruke vTaskDelete () API-funksjonen. Det tar bare ett argument.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Det er håndtaket for oppgaven som skal slettes. Det er den samme som den 6 th argumentet av xTaskCreate () API. I forrige opplæring er dette argumentet satt som NULL, men du kan sende adressen til innholdet i oppgaven ved å bruke hvilket som helst navn. La oss si hvis du vil sette oppgavehåndtak for Task2 som er erklært som
TaskHandle_t any_name; Eksempel: TaskHandle_t xTask2Handle;
Nå, i vTaskCreate () API satt 6 th argument
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1, & xTask2Handle);
Innholdet i denne oppgaven kan nå nås ved hjelp av håndtaket du har gitt.
En oppgave kan også slette seg selv ved å sende NULL i stedet for et gyldig oppgavehåndtak.
Hvis vi ønsker å slette oppgave 3 fra selve oppgave 3, må du skrive vTaskDelete (NULL); inne i Task3-funksjonen, men hvis du vil slette oppgave 3 fra oppgave 2, skriv vTaskDelete (xTask3Handle); inne i task2-funksjonen.
I forrige opplæringskode, for å slette Task2 fra oppgave2, er det bare å legge til vTaskDelete (NULL); i ugyldig TaskBlink2 (void * pvParameters) -funksjon. Da vil funksjonen ovenfor se slik ut
ugyldig TaskBlink2 (void * pvParameters) { Serial.println (“Task2 kjører og er i ferd med å slettes”); vTaskDelete (NULL); pinMode (7, OUTPUT); mens (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LAV); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Last nå opp koden og følg lysdioder og seriell skjerm. Du vil se at den andre LED-en ikke blinker nå, og task2 blir slettet etter å ha møtt slettings-API.
Så dette API-et kan brukes til å stoppe utførelsen av den aktuelle oppgaven.
La oss starte med køen.
Hva er køen i FreeRTOS?
Kø er datastrukturen som kan inneholde et endelig antall faste størrelseselementer, og den drives i FIFO-ordningen (First-in First-out). Køer gir en oppgave-til-oppgave, oppgave-å-avbryte og avbryte-til-oppgave-kommunikasjonsmekanisme.
Maksimalt antall elementer som køen kan inneholde kalles "lengde". Både lengden og størrelsen på hvert element blir angitt når køen opprettes.
Et eksempel på hvordan køen brukes til dataoverføring illustreres godt i FreeRTOS-dokumentasjon som du finner her. Du kan lett forstå det gitte eksemplet.
Etter å ha forstått køene, la oss prøve å forstå prosessen med å opprette en kø og prøve å implementere den i FreeRTOS-koden vår.
Opprette en kø i FreeRTOS
Beskriv først problemstillingen som skal implementeres ved hjelp av FreeRTOS-køen og Arduino Uno.
Vi ønsker å skrive ut verdien til LDR-sensoren på 16 * 2 LCD. Så det er to oppgaver nå
- Oppgave1 får analoge verdier av LDR.
- Task2 skriver ut den analoge verdien på LCD.
Så, her spiller køen sin rolle fordi å sende data generert av oppgave1 til oppgave2. I oppgave1 vil vi sende analog verdi til køen, og i oppgave2 vil vi motta den fra køen.
Det er tre funksjoner for å jobbe med køer
- Opprette en kø
- Sender data til kø
- Motta data fra kø
For å opprette kø, bruk xQueueCreate () funksjon API. Det tar to argumenter.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: Maksimalt antall elementer som køen som opprettes kan inneholde til enhver tid.
uxItemSize: Størrelsen i byte for hvert dataelement som kan lagres i køen.
Hvis denne funksjonen returnerer NULL, opprettes ikke køen på grunn av utilstrekkelig minne, og hvis den returnerer en verdi som ikke er NULL, opprettes køen. Lagre denne returverdien til en variabel for å bruke den som et håndtak for å få tilgang til køen som vist nedenfor.
KøHåndter_kø1; que1 = xQueueCreate (4, sizeof (int));
Dette vil opprette en 4-elementskø i heapminne av int-størrelse (2 byte i hver blokk) og lagre returverdien til kø1- håndtaksvariabelen.
2. Sende data til kø i FreeRTOS
For å sende verdiene til køen har FreeRTOS to varianter av API for dette formålet.
- xQueueSendToBack (): Brukes til å sende data til baksiden (halen) i en kø.
- xQueueSendToFront (): Brukes til å sende data til fronten (hodet) i en kø.
Nå , xQueueSend () er tilsvarende til, og nøyaktig den samme som, xQueueSendToBack ().
Alle disse API-ene tar 3 argumenter.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Håndtaket til køen som dataene sendes til (skrives). Denne variabelen er den samme som brukes til å lagre returverdien til xQueueCreate API.
pvItemToQueue: En peker til dataene som skal kopieres til køen.
xTicksToWait: Maksimum tid tiden oppgaven skal forbli i Blokkert-tilstand for å vente på at plass blir ledig i køen.
Hvis du setter xTicksToWait til portMAX_DELAY, vil oppgaven vente på ubestemt tid (uten tidsavbrudd ), forutsatt at INCLUDE_vTaskSuspend er satt til 1 i FreeRTOSConfig.h ellers kan du bruke makroen pdMS_TO_TICKS () til å konvertere en tid spesifisert i millisekunder til en tid spesifisert i flått.
3. Motta data fra kø i FreeRTOS
For å motta (lese) et element fra en kø, brukes xQueueReceive (). Varen som mottas fjernes fra køen.
Denne API-en tar også tre argumenter.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Første og tredje argument er det samme som å sende API. Bare det andre argumentet er annerledes.
const pvBuffer: En peker til minnet som mottatte data blir kopiert til.
Håper du forsto de tre API-ene. Nå skal vi implementere disse API-ene i Arduino IDE og prøve å løse problemstillingen som vi har beskrevet ovenfor.
Kretsdiagram
Slik ser det ut på brødplaten:
Implementering av FreeRTOS-kø i Arduino IDE
La oss begynne å skrive kode for applikasjonen vår.
1. Først åpner du Arduino IDE og inkluderer toppfilen Arduino_FreeRTOS.h . Nå, hvis noe kjerneobjekt som kø blir brukt, inkluderer du toppfilen til den. Når vi bruker 16 * 2 LCD, inkluder også biblioteket for det.
# inkluderer # inkluderer
2. Initialiser et køhåndtak for å lagre innholdet i køen. Initialiser også LCD-pin-tall.
QueHandle_t queue_1; LiquidCrystal lcd (7, 8, 9, 10, 11, 12);
3. I ugyldig oppsett (), initialiser LCD og seriell skjerm med 9600 baud rate. Opprett en kø og to oppgaver ved hjelp av de respektive API-ene. Her vil vi lage en kø i størrelse 4 med heltallstype. Lag en oppgave med like prioriteringer, og prøv senere å leke med dette tallet. Til slutt starter du planleggeren som vist nedenfor.
ugyldig oppsett () { Serial.begin (9600); lcd.begin (16, 2); que_1 = xQueueCreate (4, sizeof (int)); hvis (queue_1 == NULL) { Serial.println ("Kø kan ikke opprettes"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Lag nå to funksjoner TaskDisplay og TaskLDR . I TaskLDR- funksjon, les analog pin A0 i en variabel som vi har LDR koblet til A0 pin av Arduino UNO. Send nå verdien som er lagret i variabelen ved å sende den i xQueueSend API og send oppgaven til blokkeringstilstand etter 1 sekund ved hjelp av vTaskDelay () API som vist nedenfor.
ugyldig TaskLDR (ugyldig * pvParameters) { int gjeldende intensitet; mens (1) { Serial.println ("Task1"); current_intensity = analogRead (A0); Serial.println (nåværende intensitet); xQueueSend (queue_1, & current_intensity, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. Tilsvarende lager du en funksjon for TaskDisplay og mottar verdiene i en variabel som sendes til xQueueReceive- funksjonen. Dessuten returnerer xQueueReceive () pdPASS hvis dataene kan mottas fra køen, og returnerer errQUEUE_EMPTY hvis en kø er tom.
Vis nå verdiene på LCD-skjermen ved hjelp av lcd.print () -funksjonen.
ugyldig TaskDisplay (void * pvParameters) { int-intensitet = 0; mens (1) { Serial.println ("Task2"); hvis (xQueueReceive (queue_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 er ferdig med kodingsdelen av køimplementeringen. Komplett kode med en fungerende video finner du på slutten.
Nå kobler du LCD og LDR til Arduino UNO i henhold til kretsskjemaet, last opp koden. Åpne den serielle skjermen og følg oppgavene. Du vil se at oppgaver bytter og LDR-verdier endres i henhold til lysintensiteten.
MERK: De fleste biblioteker laget for forskjellige sensorer støttes ikke av FreeRTOS-kjernen på grunn av forsinket implementering av funksjonene i bibliotekene. Forsinkelse gjør at CPU-en stopper helt, derfor slutter FreeRTOS-kjernen også å fungere, og koden vil ikke kjøres lenger, og den begynner å oppføre seg feil. Så vi må gjøre bibliotekene forsinkelsesfrie for å jobbe med FreeRTOS.