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
