- From: <steve.sharples_at_nottingham.ac.uk>
- Date: Fri, 15 Jul 2005 09:02:37 +0100 (BST)
Hi there,
[apologies to the list if you get this twice, I think the first time I
sent it, it was rejected due to an email alias... anyway...]
Not sure if this is a problem with my hardware (Amplicon PCI230
multifunction DAQ), the driver (amplc_pci230), comedi-fops (sounds
unlikely!) or my userland code to read in AI, but this is really doing my
head in and I need some general guidance about how to find (and fix) the
problem....:
It appears that, in very loose language, samples are "going missing"
somewhere between being read in by the card, and appearing in my userland
array. I am _reasonably_ certain that they are being picked up by the
driver, but when in userland I do:
ret=read(comedi_fileno(comedi_dev),buf,COMEDI_BUFSZ);
...and loop through reading data until ret==0, I am often a sample or two
short.
I set up a comedi cmd that reads in a set of channels, and I select
cmd->stop_arg to be the number of averages I want to perform (on each
channel). Normally I use cmd->scan_begin_src=TRIG_EXT (ie external trigger
to begin a scan) and cmd->convert_src=TRIG_TIMER, but the problem is not
confined to using external triggers, ie if cmd->scan_begin_src=TRIG_FOLLOW
I still get the same fault.
What is interesting, is that the slower I go (cmd->convert_arg=bigger
number, ie longer time between samples) or I slow down the external
trigger, or in fact slow everything down by writing lots of spurious stuff
to the kernel log as we go along, it makes the problem worse.
After I issue the cmd, I read in the data using a loop, the bare bones of
which are:
/************************************************************************/
data_count=0;
channel_count=0;
times=0;
while(times<timeout){
ret=read(comedi_fileno(comedi_dev),buf,COMEDI_BUFSZ);
if(ret==0){ /* we're done (all data has been read) */
break;
}
else if(ret>0){ /* data in the comedi buffer, read what's available */
for(i=0;i<ret/2;i++){
data=((sampl_t *)buf)[i];
data_count++;
volts[channel_count]+=(float)comedi_to_phys(data,comedi_get_range(comedi_dev,subdev,channel_count,range),maxdata);
channel_count++;
if(channel_count == n_chan){
channel_count=0;
}
}
}
else { /* ret<0: some error occurred, might be harmless though */
times++;/* increment the timeout checker */
/* if errno==EAGAIN everything is fine, there's just
* no data there yet... keep trying until we time out */
if(errno!=EAGAIN){
printf("PCI230_read_multi_ch_avg(): problem reading the data\n");
printf(" errno=%d (\"%s\")\n",errno,strerror(errno));
return -1;
}
}
}
/* Perform averaging */
for(i=0;i<n_chan;i++){
volts[i]/=avg;
if(diagnostics) printf(">>>volts[%d] average = %g\n",i,volts[i]);
}
/************************************************************************/
With the code above, I often get values closer to zero on the later
channel(s)... obviously because I'm expecting say 3 samples and dividing
by 3, but only receiving 2 samples and dividing by 3. At the moment I
catch this:
if(data_count!=(n_chan*avg))...-> re-issue the command and try again
...but for a variety of reasons this is unacceptable.
My attempts at debugging so far have included (a) observing the behaviour
in the userland loop (where there is a fault) and (b) putting a couple of
printk's in the ai interrupt handler of the driver:
/************************************************************************/
static void pci230_handle_fifo_not_empty(comedi_device *dev, comedi_subdevice *s) {
while (devpriv->ai_count != 0) {
if (inw(dev->iobase + PCI230_ADCCON) & PCI230_ADC_FIFO_EMPTY) {
/* The FIFO is empty, block. */
printk("comedi:FIFO empty, ai_count==%d\n",devpriv->ai_count);
return;
}
/* There are sample(s) to read from FIFO, read one and
store in Comedi's circular buffer. */
comedi_buf_put(s->async, pci230_ai_read(dev));
if(devpriv->ai_count > 0) devpriv->ai_count--;
}
/* Acquisition complete. */
printk("comedi:acquisition complete apparently, ai_count==%d\n",devpriv->ai_count);
return;
}
/************************************************************************/
If I attempt to get 100 "readings" (ie 100 cmds), and 2 are incomplete and
I have to re-issue to the cmd 2 more times, then I get 102 "acquisition
complete" messages... this makes me think that the driver is probably ok
(though of course I am very happy to be proven wrong on this!).
The board shares interrupts with several other devices:
11: 9788951 XT-PIC usb-uhci, usb-uhci, eth0, amplc_pci230, nvidia
(the PC is chocker with cards, I've tried swapping things round to put it
on a slightly less busy interrupt, but to no avail).
I don't know if it's relevant or not, but at the start of my userland
program I set up comedi_dev to be non-blocking:
fcntl(comedi_fileno(comedi_dev),F_SETFL,O_NONBLOCK);
This is because I am gathering A/D data as I am controlling a moving stage
"on the fly". I set the scheduler into single-process mode, and I don't
want comedi to yield whilst waiting for data, otherwise by the time we
regain control I might have missed my chance to capture data at the
appropriate place!
So where do I go from here? I'm after general strategies, likely locations
of problems, debugging advice. I'm very hazy about "where the data goes"
between the driver doing "comedi_buf_put(s->async, pci230_ai_read(dev));"
and the read() function in userland (I know it has something to do with
"comedi-fops.c") - perhaps I need some general help in understanding this
process. But since comedi-fops is such an important and integral part of
the comedi system, it seems incredibly unlikely there's a problem there.
The only slight clue that might be useful is that "when things slow down,
things get worse."
Sorry for the low "information:length of email" ratio!
Cheers,
Steve Sharples.
Dr Steve D. Sharples steve.sharples_at_nottingham.ac.uk
Applied Optics Group
School of Electrical & Electronic Engineering, University of Nottingham
University Park, Nottingham, NG7 2RD, UK Fax +44 115 9515616
Office +44 115 95-15386 Lab +44 115 95-15638
This message has been checked for viruses but the contents of an attachment
may still contain software viruses, which could damage your computer system:
you are advised to perform your own checks. Email communications with the
University of Nottingham may be monitored as permitted by UK legislation.
Received on 2005-07-15Z07:02:37