Module: xenomai-2.5 Branch: master Commit: 2625e927276e6a7ad47e767dcfaecb458e2ae8c2 URL: http://git.xenomai.org/?p=xenomai-2.5.git;a=commit;h=2625e927276e6a7ad47e767dcfaecb458e2ae8c2
Author: Gilles Chanteperdrix <[email protected]> Date: Thu Sep 30 02:18:06 2010 +0200 arm: better calibrate the timer programming latency --- include/asm-arm/bits/init.h | 4 +- ksrc/arch/arm/hal.c | 63 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/include/asm-arm/bits/init.h b/include/asm-arm/bits/init.h index a6ecc17..133f9e8 100644 --- a/include/asm-arm/bits/init.h +++ b/include/asm-arm/bits/init.h @@ -3,7 +3,7 @@ * * ARM port * Copyright (C) 2005 Stelian Pop - * + * * Xenomai is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -51,7 +51,7 @@ unsigned long xnarch_calibrate_timer(void) { /* Compute the time needed to program the decrementer in aperiodic mode. The return value is expressed in timebase ticks. */ - return xnarch_ns_to_tsc(rthal_timer_calibrate())? : 1; + return rthal_timer_calibrate() ? : 1; } int xnarch_calibrate_sched(void) diff --git a/ksrc/arch/arm/hal.c b/ksrc/arch/arm/hal.c index 2c0dcfe..1c88c73 100644 --- a/ksrc/arch/arm/hal.c +++ b/ksrc/arch/arm/hal.c @@ -43,6 +43,7 @@ #include <asm/uaccess.h> #include <asm/unistd.h> #include <asm/xenomai/hal.h> +#include <asm/cacheflush.h> #ifdef CONFIG_PROC_FS #include <linux/proc_fs.h> #endif /* CONFIG_PROC_FS */ @@ -155,14 +156,70 @@ void rthal_timer_notify_switch(enum clock_event_mode mode, EXPORT_SYMBOL(rthal_timer_notify_switch); #endif +#define RTHAL_CALIBRATE_LOOPS 10 + unsigned long rthal_timer_calibrate(void) { - return 1000000000 / RTHAL_CLOCK_FREQ; + unsigned long long next_shot = 0, start, end, sum = 0, sum_sq = 0; + volatile unsigned const_delay = 0xffffffff; + unsigned long result, flags, tsc_lat; + unsigned delay = const_delay; + unsigned diff; + int i, j; + + flags = rthal_critical_enter(NULL); + + rthal_read_tsc(start); + barrier(); + rthal_read_tsc(end); + tsc_lat = end - start; + barrier(); + + if (__ipipe_mach_timerstolen) { + rthal_read_tsc(next_shot); + next_shot += rthal_imuldiv(__ipipe_mach_get_dec(), + RTHAL_CLOCK_FREQ, RTHAL_TIMER_FREQ); + next_shot -= tsc_lat; + } + + for (i = 0; i < RTHAL_CALIBRATE_LOOPS; i++) { + flush_cache_all(); + for (j = 0; j < RTHAL_CALIBRATE_LOOPS; j++) { + rthal_read_tsc(start); + barrier(); + rthal_timer_program_shot( + rthal_nodiv_imuldiv_ceil(delay, rthal_tsc_to_timer)); + barrier(); + rthal_read_tsc(end); + diff = end - start - tsc_lat; + + sum += diff; + sum_sq += diff * diff; + } + } + + if (__ipipe_mach_timerstolen) { + delay = (next_shot > end + ? rthal_nodiv_imuldiv_ceil(next_shot - end, + rthal_tsc_to_timer) + : 0); + rthal_timer_program_shot(delay); + } else + __ipipe_mach_release_timer(); + + rthal_critical_exit(flags); + + /* Use average + standard deviation as timer programming latency. */ + do_div(sum, RTHAL_CALIBRATE_LOOPS * RTHAL_CALIBRATE_LOOPS); + do_div(sum_sq, RTHAL_CALIBRATE_LOOPS * RTHAL_CALIBRATE_LOOPS); + result = sum + int_sqrt(sum_sq - sum * sum) + 1; + printk("calibrate result: %lu\n", result); + return result; } int rthal_irq_host_request(unsigned irq, - rthal_irq_host_handler_t handler, - char *name, void *dev_id) + rthal_irq_host_handler_t handler, + char *name, void *dev_id) { unsigned long flags; _______________________________________________ Xenomai-git mailing list [email protected] https://mail.gna.org/listinfo/xenomai-git
