~~socialite~~
====== Raspberry Pi 3 で NTP Stratum-1 Server を作る(Raspbian stretch) ======
{{ :raspberrypi:20171231_img_0021.jpg?240 |}}
Raspberry Pi 3 で NTP Stratum-1 Server を製作したので,ノートとして記録します.
以前に [[raspberrypi:log20140208_ntp_stratum_1|こちら]]で紹介した NTP Stratum-1 Server は,3年10ヶ月ほど正確な時間を刻み続けていましたが,2017-12-23 に起動不能になり正確な時刻を刻み続けることができなくなりました.これは初代ラズパイで製作したもので,今回はラズパイ3で製作します.
コメントなどありましたら, https://twitter.com/tosihisa 宛に頂けたら助かります.
===== ●まとめ =====
* Raspberry Pi 3 に GPS 時刻情報と PPS 信号を入れることで,GPS と数マイクロ秒程度で同期させることが出来ます.
===== ●GPSボード =====
GPSボードは[[raspberrypi:log20140208_ntp_stratum_1|前回]]と同じものをそのまま再利用します.
下記URLから入手できるのですが,私が購入したのはもう3年以上前なので,今のGPSボードと変わっているようです.
Raspberry Pi GPS Addon Board\\ http://ava.upuaut.net/store/index.php?route=product/product&product_id=95
===== ●必要なスキル =====
* カーネルの再コンパイルが出来る事
[[raspberrypi:log20140208_ntp_stratum_1|前回]]と異なり,今回は ntpd のコンパイルは行わず,Raspbian にパッケージされている ntpd をそのまま使います.
Linux ディストリビューションは Raspbian stretch です.
http://www.raspberrypi.org/downloads から得られる Raspbian Raw Images を SD カードに書き込みます.私は 2017-11-29-raspbian-stretch-lite.img を書き込みました.
よく知られていることとして,Raspbian をイメージから書き込んだ場合のデフォルトユーザーは ''pi'' です.
**ここ数年,Raspbian のデフォルトユーザーを狙った ssh 不正ログイン試行がインターネット上で多発していますから ''pi'' ユーザのパスワードは必ず変更しましょう!**
===== ●カーネル再コンパイル =====
[[raspberrypi:log20140208_ntp_stratum_1|前回]]と同様に,NTP Stratum-1 に合うようにRaspberry Pi 3 の Linux カーネルをコンパイルします. カーネルソースへのパッチはなく, kernel config を変更して再コンパイルします.
カーネルコンパイルの方法は, https://www.raspberrypi.org/documentation/linux/kernel/building.md の"Cross-compiling" 記載されている手順で進めました.
私が使用した Raspbian Linux カーネルソースのバージョンは 4.9.70 です.
標準の bcm2709_defconfig と NTP Stratum-1 向けの .config の差を掲載します.[[raspberrypi:log20140208_ntp_stratum_1|前回]]と似ていますが,以下のようにします.
- ''CONFIG_NO_HZ'' を無効にする.(''# CONFIG_NO_HZ is not set'') \\ 私の環境では,''CONFIG_HZ_PERIODIC=y'' にしています.
- ''CONFIG_PPS'' を有効にする.\\ bcm2709_defconfig では,すでに ''CONFIG_PPS=m'' でした.
- ''CONFIG_NTP_PPS'' を有効にする.
--- .config.org 2017-12-24 18:21:17.166881242 +0900
+++ .config-NTP-1 2017-12-24 18:32:49.820830852 +0900
@@ -77,11 +77,10 @@
# Timers subsystem
#
CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ_COMMON=y
-# CONFIG_HZ_PERIODIC is not set
-CONFIG_NO_HZ_IDLE=y
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
# CONFIG_NO_HZ_FULL is not set
-CONFIG_NO_HZ=y
+# CONFIG_NO_HZ is not set
CONFIG_HIGH_RES_TIMERS=y
#
@@ -2555,6 +2554,7 @@
#
CONFIG_PPS=m
# CONFIG_PPS_DEBUG is not set
+CONFIG_NTP_PPS=y
#
# PPS clients support
カーネル再コンパイルが済めば, https://www.raspberrypi.org/documentation/linux/kernel/building.md の手順通りにコピーとして Raspberry Pi 3 が新しいカーネルで起動するかを確認します.
===== ●ntp 導入前の諸設定 =====
==== ●ソフトを最新状態へ ====
$ sudo apt-get update
$ sudo apt-get upgrade
==== ●使用しないサービスの停止 ====
$ sudo systemctl stop triggerhappy.service
$ sudo systemctl disable triggerhappy.service
$ sudo systemctl stop triggerhappy.socket
$ sudo systemctl disable triggerhappy.socket
$ sudo systemctl stop hciuart.service
$ sudo systemctl disable hciuart.service
==== ●UART を未使用にして,pps-goioを使えるようにする ====
''sudo raspi-config'' を実行して, Interfacing Options->Serial を選択し,以下のようにします.
Would you like a login shell to be accessible over serial?
Would you like the serial port hardware to be enabled?
The serial login shell is disabled
The serial interface is disabled
また, ''/boot/cmdline.txt'' をテキストエディタで開き,''console=serial1,115200'' を削除します.
これでコンソールと UART を切り離します.
次に, ''/boot/config.txt'' をテキストエディタで開き,以下を追加します.
enable_uart=1
dtoverlay=pi3-miniuart-bt
dtoverlay=pps-gpio,gpiopin=18
これで再起動後,以下のようになっていれば,/dev/ttyAMA0 が GPS NMEA 入力として利用できます.
$ ls -al /dev/serial*
lrwxrwxrwx 1 root root 7 Dec 30 16:02 /dev/serial0 -> ttyAMA0
lrwxrwxrwx 1 root root 5 Dec 30 16:02 /dev/serial1 -> ttyS0
もし,ttyAMA0 と ttyS0 が逆転している場合,設定を再度見直してください.
==== ●CPU周波数の設定 ====
CPU周波数を常に一定で動作させるようにします.
$ sudo apt-get install cpufrequtils
''/etc/default/cpufrequtils'' を開き(無ければ新規作成),以下のようにします.
GOVERNOR=“performance"
==== ●デバイスファイルのパーミッション・シンボリックリンク設定 ====
UARTやPPSデバイスファイルを ntpd で参照できるようにします.
テキストエディタで ''/etc/udev/rules.d/09.pps.rules'' を開き(無い場合は新規作成),以下のようにします.
KERNEL=="ttyAMA0", SYMLINK+="gps0"
KERNEL=="pps0", OWNER="root", GROUP="dialout", MODE="0660", SYMLINK+="gpspps0"
==== ●再起動してチェック ====
一度 Raspberry Pi 3 を再起動して,以下をチェックします.
=== ●UARTとPPSの状態 ===
$ ls -al /dev/serial* /dev/ttyAMA0 /dev/gps0 /dev/pps0 /dev/gpspps0
lrwxrwxrwx 1 root root 7 Dec 30 16:02 /dev/gps0 -> ttyAMA0
lrwxrwxrwx 1 root root 4 Dec 30 16:02 /dev/gpspps0 -> pps0
crw-rw---- 1 root dialout 245, 0 Dec 30 16:02 /dev/pps0
lrwxrwxrwx 1 root root 7 Dec 30 16:02 /dev/serial0 -> ttyAMA0
lrwxrwxrwx 1 root root 5 Dec 30 16:02 /dev/serial1 -> ttyS0
crw-rw---- 1 root dialout 204, 64 Dec 30 16:02 /dev/ttyAMA0
$
=== ●CPU 周波数の状態 ===
$ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
performance
performance
performance
performance
$
==== ●PPSドライバの動作確認 ====
Linux カーネルのPPSドライバが,GPSモジュールのPPSを読み取っているかを確認するには,pps-tools をインストールします.
$ sudo apt-get install pps-tools
$ sudo ppstest /dev/pps0
GPSモジュールが測位している(PPS LEDが点滅している)と,ppstest ではそのPPS周期で出力を出していくはずです.
===== ●NTPサーバの導入と設定 =====
NTPサーバをインストールします.冒頭で記載した通り,今回は Raspbian stretch の NTP サーバをそのまま使います.
$ sudo apt-get install ntp
Raspbian stretch では systemd-timesyncd が SNTP クライアントとして動作していますが,NTP サーバをインストールして再起動すると,systemd-timesyncd は起動しないようになっています.
''sudo vigr'' を実行して, ''dialout'' グループに ''ntp'' ユーザを所属させます.これにより,ntp サーバが ''/dev/ttyAMA0'' と ''/dev/pps0'' にアクセス出来るようになります.
...
dialout:x:20:pi,ntp
...
ここで,一旦 NTP サーバを再起動します.
''/etc/ntp.conf'' をテキストエディタで開き,GPS と PPS を利用するようにします.
--- /etc/ntp.conf.orig 2017-12-30 02:35:45.487712787 +0000
+++ /etc/ntp.conf 2017-12-31 05:25:28.673876659 +0000
@@ -3,24 +3,30 @@
driftfile /var/lib/ntp/ntp.drift
# Enable this if you want statistics to be logged.
-#statsdir /var/log/ntpstats/
+statsdir /var/log/ntpstats/
-statistics loopstats peerstats clockstats
+#statistics loopstats peerstats clockstats
+#filegen loopstats file loopstats type day enable
+#filegen peerstats file peerstats type day enable
+#filegen clockstats file clockstats type day enable
+statistics loopstats sysstats
filegen loopstats file loopstats type day enable
-filegen peerstats file peerstats type day enable
-filegen clockstats file clockstats type day enable
+filegen sysstats file sysstats type day enable
# You do need to talk to an NTP server or two (or three).
#server ntp.your-provider.example
+server 127.127.20.0 mode 17 minpoll 4 maxpoll 4 prefer
+fudge 127.127.20.0 refid GPS
+fudge 127.127.20.0 flag1 1 flag3 1
# pool.ntp.org maps to about 1000 low-stratum NTP servers. Your server will
# pick a different set every time it starts up. Please consider joining the
# pool:
-pool 0.debian.pool.ntp.org iburst
-pool 1.debian.pool.ntp.org iburst
-pool 2.debian.pool.ntp.org iburst
-pool 3.debian.pool.ntp.org iburst
+#pool 0.debian.pool.ntp.org iburst
+#pool 1.debian.pool.ntp.org iburst
+#pool 2.debian.pool.ntp.org iburst
+#pool 3.debian.pool.ntp.org iburst
# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for
主な変更点は以下のとおりです.
- ntpd の loopstats,sysstats ログを記録する
- Generic NMEA GPS Receiver の設定
- 外部 NTP サーバを参照しないようにする
==== ●Generic NMEA GPS Receiver の設定について ====
上記の ntp.conf の設定のうち,Generic NMEA GPS Receiver 部分を再掲します.
server 127.127.20.0 mode 17 minpoll 4 maxpoll 4 prefer
fudge 127.127.20.0 refid GPS
fudge 127.127.20.0 flag1 1 flag3 1
NTPサーバの Generic NMEA GPS Receiverの設定は, https://www.eecis.udel.edu/~mills/ntp/html/drivers/driver20.html に詳細が記載されています.
まず, ''127.127.20.u'' が Generic NMEA GPS Receiver を指し,server 行の ''mode 17''は,9600bps で GPS と接続し,NMEA の $GPRMC センテンスを使用する事を示します.
''fudge 127.127.20.0 refid GPS'' は,参照先の名称を ''GPS'' にします.
''fudge 127.127.20.0 flag1 1 flag3 1'' の ''flag1 1'' は,PPSを使う事を示します.
''flag2'' は PPS信号パルスを立ち上がり(rising edge)で処理するか立ち下がり(falling edge)で処理するかを設定するもので,デフォルトでは立ち上がりで処理します.これはこのまま(デフォルトのまま)使用するので設定していません.
==== ●NTPサーバの動作検証 ====
ntpq を実行します.
$ ntpq -p
remote refid st t when poll reach delay offset jitter
==============================================================================
oGPS_NMEA(0) .GPS. 0 l 4 16 377 0.000 0.000 0.002
重要なのは,先頭に '''o''' が出ているかどうかです.これが出ていれば,PPS同期できています.
以下のように, ''ntpq -c clockvar'' を実行すると,クロック元(GPS)の情報が得られます.
''$GPRMC'' のところは,実際に受信していたセンテンスが出てきます.
$ ntpq -c clockvar
associd=0 status=0000 no events, clk_unspec,
device="NMEA GPS Clock",
timecode="$GPRMC,......................................,,,D*xx",
poll=2319, noreply=0, badformat=0, baddata=0, stratum=0, refid=GPS,
flags=5
他,''ntpq'' コマンドの使い方は, http://doc.ntp.org/4.2.8/ntpq.html に詳細があります.
このNTPサーバの loopstats をグラフにしたものを提示します.縦軸がリファレンス(GPS)との時間差をマイクロ秒で示し,横軸は1日あたりの経過秒を示します.
{{ :raspberrypi:loopstats.20180101_2_1.png |}}
loopstats には 5400件のログがあり,その内プラスマイナス1マイクロ秒以上のズレがあったのは76件で,その他はプラスマイナス1マイクロ秒未満でした.割合で述べると,約98%はプラスマイナス1マイクロ秒未満で同期しているようです.2マイクロ秒以上のズレはこの loopstats にはありませんでした.
===== ●変更履歴 =====
* 2018-01-01:初版
* 2018-01-02: jessie ではなく stretch の間違いでした!
* 2018-01-02: 「config を変更して」→「kernel config を変更して」