Pierwsze kroki z Raspberry Pi: jak dodać RTC?
Po wyświetleniu pseudo-graficznego interfejsu menuconfig z pośród dostępnych opcji wybieramy:
Device Drivers ---> <*> I2C support
dzięki czemu nie musimy ładować modułu i2c-dev przy starcie systemu, oraz:
Device Drivers ---> <*> Real Time Clock ---> [*] Set system time from RTC on startup and resume [*] /sys/class/rtc/rtcN (sysfs) [*] /proc/driver/rtc (procfs for rtcN) [*] /dev/rtcN (character devices) <*> Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025
co zwalnia nas z potrzeby ładowania modułu rtc-ds1307 oraz zapewnia automatyczną synchornizację czasu systemowego z czasem zegara RTC przy starcie systemu.
Rys. 1. Interfejs menuconfig
Jeżeli preferujemy tekstową edycję pliku .config, spośród wszystkich dostępnych opcji ustawiamy sześć poniższych wpisów:
CONFIG_I2C_BCM2708=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_COMPAT=y CONFIG_I2C_CHARDEV=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y
Tym samym mamy już za sobą część konfiguracji będącą odpowiednikiem dodania wpisów w pliku /etc/modules realizujących automatyczne ładowanie modułów. Teraz przyszedł czas na poinformowanie systemu o dołączonych urządzeniach i ich adresach programowych. Tak więc po zapisaniu wprowadzonych zmian i zakończeniu pracy z narzędziem menuconfig ostatnim etapem jest deklaracja odpowiednich struktur (i2c_board_info) w pliku ../arch/arm/mach-bcm2708/bcm2708.c.
W edytowanym pliku dołączamy dyrektywę:
static struct i2c_board_info __initdata bcm2708_i2c_devices[] = { { I2C_BOARD_INFO("rtc-ds1307", 0x68), .type = "ds1307", }, };
oraz w kodzie funkcji void __init bcm2708_init(void):
i2c_register_board_info(1,bcm2708_i2c_devices,ARRAY_SIZE(bcm2708_i2c_devices));
Po zapisaniu zmian możemy przystąpić do właściwej kompilacji jądra systemu (w 64-bitowych systemach hosta, proces kompilacji może wymagać doinstalowania pakietów 32-bitowych: glibc.i686 oraz zlib.i686):
make -j16 ARCH=arm CROSS_COMPILE=${CCPREFIX}
oraz kompilacji i instalacji modułów:
make -j16 ARCH=arm CROSS_COMPILE=${CCPREFIX} modules mkdir modules_temp make -j16 ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=./modules_temp \ modules_install
Po zakończeniu kompilacji, pliki wynikowe tego procesu kopiujemy na kartę SD z systemem Raspbian:
- plik ../linux/arch/arm/boot/Image jako kernel.img na partycję /boot,
- moduły systemu oraz firmware w postaci binarnej na partycję /rootfs:
- su -c 'cp -R ../linux/modules_temp/lib/modules/3.10.32+/ /rootfs’
- su -c 'cp -R ../linux/modules_temp/lib/firmware/ /rootfs’
Po umieszczeniu karty w czytniku SD Raspberry Pi i załadowaniu systemu sprawdzamy, czy zostało załadowane odpowiednie jądro systemu (zwracając szczególną uwagę na datę kompilacji):
pi@raspberrypi ~ $ uname -a Linux raspberrypi 3.10.32+ #1 PREEMPT Sat Mar 1 14:28:24 CET 2014 armv6l GNU/Linux
Po ponownym uruchomieniu Raspberry Pi, w systemie plików powinno zarejestrować się również 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
W przypadku problemów warto przeanalizować komunikaty występujące przy starcie systemu, np. w przypadku nieprawidłowo wykonanych połączeń sprzętowych:
pi@raspberrypi ~ $ dmesg | grep rtc [ 1.943717] rtc-ds1307: probe of 0-0068 failed with error -5 [ 2.275312] drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
oraz
pi@raspberrypi ~ $ hwclock --debug hwclock from util-linux 2.20.1 hwclock: Open of /dev/rtc failed: No such file or directory No usable clock interface found. hwclock: Cannot access the Hardware Clock via any known method.
Jeżeli nie popełniliśmy żadnych błędów zarówno na etapie połączeń sprzętowych jak i konfiguracji jądra, poniższe polecenie powinno zwrócić nam aktualnie zapisany czas zegara DS1307 (który niekoniecznie będzie już odpowiadać wartości rzeczywistej):
pi@raspberrypi ~ $ sudo hwclock -r Sun 09 Mar 2014 21:00:00 UTC -0.049805 seconds