This commit is contained in:
Florian Pose 2019-01-02 11:26:50 +01:00
commit a1ff60df73
4 changed files with 94 additions and 80 deletions

View File

@ -164,11 +164,12 @@ void run(long data)
struct timeval tv;
unsigned int sync_ref_counter = 0;
count2timeval(nano2count(rt_get_real_time_ns()), &tv);
while (1) {
t_last_cycle = get_cycles();
count2timeval(nano2count(rt_get_real_time_ns()), &tv);
ecrt_master_application_time(master, EC_TIMEVAL2NANO(tv));
// receive process data
rt_sem_wait(&master_sem);
ecrt_master_receive(master);
@ -214,18 +215,12 @@ void run(long data)
rt_sem_wait(&master_sem);
tv.tv_usec += 1000;
if (tv.tv_usec >= 1000000) {
tv.tv_usec -= 1000000;
tv.tv_sec++;
}
ecrt_master_application_time(master, EC_TIMEVAL2NANO(tv));
if (sync_ref_counter) {
sync_ref_counter--;
} else {
sync_ref_counter = 9;
ecrt_master_sync_reference_clock(master);
count2timeval(nano2count(rt_get_real_time_ns()), &tv);
ecrt_master_sync_reference_clock_to(master, EC_TIMEVAL2NANO(tv));
}
ecrt_master_sync_slave_clocks(master);
ecrt_domain_queue(domain1);

View File

@ -57,7 +57,7 @@
#define PERIOD_NS (NSEC_PER_SEC / FREQUENCY)
#define DIFF_NS(A, B) (((B).tv_sec - (A).tv_sec) * NSEC_PER_SEC + \
(B).tv_nsec - (A).tv_nsec)
(B).tv_nsec - (A).tv_nsec)
#define TIMESPEC2NS(T) ((uint64_t) (T).tv_sec * NSEC_PER_SEC + (T).tv_nsec)
@ -97,17 +97,17 @@ const struct timespec cycletime = {0, PERIOD_NS};
struct timespec timespec_add(struct timespec time1, struct timespec time2)
{
struct timespec result;
struct timespec result;
if ((time1.tv_nsec + time2.tv_nsec) >= NSEC_PER_SEC) {
result.tv_sec = time1.tv_sec + time2.tv_sec + 1;
result.tv_nsec = time1.tv_nsec + time2.tv_nsec - NSEC_PER_SEC;
} else {
result.tv_sec = time1.tv_sec + time2.tv_sec;
result.tv_nsec = time1.tv_nsec + time2.tv_nsec;
}
if ((time1.tv_nsec + time2.tv_nsec) >= NSEC_PER_SEC) {
result.tv_sec = time1.tv_sec + time2.tv_sec + 1;
result.tv_nsec = time1.tv_nsec + time2.tv_nsec - NSEC_PER_SEC;
} else {
result.tv_sec = time1.tv_sec + time2.tv_sec;
result.tv_nsec = time1.tv_nsec + time2.tv_nsec;
}
return result;
return result;
}
/*****************************************************************************/
@ -134,7 +134,7 @@ void check_master_state(void)
ecrt_master_state(master, &ms);
if (ms.slaves_responding != master_state.slaves_responding)
if (ms.slaves_responding != master_state.slaves_responding)
printf("%u slave(s).\n", ms.slaves_responding);
if (ms.al_states != master_state.al_states)
printf("AL states: 0x%02X.\n", ms.al_states);
@ -160,10 +160,17 @@ void cyclic_task()
// get current time
clock_gettime(CLOCK_TO_USE, &wakeupTime);
while(1) {
wakeupTime = timespec_add(wakeupTime, cycletime);
while(1) {
wakeupTime = timespec_add(wakeupTime, cycletime);
clock_nanosleep(CLOCK_TO_USE, TIMER_ABSTIME, &wakeupTime, NULL);
// Write application time to master
//
// It is a good idea to use the target time (not the measured time) as
// application time, because it is more stable.
//
ecrt_master_application_time(master, TIMESPEC2NS(wakeupTime));
#ifdef MEASURE_TIMING
clock_gettime(CLOCK_TO_USE, &startTime);
latency_ns = DIFF_NS(wakeupTime, startTime);
@ -191,20 +198,20 @@ void cyclic_task()
}
#endif
// receive process data
ecrt_master_receive(master);
ecrt_domain_process(domain1);
// receive process data
ecrt_master_receive(master);
ecrt_domain_process(domain1);
// check process data state (optional)
check_domain1_state();
// check process data state (optional)
check_domain1_state();
if (counter) {
counter--;
} else { // do this at 1 Hz
counter = FREQUENCY;
if (counter) {
counter--;
} else { // do this at 1 Hz
counter = FREQUENCY;
// check for master state (optional)
check_master_state();
// check for master state (optional)
check_master_state();
#ifdef MEASURE_TIMING
// output timing stats
@ -222,34 +229,32 @@ void cyclic_task()
latency_min_ns = 0xffffffff;
#endif
// calculate new process data
blink = !blink;
}
// calculate new process data
blink = !blink;
}
// write process data
EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x66 : 0x99);
EC_WRITE_U8(domain1_pd + off_counter_out, blink ? 0x00 : 0x02);
// write process data
EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x66 : 0x99);
EC_WRITE_U8(domain1_pd + off_counter_out, blink ? 0x00 : 0x02);
// write application time to master
clock_gettime(CLOCK_TO_USE, &time);
ecrt_master_application_time(master, TIMESPEC2NS(time));
if (sync_ref_counter) {
sync_ref_counter--;
} else {
sync_ref_counter = 1; // sync every cycle
if (sync_ref_counter) {
sync_ref_counter--;
} else {
sync_ref_counter = 1; // sync every cycle
ecrt_master_sync_reference_clock(master);
}
ecrt_master_sync_slave_clocks(master);
clock_gettime(CLOCK_TO_USE, &time);
ecrt_master_sync_reference_clock_to(master, TIMESPEC2NS(time));
}
ecrt_master_sync_slave_clocks(master);
// send process data
ecrt_domain_queue(domain1);
ecrt_master_send(master);
// send process data
ecrt_domain_queue(domain1);
ecrt_master_send(master);
#ifdef MEASURE_TIMING
clock_gettime(CLOCK_TO_USE, &endTime);
#endif
}
}
}
/****************************************************************************/
@ -258,10 +263,10 @@ int main(int argc, char **argv)
{
ec_slave_config_t *sc;
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
perror("mlockall failed");
return -1;
}
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
perror("mlockall failed");
return -1;
}
master = ecrt_request_master(0);
if (!master)
@ -287,24 +292,24 @@ int main(int argc, char **argv)
if (off_dig_out < 0)
return -1;
if (!(sc = ecrt_master_slave_config(master,
CounterSlavePos, IDS_Counter))) {
if (!(sc = ecrt_master_slave_config(master,
CounterSlavePos, IDS_Counter))) {
fprintf(stderr, "Failed to get slave configuration.\n");
return -1;
}
}
off_counter_in = ecrt_slave_config_reg_pdo_entry(sc,
0x6020, 0x11, domain1, NULL);
if (off_counter_in < 0)
off_counter_in = ecrt_slave_config_reg_pdo_entry(sc,
0x6020, 0x11, domain1, NULL);
if (off_counter_in < 0)
return -1;
off_counter_out = ecrt_slave_config_reg_pdo_entry(sc,
0x7020, 1, domain1, NULL);
if (off_counter_out < 0)
off_counter_out = ecrt_slave_config_reg_pdo_entry(sc,
0x7020, 1, domain1, NULL);
if (off_counter_out < 0)
return -1;
// configure SYNC signals for this slave
ecrt_slave_config_dc(sc, 0x0700, PERIOD_NS, 4400000, 0, 0);
ecrt_slave_config_dc(sc, 0x0700, PERIOD_NS, 4400000, 0, 0);
printf("Activating master...\n");
if (ecrt_master_activate(master))
@ -324,7 +329,7 @@ int main(int argc, char **argv)
perror("sched_setscheduler failed");
}
printf("Starting cyclic function.\n");
printf("Starting cyclic function.\n");
cyclic_task();
return 0;

View File

@ -193,16 +193,13 @@ void sync_distributed_clocks(void)
dc_time_ns = system_time_ns();
// set master time in nano-seconds
ecrt_master_application_time(master, dc_time_ns);
#if SYNC_MASTER_TO_REF
// get reference clock time to synchronize master cycle
ecrt_master_reference_clock_time(master, &ref_time);
dc_diff_ns = (uint32_t) prev_app_time - ref_time;
#else
// sync reference clock to master
ecrt_master_sync_reference_clock(master);
ecrt_master_sync_reference_clock_to(master, dc_time_ns);
#endif
// call to sync slaves to ref slave
@ -368,6 +365,9 @@ void wait_period(void)
break;
}
// set master time in nano-seconds
ecrt_master_application_time(master, wakeup_time);
// calc next wake time (in sys time)
wakeup_time += cycle_ns;
}
@ -504,12 +504,6 @@ int main(int argc, char *argv[])
dc_start_time_ns = system_time_ns();
dc_time_ns = dc_start_time_ns;
/* Attention: The initial application time is also used for phase
* calculation for the SYNC0/1 interrupts. Please be sure to call it at
* the correct phase to the realtime cycle.
*/
ecrt_master_application_time(master, dc_start_time_ns);
ret = ecrt_master_select_reference_clock(master, sc_ek1100);
if (ret < 0) {
fprintf(stderr, "Failed to select reference clock: %s\n",

View File

@ -51,7 +51,27 @@ noinst_HEADERS = \
voe_handler.h
libethercat_la_CFLAGS = -fno-strict-aliasing -Wall -I$(top_srcdir)
libethercat_la_LDFLAGS = -version-info 1:0:0
#
# http://www.gnu.org/software/libtool/manual/html_node/ ...
# Updating-version-info.html
#
# - If the library source code has changed at all since the last update, then
# increment revision (c:r:a becomes c:r+1:a).
# - If any interfaces have been added, removed, or changed since the last
# update, increment current, and set revision to 0.
# - If any interfaces have been added since the last public release, then
# increment age.
# - If any interfaces have been removed or changed since the last public
# release, then set age to 0.
#
# History
#
# 1:0.0
# ecrt_master_sync_reference_clock_to() added.
# 2:0:1
#
libethercat_la_LDFLAGS = -version-info 2:0:1
#------------------------------------------------------------------------------