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");
}

Reply via email to