From 188a3fc62f5f61f4cfca203550c5a55338f3f3e6 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Mon, 2 Mar 2009 18:57:11 +0000 Subject: 2009-03-02 Till Straumann PR 1375/bsps * clock/clock.c: Correct implementation of nanoseconds since last tick handler. --- c/src/lib/libbsp/m68k/uC5282/ChangeLog | 6 +++ c/src/lib/libbsp/m68k/uC5282/clock/clock.c | 63 +++++++++++++++++++++++++++--- 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 + + PR 1375/bsps + * clock/clock.c: Correct implementation of nanoseconds since last tick + handler. + 2009-02-25 Joel Sherrill * 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 -- cgit v1.2.3