System operacyjny Linux w EDK

 

Kompilacja jądra systemu operacyjnego Linux:

 

Uruchamiamy EDK i otwieramy projekt z ćw. „Embedded Development Kit”:

 

 

Wyświetli się okno projektu:

 

 

Następnie należy skonfigurować EDK w celu wygenerowania „drzewa urządzeń” (device tree) zgodnego z ustawieniami sprzętu. „Drzewo urządzeń” będzie potrzebne do uruchomienia jądra Linuxa (jądro będzie dzięki niemu znało listę i lokalizację urządzeń w przestrzeni adresowej).

 

Klikamy w menu Software a następnie Software Platform Settings (albo od razu w klawisz:  ).

Wyświetli się okienko:

 

 

W polu  OS:  zamiast  standalone  wybieramy  device-tree.

 

Następnie klikamy w OS and Libraries:

 

 

Teraz modyfikujemy: w polu console device wpisujemy:  RS232_Uart_1

W polu bootargs zmieniamy: console=ttyS0 na console=ttyUL0

(to dlatego, że używamy układu portu UartLite, a nie standardowego 16550):

 

 

Następnie naciskamy OK.

 

Klikamy w menu Software a następnie Generate Libraries and BSPs (albo od razu w klawisz:  ).

 

Spowoduje to wygenerowanie pliku xilinx.dts z drzewem urządzeń (device tree).

Plik ten zostanie wygenerowany w katalogu (w odniesieniu do katalogu projektu):

ppc405_0/libsrc/device-tree_v0_00_x

Plik ten będzie potrzebny do kompilacji jądra systemu Linux.

 

Następnie należy otworzyć terminal i uruchomić w katalogu domowym skrypt:


linux-kernel-copy

 

Skrypt ten skopiuje drzewo dystrybucji Linuxa do katalogu użytkownika.

 

Następnie należy w oknie terminala wykonać komendę:


source source_me

 

Spowoduje to ustawienie odpowiednich zmiennych środowiskowych sterujących pracą kompilatora dla procesora PowerPC.

 

Następnie należy wejść do katalogu z dystrybucją jądra Linuxa:

 

cd linux-2.6-xlnx

 

i uruchomić program konfiguracyjny:

 

make menuconfig

 

wyświetli się następujące okienko:

 


 


Główne ustawienia (m.in. rodzaj procesora) są już zrobione domyślnie, ale trzeba jeszcze włączyć obsługę GPIO przez katalog /sys:

 

W tym celu wybieramy pozycję:

 

Device Drivers  --->

 

i naciskamy ENTER.

Następnie wybieramy pozycję:

 

GPIO Support  --->

 

i naciskamy ENTER.

Następnie zaznaczamy SPACJĄ pozycję:

 

/sys/class/gpio/... (sysfs interface)

 

Powinna pojawić się przy niej gwiazdka:

 


 


Następnie wybieramy kolejno Exit aż do zapytania o potwierdzenie zapisu nowej konfiguracji – wtedy wybieramy Yes co powoduje wyjście z aplikacji i zapisanie pliku .config.

 

Teraz należy skopiować uprzednio przygotowany plik z drzewem urządzeń (zakładam, że nazwa katalogu projektowego to edk):

 

cp ~/edk/ppc405_0/libsrc/device-tree_v0_00_x/xilinx.dts  ~/linux-2.6-xlnx/arch/powerpc/boot/dts/virtex405-lab.dts

 

Następnie należy skopiować plik z filesystemem root:

 

cp /opt/buildroot/initrd.patched.ext2.gz ~/linux-2.6-xlnx/arch/powerpc/boot/ramdisk.image.gz

 

Teraz można już rozpocząć kompilację jądra (będąc w katalogu linux-2.6-xlnx): 

 

make -j 2 simpleImage.initrd.virtex405-lab

 

Kompilacja trwa około 8 minut. Skompilowane jądro znajduje się w pliku:

~/linux-2.6-xlnx/arch/powerpc/boot/simpleImage.virtex405-lab.elf

 

 

Uruchomienie systemu Linux na płytce Digilent:

 

Nie ma potrzeby uruchamiania EDK. Należy wykonać następujące komendy w oknie terminala (zakładam, że nazwa katalogu projektowego to edk):

 

cd ~/edk

impact -batch etc/download.cmd

rlwrap -c xmd -opt etc/xmd_ppc405_0.opt

 

Spowoduje to wczytanie pliku *.bit z projektem z ćw. 7, a następnie uruchomienie debugera XMD (w nowym oknie) i połączenie się z płytką.

 

Następnie należy uruchomić MINICOM i ustawić szybkość łącza 115200 bps (podobnie jak w ćw. 7).

 

Teraz w oknie XMD (prompt XMD%) należy wydać następujące komendy:

 

cd ~/linux-2.6-xlnx/arch/powerpc/boot

dow simpleImage.initrd.virtex405-lab.elf

run

 

Można także uruchomić EDK i wykonać czynności związane z ładowaniem projektu podobnie jak w ćwiczeniu poprzednim (ale ładowanie pliku *.elf przez debugger aplikacji będzie długotrwałe).

 

Po uruchomieniu systemu Linux na płytce laboratoryjnej należy zalogować się do nowego systemu na konsoli (MINICOM) jako root (bez hasła).

 

Następnie można zamontować katalog domowy z komputera laboratoryjnego (zamiast trzech kropek wpisać swój login):

 

mount –o rsize=1500,wsize=1500 192.168.1.1:/home/... /mnt

 

Można także zamontować katalog z aplikacjami.

Zamiast numerycznego IP można stosować nazwy:

 

mount –o rsize=1500,wsize=1500 labhost:/opt_local /opt

 

System Linux w PowerPC ma adres sieciowy: 192.168.1.2 i nazwę xilinx.

Opcje rsize i wsize mają ograniczyć długość pakietu tak, aby zmieścił się on w standardowej ramce Ethernet (inaczej wystąpi kosztowna czasowo fragmentacja i wydajność drastycznie spadnie) – sterownik MAC nie obsługuje dłuższych ramek.

 

 

Obsługa GPIO z poziomu userspace (metoda zalecana):

 

W celu poznania sposobu uzyskania dostępu do diod LED i przełączników należy zmienić katalog:

 

cd /sys/class/gpio

 

Następnie można wyświetlić jego zawartość:

 

ls –al

 

total 0

drwxr-xr-x    5 root     root       0 May  8 23:32 .

drwxr-xr-x   15 root     root       0 May  8 23:32 ..

--w-------    1 root     root    4096 May  9 02:23 export

drwxr-xr-x    2 root     root       0 May  8 23:38 gpiochip243

drwxr-xr-x    2 root     root       0 May  8 23:38 gpiochip248

drwxr-xr-x    2 root     root       0 May  8 23:38 gpiochip252

--w-------    1 root     root    4096 May  9 02:42 unexport

 

Pliki gpiochipxxx zawierają informacje o dostępnych urządzeniach GPIO.

Aby można było obsłużyć porty GPIO najpierw należy je udostępnić (wyeksportować) użytkownikowi. Robimy to wystawiając numery portów do pliku export. Porty są jednobitowe i mają następujące numery:

 

Przyciski (5):           243-247

LEDy (4):                  248-251

Przełączniki (4):     252-255

 

# ls

export       gpiochip243  gpiochip248  gpiochip252  unexport

# echo 248 > export

# ls

export       gpio248      gpiochip243  gpiochip248  gpiochip252  unexport

 

W związku z rozkazem eksportu pojawił się nowy katalog: gpio248

Katalog ten zawiera kolejne pliki - tym razem związane tylko z obsługą tego jednego bitu:

 

# cd gpio248

# ls

active_low  direction   subsystem   uevent      value

 

Następnie ustawiamy kierunek portu na out (lub in):

 

# echo out > direction

 

Teraz możemy już pisać (lub czytać) dane z portu:

 

# echo 1 > value

# echo 0 > value

 

Poniżej podano przykład obsługi LED i przełączników w skrypcie sh:

(LEDy migają, stan przełączników jest drukowany co 2 sekundy):

 

#!/bin/sh

cd /sys/class/gpio

echo "248" > export

echo "249" > export

echo "250" > export

echo "251" > export

echo "252" > export

echo "253" > export

echo "254" > export

echo "255" > export

echo out > gpio248/direction

echo out > gpio249/direction

echo out > gpio250/direction

echo out > gpio251/direction

echo in > gpio252/direction

echo in > gpio253/direction

echo in > gpio254/direction

echo in > gpio255/direction

while true ; do

  sleep 1

  echo 0 > gpio248/value

  echo 1 > gpio249/value

  echo 0 > gpio250/value

  echo 1 > gpio251/value

  sleep 1

  echo 1 > gpio248/value

  echo 0 > gpio249/value

  echo 1 > gpio250/value

  echo 0 > gpio251/value

  echo -n `cat gpio252/value`

  echo -n `cat gpio253/value`

  echo -n `cat gpio254/value`

  echo  `cat gpio255/value`

done

 

Po zakończeniu pracy powinno się wyłączyć wyjście (zmieniając kierunek na in) oraz eksport:

 

#!/bin/sh

cd /sys/class/gpio

echo in > gpio248/direction

echo in > gpio249/direction

echo in > gpio250/direction

echo in > gpio251/direction

echo "248" > unexport

echo "249" > unexport

echo "250" > unexport

echo "251" > unexport

echo "252" > unexport

echo "253" > unexport

echo "254" > unexport

echo "255" > unexport

 

Oczywiście dostęp do GPIO można także zrealizować w ten sposób stosując inne języki skryptowe lub język C.

 

 

Zadanie – realizacja miniserwera www pozwalającego na ustawianie stanu diod LED i odczyt stanu przełączników poprzez stronę www.

 

Zadanie można zrealizować używając dostępnego w systemie uproszczonego serwera httpd (/usr/sbin/httpd).

Należy napisać aplikację CGI realizującą obsługę GPIO i odpowiednio podłączyć ją do serwera.

CGI może być napisany w języku skryptowym (shell ash – uproszczona wersja bash), w języku TCL (tclsh8.4), w języku C (poniżej przykład kompilacji przykładowego programu hello-world) lub w innym (samodzielnie zainstalowanym).

Poniżej lista stron z informacjami pomocniczymi dotyczącymi tworzenia aplikacji CGI:

·        CGI w TCL:  http://expect.nist.gov/doc/cgi.pdf

·        CGI w ash:  http://isquared.nl/index.html?pagelink=9&desc=bourne/_bash_shell_cgi_scripts

·        CGI w C:  http://www.cs.tut.fi/~jkorpela/forms/cgic.html

 

httpd jest uproszczonym serwerem, oto jego „help”:

 

Usage: httpd [-ifv[v]] [-c CONFFILE] [-p [IP:]PORT] [-u USER[:GRP]] [-r REALM] ]

or httpd -d/-e/-m STRING

 

Listen for incoming HTTP requests

 

Options:

        -i              Inetd mode

        -f              Don't daemonize

        -v[v]           Verbose

        -c FILE         Configuration file (default httpd.conf)

        -p [IP:]PORT    Bind to ip:port (default *:80)

        -u USER[:GRP]   Set uid/gid after binding to port

        -r REALM        Authentication Realm for Basic Authentication

        -h HOME         Home directory (default .)

        -m STRING       MD5 crypt STRING

        -e STRING       HTML encode STRING

        -d STRING       URL decode STRING

 

Serwer można po prostu uruchomić tak:

 

httpd -h katalog_domowy_strony_www

 

Skrypty CGI umieszczamy w podkatalogu /cgi-bin/

Konfiguracją serwera można także sterować za pomocą pliku konfiguracyjnego.

Oto przykładowy plik konfiguracyjny:

 

H:/serverroot     # define the server root. It will override -h

A:172.20.         # Allow address from 172.20.0.0/16

A:10.0.0.0/25     # Allow any address from 10.0.0.0-10.0.0.127

A:10.0.0.0/255.255.255.128  # Allow any address that previous set

A:127.0.0.1       # Allow local loopback connections

D:*               # Deny from other IP connections

E404:/path/e404.html # /path/e404.html is the 404 (not found) error page

I:index.html      # Show index.html when a directory is requested

 

P:/url:[http://]hostname[:port]/new/path

                  # When /urlXXXXXX is requested, reverse proxy

                  # it to http://hostname[:port]/new/pathXXXXXX

 

/cgi-bin:foo:bar  # Require user foo, pwd bar on urls starting with /cgi-bin/

/adm:admin:setup  # Require user admin, pwd setup on urls starting with /adm/

/adm:toor:PaSsWd  # or user toor, pwd PaSsWd on urls starting with /adm/

.au:audio/basic   # additional mime type for audio.au files

*.php:/path/php   # run xxx.php through an interpreter

 

A/D may be as a/d or allow/deny - only first char matters.

Deny/Allow IP logic:

 - Default is to allow all (Allow all (A:*) is a no-op).

 - Deny rules take precedence over allow rules.

 - "Deny all" rule (D:*) is applied last.

 

Example:

   1. Allow only specified addresses

     A:172.20          # Allow any address that begins with 172.20.

     A:10.10.          # Allow any address that begins with 10.10.

     A:127.0.0.1       # Allow local loopback connections

     D:*               # Deny from other IP connections

 

   2. Only deny specified addresses

     D:1.2.3.        # deny from 1.2.3.0 - 1.2.3.255

     D:2.3.4.        # deny from 2.3.4.0 - 2.3.4.255

     A:*             # (optional line added for clarity)

 

If a sub directory contains a config file it is parsed and merged with any existing settings as if it was appended to the original configuration.

 

subdir paths are relative to the containing subdir and thus cannot affect the parent rules.

 

Note that since the sub dir is parsed in the forked thread servicing the subdir http request, any merge is discarded when the process exits.

As a result, the subdir settings only have a lifetime of a single request.

 

Custom error pages can contain an absolute path or be relative to 'home_httpd'. Error pages are to be static files (no CGI or script).

Error page can only be defined in the root configuration file and are not taken into account in local (directories) config files.

 

If -c is not set, an attempt will be made to open the default root configuration file.  If -c is set and the file is not found, the server exits with an error.

 

 

Kompilacja programu w C na procesor PowerPC (jeżeli wybrano realizację CGI w C):

 

Kompilację wykonuje się na komputerze głównym, następnie za pomocą udostępnionego katalogu domowego można łatwo uruchomić skompilowany program na płytce laboratoryjnej.

W oknie terminala uruchamiamy komendę (podobnie jak przed kompilacją jądra):

 

source source_me

 

Tworzymy plik main.c zawierający program.

Przykład:

 

#include <stdio.h>

main()

{

  printf("Hello World!\n");

}

 

Następnie kompilujemy (linkujemy statycznie):

 

ppc_4xx-gcc main.c -o main -static

 

Teraz w oknie MINICOM uruchamiamy skompilowany program.

 

 

 

Budowa własnego root-filesystemu (nieobowiązkowe – uwaga – bardzo długi czas kompilacji):

 

W katalogu domowym uruchomić skrypt:


buildroot-copy

 

następnie wejść do katalogu buildroot:


cd buildroot

 

uruchomić skrypty konfiguracyjne, zapisać konfigurację (można dokonać własnych zmian w konfiguracji):

make menuconfig

make busybox-menuconfig

 

teraz można uruchomić kompilację (trwa około 35 minut):

 

make

 

Następnie aplikujemy łatkę:

 

rm rootfs.powerpc.patched.tar.gz

rm initrd.patched.ext2.gz

./xilinx-patch

 

powstaje nowy root-filesystem:

 

./initrd.patched.ext2.gz

 

który należy skopiować do drzewa katalogów jądra (zmieniając nazwę):

 

cp initrd.patched.ext2.gz ~/linux-2.6-xlnx/arch/powerpc/boot/ramdisk.image.gz

 

następnie należy skompilować i uruchomić jądro Linuxa ponownie.