Skip to main content

Používáme FreeRTOS na mikrokontroleru STM32 (Ukázka, strana 99)

Page 1

Kapitola 9

Události Nástroje, které jsme využívali v předchozích kapitolách, umožňovaly připravit k běhu blokovaná vlákna. Avšak jedna data ve frontě či jeden semafor ve výsledku vždy umožnily aktivaci pouze jednomu vláknu. K hromadné změně více vláken do připraveného stavu slouží události (anglicky Events).

9.1

Funkce

Událost je nástroj operačního systému, který umožňuje naráz uvést více vláken do připraveného stavu. Jelikož tento nástroj nepracuje pouze s jednou událostí, ale rovnou s celou sadou, je také možné nastavit, aby každé vlákno čekalo v blokovaném stavu na jinou událost, nebo na kombinaci více událostí. Skupinu událostí si můžeme představit jako 32bitové slovo, z něhož jeho nejnižších 24 bitů představuje příznaky jednotlivých událostí. Jednotlivé příznaky událostí nemají žádné speciální funkce. Záleží pouze na programátorovi, jak jednotlivé bity využije. Události výrazně snižují paměťovou náročnost na synchronizaci vláken. 24 bitů událostí totiž můžeme použít podobným způsobem jako 24 semaforů, které ovšem zaberou mnohem více paměťového prostoru. Jeden semafor navíc dokáže odblokovat pouze jedno vlákno, zatímco událost může uvést do připraveného stavu vláken více. Chceme-li vygenerovat událost, stačí pouze daný příznak události (bit ve 32bitovém slově událostí) nastavit do logické jedničky. Na generování událostí a na čekání na události se využívají knihovní funkce operačního systému. Jejich praktické použití ilustruje následující příklad.

9.1.1

Příklad 19 – skupina událostí

V tomto příkladu si ukážeme, jak může naráz reagovat více vláken na jednu, nebo skupinu událostí. V našem příkladu budou dohromady čtyři vlákna. Dvě vlákna s nízkou prioritou budou generovat události. Další dvě vlákna s vysokou prioritou budou na události či jejich kombinace reagovat. První vlákno s nízkou prioritou bude generovat událost1, po 500 ms vygeneruje událost2, po dalších 500 ms opět událost1, a tak stále dokola. Druhé vlákno vždy po sekundě vygeneruje událost3. Vlákna s vysokou prioritou budou čekat na události. První vlákno bude reagovat na událost1 nebo událost2. Pokud některá z nich nastane, vlákno opustí blokovaný stav a podle toho, která událost nastala, odešle buď znak "a"nebo znak "b". Druhé vlákno bude reagovat pouze v momentě, kdy je vygenerována událost1 a zároveň událost3. V ten moment odešle znak "c". Obě vlákna po přečtení události nulují jejich příznaky. Také vytvoříme příznaky událostí a ukazatel na skupinu událostí.

91 Ukázka elektronické knihy, UID: KOS521714


KAPITOLA 9. UDÁLOSTI

uint32_t priznak1 = (1 << 0); uint32_t priznak2 = (1 << 1); uint32_t priznak3 = (1 << 2); EventGroupHandle_t udalostiUkazatel = NULL; static void VlaknoNizkaPriorita1( void *pvParameters ) { while(1) { xEventGroupSetBits(udalostiUkazatel, priznak1); vTaskDelay(pdMS_TO_TICKS(500)); xEventGroupSetBits(udalostiUkazatel, priznak2);

}

}

vTaskDelay(pdMS_TO_TICKS(500));

static void VlaknoNizkaPriorita2( void *pvParameters ) { while(1) { vTaskDelay(pdMS_TO_TICKS(1000));

}

}

xEventGroupSetBits(udalostiUkazatel, priznak3);

static void VlaknoVysokaPriorita1( void *pvParameters ) { EventBits_t priznaky = 0U; while(1) { // ceka nekonecnou dobu na priznak1 nebo priznak2, po precteni priznaky smaze priznaky = xEventGroupWaitBits(udalostiUkazatel, (priznak1 | priznak2), pdTRUE, pdFALSE, portMAX_DELAY); if((priznaky & priznak1) == priznak1) { while((USART2->ISR & USART_ISR_TXE) != USART_ISR_TXE); } else {

}

}

}

USART2->TDR = 'a';

while((USART2->ISR & USART_ISR_TXE) != USART_ISR_TXE); USART2->TDR = 'b';

92 Ukázka elektronické knihy, UID: KOS521714


9.1. FUNKCE

static void VlaknoVysokaPriorita2( void *pvParameters ) { while(1) { // ceka nekonecnou dobu, nez budou priznak a priznak3 zaroven aktivni // po precteni priznaky smaze xEventGroupWaitBits(udalostiUkazatel, (priznak1 | priznak3), pdTRUE, pdTRUE, portMAX_DELAY); while((USART2->ISR & USART_ISR_TXE) != USART_ISR_TXE);

}

}

USART2->TDR = 'c';

Ve vláknech používáme funkci na nastavení příznaků událostí: EventBits_t xEventGroupSetBits(ukazatelNaSkupinuUdalosti, generovaneUdalosti), kde • ukazatelNaSkupinuUdalosti je ukazatel na skupinu událostí, jejichž události bude funkce generovat, a • generovaneUdalosti je slovo příznaků událostí. Událost je generována nastavením příznaku do logické jedničky. Funkce vrací EventBits_t, což je slovo příznaků událostí při návratu z funkce. Tato návratová hodnota slouží k detekci přerušení funkce vláken čekající na událost a nulující příznaky. Pokud například funkcí nastavujeme události 0b11, ale návratová hodnota funkce je 0b10, víme, že funkce byla přerušena vláknem s vyšší prioritou, které čekalo na událost 0b01, kterou po přijetí smazalo. Dále používáme funkci čekání na příznaky událostí: EventBits_t xEventGroupWaitBits(ukazatelNaSkupinuUdalosti, ocekavaneUdalosti, vynulovaniUdalosti, cekatNaVsechnyUdalosti, pocetCasovychUseku), kde • ukazatelNaSkupinuUdalosti je ukazatel na skupinu událostí, na jejichž události bude funkce reagovat, • ocekavaneUdalosti je slovo příznaků událostí, v němž jednotlivé logické jedničky jednotlivých příznaků označují události, na které bude funkce reagovat, • vynulovaniUdalosti při hodnotě pdTRUE/pdFALSE vynuluje/nevynuluje příznaky událostí, na které funkce reaguje, • cekatNaVsechnyUdalosti při hodnotě pdTRUE bude funkce reagovat pouze když nastanou zároveň všechny události definované parametrem ocekavaneUdalosti (logický součin mezi příznaky událostí). Při hodnotě pdFALSE bude funkce reagovat na kteroukoliv událost (logický součet mezi příznaky událostí). Příklady viz v tabulce níže. Poslední parametr • pocetCasovychUseku je maximální počet časových úseků, po které bude funkci volající vlákno v blokovaném stavu čekat, než požadovaná událost (či více údálostí) nastane. Poté bude vlákno odblokováno.

93 Ukázka elektronické knihy


Turn static files into dynamic content formats.

Create a flipbook
Používáme FreeRTOS na mikrokontroleru STM32 (Ukázka, strana 99) by Kosmas-CZ - Issuu