Added ecrt_master_sync_reference_clock_to() method.
This commit is contained in:
parent
083bd419b8
commit
f03f15a6fc
|
|
@ -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.
|
||||
|
|
|
|||
23
lib/master.c
23
lib/master.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
106
master/ioctl.h
106
master/ioctl.h
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue