Pierwsze kroki z Raspberry Pi: jak dodać RTC?
5) Opcja I – konfiguracja programowa w obszarze przestrzeni użytkownika
Jedną z zalet dystrybucji Raspbian jest dostarczenie użytkownikowi niewielkiego jądra systemu wraz z możliwością dynamicznego załadowania dużej liczby, uprzednio przekompilowanych i dostępnych w systemie modułów jądra. Takie rozwiązanie jest szczególnie wygodne gdy finalna konfiguracja sprzętowa urządzenia nie została jeszcze ustalona (np. testujemy kilka różnych typów urządzeń peryferyjnych) lub wszystkie wykonywane przez nas połączenia sprzętowe mają wyłącznie charakter dydaktyczny (a długotrwała kompilacja jądra systemu jest poza obszarem naszych zainteresowań). Jak więc załadować wszystkie niezbędne moduły do obsługi zegara DS1307?
Edycję rozpoczynamy od pliku /etc/modules, zawierającego listę modułów jądra, które powinny zostać załadowne przy starcie systemu. Do istniejącej listy dodajemy wpisy i2c-dev, i2c-bcm2708 oraz
rtc-ds1307, który pełni rolę właściwego sterownika naszego zegara. Wyedytowany plik będzie zatem wyglądał następująco:
# /etc/modules: kernel modules to load at boot time. # # This file contains the names of kernel modules that should be loaded # at boot time, one per line. Lines beginning with "#" are ignored. # Parameters can be specified after the module name. snd-bcm2835 i2c-dev i2c-bcm2708 rtc-ds1307
Ponieważ magistrala I2C nie posiada żadnego wbudowanego mechanizmu automatycznej detekcji podłączonych do niej urządzeń, informację o typie podłączonego urządzenia oraz jego adresie programowym musimy przekazać samodzilenie:
-
- dla Raspberry Pi (rev.1) układ DS1307 został dołączony do interfejsu i2c-0:
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device
-
- dla Raspberry Pi (rev.2) układ DS1307 został dołączony do interfejsu i2c-1:
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
Ponieważ każdorazowe informowanie systemu o dołączonym zegarze RTC byłoby dość uciążliwe, warto umieścić powyższy wpis w skrypcie /etc/rc.local, np. tuż przed ostanię linią exit 0.
Po ponownym uruchomieniu Raspberry Pi, w systemie plików powinno zarejestrować się nowe urządzenie /dev/rtc0 reprezentującje podłączony zegar DS1307:
pi@raspberrypi ~ $ ls -l /dev | grep rtc crw------- 1 root root 254, 0 Mar 10 20:03 rtc0
Powyższy wpis jest dla nas informacją, że edycja plików konfiguracyjnych, załadowanie modułów oraz detekcja układu DS1307 przebiegła pomyślnie. Tym samym, minimalnym nakładem pracy skonfigurowaliśmy do pracy sprzętowy zegar RTC. Krótki opis jak wykorzystać jego możliwości (odczytać czas sprzętowy, zaktualizować czas systemowy na podstawie czasu RTC) przedstawiono w podrozdziale 7.
6) Opcja II – konfiguracja na poziomie jądra systemu Linux
W wielu przypadkach projektowych, ładowanie modułów jądra przy starcie systemu nie jest rozwiązaniem optymalnym (zwłaszcza jeżeli konfiguracja sprzętowa nie ulega już zmianie). W tym podrozdziale przedstawiony zostanie opis konfiguracji systemu z włączoną obsługą wszystkich niezbędnych komponentów już na etapie kompilacji jądra. Takie rozwiązanie jest znacznie stabilniejsze i wygodniejsze w utrzymaniu (nie ma obawy o nadpisanie plików konfiguracyjnych w przestrzeni użytkownika), jednak wymaga zarazem, na pierwszym etapie prac, wykonania kilku dość czasochłonnym zadań.
Przygotowanie systemu rozpoczynamy od pobrania kodu źródłowego systemu Linux. W obecnej chwili, sugerowany przez producentów system operacyjny Raspbian, korzysta z jądra systemu w wersji 3.10, o czym możemy się przekonać wydając w terminalu Raspberry Pi polecenie:
pi@raspberrypi ~ $ uname -a Linux raspberrypi 3.10.32+ #4 PREEMPT Wed Mar 5 22:07:08 CET 2014 armv6l GNU/Linux
Najmniej problematycznym rozwiązaniem jest pobranie źródeł jądra w tej samej wersji. W tym celu z repozytorium https://github.com/raspberrypi/linux.git pobieramy odpowiednią gałąź projektu:
git clone https://github.com/raspberrypi/linux.git -b rpi-3.10.y
Źródła jądra systemu Linux można pobrać i przekompilować zarówno bezpośrednio na urządzeniu Raspberry Pi jak i na dowolnej Linux’owej stacji roboczej – jednak ze względu na bardzo długi czas kompilacji (zapewne powyżej jednej doby) mocno sugerowaną opcją jest kompilacja skrośna (tzw. cross-kompilacja) na komputerze stacjonarnym. Decydując się na kompilację skrośną musimy wyposażyć nasz komputer w odpowiedni dla architektury docelowej kompilator. W tym celu pobieramy dedykowany dla Raspberry Pi zestaw narzędzi:
git clone git://github.com/raspberrypi/tools.git
Spośród kilku dostępnych kompilatorów, w nowoutworzonym katalogu tools wybieramy arm-bcm2708hardfp-linux-gnueabi, poprzez eksport zmiennej systemowej $CCPREFIX:
export CCPREFIX=/../tools/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi-
Po wyeksportowaniu zmiennej wskazującej na wykorzystywany przez nas kompilator, możemy przystąpić do właściwej konfiguracji i kompilacji jądra systemu. Jeżli dotychczas nie dokonywaliśmy ręcznej konfiguracji i kompilacji jądra (korzystaliśmy z konfiguracji domyślnej), po przejściu do katalogu ze źródłami, możemy załadować domyślny plik konfiguracyjny .config:
cd ../linux cp arch/arm/configs/bcmrpi_defconfig .config
W przypadku gdy nie jest to nasza pierwsza kompilacja jądra i chcemy ponownie wykorzystać konfigurację aktualnie uruchomionego systemu, wówczas możemy ją odczytać na urządzeniu Raspberry Pi poleceniem (nowoutworzony plik .config należy wówczas przekopiować do głównego katalogu z kodem źródłowym jądra):
zcat /proc/config.gz > .config
Posiadając wstępnie przygotowany plik .config możemy przystąpić do właściwej konfiguracji jądra systemu. Najwygodniejszym rozwiązaniem jest narzędzie make menuconfig (jego użycie wymaga zainstalowania w systemie hosta pakietu ncurses-devel):
make ARCH=arm CROSS_COMPILE=${CCPREFIX} menuconfig
W przypadku, gdy kompilację wykonujemy bezpośrednio na zestawie Raspberry Pi, we wszystkich komendach związanych z kompilacją i konfiguracją pomijamy ustawianie zmiennej systemowej $CCPREFIX.