/* ================================================================= * This somewhat more complicated program does the same schedule * function, but writes the data to a fifo that can be read by * a program running in user space. * * Test the RTAI scheduler. Before running this module, you * must install rtai and rtai_sched. * * ================================================================= */ #include #include #include #include #include #include #define TICK_PERIOD 5000000000 // 5 seconds in nanoseconds #define STACK_SIZE 1000 #define TASK_PRIORITY 1 #define FIFO 0 static RT_TASK rt_task; static void printTime (int val) { RTIME t; long time; long last_time; long interval; long error; // Initialize the last time. last_time = 0l; while (1) { /* * Get the time and print the interval time and error. * rt_get_time_ns gets the time since the timer started in nanoseconds */ t = (long) rt_get_time_ns (); // time = (int) t * 0.000001; // (t / 1000000 + 0.5); interval = t - last_time; error = interval - TICK_PERIOD; printk ("Interval = %ld, error = %ld\n", interval, error); last_time = t; /* Send the data to the fifo * * rtf_put sends a character buffer to the fifo * the fifo identifier * a pointer to the buffer * the size of the buffer (useable data) */ rtf_put (FIFO, &interval, sizeof (interval)); rtf_put (FIFO, &error, sizeof (error)); /* * That was fun, lets do it again. * rt_task_wait_period suspends this task until the next period is * reached. */ rt_task_wait_period (); } } int init_module (void) { RTIME tick_period; /* Create the FIFO buffer * rtf_create creates the fifo * FIFO is the fifo ID * the size of the fifo in bytes */ rtf_create (FIFO, 4000); /* * Set the mode to periodic and create a task * rt_task_init creates a task * task structure to save task data * the thread to execute when the task runs; this task must * have the calling sequence void f (int). * the data to pass to the newly created task - a single int * the stack size - STACK_SIZE is the default size constant * the task priority, 0 is highest, RT_LOWEST_PRIORITY is lowest * a flag indicating if the floating point unit will be used * the * a function to be called when the task become the current running * task after a context switch. * * rt_set_periodic_mode sets the periodic mode for the system timer; * the alternative is rt_set_oneshot_mode for a single interrupt * and then the task must be rescheduled. */ rt_set_periodic_mode (); rt_task_init (&rt_task, printTime, 1, STACK_SIZE, TASK_PRIORITY, 0, 0); /* * Set up a tick period and start the periodic scheduling. * * start_rt_timer starts the timer with the given period. nano2count * converts the time in nanoseconds to the internal clock representation. * * rt_task_make_periodic makes the task periodic with the parameters: * the task to schedule periodically * the time at which to start periodic scheduling; rt_get_time * gets that to the current time. * the period */ tick_period = start_rt_timer (nano2count (TICK_PERIOD)); rt_task_make_periodic (&rt_task, rt_get_time () + tick_period, tick_period); return 0; } void cleanup_module (void) { /* * Stop the timer and dispose of the fifo and task. */ stop_rt_timer (); rtf_destroy (FIFO); rt_task_delete (&rt_task); return; }