Produkty Novinky Články Návody Kontakty

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...
Tuxchess - stroj vítězí!