Driver Development Kit (DDK)

cancel
Showing results for 
Search instead for 
Did you mean: 

Explanation of DMA errors

Aaron-

To address your other question, arbitrarily modifying the read index to match the write index is probably dangerous to do in terms of alignment of samples in the buffer.  Certain devices might transfer data in fixed-width chunks (for example, 32-bit transfers are common on some S Series devices).  So, if your number of channels changes then the actual buffer contents might not always represent full scans.  If the library reports a buffer overflow and your code adjusts the read index in response, it is possible that you will be adjusting the index into a buffer position that effectively represents the middle of a scan rather than the beginning. 

A better bet would be to leave the read index as-is and briefly test for erroneous overflow errors (for example, you might incorrectly interpret the off chance that the DAR is less than the FIFO count as a negative number of samples in the buffer.  This is probably the most obvious case to test for).

Tom W
National Instruments
0 Kudos
Message 11 of 24
(7,481 Views)
That's basically what I thought after I had made the changes.  Since I hadn't any anomolous behavior, I thought I'd ask.

As for your modified getBytesInBuffer routine, I'll try that over the next few days and see if I see anything unusual.  Thanks.
Message 12 of 24
(7,473 Views)
I've finally had a chance to look at the code you provided.  It still generates the same errors.  In the conditions of the do..while loop, the second line (below) is always false and the loops always executes once even if it should do another loop. 

Line 1:  !(stableDAR && (deviceAddress1 >= fifoCount))

Line 2:  && (deviceAddress1 <= (fifoCount + ( deviceAddress1 - deviceAddress )))
Line 3:  && (tries < 100));

I'm not sure what this expression in Line 2 is looking for.  Maybe it is trying to check for the FIFO being emptied, which is causing deviceAddress1 to equal deviceAddress+fifoCount?  This is merely speculation and if you use numbers I've obvserved, you;ll see that the line in it's current state doesn't make sense.

stableDAR = 0
deviceAddress = 0x4598
fifoCount = 2
deviceAddress1 = 0x459a

Using these numbers, fifoCount+deviceAddress1-deviceAddress = 2+0x459a-0x4598 = 4 while deviceAddress1 = 0x459a, so this expression is essentially always false.  In the example numbers provided, the loop should execute again because the DAR is unstable and the loop expression should be true.

Below is the version of getBytesInBuffer function I've been using right now.  I suspect the original deviceAddress1 -= ... line after the do..while loop also has some issues, but it is the same test in the do..while loop and I don't understand.

u32 tDMAChannel::_getBytesInBuffer ()
{
    // 1. Update MITE's location
   
if (_direction == kIn)
    { 
        //
        // the device address indicates the number of bytes that have
        // been transfered from the device to the DMA FIFO.
        // Samples in the FIFO have not been transfered to host memory
        // so correct the number device address with the FIFO count.
        //
        // The loop avoids a _writeIdx underflows.
        //
        // 'tries' is there to have an upper bound, but it should never
        // exceed 100.
        //

        u32 deviceAddress = 0;
        u32 deviceAddress1 = 0;
        u32 fifoCount = 0;
        u32 tries = 0;
        tBoolean stableDAR;

       
do
        {
            deviceAddress = _miteChannel->DeviceAddress.readRegister ();
            fifoCount = _miteChannel->FifoCount.readFifoCR();
            deviceAddress1 = _miteChannel->DeviceAddress.readRegister ();

            stableDAR = (deviceAddress == deviceAddress1);

            ++tries;

        }
while( !stableDAR && tries < 100 );

        //deviceAddress1 -= ( stableDAR ) ? fifoCount : (fifoCount + ( deviceAddress1 - deviceAddress ));
        deviceAddress1 -= fifoCount;
        _writeIdx = deviceAddress1;
    }
   
else
    {
        _readIdx = _miteChannel->DeviceAddress.readRegister ();
    }

    // 2. Calculate difference between read and write indexes
    // checking for rollovers

    u32 bytesInBuffer = 0;

   
if ( _writeIdx < _readIdx )
    {
        bytesInBuffer = 0xffffffff - ( _readIdx - _writeIdx );
        ++bytesInBuffer;
    }
   
else
    {
        bytesInBuffer = _writeIdx - _readIdx;
    }

   
return bytesInBuffer;
}

If you would like any further information or testing or if you understand the purpose of the expressions, please let me know.

Aaron
Message 13 of 24
(7,445 Views)

Hi Aaron-

The second condition monitors for the unlikely chance that the DAR rolls over while there are samples buffered in the DMA FIFO.  The danger in this situation is that DAR-fifoCount would then be "negative", but since we're using u32 it would be interpreted as a very large number of available samples.  This would lead to a (very!) inaccurate sample count and an almost guaranteed erroneous buffer overflow error.  I agree that the loop will almost always terminate based on this condition, so a better option than having it might be to simply use your implementation for the do...while conditional and then test for a negative number of samples (i.e. DAR < fifoCount).  You might add another flag/return value to indicate the snapshot's validity based on the occurrence of that condition.

Of course, the DAR rolls over anywhere from very seldom (for M Series) to seldom (for faster devices), so the chances of actually hitting this condition are probably slim.  It's still good to account for it, though, for robustness.

Let me know if you have other questions.  Thanks-

Message Edited by Tom W [DE] on 07-02-2007 11:41 AM

Tom W
National Instruments
0 Kudos
Message 14 of 24
(7,426 Views)
Maybe I'm crazy, but the do..while doesn't seem like the time to be checking for overflow/underflow because there is no integer math inside the loop.  The loop just repeats until it receives a consistent deviceAddress/fifoCount pair.  Then the pair needs to be interpreted to see if a roll over (underflow) will occur when deviceAddress1-fifoCount is performed like the bytesInBuffer variable later.

No matter my understanding, it is clear to me based on my previous results that (deviceAddress1 <= (fifoCount + ( deviceAddress1 - deviceAddress ))) mentioned in my previous post is incorrect because it is false and terminates the loop even though no integer roll over has occurred and the DAR is unstable (i.e. the loop should have continued).  I would buy that the second expression in Line 1 in the previous post is to prevent buffer underflow, but this doesn't appear to be the purpose of Line 2 from what I can gather.

Below is another version of the code accounting for the potential underflow.  Please let me know if you see anything that is incorrect or other condition that should be tested.  Thanks.

u32 tDMAChannel::_getBytesInBuffer ()
{
    // 1. Update MITE's location
    if (_direction == kIn)
    { 
        //
        // the device address indicates the number of bytes that have
        // been transfered from the device to the DMA FIFO.
        // Samples in the FIFO have not been transfered to host memory
        // so correct the number device address with the FIFO count.
        //
        // The loop avoids a _writeIdx underflows.
        //
        // 'tries' is there to have an upper bound, but it should never
        // exceed 100.
        //

        u32 deviceAddress = 0;
        u32 deviceAddress1 = 0;
        u32 fifoCount = 0;
        u32 tries = 0;
        tBoolean stableDAR;

        do
        {
            deviceAddress = _miteChannel->DeviceAddress.readRegister ();
            fifoCount = _miteChannel->FifoCount.readFifoCR();
            deviceAddress1 = _miteChannel->DeviceAddress.readRegister ();

            stableDAR = (deviceAddress == deviceAddress1);

            ++tries;

        } while( !stableDAR && tries < 100 );

        if( deviceAddress1 >= fifoCount )
            _writeIdx =    deviceAddress1 - fifoCount;
        else
        {
            _writeIdx = 0xFFFFFFFF - ( fifoCount - deviceAddress1 );
            _writeIdx++;
        }
    }
    else
    {
        _readIdx = _miteChannel->DeviceAddress.readRegister ();
    }

    // 2. Calculate difference between read and write indexes
    // checking for rollovers

    u32 bytesInBuffer = 0;

    if ( _writeIdx < _readIdx )
    {
        bytesInBuffer = 0xffffffff - ( _readIdx - _writeIdx );
        ++bytesInBuffer;
    }
    else
    {
        bytesInBuffer = _writeIdx - _readIdx;
    }

    return bytesInBuffer;
}

Message Edited by A squared on 07-02-2007 10:00 PM

Message 15 of 24
(7,407 Views)

Hi Aaron-

The positioning and functionality of the rollover check you added seems reasonable enough to me.  How is it working in practice on your system?

Thanks-

Tom W
National Instruments
0 Kudos
Message 16 of 24
(7,322 Views)
It has been working very well so far.  Tries usually remains under 3, and I have not seen any unusual behavior.  It would have been a much slower process without your insight, so thanks greatly!

Aaron
Message 17 of 24
(7,318 Views)

Hey Aaron-

Glad to hear it- let me know if you run into anything else.

Thanks-

Tom W
National Instruments
0 Kudos
Message 18 of 24
(7,307 Views)

Tom,

I have found the same problem as Aaron and I wanted to say thanks (to both of you) for the detailed explanation and making the code fix available here on the forum.

 

I can certainly cut and paste the code posted here into my own stuff, but it makes me wonder what other fixes are out there for problems I don't even know about.  I re-checked the code downloads to see if there have been any recent updates (i.e. ftp://ftp.ni.com/support/daq/mhddk/misc/dma.zip), but all of the DDK code there looks to be dated a few years old.  Is there any other download location that might have the "latest" code that I could review to see if there are any other problems that I should be aware of?

 

Thanks,

AJ

 

 

 

 

0 Kudos
Message 19 of 24
(6,029 Views)

Hi AJ-

 

I updated the files at the MHDDK download site just now, so you can download the most recent updates (as of 06 July 2009) from the link you mentioned.  To anyone interested in the "old" files that have been posted for a long time before today, I archived them here: ftp://ftp.ni.com/support/daq/mhddk/backup/06July2009/

Tom W
National Instruments
0 Kudos
Message 20 of 24
(5,988 Views)