rtems: Add more clock tick functions

Add rtems_clock_tick_later(), rtems_clock_tick_later_usec() and
rtems_clock_tick_before().
This commit is contained in:
Sebastian Huber
2014-08-22 17:09:36 +02:00
parent 8f1bdcb9ad
commit 96ec8ee80a
5 changed files with 239 additions and 0 deletions

View File

@@ -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 */
@@ -159,6 +160,76 @@ RTEMS_INLINE_ROUTINE rtems_interval rtems_clock_get_ticks_since_boot(void)
return _Watchdog_Ticks_since_boot;
}
/**
* @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
*

View File

@@ -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
@item @code{@value{DIRPREFIX}clock_tick_later} - Get tick value in the future
@item @code{@value{DIRPREFIX}clock_tick_later_usec} - Get tick value in the future in microseconds
@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
@@ -613,6 +616,107 @@ This directive is callable from an ISR.
This directive will not cause the running task to be preempted.
@c
@c
@c
@page
@subsection CLOCK_TICK_LATER - Get tick value in the future
@subheading CALLING SEQUENCE:
@ifset is-C
@findex rtems_clock_tick_later
@example
rtems_interval rtems_clock_tick_later(
rtems_interval delta
);
@end example
@end ifset
@subheading DESCRIPTION:
Returns the ticks counter value delta ticks in the future.
@subheading NOTES:
This directive is callable from an ISR.
This directive will not cause the running task to be preempted.
@c
@c
@c
@page
@subsection CLOCK_TICK_LATER_USEC - Get tick value in the future in microseconds
@subheading CALLING SEQUENCE:
@ifset is-C
@findex rtems_clock_tick_later_usec
@example
rtems_interval rtems_clock_tick_later_usec(
rtems_interval delta_in_usec
);
@end example
@end ifset
@subheading DESCRIPTION:
Returns the ticks counter value at least delta microseconds in the future.
@subheading NOTES:
This directive is callable from an ISR.
This directive will not cause the running task to be preempted.
@c
@c
@c
@page
@subsection CLOCK_TICK_BEFORE - Is tick value is before a point in time
@subheading CALLING SEQUENCE:
@ifset is-C
@findex rtems_clock_tick_before
@example
rtems_interval rtems_clock_tick_before(
rtems_interval tick
);
@end example
@end ifset
@subheading DESCRIPTION:
Returns true if the current ticks counter value indicates a time before the
time specified by the tick value and false otherwise.
@subheading NOTES:
This directive is callable from an ISR.
This directive will not cause the running task to be preempted.
@subheading EXAMPLE:
@example
@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;
@}
@end group
@end example
@c
@c
@c

View File

@@ -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

View File

@@ -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.

View File

@@ -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