summaryrefslogtreecommitdiffstats
path: root/cpukit/sapi/include/rtems
diff options
context:
space:
mode:
authorAlexander Krutwig <alexander.krutwig@embedded-brains.de>2015-04-20 11:08:22 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-05-20 08:40:29 +0200
commit31be41653a659a52460734cb8fe1da27e6d5629e (patch)
tree098c18a376b2f180a719af07406aaadf275b3716 /cpukit/sapi/include/rtems
parenttimecounter: Honor FFCLOCK define (diff)
downloadrtems-31be41653a659a52460734cb8fe1da27e6d5629e.tar.bz2
timecounter: Port to RTEMS
New test sptests/timecounter01. Update #2271.
Diffstat (limited to 'cpukit/sapi/include/rtems')
-rw-r--r--cpukit/sapi/include/rtems/bsd.h141
-rw-r--r--cpukit/sapi/include/rtems/timecounter.h304
2 files changed, 445 insertions, 0 deletions
diff --git a/cpukit/sapi/include/rtems/bsd.h b/cpukit/sapi/include/rtems/bsd.h
new file mode 100644
index 0000000000..0c44e3787d
--- /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@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 0000000000..04bc534d55
--- /dev/null
+++ b/cpukit/sapi/include/rtems/timecounter.h
@@ -0,0 +1,304 @@
+/**
+ * @file
+ *
+ * @ingroup SAPITimecounter
+ *
+ * @brief Timecounter API
+ */
+
+/*
+ * Copyright (c) 2015 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.
+ */
+
+#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 favour 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
+ * struct timecounter tc;
+ *
+ * uint32_t get_timecount( struct timecounter *tc )
+ * {
+ * return some_free_running_counter;
+ * }
+ *
+ * void install( void )
+ * {
+ * tc.tc_get_timecount = get_timecount;
+ * tc.tc_counter_mask = 0xffffffff;
+ * tc.tc_frequency = 123456;
+ * tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ * rtems_timecounter_install( &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();
+}
+
+/**
+ * @brief Simple timecounter to support legacy clock drivers.
+ */
+typedef struct {
+ struct timecounter tc;
+ uint64_t scaler;
+ uint32_t real_interval;
+ uint32_t binary_interval;
+} rtems_timecounter_simple;
+
+/**
+ * @brief Returns the current value of a simple timecounter.
+ */
+typedef uint32_t rtems_timecounter_simple_get(
+ rtems_timecounter_simple *tc
+);
+
+/**
+ * @brief Returns true if the interrupt of a simple timecounter is pending, and
+ * false otherwise.
+ */
+typedef bool rtems_timecounter_simple_is_pending(
+ rtems_timecounter_simple *tc
+);
+
+/**
+ * @brief Initializes and installs a simple timecounter.
+ *
+ * A simple timecounter can be used if the hardware provides no free running
+ * counter or only the module used for the clock tick is available. The period
+ * of the simple timecounter equals the clock tick interval. The interval is
+ * scaled up to the next power of two.
+ *
+ * @param[in] tc Zero initialized simple timecounter.
+ * @param[in] frequency_in_hz The timecounter frequency in Hz.
+ * @param[in] timecounter_ticks_per_clock_tick The timecounter ticks per clock tick.
+ * @param[in] get_timecount The method to get the current time count.
+ *
+ * @code
+ * #include <rtems/timecounter.h>
+ *
+ * static rtems_timecounter_simple some_tc;
+ *
+ * static uint32_t some_tc_get( rtems_timecounter_simple *tc )
+ * {
+ * return some.value;
+ * }
+ *
+ * static bool some_tc_is_pending( rtems_timecounter_simple *tc )
+ * {
+ * return some.is_pending;
+ * }
+ *
+ * static uint32_t some_tc_get_timecount( struct timecounter *tc )
+ * {
+ * return rtems_timecounter_simple_downcounter_get(
+ * tc,
+ * some_tc_get,
+ * some_tc_is_pending
+ * );
+ * }
+ *
+ * static void some_tc_tick( void )
+ * {
+ * rtems_timecounter_simple_downcounter_tick( &some_tc, some_tc_get );
+ * }
+ *
+ * void install( void )
+ * {
+ * uint32_t frequency = 123456;
+ * uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
+ * uint32_t timecounter_ticks_per_clock_tick =
+ * ( frequency * us_per_tick ) / 1000000;
+ *
+ * rtems_timecounter_simple_install(
+ * &some_tc,
+ * frequency,
+ * timecounter_ticks_per_clock_tick,
+ * some_tc_get_timecount
+ * );
+ * }
+ * @endcode
+ *
+ * @see rtems_timecounter_simple_downcounter_get(),
+ * rtems_timecounter_simple_downcounter_tick(),
+ * rtems_timecounter_simple_upcounter_get() and
+ * rtems_timecounter_simple_upcounter_tick().
+ */
+void rtems_timecounter_simple_install(
+ rtems_timecounter_simple *tc,
+ uint32_t frequency_in_hz,
+ uint32_t timecounter_ticks_per_clock_tick,
+ timecounter_get_t *get_timecount
+);
+
+/**
+ * @brief Maps a simple timecounter value into its binary frequency domain.
+ *
+ * @param[in] tc The simple timecounter.
+ * @param[in] value The value of the simple timecounter.
+ *
+ * @return The scaled value.
+ */
+RTEMS_INLINE_ROUTINE uint32_t rtems_timecounter_simple_scale(
+ const rtems_timecounter_simple *tc,
+ uint32_t value
+)
+{
+ return (uint32_t) ( ( value * tc->scaler ) >> 32 );
+}
+
+/**
+ * @brief Performs a simple timecounter tick for downcounters.
+ *
+ * @param[in] tc The simple timecounter.
+ * @param[in] get The method to get the value of the simple timecounter.
+ */
+RTEMS_INLINE_ROUTINE void rtems_timecounter_simple_downcounter_tick(
+ rtems_timecounter_simple *tc,
+ rtems_timecounter_simple_get get
+)
+{
+ uint32_t current;
+
+ current = rtems_timecounter_simple_scale(
+ tc,
+ tc->real_interval - ( *get )( tc )
+ );
+
+ _Timecounter_Tick_simple( tc->binary_interval, current );
+}
+
+/**
+ * @brief Performs a simple timecounter tick for upcounters.
+ *
+ * @param[in] tc The simple timecounter.
+ * @param[in] get The method to get the value of the simple timecounter.
+ */
+RTEMS_INLINE_ROUTINE void rtems_timecounter_simple_upcounter_tick(
+ rtems_timecounter_simple *tc,
+ rtems_timecounter_simple_get get
+)
+{
+ uint32_t current;
+
+ current = rtems_timecounter_simple_scale( tc, ( *get )( tc ) );
+
+ _Timecounter_Tick_simple( tc->binary_interval, current );
+}
+
+/**
+ * @brief Gets the simple timecounter value mapped to its binary frequency
+ * domain for downcounters.
+ *
+ * @param[in] tc The simple timecounter.
+ * @param[in] get The method to get the value of the simple timecounter.
+ * @param[in] is_pending The method which indicates if the interrupt of the
+ * simple timecounter is pending.
+ */
+RTEMS_INLINE_ROUTINE uint32_t rtems_timecounter_simple_downcounter_get(
+ struct timecounter *tc_base,
+ rtems_timecounter_simple_get get,
+ rtems_timecounter_simple_is_pending is_pending
+)
+{
+ rtems_timecounter_simple *tc;
+ uint32_t counter;
+ uint32_t interval;
+
+ tc = (rtems_timecounter_simple *) tc_base;
+ counter = ( *get )( tc );
+ interval = tc->real_interval;
+
+ if ( ( *is_pending )( tc ) ) {
+ counter = ( *get )( tc );
+ interval *= 2;
+ }
+
+ return rtems_timecounter_simple_scale( tc, interval - counter );
+}
+
+/**
+ * @brief Gets the simple timecounter value mapped to its binary frequency
+ * domain for upcounters.
+ *
+ * @param[in] tc The simple timecounter.
+ * @param[in] get The method to get the value of the simple timecounter.
+ * @param[in] is_pending The method which indicates if the interrupt of the
+ * simple timecounter is pending.
+ */
+RTEMS_INLINE_ROUTINE uint32_t rtems_timecounter_simple_upcounter_get(
+ struct timecounter *tc_base,
+ rtems_timecounter_simple_get get,
+ rtems_timecounter_simple_is_pending is_pending
+)
+{
+ rtems_timecounter_simple *tc;
+ uint32_t counter;
+ uint32_t interval;
+
+ tc = (rtems_timecounter_simple *) tc_base;
+ counter = ( *get )( tc );
+ interval = 0;
+
+ if ( ( *is_pending )( tc ) ) {
+ counter = ( *get )( tc );
+ interval = tc->real_interval;
+ }
+
+ return rtems_timecounter_simple_scale( tc, interval + counter );
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _RTEMS_TIMECOUNTER_H */