- From: L.C. Karssen <l.c.karssen_at_phys.uu.nl>
- Date: Wed, 23 May 2007 22:17:49 +0200
Thanks for your help again Paolo!
On Wed, 2007-05-23 at 22:12 +0200, Paolo Mantegazza wrote:
> L.C. Karssen wrote:
> > After getting rid of the syscalls during hard RT as described below, I
> > found that the DIO lines are no longer being flipped. Only the analog
> > out works.
> > When I replaced the call to comedi_dio_bitfield() with 8 calls to
> > comedi_dio_write() (one for each DIO channel) it works again.
> > Unfortunately this takes too much time. I set a period of 20us, but when
> > I record the time using rt_get_time_ns to check the time difference
> > between to successive iterations of my for-loop I see that about once in
> > every three iterations the time difference is 40us, indicating that the
> > execution took more that one period.
> >
>
> One of the known "beuties" of using PCs for hard real time is that
> execution time of the very same stuff is not the same always, especially
> if you do some IO.
I understand that there may be a small time difference each time you run
code that does IO. However, I don't think it should be more than 10us.
The way I understand it, comedi_dio_bitfield() sets all the bits at once
(which is what I want). And of course calling comedi_dio_write() 8 times
costs more time. For my experiments I would like to have as short a
timing as possible. Therefore 20us is much better that the 40us it takes
when using 8 comedi_dio_writes().
The point I was trying to make was that I don't see any output on the
oscilloscope when looking at the DIO lines. The AO works OK. So it looks
like writing DIO with the bitfield-function in hard RT (when
#include-ing rtai_comedi.h) doesn't work.
>
> > Just to emphasise that my usage of comedi_dio_bitfield() is in principle
> > OK: Using comedi_dio_bitfield() in my code works when including
> > comedilib.h instead of rtai_comedi.h (but this results in syscalls being
> > made).
> >
>
> I'm wondering why you do not try to track the problem by making a direct
> call both with comedi and using RTAI call, without hard real mode, just
> to see where the problem is. In my view it is likely just a matter of a
> few printf and prink at right places, possibly including comedi function
> to follow the whole path.
I'm not sure how I should do that. How can I distinguish between
comedi_dio_bitfield() being called through the RTAI wrapper (so with
rtai_comedi.h) and comedi_dio_bitfield() in its "normal" form (so with
the comedilib.h file #included)? I can't have both function definitions
in the same program, can I?
B.t.w., I'm a physicist, not a programmer, so maybe I'm missing
something basic here.
>
> > So, can anybody tell me if using comedi_dio_bitfield() in hard RT works
> > for him/her? In RTAILabs rtai_comedi_dioout.c I see that only
> > comedi_dio_write() is used. I also noticed that rtai_comedi.h doesn't
> > have a wrapper for the (new) comedi_dio_bitfield2() function (which is
> > supposed to supersede the comedi_dio_bitfield() function if I'm not
> > mistaken).
>
> It is simple to add the wrapper and test it, see above. just the
> declaration and a new cal number in rtai_comedi.h the related call and
> table insertion in the module, Likely a cut and paste with few changes.
I tried to do as you suggested. This is what I did:
- In /usr/src/rtai/addons/comedi/rtai_comedi.h I added the line
#define _KCOMEDI_DIO_BITFIELD2 29
just above the deprecated GET_RANGETYPE and after the POLL line. I also
copied and edited the prototype of the ordinary bitfield function:
RTAI_PROTO(int, comedi_dio_bitfield2,(void *dev, unsigned int subdev,
unsigned int mask, unsigned int *bits, unsigned int base_channel))
{
int retval;
unsigned int lbits;
struct { void *dev; unsigned int subdev; unsigned int mask;
unsigned int *bits; unsigned int base_channel; } arg = { dev, subdev,
mask, &lbits, base_channel };
retval = rtai_lxrt(FUN_COMEDI_LXRT_INDX, COMEDI_LXRT_SIZARG,
_KCOMEDI_DIO_BITFIELD2, &arg).i[LOW];
*bits = lbits;
return retval;
- In /usr/src/rtai/addons/comedi/kcomedi_module.c I copied and adapted
the bitfield RTAI_SYSCALL_MODE line:
static RTAI_SYSCALL_MODE int _comedi_dio_bitfield2(void *dev, unsigned
int subdev, unsigned int mask, unsigned int *bits, unsigned int
base_channel)
{
return comedi_dio_bitfield2(dev, subdev, mask, bits, base_channel);
}
Then, in the rtai_comedi_fun[] struct I added the line
,[_KCOMEDI_DIO_BITFIELD2] = { 0, _comedi_dio_bitfield2 }
below the line with ,[_KCOMEDI_POLL] = { 0, comedi_poll }
(so that it was in the same order as in the rtai_comedi.h file. A bit
further down I added the line .
,[_KCOMEDI_DIO_BITFIELD2] = { 0, comedi_dio_bitfield2 }
But when I run make in this directory I get a long list of errors,
starting with:
/usr/src/rtai/addons/comedi/kcomedi-module.c: At top level:
/usr/src/rtai/addons/comedi/kcomedi-module.c:401: error:
`comedi_dio_bitfield2' undeclared here (not in a function)
/usr/src/rtai/addons/comedi/kcomedi-module.c:401: error: initializer
element is not constant
/usr/src/rtai/addons/comedi/kcomedi-module.c:401: error: (near
initialization for `rtai_comedi_fun[29].fun')
/usr/src/rtai/addons/comedi/kcomedi-module.c:401: error: initializer
element is not constant
/usr/src/rtai/addons/comedi/kcomedi-module.c:401: error: (near
initialization for `rtai_comedi_fun[29]')
I have no idea what's missing here.
>
> Paolo.
>
> >
> >
> > Thanks,
> >
> > Lennart.
> >
> >
> > On Tue, 2007-05-22 at 14:09 +0000, L.C. Karssen wrote:
> >
> >>I think I solved/worked around the problem. I don't include comedilib.h
> >>anymore and I changed the comedi_t pointer for a comedi device to a void
> >>pointer (as expected by rtai_comedi.h). Furthermore I removed all
> >>references to the comedi_range struct and the calls to
> >>comedi_get_range() and comedi_perror(). These functions are not defined
> >>in rtai_comedi.h (but are defined in comedilib.h, which I no lnger
> >>include).
> >>This removes any errors about either missing or double definitions.
> >>No more syscalls are added to /proc/rtai/scheduler. Everything seems to
> >>work now.
> >>
> >>It's probably not the nicest solution, but it works. If somebody has a
> >>better solution, I'll be glad to hear it.
> >>
> >>
> >>Lennart.
> >>
> >>On Mon, 2007-05-21 at 19:09 +0200, L.C. Karssen wrote:
> >>
> >>>On Mon, 2007-05-21 at 16:30 +0000, L.C. Karssen wrote:
> >>>
> >>>>On Mon, 2007-05-21 at 19:52 +0200, Paolo Mantegazza wrote:
> >>>>
> >>>>>L.C. Karssen wrote:
> >>>>>
> >>>>>>On Mon, 2007-05-21 at 09:42 +0000, L.C. Karssen wrote:
> >>>>>>
> >>>>>>
> >>>>>>>On Sun, 2007-05-13 at 23:37 +0200, Paolo Mantegazza wrote:
> >>>>>>>
> >>>>>>>
> >>>>>>>>L.C. Karssen writes:
> >>>>>>>>
> >>>>>>>>
> >>>>
> >>>>Furthermore, I looked at rtai_comedi_dioout.c from RTAILab and found
> >>>>that it includes rtai_comedi.h. I have the following RTAI and comedi
> >>>>related includes:
> >>>>#include "/usr/local/include/comedilib.h"
> >>>>#include <rtai_lxrt.h>
> >>>>
> >>>>I included rtai_comedi.h but that resulted in a lot of errors because of
> >>>>overshadowed definitions (because of comedilib.h).
> >>>
> >>>An example of such an error:
> >>>
> >>>In file included from daqwrite.c:25:
> >>>/usr/realtime/include/rtai_comedi.h:123: error: conflicting types for
> >>>'comedi_open'
> >>>/usr/local/include/comedilib.h:68: error: previous declaration of
> >>>'comedi_open' was here
> >>>
> >>>
> >>>In comedilib.h:68:
> >>>comedi_t *comedi_open(const char *fn);
> >>>
> >>>In rtai_comedi.h:123:
> >>>RTAI_PROTO(void *, comedi_open,(const char *filename))
> >>>{
> >>> char lfilename[COMEDI_NAMELEN];
> >>> struct { char *minor; } arg = { lfilename };
> >>> strncpy(lfilename, filename, COMEDI_NAMELEN - 1);
> >>> return rtai_lxrt(FUN_COMEDI_LXRT_INDX, COMEDI_LXRT_SIZARG,
> >>>_KCOMEDI_OPEN, &arg).v[LOW];
> >>>}
> >>>
> >>>
> >>>
> >>>>When only including
> >>>>rtai_comedi.h I get a lot of syntax errors. I'm going to check why that
> >>>>happens.
> >>>
> >>>When not including /usr/local/comedilib.h I get errors because of
> >>>missing definitions of e.g. comedi_t, comedi_range and comedi_dev. The
> >>>typedefs of these are in comedilib.h.
> >>>I need those to initialise my comedi device, as in the following code
> >>>for example:
> >>> comedi_t *comedi_dev;
> >>> comedi_dev = comedi_open(comedi_devname);
> >>>
> >>>
> >>>Lennart
> >>>
> >>>
> >>>>Thanks,
> >>>>
> >>>>Lennart
> >>>>
> >>>>>Paolo
> >>>>>
> >>>>>
> >>>>>>
> >>>>>>>Any help is appreciated!
> >>>>>>>
> >>>>>>>
> >>>>>>>Lennart.
> >>>>>>>
> >>>>>>>
> >>>>>>>int do_comedi(struct data_struct *options)
> >>>>>>>{
> >>>>>>> comedi_t *comedi_dev = options->device;
> >>>>>>> unsigned int ao_subdev = options->AO_subdevice; // Analog Output
> >>>>>>> unsigned int dio_subdev = options-> DIO_subdevice; // Digital IO
> >>>>>>> int range=0; // AO has only one range: 10V -> -10V
> >>>>>>> comedi_insn insn;
> >>>>>>> lsampl_t data;
> >>>>>>> unsigned int dio_bits;
> >>>>>>> int aref = AREF_GROUND;
> >>>>>>> unsigned int dio_mask = 0xFFFFFFFF; // Tells which DIO bits are to
> >>>>>>>be flipped (all).
> >>>>>>>
> >>>>>>> int period;
> >>>>>>> struct bits *data_arr = options->bitsarr;
> >>>>>>>
> >>>>>>> RT_TASK* task;
> >>>>>>> int priority=0;
> >>>>>>> int stack_size=4096;
> >>>>>>> int msg_size=0;
> >>>>>>>
> >>>>>>> int i;
> >>>>>>>
> >>>>>>> /* Prepare the AO instruction as much as possible. Later, in real
> >>>>>>>time
> >>>>>>> * we'll only fill in the data sample. */
> >>>>>>> insn.insn = INSN_WRITE;
> >>>>>>> insn.n = 1;
> >>>>>>> insn.subdev = ao_subdev;
> >>>>>>>
> >>>>>>> /* A better scheduler than linux' one */
> >>>>>>> struct sched_param mysched;
> >>>>>>>
> >>>>>>> /* We don't want to be swapped out the mem */
> >>>>>>> mlockall (MCL_CURRENT | MCL_FUTURE);
> >>>>>>> /* Allow nonroot users hard realtime access */
> >>>>>>> rt_allow_nonroot_hrt();
> >>>>>>>
> >>>>>>> /* Initialise Scheduler as SCHED_FIFO. Greatly improves scheduler!
> >>>>>>>*/
> >>>>>>> mysched.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1;
> >>>>>>> if( sched_setscheduler( 0, SCHED_FIFO, &mysched ) == -1 )
> >>>>>>> {
> >>>>>>> fprintf(stderr, "Error in setting the Scheduler!\n");
> >>>>>>> exit(1);
> >>>>>>> }
> >>>>>>>
> >>>>>>> /* Register this thread as a RT task. As long as it's
> >>>>>>> not switched to hard_real_time, it's still a normal process and
> >>>>>>> can do all normal things */
> >>>>>>> task = rt_task_init(nam2num("do_comedi"), priority, stack_size,
> >>>>>>>msg_size);
> >>>>>>>
> >>>>>>> // Set mode to periodic. Other option is 'oneshot'
> >>>>>>> rt_set_periodic_mode();
> >>>>>>> period = (int) nano2count((RTIME)options->period*1000);
> >>>>>>>
> >>>>>>> start_rt_timer(period);
> >>>>>>>
> >>>>>>> // Switch to hard realtime mode
> >>>>>>> rt_make_hard_real_time();
> >>>>>>>
> >>>>>>> // Start scheduler
> >>>>>>> rt_task_make_periodic(task, rt_get_time() + period, period);
> >>>>>>>
> >>>>>>>
> >>>>>>> for (i=0; i<options->n_rows; i++)
> >>>>>>> {
> >>>>>>>
> >>>>>>> /* Prepare and write digital data. */
> >>>>>>> dio_bits = data_arr[i].DIO;
> >>>>>>> comedi_dio_bitfield(comedi_dev, dio_subdev, dio_mask, &dio_bits);
> >>>>>>>
> >>>>>>> /* Prepare and write AO data */
> >>>>>>> data = data_arr[i].AO0;
> >>>>>>> insn.data = &data;
> >>>>>>> insn.chanspec = CR_PACK(0, range, aref);
> >>>>>>> if(comedi_do_insn(comedi_dev, &insn)<0)
> >>>>>>> {
> >>>>>>> comedi_perror("/dev/comedi0");
> >>>>>>> exit(1);
> >>>>>>> }
> >>>>>>>
> >>>>>>> data = data_arr[i].AO1;
> >>>>>>> insn.data = &data;
> >>>>>>> insn.chanspec = CR_PACK(1, range, aref);
> >>>>>>> if(comedi_do_insn(comedi_dev, &insn)<0)
> >>>>>>> {
> >>>>>>> comedi_perror("/dev/comedi0");
> >>>>>>> exit(1);
> >>>>>>> }
> >>>>>>> rt_task_wait_period();
> >>>>>>> }
> >>>>>>>
> >>>>>>> rt_make_soft_real_time();
> >>>>>>>
> >>>>>>>#ifdef DEBUG
> >>>>>>> printf("We're back in soft realtime.\n");
> >>>>>>>#endif
> >>>>>>>
> >>>>>>> // Stop timer
> >>>>>>> stop_rt_timer();
> >>>>>>>
> >>>>>>> // Unregister RT task
> >>>>>>> rt_task_delete(task);
> >>>>>>>
> >>>>>>> // Unlock mem
> >>>>>>> munlockall();
> >>>>>>>
> >>>>>>> return 0;
> >>>>>>>}
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>>Paolo.
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>>Lennart.
> >>>>>>>>>--
> >>>>>>>>>*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
> >>>>>>>>>L.C. Karssen
> >>>>>>>>>Department of Physics and Astronomy
> >>>>>>>>>Faculty of Science
> >>>>>>>>>Utrecht University
> >>>>>>>>>Princetonplein 1
> >>>>>>>>>3584 CC Utrecht
> >>>>>>>>>The Netherlands
> >>>>>>>>>
> >>>>>>>>>tel.: +31 (0)30-253-2208
> >>>>>>>>>fax.: +31 (0)30-253-7468
> >>>>>>>>>e-mail: L.C.Karssen_at_phys.uu.nl
> >>>>>>>>>www: http://www1.phys.uu.nl/wwwaoud
> >>>>>>>>>-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>_______________________________________________
> >>>>>>>>>RTAI mailing list
> >>>>>>>>>RTAI_at_rtai.org
> >>>>>>>>>https://mail.rtai.org/cgi-bin/mailman/listinfo/rtai
> >>>>>>>>
> >>>>>>>>
>
--
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
L.C. Karssen
Debye Institute
Dept. of Physics & Astronomy
Utrecht University
Princetonplein 1
3584 CC Utrecht
The Netherlands
tel.: +31 (0)30-253-2208
e-mail: L.C.Karssen_at_phys.uu.nl
www: http://www1.phys.uu.nl/wwwaoud
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
Received on 2007-05-23Z19:17:49