Hi guys,
I have installed a Debian+Xenomai (2.6.0) OS on my Gumstix Overo.
I want to evaluate the execution time of a simple program, executed as a
real-time thread.
I definitely wonder about which functions to use, as I have completely
inconsistent measures.
I have tried using rt_timer_read, rt_timer_tsc, clock_gettime.
I also directly read the CNNT register with ARM instructions (which is the
only one I think correct) in order to have a (good?) reference.
I join the simple program I use.
The output is :
----- ASM instruction -----
start: 62483 ; end: 172961 ; (s-e): 110478 ; overhead: 102 ;
(s-e-overhead): 110376 ; CET: 110478
----- Xenomai rt_timer_read -----
start: 1016 ; end: 3435090911 ; (s-e): 1016 ; CET: 3435246834
----- Xenomai rt_timer_tsc -----
start: 13 ; end: 938009132 ; (s-e): 13 ; CET: 938011124
----- Xenomai clock_gettime -----
[ s] start: 946689173 ; end: 946689173 ; (s-e): 0 ; CET: 0
[ns] start: 231412764 ; end: 231569761 ; (s-e): 156997 ; CET: 156997
So that I can support that the correct execution time is around 110 000
(ticks?)
Only the nsecs of clock_gettime seem to be consistent ; other functions
return erratic values!
What am I doing wrong?
Should I initialize something in my program (I tried
rt_timer_set_mode(TM_ONESHOT) without any change)?
Should I check or change my kernel or xenomai configuration options?
Any (urgent) help would be appreciated!
Thanks,
Charles.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>
#include <native/task.h>
#include <native/timer.h>
#include <rtdk.h>
#include <posix/time.h>
RT_TASK task;
int sum() {
int i = 0;
int s = 0;
for(i = 0; i < 10000; i++)
s += i;
return s;
}
static inline unsigned long int get_cyclecount (void)
{
unsigned long int value;
//MRC p15, 0, <Rd>, c9, c13, 0 ; Read CCNT Register
asm volatile ("MRC p15, 0, %[Rd], c9, c13, 0\t\n": [Rd] "=r"(value));
return value;
}
static inline void init_perfcounters (int32_t do_reset, int32_t enable_divider)
{
// in general enable all counters (including cycle counter)
int32_t value = 1;
// peform reset:
if (do_reset)
{
value |= 2; // reset all counters to zero.
value |= 4; // reset cycle counter to zero.
}
if (enable_divider)
value |= 8; // enable "by 64" divider for CCNT.
value |= 16;
// program the performance-counter control-register:
asm volatile ("MCR p15, 0, %0, c9, c12, 0\t\n" :: "r"(value));
// enable all counters:
asm volatile ("MCR p15, 0, %0, c9, c12, 1\t\n" :: "r"(0x8000000f));
// clear overflows:
asm volatile ("MCR p15, 0, %0, c9, c12, 3\t\n" :: "r"(0x8000000f));
}
void sum_task(void *arg) {
// Init ASM registers
init_perfcounters(1, 0);
// Init Timer
rt_timer_set_mode(TM_ONESHOT);
rt_printf("----- ASM instruction -----\n");
unsigned long int asm_s, asm_e, asm_c, asm_o;
asm_o = get_cyclecount(); asm_o = get_cyclecount() - asm_o;
asm_s = get_cyclecount();
sum();
asm_e = get_cyclecount();
asm_c = asm_e - asm_s;
rt_printf("start: %lu ; end: %lu ; (s-e): %lu ; overhead: %lu ; (s-e-overhead): %lu ; CET: %lu \n",
asm_s, asm_e, (asm_e - asm_s), asm_o, ((asm_e-asm_s)-asm_o), asm_c);
rt_printf("----- Xenomai rt_timer_read -----\n");
RTIME read_s, read_e, read_c;
read_s = rt_timer_read();
sum();
read_e = rt_timer_read();
read_c = read_e - read_s;
rt_printf("start: %lu ; end: %lu ; (s-e): %lu ; CET: %lu \n", read_s, read_e, (read_e - read_s), read_c);
rt_printf("----- Xenomai rt_timer_tsc -----\n");
RTIME tsc_s, tsc_e, tsc_c;
tsc_s = rt_timer_tsc();
sum();
tsc_e = rt_timer_tsc();
tsc_c = tsc_e - tsc_s;
rt_printf("start: %lu ; end: %lu ; (s-e): %lu ; CET: %lu \n", tsc_s, tsc_e, (tsc_e - tsc_s), tsc_c);
rt_printf("----- Xenomai clock_gettime -----\n");
struct timespec clock_s, clock_e, clock_c;
clock_gettime(CLOCK_REALTIME, &clock_s);
sum();
clock_gettime(CLOCK_REALTIME, &clock_e);
clock_c.tv_sec = clock_e.tv_sec - clock_s.tv_sec;
clock_c.tv_nsec = clock_e.tv_nsec - clock_s.tv_nsec;
rt_printf("[ s] start: %d ; end: %d ; (s-e): %d ; CET: %d \n",
clock_s.tv_sec, clock_e.tv_sec, (clock_e.tv_sec - clock_s.tv_sec), clock_c.tv_sec);
rt_printf("[ns] start: %d ; end: %d ; (s-e): %d ; CET: %d \n",
clock_s.tv_nsec, clock_e.tv_nsec, (clock_e.tv_nsec - clock_s.tv_nsec), clock_c.tv_nsec);
}
int main(int argc, char* argv[]) {
char str[10] ;
// Perform auto-init of rt_print buffers if the task doesn't do so
rt_print_auto_init(1);
// Lock memory : avoid memory swapping for this program
mlockall(MCL_CURRENT | MCL_FUTURE);
sprintf(str, "sum_test");
// rt_task_create(task, task name, stack size, priority, mode
rt_task_create(&task, str, 0, 50, 0);
// rt_task_start(task, task function, function argument
rt_task_start(&task, &sum_task, 0);
rt_task_join(&task);
}
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help