Hallo, attached is a piece of code where I want to aquire data using comedis callback function. After insmod the module I can read the last message set "FP on thread" and than the system reboots or is frozen. IMO I have to use the oneshot mode ( As I right remember I have to use HRTIME_INFINITY as period) for the thread. This is wakeup() by the callback and gets suspended by pthread_suspend_np. rtl_schedule() is done by this function itself- see the source on RTL. In period mode with 1 Hz and pthread_wait_np() the thread_code seems to work well. What it's going here and where is the fault, please help. The reason why I'm using threads is the use of fp inside for later use. If I'm right, that I can't use fp inside a normal kernel module ? Thanks Olaf
#ifdef __RTL__ # include <rtl_conf.h> # ifndef RTLINUX_V2 # error "We need NMN RTLinux v2!" # endif #endif /*** * standard linux modules includes */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/version.h> #include <linux/errno.h> /*** * RTL 2.2 specific includes */ #ifdef RTLINUX_V2 #include <rtl.h> #include <rtl_fifo.h> #include <rtl_sched.h> #include <rtl_sync.h> #include <rtl_debug.h> #endif #include <comedi.h> #define THREAD_STACK_SIZE 2048 pthread_t rt_thread; /* the thread */ unsigned int ai_dev=0; unsigned int ai_subdev=0; unsigned int ai_chan=CR_PACK(0,0,AREF_GROUND); comedi_trig ai_trig; unsigned int ao_dev=0; unsigned int ao_subdev=1; unsigned int ao_chan=CR_PACK(0,0,AREF_GROUND); comedi_trig ao_trig; sampl_t ai_data = 0; sampl_t ao_data = 0; void *thread_code(void *param) { static size_t ctr = 0; int ret = 0; static char buf[20]; rtl_printf("set FP on thread\n"); if((ret = pthread_setfp_np(pthread_self(), 1)) != 0) { rtl_printf("unable to use floating-point operations in realtime thread (error %d) !\n", ret); } while(1) { //pthread_wait_np(); pthread_suspend_np(pthread_self()); ao_data = ai_data; comedi_trig_ioctl(ao_dev, ao_subdev, &ao_trig); sprintf(buf, "%10d\n", ctr++); rtf_put(1, buf, 11); rtl_printf("suspended pthread self\n"); } return 0; } int callback(unsigned int flags, void *arg) { pthread_wakeup_np(rt_thread); return 1; } int init_module(void) { int ret = 0; pthread_attr_t attr; struct sched_param sched_param; // install rtf rtf_destroy(1); ret = rtf_create(1, 4096); // set up input structure ai_trig.subdev=ai_subdev; // Subdevice number ai_trig.mode=2; // Mode 2: event-driven program ai_trig.flags=TRIG_WAKE_EOS; // Trigger on end-of-scan event ai_trig.n_chan=1; // One input channel ai_trig.chanlist=&ai_chan; // Pointer to the channel variable ai_trig.data=&ai_data; // Address of the variable to put conversion result ai_trig.data_len = sizeof(ai_data); // lenght of data ai_trig.n=1; // Single sample ai_trig.trigsrc=0; ai_trig.trigvar = 100000; // Sampling period in ns eq. 10 kHz ai_trig.trigvar1 = 1000; // // set up output structure ao_trig.subdev=ao_subdev; ao_trig.mode=0; ao_trig.flags=0; ao_trig.n_chan=1; ao_trig.chanlist=&ao_chan; ao_trig.data=&ao_data; ao_trig.data_len=sizeof(ao_data); ao_trig.n=1; ao_trig.trigsrc=0; ao_trig.trigvar=0; ao_trig.trigvar1=0; // lock the subdevices comedi_lock_ioctl(ai_dev,ai_subdev); comedi_lock_ioctl(ao_dev,ao_subdev); // ... create the realtime task with the default function pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE); sched_param.sched_priority = 100; pthread_attr_setschedparam(&attr, &sched_param); rtl_printf("create thread\n"); if((ret = pthread_create(&rt_thread, &attr, thread_code, (void *)0)) != 0) { rtl_printf("unable to create realtime thread (error %d) !\n", ret); } #if 1 rtl_printf("make thread periodic\n"); if((ret = pthread_make_periodic_np(rt_thread, gethrtime() + 1000, HRTIME_INFINITY)) != 0) { rtl_printf("unable to make realtime thread periodic (error %d) !\n", ret); } #else rtl_printf("make thread periodic (1s)\n"); if((ret = pthread_make_periodic_np(rt_thread, gethrtime() + 1000, 1000000000)) != 0) { rtl_printf("unable to make realtime thread periodic (error %d) !\n", ret); } #endif rtl_printf("register our callback function\n"); ret=comedi_register_callback(ai_dev, ai_subdev, COMEDI_CB_EOS, &callback, (void *)0); /* start acq. */ ret=comedi_trig_ioctl(ai_dev,ai_subdev,&ai_trig); rtl_printf("comedi_callback module started\n"); return 0; } void cleanup_module(void) { comedi_cancel_ioctl(ai_dev,ai_subdev); comedi_unlock_ioctl(ai_dev,ai_subdev); comedi_unlock_ioctl(ao_dev,ao_subdev); pthread_suspend_np(rt_thread); pthread_setfp_np(rt_thread, 0); pthread_delete_np(rt_thread); rtf_destroy(1); rtl_printf("comedi_callback stopped\n"); }