[PATCH 2/4] timecounter: Port to RTEMS
Alexander Krutwig
alexander.krutwig at embedded-brains.de
Wed Apr 8 12:44:14 UTC 2015
New test sptests/timecounter01.
---
cpukit/sapi/Makefile.am | 4 +-
cpukit/sapi/include/rtems/bsd.h | 141 ++++++++++++
cpukit/sapi/include/rtems/timecounter.h | 123 ++++++++++
cpukit/sapi/preinstall.am | 8 +
cpukit/score/Makefile.am | 12 +
cpukit/score/include/rtems/score/timecounter.h | 250 +++++++++++++++++++++
cpukit/score/include/rtems/score/timecounterimpl.h | 49 ++++
cpukit/score/include/sys/timeffc.h | 2 +
cpukit/score/include/sys/timetc.h | 2 +
cpukit/score/preinstall.am | 33 +++
cpukit/score/src/kern_tc.c | 171 +++++++++++++-
testsuites/sptests/sptimecounter01/Makefile.am | 19 ++
testsuites/sptests/sptimecounter01/init.c | 131 +++++++++++
.../sptests/sptimecounter01/sptimecounter01.doc | 29 +++
.../sptests/sptimecounter01/sptimecounter01.scn | 2 +
15 files changed, 972 insertions(+), 4 deletions(-)
create mode 100644 cpukit/sapi/include/rtems/bsd.h
create mode 100644 cpukit/sapi/include/rtems/timecounter.h
create mode 100644 cpukit/score/include/rtems/score/timecounter.h
create mode 100644 cpukit/score/include/rtems/score/timecounterimpl.h
create mode 100644 testsuites/sptests/sptimecounter01/Makefile.am
create mode 100644 testsuites/sptests/sptimecounter01/init.c
create mode 100644 testsuites/sptests/sptimecounter01/sptimecounter01.doc
create mode 100644 testsuites/sptests/sptimecounter01/sptimecounter01.scn
diff --git a/cpukit/sapi/Makefile.am b/cpukit/sapi/Makefile.am
index 070800e..9db5d10 100644
--- a/cpukit/sapi/Makefile.am
+++ b/cpukit/sapi/Makefile.am
@@ -3,7 +3,8 @@ include $(top_srcdir)/automake/compile.am
include_rtemsdir = $(includedir)/rtems
-include_rtems_HEADERS = include/confdefs.h
+include_rtems_HEADERS = include/rtems/bsd.h
+include_rtems_HEADERS += include/confdefs.h
include_rtems_HEADERS += include/rtems/chain.h
include_rtems_HEADERS += include/rtems/config.h
include_rtems_HEADERS += include/rtems/counter.h
@@ -19,6 +20,7 @@ include_rtems_HEADERS += include/rtems/rbheap.h
include_rtems_HEADERS += include/rtems/rbtree.h
include_rtems_HEADERS += include/rtems/scheduler.h
include_rtems_HEADERS += include/rtems/sptables.h
+include_rtems_HEADERS += include/rtems/timecounter.h
include_rtems_HEADERS += include/rtems/timespec.h
EXTRA_DIST = include/rtems/README
diff --git a/cpukit/sapi/include/rtems/bsd.h b/cpukit/sapi/include/rtems/bsd.h
new file mode 100644
index 0000000..0c44e37
--- /dev/null
+++ b/cpukit/sapi/include/rtems/bsd.h
@@ -0,0 +1,141 @@
+/**
+ * @file
+ *
+ * @ingroup BSD
+ *
+ * @brief BSD Compatibility API
+ */
+
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at 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.
+ */
+
+#ifndef _RTEMS_BSD_H
+#define _RTEMS_BSD_H
+
+#include <rtems/score/timecounter.h>
+#include <rtems/score/basedefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup BSD BSD Compatibility Support
+ *
+ * @{
+ */
+
+/**
+ * @copydoc _Timecounter_Bintime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_bintime( struct bintime *bt )
+{
+ _Timecounter_Bintime( bt );
+}
+
+/**
+ * @copydoc _Timecounter_Nanotime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_nanotime( struct timespec *ts )
+{
+ _Timecounter_Nanotime( ts );
+}
+
+/**
+ * @copydoc _Timecounter_Microtime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_microtime( struct timeval *tv )
+{
+ _Timecounter_Microtime( tv );
+}
+
+/**
+ * @copydoc _Timecounter_Binuptime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_binuptime( struct bintime *bt )
+{
+ _Timecounter_Binuptime( bt );
+}
+
+/**
+ * @copydoc _Timecounter_Nanouptime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_nanouptime( struct timespec *ts )
+{
+ _Timecounter_Nanouptime( ts );
+}
+
+/**
+ * @copydoc _Timecounter_Microtime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_microuptime( struct timeval *tv )
+{
+ _Timecounter_Microuptime( tv );
+}
+
+/**
+ * @copydoc _Timecounter_Getbintime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_getbintime( struct bintime *bt )
+{
+ _Timecounter_Getbintime( bt );
+}
+
+/**
+ * @copydoc _Timecounter_Getnanotime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_getnanotime( struct timespec *ts )
+{
+ _Timecounter_Getnanotime( ts );
+}
+
+/**
+ * @copydoc _Timecounter_Getmicrotime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_getmicrotime( struct timeval *tv )
+{
+ _Timecounter_Getmicrotime( tv );
+}
+
+/**
+ * @copydoc _Timecounter_Getbinuptime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_getbinuptime( struct bintime *bt )
+{
+ _Timecounter_Getbinuptime( bt );
+}
+
+/**
+ * @copydoc _Timecounter_Getnanouptime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_getnanouptime( struct timespec *ts )
+{
+ _Timecounter_Getnanouptime( ts );
+}
+
+/**
+ * @copydoc _Timecounter_Getmicrouptime()
+ */
+RTEMS_INLINE_ROUTINE void rtems_bsd_getmicrouptime( struct timeval *tv )
+{
+ _Timecounter_Getmicrouptime( tv );
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_BSD_H */
diff --git a/cpukit/sapi/include/rtems/timecounter.h b/cpukit/sapi/include/rtems/timecounter.h
new file mode 100644
index 0000000..2495f3f
--- /dev/null
+++ b/cpukit/sapi/include/rtems/timecounter.h
@@ -0,0 +1,123 @@
+/**
+ * @file
+ *
+ * @ingroup SAPITimecounter
+ *
+ * @brief Timecounter API
+ */
+
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at 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.
+ */
+
+#ifndef _RTEMS_TIMECOUNTER_H
+#define _RTEMS_TIMECOUNTER_H
+
+#include <rtems/score/timecounter.h>
+#include <rtems/score/basedefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup SAPITimecounter Timecounter Support
+ *
+ * @{
+ */
+
+/**
+ * @brief Timecounter quality for the clock drivers.
+ *
+ * Timecounter with higher quality value are used in favor of those with lower
+ * quality value.
+ */
+#define RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER 100
+
+/**
+ * @copydoc _Timecounter_Install()
+ *
+ * Below is an exemplary code snippet that shows the adjustable parameters and
+ * the following call of the install routine
+ *
+ * @code
+ * dummy_tc.tc_get_timecount = dummy_get_timecount;
+ * dummy_tc.tc_counter_mask = 0xFFFFFFFF;
+ * dummy_tc.tc_frequency = 1000000;
+ * dummy_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ * rtems_timecounter_install(&dummy_tc);
+ * @endcode
+ */
+RTEMS_INLINE_ROUTINE void rtems_timecounter_install(
+ struct timecounter *tc
+)
+{
+ _Timecounter_Install(tc);
+}
+
+/**
+ * @copydoc _Timecounter_Tick()
+ */
+RTEMS_INLINE_ROUTINE void rtems_timecounter_tick(void)
+{
+ _Timecounter_Tick();
+}
+
+/**
+ * @copydoc _Timecounter_Tick_simple()
+ */
+RTEMS_INLINE_ROUTINE void rtems_timecounter_tick_simple(
+ u_int delta,
+ u_int offset
+)
+{
+ _Timecounter_Tick_simple(delta, offset);
+}
+
+/**
+ * @copydoc _Timecounter_Get_binary_scaler_and_mask()
+ *
+ * Below a code snippet is given that demonstrates how the binary scaler and
+ * mask are generated.
+ *
+ * @code
+ * for ( i = 0; i < 32; ++i ) {
+ * if ( power_of_two >= counter_ticks_per_clock_tick ) {
+ * break;
+ * }
+ * power_of_two *= 2;
+ * }
+ * *mask = (2 * power_of_two) - 1;
+ * *scaler = ((uint64_t) power_of_two << 32) / counter_ticks_per_clock_tick;
+ * @endcode
+ */
+RTEMS_INLINE_ROUTINE void rtems_timecounter_get_binary_scaler_and_mask(
+ uint32_t counter_ticks_per_clock_tick,
+ uint64_t *scaler,
+ uint32_t *mask
+)
+{
+ _Timecounter_Get_binary_scaler_and_mask(
+ counter_ticks_per_clock_tick,
+ scaler,
+ mask
+ );
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_TIMECOUNTER_H */
diff --git a/cpukit/sapi/preinstall.am b/cpukit/sapi/preinstall.am
index 3f864bb..e8d89b5 100644
--- a/cpukit/sapi/preinstall.am
+++ b/cpukit/sapi/preinstall.am
@@ -18,6 +18,10 @@ $(PROJECT_INCLUDE)/rtems/$(dirstamp):
@: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+$(PROJECT_INCLUDE)/rtems/bsd.h: include/rtems/bsd.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bsd.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/bsd.h
+
$(PROJECT_INCLUDE)/rtems/confdefs.h: include/confdefs.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/confdefs.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/confdefs.h
@@ -82,6 +86,10 @@ $(PROJECT_INCLUDE)/rtems/sptables.h: include/rtems/sptables.h $(PROJECT_INCLUDE)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/sptables.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/sptables.h
+$(PROJECT_INCLUDE)/rtems/timecounter.h: include/rtems/timecounter.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/timecounter.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/timecounter.h
+
$(PROJECT_INCLUDE)/rtems/timespec.h: include/rtems/timespec.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/timespec.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/timespec.h
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 090f7f6..d9aceef 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -5,6 +5,15 @@ SUBDIRS = cpu
## include
+include_sysdir = $(includedir)/sys
+
+include_sys_HEADERS =
+include_sys_HEADERS += include/sys/_ffcounter.h
+include_sys_HEADERS += include/sys/timeffc.h
+include_sys_HEADERS += include/sys/timepps.h
+include_sys_HEADERS += include/sys/timetc.h
+include_sys_HEADERS += include/sys/timex.h
+
include_rtemsdir = $(includedir)/rtems
include_rtems_HEADERS = include/rtems/debug.h
@@ -86,6 +95,8 @@ include_rtems_score_HEADERS += include/rtems/score/threadsync.h
include_rtems_score_HEADERS += include/rtems/score/timespec.h
include_rtems_score_HEADERS += include/rtems/score/timestamp.h
include_rtems_score_HEADERS += include/rtems/score/timestamp64.h
+include_rtems_score_HEADERS += include/rtems/score/timecounter.h
+include_rtems_score_HEADERS += include/rtems/score/timecounterimpl.h
include_rtems_score_HEADERS += include/rtems/score/tls.h
include_rtems_score_HEADERS += include/rtems/score/tod.h
include_rtems_score_HEADERS += include/rtems/score/todimpl.h
@@ -343,6 +354,7 @@ libscore_a_SOURCES += src/profilingisrentryexit.c
libscore_a_SOURCES += src/once.c
libscore_a_SOURCES += src/resourceiterate.c
libscore_a_SOURCES += src/smpbarrierwait.c
+libscore_a_SOURCES += src/kern_tc.c
EXTRA_DIST = src/Unlimited.txt
diff --git a/cpukit/score/include/rtems/score/timecounter.h b/cpukit/score/include/rtems/score/timecounter.h
new file mode 100644
index 0000000..5347ee4
--- /dev/null
+++ b/cpukit/score/include/rtems/score/timecounter.h
@@ -0,0 +1,250 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreTimecounter
+ *
+ * @brief Timecounter API
+ */
+
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at 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.
+ */
+
+#ifndef _RTEMS_SCORE_TIMECOUNTER_H
+#define _RTEMS_SCORE_TIMECOUNTER_H
+
+#include <sys/time.h>
+#include <sys/timetc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup ScoreTimecounter Timecounter Handler
+ *
+ * @ingroup Score
+ *
+ * @{
+ */
+
+/**
+ * @brief Returns the current time in the bintime format.
+ *
+ * @param[out] bt Returns the current time.
+ */
+void _Timecounter_Bintime( struct bintime *bt );
+
+/**
+ * @brief Returns the current time in the nanotime format.
+ *
+ * The nanotime is the boottime plus the uptime.
+ *
+ * @param[out] ts Returns the current time.
+ */
+void _Timecounter_Nanotime( struct timespec *ts );
+
+/**
+ * @brief Returns the current time in the microtime format.
+ *
+ * The microtime is the boottime plus the uptime.
+ *
+ * @param[out] ts Returns the current time.
+ */
+void _Timecounter_Microtime( struct timeval *tv );
+
+/**
+ * @brief Returns the current uptime in the bintime format.
+ *
+ * The binuptime is the amount of time that has passed since the system was
+ * booted.
+ *
+ * @param[out] bt Returns the current uptime.
+ */
+void _Timecounter_Binuptime( struct bintime *bt );
+
+/**
+ * @brief Returns the current uptime in the nanotime format.
+ *
+ * The nanouptime is the amount of time that has passed since the system was
+ * booted.
+ *
+ * @param[out] ts Returns the current uptime.
+ */
+void _Timecounter_Nanouptime( struct timespec *ts );
+
+/**
+ * @brief Returns the current uptime in the microtime format.
+ *
+ * The microuptime is the amount of time that has passed since the system was
+ * booted.
+ *
+ * @param[out] ts Returns the current uptime.
+ */
+void _Timecounter_Microuptime( struct timeval *tv );
+
+/**
+ * @brief Returns the current time in the bintime format.
+ *
+ * The difference to the rtems_bsd_bintime(bt) is the higher inexactness of the
+ * returned time information. As the addition of the time that has elapsed since
+ * the last windup call is not added, the function call is on the one hand
+ * quicker, however also more inaccurate.
+ *
+ * The bintime is the boottime plus the uptime.
+ *
+ * @param[out] ts Returns the current time.
+ */
+void _Timecounter_Getbintime( struct bintime *bt );
+
+/**
+ * @brief Returns the current time in the nanotime format.
+ *
+ * The difference to the rtems_bsd_nanotime(ts) is the higher inexactness of the
+ * returned time information. As the addition of the time that has elapsed since
+ * the last windup call is not added, the function call is on the one hand
+ * quicker, however also more inaccurate.
+ *
+ * The nanotime is the boottime plus the uptime.
+ *
+ * @param[out] ts Returns the current time.
+ */
+void _Timecounter_Getnanotime( struct timespec *ts );
+
+/**
+ * @brief Returns the current time in the microtime format.
+ *
+ * The difference to the rtems_bsd_microtime(tv) is the higher inexactness of the
+ * returned time information. As the addition of the time that has elapsed since
+ * the last windup call is not added, the function call is on the one hand
+ * quicker, however also more inaccurate.
+ *
+ * The microtime is the boottime plus the uptime.
+ *
+ * @param[out] ts Returns the current time.
+ */
+void _Timecounter_Getmicrotime( struct timeval *tv );
+
+/**
+ * @brief Returns the current uptime in the bintime format.
+ *
+ * The difference to the rtems_bsd_binuptime(bt) is the higher inexactness of the
+ * returned time information. As the addition of the time that has elapsed since
+ * the last windup call is not added, the function call is on the one hand
+ * quicker, however also more inaccurate.
+ *
+ * The binuptime is the amount of time that has passed since the system was
+ * booted.
+ *
+ * @param[out] ts Returns the current uptime.
+ */
+void _Timecounter_Getbinuptime( struct bintime *bt );
+
+/**
+ * @brief Returns the current uptime in the nanotime format.
+ *
+ * The difference to the rtems_bsd_nanouptime(ts) is the higher inexactness of
+ * the returned time information. As the addition of the time that has elapsed
+ * since the last windup call is not added, the function call is on the one hand
+ * quicker, however also more inaccurate.
+ *
+ * The nanouptime is the amount of time that has passed since the system was
+ * booted.
+ *
+ * @param[out] ts Returns the current uptime.
+ */
+void _Timecounter_Getnanouptime( struct timespec *ts );
+
+/**
+ * @brief Returns the current Timecounter microuptime.
+ *
+ * The difference to the rtems_bsd_microuptime(tv) is the higher inexactness of
+ * the returned time information. As the addition of the time that has elapsed
+ * since the last windup call is not added, the function call is on the one hand
+ * quicker, however also more inaccurate.
+ *
+ * The microuptime is the amount of time that has passed since the system was
+ * booted.
+ *
+ * @param[out] ts Returns the current uptime.
+ */
+void _Timecounter_Getmicrouptime( struct timeval *tv );
+
+/**
+ * @brief Sets up the timecounter.
+ *
+ * This routine installs a timecounter structure that is used for the
+ * timestamping in the process. Several parameters are used to design the
+ * timecounter instance.
+ *
+ * Designable Parameters are
+ * - tc_get_timecount: pointer to a timing/timecounter routine.
+ * - tc_counter_mask: masks the value received by the timecount routine.
+ * - tc_frequency: operating frequency of the application.
+ * - tc_quality: defines the quality given to a timecounter structure. A value
+ * can be set in the macro RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER.
+ *
+ * @param[in] tc One timecounter instance the structure should consist of
+ */
+void _Timecounter_Install( struct timecounter *tc );
+
+/**
+ * @brief Interrupt Routine that triggers a windup call.
+ *
+ * Usage for timecount registers that run on binary basis. The calculation of
+ * the offset that is added to the previous timestamp is executed during the
+ * execution of the routine.
+ */
+void _Timecounter_Tick( void );
+
+/**
+ * @brief Interrupt Routine that cannot trigger a windup call.
+ *
+ * This routine is needed for a get_timecounter request where the information
+ * is received from a real time clock register that does not offer a binary
+ * basis. Here the bintime is calculated by giving the previous offset and the
+ * delta that is to be added as inputs. The delta value is calculated with the
+ * help of the binary scaler and mask
+ *
+ * @param[in] delta is one timecounter interval + time from the start of the
+ * new interval.
+ * @param[in] offset is the time from the start of the new interval.
+ */
+void _Timecounter_Tick_simple( u_int delta, u_int offset );
+
+/**
+ * @brief creates scaler and mask for _Timecounter_Tick_simple.
+ *
+ * Calculates the scaler and mask of the next upcoming power of 2. The scaler
+ * is the next power of 2 divided by the counter_ticks_per_clock_ticks. The
+ * mask is double the next power of 2 minus 1, as the timecounter can return a
+ * maximum value of the length of two intervals.
+ *
+ * @param[in] counter_ticks_per_clock_tick
+ * @param[out] scaler is the value of the scaling factor which has to imposed
+ * on the values returned by the get_timecount information
+ * @param[out] mask is the value of double the next power of 2 minus 1
+ */
+void _Timecounter_Get_binary_scaler_and_mask(
+ uint32_t counter_ticks_per_clock_tick,
+ uint64_t *scaler,
+ uint32_t *mask
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_SCORE_TIMECOUNTER_H */
diff --git a/cpukit/score/include/rtems/score/timecounterimpl.h b/cpukit/score/include/rtems/score/timecounterimpl.h
new file mode 100644
index 0000000..dd47aac
--- /dev/null
+++ b/cpukit/score/include/rtems/score/timecounterimpl.h
@@ -0,0 +1,49 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreTimecounter
+ *
+ * @brief Timecounter Implementation
+ */
+
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at 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.
+ */
+
+#ifndef _RTEMS_SCORE_TIMECOUNTERIMPL_H
+#define _RTEMS_SCORE_TIMECOUNTERIMPL_H
+
+#include <rtems/score/timecounter.h>
+#include <sys/timetc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @addtogroup ScoreTimecounter
+ *
+ * @{
+ */
+
+void _Timecounter_Initialize( void );
+
+void _Timecounter_Set_clock( const struct timespec *ts );
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_SCORE_TIMECOUNTERIMPL_H */
diff --git a/cpukit/score/include/sys/timeffc.h b/cpukit/score/include/sys/timeffc.h
index 3bda5d4..c3aed67 100644
--- a/cpukit/score/include/sys/timeffc.h
+++ b/cpukit/score/include/sys/timeffc.h
@@ -55,11 +55,13 @@ struct ffclock_estimate {
#if __BSD_VISIBLE
#ifdef _KERNEL
+#ifndef __rtems__
/* Define the kern.sysclock sysctl tree. */
SYSCTL_DECL(_kern_sysclock);
/* Define the kern.sysclock.ffclock sysctl tree. */
SYSCTL_DECL(_kern_sysclock_ffclock);
+#endif /* __rtems__ */
/*
* Index into the sysclocks array for obtaining the ASCII name of a particular
diff --git a/cpukit/score/include/sys/timetc.h b/cpukit/score/include/sys/timetc.h
index e68e327..1fed542 100644
--- a/cpukit/score/include/sys/timetc.h
+++ b/cpukit/score/include/sys/timetc.h
@@ -12,9 +12,11 @@
#ifndef _SYS_TIMETC_H_
#define _SYS_TIMETC_H_
+#ifndef __rtems__
#ifndef _KERNEL
#error "no user-serviceable parts inside"
#endif
+#endif /* __rtems__ */
/*-
* `struct timecounter' is the interface between the hardware which implements
diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am
index 920c0d9..9be9fcc 100644
--- a/cpukit/score/preinstall.am
+++ b/cpukit/score/preinstall.am
@@ -13,6 +13,31 @@ all-am: $(PREINSTALL_FILES)
PREINSTALL_FILES =
CLEANFILES = $(PREINSTALL_FILES)
+$(PROJECT_INCLUDE)/sys/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_INCLUDE)/sys
+ @: > $(PROJECT_INCLUDE)/sys/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/sys/$(dirstamp)
+
+$(PROJECT_INCLUDE)/sys/_ffcounter.h: include/sys/_ffcounter.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/_ffcounter.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/_ffcounter.h
+
+$(PROJECT_INCLUDE)/sys/timeffc.h: include/sys/timeffc.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/timeffc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/timeffc.h
+
+$(PROJECT_INCLUDE)/sys/timepps.h: include/sys/timepps.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/timepps.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/timepps.h
+
+$(PROJECT_INCLUDE)/sys/timetc.h: include/sys/timetc.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/timetc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/timetc.h
+
+$(PROJECT_INCLUDE)/sys/timex.h: include/sys/timex.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/timex.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/timex.h
+
$(PROJECT_INCLUDE)/rtems/$(dirstamp):
@$(MKDIR_P) $(PROJECT_INCLUDE)/rtems
@: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
@@ -327,6 +352,14 @@ $(PROJECT_INCLUDE)/rtems/score/timestamp64.h: include/rtems/score/timestamp64.h
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/timestamp64.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/timestamp64.h
+$(PROJECT_INCLUDE)/rtems/score/timecounter.h: include/rtems/score/timecounter.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/timecounter.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/timecounter.h
+
+$(PROJECT_INCLUDE)/rtems/score/timecounterimpl.h: include/rtems/score/timecounterimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/timecounterimpl.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/timecounterimpl.h
+
$(PROJECT_INCLUDE)/rtems/score/tls.h: include/rtems/score/tls.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/tls.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/tls.h
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index 1c29041..ba4396e 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -13,6 +13,23 @@
* of Melbourne under sponsorship from the FreeBSD Foundation.
*/
+#ifdef __rtems__
+#define _KERNEL
+#define tc_init _Timecounter_Install
+#define bintime _Timecounter_Bintime
+#define nanotime _Timecounter_Nanotime
+#define microtime _Timecounter_Microtime
+#define binuptime _Timecounter_Binuptime
+#define nanouptime _Timecounter_Nanouptime
+#define microuptime _Timecounter_Microuptime
+#define getbintime _Timecounter_Getbintime
+#define getnanouptime _Timecounter_Getnanouptime
+#define getmicrouptime _Timecounter_Getmicrouptime
+#define getbinuptime _Timecounter_Getbinuptime
+#define getnanouptime _Timecounter_Getnanouptime
+#define getmicrouptime _Timecounter_Getmicrouptime
+#include <rtems/score/timecounterimpl.h>
+#endif /* __rtems__ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -21,20 +38,50 @@ __FBSDID("$FreeBSD$");
#include "opt_ffclock.h"
#include <sys/param.h>
+#ifndef __rtems__
#include <sys/kernel.h>
#include <sys/limits.h>
+#else /* __rtems__ */
+#include <limits.h>
+#endif /* __rtems__ */
#ifdef FFCLOCK
#include <sys/lock.h>
#include <sys/mutex.h>
#endif
+#ifndef __rtems__
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/systm.h>
+#endif /* __rtems__ */
#include <sys/timeffc.h>
#include <sys/timepps.h>
#include <sys/timetc.h>
#include <sys/timex.h>
+#ifndef __rtems__
#include <sys/vdso.h>
+#endif /* __rtems__ */
+#ifdef __rtems__
+#include <rtems.h>
+ISR_LOCK_DEFINE(static, _Timecounter_Lock, "Timecounter");
+#define hz rtems_clock_get_ticks_per_second()
+#define bootverbose 0
+#define printf(...)
+#define log(...)
+/* FIXME */
+static inline int
+fls(int x)
+{
+ return x ? sizeof(x) * 8 - __builtin_clz(x) : 0;
+}
+/* FIXME */
+static __inline u_int max(u_int a, u_int b) { return (a > b ? a : b); }
+/* FIXME */
+struct bintime tick_bt; /* bintime per tick (1s / hz) */
+/* FIXME */
+sbintime_t tick_sbt;
+/* FIXME */
+#define ntp_update_second(a, b) do { (void) a; (void) b; } while (0)
+#endif /* __rtems__ */
/*
* A large step happens on boot. This constant detects such steps.
@@ -76,6 +123,7 @@ struct timehands {
struct timehands *th_next;
};
+#if defined(RTEMS_SMP)
static struct timehands th0;
static struct timehands th9 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th0};
static struct timehands th8 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th9};
@@ -86,6 +134,7 @@ static struct timehands th4 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th5};
static struct timehands th3 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th4};
static struct timehands th2 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th3};
static struct timehands th1 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th2};
+#endif
static struct timehands th0 = {
&dummy_timecounter,
0,
@@ -95,7 +144,11 @@ static struct timehands th0 = {
{0, 0},
{0, 0},
1,
+#if defined(RTEMS_SMP)
&th1
+#else
+ &th0
+#endif
};
static struct timehands *volatile timehands = &th0;
@@ -108,6 +161,7 @@ volatile time_t time_second = 1;
volatile time_t time_uptime = 1;
struct bintime boottimebin;
+#ifndef __rtems__
struct timeval boottime;
static int sysctl_kern_boottime(SYSCTL_HANDLER_ARGS);
SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime, CTLTYPE_STRUCT|CTLFLAG_RD,
@@ -119,6 +173,7 @@ static SYSCTL_NODE(_kern_timecounter, OID_AUTO, tc, CTLFLAG_RW, 0, "");
static int timestepwarnings;
SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW,
×tepwarnings, 0, "Log time steps");
+#endif /* __rtems__ */
struct bintime bt_timethreshold;
struct bintime bt_tickthreshold;
@@ -128,17 +183,22 @@ struct bintime tc_tick_bt;
sbintime_t tc_tick_sbt;
int tc_precexp;
int tc_timepercentage = TC_DEFAULTPERC;
+#ifndef __rtems__
static int sysctl_kern_timecounter_adjprecision(SYSCTL_HANDLER_ARGS);
SYSCTL_PROC(_kern_timecounter, OID_AUTO, alloweddeviation,
CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 0, 0,
sysctl_kern_timecounter_adjprecision, "I",
"Allowed time interval deviation in percents");
+#endif /* __rtems__ */
static void tc_windup(void);
+#ifndef __rtems__
static void cpu_tick_calibrate(int);
+#endif /* __rtems__ */
void dtrace_getnanotime(struct timespec *tsp);
+#ifndef __rtems__
static int
sysctl_kern_boottime(SYSCTL_HANDLER_ARGS)
{
@@ -175,6 +235,7 @@ sysctl_kern_timecounter_freq(SYSCTL_HANDLER_ARGS)
freq = tc->tc_frequency;
return sysctl_handle_64(oidp, &freq, 0, req);
}
+#endif /* __rtems__ */
/*
* Return the difference between the timehands' counter value now and what
@@ -994,16 +1055,19 @@ dtrace_getnanotime(struct timespec *tsp)
} while (gen == 0 || gen != th->th_generation);
}
+#ifdef FFCLOCK
/*
* System clock currently providing time to the system. Modifiable via sysctl
* when the FFCLOCK option is defined.
*/
int sysclock_active = SYSCLOCK_FBCK;
+#endif
/* Internal NTP status and error estimates. */
extern int time_status;
extern long time_esterror;
+#ifndef __rtems__
/*
* Take a snapshot of sysclock data which can be used to compare system clocks
* and generate timestamps after the fact.
@@ -1046,7 +1110,9 @@ sysclock_getsnapshot(struct sysclock_snap *clock_snap, int fast)
} while (gen == 0 || gen != th->th_generation);
clock_snap->delta = delta;
+#ifdef FFCLOCK
clock_snap->sysclock_active = sysclock_active;
+#endif
/* Record feedback clock status and error. */
clock_snap->fb_info.status = time_status;
@@ -1133,6 +1199,7 @@ sysclock_snap2bintime(struct sysclock_snap *cs, struct bintime *bt,
return (0);
}
+#endif /* __rtems__ */
/*
* Initialize a new timecounter and possibly use it.
@@ -1140,9 +1207,11 @@ sysclock_snap2bintime(struct sysclock_snap *cs, struct bintime *bt,
void
tc_init(struct timecounter *tc)
{
- u_int u;
+// u_int u;
+#ifndef __rtems__
struct sysctl_oid *tc_root;
-
+#endif /* __rtems__ */
+#if 0
u = tc->tc_frequency / tc->tc_counter_mask;
/* XXX: We need some margin here, 10% is a guess */
u *= 11;
@@ -1159,9 +1228,10 @@ tc_init(struct timecounter *tc)
tc->tc_name, (uintmax_t)tc->tc_frequency,
tc->tc_quality);
}
-
+#endif
tc->tc_next = timecounters;
timecounters = tc;
+#ifndef __rtems__
/*
* Set up sysctl tree for this counter.
*/
@@ -1180,11 +1250,13 @@ tc_init(struct timecounter *tc)
SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
"quality", CTLFLAG_RD, &(tc->tc_quality), 0,
"goodness of time counter");
+#endif /* __rtems__ */
/*
* Never automatically use a timecounter with negative quality.
* Even though we run on the dummy counter, switching here may be
* worse since this timecounter may not be monotonous.
*/
+#if 0
if (tc->tc_quality < 0)
return;
if (tc->tc_quality < timecounter->tc_quality)
@@ -1192,9 +1264,13 @@ tc_init(struct timecounter *tc)
if (tc->tc_quality == timecounter->tc_quality &&
tc->tc_frequency < timecounter->tc_frequency)
return;
+#endif
(void)tc->tc_get_timecount(tc);
(void)tc->tc_get_timecount(tc);
timecounter = tc;
+#ifdef __rtems__
+ tc_windup();
+#endif /* __rtems__ */
}
/* Report the frequency of the current timecounter. */
@@ -1210,23 +1286,36 @@ tc_getfrequency(void)
* when we booted.
* XXX: not locked.
*/
+
+#ifndef __rtems__
void
tc_setclock(struct timespec *ts)
+#else /* __rtems__ */
+void
+_Timecounter_Set_clock(const struct timespec *ts)
+#endif /* __rtems__ */
{
+#ifndef __rtems__
struct timespec tbef, taft;
+#endif /* __rtems__ */
struct bintime bt, bt2;
+#ifndef __rtems__
cpu_tick_calibrate(1);
nanotime(&tbef);
+#endif /* __rtems__ */
timespec2bintime(ts, &bt);
binuptime(&bt2);
bintime_sub(&bt, &bt2);
bintime_add(&bt2, &boottimebin);
boottimebin = bt;
+#ifndef __rtems__
bintime2timeval(&bt, &boottime);
+#endif /* __rtems__ */
/* XXX fiddle all the little crinkly bits around the fiords... */
tc_windup();
+#ifndef __rtems__
nanotime(&taft);
if (timestepwarnings) {
log(LOG_INFO,
@@ -1236,6 +1325,7 @@ tc_setclock(struct timespec *ts)
(intmax_t)ts->tv_sec, ts->tv_nsec);
}
cpu_tick_calibrate(1);
+#endif /* __rtems__ */
}
/*
@@ -1243,6 +1333,7 @@ tc_setclock(struct timespec *ts)
* it the active timehands. Along the way we might switch to a different
* timecounter and/or do seconds processing in NTP. Slightly magic.
*/
+
static void
tc_windup(void)
{
@@ -1252,6 +1343,11 @@ tc_windup(void)
u_int delta, ncount, ogen;
int i;
time_t t;
+#ifdef __rtems__
+ ISR_lock_Context lock_context;
+
+ _ISR_lock_ISR_disable_and_acquire(_Timecounter_Lock, &lock_context);
+#endif /* __rtems__ */
/*
* Make the next timehands a copy of the current one, but do not
@@ -1329,12 +1425,14 @@ tc_windup(void)
/* Now is a good time to change timecounters. */
if (th->th_counter != timecounter) {
+#ifndef __rtems__
#ifndef __arm__
if ((timecounter->tc_flags & TC_FLAGS_C2STOP) != 0)
cpu_disable_c2_sleep++;
if ((th->th_counter->tc_flags & TC_FLAGS_C2STOP) != 0)
cpu_disable_c2_sleep--;
#endif
+#endif /* __rtems__ */
th->th_counter = timecounter;
th->th_offset_count = ncount;
tc_min_ticktock_freq = max(1, timecounter->tc_frequency /
@@ -1397,9 +1495,17 @@ tc_windup(void)
#endif
timehands = th;
+#ifndef __rtems__
timekeep_push_vdso();
+#endif /* __rtems__ */
+#ifdef __rtems__
+ _ISR_lock_Release_and_ISR_enable(_Timecounter_Lock, &lock_context);
+#endif /* __rtems__ */
}
+
+
+#ifndef __rtems__
/* Report or change the active timecounter hardware. */
static int
sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS)
@@ -1464,7 +1570,9 @@ sysctl_kern_timecounter_choice(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD,
0, 0, sysctl_kern_timecounter_choice, "A", "Timecounter hardware detected");
+#endif /* __rtems__ */
+#ifndef __rtems__
/*
* RFC 2783 PPS-API implementation.
*/
@@ -1745,6 +1853,7 @@ pps_event(struct pps_state *pps, int event)
/* Wakeup anyone sleeping in pps_fetch(). */
wakeup(pps);
}
+#endif /* __rtems__ */
/*
* Timecounters need to be updated every so often to prevent the hardware
@@ -1754,12 +1863,21 @@ pps_event(struct pps_state *pps, int event)
*/
static int tc_tick;
+#ifndef __rtems__
SYSCTL_INT(_kern_timecounter, OID_AUTO, tick, CTLFLAG_RD, &tc_tick, 0,
"Approximate number of hardclock ticks in a millisecond");
+#endif /* __rtems__ */
+#ifndef __rtems__
void
tc_ticktock(int cnt)
{
+#else /* __rtems__ */
+void
+_Timecounter_Tick(void)
+{
+ int cnt = 1;
+#endif /* __rtems__ */
static int count;
count += cnt;
@@ -1768,6 +1886,37 @@ tc_ticktock(int cnt)
count = 0;
tc_windup();
}
+#ifdef __rtems__
+void
+_Timecounter_Tick_simple(u_int delta, u_int offset)
+{
+ struct timehands *th;
+ u_int ogen;
+ ISR_lock_Context lock_context;
+
+ _ISR_lock_ISR_disable_and_acquire(_Timecounter_Lock, &lock_context);
+
+ th = timehands;
+ ogen = th->th_generation;
+ th->th_offset_count = offset;
+ bintime_addx(&th->th_offset, th->th_scale * delta);
+
+ /* Update the UTC timestamps used by the get*() functions. */
+ /* XXX shouldn't do this here. Should force non-`get' versions. */
+ bintime2timeval(&th->th_offset, &th->th_microtime);
+ bintime2timespec(&th->th_offset, &th->th_nanotime);
+
+ /*
+ * Now that the struct timehands is again consistent, set the new
+ * generation number, making sure to not make it zero.
+ */
+ if (++ogen == 0)
+ ogen = 1;
+ th->th_generation = ogen;
+
+ _ISR_lock_Release_and_ISR_enable(_Timecounter_Lock, &lock_context);
+}
+#endif /* __rtems__ */
static void __inline
tc_adjprecision(void)
@@ -1791,6 +1940,7 @@ tc_adjprecision(void)
sbt_tickthreshold = bttosbt(bt_tickthreshold);
}
+#ifndef __rtems__
static int
sysctl_kern_timecounter_adjprecision(SYSCTL_HANDLER_ARGS)
{
@@ -1807,9 +1957,15 @@ sysctl_kern_timecounter_adjprecision(SYSCTL_HANDLER_ARGS)
done:
return (0);
}
+#endif /* __rtems__ */
+#ifndef __rtems__
static void
inittimecounter(void *dummy)
+#else /* __rtems__ */
+void
+_Timecounter_Initialize(void)
+#endif /* __rtems__ */
{
u_int p;
int tick_rate;
@@ -1834,6 +1990,9 @@ inittimecounter(void *dummy)
tc_tick_sbt = bttosbt(tc_tick_bt);
p = (tc_tick * 1000000) / hz;
printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000);
+#ifdef __rtems__
+ (void) p;
+#endif /* __rtems__ */
#ifdef FFCLOCK
ffclock_init();
@@ -1844,8 +2003,11 @@ inittimecounter(void *dummy)
tc_windup();
}
+#ifndef __rtems__
SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_SECOND, inittimecounter, NULL);
+#endif /* __rtems__ */
+#ifndef __rtems__
/* Cpu tick handling -------------------------------------------------*/
static int cpu_tick_variable;
@@ -1978,7 +2140,9 @@ cputick2usec(uint64_t tick)
}
cpu_tick_f *cpu_ticks = tc_cpu_ticks;
+#endif /* __rtems__ */
+#ifndef __rtems__
static int vdso_th_enable = 1;
static int
sysctl_fast_gettime(SYSCTL_HANDLER_ARGS)
@@ -2014,6 +2178,7 @@ tc_fill_vdso_timehands(struct vdso_timehands *vdso_th)
enabled = 0;
return (enabled);
}
+#endif /* __rtems__ */
#ifdef COMPAT_FREEBSD32
uint32_t
diff --git a/testsuites/sptests/sptimecounter01/Makefile.am b/testsuites/sptests/sptimecounter01/Makefile.am
new file mode 100644
index 0000000..b231088
--- /dev/null
+++ b/testsuites/sptests/sptimecounter01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = sptimecounter01
+sptimecounter01_SOURCES = init.c
+
+dist_rtems_tests_DATA = sptimecounter01.scn sptimecounter01.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(sptimecounter01_OBJECTS)
+LINK_LIBS = $(sptimecounter01_LDLIBS)
+
+sptimecounter01$(EXEEXT): $(sptimecounter01_OBJECTS) $(sptimecounter01_DEPENDENCIES)
+ @rm -f sptimecounter01$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/sptimecounter01/init.c b/testsuites/sptests/sptimecounter01/init.c
new file mode 100644
index 0000000..a69e8bc
--- /dev/null
+++ b/testsuites/sptests/sptimecounter01/init.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <assert.h>
+
+#include <bsp/bootcard.h>
+
+#include <rtems/test.h>
+
+#include <rtems/score/timecounterimpl.h>
+#include <rtems/timecounter.h>
+#include <rtems/bsd.h>
+
+const char rtems_test_name[] = "SPTIMECOUNTER_1";
+
+typedef struct {
+ struct timecounter tc_soft;
+ u_int tc_soft_counter;
+} test_context;
+
+static test_context test_instance;
+
+static u_int test_get_timecount_soft(struct timecounter *tc)
+{
+ test_context *ctx = tc->tc_priv;
+
+ ++ctx->tc_soft_counter;
+
+ return ctx->tc_soft_counter;
+}
+
+void boot_card(const char *cmdline)
+{
+ test_context *ctx = &test_instance;
+ struct timecounter *tc_soft = &ctx->tc_soft;
+ uint64_t soft_freq = 1000000;
+ struct bintime bt;
+
+ rtems_test_begink();
+
+ _Timecounter_Initialize();
+
+ rtems_bsd_binuptime(&bt);
+ assert(bt.sec == 1);
+ assert(bt.frac== 73786976294835);
+
+ rtems_bsd_binuptime(&bt);
+ assert(bt.sec == 1);
+ assert(bt.frac == 92233720368543);
+
+ rtems_timecounter_tick();
+ rtems_bsd_binuptime(&bt);
+ assert(bt.sec == 1);
+ assert(bt.frac == 129127208515959);
+
+ ctx->tc_soft_counter = 0;
+ tc_soft->tc_get_timecount = test_get_timecount_soft;
+ tc_soft->tc_counter_mask = 0x0fffffff;
+ tc_soft->tc_frequency = soft_freq;
+ tc_soft->tc_quality = 1234;
+ tc_soft->tc_priv = ctx;
+ _Timecounter_Install(tc_soft);
+ assert(ctx->tc_soft_counter == 3);
+
+ rtems_bsd_binuptime(&bt);
+ assert(ctx->tc_soft_counter == 4);
+
+ assert(bt.sec == 1);
+ assert(bt.frac == 166020696663375);
+
+ ctx->tc_soft_counter = 0xf0000000 | 3;
+ rtems_bsd_binuptime(&bt);
+ assert(ctx->tc_soft_counter == (0xf0000000 | 4));
+
+ assert(bt.sec == 1);
+ assert(bt.frac == 166020696663375);
+
+ /* Ensure that the fraction overflows and the second remains constant */
+ ctx->tc_soft_counter = (0xf0000000 | 3) + soft_freq;
+ rtems_bsd_binuptime(&bt);
+ assert(ctx->tc_soft_counter == (0xf0000000 | 4) + soft_freq);
+ assert(bt.sec == 1);
+ assert(bt.frac == 166020695111759);
+
+ rtems_test_endk();
+
+ _Terminate(RTEMS_FATAL_SOURCE_EXIT, false, 0);
+}
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+
+#define CONFIGURE_APPLICATION_DISABLE_FILESYSTEM
+
+#define CONFIGURE_DISABLE_NEWLIB_REENTRANCY
+
+#define CONFIGURE_SCHEDULER_USER
+
+#define CONFIGURE_SCHEDULER_CONTEXT
+
+#define CONFIGURE_SCHEDULER_CONTROLS { }
+
+#define CONFIGURE_MEMORY_PER_TASK_FOR_SCHEDULER 0
+
+#define CONFIGURE_TASK_STACK_ALLOCATOR NULL
+
+#define CONFIGURE_TASK_STACK_DEALLOCATOR NULL
+
+#define CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION
+
+#define CONFIGURE_IDLE_TASK_BODY NULL
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/sptests/sptimecounter01/sptimecounter01.doc b/testsuites/sptests/sptimecounter01/sptimecounter01.doc
new file mode 100644
index 0000000..4a7442c
--- /dev/null
+++ b/testsuites/sptests/sptimecounter01/sptimecounter01.doc
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems at 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.
+ */
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: sptimecounter01
+
+directives:
+
+ _Timecounter_Initialize
+ rtems_timecounter_tick
+ _Timecounter_Install
+ rtems_bsd_bintime
+
+concepts:
+
+ This test checks the correct functioning of the FreeBSD timecounter startup
+ process
diff --git a/testsuites/sptests/sptimecounter01/sptimecounter01.scn b/testsuites/sptests/sptimecounter01/sptimecounter01.scn
new file mode 100644
index 0000000..5fa9c0f
--- /dev/null
+++ b/testsuites/sptests/sptimecounter01/sptimecounter01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SPTIMECOUNTER_1 ***
+*** END OF TEST SPTIMECOUNTER_1 ***
--
1.8.4.5
More information about the devel
mailing list