06-19-2007 02:06 PM
06-19-2007 02:58 PM
Hi A squared-
The error aliases are perhaps a bit obscure. Let me see if I can offer some explanation (all of this is basically coming out of tDMAChannel.cpp)
kNoError = 0
Self explanatory
kBufferOverflow
Occurs when bytesInBuffer > _size (i.e. buffer size). This means that we wrapped around the circular DMA buffer before transferring some number of samples to the application buffer, thus overflowing the DMA buffer. The number of overwritten samples would be equal to (bytesInBuffer - _size). This error only applies to input operations.
kBufferUnderflow
The opposite case from kBufferOverflow, this means we did not fill an output buffer fast enough and that the DMA process transferred stale data to the device.
kDataNotAvailable
This is the case where requestedBytes > bytesInBuffer. This error is the motivation for performing two read operations; the first read to determine the current quantity of bytesInBuffer so that we can intelligently choose the requestedBytes value for the second read operation.
kSpaceNotAvailable
This error is thrown when a buffer allocation fails. Your OS Interface should return an appropriate status value after the _buffer->allocate() call in
kWrongState
This is an internal error for the DMA library that is thrown whenever the expected incoming state doesn't match a requested state change (for example, you can not read() from a kIdle state.
kInvalidInput
Hopefully this helps-
06-19-2007 06:13 PM
06-21-2007 10:20 AM
Hi Aaron-
The other modes are not exposed or available in the DDK. In general, Ring mode is the easiest to implement and the least complex from a memory management standpoint. Consequently, it requires the driver client to be more diligent about checking for things like overwritten samples, etc. Ring mode literally just pumps samples into a circular buffer and keeps cycling over itself. This situation is the motivation for the extensive error checking code in tDMAChannel::read(). The other modes don't offer any obvious performance enhancements once all the memory is allocated, and (IMO) Ring mode is definitely the easiest to work with from the perspective of complexity in programming the hardware interface.
06-21-2007 02:37 PM
06-21-2007 04:18 PM
06-21-2007 04:47 PM - edited 06-21-2007 04:47 PM
Note: With the above code, I am not observing any further dma errors and I've even upped the loop rate to 2000 Hz and the acquisition rate to 160kHz on 2 analog inputs. Because of the time it takes to get from class constructor to the time when the infinite loop starts acquiring data from the card, the buffer overflows (kBufferOverFlow error occurs). I only want this to be a one time error, so I modified the kBufferOverFlow code in tDMAChannel.cpp to be:
if( bytesInBuffer > _size )Message Edited by A squared on 06-21-2007 06:12 PM
06-21-2007 06:31 PM - edited 06-21-2007 06:31 PM
Hi Aaron-
Good idea- making sure that the data is stable (or at least valid) is certainly helpful. Your method seems to be working relatively well. I did some digging into the mite control code that we use for a different product. This method also uses two reads of the DeviceAddress Register (aka DAR, please excuse the pseudo-code):
tBoolean darStabilized;
u32 numTries = 0;
u32 firstDAR, secondDAR;
firstDAR = _readDAR();
fifoCount = _readFCR();
secondDAR = _readDAR();
darStabilized = (firstDAR == secondDAR);
++numTries;
}
while ( !(darStabilized && (secondDAR >= fifoCount))&& (secondDAR <= (fifoCount + ( secondDAR - firstDAR )))
&& (numTries < 100));
secondDAR -= ( darStabilized ) ? fifoCount : (fifoCount + ( secondDAR - firstDAR ));
secondDAR is then analogous to the _bytesAvailable value in the MHDDK.
To give you a bit more of an idea what is going on here, the hardware uses the DAR to represent the total number of samples that have been acquired and queued for transfer to memory. The FIFOCount Register (FCR) gives an indication of how many samples are still queued (i.e. that haven't been transfered to memory yet). So, the difference between the two is obviously what should be available to be pulled into your application from RAM. The challenge is making sure that the two readings are in sync as both are constantly changing (presumably DAR will always be increasing while, assuming good bus throughput to memory, the FCR should remain relatively low.
I have seen this error inexplicably very rarely when testing some things here. It sounds like your system is particularly susceptible to getting out of sync with these readings. I would encourage you to give the above implementation a try since it has proven to be very reliable in the area in which it is used. Any feedback about how it works for you would be very valuable and appreciated.
Thanks-
Message Edited by Tom W [DE] on 06-21-2007 06:33 PM
06-21-2007 07:29 PM
06-25-2007 04:13 PM
Hey Aaron-
In case it helps, here's a snippet from the changes I'm testing with for the _getBytesInBuffer() method:
u32 tDMAChannel::_getBytesInBuffer ()
{
{
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 && (deviceAddress1 >= fifoCount))
&& (deviceAddress1 <= (fifoCount + ( deviceAddress1 - deviceAddress )))
&& (tries < 100));
deviceAddress1 -= ( stableDAR ) ? fifoCount : (fifoCount + ( deviceAddress1 - deviceAddress ));
_writeIdx = deviceAddress1;
}
else
{
_readIdx = _miteChannel->DeviceAddress.readRegister ();
}
// 2. Calculate difference between read and write indexes
// checking for rollovers
u32 bytesInBuffer = 0;
if ( _writeIdx < _readIdx )Does this implementation work better in your testing? Any other unforseen problems? I'm trying to nail down the best way to show this in the MHDDK, so any feedback you have would be appreciated.
Thanks-