03-21-2019 11:29 AM
Hello,
I don't know if this is the proper Forum, but I'm trying to build a kernel module which uses DAQmx in a CentOs7.5. So far I've installed DAQmx for linux and successfully built an user space application given as an example by NI and I've tried to build a similar application in kernel space. When I tried to compile that I got this message :
"WARNING: "DAQmxStopTask" [...] undefined!"
I know that this message normally happens if a dependence is not properly set or loaded, but I know, through lsmod, that ni's modules are loaded in my machine, so I'd like to know how to proper interface DAQmx to a kernel module.
For reference, here is my code
#include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/proc_fs.h> #include <linux/stringify.h> #include <linux/cdev.h> #include <asm/io.h> #include <NIDAQmx.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Victor Costa"); MODULE_DESCRIPTION("DAQMX_LOADER using drivers"); MODULE_VERSION("0.1"); static int error=0; static char errBuff[2048]={'\0'}; static TaskHandle taskHandle=0; static double data[1000]; static void error_handler(void); static int CVICALLBACK DoneCallback(TaskHandle taskHandle, int status, void *callbackData); #define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else static int __module_init (void) { printk(KERN_DEBUG "DAQMX<1>: Loading Module\n"); for(int i=0;i<1000;i++) data[i] = 9.95; DAQmxErrChk (DAQmxCreateTask("",&taskHandle)); DAQmxErrChk (DAQmxCreateAOVoltageChan(taskHandle,"Dev1/ao0","",-10.0,10.0,DAQmx_Val_Volts,NULL)); DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",1000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000)); DAQmxErrChk (DAQmxRegisterDoneEvent(taskHandle,0,DoneCallback,NULL)); /*********************************************/ // DAQmx Write Code /*********************************************/ DAQmxErrChk (DAQmxWriteAnalogF64(taskHandle,1000,0,10.0,DAQmx_Val_GroupByChannel,data,NULL,NULL)); /*********************************************/ // DAQmx Start Code /*********************************************/ DAQmxErrChk (DAQmxStartTask(taskHandle)); Error: error_handler(); return 0; } static void __module_exit (void) { printk(KERN_DEBUG "DAQMX<1>: Unloading Module\n"); } module_init(__module_init); module_exit(__module_exit); static void error_handler(void) { if( DAQmxFailed(error) ) DAQmxGetExtendedErrorInfo(errBuff,2048); if( taskHandle!=0 ) { /*********************************************/ // DAQmx Stop Code /*********************************************/ DAQmxStopTask(taskHandle); DAQmxClearTask(taskHandle); } if( DAQmxFailed(error) ) printk(KERN_DEBUG"DAQMX<1> Error: %s\n",errBuff); } static int CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData) { char errBuff[2048]={'\0'}; // Check to see if an error stopped the task. DAQmxErrChk (status); Error: if( DAQmxFailed(error) ) { DAQmxGetExtendedErrorInfo(errBuff,2048); DAQmxClearTask(taskHandle); printk(KERN_DEBUG"DAQMX<1> Error: %s\n",errBuff); } return 0; }
03-22-2019 08:46 AM
In general, you can't directly call usermode libraries from a kernel module, on any dual-mode operating system. What are you trying to do? Kernel-mode programming is quite a different sort of beast and if you have the option sticking to a user-mode solution tends to be considerably easier to debug and iterate on.
The only stable (and supported) interface to DAQmx is through its usermode libraries (libdaqmx). Those call into the DAQmx kernel modules through a user-kernel interface that we don't consider to have a stable ABI... it may change between versions, which means that the usermode side and the kernelmode side have to match. (They're installed together, so for most users it's not ordinarily an issue, because the implementation details are hidden behind libdaqmx.)
If you do need to interact with DAQmx from a kernel module, one way to do so might be to use the "call_usermodehelper" function in <linux/umh.h>... for that, you'd build yourself a usermode program that does the DAQmx interaction (and links against libdaqmx) then use call_usermodehelper to invoke it from your kernel module.