- Smazání úkolu ve FreeRTOS Arduino
- Co je to fronta ve FreeRTOS?
- Vytvoření fronty ve FreeRTOS
- Kruhový diagram
- Implementace fronty FreeRTOS v Arduino IDE
V předchozím tutoriálu jsme představili FreeRTOS v Arduino Uno a vytvořili úkol pro blikající LED. Nyní se v tomto výukovém programu ponoříme více do pokročilých konceptů rozhraní RTOS API a naučíme se komunikaci mezi různými úkoly. Zde se také dozvídáme o frontě pro přenos dat z jednoho úkolu do druhého a předvedeme fungování API fronty propojením 16x2 LCD a LDR s Arduino Uno.
Než budeme diskutovat o frontách, podívejme se ještě na jedno FreeRTOS API, které je užitečné při mazání úkolů po dokončení přidělené práce. Někdy je třeba úlohu uvolnit, aby se uvolnila přidělená paměť. V pokračování předchozího kurzu použijeme funkci API vTaskDelete () ve stejném kódu k odstranění jedné z úloh. Úkol může použít funkci API vTaskDelete () k odstranění samotného nebo jiného úkolu.
Chcete-li použít toto API, musíte nakonfigurovat soubor FreeRTOSConfig.h . Tento soubor se používá k přizpůsobení FreeRTOS podle aplikace. Používá se ke změně plánovacích algoritmů a mnoha dalších parametrů. Soubor naleznete v adresáři Arduino Directory, který je obecně k dispozici ve složce Documents ve vašem počítači. V mém případě je k dispozici v \ Documents \ Arduino \ libraries \ FreeRTOS \ src, jak je uvedeno níže.
Nyní otevřete tento soubor pomocí libovolného textového editoru a hledat na #define INCLUDE_vTaskDelete a ujistěte se, že jeho hodnota je ‚1‘(1 znamená povolit a 0 znamená zakázat). Ve výchozím nastavení je to 1, ale kontroluje to.
Tento konfigurační soubor budeme často používat v našich dalších cvičeních pro nastavení parametrů.
Nyní se podívejme, jak odstranit úkol.
Smazání úkolu ve FreeRTOS Arduino
K odstranění úkolu musíme použít funkci API vTaskDelete (). Vyžaduje to jen jeden argument.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Je to popisovač úkolu, který má být odstraněn. Je to stejné, jako 6 -tého argumentu xTaskCreate () API. V předchozím kurzu je tento argument nastaven jako NULL, ale můžete předat adresu obsahu úkolu pomocí libovolného názvu. Řekněme, že chcete nastavit popisovač úkolu pro Task2, který je deklarován jako
TaskHandle_t any_name; Příklad: TaskHandle_t xTask2Handle;
Nyní, v vTaskCreate () API set 6 th argumentů as
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1, & xTask2Handle);
K obsahu tohoto úkolu lze nyní přistupovat pomocí vámi zadaného úchytu.
Úkol se také může sám odstranit předáním hodnoty NULL namísto platného popisovače úkolu.
Pokud chceme odstranit úkol 3 ze samotného úkolu 3, musíte napsat vTaskDelete (NULL); uvnitř funkce Task3, ale pokud chcete odstranit úkol 3 z úkolu 2, napište vTaskDelete (xTask3Handle); uvnitř funkce task2.
V předchozím kódu tutoriálu, chcete-li odstranit Task2 ze samotného task2, stačí přidat vTaskDelete (NULL); ve funkci void TaskBlink2 (void * pvParameters) . Pak bude výše uvedená funkce vypadat takto
void TaskBlink2 (void * pvParameters) { Serial.println („Task2 je spuštěn a chystá se smazat“); vTaskDelete (NULL); pinMode (7, VÝSTUP); while (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LOW); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Nyní nahrajte kód a sledujte LED diody a sériový monitor. Uvidíte, že druhá LED nyní nebliká a task2 je odstraněn po setkání s API pro mazání.
Toto API lze tedy použít k zastavení provádění konkrétního úkolu.
Začněme s frontou.
Co je to fronta ve FreeRTOS?
Fronta je datová struktura, která pojme konečný počet prvků pevné velikosti a je provozována ve schématu FIFO (First-in First-out). Fronty poskytují komunikační mechanismus úkol-úkol, úkol-přerušit a přerušit úkol.
Maximální počet prvků, které může fronta obsahovat, se nazývá její „délka“. Při vytváření fronty se nastavuje délka i velikost každého prvku.
Příklad toho, jak se fronta používá pro přenos dat, je dobře ilustrován v dokumentaci FreeRTOS, kterou najdete zde. Daný příklad můžete snadno pochopit.
Zloženie: 100% bavlna.Po porozumění frontám se pokusíme porozumět procesu vytváření fronty a pokusíme se ji implementovat do našeho kódu FreeRTOS.
Vytvoření fronty ve FreeRTOS
Nejprve popište problémové prohlášení, které má být implementováno pomocí fronty FreeRTOS a Arduino Uno.
Chceme vytisknout hodnotu snímače LDR na 16 * 2 LCD. Nyní tedy existují dva úkoly
- Úkolem 1 je získávání analogových hodnot LDR.
- Úkolem 2 je tisk analogové hodnoty na LCD.
Zde tedy hraje svoji roli fronta, protože k odesílání dat vygenerovaných úkolem1 na úkol2. V task1 pošleme analogovou hodnotu do fronty a v task2 ji obdržíme z fronty.
Existují tři funkce pro práci s frontami
- Vytvoření fronty
- Odesílání dat do fronty
- Příjem dat z fronty
Pro vytvoření fronty použijte rozhraní API funkce xQueueCreate (). Vyžadují se dva argumenty.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: Maximální počet položek, které může vytvářená fronta pojmout najednou.
uxItemSize: Velikost v bajtech každé datové položky, kterou lze uložit do fronty.
Pokud tato funkce vrací NULL, fronta se nevytvoří kvůli nedostatku paměti a pokud vrátí hodnotu, která nemá NULL, fronta se vytvoří úspěšně. Uložte tuto návratovou hodnotu do proměnné a použijte ji jako popisovač pro přístup do fronty, jak je znázorněno níže.
QueueHandle_t fronta1; queue1 = xQueueCreate (4, sizeof (int));
Tím se vytvoří fronta se 4 prvky v haldě paměti velikosti int (2 bajty každého bloku) a návratová hodnota se uloží do proměnné popisovače queue1 .
2. Odesílání dat do fronty ve FreeRTOS
K odeslání hodnot do fronty má FreeRTOS pro tento účel 2 varianty API.
- xQueueSendToBack (): Používá se k odesílání dat do zadní části (fronty) fronty.
- xQueueSendToFront (): Používá se k odesílání dat do fronty fronty.
Nyní je xQueueSend () ekvivalentní a přesně stejný jako xQueueSendToBack ().
Všechna tato rozhraní API mají 3 argumenty.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Popisovač fronty, do které se data odesílají (zapisují). Tato proměnná je stejná jako použitá k uložení návratové hodnoty rozhraní xQueueCreate API.
pvItemToQueue: Ukazatel na data, která mají být zkopírována do fronty.
xTicksToWait: Maximální doba, po kterou by měl úkol zůstat ve stavu Blokováno, aby se počkalo, až bude ve frontě k dispozici místo.
Nastavení xTicksToWait na portMAX_DELAY způsobí, že úkol bude čekat neomezeně dlouho (bez časování), pokud je INCLUDE_vTaskSuspend nastaveno na 1 ve FreeRTOSConfig. Jinak můžete použít makro pdMS_TO_TICKS () k převodu času uvedeného v milisekundách na čas určený v klíšťatech.
3. Příjem dat z fronty ve FreeRTOS
Pro příjem (čtení) položky z fronty se používá xQueueReceive (). Přijatá položka je odstraněna z fronty.
Toto API má také tři argumenty.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
První a třetí argument jsou stejné jako odesílání API. Pouze druhý argument je jiný.
const pvBuffer: Ukazatel na paměť, do které budou přijata data zkopírována.
Doufám, že jste pochopili tři API. Nyní implementujeme tato API do Arduino IDE a pokusíme se vyřešit problémové prohlášení, které jsme popsali výše.
Kruhový diagram
Takto to vypadá na prkénku:
Implementace fronty FreeRTOS v Arduino IDE
Začněme psát kód pro naši aplikaci.
1. Nejprve otevřete Arduino IDE a vložte soubor záhlaví Arduino_FreeRTOS.h . Nyní, pokud se používá jakýkoli objekt jádra, jako je fronta, zahrňte jeho záhlaví. Protože používáme 16 * 2 LCD, zahrňte pro něj také knihovnu.
# zahrnout # zahrnout
2. Inicializujte popisovač fronty pro uložení obsahu fronty. Inicializujte také čísla pinů LCD.
QueueHandle_t queue_1; LiquidCrystal lcd (7, 8, 9, 10, 11, 12);
3. V nastavení void () inicializujte LCD a sériový monitor s přenosovou rychlostí 9600. Vytvořte frontu a dvě úlohy pomocí příslušných API. Zde vytvoříme frontu velikosti 4 s celočíselným typem. Vytvořte úkol se stejnými prioritami a později se pokuste hrát s tímto číslem. Nakonec spusťte plánovač, jak je znázorněno níže.
void setup () { Serial.begin (9600); lcd.begin (16, 2); queue_1 = xQueueCreate (4, sizeof (int)); if (queue_1 == NULL) { Serial.println ("Frontu nelze vytvořit"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Nyní vytvořte dvě funkce TaskDisplay a TaskLDR . Ve funkci TaskLDR načtěte analogový pin A0 v proměnné, protože máme LDR připojený k pinu A0 Arduino UNO. Nyní odešlete hodnotu uloženou v proměnné předáním v rozhraní xQueueSend API a odešlete úkol do stavu blokování po 1 sekundě pomocí rozhraní vTaskDelay () API, jak je uvedeno níže.
void TaskLDR (void * pvParameters) { int current_intensity; while (1) { Serial.println ("Task1"); current_intensity = analogRead (A0); Serial.println (current_intensity); xQueueSend (queue_1, & current_intensity, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. Podobně vytvořte funkci pro TaskDisplay a přijímejte hodnoty v proměnné, která je předána funkci xQueueReceive . Také xQueueReceive () vrací pdPASS, pokud lze data z fronty úspěšně přijmout, a vrací errQUEUE_EMPTY, pokud je fronta prázdná.
Nyní zobrazte hodnoty na LCD pomocí funkce lcd.print () .
void TaskDisplay (void * pvParameters) { int intenzita = 0; while (1) { Serial.println ("Task2"); if (xQueueReceive (queue_1, & intenzita, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intenzita:"); lcd.setCursor (11, 0); lcd.print (intenzita); } } }
A je to. Dokončili jsme část kódování implementace Queue. Kompletní kód s fungujícím videem najdete na konci.
Nyní připojte LCD a LDR k Arduino UNO podle schématu zapojení nahrajte kód. Otevřete sériový monitor a sledujte úkoly. Uvidíte, že se úlohy mění a hodnoty LDR se mění podle intenzity světla.
POZNÁMKA: Většina knihoven vytvořených pro různé senzory jádro FreeRTOS nepodporuje kvůli implementaci funkce zpoždění uvnitř knihoven. Díky zpoždění se CPU úplně zastaví, proto jádro FreeRTOS také přestane fungovat a kód se nebude dále vykonávat a začne se chovat špatně. Musíme tedy umožnit knihovnám zpoždění pro práci s FreeRTOS.