Tomas Kalibera wrote:
> Hi,
>
> is it possible, in user-space, to wait for a set of hardware interrupts
> ? Something like UNIX select, which allows to wait for multiple devices
> to become ready...
>
> Or do I need to spawn a dedicated thread for each interrupt to wait for ?
There are two answers to this question: if you use the native skin
services, and/or the various interrupt you want to wait for belongs to
the same driver, you may use the native skin event flags services. Each
interrupt handler would call rt_event_signal to signal a different bit
in the rt_event object, and you would wait for events with the
rt_event_wait service.
But Xenomai also has a select service (for now, only the posix skin
proposes this service), which looks more adapted if each interrupt
handler belongs to a different driver. If you want to use it, you will
have to implement a select_bind callback for each RTDM driver you want
to select from. For instance, if an RTDM driver looks like:
typedef struct mydriver_context {
/* ... */
rtdm_sem_t pending_sem;
/* ... */
} mydriver_context_t;
int mydriver_irq_handler(rtdm_irq_t *irq)
{
mydriver_context_t *context = /* ... */
rtdm_sem_up(&context->pending_sem);
/* ... */
}
ssize_t mydriver_read(struct rtdm_dev_context *context,
rtdm_user_info_t *user_info,
void *buf, size_t nbyte)
{
/* ... */
mydriver_context_t *mydriver_context =
(mydriver_context_t *)&context->dev_private;
int err;
/* ... */
err = rtdm_sem_down(&mydriver_context->pending_sem);
/* ... */
}
static struct rtdm_device mydriver_device {
/* ... */
.ops = {
/* ... */
.read_rt = mydriver_read;
/* ...*/
};
static int __init mydriver_init(void)
{
int err = rtdm_dev_register(&mydriver_device);
/* ... */
}
All you have to do is to write:
int mydriver_select_bind(struct rtdm_dev_context *context,
struct xnselector *selector,
unsigned type,
unsigned index)
{
mydriver_context_t *mydriver_context =
(mydriver_context_t *)&context->dev_private;
int err;
if (type == RTDM_SELECTTYPE_READ)
err = rtdm_sem_select_bind(&mydriver_context->pending_sem,
selector, type, index);
else
err = -EBADF;
return err;
}
And add in mydriver_device declaration:
static struct rtdm_device mydriver_device {
/* ... */
.ops = {
/* ... */
.select_bind = mydriver_select_bind;
/* ...*/
};
You do not have to worry very much about the performance of the
mydriver_select_bind callback: contrarily to what happens with a Linux
driver, it will be called only the first time mydriver's file descriptor
is passed to select, after that, select does all the housekeeping (the
select block gets updated by each call to rtdm_sem_up and rtdm_sem_down).
I took rtdm_sem_t as an example, but rtdm_event_t also has builtin
support for (there is an rtdm_event_select_bind service that can be
called in the implementation of a driver's select_bind callback).
Also note this scheme works well if a driver signals a semaphore (or
event) whether there is a pending reader or not, as showed in the
example. For instance, adapting Xenomai serial driver to select would be
a bit more complicated, because the driver only signals an event if
there is a pending reader, whereas we want the select block to be
updated even when there is no thread blocked in the select service.
--
Gilles.
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help