- Ta bort en uppgift i FreeRTOS Arduino
- Vad är kön i FreeRTOS?
- Skapa en kö i FreeRTOS
- Kretsschema
- Implementering av FreeRTOS-kö i Arduino IDE
I föregående handledning introducerade vi FreeRTOS i Arduino Uno och skapade en uppgift för den blinkande lysdioden. Nu, i denna handledning, kommer vi att dyka mer i förväg koncept för RTOS API: er och lära oss om kommunikation mellan olika uppgifter. Här lär vi oss också om kö för att överföra data från en uppgift till en annan och visa hur kö-API: er fungerar genom att koppla ihop 16x2 LCD och LDR med Arduino Uno.
Innan vi diskuterar om köer, låt oss se ytterligare ett FreeRTOS API som är till hjälp för att ta bort uppgifterna när det är klart med det tilldelade arbetet. Ibland måste uppgiften raderas för att frigöra det tilldelade minnet. I fortsättningen av föregående handledning använder vi vTaskDelete () API-funktionen i samma kod för att ta bort en av uppgifterna. En uppgift kan använda vTaskDelete () API-funktionen för att ta bort sig själv eller någon annan uppgift.
För att använda detta API måste du konfigurera FreeRTOSConfig.h- filen. Den här filen används för att skräddarsy FreeRTOS enligt applikationen. Den används för att ändra schemaläggningsalgoritmer och många andra parametrar. Filen finns i Arduino-katalogen som i allmänhet finns i mappen Dokument på din dator. I mitt fall är det tillgängligt i \ Documents \ Arduino \ bibliotek \ FreeRTOS \ src som visas nedan.
Nu, öppna filen med hjälp av en textredigerare och sök efter den #define INCLUDE_vTaskDelete och se till att dess värde är '1' (1 betyder aktivera och 0 betyder inaktivera). Det är 1 som standard men söker efter det.
Vi kommer att använda den här konfigurationsfilen ofta i våra nästa handledning för att ställa in parametrarna.
Låt oss nu se hur du tar bort en uppgift.
Ta bort en uppgift i FreeRTOS Arduino
För att radera en uppgift måste vi använda vTaskDelete () API-funktionen. Det krävs bara ett argument.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Det är handtaget för uppgiften som ska tas bort. Det är samma som det sjätte argumentet för xTaskCreate () API. I föregående handledning är detta argument inställt som NULL men du kan skicka adressen till innehållet i uppgiften med valfritt namn. Låt oss säga om du vill ställa in uppgiftshanteringen för Task2 som deklareras som
TaskHandle_t any_name; Exempel: TaskHandle_t xTask2Handle;
Nu, i vTaskCreate () API ange 6: e argument som
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1, & xTask2Handle);
Nu kan du komma åt innehållet i den här uppgiften med hjälp av handtaget som du har angett.
En uppgift kan också ta bort sig själv genom att skicka NULL istället för ett giltigt uppgiftshanterare.
Om vi vill ta bort uppgift 3 från uppgift 3 själv måste du skriva vTaskDelete (NULL); inuti Task3-funktionen men om du vill ta bort uppgift 3 från uppgift 2, skriv vTaskDelete (xTask3Handle); inuti task2-funktionen.
I tidigare handledningskod, för att ta bort Task2 från själva task2, lägg bara till vTaskDelete (NULL); i ogiltig TaskBlink2 (void * pvParameters) -funktion. Då kommer funktionen ovan att se ut så här
void TaskBlink2 (void * pvParameters) { Serial.println (“Task2 körs och håller på att tas bort”); vTaskDelete (NULL); pinMode (7, OUTPUT); medan (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LÅG); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Ladda nu upp koden och observera lysdioderna och den seriella bildskärmen. Du kommer att se att den andra lysdioden inte blinkar nu och task2 raderas efter att ha stött på borttagnings-API: et.
Så detta API kan användas för att stoppa körningen av den specifika uppgiften.
Låt oss börja med kön.
Vad är kön i FreeRTOS?
Kö är datastrukturen som kan innehålla det begränsade antalet element i fast storlek och den drivs i FIFO-schemat (First-in First-out). Köer ger en uppgift till uppgift, uppgift att avbryta och avbryta till uppgift kommunikationsmekanism.
Det maximala antalet element som köen kan innehålla kallas för ”längd”. Både längden och storleken på varje element ställs in när kön skapas.
Ett exempel på hur kön används för dataöverföring illustreras väl i FreeRTOS-dokumentation som finns här. Du kan lätt förstå det givna exemplet.
Efter att ha förstått köerna, låt oss försöka förstå processen för att skapa en kö och försöka implementera den i vår FreeRTOS-kod.
Skapa en kö i FreeRTOS
Beskriv först det problemuttalande som ska implementeras med hjälp av FreeRTOS-kön och Arduino Uno.
Vi vill skriva ut värdet på LDR-sensorn på 16 * 2 LCD. Så det finns två uppgifter nu
- Uppgift 1 får analoga värden på LDR.
- Task2 skriver ut det analoga värdet på LCD.
Så här spelar kön sin roll för att skicka data som genereras av uppgift1 till uppgift2. I uppgift 1 skickar vi analogt värde till kön och i uppgift 2 får vi det från kön.
Det finns tre funktioner för att arbeta med köer
- Skapa en kö
- Skicka data till kö
- Ta emot data från kö
Använd xQueueCreate () -funktion API för att skapa kö. Det krävs två argument.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: Det maximala antalet objekt som kön som skapas kan innehålla samtidigt.
uxItemSize: Storleken i byte för varje dataobjekt som kan lagras i kön.
Om den här funktionen returnerar NULL skapas inte kön på grund av otillräckligt minne och om den returnerar ett icke-NULL-värde skapas kön framgångsrikt. Lagra detta returvärde till en variabel för att använda det som ett handtag för att komma åt kön enligt nedan.
QueueHandle_t queue1; que1 = xQueueCreate (4, sizeof (int));
Detta skapar en 4-elementskö i heapminne av int-storlek (2 byte i varje block) och lagrar returvärdet till kövariabelns variabel.
2. Skicka data till kö i FreeRTOS
För att skicka värdena till kön har FreeRTOS två varianter av API för detta ändamål.
- xQueueSendToBack (): Används för att skicka data till baksidan (svansen) i en kö.
- xQueueSendToFront (): Används för att skicka data till fronten (huvudet) i en kö.
Nu , xQueueSend () är ekvivalent med, och exakt samma som, xQueueSendToBack ().
Alla dessa API: er tar 3 argument.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Handtaget för kön som data skickas till (skrivs). Denna variabel är densamma som används för att lagra returvärdet för xQueueCreate API.
pvItemToQueue: En pekare till de data som ska kopieras till kön.
xTicksToWait: Den maximala tid som uppgiften ska vara kvar i blockerat tillstånd för att vänta på att utrymme blir tillgängligt i kön.
Att ställa in xTicksToWait till portMAX_DELAY kommer att göra att uppgiften väntar på obestämd tid (utan tidsgräns), förutsatt att INCLUDE_vTaskSuspend är inställd på 1 i FreeRTOSConfig. Annars kan du använda makrot pdMS_TO_TICKS () för att konvertera en tid som anges i millisekunder till en tid som anges i fästingar.
3. Ta emot data från kö i FreeRTOS
För att ta emot (läsa) ett objekt från en kö används xQueueReceive (). Objektet som tas emot tas bort från kön.
Detta API tar också tre argument.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Första och tredje argument är desamma som att skicka API. Endast det andra argumentet är annorlunda.
const pvBuffer: En pekare till minnet till vilket mottagen data kommer att kopieras.
Hoppas att du förstod de tre API: erna. Nu kommer vi att implementera dessa API: er i Arduino IDE och försöka lösa problemförklaringen som vi har beskrivit ovan.
Kretsschema
Så här ser det ut på panelen:
Implementering av FreeRTOS-kö i Arduino IDE
Låt oss börja skriva kod för vår ansökan.
1. Öppna först Arduino IDE och inkludera rubrikfilen Arduino_FreeRTOS.h . Nu, om något kärnobjekt som kö används, inkludera sedan rubrikfilen för det. Eftersom vi använder 16 * 2 LCD så inkludera biblioteket för det också.
# inkludera # inkludera
2. Initiera ett köhandtag för att lagra innehållet i kön. Initiera också LCD-stiftnummer.
QueueHandle_t queue_1; LiquidCrystal lcd (7, 8, 9, 10, 11, 12);
3. I ogiltig inställning (), initialisera LCD och seriell bildskärm med 9600 baudhastighet. Skapa en kö och två uppgifter med respektive API: er. Här skapar vi en kö av storlek 4 med heltalstyp. Skapa en uppgift med lika prioriteringar och försök senare spela med detta nummer. Slutligen starta schemaläggaren enligt nedan.
ogiltig installation () { Serial.begin (9600); lcd.begin (16, 2); que_1 = xQueueCreate (4, sizeof (int)); if (queue_1 == NULL) { Serial.println ("Kön kan inte skapas"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Gör nu två funktioner TaskDisplay och TaskLDR . I TaskLDR- funktionen, läs den analoga stift A0 i en variabel eftersom vi har LDR ansluten till A0-stiftet i Arduino UNO. Skicka nu värdet som är lagrat i variabeln genom att skicka det i xQueueSend API och skicka uppgiften till blocktillstånd efter 1 sekund med vTaskDelay () API som visas nedan.
void TaskLDR (void * pvParameters) { int current_intensity; medan (1) { Serial.println ("Task1"); current_intensity = analogRead (A0); Serial.println (aktuell_intensitet); xQueueSend (que_1, & aktuell_intensitet, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. På samma sätt gör du en funktion för TaskDisplay och får värdena i en variabel som skickas till xQueueReceive- funktionen. Också, xQueueReceive () returnerar pdPASS om data kan tas emot med framgång från kön och returnerar errQUEUE_EMPTY om en kö är tom.
Visa nu värdena på LCD-skärmen med lcd.print () -funktionen.
void TaskDisplay (void * pvParameters) { int-intensitet = 0; medan (1) { Serial.println ("Task2"); om (xQueueReceive (queue_1, & intensitet, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intensitet:"); lcd.setCursor (11, 0); lcd.print (intensitet); } } }
Det är allt. Vi har avslutat kodningsdelen av köimplementeringen. Komplett kod med en fungerande video finns i slutet.
Anslut nu LCD och LDR med Arduino UNO enligt kretsschemat ladda upp koden. Öppna den seriella bildskärmen och observera uppgifterna. Du kommer att se att uppgifter växlar och LDR-värden ändras beroende på ljusintensiteten.
OBS! De flesta bibliotek som tillverkats för olika sensorer stöds inte av FreeRTOS-kärnan på grund av fördröjning av funktionens implementering i biblioteken. Fördröjning gör att CPU slutar helt, därför slutar FreeRTOS-kärnan också att fungera och koden kommer inte att köras längre och det börjar inte fungera. Så vi måste göra biblioteken förseningsfria för att arbeta med FreeRTOS.