/** Queues the DC reference clock drift compensation datagram for sending.
*
* The reference clock will by synchronized to the application time provided
* by the last call off ecrt_master_application_time().
*/
void ecrt_master_sync_reference_clock(
ec_master_t *master /**< EtherCAT master. */
);
ecrt_master_sync_reference_clock这个函数将最近一次从ecrt_master_application_time传入的时间戳发送给参考时钟。
这就是官方example中除了rtai_rtdm_dc这个例子使用的默认dc同步方式,即所谓的以主站作为参考时钟的方式。
/** Queues the DC clock drift compensation datagram for sending.
*
* All slave clocks synchronized to the reference clock.
*/
void ecrt_master_sync_slave_clocks(
ec_master_t *master /**< EtherCAT master. */
);
这个函数其实发送了一个EtherCAT FRMW原语包
可以追溯到master/master.c的2106行
ec_datagram_frmw(&master->sync_datagram, ref ? ref->station_address : 0xffff, 0x0910, 4);
FRMW 即配置的地址物理读/多写 (Configured Read Mutiple Write)
ECT_REG_DCSYSTIME 0x0910 (DC系统时钟,只读,64位) 获取此帧到达时,SystemTime系统时间的值.
明明是只读寄存器却可写?反正我是没懂这用法。
总之这个函数的作用是将参考时钟发送给所有从站,以实现dc时钟同步。
要想实现以从站作为参考时钟,只需要调用ecrt_master_sync_slave_clocks就可以实现,但是因为PC主站时钟与从站参考时钟有区别,会出现主站时钟与参考时钟慢慢偏离的情况。
一种解决办法是调用ecrt_master_sync_reference_clock将主站时钟同步到参考时钟,这就是官方例子采用的,优点是实现简单,缺点是dc时钟会受主站的实时性的影响。
另一种就是根据从站参考时钟来动态调整主站时钟,可以参考rtai_rtdm_dc这个例子,但是我觉得这个例子写的太复杂,所以在之前的文章里写了我自己的办法。