Embedded Linux a okýnka - 1. X-Windows? Nano-X!
V posledním dílu seriálu o připojení TFT displeje k modulu SAM9260 jsem úspěšně zprovoznil dotykový TFT displej INT070ATFT-TS jako framebuferové zařízení. To samozřejmě nebylo samoúčelné, protože když už mám plochu (framebufer), do které je možné kreslit okýnka, tak by se hodilo rozchodit i nějaké to grafické prostředí ala X-Windows, ale s nízkými systémovými nároky a snadno cross-kompilovatelné. A do páru nesmí chybět ani odlehčená GUI knihovna (widget toolkit) pro snadné vytváření prvků grafického uživatelského rozhraní.
A právě hledáním té správné embedded-kompatibilní kombinace grafického prostředí a GUI knihovny se budeme bavit v tomto seriálu. Nebojte, žádná suchá teorie vás nečeká, půjdeme na to pěkně od podlahy a hlavně prakticky - něco málo ”vo co go”, pak cross-kompilace, instalace a otestování, že to funguje.
Něco málo o ...
Není snad lepší začátek při hledání alternativ k X-Windows než jejich mikro a teď už i nano varianta The Nano-X Window System dříve Microwindows. Původní název Microwindows, kvůli panické snaze Microsoftu chránit svoji obchodní značku MS Windows, způsobil, že autor přešel na podle mě přiléhavější název Nano-X.
Nano-X se drží konceptu X-Windows a dělí grafické prostředí na nano-X server a nano-X klienty (aplikace). Spolu mohou komunikovat klasicky přes TCP/IP nebo se aplikace zakompilují rovnou do binárky nano-X, čímž se sníží nároky na systémové prostředky, protože odpadne potřeba síťové komunikace. Nano-X server v sobě obsahuje samozřejmě i ovladače pro různá vstupní zařízení od myši, klávesnici až po infračervený ovladač. Bohužel nepodporuje událostní vstupní zařízení (zařízení /dev/input/eventX). Jediným podporovaným výstupním zařízením je framebuferové zařízení.
Rozhraní (API) pro aplikace, resp. GUI knihovny, nabízí Nano-X hned dvě - Win32 (ano, skutečně windousí API) a pak API nano-X, reprezentované knihovnou libnano-X, které se snaží být co nejvíce kompatibilní s knihovnou xlib z X-Windows. Podobnost rozhraní knihoven xlib a libnano-X však neznamená, že je možné vzít aplikaci/GUI knihovnu vyvinutou pro X-Windows a provozovat ji nad Nano-X. Tak jednoduché to prostě není. Ovšem portace aplikací/GUI knihoven je s ohledem na značnou podobnost rozhraní knihoven xlib a libnano-X snadná.
Server nano-X podobně jako X-server sám o sobě poskytuje plochu pro vykreslování grafického rozhraní aplikace, kurzoru myši a obstarává také přenos událostí ze vstupních zařízení typu myš, klávesnice, touch panel do uživatelské aplikace. Toto řešení je plně vyhovující pro jednu aplikaci s oknem přes celou plochu displeje - typická embedded aplikace s GUI ovládaná přes dotykovou vrstvu displeje. Nicméně zdrojové kódy nano-X obsahují i jednoduchého okenního manažera nanowm, který se postará o rámeček okolo okna aplikace, o možnost manipulovat s oknem aplikace a samozřejmě i o obligátní křížek pro ukončení aplikace. Provozování více okenních aplikací tak není problém. Prostě embedded okýnka se vším všudy. No a aby toho nebylo málo, tak součástí zdrojových kódů je i přibalená sada volně šiřitelných fontů a několik ukázkových aplikací portovaných přímo na nano-X, např. jednoduché šachy.
Velkou výhodou Nano-X jsou, řekl bych, až směšné systémové nároky. Samotná binárka nano-X serveru měla pro modul SAM9260 cca 400kB a to nebyla ořezána pomocí utility strip, samozřejmě je potřeba započítat i podpůrné dynamické knihovny pro dekódování obrázků (jpeg, png) a fontů (dalších cca 1,6MB). S pomocí utility strip bychom se dostali na nějakých 1MB se vším všudy. Další zajímavou výhodou je možnost provozovat Nano-X na linuxovém desktopu na X-Windows pomocí nano-X ovladače do X-Windows. Snadno si tak odladíme finální vzhled GUI naší aplikace přímo na našem počítači.
Nevýhodou je naopak poněkud stagnující vývoj - poslední stabilní verze 0.92 byla vydána v červnu 2010, preview verze pak v prosinci 2010.
Než začneme
- Musíme si sehnat linuxový počítač s nějakou pořádnou distribucí, např. Debianem 6.0. Já využívám virtuální počítač. Pokud nevíte jak na to, přečtěte si návod, jak vytvořit virtuální počítač.
- Kompilaci knihoven a Nano-X ze zdrojových kódů jsem prováděl cross-kompilátorem CodeBench GNU/Linux 2010.09-50.
- Vedle kompilátoru jsem si musel instalovat utility pkg-config a libtool, které se využívají pro instalaci zkompilovaných binárek. V Debianu 6.0, který používám, se tyto utility instalují příkazy apt-get install pkg-config a apt-get install libtool prováděnými jako root nebo přes sudo.
- Zkompilované binárky knihoven, jejich hlavičkové soubory a další soubory jsem instaloval do zvláštního adresáře devel/arm/sysroot/sam9260/local v mém domovském adresáři /home/emlin. Na tento adresář se budu v textu odkazovat jako na sysroot. Je to prostě jakýsi repozitář systémových souborů pro modul SAM9260, odkud si beru potřebné soubory při sestavování souborového systému pro tento modul.
- Vedle sysrootu jsem si ve svém domovském adresáři vytvořil také adresář devel/arm/export/sam9260/roofts-nanox, kam si budu ze sysrootu kopírovat jen ty soubory a knihovny, které skutečně v souborovém systému modulu SAM9260 potřebuji. Na tento adresář se budu odkazovat jako na export.
Abych zkrátil a zpřehlednil zápisy příkazů, definoval jsem si v BASHi (příkazový interpretr) tři proměnné prostředí, které budu dále v článku používat.
$ SRC="/home/emlin/devel/arm/sysroot/sam9260/src" $ SYSROOT="/home/emlin/devel/arm/sysroot/sam9260/local" $ EXPORT="/home/emlin/devel/arm/export/sam9260/rootfs-nanox"
Závislosti
Nano-X potřebuje ke svému běhu knihovny pro vykreslování obrázků (jpeg, png) a správu fontů. Tyto knihovny je třeba stáhnout ve formě zdrojových kódů a zkompilovat pro modul SAM9260. Já jsem použil knihovny jpeg-8d, libpng-1.2.50 (verze 1.5.xx se nekamarádí s Nano-X), zlib-1.2.5 (vyžadována knihovnou libpng; novější verze nejde cross-kompilovat) a konečně freetype-2.4.11.
Knihovny kompiluji jako statické i jako dynamické. Preferuji používání dynamických knihoven, výsledná binárka nano-X serveru je díky tomu podstatně menší a navazující GUI knihovna může tyto knihovny za běhu sdílet => úspora operační paměti.
Níže uvádím seznam příkazů pro všechny čtyři knihovny, které provedou klasickou svatou trojkombinaci: konfigurace, kompilace a instalace do sysrootu (viz výše). Příkazy zadáváme vždy v kořenovém adresáři zdrojových kódů příslušné knihovny.
### cross-kompilace zlib-1.2.5: $ CC=arm-none-linux-gnueabi-gcc \ CFLAGS='-march=armv5te -mtune=arm926ej-s -mabi=aapcs-linux' \ ./configure --prefix=$SYSROOT $ make $ make install ### cross-kompilace libpng-1.2.50: $ ./configure --host=arm-none-linux-gnueabi \ --prefix=$SYSROOT \ CPPFLAGS="-I$SYSROOT/include" \ CFLAGS="-march=armv5te -mtune=arm926ej-s -mabi=aapcs-linux" \ LDFLAGS="-Wl,-rpath-link,$SYSROOT/lib -L$SYSROOT/lib" $ make $ make install ### cross-kompilace jpeg-8d: $ ./configure --host=arm-none-linux-gnueabi \ --prefix=$SYSROOT \ CFLAGS='-march=armv5te -mtune=arm926ej-s -mabi=aapcs-linux' $ make $ make install ### cross-kompilace libfreetype-2.4.11: $ ./configure --host=arm-none-linux-gnueabi \ --prefix=$SYSROOT \ CFLAGS='-march=armv5te -mtune=arm926ej-s -mabi=aapcs-linux' $ make $ make install
Kompilace a instalace do sysrootu
Stáhneme si archiv se zdrojovými kódy Nano-X (Microwindows) 0.92 (poslední stabilní verze). Rozbalíme jej; vznikne adresář microwindows-0.92.
Dále si z produktových stránek modulu SAM9260 stáhneme soubor config pro Nano-X a soubor Arch.rules pro Nano-X. Oba soubory zkopírujeme do adresáře microwindows-0.92/src a přepíšeme původní soubory. Tím provedeme konfiguraci zdrojových kódů pro modul SAM9260. Soubor config je nastaven tak, že instalace binárek a knihovny nano-X proběhne do mého sysrootu (viz výše) pro modul SAM9260 a fonty bude nano-X hledat v adresáři /usr/local/share/fonts v souborovém systému modulu SAM9260.
Ještě musíme upravit zdrojové kódy hry tuxchess, jinak si ty šachy proti Tuxovi prostě nezahrajeme. V souboru microwindows-0.92/demos/tuxchess/images.c změníme toto:
### puvodni radek: #define IMAGE_PATH "demos/tuxchess/images" ### upraveny radek: #define IMAGE_PATH "/usr/local/share/tuxchess"
Kompilaci a instalaci za nás zařídí níže uvedené příkazy v adresáři microwindows-0.92/src:
### kompilace $ make ### instalace $ make INSTALL_OWNER1= INSTALL_OWNER2= INSTALL_PREFIX=$SYSROOT install ### rucni instalaci okenniho manazera $ cp bin/nanowm $SYSROOT/bin/ ### rucni instalace fontu $ mkdir -p $SYSROOT/share/fonts $ cd $SRC/microwindows-0.92/src/fonts $ cp -r -d bdf/ fnt/ pcf/ truetype/ type1/ \ winFreeSansSerif11x13.fon winFreeSystem14x16.fon X6x13.bdf nano-X.cfg \ -t $SYSROOT/share/fonts
A protože jsem si chtěl i trochu pohrát a tak, tak si z adresáře microwindows-0.92/src nakopírujeme i další binárky:
### vytvorime si podadresar apps/ $ mkdir -p $SYSROOT/bin/apps ### zkopirujeme si nano-X terminal, tester fontu type1 a hru v sachy $ cd $SRC/microwindows-0.92/src/bin $ cp nxterm t1demo tuxchess -t $SYSROOT/bin/apps ### zkopirujeme si obrazky figurek a sachovnice pro tuxchess $ mkdir -p $SYSROOT/share/tuxchess $ cd $SRC/microwindows-0.92/src/demos/tuxchess/images $ cp *.gif $SYSROOT/share/tuxchess
Instalace do zařízení
V sysrootu máme nyní všechno potřebné pro rozběhnutí Nano-X na modulu SAM9260. Dokonce je tam i spousta věcí navíc, které nepotřebujeme (například statická knihovna libnano-X.a). Proto provedeme jakýsi výběr a ze sysrootu překopírujeme do exportu jen to skutečně potřebné (viz seznam příkazů níže).
### vytvorime si zakladni adresare $ cd $EXPORT $ mkdir bin lib share ### kopirovani bin/ $ cd $SYSROOT/bin $ cp -r apps/ nano-X nanowm -t $EXPORT/bin ### kopirovani lib/ $ cd $SYSROOT/lib $ cp -d libnano-X.so libfreetype.s* libjpeg.s* libpng.so libpng12.s* libz.s* \ -t $EXPORT/lib ### kopirovani share/ $ cp -r $SYSROOT/share/fonts/ $SYSROOT/share/tuxchess/ -t $EXPORT/share/
A jsme v semifinále. Ale jak dostat obsah exportu do adresáře /usr/local/ v modulu SAM9260? Ano, právě tam potřebujeme export nakopírovat. Mou oblíbenou cestou je použití NFS. Stačí si export nasdílet přes NFS v mém počítači a v modulu SAM9260 jej připojit jako nový obsah adresáře /usr/local. Bohužel takovéto sdílení přes síť má za následek zpomalení běhu Nano-X. Zase je však snazší doplnit případné chybějící soubory - stačí je zkopírovat do exportu a ihned jsou vidět i na modulu SAM9260.
Nicméně z pohledu rychlosti běhu Nano-X je lepší připojit export jako adresář /mnt/nfs (na modulu) a pak obsah adresáře /mnt/nfs zkopírovat do adresáře /usr/local. Nano-X tím pádem běží přímo ze souborového systému modulu a nikoliv přes počítačovou síť. První variantu využívám pro první testy, druhou pak pro přenos finálního řešení do modulu SAM9260.
Níže uvedené příkazy povolí sdílení adresáře export pro modul s IP 192.168.1.12. Sdílený adresář z mého počítače s IP 192.168.1.123 připojíme na modulu jako /usr/local. Pak aktualizujeme příkazem ldconfig cache s dostupnými dynamickými knihovnami.
### na pocitaci ### pozn.: promenna EXPORT byla definovana drive $ echo "$EXPORT 192.168.1.12(rw,sync,no_subtree_check,no_root_squash)" |\ sudo tee -a /etc/exports $ sudo service nfs-kernel-server restart ### na modulu jako root # mount -t nfs -o nolock \ 192.168.1.123://home/emlin/devel/arm/export/sam9260/rootfs-nanox \ /usr/local # ldconfig
Testování
Grand Finale! Přes USB hub připojuji k modulu SAM9260 USB myš a klávesnici. Několik suchých hlášek jádra mi oznamuje, že oboje vstupní zařízení byla jádrem rozpoznána. Paráda! Kontroluji, že myš je dostupná jako /dev/mouse. Nano-X totiž ignorují fakt, že nověji je už myš dostupná jako /dev/input/mice. Naštěstí správce zařízení mdev za nás vytvoří symbolický link. Pro zvědavce dodávám, že cestu k myši lze předefinovat pomocí proměnné prostředí MOUSE_PORT, stejně jako použitý protokol (MOUSE_TYPE) anebo cestu ke klávesnici (proměnná CONSOLE). Pak ale musíme Nano-X spouštět ze shellu, kde jsou tyto proměnné definovány.
Pomocí USB klávesnice se přihlašuji k modulu. Systémové hlášky vidím na TFT displeji, který funguje jako konzolové framebuferové zařízení. Pokud bych totiž pustil nano-X přes sériový terminál (připojení přes sériový port), tak by mi nano-X ”sebraly” klávesnici - vždy převezmou kontrolu nad klávesnicí terminálu, odkud jsou spuštěny (podobně jako X-Windows). Navíc se chci ujistit, že jsem schopen modul SAM9260 s připojeným TFT displejem a klávesnicí s myší ovládat lokálně.
Takže do příkazové řádky, zobrazené na TFT displeji, zadávám nano-X a .... a objevuje se černá plocha s kurzorem. Hýbu myší a kurzor se hýbe také. Paráda No.2! Nano-X server funguje, jak má. Mačkám 3x klávesu ESC, čímž ukončuji běh nano-X serveru. Na displeji se objevuje opět linuxový prompt (příkazový řádek).
Pouštím znovu samotný nano-X server. Teď zkusím okenního manažera nanowm a jednoduchý emulátor terminálu nxterm. Okenní manažer a nxterm ovšem musím pustit ze sériového terminálu (nebo přes telnet jak je libo), nano-X server mi totiž sebral kontrolu nad lokálním terminálem. Zadávám příkaz nanowm & /usr/local/bin/apps/nxterm. Původně černá plocha se vybarví do zelena a objevuje se okno terminálu s promptem. Chvíli zadávám příkazy a pak běh terminálu ukončuji pomocí křížku. Jak v plnokrevném linuxovém desktopu. Okenní manažer mi vrací kontrolu nad sériovým terminálem. Nxterm už neběží, ovšem okenní manažer nanowm stále ano. Musím jej ukončit příkazem killall nanowm. Tím ale skončí i nano-X server. Podivné, což? Nebo že bych měl raději používat CTRL+C?
Pouštím nano-X server znovu a zkouším ukázku použití fontů Type1. Zadávám do sériového terminálu nanowm & /usr/local/bin/apps/t1demo. Spustí se okno, kde se vypisuje nápis: ”Microwindows” v různých barvách a fontech. Fonty Type1 fungují na jedničku.
Už jsem unaven, co si takhle zahrát šachy? Já versus Tux. Pouštím z lokálního terminálu nano-X server a přes sériový terminál šachy: nanowm & /usr/local/bin/apps/tuxchess. Po pár tazích začíná vyhrávat Tux...