- Pagtanggal ng isang Gawain sa FreeRTOS Arduino
- Ano ang pila sa FreeRTOS?
- Lumilikha ng isang Queue sa FreeRTOS
- Diagram ng Circuit
- Pagpapatupad ng FreeRTOS Queue sa Arduino IDE
Sa nakaraang tutorial, ipinakilala namin ang FreeRTOS sa Arduino Uno at lumikha ng isang gawain para sa blinking LED. Ngayon, sa tutorial na ito, mas sisidhi kami sa mga advance na konsepto ng RTOS API at matutunan ang tungkol sa komunikasyon sa pagitan ng iba't ibang mga gawain. Nalaman din namin ang tungkol sa Queue upang ilipat ang data mula sa isang gawain patungo sa isa pa at ipakita ang pagtatrabaho ng mga API ng pila sa pamamagitan ng pag-interfaced ng 16x2 LCD at LDR sa Arduino Uno.
Bago talakayin ang tungkol sa Mga Queue, tingnan natin ang isa pang FreeRTOS API na kapaki-pakinabang sa pagtanggal ng mga gawain kapag natapos ito sa nakatalagang gawain. Minsan ang gawain ay kailangang tanggalin upang mapalaya ang inilaang memorya. Bilang pagpapatuloy ng nakaraang tutorial, gagamitin namin ang vTaskDelete () API function sa parehong code upang tanggalin ang isa sa mga gawain. Maaaring gamitin ng isang gawain ang pagpapaandar ng vTaskDelete () API upang tanggalin ang sarili nito, o anumang iba pang gawain.
Upang magamit ang API na ito, kailangan mong i-configure ang file na FreeRTOSConfig.h . Ang file na ito ay ginagamit upang maiangkop ang FreeRTOS alinsunod sa aplikasyon. Ginagamit ito upang baguhin ang mga pag-iiskedyul ng mga algorithm at maraming iba pang mga parameter. Ang file ay matatagpuan sa Arduino Directory na karaniwang magagamit sa folder ng Mga Dokumento ng iyong PC. Sa aking kaso, magagamit ito sa \ Documents \ Arduino \ libraries \ FreeRTOS \ src tulad ng ipinakita sa ibaba.
Ngayon, buksan ang file na ito gamit ang anumang text editor at hanapin ang #define INCLUDE_vTaskDelete at tiyaking ang halaga nito ay '1' (1 nangangahulugang paganahin at 0 ay nangangahulugang hindi paganahin). Ito ay 1 bilang default ngunit susuriin ito.
Gagamitin namin madalas ang config file na ito sa aming susunod na mga tutorial para sa pagtatakda ng mga parameter.
Ngayon, tingnan natin kung paano magtanggal ng isang gawain.
Pagtanggal ng isang Gawain sa FreeRTOS Arduino
Upang tanggalin ang isang gawain, kailangan naming gamitin ang vTaskDelete () API function. Tanging isang pagtatalo ang kinakailangan.
vTaskDelete (TaskHandle_t pxTaskToDelete);
pxTaskToDelete: Ito ang hawakan ng gawain na tatanggalin. Ito ay kapareho ng ika- 6 na argumento ng xTaskCreate () API. Sa nakaraang tutorial, ang argument na ito ay itinakda bilang NUL ngunit maaari mong ipasa ang address ng mga nilalaman ng gawain sa pamamagitan ng paggamit ng anumang pangalan. Sabihin kung nais mong itakda ang hawakan ng gawain para sa Task2 na idineklarang bilang
TaskHandle_t anumang_name; Halimbawa: TaskHandle_t xTask2Handle;
Ngayon, sa vTaskCreate () itinakda ng API ang ika- 6 na argumento bilang
xTaskCreate (TaskBlink2, "task2", 128, NULL, 1, & xTask2Handle);
Ang nilalaman ng gawaing ito ay maaari nang ma-access gamit ang hawakan na ibinigay mo.
Gayundin, maaaring tanggalin ng isang gawain ang sarili nito sa pamamagitan ng pagpasa ng Null sa lugar ng wastong hawakan ng gawain.
Kung nais naming tanggalin ang Gawain 3 mula sa gawain 3 mismo, kailangan mong isulat ang vTaskDelete (NULL); sa loob ng paggana ng Task3 ngunit kung nais mong tanggalin ang gawain 3 mula sa gawain 2 pagkatapos ay isulat ang vTaskDelete (xTask3Handle); sa loob ng gawain2 function.
Sa nakaraang tutorial code, upang tanggalin ang Task2 mula mismo sa task2, idagdag lamang ang vTaskDelete (NULL); sa walang bisa na paggana ng TaskBlink2 (walang bisa * pvParameter) . Pagkatapos ang pag-andar sa itaas ay magiging ganito
walang bisa ang TaskBlink2 (walang bisa * pvParameter) { Serial.println ("Tumatakbo ang Task2 at magtatanggal na"); vTaskDelete (NULL); pinMode (7, OUTPUT); habang (1) { digitalWrite (7, TAAS); vTaskDelay (300 / portTICK_PERIOD_MS); digitalWrite (7, LOW); vTaskDelay (300 / portTICK_PERIOD_MS); } }
Ngayon, i-upload ang code at obserbahan ang LEDs at Serial monitor. Makikita mo na ang pangalawang LED ay hindi kumikislap ngayon at ang task2 ay tinanggal pagkatapos makasalubong ang tanggalin ang API.
Kaya ang API na ito ay maaaring magamit upang ihinto ang pagpapatupad ng partikular na gawain.
Ngayon, magsimula tayo sa pila.
Ano ang pila sa FreeRTOS?
Ang pila ay ang istraktura ng data na maaaring maghawak ng may takda na bilang ng mga nakapirming mga elemento ng laki at ito ay pinapatakbo sa iskemang FIFO (First-in First-out). Ang mga pila ay nagbibigay ng isang gawain sa gawain, gawain-upang-makagambala, at makagambala-sa-gawain na mekanismo ng komunikasyon.
Ang maximum na bilang ng mga elemento ng pila na maaaring hawakan ay tinatawag na "haba" nito. Ang parehong haba at laki ng bawat elemento ay itinakda kapag ang pila ay nilikha.
Ang isang halimbawa ng kung paano ginagamit ang pila para sa paglilipat ng data ay nakalarawan nang maayos sa dokumentasyong FreeRTOS na matatagpuan dito. Madali mong maunawaan ang ibinigay na halimbawa.
Matapos maunawaan ang Mga Queue, subukan nating maunawaan ang proseso ng paglikha ng isang pila at subukang ipatupad ito sa aming FreeRTOS code.
Lumilikha ng isang Queue sa FreeRTOS
Una, ilarawan ang pahayag ng problema na ipapatupad sa tulong ng linya ng FreeRTOS at Arduino Uno.
Nais naming i- print ang halaga ng LDR sensor sa 16 * 2 LCD. Kaya mayroong dalawang mga gawain ngayon
- Ang Task1 ay nakakakuha ng mga halagang analog na LDR.
- Ang Task2 ay naglilimbag ng halagang analog sa LCD.
Kaya, narito ang pila sa papel nito dahil upang maipadala ang data na nabuo ng task1 sa task2. Sa task1, magpapadala kami ng halagang analog sa pila at sa task2, tatanggapin namin ito mula sa pila.
Mayroong tatlong mga pagpapaandar upang gumana sa mga pila
- Lumilikha ng pila
- Nagpapadala ng data sa pila
- Tumatanggap ng data mula sa Queue
Para sa paglikha ng pila, gamitin ang xQueueCreate () function API. Tumatagal ito ng dalawang argumento.
xQueueCreate (UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
uxQueueLength: Ang maximum na bilang ng mga item na nilikha ang pila ay maaaring hawakan sa anumang isang oras.
uxItemSize: Ang laki sa mga byte ng bawat item ng data na maaaring maiimbak sa pila.
Kung ang pagpapaandar na ito ay nagbabalik ng NULL pagkatapos ang pila ay hindi nilikha dahil sa hindi sapat na memorya at kung nagbabalik ito ng isang hindi-NUL na halaga, matagumpay na nilikha ang pila. Iimbak ang halaga ng pagbabalik na ito sa isang variable upang magamit ito bilang isang hawakan upang ma-access ang pila tulad ng ipinakita sa ibaba.
QueueHandle_t queue1; pila1 = xQueueCreate (4, laki ng (int));
Lilikha ito ng isang 4 na pila ng elemento sa tambak na memorya ng int laki (2 bytes ng bawat bloke) at iimbak ang halaga ng pagbalik sa variable na paghawak ng pila1 .
2. Pagpapadala ng Data sa Queue sa FreeRTOS
Upang maipadala ang mga halaga sa pila, ang FreeRTOS ay mayroong 2 magkakaibang mga API para sa hangaring ito.
- xQueueSendToBack (): Ginamit upang magpadala ng data sa likod (buntot) ng isang pila.
- xQueueSendToFront (): Ginamit upang magpadala ng data sa harap (ulo) ng isang pila.
Ngayon , ang xQueueSend () ay katumbas ng, at eksaktong kapareho ng, xQueueSendToBack ().
Ang lahat ng mga API na ito ay tumatagal ng 3 mga argumento.
xQueueSendToBack (QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
xQueue: Ang hawakan ng pila kung saan ipinapadala ang data (nakasulat). Ang variable na ito ay pareho sa ginamit upang maiimbak ang halaga ng pagbalik ng xQueueCreate API.
pvItemToQueue: Isang pointer sa data na makopya sa pila.
xTicksToWait: Ang maximum na dami ng oras na ang gawain ay dapat manatili sa naka-block na estado upang maghintay para sa puwang na magagamit sa pila.
Ang pagtatakda ng xTicksToWait sa portMAX_DELAY ay magdudulot sa gawain na maghintay nang walang katiyakan (nang walang pag-time out), na ibinigay INCLUDE_vTaskSuspend ay nakatakda sa 1 sa FreeRTOSConfig.h iba pa maaari mong gamitin ang macro pdMS_TO_TICKS () upang mai-convert ang isang oras na tinukoy sa milliseconds sa isang oras na tinukoy sa mga ticks.
3. Pagtanggap ng Data mula sa Queue sa FreeRTOS
Upang makatanggap (basahin) ang isang item mula sa isang pila, xQueueReceive () ang ginagamit. Ang item na natanggap ay tinanggal mula sa pila.
Ang API na ito ay tumatagal din ng tatlong mga argumento.
xQueueReceive (QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait);
Ang una at pangatlong argumento ay pareho sa pagpapadala ng API. Ang pangalawang argumento lamang ang naiiba.
const pvBuffer: Isang pointer sa memorya kung saan makukopya ang natanggap na data.
Sana naintindihan mo ang tatlong mga API. Ngayon, ipapatupad namin ang mga API na ito sa Arduino IDE at subukang lutasin ang pahayag ng problema na inilarawan namin sa itaas.
Diagram ng Circuit
Ito ang hitsura nito sa breadboard:
Pagpapatupad ng FreeRTOS Queue sa Arduino IDE
Simulan natin ang pagsulat ng code para sa aming aplikasyon.
1. Una, buksan ang Arduino IDE at isama ang Arduino_FreeRTOS.h header file. Ngayon, kung ang anumang kernel na bagay tulad ng pila ay ginagamit pagkatapos isama ang header file nito. Habang gumagamit kami ng 16 * 2 LCD kaya isama ang aklatan para din dito.
# isama ang # isama
2. Pasimulan ang isang panghawak ng pila upang maiimbak ang mga nilalaman ng pila. Gayundin, simulan ang mga numero ng LCD pin.
QueueHandle_t pila0; LiquidCrystal lcd (7, 8, 9, 10, 11, 12);
3. Sa void setup (), ipasimula ang LCD at serial monitor na may 9600 baud rate. Lumikha ng isang pila at dalawang gawain gamit ang kani-kanilang mga API. Dito lilikha kami ng isang pila ng laki 4 na may integer type. Lumikha ng isang gawain na may pantay na mga priyoridad at sa paglaon subukang i-play sa numerong ito. Panghuli, simulan ang tagapag-iskedyul tulad ng ipinakita sa ibaba.
void setup () { Serial.begin (9600); lcd.begin (16, 2); pila pila = xQueueCreate (4, laki ng (int)); kung (pila0 == NULL) { Serial.println ("Hindi maaaring malikha ang pila"); } xTaskCreate (TaskDisplay, "Display_task", 128, NULL, 1, NULL); xTaskCreate (TaskLDR, "LDR_task", 128, NULL, 1, NULL); vTaskStartScheduler (); }
4. Ngayon, gumawa ng dalawang pag-andar ng TaskDisplay at TaskLDR . Sa pagpapaandar ng TaskLDR , basahin ang analog pin A0 sa isang variable dahil mayroon kaming LDR na konektado sa A0 pin ng Arduino UNO. Ipadala ngayon ang halagang nakaimbak sa variable sa pamamagitan ng pagpasa nito sa xQueueSend API at ipadala ang gawain upang harangan ang estado pagkatapos ng 1 segundo gamit ang vTaskDelay () API tulad ng ipinakita sa ibaba.
walang bisa ang TaskLDR (walang bisa * pvParameter) { int kasalukuyang_intensity; habang (1) { Serial.println ("Task1"); current_intensity = analogRead (A0); Serial.println (kasalukuyang_intensity); xQueueSend (queue_1, & current_intensity, portMAX_DELAY); vTaskDelay (1000 / portTICK_PERIOD_MS); } }
5. Katulad nito, gumawa ng isang pagpapaandar para sa TaskDisplay at makatanggap ng mga halaga sa isang variable na naipasa sa pagpapaandar ng xQueueReceive . Gayundin, ang xQueueReceive () ay nagbabalik sa pdPASS kung ang data ay maaaring matagumpay na matanggap mula sa pila at ibabalik ang errQUEUE_EMPTY kung ang isang pila ay walang laman.
Ngayon, ipakita ang mga halaga sa LCD gamit ang lcd.print () function.
walang bisa ang TaskDisplay (walang bisa * pvParameter) { int intensity = 0; habang (1) { Serial.println ("Task2"); kung (xQueueReceive (queue_1, & intensity, portMAX_DELAY) == pdPASS) { lcd.clear (); lcd.setCursor (0, 0); lcd.print ("Intensity:"); lcd.setCursor (11, 0); lcd.print (intensity); } } }
Ayan yun. Natapos na namin ang bahagi ng pag-cod ng pagpapatupad ng pila. Ang kumpletong code na may gumaganang Video ay matatagpuan sa dulo.
Ngayon, ikonekta ang LCD at LDR sa Arduino UNO ayon sa circuit diagram na i-upload ang code. Buksan ang serial monitor at obserbahan ang mga gawain. Makikita mo ang paglipat ng mga gawain at ang mga halaga ng LDR ay nagbabago alinsunod sa gaanong ilaw.
TANDAAN: Karamihan sa mga aklatan na ginawa para sa iba't ibang mga sensor ay hindi suportado ng FreeRTOS kernel dahil sa pagkaantala ng pagpapatupad ng pag-andar sa loob ng mga aklatan. Ang pagkaantala ay ganap na huminto sa CPU, samakatuwid, ang kernel ng FreeRTOS ay tumitigil din sa pagtatrabaho at ang code ay hindi pa gaganap at nagsisimula ito sa maling paggawi. Kaya, kailangan nating gawin ang mga aklatan na walang pagkaantala upang magtrabaho kasama ang FreeRTOS.