はじめに
本記事では、EPSON製の高精度RTCモジュールRX8900SAというデバイスを使用して、時刻を保持する方法について記載します。接続には、I2Cバスインターフェスを使用します。
Raspberry Piには、RTC(Real Time Clock)呼ばれるハードウェア・クロックが搭載されていないため、電源をOFFにすると時計が止まります。次に電源をONにした時は、前回電源をOFFにした時刻から時計が再開されます。インターネットに接続されている環境では、電源をONにしたときにインターネット上に存在する NTP(Network Time Protocol)サーバと呼ばれる現在時刻を配信しているサーバと時刻合わせが行われるため、時刻がずれることはありません。しかし、インターネットに接続されていない環境では、電源をONにしたときにNTPサーバと時刻同期ができないため、時刻がずれてしまいます。このため、インターネットに接続できない環境で正確な時刻を保持するには、RTC(Real Time Clock)と呼ばれるモジュールが必要になります。
RTC モジュールは、バッテリーでバックアップされており、電源をOFFにした状態でも内部で時刻を保持する機能をもっているため、NTPサーバと時刻同期ができない環境でも正確な時刻を保持できるようになります。
環境
- ボード
Raspberry Pi 4 Model B - OS
Raspberry Pi OS with desktop and recommended software
Release date: October 10th 2023
System: 64-bit
Kernel version: 6.1
Debian version: 12 (bookworm)
EPSON RX8900SAについて
RX8900SAは、 I2Cバスインターフェイスを使用したリアルタイムクロックモジュールで、温度補償発振器(DTCXO)搭載し、⾼精度かつ電源切替回路搭載したモジュールです。
以下に機能概要について記載します。
- 32.768 kHz高精度温度補償発振器(DTCXO)を搭載
- インターフェイス方式:I2C-Bus(Fast-Mode 400 kHz)
- 高精度:±5.0 * 10-6 / -40℃~+85℃(月差 ± 13秒相当)
- 電源切替機能:VDD 電圧を監視しバックアップ電源に切替
バックアップ電源切替電圧:1.9V Min. - クロック出力機能
出力周波数選択可能(32.768 kHz、1024 Hz、1 Hz) - ウェイクアップタイマー機能
ソースクロック(1/60 Hz、1 Hz、64 Hz、4096 Hz)から選択して 244 μs から 2.8 ⽇までのタイマー時間が設定可能(12 bit × 1 ch)。
タイマー完了時に /INT 端⼦から割り込み出⼒後オートリリース。
この動作は指定された周期でオートリピートされるので、ウォッチドッグタイマーのような使い⽅も可能 - アラーム機能
曜~分をプログラム可能 - インターフェイス電圧範囲:2.5 V ~ 5.5 V
- 温度補償動作電圧範囲:2.0 V ~5.5 V
- 計時(保持)電圧範囲:1.6 V ~5.5 V
詳細は、EPSONの製品情報サイトをご参照ください。
ここでは、以下のRX8900搭載高精度RTCモジュール基板を使用します。
Raspberry Pi OSのアップデート
はじめに、以下のコマンドを実行しRaspberry Pi OSを最新の状態にアップデートします。
pi@raspberrypi:~ $ sudo apt update
pi@raspberrypi:~ $ sudo apt upgrade
pi@raspberrypi:~ $
アップデートが終了したら、以下のコマンドを実行し、必ず再起動を行って下さい。
pi@raspberrypi:~ $ sudo reboot
アップデートを行ったときに、カーネルバージョンがアップデートされることがあります。
カーネルバージョンがアップデートされている場合に再起動を行わずカーネルヘッダーのソースコードをインストールすると、カーネルバージョンとカーネルヘッダーのバージョンが一致しなくなり、ドライバモジュールのビルドに失敗する場合があるためです。
再起動後のOSバージョン
pi@raspberrypi:~ $ uname -a
Linux raspberrypi 6.1.0-rpi4-rpi-v8 #1 SMP PREEMPT Debian 1:6.1.54-1+rpt2 (2023-10-05) aarch64 GNU/Linux
pi@raspberrypi:~ $
I2Cバスインターフェイスの有効化
RX8900SAは、I2Cバスインターフェイスで接続して使用します。Raspberry Pi OSのインストール後の初期状態では、I2Cバスインターフェイスが無効化されているため有効化する必要があります。
I2Cバスインターフェイスを有効化する方法には、「raspi-config」コマンドを使用して有効化する方法と「/boot/config.txt」を直接編集して有効化する方法があります。ここでは、「raspi-config」コマンドを使用して有効化します。
コンフィグレーションツールを起動します。
pi@raspberrypi:~ $ sudo raspi-config
「3 Interfacing Options」を選択した後、「<Select>」を選択します。
「I4 I2C」を選択した後、「<Select>」を選択します。
「<Yes>」を選択します。
「<Ok>」を選択します。
「<Finish>」を選択し、終了します。
I2Cバスインターフェイスを有効化するため、再起動を行います。
pi@raspberrypi:~ $ sudo reboot
I2Cバスインターフェイスの有効化確認
I2Cバスインターフェイスが有効化されていることを確認します。
以下のコマンドを実行し、「i2c_bcm2835」モジュールがロードされていることを確認します。
pi@raspberrypi:~ $ lsmod | grep i2c
i2c_bcm2835 20480 0
i2c_dev 20480 0
i2c_brcmstb 16384 0
pi@raspberrypi:~ $
以下のコマンドを実行し、/dev ディレクトリにI2Cのデバイスファイル「i2c-1」が作成されていることを確認します。
pi@raspberrypi:~ $ ls -l /dev | grep i2c
crw-rw---- 1 root i2c 89, 1 Nov 27 12:43 i2c-1
crw-rw---- 1 root i2c 89, 20 Nov 27 12:42 i2c-20
crw-rw---- 1 root i2c 89, 21 Nov 27 12:42 i2c-21
pi@raspberrypi:~ $
i2c-toolsの準備
以下のコマンドを実行し、「i2c-tools」パッケージをインストールします。
「i2c-tools」パッケージには、コマンドラインからI2Cバスインターフェイスを使用して、I2Cデバイスへアクセスするための様々なコマンドが含まれています。
pi@raspberrypi:~ $ sudo apt install i2c-tools
pi@raspberrypi:~ $
RX8900SA RTCモジュールとの接続
Raspberry PiのGPIOピンとRX8900SA RTCモジュールの端子を接続します。
Raspberry Pi GPIO ピン | RX8900SA RTC モジュールピン |
---|---|
1番ピン:3V3 power | VDD ピン |
3番ピン:GPIO 2 (SDA) | SDA ピン |
5番ピン:GPIO 3 (SCL) | SCL ピン |
9番ピン:Ground | GND ピン |
接続確認
Raspberry PiとRX8900SA RTCモジュールを接続した後、以下のようにコマンドを実行します。
pi@raspberrypi:~ $ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- 32 -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
pi@raspberrypi:~ $
「32」と表示されていれば、正しく接続され認識されています。
「32(0x32)」は、RX8900SA RTCモジュールに予め割り当てれているI2C デバイスのアドレスです。
RX8900ドライバモジュールの作成
RX8900 RTCモジュールを使用するためには、ドライバモジュールが必要なります。しかし、Raspberry Piのインストール後の初期状態では、RX8900 RTCモジュールのドライバモジュールがインストールされていません。このため、別途、RX8900 RTCモジュールのドライバモジュールのビルドする必要があります。
ビルド環境の準備
カーネルモジュールなどをコンパイルしビルドするためには、Linux カーネル ヘッダーが必要になります。
Raspberry Pi OSをインストールした後の初期状態で、gccやgcc++、make等のビルドに必要なツールは既にインストールされています。しかし、ドライバモジュールをビルドするためには、現在使用しているカーネル バージョンと同じバージョンのカーネル ヘッダーのソースコードが必要になります。
以下のコマンドを実行し、現在使用しているカーネルのバージョンを確認します。
pi@raspberrypi:~ $ uname -r
6.1.0-rpi6-rpi-v8
pi@raspberrypi:~ $
最新のカーネル バージョンがリポジトリに反映されるまで、数週間かかる場合があります。このため、カーネルのクローンを作成し、カーネル ヘッダーを取得します。
Git とビルドに必要なツールをインストールします。
pi@raspberrypi:~ $ sudo apt install git bc bison flex libssl-dev make
次にカーネル ソースを取得します。これには少し時間がかかります。
pi@raspberrypi:~ $ git clone --depth=1 https://github.com/raspberrypi/linux
カーネル ヘッダーのソースコードは、「/usr/src/linux-headers-<カーネル バージョン>」にインストールされます。(例えば、カーネル バージョンが「6.1.0-rpi4-rpi-v8」の場合は、「/usr/src/linux-headers-6.1.0-rpi4-rpi-v8」にインストールされます。)
pi@raspberrypi:~ $ ls -l /usr/src/
total 32
drwxr-xr-x 4 root root 4096 Oct 10 12:38 linux-headers-6.1.0-rpi4-common-rpi
drwxr-xr-x 4 root root 4096 Oct 10 12:38 linux-headers-6.1.0-rpi4-rpi-2712
drwxr-xr-x 4 root root 4096 Oct 10 12:38 linux-headers-6.1.0-rpi4-rpi-v8
drwxr-xr-x 4 root root 4096 Nov 27 23:18 linux-headers-6.1.0-rpi6-common-rpi
drwxr-xr-x 4 root root 4096 Nov 27 23:19 linux-headers-6.1.0-rpi6-rpi-2712
drwxr-xr-x 4 root root 4096 Nov 27 23:19 linux-headers-6.1.0-rpi6-rpi-v8
lrwxrwxrwx 1 root root 23 Oct 5 20:33 linux-kbuild-6.1 -> ../lib/linux-kbuild-6.1
drwxr-xr-x 4 root root 4096 Oct 10 12:47 python3.11
drwxr-xr-x 3 root root 4096 Oct 10 12:47 sense-hat
pi@raspberrypi:~ $
以下のように、カーネルヘッダーのソースコードをインストールすると「/lib/modules/<カーネル バージョン>/build」ディレクトリが作成されます。このディレクトリは、「/usr/src/linux-headers-<カーネル バージョン>」へのシンボリックリンク」になっています。
(※カーネルヘッダーのソースコードのインストール前は、「/lib/modules/<カーネルバージョン>/build」のシンボリックリンクは存在しません。)
【カーネルヘッダーのインストール後】
pi@raspberrypi:~ $ ls -l /lib/modules/
total 16
drwxr-xr-x 3 root root 4096 Oct 10 12:38 6.1.0-rpi4-rpi-2712
drwxr-xr-x 3 root root 4096 Oct 10 12:38 6.1.0-rpi4-rpi-v8
drwxr-xr-x 3 root root 4096 Nov 27 23:30 6.1.0-rpi6-rpi-2712
drwxr-xr-x 3 root root 4096 Nov 27 23:26 6.1.0-rpi6-rpi-v8
pi@raspberrypi:~ $
pi@raspberrypi:~ $ ls -l /lib/modules/6.1.0-rpi6-rpi-v8
total 2668
lrwxrwxrwx 1 root root 40 Oct 27 23:31 build -> /usr/src/linux-headers-6.1.0-rpi6-rpi-v8
drwxr-xr-x 11 root root 4096 Nov 27 23:20 kernel
-rw-r--r-- 1 root root 627457 Nov 27 23:26 modules.alias
-rw-r--r-- 1 root root 654686 Nov 27 23:26 modules.alias.bin
-rw-r--r-- 1 root root 16768 Oct 27 23:31 modules.builtin
-rw-r--r-- 1 root root 7658 Nov 27 23:26 modules.builtin.alias.bin
-rw-r--r-- 1 root root 18916 Nov 27 23:26 modules.builtin.bin
-rw-r--r-- 1 root root 95292 Oct 27 23:31 modules.builtin.modinfo
-rw-r--r-- 1 root root 237758 Nov 27 23:26 modules.dep
-rw-r--r-- 1 root root 318860 Nov 27 23:26 modules.dep.bin
-rw-r--r-- 1 root root 384 Nov 27 23:26 modules.devname
-rw-r--r-- 1 root root 70334 Oct 27 23:31 modules.order
-rw-r--r-- 1 root root 949 Nov 27 23:26 modules.softdep
-rw-r--r-- 1 root root 293240 Nov 27 23:26 modules.symbols
-rw-r--r-- 1 root root 356141 Nov 27 23:26 modules.symbols.bin
lrwxrwxrwx 1 root root 44 Oct 27 23:31 source -> /usr/src/linux-headers-6.1.0-rpi6-common-rpi
pi@raspberrypi:~ $
※カーネルヘッダーをインストールするとシンボリックリンク「build」が作成される。
ドライバモジュールの取得
次に、ドライバモジュールのソースコードを取得します。
EPSONのリアルタイムクロックモジュール用 Linux Driver ダウンロードページで、RX8900ドライバモジュール(rx8900_k3.8-v1.0.zip、2014/2/27)をダウンロードすることができますが、このドライバは古くビルドできませんでした。このため、RX8900と互換性のあるrv8803のドライバモジュールを使用します。
以下のコマンドを実行し、rv8803のドライバモジュールのソースコードをダウンロードします。
ここでは、「~/rv8803」ディレクトリにダウンロードします。このディレクトリをドライバモジュールをビルドする際の作業用ディレクトリとして使用します。
pi@raspberrypi:~ $ mkdir rv8803
pi@raspberrypi:~ $ cd rv8803/
pi@raspberrypi:~/rv8803 $ wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-6.1.y/drivers/rtc/rtc-rv8803.c
--2023-11-28 00:25:36-- https://raw.githubusercontent.com/raspberrypi/linux/rpi-6.1.y/drivers/rtc/rtc-rv8803.c
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.111.133, 185.199.108.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 16930 (17K) [text/plain]
Saving to: ‘rtc-rv8803.c’
rtc-rv8803.c 100%[====================================================>] 16.53K --.-KB/s in 0.01s
2023-11-28 00:25:37 (1.25 MB/s) - ‘rtc-rv8803.c’ saved [16930/16930]
pi@raspberrypi:~/rv8803 $
ドライバモジュールのビルド
ダウンロードしたrv8803ドライバモジュールのソースコードをビルドするため、以下のようにMakefileを作成します。
(※ファイル名は、必ず「Makefile」というファイル名にする必要があります。)
pi@raspberrypi:~/rv8803 $ vi Makefile
【Makefileへの記載内容】
KERNEL_HEADERS=/lib/modules/$(shell uname -r)/build
obj-m := rtc-rv8803.o
all:
$(MAKE) -C $(KERNEL_HEADERS) M=$(shell pwd) modules
clean:
$(MAKE) -C $(KERNEL_HEADERS) M=$(shell pwd) clean
pi@raspberrypi:~/rv8803 $
※上記のソースコードの$(MAKE)~の前のインデントは、TABに置き換えてください。Makefileのインデントは、TABでなければエラーになりますので注意してください。
上手くいかない場合は以下のリンクをクリックし、Makefileをダウンロードしてご使用ください。
Makefileのダウンロード
以下のコマンドを実行し、ドライバモジュールのソースコードをビルドします。
pi@raspberrypi:~/rv8803 $ make
make -C /lib/modules/6.1.0-rpi6-rpi-v8/build M=/home/pi/rv8803 modules
make[1]: Entering directory '/usr/src/linux-headers-6.1.0-rpi6-rpi-v8'
CC [M] /home/pi/rv8803/rtc-rv8803.o
MODPOST /home/pi/rv8803/Module.symvers
CC [M] /home/pi/rv8803/rtc-rv8803.mod.o
LD [M] /home/pi/rv8803/rtc-rv8803.ko
make[1]: Leaving directory '/usr/src/linux-headers-6.1.0-rpi6-rpi-v8'
pi@raspberrypi:~/rv8803 $
ビルドが正常に終了すると、以下のように「rtc-rv8803.ko」というファイルが作成されます。このファイルがドライバモジュールです。
ドライバモジュールのビルドが上手くいかない場合は、以下のリンクからドライバモジュールをダウンロードしてご使用ください。(カーネルバージョン:6.1.0-rpi6-rpi-v8版)
「rtc-rv8803.ko」ドライバモジュールのダウンロード
pi@raspberrypi:~/rv8803 $ ls -l
total 92
-rw-r--r-- 1 pi pi 195 Nov 28 00:22 Makefile
-rw-r--r-- 1 pi pi 30 Nov 28 00:26 modules.order
-rw-r--r-- 1 pi pi 0 Nov 28 00:26 Module.symvers
-rw-r--r-- 1 pi pi 16930 Nov 28 00:25 rtc-rv8803.c
-rw-r--r-- 1 pi pi 24912 Nov 28 00:26 rtc-rv8803.ko
-rw-r--r-- 1 pi pi 29 Nov 28 00:26 rtc-rv8803.mod
-rw-r--r-- 1 pi pi 2219 Nov 28 00:26 rtc-rv8803.mod.c
-rw-r--r-- 1 pi pi 5768 Nov 28 00:26 rtc-rv8803.mod.o
-rw-r--r-- 1 pi pi 19896 Nov 28 00:26 rtc-rv8803.o
pi@raspberrypi:~/rv8803 $
ドライバモジュールの登録
以下のコマンドを実行し、作成された「rtc-rv8803.ko」ドライバモジュールを「/lib/modules/<カーネルバージョン>/」ディレクトリにコピーします。
コピー先のディレクトリは、使用しているカーネルのバージョンによってことなりますので、注意してください。
pi@raspberrypi:~/rv8803 $ sudo cp rtc-rv8803.ko /lib/modules/6.1.0-rpi6-rpi-v8/
pi@raspberrypi:~/rv8803 $
以下のコマンドを実行し、カーネルモジュールの依存関係リスト(/lib/modules/<カーネルバージョン>/modules.dep)を更新し、作成した「rtc-rv8803.ko」ドライバモジュールを「modprobe」コマンドでロードできるようにします。
pi@raspberrypi:~/rv8803 $ cd /lib/modules/6.1.0-rpi6-rpi-v8/
pi@raspberrypi:/lib/modules/6.1.0-rpi6-rpi-v8 $ sudo depmod
pi@raspberrypi:/lib/modules/6.1.0-rpi6-rpi-v8 $
「modules.dep」ファイルに「rtc-rv8803.ko」が登録されていることを確認します。
pi@raspberrypi:/lib/modules/6.1.0-rpi6-rpi-v8 $ cat modules.dep | grep rv8803
rtc-rv8803.ko:
pi@raspberrypi:/lib/modules/6.1.0-rpi6-rpi-v8 $
RX8900 RTCモジュールの動作確認
「modules.dep」に「rtc-rv8803.ko」ドライバモジュール が登録されると、「modprobe」コマンドを使用してドライバモジュールをロードできるようになります。
以下のコマンドを実行し、ドライバモジュールをロードします。
pi@raspberrypi:~ $ sudo modprobe rtc-rv8803
pi@raspberrypi:~ $
以下のコマンドを実行し、rv8803ドライバモジュールをRX8900 RTCモジュールのドライバとして登録します。rv8803ドライバモジュールは、rv8803またはrx8900というIDで利用できます。
pi@raspberrypi:~ $ sudo sh -c 'echo rx8900 0x32 > /sys/class/i2c-adapter/i2c-1/new_device'
pi@raspberrypi:~ $
または
pi@raspberrypi:~ $ sudo sh -c 'echo rv8803 0x32 > /sys/class/i2c-adapter/i2c-1/new_device'
pi@raspberrypi:~ $
以下のコマンドを実行し、I2Cバスインターフェイスに接続されたRX8900 RTCモジュールにドライバが適用され、「UU」と表示されていることを確認します。
(※「UU」は、ドライバモジュールが適用されていることを示しています。)
pi@raspberrypi:~ $ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- UU -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
pi@raspberrypi:~ $
OSのシステム時刻を合わせた後、以下のコマンドを実行し、OSのシステム時刻をRX8900 RTCモジュールに設定します。
pi@raspberrypi:~ $ sudo hwclock -w
pi@raspberrypi:~ $
以下のコマンドを実行し、OSのシステム時刻とRX8900 RTCモジュールの時刻が合っていることを確認します。
pi@raspberrypi:~ $ timedatectl status
Local time: Tue 2021-08-31 23:14:11 JST <--- OSのシステム時刻
Universal time: Tue 2021-08-31 14:14:11 UTC <--- OSのシステム時刻
RTC time: Tue 2021-08-31 14:14:11 <--- RX8900 RTC モジュールの時刻
Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
pi@raspberrypi:~ $
以上です。