diff --git a/examples/dc_rtai/dc_rtai_sample.c b/examples/dc_rtai/dc_rtai_sample.c index ebf95ad2..6d06b47a 100644 --- a/examples/dc_rtai/dc_rtai_sample.c +++ b/examples/dc_rtai/dc_rtai_sample.c @@ -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); diff --git a/examples/dc_user/main.c b/examples/dc_user/main.c index 2fba8446..371f481b 100644 --- a/examples/dc_user/main.c +++ b/examples/dc_user/main.c @@ -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; diff --git a/examples/rtai_rtdm_dc/main.c b/examples/rtai_rtdm_dc/main.c index de40b603..b7db5b6f 100644 --- a/examples/rtai_rtdm_dc/main.c +++ b/examples/rtai_rtdm_dc/main.c @@ -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", diff --git a/lib/Makefile.am b/lib/Makefile.am index 8a17f328..764e6b6a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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 #------------------------------------------------------------------------------