[PATCH v2] rtems: Add more clock tick functions
Sebastian Huber
sebastian.huber at embedded-brains.de
Mon Aug 25 10:05:11 UTC 2014
Add rtems_clock_tick_later(), rtems_clock_tick_later_usec() and
rtems_clock_tick_before().
---
cpukit/rtems/include/rtems/rtems/clock.h | 71 +++++++++++++++++++++
doc/user/clock.t | 104 +++++++++++++++++++++++++++++++
testsuites/sptests/sp37/init.c | 55 ++++++++++++++++
testsuites/sptests/sp37/sp37.doc | 5 ++
testsuites/sptests/sp37/system.h | 4 ++
5 files changed, 239 insertions(+)
diff --git a/cpukit/rtems/include/rtems/rtems/clock.h b/cpukit/rtems/include/rtems/rtems/clock.h
index ff71665..7595f5e 100644
--- a/cpukit/rtems/include/rtems/rtems/clock.h
+++ b/cpukit/rtems/include/rtems/rtems/clock.h
@@ -34,6 +34,7 @@
#include <rtems/score/tod.h>
#include <rtems/rtems/status.h>
#include <rtems/rtems/types.h>
+#include <rtems/config.h>
#include <sys/time.h> /* struct timeval */
@@ -160,6 +161,76 @@ RTEMS_INLINE_ROUTINE rtems_interval rtems_clock_get_ticks_since_boot(void)
}
/**
+ * @brief Returns the ticks counter value delta ticks in the future.
+ *
+ * @param[in] delta The ticks delta value.
+ *
+ * @return The tick counter value delta ticks in the future.
+ */
+RTEMS_INLINE_ROUTINE rtems_interval rtems_clock_tick_later(
+ rtems_interval delta
+)
+{
+ return _Watchdog_Ticks_since_boot + delta;
+}
+
+/**
+ * @brief Returns the ticks counter value at least delta microseconds in the
+ * future.
+ *
+ * @param[in] delta_in_usec The delta value in microseconds.
+ *
+ * @return The tick counter value at least delta microseconds in the future.
+ */
+RTEMS_INLINE_ROUTINE rtems_interval rtems_clock_tick_later_usec(
+ rtems_interval delta_in_usec
+)
+{
+ rtems_interval us_per_tick = rtems_configuration_get_microseconds_per_tick();
+
+ /*
+ * Add one additional tick, since we don't know the time to the clock next
+ * tick.
+ */
+ return _Watchdog_Ticks_since_boot
+ + (delta_in_usec + us_per_tick - 1) / us_per_tick + 1;
+}
+
+/**
+ * @brief Returns true if the current ticks counter value indicates a time
+ * before the time specified by the tick value and false otherwise.
+ *
+ * @param[in] tick The tick value.
+ *
+ * This can be used to write busy loops with a timeout.
+ *
+ * @code
+ * status busy( void )
+ * {
+ * rtems_interval timeout = rtems_clock_tick_later_usec( 10000 );
+ *
+ * do {
+ * if ( ok() ) {
+ * return success;
+ * }
+ * } while ( rtems_clock_tick_before( timeout ) );
+ *
+ * return timeout;
+ * }
+ * @endcode
+ *
+ * @retval true The current ticks counter value indicates a time before the
+ * time specified by the tick value.
+ * @retval false Otherwise.
+ */
+RTEMS_INLINE_ROUTINE bool rtems_clock_tick_before(
+ rtems_interval tick
+)
+{
+ return (int32_t) ( tick - _Watchdog_Ticks_since_boot ) > 0;
+}
+
+/**
* @brief Obtain Ticks Per Seconds
*
* This routine implements the rtems_clock_get_ticks_per_second
diff --git a/doc/user/clock.t b/doc/user/clock.t
index 921d1cb..1e821ad 100644
--- a/doc/user/clock.t
+++ b/doc/user/clock.t
@@ -21,6 +21,9 @@ the clock manager are:
@item @code{@value{DIRPREFIX}clock_get_seconds_since_epoch} - Get seconds since epoch
@item @code{@value{DIRPREFIX}clock_get_ticks_per_second} - Get ticks per second
@item @code{@value{DIRPREFIX}clock_get_ticks_since_boot} - Get current ticks counter value
+ at item @code{@value{DIRPREFIX}clock_tick_later} - Get tick value in the future
+ at item @code{@value{DIRPREFIX}clock_tick_later_usec} - Get tick value in the future in microseconds
+ at item @code{@value{DIRPREFIX}clock_tick_before} - Is tick value is before a point in time
@item @code{@value{DIRPREFIX}clock_get_uptime} - Get time since boot
@item @code{@value{DIRPREFIX}clock_get_uptime_timeval} - Get time since boot in timeval format
@item @code{@value{DIRPREFIX}clock_get_uptime_seconds} - Get seconds since boot
@@ -617,6 +620,107 @@ This directive will not cause the running task to be preempted.
@c
@c
@page
+ at subsection CLOCK_TICK_LATER - Get tick value in the future
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C
+ at findex rtems_clock_tick_later
+ at example
+rtems_interval rtems_clock_tick_later(
+ rtems_interval delta
+);
+ at end example
+ at end ifset
+
+ at subheading DESCRIPTION:
+
+Returns the ticks counter value delta ticks in the future.
+
+ at subheading NOTES:
+
+This directive is callable from an ISR.
+
+This directive will not cause the running task to be preempted.
+
+ at c
+ at c
+ at c
+ at page
+ at subsection CLOCK_TICK_LATER_USEC - Get tick value in the future in microseconds
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C
+ at findex rtems_clock_tick_later_usec
+ at example
+rtems_interval rtems_clock_tick_later_usec(
+ rtems_interval delta_in_usec
+);
+ at end example
+ at end ifset
+
+ at subheading DESCRIPTION:
+
+Returns the ticks counter value at least delta microseconds in the future.
+
+ at subheading NOTES:
+
+This directive is callable from an ISR.
+
+This directive will not cause the running task to be preempted.
+
+ at c
+ at c
+ at c
+ at page
+ at subsection CLOCK_TICK_BEFORE - Is tick value is before a point in time
+
+ at subheading CALLING SEQUENCE:
+
+ at ifset is-C
+ at findex rtems_clock_tick_before
+ at example
+rtems_interval rtems_clock_tick_before(
+ rtems_interval tick
+);
+ at end example
+ at end ifset
+
+ at subheading DESCRIPTION:
+
+Returns true if the current ticks counter value indicates a time before the
+time specified by the tick value and false otherwise.
+
+ at subheading NOTES:
+
+This directive is callable from an ISR.
+
+This directive will not cause the running task to be preempted.
+
+ at subheading EXAMPLE:
+
+ at example
+ at group
+status busy( void )
+@{
+ rtems_interval timeout = rtems_clock_tick_later_usec( 10000 );
+
+ do @{
+ if ( ok() ) @{
+ return success;
+ @}
+ @} while ( rtems_clock_tick_before( timeout ) );
+
+ return timeout;
+@}
+ at end group
+ at end example
+
+ at c
+ at c
+ at c
+ at page
@subsection CLOCK_GET_UPTIME - Get the time since boot
@cindex clock get uptime
diff --git a/testsuites/sptests/sp37/init.c b/testsuites/sptests/sp37/init.c
index be0bd32..60ae01b 100644
--- a/testsuites/sptests/sp37/init.c
+++ b/testsuites/sptests/sp37/init.c
@@ -230,6 +230,59 @@ static void test_interrupt_locks( void )
rtems_interrupt_lock_destroy( &initialized );
}
+static void test_clock_tick_functions( void )
+{
+ rtems_interrupt_level level;
+ Watchdog_Interval saved_ticks;
+
+ _Thread_Disable_dispatch();
+ rtems_interrupt_disable( level );
+
+ saved_ticks = _Watchdog_Ticks_since_boot;
+
+ _Watchdog_Ticks_since_boot = 0xdeadbeef;
+ rtems_test_assert( rtems_clock_get_ticks_since_boot() == 0xdeadbeef );
+
+ rtems_test_assert( rtems_clock_tick_later( 0 ) == 0xdeadbeef );
+ rtems_test_assert( rtems_clock_tick_later( 0x8160311e ) == 0x600df00d );
+
+ _Watchdog_Ticks_since_boot = 0;
+ rtems_test_assert( rtems_clock_tick_later_usec( 0 ) == 1 );
+ rtems_test_assert( rtems_clock_tick_later_usec( 1 ) == 2 );
+ rtems_test_assert( rtems_clock_tick_later_usec( US_PER_TICK ) == 2 );
+ rtems_test_assert( rtems_clock_tick_later_usec( US_PER_TICK + 1 ) == 3 );
+
+ _Watchdog_Ticks_since_boot = 0;
+ rtems_test_assert( !rtems_clock_tick_before( 0xffffffff ) );
+ rtems_test_assert( !rtems_clock_tick_before( 0 ) );
+ rtems_test_assert( rtems_clock_tick_before( 1 ) );
+
+ _Watchdog_Ticks_since_boot = 1;
+ rtems_test_assert( !rtems_clock_tick_before( 0 ) );
+ rtems_test_assert( !rtems_clock_tick_before( 1 ) );
+ rtems_test_assert( rtems_clock_tick_before( 2 ) );
+
+ _Watchdog_Ticks_since_boot = 0x7fffffff;
+ rtems_test_assert( !rtems_clock_tick_before( 0x7ffffffe ) );
+ rtems_test_assert( !rtems_clock_tick_before( 0x7fffffff ) );
+ rtems_test_assert( rtems_clock_tick_before( 0x80000000 ) );
+
+ _Watchdog_Ticks_since_boot = 0x80000000;
+ rtems_test_assert( !rtems_clock_tick_before( 0x7fffffff ) );
+ rtems_test_assert( !rtems_clock_tick_before( 0x80000000 ) );
+ rtems_test_assert( rtems_clock_tick_before( 0x80000001 ) );
+
+ _Watchdog_Ticks_since_boot = 0xffffffff;
+ rtems_test_assert( !rtems_clock_tick_before( 0xfffffffe ) );
+ rtems_test_assert( !rtems_clock_tick_before( 0xffffffff ) );
+ rtems_test_assert( rtems_clock_tick_before( 0 ) );
+
+ _Watchdog_Ticks_since_boot = saved_ticks;
+
+ rtems_interrupt_enable( level );
+ _Thread_Enable_dispatch();
+}
+
void test_interrupt_inline(void)
{
rtems_interrupt_level level;
@@ -413,6 +466,8 @@ rtems_task Init(
directive_failed( status, "rtems_clock_tick" );
puts( "clock_tick from task level" );
+ test_clock_tick_functions();
+
/*
* Now do a dispatch directly out of a clock tick that is
* called from a task. We need to create a task that will
diff --git a/testsuites/sptests/sp37/sp37.doc b/testsuites/sptests/sp37/sp37.doc
index 9e814f2..b98faa1 100644
--- a/testsuites/sptests/sp37/sp37.doc
+++ b/testsuites/sptests/sp37/sp37.doc
@@ -13,6 +13,9 @@ test set name: sp37
directives:
rtems_clock_tick
+ rtems_clock_tick_later()
+ rtems_clock_tick_later_usec()
+ rtems_clock_tick_before()
rtems_interrupt_disable (inline/body)
rtems_interrupt_enable (inline/body)
rtems_interrupt_flash (inline/body)
@@ -24,6 +27,8 @@ concepts:
+ Ensure that rtems_clock_tick operates properly when invoked from a task
rather than an ISR.
++ Ensure that clock tick counter functions work properly.
+
+ Ensure that the interrupt disable, enable, and flash directives operate
as expected.
diff --git a/testsuites/sptests/sp37/system.h b/testsuites/sptests/sp37/system.h
index 43bef81..6bb47ec 100644
--- a/testsuites/sptests/sp37/system.h
+++ b/testsuites/sptests/sp37/system.h
@@ -15,6 +15,8 @@
#include <tmacros.h>
+#define US_PER_TICK 10000
+
/* functions */
rtems_task Init(
@@ -28,6 +30,8 @@ rtems_task Init(
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+#define CONFIGURE_MICROSECONDS_PER_TICK US_PER_TICK
+
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_INIT_TASK_PRIORITY 2
#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_PREEMPT
--
1.8.4.5
More information about the devel
mailing list