[rtems commit] validation: Test timecounter

Sebastian Huber sebh at rtems.org
Thu Mar 24 10:01:58 UTC 2022


Module:    rtems
Branch:    master
Commit:    7eb4fc8d4331d3c1423c9d0b573141e70022cf11
Changeset: http://git.rtems.org/rtems/commit/?id=7eb4fc8d4331d3c1423c9d0b573141e70022cf11

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Dec  9 16:19:41 2021 +0100

validation: Test timecounter

The test source code is generated from specification items
by the "./spec2modules.py" script contained in the
git://git.rtems.org/rtems-central.git Git repository.

Please read the "How-To" section in the "Software Requirements Engineering"
chapter of the RTEMS Software Engineering manual to get more information about
the process.

Update #3716.

---

 spec/build/testsuites/validation/grp.yml           |    6 +
 .../validation/validation-timecounter-0.yml        |   20 +
 .../validation/validation-timecounter-1.yml        |   20 +
 .../validation/validation-timecounter-smp-0.yml    |   20 +
 testsuites/validation/tc-timecounter-get-smp.c     |  741 +++++++++++++
 testsuites/validation/tc-timecounter-get.c         |  575 ++++++++++
 testsuites/validation/tc-timecounter-install.c     | 1134 ++++++++++++++++++++
 .../validation/ts-validation-timecounter-0.c       |   77 ++
 .../validation/ts-validation-timecounter-1.c       |   75 ++
 .../validation/ts-validation-timecounter-smp-0.c   |   77 ++
 10 files changed, 2745 insertions(+)

diff --git a/spec/build/testsuites/validation/grp.yml b/spec/build/testsuites/validation/grp.yml
index 0382321..6541aff 100644
--- a/spec/build/testsuites/validation/grp.yml
+++ b/spec/build/testsuites/validation/grp.yml
@@ -60,6 +60,12 @@ links:
   uid: validation-smp-only-1
 - role: build-dependency
   uid: validation-smp-only-2
+- role: build-dependency
+  uid: validation-timecounter-0
+- role: build-dependency
+  uid: validation-timecounter-1
+- role: build-dependency
+  uid: validation-timecounter-smp-0
 type: build
 use-after:
 - validation
diff --git a/spec/build/testsuites/validation/validation-timecounter-0.yml b/spec/build/testsuites/validation/validation-timecounter-0.yml
new file mode 100644
index 0000000..b44a840
--- /dev/null
+++ b/spec/build/testsuites/validation/validation-timecounter-0.yml
@@ -0,0 +1,20 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: test-program
+cflags: []
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+cppflags: []
+cxxflags: []
+enabled-by: true
+features: c cprogram
+includes: []
+ldflags: []
+links: []
+source:
+- testsuites/validation/tc-timecounter-install.c
+- testsuites/validation/ts-validation-timecounter-0.c
+stlib: []
+target: testsuites/validation/ts-validation-timecounter-0.exe
+type: build
+use-after: []
+use-before: []
diff --git a/spec/build/testsuites/validation/validation-timecounter-1.yml b/spec/build/testsuites/validation/validation-timecounter-1.yml
new file mode 100644
index 0000000..c755cf1
--- /dev/null
+++ b/spec/build/testsuites/validation/validation-timecounter-1.yml
@@ -0,0 +1,20 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: test-program
+cflags: []
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+cppflags: []
+cxxflags: []
+enabled-by: true
+features: c cprogram
+includes: []
+ldflags: []
+links: []
+source:
+- testsuites/validation/tc-timecounter-get.c
+- testsuites/validation/ts-validation-timecounter-1.c
+stlib: []
+target: testsuites/validation/ts-validation-timecounter-1.exe
+type: build
+use-after: []
+use-before: []
diff --git a/spec/build/testsuites/validation/validation-timecounter-smp-0.yml b/spec/build/testsuites/validation/validation-timecounter-smp-0.yml
new file mode 100644
index 0000000..ff29bd1
--- /dev/null
+++ b/spec/build/testsuites/validation/validation-timecounter-smp-0.yml
@@ -0,0 +1,20 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: test-program
+cflags: []
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+cppflags: []
+cxxflags: []
+enabled-by: RTEMS_SMP
+features: c cprogram
+includes: []
+ldflags: []
+links: []
+source:
+- testsuites/validation/tc-timecounter-get-smp.c
+- testsuites/validation/ts-validation-timecounter-smp-0.c
+stlib: []
+target: testsuites/validation/ts-validation-timecounter-smp-0.exe
+type: build
+use-after: []
+use-before: []
diff --git a/testsuites/validation/tc-timecounter-get-smp.c b/testsuites/validation/tc-timecounter-get-smp.c
new file mode 100644
index 0000000..520d532
--- /dev/null
+++ b/testsuites/validation/tc-timecounter-get-smp.c
@@ -0,0 +1,741 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseScoreTimecounterValGetSmp
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated.  If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual.  The manual is provided as a part of
+ * a release.  For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/counter.h>
+#include <rtems/timecounter.h>
+#include <rtems/score/smpbarrier.h>
+#include <rtems/score/threaddispatch.h>
+
+#include "tx-support.h"
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestCaseScoreTimecounterValGetSmp \
+ *   spec:/score/timecounter/val/get-smp
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationTimecounterSmp0
+ *
+ * @brief Tests directives to get a time value.
+ *
+ * This test case performs the following actions:
+ *
+ * - Install timecounter of different quality levels and frequencies.
+ *
+ *   - Call the rtems_clock_get_realtime() directive and let it observe a
+ *     generation number of zero as well as a generation number change.
+ *
+ *   - Call the rtems_clock_get_realtime_bintime() directive and let it observe
+ *     a generation number of zero as well as a generation number change.
+ *
+ *   - Call the rtems_clock_get_realtime_timeval() directive and let it observe
+ *     a generation number of zero as well as a generation number change.
+ *
+ *   - Call the rtems_clock_get_monotonic() directive and let it observe a
+ *     generation number of zero as well as a generation number change.
+ *
+ *   - Call the rtems_clock_get_monotonic_bintime() directive and let it
+ *     observe a generation number of zero as well as a generation number
+ *     change.
+ *
+ *   - Call the rtems_clock_get_monotonic_sbintime() directive and let it
+ *     observe a generation number of zero as well as a generation number
+ *     change.
+ *
+ *   - Call the rtems_clock_get_monotonic_timeval() directive and let it
+ *     observe a generation number of zero as well as a generation number
+ *     change.
+ *
+ *   - Delete the synchronous worker task.  Reinitialize the barrier and
+ *     barrier states.  Start the zero worker task.
+ *
+ *   - Call the rtems_clock_get_realtime_coarse() directive and try to let it
+ *     observe a generation number of zero.
+ *
+ *   - Call the rtems_clock_get_realtime_coarse_bintime() directive and try to
+ *     let it observe a generation number of zero.
+ *
+ *   - Call the rtems_clock_get_realtime_coarse_timeval() directive and try to
+ *     let it observe a generation number of zero.
+ *
+ *   - Call the rtems_clock_get_monotonic_coarse() directive and try to let it
+ *     observe a generation number of zero.
+ *
+ *   - Call the rtems_clock_get_monotonic_coarse_bintime() directive and try to
+ *     let it observe a generation number of zero.
+ *
+ *   - Call the rtems_clock_get_monotonic_coarse_timeval() directive and try to
+ *     let it observe a generation number of zero.
+ *
+ *   - Call the rtems_clock_get_boot_time() directive and try to let it observe
+ *     a generation number of zero.
+ *
+ *   - Call the rtems_clock_get_boot_time_bintime() directive and try to let it
+ *     observe a generation number of zero.
+ *
+ *   - Call the rtems_clock_get_boot_time_timeval() directive and try to let it
+ *     observe a generation number of zero.
+ *
+ *   - Delete the zero worker task.  Reinitialize the barrier and barrier
+ *     states.  Start the change worker task.
+ *
+ *   - Call the rtems_clock_get_realtime_coarse() directive and try to let it
+ *     observe a changing generation number.
+ *
+ *   - Call the rtems_clock_get_realtime_coarse_bintime() directive and try to
+ *     let it observe a changing generation number.
+ *
+ *   - Call the rtems_clock_get_realtime_coarse_timeval() directive and try to
+ *     let it observe a changing generation number.
+ *
+ *   - Call the rtems_clock_get_monotonic_coarse() directive and try to let it
+ *     observe a changing generation number.
+ *
+ *   - Call the rtems_clock_get_monotonic_coarse_bintime() directive and try to
+ *     let it observe a changing generation number.
+ *
+ *   - Call the rtems_clock_get_monotonic_coarse_timeval() directive and try to
+ *     let it observe a changing generation number.
+ *
+ *   - Call the rtems_clock_get_boot_time() directive and try to let it observe
+ *     a changing generation number.
+ *
+ *   - Call the rtems_clock_get_boot_time_bintime() directive and try to let it
+ *     observe a changing generation number.
+ *
+ *   - Call the rtems_clock_get_boot_time_timeval() directive and try to let it
+ *     observe a changing generation number.
+ *
+ *   - Delete the change worker task.
+ *
+ * @{
+ */
+
+typedef struct {
+  struct timecounter  base;
+  Atomic_Ulong        counter;
+  Atomic_Uint        *generation_0;
+  Atomic_Uint        *generation_1;
+  SMP_barrier_Control barrier;
+  SMP_barrier_State   barrier_state[ 2 ];
+} Timecounter;
+
+static Timecounter test_timecounter;
+
+static uint32_t GetTimecount( struct timecounter *base )
+{
+  Timecounter *tc;
+
+  tc = (Timecounter *) base;
+
+  return (uint32_t) _Atomic_Fetch_add_ulong(
+    &tc->counter,
+    1,
+    ATOMIC_ORDER_RELAXED
+  );
+}
+
+static uint32_t GetTimecountBarrier( struct timecounter *base )
+{
+  Timecounter *tc;
+
+  tc = (Timecounter *) base;
+
+  /* C0, C1, C2 */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+  /* D0, D1, D2 */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+  return GetTimecount( &tc->base );
+}
+
+static uint32_t GetCounter( const Timecounter *tc )
+{
+  return (uint32_t) _Atomic_Load_ulong(
+    &tc->counter,
+    ATOMIC_ORDER_RELAXED
+  );
+}
+
+static void SetCounter( Timecounter *tc, uint32_t counter )
+{
+  _Atomic_Store_ulong(
+    &tc->counter,
+    counter,
+    ATOMIC_ORDER_RELAXED
+  );
+}
+
+static void CallTimecounterTick( void )
+{
+  Per_CPU_Control *cpu_self;
+
+  cpu_self = _Thread_Dispatch_disable();
+  rtems_timecounter_tick();
+  _Thread_Dispatch_enable( cpu_self );
+}
+
+static void SetGeneration( Timecounter *tc, unsigned int generation )
+{
+  _Atomic_Store_uint( tc->generation_0, generation, ATOMIC_ORDER_RELAXED );
+  _Atomic_Store_uint( tc->generation_1, generation, ATOMIC_ORDER_RELAXED );
+}
+
+static void PrepareSynchronousWork( Timecounter *tc )
+{
+  /* A */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+  SetCounter( tc, 0 );
+
+  /* B */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+}
+
+static void CleanupSynchronousWork( Timecounter *tc )
+{
+  /* E */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+  T_eq_u32( GetCounter( tc ), 3 );
+}
+
+static void SynchronousWorker( rtems_task_argument arg )
+{
+  Timecounter *tc;
+
+  tc = (Timecounter *) arg;
+
+  while ( true ) {
+    /* A */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    SetGeneration( tc, 0 );
+
+    /* B */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    /* C0 */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    SetGeneration( tc, 1 );
+
+    /* D0 */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    /* C1 */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    SetGeneration( tc, 2 );
+
+    /* D1 */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    /* C2 */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    /* D2 */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    /* E */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+  }
+}
+
+static void PrepareZeroWork( Timecounter *tc )
+{
+  /* F */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+  SetCounter( tc, 0 );
+
+  /* G */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+}
+
+static void CleanupZeroWork( Timecounter *tc )
+{
+  /* H */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+  T_eq_u32( GetCounter( tc ), 0 );
+}
+
+static void ZeroWorker( rtems_task_argument arg )
+{
+  Timecounter *tc;
+
+  tc = (Timecounter *) arg;
+
+  while ( true ) {
+    /* F */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    SetGeneration( tc, 0 );
+
+    /* G */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    rtems_counter_delay_nanoseconds( 10000000 );
+    SetGeneration( tc, 1 );
+
+    /* H */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+  }
+}
+
+static void PrepareChangeWork( Timecounter *tc )
+{
+  /* F */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+  SetCounter( tc, 0 );
+
+  /* G */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+}
+
+static void CleanupChangeWork( Timecounter *tc )
+{
+  /* H */
+  _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+  T_eq_u32( GetCounter( tc ), 0 );
+}
+
+static void ChangeWorker( rtems_task_argument arg )
+{
+  Timecounter *tc;
+
+  tc = (Timecounter *) arg;
+
+  while ( true ) {
+    unsigned int i;
+
+    /* F */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    /* G */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    for ( i = 1; i < 1000; ++i ) {
+      SetGeneration( tc, i );
+    }
+
+    /* H */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+  }
+}
+
+/* This definition must be identical to the one in kern_tc.c */
+struct timehands {
+  struct timecounter *th_counter;
+  int64_t             th_adjustment;
+  uint64_t            th_scale;
+  uint32_t            th_large_delta;
+  uint32_t            th_offset_count;
+  struct bintime      th_offset;
+  struct bintime      th_bintime;
+  struct timeval      th_microtime;
+  struct timespec     th_nanotime;
+  struct bintime      th_boottime;
+  Atomic_Uint         th_generation;
+  struct timehands   *th_next;
+};
+
+static void NtpUpdateSecond( int64_t *adjustment, time_t *newsec )
+{
+  Timecounter      *tc;
+  struct timehands *th;
+
+  tc = &test_timecounter;
+  th = RTEMS_CONTAINER_OF( adjustment, struct timehands, th_adjustment );
+  T_assert_eq_ptr( th, th->th_next->th_next );
+  tc->generation_0 = &th->th_generation;
+  tc->generation_1 = &th->th_next->th_generation;
+}
+
+/**
+ * @brief Install timecounter of different quality levels and frequencies.
+ */
+static void ScoreTimecounterValGetSmp_Action_0( void )
+{
+  Timecounter     *tc;
+  rtems_id         worker_id;
+  struct bintime   bt;
+  sbintime_t       sbt;
+  struct timespec  ts;
+  struct timeval   tv;
+  unsigned int     i;
+
+  tc = &test_timecounter;
+  tc->base.tc_get_timecount = GetTimecount;
+  tc->base.tc_counter_mask = 0xffffffff;
+  tc->base.tc_frequency = 0x10000000;
+  tc->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+  rtems_timecounter_install( &tc->base );
+
+  SetCounter( tc, tc->base.tc_frequency );
+  _Timecounter_Set_NTP_update_second( NtpUpdateSecond );
+  CallTimecounterTick();
+  _Timecounter_Set_NTP_update_second( NULL );
+
+  T_assert_not_null( tc->generation_0 );
+  T_assert_not_null( tc->generation_1 );
+
+  _SMP_barrier_Control_initialize( &tc->barrier );
+  _SMP_barrier_State_initialize( &tc->barrier_state[ 0 ] );
+  _SMP_barrier_State_initialize( &tc->barrier_state[ 1 ] );
+
+  worker_id = CreateTask( "WORK", PRIO_NORMAL );
+  SetScheduler( worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
+  StartTask( worker_id, SynchronousWorker, tc );
+
+  tc->base.tc_get_timecount = GetTimecountBarrier;
+
+  /*
+   * Call the rtems_clock_get_realtime() directive and let it observe a
+   * generation number of zero as well as a generation number change.
+   */
+  PrepareSynchronousWork( tc );
+  rtems_clock_get_realtime( &ts );
+  T_eq_i64( ts.tv_sec, 567993616 );
+  T_eq_long( ts.tv_nsec, 7 );
+  CleanupSynchronousWork( tc );
+
+  /*
+   * Call the rtems_clock_get_realtime_bintime() directive and let it observe a
+   * generation number of zero as well as a generation number change.
+   */
+  PrepareSynchronousWork( tc );
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993616 );
+  T_eq_u64( bt.frac, 137438953472 );
+  CleanupSynchronousWork( tc );
+
+  /*
+   * Call the rtems_clock_get_realtime_timeval() directive and let it observe a
+   * generation number of zero as well as a generation number change.
+   */
+  PrepareSynchronousWork( tc );
+  rtems_clock_get_realtime_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 567993616 );
+  T_eq_long( tv.tv_usec, 0 );
+  CleanupSynchronousWork( tc );
+
+  /*
+   * Call the rtems_clock_get_monotonic() directive and let it observe a
+   * generation number of zero as well as a generation number change.
+   */
+  PrepareSynchronousWork( tc );
+  rtems_clock_get_monotonic( &ts );
+  T_eq_i64( ts.tv_sec, 17 );
+  T_eq_long( ts.tv_nsec, 7 );
+  CleanupSynchronousWork( tc );
+
+  /*
+   * Call the rtems_clock_get_monotonic_bintime() directive and let it observe
+   * a generation number of zero as well as a generation number change.
+   */
+  PrepareSynchronousWork( tc );
+  rtems_clock_get_monotonic_bintime( &bt );
+  T_eq_i64( bt.sec, 17 );
+  T_eq_u64( bt.frac, 137438953472 );
+  CleanupSynchronousWork( tc );
+
+  /*
+   * Call the rtems_clock_get_monotonic_sbintime() directive and let it observe
+   * a generation number of zero as well as a generation number change.
+   */
+  PrepareSynchronousWork( tc );
+  sbt = rtems_clock_get_monotonic_sbintime();
+  T_eq_i64( sbt, 73014444064 );
+  CleanupSynchronousWork( tc );
+
+  /*
+   * Call the rtems_clock_get_monotonic_timeval() directive and let it observe
+   * a generation number of zero as well as a generation number change.
+   */
+  PrepareSynchronousWork( tc );
+  rtems_clock_get_monotonic_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 17 );
+  T_eq_long( tv.tv_usec, 0 );
+  CleanupSynchronousWork( tc );
+
+  /*
+   * Delete the synchronous worker task.  Reinitialize the barrier and barrier
+   * states.  Start the zero worker task.
+   */
+  tc->base.tc_get_timecount = GetTimecount;
+  DeleteTask( worker_id );
+
+  _SMP_barrier_Control_initialize( &tc->barrier );
+  _SMP_barrier_State_initialize( &tc->barrier_state[ 0 ] );
+  _SMP_barrier_State_initialize( &tc->barrier_state[ 1 ] );
+
+  worker_id = CreateTask( "WORK", PRIO_NORMAL );
+  SetScheduler( worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
+  StartTask( worker_id, ZeroWorker, tc );
+
+  /*
+   * Call the rtems_clock_get_realtime_coarse() directive and try to let it
+   * observe a generation number of zero.
+   */
+  PrepareZeroWork( tc );
+  rtems_clock_get_realtime_coarse( &ts );
+  CleanupZeroWork( tc );
+
+  /*
+   * Call the rtems_clock_get_realtime_coarse_bintime() directive and try to
+   * let it observe a generation number of zero.
+   */
+  PrepareZeroWork( tc );
+  rtems_clock_get_realtime_coarse_bintime( &bt );
+  CleanupZeroWork( tc );
+
+  /*
+   * Call the rtems_clock_get_realtime_coarse_timeval() directive and try to
+   * let it observe a generation number of zero.
+   */
+  PrepareZeroWork( tc );
+  rtems_clock_get_realtime_coarse_timeval( &tv );
+  CleanupZeroWork( tc );
+
+  /*
+   * Call the rtems_clock_get_monotonic_coarse() directive and try to let it
+   * observe a generation number of zero.
+   */
+  PrepareZeroWork( tc );
+  rtems_clock_get_monotonic_coarse( &ts );
+  CleanupZeroWork( tc );
+
+  /*
+   * Call the rtems_clock_get_monotonic_coarse_bintime() directive and try to
+   * let it observe a generation number of zero.
+   */
+  PrepareZeroWork( tc );
+  rtems_clock_get_monotonic_coarse_bintime( &bt );
+  CleanupZeroWork( tc );
+
+  /*
+   * Call the rtems_clock_get_monotonic_coarse_timeval() directive and try to
+   * let it observe a generation number of zero.
+   */
+  PrepareZeroWork( tc );
+  rtems_clock_get_monotonic_coarse_timeval( &tv );
+  CleanupZeroWork( tc );
+
+  /*
+   * Call the rtems_clock_get_boot_time() directive and try to let it observe a
+   * generation number of zero.
+   */
+  PrepareZeroWork( tc );
+  rtems_clock_get_boot_time( &ts );
+  CleanupZeroWork( tc );
+
+  /*
+   * Call the rtems_clock_get_boot_time_bintime() directive and try to let it
+   * observe a generation number of zero.
+   */
+  PrepareZeroWork( tc );
+  rtems_clock_get_boot_time_bintime( &bt );
+  CleanupZeroWork( tc );
+
+  /*
+   * Call the rtems_clock_get_boot_time_timeval() directive and try to let it
+   * observe a generation number of zero.
+   */
+  PrepareZeroWork( tc );
+  rtems_clock_get_boot_time_timeval( &tv );
+  CleanupZeroWork( tc );
+
+  /*
+   * Delete the zero worker task.  Reinitialize the barrier and barrier states.
+   * Start the change worker task.
+   */
+  DeleteTask( worker_id );
+
+  _SMP_barrier_Control_initialize( &tc->barrier );
+  _SMP_barrier_State_initialize( &tc->barrier_state[ 0 ] );
+  _SMP_barrier_State_initialize( &tc->barrier_state[ 1 ] );
+
+  worker_id = CreateTask( "WORK", PRIO_NORMAL );
+  SetScheduler( worker_id, SCHEDULER_B_ID, PRIO_NORMAL );
+  StartTask( worker_id, ChangeWorker, tc );
+
+  /*
+   * Call the rtems_clock_get_realtime_coarse() directive and try to let it
+   * observe a changing generation number.
+   */
+  PrepareChangeWork( tc );
+
+  for ( i = 0; i < 100; ++i ) {
+    rtems_clock_get_realtime_coarse( &ts );
+  }
+
+  CleanupChangeWork( tc );
+
+  /*
+   * Call the rtems_clock_get_realtime_coarse_bintime() directive and try to
+   * let it observe a changing generation number.
+   */
+  PrepareChangeWork( tc );
+
+  for ( i = 0; i < 100; ++i ) {
+    rtems_clock_get_realtime_coarse_bintime( &bt );
+  }
+
+  CleanupChangeWork( tc );
+
+  /*
+   * Call the rtems_clock_get_realtime_coarse_timeval() directive and try to
+   * let it observe a changing generation number.
+   */
+  PrepareChangeWork( tc );
+
+  for ( i = 0; i < 100; ++i ) {
+    rtems_clock_get_realtime_coarse_timeval( &tv );
+  }
+
+  CleanupChangeWork( tc );
+
+  /*
+   * Call the rtems_clock_get_monotonic_coarse() directive and try to let it
+   * observe a changing generation number.
+   */
+  PrepareChangeWork( tc );
+
+  for ( i = 0; i < 100; ++i ) {
+    rtems_clock_get_monotonic_coarse( &ts );
+  }
+
+  CleanupChangeWork( tc );
+
+  /*
+   * Call the rtems_clock_get_monotonic_coarse_bintime() directive and try to
+   * let it observe a changing generation number.
+   */
+  PrepareChangeWork( tc );
+
+  for ( i = 0; i < 100; ++i ) {
+    rtems_clock_get_monotonic_coarse_bintime( &bt );
+  }
+
+  CleanupChangeWork( tc );
+
+  /*
+   * Call the rtems_clock_get_monotonic_coarse_timeval() directive and try to
+   * let it observe a changing generation number.
+   */
+  PrepareChangeWork( tc );
+
+  for ( i = 0; i < 100; ++i ) {
+    rtems_clock_get_monotonic_coarse_timeval( &tv );
+  }
+
+  CleanupChangeWork( tc );
+
+  /*
+   * Call the rtems_clock_get_boot_time() directive and try to let it observe a
+   * changing generation number.
+   */
+  PrepareChangeWork( tc );
+
+  for ( i = 0; i < 100; ++i ) {
+    rtems_clock_get_boot_time( &ts );
+  }
+
+  CleanupChangeWork( tc );
+
+  /*
+   * Call the rtems_clock_get_boot_time_bintime() directive and try to let it
+   * observe a changing generation number.
+   */
+  PrepareChangeWork( tc );
+
+  for ( i = 0; i < 100; ++i ) {
+    rtems_clock_get_boot_time_bintime( &bt );
+  }
+
+  CleanupChangeWork( tc );
+
+  /*
+   * Call the rtems_clock_get_boot_time_timeval() directive and try to let it
+   * observe a changing generation number.
+   */
+  PrepareChangeWork( tc );
+
+  for ( i = 0; i < 100; ++i ) {
+    rtems_clock_get_boot_time_timeval( &tv );
+  }
+
+  CleanupChangeWork( tc );
+
+  /*
+   * Delete the change worker task.
+   */
+  DeleteTask( worker_id );
+}
+
+/**
+ * @fn void T_case_body_ScoreTimecounterValGetSmp( void )
+ */
+T_TEST_CASE( ScoreTimecounterValGetSmp )
+{
+  ScoreTimecounterValGetSmp_Action_0();
+}
+
+/** @} */
diff --git a/testsuites/validation/tc-timecounter-get.c b/testsuites/validation/tc-timecounter-get.c
new file mode 100644
index 0000000..7ab746a
--- /dev/null
+++ b/testsuites/validation/tc-timecounter-get.c
@@ -0,0 +1,575 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseScoreTimecounterValGet
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated.  If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual.  The manual is provided as a part of
+ * a release.  For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/counter.h>
+#include <rtems/timecounter.h>
+#include <rtems/score/timecounterimpl.h>
+
+#include "tx-support.h"
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestCaseScoreTimecounterValGet \
+ *   spec:/score/timecounter/val/get
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationTimecounter1
+ *
+ * @brief Tests directives to get a time value.
+ *
+ * This test case performs the following actions:
+ *
+ * - Install a timecounter which can be used to perform interrut tests for the
+ *   get time directives.
+ *
+ *   - Try to interrupt the rtems_clock_get_realtime() directive to provoke a
+ *     change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_realtime_bintime() directive to
+ *     provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_realtime_timeval() directive to
+ *     provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_monotonic() directive to provoke a
+ *     change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_monotonic_bintime() directive to
+ *     provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_monotonic_sbintime() directive to
+ *     provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_monotonic_timeval() directive to
+ *     provoke a change in the timehand generation number.
+ *
+ *   - Prepare for the coarse get time directives.
+ *
+ *   - Try to interrupt the rtems_clock_get_realtime_coarse() directive to
+ *     provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_realtime_coarse_bintime() directive
+ *     to provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_realtime_coarse_timeval() directive
+ *     to provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_monotonic_coarse() directive to
+ *     provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_monotonic_coarse_bintime()
+ *     directive to provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_monotonic_coarse_timeval()
+ *     directive to provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_boot_time() directive to provoke a
+ *     change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_boot_time_bintime() directive to
+ *     provoke a change in the timehand generation number.
+ *
+ *   - Try to interrupt the rtems_clock_get_boot_time_timeval() directive to
+ *     provoke a change in the timehand generation number.
+ *
+ * @{
+ */
+
+typedef enum {
+  STATE_EARLY,
+  STATE_GET_TIMECOUNT_BEFORE,
+  STATE_GET_TIMECOUNT_BUSY,
+  STATE_GET_TIMECOUNT_DONE,
+  STATE_GET_TIMECOUNT_AFTER
+} State;
+
+typedef struct {
+  struct timecounter  base;
+  State               state;
+  uint_fast32_t       busy;
+  struct bintime      tod;
+} Timecounter;
+
+static Timecounter test_timecounter;
+
+static uint32_t GetTimecount( struct timecounter *base )
+{
+  Timecounter *tc;
+
+  tc = (Timecounter *) base;
+
+  if (
+    tc->state == STATE_GET_TIMECOUNT_BEFORE &&
+    !rtems_interrupt_is_in_progress()
+  ) {
+    tc->state = STATE_GET_TIMECOUNT_BUSY;
+    T_busy( tc->busy );
+    tc->state = STATE_GET_TIMECOUNT_DONE;
+  }
+
+  return rtems_counter_read();
+}
+
+static void InterruptPrepare( void *arg )
+{
+  Timecounter *tc;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_EARLY;
+}
+
+static void ActionRealtime( void *arg )
+{
+  Timecounter    *tc;
+  struct timespec ts;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_realtime( &ts );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionRealtimeBintime( void *arg )
+{
+  Timecounter   *tc;
+  struct bintime bt;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_realtime_bintime( &bt );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionRealtimeTimeval( void *arg )
+{
+  Timecounter   *tc;
+  struct timeval tv;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_realtime_timeval( &tv );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionMonotonic( void *arg )
+{
+  Timecounter    *tc;
+  struct timespec ts;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_monotonic( &ts );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionMonotonicBintime( void *arg )
+{
+  Timecounter   *tc;
+  struct bintime bt;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_monotonic_bintime( &bt );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionMonotonicSbintime( void *arg )
+{
+  Timecounter *tc;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  (void) rtems_clock_get_monotonic_sbintime();
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionMonotonicTimeval( void *arg )
+{
+  Timecounter   *tc;
+  struct timeval tv;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_monotonic_timeval( &tv );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionCoarseRealtime( void *arg )
+{
+  Timecounter    *tc;
+  struct timespec ts;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_realtime_coarse( &ts );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionCoarseRealtimeBintime( void *arg )
+{
+  Timecounter   *tc;
+  struct bintime bt;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_realtime_coarse_bintime( &bt );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionCoarseRealtimeTimeval( void *arg )
+{
+  Timecounter   *tc;
+  struct timeval tv;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_realtime_coarse_timeval( &tv );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionCoarseMonotonic( void *arg )
+{
+  Timecounter    *tc;
+  struct timespec ts;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_monotonic_coarse( &ts );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionCoarseMonotonicBintime( void *arg )
+{
+  Timecounter   *tc;
+  struct bintime bt;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_monotonic_coarse_bintime( &bt );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionCoarseMonotonicTimeval( void *arg )
+{
+  Timecounter   *tc;
+  struct timeval tv;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_monotonic_coarse_timeval( &tv );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionBootTime( void *arg )
+{
+  Timecounter    *tc;
+  struct timespec ts;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_boot_time( &ts );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionBootTimeBintime( void *arg )
+{
+  Timecounter   *tc;
+  struct bintime bt;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_boot_time_bintime( &bt );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void ActionBootTimeTimeval( void *arg )
+{
+  Timecounter   *tc;
+  struct timeval tv;
+
+  tc = (Timecounter *) arg;
+  tc->state = STATE_GET_TIMECOUNT_BEFORE;
+  rtems_clock_get_boot_time_timeval( &tv );
+  tc->state = STATE_GET_TIMECOUNT_AFTER;
+}
+
+static void CallTimcounterWindupTwice( const Timecounter *tc )
+{
+  ISR_lock_Context lock_context;
+
+  /*
+   * Make sure that tc_windup() was called at least twice to increment the
+   * generation number for * both timehands.
+   */
+
+  _Timecounter_Acquire( &lock_context );
+  _Timecounter_Set_clock( &tc->tod, &lock_context );
+
+  _Timecounter_Acquire( &lock_context );
+  _Timecounter_Set_clock( &tc->tod, &lock_context );
+}
+
+static T_interrupt_test_state Interrupt( void *arg )
+{
+  Timecounter *tc;
+  State        state;
+
+  tc = (Timecounter *) arg;
+  state = tc->state;
+
+  if ( state == STATE_EARLY || state == STATE_GET_TIMECOUNT_BEFORE ) {
+    return T_INTERRUPT_TEST_EARLY;
+  }
+
+  if ( state == STATE_GET_TIMECOUNT_BUSY ) {
+    CallTimcounterWindupTwice( tc );
+
+    return T_INTERRUPT_TEST_DONE;
+  }
+
+  return T_INTERRUPT_TEST_LATE;
+}
+
+static T_interrupt_test_state InterruptCoarse( void *arg )
+{
+  Timecounter *tc;
+  State        state;
+
+  tc = (Timecounter *) arg;
+  state = tc->state;
+
+  if ( state == STATE_EARLY ) {
+    return T_INTERRUPT_TEST_EARLY;
+  }
+
+  if ( state == STATE_GET_TIMECOUNT_BEFORE ) {
+    CallTimcounterWindupTwice( tc );
+
+    return T_INTERRUPT_TEST_DONE;
+  }
+
+  return T_INTERRUPT_TEST_LATE;
+}
+
+static bool InterruptTest(
+  const T_interrupt_test_config *config,
+  void                          *arg,
+  uint32_t                       iterations
+)
+{
+  uint32_t i;
+  bool     ok;
+
+  ok = false;
+
+  for ( i = 0; i < iterations; ++i ) {
+    T_interrupt_test_state test_state;
+
+    test_state = T_interrupt_test( config, arg );
+    ok = ok || test_state == T_INTERRUPT_TEST_DONE;
+  }
+
+  return ok;
+}
+
+/**
+ * @brief Install a timecounter which can be used to perform interrut tests for
+ *   the get time directives.
+ */
+static void ScoreTimecounterValGet_Action_0( void )
+{
+  T_interrupt_test_config config = {
+    .prepare = InterruptPrepare,
+    .interrupt = Interrupt,
+    .max_iteration_count = 10000
+  };
+  Timecounter *tc;
+
+  tc = &test_timecounter;
+  tc->base.tc_get_timecount = GetTimecount;
+  tc->base.tc_counter_mask = 0xffffffff;
+  tc->base.tc_frequency = rtems_counter_frequency();
+  tc->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER + 1;
+  tc->busy = T_get_one_clock_tick_busy() / 10;
+  rtems_clock_get_realtime_bintime( &tc->tod );
+  rtems_timecounter_install( &tc->base );
+
+  /*
+   * Try to interrupt the rtems_clock_get_realtime() directive to provoke a
+   * change in the timehand generation number.
+   */
+  config.action = ActionRealtime;
+  T_true( InterruptTest( &config, tc, 1 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_realtime_bintime() directive to
+   * provoke a change in the timehand generation number.
+   */
+  config.action = ActionRealtimeBintime;
+  T_true( InterruptTest( &config, tc, 1 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_realtime_timeval() directive to
+   * provoke a change in the timehand generation number.
+   */
+  config.action = ActionRealtimeTimeval;
+  T_true( InterruptTest( &config, tc, 1 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_monotonic() directive to provoke a
+   * change in the timehand generation number.
+   */
+  config.action = ActionMonotonic;
+  T_true( InterruptTest( &config, tc, 1 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_monotonic_bintime() directive to
+   * provoke a change in the timehand generation number.
+   */
+  config.action = ActionMonotonicBintime;
+  T_true( InterruptTest( &config, tc, 1 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_monotonic_sbintime() directive to
+   * provoke a change in the timehand generation number.
+   */
+  config.action = ActionMonotonicSbintime;
+  T_true( InterruptTest( &config, tc, 1 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_monotonic_timeval() directive to
+   * provoke a change in the timehand generation number.
+   */
+  config.action = ActionMonotonicTimeval;
+  T_true( InterruptTest( &config, tc, 1 ) );
+
+  /*
+   * Prepare for the coarse get time directives.
+   */
+  config.interrupt = InterruptCoarse;
+
+  /*
+   * Try to interrupt the rtems_clock_get_realtime_coarse() directive to
+   * provoke a change in the timehand generation number.
+   */
+  config.action = ActionCoarseRealtime;
+  T_true( InterruptTest( &config, tc, 10 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_realtime_coarse_bintime() directive
+   * to provoke a change in the timehand generation number.
+   */
+  config.action = ActionCoarseRealtimeBintime;
+  T_true( InterruptTest( &config, tc, 10 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_realtime_coarse_timeval() directive
+   * to provoke a change in the timehand generation number.
+   */
+  config.action = ActionCoarseRealtimeTimeval;
+  T_true( InterruptTest( &config, tc, 10 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_monotonic_coarse() directive to
+   * provoke a change in the timehand generation number.
+   */
+  config.action = ActionCoarseMonotonic;
+  T_true( InterruptTest( &config, tc, 10 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_monotonic_coarse_bintime() directive
+   * to provoke a change in the timehand generation number.
+   */
+  config.action = ActionCoarseMonotonicBintime;
+  T_true( InterruptTest( &config, tc, 10 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_monotonic_coarse_timeval() directive
+   * to provoke a change in the timehand generation number.
+   */
+  config.action = ActionCoarseMonotonicTimeval;
+  T_true( InterruptTest( &config, tc, 10 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_boot_time() directive to provoke a
+   * change in the timehand generation number.
+   */
+  config.action = ActionBootTime;
+  T_true( InterruptTest( &config, tc, 10 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_boot_time_bintime() directive to
+   * provoke a change in the timehand generation number.
+   */
+  config.action = ActionBootTimeBintime;
+  T_true( InterruptTest( &config, tc, 10 ) );
+
+  /*
+   * Try to interrupt the rtems_clock_get_boot_time_timeval() directive to
+   * provoke a change in the timehand generation number.
+   */
+  config.action = ActionBootTimeTimeval;
+  T_true( InterruptTest( &config, tc, 10 ) );
+}
+
+/**
+ * @fn void T_case_body_ScoreTimecounterValGet( void )
+ */
+T_TEST_CASE( ScoreTimecounterValGet )
+{
+  ScoreTimecounterValGet_Action_0();
+}
+
+/** @} */
diff --git a/testsuites/validation/tc-timecounter-install.c b/testsuites/validation/tc-timecounter-install.c
new file mode 100644
index 0000000..3189f37
--- /dev/null
+++ b/testsuites/validation/tc-timecounter-install.c
@@ -0,0 +1,1134 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseScoreTimecounterValInstall
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated.  If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual.  The manual is provided as a part of
+ * a release.  For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/timecounter.h>
+#include <rtems/score/atomic.h>
+#include <rtems/score/threaddispatch.h>
+
+#include "tx-support.h"
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestCaseScoreTimecounterValInstall \
+ *   spec:/score/timecounter/val/install
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationTimecounter0
+ *
+ * @brief Tests timecounter installation related functions and directives of
+ *   the Clock Manager.
+ *
+ * This test case performs the following actions:
+ *
+ * - Call the simple timecounter tick service with a zero delta and offset.
+ *   This will lead to an overflow to zero of the timehand generation.  It
+ *   shall not change the initial clock values.
+ *
+ * - Call the directives to get the initial value of CLOCK_REALTIME and the
+ *   initial boot time.
+ *
+ *   - Check the initial CLOCK_REALTIME in seconds and nanoseconds format.
+ *
+ *   - Check that CLOCK_REALTIME is frozen in seconds and nanoseconds format.
+ *
+ *   - Check the initial CLOCK_REALTIME in coarse resolution in seconds and
+ *     nanoseconds format.
+ *
+ *   - Check that CLOCK_REALTIME is frozen in coarse resolution in seconds and
+ *     nanoseconds format.
+ *
+ *   - Check the initial CLOCK_REALTIME in binary time format.
+ *
+ *   - Check that CLOCK_REALTIME is frozen in binary time format.
+ *
+ *   - Check the initial CLOCK_REALTIME in coarse resolution in binary time
+ *     format.
+ *
+ *   - Check that CLOCK_REALTIME is frozen in coarse resolution in binary time
+ *     format.
+ *
+ *   - Check the initial CLOCK_REALTIME in seconds and microseconds format.
+ *
+ *   - Check that CLOCK_REALTIME is frozen in seconds and microseconds format.
+ *
+ *   - Check the initial CLOCK_REALTIME in coarse resolution in seconds and
+ *     microseconds format.
+ *
+ *   - Check that CLOCK_REALTIME is frozen in coarse resolution in seconds and
+ *     microseconds format.
+ *
+ *   - Check the initial boot time in seconds and nanoseconds format.
+ *
+ *   - Check the initial boot time in binary time format.
+ *
+ *   - Check the initial boot time in seconds and microseconds format.
+ *
+ * - Call the directives to get the initial value of CLOCK_MONOTONIC and the
+ *   initial boot time.
+ *
+ *   - Check the initial CLOCK_MONOTONIC in seconds and nanoseconds format.
+ *
+ *   - Check that CLOCK_MONOTONIC is frozen in seconds and nanoseconds format.
+ *
+ *   - Check the initial CLOCK_MONOTONIC in coarse resolution in seconds and
+ *     nanoseconds format.
+ *
+ *   - Check that CLOCK_MONOTONIC is frozen in coarse resolution in seconds and
+ *     nanoseconds format.
+ *
+ *   - Check the initial CLOCK_MONOTONIC in binary time format.
+ *
+ *   - Check that CLOCK_MONOTONIC is frozen in binary time format.
+ *
+ *   - Check the initial CLOCK_MONOTONIC in coarse resolution in binary time
+ *     format.
+ *
+ *   - Check that CLOCK_MONOTONIC is frozen in coarse resolution in binary time
+ *     format.
+ *
+ *   - Check the initial CLOCK_MONOTONIC in signed binary time format.
+ *
+ *   - Check that CLOCK_MONOTONIC is frozen in signed binary time format.
+ *
+ *   - Check the initial CLOCK_MONOTONIC in seconds and microseconds format.
+ *
+ *   - Check that CLOCK_MONOTONIC is frozen in seconds and microseconds format.
+ *
+ *   - Check the initial CLOCK_MONOTONIC in coarse resolution in seconds and
+ *     microseconds format.
+ *
+ *   - Check that CLOCK_MONOTONIC is frozen in coarse resolution in seconds and
+ *     microseconds format.
+ *
+ * - Install timecounter of different quality levels and frequencies.
+ *
+ *   - Install a timecounter with a high quality level and normal frequency.
+ *     Check that it was installed.
+ *
+ *   - Install a timecounter with a high quality level and low frequency. Check
+ *     that it was not installed.
+ *
+ *   - Install a timecounter with a high quality level and high frequency.
+ *     Check that it was installed.
+ *
+ *   - Install a timecounter with a low quality level.  Check that it was not
+ *     installed.
+ *
+ * - Call the directives to get the time in the highest resolution available to
+ *   the system.
+ *
+ *   - Check that the timecounter was used by rtems_clock_get_realtime().
+ *
+ *   - Check that the timecounter was used by
+ *     rtems_clock_get_realtime_bintime().
+ *
+ *   - Check that the timecounter was used by
+ *     rtems_clock_get_realtime_timeval().
+ *
+ *   - Check that the timecounter was used by rtems_clock_get_monotonic().
+ *
+ *   - Check that the timecounter was used by
+ *     rtems_clock_get_monotonic_bintime().
+ *
+ *   - Check that the timecounter was used by
+ *     rtems_clock_get_monotonic_sbintime().
+ *
+ *   - Check that the timecounter was used by
+ *     rtems_clock_get_monotonic_timeval().
+ *
+ * - Call the directives to get the time in a coarse resolution.
+ *
+ *   - Check that the timecounter was not used by
+ *     rtems_clock_get_realtime_coarse().
+ *
+ *   - Check that the timecounter was not used by
+ *     rtems_clock_get_realtime_coarse_bintime().
+ *
+ *   - Check that the timecounter was not used by
+ *     rtems_clock_get_realtime_coarse_timeval().
+ *
+ *   - Check that the timecounter was not used by
+ *     rtems_clock_get_monotonic_coarse().
+ *
+ *   - Check that the timecounter was not used by
+ *     rtems_clock_get_monotonic_coarse_bintime().
+ *
+ *   - Check that the timecounter was not used by
+ *     rtems_clock_get_monotonic_coarse_timeval().
+ *
+ *   - Check that the timecounter was not used by rtems_clock_get_boot_time().
+ *
+ *   - Check that the timecounter was not used by
+ *     rtems_clock_get_boot_time_bintime().
+ *
+ *   - Check that the timecounter was not used by
+ *     rtems_clock_get_boot_time_timeval().
+ *
+ * - Call the directives to get the time in the highest resolution available to
+ *   the system.
+ *
+ *   - Prepare the timecounter to get a large time difference.  Check that
+ *     rtems_clock_get_realtime() returns the correct time.
+ *
+ *   - Prepare the timecounter to get a large time difference.  Check that
+ *     rtems_clock_get_realtime_bintime() returns the correct time.
+ *
+ *   - Prepare the timecounter to get a large time difference.  Check that
+ *     rtems_clock_get_realtime_timeval() returns the correct time.
+ *
+ *   - Prepare the timecounter to get a large time difference.  Check that
+ *     rtems_clock_get_monotonic() returns the correct time.
+ *
+ *   - Prepare the timecounter to get a large time difference.  Check that
+ *     rtems_clock_get_monotonic_bintime() returns the correct time.
+ *
+ *   - Prepare the timecounter to get a large time difference.  Check that
+ *     rtems_clock_get_monotonic_sbintime() returns the correct time.
+ *
+ *   - Prepare the timecounter to get a large time difference.  Check that
+ *     rtems_clock_get_monotonic_timeval() returns the correct time.
+ *
+ * - Update the oldest timehand after a large time interval.
+ *
+ * - Call the simple timecounter tick service with non-zero delta and offset
+ *   parameter values so that exactly one second passed.
+ *
+ *   - Check that exactly one second passed due to the simple clock tick
+ *     service.
+ *
+ * - Install a very high quality timecounter with a low frequency to test the
+ *   NTP support.
+ *
+ *   - Let the seconds value of CLOCK_REALTIME not change. Check that the NTP
+ *     update second handler is not called.
+ *
+ *   - Let the seconds value of CLOCK_REALTIME change by one. Check that the
+ *     NTP update second handler is called exactly once.
+ *
+ *   - Let the seconds value of CLOCK_REALTIME change by 200. Check that the
+ *     NTP update second handler is called exactly 200 times.
+ *
+ *   - Let the seconds value of CLOCK_REALTIME change by 201. Check that the
+ *     NTP update second handler is called exactly twice.
+ *
+ *   - Let the seconds value of CLOCK_REALTIME change by one. Check that the
+ *     NTP update second handler is incremented the CLOCK_REALTIME by one
+ *     second.
+ *
+ *   - Let the seconds value of CLOCK_REALTIME change by one. Check that the
+ *     NTP update second handler is decremented the CLOCK_REALTIME by one
+ *     second.
+ *
+ *   - Let the seconds value of CLOCK_REALTIME change by one. Check that the
+ *     NTP update second handler increased the timecounter frequency.
+ *
+ *   - Let the seconds value of CLOCK_REALTIME change by one. Check that the
+ *     NTP update second handler decreased the timecounter frequency.
+ *
+ * @{
+ */
+
+typedef struct {
+  struct timecounter base;
+  Atomic_Ulong counter;
+} Timecounter;
+
+static Timecounter high_quality_low_frequency;
+
+static Timecounter high_quality_normal_frequency;
+
+static Timecounter high_quality_high_frequency;
+
+static Timecounter low_quality;
+
+static Timecounter very_high_quality;
+
+static uint32_t ntp_counter;
+
+static uint32_t GetTimecount( struct timecounter *base )
+{
+  Timecounter *tc;
+
+  tc = (Timecounter *) base;
+
+  return (uint32_t) _Atomic_Fetch_add_ulong(
+    &tc->counter,
+    1,
+    ATOMIC_ORDER_RELAXED
+  );
+}
+
+static uint32_t GetCounter( const Timecounter *tc )
+{
+  return (uint32_t) _Atomic_Load_ulong(
+    &tc->counter,
+    ATOMIC_ORDER_RELAXED
+  );
+}
+
+static void SetCounter( Timecounter *tc, uint32_t counter )
+{
+  _Atomic_Store_ulong(
+    &tc->counter,
+    counter,
+    ATOMIC_ORDER_RELAXED
+  );
+}
+
+static void NtpUpdateCounter( int64_t *adjustment, time_t *newsec )
+{
+  (void) newsec;
+  T_eq_i64( *adjustment, 0 );
+  ++ntp_counter;
+}
+
+static void NtpUpdateSecondIncrement( int64_t *adjustment, time_t *newsec )
+{
+  (void) adjustment;
+  ++(*newsec);
+}
+
+static void NtpUpdateSecondDecrement( int64_t *adjustment, time_t *newsec )
+{
+  (void) adjustment;
+  --(*newsec);
+}
+
+static void NtpUpdateAdjustmentFaster( int64_t *adjustment, time_t *newsec )
+{
+  *adjustment = ( (int64_t) 5000 ) << 32;
+  (void) newsec;
+}
+
+static void NtpUpdateAdjustmentSlower( int64_t *adjustment, time_t *newsec )
+{
+  *adjustment = -( (int64_t) 5000 ) << 32;
+  (void) newsec;
+}
+
+static void CallTimecounterTick( void )
+{
+  Per_CPU_Control *cpu_self;
+
+  cpu_self = _Thread_Dispatch_disable();
+  rtems_timecounter_tick();
+  _Thread_Dispatch_enable( cpu_self );
+}
+
+/**
+ * @brief Call the simple timecounter tick service with a zero delta and
+ *   offset. This will lead to an overflow to zero of the timehand generation.
+ *   It shall not change the initial clock values.
+ */
+static void ScoreTimecounterValInstall_Action_0( void )
+{
+  ISR_lock_Context lock_context;
+
+  _Timecounter_Acquire( &lock_context );
+  _Timecounter_Tick_simple( 0, 0, &lock_context );
+}
+
+/**
+ * @brief Call the directives to get the initial value of CLOCK_REALTIME and
+ *   the initial boot time.
+ */
+static void ScoreTimecounterValInstall_Action_1( void )
+{
+  struct bintime  bt;
+  struct timespec ts;
+  struct timeval  tv;
+
+  /*
+   * Check the initial CLOCK_REALTIME in seconds and nanoseconds format.
+   */
+  rtems_clock_get_realtime( &ts );
+  T_eq_i64( ts.tv_sec, 567993600 );
+  T_eq_u64( ts.tv_nsec, 0 );
+
+  /*
+   * Check that CLOCK_REALTIME is frozen in seconds and nanoseconds format.
+   */
+  rtems_clock_get_realtime( &ts );
+  T_eq_i64( ts.tv_sec, 567993600 );
+  T_eq_u64( ts.tv_nsec, 0 );
+
+  /*
+   * Check the initial CLOCK_REALTIME in coarse resolution in seconds and
+   * nanoseconds format.
+   */
+  rtems_clock_get_realtime_coarse( &ts );
+  T_eq_i64( ts.tv_sec, 567993600 );
+  T_eq_u64( ts.tv_nsec, 0 );
+
+  /*
+   * Check that CLOCK_REALTIME is frozen in coarse resolution in seconds and
+   * nanoseconds format.
+   */
+  rtems_clock_get_realtime_coarse( &ts );
+  T_eq_i64( ts.tv_sec, 567993600 );
+  T_eq_u64( ts.tv_nsec, 0 );
+
+  /*
+   * Check the initial CLOCK_REALTIME in binary time format.
+   */
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993600 );
+  T_eq_u64( bt.frac, 0 );
+
+  /*
+   * Check that CLOCK_REALTIME is frozen in binary time format.
+   */
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993600 );
+  T_eq_u64( bt.frac, 0 );
+
+  /*
+   * Check the initial CLOCK_REALTIME in coarse resolution in binary time
+   * format.
+   */
+  rtems_clock_get_realtime_coarse_bintime( &bt );
+  T_eq_i64( bt.sec, 567993600 );
+  T_eq_u64( bt.frac, 0 );
+
+  /*
+   * Check that CLOCK_REALTIME is frozen in coarse resolution in binary time
+   * format.
+   */
+  rtems_clock_get_realtime_coarse_bintime( &bt );
+  T_eq_i64( bt.sec, 567993600 );
+  T_eq_u64( bt.frac, 0 );
+
+  /*
+   * Check the initial CLOCK_REALTIME in seconds and microseconds format.
+   */
+  rtems_clock_get_realtime_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 567993600 );
+  T_eq_long( tv.tv_usec, 0 );
+
+  /*
+   * Check that CLOCK_REALTIME is frozen in seconds and microseconds format.
+   */
+  rtems_clock_get_realtime_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 567993600 );
+  T_eq_long( tv.tv_usec, 0 );
+
+  /*
+   * Check the initial CLOCK_REALTIME in coarse resolution in seconds and
+   * microseconds format.
+   */
+  rtems_clock_get_realtime_coarse_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 567993600 );
+  T_eq_long( tv.tv_usec, 0 );
+
+  /*
+   * Check that CLOCK_REALTIME is frozen in coarse resolution in seconds and
+   * microseconds format.
+   */
+  rtems_clock_get_realtime_coarse_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 567993600 );
+  T_eq_long( tv.tv_usec, 0 );
+
+  /*
+   * Check the initial boot time in seconds and nanoseconds format.
+   */
+  rtems_clock_get_boot_time( &ts );
+  T_eq_i64( ts.tv_sec, 567993599 );
+  T_eq_u64( ts.tv_nsec, 0 );
+
+  /*
+   * Check the initial boot time in binary time format.
+   */
+  rtems_clock_get_boot_time_bintime( &bt );
+  T_eq_i64( bt.sec, 567993599 );
+  T_eq_u64( bt.frac, 0 );
+
+  /*
+   * Check the initial boot time in seconds and microseconds format.
+   */
+  rtems_clock_get_boot_time_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 567993599 );
+  T_eq_long( tv.tv_usec, 0 );
+}
+
+/**
+ * @brief Call the directives to get the initial value of CLOCK_MONOTONIC and
+ *   the initial boot time.
+ */
+static void ScoreTimecounterValInstall_Action_2( void )
+{
+  struct bintime  bt;
+  sbintime_t      sb;
+  struct timespec ts;
+  struct timeval  tv;
+
+  /*
+   * Check the initial CLOCK_MONOTONIC in seconds and nanoseconds format.
+   */
+  rtems_clock_get_monotonic( &ts );
+  T_eq_i64( ts.tv_sec, 1 );
+  T_eq_u64( ts.tv_nsec, 0 );
+
+  /*
+   * Check that CLOCK_MONOTONIC is frozen in seconds and nanoseconds format.
+   */
+  rtems_clock_get_monotonic( &ts );
+  T_eq_i64( ts.tv_sec, 1 );
+  T_eq_u64( ts.tv_nsec, 0 );
+
+  /*
+   * Check the initial CLOCK_MONOTONIC in coarse resolution in seconds and
+   * nanoseconds format.
+   */
+  rtems_clock_get_monotonic_coarse( &ts );
+  T_eq_i64( ts.tv_sec, 1 );
+  T_eq_u64( ts.tv_nsec, 0 );
+
+  /*
+   * Check that CLOCK_MONOTONIC is frozen in coarse resolution in seconds and
+   * nanoseconds format.
+   */
+  rtems_clock_get_monotonic_coarse( &ts );
+  T_eq_i64( ts.tv_sec, 1 );
+  T_eq_u64( ts.tv_nsec, 0 );
+
+  /*
+   * Check the initial CLOCK_MONOTONIC in binary time format.
+   */
+  rtems_clock_get_monotonic_bintime( &bt );
+  T_eq_i64( bt.sec, 1 );
+  T_eq_u64( bt.frac, 0 );
+
+  /*
+   * Check that CLOCK_MONOTONIC is frozen in binary time format.
+   */
+  rtems_clock_get_monotonic_bintime( &bt );
+  T_eq_i64( bt.sec, 1 );
+  T_eq_u64( bt.frac, 0 );
+
+  /*
+   * Check the initial CLOCK_MONOTONIC in coarse resolution in binary time
+   * format.
+   */
+  rtems_clock_get_monotonic_coarse_bintime( &bt );
+  T_eq_i64( bt.sec, 1 );
+  T_eq_u64( bt.frac, 0 );
+
+  /*
+   * Check that CLOCK_MONOTONIC is frozen in coarse resolution in binary time
+   * format.
+   */
+  rtems_clock_get_monotonic_coarse_bintime( &bt );
+  T_eq_i64( bt.sec, 1 );
+  T_eq_u64( bt.frac, 0 );
+
+  /*
+   * Check the initial CLOCK_MONOTONIC in signed binary time format.
+   */
+  sb = rtems_clock_get_monotonic_sbintime();
+  T_eq_i64( sb, SBT_1S );
+
+  /*
+   * Check that CLOCK_MONOTONIC is frozen in signed binary time format.
+   */
+  sb = rtems_clock_get_monotonic_sbintime();
+  T_eq_i64( sb, SBT_1S );
+
+  /*
+   * Check the initial CLOCK_MONOTONIC in seconds and microseconds format.
+   */
+  rtems_clock_get_monotonic_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 1 );
+  T_eq_long( tv.tv_usec, 0 );
+
+  /*
+   * Check that CLOCK_MONOTONIC is frozen in seconds and microseconds format.
+   */
+  rtems_clock_get_monotonic_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 1 );
+  T_eq_long( tv.tv_usec, 0 );
+
+  /*
+   * Check the initial CLOCK_MONOTONIC in coarse resolution in seconds and
+   * microseconds format.
+   */
+  rtems_clock_get_monotonic_coarse_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 1 );
+  T_eq_long( tv.tv_usec, 0 );
+
+  /*
+   * Check that CLOCK_MONOTONIC is frozen in coarse resolution in seconds and
+   * microseconds format.
+   */
+  rtems_clock_get_monotonic_coarse_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 1 );
+  T_eq_long( tv.tv_usec, 0 );
+}
+
+/**
+ * @brief Install timecounter of different quality levels and frequencies.
+ */
+static void ScoreTimecounterValInstall_Action_3( void )
+{
+  Timecounter *hqlf;
+  Timecounter *hqnf;
+  Timecounter *hqhf;
+  Timecounter *lq;
+  sbintime_t   sb;
+
+  hqlf = &high_quality_low_frequency;
+  hqnf = &high_quality_normal_frequency;
+  hqhf = &high_quality_high_frequency;
+  lq = &low_quality;
+
+  /*
+   * Install a timecounter with a high quality level and normal frequency.
+   * Check that it was installed.
+   */
+  hqnf->base.tc_get_timecount = GetTimecount;
+  hqnf->base.tc_counter_mask = 0xffffffff;
+  hqnf->base.tc_frequency = 0x20000000;
+  hqnf->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER + 1;
+  rtems_timecounter_install( &hqnf->base );
+
+  T_eq_u32( GetCounter( hqnf ), 1 );
+
+  sb = rtems_clock_get_monotonic_sbintime();
+  T_eq_u32( GetCounter( hqnf ), 2 );
+  T_eq_i64( sb, SBT_1S + 8 );
+
+  /*
+   * Install a timecounter with a high quality level and low frequency. Check
+   * that it was not installed.
+   */
+  hqlf->base.tc_get_timecount = GetTimecount;
+  hqlf->base.tc_counter_mask = 0xffffffff;
+  hqlf->base.tc_frequency = 0x10000000;
+  hqlf->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER + 1;
+  rtems_timecounter_install( &hqlf->base );
+
+  T_eq_u32( GetCounter( hqlf ), 0 );
+  T_eq_u32( GetCounter( hqnf ), 2 );
+
+  sb = rtems_clock_get_monotonic_sbintime();
+  T_eq_u32( GetCounter( hqlf ), 0 );
+  T_eq_u32( GetCounter( hqnf ), 3 );
+  T_eq_i64( sb, SBT_1S + 16 );
+
+  /*
+   * Install a timecounter with a high quality level and high frequency. Check
+   * that it was installed.
+   */
+  hqhf->base.tc_get_timecount = GetTimecount;
+  hqhf->base.tc_counter_mask = 0xffffffff;
+  hqhf->base.tc_frequency = 0x40000000;
+  hqhf->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER + 1;
+  rtems_timecounter_install( &hqhf->base );
+
+  T_eq_u32( GetCounter( hqlf ), 0 );
+  T_eq_u32( GetCounter( hqnf ), 4 );
+  T_eq_u32( GetCounter( hqhf ), 1 );
+
+  sb = rtems_clock_get_monotonic_sbintime();
+  T_eq_u32( GetCounter( hqlf ), 0 );
+  T_eq_u32( GetCounter( hqnf ), 4 );
+  T_eq_u32( GetCounter( hqhf ), 2 );
+  T_eq_i64( sb, SBT_1S + 28 );
+
+  /*
+   * Install a timecounter with a low quality level.  Check that it was not
+   * installed.
+   */
+  lq->base.tc_get_timecount = GetTimecount;
+  lq->base.tc_counter_mask = 0xffffffff;
+  lq->base.tc_frequency = 0x80000000;
+  lq->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+  rtems_timecounter_install( &lq->base );
+
+  T_eq_u32( GetCounter( hqlf ), 0 );
+  T_eq_u32( GetCounter( hqnf ), 4 );
+  T_eq_u32( GetCounter( hqhf ), 2 );
+  T_eq_u32( GetCounter( lq ), 0 );
+
+  sb = rtems_clock_get_monotonic_sbintime();
+  T_eq_u32( GetCounter( hqlf ), 0 );
+  T_eq_u32( GetCounter( hqnf ), 4 );
+  T_eq_u32( GetCounter( hqhf ), 3 );
+  T_eq_u32( GetCounter( lq ), 0 );
+  T_eq_i64( sb, SBT_1S + 32 );
+}
+
+/**
+ * @brief Call the directives to get the time in the highest resolution
+ *   available to the system.
+ */
+static void ScoreTimecounterValInstall_Action_4( void )
+{
+  Timecounter    *tc;
+  uint32_t        counter;
+  struct bintime  bt;
+  struct timespec ts;
+  struct timeval  tv;
+
+  tc = &high_quality_high_frequency;
+  counter = GetCounter( tc );
+
+  /*
+   * Check that the timecounter was used by rtems_clock_get_realtime().
+   */
+  rtems_clock_get_realtime( &ts );
+  T_eq_u32( GetCounter( tc ), counter + 1 );
+
+  /*
+   * Check that the timecounter was used by rtems_clock_get_realtime_bintime().
+   */
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_u32( GetCounter( tc ), counter + 2 );
+
+  /*
+   * Check that the timecounter was used by rtems_clock_get_realtime_timeval().
+   */
+  rtems_clock_get_realtime_timeval( &tv );
+  T_eq_u32( GetCounter( tc ), counter + 3 );
+
+  /*
+   * Check that the timecounter was used by rtems_clock_get_monotonic().
+   */
+  rtems_clock_get_monotonic( &ts );
+  T_eq_u32( GetCounter( tc ), counter + 4 );
+
+  /*
+   * Check that the timecounter was used by
+   * rtems_clock_get_monotonic_bintime().
+   */
+  rtems_clock_get_monotonic_bintime( &bt );
+  T_eq_u32( GetCounter( tc ), counter + 5 );
+
+  /*
+   * Check that the timecounter was used by
+   * rtems_clock_get_monotonic_sbintime().
+   */
+  (void) rtems_clock_get_monotonic_sbintime();
+  T_eq_u32( GetCounter( tc ), counter + 6 );
+
+  /*
+   * Check that the timecounter was used by
+   * rtems_clock_get_monotonic_timeval().
+   */
+  rtems_clock_get_monotonic_timeval( &tv );
+  T_eq_u32( GetCounter( tc ), counter + 7 );
+}
+
+/**
+ * @brief Call the directives to get the time in a coarse resolution.
+ */
+static void ScoreTimecounterValInstall_Action_5( void )
+{
+  Timecounter    *tc;
+  uint32_t        counter;
+  struct bintime  bt;
+  struct timespec ts;
+  struct timeval  tv;
+
+  tc = &high_quality_high_frequency;
+  counter = GetCounter( tc );
+
+  /*
+   * Check that the timecounter was not used by
+   * rtems_clock_get_realtime_coarse().
+   */
+  rtems_clock_get_realtime_coarse( &ts );
+  T_eq_u32( GetCounter( tc ), counter );
+
+  /*
+   * Check that the timecounter was not used by
+   * rtems_clock_get_realtime_coarse_bintime().
+   */
+  rtems_clock_get_realtime_coarse_bintime( &bt );
+  T_eq_u32( GetCounter( tc ), counter );
+
+  /*
+   * Check that the timecounter was not used by
+   * rtems_clock_get_realtime_coarse_timeval().
+   */
+  rtems_clock_get_realtime_coarse_timeval( &tv );
+  T_eq_u32( GetCounter( tc ), counter );
+
+  /*
+   * Check that the timecounter was not used by
+   * rtems_clock_get_monotonic_coarse().
+   */
+  rtems_clock_get_monotonic_coarse( &ts );
+  T_eq_u32( GetCounter( tc ), counter );
+
+  /*
+   * Check that the timecounter was not used by
+   * rtems_clock_get_monotonic_coarse_bintime().
+   */
+  rtems_clock_get_monotonic_coarse_bintime( &bt );
+  T_eq_u32( GetCounter( tc ), counter );
+
+  /*
+   * Check that the timecounter was not used by
+   * rtems_clock_get_monotonic_coarse_timeval().
+   */
+  rtems_clock_get_monotonic_coarse_timeval( &tv );
+  T_eq_u32( GetCounter( tc ), counter );
+
+  /*
+   * Check that the timecounter was not used by rtems_clock_get_boot_time().
+   */
+  rtems_clock_get_boot_time( &ts );
+  T_eq_u32( GetCounter( tc ), counter );
+
+  /*
+   * Check that the timecounter was not used by
+   * rtems_clock_get_boot_time_bintime().
+   */
+  rtems_clock_get_boot_time_bintime( &bt );
+  T_eq_u32( GetCounter( tc ), counter );
+
+  /*
+   * Check that the timecounter was not used by
+   * rtems_clock_get_boot_time_timeval().
+   */
+  rtems_clock_get_boot_time_timeval( &tv );
+  T_eq_u32( GetCounter( tc ), counter );
+}
+
+/**
+ * @brief Call the directives to get the time in the highest resolution
+ *   available to the system.
+ */
+static void ScoreTimecounterValInstall_Action_6( void )
+{
+  Timecounter    *tc;
+  uint32_t        counter;
+  struct bintime  bt;
+  sbintime_t      sb;
+  struct timespec ts;
+  struct timeval  tv;
+
+  tc = &high_quality_high_frequency;
+  counter = 3 * tc->base.tc_frequency + 123456789;
+
+  /*
+   * Prepare the timecounter to get a large time difference.  Check that
+   * rtems_clock_get_realtime() returns the correct time.
+   */
+  SetCounter( tc, counter );
+  rtems_clock_get_realtime( &ts );
+  T_eq_i64( ts.tv_sec, 567993603 );
+  T_eq_u64( ts.tv_nsec, 114978100 );
+
+  /*
+   * Prepare the timecounter to get a large time difference.  Check that
+   * rtems_clock_get_realtime_bintime() returns the correct time.
+   */
+  SetCounter( tc, counter );
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993603 );
+  T_eq_u64( bt.frac, 2120971587975905280 );
+
+  /*
+   * Prepare the timecounter to get a large time difference.  Check that
+   * rtems_clock_get_realtime_timeval() returns the correct time.
+   */
+  SetCounter( tc, counter );
+  rtems_clock_get_realtime_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 567993603 );
+  T_eq_long( tv.tv_usec, 114978 );
+
+  /*
+   * Prepare the timecounter to get a large time difference.  Check that
+   * rtems_clock_get_monotonic() returns the correct time.
+   */
+  SetCounter( tc, counter );
+  rtems_clock_get_monotonic( &ts );
+  T_eq_i64( ts.tv_sec, 4 );
+  T_eq_u64( ts.tv_nsec, 114978100 );
+
+  /*
+   * Prepare the timecounter to get a large time difference.  Check that
+   * rtems_clock_get_monotonic_bintime() returns the correct time.
+   */
+  SetCounter( tc, counter );
+  rtems_clock_get_monotonic_bintime( &bt );
+  T_eq_i64( bt.sec, 4 );
+  T_eq_u64( bt.frac, 2120971587975905280 );
+
+  /*
+   * Prepare the timecounter to get a large time difference.  Check that
+   * rtems_clock_get_monotonic_sbintime() returns the correct time.
+   */
+  SetCounter( tc, counter );
+  sb = rtems_clock_get_monotonic_sbintime();
+  T_eq_i64( sb, 17673696364 );
+
+  /*
+   * Prepare the timecounter to get a large time difference.  Check that
+   * rtems_clock_get_monotonic_timeval() returns the correct time.
+   */
+  SetCounter( tc, counter );
+  rtems_clock_get_monotonic_timeval( &tv );
+  T_eq_i64( tv.tv_sec, 4 );
+  T_eq_long( tv.tv_usec, 114978 );
+}
+
+/**
+ * @brief Update the oldest timehand after a large time interval.
+ */
+static void ScoreTimecounterValInstall_Action_7( void )
+{
+  Timecounter    *tc;
+  struct bintime  bt;
+
+  tc = &high_quality_high_frequency;
+
+  SetCounter( tc, 0 );
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993600 );
+  T_eq_u64( bt.frac, 103079215104 );
+
+  SetCounter( tc, 2 * tc->base.tc_frequency );
+  CallTimecounterTick();
+
+  SetCounter( tc, 2 * tc->base.tc_frequency );
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993602 );
+  T_eq_u64( bt.frac, 103079215104 );
+}
+
+/**
+ * @brief Call the simple timecounter tick service with non-zero delta and
+ *   offset parameter values so that exactly one second passed.
+ */
+static void ScoreTimecounterValInstall_Action_8( void )
+{
+  ISR_lock_Context lock_context;
+  Timecounter     *tc;
+  struct bintime   bt;
+
+  tc = &high_quality_high_frequency;
+
+  _Timecounter_Acquire( &lock_context );
+  _Timecounter_Tick_simple(
+    tc->base.tc_frequency / 2,
+    GetCounter( tc ) - tc->base.tc_frequency / 2,
+    &lock_context
+  );
+
+  /*
+   * Check that exactly one second passed due to the simple clock tick service.
+   */
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993603 );
+  T_eq_u64( bt.frac, 103079215104 );
+}
+
+/**
+ * @brief Install a very high quality timecounter with a low frequency to test
+ *   the NTP support.
+ */
+static void ScoreTimecounterValInstall_Action_9( void )
+{
+  Timecounter   *tc;
+  struct bintime bt;
+
+  tc = &very_high_quality;
+  tc->base.tc_get_timecount = GetTimecount;
+  tc->base.tc_counter_mask = 0xffffffff;
+  tc->base.tc_frequency = 0x01000000;
+  tc->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER + 2;
+  rtems_timecounter_install( &tc->base );
+
+  T_eq_u32( GetCounter( tc ), 1 );
+
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993603 );
+  T_eq_u64( bt.frac, 1219770712064 );
+
+  /*
+   * Let the seconds value of CLOCK_REALTIME not change. Check that the NTP
+   * update second handler is not called.
+   */
+  _Timecounter_Set_NTP_update_second( NtpUpdateCounter );
+  SetCounter( tc, tc->base.tc_frequency / 2 );
+  CallTimecounterTick();
+  _Timecounter_Set_NTP_update_second( NULL );
+
+  T_eq_u32( ntp_counter, 0 );
+
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993603 );
+  T_eq_u64( bt.frac, UINT64_C( 9223373256625487872 ) );
+
+  /*
+   * Let the seconds value of CLOCK_REALTIME change by one. Check that the NTP
+   * update second handler is called exactly once.
+   */
+  _Timecounter_Set_NTP_update_second( NtpUpdateCounter );
+  SetCounter( tc, tc->base.tc_frequency );
+  CallTimecounterTick();
+  _Timecounter_Set_NTP_update_second( NULL );
+
+  T_eq_u32( ntp_counter, 1 );
+
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993604 );
+  T_eq_u64( bt.frac, 1219770712064 );
+
+  /*
+   * Let the seconds value of CLOCK_REALTIME change by 200. Check that the NTP
+   * update second handler is called exactly 200 times.
+   */
+  _Timecounter_Set_NTP_update_second( NtpUpdateCounter );
+  SetCounter( tc, 201 * tc->base.tc_frequency );
+  CallTimecounterTick();
+  _Timecounter_Set_NTP_update_second( NULL );
+
+  T_eq_u32( ntp_counter, 201 );
+
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567993804 );
+  T_eq_u64( bt.frac, 1219770712064 );
+
+  /*
+   * Let the seconds value of CLOCK_REALTIME change by 201. Check that the NTP
+   * update second handler is called exactly twice.
+   */
+  _Timecounter_Set_NTP_update_second( NtpUpdateCounter );
+  SetCounter( tc, 402 * tc->base.tc_frequency );
+  CallTimecounterTick();
+  _Timecounter_Set_NTP_update_second( NULL );
+
+  T_eq_u32( ntp_counter, 203 );
+
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567994005 );
+  T_eq_u64( bt.frac, 1219770712064 );
+
+  /*
+   * Let the seconds value of CLOCK_REALTIME change by one. Check that the NTP
+   * update second handler is incremented the CLOCK_REALTIME by one second.
+   */
+  _Timecounter_Set_NTP_update_second( NtpUpdateSecondIncrement );
+  SetCounter( tc, 403 * tc->base.tc_frequency );
+  CallTimecounterTick();
+  _Timecounter_Set_NTP_update_second( NULL );
+
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567994007 );
+  T_eq_u64( bt.frac, 1219770712064 );
+
+  /*
+   * Let the seconds value of CLOCK_REALTIME change by one. Check that the NTP
+   * update second handler is decremented the CLOCK_REALTIME by one second.
+   */
+  _Timecounter_Set_NTP_update_second( NtpUpdateSecondDecrement );
+  SetCounter( tc, 404 * tc->base.tc_frequency );
+  CallTimecounterTick();
+  _Timecounter_Set_NTP_update_second( NULL );
+
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567994007 );
+  T_eq_u64( bt.frac, 1219770712064 );
+
+  /*
+   * Let the seconds value of CLOCK_REALTIME change by one. Check that the NTP
+   * update second handler increased the timecounter frequency.
+   */
+  _Timecounter_Set_NTP_update_second( NtpUpdateAdjustmentFaster );
+  SetCounter( tc, 405 * tc->base.tc_frequency );
+  CallTimecounterTick();
+  _Timecounter_Set_NTP_update_second( NULL );
+
+  SetCounter( tc, 406 * tc->base.tc_frequency );
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567994009 );
+  T_eq_u64( bt.frac, 92353004044288 );
+
+  /*
+   * Let the seconds value of CLOCK_REALTIME change by one. Check that the NTP
+   * update second handler decreased the timecounter frequency.
+   */
+  _Timecounter_Set_NTP_update_second( NtpUpdateAdjustmentSlower );
+  SetCounter( tc, 407 * tc->base.tc_frequency );
+  CallTimecounterTick();
+  _Timecounter_Set_NTP_update_second( NULL );
+
+  SetCounter( tc, 408 * tc->base.tc_frequency );
+  rtems_clock_get_realtime_bintime( &bt );
+  T_eq_i64( bt.sec, 567994011 );
+  T_eq_u64( bt.frac, 92353004044288 );
+}
+
+/**
+ * @fn void T_case_body_ScoreTimecounterValInstall( void )
+ */
+T_TEST_CASE( ScoreTimecounterValInstall )
+{
+  ScoreTimecounterValInstall_Action_0();
+  ScoreTimecounterValInstall_Action_1();
+  ScoreTimecounterValInstall_Action_2();
+  ScoreTimecounterValInstall_Action_3();
+  ScoreTimecounterValInstall_Action_4();
+  ScoreTimecounterValInstall_Action_5();
+  ScoreTimecounterValInstall_Action_6();
+  ScoreTimecounterValInstall_Action_7();
+  ScoreTimecounterValInstall_Action_8();
+  ScoreTimecounterValInstall_Action_9();
+}
+
+/** @} */
diff --git a/testsuites/validation/ts-validation-timecounter-0.c b/testsuites/validation/ts-validation-timecounter-0.c
new file mode 100644
index 0000000..9e4abee
--- /dev/null
+++ b/testsuites/validation/ts-validation-timecounter-0.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationTimecounter0
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated.  If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual.  The manual is provided as a part of
+ * a release.  For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestSuiteTestsuitesValidationTimecounter0 \
+ *   spec:/testsuites/validation-timecounter-0
+ *
+ * @ingroup RTEMSTestSuites
+ *
+ * @brief This validation test suite is intended test cases related to the
+ *   installation of timecouters.  The Clock Driver is disabled.
+ *
+ * @{
+ */
+
+const char rtems_test_name[] = "ValidationTimecounter0";
+
+#define CONFIGURE_MAXIMUM_PROCESSORS 1
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+
+#include "ts-default.h"
+
+/** @} */
diff --git a/testsuites/validation/ts-validation-timecounter-1.c b/testsuites/validation/ts-validation-timecounter-1.c
new file mode 100644
index 0000000..ec0ff02
--- /dev/null
+++ b/testsuites/validation/ts-validation-timecounter-1.c
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationTimecounter1
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated.  If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual.  The manual is provided as a part of
+ * a release.  For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestSuiteTestsuitesValidationTimecounter1 \
+ *   spec:/testsuites/validation-timecounter-1
+ *
+ * @ingroup RTEMSTestSuites
+ *
+ * @brief This validation test suite is intended test cases related to the use
+ *   of timecouters.  The Clock Driver is enabled.
+ *
+ * @{
+ */
+
+const char rtems_test_name[] = "ValidationTimecounter1";
+
+#define CONFIGURE_MAXIMUM_PROCESSORS 4
+
+#include "ts-default.h"
+
+/** @} */
diff --git a/testsuites/validation/ts-validation-timecounter-smp-0.c b/testsuites/validation/ts-validation-timecounter-smp-0.c
new file mode 100644
index 0000000..6ae0311
--- /dev/null
+++ b/testsuites/validation/ts-validation-timecounter-smp-0.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationTimecounterSmp0
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated.  If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual.  The manual is provided as a part of
+ * a release.  For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestSuiteTestsuitesValidationTimecounterSmp0 \
+ *   spec:/testsuites/validation-timecounter-smp-0
+ *
+ * @ingroup RTEMSTestSuites
+ *
+ * @brief This validation test suite is intended test cases related to the use
+ *   of timecouters.  The Clock Driver is disabled.
+ *
+ * @{
+ */
+
+const char rtems_test_name[] = "ValidationTimecounterSmp0";
+
+#define CONFIGURE_MAXIMUM_PROCESSORS 4
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+
+#include "ts-default.h"
+
+/** @} */



More information about the vc mailing list