Yes, it solved the issue. There is one thing that bothers me, though. When I run "xeno-test", the average and minimal latencies are constant all the time.
The unpatched version of the xeno kernel seems more consistent when it comes to minimum, maximum and average latencies. I attached a couple of snippets of xeno-test outputs . Thanks, R. On Sun, Nov 7, 2010 at 4:45 AM, Gilles Chanteperdrix < [email protected]> wrote: > Gilles Chanteperdrix wrote: > > at91_enthus wrote: > >> Hi! > >> > >> I installed the latest xenomai patch on a AT91SAM9G20 board and > >> everything looked good at a first glance: no compilation problems, low > >> latencies. > >> > >> However, when I typed cat /proc/timer_list , the resolutions in cpu0 > >> and cpu1 items showed 100000 (ns). > >> (I compiled the Xenomai patched kernel with High Resolution Timers > enabled.) > >> > >> I don't have this problem when I boot a real time kernel (RT_PREEMPT). > > > > You mean another real-time kernel? If RT_PREEMPT uses the sys timer > > running at 32kHz, and it tells you that it has a 1ns resolution, then it > > is lying, because 32kHz, means a 30us resolution. > > > > Xenomai uses one TC as a timer at whatever frequency your chip proposes > > over 1 MHz, this means a resolution below 1us, the downside is that this > > also means a very short wrap time. And since the TC is also used as a > > clock, this means that we must enter the timer interrupt handler before > > the counter wraps. And this is something that Linux without Xenomai > > running can not guarantee. > > On the other hand, we can keep the timer ticking behind Linux' back. > Does the following patch fix the issue for you? > > diff --git a/arch/arm/mach-at91/at91_ipipe_time.c > b/arch/arm/mach-at91/at91_ipipe_time.c > index b0327eb..6c6f0d7 100644 > --- a/arch/arm/mach-at91/at91_ipipe_time.c > +++ b/arch/arm/mach-at91/at91_ipipe_time.c > @@ -76,9 +76,7 @@ > #define TCNXCNS(timer,v) ((v) << ((timer)<<1)) > #define AT91_TC_REG_MASK (0xffff) > > -static unsigned long next_match; > - > -static unsigned max_delta_ticks, min_delta_ticks; > +static unsigned max_delta_ticks, min_delta_ticks, tick_pending; > static struct clock_event_device clkevt; > static int tc_timer_clock; > > @@ -116,7 +114,11 @@ EXPORT_SYMBOL(__ipipe_mach_ticks_per_jiffy); > */ > static irqreturn_t at91_timer_interrupt(int irq, void *dev_id) > { > - clkevt.event_handler(&clkevt); > + if (__ipipe_mach_timerstolen || tick_pending) { > + tick_pending = 0; > + clkevt.event_handler(&clkevt); > + } > + > return IRQ_HANDLED; > } > > @@ -130,12 +132,8 @@ void __ipipe_mach_acktimer(void) > { > at91_tc_read(AT91_TC_SR); > > - if (unlikely(!__ipipe_mach_timerstolen)) { > - __ipipe_tsc_update(); > - next_match = (next_match + __ipipe_mach_ticks_per_jiffy) > - & AT91_TC_REG_MASK; > - write_RC(next_match); > - } > + if (unlikely(!__ipipe_mach_timerstolen)) > + __ipipe_mach_set_dec(max_delta_ticks); > } > > static void > @@ -147,7 +145,7 @@ at91_tc_set_mode(enum clock_event_mode mode, struct > clock_event_device *dev) > /* Disable all interrupts. */ > at91_tc_write(AT91_TC_IDR, ~0ul); > > - if (mode == CLOCK_EVT_MODE_PERIODIC) { > + if (mode == CLOCK_EVT_MODE_ONESHOT) { > unsigned long v; > > #ifndef CONFIG_ARCH_AT91SAM9263 > @@ -169,9 +167,7 @@ at91_tc_set_mode(enum clock_event_mode mode, struct > clock_event_device *dev) > /* Use the clock selected by at91_timer_init as input clock. > */ > at91_tc_write(AT91_TC_CMR, tc_timer_clock); > > - /* Load the TC register C. */ > - next_match = __ipipe_mach_ticks_per_jiffy; > - write_RC(next_match); > + __ipipe_mach_set_dec(max_delta_ticks); > > /* Enable CPCS interrupt. */ > at91_tc_write(AT91_TC_IER, AT91_TC_CPCS); > @@ -181,6 +177,14 @@ at91_tc_set_mode(enum clock_event_mode mode, struct > clock_event_device *dev) > } > } > > +static int > +at91_tc_set_next_event(unsigned long delta, struct clock_event_device > *dev) > +{ > + tick_pending = 1; > + __ipipe_mach_set_dec(delta); > + return 0; > +} > + > /* > * Reprogram the timer > */ > @@ -208,10 +212,11 @@ int __ipipe_check_tickdev(const char *devname) > > static struct clock_event_device clkevt = { > .name = "at91_tc" __stringify(CONFIG_IPIPE_AT91_TC), > - .features = CLOCK_EVT_FEAT_PERIODIC, > + .features = CLOCK_EVT_FEAT_ONESHOT, > .shift = 20, > .rating = 250, > .set_mode = at91_tc_set_mode, > + .set_next_event = at91_tc_set_next_event, > }; > > static struct __ipipe_tscinfo tsc_info = { > @@ -230,7 +235,7 @@ static struct __ipipe_tscinfo tsc_info = { > > void __ipipe_mach_release_timer(void) > { > - __ipipe_mach_set_dec(__ipipe_mach_ticks_per_jiffy); > + clkevt.set_next_event(__ipipe_mach_ticks_per_jiffy, &clkevt); > } > EXPORT_SYMBOL(__ipipe_mach_release_timer); > > @@ -293,15 +298,16 @@ void __init at91_timer_init(void) > clkevt.max_delta_ns = wrap_ns; > clkevt.min_delta_ns = 2000; > clkevt.cpumask = cpumask_of(0); > - clockevents_register_device(&clkevt); > - > - tsc_info.freq = divided_freq; > - __ipipe_tsc_register(&tsc_info); > > __ipipe_mach_ticks_per_jiffy = (divided_freq + HZ/2) / HZ; > max_delta_ticks = (wrap_ns * clkevt.mult) >> clkevt.shift; > min_delta_ticks = ((unsigned long long) clkevt.min_delta_ns > * clkevt.mult) >> clkevt.shift; > + > + clockevents_register_device(&clkevt); > + > + tsc_info.freq = divided_freq; > + __ipipe_tsc_register(&tsc_info); > } > > #ifdef CONFIG_ARCH_AT91RM9200 > > > -- > Gilles. >
benchmark_no_patch
Description: Binary data
benchmark_patched
Description: Binary data
_______________________________________________ Xenomai-help mailing list [email protected] https://mail.gna.org/listinfo/xenomai-help
