Hi,

Sorry for answering late.

2011/10/10 Fernando Herrero Carrón <elfe...@gmail.com>:
>
>
> El 7 de octubre de 2011 19:06, Alexis Berlemont <alexis.berlem...@gmail.com>
> escribió:
>>
>> Hi,
>>
>> 2011/10/7 Fernando Herrero Carrón <elfe...@gmail.com>:
>> > El 6 de octubre de 2011 18:31, Alexis Berlemont
>> > <alexis.berlem...@gmail.com>
>> > escribió:
>> >>
>> >> Hi,
>> >>
>> >> 2011/10/6 Fernando Herrero Carrón <elfe...@gmail.com>:
>> >> >
>> >> >
>> >> > El 5 de octubre de 2011 20:06, Fernando Herrero Carrón
>> >> > <elfe...@gmail.com>
>> >> > escribió:
>> >> >>
>> >> >> El 5 de octubre de 2011 18:16, Alexis Berlemont
>> >> >> <alexis.berlem...@gmail.com> 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.
>

I took some time to compare both versions of code (comedi and
analogy). I did not find anything interesting in mite.c. I was about
to ask you to increase verbosity (debug + a specific patch) when I got
a glimpse on the allocation of the asynchronous buffer on the comedi
side.

The methods are not the same at that level:
- comedi: n * dma_alloc_coherent  + a vmap at the end
- analogy:  a big vmalloc + n * page_to_phys(vmalloc_to_page(vaddr)

I don't understand the reason why the analogy way is not correct, I
did not have time to check yet. If anyone has any idea, please help
me.

However, the NI mite expects 32 bit addresses... (because of
cpu_to_le32 in the mite driver).

If I remember well, you are using a 64-bit architecture. Is it
correct? There may be a bug here; analogy might give to the mite
physical addresses which are not below 2^32.

So, could you:
- with comedi, add some printk("%lx") in mite_buf_change so as to dump
the pages physical addresses
- with analogy, do the same thing in a4l_mite_buf_change.

Or you can test on another machine.

So far, I got only remote access on a 32 bit machine in which there is
a NI card; I must have missed something...

> Best regards,
> Fernando
>
> _______________________________________________
> Xenomai-help mailing list
> Xenomai-help@gna.org
> https://mail.gna.org/listinfo/xenomai-help
>
>

Best regards,

Alexis.

_______________________________________________
Xenomai-help mailing list
Xenomai-help@gna.org
https://mail.gna.org/listinfo/xenomai-help

Reply via email to