As an alternative to commercially developed Linux drivers, users of boards from some popular suppliers can turn to Comedi, the name given to a collection of drivers whose open-source nature mirrors the philosophy behind the OS itself. These drivers, limited documentation, and a few example programs are available at stm.lbl.gov/comedi/.
Many users have found this website an important source of information on Linux drivers for data acquisition cards. For instance, if you surf over to National Instruments’ (NI) site, you’ll find that the company supplies a version of LabVIEW for Linux. However, when you start digging for drivers, you’ll discover that LabVIEW doesn’t work directly with hardware under Linux. NI also doesn’t offer any Linux drivers for its data acquisition boards, but instead refers you to the Comedi site.
The good news is that contributions from engineers around the world are increasing the number of cards and manufacturers for which you can find Comedi drivers. The not-so-good news is that several problems linger in the background.
First, the selection of vendors for which users have submitted Comedi drivers remains relatively small. Even for the most popular companies, not all their products are represented. These drivers support only the very basic features of the cards, and they do not encompass a comprehensive feature set. Indeed, it’s unrealistic to expect any general-purpose driver written to support a wide range of I/O cards to be optimized for any one of them.
Finally, you should have a reasonably high level of expertise with Linux and low-level data acquisition programming before you tackle a Comedi driver. The documentation is spotty at best. Even though the Comedi site includes a lively forum for exchanging technical information, some questions simply remain unanswered, and there’s no dedicated support staff you can count on.
Let’s look at the components that make up Comedi as well as how to use them. There are two key elements.
A device driver is designed for a specific piece of hardware, and collectively drivers fall under the name Comedi. These drivers implement a set of common functions and rely on individual low-level code for specific tasks.
Each driver is implemented as a core Linux kernel module, which you compile separately. After being dynamically loaded, these modules function as if they were part of the kernel.
The Comedi driver set consists of those files that various engineers have submitted to the Comedi site for use by others. They consist of two major types:
- General-purpose drivers. This group includes drivers that interface to the classic 8255 digital I/O chip (but work with the device only in Mode 0) and those that borrow lines from the parallel port for digital I/O tasks. Not present at this time is a sound-card driver that would allow for analog inputs with generic hardware.
- Vendor-specific drivers, with support for selected cards from Adlink, Keithley, Measurement Computing, Data Translation, Intelligent Instrumentation, Quanser Consulting, National Instruments, Advantech, Quatech, and Analog Devices.
The second major component of Comedi is comedilib, a user-space library that provides a common user interface to the Comedi device drivers. The distribution files also come with configuration and calibration utilities as well as demo programs.
In addition, the website includes kcomedilib, an alternative interface library. It is a kernel module that you link into the OS and allows real-time tasks to make calls into a Comedi driver from the kernel space.
To load the drivers and operate a data acquisition card with the help of Comedi, you must follow steps similar to these:
- Go to the comedi-0.7.xx directory.
- Type make to compile the kernel modules.
- Type make install to copy the compiled modules to the /lib/modules directory.
- Type make dev to create the device files.
- Type modprobe to load the comedi kernel module and the driver. For example, typing modprobe 8255 loads both the comedi.o and 8255.o modules in memory so that they can be used by comedilib. For some cards, you might need to include multiple files. For instance, with some National Instruments cards, you need the specific NI file plus the generic 8255 driver if you plan to use digital I/O.
- Finally, enable the board-specific driver. To do so, run comedi_config. That utility tells the library which board you are working with. The main page of this utility indicates that you must know details about the card such as the I/O base address, interrupts, and DMA channels. You also might have to tell it whether a card is configured for unipolar or bipolar operation and if it is set for single-ended or differential operation.
Now it’s a good idea to see if the comedi kernel module can detect the hardware. It is advisable to go to one of the demo programs to see if the hardware and software are correctly installed.
As an initial test, use ./info, which prints a list of subdevices the driver recognizes. Then continue with ./inp –s -c to read individual samples or use ./out -s-c to set an output value.
Because the driver module is part of the kernel, it prints messages to the kernel logs, which you can access through the dmesg command or view them directly at /var/log/messages. You either will see a configuration failure message or a line that indicates that the module correctly identified the board.
With installation and initial tests complete, you can start programming your application in Comedi. Let’s examine some of the commands in comedilib.
Be aware that Comedi works with subdevices on a given card. For example, the analog-input section is a subdevice as are analog output, digital input, digital output, counter, timer, memory, calibration DACs, and processor/DSP.
Then you can use other commands to interrogate the status or configuration of a subdevice. For instance, comedi_get_n_channels() returns the number of channels in the specified subdevice.
The commands you probably will use most often are comedi_data_read() and comedi_data_write(). As their names imply, they read or write a single analog sample on the specified channel; a read places the data value in the location pointed to by a variable in the calling arguments.
To get an idea of the maximum speed you can expect with these functions, you might refer to a recent thread on the Comedi discussion group. A posting from the group leader notes that the time to read an analog input is a combination of the kernel/user context switch (typically microseconds), the device setup time (a few microseconds), and the actual time to convert the samples. The peak sampling time will vary with the speed of the CPU clock and other system hardware components.
Next, consider comedi_sv_init(), which performs an averaging function to filter out noise and makes it easier to accurately measure a slowly varying analog input, one that is effectively constant over roughly 100 conversions. However, because these conversions can sometimes be preempted by scheduling, for most purposes, a slowly varying signal should be roughly constant for greater than 20 ms (the default Linux timeslice).
Asynchronous Operation And DMA
Single-point I/O won’t handle many real-world applications, and you’ll often want asynchronous acquisition where an onboard timer or external event triggers an acquisition or scan rather than wait for software to trigger that activity. For such situations, Comedi comes with a separate set of cmd functions that combine the standard commands along with another argument that defines a trigger source.
An example program provided with the code, cmd.c, illustrates how to work with the command library, but it also shows some of the tricky parts and unanticipated problem areas you might encounter. The program uses a series of special comedilib routines to find a command that works for a given hardware device. First, prepare_cmd() explicitly creates a command that might or might not work with your device.
As a result, you’ll want to test the command, and here the library includes comedi_command_test(). It determines if the trigger sources and function arguments are valid for the selected subdevice. If either the trigger or arguments are invalid, this function makes several attempts to find valid replacements, but it isn’t guaranteed to be successful.
Just as important for many applications is the capability to support DMA, which comes into play for high-speed acquisitions of multiple scans that exceed the size of an onboard buffer. For a small subset of cards, users have written drivers that support DMA, but you’ll have to read the comments embedded in the various driver source files to determine which ones do and if there are any limitations.
Because Comedi becomes part of the Linux kernel, the DMA buffer exists in the kernel memory space, and you must incur the overhead of moving the dataset into user memory. For this task, you have two options. Comedi supports the Linux mmap() function, or you could use the standard read() function, which would be less efficient. In either case, the extra overhead might place some limitations on the value of DMA operation in some applications.
Although Comedi drivers can handle many tasks, remember that you can’t expect everything from what is, on one hand, intended as a universal driver and, on the other hand, coming from other engineers who have something very specific in mind. They write drivers to handle some specific tasks in the manner they need and with a particular hardware setup.
Members of the engineering community who have looked at Comedi have mixed reactions. One group is happy for any head start they can get from fellow engineers. Others believe that the supplied code has little to offer, that it makes programmers sift through endless blocks of conditional compilations and follow the initialization of countless function pointers and other things in gigantic structures. Only then, these people argue, can anyone even begin to guess what the code really is going to do.
They also claim that the code is so sparsely commented that it’s impossible to determine what capabilities and functions it intends to support and how to use them. In this vein, note that the comedilib documentation makes a passing reference to more than a dozen undocumented functions, doing nothing more than to list them as undocumented.
Another issue is the application programming interface (API) itself. In trying to cover shared functions from a wide range of cards with one interface, that interface, by necessity, must handle only relatively simplistic operations. It becomes awkward to work with when developing an application that takes any level of sophistication. Consider the various programming models from different manufacturers as well as the set of timing and triggering methods you’ll encounter, and it becomes clear why a single monolithic universal driver has serious disadvantages.
For instance, the basic Comedi command handles only single-point analog I/O and basic counter/timer operations. The basic driver performs digital I/O on a single-line basis. Even though the driver includes a command called comedi_dio_bitfield(), which reads multiple channels with one call, the current implementation reads and writes bits using separate system calls. Also, it is not possible to access more than 31 channels with this function.
You can’t use an analog output for stimulus and simultaneously run an analog input to measure the response. Also, if you’re looking for true simultaneous sampling, you’ll be hard-pressed to find a driver that supports such a card.
When there are no alternatives, Comedi can give you a considerable head start in developing drivers for a data acquisition card. However, some companies have recognized the growing demand for this type of support software. They distribute professionally written, fully supported drivers optimized to work with all of a board’s functions.
Consider, for instance, the Linux drivers that United Electronic Industries ships with its PCI and PXI-based I/O boards. This PowerDAQ for Linux software is available at no charge, there are no run-time royalty payments, and the drivers support every board function under a given hardware environment. You also can run multiple subsystems simultaneously, such as collecting analog inputs, evaluating them, and while in the same control loop, setting digital outputs in response.
An additional advantage is the consistency of a single API for Win32, Win16, Linux, RTLinux, and even QNX. This driver uses huge chunks of memory shared between the kernel and user spaces so you do not need to copy data with functions such as put user() or get user(). The driver comes with many examples that accelerate the development of real-world applications, and UEI has automated the installation of these drivers under all major Linux distributions.
In conclusion, if you’re working under a tight deadline to develop a mission-critical system, you might think twice about working with user-community-supported drivers rather than with commercially developed and professionally supported drivers—especially if they don’t cost anything extra.
- Comedi home page, stm.lbl.gov/comedi/
- PowerDAQ for Linux, source code and example programs from United Electronic Industries for its PCI and PXI I/O modules, www.ueidaq.com/cgi-bin/products.cgi?l=2&o=385
- “How Do I Install a Comedi Linux DAQ Driver on Redhat 7.0?,” National Instruments’ KnowledgeBase, digital.ni.com/public.nsf/3efedde4322fef19862567740067f3cc/
- Jennings, R, “Hands On With LabVIEW and Embedded Linux,” www.linuxdevices.com/articles/AT3267273722.html
About the Author
Paul G. Schreier is director of international marketing at United Electronic Industries. He holds bachelor’s degrees in humanities and electrical engineering from the University of Notre Dame and a master’s in engineering management from Northeastern University. Prior to working with UEI, he was the founding editor of Personal Engineering & Instrumentation News. United Electronic Industries, 10 Dexter Ave., Watertown, MA 02472, 617-924-1155, e-mail: [email protected]
Return to EE Home Page
Published by EE-Evaluation Engineering
All contents © 2001 Nelson Publishing Inc.
No reprint, distribution, or reuse in any medium is permitted
without the express written consent of the publisher.