All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bart Jonkers <jonkersbart@domain.hid>
To: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
Cc: xenomai@xenomai.org
Subject: Re: [Xenomai-core] Xenomai on PXA
Date: Thu, 03 Aug 2006 11:12:34 +0200	[thread overview]
Message-ID: <1154596354.9835.28.camel@domain.hid> (raw)
In-Reply-To: <17616.59841.283196.201008@domain.hid>

On Wed, 2006-08-02 at 20:06 +0200, Gilles Chanteperdrix wrote:
> Bart Jonkers wrote:
>  > On Wed, 2006-08-02 at 15:09 +0200, Gilles Chanteperdrix wrote:
>  > > Detlef Vollmann wrote:
>  > >  > > I also added an interrupt handler on a button which is connected to GPIO
>  > >  > > pin. The interrupt handler should print something when it is executed.
>  > >  > > When I push the button a couple of times nothing happens. So GPIO
>  > >  > > interrupts doesn't seems to work.
>  > >  > Probably GPIO0 and GPIO1 work.
>  > >  > I suspect it's the cascading interrupt that doesn't work.
>  > >  > When I played around with an earlier version of ipipe, I found that
>  > >  > the IRQ_GPIO_2_80 (IRQ 10 on PXA270) is masked, but never unmasked
>  > >  > again.
>  > >  > 
>  > >  > The problem is that for the cascading interrupt you need a special
>  > >  > IPIPE handler, and I don't think there is currently one for PXA.
>  > >  > 
>  > >  > How is that done on other machines/architectures?
>  > > 
>  > > When looking at the ipipe_enable_pipeline function, we see that
>  > > interrupts management routines are all intercepted by the I-pipe, so the
>  > > cascaded interrupts management routines should be automatically
>  > > intercepted. 
>  > > 
>  > > In order to have a better understanding of the issue, it would be
>  > > interesting if you could trace the functions that are called on the path
>  > > from the interrupt to the execution of the final handler.
>  > 
>  > I have tracked and solved the issue. I have looked to the i.MX21 port
>  > and they added some code to the GPIO interrupt handler of the i.MX21.
>  > When IPIPE is active they unmask the interrupt for the GPIO pins at the
>  > end of the handler. I did the same for PXA and my GPIO interrupt problem
>  > is solved. I think that the same is needed for SA-1100.
> 
> Here is a new version of the ipipe-sa1100-pxa patch that unmaks
> interrupts at the end of the demux handlers, and that attempt to fix the
> gettimeoffset issue. I have run 20 minutes (time for OSCR to wrap) latency
> with a test program verifying that time returned by gettimeofday is
> never going backward.
> 
> The patch and the test program are attached, it would be nice if you
> could test them.
I have tested the patch and ran the test program.
The test program give no problems.

The interrupt problem in Linux is also solved. But I have another one.
I have created a small real-time kernel module which uses the native
interface to handle an GPIO interrupt. The problem is that Xenomai
doesn't see the interrupt. When I use GPIO0 (which doesn't use the
chained handler) to receive the interrupt everything works as it should.

So it seems to be that xenomai have a problem with the chained handler.
Does someone have an idea to solve this problem?

Bart
> 
> plain text document attachment (ipipe-sa1100-pxa.2.patch)
> --- linux-2.6.16.5-tcl1/arch/arm/mach-pxa/irq.c	2005-10-28 02:02:08.000000000 +0200
> +++ linux-2.6.16.5-tcl1-ipipe/arch/arm/mach-pxa/irq.c	2006-08-02 17:57:30.000000000 +0200
> @@ -143,6 +143,10 @@ static struct irqchip pxa_low_gpio_chip 
>  static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
>  				   struct pt_regs *regs)
>  {
> +#ifdef CONFIG_IPIPE
> +	struct irqdesc *desc_unused = desc;
> +	unsigned irq_unused = irq;
> +#endif /* CONFIG_IPIPE */
>  	unsigned int mask;
>  	int loop;
>  
> @@ -212,6 +216,10 @@ static void pxa_gpio_demux_handler(unsig
>  		}
>  #endif
>  	} while (loop);
> +
> +#ifdef CONFIG_IPIPE
> +	desc_unused->chip->unmask(irq_unused);
> +#endif /* CONFIG_IPIPE */
>  }
>  
>  static void pxa_ack_muxed_gpio(unsigned int irq)
> --- linux-2.6.16.5-tcl1/arch/arm/mach-pxa/time.c	2006-05-07 15:36:35.000000000 +0200
> +++ linux-2.6.16.5-tcl1-ipipe/arch/arm/mach-pxa/time.c	2006-08-02 19:17:30.000000000 +0200
> @@ -19,6 +19,7 @@
>  #include <linux/signal.h>
>  #include <linux/errno.h>
>  #include <linux/sched.h>
> +#include <linux/module.h>
>  
>  #include <asm/system.h>
>  #include <asm/hardware.h>
> @@ -30,6 +31,23 @@
>  #include <asm/arch/pxa-regs.h>
>  
> 
> +#ifdef CONFIG_IPIPE
> +#ifdef CONFIG_NO_IDLE_HZ
> +#error "dynamic tick timer not yet supported with IPIPE"
> +#endif /* CONFIG_NO_IDLE_HZ */
> +int __ipipe_mach_timerint = IRQ_OST0;
> +EXPORT_SYMBOL(__ipipe_mach_timerint);
> +
> +int __ipipe_mach_timerstolen = 0;
> +EXPORT_SYMBOL(__ipipe_mach_timerstolen);
> +
> +unsigned int __ipipe_mach_ticks_per_jiffy = LATCH;
> +EXPORT_SYMBOL(__ipipe_mach_ticks_per_jiffy);
> +
> +static int pxa_timer_initialized;
> +static unsigned long pxa_jiffies;
> +#endif /* CONFIG_IPIPE */
> +
>  static inline unsigned long pxa_get_rtc_time(void)
>  {
>  	return RCNR;
> @@ -54,6 +72,9 @@ static unsigned long pxa_gettimeoffset (
>  {
>  	long ticks_to_match, elapsed, usec;
>  
> +#ifdef CONFIG_IPIPE
> +	if (!__ipipe_mach_timerstolen) {
> +#endif
>  	/* Get ticks before next timer match */
>  	ticks_to_match = OSMR0 - OSCR;
>  
> @@ -63,6 +84,10 @@ static unsigned long pxa_gettimeoffset (
>  	/* don't get fooled by the workaround in pxa_timer_interrupt() */
>  	if (elapsed <= 0)
>  		return 0;
> +#ifdef CONFIG_IPIPE
> +	} else
> +		elapsed = OSCR - pxa_jiffies * LATCH;
> +#endif
>  
>  	/* Now convert them to usec */
>  	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
> @@ -105,9 +130,27 @@ pxa_timer_interrupt(int irq, void *dev_i
>  	 * affect things only when the timer IRQ has been delayed by nearly
>  	 * exactly one tick period which should be a pretty rare event.
>  	 */
> +#ifdef CONFIG_IPIPE
> +	/*
> +	 * - if Linux is running natively (no ipipe), ack and reprogram the timer
> +	 * - if Linux is running under ipipe, but it still has the control over
> +	 *   the timer (no Xenomai for example), then reprogram the timer (ipipe
> +	 *   has already acked it)
> +	 * - if some other domain has taken over the timer, then do nothing
> +	 *   (ipipe has acked it, and the other domain has reprogramed it)
> +	 */
> +	if (__ipipe_mach_timerstolen) {
> +		timer_tick(regs);
> +		++pxa_jiffies;
> +	} else
> +#endif /* CONFIG_IPIPE */
>  	do {
>  		timer_tick(regs);
> +#ifdef CONFIG_IPIPE
> +		++pxa_jiffies;
> +#else /* !CONFIG_IPIPE */
>  		OSSR = OSSR_M0;  /* Clear match on timer 0 */
> +#endif /* !CONFIG_IPIPE */
>  		next_match = (OSMR0 += LATCH);
>  	} while( (signed long)(next_match - OSCR) <= 8 );
>  
> @@ -139,6 +182,10 @@ static void __init pxa_timer_init(void)
>  	setup_irq(IRQ_OST0, &pxa_timer_irq);
>  	OIER = OIER_E0;		/* enable match on timer 0 to cause interrupts */
>  	OSCR = 0;		/* initialize free-running timer */
> +
> +#ifdef CONFIG_IPIPE
> +	pxa_timer_initialized = 1;
> +#endif /* CONFIG_IPIPE */
>  }
>  
>  #ifdef CONFIG_NO_IDLE_HZ
> @@ -216,3 +263,69 @@ struct sys_timer pxa_timer = {
>  	.dyn_tick	= &pxa_dyn_tick,
>  #endif
>  };
> +
> +#ifdef CONFIG_IPIPE
> +void __ipipe_mach_acktimer(void)
> +{
> +	OSSR = OSSR_M0;  /* Clear match on timer 0 */
> +}
> +
> +unsigned long long __ipipe_mach_get_tsc(void)
> +{
> +	if (likely(pxa_timer_initialized)) {
> +		static union {
> +#ifdef __BIG_ENDIAN
> +			struct {
> +				unsigned long high;
> +				unsigned long low;
> +			};
> +#else /* __LITTLE_ENDIAN */
> +			struct {
> +				unsigned long low;
> +				unsigned long high;
> +			};
> +#endif /* __LITTLE_ENDIAN */
> +			unsigned long long full;
> +		} tsc[NR_CPUS], *local_tsc;
> +		unsigned long stamp, flags;
> +		unsigned long long result;
> +
> +		local_irq_save_hw(flags);
> +		local_tsc = &tsc[ipipe_processor_id()];
> +		stamp = OSCR;
> +		if (unlikely(stamp < local_tsc->low))
> +			/* 32 bit counter wrapped, increment high word. */
> +			local_tsc->high++;
> +		local_tsc->low = stamp;
> +		result = local_tsc->full;
> +		local_irq_restore_hw(flags);
> +
> +		return result;
> +	}
> +	
> +        return 0;
> +}
> +EXPORT_SYMBOL(__ipipe_mach_get_tsc);
> +
> +/*
> + * Reprogram the timer
> + */
> +
> +void __ipipe_mach_set_dec(unsigned long delay)
> +{
> +	if (delay > 8) {
> +		unsigned long flags;
> +
> +		local_irq_save_hw(flags);
> +		OSMR0 = delay + OSCR;
> +		local_irq_restore_hw(flags);
> +	} else
> +		ipipe_trigger_irq(IRQ_OST0);
> +}
> +EXPORT_SYMBOL(__ipipe_mach_set_dec);
> +
> +unsigned long __ipipe_mach_get_dec(void)
> +{
> +	return OSMR0 - OSCR;
> +}
> +#endif /* CONFIG_IPIPE */
> --- linux-2.6.16.5-tcl1/arch/arm/mach-sa1100/irq.c	2005-10-28 02:02:08.000000000 +0200
> +++ linux-2.6.16.5-tcl1-ipipe/arch/arm/mach-sa1100/irq.c	2006-08-02 17:55:48.000000000 +0200
> @@ -111,6 +111,10 @@ static void
>  sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc,
>  			 struct pt_regs *regs)
>  {
> +#ifdef CONFIG_IPIPE
> +	struct irqdesc *desc_unused = desc;
> +	unsigned irq_unused = irq;
> +#endif /* CONFIG_IPIPE */
>  	unsigned int mask;
>  
>  	mask = GEDR & 0xfffff800;
> @@ -134,6 +138,10 @@ sa1100_high_gpio_handler(unsigned int ir
>  
>  		mask = GEDR & 0xfffff800;
>  	} while (mask);
> +
> +#ifdef CONFIG_IPIPE
> +	desc_unused->chip->unmask(irq_unused);
> +#endif /* CONFIG_IPIPE */
>  }
>  
>  /*
> --- linux-2.6.16.5-tcl1/arch/arm/mach-sa1100/time.c	2006-05-07 15:36:35.000000000 +0200
> +++ linux-2.6.16.5-tcl1-ipipe/arch/arm/mach-sa1100/time.c	2006-08-02 19:09:06.000000000 +0200
> @@ -13,6 +13,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/timex.h>
>  #include <linux/signal.h>
> +#include <linux/module.h>
>  
>  #include <asm/mach/time.h>
>  #include <asm/hardware.h>
> @@ -20,6 +21,23 @@
>  #define RTC_DEF_DIVIDER		(32768 - 1)
>  #define RTC_DEF_TRIM            0
>  
> +#ifdef CONFIG_IPIPE
> +#ifdef CONFIG_NO_IDLE_HZ
> +#error "dynamic tick timer not yet supported with IPIPE"
> +#endif /* CONFIG_NO_IDLE_HZ */
> +int __ipipe_mach_timerint = IRQ_OST0;
> +EXPORT_SYMBOL(__ipipe_mach_timerint);
> +
> +int __ipipe_mach_timerstolen = 0;
> +EXPORT_SYMBOL(__ipipe_mach_timerstolen);
> +
> +unsigned int __ipipe_mach_ticks_per_jiffy = LATCH;
> +EXPORT_SYMBOL(__ipipe_mach_ticks_per_jiffy);
> +
> +static int sa1100_timer_initialized;
> +static unsigned long sa1100_jiffies;
> +#endif /* CONFIG_IPIPE */
> +
>  static unsigned long __init sa1100_get_rtc_time(void)
>  {
>  	/*
> @@ -58,11 +76,18 @@ static unsigned long sa1100_gettimeoffse
>  {
>  	unsigned long ticks_to_match, elapsed, usec;
>  
> +#ifdef CONFIG_IPIPE
> +	if (!__ipipe_mach_timerstolen) {
> +#endif
>  	/* Get ticks before next timer match */
>  	ticks_to_match = OSMR0 - OSCR;
>  
>  	/* We need elapsed ticks since last match */
>  	elapsed = LATCH - ticks_to_match;
> +#ifdef CONFIG_IPIPE
> +	} else
> +		elapsed = OSCR - sa1100_jiffies * LATCH;
> +#endif
>  
>  	/* Now convert them to usec */
>  	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
> @@ -97,9 +122,27 @@ sa1100_timer_interrupt(int irq, void *de
>  	 * ensured, hence we can use do_gettimeofday() from interrupt
>  	 * handlers.
>  	 */
> +#ifdef CONFIG_IPIPE
> +	/*
> +	 * - if Linux is running natively (no ipipe), ack and reprogram the timer
> +	 * - if Linux is running under ipipe, but it still has the control over
> +	 *   the timer (no Xenomai for example), then reprogram the timer (ipipe
> +	 *   has already acked it)
> +	 * - if some other domain has taken over the timer, then do nothing
> +	 *   (ipipe has acked it, and the other domain has reprogramed it)
> +	 */
> +	if (__ipipe_mach_timerstolen) {
> +		timer_tick(regs);
> +		++sa1100_jiffies;
> +	} else
> +#endif /* CONFIG_IPIPE */
>  	do {
>  		timer_tick(regs);
> +#ifdef CONFIG_IPIPE
> +		++sa1100_jiffies;
> +#else /* !CONFIG_IPIPE */
>  		OSSR = OSSR_M0;  /* Clear match on timer 0 */
> +#endif /* !CONFIG_IPIPE */
>  		next_match = (OSMR0 += LATCH);
>  	} while ((signed long)(next_match - OSCR) <= 0);
>  
> @@ -131,6 +174,10 @@ static void __init sa1100_timer_init(voi
>  	setup_irq(IRQ_OST0, &sa1100_timer_irq);
>  	OIER = OIER_E0;		/* enable match on timer 0 to cause interrupts */
>  	OSCR = 0;		/* initialize free-running timer */
> +
> +#ifdef CONFIG_IPIPE
> +	sa1100_timer_initialized = 1;
> +#endif /* CONFIG_IPIPE */
>  }
>  
>  #ifdef CONFIG_NO_IDLE_HZ
> @@ -209,3 +256,66 @@ struct sys_timer sa1100_timer = {
>  	.dyn_tick	= &sa1100_dyn_tick,
>  #endif
>  };
> +
> +#ifdef CONFIG_IPIPE
> +void __ipipe_mach_acktimer(void)
> +{
> +	OSSR = OSSR_M0;  /* Clear match on timer 0 */
> +}
> +
> +unsigned long long __ipipe_mach_get_tsc(void)
> +{
> +	if (likely(sa1100_timer_initialized)) {
> +		static union {
> +#ifdef __BIG_ENDIAN
> +			struct {
> +				unsigned long high;
> +				unsigned long low;
> +			};
> +#else /* __LITTLE_ENDIAN */
> +			struct {
> +				unsigned long low;
> +				unsigned long high;
> +			};
> +#endif /* __LITTLE_ENDIAN */
> +			unsigned long long full;
> +		} tsc[NR_CPUS], *local_tsc;
> +		unsigned long stamp, flags;
> +		unsigned long long result;
> +
> +		local_irq_save_hw(flags);
> +		local_tsc = &tsc[ipipe_processor_id()];
> +		stamp = OSCR;
> +		if (unlikely(stamp < local_tsc->low))
> +			/* 32 bit counter wrapped, increment high word. */
> +			local_tsc->high++;
> +		local_tsc->low = stamp;
> +		result = local_tsc->full;
> +		local_irq_restore_hw(flags);
> +
> +		return result;
> +	}
> +	
> +        return 0;
> +}
> +EXPORT_SYMBOL(__ipipe_mach_get_tsc);
> +
> +/*
> + * Reprogram the timer
> + */
> +
> +void __ipipe_mach_set_dec(unsigned long delay)
> +{
> +	unsigned long flags;
> +
> +	local_irq_save_hw(flags);
> +        OSMR0 = delay + OSCR;
> +	local_irq_restore_hw(flags);
> +}
> +EXPORT_SYMBOL(__ipipe_mach_set_dec);
> +
> +unsigned long __ipipe_mach_get_dec(void)
> +{
> +	return OSMR0 - OSCR;
> +}
> +#endif /* CONFIG_IPIPE */
> plain text document attachment (test_gettimeofday.c)
> #include <stdio.h>
> #include <time.h>
> #include <sys/time.h>
> 
> int main(void)
> {
> 	struct timeval tv, old_tv;
> 
> 	gettimeofday(&old_tv, NULL);
> 	for (;;) {
> 		gettimeofday(&tv, NULL);
> 		if (tv.tv_sec < old_tv.tv_sec ||
> 		    (tv.tv_sec == old_tv.tv_sec && tv.tv_usec < old_tv.tv_usec))
> 			printf("Time is going backward !\n");
> 		old_tv = tv;
> 	}
> }



  reply	other threads:[~2006-08-03  9:12 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-07-07 15:02 [Xenomai-core] Xenomai on PXA Danilo Levantesi
2006-07-07 20:32 ` Gilles Chanteperdrix
2006-07-11  6:20   ` Detlef Vollmann
2006-07-11 15:01     ` Stelian Pop
2006-07-12 13:13       ` Bart Jonkers
2006-07-11 15:02     ` Stelian Pop
2006-07-17 16:17     ` Gilles Chanteperdrix
2006-07-17 16:29       ` Philippe Gerum
2006-07-17 16:56         ` Gilles Chanteperdrix
2006-07-31  8:34           ` Bart Jonkers
2006-07-31  9:20             ` Detlef Vollmann
2006-07-31 10:33               ` Bart Jonkers
2006-07-31 11:08                 ` Detlef Vollmann
2006-08-02 13:09                   ` Gilles Chanteperdrix
2006-08-02 13:33                     ` Bart Jonkers
2006-08-02 13:56                       ` Gilles Chanteperdrix
2006-08-02 18:06                       ` Gilles Chanteperdrix
2006-08-03  9:12                         ` Bart Jonkers [this message]
2006-08-03 13:18                           ` Gilles Chanteperdrix
2006-08-03 14:56                             ` Philippe Gerum
2006-08-03 17:14                               ` Gilles Chanteperdrix
2006-08-04  6:10                                 ` Bart Jonkers
2006-08-04  6:10                                 ` Detlef Vollmann
2006-08-04  9:04                                   ` Philippe Gerum
2006-08-04 11:37                                   ` Gilles Chanteperdrix
2006-08-04 14:52                                 ` Bart Jonkers
2006-08-13 13:16                                   ` Gilles Chanteperdrix
2006-09-10  8:56                                     ` Detlef Vollmann
2006-09-10 12:19                                       ` Gilles Chanteperdrix
2006-09-10 16:31                                         ` Detlef Vollmann
2006-09-10 16:37                                           ` Gilles Chanteperdrix
2006-09-10 19:20                                             ` Detlef Vollmann
2006-09-10 19:42                                               ` Gilles Chanteperdrix
2006-08-03 11:23                         ` Bart Jonkers
2006-07-17 22:33       ` Danilo Levantesi
  -- strict thread matches above, loose matches on Subject: below --
2007-10-17 16:29 Patrick

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1154596354.9835.28.camel@domain.hid \
    --to=jonkersbart@domain.hid \
    --cc=gilles.chanteperdrix@xenomai.org \
    --cc=xenomai@xenomai.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.