Jste zde

Co umožňuje a programátorovi přináší RTOS MQX od Freescale ? – 1.díl

MCU Kinetis a vývojový kit KWIKSTIK jsou ideální pro seznámení se a pokusy s real-time operačním systémem MQX. Jeho služby využívá i DEMO program pro KWIKSTIK. Pojďme se podívat, co MQX umožňuje a nabízí programátorovi, který ho využije.

V článku „Vývojová deska Freescale KWIKSTIK pro MCU Kinetis K40“ bylo mimo jiné obecně nastíněno, co představuje real-time operační systém MQX společnosti Freescale, který lze provozovat na všech výkonných procesorech v nabídce Freescale (MCU a CPU Coldfire, MCU Kinetis, PowerPC apod.). Dále byl v tomto článku stručně uveden zajímavý DEMO program právě pro MCU Kinetis K40 a vývojovou desku KWIKSTIK, ve které je i od výrobce přednahrán. I ten využívá služeb RTOS MQX a má být v tomto směru vodítkem pro začátečníky k zahájení vývoje vlastní aplikace / programu pro tuto platformu.

V následujících řádcích a odstavcích tohoto článku se teď zkusíme blíže podívat, co použití MQX programátorovi vlastně prakticky přináší a kde se vlastně v nabízeném DEMO programu využívá.

Co přináší MQX programátorovi?

Real-time operační systém MQX není OS v podobě, jak jej známe dnes například v podobě OS Windows. MQX je prakticky run-time knihovna funkcí, které může programátorem psaná aplikace využívat, aby mu jednak ulehčila práci (snadná práce se vstupy/výstupy, obsluhy přerušení, datová komunikace, správa paměti  apod.) a také aby se jeho program mohl stát v reálném čase běžící multi-tasking aplikací. Tedy programem, kde "paralelně" vykonává více funkcí (částí programu) současně a dělí se o pracovní čas procesoru. Díky již vytvořeným propracovaným MQX funkcím se tak programátor nemusí zabývat nastavováním bitů na úrovni jednotlivých registrů, řízení běhu programu, ošetřování hardwarových přerušení, ale prostě již využívá vhodného nastavení a volání různých MQX funkcí (tzv. komponent), které již sami v reálném čase zajistí a monitorují vše potřebné.

Programátor aplikace se tak nemusí detailně zabývat samotnou hardwarovou strukturou procesoru, pro který program vytváří, ale již pracuje na vyšší úrovni a může plně využívat možností programovacího jazyku C.

DEMO program pro desku KWIKSTIK

I když to již bylo uvedeno v druhé polovině článku "Vývojová deska Freescale KWIKSTIK pro MCU Kinetis K40", raději zde připomenu, co DEMO program pro Freescale kit KWIKSTIK provádí. Zdrojové kódy pro nahlédnutí lze stáhnout zde. Jinak pro praktické hraní doporučuji si stáhnout ze stránek Freescale samoinstalační balíček poskytující kompletní projekt pro CodeWarrior for MCU 10, ve kterém mám vyzkoušeno, že vše opravdu je k dispozici a běhá, jak má (viz stránky www.freescale.com/webapp/sps/site/prod_s....).

Demo program obsahuje několik režimů, kterými umožňuje: nahrání několika sekund zvuku z mikrofonu do vnitřní paměti MCU a následné přehrání (režim Sound Recorder), chovat se jako dálkový ovladač (režim Remote Control), po připojení přes USB do PC pracovat jako myš (režim USB HID Mouse), zahrát si pomocí tlačítek a LCD displeje hru „FreTris“ (obdoba Tetrisu). Všechny tyto režimy jsou v programu realizovány jako jednotlivé úlohy (Tasks), běží v područí RTOS MQX a jsou voleny ze společného menu ovládaného dotykovými kapacitními tlačítky. Volící menu tak prakticky realizuje následující stavový automat:

Komponenty a příklady použití MQX

MQX se skládá z komponent jádra a doplňkových rozšiřujících komponent. V případě komponent jádra (core components) pak pouze ty, které jsou využívány MQX nebo volány aplikací, se vloží při překladu do programu. Tím se minimalizuje velikost kódu. Ke splnění dalších požadavků, které rozšiřují aplikace a konfigurují komponenty jádra, se pak dále vkládají další doplňkové komponenty (optional components).

Inicializace MQX (Initialization)

Dá se říct, že mezi hlavní a nejdůležitější části jádra patří komponenta „Inicializace“ (Initialization). Tato  funkce totiž inicializuje hardware a spustí MQX. To následně vytvoří a spustí úlohy (tasks), které jsou v inicializaci definovány jako „autostart“ (autostart tasks). Bez komponenty inicializace by tedy se MQX ani program nespustil a neběžel.

Konkrétně inicializace provádí následující kroky:

  • Nastaví a inicializuje data, která MQX využívá interně, včetně základní paměťové oblasti, fronty, zásobníku přerušení a úloh.
  • Inicializuje hardware.
  • Uvolní časovače.
  • Nastaví základní hodnoty časového dělení (time slice).
  • Vytvoří čekací úlohu (Idle task), která bude aktivní v případě, kdy žádná další úloha neběží.
  • Vytvoří úlohy, které jsou definovány v seznamu úlohu (task template list) s definicí „autostart task“.
  • Zahájí plánování úloh.

Seznam úloh (task template list) definuje takovou zahajovací skupinu, ze kterých mohou být v procesoru úlohy vytvořeny. Po inicializaci MQX vytvoří jeden exemplář každé úlohy, která na seznamu figuruje s položkou „autostart task“. Tyto úlohy pak mohou dále vytvářet a spouštět další úlohy. Konec seznamu úloh je vždy zakončen „nulovou úlohou“.

Příklad provedení inicializace MQX a provedení seznamu šablon úloh v DEMO programu pro KWIKSTIK:

Inicializaci a definování seznamu úloh má v DEMO programu pro KWIKSTIK na starosti zdrojový kód v souboru „Task.c“:

Část zdrojového kódu pro inicializaci MXQ v DEMO programu pro KWIKSTIK (soubor „Task.c“ ).

Z příkladu je patrné, že v inicializaci jsou pro automatické spuštění uvedeny prakticky všechny jednotlivé funkce / úlohy (hlavní smyčka - Main_Task, USB komunikace s PC v režimu Mouse - USB_Task, ovládání pomocí kapacitních tlačítek - TSI_Task, režim dálkového řízení infračerveným světlem - _RemoteControl_Task, režim nahrávání a přehrávání zvuku - _SoundControler_Task, hra Fretris - F_Task a také úloha nabíjení, monitorování a indikace stavu akumulátoru desky KWIKSTIK).

Všechny úlohy až na "Status_Task" mají nastaven autostart (položka MQX_AUTO_START_TASK), tedy se vytvoří a zprovozní hned po rozběhu MQX. Pouze "Status_Task" se spouští "ručně" z úlohy "Main_Task" (viz příklad níže v odstavci správy úloh). Nejvyšší prioritu však má úloha sledování a vyhodnocení stisku dotykových tlačítek „TSI_Task“), nejnižší prioritu naopak hra FRETRIS (úloha "F_Task"). Čísla v sloupci "Stack" pak udávají adresu v zásobníku, kam se mají ukládat a kde číst data úlohy při jejím opětovném vyvolání. Označení ve sloupci "TASK INDEX" pak slouží pro identifikaci, např. pro přechod na danou úlohu.

Řízení a správa úloh (Task management)

Další komponentou jádra je řízení úlohy (Task management). Automaticky spuštěné úlohy po spuštění MQX totiž mohou dále spravovat (vytvářet, spouštět, zastavovat, rušit) další úlohy běžícího programu. Lze provádět i několikanásobné spuštění stejné úlohy a není definován žádný limit na počet běžících úloh v aplikaci. Tyto úlohy koexistují, protože mají unikátní identifikaci. MQX udržuje každou úlohu ukládáním jejího obsahu (program counter, registry a zásobník). Zároveň lze dynamicky za běhu provádět změnu atributů každé úlohy podle potřeby. Po ukončení každé úlohy pak MQX automaticky uvolní paměť a její prostředky pro další úlohy. Pro každou úlohu lze také specifikovat výstupní funkci (exit function), kterou MQX zavolá při ukončování úlohy, nebo správce výjimek (exception handler), který MQX zavolá, pokud za běhu úloh dojde k nějaké neočekávanému stavu.

Příklad využití příkazů a funkcí správy úloh v DEMO programu pro KWIKSTIK:

V hlavní smyčce programu, úloze Main_Task (soubor „Task-Main.c“) lze například najít „ruční“ inicializaci a vytvoření úlohy STATUS_TASK funkcí _task_create :

Dále například v úloze _RemoteControl_Task v souboru "Mouse.c" se využívá funkce _task_block() pro blokování aktuálně aktivní funkce, zde z důvodu zajištění USB HID komunikace:

Plánování (Scheduling)

Další komponentou jádra je plánovaní (Scheduling). To splňuje požadavky POSIX.4 a podporuje následující chování:

  • FIFO plánování (priority-based preemptive) - úloha s nejvyšší prioritou je nejdéle aktivní. FIFO plánování je základní plánovací prostředek. Úloha, která má běžet po aktuálně běžící úloze, je ta s největší prioritou, která čekala nejdelší dobu. Tato úloha běží až do doby, kdy procesor je volán blokovací MQX funkcí, nastane přerušení s vyšší prioritou než má běžící úloha, či dokud nějaká jiná úloha s vyšší prioritou je připravena. Změnu priority lze programově provést zavoláním funkce _task_set_priority().
  • Round robin plánování (time slice) - úloha s nejvyšší prioritou je aktivní po nejdelší dobu bez spotřebovávání vlastního časového úseku. Systém Round robin je podobný FIFO plánování, ale s přidaným dalším omezením. Každá úloha totiž má přiděleno maximální množství času (časový úsek - time slice), po kterou může být aktivní. Jestliže časový úsek (time slice) vyprší pro aktuálně běžící úlohu, MQX uloží její obsah, pozastaví ji a spustí další úlohu, která je aktuálně ve frontě na řadě. Právě pozastavená úloha se zařadí na konec fronty. Pokud po úloze, které uplynul čas žádné ve frontě nečeká, pokračuje tato úloha dále v provozu až do doby připravenosti další úlohy.
  • Otevřené plánování (explicit scheduling) - využívá frontu úloh k přesnému přímému plánování nebo k vytvoření více komplexního synchronizačního mechanismu. Protože fronta úloh poskytuje nejmenší rozsah funkcí, je tedy nejméně náročná na zpracování a tedy je i nejrychlejší. Aplikace (program) může specifikovat pravidla FIFO nebo round-robin plánování během vytváření fronty úloh.

 

Události (Events)

Události (Events) jsou doplňkovou komponentou. Podporují dynamickou správu objektů, které jsou formátovány jako bitová pole. Úlohy a služby rutin přerušení mohou využívat události k synchronizaci a přenosu jednoduché informace ve formě změn stavu bitů. Jsou pojmenovány a sdruženy do skupin událostí (Event groups). Počet bitů události ve skupině událostí se definuje při založení skupiny. Jakákoliv úloha může čekat na tyto bity. Jestliže nejsou nastaveny, úloha je blokována, přičemž jakákoli jiná úloha nebo přerušení ISR může tyto bity nastavit. Když se tak stane, MQX spustí všechny úlohy, které čekají na splnění stavu. Každá skupina událostí (Events group) pak navíc má samočisticí bity, kterými po jejich nastavení MQX okamžitě vynuluje všechny ostatní bity skupiny. Aplikace pak může nastavovat bity i ve skupině událostí definované na vzdáleném procesoru.

Každá skupina je identifikována unikátním jménem ve formě řetězce znaků nebo číslem v případě rychlých skupin událostí. Každá aplikace (program) může otevřít skupinu událostí aplikace i na vzdáleném procesoru a nastavit její bity.

Příklad použití událostí v DEMO programu pro KWIKSTIK:

Komponenty události využíval programátor tohoto DEMO programu velmi hojně a jeho příkazy najdeme prakticky ve všech částech celého programu. Slouží zde pro předávání jednoduchých informací mezi jednotlivými režimy programu (úlohami). Typický pěkný příklad vytvoření skupiny události (funkce _event_create), jejího otevření (_event_open) a nastavení události (_event_set) je v úloze TSI_Task, která zajišťuje snímání a vyhodnocení stisku kapacitních tlačítek desky KWIKSTIK:

Část zdrojového kódu ukazující využívání komponenty událostí v DEMO programu pro KWIKSTIK (soubor „TSI_Task.c“ ).

Semafory (Semaphores)

Další doplňkovou komponentou jsou tzv. semafory (Semaphores). Konkrétně jde o počítací semafory a lze je použít k synchronizaci úloh nebo k ochraně přístupu ke sdíleným datovým zdrojům nebo pro implementování signalizačního mechanismu. Semafory poskytují vytváření FIFO front (FIFO queuing), priorit front a dědění priorit.

Zprávy (Messages)

Další doplňkovou komponentou jsou zprávy (Messages). Jejich prostřednictvím mohou úlohy mezi sebou komunikovat prostřednictvím přidávání zpráv do fronty zpráv otevírané jinou úlohou. Každá úloha otevírá svoji vlastní frontu zpráv, která je jasně identifikovatelná pomocí speciálního ID, které přidělí MQX při jejím založení. Pouze úlohy, které otevírají frontu zpráv mohou přijímat zprávy do fronty prostřednictvím sdílení prostoru systémových zpráv (system-message pools) a prostoru privátních zpráv (private-message pools). Každá úloha pak může alokovat zprávy (systémové zprávy) z prostoru sdílení systémových zpráv a každá úloha s ID může alokovat privátní zprávy z prostoru sdílení privátních zpráv.

Čas a časovače (Time and Timers)

Komponenta čas (Time) a časovač (Timer) je také doplňkovou částí MQX a lze ji povolit či zablokovat na úrovni BSP (Board Support Package - souhrn hardwarově závislých souborů zohledňující vlastnosti jednodeskových počítačů). K dispozici je zde hodnota prošlého času (elapsed time) a absolutního času (absolute time). V případě absolutní času je možné jej nastavit na konkrétní hodnotu podobně, jako když seřizujete hodinky. Rozlišení času závisí na programem definovaném rozlišení, které se nastavuje vzhledem ke konkrétnímu použitému hardwaru, na kterém MQX běží. Vnitřně MQX udržuje čas jako 64bitový čítač počtu tiků taktování procesoru od doby, kdy byla aplikace (program) na procesoru spuštěn. To mimochodem poskytuje velmi dlouhou dobu, než dojde k přetečení čítače (v případě taktu 1 ns by to trvalo 584 let). Časovače mohou poskytovat jako jednorázové odpočítávání času (one-shot timers), které po vypršení skončí, nebo periodické odpočítávání času (periodic timers), které periodicky stále dokola odpočítávají zadanou periodu. Časovače lze spustit buď v přesně specifikovaném čase nebo po definovaném prodlení. Oznamovací funkci lze pak použít pro synchronizaci úloh zasíláním zpráv, nastavováním událostí nebo použitím jednoho ze synchronizačních mechanismů MQX.

K dispozici jsou i tzv. lehké časovače (Lightweight timers), které poskytují mechanismus pro periodické volání částí programů ve zvolených intervalech. Lehké časovače jsou vytvářeny periodickou frontou hodnot časů, které se přičítají k běžícímu časovači jako ofset k začátku periody. Jestliže přidáte lehký časovač do fronty, specifikuje se tím oznamovací funkce, která bude volána MQX přerušením „MQX tick ISR“, když časovač dospěje k požadovanému času. Protože časovač běží z ISR (služby řízení přerušení), nelze takto volat všechny MQX funkce.

Příklad použití časování v DEMO programu pro KWIKSTIK:

Též komponenty času a  časovačů jsou v programu využívány dost hojně, hlavně prostřednictvím funkce _timedelay(). Možností je však daleko více. Stačí se podívat jen do referenčního manuálu k MQX, který má 486 stránek a popisu syntaxi a základní použití většiny funkcí MQX. Jen pro časování se v něm nachází více než 30 funkcí („příkazů“). Funkce _timedelay pak dělá jen „triviální“ zpoždění běhu programu o x sekund. Zajímavější pak jsou funkce pro řízení času (např. _time_get a _time_to_date).


Část zdrojového kódu ukazující využívání komponenty Timer v DEMO programu pro KWIKSTIK (soubor „Main_Task.c“ ).

Softwarový watchdog

Samozřejmostí u každého MCU je dnes watchdog. Musíme však rozlišovat watchdog hardwarový a softwarový. V případě hardwarového watchdogu se v případě zablokování programu provede reset celého procesoru, tedy kompletní nové spuštění celé aplikace. V případě softwarového watchdog pak nadřazený program v podobě operačního systému monitoruje běh (zacyklení, zablokování) na úrovni jednotlivých úloh (Tasks) a když nějaká z nich nepracuje správně, prostě se resetuje jen ta jedna úloha, nikoliv kompletní běh aplikace. Ostatní úlohy tedy normálně pracují dále.

Principielně však tento softwarový watchdog pracuje stejně jako ten hardwarový, tedy po spuštění úlohy běží časovač a pokud jej úloha do daného momentu nezastaví či neresetuje a watchdog přeteče, dojde k resetu dané úlohy, ke které přísluší. To provádí přímo samotné jádro MQX, které vyvolá pro tento účel specializovanou funkci, které reset úlohy vyvolá nezávisle na tom, jak je funkce naprogramovaná. V případě současného běhu většího množství úloh je to velmi užitečná funkce.

Přerušení (Interrupts)

Přerušení (Interrupts) a správa výjimek (exception handling) je doplněk na úrovni PSP (Processor Support Package - skupina specifických souborů pro daný typ CPU). MQX obsluhuje všechna hardwarová přerušení v celém rozsahu, jak jej definuje BSP a ukládá minimální množství pro aktivní úlohy. MQX plně podporuje všechna přerušení, která podporuje i CPU / MCU. Jakmile je aktivní nějaká rutina obsluhy přerušení ISR (Interrupt Service Routine), aplikace ji může znovu povolit jakoukoliv úroveň přerušení. K dalšímu zredukování prodlevy obsluhy přerušení, umí MQX "pozdržet" přeplánování úloh až do doby, kdy všechny ISR proběhly. Pro redukování velikosti zásobníku, MQX podporuje oddělený zásobník pro přerušení (interrupt stack).

ISR není úloha. Je to malá a velmi rychlá rutina napsaná přímo v asembleru, která co nejrychleji reaguje na hardwarová přerušení. ISR lze použít k signalizaci úlohy s jakoukoliv MQX neblokující funkcí. Když MQX zavolá rutinu obsluhy přerušení ISR, předá jí parametry, které jsou definovány aplikací při vzniku ISR. Takovým parametrem může být například ukazatel na konfigurační strukturu, která specifikuje hardware. ISR může běžet i v režimu, kdy jsou nějaká přerušení vypnuta v závislosti na tom, na jaké úrovni priority jsou obsluhovány. Obecně je vždy nutné, aby ISR vykonávala co nejméně funkcí, protože cílem je co nejrychlejší předání informací a stavů, které přerušení vyvolá, dané úloze ke zpracování. S tím souvisí i priorita dané úlohy. Čím vyšší prioritu má, tím dříve je i její přerušení zpracované.

Jádrem celého řízení obsluhy přerušení ISR je v MQX malý kernel ISR, který MQX při svém startu povoluje všechna dostupná přerušení. Tento kernel běží nad všemi ostatními ISR a provádí například ukládání obsahu aktivních úloh, přepíná zásobník přerušení, volá příslušné ISR a po návratu ISR obnovuje obsah úlohy s nejvyšší prioritou.

Příklad použití časování v DEMO programu pro KWIKSTIK:

Samozřejmě, že DEMO program též využívá obsluhy přerušení ISR. Například se využívá pro časování režimů dálkového ovládání Remote Control, nahrávání a přehrávání zvuku Sound Recorder a zvukových upozornění Buzzer:

Část zdrojového kódu ukazující využívání rutiny obsluhy přerušení ISR v DEMO programu pro KWIKSTIK (soubor „Main_Task.c“ ).

Záznamy (Logs)

A nakonec jsou tu záznamy (Logs) také jako doplňková komponenta, která umožňuje ukládat a vyvolat specifické informace aplikace. Každý záznam má časovou značku a číslo sekvence. Tyto informace lze využít pro testování, ladění a analýzu výkonu.

Závěr 1.dílu

Zde v 1. dílu nastíněné vlastnosti MQX jsou jen základními možnostmi tohoto real-time operačního systému. Tyto funkce jsou pak přesně a detailně popsány i s příklady v referenčního manuálu MQX (486 stran ) - MQXRN.pdf a v MQX User’s Guide (216 stran) - MQXOUG.pdf

Mimo zde uvedených komponent a funkcí poskytuje i dále správu a řízení paměti, vstupů / výstupů, podporu datové komunikace či vytváření a správu souborů, například na Flash kartě. Tyto funkce jsou také použity a předvedeny v DEMO programu pro KWIKSTIK u nahrávání a přehrávání zvuku (I/O drivery) a komunikace KWIKSTIKU s PC přes USB ve formě simulace USB myši. Do této „kuchyně“ pak nakoukneme v 2. dílu o MQX.

Článek vytvořil: Antonín Vojáček

DOWNLOAD & Odkazy

Přílohy: 
PřílohaVelikost
PDF icon MQXRM.pdf1.43 MB
PDF icon MQXIOUG.pdf641.38 KB
Package icon zdrojovy_kod_DEMO_KWIKSTIK.zip239.42 KB
Hodnocení článku: 

Komentáře

Dobrý den
Chtěl jsem odzkoušet své vlastní funkce pro MQX na 52259 ale ve spec.edici to nahlásilo překročení limitu, je nutno použít vyšší verzi. Nevím jestli existuje možnost nahrát MQX do flash a v CW 7.2 SE a pak vytvářet jen funkce, které by se k flash přihrávaly.

Pavel

Obecně speciální edice CW není pro práci MQX vhodná, protože je velká pravděpodobnost, že narazíte na limit. Teda já to zatím zkoušel jen s nejnovějším CW MCU 10.1 (Eclipse IDE) a s Kinetisem K40 a mimo prakticky absolutně oklešného MQX s miniaturním jednoduchým prográmek (ta prošla) to jinak ve verzi Special Edition vždy narazilo na nějaký limit či omezení. Na plné verzi (tj. i na stáhnuté trial plné verzi omezené na 30 dní) to pak je bez problémů. Jinak nevím o možnosti MQX nahrát na Flash a pak přidávat jen aplikace jako u "větších OS". Ale nejsem expert...

zdravim,
je mozne buildnout knihovny (tak jak to je vyzadovano po instalaci mqx) v codewarrior verze basic(tzn c kod o maximalni velikosti 512KB) ? verze standart je uz mimo moje financni moznosti.