[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