From 75acd9e69f906cbd880a17ee4ca705ad7caa92c0 Mon Sep 17 00:00:00 2001 From: Alexander Krutwig Date: Wed, 1 Apr 2015 15:33:25 +0200 Subject: bsps: Convert clock drivers to use a timecounter Update #2271. --- c/src/lib/libbsp/arm/beagle/clock.c | 35 ++---- c/src/lib/libbsp/arm/edb7312/clock/clockdrv.c | 2 + c/src/lib/libbsp/arm/gba/clock/clockdrv.c | 2 + .../libbsp/arm/lpc176x/include/lpc-clock-config.h | 1 + .../libbsp/arm/lpc24xx/include/lpc-clock-config.h | 2 + .../libbsp/arm/lpc32xx/include/lpc-clock-config.h | 2 + c/src/lib/libbsp/arm/nds/clock/clock.c | 2 + c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c | 12 +- .../libbsp/arm/shared/arm-a9mpcore-clock-config.c | 48 +++----- .../arm/shared/armv7m/clock/armv7m-clock-config.c | 65 ++++++----- .../libbsp/arm/shared/lpc/clock/lpc-clock-config.c | 37 +++--- c/src/lib/libbsp/arm/tms570/clock/clock.c | 40 +++---- c/src/lib/libbsp/i386/pc386/clock/ckinit.c | 125 ++++----------------- c/src/lib/libbsp/lm32/shared/clock/ckinit.c | 2 + .../libbsp/lm32/shared/milkymist_clock/ckinit.c | 2 + c/src/lib/libbsp/m68k/av5282/clock/clock.c | 2 + c/src/lib/libbsp/m68k/gen68360/clock/clock.c | 2 + c/src/lib/libbsp/m68k/genmcf548x/clock/clock.c | 2 + c/src/lib/libbsp/m68k/mcf52235/clock/clock.c | 50 +++++---- c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c | 44 ++++++-- c/src/lib/libbsp/m68k/mcf5235/clock/clock.c | 2 + c/src/lib/libbsp/m68k/mcf5329/clock/clock.c | 49 ++++---- c/src/lib/libbsp/m68k/sim68000/clock/clockdrv.c | 2 + c/src/lib/libbsp/m68k/uC5282/clock/clock.c | 48 ++++++-- c/src/lib/libbsp/mips/csb350/clock/clockdrv.c | 2 + .../lib/libbsp/mips/genmongoosev/clock/clockdrv.c | 2 + c/src/lib/libbsp/mips/jmr3904/clock/clockdrv.c | 2 + c/src/lib/libbsp/mips/rbtx4925/clock/clockdrv.c | 1 + c/src/lib/libbsp/mips/rbtx4938/clock/clockdrv.c | 2 + c/src/lib/libbsp/mips/shared/clock/clockdrv.c | 10 +- c/src/lib/libbsp/nios2/nios2_iss/clock/clock.c | 2 + .../lib/libbsp/or1k/generic_or1k/clock/clockdrv.c | 50 +++++---- .../libbsp/powerpc/mpc55xxevb/clock/clock-config.c | 96 ++++++++++------ .../lib/libbsp/powerpc/qoriq/clock/clock-config.c | 61 +++++----- c/src/lib/libbsp/powerpc/qoriq/configure.ac | 4 + c/src/lib/libbsp/powerpc/shared/clock/clock.c | 56 +++------ c/src/lib/libbsp/shared/clock_driver_simidle.c | 2 + c/src/lib/libbsp/shared/clockdrv_shell.h | 52 ++++++--- c/src/lib/libbsp/sparc/erc32/clock/ckinit.c | 52 ++++++--- c/src/lib/libbsp/sparc/leon2/clock/ckinit.c | 52 ++++++--- c/src/lib/libbsp/sparc/leon3/clock/ckinit.c | 97 +++++++++++----- c/src/lib/libbsp/sparc64/shared/clock/ckinit.c | 2 + c/src/lib/libcpu/arm/at91rm9200/clock/clock.c | 23 +--- c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c | 53 ++++++--- c/src/lib/libcpu/arm/mc9328mxl/clock/clockdrv.c | 3 + c/src/lib/libcpu/arm/pxa255/clock/clock.c | 2 + c/src/lib/libcpu/arm/s3c24xx/clock/clockdrv.c | 14 +-- c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c | 107 +++++------------- 48 files changed, 685 insertions(+), 640 deletions(-) diff --git a/c/src/lib/libbsp/arm/beagle/clock.c b/c/src/lib/libbsp/arm/beagle/clock.c index 66aba1b84b..912d904197 100644 --- a/c/src/lib/libbsp/arm/beagle/clock.c +++ b/c/src/lib/libbsp/arm/beagle/clock.c @@ -15,11 +15,12 @@ */ #include +#include #include #include -#ifdef ARM_MULTILIB_ARCH_V4 +static struct timecounter beagle_clock_tc; static omap_timer_registers_t regs_v1 = { .TIDR = OMAP3_TIMER_TIDR, @@ -115,8 +116,6 @@ static struct omap_timer *timer = &am335x_timer; #endif -static int done = 0; - #if IS_AM335X #define FRCLOCK_HZ (16*1500000) #endif @@ -181,20 +180,14 @@ omap3_frclock_init(void) /* Start timer, without prescaler */ mmio_set(fr_timer->base + fr_timer->regs->TCLR, OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST); - done = 1; } -static inline uint32_t -read_frc(void) +static uint32_t +beagle_clock_get_timecount(struct timecounter *tc) { - if (done == 0) { - return 0; - } return mmio_read(fr_timer->base + fr_timer->regs->TCRR); } -static uint32_t last_tick_nanoseconds; - static void beagle_clock_initialize(void) { @@ -262,12 +255,16 @@ beagle_clock_initialize(void) while(mmio_read(AM335X_WDT_BASE+AM335X_WDT_WWPS) != 0) ; #endif + /* Install timecounter */ \ + beagle_clock_tc.tc_get_timecount = beagle_clock_get_timecount; + beagle_clock_tc.tc_counter_mask = 0xffffffff; + beagle_clock_tc.tc_frequency = FRCLOCK_HZ; + beagle_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&beagle_clock_tc); } static void beagle_clock_at_tick(void) { - last_tick_nanoseconds = read_frc(); - mmio_write(timer->base + timer->regs->TISR, OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG | OMAP3_TISR_TCAR_IT_FLAG); @@ -315,14 +312,6 @@ static void beagle_clock_cleanup(void) mmio_clear(fr_timer->base + fr_timer->regs->TCLR, OMAP3_TCLR_ST); } -static inline uint32_t beagle_clock_nanoseconds_since_last_tick(void) -{ - /* this arithmetic also works if read_frc() wraps around, as long - * as the subtraction wraps around too - */ - return (read_frc() - (uint64_t) last_tick_nanoseconds) * 1000000000 / FRCLOCK_HZ; -} - #define Clock_driver_support_at_tick() beagle_clock_at_tick() #define Clock_driver_support_initialize_hardware() beagle_clock_initialize() #define Clock_driver_support_install_isr(isr, old_isr) \ @@ -332,10 +321,6 @@ static inline uint32_t beagle_clock_nanoseconds_since_last_tick(void) } while (0) #define Clock_driver_support_shutdown_hardware() beagle_clock_cleanup() -#define Clock_driver_nanoseconds_since_last_tick \ - beagle_clock_nanoseconds_since_last_tick /* Include shared source clock driver code */ #include "../../shared/clockdrv_shell.h" - -#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/c/src/lib/libbsp/arm/edb7312/clock/clockdrv.c b/c/src/lib/libbsp/arm/edb7312/clock/clockdrv.c index 499a27904c..121b2c9d32 100644 --- a/c/src/lib/libbsp/arm/edb7312/clock/clockdrv.c +++ b/c/src/lib/libbsp/arm/edb7312/clock/clockdrv.c @@ -68,4 +68,6 @@ void Clock_isr(void * arg); assert(status == RTEMS_SUCCESSFUL); \ } while (0) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/arm/gba/clock/clockdrv.c b/c/src/lib/libbsp/arm/gba/clock/clockdrv.c index 72d0b81e32..ff171110b9 100644 --- a/c/src/lib/libbsp/arm/gba/clock/clockdrv.c +++ b/c/src/lib/libbsp/arm/gba/clock/clockdrv.c @@ -92,4 +92,6 @@ void Clock_driver_support_initialize_hardware(void) GBA_REG_TM3CNT = (0x00c0|GBA_TMCNT_PS); } +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/arm/lpc176x/include/lpc-clock-config.h b/c/src/lib/libbsp/arm/lpc176x/include/lpc-clock-config.h index c72575f719..3eef02152e 100644 --- a/c/src/lib/libbsp/arm/lpc176x/include/lpc-clock-config.h +++ b/c/src/lib/libbsp/arm/lpc176x/include/lpc-clock-config.h @@ -33,6 +33,7 @@ extern "C" { #define LPC_CLOCK_INTERRUPT LPC176X_IRQ_TIMER_0 #define LPC_CLOCK_TIMER_BASE TMR0_BASE_ADDR +#define LPC_CLOCK_TIMECOUNTER_BASE TMR1_BASE_ADDR #define LPC_CLOCK_REFERENCE LPC176X_PCLK #define LPC_CLOCK_MODULE_ENABLE() \ lpc176x_module_enable( LPC176X_MODULE_TIMER_0, LPC176X_MODULE_PCLK_DEFAULT ) diff --git a/c/src/lib/libbsp/arm/lpc24xx/include/lpc-clock-config.h b/c/src/lib/libbsp/arm/lpc24xx/include/lpc-clock-config.h index 1edab4eb02..5e6b469e0f 100644 --- a/c/src/lib/libbsp/arm/lpc24xx/include/lpc-clock-config.h +++ b/c/src/lib/libbsp/arm/lpc24xx/include/lpc-clock-config.h @@ -35,6 +35,8 @@ extern "C" { #define LPC_CLOCK_TIMER_BASE TMR0_BASE_ADDR +#define LPC_CLOCK_TIMECOUNTER_BASE TMR1_BASE_ADDR + #define LPC_CLOCK_REFERENCE LPC24XX_PCLK #define LPC_CLOCK_MODULE_ENABLE() \ diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/lpc-clock-config.h b/c/src/lib/libbsp/arm/lpc32xx/include/lpc-clock-config.h index accd0d256a..2b676b433f 100644 --- a/c/src/lib/libbsp/arm/lpc32xx/include/lpc-clock-config.h +++ b/c/src/lib/libbsp/arm/lpc32xx/include/lpc-clock-config.h @@ -44,6 +44,8 @@ extern "C" { #define LPC_CLOCK_TIMER_BASE LPC32XX_BASE_TIMER_0 +#define LPC_CLOCK_TIMECOUNTER_BASE LPC32XX_BASE_TIMER_1 + #define LPC_CLOCK_REFERENCE LPC32XX_PERIPH_CLK #define LPC_CLOCK_MODULE_ENABLE() diff --git a/c/src/lib/libbsp/arm/nds/clock/clock.c b/c/src/lib/libbsp/arm/nds/clock/clock.c index a24f8cc788..1e239d44d9 100644 --- a/c/src/lib/libbsp/arm/nds/clock/clock.c +++ b/c/src/lib/libbsp/arm/nds/clock/clock.c @@ -81,4 +81,6 @@ void Clock_driver_support_initialize_hardware (void) TIMER_DATA (0) = TIMER_FREQ_64 ((uint16_t) freq); } +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c b/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c index 533873cf19..f765485570 100644 --- a/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c +++ b/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c @@ -72,14 +72,6 @@ static void raspberrypi_clock_cleanup(void) } } -/* - * Return the nanoseconds since last tick - */ -static uint32_t raspberrypi_clock_nanoseconds_since_last_tick(void) -{ - return 0; -} - #define Clock_driver_support_at_tick() raspberrypi_clock_at_tick() #define Clock_driver_support_initialize_hardware() raspberrypi_clock_initialize() @@ -92,8 +84,6 @@ static uint32_t raspberrypi_clock_nanoseconds_since_last_tick(void) #define Clock_driver_support_shutdown_hardware() raspberrypi_clock_cleanup() -#define Clock_driver_nanoseconds_since_last_tick \ - raspberrypi_clock_nanoseconds_since_last_tick - +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c index f2ce07e3b6..8e2e153b46 100644 --- a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c +++ b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-clock-config.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. + * Copyright (c) 2013-2015 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -17,14 +17,11 @@ #include #include #include +#include #define A9MPCORE_GT ((volatile a9mpcore_gt *) BSP_ARM_A9MPCORE_GT_BASE) -static uint64_t a9mpcore_clock_last_tick_k; - -static uint32_t a9mpcore_clock_last_tick_cmpvallower; - -static uint32_t a9mpcore_clock_autoinc; +static struct timecounter a9mpcore_tc; /* This is defined in clockdrv_shell.h */ void Clock_isr(rtems_irq_hdl_param arg); @@ -39,13 +36,6 @@ static void a9mpcore_clock_at_tick(void) { volatile a9mpcore_gt *gt = A9MPCORE_GT; - /* - * FIXME: Now the _TOD_Get_with_nanoseconds() yields wrong values until - * _TOD_Tickle_ticks() managed to update the uptime. See also PR2180. - */ - a9mpcore_clock_last_tick_cmpvallower = - gt->cmpvallower - a9mpcore_clock_autoinc; - gt->irqst = A9MPCORE_GT_IRQST_EFLG; } @@ -80,6 +70,13 @@ static uint64_t a9mpcore_clock_get_counter(volatile a9mpcore_gt *gt) return ((uint64_t) cu2 << 32) | cl; } +static uint32_t a9mpcore_clock_get_timecount(struct timecounter *tc) +{ + volatile a9mpcore_gt *gt = A9MPCORE_GT; + + return gt->cntrlower; +} + static void a9mpcore_clock_initialize(void) { volatile a9mpcore_gt *gt = A9MPCORE_GT; @@ -98,14 +95,16 @@ static void a9mpcore_clock_initialize(void) gt->cmpvalupper = (uint32_t) (cmpval >> 32); gt->autoinc = interval; - a9mpcore_clock_last_tick_k = (UINT64_C(1000000000) << 32) / periphclk; - a9mpcore_clock_last_tick_cmpvallower = (uint32_t) cmpval - interval; - a9mpcore_clock_autoinc = interval; - gt->ctrl = A9MPCORE_GT_CTRL_AUTOINC_EN | A9MPCORE_GT_CTRL_IRQ_EN | A9MPCORE_GT_CTRL_COMP_EN | A9MPCORE_GT_CTRL_TMR_EN; + + a9mpcore_tc.tc_get_timecount = a9mpcore_clock_get_timecount; + a9mpcore_tc.tc_counter_mask = 0xffffffff; + a9mpcore_tc.tc_frequency = periphclk; + a9mpcore_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&a9mpcore_tc); } CPU_Counter_ticks _CPU_Counter_read(void) @@ -147,16 +146,6 @@ static void a9mpcore_clock_cleanup(void) } } -static uint32_t a9mpcore_clock_nanoseconds_since_last_tick(void) -{ - volatile a9mpcore_gt *gt = A9MPCORE_GT; - uint64_t k = a9mpcore_clock_last_tick_k; - uint32_t n = a9mpcore_clock_last_tick_cmpvallower; - uint32_t c = gt->cntrlower; - - return (uint32_t) (((c - n) * k) >> 32); -} - #define Clock_driver_support_at_tick() \ a9mpcore_clock_at_tick() @@ -165,15 +154,12 @@ static uint32_t a9mpcore_clock_nanoseconds_since_last_tick(void) #define Clock_driver_support_install_isr(isr, old_isr) \ do { \ - a9mpcore_clock_handler_install(); \ + a9mpcore_clock_handler_install(); \ old_isr = NULL; \ } while (0) #define Clock_driver_support_shutdown_hardware() \ a9mpcore_clock_cleanup() -#define Clock_driver_nanoseconds_since_last_tick \ - a9mpcore_clock_nanoseconds_since_last_tick - /* Include shared source clock driver code */ #include "../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c b/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c index 8e4ae338f8..e78684c8d2 100644 --- a/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c +++ b/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c @@ -13,6 +13,7 @@ */ #include +#include #include #include @@ -22,15 +23,35 @@ /* This is defined in clockdrv_shell.h */ static void Clock_isr(void *arg); -#define _ARMV7M_Systick_get_factor(freq) \ - ((1000000000ULL << 32) / (freq)) +static rtems_timecounter_simple _ARMV7M_TC; -#ifdef BSP_ARMV7M_SYSTICK_FREQUENCY - #define _ARMV7M_Systick_factor \ - _ARMV7M_Systick_get_factor(BSP_ARMV7M_SYSTICK_FREQUENCY) -#else - static uint64_t _ARMV7M_Systick_factor; -#endif +static uint32_t _ARMV7M_TC_get(rtems_timecounter_simple *tc) +{ + volatile ARMV7M_Systick *systick = _ARMV7M_Systick; + + return systick->cvr; +} + +static bool _ARMV7M_TC_is_pending(rtems_timecounter_simple *tc) +{ + volatile ARMV7M_SCB *scb = _ARMV7M_SCB; + + return ((scb->icsr & ARMV7M_SCB_ICSR_PENDSTSET) != 0); +} + +static uint32_t _ARMV7M_TC_get_timecount(struct timecounter *tc) +{ + return rtems_timecounter_simple_downcounter_get( + tc, + _ARMV7M_TC_get, + _ARMV7M_TC_is_pending + ); +} + +static void _ARMV7M_TC_tick(void) +{ + rtems_timecounter_simple_downcounter_tick(&_ARMV7M_TC, _ARMV7M_TC_get); +} static void _ARMV7M_Systick_at_tick(void) { @@ -67,15 +88,18 @@ static void _ARMV7M_Systick_initialize(void) uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); uint64_t interval = (freq * us_per_tick) / 1000000ULL; - #ifndef BSP_ARMV7M_SYSTICK_FREQUENCY - _ARMV7M_Systick_factor = _ARMV7M_Systick_get_factor(freq); - #endif - systick->rvr = (uint32_t) interval; systick->cvr = 0; systick->csr = ARMV7M_SYSTICK_CSR_ENABLE | ARMV7M_SYSTICK_CSR_TICKINT | ARMV7M_SYSTICK_CSR_CLKSOURCE; + + rtems_timecounter_simple_install( + &_ARMV7M_TC, + freq, + interval, + _ARMV7M_TC_get_timecount + ); } static void _ARMV7M_Systick_cleanup(void) @@ -85,19 +109,7 @@ static void _ARMV7M_Systick_cleanup(void) systick->csr = 0; } -static uint32_t _ARMV7M_Systick_nanoseconds_since_last_tick(void) -{ - volatile ARMV7M_Systick *systick = _ARMV7M_Systick; - volatile ARMV7M_SCB *scb = _ARMV7M_SCB; - uint32_t rvr = systick->rvr; - uint32_t c = rvr - systick->cvr; - - if ((scb->icsr & ARMV7M_SCB_ICSR_PENDSTSET) != 0) { - c = rvr - systick->cvr + rvr; - } - - return (uint32_t) ((c * _ARMV7M_Systick_factor) >> 32); -} +#define Clock_driver_timecounter_tick() _ARMV7M_TC_tick() #define Clock_driver_support_at_tick() \ _ARMV7M_Systick_at_tick() @@ -114,9 +126,6 @@ static uint32_t _ARMV7M_Systick_nanoseconds_since_last_tick(void) #define Clock_driver_support_shutdown_hardware() \ _ARMV7M_Systick_cleanup() -#define Clock_driver_nanoseconds_since_last_tick \ - _ARMV7M_Systick_nanoseconds_since_last_tick - /* Include shared source clock driver code */ #include "../../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/arm/shared/lpc/clock/lpc-clock-config.c b/c/src/lib/libbsp/arm/shared/lpc/clock/lpc-clock-config.c index 05c94a6b2c..a55ba0e33c 100644 --- a/c/src/lib/libbsp/arm/shared/lpc/clock/lpc-clock-config.c +++ b/c/src/lib/libbsp/arm/shared/lpc/clock/lpc-clock-config.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2009-2012 embedded brains GmbH. All rights reserved. + * Copyright (c) 2009-2015 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * @@ -21,6 +21,7 @@ */ #include +#include #include #include @@ -33,6 +34,16 @@ void Clock_isr(rtems_irq_hdl_param arg); static volatile lpc_timer *const lpc_clock = (volatile lpc_timer *) LPC_CLOCK_TIMER_BASE; +static volatile lpc_timer *const lpc_timecounter = + (volatile lpc_timer *) LPC_CLOCK_TIMECOUNTER_BASE; + +static struct timecounter lpc_clock_tc; + +static uint32_t lpc_clock_tc_get_timecount(struct timecounter *tc) +{ + return lpc_timecounter->tc; +} + static void lpc_clock_at_tick(void) { lpc_clock->ir = LPC_TIMER_IR_MR0; @@ -56,6 +67,7 @@ static void lpc_clock_handler_install(void) static void lpc_clock_initialize(void) { + uint32_t mask; uint64_t interval = ((uint64_t) LPC_CLOCK_REFERENCE * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000; @@ -85,6 +97,13 @@ static void lpc_clock_initialize(void) /* Enable timer */ lpc_clock->tcr = LPC_TIMER_TCR_EN; + + /* Install timecounter */ + lpc_clock_tc.tc_get_timecount = lpc_clock_tc_get_timecount; + lpc_clock_tc.tc_counter_mask = 0xffffffff; + lpc_clock_tc.tc_frequency = LPC_CLOCK_REFERENCE; + lpc_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&lpc_clock_tc); } static void lpc_clock_cleanup(void) @@ -105,18 +124,6 @@ static void lpc_clock_cleanup(void) } } -static uint32_t lpc_clock_nanoseconds_since_last_tick(void) -{ - uint64_t k = (1000000000ULL << 32) / LPC_CLOCK_REFERENCE; - uint64_t c = lpc_clock->tc; - - if ((lpc_clock->ir & LPC_TIMER_IR_MR0) != 0) { - c = lpc_clock->tc + lpc_clock->mr0; - } - - return (uint32_t) ((c * k) >> 32); -} - #define Clock_driver_support_at_tick() lpc_clock_at_tick() #define Clock_driver_support_initialize_hardware() lpc_clock_initialize() #define Clock_driver_support_install_isr(isr, old_isr) \ @@ -126,8 +133,6 @@ static uint32_t lpc_clock_nanoseconds_since_last_tick(void) } while (0) #define Clock_driver_support_shutdown_hardware() lpc_clock_cleanup() -#define Clock_driver_nanoseconds_since_last_tick \ - lpc_clock_nanoseconds_since_last_tick /* Include shared source clock driver code */ #include "../../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/arm/tms570/clock/clock.c b/c/src/lib/libbsp/arm/tms570/clock/clock.c index 4dba949c86..d438a3da34 100644 --- a/c/src/lib/libbsp/arm/tms570/clock/clock.c +++ b/c/src/lib/libbsp/arm/tms570/clock/clock.c @@ -30,13 +30,14 @@ #include #include #include +#include -/** - * holds HW counter value since last interrupt event - * sets in tms570_clock_driver_support_at_tick - * used in tms570_clock_driver_nanoseconds_since_last_tick - */ -static uint32_t tms570_rti_last_tick_fcr0; +static struct timecounter tms570_rti_tc; + +static uint32_t tms570_rti_get_timecount(struct timecounter tc) +{ + return TMS570_RTI.RTIFRC0; +} /** * @brief Initialize the HW peripheral for clock driver @@ -72,6 +73,12 @@ static void tms570_clock_driver_support_initialize_hardware( void ) TMS570_RTI.RTISETINTENA = 0x1; /* enable timer */ TMS570_RTI.RTIGCTRL = 1; + /* set timecounter */ + tms570_rti_tc.tc_get_timecount = tms570_rti_get_timecount; + tms570_rti_tc.tc_counter_mask = 0xffffffff; + tms570_rti_tc.tc_frequency = BSP_PLL_OUT_CLOCK; + tms570_rti_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&tms570_rti_tc); } /** @@ -82,7 +89,6 @@ static void tms570_clock_driver_support_initialize_hardware( void ) static void tms570_clock_driver_support_at_tick( void ) { TMS570_RTI.RTIINTFLAG = 0x00000001; - tms570_rti_last_tick_fcr0 = TMS570_RTI.RTICOMP0 - TMS570_RTI.RTIUDCP0; } /** @@ -124,24 +130,6 @@ static void tms570_clock_driver_support_shutdown_hardware( void ) TMS570_RTI.RTICLEARINTENA = 0x20000; } -/** - * @brief returns the nanoseconds since last tick - * - * Return the nanoseconds since last tick - * - * @retval x nanoseconds - * - */ -static uint32_t tms570_clock_driver_nanoseconds_since_last_tick( void ) -{ - uint32_t actual_fcr0 = TMS570_RTI.RTIFRC0; - uint32_t usec_since_tick; - - usec_since_tick = actual_fcr0 - tms570_rti_last_tick_fcr0; - - return usec_since_tick * 1000; -} - #define Clock_driver_support_initialize_hardware \ tms570_clock_driver_support_initialize_hardware #define Clock_driver_support_at_tick \ @@ -150,8 +138,6 @@ static uint32_t tms570_clock_driver_nanoseconds_since_last_tick( void ) tms570_clock_driver_support_initialize_hardware #define Clock_driver_support_shutdown_hardware \ tms570_clock_driver_support_shutdown_hardware -#define Clock_driver_nanoseconds_since_last_tick \ - tms570_clock_driver_nanoseconds_since_last_tick #define Clock_driver_support_install_isr(Clock_isr, Old_ticker ) \ tms570_clock_driver_support_install_isr( Clock_isr ) diff --git a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c index 2782252680..44a35bc6c1 100644 --- a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c +++ b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c @@ -28,6 +28,7 @@ #include #include #include +#include #define CLOCK_VECTOR 0 @@ -39,29 +40,24 @@ uint32_t pc386_clock_click_count; void Clock_isr(void *param); static void Clock_driver_support_at_tick_empty(void); static void clockOff(void); -static void Clock_driver_support_at_tick_tsc(void); -static uint32_t bsp_clock_nanoseconds_since_last_tick_tsc(void); -static uint32_t bsp_clock_nanoseconds_since_last_tick_i8254(void); static void Clock_isr_handler(void *param); /* - * Roughly the number of cycles per tick and per nanosecond. Note that these + * Roughly the number of cycles per second. Note that these * will be wildly inaccurate if the chip speed changes due to power saving * or thermal modes. * * NOTE: These are only used when the TSC method is used. */ -uint64_t pc586_tsc_per_tick; -uint64_t pc586_nanoseconds_per_tick; +static uint64_t pc586_tsc_frequency; -uint64_t pc586_tsc_at_tick; +static struct timecounter pc386_tc; /* this driver may need to count ISRs per tick */ #define CLOCK_DRIVER_ISRS_PER_TICK 1 #define CLOCK_DRIVER_ISRS_PER_TICK_VALUE pc386_isrs_per_tick -/* The driver uses the count in Clock_driver_support_at_tick */ -extern volatile uint32_t Clock_driver_isrs; +extern volatile uint32_t Clock_driver_ticks; #define READ_8254( _lsb, _msb ) \ do { outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH); \ @@ -74,60 +70,21 @@ extern volatile uint32_t Clock_driver_isrs; * Hooks which get swapped based upon which nanoseconds since last * tick method is preferred. */ -void (*Clock_driver_support_at_tick)(void) = NULL; -uint32_t (*Clock_driver_nanoseconds_since_last_tick)(void) = NULL; - -/* - * What do we do at each clock tick? - */ -static void Clock_driver_support_at_tick_tsc(void) -{ - pc586_tsc_at_tick = rdtsc(); -} - -static void Clock_driver_support_at_tick_empty(void) -{ -} +#define Clock_driver_support_at_tick() #define Clock_driver_support_install_isr( _new, _old ) \ do { \ _old = NULL; \ } while(0) -/* - * Get nanoseconds using Pentium-compatible TSC register - */ -static uint32_t bsp_clock_nanoseconds_since_last_tick_tsc(void) +static uint32_t pc386_get_timecount_tsc(struct timecounter *tc) { - uint64_t diff_nsec; - - diff_nsec = rdtsc() - pc586_tsc_at_tick; - - /* - * At this point, with a hypothetical 10 GHz CPU clock and 100 Hz tick - * clock, diff_nsec <= 27 bits. - */ - diff_nsec *= pc586_nanoseconds_per_tick; /* <= 54 bits */ - diff_nsec /= pc586_tsc_per_tick; - - if (diff_nsec > pc586_nanoseconds_per_tick) - /* - * Hmmm... Some drift or rounding. Pin the value to 1 nanosecond before - * the next tick. - */ - /* diff_nsec = pc586_nanoseconds_per_tick - 1; */ - diff_nsec = 12345; - - return (uint32_t)diff_nsec; + return (uint32_t)rdtsc(); } -/* - * Get nanoseconds using 8254 timer chip - */ -static uint32_t bsp_clock_nanoseconds_since_last_tick_i8254(void) +static uint32_t pc386_get_timecount_i8254(struct timecounter *tc) { - uint32_t usecs, clicks, isrs; - uint32_t usecs1, usecs2; + uint32_t irqs; uint8_t lsb, msb; rtems_interrupt_level level; @@ -136,34 +93,10 @@ static uint32_t bsp_clock_nanoseconds_since_last_tick_i8254(void) */ rtems_interrupt_disable(level); READ_8254(lsb, msb); - isrs = Clock_driver_isrs; + irqs = Clock_driver_ticks; rtems_interrupt_enable(level); - /* - * Now do the math - */ - /* convert values read into counter clicks */ - clicks = ((msb << 8) | lsb); - - /* whole ISRs we have done since the last tick */ - usecs1 = (pc386_isrs_per_tick - isrs - 1) * pc386_microseconds_per_isr; - - /* the partial ISR we in the middle of now */ - usecs2 = pc386_microseconds_per_isr - TICK_TO_US(clicks); - - /* total microseconds */ - usecs = usecs1 + usecs2; - #if 0 - printk( "usecs1=%d usecs2=%d ", usecs1, usecs2 ); - printk( "maxclicks=%d clicks=%d ISRs=%d ISRsper=%d usersPer=%d usecs=%d\n", - pc386_clock_click_count, clicks, - Clock_driver_isrs, pc386_isrs_per_tick, - pc386_microseconds_per_isr, usecs ); - #endif - - /* return it in nanoseconds */ - return usecs * 1000; - + return (irqs + 1) * pc386_microseconds_per_isr - ((msb << 8) | lsb); } /* @@ -175,9 +108,6 @@ static void calibrate_tsc(void) uint8_t then_lsb, then_msb, now_lsb, now_msb; uint32_t i; - pc586_nanoseconds_per_tick = - rtems_configuration_get_microseconds_per_tick() * 1000; - /* * We just reset the timer, so we know we're at the beginning of a tick. */ @@ -204,16 +134,11 @@ static void calibrate_tsc(void) } while (1); } - pc586_tsc_per_tick = rdtsc() - begin_time; - - /* Initialize "previous tick" counters */ - pc586_tsc_at_tick = rdtsc(); + pc586_tsc_frequency = rdtsc() - begin_time; #if 0 - printk( "CPU clock at %u MHz\n", (uint32_t)(pc586_tsc_per_tick / 1000000)); + printk( "CPU clock at %u MHz\n", (uint32_t)(pc586_tsc_frequency / 1000000)); #endif - - pc586_tsc_per_tick /= rtems_clock_get_ticks_per_second(); } static void clockOn(void) @@ -299,24 +224,18 @@ void Clock_driver_support_initialize_hardware(void) if ( use_8254 ) { /* printk( "Use 8254\n" ); */ - Clock_driver_support_at_tick = Clock_driver_support_at_tick_empty; - Clock_driver_nanoseconds_since_last_tick = - bsp_clock_nanoseconds_since_last_tick_i8254; + pc386_tc.tc_get_timecount = pc386_get_timecount_i8254; + pc386_tc.tc_counter_mask = 0xffffffff; + pc386_tc.tc_frequency = TIMER_TICK; } else { /* printk( "Use TSC\n" ); */ - Clock_driver_support_at_tick = Clock_driver_support_at_tick_tsc; - Clock_driver_nanoseconds_since_last_tick = - bsp_clock_nanoseconds_since_last_tick_tsc; + pc386_tc.tc_get_timecount = pc386_get_timecount_tsc; + pc386_tc.tc_counter_mask = 0xffffffff; + pc386_tc.tc_frequency = pc586_tsc_frequency; } - /* Shell installs nanosecond handler before calling - * Clock_driver_support_initialize_hardware() :-( - * so we do it again now that we're ready. - */ - rtems_clock_set_nanoseconds_extension( - Clock_driver_nanoseconds_since_last_tick - ); - + pc386_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&pc386_tc); Clock_isr_enabled = true; } diff --git a/c/src/lib/libbsp/lm32/shared/clock/ckinit.c b/c/src/lib/libbsp/lm32/shared/clock/ckinit.c index ae065de0d8..b1f5c8d0b9 100644 --- a/c/src/lib/libbsp/lm32/shared/clock/ckinit.c +++ b/c/src/lib/libbsp/lm32/shared/clock/ckinit.c @@ -75,5 +75,7 @@ static void Clock_driver_support_shutdown_hardware(void) clockwrite(LM32_CLOCK_CR, LM32_CLOCK_CR_STOP); } +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c b/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c index 65651e6470..3230d83325 100644 --- a/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c +++ b/c/src/lib/libbsp/lm32/shared/milkymist_clock/ckinit.c @@ -46,4 +46,6 @@ static void Clock_driver_support_shutdown_hardware(void) MM_WRITE(MM_TIMER0_CONTROL, 0); } +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/m68k/av5282/clock/clock.c b/c/src/lib/libbsp/m68k/av5282/clock/clock.c index 3dded8adf1..182693fe03 100644 --- a/c/src/lib/libbsp/m68k/av5282/clock/clock.c +++ b/c/src/lib/libbsp/m68k/av5282/clock/clock.c @@ -58,4 +58,6 @@ MCF5282_PIT_PCSR_EN; \ } while (0) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/m68k/gen68360/clock/clock.c b/c/src/lib/libbsp/m68k/gen68360/clock/clock.c index 78deaf9cce..3b9d4ca293 100644 --- a/c/src/lib/libbsp/m68k/gen68360/clock/clock.c +++ b/c/src/lib/libbsp/m68k/gen68360/clock/clock.c @@ -98,4 +98,6 @@ extern int m360_clock_rate; m360.pitr |= divisor; \ } while (0) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/m68k/genmcf548x/clock/clock.c b/c/src/lib/libbsp/m68k/genmcf548x/clock/clock.c index d3f6eb467c..d0f28c6b72 100644 --- a/c/src/lib/libbsp/m68k/genmcf548x/clock/clock.c +++ b/c/src/lib/libbsp/m68k/genmcf548x/clock/clock.c @@ -98,5 +98,7 @@ MCF548X_SLT_SCR0 |= (MCF548X_SLT_SCR_TEN | MCF548X_SLT_SCR_RUN | MCF548X_SLT_SCR_IEN); \ } while (0) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c b/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c index c22393d5ae..7a508a3b1c 100644 --- a/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c +++ b/c/src/lib/libbsp/m68k/mcf52235/clock/clock.c @@ -3,6 +3,7 @@ */ #include +#include #include /* @@ -10,34 +11,37 @@ */ #define CLOCK_VECTOR (64+56) -static uint32_t s_pcntrAtTick = 0; -static uint32_t s_nanoScale = 0; +static rtems_timecounter_simple mcf52235_tc; -/* - * Provide nanosecond extension - * Interrupts are disabled when this is called - */ -static uint32_t bsp_clock_nanoseconds_since_last_tick(void) +static uint32_t mcf52235_tc_get(rtems_timecounter_simple *tc) { - uint32_t i; + return MCF_PIT1_PCNTR; +} - if (MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF) { - i = s_pcntrAtTick + (MCF_PIT1_PMR - MCF_PIT1_PCNTR); - } - else { - i = s_pcntrAtTick - MCF_PIT1_PCNTR; - } - return i * s_nanoScale; +static bool mcf52235_tc_is_pending(rtems_timecounter_simple *tc) +{ + return (MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF) != 0; } -#define Clock_driver_nanoseconds_since_last_tick bsp_clock_nanoseconds_since_last_tick +static uint32_t mcf52235_tc_get_timecount(struct timecounter *tc) +{ + return rtems_timecounter_simple_downcounter_get( + tc, + mcf52235_tc_get, + mcf52235_tc_is_pending + ); +} + +static void mcf52235_tc_tick(void) +{ + rtems_timecounter_simple_downcounter_tick(&mcf52235_tc, mcf52235_tc_get); +} /* * Periodic interval timer interrupt handler */ #define Clock_driver_support_at_tick() \ do { \ - s_pcntrAtTick = MCF_PIT1_PCNTR; \ MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF; \ } while (0) \ @@ -64,6 +68,7 @@ static void Clock_driver_support_shutdown_hardware(void) */ static void Clock_driver_support_initialize_hardware(void) { + uint32_t mask; int level; uint32_t pmr; uint32_t preScaleCode = 0; @@ -76,7 +81,6 @@ static void Clock_driver_support_initialize_hardware(void) break; preScaleCode++; } - s_nanoScale = 1000000000 / (clk >> preScaleCode); MCF_INTC0_ICR56 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL) | MCF_INTC_ICR_IP(PIT3_IRQ_PRIORITY); @@ -90,7 +94,15 @@ static void Clock_driver_support_initialize_hardware(void) MCF_PIT1_PMR = pmr; MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) | MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN; - s_pcntrAtTick = MCF_PIT1_PCNTR; + + rtems_timecounter_simple_install( + &mcf52235_tc, + clk >> preScaleCode, + pmr, + mcf52235_tc_get_timecount + ); } +#define Clock_driver_timecounter_tick() mcf52235_tc_tick() + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c b/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c index d058126798..33fd76c0ae 100644 --- a/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c +++ b/c/src/lib/libbsp/m68k/mcf5225x/clock/clock.c @@ -3,6 +3,7 @@ */ #include +#include #include /* @@ -10,26 +11,37 @@ */ #define CLOCK_VECTOR (64+56) -static uint32_t s_pcntrAtTick = 0; -static uint32_t s_nanoScale = 0; +static rtems_timecounter_simple mcf5225x_tc; -/* - * Provide nanosecond extension - * Interrupts are disabled when this is called - */ -static uint32_t bsp_clock_nanoseconds_since_last_tick(void) +static uint32_t mcf5225x_tc_get(rtems_timecounter_simple *tc) +{ + return MCF_PIT1_PCNTR; +} + +static bool mcf5225x_tc_is_pending(rtems_timecounter_simple *tc) +{ + return (MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF) != 0; +} + +static uint32_t mcf5225x_tc_get_timecount(struct timecounter *tc) { - return MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF ? (s_pcntrAtTick + (MCF_PIT1_PMR - MCF_PIT1_PCNTR)) * s_nanoScale : (s_pcntrAtTick - MCF_PIT1_PCNTR) * s_nanoScale; + return rtems_timecounter_simple_downcounter_get( + tc, + mcf5225x_tc_get, + mcf5225x_tc_is_pending + ); } -#define Clock_driver_nanoseconds_since_last_tick bsp_clock_nanoseconds_since_last_tick +static void mcf5225x_tc_tick(void) +{ + rtems_timecounter_simple_downcounter_tick(&mcf5225x_tc, mcf5225x_tc_get); +} /* * Periodic interval timer interrupt handler */ #define Clock_driver_support_at_tick() \ do { \ - s_pcntrAtTick = MCF_PIT1_PCNTR; \ MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF; \ } while (0) \ @@ -56,6 +68,7 @@ static void Clock_driver_support_shutdown_hardware(void) */ static void Clock_driver_support_initialize_hardware(void) { + uint32_t mask; int level; uint32_t pmr; uint32_t preScaleCode = 0; @@ -68,7 +81,6 @@ static void Clock_driver_support_initialize_hardware(void) break; preScaleCode++; } - s_nanoScale = 1000000000 / (clk >> preScaleCode); MCF_INTC0_ICR56 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL) | MCF_INTC_ICR_IP(PIT3_IRQ_PRIORITY); @@ -82,7 +94,15 @@ static void Clock_driver_support_initialize_hardware(void) MCF_PIT1_PMR = pmr; MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) | MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN; - s_pcntrAtTick = MCF_PIT1_PCNTR; + + rtems_timecounter_simple_install( + &mcf5225x_tc, + clk >> preScaleCode, + pmr, + mcf5225x_tc_get_timecount + ); } +#define Clock_driver_timecounter_tick() mcf5225x_tc_tick() + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/m68k/mcf5235/clock/clock.c b/c/src/lib/libbsp/m68k/mcf5235/clock/clock.c index c057796e59..95b7f37bac 100644 --- a/c/src/lib/libbsp/m68k/mcf5235/clock/clock.c +++ b/c/src/lib/libbsp/m68k/mcf5235/clock/clock.c @@ -58,4 +58,6 @@ MCF5235_PIT_PCSR_EN; \ } while (0) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c b/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c index ed11320bba..94c5bb0b04 100644 --- a/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c +++ b/c/src/lib/libbsp/m68k/mcf5329/clock/clock.c @@ -3,6 +3,7 @@ */ #include +#include #include /* @@ -10,36 +11,40 @@ */ #define CLOCK_VECTOR (128+46) -static uint32_t s_pcntrAtTick = 0; -static uint32_t s_nanoScale = 0; +static rtems_timecounter_simple mcf5329_tc; -/* - * Provide nanosecond extension - */ -static uint32_t bsp_clock_nanoseconds_since_last_tick(void) +static uint32_t mcf5329_tc_get(rtems_timecounter_simple *tc) { - uint32_t i; + return MCF_PIT3_PCNTR; +} - if (MCF_PIT3_PCSR & MCF_PIT_PCSR_PIF) { - i = s_pcntrAtTick + (MCF_PIT3_PMR - MCF_PIT3_PCNTR); - } else { - i = s_pcntrAtTick - MCF_PIT3_PCNTR; - } - return i * s_nanoScale; +static bool mcf5329_tc_is_pending(rtems_timecounter_simple *tc) +{ + return (MCF_PIT3_PCSR & MCF_PIT_PCSR_PIF) != 0; +} + +static uint32_t mcf5329_tc_get_timecount(struct timecounter *tc) +{ + return rtems_timecounter_simple_downcounter_get( + tc, + mcf5329_tc_get, + mcf5329_tc_is_pending + ); } -#define Clock_driver_nanoseconds_since_last_tick bsp_clock_nanoseconds_since_last_tick +static void mcf5329_tc_tick(void) +{ + rtems_timecounter_simple_downcounter_tick(&mcf5329_tc, mcf5329_tc_get); +} /* * Periodic interval timer interrupt handler */ #define Clock_driver_support_at_tick() \ do { \ - s_pcntrAtTick = MCF_PIT3_PCNTR; \ MCF_PIT3_PCSR |= MCF_PIT_PCSR_PIF; \ } while (0) \ - /* * Attach clock interrupt handler */ @@ -75,8 +80,6 @@ static void Clock_driver_support_initialize_hardware(void) break; preScaleCode++; } - s_nanoScale = 1000000000 / (clk >> preScaleCode); - MCF_INTC1_ICR46 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL); rtems_interrupt_disable(level); @@ -89,7 +92,15 @@ static void Clock_driver_support_initialize_hardware(void) MCF_PIT3_PMR = pmr; MCF_PIT3_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) | MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN; - s_pcntrAtTick = MCF_PIT3_PCNTR; + + rtems_timecounter_simple_install( + &mcf5329_tc, + clk >> preScaleCode, + pmr, + mcf5329_tc_get_timecount + ); } +#define Clock_driver_timecounter_tick() mcf5329_tc_tick() + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/m68k/sim68000/clock/clockdrv.c b/c/src/lib/libbsp/m68k/sim68000/clock/clockdrv.c index 3cf981863a..0a78abc15f 100644 --- a/c/src/lib/libbsp/m68k/sim68000/clock/clockdrv.c +++ b/c/src/lib/libbsp/m68k/sim68000/clock/clockdrv.c @@ -48,4 +48,6 @@ static void Clock_driver_support_shutdown_hardware(void) t->cr = 0xA0; /* initialize with timer disabled */ } +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/m68k/uC5282/clock/clock.c b/c/src/lib/libbsp/m68k/uC5282/clock/clock.c index 8636f96fe0..46e045cae3 100644 --- a/c/src/lib/libbsp/m68k/uC5282/clock/clock.c +++ b/c/src/lib/libbsp/m68k/uC5282/clock/clock.c @@ -12,6 +12,7 @@ */ #include +#include #include #include @@ -20,6 +21,32 @@ */ #define CLOCK_VECTOR (64+58) +static rtems_timecounter_simple uC5282_tc; + +static uint32_t uC5282_tc_get(rtems_timecounter_simple *tc) +{ + return MCF5282_PIT3_PCNTR; +} + +static bool uC5282_tc_is_pending(rtems_timecounter_simple *tc) +{ + return (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF) != 0; +} + +static uint32_t uC5282_tc_get_timecount(struct timecounter *tc) +{ + return rtems_timecounter_simple_downcounter_get( + tc, + uC5282_tc_get, + uC5282_tc_is_pending + ); +} + +static void uC5282_tc_tick(void) +{ + rtems_timecounter_simple_downcounter_tick(&uC5282_tc, uC5282_tc_get); +} + /* * CPU load counters * Place in static RAM so updates don't hit the SDRAM @@ -31,17 +58,6 @@ #define NSEC_PER_PITC __SRAMBASE.nsec_per_pitc #define FILTER_SHIFT 6 -static 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 - PITC_PER_TICK; - return (PITC_PER_TICK - i) * NSEC_PER_PITC; -} - -#define Clock_driver_nanoseconds_since_last_tick \ - bsp_clock_nanoseconds_since_last_tick - /* * Periodic interval timer interrupt handler */ @@ -83,7 +99,7 @@ static uint32_t bsp_clock_nanoseconds_since_last_tick(void) */ #define Clock_driver_support_initialize_hardware() \ do { \ - unsigned long long N; \ + unsigned long long N; \ int level; \ int preScaleCode = 0; \ N = bsp_get_CPU_clock_speed(); \ @@ -116,6 +132,12 @@ static uint32_t bsp_clock_nanoseconds_since_last_tick(void) MCF5282_PIT_PCSR_PIE | \ MCF5282_PIT_PCSR_RLD | \ MCF5282_PIT_PCSR_EN; \ + rtems_timecounter_simple_install( \ + &uC5282_tc, \ + bsp_get_CPU_clock_speed() >> (preScaleCode + 1), \ + PITC_PER_TICK, \ + uC5282_tc_get_timecount \ + ); \ } while (0) /* @@ -135,4 +157,6 @@ int bsp_cpu_load_percentage(void) 0; } +#define Clock_driver_timecounter_tick() uC5282_tc_tick() + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/mips/csb350/clock/clockdrv.c b/c/src/lib/libbsp/mips/csb350/clock/clockdrv.c index c733a1b19a..537bf7ee1e 100644 --- a/c/src/lib/libbsp/mips/csb350/clock/clockdrv.c +++ b/c/src/lib/libbsp/mips/csb350/clock/clockdrv.c @@ -88,4 +88,6 @@ void au1x00_clock_init(void) #define Clock_driver_support_shutdown_hardware() +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/mips/genmongoosev/clock/clockdrv.c b/c/src/lib/libbsp/mips/genmongoosev/clock/clockdrv.c index 05c1a92ac4..20f730ad6b 100644 --- a/c/src/lib/libbsp/mips/genmongoosev/clock/clockdrv.c +++ b/c/src/lib/libbsp/mips/genmongoosev/clock/clockdrv.c @@ -54,4 +54,6 @@ #define Clock_driver_support_shutdown_hardware() \ MONGOOSEV_WRITE_REGISTER( CLOCK_BASE, MONGOOSEV_TIMER_CONTROL_REGISTER, 0 ) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/mips/jmr3904/clock/clockdrv.c b/c/src/lib/libbsp/mips/jmr3904/clock/clockdrv.c index 4aa1f9ebb6..f3bcbe25f1 100644 --- a/c/src/lib/libbsp/mips/jmr3904/clock/clockdrv.c +++ b/c/src/lib/libbsp/mips/jmr3904/clock/clockdrv.c @@ -55,4 +55,6 @@ #define Clock_driver_support_shutdown_hardware() +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/mips/rbtx4925/clock/clockdrv.c b/c/src/lib/libbsp/mips/rbtx4925/clock/clockdrv.c index 4a45c9a955..2fb56c6eb9 100644 --- a/c/src/lib/libbsp/mips/rbtx4925/clock/clockdrv.c +++ b/c/src/lib/libbsp/mips/rbtx4925/clock/clockdrv.c @@ -123,5 +123,6 @@ TX4925_REG_WRITE( TX4925_REG_BASE, TX4925_TIMER0_BASE + TX4925_TIMER_TCR, 0x0 ); /* Disable timer */ \ } while(0) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/mips/rbtx4938/clock/clockdrv.c b/c/src/lib/libbsp/mips/rbtx4938/clock/clockdrv.c index f50c6d2fdc..59b3452d88 100644 --- a/c/src/lib/libbsp/mips/rbtx4938/clock/clockdrv.c +++ b/c/src/lib/libbsp/mips/rbtx4938/clock/clockdrv.c @@ -114,4 +114,6 @@ void new_brk_esr(void) } while(0) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/mips/shared/clock/clockdrv.c b/c/src/lib/libbsp/mips/shared/clock/clockdrv.c index 8ee52c63ed..8b178bbd52 100644 --- a/c/src/lib/libbsp/mips/shared/clock/clockdrv.c +++ b/c/src/lib/libbsp/mips/shared/clock/clockdrv.c @@ -43,17 +43,11 @@ static uint32_t mips_timer_rate = 0; mips_enable_in_interrupt_mask(CLOCK_VECTOR_MASK); \ } while(0) -static uint32_t bsp_clock_nanoseconds_since_last_tick(void) -{ - return 0; -} - -#define Clock_driver_nanoseconds_since_last_tick \ - bsp_clock_nanoseconds_since_last_tick - #define Clock_driver_support_shutdown_hardware() \ do { \ mips_disable_in_interrupt_mask(CLOCK_VECTOR_MASK); \ } while (0) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/nios2/nios2_iss/clock/clock.c b/c/src/lib/libbsp/nios2/nios2_iss/clock/clock.c index 939af651c5..1656e763c1 100644 --- a/c/src/lib/libbsp/nios2/nios2_iss/clock/clock.c +++ b/c/src/lib/libbsp/nios2/nios2_iss/clock/clock.c @@ -49,5 +49,7 @@ static void Clock_driver_support_initialize_hardware(void) NIOS2_IENABLE(1 << CLOCK_VECTOR); } +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c b/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c index 57e46c1897..e01d2e506d 100644 --- a/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c +++ b/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c @@ -22,11 +22,14 @@ #include #include #include +#include /* The number of clock cycles before generating a tick timer interrupt. */ #define TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT 0x09ED9 #define OR1K_CLOCK_CYCLE_TIME_NANOSECONDS 10 +static struct timecounter or1ksim_tc; + /* CPU counter */ static CPU_Counter_ticks cpu_counter_ticks; @@ -69,8 +72,23 @@ static void generic_or1k_clock_handler_install( } } +static uint32_t or1ksim_get_timecount(struct timecounter *tc) +{ + uint32_t ticks_since_last_timer_interrupt; + + ticks_since_last_timer_interrupt = _OR1K_mfspr(CPU_OR1K_SPR_TTCR); + + return cpu_counter_ticks + ticks_since_last_timer_interrupt; +} + +CPU_Counter_ticks _CPU_Counter_read(void) +{ + return or1ksim_get_timecount(NULL); +} + static void generic_or1k_clock_initialize(void) { + uint64_t frequency = (1000000000 / OR1K_CLOCK_CYCLE_TIME_NANOSECONDS); uint32_t TTMR; /* For TTMR register, @@ -90,11 +108,15 @@ static void generic_or1k_clock_initialize(void) _OR1K_mtspr(CPU_OR1K_SPR_TTMR, TTMR); _OR1K_mtspr(CPU_OR1K_SPR_TTCR, 0); - /* Initialize CPU Counter */ - cpu_counter_ticks = 0; + /* Initialize timecounter */ + or1ksim_tc.tc_get_timecount = or1ksim_get_timecount; + or1ksim_tc.tc_counter_mask = 0xffffffff; + or1ksim_tc.tc_frequency = frequency; + or1ksim_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&or1ksim_tc); } - static void generic_or1k_clock_cleanup(void) +static void generic_or1k_clock_cleanup(void) { uint32_t sr; @@ -109,24 +131,6 @@ static void generic_or1k_clock_initialize(void) _OR1K_mtspr(CPU_OR1K_SPR_TTMR, 0); } -/* - * Return the nanoseconds since last tick - */ -static uint32_t generic_or1k_clock_nanoseconds_since_last_tick(void) -{ - return - TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT * OR1K_CLOCK_CYCLE_TIME_NANOSECONDS; -} - -CPU_Counter_ticks _CPU_Counter_read(void) -{ - uint32_t ticks_since_last_timer_interrupt; - - ticks_since_last_timer_interrupt = _OR1K_mfspr(CPU_OR1K_SPR_TTCR); - - return cpu_counter_ticks + ticks_since_last_timer_interrupt; -} - CPU_Counter_ticks _CPU_Counter_difference( CPU_Counter_ticks second, CPU_Counter_ticks first @@ -134,6 +138,7 @@ CPU_Counter_ticks _CPU_Counter_difference( { return second - first; } + #define Clock_driver_support_at_tick() generic_or1k_clock_at_tick() #define Clock_driver_support_initialize_hardware() generic_or1k_clock_initialize() @@ -146,7 +151,4 @@ CPU_Counter_ticks _CPU_Counter_difference( #define Clock_driver_support_shutdown_hardware() generic_or1k_clock_cleanup() -#define Clock_driver_nanoseconds_since_last_tick \ - generic_or1k_clock_nanoseconds_since_last_tick - #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c b/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c index 5743dcff35..5724f9bf4b 100644 --- a/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c +++ b/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c @@ -26,14 +26,40 @@ #include +#include + void Clock_isr(void *arg); -static uint64_t mpc55xx_clock_factor; +static rtems_timecounter_simple mpc55xx_tc; #if defined(MPC55XX_CLOCK_EMIOS_CHANNEL) #include +static uint32_t mpc55xx_tc_get(rtems_timecounter_simple *tc) +{ + return EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CCNTR.R; +} + +static bool mpc55xx_tc_is_pending(rtems_timecounter_simple *tc) +{ + return EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.B.FLAG != 0; +} + +static uint32_t mpc55xx_tc_get_timecount(struct timecounter *tc) +{ + return rtems_timecounter_simple_upcounter_get( + tc, + mpc55xx_tc_get, + mpc55xx_tc_is_pending + ); +} + +static void mpc55xx_tc_tick(void) +{ + rtems_timecounter_simple_upcounter_tick(&mpc55xx_tc, mpc55xx_tc_get); +} + static void mpc55xx_clock_at_tick(void) { union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS; @@ -60,6 +86,7 @@ static void mpc55xx_clock_handler_install(rtems_isr_entry isr) static void mpc55xx_clock_initialize(void) { + uint32_t mask; volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL]; union EMIOS_CCR_tag ccr = MPC55XX_ZERO_FLAGS; union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS; @@ -68,8 +95,6 @@ static void mpc55xx_clock_initialize(void) uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); uint64_t interval = (reference_clock * us_per_tick) / 1000000; - mpc55xx_clock_factor = (1000000000ULL << 32) / reference_clock; - /* Apply prescaler */ if (prescaler > 0) { interval /= (uint64_t) prescaler; @@ -110,6 +135,13 @@ static void mpc55xx_clock_initialize(void) ccr.B.FEN = 1; ccr.B.FREN = 1; regs->CCR.R = ccr.R; + + rtems_timecounter_simple_install( + &mpc55xx_tc, + reference_clock, + interval, + mpc55xx_tc_get_timecount + ); } static void mpc55xx_clock_cleanup(void) @@ -122,21 +154,31 @@ static void mpc55xx_clock_cleanup(void) regs->CCR.R = ccr.R; } -static uint32_t mpc55xx_clock_nanoseconds_since_last_tick(void) +#elif defined(MPC55XX_CLOCK_PIT_CHANNEL) + +static uint32_t mpc55xx_tc_get(rtems_timecounter_simple *tc) { - volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL]; - uint64_t c = regs->CCNTR.R; - union EMIOS_CSR_tag csr = { .R = regs->CSR.R }; - uint64_t k = mpc55xx_clock_factor; + return PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL].CVAL.R; +} - if (csr.B.FLAG != 0) { - c = regs->CCNTR.R + regs->CADR.R + 1; - } +static bool mpc55xx_tc_is_pending(rtems_timecounter_simple *tc) +{ + return PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL].TFLG.B.TIF != 0; +} - return (uint32_t) ((c * k) >> 32); +static uint32_t mpc55xx_tc_get_timecount(struct timecounter *tc) +{ + return rtems_timecounter_simple_downcounter_get( + tc, + mpc55xx_tc_get, + mpc55xx_tc_is_pending + ); } -#elif defined(MPC55XX_CLOCK_PIT_CHANNEL) +static void mpc55xx_tc_tick(void) +{ + rtems_timecounter_simple_downcounter_tick(&mpc55xx_tc, mpc55xx_tc_get); +} static void mpc55xx_clock_at_tick(void) { @@ -166,6 +208,7 @@ static void mpc55xx_clock_handler_install(rtems_isr_entry isr) static void mpc55xx_clock_initialize(void) { + uint32_t mask; volatile PIT_RTI_CHANNEL_tag *channel = &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL]; uint64_t reference_clock = bsp_clock_speed; @@ -174,11 +217,16 @@ static void mpc55xx_clock_initialize(void) PIT_RTI_PITMCR_32B_tag pitmcr = { .B = { .FRZ = 1 } }; PIT_RTI_TCTRL_32B_tag tctrl = { .B = { .TIE = 1, .TEN = 1 } }; - mpc55xx_clock_factor = (1000000000ULL << 32) / reference_clock; - PIT_RTI.PITMCR.R = pitmcr.R; channel->LDVAL.R = interval; channel->TCTRL.R = tctrl.R; + + rtems_timecounter_simple_install( + &mpc55xx_tc, + reference_clock, + interval, + mpc55xx_tc_get_timecount + ); } static void mpc55xx_clock_cleanup(void) @@ -189,23 +237,9 @@ static void mpc55xx_clock_cleanup(void) channel->TCTRL.R = 0; } -static uint32_t mpc55xx_clock_nanoseconds_since_last_tick(void) -{ - volatile PIT_RTI_CHANNEL_tag *channel = - &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL]; - uint32_t c = channel->CVAL.R; - uint32_t i = channel->LDVAL.R; - uint64_t k = mpc55xx_clock_factor; - - if (channel->TFLG.B.TIF != 0) { - c = channel->CVAL.R - i; - } - - return (uint32_t) (((i - c) * k) >> 32); -} - #endif +#define Clock_driver_timecounter_tick() mpc55xx_tc_tick() #define Clock_driver_support_at_tick() \ mpc55xx_clock_at_tick() #define Clock_driver_support_initialize_hardware() \ @@ -217,8 +251,6 @@ static uint32_t mpc55xx_clock_nanoseconds_since_last_tick(void) } while (0) #define Clock_driver_support_shutdown_hardware() \ mpc55xx_clock_cleanup() -#define Clock_driver_nanoseconds_since_last_tick \ - mpc55xx_clock_nanoseconds_since_last_tick /* Include shared source clock driver code */ #include "../../../../libbsp/shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c b/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c index 039edde46e..c6300e254f 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c +++ b/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2011-2012 embedded brains GmbH. All rights reserved. + * Copyright (c) 2011-2015 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * @@ -20,6 +20,8 @@ * http://www.rtems.org/license/LICENSE. */ +#include + #include #include @@ -29,10 +31,6 @@ /* This is defined in clockdrv_shell.h */ static rtems_isr Clock_isr(void *arg); -static uint32_t qoriq_clock_last_ccr; - -static uint32_t qoriq_clock_nanoseconds_per_timer_tick; - static volatile qoriq_pic_global_timer *const qoriq_clock = #if QORIQ_CLOCK_TIMER < 4 &qoriq.pic.gta [QORIQ_CLOCK_TIMER]; @@ -40,8 +38,17 @@ static volatile qoriq_pic_global_timer *const qoriq_clock = &qoriq.pic.gtb [QORIQ_CLOCK_TIMER - 4]; #endif +static volatile qoriq_pic_global_timer *const qoriq_timecounter = + #if QORIQ_CLOCK_TIMECOUNTER < 4 + &qoriq.pic.gta [QORIQ_CLOCK_TIMECOUNTER]; + #else + &qoriq.pic.gtb [QORIQ_CLOCK_TIMECOUNTER - 4]; + #endif + #define CLOCK_INTERRUPT (QORIQ_IRQ_GT_BASE + QORIQ_CLOCK_TIMER) +static struct timecounter qoriq_clock_tc; + static void qoriq_clock_handler_install(rtems_isr_entry *old_isr) { rtems_status_code sc = RTEMS_SUCCESSFUL; @@ -77,18 +84,28 @@ static void qoriq_clock_handler_install(rtems_isr_entry *old_isr) } } +static uint32_t qoriq_clock_get_timecount(struct timecounter *tc) +{ + uint32_t ccr = qoriq_timecounter->ccr; + + return GTCCR_COUNT_GET(-ccr); +} + static void qoriq_clock_initialize(void) { uint32_t timer_frequency = BSP_bus_frequency / 8; - uint32_t nanoseconds_per_second = 1000000000; uint32_t interval = (uint32_t) (((uint64_t) timer_frequency * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000); - qoriq_clock_nanoseconds_per_timer_tick = - nanoseconds_per_second / timer_frequency; - qoriq_clock->bcr = GTBCR_COUNT(interval); - qoriq_clock_last_ccr = qoriq_clock->ccr; + + qoriq_timecounter->bcr = GTBCR_COUNT(0xffffffff); + + qoriq_clock_tc.tc_get_timecount = qoriq_clock_get_timecount; + qoriq_clock_tc.tc_counter_mask = GTCCR_COUNT_GET(0xffffffff); + qoriq_clock_tc.tc_frequency = timer_frequency; + qoriq_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&qoriq_clock_tc); } static void qoriq_clock_cleanup(void) @@ -107,33 +124,13 @@ static void qoriq_clock_cleanup(void) } } -static void qoriq_clock_at_tick(void) -{ - qoriq_clock_last_ccr = qoriq_clock->ccr; -} - -static uint32_t qoriq_clock_nanoseconds_since_last_tick(void) -{ - uint32_t ccr = qoriq_clock->ccr; - uint32_t bcr = qoriq_clock->bcr; - - if ((ccr & GTCCR_TOG) != (qoriq_clock_last_ccr & GTCCR_TOG)) { - bcr += bcr; - } - - return (bcr - GTCCR_COUNT_GET(ccr)) * qoriq_clock_nanoseconds_per_timer_tick; -} - -#define Clock_driver_support_at_tick() \ - qoriq_clock_at_tick() +#define Clock_driver_support_at_tick() #define Clock_driver_support_initialize_hardware() \ qoriq_clock_initialize() #define Clock_driver_support_install_isr(clock_isr, old_isr) \ qoriq_clock_handler_install(&old_isr) #define Clock_driver_support_shutdown_hardware() \ qoriq_clock_cleanup() -#define Clock_driver_nanoseconds_since_last_tick \ - qoriq_clock_nanoseconds_since_last_tick /* Include shared source clock driver code */ #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/powerpc/qoriq/configure.ac b/c/src/lib/libbsp/powerpc/qoriq/configure.ac index f1ff103d7c..409ac193c4 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/configure.ac +++ b/c/src/lib/libbsp/powerpc/qoriq/configure.ac @@ -154,6 +154,10 @@ RTEMS_BSPOPTS_SET([QORIQ_CLOCK_TIMER],[qoriq_core_1],[4]) RTEMS_BSPOPTS_SET([QORIQ_CLOCK_TIMER],[*],[0]) RTEMS_BSPOPTS_HELP([QORIQ_CLOCK_TIMER],[global timer used for system clock, 0..3 maps to A0..A3, and 4..7 maps to B0..B3]) +RTEMS_BSPOPTS_SET([QORIQ_CLOCK_TIMECOUNTER],[qoriq_core_1],[5]) +RTEMS_BSPOPTS_SET([QORIQ_CLOCK_TIMECOUNTER],[*],[1]) +RTEMS_BSPOPTS_HELP([QORIQ_CLOCK_TIMECOUNTER],[global timer used for the timecounter, 0..3 maps to A0..A3, and 4..7 maps to B0..B3]) + RTEMS_BSPOPTS_SET([QORIQ_CHIP_VARIANT],[qoriq_t2080*],[QORIQ_CHIP_T2080]) RTEMS_BSPOPTS_SET([QORIQ_CHIP_VARIANT],[qoriq_t4240*],[QORIQ_CHIP_T4240]) RTEMS_BSPOPTS_SET([QORIQ_CHIP_VARIANT],[*],[QORIQ_CHIP_P1020]) diff --git a/c/src/lib/libbsp/powerpc/shared/clock/clock.c b/c/src/lib/libbsp/powerpc/shared/clock/clock.c index e9b1d4d24a..d2f2d0d1b0 100644 --- a/c/src/lib/libbsp/powerpc/shared/clock/clock.c +++ b/c/src/lib/libbsp/powerpc/shared/clock/clock.c @@ -7,7 +7,7 @@ */ /* - * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved. + * Copyright (c) 2008-2015 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Obere Lagerstr. 30 @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -46,7 +47,12 @@ static uint32_t ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX; static uint32_t ppc_clock_next_time_base; -static uint64_t ppc_clock_factor; +static struct timecounter ppc_tc; + +static uint32_t ppc_get_timecount(struct timecounter *tc) +{ + return ppc_time_base(); +} static void ppc_clock_no_tick(void) { @@ -161,28 +167,6 @@ static int ppc_clock_exception_handler_ppc405(BSP_Exception_frame *frame, unsign return 0; } -static uint32_t ppc_clock_nanoseconds_since_last_tick(void) -{ - uint64_t k = ppc_clock_factor; - uint32_t c = ppc_decrementer_register(); - uint32_t i = ppc_clock_decrementer_value + 1; - - return (uint32_t) (((i - c) * k) >> 32); -} - -static uint32_t ppc_clock_nanoseconds_since_last_tick_ppc405(void) -{ - uint64_t k = ppc_clock_factor; - uint32_t i = ppc_clock_decrementer_value; - uint32_t c = i - PPC_SPECIAL_PURPOSE_REGISTER(PPC405_PIT); - - if ((PPC_SPECIAL_PURPOSE_REGISTER(PPC405_TSR) & BOOKE_TSR_DIS) != 0) { - c = i - PPC_SPECIAL_PURPOSE_REGISTER(PPC405_PIT) + i; - } - - return (uint32_t) ((c * k) >> 32); -} - void Clock_exit(void) { /* Set the decrementer to the maximum value */ @@ -201,18 +185,12 @@ rtems_device_driver Clock_initialize( uint64_t frequency = bsp_time_base_frequency; uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000); + uint32_t mask; /* * Set default ticker. - * - * The function rtems_clock_tick() returns a status code. This value - * will be discarded since the RTEMS documentation claims that it is - * always successful. */ - ppc_clock_tick = (void (*)(void)) rtems_clock_tick; - - /* Factor for nano seconds extension */ - ppc_clock_factor = (1000000000ULL << 32) / frequency; + ppc_clock_tick = rtems_timecounter_tick; if (ppc_cpu_is_bookE() != PPC_BOOKE_405) { /* Decrementer value */ @@ -223,10 +201,6 @@ rtems_device_driver Clock_initialize( ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX; RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n"); } - - /* Set the nanoseconds since last tick handler */ - rtems_clock_set_nanoseconds_extension( ppc_clock_nanoseconds_since_last_tick); - if (ppc_cpu_is_bookE()) { /* Set decrementer auto-reload value */ PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value); @@ -253,9 +227,6 @@ rtems_device_driver Clock_initialize( /* PIT interval value */ ppc_clock_decrementer_value = interval; - /* Set the nanoseconds since last tick handler */ - rtems_clock_set_nanoseconds_extension(ppc_clock_nanoseconds_since_last_tick_ppc405); - /* Install exception handler */ ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_ppc405); @@ -266,5 +237,12 @@ rtems_device_driver Clock_initialize( PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_PIT, interval); } + /* Install timecounter */ + ppc_tc.tc_get_timecount = ppc_get_timecount; + ppc_tc.tc_counter_mask = 0xffffffff; + ppc_tc.tc_frequency = frequency; + ppc_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&ppc_tc); + return RTEMS_SUCCESSFUL; } diff --git a/c/src/lib/libbsp/shared/clock_driver_simidle.c b/c/src/lib/libbsp/shared/clock_driver_simidle.c index 0f94b1e56b..ee4b116b40 100644 --- a/c/src/lib/libbsp/shared/clock_driver_simidle.c +++ b/c/src/lib/libbsp/shared/clock_driver_simidle.c @@ -28,6 +28,8 @@ volatile bool clock_driver_enabled; clock_driver_enabled = false; \ } while (0) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "clockdrv_shell.h" /* diff --git a/c/src/lib/libbsp/shared/clockdrv_shell.h b/c/src/lib/libbsp/shared/clockdrv_shell.h index 5dbea1335f..628ba58672 100644 --- a/c/src/lib/libbsp/shared/clockdrv_shell.h +++ b/c/src/lib/libbsp/shared/clockdrv_shell.h @@ -20,6 +20,10 @@ #include #include +#ifdef Clock_driver_nanoseconds_since_last_tick +#error "Update driver to use the timecounter instead of nanoseconds extension" +#endif + /** * @defgroup bsp_clock Clock Support * @@ -39,6 +43,18 @@ #define Clock_driver_support_find_timer() #endif +/* + * A specialized clock driver may use for example rtems_timecounter_tick_simple() + * instead of the default. + */ +#ifndef Clock_driver_timecounter_tick + #ifdef CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #define Clock_driver_timecounter_tick() rtems_clock_tick() + #else + #define Clock_driver_timecounter_tick() rtems_timecounter_tick() + #endif +#endif + /** * @brief ISRs until next clock tick */ @@ -78,16 +94,24 @@ rtems_isr Clock_isr( Clock_driver_ticks += 1; #if CLOCK_DRIVER_USE_FAST_IDLE - do { - rtems_clock_tick(); - } while ( - _Thread_Heir == _Thread_Executing - && _Thread_Executing->Start.entry_point - == (Thread_Entry) rtems_configuration_get_idle_task() - ); + { + struct timecounter *tc = _Timecounter; + uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); + uint32_t interval = (uint32_t) + ((tc->tc_frequency * us_per_tick) / 1000000); + + Clock_driver_timecounter_tick(); + + while ( + _Thread_Heir == _Thread_Executing + && _Thread_Executing->Start.entry_point + == (Thread_Entry) rtems_configuration_get_idle_task() + ) { + _Timecounter_Tick_simple(interval, (*tc->tc_get_timecount)(tc)); + } - Clock_driver_support_at_tick(); - return; + Clock_driver_support_at_tick(); + } #else /* * Do the hardware specific per-tick action. @@ -101,7 +125,7 @@ rtems_isr Clock_isr( * The driver is multiple ISRs per clock tick. */ if ( !Clock_driver_isrs ) { - rtems_clock_tick(); + Clock_driver_timecounter_tick(); Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK; } @@ -110,7 +134,7 @@ rtems_isr Clock_isr( /* * The driver is one ISR per clock tick. */ - rtems_clock_tick(); + Clock_driver_timecounter_tick(); #endif #endif } @@ -160,12 +184,6 @@ rtems_device_driver Clock_initialize( (void) Old_ticker; Clock_driver_support_install_isr( Clock_isr, Old_ticker ); - #if defined(Clock_driver_nanoseconds_since_last_tick) - rtems_clock_set_nanoseconds_extension( - Clock_driver_nanoseconds_since_last_tick - ); - #endif - /* * Now initialize the hardware that is the source of the tick ISR. */ diff --git a/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c b/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c index 2afe770b4b..46f99a5e7d 100644 --- a/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c +++ b/c/src/lib/libbsp/sparc/erc32/clock/ckinit.c @@ -25,6 +25,7 @@ #include #include #include +#include #if SIMSPARC_FAST_IDLE==1 #define CLOCK_DRIVER_USE_FAST_IDLE 1 @@ -44,24 +45,34 @@ extern int CLOCK_SPEED; -static uint32_t bsp_clock_nanoseconds_since_last_tick(void) +static rtems_timecounter_simple erc32_tc; + +static uint32_t erc32_tc_get( rtems_timecounter_simple *tc ) +{ + return ERC32_MEC.Real_Time_Clock_Counter; +} + +static bool erc32_tc_is_pending( rtems_timecounter_simple *tc ) +{ + return ERC32_Is_interrupt_pending( ERC32_INTERRUPT_REAL_TIME_CLOCK ); +} + +static uint32_t erc32_tc_get_timecount( struct timecounter *tc ) { - uint32_t clicks; - uint32_t usecs; - - clicks = ERC32_MEC.Real_Time_Clock_Counter; - - if ( ERC32_Is_interrupt_pending( ERC32_INTERRUPT_REAL_TIME_CLOCK ) ) { - clicks = ERC32_MEC.Real_Time_Clock_Counter; - usecs = (2*rtems_configuration_get_microseconds_per_tick() - clicks); - } else { - usecs = (rtems_configuration_get_microseconds_per_tick() - clicks); - } - return usecs * 1000; + return rtems_timecounter_simple_downcounter_get( + tc, + erc32_tc_get, + erc32_tc_is_pending + ); } -#define Clock_driver_nanoseconds_since_last_tick \ - bsp_clock_nanoseconds_since_last_tick +static void erc32_tc_tick( void ) +{ + rtems_timecounter_simple_downcounter_tick( + &erc32_tc, + erc32_tc_get + ); +} static CPU_Counter_ticks erc32_counter_difference( CPU_Counter_ticks second, @@ -75,6 +86,7 @@ static CPU_Counter_ticks erc32_counter_difference( #define Clock_driver_support_initialize_hardware() \ do { \ + uint32_t frequency = 1000000; \ /* approximately 1 us per countdown */ \ ERC32_MEC.Real_Time_Clock_Scalar = CLOCK_SPEED - 1; \ ERC32_MEC.Real_Time_Clock_Counter = \ @@ -89,14 +101,22 @@ static CPU_Counter_ticks erc32_counter_difference( ERC32_MEC_Set_Real_Time_Clock_Timer_Control( \ ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING | \ ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO \ + ); \ + rtems_timecounter_simple_install( \ + &erc32_tc, \ + frequency, \ + rtems_configuration_get_microseconds_per_tick(), \ + erc32_tc_get_timecount \ ); \ _SPARC_Counter_initialize( \ &ERC32_MEC.Real_Time_Clock_Counter, \ erc32_counter_difference \ ); \ - rtems_counter_initialize_converter(1000000); \ + rtems_counter_initialize_converter( frequency ); \ } while (0) +#define Clock_driver_timecounter_tick() erc32_tc_tick() + #define Clock_driver_support_shutdown_hardware() \ do { \ ERC32_Mask_interrupt( ERC32_INTERRUPT_REAL_TIME_CLOCK ); \ diff --git a/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c b/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c index ab4efa0e8a..3dd68e080a 100644 --- a/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c +++ b/c/src/lib/libbsp/sparc/leon2/clock/ckinit.c @@ -24,11 +24,38 @@ #include #include +#include #if SIMSPARC_FAST_IDLE==1 #define CLOCK_DRIVER_USE_FAST_IDLE 1 #endif +static rtems_timecounter_simple leon2_tc; + +static uint32_t leon2_tc_get( rtems_timecounter_simple *tc ) +{ + return LEON_REG.Timer_Counter_1; +} + +static bool leon2_tc_is_pending( rtems_timecounter_simple *tc ) +{ + return LEON_Is_interrupt_pending( LEON_INTERRUPT_TIMER1 ); +} + +static uint32_t leon2_tc_get_timecount( struct timecounter *tc ) +{ + return rtems_timecounter_simple_downcounter_get( + tc, + leon2_tc_get, + leon2_tc_is_pending + ); +} + +static void leon2_tc_tick( void ) +{ + rtems_timecounter_simple_downcounter_tick( &leon2_tc, leon2_tc_get ); +} + /* * The Real Time Clock Counter Timer uses this trap type. */ @@ -54,6 +81,12 @@ extern int CLOCK_SPEED; LEON_REG_TIMER_COUNTER_RELOAD_AT_ZERO | \ LEON_REG_TIMER_COUNTER_LOAD_COUNTER \ ); \ + rtems_timecounter_simple_install( \ + &leon2_tc, \ + 1000000, \ + rtems_configuration_get_microseconds_per_tick(), \ + leon2_tc_get_timecount \ + ); \ } while (0) #define Clock_driver_support_shutdown_hardware() \ @@ -62,23 +95,6 @@ extern int CLOCK_SPEED; LEON_REG.Timer_Control_1 = 0; \ } while (0) -static uint32_t bsp_clock_nanoseconds_since_last_tick(void) -{ - uint32_t clicks; - uint32_t usecs; - - clicks = LEON_REG.Timer_Counter_1; - - if ( LEON_Is_interrupt_pending( LEON_INTERRUPT_TIMER1 ) ) { - clicks = LEON_REG.Timer_Counter_1; - usecs = (2*rtems_configuration_get_microseconds_per_tick() - clicks); - } else { - usecs = (rtems_configuration_get_microseconds_per_tick() - clicks); - } - return usecs * 1000; -} - -#define Clock_driver_nanoseconds_since_last_tick \ - bsp_clock_nanoseconds_since_last_tick +#define Clock_driver_timecounter_tick() leon2_tc_tick() #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c b/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c index ad226161bc..b82b457866 100644 --- a/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c +++ b/c/src/lib/libbsp/sparc/leon3/clock/ckinit.c @@ -24,6 +24,7 @@ #include #include #include +#include /* The LEON3 BSP Timer driver can rely on the Driver Manager if the * DrvMgr is initialized during startup. Otherwise the classic driver @@ -40,6 +41,43 @@ /* LEON3 Timer system interrupt number */ static int clkirq; +static bool leon3_tc_use_irqmp; + +static rtems_timecounter_simple leon3_tc; + +static uint32_t leon3_tc_get(rtems_timecounter_simple *tc) +{ + return LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].value; +} + +static bool leon3_tc_is_pending(rtems_timecounter_simple *tc) +{ + return LEON_Is_interrupt_pending(clkirq); +} + +static uint32_t leon3_tc_get_timecount(struct timecounter *tc) +{ + return rtems_timecounter_simple_downcounter_get( + tc, + leon3_tc_get, + leon3_tc_is_pending + ); +} + +static uint32_t leon3_tc_get_timecount_irqmp(struct timecounter *tc) +{ + return LEON3_IrqCtrl_Regs->timestamp[0].counter; +} + +static void leon3_tc_tick(void) +{ + if (leon3_tc_use_irqmp) { + rtems_timecounter_tick(); + } else { + rtems_timecounter_simple_downcounter_tick(&leon3_tc, leon3_tc_get); + } +} + static void leon3_clock_profiling_interrupt_delay(void) { #ifdef RTEMS_PROFILING @@ -112,15 +150,36 @@ static void bsp_clock_handler_install(rtems_isr *new) } } +static void leon3_clock_initialize(void) +{ + volatile struct irqmp_timestamp_regs *irqmp_ts = + &LEON3_IrqCtrl_Regs->timestamp[0]; + + LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].reload = + rtems_configuration_get_microseconds_per_tick() - 1; + LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].ctrl = + GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_RS | + GPTIMER_TIMER_CTRL_LD | GPTIMER_TIMER_CTRL_IE; + + if (leon3_irqmp_has_timestamp(irqmp_ts)) { + leon3_tc.tc.tc_get_timecount = leon3_tc_get_timecount_irqmp; + 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_use_irqmp = true; + rtems_timecounter_install(&leon3_tc.tc); + } else { + rtems_timecounter_simple_install( + &leon3_tc, + LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER, + rtems_configuration_get_microseconds_per_tick(), + leon3_tc_get_timecount + ); + } +} + #define Clock_driver_support_initialize_hardware() \ - do { \ - LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].reload = \ - rtems_configuration_get_microseconds_per_tick() - 1; \ - \ - LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].ctrl = \ - GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_RS | \ - GPTIMER_TIMER_CTRL_LD | GPTIMER_TIMER_CTRL_IE; \ - } while (0) + leon3_clock_initialize() #define Clock_driver_support_shutdown_hardware() \ do { \ @@ -128,27 +187,7 @@ static void bsp_clock_handler_install(rtems_isr *new) LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].ctrl = 0; \ } while (0) -static uint32_t bsp_clock_nanoseconds_since_last_tick(void) -{ - uint32_t clicks; - uint32_t usecs; - - if ( !LEON3_Timer_Regs ) - return 0; - - clicks = LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].value; - - if ( LEON_Is_interrupt_pending( clkirq ) ) { - clicks = LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].value; - usecs = (2*rtems_configuration_get_microseconds_per_tick() - clicks); - } else { - usecs = (rtems_configuration_get_microseconds_per_tick() - clicks); - } - return usecs * 1000; -} - -#define Clock_driver_nanoseconds_since_last_tick \ - bsp_clock_nanoseconds_since_last_tick +#define Clock_driver_timecounter_tick() leon3_tc_tick() #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/sparc64/shared/clock/ckinit.c b/c/src/lib/libbsp/sparc64/shared/clock/ckinit.c index a3f9450174..ff0464c8f2 100644 --- a/c/src/lib/libbsp/sparc64/shared/clock/ckinit.c +++ b/c/src/lib/libbsp/sparc64/shared/clock/ckinit.c @@ -114,5 +114,7 @@ static void Clock_driver_support_initialize_hardware(void) \ } while ( 0 ) +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libcpu/arm/at91rm9200/clock/clock.c b/c/src/lib/libcpu/arm/at91rm9200/clock/clock.c index 16cf145b37..42b85f3f98 100644 --- a/c/src/lib/libcpu/arm/at91rm9200/clock/clock.c +++ b/c/src/lib/libcpu/arm/at91rm9200/clock/clock.c @@ -22,8 +22,6 @@ #include #include -static unsigned long st_pimr_reload; - /** * Enables clock interrupt. * @@ -77,17 +75,16 @@ rtems_irq_connect_data clock_isr_data = { BSP_install_rtems_irq_handler(&clock_isr_data); \ } while(0) -uint16_t st_pimr_value; static void Clock_driver_support_initialize_hardware(void) { uint32_t st_str; int slck; + unsigned long value; /* the system timer is driven from SLCK */ slck = at91rm9200_get_slck(); - st_pimr_value = (((rtems_configuration_get_microseconds_per_tick() * slck) + + value = (((rtems_configuration_get_microseconds_per_tick() * slck) + (1000000/2))/ 1000000); - st_pimr_reload = st_pimr_value; /* read the status to clear the int */ st_str = ST_REG(ST_SR); @@ -97,21 +94,9 @@ static void Clock_driver_support_initialize_hardware(void) AIC_SMR_REG(AIC_SMR_SYSIRQ) = AIC_SMR_PRIOR(0x7); /* set the timer value */ - ST_REG(ST_PIMR) = st_pimr_reload; + ST_REG(ST_PIMR) = value; } -static uint32_t bsp_clock_nanoseconds_since_last_tick(void) -{ - uint16_t slck_counts; - - slck_counts = st_pimr_value - st_pimr_reload; - return (rtems_configuration_get_microseconds_per_tick() * slck_counts * 1000) - / st_pimr_value; -} - -#define Clock_driver_nanoseconds_since_last_tick \ - bsp_clock_nanoseconds_since_last_tick - #define Clock_driver_support_at_tick() \ do { \ uint32_t st_str; \ @@ -126,4 +111,6 @@ static void Clock_driver_support_shutdown_hardware( void ) BSP_remove_rtems_irq_handler(&clock_isr_data); } +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../../libbsp/shared/clockdrv_shell.h" diff --git a/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c b/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c index 02f5b8c5ea..e75fed8a9e 100644 --- a/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c +++ b/c/src/lib/libcpu/arm/lpc22xx/clock/clockdrv.c @@ -17,12 +17,39 @@ #include #include #include /* for printk */ +#include void Clock_isr(rtems_irq_hdl_param arg); static void clock_isr_on(const rtems_irq_connect_data *unused); static void clock_isr_off(const rtems_irq_connect_data *unused); static int clock_isr_is_on(const rtems_irq_connect_data *irq); +static rtems_timecounter_simple lpc22xx_tc; + +static uint32_t lpc22xx_tc_get(rtems_timecounter_simple *tc) +{ + return T0TC; +} + +static bool lpc22xx_tc_is_pending(rtems_timecounter_simple *tc) +{ + return (T0IR & 0x1) != 0; +} + +static uint32_t lpc22xx_tc_get_timecount(struct timecounter *tc) +{ + return rtems_timecounter_simple_upcounter_get( + tc, + lpc22xx_tc_get, + lpc22xx_tc_is_pending + ); +} + +static void lpc22xx_tc_tick(void) +{ + rtems_timecounter_simple_upcounter_tick(&lpc22xx_tc, lpc22xx_tc_get); +} + /* Replace the first value with the clock's interrupt name. */ rtems_irq_connect_data clock_isr_data = { .name = LPC22xx_INTERRUPT_TIMER0, @@ -74,9 +101,10 @@ rtems_irq_connect_data clock_isr_data = { */ #define Clock_driver_support_initialize_hardware() \ do { \ + uint32_t mask; \ /* disable and clear timer 0, set to */ \ T0TCR &= 0; \ - /* TC is incrementet on every pclk.*/ \ + /* TC is incremented on every pclk.*/ \ T0PC = 0; \ /* initialize the timer period and prescaler */ \ T0MR0 = ((LPC22xx_Fpclk/1000 * \ @@ -89,6 +117,13 @@ rtems_irq_connect_data clock_isr_data = { T0TCR = 1; \ /* enable interrupt, skyeye will check this*/ \ T0IR |= 0x01; \ + /* install timecounter */ \ + rtems_timecounter_simple_install( \ + &lpc22xx_tc, \ + LPC22xx_Fpclk, \ + T0MR0, \ + lpc22xx_tc_get_timecount \ + ); \ } while (0) /** @@ -104,20 +139,6 @@ rtems_irq_connect_data clock_isr_data = { BSP_remove_rtems_irq_handler(&clock_isr_data); \ } while (0) -static uint32_t bsp_clock_nanoseconds_since_last_tick(void) -{ - uint32_t clicks; - uint32_t microseconds; - - clicks = T0TC; /* T0TC is the 32bit time counter 0 */ - - microseconds = (rtems_configuration_get_microseconds_per_tick() - clicks); - return microseconds * 1000; -} - -#define Clock_driver_nanoseconds_since_last_tick \ - bsp_clock_nanoseconds_since_last_tick - /** * Enables clock interrupt. * @@ -149,6 +170,8 @@ static int clock_isr_is_on(const rtems_irq_connect_data *irq) return T0IR & 0x01; /* MR0 mask */ } +#define Clock_driver_timecounter_tick() lpc22xx_tc_tick() + /* Make sure to include this, and only at the end of the file */ #include "../../../../libbsp/shared/clockdrv_shell.h" diff --git a/c/src/lib/libcpu/arm/mc9328mxl/clock/clockdrv.c b/c/src/lib/libcpu/arm/mc9328mxl/clock/clockdrv.c index 0c3ab5dd93..d5dc69c9a0 100644 --- a/c/src/lib/libcpu/arm/mc9328mxl/clock/clockdrv.c +++ b/c/src/lib/libcpu/arm/mc9328mxl/clock/clockdrv.c @@ -130,5 +130,8 @@ static int clock_isr_is_on(const rtems_irq_connect_data *irq) return MC9328MXL_TMR1_TCTL & MC9328MXL_TMR_TCTL_IRQEN; } +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + /* Make sure to include this, and only at the end of the file */ + #include "../../../../libbsp/shared/clockdrv_shell.h" diff --git a/c/src/lib/libcpu/arm/pxa255/clock/clock.c b/c/src/lib/libcpu/arm/pxa255/clock/clock.c index 92d9b21d2b..69b684926c 100644 --- a/c/src/lib/libcpu/arm/pxa255/clock/clock.c +++ b/c/src/lib/libcpu/arm/pxa255/clock/clock.c @@ -116,4 +116,6 @@ static void Clock_driver_support_shutdown_hardware( void ) BSP_remove_rtems_irq_handler(&clock_isr_data); } +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + #include "../../../../libbsp/shared/clockdrv_shell.h" diff --git a/c/src/lib/libcpu/arm/s3c24xx/clock/clockdrv.c b/c/src/lib/libcpu/arm/s3c24xx/clock/clockdrv.c index 519d3f850d..a92dc607a3 100644 --- a/c/src/lib/libcpu/arm/s3c24xx/clock/clockdrv.c +++ b/c/src/lib/libcpu/arm/s3c24xx/clock/clockdrv.c @@ -27,17 +27,6 @@ rtems_irq_connect_data clock_isr_data = { .isOn = clock_isr_is_on, }; -/** - * Return the nanoseconds since last tick - */ -static uint32_t clock_driver_get_nanoseconds_since_last_tick(void) -{ - return 0; -} - -#define Clock_driver_nanoseconds_since_last_tick \ - clock_driver_get_nanoseconds_since_last_tick - /** * When we get the clock interrupt * - clear the interrupt bit? @@ -74,6 +63,7 @@ static uint32_t clock_driver_get_nanoseconds_since_last_tick(void) do { \ uint32_t cr; \ uint32_t freq; \ + uint32_t mask; \ /* set MUX for Timer4 to 1/16 */ \ cr=rTCFG1 & 0xFFF0FFFF; \ rTCFG1=(cr | (3<<16)); \ @@ -131,5 +121,7 @@ static int clock_isr_is_on(const rtems_irq_connect_data *irq) return 1; } +#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER + /* Make sure to include this, and only at the end of the file */ #include "../../../../libbsp/shared/clockdrv_shell.h" diff --git a/c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c b/c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c index 218828cf4a..41b10cb30d 100644 --- a/c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c +++ b/c/src/lib/libcpu/powerpc/mpc6xx/clock/c_clock.c @@ -29,6 +29,7 @@ #include #include /* for printk() */ #include +#include #include /* for CLOCK_DRIVER_USE_FAST_IDLE */ @@ -48,11 +49,12 @@ volatile uint32_t Clock_driver_ticks; */ static uint32_t Clock_Decrementer_value; -/* - * This is the value by which elapsed count down timer ticks are multiplied to - * give an elapsed duration in nanoseconds, left-shifted by 32 bits - */ -static uint64_t Clock_Decrementer_reference; +static struct timecounter Clock_TC; + +static uint32_t Clock_Get_timecount(struct timecounter *tc) +{ + return ppc_time_base(); +} void clockOff(void* unused) { @@ -94,16 +96,27 @@ void clockOn(void* unused) static void clockHandler(void) { #if (CLOCK_DRIVER_USE_FAST_IDLE == 1) - do { - rtems_clock_tick(); - } while ( + rtems_interrupt_level level; + uint32_t tb; + + rtems_interrupt_disable(level); + + tb = ppc_time_base(); + rtems_timecounter_tick(); + + while ( _Thread_Heir == _Thread_Executing && _Thread_Executing->Start.entry_point == (Thread_Entry) rtems_configuration_get_idle_task() - ); + ) { + tb += Clock_Decrementer_value; + ppc_set_time_base( tb ); + rtems_timecounter_tick(); + } + rtems_interrupt_enable(level); #else - rtems_clock_tick(); + rtems_timecounter_tick(); #endif } @@ -141,7 +154,6 @@ void clockIsr(void *unused) rtems_interrupt_enable(flags); Clock_driver_ticks += 1; - /* * Real Time Clock counter/timer is set to automatically reload. */ @@ -187,7 +199,6 @@ int clockIsOn(void* unused) return 0; } - /* * Clock_exit * @@ -199,53 +210,6 @@ void Clock_exit( void ) (void) BSP_disconnect_clock_handler (); } -static uint32_t Clock_driver_nanoseconds_since_last_tick(void) -{ - uint32_t clicks, tmp; - - PPC_Get_decrementer( clicks ); - - /* - * Multiply by 1000 here separately from below so we do not overflow - * and get a negative value. - */ - tmp = (Clock_Decrementer_value - clicks) * 1000; - tmp /= (BSP_bus_frequency/BSP_time_base_divisor); - - return tmp * 1000; -} - -static uint32_t Clock_driver_nanoseconds_since_last_tick_bookE(void) -{ - uint32_t clicks; - uint64_t c; - - PPC_Get_decrementer( clicks ); - c = Clock_Decrementer_value - clicks; - - /* - * Check whether a clock tick interrupt is pending and hence that the - * decrementer's wrapped. If it has, we'll compensate by returning a time one - * tick period longer. - * - * We have to check interrupt status after reading the decrementer. If we - * don't, we may miss an interrupt and read a wrapped decrementer value - * without compensating for it - */ - if ( _read_BOOKE_TSR() & BOOKE_TSR_DIS ) - { - /* - * Re-read the decrementer: The tick interrupt may have been - * generated and the decrementer wrapped during the time since we - * last read it and the time we checked the interrupt status - */ - PPC_Get_decrementer( clicks ); - c = (Clock_Decrementer_value - clicks) + Clock_Decrementer_value; - } - - return (uint32_t)((c * Clock_Decrementer_reference) >> 32); -} - /* * Clock_initialize * @@ -262,9 +226,6 @@ rtems_device_driver Clock_initialize( Clock_Decrementer_value = (BSP_bus_frequency/BSP_time_base_divisor)* rtems_configuration_get_milliseconds_per_tick(); - Clock_Decrementer_reference = ((uint64_t)1000000U<<32)/ - (BSP_bus_frequency/BSP_time_base_divisor); - /* set the decrementer now, prior to installing the handler * so no interrupts will happen in a while. */ @@ -283,24 +244,14 @@ rtems_device_driver Clock_initialize( _write_BOOKE_TCR(tcr); rtems_interrupt_enable(l); - - /* - * Set the nanoseconds since last tick handler - */ - rtems_clock_set_nanoseconds_extension( - Clock_driver_nanoseconds_since_last_tick_bookE - ); - } - else - { - /* - * Set the nanoseconds since last tick handler - */ - rtems_clock_set_nanoseconds_extension( - Clock_driver_nanoseconds_since_last_tick - ); } + Clock_TC.tc_get_timecount = Clock_Get_timecount; + Clock_TC.tc_counter_mask = 0xffffffff; + Clock_TC.tc_frequency = (1000 * BSP_bus_frequency) / BSP_time_base_divisor; + Clock_TC.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(&Clock_TC); + /* * If a decrementer exception was pending, it is cleared by * executing the default (nop) handler at this point; -- cgit v1.2.3