Driver Development Kit (DDK)

cancel
Showing results for 
Search instead for 
Did you mean: 

trying to understand how the DDK works

Hi,

1.)  If I wanted to be able to use a wide variety of NI DAQ cards under the QNX RTOS, would the NI Measurement Hardware DDK be able to faciliate this?

2.)  From looking at the web-page describing the DDK, it looks to me that the driver code written by NI is done in a platform indepedant way, using only ANSI C/C++ function, and when it needs to do something platform specific, it calls out to functions that I can provide.  Is this correct?  I am envisioning having to provide code to get PCI resources, attach to interrupt, hw I/O.... am I on the right track?

3.)  I've downloaded the NI HW DDK OTHER code, but it's not clear to me how the platform-dependant code for QNX will integrate with this.  I have the DAQ PCI_E_series Register Level Programming Manual and STC manual, but I can't find any docs on how to use the code in this archive.  What am I missing?

Thanks

0 Kudos
Message 1 of 7
(8,726 Views)
Hi,

1.)  If I wanted to be able to use a wide variety of NI DAQ cards under the QNX RTOS, would the NI Measurement Hardware DDK be able to faciliate this?

Depends.  MHDDK provides register information for a number of NI DAQ devices.  There isn't an API that abstracts the measurement task form the hardware, like DAQmx does.

You would need to write the high level functions for each type of device you what to use and provide an API to your application that would select the appropriate device specific function.  I guess something like

startDevice()
{
    // somehow get deviceTypeId
    switch (deviceTypeId)
    {
    case kMSeries:
          mseries_startDevice();
    case ESeries
          eseries_startDevice();
    [...]
    }
}


or using function pointers, or c++ inheritance.  There are many possibilities...

2.) .... am I on the right track?

Yes.  MHDDK only abstracts device access using the iBus and tAddressSpace objects.  The iBus contains the address spaces of the device.  You request address spaces from the bus and use it write/read from the device.  For PCI devices the read/write functions using pointer manipuilation.  For a PCMCIA device on a x86 you would use the port io instructions.

iBus objects are created and destroy using the factory methods acquireBoard() and releaseBoard().  This is where all the platform dependent magic should occur. 
Here are a couple of KBs with more info:

Measurement Hardware Driver Development Kit Register Level Programming Architecture
How to Make an iBus

3.)  I've downloaded the NI HW DDK OTHER code, but it's not clear to me how the platform-dependant code for QNX will integrate with this.  I have the DAQ PCI_E_series Register Level Programming Manual and STC manual, but I can't find any docs on how to use the code in this archive.  What am I missing?

In  osiUserCode.cpp, implement acquireBoard(tChar*) and releaseBoard(iBus *&).   To acquire the board you usually have to loacte the device, find bar0 and bar1 , and map them to the current address space. 

This article shows exactly how to do that in QNX:
Talking to hardware under QNX Neutrino

Also, create a QNX specific structure to attach to the iBus where you can store any handles you need for releaseBoard() to clean up.

Hope this helps.
Diego

0 Kudos
Message 2 of 7
(8,701 Views)
Thanks Diego,

Unfortunately, I am still confused.

Would I have to write an iBus for every card that would be supported, or write the iBus once and it will allow the same example code (e.g. aiex1.cpp) to work for many cards?

Thanks

0 Kudos
Message 3 of 7
(8,680 Views)

There's one iBus implementation per OS.  You would write the acquireBoard()/releaseBoard() functions to create/destroy the iBus for the OS you are working with.  The examples then use the interface defined by iBus to comunicate with the hardware.
 
The examples show how to program a device family: eseries, mseries, aowaveform, etc.  An example should work with most models in that family.  I say should since there are  difference between models that might require minor changes in the examples (max sample rate, number of channels, support ranges, ...)

I'm attaching an implementation of acquireBoard()/releaseBoard() based on the QNX article.  It still needs some work (error handling), but it should provide a good starting point.

Hope this helps.  Let me know if you need more information.
Diego
Download All
Message 4 of 7
(8,664 Views)
Wow!  Thanks, it's not every day that someone on a msg board writes code for you!

This clears up a lot for me.  I have tweaked the code a little, and it's not far from building. 

Where does interrupt handling code fit into this?  For a fully functional application, isn't there more OS-dependant code than just what's in acquireBoard() and releaseBoard()?

0 Kudos
Message 5 of 7
(8,655 Views)
Yes your right there is more OS dependant code required in the form of registering the interrupt routine, however this code can still be written within the same acquireCard() function. Some of the information within this function is actually even required anyway, like the IRQ number, board number etc. If you wanted to keep these functions seperate you could always add another two member functions to the iBus object, however I'd just keep it all in the two functions declared already.

Message Edited by studio_uk on 12-03-2005 03:47 AM

0 Kudos
Message 6 of 7
(8,634 Views)
Thanks!  Seems pretty clear now.
0 Kudos
Message 7 of 7
(8,588 Views)