[Xenomai] RTDM driver init: interrupts and context objects

andrija at stupar.com andrija at stupar.com
Fri Mar 3 05:10:00 CET 2017

Hi Philippe,

Thank you very much for your earlier response. I have figured that part 
of the driver out and opening and requesting an interrupt line works 
well. Also, upon an interrupt, an interrupt service routine is executed 
as expected. However I have one remaining problem I hope you could help 
me out with. For interrupt-driven A/D conversion, the hardware I am 
using works like this: 1) I write to a register to initiate 
interrupt-driven A/D conversion 2) the write call then goes to sleep 
until data is ready 3) an interrupt handler awakens the write call 4) 
the write call returns and 5) the code which made the write call now 
knows that it should read data from an input register.

In the original driver, the code doing steps 1), 2) and 4) looks like 

wqc = 0;       /* indicate waiting */
writew( (int)ldata, (void *)(*adata) );
wait_event_interruptible(ain_queue, wqc);
wqc = 2;       /* indicate complete */
.... return (...) ;

Since interrupts in RTDM work slightly differently and there is no wait 
queue in the RTDM/Xenomai version I am using, I ported the above code to 
RTDM like this:

writew( (int)ldata, (void *)(*adata) );
if (!my_context->data_flag) {
	 my_context->wait_flag = TRUE; /* indicate waiting */
          if (rtdm_event_wait(&my_context->apc8620_wait)) { /* wait */
                        my_context->wait_flag = FALSE;
                        return ( -ERESTARTSYS );
/* indicate complete */
my_context->data_flag = FALSE;
my_context->wait_flag = FALSE;
.... return (...) ;

In the original driver, step 3) is the in the interrupt handler function 
and looks like this:

if( wqc == 0)        /* waiting for a blocked start convert AND an 
interrupt from the input board */
      wqc = 1;               /* when received, change the condition to 
true... */
       wake_up_interruptible(&ain_queue);	 /* ... and wake the blocked 
write */

My port of the above to RTDM is:

if (my_context->wait_flag && !(my_context->data_flag)) {
       	 my_context->data_flag = TRUE;
          my_context->wait_flag = FALSE;

My understanding is that the above two pairs of code snippets (vanilla 
Linux and RTDM) do the same thing, functionally. However they do not. 
The interrupt driven A/D conversion is defined by a timer which can be 
set to some range of values (e.g. 1 second). However it seems that the 
board generates interrupts for other reasons as well.

When I run this using the Linux driver, my write call that initiates 
sleeps for about a second (i.e. the timer period) and then returns, and 
then there is data to read. When I run this running my RTDM driver, my 
write call sleeps much less, it returns almost immediately, and there is 
no data to read.

My question is therefore - have I made some obvious mistake in porting 
the regular interrupts to RTDM interrupts in the code above? Am I using 
RTDM interrupts correctly here? Or is the code I've written expectedly 
behaving differently from the original code?

Thanks for any help.

Best regards,

Andrija Stupar

On 2017-02-24 04:03, Philippe Gerum wrote:

> No issue with that. Any call site from a regular kernel context (i.e.
> not Xenomai's primary/rt mode) will do.
> A context in the usual sense applies to a particular _connection_ to a
> device, i.e. per-fd, not to the device itself. In that sense, the 
> open()
> handler setting up a connection may refer to some global data for
> retrieving the setup information about the particular device instance
> the connection refers to. Since init_module() only knows about device
> instances, you need some proxy data structure to expose the device
> information to the open() handler.

More information about the Xenomai mailing list