Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
tsn-measures
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
tsn-measures
Commits
e51b5052
Commit
e51b5052
authored
Oct 05, 2020
by
Joanne Hugé
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve motor interface
parent
6c2dd397
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
229 additions
and
68 deletions
+229
-68
packet-exchange/src/client.c
packet-exchange/src/client.c
+68
-30
packet-exchange/src/common.h
packet-exchange/src/common.h
+1
-1
packet-exchange/src/gpio.c
packet-exchange/src/gpio.c
+28
-12
packet-exchange/src/gpio.h
packet-exchange/src/gpio.h
+2
-2
packet-exchange/src/server.c
packet-exchange/src/server.c
+59
-23
scripts/start-motor
scripts/start-motor
+71
-0
No files found.
packet-exchange/src/client.c
View file @
e51b5052
...
@@ -107,6 +107,8 @@ static struct timespec measures_start;
...
@@ -107,6 +107,8 @@ static struct timespec measures_start;
static
struct
timespec
measures_end
;
static
struct
timespec
measures_end
;
static
char
send_data
[
MAX_BUFFER_SIZE
];
static
char
send_data
[
MAX_BUFFER_SIZE
];
static
int
reverse_motors
=
0
;
static
void
help
(
char
*
argv
[])
{
static
void
help
(
char
*
argv
[])
{
printf
(
printf
(
"Usage: %s [-a CPU -p PRIO -i USEC -r USEC -l N] [-d BUF_LEN | -c "
"Usage: %s [-a CPU -p PRIO -i USEC -r USEC -l N] [-d BUF_LEN | -c "
...
@@ -134,6 +136,13 @@ static void help(char *argv[]) {
...
@@ -134,6 +136,13 @@ static void help(char *argv[]) {
argv
[
0
]);
argv
[
0
]);
}
}
static
double
i_to_rps
(
int
i
)
{
return
((
double
)
USEC_PER_SEC
)
/
(
MOTOR_STEPS
*
i
);
}
static
int
rps_to_i
(
double
rps
)
{
return
USEC_PER_SEC
/
(
MOTOR_STEPS
*
rps
);
}
static
void
*
print_thread
(
void
*
p
)
{
static
void
*
print_thread
(
void
*
p
)
{
(
void
)
p
;
(
void
)
p
;
...
@@ -142,7 +151,9 @@ static void *print_thread(void *p) {
...
@@ -142,7 +151,9 @@ static void *print_thread(void *p) {
nb_cycles
>=
((
unsigned
int
)
thread_params
.
max_cycles
))
nb_cycles
>=
((
unsigned
int
)
thread_params
.
max_cycles
))
break
;
break
;
printf
(
"Interval: %10"
PRIu64
" Target: %10"
PRIu64
"
\n
"
,
thread_params
.
interval
/
1000
,
main_params
.
target_interval
);
printf
(
"RPS: %5F RPS Target: %5F s/100 RPS %5d
\n
"
,
i_to_rps
(
thread_params
.
interval
/
1000
),
i_to_rps
(
main_params
.
target_interval
),
main_params
.
transition_time
);
printf
(
"
\033
[%dA"
,
1
);
printf
(
"
\033
[%dA"
,
1
);
usleep
(
100000
);
usleep
(
100000
);
...
@@ -244,6 +255,12 @@ static void *packet_sending_thread(void *p) {
...
@@ -244,6 +255,12 @@ static void *packet_sending_thread(void *p) {
if
(
thread_params
.
enable_send_ts
)
{
if
(
thread_params
.
enable_send_ts
)
{
tx_data
=
next
.
tv_sec
*
NSEC_PER_SEC
+
next
.
tv_nsec
;
tx_data
=
next
.
tv_sec
*
NSEC_PER_SEC
+
next
.
tv_nsec
;
tx_data
+=
thread_params
.
send_ts_delay
;
tx_data
+=
thread_params
.
send_ts_delay
;
if
(
reverse_motors
)
{
reverse_motors
=
0
;
tx_data
=
17
;
}
}
}
// Update statistics
// Update statistics
...
@@ -281,9 +298,9 @@ static void *packet_sending_thread(void *p) {
...
@@ -281,9 +298,9 @@ static void *packet_sending_thread(void *p) {
next_increment
=
0
;
next_increment
=
0
;
if
(
i_t
<
i_s
)
if
(
i_t
<
i_s
)
end_t
=
(
main_params
.
transition_time
*
USEC_PER_SEC
*
USEC_PER_SEC
*
(
i_c
-
i_t
))
/
(
MOTOR_STEPS
*
i_t
*
i_c
);
end_t
=
(
main_params
.
transition_time
*
USEC_PER_SEC
*
USEC_PER_SEC
*
(
i_c
-
i_t
))
/
(
100
*
MOTOR_STEPS
*
i_t
*
i_c
);
else
else
end_t
=
(
main_params
.
transition_time
*
USEC_PER_SEC
*
USEC_PER_SEC
*
(
i_t
-
i_c
))
/
(
MOTOR_STEPS
*
i_t
*
i_c
);
end_t
=
(
main_params
.
transition_time
*
USEC_PER_SEC
*
USEC_PER_SEC
*
(
i_t
-
i_c
))
/
(
100
*
MOTOR_STEPS
*
i_t
*
i_c
);
}
}
...
@@ -339,6 +356,28 @@ invalid_ts:
...
@@ -339,6 +356,28 @@ invalid_ts:
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
static
void
motor_input
(
void
)
{
char
user_input
[
255
];
int
v
;
scanf
(
"%s"
,
user_input
);
switch
(
user_input
[
0
])
{
case
'a'
:
v
=
atoi
(
user_input
+
1
);
if
(
v
)
main_params
.
transition_time
=
v
;
break
;
case
'r'
:
reverse_motors
=
1
;
break
;
default:
v
=
rps_to_i
(
strtod
(
user_input
,
NULL
));
if
(
v
)
main_params
.
target_interval
=
v
;
break
;
}
}
/*
/*
* Main thread:
* Main thread:
* - Has non-real time priority
* - Has non-real time priority
...
@@ -463,10 +502,9 @@ int main(int argc, char *argv[]) {
...
@@ -463,10 +502,9 @@ int main(int argc, char *argv[]) {
usleep
(
main_params
.
refresh_rate
);
usleep
(
main_params
.
refresh_rate
);
if
(
main_params
.
interval_input
)
{
if
(
main_params
.
interval_input
)
{
uint64_t
user_input
;
scanf
(
"%"
PRIu64
,
&
user_input
);
motor_input
();
if
(
user_input
)
main_params
.
target_interval
=
user_input
;
}
}
else
if
(
main_params
.
verbose
)
{
else
if
(
main_params
.
verbose
)
{
// RTT stats printing
// RTT stats printing
...
@@ -508,7 +546,7 @@ int main(int argc, char *argv[]) {
...
@@ -508,7 +546,7 @@ int main(int argc, char *argv[]) {
}
}
/* Critical TSN task
/* Critical TSN task
*/
*/
static
void
do_tsn_task
(
char
*
data
,
uint64_t
next_txtime
)
{
static
void
do_tsn_task
(
char
*
data
,
uint64_t
next_txtime
)
{
struct
timespec
t1
,
t2
;
struct
timespec
t1
,
t2
;
int
rtt_us
;
int
rtt_us
;
...
@@ -542,7 +580,7 @@ static void do_tsn_task(char *data, uint64_t next_txtime) {
...
@@ -542,7 +580,7 @@ static void do_tsn_task(char *data, uint64_t next_txtime) {
}
}
/* Print histogram
/* Print histogram
*/
*/
static
void
print_histograms
()
{
static
void
print_histograms
()
{
uint64_t
duration
;
uint64_t
duration
;
int
duration_hour
,
duration_minutes
;
int
duration_hour
,
duration_minutes
;
...
@@ -586,7 +624,7 @@ static void sighand(int sig_num) {
...
@@ -586,7 +624,7 @@ static void sighand(int sig_num) {
}
}
/* Process bash options
/* Process bash options
*/
*/
static
void
process_options
(
int
argc
,
char
*
argv
[])
{
static
void
process_options
(
int
argc
,
char
*
argv
[])
{
for
(;;)
{
for
(;;)
{
int
c
=
getopt
(
argc
,
argv
,
"a:bc:d:e:ghi:l:p:q:r:s:tvTS:U:"
);
int
c
=
getopt
(
argc
,
argv
,
"a:bc:d:e:ghi:l:p:q:r:s:tvTS:U:"
);
...
...
packet-exchange/src/common.h
View file @
e51b5052
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
#include <linux/udp.h>
#include <linux/udp.h>
#endif
#endif
#define MOTOR_STEPS
200
00
#define MOTOR_STEPS
8
00
#define NSEC_PER_SEC UINT64_C(1000000000)
#define NSEC_PER_SEC UINT64_C(1000000000)
#define USEC_PER_SEC UINT64_C(1000000)
#define USEC_PER_SEC UINT64_C(1000000)
...
...
packet-exchange/src/gpio.c
View file @
e51b5052
...
@@ -5,28 +5,44 @@
...
@@ -5,28 +5,44 @@
#include <sys/stat.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fcntl.h>
static
int
gpio_state
;
static
char
path
[
64
]
;
static
char
cmd
[
128
];
static
char
cmd
[
128
];
static
char
*
one
=
"1"
;
static
char
*
one
=
"1"
;
static
char
*
zero
=
"0"
;
static
char
*
zero
=
"0"
;
static
int
fd
;
void
enable_gpio
(
int
gpio_index
)
{
int
enable_gpio
(
int
*
fd
,
int
gpio_index
)
{
sprintf
(
cmd
,
"echo %d > /sys/class/gpio/export"
,
gpio_index
);
FILE
*
fp
;
system
(
cmd
);
char
gpio_state_str
[
16
];
sprintf
(
cmd
,
"echo out > /sys/class/gpio/gpio%d/direction"
,
gpio_index
);
int
gpio_state
=
0
;
system
(
cmd
);
sprintf
(
cmd
,
"/sys/class/gpio/gpio%d/value"
,
gpio_index
);
sprintf
(
path
,
"/sys/class/gpio/gpio%d/value"
,
gpio_index
);
fd
=
open
(
cmd
,
O_WRONLY
);
sprintf
(
cmd
,
"cat %s"
,
path
);
fp
=
popen
(
cmd
,
"r"
);
if
(
fp
==
NULL
)
{
fprintf
(
stderr
,
"Error when reading gpio
\n
"
);
exit
(
EXIT_FAILURE
);
}
while
(
fgets
(
gpio_state_str
,
sizeof
(
gpio_state_str
),
fp
)
!=
NULL
)
{
gpio_state
=
atoi
(
gpio_state_str
);
}
pclose
(
fp
);
*
fd
=
open
(
path
,
O_WRONLY
);
return
gpio_state
;
}
}
void
toggle_gpio
(
)
{
int
toggle_gpio
(
int
fd
,
int
gpio_state
)
{
if
(
gpio_state
)
if
(
gpio_state
)
write
(
fd
,
one
,
1
);
else
write
(
fd
,
zero
,
1
);
write
(
fd
,
zero
,
1
);
else
write
(
fd
,
one
,
1
);
gpio_state
=
!
gpio_state
;
gpio_state
=
!
gpio_state
;
return
gpio_state
;
}
}
packet-exchange/src/gpio.h
View file @
e51b5052
#ifndef GPIO_H
#ifndef GPIO_H
#define GPIO_H
#define GPIO_H
void
enable_gpio
(
int
gpio_index
);
int
enable_gpio
(
int
*
fd
,
int
gpio_index
);
void
toggle_gpio
(
);
int
toggle_gpio
(
int
fd
,
int
gpio_state
);
#endif
#endif
packet-exchange/src/server.c
View file @
e51b5052
...
@@ -88,8 +88,15 @@ static int64_t max_diff_ts = 0;
...
@@ -88,8 +88,15 @@ static int64_t max_diff_ts = 0;
static
int64_t
avg_diff_ts
=
0
;
static
int64_t
avg_diff_ts
=
0
;
static
uint64_t
high_diff_ts
=
0
;
static
uint64_t
high_diff_ts
=
0
;
static
int
debug_latencies
=
0
;
static
int
interval_us
;
static
int
interval_us
;
static
int
gpio86_fd
;
static
int
gpio84_fd
;
static
int
gpio86_state
;
static
int
gpio84_state
;
static
int
received_reverse_motor
=
0
;
static
char
ts_tracemark_buf
[
64
];
static
char
ts_tracemark_buf
[
64
];
static
void
help
(
char
*
argv
[])
{
static
void
help
(
char
*
argv
[])
{
...
@@ -110,6 +117,7 @@ static void help(char *argv[]) {
...
@@ -110,6 +117,7 @@ static void help(char *argv[]) {
" -g Print histograms to sdtout on exit
\n
"
" -g Print histograms to sdtout on exit
\n
"
" -t Enable timestamps
\n
"
" -t Enable timestamps
\n
"
" -x Use AF_XDP sockets
\n
"
" -x Use AF_XDP sockets
\n
"
" -D Debug latencies
\n
"
" -X Trace during XDP packet reception
\n
"
" -X Trace during XDP packet reception
\n
"
" -T THRESHOLD Enable tracing until THRESHOLD is reached
\n
"
" -T THRESHOLD Enable tracing until THRESHOLD is reached
\n
"
" -M Send tracemark when packet is received
\n
"
" -M Send tracemark when packet is received
\n
"
...
@@ -127,6 +135,7 @@ static void *emit_signal_thread(void *p) {
...
@@ -127,6 +135,7 @@ static void *emit_signal_thread(void *p) {
int64_t
emit_diff
,
ts_diff
;
int64_t
emit_diff
,
ts_diff
;
int
latency_spike
=
0
;
int
latency_spike
=
0
;
int
ret
;
int
ret
;
int
reverse_motor
=
0
;
// Set thread CPU affinity
// Set thread CPU affinity
if
(
thread_params
.
affinity_cpu
)
{
if
(
thread_params
.
affinity_cpu
)
{
...
@@ -142,34 +151,51 @@ static void *emit_signal_thread(void *p) {
...
@@ -142,34 +151,51 @@ static void *emit_signal_thread(void *p) {
for
(
int
i
=
0
;;
i
++
)
{
for
(
int
i
=
0
;;
i
++
)
{
pthread_cond_wait
(
&
emit_signal_ts_received
,
&
emit_signal_mutex
);
pthread_cond_wait
(
&
emit_signal_ts_received
,
&
emit_signal_mutex
);
if
(
received_reverse_motor
)
{
received_reverse_motor
=
0
;
reverse_motor
=
1
;
continue
;
}
ret
=
clock_nanosleep
(
CLOCK_REALTIME
,
TIMER_ABSTIME
,
&
emit_signal_next
,
NULL
);
ret
=
clock_nanosleep
(
CLOCK_REALTIME
,
TIMER_ABSTIME
,
&
emit_signal_next
,
NULL
);
if
(
ret
)
{
if
(
ret
)
{
fprintf
(
stderr
,
"clock_nanosleep returned error: %d, aborting...
\n
"
,
ret
);
fprintf
(
stderr
,
"clock_nanosleep returned error: %d, aborting...
\n
"
,
ret
);
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
toggle_gpio
();
if
(
reverse_motor
)
{
gpio84_state
=
toggle_gpio
(
gpio84_fd
,
gpio84_state
);
reverse_motor
=
0
;
}
else
{
gpio86_state
=
toggle_gpio
(
gpio86_fd
,
gpio86_state
);
usleep
(
3
);
gpio86_state
=
toggle_gpio
(
gpio86_fd
,
gpio86_state
);
}
clock_gettime
(
CLOCK_REALTIME
,
&
current
);
clock_gettime
(
CLOCK_REALTIME
,
&
current
);
// Check if something went wrong
if
(
debug_latencies
)
{
//if(i > 0) {
//Check if something went wrong
// emit_diff = calcdiff_ns_signed(current, previous_emit);
if
(
i
>
0
)
{
// ts_diff = calcdiff_ns_signed(emit_signal_next, previous_ts);
emit_diff
=
calcdiff_ns_signed
(
current
,
previous_emit
);
// if((emit_diff < ((int64_t)thread_params.interval) - ERROR_MARGIN_NS) ||
ts_diff
=
calcdiff_ns_signed
(
emit_signal_next
,
previous_ts
);
// (emit_diff > ((int64_t)thread_params.interval) + ERROR_MARGIN_NS)) {
if
((
emit_diff
<
((
int64_t
)
thread_params
.
interval
)
-
ERROR_MARGIN_NS
)
||
// fprintf(stderr, "Signal emission interval reached error threshold: %" PRIi64 "\n", emit_diff);
(
emit_diff
>
((
int64_t
)
thread_params
.
interval
)
+
ERROR_MARGIN_NS
))
{
// latency_spike = 1;
fprintf
(
stderr
,
"Signal emission interval reached error threshold: %"
PRIi64
"
\n
"
,
emit_diff
);
// }
latency_spike
=
1
;
// if((ts_diff < ((int64_t)thread_params.interval) - ERROR_MARGIN_NS) ||
}
// (ts_diff > ((int64_t)thread_params.interval) + ERROR_MARGIN_NS)) {
if
((
ts_diff
<
((
int64_t
)
thread_params
.
interval
)
-
ERROR_MARGIN_NS
)
||
// fprintf(stderr, "Timestamp interval reached error threshold: %" PRIi64 "\n", ts_diff);
(
ts_diff
>
((
int64_t
)
thread_params
.
interval
)
+
ERROR_MARGIN_NS
))
{
// latency_spike = 1;
fprintf
(
stderr
,
"Timestamp interval reached error threshold: %"
PRIi64
"
\n
"
,
ts_diff
);
// }
latency_spike
=
1
;
// if(latency_spike) {
}
// fprintf(stderr, "Exiting... Current interval: %d\n", interval_us);
if
(
latency_spike
)
{
// exit(EXIT_FAILURE);
fprintf
(
stderr
,
"Exiting... Current interval: %d
\n
"
,
interval_us
);
// }
exit
(
EXIT_FAILURE
);
//}
}
}
}
previous_emit
=
current
;
previous_emit
=
current
;
previous_ts
=
emit_signal_next
;
previous_ts
=
emit_signal_next
;
}
}
...
@@ -255,7 +281,13 @@ static void *tsn_thread(void *p) {
...
@@ -255,7 +281,13 @@ static void *tsn_thread(void *p) {
else
else
emit_signal_t
=
decode
(
ingress_stats
.
data
);
emit_signal_t
=
decode
(
ingress_stats
.
data
);
if
(
emit_signal_t
<
UINT64_C
(
1576800000000000000
)
&&
emit_signal_t
!=
17
)
continue
;
pthread_mutex_lock
(
&
emit_signal_mutex
);
pthread_mutex_lock
(
&
emit_signal_mutex
);
if
(
emit_signal_t
==
17
)
received_reverse_motor
=
1
;
else
emit_signal_next
=
uint_to_ts
(
emit_signal_t
);
emit_signal_next
=
uint_to_ts
(
emit_signal_t
);
pthread_cond_signal
(
&
emit_signal_ts_received
);
pthread_cond_signal
(
&
emit_signal_ts_received
);
pthread_mutex_unlock
(
&
emit_signal_mutex
);
pthread_mutex_unlock
(
&
emit_signal_mutex
);
...
@@ -445,7 +477,8 @@ int main(int argc, char *argv[]) {
...
@@ -445,7 +477,8 @@ int main(int argc, char *argv[]) {
pthread_mutex_init
(
&
emit_signal_mutex
,
NULL
);
pthread_mutex_init
(
&
emit_signal_mutex
,
NULL
);
pthread_cond_init
(
&
emit_signal_ts_received
,
NULL
);
pthread_cond_init
(
&
emit_signal_ts_received
,
NULL
);
enable_gpio
(
86
);
gpio86_state
=
enable_gpio
(
&
gpio86_fd
,
86
);
gpio84_state
=
enable_gpio
(
&
gpio84_fd
,
84
);
}
}
create_thread
(
tsn_thread
);
create_thread
(
tsn_thread
);
...
@@ -577,7 +610,7 @@ static void process_options(int argc, char *argv[]) {
...
@@ -577,7 +610,7 @@ static void process_options(int argc, char *argv[]) {
int
network_if_specified
=
0
;
int
network_if_specified
=
0
;
for
(;;)
{
for
(;;)
{
int
c
=
getopt
(
argc
,
argv
,
"a:b:cCs:d:f:ghi:p:r:tvxXT:GMS"
);
int
c
=
getopt
(
argc
,
argv
,
"a:b:cCs:d:f:ghi:p:r:tvx
D
XT:GMS"
);
if
(
c
==
-
1
)
break
;
if
(
c
==
-
1
)
break
;
...
@@ -634,6 +667,9 @@ static void process_options(int argc, char *argv[]) {
...
@@ -634,6 +667,9 @@ static void process_options(int argc, char *argv[]) {
case
'x'
:
case
'x'
:
tsn_task
=
XDP_TASK
;
tsn_task
=
XDP_TASK
;
break
;
break
;
case
'D'
:
debug_latencies
=
1
;
break
;
case
'X'
:
case
'X'
:
main_params
.
enable_xdp_tracing
=
1
;
main_params
.
enable_xdp_tracing
=
1
;
break
;
break
;
...
...
scripts/start-motor
0 → 100755
View file @
e51b5052
#!/bin/bash
script_dir
=
$(
dirname
$(
realpath
$0
))
usage
()
{
cat
<<
ENDUSAGE
Usage:
$0
[-h] [-is -c USEC] [-X]
-h Show help
-i Init motors
-s Start servers on olimex boards
-c USEC Specify which offset to use for the timestamp in the packet
-X Use XDP
BOARD_HOSTNAME Uses /etc/hosts to find the IP address associated to the hostname
ENDUSAGE
1>&2
;
exit
1
;
}
interval
=
1000
server_opts
=
""
delay
=
250
while
getopts
"hisc:X"
opt
;
do
case
"
${
opt
}
"
in
h
)
usage
;;
i
)
init_motors
=
1
;;
s
)
start_servers
=
1
;;
c
)
delay
=
${
OPTARG
}
;;
X
)
server_opts+
=
" -X "
;;
*
)
usage
;;
esac
done
shift
$((
OPTIND-1
))
board1
=
"onyx"
board2
=
"slate"
killall client
;
killall run-client
;
if
[
-n
"
$init_motors
"
]
;
then
$script_dir
/sudossh
$board1
"motor-scripts/motor-init"
;
$script_dir
/sudossh
$board2
"motor-scripts/motor-init"
;
$script_dir
/sudossh
$board1
"motor-scripts/motor-cw"
;
$script_dir
/sudossh
$board2
"motor-scripts/motor-ccw"
;
fi
if
[
-n
"
$start_servers
"
]
;
then
$script_dir
/sudossh
$board1
"killall server"
;
$script_dir
/sudossh
$board2
"killall server"
;
$script_dir
/exec-ssh-nohup
$board1
"run-server -c
$interval
$server_opts
"
server_log
;
$script_dir
/exec-ssh-nohup
$board2
"run-server -c
$interval
$server_opts
"
server_log
;
sleep
5
;
fi
echo
"
$script_dir
/run-client -i 40000 -c
$delay
-U 100 enp1s0
$board1
enp2s0
$board2
"
;
$script_dir
/run-client
-i
40000
-c
$delay
-U
100 enp1s0
$board1
enp2s0
$board2
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment