05-26-2010 02:17 AM
Hallo,
We have serious problems after upgrading our app to DAQmx.
The problem is that we face dead-locks of DAQmxWriteBinaryI16
and DAXmxStopTask in combination with certain states of the progress
of the external pattern clock.
We use externally clocked AO using a PCI-6711 / PCI-6713 board.
We selected this board because it uses the main PC memory which can
be accessed by the CPU during AO operation. As a result the waveform
can be updated by the CPU on the fly with minimal lag.
With the DAQ32 library, the WFM_Load(,,,buffer[2048*2048*4],,) was
called to pass the address of the buffer. During AO operation, the contents
of the buffer was modified and the new waveform was visible on the output
with minimal lag (~ the size of the hardware DMA buffer).
With DAQmx this update on-the-fly type of operation seems to be impossible.
DAQmxWriteBinaryI16 is now used, but this method synchronizes with the
actual AO progress. In the forum there are several topics found that explain
why this buffering and synchronizing strategy slows down the time in which
the DAQmxWriteBinaryI16 returns. However, I have not found a suggestion
how we can implement the fast DAQ32 non-synchronized behaviour.
Note that:
- stopping and restarting the task is not possible because it would break the
synchronization with the external pixelclock
- we understand that updating the buffer during AO introduces glitches in the
output, but that is acceptable for our hardware
- the total duration of one wave ranges from 100 ms to 60 seconds.
with DAQ32, any changes in the buffer were visible within a fraction of second, which is
an acceptable respons time. With DAQmx, DAQmxWriteBinaryI16 can take
up to 30 seconds to return, which is killing for the user experience.
Because the DAQmxWriteBinaryI16 method could take a long time to return
we have moved this call to a separate working thread that writes the buffer in
the background:
while(WaitForAction(INFINITE) == EDoWork)
{
m_BufferChanged.Reset();
DAQmxWriteBinaryI16(,,,);
}
The problem our QA team now discovered that that a sometimes a dead-lock occurs in
the following situation:
- the external pixel-clock is stopped
- the DAQmxWriteBinaryI16 is executing (blocked), clearly waiting for the AO to come to
an certain state
- the DAQmxStopTask is called but never returns.
This problem does not happen frequently, I can imaging that it happens only when the clock is
stopped at a certain phase in the total cycle.
The dead-lock seems to me a side-effect of the synchronization with AO.
Note that we don't want to have the synchronization in the first place.
Could you please tell us if there is a (hidden) method that can be called after DAQmxStartTask
to get a user-space pointer to the shared memory that is used to store the buffer ?
Using this pointer we can update the waveform on the fly without synchronization with the AO progress.
Alternatively, please teach us how to prevent the dead-lock situation that we encounter.
WR,
Kees van der Oord
07-26-2010 02:26 AM
Dear Kees van der Oord,
In DAQmx this is not possible. The best you can do is disable the regeneration, and break your waveform in smaller chunks.
Regards,
Bas van Dijke
NI Netherlands
07-26-2010 03:28 AM
Bas,
Thanks for the suggestion.
I had the same idea.
The update is now broken into smaller pieces and performed by a thread in the background.
The response time is better now, but far not as good as it was.
The solution requires a lot of administration and thread-synchronisation.
It looks strange to add so much error-prone code to work-around the limitations of the API.
I like the simplicity of the NI software interface, but this seems to be the opposite of simple.
WR,
Kees