From: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
To: Bart Jonkers <jonkersbart@domain.hid>
Cc: xenomai@xenomai.org
Subject: Re: [Xenomai-core] Xenomai on PXA
Date: Wed, 2 Aug 2006 20:06:57 +0200 [thread overview]
Message-ID: <17616.59841.283196.201008@domain.hid> (raw)
In-Reply-To: <1154525585.9559.22.camel@domain.hid>
[-- Attachment #1: message body and .signature --]
[-- Type: text/plain, Size: 2140 bytes --]
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.
--
Gilles Chanteperdrix.
[-- Attachment #2: ipipe-sa1100-pxa.2.patch --]
[-- Type: text/plain, Size: 9947 bytes --]
--- 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 */
[-- Attachment #3: test_gettimeofday.c --]
[-- Type: text/plain, Size: 338 bytes --]
#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;
}
}
next prev parent reply other threads:[~2006-08-02 18:06 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 [this message]
2006-08-03 9:12 ` Bart Jonkers
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=17616.59841.283196.201008@domain.hid \
--to=gilles.chanteperdrix@xenomai.org \
--cc=jonkersbart@domain.hid \
--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.