Použití OS Linux pro měřicí aplikace

measure.feld.cvut.cz

Použití OS Linux pro měřicí aplikace

ČVUT - Fakulta ElektrotechnickáBakalářská prácePoužití OS Linux pro měřicí aplikaceJakub Kocourek2009


Čestné prohlášeníProhlašuji, že jsem svou bakalářskou práci vypracoval samostatně a použil jsem pouze podklady (literaturu,projekty, SW atd.) uvedené v přiloženém seznamu.Nemám závažný důvod proti užití tohoto školního díla ve smyslu § 60 Zákona č.121/2000 Sb., o právuautorském, o právech souvisejících s právem autorským a o změně některých zákonů (autorský zákon).Datum:Podpis:2


Děkuji Doc. Roztočilovi za pomoc při tvorbě této práce a cenné připomínky. Special thanks to IanAbbotti, the author of Amplicon driver, for comprehensive information about DIO card and its driver.3


Použití OS Linux pro měřicí aplikaceTato práce sa zabývá generováním přesného času v operačním systému Linux, s použitím běžného počítačePC a univerzální DAQ měřicí karty. Popsána a vyzkoušena jsou rozšíření RT_PATCH a Xenomai,aplikovaná na standardní jádro GNU/Linux, včetně měření latence systému a přerušení.Building Measurement Applications underLinuxThis thesis is focused on generation of time in Linux operating system, using standard personal computerand DAQ card. There are theoretical information abou RT_PATCH and Xenomai extensions in the text.Both were tested for time generation and reviewed. System and interrupt latency were tested too.4


Obsah1 Real-Time 71.1 Parametry RT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.2 Real-time v měřicích aplikacích . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Linux 92.1 Rozšíření pro RT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.2 RT patch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.3 RTAI (Xenomai) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.4 Comedi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Časovače v PC 143.1 PIT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.2 RTC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.3 APIC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.4 TSC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.5 HPET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.6 Problémy časování . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Měřicí karty 164.1 NI PCI 6221 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164.2 Amplicon PCI 236 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Generování přesného času 185.1 Latence systému . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185.2 Sekundový generátor s HPET časovačem a RT_PATCH . . . . . . . . . . . . . . . . . . . 185.3 Sekundový generátor s TSC časovačem a Xenomai . . . . . . . . . . . . . . . . . . . . . . 195.4 Zpětnovazební sekundový generátor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195.5 Latence přerušení . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 Výsledky 216.1 Postup měření . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216.2 Výpočty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Zhodnocení 258 Použitá literatura 265


OBSAHA Zdrojový kód - test latence systému 27B Zdrojový kód - sekundový generátor s HPET časovačem 29C Zdrojový kód - sekundový generátor s TSC časovačem 31D Zdrojový kód - latence přerušení 346


KAPITOLA 1Real-TimeV literatuře lze najít nejrůznější definice Real-time (dále jen RT) systémů, často ale ne příliš přesné.Obecně lze za RT označit libovolný systém, který splňuje námi zadané časové podmínky, ať už chcemeasynchronně spouštět různé úlohy s určitou garantovanou prodlevou nebo žádáme spouštění periodické.1.1 Parametry RTV obou případech definujeme tzv. Release time, neboli minimální prodlevu, se kterou se úloha spustí(čas na přípravu úlohy) a Deadline, neboli maximální dobu dokončení. U periodických úloh navíc žádámedodržení periody běhu.Systémy se ještě často dělí na Soft a Hard Real-time. Platí, že pokud žádáme přesné dodržení mezíRelease time a Deadline, jedná se o Hard Real-time. Když chceme jen udržení určitých kvalitativníchvlastností (např. maximální počet nedodržení Deadline za časový úsek), pak užíváme označení Soft Realtime.Takové chování si ale můžeme dovolit jen v málo RT aplikacích.Mezi další charakteristické parametry Real-time systému (např. z pohledu odezvy přerušovacího systému)patří latence a jitter. Latence obecně značí dobu mezi zadáním požadavku a jeho provedením.V našem případě se může jednat např. o čas mezi příchodem přerušovacího signálu a jeho obsluhou.Rozkmit latence od střední hodnoty se nazývá jitter.Naprostá většina průmyslových aplikací vyžaduje Hard Real-time. Jako příklad uveďme embededsystémy pro automatické řízení vlaků [9]. RT systém musí na asynchronní události (změna semaforu)reagovat v garantovaném čase, aby mohl bezpečně provést odpovídající akci. Takovýto systém nepřipouštípozdní zpracování.Uvedeným příkladem se dostáváme k problému garance latence. Je relativně snadné garantovat odezvujednoduchých specializovaných systémů, např. snímání a regulace otáček motoru jednoúčelovým uP.V takovém případě známe počet běžících úloh a dobu potřebnou k jejich vykonání. Zde je tedy možné předemsestavit tabulku plánovače (statické plánování) a případné sporadické úlohy umisťovat do časovýchmezer.Ve chvíli, kdy je třeba reagovat na asynchronní události a dodržet jejich striktní Deadline, začínajíproblémy. Je nutné rozhodnout o prioritě úloh, zajistit preemptivitu a plánovat spouštění tak, aby bylydodrženy požadované parametry. Zde nastupují algoritmy dynamického rozvrhování. Např. algoritmusEDF (Earliest Deadline First) umožňuje přeskládávat úlohy podle jejich termínu Deadline.7


KAPITOLA 1. REAL-TIME1.2 Real-time v měřicích aplikacíchK nasazení v měřicí a regulační technice je třeba vybrat správný systém. Pro safety critical aplikace,jako je řízení velkých strojů, nemocničních zařízení, atd., se obvykle preferuje nasazení embeded systémů,které jsou na RT připraveny a případně se spojují do většího celku, který řídí klasické PC s RT systémem.V těchto případech se ještě užívají speciální zařízení, jako např. Watchdog timer, pro ošetření případnéhoselhání, redundantní čidla i celé systémy, atd.Pro běžné měření a regulaci pomocí DAQ karet postačují PC s RT operačním systémem. Je všaktřeba počítat s omezeními danými operačním systémem a hardwarem PC. Systémová volání a obsluhypřerušení mohou předbíhat jiné úlohy, maximální rozlišení času je dáno systémovým časovačem (obvykleHPET nebo TSC). Funkce jako SMI (viz dále) mohou poškodit časování. SMI, DMA a další hardwarovézáležitosti mohou způsobit i nedodržení nejhorších stanovených hodnot Release time a Deadline.Je však pravdou, že i přes uváděné problémy s nasazením PC v safety critical aplikacích, již existujenapř. systém PikeOS (výrobce Sysgo), postavený na takovémto hardwaru s využitím OS Linux, kterýmá certifikace DO-178B, IEC 61508 a EN 50128. Jedná se v podstatě o upravený GNU/Linux, s mikrokernelem a výborným vrstvením systému. PikeOS také nabízí široké spektrum podporovaných vývojovýchAPI a platforem, vzdálené ladění a monitoring po síti LAN, update systému bez nutnosti výpadku, atd.Dále viz. [2].8


KAPITOLA 2LinuxGNU/Linux je primárně určen k serverovým a desktopovým aplikacím. Nicméně díky podpoře mhoharůzných platforem vznikly i nejrůznější úpravy jádra pro speciální nasazení. Knihovny Comedi, kterépoužívám pro řízení DAQ karty, jsou kompatibilní s RT patchem Ingo Molnára a RTAI.2.1 Rozšíření pro RTVe standardním jádru se nachází mnoho kritických sekcí, jejichž souběhu (při přerušení nebo preempci)brání spin locky – zámky paměti s aktivním čekáním. Také vykonání přerušení může úlohy blokovatna velmi dlouho. Patch mění povahu obslužných rutin přerušení na běžné úlohy, kterým je možné přiřaditpříslušnou prioritu (nižší, než má RT úloha). Prodlevy při souběhu vláken jsou místo spin lockuřešeny mutexy, které umožňují uzamknout jednotlivé nezávislé kritické sekce různým úlohám (CPU senevyhradí pro jednu úlohu, která vyvolala spin lock pro libovolnou sekci). Patch mění část jádra, ale proprogramátora uživatelských aplikací je transparentní .RTAI sází na jinou koncepci. Místo úpravy jádra pouze přidává nový modul 1 , který funguje jakovrstva HAL mezi operačním systémem a skutečným hardwarem, která plánuje přerušení a programujesystémový časovač. RTAI nabízí dva módy činnosti. Primární mód garantuje zpoždění aplikace do 50 us(nejhorší případ) a k plánování využívá nepřerušitelný co-scheduler. Pokud se mají vykonávat standardnísystémová volání, úloha přejde do sekundárního módu, ve kterém již nemá takovou prioritu. Tento módzaručuje pozdržení přerušení, do doby než doběhnou RT úlohy, aby nevznikaly nežádoucí prodlevy. Vznikázde tedy skutečně něco mezi vrstvou HAL a virtualizací OS.Při přípravě jádra Linux jsem zkoušel aplikovat oba dva patche. Úprava Ingo Molnára je dnes jižve stabilním stavu a nezaznamenal jsem žádný problém. Naopak RTAI nefunguje tak jak má, neobsahujeuniverzální patche Adeos/I-Pipe, ale své modifikace, nekompatibilní s mnoha verzemi jádra. Instalačníproces je pro systémy Unixového typu značně nestandardní a poskytované API není příliš „programátorskypřívětivé”. Z těchto důvodů jsem RTAI nahradil patchem Xenomai. Jedná se o mladší větev RTAI,oddělenou od původního vývoje.Další informace o RT modifikacích a jejich srovnání lze najít v [10].1 Dnešní implementace Xenomai jádro upravuje, viz [12], myšlenka HAL je využita nadále.9


KAPITOLA 2. LINUX2.2 RT patchPro použití RT patche je běžně potřeba překompilovat jádro. Po několika testech latence jsem však zjistil,že RT jádro, které je součástí distribuce Ubuntu, vykazuje nejlepší parametry. I přes použití tohoto zdeuvedu některá nastavení, nutná při kompilaci [6]:• pro správnou funkci je zásadní hardwarová podpora přesných časovačů a její zapnutí v jádře (HPETči TSC)• dále je nutné deaktivovat APM, nechat aktivní ACPI (pro funkci HPET), ale její části vypnout –nadbytečné moduly správy napájení zvyšují latenci a vyvolávají nežádoucí přerušení• aktivovat volby „CONFIG_PREEMPT=y“, „CONFIG_PREEMPT_RT=y„ a také vysoce přesnéčasovače „CONFIG_HIGH_RES_TIMERS=y“• jakékoliv ladicí volby (debug) prodlužují latenci jádra• neaktivujte podporu swapu – výpadky stránek (page fault) vedou k velké latenci• podpora škálování CPU (změna napájení/frekvence za běhu) nesmí být povolena (může mít vlivnejen na výkon, ale i funkci některých časovačů)I při správném nastavení jádra je potřeba dát pozor na některé hardwarové problémy. Největším z nich jeSMI mód procesoru. Ten může být kdykoliv vyvolán hardwarem a má větší prioritu než nemaskovatelnápřerušení. Když procesor přejde do SMI, vykoná obslužný kód z pevně dané adresy (obvykle BIOSROM) a systém nejen nemůže rutinu zdržet, ale ani není schopen přechod do SMI detekovat a reagovatna něj. Tento problém působí latenci až v řádu stovek mikro sekund a projevuje se na x86 platformě ive specializovaných RT operačních systémech.Další systémově nezávislou latenci v řádu mikro sekund může působit přidělování DMA (s tímtoproblémem jsem se nesetkal). V lepších případech je možné latenci ovlivnit nastavením ovladače.VGA konzole působí velmi vysokou latenci. Zápis na ni může zcela znehodnotit běh RT aplikace. Jedoporučeno využít sériovou konzoli, SSH, grafické prostředí nebo framebuffer.Při psaní RT programů je potřeba dodržovat některé zásady. Předně je nutné vyvarovat se výpadkustránek. Nelze v RT sekcích pracovat se soubory, které nejsou načtené v operační paměti a provádět dalšísystémová volání, která mohou způsobit výpadek stránky. Vlákna s RT prioritou se vytváří na začátkuprogramu – ne dynamicky. Stejně tak je vhodné pro pozdější dynamickou alokaci paměti vyhradit místo jižpřed spuštěním RT sekcí, pomocí funkce malloc(). Co nejdříve se v sekci Main() zapíše volání mlockall(),které zajistí uzamčení všech zdrojů (soubory mapované do paměti, použité knihovny...) v operační paměti.Pokud je potřeba přistupovat ke sdíleným zdrojům, nesmí se použít semafory, ale speciální mutex„PTHREAD_PRIO_INHERIT“. Ten umožňuje navýšení priority vlákna vlastnícího zdroj, pokudve frontě čeká úloha s vysokou prioritou, čímž se dosáhne co nejrychlejšího dokončení práce s uzamčenýmzdrojem a jeho předání RT úloze. Některé specializované systémy ve svém API umožňují zapnutí PriorityInheritance při vytváření semaforu.U složitějších aplikací je nejlepším řešením předávání dat použitím více vláken, která si předávajídata pomocí soketů. Hlavní vlákno běží s vysokou prioritou a ostatní (pro zpracování souborů, výpisyvýsledků, atd.) mají prioritu mnohem nižší. Více informací uvádí literatura [3].10


KAPITOLA 2. LINUX2.3 RTAI (Xenomai)Veškeré informace uvedené v této části se budou týkat Xenomai a nemusí zcela platit pro původní RTAI.Xenomai vznikl jako nová větev, která si klade za cíl vylepšit původní implementaci a také pozdějidosáhnout kompatibility s RT_PATCH. Sám mohu potvrdit, že instalace Xenomai je jednodušší, rozšířenístabilní a obsahuje dokonalejší API.Po stažení balíku Xenomai a patche Adeos/iPipe dojde nejprve ke spuštění úvodního nastavení, přikterém Xenomai aplikuje patch. Narozdíl od RTAI je zde stažen oficiální patch z projektu Adeos, cožumožňuje instalovat téměř na libovolné jádro (RTAI poskytuje jen velmi omezenou podporu jader) avyužít tak i bezpečnostní patche hlavní větve jádra.V další části již lze spustit standardní konfiguraci a kompilaci jádra GNU/Linux. V konfiguračnímmenu přibudou volby pro aktivaci Xenomai. Patch dokonce nepovolí aktivaci Xenomai pokud je např.aktivováno ACPI nebo jiná nekompatibilní součást. Obecně platí při konfiguraci podobné zásady jakou výše zmíněného RT_PATCH. Po restartu do nového jádra je nutno kompilovat samotné Xenomai. Propodrobné nastavení doporučuji prostudovat [4].Xenomai redukuje problémy s SMI. V krajním případě je možné se pokusit jej zcela vypnout - toale nelze doporučit, protože tím zastavíte i některé bezpečnostní mechanismy, např. Thermal Throtling,který se stará o zastavení CPU při přehřátí.Pro psaní programů platí stejné zásady jako ty uvedené v části o RT_PATCH. Dále je nutno zmínit,že Xenomai ještě není zcela kompatibilní s knihovnami Comedi. Nicméně žádný problém jsem nezaznamenala s Xenomai jsem nakonec dosáhl výborných výsledků i při nasazení na velmi vytíženém systému.Pro psaní programů je neocenitelná výborná dokumantace [1].Rozšíření se snaží o snadný přechod z jiných RT systémů. Proto API definuje RT úlohy jako speciálníobjekty „task” a nabízí metody pro manipulaci s nimi. Dále počítá s periodickými úlohami a obsahujespeciální čekací metody. Jako příklad uvedu vytvoření jednoduché periodické RT úlohy.RT_TASK p e r i o d i c _ t a s k ;v oid task_body ( v o id ∗ a r g ){/∗∗ Arguments : &t a s k (NULL=s e l f ) ,∗ s t a r t time ,∗ p e r i o d ( h e r e : 1 s )∗/r t _ t a s k _ s e t _ p e r i o d i c (NULL , TM_NOW, 1000000000) ;w h i l e ( t r u e ) {// Do code . . . . .rt_task_wait_period (NULL) ;}r e t u r n ;}i n t main ( i n t argc , char ∗ a r g v [ ] ){/∗ A v o i d s memory swapping f o r t h i s program ∗/m l o c k a l l (MCL_CURRENT|MCL_FUTURE) ;/∗∗ Arguments : &task ,∗ name ,∗ s t a c k s i z e (0= d e f a u l t ) ,∗ p r i o r i t y ,11


KAPITOLA 2. LINUX}∗ mode (FPU , s t a r t suspended , . . . )∗/r t _ t a s k _ c r e a t e (& p e r i o d i c _ t a s k , " t r i v i a l " , 0 , 99 , T_JOINABLE) ;/∗∗ Arguments : &task ,∗ t a s k f u n c t i o n ,∗ f u n c t i o n argument∗/r t _ t a s k _ s t a r t (& p e r i o d i c _ t a s k , &task_body , NULL) ;/∗ Wait f o r t a s k f i n i s h ∗/r t _ t a s k _ j o i n (& p e r i o d i c _ t a s k ) ;r t _ t a s k _ d e l e t e (& p e r i o d i c _ t a s k ) ;e x i t ( 0 ) ;2.4 ComediProjekt Comedi vytváří a spravuje ovladače zařízení pro měřicí karty mnoha výrobců (National Instruments,Amplicon, Adlink, Advantech, Analog Devices, atd.). Jedná se o karty do PCI, ISA i USB a tohlavně univerzální DAQ a DIO zařízení. Comedi umožňuje i snadnou úpravu ovladačů a tvorbu nových.Stačí aby nový ovladač využíval předdefinované struktury Comedi a inicializační rutiny.Většina kódu je udržována komunitou, nicméně někteří výrobci již vyvýjí sami ovladače pro Comedia nabízí je zákazníkům. Tento postup je pro ně výhodnější než vývoj čistě komerčních ovladačů a při tomzachovává možnost uchovat některé části kódu uzavřené, použitím proprietárního firmware procesoruna DAQ kartě. Pro zákazníka je výhoda otevřenosti ovladačů tímto dotčena jen minimálně. Při použitíComedi je možné aby si zákazník sám ovladač upravil, měl možnost zkontrolovat jeho kvalitu a pochopit,co karta s daty provádí.Obrázek 2.1: Získávání dat z DAQ kartySoučásttí projektu je také Comedilib, což je sada knihoven, které lze využít pro kumunikaci s ovladačem.Nejjednodušší na použití, ale také nejméně konfigurovatelné jsou funkce comedi_data_read() acomedi_dio_read() (případně „write” verze). Pomocí nich lze snadno vyčítat analogové a digitální kanálya s využitím comedi_to_phys() i převádět data na správné fyzikální jednotky. Dále existují funkcepro konfiguraci kanálů atd.O málo složitější, ale velmi flexibilní jsou instrukce. Pro jejich provedení stačí vyplnit strukturu comedi_insn_struct,která obsahuje instrukci (získání dat, zápis dat, konfiguraci kanálu), údaje o kanálu12


KAPITOLA 2. LINUXkterý se bude měřit a ukazatel na data. Takto lze nadefinovat celé pole (insnlist) připravených struktur,které představuje po sobě jdoucí instrukce a celé jej vykonat pomocí comedi_do_insnlist().Nejsložitější je použití příkazů. Je nutné naplnit strukturu comedi_cmd(), která obsahuje údaje nejeno měřených kanálech a jejich konfiguraci, ale také o spouštění měření, odměru kanálu, A/D převodu, atd.,jak je vidět z obrázku 2.1.Je nutno říct, že ne všechny zásuvné měřicí karty podporují všechny typy spouštění. K tomu je totižpotřeba skutečná hardwarová podpora příslušných spouštění. Např. karta NI 6221 podporuje hardwarovéspouštění externím vstupem pouze na analogových linkách. V případě dražších karet lze ale periodickyvyčítat / nastavovat digitální i analogové vstupy při spouštění digitálním vstupem, určit spouštění všechudálostí z 2.1, atd.Vývoj Comedilib je stále aktivní a do budoucna se testuje podpora analogové filtrace, analogovéhospouštění, spouštění celým bajtem (shoda v bitech), NI RTSI Trigger Bus a mnohé další.13


KAPITOLA 3Časovače v PCV počítači typu PC se můžeme setkat s mnoha programovatelnými časovači [5]. Některé na základníchdeskách zůstávají již jen z historických důvodů, jiné se teprve začínají využívat. V této kapitole najdetepopis nějběžněji používaných časovačů.3.1 PITJedná se o nejstarší typ časovače, který přes své nevýhody stále přežívá i v moderních počítačích. Dřívebyl realizován samostatným obvodem Intel 8253 [11], dnes je často integrován do chipsetu (southbridge).Obvod obsahuje tři nezávislé šestnáctibitové programovatelné časovače, z nichž časovač číslo dva bývápoužit pro refresh cyklus operační paměti a číslo tři ke generování tónů pro PC speaker.Každý z časovačů lze naprogramovat do jiného módu. Čítání od zadaného čísla do nuly, modulo N,generátor obdélníku, ... Pokud je tento časovač použit jako systémový, je spuštěn v periodickém čítáníod N do nuly.Jeho maximální frekvence je 1000 Hz. Nebývá ale příliš přesný a přístup pro čtení/zápis je zdlouhavý(dáno umístěním na southbridge).3.2 RTCObvod Real Time Clock je dnes již také běžnou součástí chipsetu. Jedná se o obvod s nízkým časovýmrozlišením, který běží neustále (napájen z baterie a udržuje čas PC). Jeho programování je nejpomalejšíze všech časovačů – používá se téměř výhradně v periodickém módu (OS GNU/Linux jen pro čtení dataa času). Je schopen dosáhnout frekvencí 2 Hz až 8192 Hz. Určitou výhodou tohoto časovače je nezávislostna konkrétním CPU a chipsetu.3.3 APICObvod APIC (Advanced Programmable Interrupt Controller) se stará o řazení přerušení a jejich doručenína příslušný procesor a zajišťuje meziprocesorová přerušení.Z tohoto obvodu lze použít časovač APIC Timer [7]. Jedná se o třicetidvoubitový programovatelnýčasovač, použitelný pro časování systémových úloh a přesné měření času v aplikacích. Jeho frekvence jeodvozena od systémové sběrnice a vydělena registrem Divide. Používá se opět mód čítání od N do nuly.14


KAPITOLA 3. ČASOVAČE V PCPokud je aktivován periodický mód, čítač po vyvolání přerušení pokračuje opět od N. Hodnota čítačemůže být resetována při hlubokém spánku CPU (Intel SpeedStep).V OS GNU/Linux bývá výchozím časovačem (pokud není deaktivován APIC nebo není dostupnývhodný TSC časovač).3.4 TSCTSC (Time Stamp Counter) je součástí CPU [7], a proto může být vyčítán ještě rychleji než APICTimer. Jeho frekvence je odvozena od frekvence CPU a obsahuje 64 bitová data. Teoretické rozlišení tedyodpovídá frekvenci procesoru, což se může pohybovat pod 1 ns.Tento časovač však přináší některé nevýhody. Je bezpodmínečně nutné nepoužívat Intel SpeedStep,protože snížení frekvence CPU vede ke změně frekvence časovače (novější Intel P4 používají pro časovačkonstantní násobič a změna frekvence tak nevadí). Procesor nesmí přejít do stavu hlubokého spánku(časovač se zastaví). Největší komplikací jsou výcejádrové procesory. Každé jádro používá vlastní TSCčasovač a při plánování jedné úlohy na různá jádra může dojít k nečekaným časovým posunům – OSGNU/Linux však již obsahuje některé patche pro odstranění tohoto problému.3.5 HPETHPET (High Precision Event Timer) je nejmladší časovač ze všech zmiňovaným [8]. Microsoft jej implementovalaž ve Windows Vista a GNU/Linux jej stále ještě příliš nevyužívá (podpora ale existuje déle).Tento časovač by měl podle Intelu časem nahradit starý obvod PIT, čemuž svědčí i zájem firmy AMD aimplementace v jejích chipsetech.Časovač dosahuje podobného rozlišení jako TSC, má také 64 bitové registry, ale nezpůsobuje problémys Intel SpeedStep a vícejádrovými procesory (i tak je ale Intel SpeedStep pro RT aplikace nevhodný),protože je součástí chipsetu a využívá externí krystalový oscilátor. Ne všichni výrobci základních desekvšak HPET ve firmwareu aktivují a na desku umisťují příslušný oscilátor.Registry časovače jsou mapovány do I/O prostoru PC a snadněji dostupné pro CPU než PIT.3.6 Problémy časováníVšechny časovače v PC mají nějaké nevýhody. Ty specifické pro určité typy jsou uvedeny výše. Dálevšak přesnost časování ovlivňují další vlastnosti architektury dnešních procesorů. Paradoxně větší výkona efektivnost procesorů je pro RT úlohy na škodu a starší procesory by některé úlohy řešily s menšímrozptylem časování (jitter), v době jejich používání ovšem neexistovaly přesné časovače.Dnešní CPU využívají např. tzv. Instruction Pool, který jim umožňuje měnit pořadí zpracování instrukcí.Při normálním nasazení toto nevadí – vede to k možnosti paralelně načítat instrukce a dataa zpracovávat instrukce, právě dle času doručení potřebných zdrojů. U RT aplikace však situace vedeke zvětšení jitteru. Stejně tak odhadování skoků může mít vážné následky – někdy je odhadnut správnýprůchod cyklem, někdy ne, což vede opět na větší jitter.Přerušení, míříci na nožičky CPU prochází přes APIC, takže nelze zaručit jejich okamžité doručenív původním pořadí.15


KAPITOLA 4Měřicí kartyCelkem byly použity dvě měřicí karty - DAQ NI PCI 6221 a DIO Amplicon PCI 236.4.1 NI PCI 6221Jedná se o DAQ zásuvnou měřicí kartu určenoupro slot PCI, obsahující 16 bit analogové vstupy/-výstupy, 10 DIO linek a 32 bit čítač. Použitý vzorek,který byl katedře věnován firmou National Instruments,nebyl zcela funkční, nicméně DIO linkyjsou použitelné. Na této kartě byla provedena prvotníměření. Z důvodu složitějšího obvodového řešenía proprietárního procesoru jsem se obával zbytečnélatence v obvodech měřicí karty. Zpracovánípřerušení zde také není triviální záležitostí.4.2 Amplicon PCI 236Tato karta byla použita jako druhá, hlavně pro měřenílatence přerušení. Její obvodové řešení je velmijednoduché a zaručuje nízkou latenci. Karta obsahujepouze obvod PPI (82C55) a připojení na sběrniciPCI pomocí PLX9052. Brána C, pin 3 je navícpřipojen na pin přerušení PLX9052. Oba obvodyjsou mapovány do IO prostoru PCI sběrnice a jejichkonfigurační registry je možno libovolně nastavovat.PPI 82C55 je programovatelný obvod, obsahujícítři 8 bit brány a konfigurační registr. BrányA, B a 2x 1/2 C lze individuálně konfigurovatna vstup/výstup. Verzi použitou na měřicí kartěvyrábí firma OKI a od původního 8255 se liší vyšší16


KAPITOLA 4. MĚŘICÍ KARTYrychlostí a nižším proudovým odběrem.PLX9052 je velmi univerzální obvod, umožňující připojení množství různorodých periferií na sběrniciPCI, včetně obvodů určených původně pro ISA. Obvod vytváří sběrnici local bus, která může být 8 bitaž 32 bit, je vybaven FIFO frontou a nezávislými hodinami, pro připojení obvodů s jinou rychlostí nežPCI sběrnice. Výběr obvodu, který bude aktivní na local bus lze realizovat až čtyřmi signály chip selecta v případě multiplexování sběrnice je přítomen signál ALE. Pro uchování konfiguračních dat (včetně IDvýrobce a zařízení k identifikaci na PCI) lze připojit paměť EEPROM.Karta je primárně určena k výzkumu a testování, čemuž odpovídá umístění pájivého kontaktníhopole v blízkosti DIO linek, které umožňuje přidání vlastních obvodů (dokumentace poskytuje i návod prozapojení optických oddělovačů a dalších obvodů) a v neposlední řadě také použití patice pro PPI (snadnávýměna při poškození).Ke kartě je dodávána plná technické dokumentace, včetně schéma zapojení, příkladů programů (C/C++,.NET, Delphi), ovladač pro Windows a NI LabView.17


KAPITOLA 5Generování přesného časuPo studiu možností GNU/Linux a jeho RT rozšíření jsem začal psát real-time aplikace v jazyce C.Basic latency using RT_patchJakub KocourekMarch 14, 2009Obrázek 5.1:STARTmainset_RT_priorityFi = 0 i = i + 1i


KAPITOLA 5. GENEROVÁNÍ PŘESNÉHO ČASUpro test této RT modifikace. Vývojový diagram je na obrázku 5.2. Jedná se o jednoduchou smyčku, vekteré nastavuji jeden pin na připojené DAQ kartě. Průměrná latence systému (systematická chyba) jekompenzována staticky. Hodnota kompenzační konstanty nemá hlubší opodstatnění, protože není možné,Basic DIO using RT_patchJakub Kocourekna rozdíl od jednoduchých uP bez OS, snadno určit dobu běhu jednotlivých příkazů.Kalibrace tedy probíhá tak, že je program spuštěns nulovou kompenzací, z naměřených chyb jevypočtena střední hodnota (jako aritmetický průměr)a ta je následně použita jako hledaná konstanta.Tímto způsobem je možno systematickouchybu redukovat na několik desítek nanosekund.V případě tohoto generátoru je změřená hodnotaprůměrné latence (ze sta odměrů) 236,6758 us/tik.S programem bylo dosaženo směrodatné odchylkypod jednu mikrosekundu, což je o řád lepší,než vyžaduje zadání.Zdrojový kód je v příloze B.STARTmainset_RT_prioritytrueTset_DIOFMarch 14, 2009wait (Tup)5.3 Sekundový generátor s TSCčasovačem a Xenomaiclear_DIOPři použití rozšíření Xenomai je naopak výchozívolbou časovač TSC (u HPET stále hrozí kolizes dalšími úlohami, zvláště na 64 bit systémech).Na vývojovém diagramu 5.3 a zvláště na zdrojovémkódu C je patrná odlišnost od předchozíhoprogramu - jak jsem již uvedl, Xenomai se snažío maximální kompatibilitu se skutečnými RT systémy(např. VxWorks), a proto zde existují úlohy(task), kterým je možné nastavit periodicitu.Jádro programu je však stejné. Opět pomocíObrázek 5.2:wait(Tdown)klihoven Comedi nastavuji DAQ kartu. Xenomai však již počítá s periodickými úlohami, lze tedy provésthlavní kód cyklu a následně nechat úlohu dospat zbylý čas do jedné sekundy. Ale ani s touto podporouknihoven Xenomai není časovač přesný a je nutné staticky kompenzovat systematickou chybu stejnýmzpůsobem jako v případě RT_PATCH. Zde je průměrná latence 75,9615 us/tik. Protože Xenomai seo tuto kompenzaci částečně pokouší sám, při nulové kompenzaci v programu obvykle dojde k předčasnémuprobouzení procesu, proto se v programu objevuje záporná kompenzace.Dosahl jsem směrodatné odchylky pod polovinu mikrosekundy. To je také nejlepší dosažený výsledek.STOPmainPage 1 of 15.4 Zpětnovazební sekundový generátorMůj další pokus vedl k myšlence eliminovat latency „zpětnou vazbou”. Pokud po každém průchodu cyklemgenerování tiku zjistím o kolik nanosekund jsem se odchýlil (regulační odchylka), mohu latency v dalšímkroku korigovat (akční zásah).19


KAPITOLA 5. GENEROVÁNÍ PŘESNÉHO ČASUPředpokladem takového řízení je však použitíSTARTgen_tik ()velmi přesného referenčního signálu, což při praktickémpokusu ani jeden z časovačů nedokázal. Latencebyla stabilnější, ale kvůli systematické chyběset_periodic(T)časovačů generátor nevyhověl žádaným parametrům.trueTFV budoucnu bych rád zkusil použití přesnéhokrystalového oscilátoru, připojeného do čítačena DAQ kartě. Časovače v PC by tak bylyset_DIOpoužity pro krátkodobé časování a v pravidelnýchwait (Tup)STARTmainintervalech by docházelo k jejich korekci proti externímučasovači.clear_DIOcreate task(gen_tik)5.5 Latence přerušenístart task(gen_tik)Předchozí změřené hodnoty neodpovídají skutečnéwait_periodlatenci (systematická chyba), protože ta je z velkéjoin_task(gen_tik)části kompenzována, ale jitteru, tedy měří se odchylkyod průměru. Měření skutečné latence přeru-Obrázek 5.3:STOPgen_tik ()STOPmainšovacího systému je zajímavým parametrem, kterýodhalí část latence výceméně nezávislou na tokuprogramu (nicméně nejedná se o latenci způsobenoupouze obvody karty). Rozšíření Xenomaiumožňuje v části user space ošetřovat přerušení,což jsem také k tomuto měření využil.20


KAPITOLA 6VýsledkyGenerátory, využívající oba typy RT rozšíření, byly testovány za standardních podmínek - teplota nebylaregulována, PC skříň neobsahuje žádné vylepšené stínění ani speciální hardware. Při vysokém zatíženíPC a následném zahřátí jsem pozoroval značné odchylky periody generovaného signálu (zvýšení teplotyCPU o 15°C vyvolá nárůst systematické chyby téměř jedna mikrosekunda a směrodatnou odchylku zvýšío 140%).Teplotně závislá kompenzace je možná, má však nevýhodu - je nutno použít externí teplotní čidla,protože integrovaná čidla užívají SMI přerušení. Při praktickém nasazení by bylo nutné PC provozovatv klimatizovaném boxu a navíc vždy vyčkat zahřátí CPU a dalších součástí na provozní teplotu. Ani taknelze vyloučit problémy, protože CPU může podléhat velmi rychlým teplotním změnám. V tomto případěskutečně platí pravidlo „RT systém není pouze výkonný systém” a lze jen doporučit úsporná mobilní CPUs nízkým příkonem (samozřejmě s deaktivovaným Intel SpeedStep) a kvalitní chlazení.6.1 Postup měřeníGenerátor byl na začátku měření vždy kalibrován (výše popsané nastavení statické kompenzace systematickéchyby) a PC nebylo zatíženo žádnou jinou aktivní úlohou (pokud není uvedeno jinak) 1 .V tabulce 6.1 jsou uvedeny naměřené hodnoty odchylky od generované periody.Při použití HPET časovače a RT_PATCH jsem dosáhl směrodatné odchylky pod jednu mikrosekundu.S TSC časovačem a Xenomai byl výsledek nejlepší - pouhých dvěstě osm nanosekund.Jak jsem zmínil výše, úlohy s nízkou prioritou nesmí chování systému příliš ovlivnit. Proto jsemprovedl další měření, při kterém byl systém zatížen nejprve síťovým provozem (ping -i 0.02 localhost) anásledně vysokou činností pevného disku (dd if=/dev/zero >/test.file 2 ). Test prokázal, že RT_PATCHtrpí zvyšováním offsetu generované periody se zvyšující se zátěží. Při extrémním vytížení (kopírovánísouboru) již značně roste i směrodatná odchylka. Naopak Xenomai se vypořádal s vytíženým systémemvýborně, směrodatná odchylka ani offset významněji nenarostly.Naměřené odchylky od generované periody jsou uvedeny v tabulce 6.2. V případě Xenomai narostloffset na hodnotu cca 1 us se směrodatnou odchylkou 1,3 us v případě síťového provozu a 3,3 us při plnézátěži.1 Paralelně běžící úloha, běžící s normální prioritou by neměla ovlivnit RT úlohu, ale může zvyšovat zahřátí CPU a tímznačně ovlivnit měření.2 Příkaz kopíruje data z virtuálního znakového zařízení, v tomto případě přečte samé nuly a dále je zapisuje na disk.Dochází tedy k rozsáhlé komunikaci DMA kanálem a vysoké zátěži CPU.21


KAPITOLA 6. VÝSLEDKYNezatížený NIRT_PATCH XenomaiNr. Latence (us) Latence (us)1 0,138116 0,0481362 0,024143 0,0760533 0,358548 -0,0289044 0,902119 0,0717645 -0,491965 -0,0853926 -0,268267 0,0878347 0,135265 -0,0333668 -0,924295 0,0473339 -0,031822 0,07516010 -0,250480 0,57572511 -0,370695 -0,14389612 0,558922 -0,02433813 -0,662443 0,19408614 0,814724 -0,17304415 -0,302127 -0,30827616 0,691097 -0,09612917 0,450993 0,31146918 0,027143 0,21329519 -0,092019 -0,297800Nezatížený AmpliconXenomaiNr. Latence (us)1 0,2572842 0,7978193 -0,2570344 0,3327345 0,2306566 0,1619037 0,6788578 0,5392429 0,31693510 0,32992111 -0,64646512 0,43081613 0,38769114 0,34137615 0,55545516 0,70244117 0,37524718 0,48759819 0,192109Tabulka 6.1: Časovače HPET a TSCPoslední částí měření byla latence přerušení. Měření bylo provedeno na DIO kartě Amplicon PCI 236.Na přerušovací vstup (Port C, pin 3) byl z generátoru přiveden obdélníkový signál periody 1 Hz a výstupkarty snímán opět čítačem. Přerušení bylo zpracováno v Xenomai.Z tabulky 6.3 je viditelná přímá souvislost latence přerušení s celkovou latencí, a to jak růst systematickésložky, tak náhodné chyby. 3Počítač na kterém provádím testy je jednojádrový. Nebylo proto bohužel možné otestovat jak kvalitněobě RT úpravy plánují úlohy na víceprocesorových systémech.6.2 VýpočtyPro všechna měření byla určena střední hodnota odchylky od generované periody a směrodatná odchylka.Výsledky jsou uvedeny v tabulce 6.4. Pro srovnání je přidán i generátor sekundových pulzů na báziGPS modulu, který využívá nejen vnitřní krystalový oscilátor, ale také se synchronizuje s UTC stupnicívysílanou GPS satelity.K měření byl použit přesný číslicový čítač SR620, s nastavením: režim měření periody, sample size 1,mean; dle doporučení výrobce měření probíhalo po zahřátí přístroje (30 minut).3 Při pohledu do tabulky nezapomeňte, že se jedná o latenci vstupní signál - zpracování - výstupní signál => pro porovnáníse sekundovým generátorem je potřeba uvažovat latenci přibližně poloviční.22


KAPITOLA 6. VÝSLEDKYZatížený NIPing -i 0.02dd if=/dev/zero of=/test.fileRT_PATCH Xenomai RT_PATCH XenomaiNr. Latence (us) Latence (us) Latence (us) Latence (us)1 4,728035 -1,314090 26,522366 1,1634332 2,982856 -0,596590 26,558537 -8,1475023 3,405238 -0,770900 27,871766 -6,1105714 2,761412 -0,563525 17,547833 0,7640815 3,946772 0,402851 31,689233 1,6838326 3,378518 -3,592917 28,858341 0,2348177 3,823351 -1,610528 27,701942 -2,2674188 4,816829 -3,529700 22,055732 -1,6768239 4,116759 -0,261070 31,142486 -0,16965110 1,496992 1,300003 25,681642 0,18134211 2,973858 -0,65527112 1,248413 -2,99276813 3,003415 -1,62662214 1,782794 0,81151815 2,108667 -1,33496116 2,655170 -0,32097717 2,877431 -1,51749718 2,868468 -1,69342719 2,390652 -0,291718Zatížený AmpliconPing -i 0.02 dd if=/dev/zero of=/test.fileRT_PATCHXenomaiNr. Latence (us) Latence (us)1 0,393845 0,9754202 -0,537568 9,3581433 -0,641919 0,0800294 0,445326 4,1472015 0,066891 -0,0612066 0,658027 1,4407827 2,225106 -0,3096258 -0,209842 -0,7599379 1,942543 4,77662510 -0,334353 0,59060311 0,84546212 -0,89874913 0,98754614 1,15792915 -0,09290616 0,09137117 1,63668118 1,43625519 0,333404Tabulka 6.2: Sekundový generátor na zatíženém systému23


KAPITOLA 6. VÝSLEDKYNezatížený Ping -i 0.02 dd if=/dev/zero of=/test.fileNr. Latence (us) Latence (us) Latence (us)1 29,899537 33,313797 61,3548162 29,693331 32,142307 56,8932063 29,095331 33,954552 54,1507344 29,384040 34,491528 51,0833755 29,941036 33,915926 50,0890036 29,701259 32,572507 58,7549557 29,286675 33,927029 66,6720198 28,099839 38,893306 62,6286259 27,628202 34,618979 62,19877110 30,803522 35,951790 57,18225611 29,555659 34,904263 51,15803212 29,731634 35,308719 51,07088213 28,530764 34,350449 62,03323214 28,579183 34,811306 57,44905615 27,615211 36,179720 52,39725116 28,729956 35,397583 50,97812817 29,402074 35,107123 60,52479218 29,435946 34,046890 62,68866519 29,532034 33,793369 58,751817Latence (us) 29,191854 ± 0,817111 34,614797 ± 1,461691 57,266296 ± 5,077210Tabulka 6.3: Latence přerušeníČasovač Latence (us) NI Latence (us) AmpliconRT_PATCH (HPET) +0,037208 ± 0,501110 NeměřenoXenomai (TSC) +0,026827 ± 0,208202 +0,327083 ± 0,331237RT_PATCH ping +3,053914 ± 0,974659 NeměřenoXenomai ping -1,007909, ± 1,319111 +0,500266 ± 0,892113RT_PATCH dd Přes 10 us směrodat. odch. NeměřenoXenomai dd -1,434446 ± 3,265764 +2,023804 ± 3,011545GPS +0,004365 ± 0,013650 +0,004365 ± 0,013650Tabulka 6.4: Výsledky24


KAPITOLA 7ZhodnoceníJe patrné, že generátor přesných pulzů, založený na bázi běžného PC nemůže konkurovat jednoúčelovýmzařízením. Primitivní integrované obvody jsou vždy schopné zajistit časování mnohem přesněji, než komplexníuP, podporující běh mnoha úloh, které nejsou navrženy pro specifické potřeby RT aplikací. I přesto jsou dosažené výsledky lepší než očekávané, hlavně proto že v posledních několika letech se integrovanéčasovače velmi zlepšily (což dokazuje i zájem firmy AMD o HPET časovač, který původně vyvinul Intel)a také GNU/Linux postupně vylepšuje práci s nimi a řeší nejrůznější problémy (např. TSC časovače naSMP systému). Nové časovače se ale prosazují velmi pomalu a ještě dlouho potrvá jejich plná podporav operačních systémech, proto se stále setkáváme ve starými obvody PIT a APIC. Výrobci hardware ivývojáři RT rozšíření mají do budoucna rozhodně co vylepšovat. Ostatně z kapitoly 5 je patrné, že dnesneexistuje žádný ideální časovač a navíc každý OS preferuje jiný a jinak řeší různé problémy.Obě testovaná RT rozšíření se osvědčila. Pro skutečnou garanci latence a přenos kódu na RT systémyjako např. VxWorks bych doporučil spíše Xenomai se svým jednoduchým API, podobným právě VxWorks.Navíc RT_PATCH mne o svých kvalitách nepřesvědčil, kvůli špatným výsledkům na zatíženém systému.Mezi další výhody Xenomai patří snadný přístup k hardwaru - registrům, handleru přerušení, atd.Tato práce měla mapovat možnosti RT rozšíření v GNU/Linux a základní problémy při práci s měřicímikartami při generování času. S kartou NI PCI 6221 i Amplicon PCI 236 jsem dosáhl obdobnýchvýsledků. Seměrodatná odchylka se pohybovala od 0,2 us u nezatíženého systému, až po 3,3 us na vytíženémsystému (v obou případech měřeno s Xenomai).V dalším studiu bych rád v práci pokračoval měřením dlouhodobé časové stability a prozkoumánímmožnosti synchronizace s externím přesným oscilátorem.25


KAPITOLA 8Použitá literatura[1] Xenomai API reference, 26.2.2009. Dostupné z: http://www.xenomai.org/documentation/branches/v2.4.x/html/api/index.html.[2] AG, S. PikeOS datasheet, 2009. Dostupné z: http://www.sysgo.com/fileadmin/user_upload/datasheets/PikeOS.pdf.[3] BOHMER, R. HOWTO: Build an RT-application, 29.1.2008. Dostupné z: http://rt.wiki.kernel.org/index.php/HOWTO:_Build_an_RT-application.[4] BOUWMAN, W. Xenomai quick build guide, 20.8.2008. Dostupné z: http://www.xenomai.org/index.php/Xenomai_quick_build_quide.[5] BOVET, D. P. – CESATI, M. Understanding the Linux Kernel, 3rd Edition. O’Reilly, 2005.[6] FU, L. – SCHWEBEL, R. RT Preempt Howto, 28.4.2006. Dostupné z: http://rt.wiki.kernel.org/index.php/RT_PREEMPT_HOWTO.[7] INTEL. Intel(R) 64 and IA-32 Architectures Software Developer’s Manuals, Ver. 029. Dostupné z:http://www.intel.com/products/processor/manuals/index.htm.[8] INTEL. IA-PC HPET (High Precision Event Timers) Specification, Ver. 1.0a. Dostupné z: http://www.intel.com/hardwaredesign/hpetspec_1.pdf.[9] LIU, J. W. S. Real-time systems. Prentice Hall, 2000.[10] PELČÁK, V. Real-time modifikace Linuxu, 3.2.2006. Dostupné z: www.abclinuxu.cz.[11] WIKIPEDIA. Intel 8253, 9.3.2009. Dostupné z: http://en.wikipedia.org/wiki/Intel_8253.[12] YAGHMOUR, K. Adeos design document, 15.2.2001. Dostupné z: http://www.opersys.com/adeos/dox/adeos/index.html.26


PŘÍLOHA AZdrojový kód - test latence systému#i n clude #i n clude #i n clude #i n clude #i n clude #define CNT 10/∗ S u b s t r a c t i o n i n t e r v a l=now−b e g i n ∗/i n t d e l t a _ t ( s t r u c t t i m e s p e c ∗ i n t e r v a l , s t r u c t t i m e s p e c ∗ begin , s t r u c tt i m e s p e c ∗now ){i n t e r v a l −>tv_nsec = now−>tv_nsec − begin −>tv_nsec ; /∗ S u b t r a c t ’ d e c i m a lf r a c t i o n ’ f i r s t ∗/i f ( i n t e r v a l −>tv_nsec < 0 ) {i n t e r v a l −>tv_nsec += 1000000000; /∗ Borrow 1 s e c from ’ tv_sec ’ i fs u b t r a c t i o n −ve ∗/i n t e r v a l −>tv_sec = now−>tv_sec − begin −>tv_sec − 1 ; /∗ S u b t r a c twhole number o f s e c o n d s and r e t u r n 1 ∗/return ( 1 ) ;}e l s e {i n t e r v a l −>tv_sec = now−>tv_sec − begin −>tv_sec ; /∗ S u b t r a c t wholenumber o f s e c o n d s and r e t u r n 0 ∗/return ( 0 ) ;}}i n t main ( ) {s t r u c t t i m e s p e c ts , t s _ a f t e r , t s _ d e l t a ;s t r u c t t i m e s p e c t t s , t t s _ a f t e r , t t s _ d e l t a ;27


PŘÍLOHA A. ZDROJOVÝ KÓD - TEST LATENCE SYSTÉMUconst s t r u c t t i m e s p e c i n t e r v a l = { 1 , 0 } ;s t r u c t sched_param s c h e d u l i n g _ p a r a m e t e r s ;i n t count = 0 ;unsigned long td [CNT ] ;/∗ Lock pages i n r e a l memmory ∗/m l o c k a l l (MCL_CURRENT|MCL_FUTURE) ;/∗ Setup p r i o r i t y ∗/s c h e d u l i n g _ p a r a m e t e r s . s c h e d _ p r i o r i t y = sched_get_priority_max (SCHED_FIFO) − 4 ;/∗ Setup FIFO s c h e d u l e r ∗/i f (0 != pthread_setschedparam ( p t h r e a d _ s e l f ( ) , SCHED_FIFO , &s c h e d u l i n g _ p a r a m e t e r s ) ){p e r r o r ( " pthread_setschedparam ␣ e r r o r " ) ;}/∗ Get time to measure r u n n i n g time ∗/c l ock_gettime (CLOCK_REALTIME,& t t s ) ;f o r ( count = 0 ; count < CNT; count++) {// Time b e f o r ec l o c k _ g e t t i m e (CLOCK_REALTIME,& t s ) ;n a n o s l e e p (& i n t e r v a l , NULL) ;// Time a f t e rc l o c k _ g e t t i m e (CLOCK_REALTIME,& t s _ a f t e r ) ;d e l t a _ t (& ts_delta , &ts , &t s _ a f t e r ) ;// Write l a t e n c ytd [ count ] = t s _ d e l t a . tv_nsec ;}/∗ Get time to measure r u n n i n g time ∗/c l ock_gettime (CLOCK_REALTIME,& t t s _ a f t e r ) ;d e l t a _ t (& t t s _ d e l t a , &t t s , &t t s _ a f t e r ) ;p r i n t f ( " Total ␣ w a i t : ␣%l u ␣ s e c ␣%l u ␣ nsec \n" , t t s _ d e l t a . tv_sec , t t s _ d e l t a .tv_nsec ) ;f o r ( count = 0 ; count < CNT; count++) {}p r i n t f ( " Waited : ␣%l u ␣ nsec ␣\n" , td [ count ] ) ;}return 0 ;28


PŘÍLOHA BZdrojový kód - sekundový generátor s HPETčasovačem#i n clude #i n clude #i n clude #i n clude #i n clude #i n clude #define CNT 100#define CORRECT_SYST 23168 // C o r r e c t i o n o f s y s t e m a t i c e r r o r/∗ S u b s t r a c t i o n i n t e r v a l=now−b e g i n ∗/i n t d e l t a _ t ( s t r u c t t i m e s p e c ∗ i n t e r v a l , s t r u c t t i m e s p e c ∗ begin , s t r u c tt i m e s p e c ∗now ){i n t e r v a l −>tv_nsec = now−>tv_nsec − begin −>tv_nsec ; /∗ S u b t r a c t ’ d e c i m a lf r a c t i o n ’ f i r s t ∗/i f ( i n t e r v a l −>tv_nsec < 0 ) {i n t e r v a l −>tv_nsec += 1000000000; /∗ Borrow 1 s e c from ’ tv_sec ’ i fs u b t r a c t i o n −ve ∗/i n t e r v a l −>tv_sec = now−>tv_sec − begin −>tv_sec − 1 ; /∗ S u b t r a c twhole number o f s e c o n d s and r e t u r n 1 ∗/return ( 1 ) ;}e l s e {i n t e r v a l −>tv_sec = now−>tv_sec − begin −>tv_sec ; /∗ S u b t r a c t wholenumber o f s e c o n d s and r e t u r n 0 ∗/return ( 0 ) ;}29


PŘÍLOHA B. ZDROJOVÝ KÓD - SEKUNDOVÝ GENERÁTOR S HPET ČASOVAČEM}i n t main ( ) {s t r u c t t i m e s p e c t t s , t t s _ a f t e r , t t s _ d e l t a ;const s t r u c t t i m e s p e c i n t e r v a l _ u p = {0 ,100000000};s t r u c t t i m e s p e c interval_down = {0 ,900000000 −CORRECT_SYST} ;s t r u c t sched_param s c h e d u l i n g _ p a r a m e t e r s ;i n t count = 0 ;comedi_t ∗ i t ;i n t subdev = 2 ;i n t chan = 0 ;/∗ Lock pages i n r e a l memmory ∗/m l o c k a l l (MCL_CURRENT|MCL_FUTURE) ;/∗ Setup p r i o r i t y o f p r o c e s s ∗/s c h e d u l i n g _ p a r a m e t e r s . s c h e d _ p r i o r i t y = sched_get_priority_max (SCHED_FIFO) − 4 ;/∗ Setup s c h e d u l i n g s t r a t e g y ∗/i f (0 != pthread_setschedparam ( p t h r e a d _ s e l f ( ) , SCHED_FIFO , &s c h e d u l i n g _ p a r a m e t e r s ) ){p e r r o r ( " pthread_setschedparam ␣ e r r o r " ) ;}/∗ Open Comedi d e v i c e ∗/i t = comedi_open ( "/ dev / comedi0 " ) ;/∗ C o n f i g u r e l i n e s to DO ∗/comedi_dio_config ( i t , subdev , chan ,COMEDI_OUTPUT) ;}/∗ Get time to measure r u n n i n g time ∗/c l ock_gettime (CLOCK_REALTIME,& t t s ) ;f o r ( count = 0 ; count < CNT; count++) {comedi_dio_write ( i t , subdev , chan , 1 ) ;n a n o s l e e p (& i n t e r v a l _ u p , NULL) ;comedi_dio_write ( i t , subdev , chan , 0 ) ;n a n o s l e e p (& interval_down , NULL) ;}/∗ Get time to measure r u n n i n g time ∗/c l ock_gettime (CLOCK_REALTIME,& t t s _ a f t e r ) ;d e l t a _ t (& t t s _ d e l t a , &t t s , &t t s _ a f t e r ) ;p r i n t f ( " Total ␣ w a i t : ␣%l u ␣ s e c ␣%l u ␣ nsec \n" , t t s _ d e l t a . tv_sec , t t s _ d e l t a .tv_nsec ) ;comedi_close ( i t ) ;return 0 ;30


PŘÍLOHA CZdrojový kód - sekundový generátor s TSCčasovačem#i n clude #i n clude #i n clude #i n clude #i n clude #i n clude #i n clude #i n clude #i n clude #define CNT 10#define CORRECT_SYST −2640 // C o r r e c t i o n o f s y s t e m a t i c e r r o rRT_TASK comedi_task ;RTIME s t a r t , end ;/∗ S u b s t r a c t i o n i n t e r v a l=now−b e g i n ∗/i n t d e l t a _ t ( s t r u c t t i m e s p e c ∗ i n t e r v a l , s t r u c t t i m e s p e c ∗ begin , s t r u c tt i m e s p e c ∗now ){i n t e r v a l −>tv_nsec = now−>tv_nsec − begin −>tv_nsec ;i f ( i n t e r v a l −>tv_nsec < 0) {i n t e r v a l −>tv_nsec += 1000000000;i n t e r v a l −>tv_sec = now−>tv_sec − begin −>tv_sec − 1 ;return ( 1 ) ;}e l s e {i n t e r v a l −>tv_sec = now−>tv_sec − begin −>tv_sec ;31


PŘÍLOHA C. ZDROJOVÝ KÓD - SEKUNDOVÝ GENERÁTOR S TSC ČASOVAČEM}}return ( 0 ) ;void comedi ( void ∗ arg ){i n t count ;comedi_t ∗ i t ;i n t subdev = 2 ;i n t chan = 0 ;const s t r u c t t i m e s p e c i n t e r v a l _ u p = {0 ,100000000};/∗ Open Comedi d e v i c e ∗/i t = comedi_open ( "/ dev / comedi0 " ) ;/∗ C o n f i g u r e l i n e s to DO ∗/comedi_dio_config ( i t , subdev , chan ,COMEDI_OUTPUT) ;/∗∗ Set t h i s t a s k p e r i o d i c∗ Arguments : &t a s k (NULL=s e l f ) ,∗ s t a r t time ,∗ p e r i o d ( h e r e : 1 s )∗/r t _ t a s k _ s e t _ p e r i o d i c (NULL , TM_NOW, 1000000000−CORRECT_SYST) ;f o r ( count =0; count


PŘÍLOHA C. ZDROJOVÝ KÓD - SEKUNDOVÝ GENERÁTOR S TSC ČASOVAČEM}/∗∗ C r e a t e new t a s k ( t h r e a d )∗ Arguments : &task ,∗ name ,∗ s t a c k s i z e (0= d e f a u l t ) ,∗ p r i o r i t y ,∗ mode (FPU, s t a r t suspended , . . . )∗/r t _ t a s k _ c r e a t e (&comedi_task , " t r i v i a l " , 0 , 99 , T_JOINABLE) ;c l ock_gettime (CLOCK_REALTIME,& t t s ) ;/∗∗ S t a r t t a s k∗ Arguments : &task ,∗ t a s k f u n c t i o n ,∗ f u n c t i o n argument∗/r t _ t a s k _ s t a r t (&comedi_task , &comedi , NULL) ;/∗ Wait f o r t a s k t e r m i n a t i o n ∗/r t _ t a s k _ j o i n (&comedi_task ) ;/∗ D e l e t e t a s k ∗/r t _ t a s k _ d e l e t e (&comedi_task ) ;c l ock_gettime (CLOCK_REALTIME,& t t s _ a f t e r ) ;d e l t a _ t (& t t s _ d e l t a , &t t s , &t t s _ a f t e r ) ;p r i n t f ( " Total ␣ w a i t : ␣%l u ␣ s e c ␣%l u ␣ nsec \n" , t t s _ d e l t a . tv_sec , t t s _ d e l t a .tv_nsec ) ;e x i t ( 0 ) ;33


PŘÍLOHA DZdrojový kód - latence přerušení#i n clude #i n clude #i n clude #i n clude #i n clude #i n clude #i n clude #i n clude < f c n t l . h>#i n clude #i n clude #i n clude #i n clude #i n clude #i n clude #define _POSIX_SOURCE 1#define FALSE 0#define TRUE 1#define IRQ 22void comedi_setup_IRQ ( ) ;void pollTaskRun ( ) ;void c a t c h _ s i g n a l ( i n t s i g ) ;void i n i t T a s k R u n ( ) ;RT_TASK p o l l T a s k ;RT_TASK i n i t T a s k ;RT_INTR d i o I n t r ;v o l a t i l e i n t STOP=FALSE ;const s t r u c t t i m e s p e c i n t e r v a l _ u p = {0 ,100000000};comedi_t ∗ i t ;34


PŘÍLOHA D. ZDROJOVÝ KÓD - LATENCE PŘERUŠENÍi n t chan ;i n t subdev ;comedi_cmd cmd ;i n t main ( ){i n t e r r ;/∗ Lock pages i n r e a l memmory ∗/m l o c k a l l (MCL_CURRENT|MCL_FUTURE) ;/∗ C r e a t e new IRQ h a n d l e r . A f t e r p r o c e s s i n g i n my h a n d l e r , p r o pa g a t e i tto Linux d r i v e r h a n d l e r i n K e r n e l space . ∗/e r r = r t _ i n t r _ c r e a t e (& d i o I n t r , "Port_C_3" , IRQ , I_PROPAGATE) ;p r i n t f ( " I n t r ␣ c r e a t e : ␣%i \n" , e r r ) ;e r r = r t _ i n t r _ e n a b l e (& d i o I n t r ) ;p r i n t f ( " I n t r ␣ e n a b l e : ␣%i \n" , e r r ) ;/∗ C r e a t e new t a s k ( t h r e a d ) − IRQ h a n d l e r ∗/r t _ t a s k _ c r e a t e (& p o l l T a s k , " p o l l T a s k " , 0 , 60 , T_JOINABLE) ;/∗ C r e a t e new t a s k ( t h r e a d ) − i n i t t a s k ∗/r t _ t a s k _ c r e a t e (& i n i t T a s k , " i n i t T a s k " , 0 , 40 , T_JOINABLE) ;s i g n a l (SIGTERM , c a t c h _ s i g n a l ) ;/∗ S t a r t t a s k − IRQ h a n d l e r ∗/r t _ t a s k _ s t a r t (& p o l l T a s k , &pollTaskRun , NULL) ;/∗ S t a r t t a s k − i n i t t a s k ∗/r t _ t a s k _ s t a r t (& i n i t T a s k , &initTaskRun , NULL) ;/∗ Wait f o r t a s k t e r m i n a t i o n ∗/r t _ t a s k _ j o i n (& i n i t T a s k ) ;}void c a t c h _ s i g n a l ( i n t s i g ){comedi_cancel ( i t , subdev +1) ;comedi_close ( i t ) ;e x i t ( 0 ) ;}void i n i t T a s k R u n ( ){i n t r e t = 0 ;subdev = 0 ;chan = 0 ;/∗ Open Comedi d e v i c e ∗/i t = comedi_open ( "/ dev / comedi0 " ) ;/∗ C o n f i g u r e l i n e s to DO ∗/comedi_dio_config ( i t , subdev , chan ,COMEDI_OUTPUT) ;/∗ C o n f i g u r e l i n e s to DI ∗/comedi_dio_config ( i t , subdev +1,chan , COMEDI_INPUT) ;35


PŘÍLOHA D. ZDROJOVÝ KÓD - LATENCE PŘERUŠENÍ/∗ Enable IRQ ∗/comedi_setup_IRQ(& i t ) ;while (STOP==FALSE) {p r i n t f ( " . " ) ; f f l u s h (NULL) ; u s l e e p (100000) ;}comedi_close ( i t ) ;}/∗ This method e n a b l e s IRQ . I t i s v i r t u a l Comedi command , d e f i n e d i n d r i v e r. ∗/void comedi_setup_IRQ ( ){unsigned i n t c h a n l i s t [ 0 ] ;i n t e r r ;cmd . subdev = 1 ;cmd . f l a g s = 0 ;cmd . s t a r t _ s r c = TRIG_NOW;cmd . s t a r t _ a r g = 0 ;cmd . scan_begin_src = TRIG_EXT ;cmd . scan_begin_arg = 0 ;cmd . c o n v e r t _ s r c = TRIG_FOLLOW;cmd . convert_arg = 0 ;cmd . scan_end_src = TRIG_COUNT;cmd . scan_end_arg = 1 ;cmd . stop_src = TRIG_NONE;cmd . stop_arg = 0 ;cmd . c h a n l i s t = c h a n l i s t ;cmd . c h a n l i s t _ l e n = 1 ;c h a n l i s t [ 0 ] = CR_PACK( 0 , 0 , 0 ) ;e r r = comedi_command ( i t , &cmd) ;p r i n t f ( "Command␣ s t a t u s : ␣%i \n" , e r r ) ;}/∗ IRQ h a n d l e r ∗/void pollTaskRun ( i n t s t a t u s ) {i n t e r r ;while (TRUE) {p r i n t f ( " Waiting ␣ f o r ␣INT\n" ) ;/∗ Wait f o r i n t e r r u p t ∗/e r r = r t _ i n t r _ w a i t (& d i o I n t r , TM_INFINITE) ;i f ( e r r

More magazines by this user
Similar magazines