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ę:
i naciskamy ENTER.
Następnie wybieramy pozycję:
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.