Skip to content

Commit 36e1737

Browse files
committed
EVL: Start xenomai4
1 parent 2aee010 commit 36e1737

3 files changed

Lines changed: 232 additions & 1 deletion

File tree

src/configure.ac

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,15 @@ AC_SUBST([RTAI_CONFIG])
212212
AC_PATH_PROG([XENOMAI_CONFIG], [xeno-config], [none])
213213
AC_SUBST([XENOMAI_CONFIG])
214214

215+
#Just check a header to decide if EVL is installed
216+
AC_CHECK_HEADER([evl/thread.h],[
217+
AC_MSG_NOTICE([libevl evl/thread.h found, building xenomai4 (EVL)])
218+
CONFIG_USPACE_XENOMAI_EVL=y
219+
],[
220+
AC_MSG_NOTICE([libevl evl/thread.h missing, not building xenomai4 (EVL)])
221+
CONFIG_USPACE_XENOMAI_EVL=n
222+
])
223+
215224
AC_MSG_CHECKING([for realtime API(s) to use])
216225
if test "$RTS" = uspace || test -z "$RTS" -a "$RTAI_CONFIG" = "none" ; then
217226
RTS=uspace
@@ -243,11 +252,23 @@ if test "$RTS" = uspace || test -z "$RTS" -a "$RTAI_CONFIG" = "none" ; then
243252
XENOMAI_LDFLAGS=`$XENOMAI_CONFIG --skin posix --ldflags`
244253
AC_DEFINE([USPACE_XENOMAI], [], [Define if uspace realtime should optionally support Xenomai])
245254
fi
255+
256+
if test "$CONFIG_USPACE_XENOMAI_EVL" = "n" ; then
257+
USPACE_XENOMAI_EVL=
258+
XENOMAI_EVL_CFLAGS=
259+
XENOMAI_EVL_LDFLAGS=
260+
else
261+
USPACE_XENOMAI_EVL=+xenomai4
262+
XENOMAI_EVL_CFLAGS=
263+
XENOMAI_EVL_LDFLAGS=-levl
264+
AC_DEFINE([USPACE_XENOMAI_EVL], [], [Define if uspace realtime should optionally support Xenomai])
265+
fi
266+
246267
AC_SUBST([CONFIG_USPACE_XENOMAI])
247268
AC_SUBST([XENOMAI_CFLAGS])
248269
AC_SUBST([XENOMAI_LDFLAGS])
249270

250-
AC_MSG_RESULT([$RTS$USPACE_RTAI$USPACE_XENOMAI])
271+
AC_MSG_RESULT([$RTS$USPACE_RTAI$USPACE_XENOMAI$USPACE_XENOMAI_EVL])
251272

252273
AC_MSG_CHECKING([whether to enable userspace PCI access])
253274
AC_ARG_ENABLE(userspace-pci,

src/rtapi/Submakefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,14 @@ $(call TOOBJSDEPS, $(USPACE_XENOMAI_SRCS)): EXTRAFLAGS += -fPIC $(XENOMAI_CFLAGS
6868
TARGETS += ../lib/libuspace-xenomai.so.0
6969
TARGETS += ../lib/libuspace-xenomai.so
7070
endif
71+
72+
ifeq ($(CONFIG_USPACE_XENOMAI_EVL),y)
73+
USPACE_XENOMAI_EVL_SRCS := rtapi/uspace_xenomai_evl.cc
74+
USERSRCS += $(USPACE_XENOMAI_EVL_SRCS)
75+
$(call TOOBJSDEPS, $(USPACE_XENOMAI_EVL_SRCS)): EXTRAFLAGS += -fPIC $(XENOMAI_EVL_CFLAGS)
76+
../lib/libuspace-xenomai-evl.so.0: $(call TOOBJS, $(USPACE_XENOMAI_EVL_SRCS))
77+
$(ECHO) Linking $(notdir $@)
78+
$(Q)$(CXX) -shared $(LDFLAGS) -o $@ $^ $(XENOMAI_EVL_LDFLAGS) -Wl,-soname,$(notdir $@)
79+
TARGETS += ../lib/libuspace-xenomai-evl.so.0
80+
TARGETS += ../lib/libuspace-xenomai-evl.so
81+
endif

src/rtapi/uspace_xenomai_evl.cc

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
#include "config.h"
2+
#include "rtapi.h"
3+
#include "rtapi_uspace.hh"
4+
#include <pthread.h>
5+
#include <errno.h>
6+
#include <stdio.h>
7+
#include <cstring>
8+
#ifdef HAVE_SYS_IO_H
9+
#include <sys/io.h>
10+
#endif
11+
12+
namespace
13+
{
14+
struct RtaiTask : rtapi_task {
15+
RtaiTask() : rtapi_task{}, cancel{}, thr{} {}
16+
std::atomic_int cancel;
17+
pthread_t thr;
18+
};
19+
20+
21+
struct XenomaiApp : RtapiApp {
22+
XenomaiApp() : RtapiApp(SCHED_FIFO) {
23+
pthread_once(&key_once, init_key);
24+
}
25+
26+
RtaiTask *do_task_new() {
27+
return new RtaiTask;
28+
}
29+
30+
int task_delete(int id) {
31+
auto task = ::rtapi_get_task<RtaiTask>(id);
32+
if(!task) return -EINVAL;
33+
34+
task->cancel = 1;
35+
pthread_join(task->thr, nullptr);
36+
task->magic = 0;
37+
task_array[id] = 0;
38+
delete task;
39+
return 0;
40+
}
41+
42+
int task_start(int task_id, unsigned long period_nsec) {
43+
auto task = ::rtapi_get_task<RtaiTask>(task_id);
44+
if(!task) return -EINVAL;
45+
46+
task->period = period_nsec;
47+
struct sched_param param;
48+
memset(&param, 0, sizeof(param));
49+
param.sched_priority = task->prio;
50+
51+
// limit PLL correction values to +/-1% of cycle time
52+
task->pll_correction_limit = period_nsec / 100;
53+
task->pll_correction = 0;
54+
55+
cpu_set_t cpuset;
56+
CPU_ZERO(&cpuset);
57+
int nprocs = sysconf( _SC_NPROCESSORS_ONLN );
58+
CPU_SET(nprocs-1, &cpuset); // assumes processor numbers are contiguous
59+
60+
int ret;
61+
pthread_attr_t attr;
62+
if((ret = pthread_attr_init(&attr)) != 0)
63+
return -ret;
64+
if((ret = pthread_attr_setstacksize(&attr, task->stacksize)) != 0)
65+
return -ret;
66+
if((ret = pthread_attr_setschedpolicy(&attr, policy)) != 0)
67+
return -ret;
68+
if((ret = pthread_attr_setschedparam(&attr, &param)) != 0)
69+
return -ret;
70+
if((ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) != 0)
71+
return -ret;
72+
if(nprocs > 1)
73+
if((ret = pthread_attr_setaffinity_np(&attr, sizeof(cpuset), &cpuset)) != 0)
74+
return -ret;
75+
if((ret = pthread_create(&task->thr, &attr, &wrapper, reinterpret_cast<void*>(task))) != 0)
76+
return -ret;
77+
78+
return 0;
79+
}
80+
81+
static void *wrapper(void *arg) {
82+
auto task = reinterpret_cast<RtaiTask*>(arg);
83+
pthread_setspecific(key, arg);
84+
85+
struct timespec now;
86+
clock_gettime(CLOCK_MONOTONIC, &now);
87+
88+
// originally, I used pthread_make_periodic_np here, and
89+
// pthread_wait_np in wait(), but in about 1 run in 50 this led to
90+
// "xenomai: watchdog triggered" and rtapi_app was killed.
91+
//
92+
// encountered on: 3.18.20-xenomai-2.6.5 with a 2-thread SMP system
93+
rtapi_timespec_advance(task->nextstart, now, task->period + task->pll_correction);
94+
95+
(task->taskcode) (task->arg);
96+
97+
rtapi_print("ERROR: reached end of wrapper for task %d\n", task->id);
98+
return nullptr;
99+
}
100+
101+
int task_pause(int task_id) {
102+
return -ENOSYS;
103+
}
104+
105+
int task_resume(int task_id) {
106+
return -ENOSYS;
107+
}
108+
109+
long long task_pll_get_reference(void) {
110+
struct rtapi_task *task = reinterpret_cast<rtapi_task*>(pthread_getspecific(key));
111+
if(!task) return 0;
112+
return task->nextstart.tv_sec * 1000000000LL + task->nextstart.tv_nsec;
113+
}
114+
115+
int task_pll_set_correction(long value) {
116+
struct rtapi_task *task = reinterpret_cast<rtapi_task*>(pthread_getspecific(key));
117+
if(!task) return -EINVAL;
118+
if (value > task->pll_correction_limit) value = task->pll_correction_limit;
119+
if (value < -(task->pll_correction_limit)) value = -(task->pll_correction_limit);
120+
task->pll_correction = value;
121+
return 0;
122+
}
123+
124+
void wait() {
125+
int task_id = task_self();
126+
auto task = ::rtapi_get_task<RtaiTask>(task_id);
127+
if(task->cancel) {
128+
pthread_exit(nullptr);
129+
}
130+
rtapi_timespec_advance(task->nextstart, task->nextstart, task->period + task->pll_correction);
131+
struct timespec now;
132+
clock_gettime(CLOCK_MONOTONIC, &now);
133+
if(rtapi_timespec_less(task->nextstart, now))
134+
{
135+
if(policy == SCHED_FIFO)
136+
unexpected_realtime_delay(task);
137+
}
138+
else
139+
{
140+
int res = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &task->nextstart, nullptr);
141+
if(res < 0) perror("clock_nanosleep");
142+
}
143+
}
144+
145+
unsigned char do_inb(unsigned int port) {
146+
#ifdef HAVE_SYS_IO_H
147+
return inb(port);
148+
#else
149+
return 0;
150+
#endif
151+
}
152+
153+
void do_outb(unsigned char val, unsigned int port) {
154+
#ifdef HAVE_SYS_IO_H
155+
return outb(val, port);
156+
#else
157+
return 0;
158+
#endif
159+
}
160+
161+
int run_threads(int fd, int (*callback)(int fd)) {
162+
while(callback(fd)) { /* nothing */ }
163+
return 0;
164+
}
165+
166+
int task_self() {
167+
struct rtapi_task *task = reinterpret_cast<rtapi_task*>(pthread_getspecific(key));
168+
if(!task) return -EINVAL;
169+
return task->id;
170+
}
171+
172+
static pthread_once_t key_once;
173+
static pthread_key_t key;
174+
static void init_key(void) {
175+
pthread_key_create(&key, NULL);
176+
}
177+
178+
long long do_get_time() {
179+
struct timespec ts;
180+
clock_gettime(CLOCK_MONOTONIC, &ts);
181+
return ts.tv_sec * 1000000000LL + ts.tv_nsec;
182+
}
183+
184+
void do_delay(long ns) {
185+
struct timespec ts = {0, ns};
186+
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, nullptr);
187+
}
188+
};
189+
190+
pthread_once_t XenomaiApp::key_once;
191+
pthread_key_t XenomaiApp::key;
192+
}
193+
194+
extern "C" RtapiApp *make();
195+
196+
RtapiApp *make() {
197+
rtapi_print_msg(RTAPI_MSG_ERR, "Note: Using XENOMAI (posix-skin) realtime\n");
198+
return new XenomaiApp;
199+
}

0 commit comments

Comments
 (0)