summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2009-03-02 18:57:11 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2009-03-02 18:57:11 +0000
commit188a3fc62f5f61f4cfca203550c5a55338f3f3e6 (patch)
treeb8559038057876c4571bd46e3df31770337f91b0
parent2009-03-02 Joel Sherrill <joel.sherrill@oarcorp.com> (diff)
downloadrtems-188a3fc62f5f61f4cfca203550c5a55338f3f3e6.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.
-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 24ec642801..579552a7c9 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-02-25 Joel Sherrill <joel.sherrill@OARcorp.com>
* clock/clock.c, include/bsp.h: Make bsp idle thread names match.
diff --git a/c/src/lib/libbsp/m68k/uC5282/clock/clock.c b/c/src/lib/libbsp/m68k/uC5282/clock/clock.c
index 6ea98c875f..a15d1536f6 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