Added ecrt_master_sync_reference_clock_to() method.

This commit is contained in:
Florian Pose 2018-11-26 17:41:27 +01:00
parent 083bd419b8
commit f03f15a6fc
5 changed files with 139 additions and 68 deletions

View File

@ -187,6 +187,10 @@
*/
#define EC_HAVE_REG_BY_POS
/** Defined if the method ecrt_master_sync_reference_clock_to() is available.
*/
#define EC_HAVE_SYNC_TO
/*****************************************************************************/
/** End of list marker.
@ -1016,11 +1020,10 @@ int ecrt_master_link_state(
* distributed clocks. The time is not incremented by the master itself, so
* this method has to be called cyclically.
*
* \attention The first call of this method is used to calculate the phase
* delay for the slaves' SYNC0/1 interrupts. Either the method has to be
* called during the realtime cycle *only*, or the first time submitted must
* be in-phase with the realtime cycle. Otherwise synchronisation problems can
* occur.
* \attention The time passed to this method is used to calculate the phase of
* the slaves' SYNC0/1 interrupts. It should be called constantly at the same
* point of the realtime cycle. So it is recommended to call it at the start
* of the calculations to avoid deviancies due to changing execution times.
*
* The time is used when setting the slaves' <tt>System Time Offset</tt> and
* <tt>Cyclic Operation Start Time</tt> registers and when synchronizing the
@ -1028,7 +1031,8 @@ int ecrt_master_link_state(
* ecrt_master_sync_reference_clock().
*
* The time is defined as nanoseconds from 2000-01-01 00:00. Converting an
* epoch time can be done with the EC_TIMEVAL2NANO() macro.
* epoch time can be done with the EC_TIMEVAL2NANO() macro, but is not
* necessary, since the absolute value is not of any interest.
*/
void ecrt_master_application_time(
ec_master_t *master, /**< EtherCAT master. */
@ -1044,6 +1048,16 @@ void ecrt_master_sync_reference_clock(
ec_master_t *master /**< EtherCAT master. */
);
/** Queues the DC reference clock drift compensation datagram for sending.
*
* The reference clock will by synchronized to the time passed in the
* sync_time parameter.
*/
void ecrt_master_sync_reference_clock_to(
ec_master_t *master, /**< EtherCAT master. */
uint64_t sync_time /**< Sync reference clock to this time. */
);
/** Queues the DC clock drift compensation datagram for sending.
*
* All slave clocks synchronized to the reference clock.

View File

@ -668,12 +668,12 @@ int ecrt_master_link_state(const ec_master_t *master, unsigned int dev_idx,
void ecrt_master_application_time(ec_master_t *master, uint64_t app_time)
{
ec_ioctl_app_time_t data;
uint64_t time;
int ret;
data.app_time = app_time;
time = app_time;
ret = ioctl(master->fd, EC_IOCTL_APP_TIME, &data);
ret = ioctl(master->fd, EC_IOCTL_APP_TIME, &time);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to set application time: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
@ -695,6 +695,23 @@ void ecrt_master_sync_reference_clock(ec_master_t *master)
/****************************************************************************/
void ecrt_master_sync_reference_clock_to(ec_master_t *master,
uint64_t sync_time)
{
uint64_t time;
int ret;
time = sync_time;
ret = ioctl(master->fd, EC_IOCTL_SYNC_REF_TO, &time);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to sync reference clock: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
}
}
/****************************************************************************/
void ecrt_master_sync_slave_clocks(ec_master_t *master)
{
int ret;

View File

@ -1925,16 +1925,16 @@ static ATTRIBUTES int ec_ioctl_app_time(
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
)
{
ec_ioctl_app_time_t data;
uint64_t time;
if (unlikely(!ctx->requested))
return -EPERM;
if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
if (copy_from_user(&time, (void __user *) arg, sizeof(time))) {
return -EFAULT;
}
ecrt_master_application_time(master, data.app_time);
ecrt_master_application_time(master, time);
return 0;
}
@ -1960,6 +1960,31 @@ static ATTRIBUTES int ec_ioctl_sync_ref(
/*****************************************************************************/
/** Sync the reference clock.
*
* \return Zero on success, otherwise a negative error code.
*/
static ATTRIBUTES int ec_ioctl_sync_ref_to(
ec_master_t *master, /**< EtherCAT master. */
void *arg, /**< ioctl() argument. */
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
)
{
uint64_t time;
if (unlikely(!ctx->requested))
return -EPERM;
if (copy_from_user(&time, (void __user *) arg, sizeof(time))) {
return -EFAULT;
}
ecrt_master_sync_reference_clock_to(master, time);
return 0;
}
/*****************************************************************************/
/** Sync the slave clocks.
*
* \return Zero on success, otherwise a negative error code.
@ -4309,6 +4334,13 @@ long EC_IOCTL(
}
ret = ec_ioctl_sync_ref(master, arg, ctx);
break;
case EC_IOCTL_SYNC_REF_TO:
if (!ctx->writable) {
ret = -EPERM;
break;
}
ret = ec_ioctl_sync_ref_to(master, arg, ctx);
break;
case EC_IOCTL_SYNC_SLAVES:
if (!ctx->writable) {
ret = -EPERM;

View File

@ -56,7 +56,7 @@
*
* Increment this when changing the ioctl interface!
*/
#define EC_IOCTL_VERSION_MAGIC 29
#define EC_IOCTL_VERSION_MAGIC 30
// Command-line tool
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
@ -103,55 +103,56 @@
#define EC_IOCTL_RECEIVE EC_IO(0x25)
#define EC_IOCTL_MASTER_STATE EC_IOR(0x26, ec_master_state_t)
#define EC_IOCTL_MASTER_LINK_STATE EC_IOWR(0x27, ec_ioctl_link_state_t)
#define EC_IOCTL_APP_TIME EC_IOW(0x28, ec_ioctl_app_time_t)
#define EC_IOCTL_APP_TIME EC_IOW(0x28, uint64_t)
#define EC_IOCTL_SYNC_REF EC_IO(0x29)
#define EC_IOCTL_SYNC_SLAVES EC_IO(0x2a)
#define EC_IOCTL_REF_CLOCK_TIME EC_IOR(0x2b, uint32_t)
#define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x2c)
#define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x2d, uint32_t)
#define EC_IOCTL_RESET EC_IO(0x2e)
#define EC_IOCTL_SC_SYNC EC_IOW(0x2f, ec_ioctl_config_t)
#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x30, ec_ioctl_config_t)
#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x31, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x32, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x33, ec_ioctl_add_pdo_entry_t)
#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x34, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x35, ec_ioctl_reg_pdo_entry_t)
#define EC_IOCTL_SC_REG_PDO_POS EC_IOWR(0x36, ec_ioctl_reg_pdo_pos_t)
#define EC_IOCTL_SC_DC EC_IOW(0x37, ec_ioctl_config_t)
#define EC_IOCTL_SC_SDO EC_IOW(0x38, ec_ioctl_sc_sdo_t)
#define EC_IOCTL_SC_EMERG_SIZE EC_IOW(0x39, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_POP EC_IOWR(0x3a, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_CLEAR EC_IOW(0x3b, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_OVERRUNS EC_IOWR(0x3c, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x3d, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SC_REG_REQUEST EC_IOWR(0x3e, ec_ioctl_reg_request_t)
#define EC_IOCTL_SC_VOE EC_IOWR(0x3f, ec_ioctl_voe_t)
#define EC_IOCTL_SC_STATE EC_IOWR(0x40, ec_ioctl_sc_state_t)
#define EC_IOCTL_SC_IDN EC_IOW(0x41, ec_ioctl_sc_idn_t)
#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x42)
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x43)
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x44)
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x45)
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x46, ec_ioctl_domain_state_t)
#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x47, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x48, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x49, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x4a, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x4b, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x4c, ec_ioctl_sdo_request_t)
#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x4d, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x4e, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x4f, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x50, ec_ioctl_reg_request_t)
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x51, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x52, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x53, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x54, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x55, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x56, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x57, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x58, size_t)
#define EC_IOCTL_SYNC_REF_TO EC_IOW(0x2a, uint64_t)
#define EC_IOCTL_SYNC_SLAVES EC_IO(0x2b)
#define EC_IOCTL_REF_CLOCK_TIME EC_IOR(0x2c, uint32_t)
#define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x2d)
#define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x2e, uint32_t)
#define EC_IOCTL_RESET EC_IO(0x2f)
#define EC_IOCTL_SC_SYNC EC_IOW(0x30, ec_ioctl_config_t)
#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x31, ec_ioctl_config_t)
#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x32, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x33, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x34, ec_ioctl_add_pdo_entry_t)
#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x35, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x36, ec_ioctl_reg_pdo_entry_t)
#define EC_IOCTL_SC_REG_PDO_POS EC_IOWR(0x37, ec_ioctl_reg_pdo_pos_t)
#define EC_IOCTL_SC_DC EC_IOW(0x38, ec_ioctl_config_t)
#define EC_IOCTL_SC_SDO EC_IOW(0x39, ec_ioctl_sc_sdo_t)
#define EC_IOCTL_SC_EMERG_SIZE EC_IOW(0x3a, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_POP EC_IOWR(0x3b, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_CLEAR EC_IOW(0x3c, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_OVERRUNS EC_IOWR(0x3d, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x3e, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SC_REG_REQUEST EC_IOWR(0x3f, ec_ioctl_reg_request_t)
#define EC_IOCTL_SC_VOE EC_IOWR(0x40, ec_ioctl_voe_t)
#define EC_IOCTL_SC_STATE EC_IOWR(0x41, ec_ioctl_sc_state_t)
#define EC_IOCTL_SC_IDN EC_IOW(0x42, ec_ioctl_sc_idn_t)
#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x43)
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x44)
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x45)
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x46)
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x47, ec_ioctl_domain_state_t)
#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x48, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x49, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x4a, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x4b, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x4c, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x4d, ec_ioctl_sdo_request_t)
#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x4e, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x4f, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x50, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x51, ec_ioctl_reg_request_t)
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x52, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x53, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x54, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x55, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x56, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x57, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x58, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x59, size_t)
/*****************************************************************************/
@ -750,13 +751,6 @@ typedef struct {
/*****************************************************************************/
typedef struct {
// inputs
uint64_t app_time;
} ec_ioctl_app_time_t;
/*****************************************************************************/
#ifdef __KERNEL__
/** Context data structure for file handles.

View File

@ -2808,6 +2808,19 @@ void ecrt_master_sync_reference_clock(ec_master_t *master)
/*****************************************************************************/
void ecrt_master_sync_reference_clock_to(
ec_master_t *master,
uint64_t sync_time
)
{
if (master->dc_ref_clock) {
EC_WRITE_U32(master->ref_sync_datagram.data, sync_time);
ec_master_queue_datagram(master, &master->ref_sync_datagram);
}
}
/*****************************************************************************/
void ecrt_master_sync_slave_clocks(ec_master_t *master)
{
if (master->dc_ref_clock) {
@ -3280,6 +3293,7 @@ EXPORT_SYMBOL(ecrt_master_state);
EXPORT_SYMBOL(ecrt_master_link_state);
EXPORT_SYMBOL(ecrt_master_application_time);
EXPORT_SYMBOL(ecrt_master_sync_reference_clock);
EXPORT_SYMBOL(ecrt_master_sync_reference_clock_to);
EXPORT_SYMBOL(ecrt_master_sync_slave_clocks);
EXPORT_SYMBOL(ecrt_master_reference_clock_time);
EXPORT_SYMBOL(ecrt_master_sync_monitor_queue);