summaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2009-03-02 18:57:20 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2009-03-02 18:57:20 +0000
commitcb54e106866c4b9afb5a58ce6ee34486c46bb0db (patch)
treeed8dfe82d283cff5d67c95c254835d779ea250d9 /c
parent2009-03-02 Daniel Hellstrom <daniel@gaisler.com> (diff)
downloadrtems-cb54e106866c4b9afb5a58ce6ee34486c46bb0db.tar.bz2
2009-03-02 Till Straumann <strauman@slac.stanford.edu>
PR 1375/bsps * clock/clock.c: Correct implementation of nanoseconds since last tick handler.
Diffstat (limited to 'c')
-rw-r--r--c/src/lib/libbsp/m68k/uC5282/ChangeLog6
-rw-r--r--c/src/lib/libbsp/m68k/uC5282/clock/clock.c63
2 files changed, 64 insertions, 5 deletions
diff --git a/c/src/lib/libbsp/m68k/uC5282/ChangeLog b/c/src/lib/libbsp/m68k/uC5282/ChangeLog
index dfac8da347..c6fd4f78af 100644
--- a/c/src/lib/libbsp/m68k/uC5282/ChangeLog
+++ b/c/src/lib/libbsp/m68k/uC5282/ChangeLog
@@ -1,3 +1,9 @@
+2009-03-02 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 1375/bsps
+ * clock/clock.c: Correct implementation of nanoseconds since last tick
+ handler.
+
2009-01-21 Eric Norum <norume@aps.anl.gov>
PR 1358/bsps
diff --git a/c/src/lib/libbsp/m68k/uC5282/clock/clock.c b/c/src/lib/libbsp/m68k/uC5282/clock/clock.c
index 90308d8299..793b45c2c8 100644
--- a/c/src/lib/libbsp/m68k/uC5282/clock/clock.c
+++ b/c/src/lib/libbsp/m68k/uC5282/clock/clock.c
@@ -35,13 +35,66 @@ extern int __SRAMBASE[];
uint32_t bsp_clock_nanoseconds_since_last_tick(void)
{
- int i = MCF5282_PIT3_PCNTR;
- if (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF)
- i = MCF5282_PIT3_PCNTR - USEC_PER_TICK;
- return (USEC_PER_TICK - i) * 1000;
+ uint32_t tdiff;
+
+ /* Details to consider here:
+ *
+ * - PIT is 16-bit. To properly handle differences of two
+ * 16-bit numbers (which requires 17-bits) we want to
+ * do the arithmetic in a wider data type. PIT reading
+ * is a unsigned 16-bit count.
+ *
+ * => must make sure PIT is a *unsigned* 16-bit type. Otherwise
+ * values get sign-extended when converted to wider type
+ * (regardless of the signedness of wider type):
+ *
+ * (unsigned)(signed short)0xffff -> 0xffffffff.
+ *
+ * and thus
+ *
+ * (uint32_t)(int16_t)65535 - (uin32_t)(int16_t)1
+ *
+ * would yield 0xfffffffe, not 65534!
+ *
+ *
+ * - PIT counts backwards from PMR -> zero, hence
+ *
+ * now - tick_base = (PMR - now) - (PMR - tick_base) = tick_base - now;
+ *
+ * result may be negative (if rolled-over).
+ *
+ * - PIF flag, counter and PCNTR_AT_TICK must all
+ * be read atomically - otherwise an interrupt may
+ * have altered their values while we're looking.
+ *
+ * NOTE: score framework calling this routine disables
+ * interrupts during execution of this callout.
+ *
+ * - Last but not least, rollover might have happened
+ * just between reading counter and PIF flag; hence
+ * we have to re-read the counter if PIF is set.
+ *
+ */
+
+ /* obtain current value */
+ tdiff = (uint16_t)MCF5282_PIT3_PCNTR;
+
+ if (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF) {
+ /* rollover may just have happened;
+ * must reload PCNTR.
+ */
+ tdiff = + (uint32_t)(uint16_t)MCF5282_PIT3_PMR
+ + (uint32_t)(uint16_t)PCNTR_AT_TICK
+ - (uint32_t)(uint16_t)MCF5282_PIT3_PCNTR;
+ } else {
+ tdiff = + (uint32_t)(uint16_t)PCNTR_AT_TICK - tdiff;
+ }
+
+ return tdiff * 1000;
}
-#define Clock_driver_nanoseconds_since_last_tick bsp_clock_nanoseconds_since_last_tick
+#define Clock_driver_nanoseconds_since_last_tick \
+ bsp_clock_nanoseconds_since_last_tick
/*
* Periodic interval timer interrupt handler