[etherlab-dev] Xenomai RTDM

Rob Stocks rjs at computerway.biz
Wed Oct 10 16:48:04 CEST 2012


I have just tried the recently reworked RTDM interface of the EtherCAT
master with Xenomai 2.6.1 on Linux 3.2.21 with a e1000e network card and I
have to say that it works very well!

However, although the example Xenomai application works without problem, I
found that my own Xenomai application did not. After some investigation, I
found that this was because I was calling the ecrt_master_activate function
from a Xenomai real-time task in primary mode (rather than from a standard
Linux process as per the example code). The problem is that activating the
master causes the idle thread to be stopped via kthread_stop which cannot
be run in a real-time context and causes the kernel to panic with
"scheduling while atomic".

The current implementation uses the same ioctl function for real-time and
non real-time callers and does not check the mode of the caller in order to
return -ENOSYS to get the caller to try again in the opposite context. I
added a check in the ec_rtdm_ioctl() function (in master/rtdm.c) and
if rtdm_in_rt_context() returns true and the request is EC_IOCTL_ACTIVATE,
return -ENOSYS. This makes the caller switch to secondary mode and try
again. On the second occasion, the code continues to the ec_ioctl_rtdm
function as normal. This fixes the problem for activate. However, I also
noted a similar problem with EC_IOCTL_CREATE_SLAVE_CONFIG if called from a
real-time context so I added this case to my check and now it all works
perfectly. I suspect that there may be other IOCTLs that cannot be called
safely from a (primary mode) real-time context and therefore need adding to
this check.

My revised code for ec_rtdm_ioctl() is:

int ec_rtdm_ioctl(
        struct rtdm_dev_context *context, /**< Context. */
        rtdm_user_info_t *user_info, /**< User data. */
        unsigned int request, /**< Request. */
        void __user *arg /**< Argument. */
        )
{
    ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private;
    ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *)
context->device->device_data;

*    if (rtdm_in_rt_context())*
*    {*
*        switch (request)*
*        {*
*        case EC_IOCTL_ACTIVATE:*
*        case EC_IOCTL_CREATE_SLAVE_CONFIG:*
*            return -ENOSYS;*
*        }*
*    }*

#if DEBUG
    EC_MASTER_INFO(rtdm_dev->master, "ioctl(request = %u, ctl = %02x)"
            " on RTDM device %s.\n", request, _IOC_NR(request),
            context->device->device_name);
#endif
    return ec_ioctl_rtdm(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
}


Note that if using the generic driver, you will have more kernel
"complaints" as there are situations where the xmit function cannot be
called safely from a real-time context. If you add the EC_IOCTL_SEND case
to the above, you will not have hard real-time support as the calling task
will always be switching in and out of secondary mode. This may not be an
issue depending on the application but it should not be added as standard
because it will unnecessarily break hard real-time support when using a
ported driver (such as e1000e).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.etherlab.org/pipermail/etherlab-dev/attachments/20121010/e525765e/attachment.htm>


More information about the etherlab-dev mailing list