El 7 de octubre de 2011 19:06, Alexis Berlemont
<[email protected]>escribió:

> Hi,
>
> 2011/10/7 Fernando Herrero Carrón <[email protected]>:
> > El 6 de octubre de 2011 18:31, Alexis Berlemont <
> [email protected]>
> > escribió:
> >>
> >> Hi,
> >>
> >> 2011/10/6 Fernando Herrero Carrón <[email protected]>:
> >> >
> >> >
> >> > El 5 de octubre de 2011 20:06, Fernando Herrero Carrón
> >> > <[email protected]>
> >> > escribió:
> >> >>
> >> >> El 5 de octubre de 2011 18:16, Alexis Berlemont
> >> >> <[email protected]> escribió:
> >> >>>
> >> >>> I think the problem might be located at two different places:
> >> >>> 1) Either the DMA controller is badly configured and it copies the
> >> >>> properly acquired values to wrong places.
> >> >>> 2) Or the DAQ-STC module is badly configured; so, the  DMA
> controller
> >> >>> copies the wrong values to right places.
> >> >>>
> >> >>> Concerning the alternative 1, I think it is not the most probable
> one.
> >> >>> Why? Because, the DMA controller (the MITE) is configured the same
> way
> >> >>> whatever the NI acquisition board holds it (or nearly).
> >> >>> To check this idea: let's make a little test with cmd_read.
> >> >>>
> >> >>> If cmd_read is launched with the option -m (map), we get direct
> >> >>> access, in user space, to the memory area the DMA controller is
> >> >>> supposed to shot to.
> >> >>>
> >> >>> So, just after a4l_mmap (before the DMA controller shots anything):
> >> >>> 367:            /* Map the analog input subdevice buffer */
> >> >>> 368:            ret = a4l_mmap(&dsc, cmd.idx_subd, buf_size, &map);
> >> >>> you can have a look at the values hold by the buffer:
> >> >>> - If the values are already 0x8000, we might conclude that the DMA
> >> >>> controller does not send anything there.
> >> >>> - If the values are not 0x8000, then we are sure that the DMA
> >> >>> controller does behave as expected. Consequently we can skip
> >> >>> alternative 1) and focus on the second one.
> >> >>>
> >> >>> If the DAQ is not properly configured; things are getting a little
> bit
> >> >>> simpler (if we have the documentation /. developer manual of your
> >> >>> acquisition card). We just have to find which stuff was not properly
> >> >>> configured.  A simple solution could be the monitoring of the status
> >> >>> registers. In such a case, I can send you a patch which will dump
> the
> >> >>> content of these registers.
> >> >>>
> >> >>> But before going that way, could you make the test with cmd_read +
> >> >>> mmap?
> >> >>>
> >> >>> Regards,
> >> >>>
> >> >>> Alexis.
> >> >>
> >> >> Ok, I'll check those tomorrow. From what I recall, I checked cmd_read
> >> >> just
> >> >> passing the '-m' option and resulted in the same behaviour, but I'll
> >> >> recheck
> >> >> tomorrow.
> >> >>
> >> >> What I find somewhat surprising is that I got it working with comedi,
> >> >> so I
> >> >> guess that the register programming should also be working with
> >> >> analogy. The
> >> >> only difference I have managed to find so far between the analogy and
> >> >> the
> >> >> comedi drivers, besides generic buffer management, is that comedi
> >> >> appears to
> >> >> handle DMA through the "generic device" interface (as in
> >> >> http://www.mjmwired.net/kernel/Documentation/DMA-API.txt) and
> analogy
> >> >> handles DMA through the PCI interface (as in
> >> >>
> >> >>
> http://m8-android-kernel.googlecode.com/svn/trunk/Documentation/DMA-mapping.txt
> ).
> >> >> But this is merely speculation.
> >> >>
> >> >> I'll look tomorrow at your two options in more detail.
> >> >>
> >> >> Thanks for your help!
> >> >> Fernando
> >> >
> >> > Dear Alexis,
> >> >
> >> > I just repeated the tests with mmap.
> >> >
> >> > Running the provided example of "cmd_read" with either "-m" or "-m -r"
> >> > only
> >> > dumps the 0x8000 value. _Sometimes_, very rarely, I can get to see
> >> > different
> >> > values not far from that one, but if I get to plot it it just looks
> like
> >> > noise. I don't know what is causing those values and I cannot
> reproduce
> >> > the
> >> > conditions for them.
> >> >
> >> > Now I used gdb to step through the process (with my own code) and here
> >> > is
> >> > the sequence:
> >> >
> >> > -  I run up to the line where the "mmapping" happens. I check that map
> >> > ==
> >> > NULL and after I run the "mmap()" it gets a different value and ret ==
> >> > 0,
> >> > ok.
> >> >
> >> > - I do a
> >> > print *(unsigned short *)map@100
> >> >
> >> >   to dump the contents of the buffer and it is all filled with zeroes
> at
> >> > this point.
> >> >
> >> > - I setup my command structure like this:
> >> >
> >> >     cmd.idx_subd = 0;
> >> >     cmd.start_src = TRIG_NOW;
> >> >     cmd.start_arg = 0;
> >> >     cmd.flags = TRIG_WAKE_EOS;
> >> >     cmd.scan_begin_src = TRIG_TIMER;
> >> >     cmd.scan_begin_arg = 1e9 / INPUT_FREQ;
> >> >     cmd.convert_src = TRIG_NOW;
> >> >     cmd.convert_arg = 0;
> >> >     cmd.chan_descs = chanlist;
> >> >     cmd.nb_chan = NICHAN;
> >> >     cmd.scan_end_src = TRIG_COUNT;
> >> >     cmd.scan_end_arg    = NICHAN;
> >> >
> >> >     cmd.stop_src = TRIG_COUNT;
> >> >     cmd.stop_arg = SAMPLE_HISTORY;
> >> >
> >> > with
> >> >
> >> > INPUT_FREQ = 1000 (1kHz)
> >> > NICHAN = 1   (I have also tried 4 and 8 with no difference in results)
> >> >
> >> > and call the a4l_snd_command() function, which returns without errors.
> >> >
> >> > I dump the contents of the buffer and it is still filled with zeroes.
> >> >
> >> > - I declare
> >> >
> >> > unsigned long front = 0;
> >> >
> >> > and call
> >> >
> >> > ret = a4l_mark_bufrw(&dev_input, 0, front, &front);
> >> >
> >> > at this point the buffer gets filled with 0x8000:
> >> >
> >> >
> >> > (gdb) print *(unsigned short *)map@100 $1 = {0 <repeats 100 times>}
> >> > (gdb) n     <------------------ calls a4l_mark_bufrw()
> >> >
> >> > 186            if (front == 0) {
> >> >
> >> > (gdb) print /x*(unsigned short *)map@100
> >> > $2 = {0x8000 <repeats 100 times>}
> >> >
> >> > Now I find it funny that the value read is always the same. Could it
> be
> >> > that
> >> > everything is working fine and it is the board itself that is
> >> > transferring
> >> > that value? Could it be an indicator for an error condition?
> >>
> >> I don't think it is an error indicator; errors are reported in
> >> dedicated status registers.
> >>
> >
> > Yep, you're right on that one...
> >
> >>
> >> If I understand correctly, most of the times you acquire 0x8000 and a
> >> few times other values. That could mean that 0x8000 values are really
> >> produced by the ADC converter. By the way, 0x8000 is not a meaningless
> >> value (0x0000 - 0xFFFF median). I don't know which range was selected
> >> (-5V / 5V by default?) but it could mean that the card is acquiring a
> >> continuous 0V signal.
> >
> >
> >>
> >> Which channel are you using?
> >> Could you test each channel separately and all of them at once?
> >> Could try another range? 0V / 5V could be a great candidate: with this
> >> one the acquired values could be 0x0000 instead of 0x8000.
> >>
> >
> > That makes sense, but with insn_read I get the right waveshape, with the
> > same setup. I am reading a 3Hz, 3V input signal. Unfortunately, this
> board
> > reports only one possible range. The output of cmd_read -v reports:
> >
> > cmd_read: device analogy0 opened (fd=0)
> > cmd_read: basic descriptor retrieved
> >      subdevices count = 14
> >      read subdevice index = 0
> >      write subdevice index = 0
> > cmd_read: complex descriptor retrieved
> > cmd_read: channel 0
> >      ranges count = 1
> >      bit width = 16 (bits)
> >
> > Now here goes a crazy thing. I modified
> > ksrc/drivers/analogy/national_instruments/mio_common.c:ni_ai_cmd() so
> that
> > every time a command is issued the buffer is filled with 0x0f. That is, I
> > added the following line:
> >
> >     memset(subd->buf->buf, 0x0f, subd->buf->size);
> >
> > Now I repeat the same sequence as in my previous mail with gdb:
> >
> > - Map the buffer, check address and content (buffer has some leftovers
> from
> > previous runs)
> >
> > ret = a4l_mmap(&dev_input, 0, buf_size, &map);
> >
> > (gdb) print map
> > $1 = (void *) 0x7ffff7fc8000
> > (gdb) print /x*(unsigned short *)map@100
> > $2 = {0x600, 0x5e04, 0x0 <repeats 98 times>}
> >
> > - Issue the command and recheck contents. Now the buffer is filled with
> > 0x0f0f
> >
> > (gdb) n
> > 173        setup_input_card(&dev_input);
> >
> > (gdb) n
> > Channel 0 has 16 bits and 1 different ranges
> > 175        unsigned long front = 0;
> >
> > (gdb) print /x*(unsigned short *)map@100
> > $3 = {0xf0f <repeats 100 times>}
> >
> > - Call a4l_mark_bufrw() and recheck contents. 70 samples have changed
> > values, 30 remain the same. In those samples that changed value, only one
> > bit changed!!
> >
> > (gdb) n
> > 177        for(int scan = 0; scan < SAMPLE_HISTORY; scan++)
> >
> > (gdb) n
> > 180            ret = a4l_mark_bufrw(&dev_input, 0, front, &front);
> >
> > (gdb) n
> > 186            if (front == 0) {
> >
> > (gdb) print /x*(unsigned short *)map@100
> > $4 = {0x8f0f <repeats 70 times>, 0xf0f <repeats 30 times>}
> >
> > So there is either an 'or' operation or an addition operation with 0x8000
> > that is changing those values. As you said, 0x8000 is a very
> representative
> > value. It represents zero on a 16 DAQ like mine, and it is also a value
> used
> > as a mask in various places:
> >
> > ./ksrc/drivers/analogy/national_instruments/ni_stc.h:#define
> > _bit15             0x8000
> > ./ksrc/drivers/analogy/national_instruments/ni_stc.h:#define
> > Calibration_Channel_6143_RelayOn   0x8000 (which happens to be my DAQ...)
> >
> > Running cmd_read only yields the 0x8f0f value now, by the way.
> >
> > I now it's hard to imagine what is happening without having the board
> > yourself, so I really appreciate your help.
>
> I may have an idea thanks to your additional test. I cant' figure out
> how a DMA controller could perform a or / add operation on memory with
> one single write shot; so, this operation must be done by the CPU.
>
> The only way for the CPU to interfere is through a munge operaiton,
> let's have a look at ni_ai_munge16:
>
> static void ni_ai_munge16(a4l_subd_t *subd, void *buf, unsigned long size)
> {
>        a4l_dev_t *dev = subd->dev;
>        a4l_cmd_t *cmd = a4l_get_cmd(subd);
>        int chan_idx = a4l_get_chan(subd);
>        unsigned int i;
>        sampl_t *array = buf;
>
>        for (i = 0; i < size / sizeof(sampl_t); i++) {
> #if (defined(CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE) || \
>     defined(CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE_MODULE))
>                array[i] = le16_to_cpu(array[i]);
> #endif /* CONFIG_XENO_DRIVERS_ANALOGY_NI_MITE */
>
> ###### HERE
>                array[i] += devpriv->ai_offset[chan_idx];
> ######## HERE
>
>                chan_idx++;
>                chan_idx %= cmd->nb_chan;
>        }
> }
>
> According to the code in ni_load_channelgain_list, I think ai_offset
> is set to 0x8000 in your case.
>
> Could you empty the function ni_ai_munge16 and check that the buffer
> is not modified anymore?
>
> If it is the case, let's go back to your first theory: the DMA controller.
>
>
Dear Alexis,

Yes, I commented out that line you mentioned and indeed the buffer is now
filled with 0x0f0f instead of 0x8f0f. So yes, I still suspect it has to do
with the DMA transfers.

Recalling, it seems that everything is working with the DMA except this very
point. I mean, I set my board to transfer data at the end of every scan
(with .flags = TRIG_WAKE_EOS) and I program a given frequency, say 1kHz. The
dmesg reports an interrupt from the board with the right timing and my
"a4l_async_read()" call gets unblocked apparently with the right timing as
well. At the end of buffer.c:a4l_buf_evt() I dump the value of "count",
which reports the number of bytes transferred in the current event, and it
reports the expected value (except in some cases, which I will comment on a
separate mail).

So I would like to check the following points:

- Check that the subdevice's buffer is properly configured when the device
is set up and/or when the command is launched.

- Check that the DMA programming is actually using that buffer.

- Check that the read operation is accessing the right buffer as well.

I can't think of many other things going wrong. While writing this email I
have thought of some further tests, so here is the result :)

I have changed the size of the default buffer using analogy_config. First, I
have specified:

sudo /usr/xenomai/sbin/analogy_config -v analogy0 -S 4

Then I have run cmd_read, with the same results, but I have dumped some
values at "ni_ai_setup_MITE_dma()" and at a4l_buf_evt():

[ 3115.793026] Analogy: analogy_ni_pcimio: ni_ai_setup_MITE_dma: beginning
[ 3115.793029] Analogy: analogy_ni_pcimio: ni_ai_setup_MITE_dma: buf->buf:
ffffc90001893000; buf->end_count 800; buf->prd_count 0; buf->cns_count 0;
buf->tmp_count 0
[ 3115.793035] Analogy: analogy_ni_pcimio: ni_ai_cmd: exit
[ 3116.593187] Analogy: analogy_ni_pcimio: ni_mio_common: interrupt:
a_status=90f0 ai_mite_status=00200000
[ 3116.593189] Analogy: analogy_ni_pcimio: ni_mio_common: SC_TC interrupt
[ 3116.593191] Analogy: Signalling event. Available data to user: 800. Two
first bytes in buffer: 15d 15d. Buffer pointer: ffffc90001893000

Now I changed the size of the buffer to 8, which aparently resulted in a
buffer reallocation:

[ 3119.523172] Analogy: analogy_ni_pcimio: ni_ai_setup_MITE_dma: beginning
[ 3119.523175] Analogy: analogy_ni_pcimio: ni_ai_setup_MITE_dma: buf->buf:
ffffc9000189b000; buf->end_count 800; buf->prd_count 0; buf->cns_count 0;
buf->tmp_count 0
[ 3119.523181] Analogy: analogy_ni_pcimio: ni_ai_cmd: exit
[ 3120.323332] Analogy: analogy_ni_pcimio: ni_mio_common: interrupt:
a_status=90f0 ai_mite_status=00200000
[ 3120.323335] Analogy: analogy_ni_pcimio: ni_mio_common: SC_TC interrupt
[ 3120.323336] Analogy: Signalling event. Available data to user: 800. Two
first bytes in buffer: 15d 15d. Buffer pointer: ffffc9000189b000

I don't know if this is really useful, but this is proving that at least
"ni_ai_setup_MITE_dma()" and "a4l_buf_evt()" are consistent in their notion
of buffer.

Best regards,
Fernando
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help

Reply via email to