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.
Alexis.
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help