summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2012-06-19 08:34:37 +0200
committerDaniel Hellstrom <daniel@gaisler.com>2015-04-17 01:10:18 +0200
commit16d6e42c43887259316ce53b0bc1d7e21e98726f (patch)
treea9ea7912616f61944f94e73810fa3bced065b5c5 /c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
parentGRTM: fixed bug where transmitter start loop was optimized away (diff)
downloadrtems-16d6e42c43887259316ce53b0bc1d7e21e98726f.tar.bz2
LEON3: fixed nano seconds support in TLIB
The _Watchdog_Nanoseconds_since_tick_handler() function caller does not take into account that the timer counter may wrap, underflow or overflow. Instead, the driver must take that into account. This GPTIMER DrvMgr driver patch makes use of the IRQ-Pending bit to determine if a underflow has happened. In that case a greater time than one tick is returned (even considering the function name..). The TLIB clock layer must also ACK the interrupt pending bit, otherwise we couldn't determine whether an IRQ is pending or if belongs to un old already handled tick IRQ. Note that this patch only fixes the DrvMgr GPTIMER driver and TLIB, the standard LEON3 GPTIMER driver still needs a fix.
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c')
-rw-r--r--c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c b/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
index 02b1781269..0abcc08eb0 100644
--- a/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
+++ b/c/src/lib/libbsp/sparc/shared/timer/tlib_ckinit.c
@@ -75,6 +75,14 @@ rtems_device_minor_number rtems_clock_minor;
void Clock_isr(void *arg_unused)
{
/*
+ * Support for shared interrupts. Ack IRQ at source, only handle
+ * interrupts generated from the tick-timer. Clearing pending bit
+ * is also needed for Clock_nanoseconds_since_last_tick() to work.
+ */
+ if ( tlib_interrupt_pending(Clock_handle, 1) == 0 )
+ return;
+
+ /*
* Accurate count of ISRs
*/
@@ -147,22 +155,30 @@ void Clock_exit( void )
uint32_t Clock_nanoseconds_since_last_tick(void)
{
uint32_t clicks;
+ int ip;
+
if ( !Clock_handle )
return 0;
tlib_get_counter(Clock_handle, (unsigned int *)&clicks);
+ /* protect against timer counter underflow/overflow */
+ ip = tlib_interrupt_pending(Clock_handle, 0);
+ if (ip)
+ tlib_get_counter(Clock_handle, (unsigned int *)&clicks);
#ifdef CLOCK_DRIVER_DONT_ASSUME_PRESCALER_1MHZ
{
/* Down counter. Calc from BaseFreq. */
uint64_t tmp;
+ if (ip)
+ clicks += Clock_basefreq;
tmp = ((uint64_t)clicks * 1000000000) / ((uint64_t)Clock_basefreq);
return (uint32_t)tmp;
}
#else
/* Down counter. Timer base frequency is initialized to 1 MHz */
return (uint32_t)
- (rtems_configuration_get_microseconds_per_tick() - clicks) * 1000;
+ ((rtems_configuration_get_microseconds_per_tick() << ip) - clicks) * 1000;
#endif
}