On Sun, Jun 29, 2014 at 12:29:50PM +0200, Marius Liebenberg wrote:
> Hi Jeff,
> I have been following your thread with great interest. I am not to clued 
> up with the different flavours of kernels and RTAI interfaces though. 
> Would it be possible to give us laymen a simple description of what your 
> work means to us, what it intends to achieve and what we have to look 
> for when testing it. I mean a real high level description please.

Short version:

These patches enable linuxcnc to run with a different realtime kernel,
RT-PREEMPT.  A compatible kernel is packaged by Debian, which means less
work by linuxcnc developers to run on a new OS version.  Because it has
higher latency than RTAI on most systems, this kernel isn't good for
software step generation, but is good for use with smart FPGA boards.
Since this version runs realtime code in userspace, it may make a good
basis for drivers that work with ethernet motion control cards like the
Mesa 7i80 family.

The RT-PREEMPT kernel's home page is
https://rt.wiki.kernel.org/index.php/Main_Page


Long version:

There are multiple choices for realtime kernels on Linux, and they each
have trade-offs.

For a very long time, the linuxcnc project has only been able to work
with the "RTAI" realtime kernels.  On a wide range of hardware (but by
no means all hardware), "RTAI" provides realtime performance that is
suitable for software step generation and in a few cases software
encoder counting.  However, at times the RTAI project has lagged far
behind in kernel version support as well as availability on non-i386
architectures.  Also, no linux distro offers a RTAI kernel, so the
linuxcnc project has to build one themselves.  This requirement, more
than any other dependency of linuxcnc, is the reason that we are slow to
offer packages for new operating system versions.

Another realtime kernel is the RT-PREEMPT kernel.  This project seems to
have a lot more traction (though it also lags behind the mainline of
kernel development), and more importantly, Debian offers "-rt" kernels
with RT-PREEMPT patches.  (Ubuntu seems to also offer -rt and/or
-realtime kernels, but I am less familiar with the details on Ubuntu)
Generally, the realtime performance of RT-PREEMPT is too slow for
software step generation, so it's likely only to be useful for systems
where you have motion control hardware like the various FPGA cards that
work with linuxcnc.  We couldn't switch to *only* RT-PREEMPT without
leaving some of our users behind.


My project is about supporting the RT-PREEMPT kernel (in addition to the
RTAI kernel).  This has all happened before, most recently by the people
now working on the "machinekit" project, a linuxcnc derivative.  The
main problem with adopting their work into linuxcnc was that work that
many linuxcnc developers wanted (support for RT-PREEMPT kernels) was
mixed with work that at least a few developers (including me) did not
want (such as an unfinished web interface to linuxcnc).  Our inability
to resolve this impasse is in part why the machinekit people are now
choosing to go their own way.

My work builds on the existing userspace simulator, sim_rtapi, but
changes it to use the standard Unix API for multithreaded software,
pthreads.  It also provides rtapi versions of the kernel functions used
in the hal components "serport", "hostmot2", "hm2_pci" and "hm2_test",
so that these hardware drivers can now be loaded either in traditional
RTAI kernel realtime systems and in the new RT-PREEMPT userspace
realtime system.  The framework should allow other hardware drivers to
be adapted too, though for smart parallel (EPP) boards some additional
groundwork will be required.  So far, I've only adapted drivers for
hardware I own and can personally test.

Before talking a little bit more about what I find unfavorable in the
machinekit code, I want to again emphasize that their code was very
useful to study as I worked on this project, and that two specific parts
(harden_rt and rtapi_pci) are adaptations of their GPL-licensed work,
rather than my own original work.


First off, as I touched on earlier, the branch that they proposed to
merge into linuxcnc.org's master branch (unified-build-candidate-3)
included a number of unrelated projects.  The organization of their
branch meant that we could choose either to merge all of it, or to merge
none of it.  Ultimately, this meant that no developers could give a
resounding "yes" to the merge, and some developers (including me) had to
come down on the side of "no" due to the unwanted parts.  Git gives this
summary of the changes in unified-build-candidate-3:
    1412 commits, 645 files changed, 89622 insertions(+), 10373 deletions(-)
while my branch, which has a focused purpose (what git calls a "topic
branch"):
    29 commits, 93 files changed, 4146 insertions(+), 2251 deletions(-)
and it is organized in three separate phases which could be merged in
three steps if that's how review proceeds.

Second, there's a specific kind of bad design to the kernel-and-
userspace portability layer in machinekit: they ended up adding a lot
more #ifs to the driver code.  One example, from the motenc driver
(which admittedly I have not yet converted):

diff --git a/src/hal/drivers/hal_motenc.c b/src/hal/drivers/hal_motenc.c
--- a/src/hal/drivers/hal_motenc.c
+++ b/src/hal/drivers/hal_motenc.c
@@ -291,8 +301,11 @@ rtapi_app_main(void)
 
     i = 0;
     // Find a MOTENC card.
-    while((i < MAX_DEVICES) && ((pDev = pci_get_device(MOTENC_VENDOR_ID, 
MOTENC_DEVICE_ID, pDev)) != NULL)){
-
+#if defined(BUILD_SYS_USER_DSO)
+    while((i < MAX_DEVICES) && ((pDev = rtapi_pci_get_device(MOTENC_VENDOR_ID, 
MOTENC_DEVICE_ID, pDev)) != NULL)){
+#else
+       while((i < MAX_DEVICES) && ((pDev = pci_get_device(MOTENC_VENDOR_ID, 
MOTENC_DEVICE_ID, pDev)) != NULL)){
+#endif
        // Allocate memory for device object.
        pDevice = hal_malloc(sizeof(Device));
 
There are many such #if defined checks, each one turning what should
have been one line into 5. In my design, the function
rtapi_pci_get_device exists whether you are in kernel or user, so
hardware drivers can simply call the one required function.  Some
conditional compilation is required in a header, but the use sites all
look nice and clean.  In my branch, assuming I implemented
rtapi_pci_get_device yet, the change would be

-    while((i < MAX_DEVICES) && ((pDev = pci_get_device(MOTENC_VENDOR_ID, 
MOTENC_DEVICE_ID, pDev)) != NULL)){
+    while((i < MAX_DEVICES) && ((pDev = rtapi_pci_get_device(MOTENC_VENDOR_ID, 
MOTENC_DEVICE_ID, pDev)) != NULL)){

i.e., just prefix with "rtapi_".

Jeff

------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Emc-developers mailing list
Emc-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/emc-developers

Reply via email to