mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-09-27 12:33:48 +08:00
merge
This commit is contained in:
@@ -164,11 +164,12 @@ void run(long data)
|
|||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
unsigned int sync_ref_counter = 0;
|
unsigned int sync_ref_counter = 0;
|
||||||
|
|
||||||
count2timeval(nano2count(rt_get_real_time_ns()), &tv);
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
t_last_cycle = get_cycles();
|
t_last_cycle = get_cycles();
|
||||||
|
|
||||||
|
count2timeval(nano2count(rt_get_real_time_ns()), &tv);
|
||||||
|
ecrt_master_application_time(master, EC_TIMEVAL2NANO(tv));
|
||||||
|
|
||||||
// receive process data
|
// receive process data
|
||||||
rt_sem_wait(&master_sem);
|
rt_sem_wait(&master_sem);
|
||||||
ecrt_master_receive(master);
|
ecrt_master_receive(master);
|
||||||
@@ -214,18 +215,12 @@ void run(long data)
|
|||||||
|
|
||||||
rt_sem_wait(&master_sem);
|
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) {
|
if (sync_ref_counter) {
|
||||||
sync_ref_counter--;
|
sync_ref_counter--;
|
||||||
} else {
|
} else {
|
||||||
sync_ref_counter = 9;
|
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_master_sync_slave_clocks(master);
|
||||||
ecrt_domain_queue(domain1);
|
ecrt_domain_queue(domain1);
|
||||||
|
|||||||
+64
-59
@@ -57,7 +57,7 @@
|
|||||||
#define PERIOD_NS (NSEC_PER_SEC / FREQUENCY)
|
#define PERIOD_NS (NSEC_PER_SEC / FREQUENCY)
|
||||||
|
|
||||||
#define DIFF_NS(A, B) (((B).tv_sec - (A).tv_sec) * NSEC_PER_SEC + \
|
#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)
|
#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 timespec_add(struct timespec time1, struct timespec time2)
|
||||||
{
|
{
|
||||||
struct timespec result;
|
struct timespec result;
|
||||||
|
|
||||||
if ((time1.tv_nsec + time2.tv_nsec) >= NSEC_PER_SEC) {
|
if ((time1.tv_nsec + time2.tv_nsec) >= NSEC_PER_SEC) {
|
||||||
result.tv_sec = time1.tv_sec + time2.tv_sec + 1;
|
result.tv_sec = time1.tv_sec + time2.tv_sec + 1;
|
||||||
result.tv_nsec = time1.tv_nsec + time2.tv_nsec - NSEC_PER_SEC;
|
result.tv_nsec = time1.tv_nsec + time2.tv_nsec - NSEC_PER_SEC;
|
||||||
} else {
|
} else {
|
||||||
result.tv_sec = time1.tv_sec + time2.tv_sec;
|
result.tv_sec = time1.tv_sec + time2.tv_sec;
|
||||||
result.tv_nsec = time1.tv_nsec + time2.tv_nsec;
|
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);
|
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);
|
printf("%u slave(s).\n", ms.slaves_responding);
|
||||||
if (ms.al_states != master_state.al_states)
|
if (ms.al_states != master_state.al_states)
|
||||||
printf("AL states: 0x%02X.\n", ms.al_states);
|
printf("AL states: 0x%02X.\n", ms.al_states);
|
||||||
@@ -160,10 +160,17 @@ void cyclic_task()
|
|||||||
// get current time
|
// get current time
|
||||||
clock_gettime(CLOCK_TO_USE, &wakeupTime);
|
clock_gettime(CLOCK_TO_USE, &wakeupTime);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
wakeupTime = timespec_add(wakeupTime, cycletime);
|
wakeupTime = timespec_add(wakeupTime, cycletime);
|
||||||
clock_nanosleep(CLOCK_TO_USE, TIMER_ABSTIME, &wakeupTime, NULL);
|
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
|
#ifdef MEASURE_TIMING
|
||||||
clock_gettime(CLOCK_TO_USE, &startTime);
|
clock_gettime(CLOCK_TO_USE, &startTime);
|
||||||
latency_ns = DIFF_NS(wakeupTime, startTime);
|
latency_ns = DIFF_NS(wakeupTime, startTime);
|
||||||
@@ -191,20 +198,20 @@ void cyclic_task()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// receive process data
|
// receive process data
|
||||||
ecrt_master_receive(master);
|
ecrt_master_receive(master);
|
||||||
ecrt_domain_process(domain1);
|
ecrt_domain_process(domain1);
|
||||||
|
|
||||||
// check process data state (optional)
|
// check process data state (optional)
|
||||||
check_domain1_state();
|
check_domain1_state();
|
||||||
|
|
||||||
if (counter) {
|
if (counter) {
|
||||||
counter--;
|
counter--;
|
||||||
} else { // do this at 1 Hz
|
} else { // do this at 1 Hz
|
||||||
counter = FREQUENCY;
|
counter = FREQUENCY;
|
||||||
|
|
||||||
// check for master state (optional)
|
// check for master state (optional)
|
||||||
check_master_state();
|
check_master_state();
|
||||||
|
|
||||||
#ifdef MEASURE_TIMING
|
#ifdef MEASURE_TIMING
|
||||||
// output timing stats
|
// output timing stats
|
||||||
@@ -222,34 +229,32 @@ void cyclic_task()
|
|||||||
latency_min_ns = 0xffffffff;
|
latency_min_ns = 0xffffffff;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// calculate new process data
|
// calculate new process data
|
||||||
blink = !blink;
|
blink = !blink;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write process data
|
// write process data
|
||||||
EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x66 : 0x99);
|
EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x66 : 0x99);
|
||||||
EC_WRITE_U8(domain1_pd + off_counter_out, blink ? 0x00 : 0x02);
|
EC_WRITE_U8(domain1_pd + off_counter_out, blink ? 0x00 : 0x02);
|
||||||
|
|
||||||
// write application time to master
|
if (sync_ref_counter) {
|
||||||
clock_gettime(CLOCK_TO_USE, &time);
|
sync_ref_counter--;
|
||||||
ecrt_master_application_time(master, TIMESPEC2NS(time));
|
} else {
|
||||||
|
sync_ref_counter = 1; // sync every cycle
|
||||||
|
|
||||||
if (sync_ref_counter) {
|
clock_gettime(CLOCK_TO_USE, &time);
|
||||||
sync_ref_counter--;
|
ecrt_master_sync_reference_clock_to(master, TIMESPEC2NS(time));
|
||||||
} else {
|
}
|
||||||
sync_ref_counter = 1; // sync every cycle
|
ecrt_master_sync_slave_clocks(master);
|
||||||
ecrt_master_sync_reference_clock(master);
|
|
||||||
}
|
|
||||||
ecrt_master_sync_slave_clocks(master);
|
|
||||||
|
|
||||||
// send process data
|
// send process data
|
||||||
ecrt_domain_queue(domain1);
|
ecrt_domain_queue(domain1);
|
||||||
ecrt_master_send(master);
|
ecrt_master_send(master);
|
||||||
|
|
||||||
#ifdef MEASURE_TIMING
|
#ifdef MEASURE_TIMING
|
||||||
clock_gettime(CLOCK_TO_USE, &endTime);
|
clock_gettime(CLOCK_TO_USE, &endTime);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
@@ -258,10 +263,10 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
ec_slave_config_t *sc;
|
ec_slave_config_t *sc;
|
||||||
|
|
||||||
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
|
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
|
||||||
perror("mlockall failed");
|
perror("mlockall failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
master = ecrt_request_master(0);
|
master = ecrt_request_master(0);
|
||||||
if (!master)
|
if (!master)
|
||||||
@@ -287,24 +292,24 @@ int main(int argc, char **argv)
|
|||||||
if (off_dig_out < 0)
|
if (off_dig_out < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!(sc = ecrt_master_slave_config(master,
|
if (!(sc = ecrt_master_slave_config(master,
|
||||||
CounterSlavePos, IDS_Counter))) {
|
CounterSlavePos, IDS_Counter))) {
|
||||||
fprintf(stderr, "Failed to get slave configuration.\n");
|
fprintf(stderr, "Failed to get slave configuration.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_counter_in = ecrt_slave_config_reg_pdo_entry(sc,
|
off_counter_in = ecrt_slave_config_reg_pdo_entry(sc,
|
||||||
0x6020, 0x11, domain1, NULL);
|
0x6020, 0x11, domain1, NULL);
|
||||||
if (off_counter_in < 0)
|
if (off_counter_in < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
off_counter_out = ecrt_slave_config_reg_pdo_entry(sc,
|
off_counter_out = ecrt_slave_config_reg_pdo_entry(sc,
|
||||||
0x7020, 1, domain1, NULL);
|
0x7020, 1, domain1, NULL);
|
||||||
if (off_counter_out < 0)
|
if (off_counter_out < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// configure SYNC signals for this slave
|
// 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");
|
printf("Activating master...\n");
|
||||||
if (ecrt_master_activate(master))
|
if (ecrt_master_activate(master))
|
||||||
@@ -324,7 +329,7 @@ int main(int argc, char **argv)
|
|||||||
perror("sched_setscheduler failed");
|
perror("sched_setscheduler failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Starting cyclic function.\n");
|
printf("Starting cyclic function.\n");
|
||||||
cyclic_task();
|
cyclic_task();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -193,16 +193,13 @@ void sync_distributed_clocks(void)
|
|||||||
|
|
||||||
dc_time_ns = system_time_ns();
|
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
|
#if SYNC_MASTER_TO_REF
|
||||||
// get reference clock time to synchronize master cycle
|
// get reference clock time to synchronize master cycle
|
||||||
ecrt_master_reference_clock_time(master, &ref_time);
|
ecrt_master_reference_clock_time(master, &ref_time);
|
||||||
dc_diff_ns = (uint32_t) prev_app_time - ref_time;
|
dc_diff_ns = (uint32_t) prev_app_time - ref_time;
|
||||||
#else
|
#else
|
||||||
// sync reference clock to master
|
// sync reference clock to master
|
||||||
ecrt_master_sync_reference_clock(master);
|
ecrt_master_sync_reference_clock_to(master, dc_time_ns);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// call to sync slaves to ref slave
|
// call to sync slaves to ref slave
|
||||||
@@ -368,6 +365,9 @@ void wait_period(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set master time in nano-seconds
|
||||||
|
ecrt_master_application_time(master, wakeup_time);
|
||||||
|
|
||||||
// calc next wake time (in sys time)
|
// calc next wake time (in sys time)
|
||||||
wakeup_time += cycle_ns;
|
wakeup_time += cycle_ns;
|
||||||
}
|
}
|
||||||
@@ -504,12 +504,6 @@ int main(int argc, char *argv[])
|
|||||||
dc_start_time_ns = system_time_ns();
|
dc_start_time_ns = system_time_ns();
|
||||||
dc_time_ns = dc_start_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);
|
ret = ecrt_master_select_reference_clock(master, sc_ek1100);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Failed to select reference clock: %s\n",
|
fprintf(stderr, "Failed to select reference clock: %s\n",
|
||||||
|
|||||||
+21
-1
@@ -51,7 +51,27 @@ noinst_HEADERS = \
|
|||||||
voe_handler.h
|
voe_handler.h
|
||||||
|
|
||||||
libethercat_la_CFLAGS = -fno-strict-aliasing -Wall -I$(top_srcdir)
|
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
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user