Linux_embedded_cz2.pdf

(525 KB) Pobierz
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
Wprowadzenie do Linux’a embedded
KURS
Wprowadzenie do
Linux’a embedded (2)
Klawiatura matrycowa,
podsystem input,
zaawansowana obsługa
wejścia – wyjścia
Dodatkowe materiały
na CD/FTP
W  poprzednim odcinku zapoznaliśmy się z  obsługą portów GPIO
w  Linuksie za pomocą aplikacji użytkownika wykorzystując interfejs
sysfs-gpio. Sprawdzenia stanu wciśnięcia klawisza dokonywaliśmy
poprzez cyklicznie odczytywanie stanu, co powodowało, że proces
zupełnie niepotrzebnie był co chwilę aktywowany, w  celu wykrycia
zbocza na linii wejściowej. W  środowiskach wielozadaniowych
powinniśmy unikać cyklicznego odpytywania, aby procesor był
dostępny dla innych procesów. Poza tym, jak wspomniano
poprzednio, porty GPIO nie są same w  sobie funkcjonalnym
urządzeniem, służą one jedynie do podłączenia innych układów np.
diod LED itp. W  bieżącym odcinku pokażemy zatem jak w  jaki
sposób obsłużyć klawiaturę, oraz diody LED zgodnie z  i lozoi ą
jądra Linuksa.
Dodatkowe materiały na CD/FTP:
ftp://ep.com.pl , user: 12147 , pass: 2e7u6a2a
• pierwsza część kursu
jest możliwy za pomocą kilku interfejsów
które stanowią: intefejs klawiatury, Inter-
fejs myszy, Interfejs Joysticka oraz Interfejs
zdarzeń. Dostęp do poszczególnych interfej-
sów aplikacjom zapewniają pliki urządzeń.
(Jak mawia stare powiedzenie w  linuksie
wszystko jest plikiem). Interfejs klawiatury
myszy i joysticka jest dedykowany obsłudze
wyżej wspomnianych urządzeń i jego zasto-
sowanie nie wymaga dodatkowego komen-
tarza. Interfejs Event służy do podłączania
innych rodzajów przycisków czy klawiszy,
(np. przycisk zamknięcia obudowy laptopa,
przyciski głośności itp.), i umożliwia gene-
rowanie zdarzeń, możliwych do odczytania
z aplikacji użytkownika. Może się wydawać,
że interfejs event, a interfejs klawiatury to
w zasadzie to samo, jednak różnica jest taką,
że interfejs klawiatury mapuje bezpośrednio
klawiaturę do konsoli, Interfejs event z kolei
umożliwia odczytywanie stanu pozostałych
klawiszy istotnych dla danej platformy.
Aby urozmaić przykład zamiast pojedyn-
czego przycisku podłączymy klawiaturę ma-
trycową w roli której wykorzystamy moduł
KAMODKBD4x4 i rmy Kamami. Klawiaturę
tą podłączymy do podsystemu Input jądra,
za pomocą odpowiedniego sterownika, nato-
miast do sterowania diodami LED użyjemy
interfejsu leds, który jest przeznaczony do
sterowania diodami LED.
nuksa przedstawiono na rysunku 4 zaczerp-
niętym z czasopisma „The Linux Journal”
( http://www.linuxjournal.com ).
Interfejs ten składa się z jądra podsyste-
mu (Input core), które od strony niskopozio-
mowej komunikuje się ze sterownikami urzą-
dzeń, które są odpowiedzialne za bezpośred-
nią komunikację z urządzeniami. Natomiast
od strony aplikacji użytkownika zapewnia
jednolity interfejs. Od strony aplikacji dostęp
Zagadnienia teoretyczne
Podsystem wejścia ( Linux Input Sub-
system ). Podsystem wejścia jądra systemu
linuks, zapewnia jednolity interfejs dla ob-
sługi wszelkich urządzeń wejściowych, ta-
kich jak klawiatury, myszki, joysticki, oraz
inne urządzenia. Zapewnia on obsługę urzą-
dzeń z wykorzystaniem, zdarzeń. Zapewnia
on również sterowanie, np. diodami LED
klawiatury, wibracjami joysticka itp. Mecha-
nizm dostarcza warstwę abstrakcji unieza-
leżniającą aplikację użytkownika od sprzętu,
magistrali do której zostało urządzenie pod-
łączone. np. USB, PS2, GPIO itp. Schemat
blokowy podsystemu wejścia w jądrze Li-
Rysunek 4. Schemat blokowy podsystemu wejścia w jądrze Linuksa
95
ELEKTRONIKA PRAKTYCZNA 5/2011
883836618.426.png 883836618.437.png 883836618.448.png 883836618.459.png 883836618.001.png 883836618.012.png 883836618.023.png 883836618.034.png 883836618.045.png 883836618.056.png 883836618.067.png 883836618.078.png 883836618.089.png 883836618.100.png 883836618.111.png 883836618.122.png 883836618.133.png 883836618.144.png 883836618.155.png 883836618.166.png 883836618.177.png 883836618.188.png 883836618.199.png 883836618.210.png 883836618.221.png 883836618.232.png 883836618.243.png 883836618.254.png 883836618.265.png 883836618.276.png 883836618.287.png 883836618.298.png 883836618.309.png 883836618.320.png 883836618.331.png 883836618.342.png 883836618.353.png 883836618.364.png 883836618.375.png 883836618.386.png 883836618.397.png 883836618.408.png 883836618.414.png 883836618.415.png 883836618.416.png 883836618.417.png 883836618.418.png 883836618.419.png 883836618.420.png 883836618.421.png 883836618.422.png 883836618.423.png 883836618.424.png 883836618.425.png 883836618.427.png 883836618.428.png 883836618.429.png 883836618.430.png 883836618.431.png 883836618.432.png 883836618.433.png 883836618.434.png 883836618.435.png 883836618.436.png 883836618.438.png 883836618.439.png 883836618.440.png 883836618.441.png 883836618.442.png 883836618.443.png 883836618.444.png 883836618.445.png 883836618.446.png 883836618.447.png 883836618.449.png 883836618.450.png 883836618.451.png 883836618.452.png 883836618.453.png 883836618.454.png 883836618.455.png 883836618.456.png 883836618.457.png 883836618.458.png 883836618.460.png 883836618.461.png 883836618.462.png 883836618.463.png 883836618.464.png 883836618.465.png 883836618.466.png 883836618.467.png 883836618.468.png 883836618.469.png 883836618.002.png 883836618.003.png 883836618.004.png 883836618.005.png 883836618.006.png 883836618.007.png 883836618.008.png 883836618.009.png 883836618.010.png 883836618.011.png 883836618.013.png
KURS
sterowniki dla większości typo-
wych urządzeń dołączanych do
portów GPIO. W poprzednim od-
cinku wspominaliśmy o sterow-
niku gpio_buttons dla pojedyn-
czych przycisków. W przypadku
klawiatury matrycowej odpo-
wiednim sterownikiem będzie
matrix_keypad , a jedyną rzeczą
jaką będziemy musieli wykonać
to zdei niować kilka struktur
oraz zarejestrować opis urządze-
nia w odpowiednich strukturach
przechowujących koni gurację, za pomocą
funkcji platform_register_device() , w  pliku
inicjalizującym daną płytkę.
Sterowanie klawiatura matrycową od-
bywa się za pomocą przemiatania poprzez
wystawienie odpowiednich stanów na linii
wierszy (ROW), oraz sprawdzania stanów
na liniach kolumn (COL). Przy czym spraw-
dzanie stanów może się odbywać za pomo-
cą aktywnego odpytywania, lub za pomocą
przerwań. Sterownik matrix-keypad , został
napisany, z wykorzystaniem tego drugiego
sposobu, i do prawidłowej pracy wymaga li-
nii GPIO, które potrai ą zgłaszać przerwania.
Na szczęście porty GPIO naszego mikrokon-
trolera RM9200 posiadają taką możliwość,
zatem bez problemu możemy wykorzystać
sterownik matrix_keypad . Aby sterownik
mógł działać poprawnie musimy w struktu-
rach przechowujących koni gurację maszy-
ny, określić rodzaj klawiatury, oraz sposób
jej dołączenia co jest realizowane za pomocą
struktury z  listingu   1 .
Pole keymap_data wskazuje na kolejną
strukturę matrix_keymap_data , która za-
wiera wskaźnik do tablicy dei niującej przy-
pisania kodów klawiszy do poszczególnych
wierszy i kolumn. Pole row_gpios , wskazuje
na tablicę zawierającą numery porządkowe
portów GPIO (poprzedni artykuł), określa-
jące i zyczne linie GPIO, które będą użyte
w roli linii wierszy, podobnie pole col_gpios ,
określa linie GPIO, które będą użyte w roli li-
nii kolumn. Pola num_row_gpios oraz num_
col_gpios , określają ilość linii kolumn, oraz
linii wierszy klawiatury matrycowej. Pole
col_scan_delay_us określa, czas opóźnienia
pomiędzy ustawieniem linii stanu linii wier-
szy, a odczytywaniem stanu linii kolumn.
Pole debounce_ms określa czas potrzebny
do wyeliminowania drgań zestyków. Pole
active_low określa, czy stanem aktywnym
jest sygnał 1 czy 0. Pole wakeup , określa czy
klawiatura umożliwia wybudzanie systemu
ze stanu uśpienia. Pole no_autorepeat , okre-
śla że klawiatura nie generuje kodów powtó-
rzeń podczas ciągłego trzymania klawisza,
a jedynie eventy wciśnięcia oraz zwolnienia
klawisza. Wypełnienie struktury matrix_
keypad_platform , zapewnia sterownikowi
matrix-keypad , wszystkie niezbędne dane
potrzebne do działania, oraz informuje ste-
rownik o obecności klawiatury matrycowej
dołączonej do portów GPIO.
Dostęp do klawiatury z aplikacji użyt-
kownika, z  wykorzystaniem interfejsu
event. Dostęp do zdarzeń podsystemu in-
put realizowany jest za pomocą pliku /dev/
input/eventX (gdzie X określa kolejny numer
urządzenia). Po otwarciu urządzenia dane
o zdarzeniach od urządzenia, będzie można
odczytywać za pomocą wywołania systemo-
wego read(). Ponieważ domyślnie funkcja
read(), jest blokująca (usypiająca proces),
wywołanie funkcji read spowoduje uśpienie
wywołującego procesu do momentu wystą-
pienia zdarzenia od podsystemu input. Zda-
rzenia zostały zdei niowane w postaci struk-
tury umieszczonej na listingu   2 .
Pole timeval , zawiera znacznik czasu
wystąpienia zdarzenia, pole type określa typ
zdarzenia, w przypadku klawiatury, będą to
zdarzenia typu EV_KEY , natomiast pole va-
lue , określa wartość dla danego zdarzenia.
Dla zdarzenia EV_KEY , wciśnięcie klawisza
będzie sygnalizowane zwróceniem wartości
1 w polu value , zwolnienie klawisza sygna-
lizowane będzie zwróceniem wartości 0 , na-
tomiast wciśnięcie i przytrzymanie klawisza
będzie powodowało generowanie cyklicz-
nych zdarzeń powtórzonych, które będą sy-
gnalizowane wartością 2. Pole code zawiera
kod klawisza który został wciśnięty. Zatem
odczytując zdarzenia za pomocą funkcji
read() , spowodujemy uśpienie wywołujące-
go procesu do momentu wystąpienia zdarze-
nia.
Lisitng 1. Struktura służąca do obsługi klawiatury
struct matrix_keypad_platform_data {
const struct matrix_keymap_data *keymap_data;
const unsigned int *row_gpios;
const unsigned int *col_gpios;
unsigned int num_row_gpios;
unsigned int num_col_gpios;
unsigned int col_scan_delay_us;
/* key debounce interval in milli-second */
unsigned int debounce_ms;
unsigned int clustered_irq;
unsigned int clustered_irq_fl ags;
bool active_low;
bool wakeup;
bool no_autorepeat;
};
Dane platform device, umożliwiające
określenie koni guracji maszyny. Klasyczne
komputery PC mają ściśle określoną archi-
tekturę oraz podsystem BIOS umożliwiają-
cy, określenie urządzeń zewnętrznych i we-
wnętrznych będących częścią komputera.
Aby dowiedzieć się w jakie urządzenia wy-
posażony jest komputer, wystarczy odpytać
BIOS, lub urządzenia PnP (Plug and Play).
W przypadku innych architektur, a szczegól-
nie w przypadku urządzeń wbudowanych,
mamy do czynienia z wieloma różnymi kon-
strukcjami sprzętowymi, zawierającymi róż-
ne komponenty i podzespoły. Najczęściej nie
istnieje również żaden jednolity interfejs sta-
nowiący funkcjonalny odpowiednik syste-
mu BIOS, który umożliwia zapytanie o listę
dostępnego sprzętu. Jedynym zatem sposo-
bem sprawdzenia, listy dostępnych kompo-
nentów danej platformy jest zdei niowanie
listy podzespołów bezpośrednio w kodzie.
W linuksie kod zdei niowany jest w postaci
struktur danych platform_data zawierają-
cych listę podzespołów danej maszyny. Lista
ta dei niowana jest w jądrze w pliku odpo-
wiedzialnym za koni gurację danej maszyny.
W przypadku BF210 plikiem odpowiedzial-
nym za inicjalizację jest plik w kodzie jądra
znajdujący się w  następującej lokalizacji:
arch/arm/mach-at91/board-boff210.c Lista
uradzeń dostępnych na danej platformie zor-
ganizowana jest w postaci dei nicji struktur
struct platform_device , które następnie są ini-
cjalizowane za pomocą funkcji platform_de-
vice_register() ...
Sterownik klawiatury matrycowej ma-
trix-keypad. Aby urządzenie było widocz-
ne przez podsystem wejścia, musi posiadać
sterownik dla podsystemu. Dołączenie
odpowiedniego urządzenia wymaga zatem
napisania sterownika jądra, co może być za-
daniem stosunkowo skomplikowanym dla
początkującego użytkownika. W  głowach
czytelników rodzi się pytanie, czy aby do-
łączyć tytułową klawiaturę KAMOD4x4
będziemy musieli się zmagać z napisaniem
odpowiedniego sterownika dla podsystemu
input? Wiadomość jest bardzo optymistycz-
na i brzmi NIE. Dzięki warstwie abstrakcji
obsługi portów GPIO istniejącym w kerne-
lu, oraz danych koni guracyjnych, dla danej
platformy ( platform data ), istnieją gotowe
Przykład praktyczny KAMOD4x4
ze sterownikiem matrix-keypad.
Diody LED sterowane przez leds-
gpio
Wstęp, schemat ideowy. Po zapoznaniu
się z  częścią teoretyczną przejdziemy do pre-
zentacji, przykładu w którym wykorzystamy
klawiaturę matrycowa KAMODKBD4x4 ,oraz
minimoduł KAMODLED8 produkcji KAMAMI .
Będzie to bardzo prosty przykład, w którym
wciśnięcie i trzymanie klawisza, będzie zapa-
lało diody LED D0-D3 , odpowiadające wciśnię-
temu klawiszowi, natomiast zwolnienie klawi-
sza powodować będzie wyłączenie wszystkich
diod. Klawiatura matrycowa będzie dołączona
do podsystemu input, z wykorzystaniem ste-
rownika matrix-keypad , co umożliwi nam cał-
kowicie pasywne sprawdzanie stanu klawiszy.
Diody LED będą dołączone do podsystemu
LED za pomocą sterownika leds-gpio . Aplika-
cja przestrzeni użytkownika będzie używać in-
terfejsu evdev , do odczytywania stanu klawia-
Listing 2. Struktura defi niująca
zdarzenia
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
96
ELEKTRONIKA PRAKTYCZNA 5/2011
883836618.014.png 883836618.015.png 883836618.016.png 883836618.017.png
Wprowadzenie do Linux’a embedded
kolumn, które zostało zdeiniowane na 10 us.
Pole debounce_time , zawiera opóźnienie eli-
munujące drgania zestyków, które zostało usta-
wione na 10 ms. Pole active_low informuje że
skanowanie wierszy i kolumn odbywa się za
pomocą stanu niskiego, dzięki czemu możliwe
jest wykorzystanie wewnętrznych rezystorów
podciągających. Pole wake_up=1 , określa że
możliwe jest wybudzanie urządzenia ze sta-
nu uśpienia w wyniku wciśnięcia klawisza.
Tak przygotowana struktura informacyjna dla
sterownika matrix_keypad , jest następnie przy-
pisywana do struktury platform_device , która
następnie jest rejestrowana w systemie w funk-
cji inicjalizującej maszyne bf_board_init() za
pomocą wywołania p latform_device_register(
&keypad_device)
Tablica struktur gpio_leds zdeiniowana
jako LEDS zawiera informację o koniguracji
diod LED, i sprowadza się ona do przypisa-
nia nazwy poszczególnych diod LED w polu
name , oraz przypisania odpowiadającej jej
linii GPIO. Nazwy te następnie będą widocz-
ne w  przestrzeni użytkownika w  katalogu
/sys/class/led.
Zaprezentowany przykład jest dostępny
w  postaci kompletnego obrazu karty, przy-
gotowanego do testów, jednak w przypadku
samodzielnego konigurowania urządzeń, ko-
nieczna będzie modyikacja kodu jądra Linuk-
sa, chociaż w minimalnie opisanym zakresie,
dlatego w dalszej części tekstu opiszemy w jaki
sposób dokonywać zmian we własnym zakre-
sie. Mniej dociekliwi czytelnicy mogą pominąć
niniejszy fragment.
W świecie Open Source, zmiany w kodzie
źródłowym dla istniejącego kodu dołączane
są w postaci plików patch. Są to proste pliki
tekstowe, które zawierają różnice pomiędzy
oryginalnym, a  zmodyikowanym kodem,
obsługiwane przez program patch . Plik l eds-
keypad.patch , zawiera patch dla jądra linuxa,
zawierający wcześniej opisany fragment kodu,
konigurującego klawiaturę oraz diody. Po-
nieważ do kompilacji jądra nie są potrzebne
żadne biblioteki zewnętrzne możemy w zasa-
dzie wykorzystać dowolną wersję kompilatora
gcc, która zawiera obsługę EABI . Na przykład
w Ubuntu 10.10, wystarczy zainstalować pa-
kiet gcc-4.5-arm-linux-gnueabi (polecenie
sudo apt-get install gcc-4.5-arm-linux-gnueabi )
Następnie aby skompilować przykład należy
ściągnąć źródła jądra 2.6.37 ze strony http://
www.kernel.org/ rozpakować je, a następnie za-
stosować patch dla maszyny BF210 który jest
dostępny tutaj http://www.boff.pl/content/iles/
id5/2.6.37-boff-bf210.patch (po lecenie patch
-p1 -d linux-2.6.37 < 2.6.37-boff-210.patch ).
Kolejną czynnością jest zastosowanie patcha,
który dodaje opisane wcześniej struktury plat-
form-data , za pomocą polecenia: patch -p1 -d
linux-2.6.37 < leds_keypad.patch . Gdy już
mamy odpowiednio skonigurowane źródła
możemy przystąpić koniguracji jądra. W tym
celu do katalogu linux-2.6.37 , należy skopio-
KAMODLED8: (+5V – J2PIN1, GND – J2PIN2, D0 – J2PIN7, D1 – J2PIN9,
D2 – J2PIN17, D3 – J2PIN19, D4-J2PIN4, D5-J2PIN6, D6-J2PIN8, D7-J2PIN10)
KAMODKB4x4: ( ROW1 – J3PIN9, ROW2 – J3PIN15, ROW3- J3PIN27, ROW4-J3PIN29,
COL1-J3PIN17, COL2-J3PIN19, COL3-J3PIN21, COL4-J3PIN23)
Rysunek 5. Schemat ideowy dołączenia modułów do płyty prototypowej BF210
tury. Schemat ideowy dołączenia modułów do
płyty prototypowej BF210 przedstawiono na
rysunku 5 .
Linie LED-ów zostały dołączone odpo-
wiednio do linii portów PB1, PB2, PB6, PB7,
natomiast linie wierszy i kolumn odpowiednio
do linii PB26, PB29, PC5, PC6, PC0, PC1, PC2,
PC3. Dzięki możliwości włączenia wbudowa-
nych w linie GPIO rezystorów podciągających,
nie będą potrzebne dodatkowe rezystory, a po-
łączenie wszystkich modułów możemy doko-
nać np. za pomocą przewodów CAB, do naby-
cia w irmie Kamami.
Konigurowanie jądra. Jak już wcześniej
wspomniano, lista dostępnych urządzeń na
danej maszynie determinowana jest za pomo-
cą struktur platform-device. BF210 jest płytą
prototypową zatem z uwagi na niemożliwość
określenia przeznaczenia a zatem przypisa-
nia linii GPIO, nie jest możliwe dostarczenie
gotowego binarnego jądra, które nadaje się
do wykorzystania we wszystkich projektach.
W związku z tym w przypadku dołączenia
urządzeń które nie są Plug&Play (u nas tylko
USB), i wykorzystaniu sterowników jądra, bę-
dziemy zmuszeni do edycji kodu źródłowego
jądra, a konkretnie pliku odpowiedzialnego za
konigurację maszyny, oraz rekompilację jądra.
W przypadku płyty prototypowej BF210, kod
linuxa jest zdeiniowany w pliku a rch/arm/
mach-at91/board-boff210.c . Na listingu   3 prze-
stawiono fragment struktur, odpowiedzialnych
za informację, o dołączeniu klawiatury matry-
cowej, oraz diod LED.
Na początku tworzona jest tablica, zawie-
rająca przypisanie poszczególnych wierszy
i kolumn, do odpowiedniego kodu klawiszy.
Następnie na podstawie tablicy mapy two-
rzona jest struktura matrix_keypad_data , do
której przypisujemy mapę stworzonych klawi-
szy. Mapa ta określa kod klawisza, zwrócony
w wyniku wykrycia wciśnięcia na przecięciu
odpowiedniej kolumny i odpowiedniego wier-
sza. Następnie tworzone są dwie tablice zawie-
rające mapę przypisań linii GPIO , do wierszy,
oraz kolumn. Następnie na bazie wcześniej
zdeiniowanych struktur tworzona jest struk-
tura matrix_keypad_platform_data stanowią-
ca informację dla sterownika matrix-keypad .
Pole keymap_data , zawiera przypisanie wcze-
śniej utworzonej koniguracji klawiszy. Pola
row_gpios , num_row_gpios zawierają odpo-
wiednio przypisania mapy linii GPIO, które
stanowią linie kolumn, oraz ilość linii. Podob-
nie sytuacja wygląda w przypadku przypisania
linii GPIO wierszy. Pole con_scan_delay_us ,
określa opóźnienie pomiędzy wystawieniem
stanu na linii wierszy, a odczytaniem stanu
97
ELEKTRONIKA PRAKTYCZNA 5/2011
883836618.018.png 883836618.019.png 883836618.020.png 883836618.021.png 883836618.022.png 883836618.024.png 883836618.025.png 883836618.026.png 883836618.027.png 883836618.028.png 883836618.029.png 883836618.030.png 883836618.031.png 883836618.032.png 883836618.033.png 883836618.035.png 883836618.036.png 883836618.037.png 883836618.038.png 883836618.039.png 883836618.040.png 883836618.041.png 883836618.042.png 883836618.043.png 883836618.044.png 883836618.046.png 883836618.047.png 883836618.048.png 883836618.049.png 883836618.050.png 883836618.051.png 883836618.052.png 883836618.053.png 883836618.054.png 883836618.055.png 883836618.057.png 883836618.058.png 883836618.059.png 883836618.060.png 883836618.061.png 883836618.062.png 883836618.063.png 883836618.064.png 883836618.065.png 883836618.066.png 883836618.068.png 883836618.069.png 883836618.070.png 883836618.071.png 883836618.072.png 883836618.073.png 883836618.074.png 883836618.075.png 883836618.076.png 883836618.077.png 883836618.079.png 883836618.080.png 883836618.081.png 883836618.082.png 883836618.083.png 883836618.084.png 883836618.085.png 883836618.086.png 883836618.087.png 883836618.088.png 883836618.090.png 883836618.091.png 883836618.092.png 883836618.093.png 883836618.094.png 883836618.095.png 883836618.096.png 883836618.097.png 883836618.098.png 883836618.099.png 883836618.101.png 883836618.102.png 883836618.103.png 883836618.104.png 883836618.105.png 883836618.106.png 883836618.107.png 883836618.108.png 883836618.109.png 883836618.110.png 883836618.112.png 883836618.113.png 883836618.114.png 883836618.115.png 883836618.116.png 883836618.117.png 883836618.118.png 883836618.119.png 883836618.120.png 883836618.121.png 883836618.123.png 883836618.124.png 883836618.125.png 883836618.126.png 883836618.127.png 883836618.128.png 883836618.129.png 883836618.130.png 883836618.131.png 883836618.132.png 883836618.134.png 883836618.135.png 883836618.136.png 883836618.137.png 883836618.138.png 883836618.139.png 883836618.140.png 883836618.141.png 883836618.142.png 883836618.143.png 883836618.145.png 883836618.146.png 883836618.147.png 883836618.148.png 883836618.149.png 883836618.150.png 883836618.151.png 883836618.152.png 883836618.153.png 883836618.154.png 883836618.156.png 883836618.157.png 883836618.158.png 883836618.159.png 883836618.160.png 883836618.161.png 883836618.162.png 883836618.163.png 883836618.164.png 883836618.165.png 883836618.167.png 883836618.168.png 883836618.169.png 883836618.170.png 883836618.171.png 883836618.172.png 883836618.173.png 883836618.174.png 883836618.175.png 883836618.176.png 883836618.178.png 883836618.179.png 883836618.180.png 883836618.181.png 883836618.182.png 883836618.183.png 883836618.184.png 883836618.185.png 883836618.186.png 883836618.187.png 883836618.189.png 883836618.190.png 883836618.191.png 883836618.192.png 883836618.193.png 883836618.194.png 883836618.195.png 883836618.196.png 883836618.197.png 883836618.198.png 883836618.200.png 883836618.201.png 883836618.202.png 883836618.203.png 883836618.204.png 883836618.205.png 883836618.206.png 883836618.207.png 883836618.208.png 883836618.209.png 883836618.211.png 883836618.212.png 883836618.213.png 883836618.214.png 883836618.215.png 883836618.216.png 883836618.217.png 883836618.218.png 883836618.219.png 883836618.220.png 883836618.222.png 883836618.223.png 883836618.224.png 883836618.225.png 883836618.226.png 883836618.227.png 883836618.228.png 883836618.229.png 883836618.230.png 883836618.231.png 883836618.233.png 883836618.234.png 883836618.235.png 883836618.236.png 883836618.237.png 883836618.238.png 883836618.239.png 883836618.240.png 883836618.241.png 883836618.242.png 883836618.244.png 883836618.245.png 883836618.246.png 883836618.247.png 883836618.248.png 883836618.249.png 883836618.250.png 883836618.251.png 883836618.252.png 883836618.253.png 883836618.255.png 883836618.256.png 883836618.257.png 883836618.258.png 883836618.259.png 883836618.260.png 883836618.261.png 883836618.262.png 883836618.263.png 883836618.264.png 883836618.266.png 883836618.267.png 883836618.268.png 883836618.269.png 883836618.270.png 883836618.271.png 883836618.272.png 883836618.273.png 883836618.274.png 883836618.275.png 883836618.277.png 883836618.278.png 883836618.279.png 883836618.280.png 883836618.281.png 883836618.282.png 883836618.283.png 883836618.284.png 883836618.285.png 883836618.286.png 883836618.288.png 883836618.289.png 883836618.290.png 883836618.291.png 883836618.292.png 883836618.293.png 883836618.294.png 883836618.295.png 883836618.296.png 883836618.297.png 883836618.299.png 883836618.300.png 883836618.301.png 883836618.302.png 883836618.303.png 883836618.304.png 883836618.305.png 883836618.306.png 883836618.307.png 883836618.308.png 883836618.310.png 883836618.311.png 883836618.312.png 883836618.313.png 883836618.314.png 883836618.315.png 883836618.316.png 883836618.317.png 883836618.318.png 883836618.319.png 883836618.321.png 883836618.322.png 883836618.323.png 883836618.324.png 883836618.325.png 883836618.326.png 883836618.327.png 883836618.328.png 883836618.329.png 883836618.330.png 883836618.332.png 883836618.333.png 883836618.334.png 883836618.335.png 883836618.336.png 883836618.337.png 883836618.338.png 883836618.339.png 883836618.340.png 883836618.341.png 883836618.343.png 883836618.344.png 883836618.345.png 883836618.346.png 883836618.347.png 883836618.348.png 883836618.349.png 883836618.350.png 883836618.351.png 883836618.352.png 883836618.354.png 883836618.355.png 883836618.356.png 883836618.357.png 883836618.358.png
KURS
wać koni gurację jądra ex2_coni g do pliku
.coni g w katalogu linux-2.6.37 ( polecenie cp
ex2_coni g linux-2.6.37/.coni g ) . Następnie
należy zmienić bieżącą ścieżkę aby znaleźć
się w katalogu linux 2.6.37, a następnie wy-
wołać polecenie make oldconi g ARCH=arm ,
co spowoduje skoni gurowanie jądra według
załączonego pliku .coni g. Po skoni gurowaniu
jądra możemy przystąpić do jego kompilacji za
pomocą polecenia: make uImage ARCH=arm .
Po dłużej chwili w katalogu uImage pojawi się
gotowy plik binarny z jądrem. Tak przygoto-
wane jądro możemy wgrać do katalogu /boot
na karcie docelowej. Kolejną czynnością jest
kompilacja modułów jądra, która odbywa się
z wykorzystaniem polecenia make modules
ARCH=arm . Podobnie moduły jądra należy
wgrać na kartę docelową np. poprzez zamo-
towanie karty w katalogu /mnt , a następnie
wydanie polecenia make modules_install IN-
STALL_MOD_PATH=/mnt/
Aplikacja przestrzeni użytkownika matri-
xkbd. Aby zademonstrować użycie klawiatury
matrycowej, oraz diod LED z wykorzystaniem
podsystemów input , oraz led , napisano bardzo
prostą aplikację przestrzeni użytkownika, któ-
ra w momencie wciśnięcia klawisza, będzie za-
palała diody LED przypisane do danego klawi-
sza, oraz powodowała wyłączenie diod w mo-
mencie puszczenia klawisza. Jednocześnie na
standardowym wyjściu (konsoli) wypisywane
będą komunikaty informujące o otrzymywa-
nych zdarzeniach klawiatury typu EV_KEY .
(Kod źródłowy aplikacji znajduje się w pliku
matrixkbd.c ) Klawiatura widoczna będzie jako
plik /dev/input/event0 , natomiast diody D0..
D3 , widoczne będą jako katalogi /sys/class/ledX
(gdzie X=0-3) . Włączanie oraz wyłączanie
diod LED realizowane jest za pomocą funkcji
led_ctl ( listing   4 ).
Funkcja ta jako argument no przyjmuje
numer porządkowy diody (0–3), określająca nr
diody, natomiast jako argument value , przyj-
muje wartość oznaczająca czy ma być ona włą-
czona czy wyłączona. Jej działanie jest bardzo
proste i sprowadza się do wpisania za pomocą
funkcji write() do pliku brightness odpowied-
niej diody, wartości 0 lub 1.
Program zaczyna wykonywanie od funk-
cji main w której realizowany jest odczyt sta-
nu kodów klawiszy ( listing   5 ).
Na początku za pomocą wywołania sys-
temowego open() , jest otwierane urządzenie
/dev/input/event0 reprezentujące klawiaturę.
Następnie za pomocą funkcji ioctl() pobierana
jest nazwa klawiatury, co może być użyteczne
w przypadku gdy mamy do czynienia z więk-
szą ilością urządzeń wejściowych. (W naszym
przypadku mamy jedno urządzenie, więc po
prostu otwieramy /dev/input/event0 ), a  na-
stępnie wypisujemy nazwę jaka została przy-
pisana urządzeniu klawiatury matrycowej.
Następnie program wchodzi do pętli nieskoń-
czonej, gdzie zdarzenia od klawiatury odczy-
tywane są za pomocą wywołania systemowe-
go read() . Wywołanie to spowoduje uśpienie
procesu, do momentu wystąpienia zdarzenia,
na interfejsie event0 . W przypadku wystąpie-
nia zdarzenia tablica struktur events zostanie
wypełniona. Następnie w pętli for() odczyty-
wane są wszystkie zdarzenia. W przypadku
Listing 3. Fragmenty struktur odpowiedzialnych za informację o dołączeniu
klawiatury matrycowej oraz diod LED
static const uint32_t keymap[] =
{
KEY(0, 0, KEY_1),
KEY(0, 1, KEY_4),
KEY(0, 2, KEY_7),
KEY(0, 3, KEY_ENTER),
KEY(1, 0, KEY_2),
KEY(1, 1, KEY_5),
KEY(1, 2, KEY_8),
KEY(1, 3, KEY_0),
KEY(2, 0, KEY_3),
KEY(2, 1, KEY_6),
KEY(2, 2, KEY_9),
KEY(2, 3, KEY_ESC),
KEY(3, 0, KEY_A),
KEY(3, 1, KEY_B),
KEY(3, 2, KEY_C),
KEY(3, 3, KEY_D),
};
static const struct matrix_keymap_data keymap_data =
{
.keymap = keymap,
.keymap_size = ARRAY_SIZE(keymap)
};
static const uint32_t row_gpios[] =
{
AT91_PIN_PC0, AT91_PIN_PC1, AT91_PIN_PC2, AT91_PIN_PC3
};
//PB26 PB29 PC5 PC6
static const uint32_t col_gpios[] =
{
AT91_PIN_PB26, AT91_PIN_PB29, AT91_PIN_PC5, AT91_PIN_PC6
};
static struct matrix_keypad_platform_data keypad_confi g =
{
.keymap_data = &keymap_data,
.row_gpios = row_gpios,
.num_row_gpios = ARRAY_SIZE(row_gpios),
.col_gpios = col_gpios,
.num_col_gpios = ARRAY_SIZE(col_gpios),
.col_scan_delay_us = 10,
.debounce_ms = 10,
.active_low = 1, /* pull up realization */
.no_autorepeat = 0,
.wakeup = 1
};
static struct platform_device keypad_device =
{
.name = “matrix-keypad”,
.id = -1,
.dev =
{
.platform_data = &keypad_confi g,
},
};
static struct gpio_led leds[] =
{
{
.name = “led0”,
.gpio = AT91_PIN_PB1
},
{
.name = “led1”,
.gpio = AT91_PIN_PB2
},
{
.name = “led2”,
.gpio = AT91_PIN_PB6
},
{
.name = “led3”,
.gpio = AT91_PIN_PB7
}
};
Listing 4. Funkcja led_ctl
//Led enable disable
static void led_ctl( int no, bool value )
{
char name_buf[128];
//Create led by name
snprintf(name_buf,sizeof(name_buf),”/sys/class/leds/led%i/brightness”,no);
int led_fd = open(name_buf, O_WRONLY); //Open the led fi le
error( led_fd );
int led_wr = write( led_fd, value?”1”:”0”,1); //Write the led value
error( led_wr );
close( led_fd ); //Close the led handle
}
98
ELEKTRONIKA PRAKTYCZNA 5/2011
883836618.359.png 883836618.360.png
Wprowadzenie do Linux’a embedded
Listing 5. Odczyt stanu kodów klawiszy
//Main loop
int main( void )
{
//Input event device0
int input_fd = open(“/dev/input/event0”,O_RDONLY);
error(input_fd);
//Get device name
{
char buf[128];
int ioctl_ret = ioctl(input_fd,EVIOCGNAME(sizeof(buf)),buf);
error(ioctl_ret);
printf(“Input device name: %s\n”,buf);
}
//Handle input events
struct input_event event[MAX_KEY_MSGS];
for(;;)
{
int input_rd = read(input_fd,event,sizeof(event));
error(input_rd);
for ( size_t i=0; i< input_rd/sizeof ( struct input_event);i++)
if( event[i].type == EV_KEY ) //Interested only with key event
on_key(&event[i]);
}
close( input_fd );
return 0;
}
Listing 7. Przykładowe komunikaty
wyświetlane przez konsolę Linux
root@bf210-at91:~# matrixkbd
Input device name: matrix-keypad
Got key scancode 10 value PRESSED
Got key scancode 10 value RELEASED
Got key scancode 10 value PRESSED
Got key scancode 10 value RELEASED
Got key scancode 48 value PRESSED
Got key scancode 48 value RELEASED
Got key scancode 30 value PRESSED
Got key scancode 30 value RELEASED
Got key scancode 4 value PRESSED
Got key scancode 4 value RELEASED
Got key scancode 3 value PRESSED
Got key scancode 3 value RELEASED
Got key scancode 9 value PRESSED
Got key scancode 9 value RELEASED
Got key scancode 48 value PRESSED
Got key scancode 48 value REPEAT
Got key scancode 48 value REPEAT
Got key scancode 48 value REPEAT
Got key scancode 48 value REPEAT
Got key scancode 48 value REPEAT
Got key scancode 48 value RELEASED
systemem Linux, oraz jądrem dostosowanym
do potrzeb bieżącego odcinka jest dostarcza-
ny w  postaci pliku obrazu example2.img.
Przykład można nagrać na czystą kartę SD,
w sposób analogiczny jak opisano w poprzed-
nim artykule, a następnie tak nagraną kartę
umieścić w złączu BF210 i włączyć napięcie
zasilające. Po uruchomieniu linuksa należy
zalogować się do konsoli jako root, a następ-
nie uruchomić program wpisując polecenie
matrixkbd . Teraz wciskając i zwalniając kla-
wisze klawiatury matrycowej, będziemy mo-
gli obserwować zapalanie odpowiednich diod
LED w minimodule KAMODLED8 , oraz ob-
serwować komunikaty w konsoli Linux’owej,
na której jest uruchomiony program. Przykła-
dowy fragment komunikatów umieszczono
na listingu   7 .
W komunikatach aplikacji możemy zo-
baczyć początkową nazwę urządzenia wej-
ściowego, które zostało ustalone w strukturze
platform-data, następnie widzimy informację
o kolejnych wciśnięciach i zwolnieniach kla-
wisza, oraz w przypadku trzymania klawisza
możemy obserwować ciągłe komunikaty, ge-
nerowane przez mechanizm auto powtarza-
nia.
Listing 6. Funkcja on_key obsługująca zdarzenie naciśnięcia klawisza
//Handle input event
static void on_key(const struct input_event *ev)
{
printf( “Got key scancode %d value %s\n”,ev->code, ch_keyval(ev->value) );
if ( ev->value == KEYV_PRESS) //MAP keyboyard scancodes to key
switch ( ev-> code)
{
case KEY_1: led_bitmask(1); break ;
case KEY_2: led_bitmask(2); break ;
case KEY_3: led_bitmask(3); break ;
case KEY_4: led_bitmask(4); break ;
case KEY_5: led_bitmask(5); break ;
case KEY_6: led_bitmask(6); break ;
case KEY_7: led_bitmask(7); break ;
case KEY_8: led_bitmask(8); break ;
case KEY_9: led_bitmask(9); break ;
case KEY_0: led_bitmask(10); break ;
case KEY_A: led_bitmask(11); break ;
case KEY_B: led_bitmask(12); break ;
case KEY_C: led_bitmask(13); break ;
case KEY_D: led_bitmask(14); break ;
case KEY_ENTER: led_bitmask(15); break ;
default : led_bitmask(0); break ;
}
else if ( ev->value == KEYV_RELEASE) led_bitmask(0);
}
otrzymania zdarzenia typu EV_KEY , wywo-
ływana jest funkcja on_key() , która jako argu-
ment przyjmuje wskaźnik na strukturę input_
event reprezentującą zdarzenie ( listing   6 ).
Funkcja ta na początku wypisuje kod wci-
śniętego klawisza, oraz jego stan (wciśnięty,
zwolniony, autopotarzanie). W  przypadku
gdy mamy do czynienia z wciśnięciem kla-
wisza, w zależności od numeru klawisza wy-
woływana jest funkcja led_bitmask() , która
powoduje włączenie odpowiednich diod LED
przypisanych do danego klawisza. W przy-
padku, wystąpienia zdarzenia od zwolnienia
klawisza, wywoływana jest funkcja led_bit-
mask(0) , co powoduje wyłączenie wszystkich
diod LED.
Uruchomienie przykładu na BF210.
Skompilowany przykład, wraz z kompletnym
Lucjan Bryndza, EP
lucjan.bryndza@ep.com.pl
REKLAMA
99
ELEKTRONIKA PRAKTYCZNA 5/2011
883836618.361.png 883836618.362.png 883836618.363.png 883836618.365.png 883836618.366.png 883836618.367.png 883836618.368.png 883836618.369.png 883836618.370.png 883836618.371.png 883836618.372.png 883836618.373.png 883836618.374.png 883836618.376.png 883836618.377.png 883836618.378.png 883836618.379.png 883836618.380.png 883836618.381.png 883836618.382.png 883836618.383.png 883836618.384.png 883836618.385.png 883836618.387.png 883836618.388.png 883836618.389.png 883836618.390.png 883836618.391.png 883836618.392.png 883836618.393.png 883836618.394.png 883836618.395.png 883836618.396.png 883836618.398.png 883836618.399.png 883836618.400.png 883836618.401.png 883836618.402.png 883836618.403.png 883836618.404.png 883836618.405.png 883836618.406.png 883836618.407.png 883836618.409.png 883836618.410.png 883836618.411.png 883836618.412.png 883836618.413.png
 
Zgłoś jeśli naruszono regulamin