- Užduoties ištrynimas iš „FreeRTOS Arduino“
- Kokia yra „FreeRTOS“ eilė?
- Eilės kūrimas „FreeRTOS“
- Grandinės schema
- „FreeRTOS“ eilės diegimas „Arduino IDE“
Ankstesnėje pamokoje pristatėme „FreeRTOS“ „Arduino Uno“ ir sukūrėme užduotį mirksinčiam šviesos diodui. Dabar šioje pamokoje mes daugiau pasinersime į išankstines RTOS API koncepcijas ir sužinosime apie skirtingų užduočių bendravimą. Čia mes taip pat sužinome apie eilę, norėdami perkelti duomenis iš vienos užduoties į kitą ir parodyti eilės API veikimą susiejant 16x2 LCD ir LDR su „Arduino Uno“.
Prieš diskutuodami apie eiles, pažiūrėkime dar vieną „FreeRTOS“ API, kuri yra naudinga ištrinant užduotis, kai ji bus baigta priskirtą darbą. Kartais, norint atlaisvinti skirtą atmintį, užduotį reikia ištrinti. Tęsdami ankstesnę mokymo programą, tame pačiame kode naudosime funkciją „vTaskDelete ()“, kad ištrintume vieną iš užduočių. Užduotis gali naudoti API funkciją „ vTaskDelete ()“, kad ištrintų save ar bet kurią kitą užduotį.
Norėdami naudoti šią API, turite sukonfigūruoti FreeRTOSConfig.h failą. Šis failas naudojamas pritaikyti „FreeRTOS“ pagal programą. Jis naudojamas planavimo algoritmams ir daugeliui kitų parametrų pakeisti. Failą galite rasti „Arduino“ kataloge, kuris paprastai yra jūsų kompiuterio aplanke Dokumentai. Mano atveju tai galima rasti \ Documents \ Arduino \ libraries \ FreeRTOS \ src, kaip parodyta žemiau.
Dabar, atidaryti šį failą, naudojant bet kokį tekstinį redaktorių ir ieškoti į #define INCLUDE_vTaskDelete ir įsitikinkite, kad jo vertė yra "1" (1 priemonė įjungti ir 0 reiškia išjungti). Pagal numatytuosius nustatymus jis yra 1, bet patikrina.
Mes dažnai naudosime šį konfigūracijos failą kitose instrukcijose nustatydami parametrus.
Dabar pažiūrėkime, kaip ištrinti užduotį.
Užduoties ištrynimas iš „FreeRTOS Arduino“
Norėdami ištrinti užduotį, turime naudoti API funkciją vTaskDelete (). Tam reikia tik vieno argumento.
„vTaskDelete“ („TaskHandle_t pxTaskToDelete“);
pxTaskToDelete: Būtina ištrinti užduoties rankeną. Tai tas pats, kas 6 -asis „ xTaskCreate () API“ argumentas. Ankstesnėje mokymo programoje šis argumentas nustatytas kaip NULL, tačiau užduoties turinio adresą galite perduoti naudodami bet kurį vardą. Tarkime, jei norite nustatyti „Task2“ užduoties rankeną, kuri deklaruojama kaip
„TaskHandle_t any_name“; Pavyzdys: TaskHandle_t xTask2Handle;
Dabar programoje „vTaskCreate“) API nustatykite 6 -ąjį argumentą kaip
„xTaskCreate“ („TaskBlink2“, „task2“, 128, NULL, 1 ir xTask2Handle);
Dabar prie šios užduoties turinio galima susipažinti naudojantis jūsų duota rankena.
Be to, užduotis gali ištrinti pati praleidžiant NULL vietoje galiojančios užduoties rankenos.
Jei norime ištrinti 3 užduotį iš pačios 3 užduoties, turite parašyti „ vTaskDelete“ (NULL); funkcijos Task3 viduje, bet jei norite ištrinti 3 užduotį iš 2 užduoties, tada parašykite vTaskDelete (xTask3Handle); funkcijos task2 viduje.
Ankstesniame mokymo kode, norėdami ištrinti „Task2“ iš paties task2, tiesiog pridėkite „ vTaskDelete“ (NULL); į tuščia TaskBlink2 (void * pvParameters) funkcija. Tada minėta funkcija atrodys taip
void TaskBlink2 (void * pvParameters) { Serial.println („2 užduotis vykdoma ir tuoj bus ištrinta“); „vTaskDelete“ (NULL); pinMode (7, OUTPUT); o (1) { digitalWrite (7, HIGH); „vTaskDelay“ (300 / portTICK_PERIOD_MS); digitalWrite (7, LOW); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Dabar įkelkite kodą ir stebėkite šviesos diodus ir nuoseklųjį monitorių. Pamatysite, kad antrasis šviesos diodas nemirksi dabar ir užduotis 2 bus ištrinta, susidūrus su ištrynimo API.
Taigi šią API galima naudoti norint sustabdyti konkrečios užduoties vykdymą.
Pradėkime nuo eilės.
Kokia yra „FreeRTOS“ eilė?
Eilė yra duomenų struktūra, kurioje gali būti ribotas fiksuoto dydžio elementų skaičius, ir ji naudojama FIFO schemoje („First-in First-out“). Eilėse pateikiamas užduoties užduoties, užduoties pertraukimo ir pertraukimo užduoties komunikacijos mechanizmas.
Didžiausias eilės elementų skaičius gali būti vadinamas „ilgiu“. Kuriant eilę nustatomas kiekvieno elemento ilgis ir dydis.
Pavyzdys, kaip eilė naudojama duomenims perduoti, gerai parodytas „FreeRTOS“ dokumentuose, kuriuos galite rasti čia. Galite lengvai suprasti pateiktą pavyzdį.
ASupratę eiles, pabandykime suprasti eilės kūrimo procesą ir pabandykime jį įdiegti savo „FreeRTOS“ kode.
Eilės kūrimas „FreeRTOS“
Pirmiausia apibūdinkite probleminį teiginį, kuris turi būti įgyvendintas naudojant „FreeRTOS“ eilę ir „Arduino Uno“.
Mes norime atspausdinti LDR jutiklio vertę 16 * 2 skystųjų kristalų ekrane. Taigi dabar yra dvi užduotys
- 1 užduotis gauna analogines LDR vertes.
- 2 užduotis spausdina analoginę vertę LCD.
Taigi, čia eilė vaidina savo vaidmenį, nes norint išsiųsti task1 sugeneruotus duomenis į task2. Užduotyje 1 mes nusiųsime analoginę vertę į eilę, o užduotyje 2 - iš eilės.
Yra trys funkcijos dirbti su eilėmis
- Eilės kūrimas
- Siunčiami duomenys į eilę
- Gaunami duomenys iš eilės
Norėdami sukurti eilę, naudokite xQueueCreate () funkcijos API. Tam reikia dviejų argumentų.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: maksimalus elementų, kuriuos bet kuriuo metu gali turėti kuriama eilė, skaičius.
uxItemSize: kiekvieno duomenų elemento, kurį galima išsaugoti eilėje, dydis baitais.
Jei ši funkcija grąžina NULL, eilė nesukuriama dėl nepakankamos atminties ir jei ji pateikia ne NULL reikšmę, eilė sukuriama sėkmingai. Saugokite šią grąžinimo vertę kintamajame, kad galėtumėte naudoti ją kaip rankeną norėdami patekti į eilę, kaip parodyta žemiau.
„QueueHandle_t“ eilė1; eilė1 = xQueueCreate (4, sizeof (int));
Tai sukurs 4 elementų eilę kaupiklio atmintyje int dydžio (2 baitai kiekvieno bloko) ir išsaugos grąžinimo vertę „ queue1“ rankenos kintamajame.
2. Duomenų siuntimas į eilę „FreeRTOS“
Norėdami siųsti reikšmes į eilę, „FreeRTOS“ šiam tikslui turi 2 API variantus.
- „xQueueSendToBack“ (): naudojamas duomenims siųsti į eilės galą (uodegą).
- „xQueueSendToFront ()“: naudojamas duomenims siųsti į priekinę eilę (galvą).
Dabar , xQueueSend () yra lygiavertis ir lygiai tas pats, kaip, xQueueSendToBack ().
Visoms šioms API reikia 3 argumentų.
xQueueSendToBack (QueueHandle_t xQueue, const negalioja * pvItemToQueue, TickType_t xTicksToWait);
„xQueue“: eilės, į kurią siunčiami (rašomi), rankena. Šis kintamasis yra tas pats, kuris naudojamas saugoti „xQueueCreate“ API grąžinimo vertę.
pvItemToQueue: rodyklė duomenims, kurie bus nukopijuoti į eilę.
„xTicksToWait“: maksimalus laiko tarpas, kurį užduotis turi likti užblokuotoje būsenoje, kol laukia, kol eilėje atsiras vietos.
Nustačius „ xTicksToWait“ į „ portMAX_DELAY “, užduotis laukia neribotą laiką (be skirtingo laiko), jei INCLUDE_vTaskSuspend yra nustatyta kaip 1 FreeRTOSConfig.h , be to, galite naudoti makrokomandą pdMS_TO_TICKS (), kad milisekundėmis nurodytą laiką paverstumėte į erkėse nurodytą laiką.
3. Duomenų iš eilės gavimas „FreeRTOS“
Norėdami gauti (perskaityti) elementą iš eilės, naudojama „ xQueueReceive“ (). Gautas elementas pašalinamas iš eilės.
Ši API taip pat turi tris argumentus.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Pirmasis ir trečiasis argumentai yra tokie patys kaip siunčiant API. Tik antrasis argumentas yra kitoks.
const pvBuffer: rodyklė į atmintį, į kurią bus nukopijuoti gauti duomenys.
Tikiuosi, kad supratote tris API. Dabar mes įdiegsime šias API „Arduino IDE“ ir bandysime išspręsti aukščiau aprašytą problemos teiginį.
Grandinės schema
Taip atrodo ant duonos lentos:
„FreeRTOS“ eilės diegimas „Arduino IDE“
Pradėkime rašyti savo programos kodą.
1. Pirmiausia atidarykite „Arduino IDE“ ir įtraukite „ Arduino_FreeRTOS.h“ antraštės failą. Dabar, jei naudojamas koks nors branduolio objektas, pvz., Eilė, įtraukite jo antraštės failą. Kadangi mes naudojame 16 * 2 skystųjų kristalų ekraną, įtraukite ir jo biblioteką.
# įtraukti # įtraukti
2. Inicijuokite eilės rankeną, kad išsaugotumėte eilės turinį. Taip pat inicializuokite LCD kaiščių numerius.
QueueHandle_t queue_1; „LiquidCrystal“ lcd (7, 8, 9, 10, 11, 12);
3. Atlikdami tuščią sąranką (), pradėkite LCD ir nuoseklųjį monitorių naudodami 9600 perdavimo greitį. Sukurkite eilę ir dvi užduotis naudodami atitinkamas API. Čia sukursime 4 dydžio eilę su sveiko skaičiaus tipu. Sukurkite užduotį su vienodais prioritetais ir vėliau pabandykite žaisti su šiuo skaičiumi. Galiausiai paleiskite tvarkaraštį, kaip parodyta žemiau.
negaliojanti sąranka () { Serial.begin (9600); lcd.begin (16, 2); eilė_1 = xQueueCreate (4, sizeof (int)); if (queue_1 == NULL) { Serial.println ("Eilės sukurti negalima"); } xTaskCreate („TaskDisplay“, „Display_task“, 128, NULL, 1, NULL); „xTaskCreate“ („TaskLDR“, „LDR_task“, 128, NULL, 1, NULL); „vTaskStartScheduler“ (); }
4. Dabar atlikite dvi funkcijas „ TaskDisplay“ ir „ TaskLDR“ . Be TaskLDR funkcija, skaityti analoginis pin A0 į kintamąjį kaip mes LDR prijungtas prie A0 Kaisčiai Arduino UNO. Dabar išsiųskite kintamajame saugomą vertę, perduodami ją į „ xQueueSend“ API ir išsiųskite užduotį blokuoti būseną po 1 sekundės naudodami „ vTaskDelay () API“, kaip parodyta žemiau.
void TaskLDR (void * pvParameters) { int current_intensity; o (1) { Serial.println ("Užduotis1"); current_intensity = analogRead (A0); Serial.println (dabartinis_intensyvumas); xQueueSend (eilė_1, & dabartinis_intensyvumas, portMAX_DELAY); „vTaskDelay“ (1000 / portTICK_PERIOD_MS); } }
5. Panašiai sukurkite „ TaskDisplay“ funkciją ir gaukite reikšmes kintamajame, kuris perduodamas funkcijai „ xQueueReceive“ . Be to, xQueueReceive () pateikia pdPASS, jei duomenis galima sėkmingai gauti iš eilės, ir grąžina errQUEUE_EMPTY, jei eilė tuščia.
Dabar naudodamiesi lcd.print () funkcija, rodykite vertes skystųjų kristalų ekrane.
void TaskDisplay (void * pvParameters) { int intensyvumas = 0; o (1) { Serial.println ("Užduotis2"); if (xQueueReceive (eilė_1, & intensyvumas, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intensyvumas:"); lcd.setCursor (11, 0); lcd.print (intensyvumas); } } }
Viskas. Baigėme eilės diegimo kodavimo dalį. Pabaigoje galite rasti visą kodą su veikiančiu vaizdo įrašu.
Dabar prijunkite LCD ir LDR su „Arduino UNO“ pagal grandinės schemą, įkelkite kodą. Atidarykite nuoseklųjį monitorių ir stebėkite užduotis. Pamatysite, kad užduotys keičiasi, o LDR vertės keičiasi atsižvelgiant į šviesos intensyvumą.
PASTABA: „FreeRTOS“ branduolys nepalaiko daugelio bibliotekų, sukurtų skirtingiems jutikliams, nes bibliotekose vėluojamos funkcijos. Uždelsimas priverčia procesorių visiškai sustoti, todėl „FreeRTOS“ branduolys taip pat nustoja veikti, kodas toliau nevykdomas ir jis pradeda elgtis netinkamai. Taigi, mes turime priversti bibliotekas nedelsti dirbti su „FreeRTOS“.