IEEE1588是精確網絡對時協議,簡稱PTP。它通過硬件實現的時間標簽(hardware time stamp),使對時精度達到亞微秒級(< 1us),大大高于常規的網絡對時協議(NTP)。PTP協議的另一個特色是它可輸出精確時間同步的硬件脈沖,通常稱為PPS脈沖。在網絡化的嵌入式系統中,利用PTP的硬件PPS脈沖,可對處于不同位置的多臺設備實現同步觸發的功能。這對分布式系統的數據采集、實時控制都具有非常的意義。
英創公司的多款嵌入式主板,ESM7000、ESM6802和ESM6800,其網絡接口均支持PTP協議,且可輸出PPS脈沖,因此是分布式智能設備的理想嵌入式平臺。以下將以ESM7000為例,介紹實現分布式同步觸發的軟硬件方案。
基于PTP的同步觸發軟件流程
ESM7000預裝的Linux平臺文件系統中,已包含了PTP對時及硬件時間同步的完整工具,即ptp4l和phc2sys,同時可方便的控制PPS脈沖的使能。在這個基礎上,按照圖1所示流程就可實現同步觸發的功能。
圖1同步觸發軟件流程
在實際的測試中發現,PTP的對時精度與網絡環境有密切關系。在單一的100M網絡環境所獲得的設備間的同步精度在±200ns;而在1000M網環境,同步精度就下降到±1us;混合網絡環境,同步精度可差至±15us。
同步觸發脈沖的硬件方案
所謂硬件方案,是指圖1中觸發脈沖生成器的實現方案。以PTP協議生成的周期性PPS脈沖為基礎,由應用程序生成觸發使能信號,再通過一個簡單的D觸發器生成最后的觸發脈沖。硬件方案涉及3個信號如下:
●PPS_OUT:整秒脈沖輸出,即周期固定為1秒,在ESM7000上,PPS的脈沖寬度為10ns,上升沿有效。
●TRG_EN:觸發使能,通常用一位GPIO來實現,其高電平有效。
●TRG_PULSE:觸發脈沖,上升沿有效;在TRG_EN為低時,將強制TRG_PULSE為低;當TRG_EN為高時,后續的PPS_OUT脈沖上升沿將鎖存高電平,從而是TRG_PULSE變高電平。TRG_PULSE脈沖上升沿將將作為系統采集控制硬件單元的觸發輸入,觸發各個嵌入式設備同步動作。
圖2同步觸發脈沖生成電路原理圖
在圖2中,TRG_PULSE還可反饋給ESM7000主板,通知同步觸發已發生。但不是必須的。
大部分ESMARC主板均可支持PTP同步觸發功能。對不同型號的主板,PPS脈沖輸出管腳有所不同,如下表所示:
主板型號 | PTP網口 | PPS信號管腳 | 備注 |
ESM7000系列 | eth0 | CN2.GPIO0 | |
ESM6802系列 | eth0 | CN2.GPIO24 | V2.4版才支持 |
ESM6800系列 | eth1 | CN2.GPIO22 | 不能使用SD卡 |
ES6801 | eth0 | CN1.GPIO0 | 不能使用CAN1 |
對選擇哪一位GPIO管腳作為TRG_EN,本方案沒有限制??筛鶕O備的具體情況來確定。
對同步觸發從設備測試
本測試用從設備的“當前時間+ 偏移量”來代替主設備發布的觸發時間TRGTIME,就可用簡單的腳本測試整個觸發過程,具體的腳本如下:
#!/bin/sh # trg_en_3 $1 [$2] [$3] # $1 = 0, off ptp; = 1: on ptp # $2 = number of seconds to delay from cuurent time # $3 = ip:port PATH="/usr/bin:$PATH" E_NOARGS=85 re='^[0-9]+$' TRG_EN_GPIO="gpio1" TRG_EN_DIRECTORY="/sys/class/em_gpio/em_gpio/$TRG_EN_GPIO" PHC2SYSLOG="/tmp/phc2syslog.txt" DELAY=10 # if no arg, exit if [ -z "$1" ] then echo "Usage: `basename $0` filename" exit $E_NOARGS fi # if $1 != 1, off ptp and exit if [ "$1" -ne 1 ] then echo 0 > /sys/class/ptp/ptp0/pps_enable pkill phc2sys pkill ptp4l exit 0 fi # get trigger delay is available, default = 10(s) if [ $# -ge 2 ] then DELAY="$2" fi # now we start to make trg_en step by step echo "step 1: setup gpio1 as trg_en" if [ ! -d "$TRG_EN_DIRECTORY" ] then echo "config $TRG_EN_GPIO as trg_en" echo 1 > /sys/class/em_gpio/em_gpio/export fi echo out > /sys/class/em_gpio/em_gpio/$TRG_EN_GPIO/direction echo 0 > /sys/class/em_gpio/em_gpio/$TRG_EN_GPIO/value echo "step 2: start ptp" phc2sys -s eth0 -c CLOCK_REALTIME -w -m -u 4 > $PHC2SYSLOG & sleep 1 ptp4l -i eth0 -s & echo "step 3: wait phc2sys sync convergence" num_rms=0 while [ "$num_rms" -lt 3 ] do RMS_ARRAY=$(cat $PHC2SYSLOG | tail -n 3 | sed -r 's/.*rms[ ]+([0-9]+).*/\1/g') # echo "$RMS_ARRAY" for rms in $RMS_ARRAY do if ! [[ $rms =~ $re ]] then echo "$rms is NOT an integer!" break fi echo "$rms" if [ "$rms" -lt 350 ]; then let "num_rms += 1" fi done # clear log file if rms is convergence if [ "$num_rms" -ge 3 ]; then echo "rms is convergence ($num_rms)" cat /dev/null > $PHC2SYSLOG else let "num_rms = 0" sleep 2 fi done echo "step 4: enable pps, and setup trigger time" echo 1 > /sys/class/ptp/ptp0/pps_enable TRGTIME=$(date +%s) # get current date in seconds let "TRGTIME = $TRGTIME + $DELAY" PPSTIME=$(cat /sys/class/pps/pps0/assert | cut -d '.' -f 1) echo "TRGTIME = $TRGTIME PPSTIME = $PPSTIME" echo "step 5: wait pps time reach trigger time" while [ "$PPSTIME" -lt "$TRGTIME" ] do sleep 0.1 PPSTIME=$(cat /sys/class/pps/pps0/assert | cut -d '.' -f 1) done echo "step 6: now PPSTIME = TRGTIME, set trg_en" echo 1 > /sys/class/em_gpio/em_gpio/$TRG_EN_GPIO/value echo "step 7: wait pps time reach trigger time + 1" let "TRGTIME = $TRGTIME + 1" while [ "$PPSTIME" -lt "$TRGTIME" ] do sleep 0.1 PPSTIME=$(cat /sys/class/pps/pps0/assert | cut -d '.' -f 1) done echo "step 8: clear trg_en" echo 0 > /sys/class/em_gpio/em_gpio/$TRG_EN_GPIO/value echo "basename $0 done" |
從示波器可觀察到,上述腳本產生的TRG_EN信號,準確使能PPS脈沖產生與之上升沿完全同步的觸發脈沖TRG_PULSE。
對分布式系統同步觸發功能感興趣的客戶,可通過郵件support@emtronix.com與英創公司技術部門聯系,以了解詳細的實現代碼。
-
Linux
+關注
關注
87文章
11320瀏覽量
209845 -
嵌入式主板
+關注
關注
7文章
6085瀏覽量
35438
發布評論請先 登錄
相關推薦
評論