Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
E
etherlabmaster
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
ICS Control System Infrastructure
etherlabmaster
Commits
e70a2879
Commit
e70a2879
authored
14 years ago
by
Florian Pose
Browse files
Options
Downloads
Patches
Plain Diff
Improved dc_user example.
parent
4b5ca525
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
examples/dc_user/Makefile.am
+1
-1
1 addition, 1 deletion
examples/dc_user/Makefile.am
examples/dc_user/main.c
+135
-104
135 additions, 104 deletions
examples/dc_user/main.c
with
136 additions
and
105 deletions
examples/dc_user/Makefile.am
+
1
−
1
View file @
e70a2879
...
@@ -33,6 +33,6 @@ noinst_PROGRAMS = ec_dc_user_example
...
@@ -33,6 +33,6 @@ noinst_PROGRAMS = ec_dc_user_example
ec_dc_user_example_SOURCES
=
main.c
ec_dc_user_example_SOURCES
=
main.c
ec_dc_user_example_CFLAGS
=
-I
$(
top_srcdir
)
/include
ec_dc_user_example_CFLAGS
=
-I
$(
top_srcdir
)
/include
ec_dc_user_example_LDFLAGS
=
-L
$(
top_builddir
)
/lib/.libs
-lethercat
ec_dc_user_example_LDFLAGS
=
-L
$(
top_builddir
)
/lib/.libs
-lethercat
-lrt
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
This diff is collapsed.
Click to expand it.
examples/dc_user/main.c
+
135
−
104
View file @
e70a2879
...
@@ -35,6 +35,9 @@
...
@@ -35,6 +35,9 @@
#include
<sys/time.h>
#include
<sys/time.h>
#include
<sys/types.h>
#include
<sys/types.h>
#include
<unistd.h>
#include
<unistd.h>
#include
<time.h>
#include
<sys/mman.h>
#include
<malloc.h>
/****************************************************************************/
/****************************************************************************/
...
@@ -43,12 +46,20 @@
...
@@ -43,12 +46,20 @@
/****************************************************************************/
/****************************************************************************/
// Application parameters
// Application parameters
#define FREQUENCY 100
#define FREQUENCY 1000
#define PRIORITY 1
#define CLOCK_TO_USE CLOCK_REALTIME
#define MEASURE_TIMING
// Optional features
/****************************************************************************/
#define CONFIGURE_PDOS 1
#define NSEC_PER_SEC (1000000000L)
#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)
#define TIMESPEC2NS(T) ((uint64_t) (T).tv_sec * NSEC_PER_SEC + (T).tv_nsec)
/****************************************************************************/
/****************************************************************************/
// EtherCAT
// EtherCAT
...
@@ -58,10 +69,6 @@ static ec_master_state_t master_state = {};
...
@@ -58,10 +69,6 @@ static ec_master_state_t master_state = {};
static
ec_domain_t
*
domain1
=
NULL
;
static
ec_domain_t
*
domain1
=
NULL
;
static
ec_domain_state_t
domain1_state
=
{};
static
ec_domain_state_t
domain1_state
=
{};
// Timer
static
unsigned
int
sig_alarms
=
0
;
static
unsigned
int
user_alarms
=
0
;
/****************************************************************************/
/****************************************************************************/
// process data
// process data
...
@@ -81,10 +88,26 @@ static int off_counter_in;
...
@@ -81,10 +88,26 @@ static int off_counter_in;
static
int
off_counter_out
;
static
int
off_counter_out
;
static
unsigned
int
counter
=
0
;
static
unsigned
int
counter
=
0
;
static
unsigned
int
blink_counter
=
0
;
static
unsigned
int
blink
=
0
;
static
unsigned
int
blink
=
0
;
static
unsigned
int
sync_ref_counter
=
0
;
static
unsigned
int
sync_ref_counter
=
0
;
struct
timeval
app_time
;
const
struct
timespec
cycletime
=
{
0
,
PERIOD_NS
};
/*****************************************************************************/
struct
timespec
timespec_add
(
struct
timespec
time1
,
struct
timespec
time2
)
{
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
;
}
return
result
;
}
/*****************************************************************************/
/*****************************************************************************/
...
@@ -110,7 +133,7 @@ void check_master_state(void)
...
@@ -110,7 +133,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
);
...
@@ -124,68 +147,108 @@ void check_master_state(void)
...
@@ -124,68 +147,108 @@ void check_master_state(void)
void
cyclic_task
()
void
cyclic_task
()
{
{
int
i
;
struct
timespec
wakeupTime
,
time
;
#ifdef MEASURE_TIMING
struct
timespec
startTime
,
endTime
,
lastStartTime
=
{};
uint32_t
period_ns
=
0
,
exec_ns
=
0
,
latency_ns
=
0
,
latency_min_ns
=
0
,
latency_max_ns
=
0
,
period_min_ns
=
0
,
period_max_ns
=
0
,
exec_min_ns
=
0
,
exec_max_ns
=
0
;
#endif
// receive process data
// get current time
ecrt_master_receive
(
master
);
clock_gettime
(
CLOCK_TO_USE
,
&
wakeupTime
);
ecrt_domain_process
(
domain1
);
// check process data state (optional)
while
(
1
)
{
check_domain1_state
();
wakeupTime
=
timespec_add
(
wakeupTime
,
cycletime
);
clock_nanosleep
(
CLOCK_TO_USE
,
TIMER_ABSTIME
,
&
wakeupTime
,
NULL
);
if
(
counter
)
{
#ifdef MEASURE_TIMING
counter
--
;
clock_gettime
(
CLOCK_TO_USE
,
&
startTime
);
}
else
{
// do this at 1 Hz
latency_ns
=
DIFF_NS
(
wakeupTime
,
startTime
);
counter
=
FREQUENCY
;
period_ns
=
DIFF_NS
(
lastStartTime
,
startTime
);
exec_ns
=
DIFF_NS
(
lastStartTime
,
endTime
);
lastStartTime
=
startTime
;
// calculate new process data
if
(
latency_ns
>
latency_max_ns
)
{
blink
=
!
blink
;
latency_max_ns
=
latency_ns
;
}
if
(
latency_ns
<
latency_min_ns
)
{
latency_min_ns
=
latency_ns
;
}
if
(
period_ns
>
period_max_ns
)
{
period_max_ns
=
period_ns
;
}
if
(
period_ns
<
period_min_ns
)
{
period_min_ns
=
period_ns
;
}
if
(
exec_ns
>
exec_max_ns
)
{
exec_max_ns
=
exec_ns
;
}
if
(
exec_ns
<
exec_min_ns
)
{
exec_min_ns
=
exec_ns
;
}
#endif
// check for master state (optional)
// receive process data
check_master_state
();
ecrt_master_receive
(
master
);
}
ecrt_domain_process
(
domain1
);
// check process data state (optional)
check_domain1_state
();
if
(
counter
)
{
counter
--
;
}
else
{
// do this at 1 Hz
counter
=
FREQUENCY
;
// check for master state (optional)
check_master_state
();
#ifdef MEASURE_TIMING
// output timing stats
printf
(
"period %10u ... %10u
\n
"
,
period_min_ns
,
period_max_ns
);
printf
(
"exec %10u ... %10u
\n
"
,
exec_min_ns
,
exec_max_ns
);
printf
(
"latency %10u ... %10u
\n
"
,
latency_min_ns
,
latency_max_ns
);
period_max_ns
=
0
;
period_min_ns
=
0xffffffff
;
exec_max_ns
=
0
;
exec_min_ns
=
0xffffffff
;
latency_max_ns
=
0
;
latency_min_ns
=
0xffffffff
;
#endif
if
(
blink_counter
)
{
// calculate new process data
blink_counter
--
;
blink
=
!
blink
;
}
else
{
}
blink_counter
=
9
;
// calculate new
process data
// write
process data
blink
=
!
blink
;
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
// write
application time to master
EC_WRITE_U8
(
domain1_pd
+
off_dig_out
,
blink
?
0x66
:
0x99
);
clock_gettime
(
CLOCK_TO_USE
,
&
time
);
EC_WRITE_U8
(
domain1_pd
+
off_counter_out
,
blink
?
0x00
:
0x02
);
ecrt_master_application_time
(
master
,
timespec2u64
(
time
)
);
app_time
.
tv_usec
+=
1000000
/
FREQUENCY
;
if
(
sync_ref_counter
)
{
if
(
app_time
.
tv_usec
>=
1000000
)
{
sync_ref_counter
--
;
app_time
.
tv_usec
-=
1000000
;
}
else
{
app_time
.
tv_sec
++
;
sync_ref_counter
=
1
;
// sync every cycle
}
ecrt_master_sync_reference_clock
(
master
);
ecrt_master_application_time
(
master
,
EC_TIMEVAL2NANO
(
app_time
));
}
ecrt_master_sync_slave_clocks
(
master
);
if
(
sync_ref_counter
)
{
// send process data
sync_ref_counter
--
;
ecrt_domain_queue
(
domain1
);
}
else
{
ecrt_master_send
(
master
);
sync_ref_counter
=
9
;
ecrt_master_sync_reference_clock
(
master
);
}
ecrt_master_sync_slave_clocks
(
master
);
// send process data
#ifdef MEASURE_TIMING
ecrt_domain_queue
(
domain1
);
clock_gettime
(
CLOCK_TO_USE
,
&
endTime
);
ecrt_master_send
(
master
);
#endif
}
}
/****************************************************************************/
void
signal_handler
(
int
signum
)
{
switch
(
signum
)
{
case
SIGALRM
:
sig_alarms
++
;
break
;
}
}
}
/****************************************************************************/
/****************************************************************************/
...
@@ -193,8 +256,11 @@ void signal_handler(int signum) {
...
@@ -193,8 +256,11 @@ void signal_handler(int signum) {
int
main
(
int
argc
,
char
**
argv
)
int
main
(
int
argc
,
char
**
argv
)
{
{
ec_slave_config_t
*
sc
;
ec_slave_config_t
*
sc
;
struct
sigaction
sa
;
struct
itimerval
tv
;
if
(
mlockall
(
MCL_CURRENT
|
MCL_FUTURE
)
==
-
1
)
{
perror
(
"mlockall failed"
);
return
-
1
;
}
master
=
ecrt_request_master
(
0
);
master
=
ecrt_request_master
(
0
);
if
(
!
master
)
if
(
!
master
)
...
@@ -237,7 +303,7 @@ int main(int argc, char **argv)
...
@@ -237,7 +303,7 @@ int main(int argc, char **argv)
return
-
1
;
return
-
1
;
// configure SYNC signals for this slave
// configure SYNC signals for this slave
ecrt_slave_config_dc
(
sc
,
0x0700
,
10000000
,
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
))
...
@@ -247,50 +313,15 @@ int main(int argc, char **argv)
...
@@ -247,50 +313,15 @@ int main(int argc, char **argv)
return
-
1
;
return
-
1
;
}
}
#if PRIORITY
pid_t
pid
=
getpid
();
pid_t
pid
=
getpid
();
if
(
setpriority
(
PRIO_PROCESS
,
pid
,
-
19
))
if
(
setpriority
(
PRIO_PROCESS
,
pid
,
-
19
))
fprintf
(
stderr
,
"Warning: Failed to set priority: %s
\n
"
,
fprintf
(
stderr
,
"Warning: Failed to set priority: %s
\n
"
,
strerror
(
errno
));
strerror
(
errno
));
#endif
sa
.
sa_handler
=
signal_handler
;
printf
(
"Starting cyclic function.
\n
"
);
sigemptyset
(
&
sa
.
sa_mask
);
cyclic_task
();
sa
.
sa_flags
=
0
;
if
(
sigaction
(
SIGALRM
,
&
sa
,
0
))
{
return
0
;
fprintf
(
stderr
,
"Failed to install signal handler!
\n
"
);
return
-
1
;
}
printf
(
"Starting timer...
\n
"
);
tv
.
it_interval
.
tv_sec
=
0
;
tv
.
it_interval
.
tv_usec
=
1000000
/
FREQUENCY
;
tv
.
it_value
.
tv_sec
=
0
;
tv
.
it_value
.
tv_usec
=
1000
;
if
(
setitimer
(
ITIMER_REAL
,
&
tv
,
NULL
))
{
fprintf
(
stderr
,
"Failed to start timer: %s
\n
"
,
strerror
(
errno
));
return
1
;
}
gettimeofday
(
&
app_time
,
NULL
);
printf
(
"Started.
\n
"
);
while
(
1
)
{
pause
();
#if 0
struct timeval t;
gettimeofday(&t, NULL);
printf("%u.%06u\n", t.tv_sec, t.tv_usec);
#endif
while
(
sig_alarms
!=
user_alarms
)
{
cyclic_task
();
user_alarms
++
;
}
}
return
0
;
}
}
/****************************************************************************/
/****************************************************************************/
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment