summaryrefslogtreecommitdiffstats
path: root/cpukit/score
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-05-03 13:03:27 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-12-07 14:22:01 +0100
commit0a1f5df98e52b028bf8b4de3bf63e39702fa5f34 (patch)
tree7b3d8bfe7a9e760ee2bbb8916d3284f34edfec89 /cpukit/score
parentscore: Avoid sbintime_t in API headers (diff)
downloadrtems-0a1f5df98e52b028bf8b4de3bf63e39702fa5f34.tar.bz2
Simplify _CPU_Counter_difference()
In order to simplify the use of CPU counter values it is beneficial to have monotonic increasing values within the range of the CPU counter ticks data type, e.g. 32-bit unsigned integer. This eases the use of CPU counter timestamps in external tools which do not know the details of the CPU counter hardware. The CPU counter is the fastest way to get a time on an RTEMS system. Such a CPU counter may be also used as the timecounter. Use it on SPARC for this purpose to simplify the clock drivers. Update #3456.
Diffstat (limited to 'cpukit/score')
-rw-r--r--cpukit/score/cpu/no_cpu/include/rtems/score/cpu.h7
-rw-r--r--cpukit/score/cpu/or1k/include/rtems/score/cpu.h7
-rw-r--r--cpukit/score/cpu/sparc/include/rtems/score/cpu.h23
-rw-r--r--cpukit/score/cpu/sparc/include/rtems/score/sparcimpl.h61
-rw-r--r--cpukit/score/cpu/sparc/sparc-counter-asm.S105
-rw-r--r--cpukit/score/cpu/sparc/sparc-counter.c48
6 files changed, 150 insertions, 101 deletions
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;
-}