2010
01.30

FreeRTOSFreeRTOS je operační systém reálného času pro vestavné zařízení. Téměř celý operační systém je napsán v programovacím jazyce C, pouze několik funkcí je vytvořeno v assembleru. Podporuje jak plně preemptivní tak kooperativní zpracování vláken. Jádro tohoto RTOS je složeno pouze ze tří souborů, a to task.c, queue.c a list.c.

FreeRTOS je jednou ze tří distribucí, které výrobce poskytuje. Zbývající dvě verze jsou:

  • OpenRTOS – komerční verze FreeRTOS, která sebou nese plnou podporu USB a TCP/IP.
  • SafeRTOS – certifikovaná verze pro bezpečnostní vestavné aplikace. Splňuje normu SIL3 dle IEC61508.

Pro komunikaci mezi vlákny, nebo mezi přerušeními a vlákny poskytuje komunikační a synchronizační nástroje typu fronta zpráv, (binární) semafor a mutex. Nástroj mutex zároveň řeší inverzi priorit.

Plánovač

Srdcem každého operačního systému je plánovač (scheduler). FreeRTOS disponuje plánovačem s prioritním plánováním, kdy je každému vláknu přiřazena hodnota jeho priority. Menší číslo znamená nižší přiřazenou prioritu, přičemž nejnižší možná hodnota je 0. V případě vláken se stejnou prioritou jsou vlákna plánována metodou „kruhu“ (Round robin). To znamená, že jsou pravidelně střídána. Maximální priorita je omezena na námi požadovanou hodnotu, kterou lze nastavit v souboru „FreeRTOSConfig.h“

Na následujícím obrázku (Obr. 1 ) jsou znázorněny stavy, ve kterých se vlákno může nacházet. V jednom okamžiku může být procesoru přiděleno pouze jedno, a to odpovídá stavu „Běžící“. Ostatní vlákna jsou v tom okamžiku ve stavu „neběží“, který se pak dále rozděluje:

  • Pozastaven (Suspended) – vlákna v tomto stavu nejsou přístupná plánovači. Každé vlákno lze umístit a vyjmout z tohoto stavu funkcemi vTaskSuspend() a vTaskResume().
  • Připraven (Ready) – vlákna v tomto stavu jsou připravena ke zpracování a čekají na přidělení plánovače.
  • Blokován (Blocked) – vlákna čekající na událost. Události mohou být časové (vlákno je zablokováno na určitý čas) a synchronizační (semafor, mutex, fronta zpráv).

Stavy, ve kterých se vlákno může nacházet

Obr. 1 Stavy, ve kterých se vlákno může nacházet

Vlákna (API funkce)

Systém FreeRTOS se skoro nedá ani nazývat „Operačním systémem“, je to spíše pouze jeho jádro (kernel), které obsahuje pouze plánovač a soubor API funkcí pro práci s vlákny a synchronizačními nástroji.

Abychom si ujasnili terminologii, porovnáme FreeRTOS se běžnými operačními systémy, jako je Linux, nebo MS Windows. Běžně se výpočetní výkon PC rozděluje mezi takzvané procesy, které běží ve svém vlastním paměťovém prostoru, a ty se pak dále dělí na takzvaná vlákna (threads), která mají společný paměťový prostor v rámci daného procesu, ve kterém byla vytvořena. Jelikož je FreeRTOS velice jednoduchý, neexistuje v něm striktní oddělení paměťového prostoru, hovoříme o vláknech, a nikoli o procesech.

V systému můžeme vytvořit tolik vláken, kolik máme operační paměti. Každé z nich si ukousne část paměti a s ní pak pracuje. Kolik paměti si vlákno vezme, mu říkáme při vytváření, atributem funkce „vTaskCreate()„. Mimo to že vlákno můžeme vytvořit, ho můžeme také smazat, změnit mu prioritu anebo suspendovat (dočasně pozastavit).

Synchronizační nástroje

Při běžném programování mikroprocesorů se snažíme psát kód tak, aby byl takzvaně „průchozí“, to je aby se nikde zbytečně nezastavoval v „čekacích“ smyčkách, a tím omezoval ostatní části programu. Aniž si to uvědomujeme, vytváříme tak kooperativní multitasking. Naopak při psaní vláken s preemptivním plánováním se snažíme využívat synchronizačních nástrojů, které zajistí, že při čekání například na příchod znaku ze sériové linky nespotřebovávají výpočetní čas procesoru vůbec, jsou takzvaně blokovány.

1. Mutex

Mutex je asi nejjednodušší synchronizační nástroj, který řeší úlohu takzvaného výlučného přístupu. Využíváme ho tam, kde může přistupovat do zařízení (paměti) vždy pouze jedno vlákno. Dobrým příkladem je například sběrnice IIC. Představme si, že dvě vlákna čtou přes tuto sběrnici data ze dvou různých zařízení. Transakce čtení ze zařízení se skládá z několika kroků, které nesmí být ve svém průběhu přerušeny, a proto před samotným zahájením komunikace se pokusíme o získání (zamknutí) mutexu funkcí „xSemaphoreTake()“. Pokud druhé vlákno v tomto okamžiku nekomunikuje (nevlastní mutex), mutex získáme, zahájíme komunikaci a po jejím skončení ho zase uvolníme „xSemaphoreGive()“. V případě, že druhé vlákno již mutex vlastní, operační systém zajistí, že našemu vláknu nebude přidělován čas procesoru do té doby, dokud nebude mutex opět volný.

2. Binární semafor

Binární semafor se využívá pro synchronizaci dvou vláken, nebo také hardwarového přerušení a vlákna. Využívají se především v úlohách typu „producent – konzument“, to je, když jedno nebo více vláken produkují data, nebo informace a další vlákno tyto data konzumuje. Proměnná binárního semaforu nabývá hodnot nula a jedna. Funkcí „xSemaphoreGive()“ se jeho hodnota nastaví na jedna, i když už před tím tuto hodnotu měl (tato funkce nemá blokující charakter). Funkcí „xSemaphoreTake()“ se hodnota semaforu nastaví na nulu, ale jen v případě, že měl hodnotu jedna. Pokud se v semaforu již nula nachází, vlákno se přesune do blokovaného stavu „Blocked“, a bude opět spuštěno až některé z vláken (producentů) hodnotu semaforu nenastaví na jedna.

3. Semafor

Semafor je další nástroj pro synchronizaci vláken. Může být použit pro počítání libovolných událostí, nebo opět pro úlohu typu „producent – konzument“. Je obdobou binárního semaforu, ale s tím rozdílem že jeho hodnota může nabývat kladných čísel včetně nuly. Pomocí funkcí „xSemaphoreGive()“ a „xSemaphoreTake()“ se inkrementuje a dekrementuje hodnota semaforu, podle kterého se řídí běh vláken. Zjednodušeně se dá říci, že semafor je proměnná, která může nabývat kladných čísel a jeho hodnota se mění pomocí funkcí „xSemaphoreGive()“ a „xSemaphoreTake()“.

Pokud zavoláte funkci „xSemaphoreTake()“ na semafor, který má hodnotu větší než 0, tak vykonávání programu nebude zablokováno. Pokud se zavolá funkce „xSemaphoreTake()“ na semafor, který má nulovou hodnotu, tak vykonávání programu bude blokováno do té doby, dokud jiné vlákno nezvýší semafor do kladných hodnot pomocí funkce „xSemaphoreGive()“.

4. Fronta zpráv

Fronta zpráv je ideální v případě, když potřebujeme nejenom dvě nebo více vláken synchronizovat, ale také rovnou mezi nimi i předávat data. Jedná se vlastně o paměť typu FIFO (First In First Out), která zároveň při pokusu o čtení prázdné paměti zařídí blokaci vlákna, které se o to pokusilo. Tím se zajistí, že vlákno, které slouží ke zpracování dat, ale nemá tyto data k dispozici, nedostává výpočetní čas procesoru do té doby, dokud nejsou nějaká data opět dostupná. Mezi dvě hlavní API funkce, pomocí kterých pracujeme s frontou zpráv, jsou „xQueueSend()“ a „xQueueReceive()“.

Závěr

Představili jsme si jednoduchý operační systém reálného času, který dokáže běžet i na 8bitových mikroprocesorech a je poskytován zdarma pod GNU licencí. To znamená, že nemusíme publikovat naše zdrojové kódy, ale pouze naše úpravy v jádře systému, takže se dobře hodí i pro komerční produkty. Výhodou je také možnost koupení mutace systému pro bezpečnostní aplikace splňující normu SIL3. Celý operační sysytém, včetně demo úloh je možné stáhnout ze stránek www.freertos.org

Tento článek nezabíhá moc do hloubky problému, ale ti, kterým tento OS zamlouvá, se mohou těšit na pokračování, ve kterém budeme postupně probírat jednotlivé části podrobněji, a samozřejmě vše vysvětlovat na ukázkách zdrojových kódů. Do budoucna chystáme i vývojový kit s nejnovějším mikroprocesorem PIC32 firmy Microchip, na kterém poběží právě tento operační systém.

Žádné komentáře.

Přidej komentář.

Musíte být přihlášen pro vkládání příspěvků.