Ben's notes

Linux, Unix, network, radio...

User Tools

Site Tools


pc_engines_apu1_hopf_clock_ntp

PC Engines APU1 - Hopf NTP Server

Requirements

  • PC Enginges board, with DCD line (APU = ok, ALIX = not ok)
  • Debian 10 installed.
  • Getty on ttyS0 disabled.
  • APU1 to Hopf 7001 system connected over serial (see wiring below).
  • Hopf 7245 interface card configured for NTP (see 7245 interface board documentation).
  • NTP source code download.

Documentation

  • Interface board 7245 DIP-switch settings.
    1 = on 
    0 = off
    
    SW1      SW2      SW3
    12345678 12345678 12345678 
    11111001 11000111 11111110

Serial cable

  • Construct a serial cable to route PPS to DCD.
    Hopf 7245     1 GND --------- 5 GND     PC Engines
    S1 RS232      2 TXD --------- 2 RXD     APU1 board
                  6 RTS (PPS) --- 1 DCD
    

Install packages

  • Install required tooling.
    apt install build-essential libcap-dev pps-tools
  • Create new udev rules file.
    cat > /etc/udev/rules.d/hopf.rules <<EOF
    KERNEL=="ttyS0", SYMLINK+="refclock-0"
    KERNEL=="ttyS0", RUN+="stty -F /dev/%k 9600 cs8 -cstopb -parenb"
    KERNEL=="ttyS0", TAG+="systemd", ENV{SYSTEMD_WANTS}="pps.service"
    KERNEL=="pps0",  SYMLINK+="refclockpps-0"
    EOF
  • Reload the udev rules or reboot to test.
    ls -l /dev/refc*
    lrwxrwxrwx 1 root root 5 Jan  4 14:37 /dev/refclock-0 -> ttyS0
    lrwxrwxrwx 1 root root 4 Jan  4 14:37 /dev/refclockpps-0 -> pps0
    
    ppstest /dev/pps0
    trying PPS source "/dev/pps0"
    found PPS source "/dev/pps0"
    ok, found 1 source(s), now start fetching data...
    source 0 - assert 1578145727.901770116, sequence: 1313 - clear  1578145072.692767609, sequence: 2
    source 0 - assert 1578145728.000351551, sequence: 1314 - clear  1578145072.692767609, sequence: 2
    source 0 - assert 1578145728.901731373, sequence: 1315 - clear  1578145072.692767609, sequence: 2
    source 0 - assert 1578145729.000557999, sequence: 1316 - clear  1578145072.692767609, sequence: 2
    ^C
    

Install NTP

  • Disable and remove other time sync applications.
    apt-get remove --purge ntp chrony
    timedatectl set-ntp false
    systemctl stop systemd-timesyncd
    systemctl disable systemd-timesyncd
  • Add ntp user.
    groupadd ntp
    useradd -c "Network Time Protocol" -d /var/lib/ntp -g ntp -s /bin/false ntp
    usermod -a -G dialout ntp
      * Create directories.<code>
    install -v -o ntp -g ntp -d /var/lib/ntp
    install -v -o ntp -g ntp -d /var/log/ntpstats
  • Compile source code.
    tar zxf ntp-4.2.8p13.tar.gz 
    cd ntp-4.2.8p13
    
    # from Linux From Scratch
    ./configure CFLAGS="-O2 -g -fPIC" \
                --prefix=/usr         \
                --bindir=/usr/sbin    \
                --sysconfdir=/etc     \
                --enable-linuxcaps    \
                --enable-parse-clocks \
                --with-lineeditlibs=readline \
                --docdir=/usr/share/doc/ntp-4.2.8p13
    
    make
    
    make install
  • Add systemd services.
    cat > /etc/systemd/system/ntpd.service <<EOF
    [Unit]
    Description=Network Time Service
    After=syslog.target ntpdate.service sntp.service
    Conflicts=systemd-timesyncd.service
    
    [Service]
    Type=forking
    ExecStart=/usr/local/bin/ntpd -g -u ntp:ntp
    PrivateTmp=true
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    systemctl enable ntpd
    systemctl start ntpd
    
    
    cat > /etc/systemd/system/pps.server <<EOF
    [Service]
    Type=simple
    ExecStart=/usr/bin/ppsldisc /dev/ttyS0
    EOF

Hopf DCF /etc/ntp.conf

  • Create /etc/ntpd.conf.
    #Stratum level when no ref source available
    tos orphan 12
    
    # Hopf DCF clock
    # Mode 12 + 128 (pps) = 140
    server 127.127.8.0     mode 140
    
    fudge  127.127.8.0     refid PPS       # Reference identifier
    
    #leapfile /etc/leap_second
    
    restrict -4 default notrap nomodify nopeer noquery
    restrict -6 default notrap nomodify nopeer noquery
    restrict 127.0.0.1
    restrict ::1
    
    statsdir /var/log/ntpstats/
    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
    
    driftfile /var/lib/ntp/ntp.drift
    

Check timecode

ntpq -c 'cv 0 timecode'
timecode="\x02CB154556010120\x0a\x0d\x03"

Nagios Hopf 7001 check

#!/bin/bash
#
# Tested with Hopf 7001 DCF Base station with 7245 serial interface boards
# Datastring 7001/6021
#
# BS, 2013/05

ntpq="/usr/bin/ntpq"

# get timecode variable, received from the clock
eval `$ntpq -c 'cv 0 timecode'`

function quit {
	case "$2" in
	0)	echo "OK: $1"
		exit 0
		;;
	1)	echo "Warning: $1"
		exit 1
		;;
	2)	echo "Critical: $1"
		exit 2
		;;
	3)	echo "Unknown: $1"
		exit 3
		;;
	esac
}

function clockstat {
	# Status nibble from hex
	hex0=0000
	hex1=0001
	hex2=0010
	hex3=0011
	hex4=0100
	hex5=0101
	hex6=0110
	hex7=0111
	hex8=1000
	hex9=1001
	hexA=1010
	hexB=1011
	hexC=1100
	hexD=1101
	hexE=1110
	hexF=1111

	eval statnibble='hex$1'
	snibble=${!statnibble}

	case ${snibble:0:2} in
	00)
		textstatus="time/date invalid"
		exitcode=2
		;;
	01)
		textstatus="crystal operation"
		exitcode=1
		;;
        10)
                textstatus="radio operation"
		exitcode=0
		;;
	11)
		textstatus="radio operation (high accuracy)"
		exitcode=0
		;;
	esac

	case ${snibble:2:1} in
	0)
		dss="standard time"
		;;
	1)
		dss="daylight saving time"
		;;
	esac

        case ${snibble:3:1} in
        0)
                ann="no announcement hour"
                ;;
        1)
                ann="announcement (ds-st-ds)"
                ;;
        esac

	quit "status hex=\"$1\", bin=\"$snibble\": $textstatus, $dss, $ann" $exitcode
}


# check for complete string, for example: \x028D194223310513\x0a\x0d\x03
# This is from the Hopf 7245 serial interface board
#
# x20 = Space
# x0D = CR (carriage return)
# x0A = LF (line feed)
# x02 = STX (start of text)
# x03 = ETX (end of text)
#
if [[ $timecode == \\x02*\\x0a\\x0d\\x03 ]];
then
	clockstat ${timecode:4:1}
else
	quit "Timecode not complete" 3	# return Unkown status
fi

Troubleshooting

  • Show peer status:
    ntpq -p
  • Show timecode from receiver:
    ntpq -c 'cv 0 timecode'
  • Show client list (max. 600):
    ntpdc -n -c monlist
    
    ## ntp 2.4.7 removed monlist in favour of ntpq's mrulist
    ntpq -c "mrulist"
pc_engines_apu1_hopf_clock_ntp.txt · Last modified: 2021/10/09 15:14 by 127.0.0.1