summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-06-21 10:58:04 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-06-21 15:54:18 +0200
commit291945f137d411834c0eaf3b0bb819263efb845b (patch)
treee7210c8394a57e40c156d8d3ae1fcf65533386db
parent9460333e9910471eda010423dcb493f758d997d4 (diff)
downloadrtems-291945f137d411834c0eaf3b0bb819263efb845b.tar.bz2
bsp/leon3: Fix interrupt timestamping
Close #2684.
-rw-r--r--c/src/lib/libbsp/sparc/leon3/clock/ckinit.c55
1 files changed, 35 insertions, 20 deletions
diff --git a/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c b/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c
index ef24ee4303..b96e1098e7 100644
--- a/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c
+++ b/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c
@@ -92,35 +92,50 @@ static uint32_t leon3_tc_get_timecount_second_timer(struct timecounter *tc)
}
#endif
+#ifdef RTEMS_PROFILING
+#define IRQMP_TIMESTAMP_S1_S2 ((1U << 25) | (1U << 26))
+
static void leon3_tc_tick_irqmp_timestamp(void)
{
+ volatile struct irqmp_timestamp_regs *irqmp_ts =
+ &LEON3_IrqCtrl_Regs->timestamp[0];
+ unsigned int first = irqmp_ts->assertion;
+ unsigned int second = irqmp_ts->counter;
+
+ irqmp_ts->control |= IRQMP_TIMESTAMP_S1_S2;
+
+ _Profiling_Update_max_interrupt_delay(_Per_CPU_Get(), second - first);
+
+ rtems_timecounter_tick();
+}
+#endif
+
+static void leon3_tc_tick_irqmp_timestamp_init(void)
+{
#ifdef RTEMS_PROFILING
/*
- * We need a small state machine to ignore the first clock interrupt, since
- * it contains the sequential system initialization time. Do the timestamp
- * initialization on the fly.
+ * Ignore the first clock interrupt, since it contains the sequential system
+ * initialization time. Do the timestamp initialization on the fly.
*/
- static int state = 1;
-
- volatile struct irqmp_timestamp_regs *irqmp_ts =
- &LEON3_IrqCtrl_Regs->timestamp[0];
- unsigned int s1_s2 = (1U << 25) | (1U << 26);
- if (state == 0) {
- unsigned int first = irqmp_ts->assertion;
- unsigned int second = irqmp_ts->counter;
+#ifdef RTEMS_SMP
+ static Atomic_Uint counter = ATOMIC_INITIALIZER_UINT(0);
- irqmp_ts->control |= s1_s2;
+ bool done =
+ _Atomic_Fetch_add_uint(&counter, 1, ATOMIC_ORDER_RELAXED)
+ == rtems_get_processor_count() - 1;
+#else
+ bool done = true;
+#endif
- _Profiling_Update_max_interrupt_delay(_Per_CPU_Get(), second - first);
- } else if (state == 1) {
- unsigned int ks = 1U << 5;
+ volatile struct irqmp_timestamp_regs *irqmp_ts =
+ &LEON3_IrqCtrl_Regs->timestamp[0];
+ unsigned int ks = 1U << 5;
- state = 0;
+ irqmp_ts->control = ks | IRQMP_TIMESTAMP_S1_S2 | (unsigned int) clkirq;
- irqmp_ts->control = ks | s1_s2 | (unsigned int) clkirq;
- } else if (state == 1) {
- state = 2;
+ if (done) {
+ leon3_tc_tick = leon3_tc_tick_irqmp_timestamp;
}
#endif
@@ -201,7 +216,7 @@ static void leon3_clock_initialize(void)
leon3_tc.tc.tc_counter_mask = 0xffffffff;
leon3_tc.tc.tc_frequency = ambapp_freq_get(&ambapp_plb, LEON3_Timer_Adev);
leon3_tc.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
- leon3_tc_tick = leon3_tc_tick_irqmp_timestamp;
+ leon3_tc_tick = leon3_tc_tick_irqmp_timestamp_init;
rtems_timecounter_install(&leon3_tc.tc);
} else {
#ifdef RTEMS_SMP