Captain's Universe Home
Captain's Universe Home
Cosmic Ray Muon DetectorTeleGarden Pages
Time on MarsBryophyllum Plants
Jupiter Radio AstronomyAncient Pages
Salzburg Tourist GuideEarth Magnetometer
  H O M E     AJAX & MORE     LINUX & MORE     RTAI     XENOMAI     ADEOS IPIPE      
    JAVA & BROWSERS     *NIX     ELECTRONICS     REVIEWS     ARTEMIA     FAIRY SHRIMP      


Xenomai Timer Task Example

Here we have two simple Xenomai hard real time user-space timer examples. They actually do the same, but with different approaches. Both examples are for Xenomai 2.1 - everything is compiled into the kernel, so we don't need to load kernel modules before starting the examples.

UPDATE:
Example #2 works only if the periodic timer support is enabled (it is disabled by default). Enable it when configuring the kernel:
Real-time sub-system  ---> 
	Machine  --->
		[ ] Enable periodic timer support
As a sidenote, make sure ipipe is enabled:
General setup  ---> 
	[*] Interrupt pipeline

From the Xenomai-core maillist:
Hannes Mayer: What's the reason why the periodic mode is disabled by default ?
Philippe Gerum: Because AFAICT, most people would rather use the aperiodic timing mode in usual configurations for a much better accuracy. Since the periodic mode uses the available hw PIT and programs it once (or even some decrementer but without handling the time drift when reprogramming it after each shot), it suffers from cumulated rounding errors of the period. If you look at the jitter results of a trivial periodic loop over a broad timescale, you will see the wakeup time irremediably drift, whilst the average interval between shots remains stable and reasonably accurate. The periodic timer should be used for configurations that only need to enforce delays or timeouts, and not, well, precise timings."


Compile the program "timer.c" with "make" (Makefile below).
Run "timer" (press CTRL-C to end it).

Example #1 - timer.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/io.h>
#include <sys/mman.h>
#include <native/task.h>
#include <native/queue.h>
#include <native/intr.h>

#define STACK_SIZE 8192
#define STD_PRIO 1

RT_TASK test_task_ptr;
int int_count = 0;
int end = 0;

//                     --s-ms-us-ns
RTIME task_period_ns =   1000000000llu;

void testtask(void *cookie){
	int count = 0;
	int ret;
	unsigned long overrun;
	ret = rt_task_set_periodic(NULL, TM_NOW, rt_timer_ns2ticks(task_period_ns));
	if (ret) {
		printf("error while set periodic, code %d\n",ret);
		return;
	}

	while(!end){
		ret = rt_task_set_mode(0, T_PRIMARY, NULL);
		if (ret) {
			printf("error while rt_task_set_mode, code %d\n",ret);
			return;
		}
		ret = rt_task_wait_period(&overrun);
		if (ret) {
			printf("error while rt_task_wait_period, code %d\n",ret);
			return;
		}
		count++;
		printf("message from testtask: count=%d\n", count);
		fflush(NULL);
	}
}
// signal-handler, to ensure clean exit on Ctrl-C
void clean_exit(int dummy) {
	printf("cleanup\n");
	end = 1;
	rt_task_delete(&test_task_ptr);
	printf("end\n");
}

int main(int argc, char *argv[]) {
	int err, ret;
	printf("start\n");
	// install signal handler
	signal(SIGTERM, clean_exit);	
	signal(SIGINT, clean_exit);	
	// start timer -> depricated in Xeno 2.2
	/* ret = rt_timer_start(TM_ONESHOT);
	switch (ret) {
		case 0:       printf("timer started\n");
		              break;
		case -EBUSY:  printf("timer is running\n");
		              break;
		case -ENOSYS: printf("can't start timer\n");
		              return ret;
	}
	*/
	mlockall(MCL_CURRENT | MCL_FUTURE);
	err = rt_task_spawn(&test_task_ptr, "Timer", STACK_SIZE, STD_PRIO, 0, &testtask, NULL);
	if (err) {
		printf("error rt_task_spawn\n");
		return 0;
	}
	// wait for signal & return of signal handler
	pause();
	fflush(NULL);
	return 0;
}


Example #2 - timer.c

Remember: This works only if periodic timer support is enabled (see above). Usually you should use aperiodic mode (example #1) to have better accuracy.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/io.h>
#include <sys/mman.h>
#include <native/task.h>
#include <native/queue.h>
#include <native/intr.h>

#define STACK_SIZE 8192
#define STD_PRIO 1

RT_TASK test_task_ptr;
int int_count = 0;
int end = 0;

void testtask(void *cookie){
	int count = 0;
	while(!end){
 		rt_task_sleep(1000);	// sleep 1 sec (1000 ticks, 1ms each)
		count++;
		printf("message from testtask: count=%d\n", count);
		fflush(NULL);
	}
}
// signal-handler, to ensure clean exit on Ctrl-C
void clean_exit(int dummy) {
	printf("cleanup\n");
	end = 1;
	rt_task_delete(&test_task_ptr);
	printf("end\n");
}

int main(int argc, char *argv[]) {
	int err;
	printf("start\n");
	// install signal handler
	signal(SIGTERM, clean_exit);	
	signal(SIGINT, clean_exit);	
	// start timer -> depricated in 2.2
	/* err = rt_timer_start(1000000); // 1ms ticks
	if (err) {
		printf("error rt_timer_start - did you 'Enable periodic timer support' ?\n");
		return 0;
	}
	*/
	mlockall(MCL_CURRENT | MCL_FUTURE);
	err = rt_task_spawn(&test_task_ptr, "Timer", STACK_SIZE, STD_PRIO, 0, &testtask, NULL);
	if (err) {
		printf("error rt_task_spawn\n");
		return 0;
	}
	// wait for signal & return of signal handler
	pause();
	fflush(NULL);
	return 0;
}


Makefile

prefix := $(shell xeno-config --prefix)

ifeq ($(prefix),)
$(error Please add <xeno-install>/bin to your PATH variable)
endif

CC = $(shell xeno-config --cc)
LXRT_CFLAGS = $(shell xeno-config --xeno-cflags)
LXRT_LDFLAGS = $(shell xeno-config --xeno-ldflags)

all: timer

timer: timer.c
	$(CC) $(LXRT_CFLAGS) $(LXRT_LDFLAGS) -lnative -o $@ $<

clean:
	rm -f *.o timer

.PHONY: clean
Last-Modified: Sun, 23 Jul 2006 19:36:57 GMT

Google
 
Web www.captain.at
go to top
© 1996-2010 . All rights reserved.
No reproduction, distribution, publishing or transmission of the copyrighted materials at this site is permitted. Policy
go to top