- Vymazanie úlohy vo FreeRTOS Arduino
- Čo je to poradie vo FreeRTOS?
- Vytvorenie frontu vo FreeRTOS
- Schéma zapojenia
- Implementácia frontu FreeRTOS v Arduino IDE
V predchádzajúcom tutoriáli sme si predstavili FreeRTOS v Arduino Uno a vytvorili sme úlohu pre blikajúcu LED. Teraz sa v tomto výučbe ponoríme viac do pokročilých konceptov rozhraní RTOS API a dozvieme sa viac o komunikácii medzi rôznymi úlohami. Tu sa tiež dozvedáme o fronte na prenos údajov z jednej úlohy do druhej a demonštrujeme fungovanie API frontov prepojením 16x2 LCD a LDR s Arduino Uno.
Predtým, ako diskutujeme o Frontoch, pozrime sa na ďalšie API FreeRTOS, ktoré je užitočné pri odstraňovaní úloh, keď je práca s úlohou dokončená. Niekedy je potrebné úlohu vymazať, aby sa uvoľnila pridelená pamäť. V pokračovaní predchádzajúceho tutoriálu použijeme funkciu API vTaskDelete () v rovnakom kóde na odstránenie jednej z úloh. Úloha môže na odstránenie svojej úlohy alebo akejkoľvek inej úlohy použiť funkciu API vTaskDelete () .
Ak chcete použiť toto API, musíte nakonfigurovať súbor FreeRTOSConfig.h . Tento súbor sa používa na prispôsobenie FreeRTOS podľa aplikácie. Používa sa na zmenu plánovacích algoritmov a mnohých ďalších parametrov. Súbor sa nachádza v adresári Arduino Directory, ktorý je zvyčajne k dispozícii v priečinku Documents vo vašom počítači. V mojom prípade je k dispozícii v priečinku \ Documents \ Arduino \ libraries \ FreeRTOS \ src, ako je uvedené nižšie.
Teraz otvorte tento súbor pomocou ľubovoľného textového editora a hľadať na #define INCLUDE_vTaskDelete a uistite sa, že jeho hodnota je, 1 '(1 znamená povoliť a 0 znamená zakázať). Predvolene je to 1, ale kontroluje sa to.
Tento konfiguračný súbor budeme často používať v našich ďalších návodoch na nastavenie parametrov.
Teraz sa pozrime, ako odstrániť úlohu.
Vymazanie úlohy vo FreeRTOS Arduino
Na odstránenie úlohy musíme použiť funkciu API vTaskDelete (). Chce to iba jeden argument.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Je to popisovač úlohy, ktorý sa má vymazať. Je to rovnaké ako šiesty argument rozhrania xTaskCreate () API. V predchádzajúcom tutoriáli je tento argument nastavený na hodnotu NULL, ale adresu obsahu môžete zadať pomocou ľubovoľného názvu. Povedzme, že chcete nastaviť handle úlohy pre Task2, ktorá je deklarovaná ako
TaskHandle_t any_name; Príklad: TaskHandle_t xTask2Handle;
Teraz v API vTaskCreate () nastavte šiesty argument ako
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1, & xTask2Handle);
K obsahu tejto úlohy je teraz možné pristupovať pomocou vami zadaného ovládača.
Úloha sa tiež môže vymazať odovzdaním hodnoty NULL namiesto platného popisovača úlohy.
Ak chceme odstrániť úlohu 3 zo samotnej úlohy 3, musíte napísať vTaskDelete (NULL); vo vnútri funkcie Task3, ale ak chcete vymazať úlohu 3 z úlohy 2, napíšte vTaskDelete (xTask3Handle); vo vnútri funkcie task2.
Ak chcete v predchádzajúcom kóde tutoriálu odstrániť Task2 zo samotnej task2, stačí pridať vTaskDelete (NULL); vo funkcii void TaskBlink2 (void * pvParameters) . Potom bude vyššie uvedená funkcia vyzerať takto
void TaskBlink2 (void * pvParameters) { Serial.println („Task2 je spustený a chystá sa vymazať“); vTaskDelete (NULL); pinMode (7, VÝSTUP); while (1) { digitalWrite (7, HIGH); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LOW); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Teraz nahrajte kód a sledujte LED diódy a sériový monitor. Uvidíte, že druhá LED teraz nebliká a task2 je vymazaná po zistení vymazania API.
Toto API je možné použiť na zastavenie vykonávania konkrétnej úlohy.
Teraz začnime radom.
Čo je to poradie vo FreeRTOS?
Fronta je dátová štruktúra, ktorá pojme konečný počet prvkov pevnej veľkosti, a je prevádzkovaná v schéme FIFO (First-in First-out). Fronty poskytujú komunikačný mechanizmus medzi úlohami, medzi úlohami a medzi prerušeniami a úlohami.
Maximálny počet prvkov, ktoré môže fronta obsahovať, sa nazýva jej „dĺžka“. Pri vytváraní frontu sa nastavuje dĺžka aj veľkosť každého prvku.
Príklad použitia frontu na prenos dát je dobre ilustrovaný v dokumentácii FreeRTOS, ktorú nájdete tu. Daný príklad ľahko pochopíte.
Zloženie: 100% bavlna.Po porozumení frontu sa pokúsime porozumieť procesu vytvárania frontu a pokúsime sa ho implementovať do nášho kódu FreeRTOS.
Vytvorenie frontu vo FreeRTOS
Najskôr popíšte vyhlásenie o probléme, ktoré sa má implementovať pomocou frontu FreeRTOS a Arduino Uno.
Chceme vytlačiť hodnotu snímača LDR na 16 * 2 LCD. Teraz teda existujú dve úlohy
- Úlohou 1 je získať analógové hodnoty LDR.
- Úloha 2 tlačí analógovú hodnotu na LCD.
Takže tu zohráva svoju úlohu fronta, pretože na odoslanie údajov generovaných úlohou1 do úlohy2. V úlohe 1 pošleme analógovú hodnotu do frontu a v úlohe 2 ju dostaneme z frontu.
Existujú tri funkcie pre prácu s frontami
- Vytváranie frontu
- Odosielanie údajov do frontu
- Prijímanie údajov z frontu
Na vytvorenie frontu použite funkčné rozhranie API xQueueCreate (). Sú na to potrebné dva argumenty.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: Maximálny počet položiek, ktoré môže vytváraný front obsahovať naraz.
uxItemSize: Veľkosť každej dátovej položky v bajtoch, ktorú je možné uložiť do frontu.
Ak táto funkcia vráti hodnotu NULL, front sa nevytvorí z dôvodu nedostatočnej pamäte a ak vráti hodnotu, ktorá nemá hodnotu NULL, front sa vytvorí úspešne. Uložte túto návratovú hodnotu do premennej, aby ste ju mohli použiť ako popisovač na prístup do frontu, ako je uvedené nižšie.
QueueHandle_t queue1; queue1 = xQueueCreate (4, sizeof (int));
Takto sa v halde pamäte s veľkosťou int (2 bajty každého bloku) vytvorí fronta so štyrmi prvkami a návratová hodnota sa uloží do premennej handle queue1 .
2. Odosielanie údajov do frontu vo FreeRTOS
Na odoslanie hodnôt do frontu má FreeRTOS na tento účel 2 varianty API.
- xQueueSendToBack (): Používa sa na odosielanie údajov dozadu (chvost) frontu.
- xQueueSendToFront (): Používa sa na odoslanie údajov na prednú časť frontu.
Teraz je xQueueSend () ekvivalentné a úplne rovnaké ako xQueueSendToBack ().
Všetky tieto API majú 3 argumenty.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Popisovač frontu, do ktorého sa údaje odosielajú (zapisujú). Táto premenná je rovnaká ako tá, ktorá sa používa na uloženie návratovej hodnoty rozhrania xQueueCreate API.
pvItemToQueue: Ukazovateľ na údaje, ktoré sa majú kopírovať do frontu.
xTicksToWait: Maximálna doba, po ktorú by úloha mala zostať v zablokovanom stave, aby čakala na sprístupnenie miesta vo fronte.
Nastavenie parametra xTicksToWait na portMAX_DELAY spôsobí, že úloha bude čakať neurčito (bez časového limitu), ak je vo voľbe INCLUDE_vTaskSuspend nastavená hodnota 1 vo FreeRTOSConfig. Inak môžete na konverziu času uvedeného v milisekundách na čas určený v kliešťach použiť makro pdMS_TO_TICKS () .
3. Príjem dát z frontu vo FreeRTOS
Na príjem (čítanie) položky z frontu sa používa xQueueReceive (). Prijatá položka je odstránená z frontu.
Toto API tiež vyžaduje tri argumenty.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Prvý a tretí argument sú rovnaké ako odoslanie API. Iba druhý argument je iný.
const pvBuffer: Ukazovateľ na pamäť, do ktorej budú prijaté údaje skopírované.
Dúfam, že ste pochopili tri API. Teraz implementujeme tieto API do Arduino IDE a pokúsime sa vyriešiť problémové vyhlásenie, ktoré sme opísali vyššie.
Schéma zapojenia
Takto to vyzerá na doske:
Implementácia frontu FreeRTOS v Arduino IDE
Začnime písať kód pre našu aplikáciu.
1. Najskôr otvorte Arduino IDE a vložte súbor hlavičky Arduino_FreeRTOS.h . Teraz, ak sa použije akýkoľvek objekt jadra ako fronta, zahrňte jeho hlavičkový súbor. Pretože používame 16 * 2 LCD, zahrňte pre ňu aj knižnicu.
#include #include
2. Inicializujte popisovač frontu na uloženie obsahu frontu. Inicializujte tiež čísla pinov LCD.
QueueHandle_t queue_1; LiquidCrystal lcd (7, 8, 9, 10, 11, 12);
3. V programe void setup () inicializujte LCD a sériový monitor s prenosovou rýchlosťou 9600. Vytvorte poradie a dve úlohy pomocou príslušných rozhraní API. Tu vytvoríme rad veľkosti 4 s celočíselným typom. Vytvorte úlohu s rovnakými prioritami a neskôr sa pokúste hrať s týmto číslom. Nakoniec spustite plánovač, ako je uvedené nižšie.
void setup () { Serial.begin (9600); lcd.začiatok (16, 2); queue_1 = xQueueCreate (4, sizeof (int)); if (queue_1 == NULL) { Serial.println ("Fronta sa nedá vytvoriť"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Teraz urobte dve funkcie TaskDisplay a TaskLDR . Vo funkcii TaskLDR čítajte analógový pin A0 v premennej, pretože máme LDR pripojený k pinu A0 Arduino UNO. Teraz pošlite hodnotu uloženú v premennej jej odovzdaním v rozhraní xQueueSend API a po 1 sekunde odošlite úlohu do stavu blokovania pomocou rozhrania vTaskDelay () API, ako je uvedené nižšie.
void TaskLDR (void * pvParameters) { int current_intensity; while (1) { Serial.println ("Task1"); current_intensity = analogRead (A0); Serial.println (current_intensity); xQueueSend (front_1, & current_intensity, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. Podobne urobte funkciu pre TaskDisplay a prijímajte hodnoty v premennej, ktorá sa odovzdáva funkcii xQueueReceive . Tiež xQueueReceive () vracia pdPASS v prípade, že dáta môžu byť úspešne prijatý z frontu a vráti errQUEUE_EMPTY -Li fronta prázdna.
Teraz zobrazte hodnoty na LCD displeji pomocou funkcie lcd.print () .
void TaskDisplay (void * pvParameters) { int intenzita = 0; while (1) { Serial.println ("Task2"); if (xQueueReceive (fronta_1, & intenzita, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intenzita:"); lcd.setCursor (11, 0); lcd.tlač (intenzita); } } }
To je všetko. Dokončili sme časť kódovania implementácie frontu. Celý kód s funkčným videom nájdete na konci.
Teraz pripojte LCD a LDR k Arduino UNO podľa schémy nahrávania kódu. Otvorte sériový monitor a sledujte úlohy. Uvidíte, že úlohy sa prepínajú a hodnoty LDR sa menia podľa intenzity svetla.
POZNÁMKA: Väčšina knižníc vytvorených pre rôzne senzory jadro FreeRTOS nepodporuje z dôvodu implementácie funkcie oneskorenia vo vnútri knižníc. Vďaka oneskoreniu sa procesor úplne zastaví, preto jadro FreeRTOS tiež prestane pracovať a kód sa nebude ďalej vykonávať a začne sa správať nesprávne. Musíme teda urobiť knižnice bez oneskorenia pre prácu s FreeRTOS.