diff options
-rw-r--r-- | bsps/or1k/generic_or1k/clock/clockdrv.c | 8 | ||||
-rw-r--r-- | bsps/shared/dev/cpucounter/cpucounterdiff.c | 23 | ||||
-rw-r--r-- | bsps/sparc/erc32/clock/ckinit.c | 138 | ||||
-rw-r--r-- | bsps/sparc/leon2/clock/ckinit.c | 93 | ||||
-rw-r--r-- | bsps/sparc/leon3/clock/ckinit.c | 126 | ||||
-rw-r--r-- | bsps/sparc/leon3/include/leon.h | 6 | ||||
-rw-r--r-- | bsps/sparc/leon3/start/cpucounter.c | 32 | ||||
-rw-r--r-- | c/src/lib/libbsp/sparc/leon2/Makefile.am | 1 | ||||
-rw-r--r-- | cpukit/Makefile.am | 1 | ||||
-rw-r--r-- | cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h | 7 | ||||
-rw-r--r-- | cpukit/score/cpu/or1k/include/rtems/score/cpu.h | 7 | ||||
-rw-r--r-- | cpukit/score/cpu/sparc/include/rtems/score/cpu.h | 23 | ||||
-rw-r--r-- | cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h | 61 | ||||
-rw-r--r-- | cpukit/score/cpu/sparc/sparc-counter-asm.S | 105 | ||||
-rw-r--r-- | cpukit/score/cpu/sparc/sparc-counter.c | 48 |
15 files changed, 332 insertions, 347 deletions
diff --git a/bsps/or1k/generic_or1k/clock/clockdrv.c b/bsps/or1k/generic_or1k/clock/clockdrv.c index 44365aa02c..7b8a07fd3d 100644 --- a/bsps/or1k/generic_or1k/clock/clockdrv.c +++ b/bsps/or1k/generic_or1k/clock/clockdrv.c @@ -109,14 +109,6 @@ static void generic_or1k_clock_initialize(void) rtems_timecounter_install(&or1ksim_tc); } -CPU_Counter_ticks _CPU_Counter_difference( - CPU_Counter_ticks second, - CPU_Counter_ticks first -) -{ - return second - first; -} - #define Clock_driver_support_at_tick() generic_or1k_clock_at_tick() #define Clock_driver_support_initialize_hardware() generic_or1k_clock_initialize() diff --git a/bsps/shared/dev/cpucounter/cpucounterdiff.c b/bsps/shared/dev/cpucounter/cpucounterdiff.c deleted file mode 100644 index d77945d5b8..0000000000 --- a/bsps/shared/dev/cpucounter/cpucounterdiff.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2014 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * <rtems@embedded-brains.de> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include <rtems/score/cpu.h> - -CPU_Counter_ticks _CPU_Counter_difference( - CPU_Counter_ticks second, - CPU_Counter_ticks first -) -{ - return second - first; -} diff --git a/bsps/sparc/erc32/clock/ckinit.c b/bsps/sparc/erc32/clock/ckinit.c index e7c5b07f33..6d6a335fed 100644 --- a/bsps/sparc/erc32/clock/ckinit.c +++ b/bsps/sparc/erc32/clock/ckinit.c @@ -24,103 +24,97 @@ #include <bsp.h> #include <bspopts.h> -#include <rtems/counter.h> +#include <rtems/sysinit.h> #include <rtems/timecounter.h> #include <rtems/score/sparcimpl.h> -#define ERC32_REAL_TIME_CLOCK_FREQUENCY 1000000 - -/* - * The Real Time Clock Counter Timer uses this trap type. - */ -#define CLOCK_VECTOR ERC32_TRAP_TYPE( ERC32_INTERRUPT_REAL_TIME_CLOCK ) - -#define Clock_driver_support_install_isr( _new ) \ - set_vector( _new, CLOCK_VECTOR, 1 ) - -#define Clock_driver_support_set_interrupt_affinity( _online_processors ) \ - do { \ - (void) _online_processors; \ - } while (0) - extern int CLOCK_SPEED; -static rtems_timecounter_simple erc32_tc; +#define ERC32_REAL_TIME_CLOCK_FREQUENCY 1000000 -static uint32_t erc32_tc_get( rtems_timecounter_simple *tc ) -{ - return ERC32_MEC.Real_Time_Clock_Counter; -} +static struct timecounter erc32_tc; -static bool erc32_tc_is_pending( rtems_timecounter_simple *tc ) +static void erc32_clock_init( void ) { - return ERC32_Is_interrupt_pending( ERC32_INTERRUPT_REAL_TIME_CLOCK ); + struct timecounter *tc; + + tc = &erc32_tc; + tc->tc_get_timecount = _SPARC_Get_timecount_clock; + tc->tc_counter_mask = 0xffffffff; + tc->tc_frequency = ERC32_REAL_TIME_CLOCK_FREQUENCY; + tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(tc); } -static uint32_t erc32_tc_get_timecount( struct timecounter *tc ) +uint32_t _CPU_Counter_frequency(void) { - return rtems_timecounter_simple_downcounter_get( - tc, - erc32_tc_get, - erc32_tc_is_pending - ); + return ERC32_REAL_TIME_CLOCK_FREQUENCY; } -static void erc32_tc_at_tick( rtems_timecounter_simple *tc ) +static void erc32_clock_at_tick( void ) { - /* Nothing to do */ -} + SPARC_Counter *counter; + rtems_interrupt_level level; -static void erc32_tc_tick( void ) -{ - rtems_timecounter_simple_downcounter_tick( - &erc32_tc, - erc32_tc_get, - erc32_tc_at_tick - ); + counter = &_SPARC_Counter_mutable; + rtems_interrupt_local_disable(level); + + ERC32_Clear_interrupt( ERC32_INTERRUPT_REAL_TIME_CLOCK ); + counter->accumulated += counter->interval; + + rtems_interrupt_local_enable(level); } -static void erc32_counter_initialize( void ) +static void erc32_clock_initialize_early( void ) { - _SPARC_Counter_initialize( - _SPARC_Counter_read_address, - _SPARC_Counter_difference_clock_period, - &ERC32_MEC.Real_Time_Clock_Counter + SPARC_Counter *counter; + + /* approximately 1 us per countdown */ + ERC32_MEC.Real_Time_Clock_Scalar = CLOCK_SPEED - 1; + ERC32_MEC.Real_Time_Clock_Counter = + rtems_configuration_get_microseconds_per_tick(); + ERC32_MEC_Set_Real_Time_Clock_Timer_Control( + ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING | + ERC32_MEC_TIMER_COUNTER_LOAD_SCALER | + ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER + ); + ERC32_MEC_Set_Real_Time_Clock_Timer_Control( + ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING | + ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO ); -} -uint32_t _CPU_Counter_frequency(void) -{ - return ERC32_REAL_TIME_CLOCK_FREQUENCY; + counter = &_SPARC_Counter_mutable; + counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled; + counter->read = _SPARC_Counter_read_clock; + counter->counter_register = &ERC32_MEC.Real_Time_Clock_Counter, + counter->pending_register = &ERC32_MEC.Interrupt_Pending; + counter->pending_mask = UINT32_C(1) << ERC32_INTERRUPT_REAL_TIME_CLOCK; + counter->accumulated = rtems_configuration_get_microseconds_per_tick(); + counter->interval = rtems_configuration_get_microseconds_per_tick(); } -#define Clock_driver_support_initialize_hardware() \ +RTEMS_SYSINIT_ITEM( + erc32_clock_initialize_early, + RTEMS_SYSINIT_CPU_COUNTER, + RTEMS_SYSINIT_ORDER_FIRST +); + +/* + * The Real Time Clock Counter Timer uses this trap type. + */ +#define CLOCK_VECTOR ERC32_TRAP_TYPE( ERC32_INTERRUPT_REAL_TIME_CLOCK ) + +#define Clock_driver_support_install_isr( _new ) \ + set_vector( _new, CLOCK_VECTOR, 1 ) + +#define Clock_driver_support_set_interrupt_affinity( _online_processors ) \ do { \ - /* approximately 1 us per countdown */ \ - ERC32_MEC.Real_Time_Clock_Scalar = CLOCK_SPEED - 1; \ - ERC32_MEC.Real_Time_Clock_Counter = \ - rtems_configuration_get_microseconds_per_tick(); \ - \ - ERC32_MEC_Set_Real_Time_Clock_Timer_Control( \ - ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING | \ - ERC32_MEC_TIMER_COUNTER_LOAD_SCALER | \ - ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER \ - ); \ - \ - 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, \ - ERC32_REAL_TIME_CLOCK_FREQUENCY, \ - rtems_configuration_get_microseconds_per_tick(), \ - erc32_tc_get_timecount \ - ); \ - erc32_counter_initialize(); \ + (void) _online_processors; \ } while (0) -#define Clock_driver_timecounter_tick() erc32_tc_tick() +#define Clock_driver_support_at_tick() erc32_clock_at_tick() + +#define Clock_driver_support_initialize_hardware() erc32_clock_init() #include "../../../shared/dev/clock/clockimpl.h" diff --git a/bsps/sparc/leon2/clock/ckinit.c b/bsps/sparc/leon2/clock/ckinit.c index f622975832..2707c7daa2 100644 --- a/bsps/sparc/leon2/clock/ckinit.c +++ b/bsps/sparc/leon2/clock/ckinit.c @@ -24,42 +24,73 @@ #include <bsp.h> #include <bspopts.h> +#include <rtems/sysinit.h> #include <rtems/timecounter.h> #include <rtems/score/sparcimpl.h> -static rtems_timecounter_simple leon2_tc; +extern int CLOCK_SPEED; + +#define LEON2_TIMER_1_FREQUENCY 1000000 + +static struct timecounter leon2_tc; -static uint32_t leon2_tc_get( rtems_timecounter_simple *tc ) +static void leon2_clock_init( void ) { - return LEON_REG.Timer_Counter_1; + struct timecounter *tc; + + tc = &leon2_tc; + tc->tc_get_timecount = _SPARC_Get_timecount_clock; + tc->tc_counter_mask = 0xffffffff; + tc->tc_frequency = LEON2_TIMER_1_FREQUENCY; + tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(tc); } -static bool leon2_tc_is_pending( rtems_timecounter_simple *tc ) +static void leon2_clock_at_tick( void ) { - return LEON_Is_interrupt_pending( LEON_INTERRUPT_TIMER1 ); + SPARC_Counter *counter; + rtems_interrupt_level level; + + counter = &_SPARC_Counter_mutable; + rtems_interrupt_local_disable(level); + + LEON_Clear_interrupt( LEON_INTERRUPT_TIMER1 ); + counter->accumulated += counter->interval; + + rtems_interrupt_local_enable(level); } -static uint32_t leon2_tc_get_timecount( struct timecounter *tc ) +static void leon2_clock_initialize_early( void ) { - return rtems_timecounter_simple_downcounter_get( - tc, - leon2_tc_get, - leon2_tc_is_pending + SPARC_Counter *counter; + + LEON_REG.Timer_Reload_1 = + rtems_configuration_get_microseconds_per_tick() - 1; + LEON_REG.Timer_Control_1 = ( + LEON_REG_TIMER_COUNTER_ENABLE_COUNTING | + LEON_REG_TIMER_COUNTER_RELOAD_AT_ZERO | + LEON_REG_TIMER_COUNTER_LOAD_COUNTER ); -} -static void leon2_tc_at_tick( rtems_timecounter_simple *tc ) -{ - /* Nothing to do */ + counter = &_SPARC_Counter_mutable; + counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled; + counter->read = _SPARC_Counter_read_clock; + counter->counter_register = &LEON_REG.Timer_Counter_1; + counter->pending_register = &LEON_REG.Interrupt_Pending; + counter->pending_mask = UINT32_C(1) << LEON_INTERRUPT_TIMER1; + counter->accumulated = rtems_configuration_get_microseconds_per_tick(); + counter->interval = rtems_configuration_get_microseconds_per_tick(); } -static void leon2_tc_tick( void ) +RTEMS_SYSINIT_ITEM( + leon2_clock_initialize_early, + RTEMS_SYSINIT_CPU_COUNTER, + RTEMS_SYSINIT_ORDER_FIRST +); + +uint32_t _CPU_Counter_frequency(void) { - rtems_timecounter_simple_downcounter_tick( - &leon2_tc, - leon2_tc_get, - leon2_tc_at_tick - ); + return LEON2_TIMER_1_FREQUENCY; } /* @@ -71,27 +102,9 @@ static void leon2_tc_tick( void ) #define Clock_driver_support_install_isr( _new ) \ set_vector( _new, CLOCK_VECTOR, 1 ) -extern int CLOCK_SPEED; +#define Clock_driver_support_at_tick() leon2_clock_at_tick() -#define Clock_driver_support_initialize_hardware() \ - do { \ - LEON_REG.Timer_Reload_1 = \ - rtems_configuration_get_microseconds_per_tick() - 1; \ - \ - LEON_REG.Timer_Control_1 = ( \ - LEON_REG_TIMER_COUNTER_ENABLE_COUNTING | \ - 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_timecounter_tick() leon2_tc_tick() +#define Clock_driver_support_initialize_hardware() leon2_clock_init() #include "../../../shared/dev/clock/clockimpl.h" diff --git a/bsps/sparc/leon3/clock/ckinit.c b/bsps/sparc/leon3/clock/ckinit.c index 0cd78ea716..fecbf32c1b 100644 --- a/bsps/sparc/leon3/clock/ckinit.c +++ b/bsps/sparc/leon3/clock/ckinit.c @@ -27,6 +27,7 @@ #include <rtems/rtems/intr.h> #include <ambapp.h> #include <rtems/score/profiling.h> +#include <rtems/score/sparcimpl.h> #include <rtems/timecounter.h> /* The LEON3 BSP Timer driver can rely on the Driver Manager if the @@ -42,59 +43,7 @@ static int clkirq; static void (*leon3_tc_tick)(void); -static rtems_timecounter_simple leon3_tc; - -#ifndef RTEMS_SMP -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 void leon3_tc_at_tick( rtems_timecounter_simple *tc ) -{ - /* Nothing to do */ -} - -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 void leon3_tc_tick_simple(void) -{ - rtems_timecounter_simple_downcounter_tick( - &leon3_tc, - leon3_tc_get, - leon3_tc_at_tick - ); -} -#endif - -static uint32_t leon3_tc_get_timecount_up_counter(struct timecounter *tc) -{ - return leon3_up_counter_low(); -} - -static uint32_t leon3_tc_get_timecount_irqmp(struct timecounter *tc) -{ - return LEON3_IrqCtrl_Regs->timestamp[0].counter; -} - -#ifdef RTEMS_SMP -static uint32_t leon3_tc_get_timecount_second_timer(struct timecounter *tc) -{ - return 0xffffffff - LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX + 1].value; -} -#endif +static struct timecounter leon3_tc; #ifdef RTEMS_PROFILING #define IRQMP_TIMESTAMP_S1_S2 ((1U << 25) | (1U << 26)) @@ -146,12 +95,23 @@ static void leon3_tc_tick_irqmp_timestamp_init(void) rtems_timecounter_tick(); } -#ifdef RTEMS_SMP -static void leon3_tc_tick_second_timer(void) +static void leon3_tc_tick_default(void) { +#ifndef RTEMS_SMP + SPARC_Counter *counter; + rtems_interrupt_level level; + + counter = &_SPARC_Counter_mutable; + rtems_interrupt_local_disable(level); + + LEON3_IrqCtrl_Regs->iclear = counter->pending_mask; + counter->accumulated += counter->interval; + + rtems_interrupt_local_enable(level); +#endif + rtems_timecounter_tick(); } -#endif static void leon3_tc_do_tick(void) { @@ -196,9 +156,11 @@ static void leon3_clock_initialize(void) { volatile struct irqmp_timestamp_regs *irqmp_ts; volatile struct gptimer_regs *gpt; + struct timecounter *tc; irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0]; gpt = LEON3_Timer_Regs; + tc = &leon3_tc; gpt->timer[LEON3_CLOCK_INDEX].reload = rtems_configuration_get_microseconds_per_tick() - 1; @@ -210,10 +172,8 @@ static void leon3_clock_initialize(void) if (leon3_up_counter_is_available()) { /* Use the LEON4 up-counter if available */ - leon3_tc.tc.tc_get_timecount = leon3_tc_get_timecount_up_counter; - leon3_tc.tc.tc_counter_mask = 0xffffffff; - leon3_tc.tc.tc_frequency = leon3_up_counter_frequency(); - leon3_tc.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + tc->tc_get_timecount = _SPARC_Get_timecount_asr23; + tc->tc_frequency = leon3_up_counter_frequency(); #ifdef RTEMS_PROFILING if (!leon3_irqmp_has_timestamp(irqmp_ts)) { @@ -222,13 +182,11 @@ static void leon3_clock_initialize(void) #endif leon3_tc_tick = leon3_tc_tick_irqmp_timestamp_init; - rtems_timecounter_install(&leon3_tc.tc); } else if (leon3_irqmp_has_timestamp(irqmp_ts)) { /* Use the interrupt controller timestamp counter if available */ - 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; + tc->tc_get_timecount = _SPARC_Get_timecount_up; + tc->tc_frequency = ambapp_freq_get(&ambapp_plb, LEON3_Timer_Adev); + leon3_tc_tick = leon3_tc_tick_irqmp_timestamp_init; /* @@ -236,8 +194,6 @@ static void leon3_clock_initialize(void) * counter. Use an arbitrary interrupt source. */ irqmp_ts->control = 0x1; - - rtems_timecounter_install(&leon3_tc.tc); } else { #ifdef RTEMS_SMP /* @@ -245,24 +201,32 @@ static void leon3_clock_initialize(void) * controller. At least on SMP configurations we must use a second timer * in free running mode for the timecounter. */ - gpt->timer[LEON3_CLOCK_INDEX + 1].ctrl = + gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].ctrl = GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_IE; - leon3_tc.tc.tc_get_timecount = leon3_tc_get_timecount_second_timer; - leon3_tc.tc.tc_counter_mask = 0xffffffff; - leon3_tc.tc.tc_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER; - leon3_tc.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; - leon3_tc_tick = leon3_tc_tick_second_timer; - rtems_timecounter_install(&leon3_tc.tc); + + tc->tc_get_timecount = _SPARC_Get_timecount_down; #else - leon3_tc_tick = leon3_tc_tick_simple; - rtems_timecounter_simple_install( - &leon3_tc, - LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER, - rtems_configuration_get_microseconds_per_tick(), - leon3_tc_get_timecount - ); + SPARC_Counter *counter; + + counter = &_SPARC_Counter_mutable; + counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled; + counter->read = _SPARC_Counter_read_clock; + counter->counter_register = &gpt->timer[LEON3_CLOCK_INDEX].value; + counter->pending_register = &LEON3_IrqCtrl_Regs->ipend; + counter->pending_mask = UINT32_C(1) << clkirq; + counter->accumulated = rtems_configuration_get_microseconds_per_tick(); + counter->interval = rtems_configuration_get_microseconds_per_tick(); + + tc->tc_get_timecount = _SPARC_Get_timecount_clock; #endif + + tc->tc_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER, + leon3_tc_tick = leon3_tc_tick_default; } + + tc->tc_counter_mask = 0xffffffff; + tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(tc); } #define Clock_driver_support_initialize_hardware() \ diff --git a/bsps/sparc/leon3/include/leon.h b/bsps/sparc/leon3/include/leon.h index 758b760b0b..afe0d91ca4 100644 --- a/bsps/sparc/leon3/include/leon.h +++ b/bsps/sparc/leon3/include/leon.h @@ -333,6 +333,12 @@ extern rtems_interrupt_lock LEON3_IrqCtrl_Lock; #define LEON3_CLOCK_INDEX 0 #endif +#if defined(RTEMS_SMP) +#define LEON3_COUNTER_GPTIMER_INDEX (LEON3_CLOCK_INDEX + 1) +#else +#define LEON3_COUNTER_GPTIMER_INDEX LEON3_CLOCK_INDEX +#endif + /* * We assume that a boot loader (usually GRMON) initialized the GPTIMER 0 to * run with 1MHz. This is used to determine all clock frequencies of the PnP diff --git a/bsps/sparc/leon3/start/cpucounter.c b/bsps/sparc/leon3/start/cpucounter.c index f583d9b0fb..007bb6d8ec 100644 --- a/bsps/sparc/leon3/start/cpucounter.c +++ b/bsps/sparc/leon3/start/cpucounter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016 embedded brains GmbH. All rights reserved. + * Copyright (c) 2014, 2018 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -29,46 +29,38 @@ static void leon3_counter_initialize(void) { volatile struct irqmp_timestamp_regs *irqmp_ts; volatile struct gptimer_regs *gpt; + SPARC_Counter *counter; irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0]; gpt = LEON3_Timer_Regs; + counter = &_SPARC_Counter_mutable; leon3_up_counter_enable(); if (leon3_up_counter_is_available()) { /* Use the LEON4 up-counter if available */ - - _SPARC_Counter_initialize( - _SPARC_Counter_read_asr23, - _SPARC_Counter_difference_normal, - NULL - ); + counter->read_isr_disabled = _SPARC_Counter_read_asr23; + counter->read = _SPARC_Counter_read_asr23; leon3_counter_frequency = leon3_up_counter_frequency(); } else if (leon3_irqmp_has_timestamp(irqmp_ts)) { /* Use the interrupt controller timestamp counter if available */ + counter->read_isr_disabled = _SPARC_Counter_read_up; + counter->read = _SPARC_Counter_read_up; + counter->counter_register = &LEON3_IrqCtrl_Regs->timestamp[0].counter; /* Enable interrupt timestamping for an arbitrary interrupt line */ irqmp_ts->control = 0x1; - _SPARC_Counter_initialize( - _SPARC_Counter_read_address, - _SPARC_Counter_difference_normal, - (volatile const uint32_t *) &irqmp_ts->counter - ); - leon3_counter_frequency = ambapp_freq_get(&ambapp_plb, LEON3_IrqCtrl_Adev); } else if (gpt != NULL) { /* Fall back to the first GPTIMER if available */ + counter->read_isr_disabled = _SPARC_Counter_read_down; + counter->read = _SPARC_Counter_read_down; + counter->counter_register = &gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].value; /* Enable timer just in case no clock driver is configured */ - gpt->timer[LEON3_CLOCK_INDEX].ctrl |= GPTIMER_TIMER_CTRL_EN; - - _SPARC_Counter_initialize( - _SPARC_Counter_read_address, - _SPARC_Counter_difference_clock_period, - (volatile const uint32_t *) &gpt->timer[LEON3_CLOCK_INDEX].value - ); + gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].ctrl |= GPTIMER_TIMER_CTRL_EN; leon3_counter_frequency = ambapp_freq_get(&ambapp_plb, LEON3_Timer_Adev) / (gpt->scaler_reload + 1); diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am index 7471007ef9..72946c03db 100644 --- a/c/src/lib/libbsp/sparc/leon2/Makefile.am +++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am @@ -26,7 +26,6 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspfatal-default.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspreset-empty.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/bspstart.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bspgetworkarea.c -librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/cpucounter/cpucounterfrequency.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/getentropy/getentropy-cpucounter.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/setvec.c diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am index 5e7d471329..188001aed7 100644 --- a/cpukit/Makefile.am +++ b/cpukit/Makefile.am @@ -1753,7 +1753,6 @@ librtemscpu_a_SOURCES += score/cpu/sparc/sparc-access.S librtemscpu_a_SOURCES += score/cpu/sparc/sparc-context-validate.S librtemscpu_a_SOURCES += score/cpu/sparc/sparc-context-volatile-clobber.S librtemscpu_a_SOURCES += score/cpu/sparc/sparc-counter-asm.S -librtemscpu_a_SOURCES += score/cpu/sparc/sparc-counter.c librtemscpu_a_SOURCES += score/cpu/sparc/syscall.S librtemscpu_a_SOURCES += score/cpu/sparc/window.S diff --git a/cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h b/cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h index 7ab09d990e..6b6094ae10 100644 --- a/cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h @@ -1219,10 +1219,13 @@ CPU_Counter_ticks _CPU_Counter_read( void ); * * @return Returns second minus first modulo counter period. */ -CPU_Counter_ticks _CPU_Counter_difference( +static inline CPU_Counter_ticks _CPU_Counter_difference( CPU_Counter_ticks second, CPU_Counter_ticks first -); +) +{ + return second - first; +} #ifdef RTEMS_SMP /** diff --git a/cpukit/score/cpu/or1k/include/rtems/score/cpu.h b/cpukit/score/cpu/or1k/include/rtems/score/cpu.h index 0d1566a0c9..663a1755ba 100644 --- a/cpukit/score/cpu/or1k/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/or1k/include/rtems/score/cpu.h @@ -712,10 +712,13 @@ uint32_t _CPU_Counter_frequency( void ); CPU_Counter_ticks _CPU_Counter_read( void ); -CPU_Counter_ticks _CPU_Counter_difference( +static inline CPU_Counter_ticks _CPU_Counter_difference( CPU_Counter_ticks second, CPU_Counter_ticks first -); +) +{ + return second - first; +} /** Type that can store a 32-bit integer or a pointer. */ typedef uintptr_t CPU_Uint32ptr; diff --git a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h index 252aa4026e..abc813cfa5 100644 --- a/cpukit/score/cpu/sparc/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/sparc/include/rtems/score/cpu.h @@ -1103,29 +1103,28 @@ uint32_t _CPU_Counter_frequency( void ); typedef CPU_Counter_ticks ( *SPARC_Counter_read )( void ); -typedef CPU_Counter_ticks ( *SPARC_Counter_difference )( - CPU_Counter_ticks second, - CPU_Counter_ticks first -); - /* * The SPARC processors supported by RTEMS have no built-in CPU counter * support. We have to use some hardware counter module for this purpose, for * example the GPTIMER instance used by the clock driver. The BSP must provide - * an implementation of the CPU counter read and difference functions. This - * allows the use of dynamic hardware enumeration. + * an implementation of the CPU counter read function. This allows the use of + * dynamic hardware enumeration. */ typedef struct { - SPARC_Counter_read counter_read; - SPARC_Counter_difference counter_difference; - volatile const CPU_Counter_ticks *counter_address; + SPARC_Counter_read read_isr_disabled; + SPARC_Counter_read read; + volatile const CPU_Counter_ticks *counter_register; + volatile const uint32_t *pending_register; + uint32_t pending_mask; + CPU_Counter_ticks accumulated; + CPU_Counter_ticks interval; } SPARC_Counter; extern const SPARC_Counter _SPARC_Counter; static inline CPU_Counter_ticks _CPU_Counter_read( void ) { - return ( *_SPARC_Counter.counter_read )(); + return ( *_SPARC_Counter.read )(); } static inline CPU_Counter_ticks _CPU_Counter_difference( @@ -1133,7 +1132,7 @@ static inline CPU_Counter_ticks _CPU_Counter_difference( CPU_Counter_ticks first ) { - return ( *_SPARC_Counter.counter_difference )( second, first ); + return second - first; } /** Type that can store a 32-bit integer or a pointer. */ diff --git a/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h b/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h index 81b4441b25..edc03bd074 100644 --- a/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h +++ b/cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * Copyright (c) 2016, 2018 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -21,6 +21,8 @@ extern "C" { #endif /* __cplusplus */ +struct timecounter; + /* * Provides a mutable alias to _SPARC_Counter for use in * _SPARC_Counter_initialize(). The _SPARC_Counter and _SPARC_Counter_mutable @@ -28,40 +30,27 @@ extern "C" { */ extern SPARC_Counter _SPARC_Counter_mutable; -CPU_Counter_ticks _SPARC_Counter_read_address( void ); +void _SPARC_Counter_at_tick_clock( void ); + +CPU_Counter_ticks _SPARC_Counter_read_default( void ); + +CPU_Counter_ticks _SPARC_Counter_read_up( void ); + +CPU_Counter_ticks _SPARC_Counter_read_down( void ); + +CPU_Counter_ticks _SPARC_Counter_read_clock_isr_disabled( void ); + +CPU_Counter_ticks _SPARC_Counter_read_clock( void ); CPU_Counter_ticks _SPARC_Counter_read_asr23( void ); -CPU_Counter_ticks _SPARC_Counter_difference_normal( - CPU_Counter_ticks second, - CPU_Counter_ticks first -); +uint32_t _SPARC_Get_timecount_up( struct timecounter * ); -CPU_Counter_ticks _SPARC_Counter_difference_clock_period( - CPU_Counter_ticks second, - CPU_Counter_ticks first -); +uint32_t _SPARC_Get_timecount_down( struct timecounter * ); -/* - * Returns always a value of one regardless of the parameters. This prevents - * an infinite loop in rtems_counter_delay_ticks(). Its only a reasonably safe - * default. - */ -CPU_Counter_ticks _SPARC_Counter_difference_one( - CPU_Counter_ticks second, - CPU_Counter_ticks first -); - -static inline void _SPARC_Counter_initialize( - SPARC_Counter_read counter_read, - SPARC_Counter_difference counter_difference, - volatile const CPU_Counter_ticks *counter_address -) -{ - _SPARC_Counter_mutable.counter_read = counter_read; - _SPARC_Counter_mutable.counter_difference = counter_difference; - _SPARC_Counter_mutable.counter_address = counter_address; -} +uint32_t _SPARC_Get_timecount_clock( struct timecounter * ); + +uint32_t _SPARC_Get_timecount_asr23( struct timecounter * ); /* * Defines the _SPARC_Counter and _SPARC_Counter_mutable global variables. @@ -75,12 +64,16 @@ static inline void _SPARC_Counter_initialize( "\t.section\t.data._SPARC_Counter,\"aw\",@progbits\n" \ "\t.align\t4\n" \ "\t.type\t_SPARC_Counter, #object\n" \ - "\t.size\t_SPARC_Counter, 12\n" \ + "\t.size\t_SPARC_Counter, 28\n" \ "_SPARC_Counter:\n" \ "_SPARC_Counter_mutable:\n" \ - "\t.long\t_SPARC_Counter_read_address\n" \ - "\t.long\t_SPARC_Counter_difference_one\n" \ - "\t.long\t_SPARC_Counter\n" \ + "\t.long\t_SPARC_Counter_read_default\n" \ + "\t.long\t_SPARC_Counter_read_default\n" \ + "\t.long\t0\n" \ + "\t.long\t0\n" \ + "\t.long\t0\n" \ + "\t.long\t0\n" \ + "\t.long\t0\n" \ "\t.previous\n" \ ) diff --git a/cpukit/score/cpu/sparc/sparc-counter-asm.S b/cpukit/score/cpu/sparc/sparc-counter-asm.S index 8ed079f48b..6f3e61c12b 100644 --- a/cpukit/score/cpu/sparc/sparc-counter-asm.S +++ b/cpukit/score/cpu/sparc/sparc-counter-asm.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * Copyright (c) 2016, 2018 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -18,17 +18,116 @@ #include <rtems/asm.h> + /* + * All functions except _SPARC_Counter_read_clock() in this module are + * sometimes called with traps disabled. + */ + .section ".text" .align 4 - PUBLIC(_SPARC_Counter_read_address) -SYM(_SPARC_Counter_read_address): + PUBLIC(_SPARC_Counter_read_default) +SYM(_SPARC_Counter_read_default): + sethi %hi(_SPARC_Counter + 12), %o1 + ld [%o1 + %lo(_SPARC_Counter + 12)], %o0 + add %o0, 1, %o0 + jmp %o7 + 8 + st %o0, [%o1 + %lo(_SPARC_Counter + 12)] + + PUBLIC(_SPARC_Counter_read_up) + PUBLIC(_SPARC_Get_timecount_up) +SYM(_SPARC_Counter_read_up): +SYM(_SPARC_Get_timecount_up): sethi %hi(_SPARC_Counter + 8), %o0 ld [%o0 + %lo(_SPARC_Counter + 8)], %o0 jmp %o7 + 8 ld [%o0], %o0 + PUBLIC(_SPARC_Counter_read_down) + PUBLIC(_SPARC_Get_timecount_down) +SYM(_SPARC_Counter_read_down): +SYM(_SPARC_Get_timecount_down): + sethi %hi(_SPARC_Counter + 8), %o0 + ld [%o0 + %lo(_SPARC_Counter + 8)], %o0 + ld [%o0], %o0 + jmp %o7 + 8 + xnor %g0, %o0, %o0 + + /* + * For the corresponding C code is something like this: + * + * CPU_Counter_ticks _SPARC_Counter_read_clock_isr_disabled( void ) + * { + * const SPARC_Counter *ctr; + * CPU_Counter_ticks ticks; + * CPU_Counter_ticks accumulated; + * + * ctr = &_SPARC_Counter; + * ticks = *ctr->counter_register; + * accumulated = ctr->accumulated; + * + * if ( ( *ctr->pending_register & ctr->pending_mask ) != 0 ) { + * ticks = *ctr->counter_register; + * accumulated += ctr->interval; + * } + * + * return accumulated - ticks; + * } + */ + PUBLIC(_SPARC_Counter_read_clock_isr_disabled) +SYM(_SPARC_Counter_read_clock_isr_disabled): + sethi %hi(_SPARC_Counter), %o5 + or %o5, %lo(_SPARC_Counter), %o5 + ld [%o5 + 8], %o3 + ld [%o5 + 12], %o4 + ld [%o5 + 16], %o2 + ld [%o3], %o0 + ld [%o4], %o1 + btst %o1, %o2 + bne .Lpending_isr_disabled + ld [%o5 + 20], %o4 + jmp %o7 + 8 + sub %o4, %o0, %o0 +.Lpending_isr_disabled: + ld [%o5 + 24], %o5 + ld [%o3], %o0 + add %o4, %o5, %o4 + jmp %o7 + 8 + sub %o4, %o0, %o0 + + /* + * For the corresponding C code see + * _SPARC_Counter_read_clock_isr_disabled() above. + */ + PUBLIC(_SPARC_Counter_read_clock) + PUBLIC(_SPARC_Get_timecount_clock) +SYM(_SPARC_Counter_read_clock): +SYM(_SPARC_Get_timecount_clock): + sethi %hi(_SPARC_Counter), %o5 + or %o5, %lo(_SPARC_Counter), %o5 + ta SPARC_SWTRAP_IRQDIS + ld [%o5 + 8], %o3 + ld [%o5 + 12], %o4 + ld [%o5 + 16], %o2 + ld [%o3], %o0 + ld [%o4], %o1 + btst %o1, %o2 + bne .Lpending + ld [%o5 + 20], %o4 + ta SPARC_SWTRAP_IRQEN + jmp %o7 + 8 + sub %o4, %o0, %o0 +.Lpending: + ld [%o5 + 24], %o5 + ld [%o3], %o0 + ta SPARC_SWTRAP_IRQEN + add %o4, %o5, %o4 + jmp %o7 + 8 + sub %o4, %o0, %o0 + PUBLIC(_SPARC_Counter_read_asr23) + PUBLIC(_SPARC_Get_timecount_asr23) SYM(_SPARC_Counter_read_asr23): +SYM(_SPARC_Get_timecount_asr23): jmp %o7 + 8 mov %asr23, %o0 diff --git a/cpukit/score/cpu/sparc/sparc-counter.c b/cpukit/score/cpu/sparc/sparc-counter.c deleted file mode 100644 index 9bc4061e9e..0000000000 --- a/cpukit/score/cpu/sparc/sparc-counter.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2014, 2016 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * <rtems@embedded-brains.de> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include <rtems/score/sparcimpl.h> -#include <rtems/config.h> - -CPU_Counter_ticks _SPARC_Counter_difference_normal( - CPU_Counter_ticks second, - CPU_Counter_ticks first -) -{ - return second - first; -} - -CPU_Counter_ticks _SPARC_Counter_difference_clock_period( - CPU_Counter_ticks second, - CPU_Counter_ticks first -) -{ - CPU_Counter_ticks period; - - period = rtems_configuration_get_microseconds_per_tick(); - - return ( first + period - second ) % period; -} - -CPU_Counter_ticks _SPARC_Counter_difference_one( - CPU_Counter_ticks second, - CPU_Counter_ticks first -) -{ - return 1; -} |