česky english Vítejte, dnes je čtvrtek 21. listopad 2024

Návrh operačního systému reálného času pro embedded systémy

DPS 5/2011 | Články
Autor: Ing. Petr Volný

Základní úlohou operačního systému je plánování a obsluha zdrojů počítače pro jednotlivé úlohy, které na počítači běží. Mezi takto obsluhované zdroje patří procesor, operační paměť, sekundární paměti (disky, FLASH paměti pro data apod.) a různá komunikační rozhraní, jako jsou sériové a paralelní porty všech typů.

Cílem návrhu bylo vytvořit a implementovat reálný a provozuschopný operační systém, určený pro velmi malé počítačové systémy, disponující pouze jednotkami kilobyte paměti pro program i data. Zároveň by takový systém měl podporovat preemptivní multitasking, nějakou univerzální formu meziprocesové komunikace a podporu práce s přerušením.

Jako inspirace sloužil operační systém iRMX firmy Intel Corporation. Proto jsem jako pracovní název pro tento můj operační systém zvolil jRMX. Z hlediska jednoduchosti a i prostředí, kde daný operační systém poběží, pak vlastní jádro systému obsahuje pouze obsluhu (plánovač) procesoru a implementaci jedné formy meziprocesové komunikace. Obsluhy ostatních zdrojů počítačového systému mohou být implementovány ve formě uživatelských úloh, podobně, jako je tomu u iRMX firmy Intel.

Jako prostředí pro svůj chod potřebuje operační systém kromě procesoru a paměti také jeden systémový časovač. Od něj jsou odvozeny aktivity systému jako je přeplánování úloh, reálný čas a fronta časovače.

Plánování procesoru

Plánování procesoru je hlavní částí celého systému. Operační systém vytváří takzvané virtuální procesory pro každou běžící úlohu. Implementuje preemptivní multitasking s technikou „Round-robin“ pro úlohy se stejnou prioritou.

Úloha

Úloha je definována kódem a daty úlohy, zásobníkem a dvěma řídicími bloky.

Návrh operačního systému reálného času pro embedded systémy - tabulka1

Tabulka 1 Stavy úlohy operačního systému jRMX

Řídicí blok úlohy (TCB) je dynamickou strukturou, kterou operační systém používá pro simulaci virtuálního procesoru přiděleného úloze. Mimo jiné obsahuje stav a prioritu úlohy, registry procesoru a hodnotu časovače. Stavy úlohy jsou uvedeny v tabulce 1 a jejich přechodový graf je na obrázku 1. Priorita úlohy může nabývat hodnoty 0 až 255, přičemž nejnižší priorita je 0, nejvyšší je 255.

Návrh operačního systému reálného času pro embedded systémy 1.jpg

Obr. 1 Přechodový graf stavů úlohy

Informační blok úlohy (TIB) je statickou strukturou, která slouží k popisu úlohy a ve fázi startu operačního systému k aktivaci řídicího bloku úlohy.

Služby jádra operačního systému

Množina služeb jádra operačního systému je poměrně malá, avšak plně odpovídající potřebám daného systému. Navíc dodatečné vlastnosti lze implementovat pomocí existujících, jak bude například naznačeno v kapitole „Použití meziprocesové komunikace“.

Návrh operačního systému reálného času pro embedded systémy - tabulka 2

Tabulka 2 Funkce jádra operačního systému jRMX

Celkový seznam služeb jRMX udává tabulka 2.

Mechanismy meziprocesové komunikace

Operační systém jRMX implementuje pouze jednu formu meziprocesové komunikace, nazývanou schránka (mailbox). Schránka je datovou strukturou dvou front. Jedna fronta je frontou zpráv (message), zaslaných do dané schránky. Druhou frontou je pak fronta čekajícíchúloh u dané schránky. Tím je realizován klasický mechanismus, známý z teorie operačních systémů jako „producentkonzument“.

Schránky se rozlišují na globální a lokální. Globální schránky jsou definovány při startu operačního systému a předpokládá se jejich existence po celou dobu běhu systému. Lokální schránky jsou vytvářeny za běhu programu a jsou určeny pro jednu výměnu zpráv mezi dvěma úlohami. Po této výměně zpráv mohou zaniknout.

Zpráva, zasílaná do schránky, má povinnou část (hlavičku) tak, aby operační systém mohl se zprávou pracovat a nepovinnou část, což je jakákoliv struktura, odpovídající výměně dat mezi jednotlivými úlohami.

Tento mechanismus vede k přirozenému návrhu programu jako množiny spolupracujících procesů, které si mezi sebou zasílají zprávy. Typicky jsou takovými zprávami události nebo datové pakety. Speciální zprávy jsou zasílány funkcemi pro obsluhu přerušení.

Návrh operačního systému reálného času pro embedded systémy 2.jpg

Obr. 2 Možné stavy schránky

Možné stavy schránky jsou zobrazeny na obrázku 2.

Použití meziprocesové komunikace

Typickým použitím výše uvedeného mechanismu je zasílání zpráv mezi úlohami. V typické aplikaci má každá úloha jednu schránku, do které ostatní úlohy a obslužné funkce přerušení zasílají různé zprávy. Úloha je řešena jako nekonečná smyčka, kdy první akcí je volání jxWait() na svoji schránku. Po vybrání zprávy úlohou je tato zpracována a situace se opakuje. Je to vlastně klasická aplikace událostmi řízeného programování.

Návrh operačního systému reálného času pro embedded systémy - výpis 1

Jako další příklad použití meziprocesové komunikace uvedu implementaci binárního a čítacího semaforu. Semafory se používají ve víceúlohových operačních systémech pro synchronizaci přístupu více úloh k nějakému sdílenému prostředku, například ke sdíleným datům v operační paměti. Část kódu, která manipuluje se sdíleným prostředkem, se nazývá „kritická sekce“. Kritická sekce bývá ohraničena operacemi uzamknutí a odemknutí semaforu. Tyto operace lze v jRMX implementovat pomocí schránky a zprávy. Jak ekvivalent binárního semaforu je vytvořena schránka a do ní je zaslána právě jedna zpráva. Tato zpráva slouží jako klíč. Uzamknutí semaforu je pak provedeno úlohou pomocí funkce jxWait() jako pokus o získání klíče. Odemknutí semaforu je pak provedeno funkcí jxSend() s předchozí získanou zprávou (klíčem). Pokud byl klíč při pokusu o odemknutí již získán jinou úlohou, je tato nová úloha pozastavena do doby, než předchozí úloha vrátí klíč (zprávu) do schránky. Při implementaci čítacího semaforu je jediná změna v tom, že do schránky je na začátku zasláno tolik zpráv, kolik chceme, aby měl čítací semafor počáteční hodnotu. Příklad kritické sekce je uveden ve výpisu č. 2.

Návrh operačního systému reálného času pro embedded systémy - výpis 2

Časová fronta

Časová fronta slouží operačnímu systému pro obsluhu úloh, čekajících na zprávu u schránky, nebo těch, které volaly funkci jxSleep(). Je realizována jako obousměrný zřetězený seznam řídicích bloků úloh (TCB). Pro obsluhu časové fronty je definovaná funkce jxTimer-Tick(). Tato funkce musí být volána během obslužné funkce přerušení od systémového časovače.

Obsluha přerušení

Operační systém jRMX umožňuje ve funkci obsluhy přerušení zaslat zprávu do jakékoliv schránky. Zpráva pak typicky obsahuje doplňkovou informaci o typu přerušení, například zda je vysílací registr sériového řadiče prázdný nebo zda uplynul nějaký timeout od hardwarového časovače a podobně. Pro zaslání zprávy z obslužné funkce přerušení existuje speciální varianta jxISend().

Start systému

Pro start systému je nutno definovat seznam úloh a seznam globálních schránek. Ukazatele na tyto seznamy jsou umístěny do jedné struktury takzvaného Inicializačního řídicího bloku (ICCB), který je předán jako jediný parametr funkci jxInit(). Tato funkce inicializuje všechny globální schránky, všechny úlohy připraví k běhu a pak nastartuje plánovač procesoru, který spustí úlohu s nejvyšší prioritou.

Úloha Idle

Operační systém musí mít v době startu definovánu alespoň jednu úlohu. Úloha Idle bývá touto povinnou výbavou každého systému na bázi jRMX. Tato úloha má nejnižší prioritu 0 a bývá v ní často implementován mechanismus snižování spotřeby. Vzor takové úlohy pro procesor MSP430 je uveden ve zdrojovém kódu č. 1.

Implementace pro procesory ARM-Cortex M3

Toto jsou velmi výkonné 32bitové procesory, s mnoha periferiemi a relativně velkou operační pamětí vzhledem k nárokům operačního systému jRMX.

Kód jádra zabírá asi 1280 byte. Proměnné jádra pak 160 byte. Registry procesoru jsou uschovávány v zásobníku úlohy. Proto je nutné počítat s 60 byte zásobníku navíc. Procesor obsahuje mechanismy pro podporu operačních systémů, které jRMX využívá. Prvním zmíněným jsou 2 ukazatele zásobníku. MSP (Master Stack Pointer) je systémový zásobník, použitý při startu systému a jako zásobník pro obsluhu přerušení. PSP (Process Stack Pointer) je pak využíván pro jednotlivé úlohy.

Obslužné funkce přerušení se pro tento procesor mohou psát přímo v jazyce „C“ bez nutnosti jakýchkoliv speciálních direktiv nebo #pragma definic.

Dalším mechanismem, který jRMX používá pro přepnutí kontextu úlohy je výjimka PendSV. Tato výjimka je přímo doporučována k tomuto úkolu firmou ARM. Mimo jiné výhodou je, že během přepínání kontextu úlohy není vůbec zakázáno přerušení, což u ostatních architektur není možné.

Z hlediska výkonu plánovače úloh pak tyto procesory dosahují při taktovací frekvenci 48 MHz více než 120000 zaslání zpráv mezi úlohami za sekundu. K této variantě existuje také implementace UDP/IP protokolu, ovladače řadiče Ethernet pro procesory firmy Texas Instruments řady LM3S, a také například implementace SNMP protokolu, vše na bázi několika úloh operačního systému jRMX.

Implementace pro procesory MSP430

Procesory MSP430 mají velmi nízký příkon a mimo jiné proto většina modelů disponuje poměrně malou kapacitou paměti RAM, řádově od 128 byte až po 4 kilobyte. Několik větších modelů pak disponuje 16 kilobyte. Pro rozumné použití operačního systému je vhodná dolní hranice 1 kilobyte paměti RAM.

Pro úschovu kontextu procesoru a lokálních proměnných při přerušení je uměle (programově) vytvořen systémový zásobník, který je použit rovněž při startu systému. Ten pak uspoří kapacitu zásobníků jednotlivých úloh. Ty nemusí mít rezervován prostor v zásobníku na případnou obsluhu přerušení. Kód jádra zabírá asi 1200 byte. Proměnné jádra pak 48 byte. Registry procesoru jsou uschovávány v zásobníku úlohy. Proto je nutné počítat s 28 byte zásobníku navíc.

Návrh operačního systému reálného času pro embedded systémy - výpis3

Přerušení nemohou být zanořena, nesmí se tedy povolit přerušení během obslužné funkce přerušení. Obslužnou funkci přerušení je nutno psát v jazyce assembler. Výpis č. 3 ukazuje možnou realizaci takové obslužné funkce.

Závěr

Operační systém jRMX je implementován jako sada reentrantních funkcí v jazyce „C“, s výjimkou funkce jxTaskSw(), která způsobuje přepnutí kontextu úlohy. Tato funkce je napsána v assembleru pro daný typ procesoru. Kromě výše uvedených procesorů je tento systém rovněž implementován na procesory ARM7/ARM9, V850 a 78K firmy NEC (Renesas).

Komerčně se tento systém používá u výrobků firmy Softlink s. r. o (řada bezdrátových zařízení WACO). Samotný operační systém je distribuován ve formě knihovny funkcí a hlavičkového souboru pro překladač jazyka „C“.

Další podrobnosti a uživatelský manuál ve formě PDF souboru je možné získat na internetových stránkách www.jsoft.cz.