目次
Raspberry Pi 3 で NTP Stratum-1 Server を作る(Raspbian stretch)
Raspberry Pi 3 で NTP Stratum-1 Server を製作したので,ノートとして記録します.
以前に こちらで紹介した NTP Stratum-1 Server は,3年10ヶ月ほど正確な時間を刻み続けていましたが,2017-12-23 に起動不能になり正確な時刻を刻み続けることができなくなりました.これは初代ラズパイで製作したもので,今回はラズパイ3で製作します.
コメントなどありましたら, https://twitter.com/tosihisa 宛に頂けたら助かります.
●まとめ
- Raspberry Pi 3 に GPS 時刻情報と PPS 信号を入れることで,GPS と数マイクロ秒程度で同期させることが出来ます.
●GPSボード
GPSボードは前回と同じものをそのまま再利用します. 下記URLから入手できるのですが,私が購入したのはもう3年以上前なので,今のGPSボードと変わっているようです.
Raspberry Pi GPS Addon Board
http://ava.upuaut.net/store/index.php?route=product/product&product_id=95
●必要なスキル
- カーネルの再コンパイルが出来る事
前回と異なり,今回は 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
ユーザのパスワードは必ず変更しましょう!
●カーネル再コンパイル
前回と同様に,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 の差を掲載します.前回と似ていますが,以下のようにします.
CONFIG_NO_HZ
を無効にする.(# CONFIG_NO_HZ is not set
)
私の環境では,CONFIG_HZ_PERIODIC=y
にしています.CONFIG_PPS
を有効にする.
bcm2709_defconfig では,すでにCONFIG_PPS=m
でした.CONFIG_NTP_PPS
を有効にする.
- .config-NTP-1.patch
--- .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? <No> Would you like the serial port hardware to be enabled? <No> The serial login shell is disabled The serial interface is disabled
また, /boot/cmdline.txt
をテキストエディタで開き,console=serial1,115200
を削除します.
これでコンソールと UART を切り離します.
次に, /boot/config.txt
をテキストエディタで開き,以下を追加します.
- /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
を開き(無ければ新規作成),以下のようにします.
- /etc/default/cpufrequtils
GOVERNOR=“performance"
●デバイスファイルのパーミッション・シンボリックリンク設定
UARTやPPSデバイスファイルを ntpd で参照できるようにします.
テキストエディタで /etc/udev/rules.d/09.pps.rules
を開き(無い場合は新規作成),以下のようにします.
- /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
にアクセス出来るようになります.
- /etc/group
... dialout:x:20:pi,ntp ...
ここで,一旦 NTP サーバを再起動します.
/etc/ntp.conf
をテキストエディタで開き,GPS と PPS を利用するようにします.
- ntp.conf.patch
--- /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: <http://www.pool.ntp.org/join.html> -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 部分を再掲します.
- ntp.conf
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日あたりの経過秒を示します.
loopstats には 5400件のログがあり,その内プラスマイナス1マイクロ秒以上のズレがあったのは76件で,その他はプラスマイナス1マイクロ秒未満でした.割合で述べると,約98%はプラスマイナス1マイクロ秒未満で同期しているようです.2マイクロ秒以上のズレはこの loopstats にはありませんでした.
●変更履歴
- 2018-01-01:初版
- 2018-01-02: jessie ではなく stretch の間違いでした!
- 2018-01-02: 「config を変更して」→「kernel config を変更して」