[rtems-central commit] spec: Specify and test timecounters

Sebastian Huber sebh at rtems.org
Wed Oct 13 07:58:21 UTC 2021


Module:    rtems-central
Branch:    master
Commit:    6146398a1794bc2aa3f8c8e93fd9783e02c27b0b
Changeset: http://git.rtems.org/rtems-central/commit/?id=6146398a1794bc2aa3f8c8e93fd9783e02c27b0b

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Tue Oct 12 10:19:44 2021 +0200

spec: Specify and test timecounters

---

 spec/req/clocks.yml                                |  14 +
 spec/rtems/clock/req/get-boot-time.yml             |  21 +
 spec/rtems/clock/req/get-monotonic-coarse.yml      |  22 +
 spec/rtems/clock/req/get-monotonic.yml             |  24 +
 spec/rtems/clock/req/get-realtime-coarse.yml       |  23 +
 spec/rtems/clock/req/get-realtime.yml              |  23 +
 .../req/clock-monotonic-initial-frozen.yml         |  15 +
 .../timecounter/req/clock-monotonic-initial.yml    |  15 +
 spec/score/timecounter/req/clock-monotonic.yml     |  15 +
 .../req/clock-realtime-initial-frozen.yml          |  15 +
 .../timecounter/req/clock-realtime-initial.yml     |  15 +
 spec/score/timecounter/req/clock-realtime.yml      |  15 +
 .../score/timecounter/req/get-coarse-no-device.yml |  15 +
 spec/score/timecounter/req/get-coarse.yml          |  15 +
 spec/score/timecounter/req/get-device.yml          |  15 +
 spec/score/timecounter/req/get-large-delta.yml     |  16 +
 spec/score/timecounter/req/get-non-blocking.yml    |  17 +
 spec/score/timecounter/req/get.yml                 |  15 +
 spec/score/timecounter/req/group.yml               |  15 +
 spec/score/timecounter/req/install-frequency.yml   |  17 +
 spec/score/timecounter/req/install-quality.yml     |  16 +
 spec/score/timecounter/req/install.yml             |  15 +
 spec/score/timecounter/unit/kern-tc.yml            | 162 +---
 spec/score/timecounter/val/get-smp.yml             | 161 ++++
 spec/score/timecounter/val/get.yml                 | 518 +++++++++++++
 spec/score/timecounter/val/install.yml             | 816 +++++++++++++++++++++
 spec/testsuites/validation-timecounter-0.yml       |  24 +
 spec/testsuites/validation-timecounter-1.yml       |  22 +
 spec/testsuites/validation-timecounter-smp-0.yml   |  24 +
 29 files changed, 1942 insertions(+), 158 deletions(-)

diff --git a/spec/req/clocks.yml b/spec/req/clocks.yml
new file mode 100644
index 0000000..5379931
--- /dev/null
+++ b/spec/req/clocks.yml
@@ -0,0 +1,14 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: root
+non-functional-type: design
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The system shall provide clocks.
+type: requirement
diff --git a/spec/rtems/clock/req/get-boot-time.yml b/spec/rtems/clock/req/get-boot-time.yml
new file mode 100644
index 0000000..da47774
--- /dev/null
+++ b/spec/rtems/clock/req/get-boot-time.yml
@@ -0,0 +1,21 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: interface-function
+  uid: ../if/get-boot-time
+- role: interface-function
+  uid: ../if/get-boot-time-bintime
+- role: interface-function
+  uid: ../if/get-boot-time-timeval
+- role: function-implementation
+  uid: /score/timecounter/req/get-coarse
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  The directive shall return a time point during system initialization which is
+  used by ${/glossary/clock-realtime:/term}.
+type: requirement
diff --git a/spec/rtems/clock/req/get-monotonic-coarse.yml b/spec/rtems/clock/req/get-monotonic-coarse.yml
new file mode 100644
index 0000000..ef3956c
--- /dev/null
+++ b/spec/rtems/clock/req/get-monotonic-coarse.yml
@@ -0,0 +1,22 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: interface-function
+  uid: ../if/get-monotonic-coarse
+- role: interface-function
+  uid: ../if/get-monotonic-coarse-bintime
+- role: interface-function
+  uid: ../if/get-monotonic-coarse-timeval
+- role: function-implementation
+  uid: /score/timecounter/req/get-coarse
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  The directive shall return the time elapsed since some fixed time point in
+  the past measured using the ${/glossary/clock-monotonic:/term} at some time
+  point close to the directive call.
+type: requirement
diff --git a/spec/rtems/clock/req/get-monotonic.yml b/spec/rtems/clock/req/get-monotonic.yml
new file mode 100644
index 0000000..33a257e
--- /dev/null
+++ b/spec/rtems/clock/req/get-monotonic.yml
@@ -0,0 +1,24 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: interface-function
+  uid: ../if/get-monotonic
+- role: interface-function
+  uid: ../if/get-monotonic-bintime
+- role: interface-function
+  uid: ../if/get-monotonic-sbintime
+- role: interface-function
+  uid: ../if/get-monotonic-timeval
+- role: function-implementation
+  uid: /score/timecounter/req/get
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  The directive shall return the time elapsed since some fixed time point in
+  the past measured using the ${/glossary/clock-monotonic:/term} at some time
+  point during the directive call.
+type: requirement
diff --git a/spec/rtems/clock/req/get-realtime-coarse.yml b/spec/rtems/clock/req/get-realtime-coarse.yml
new file mode 100644
index 0000000..9d685f2
--- /dev/null
+++ b/spec/rtems/clock/req/get-realtime-coarse.yml
@@ -0,0 +1,23 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: interface-function
+  uid: ../if/get-realtime-coarse
+- role: interface-function
+  uid: ../if/get-realtime-coarse-bintime
+- role: interface-function
+  uid: ../if/get-realtime-coarse-timeval
+- role: function-implementation
+  uid: /score/timecounter/req/get-coarse
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  The directive shall return the time elapsed since the
+  ${/glossary/unix-epoch:/term} measured using the
+  ${/glossary/clock-realtime:/term} at some time point close to the directive
+  call.
+type: requirement
diff --git a/spec/rtems/clock/req/get-realtime.yml b/spec/rtems/clock/req/get-realtime.yml
new file mode 100644
index 0000000..20e2608
--- /dev/null
+++ b/spec/rtems/clock/req/get-realtime.yml
@@ -0,0 +1,23 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: interface-function
+  uid: ../if/get-realtime
+- role: interface-function
+  uid: ../if/get-realtime-bintime
+- role: interface-function
+  uid: ../if/get-realtime-timeval
+- role: function-implementation
+  uid: /score/timecounter/req/get
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  The directive shall return the time elapsed since the
+  ${/glossary/unix-epoch:/term} measured using the
+  ${/glossary/clock-realtime:/term} at some time point during the directive
+  call.
+type: requirement
diff --git a/spec/score/timecounter/req/clock-monotonic-initial-frozen.yml b/spec/score/timecounter/req/clock-monotonic-initial-frozen.yml
new file mode 100644
index 0000000..5429d22
--- /dev/null
+++ b/spec/score/timecounter/req/clock-monotonic-initial-frozen.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: clock-monotonic
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  While no timecounter is installed, the ${/glossary/clock-monotonic:/term}
+  shall remain at the initial value.
+type: requirement
diff --git a/spec/score/timecounter/req/clock-monotonic-initial.yml b/spec/score/timecounter/req/clock-monotonic-initial.yml
new file mode 100644
index 0000000..81321d9
--- /dev/null
+++ b/spec/score/timecounter/req/clock-monotonic-initial.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: clock-monotonic
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  The initial value of the ${/glossary/clock-monotonic:/term} shall be
+  0000-00-00T00:00:01.000000000.
+type: requirement
diff --git a/spec/score/timecounter/req/clock-monotonic.yml b/spec/score/timecounter/req/clock-monotonic.yml
new file mode 100644
index 0000000..12f119c
--- /dev/null
+++ b/spec/score/timecounter/req/clock-monotonic.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: group
+non-functional-type: design
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The timecounter component shall provide the
+  ${/glossary/clock-monotonic:/term}.
+type: requirement
diff --git a/spec/score/timecounter/req/clock-realtime-initial-frozen.yml b/spec/score/timecounter/req/clock-realtime-initial-frozen.yml
new file mode 100644
index 0000000..d87265b
--- /dev/null
+++ b/spec/score/timecounter/req/clock-realtime-initial-frozen.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: clock-realtime
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  While no timecounter is installed, the ${/glossary/clock-realtime:/term}
+  shall remain at the initial value.
+type: requirement
diff --git a/spec/score/timecounter/req/clock-realtime-initial.yml b/spec/score/timecounter/req/clock-realtime-initial.yml
new file mode 100644
index 0000000..278fa36
--- /dev/null
+++ b/spec/score/timecounter/req/clock-realtime-initial.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: clock-realtime
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  The initial value of the ${/glossary/clock-realtime:/term} shall be
+  1988-01-01T00:00:00.000000000.
+type: requirement
diff --git a/spec/score/timecounter/req/clock-realtime.yml b/spec/score/timecounter/req/clock-realtime.yml
new file mode 100644
index 0000000..7c91145
--- /dev/null
+++ b/spec/score/timecounter/req/clock-realtime.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: group
+non-functional-type: design
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The timecounter component shall provide the
+  ${/glossary/clock-realtime:/term}.
+type: requirement
diff --git a/spec/score/timecounter/req/get-coarse-no-device.yml b/spec/score/timecounter/req/get-coarse-no-device.yml
new file mode 100644
index 0000000..752ee27
--- /dev/null
+++ b/spec/score/timecounter/req/get-coarse-no-device.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: get-coarse
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  The directives to get time values in a coarse precision shall not use the
+  currently installed timecounter.
+type: requirement
diff --git a/spec/score/timecounter/req/get-coarse.yml b/spec/score/timecounter/req/get-coarse.yml
new file mode 100644
index 0000000..875d455
--- /dev/null
+++ b/spec/score/timecounter/req/get-coarse.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: group
+non-functional-type: design
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The timecounter component shall implement directives to get time values in a
+  coarse precision.
+type: requirement
diff --git a/spec/score/timecounter/req/get-device.yml b/spec/score/timecounter/req/get-device.yml
new file mode 100644
index 0000000..27219eb
--- /dev/null
+++ b/spec/score/timecounter/req/get-device.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: get
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  The directives to get time values in the highest precision shall use the
+  currently installed timecounter to get a clock snapshot.
+type: requirement
diff --git a/spec/score/timecounter/req/get-large-delta.yml b/spec/score/timecounter/req/get-large-delta.yml
new file mode 100644
index 0000000..1b7770b
--- /dev/null
+++ b/spec/score/timecounter/req/get-large-delta.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: get
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  While the timehand used to get the time was not updated for one second or
+  more, while the timecounter of the timehand did not overflow, the directives
+  to get time values in the highest precision shall return the correct time.
+type: requirement
diff --git a/spec/score/timecounter/req/get-non-blocking.yml b/spec/score/timecounter/req/get-non-blocking.yml
new file mode 100644
index 0000000..c3eb2b9
--- /dev/null
+++ b/spec/score/timecounter/req/get-non-blocking.yml
@@ -0,0 +1,17 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: get
+- role: requirement-refinement
+  uid: get-coarse
+non-functional-type: design
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The directives to get time values shall use a sequence lock to synchronize
+  the reader with exactly one writer.
+type: requirement
diff --git a/spec/score/timecounter/req/get.yml b/spec/score/timecounter/req/get.yml
new file mode 100644
index 0000000..fa8234e
--- /dev/null
+++ b/spec/score/timecounter/req/get.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: group
+non-functional-type: design
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The timecounter component shall implement directives to get time values in
+  the highest precision available to the system.
+type: requirement
diff --git a/spec/score/timecounter/req/group.yml b/spec/score/timecounter/req/group.yml
new file mode 100644
index 0000000..7a2e0ff
--- /dev/null
+++ b/spec/score/timecounter/req/group.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+identifier: RTEMSScoreTimecounter
+links:
+- role: interface-ingroup
+  uid: ../../if/group
+non-functional-type: design-group
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The super core shall have a component containing the clock implementation.
+type: requirement
diff --git a/spec/score/timecounter/req/install-frequency.yml b/spec/score/timecounter/req/install-frequency.yml
new file mode 100644
index 0000000..d88401f
--- /dev/null
+++ b/spec/score/timecounter/req/install-frequency.yml
@@ -0,0 +1,17 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: install
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  While the timecounter to install has a quality level equal to the quality
+  level of the currently installed timecounter, while the timecounter to
+  install has a higher frequancy greater than the frequency of the currently
+  installed timecounter, the timecounter to install shall be installed.
+type: requirement
diff --git a/spec/score/timecounter/req/install-quality.yml b/spec/score/timecounter/req/install-quality.yml
new file mode 100644
index 0000000..8e83424
--- /dev/null
+++ b/spec/score/timecounter/req/install-quality.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: install
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  While the timecounter to install has a quality level greater than the quality
+  level of the currently installed timecounter, the timecounter to install
+  shall be installed.
+type: requirement
diff --git a/spec/score/timecounter/req/install.yml b/spec/score/timecounter/req/install.yml
new file mode 100644
index 0000000..1356890
--- /dev/null
+++ b/spec/score/timecounter/req/install.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: group
+non-functional-type: design
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+  The timecounter component shall implement a directive to install a
+  timecounter.
+type: requirement
diff --git a/spec/score/timecounter/unit/kern-tc.yml b/spec/score/timecounter/unit/kern-tc.yml
index 3e4dcd3..fb1cdca 100644
--- a/spec/score/timecounter/unit/kern-tc.yml
+++ b/spec/score/timecounter/unit/kern-tc.yml
@@ -5,158 +5,6 @@ enabled-by: true
 links: []
 test-actions:
 
-#### _Timecounter_Getbintime() ################################################
-
-- action-brief: |
-    Call function _Timecounter_Getbintime().
-  action-code: |
-    struct bintime bt;
-    _Timecounter_Getbintime( &bt );
-  checks:
-  - brief: |
-      Check value returned by function call.
-    code: |
-      T_eq_u64( bt.sec, TOD_SECONDS_1970_THROUGH_1988 );
-      T_eq_long( bt.frac, 0 );
-    links: []
-  links:
-  - name: _Timecounter_Getbintime
-    role: unit-test
-    uid: ../../if/domain
-
-#### _Timecounter_Getbinuptime() ##############################################
-
-- action-brief: |
-    Call function _Timecounter_Getbinuptime().
-  action-code: |
-    struct bintime bt;
-    _Timecounter_Getbinuptime( &bt );
-  checks:
-  - brief: |
-      Check value returned by function call.
-    code: |
-      T_eq_u64( bt.sec, 1 );
-      T_eq_long( bt.frac, 0 );
-    links: []
-  links:
-  - name: _Timecounter_Getbinuptime
-    role: unit-test
-    uid: ../../if/domain
-
-#### _Timecounter_Getboottime() ##############$$$##############################
-
-- action-brief: |
-    Call function _Timecounter_Getboottime().
-  action-code: |
-    struct timeval tv;
-    _Timecounter_Getboottime( &tv );
-  checks:
-  - brief: |
-      Check value returned by function call.
-    code: |
-      T_eq_u64( tv.tv_sec, TOD_SECONDS_1970_THROUGH_1988 - 1 );
-      T_eq_long( tv.tv_usec, 0 );
-    links: []
-  links:
-  - name: _Timecounter_Getboottime
-    role: unit-test
-    uid: ../../if/domain
-
-#### _Timecounter_Getboottimebin() ############################################
-
-- action-brief: |
-    Call function _Timecounter_Getboottimebin().
-  action-code: |
-    struct bintime bt;
-    _Timecounter_Getboottimebin( &bt );
-  checks:
-  - brief: |
-      Check value returned by function call.
-    code: |
-      T_eq_u64( bt.sec, TOD_SECONDS_1970_THROUGH_1988 - 1 );
-      T_eq_long( bt.frac, 0 );
-    links: []
-  links:
-  - name: _Timecounter_Getboottimebin
-    role: unit-test
-    uid: ../../if/domain
-
-#### _Timecounter_Getmicrotime() ##############################################
-
-- action-brief: |
-    Call function _Timecounter_Getmicrotime().
-  action-code: |
-    struct timeval tv;
-    _Timecounter_Getmicrotime( &tv );
-  checks:
-  - brief: |
-      Check value returned by function call.
-    code: |
-      T_eq_u64( tv.tv_sec, TOD_SECONDS_1970_THROUGH_1988 );
-      T_eq_long( tv.tv_usec, 0 );
-    links: []
-  links:
-  - name: _Timecounter_Getmicrotime
-    role: unit-test
-    uid: ../../if/domain
-
-#### _Timecounter_Getmicrouptime() ############################################
-
-- action-brief: |
-    Call function _Timecounter_Getmicrouptime().
-  action-code: |
-    struct timeval tv;
-    _Timecounter_Getmicrouptime( &tv );
-  checks:
-  - brief: |
-      Check value returned by function call.
-    code: |
-      T_eq_u64( tv.tv_sec, 1 );
-      T_eq_long( tv.tv_usec, 0 );
-    links: []
-  links:
-  - name: _Timecounter_Getmicrouptime
-    role: unit-test
-    uid: ../../if/domain
-
-#### _Timecounter_Microuptime() ##############################################
-
-- action-brief: |
-    Call function _Timecounter_Microuptime().
-  action-code: |
-    struct timeval tv;
-    _Timecounter_Microuptime( &tv );
-  checks:
-  - brief: |
-      Check value returned by function call.
-    code: |
-      T_eq_u64( tv.tv_sec, 1 );
-      /* T_eq_long( tv.tv_usec, 0 ); is increased by other sources */
-    links: []
-  links:
-  - name: _Timecounter_Microuptime
-    role: unit-test
-    uid: ../../if/domain
-
-#### _Timecounter_Nanotime() #################################################
-
-- action-brief: |
-    Call function _Timecounter_Nanotime().
-  action-code: |
-    struct timespec ts;
-    _Timecounter_Nanotime( &ts );
-  checks:
-  - brief: |
-      Check value returned by function call.
-    code: |
-      T_eq_u64( ts.tv_sec, TOD_SECONDS_1970_THROUGH_1988 );
-      /* T_eq_long( ts.tv_nsec, 0 ); is increased by other sources */
-    links: []
-  links:
-  - name: _Timecounter_Nanotime
-    role: unit-test
-    uid: ../../if/domain
-
 #### _Timecounter_Tick_simple() ###############################################
 
 - action-brief: |
@@ -178,15 +26,13 @@ test-brief: |
 test-context: []
 test-context-support: null
 test-description: |
-  Parts of the file ``cpukit/score/src/kern_tc.c``
-  are only executed by the POSIX API and certain device driver code.  The
-  space qualified code subset does not contain those features.  This test
-  exercises the code parts otherwise not reached in order to achieve full
-  code coverage.
+  Parts of the file ``cpukit/score/src/kern_tc.c`` are only executed by certain
+  device driver code.  The space qualified code subset does not contain those
+  features.  This test exercises the code parts otherwise not reached in order
+  to achieve full code coverage.
 test-header: null
 test-includes:
 - rtems/score/timecounter.h
-- rtems/score/todimpl.h
 test-local-includes: []
 test-setup: null
 test-stop: null
diff --git a/spec/score/timecounter/val/get-smp.yml b/spec/score/timecounter/val/get-smp.yml
new file mode 100644
index 0000000..d3257d7
--- /dev/null
+++ b/spec/score/timecounter/val/get-smp.yml
@@ -0,0 +1,161 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links: []
+test-actions:
+- action-brief: |
+    Install timecounter of different quality levels and frequencies.
+  action-code: |
+    Timecounter     *tc;
+    rtems_id         worker_id;
+    Per_CPU_Control *cpu_self;
+
+    tc = &test_timecounter;
+    _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, Worker, tc );
+
+    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 );
+
+    /* A */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+  checks:
+  - brief: |
+      Install a timecounter with a high quality level and normal frequency.
+      Check that it was installed.
+    code: |
+      /* B0 */
+      _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+      /* B1 */
+      _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+      cpu_self = _Thread_Dispatch_disable();
+      tc->delay = false;
+      rtems_timecounter_tick();
+      tc->delay = true;
+      rtems_timecounter_tick();
+      _Thread_Dispatch_enable( cpu_self );
+
+      /* B4 */
+      _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+      /* B5 */
+      _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+      tc->base.tc_get_timecount = GetTimecountDummy;
+      DeleteTask( worker_id );
+    links:
+    - role: validation
+      uid: ../req/install-quality
+  links: []
+test-brief: |
+  Tests directives to get a time value.
+test-context: []
+test-context-support: null
+test-description: null
+test-header: null
+test-includes:
+- rtems.h
+- rtems/timecounter.h
+- rtems/score/threaddispatch.h
+- rtems/score/smpbarrier.h
+test-local-includes:
+- tx-support.h
+test-setup: null
+test-stop: null
+test-support: |
+  typedef struct {
+    struct timecounter  base;
+    bool                delay;
+    uint32_t            counter;
+    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;
+
+    if ( rtems_scheduler_get_processor() == 0 ) {
+      if ( !tc->delay ) {
+        return 0;
+      }
+
+      /* B2 */
+      _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+      /* B3 */
+      _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 0 ], 2 );
+
+      return 0;
+    }
+
+    if ( tc->counter == 0 ) {
+      /* Do nothing */
+    } else if ( tc->counter == 1 ) {
+      tc->counter = 2;
+
+      /* B1 */
+      _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+      /* B2 */
+      _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+    } else if ( tc->counter == 2 ) {
+      tc->counter = 3;
+
+      /* B3 */
+      _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+      /* B4 */
+      _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+    }
+
+    return 0;
+  }
+
+  static uint32_t GetTimecountDummy( struct timecounter *base )
+  {
+    (void) base;
+
+    return 0;
+  }
+
+  static void Worker( rtems_task_argument arg )
+  {
+    Timecounter   *tc;
+    struct bintime bt;
+
+    tc = (Timecounter *) arg;
+
+    /* A */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    tc->counter = 1;
+
+    /* B0 */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    rtems_clock_get_realtime_bintime( &bt );
+
+    /* B5 */
+    _SMP_barrier_Wait( &tc->barrier, &tc->barrier_state[ 1 ], 2 );
+
+    ReceiveAnyEvents();
+  }
+test-target: testsuites/validation/tc-timecounter-get-smp.c
+test-teardown: null
+type: test-case
diff --git a/spec/score/timecounter/val/get.yml b/spec/score/timecounter/val/get.yml
new file mode 100644
index 0000000..a09072f
--- /dev/null
+++ b/spec/score/timecounter/val/get.yml
@@ -0,0 +1,518 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links: []
+test-actions:
+- action-brief: |
+    Install a timecounter which can be used to perform interrut tests for the
+    get time directives.
+  action-code: |
+    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 );
+  checks:
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-realtime:/name} directive to
+      provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionRealtime;
+      InterruptTest( &config, tc, 1 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-realtime-bintime:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionRealtimeBintime;
+      InterruptTest( &config, tc, 1 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-realtime-timeval:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionRealtimeTimeval;
+      InterruptTest( &config, tc, 1 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-monotonic:/name} directive to
+      provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionMonotonic;
+      InterruptTest( &config, tc, 1 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-monotonic-bintime:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionMonotonicBintime;
+      InterruptTest( &config, tc, 1 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-monotonic-sbintime:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionMonotonicSbintime;
+      InterruptTest( &config, tc, 1 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-monotonic-timeval:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionMonotonicTimeval;
+      InterruptTest( &config, tc, 1 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Prepare for the coarse get time directives.
+    code: |
+      config.interrupt = InterruptCoarse;
+    links: []
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-realtime-coarse:/name} directive to
+      provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionCoarseRealtime;
+      InterruptTest( &config, tc, 10 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-realtime-coarse
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-realtime-coarse-bintime:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionCoarseRealtimeBintime;
+      InterruptTest( &config, tc, 10 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-realtime-coarse
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-realtime-coarse-timeval:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionCoarseRealtimeTimeval;
+      InterruptTest( &config, tc, 10 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-realtime-coarse
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-monotonic-coarse:/name} directive to
+      provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionCoarseMonotonic;
+      InterruptTest( &config, tc, 10 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic-coarse
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-monotonic-coarse-bintime:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionCoarseMonotonicBintime;
+      InterruptTest( &config, tc, 10 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic-coarse
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-monotonic-coarse-timeval:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionCoarseMonotonicTimeval;
+      InterruptTest( &config, tc, 10 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic-coarse
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-boot-time:/name} directive to
+      provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionBootTime;
+      InterruptTest( &config, tc, 10 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-boot-time
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-boot-time-bintime:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionBootTimeBintime;
+      InterruptTest( &config, tc, 10 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-boot-time
+  - brief: |
+      Try to interrupt the ${/rtems/clock/if/get-boot-time-timeval:/name}
+      directive to provoke a change in the timehand generation number.
+    code: |
+      config.action = ActionBootTimeTimeval;
+      InterruptTest( &config, tc, 10 );
+    links:
+    - role: validation
+      uid: ../req/get-non-blocking
+    - role: validation
+      uid: /rtems/clock/req/get-boot-time
+  links: []
+test-brief: |
+  Tests directives to get a time value.
+test-context: []
+test-context-support: |
+test-description: null
+test-header: null
+test-includes:
+- rtems.h
+- rtems/counter.h
+- rtems/timecounter.h
+- rtems/score/timecounterimpl.h
+test-local-includes:
+- tx-support.h
+test-setup: null
+test-stop: null
+test-support: |
+  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 void InterruptTest(
+    const T_interrupt_test_config *config,
+    void                          *arg,
+    uint32_t                       iterations
+  )
+  {
+    uint32_t i;
+
+    for ( i = 0; i < iterations; ++i ) {
+      T_interrupt_test_state test_state;
+
+      test_state = T_interrupt_test( config, arg );
+      T_eq_int( test_state, T_INTERRUPT_TEST_DONE );
+    }
+  }
+test-target: testsuites/validation/tc-timecounter-get.c
+test-teardown: null
+type: test-case
diff --git a/spec/score/timecounter/val/install.yml b/spec/score/timecounter/val/install.yml
new file mode 100644
index 0000000..82684e7
--- /dev/null
+++ b/spec/score/timecounter/val/install.yml
@@ -0,0 +1,816 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links: []
+test-actions:
+- action-brief: |
+    Call the directives to get the initial value of
+    ${/glossary/clock-realtime:/term} and the initial boot time.
+  action-code: |
+    struct bintime  bt;
+    struct timespec ts;
+    struct timeval  tv;
+  checks:
+  - brief: |
+      Check the initial ${/glossary/clock-realtime:/term} in seconds and
+      nanoseconds format.
+    code: |
+      rtems_clock_get_realtime( &ts );
+      T_eq_i64( ts.tv_sec, 567993600 );
+      T_eq_u64( ts.tv_nsec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Check that ${/glossary/clock-realtime:/term} is frozen in seconds and
+      nanoseconds format.
+    code: |
+      rtems_clock_get_realtime( &ts );
+      T_eq_i64( ts.tv_sec, 567993600 );
+      T_eq_u64( ts.tv_nsec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-realtime:/term} in coarse precision
+      in seconds and nanoseconds format.
+    code: |
+      rtems_clock_get_realtime_coarse( &ts );
+      T_eq_i64( ts.tv_sec, 567993600 );
+      T_eq_u64( ts.tv_nsec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial
+    - role: validation
+      uid: /rtems/clock/req/get-realtime-coarse
+  - brief: |
+      Check that ${/glossary/clock-realtime:/term} is frozen in coarse
+      precision in seconds and nanoseconds format.
+    code: |
+      rtems_clock_get_realtime_coarse( &ts );
+      T_eq_i64( ts.tv_sec, 567993600 );
+      T_eq_u64( ts.tv_nsec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-realtime:/term} in binary time
+      format.
+    code: |
+      rtems_clock_get_realtime_bintime( &bt );
+      T_eq_i64( bt.sec, 567993600 );
+      T_eq_u64( bt.frac, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Check that ${/glossary/clock-realtime:/term} is frozen in binary time
+      format.
+    code: |
+      rtems_clock_get_realtime_bintime( &bt );
+      T_eq_i64( bt.sec, 567993600 );
+      T_eq_u64( bt.frac, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-realtime:/term} in coarse precision
+      in binary time format.
+    code: |
+      rtems_clock_get_realtime_coarse_bintime( &bt );
+      T_eq_i64( bt.sec, 567993600 );
+      T_eq_u64( bt.frac, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial
+    - role: validation
+      uid: /rtems/clock/req/get-realtime-coarse
+  - brief: |
+      Check that ${/glossary/clock-realtime:/term} is frozen in coarse
+      precision in binary time format.
+    code: |
+      rtems_clock_get_realtime_coarse_bintime( &bt );
+      T_eq_i64( bt.sec, 567993600 );
+      T_eq_u64( bt.frac, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-realtime:/term} in seconds and
+      microseconds format.
+    code: |
+      rtems_clock_get_realtime_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 567993600 );
+      T_eq_long( tv.tv_usec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Check that ${/glossary/clock-realtime:/term} is frozen in seconds and
+      microseconds format.
+    code: |
+      rtems_clock_get_realtime_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 567993600 );
+      T_eq_long( tv.tv_usec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-realtime:/term} in coarse precision
+      in seconds and microseconds format.
+    code: |
+      rtems_clock_get_realtime_coarse_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 567993600 );
+      T_eq_long( tv.tv_usec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial
+    - role: validation
+      uid: /rtems/clock/req/get-realtime-coarse
+  - brief: |
+      Check that ${/glossary/clock-realtime:/term} is frozen in coarse
+      precision in seconds and microseconds format.
+    code: |
+      rtems_clock_get_realtime_coarse_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 567993600 );
+      T_eq_long( tv.tv_usec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial-frozen
+  - brief: |
+      Check the initial boot time in seconds and nanoseconds format.
+    code: |
+      rtems_clock_get_boot_time( &ts );
+      T_eq_i64( ts.tv_sec, 567993599 );
+      T_eq_u64( ts.tv_nsec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial
+    - role: validation
+      uid: ../req/clock-monotonic-initial
+    - role: validation
+      uid: /rtems/clock/req/get-boot-time
+  - brief: |
+      Check the initial boot time in binary time format.
+    code: |
+      rtems_clock_get_boot_time_bintime( &bt );
+      T_eq_i64( bt.sec, 567993599 );
+      T_eq_u64( bt.frac, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial
+    - role: validation
+      uid: ../req/clock-monotonic-initial
+    - role: validation
+      uid: /rtems/clock/req/get-boot-time
+  - brief: |
+      Check the initial boot time in seconds and microseconds format.
+    code: |
+      rtems_clock_get_boot_time_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 567993599 );
+      T_eq_long( tv.tv_usec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-realtime-initial
+    - role: validation
+      uid: ../req/clock-monotonic-initial
+    - role: validation
+      uid: /rtems/clock/req/get-boot-time
+  links: []
+- action-brief: |
+    Call the directives to get the initial value of
+    ${/glossary/clock-monotonic:/term} and the initial boot time.
+  action-code: |
+    struct bintime  bt;
+    sbintime_t      sb;
+    struct timespec ts;
+    struct timeval  tv;
+  checks:
+  - brief: |
+      Check the initial ${/glossary/clock-monotonic:/term} in seconds and
+      nanoseconds format.
+    code: |
+      rtems_clock_get_monotonic( &ts );
+      T_eq_i64( ts.tv_sec, 1 );
+      T_eq_u64( ts.tv_nsec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Check that ${/glossary/clock-monotonic:/term} is frozen in seconds and
+      nanoseconds format.
+    code: |
+      rtems_clock_get_monotonic( &ts );
+      T_eq_i64( ts.tv_sec, 1 );
+      T_eq_u64( ts.tv_nsec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-monotonic:/term} in coarse precision
+      in seconds and nanoseconds format.
+    code: |
+      rtems_clock_get_monotonic_coarse( &ts );
+      T_eq_i64( ts.tv_sec, 1 );
+      T_eq_u64( ts.tv_nsec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic-coarse
+  - brief: |
+      Check that ${/glossary/clock-monotonic:/term} is frozen in coarse
+      precision in seconds and nanoseconds format.
+    code: |
+      rtems_clock_get_monotonic_coarse( &ts );
+      T_eq_i64( ts.tv_sec, 1 );
+      T_eq_u64( ts.tv_nsec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-monotonic:/term} in binary time
+      format.
+    code: |
+      rtems_clock_get_monotonic_bintime( &bt );
+      T_eq_i64( bt.sec, 1 );
+      T_eq_u64( bt.frac, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Check that ${/glossary/clock-monotonic:/term} is frozen in binary time
+      format.
+    code: |
+      rtems_clock_get_monotonic_bintime( &bt );
+      T_eq_i64( bt.sec, 1 );
+      T_eq_u64( bt.frac, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-monotonic:/term} in coarse precision
+      in binary time format.
+    code: |
+      rtems_clock_get_monotonic_coarse_bintime( &bt );
+      T_eq_i64( bt.sec, 1 );
+      T_eq_u64( bt.frac, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic-coarse
+  - brief: |
+      Check that ${/glossary/clock-monotonic:/term} is frozen in coarse
+      precision in binary time format.
+    code: |
+      rtems_clock_get_monotonic_coarse_bintime( &bt );
+      T_eq_i64( bt.sec, 1 );
+      T_eq_u64( bt.frac, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-monotonic:/term} in signed binary
+      time format.
+    code: |
+      sb = rtems_clock_get_monotonic_sbintime();
+      T_eq_i64( sb, SBT_1S );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Check that ${/glossary/clock-monotonic:/term} is frozen in signed binary
+      time format.
+    code: |
+      sb = rtems_clock_get_monotonic_sbintime();
+      T_eq_i64( sb, SBT_1S );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-monotonic:/term} in seconds and
+      microseconds format.
+    code: |
+      rtems_clock_get_monotonic_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 1 );
+      T_eq_long( tv.tv_usec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Check that ${/glossary/clock-monotonic:/term} is frozen in seconds and
+      microseconds format.
+    code: |
+      rtems_clock_get_monotonic_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 1 );
+      T_eq_long( tv.tv_usec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial-frozen
+  - brief: |
+      Check the initial ${/glossary/clock-monotonic:/term} in coarse precision
+      in seconds and microseconds format.
+    code: |
+      rtems_clock_get_monotonic_coarse_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 1 );
+      T_eq_long( tv.tv_usec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic-coarse
+  - brief: |
+      Check that ${/glossary/clock-monotonic:/term} is frozen in coarse
+      precision in seconds and microseconds format.
+    code: |
+      rtems_clock_get_monotonic_coarse_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 1 );
+      T_eq_long( tv.tv_usec, 0 );
+    links:
+    - role: validation
+      uid: ../req/clock-monotonic-initial-frozen
+  links: []
+- action-brief: |
+    Install timecounter of different quality levels and frequencies.
+  action-code: |
+    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;
+  checks:
+  - brief: |
+      Install a timecounter with a high quality level and normal frequency.
+      Check that it was installed.
+    code: |
+      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 );
+    links:
+    - role: validation
+      uid: ../req/install-quality
+  - brief: |
+      Install a timecounter with a high quality level and low frequency.
+      Check that it was not installed.
+    code: |
+      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 );
+    links:
+    - role: validation
+      uid: ../req/install-frequency
+  - brief: |
+      Install a timecounter with a high quality level and high frequency.
+      Check that it was installed.
+    code: |
+      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 );
+    links:
+    - role: validation
+      uid: ../req/install-frequency
+  - brief: |
+      Install a timecounter with a low quality level.  Check that it was not
+      installed.
+    code: |
+      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 );
+    links:
+    - role: validation
+      uid: ../req/install-quality
+  links: []
+- action-brief: |
+    Call the directives to get the time in the highest precision available to
+    the system.
+  action-code: |
+    Timecounter    *tc;
+    uint32_t        counter;
+    struct bintime  bt;
+    struct timespec ts;
+    struct timeval  tv;
+
+    tc = &high_quality_high_frequency;
+    counter = GetCounter( tc );
+  checks:
+  - brief: |
+      Check that the timecounter was used by
+      ${/rtems/clock/if/get-realtime:/name}.
+    code: |
+      rtems_clock_get_realtime( &ts );
+      T_eq_u32( GetCounter( tc ), counter + 1 );
+    links:
+    - role: validation
+      uid: ../req/get-device
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Check that the timecounter was used by
+      ${/rtems/clock/if/get-realtime-bintime:/name}.
+    code: |
+      rtems_clock_get_realtime_bintime( &bt );
+      T_eq_u32( GetCounter( tc ), counter + 2 );
+    links:
+    - role: validation
+      uid: ../req/get-device
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Check that the timecounter was used by
+      ${/rtems/clock/if/get-realtime-timeval:/name}.
+    code: |
+      rtems_clock_get_realtime_timeval( &tv );
+      T_eq_u32( GetCounter( tc ), counter + 3 );
+    links:
+    - role: validation
+      uid: ../req/get-device
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Check that the timecounter was used by
+      ${/rtems/clock/if/get-monotonic:/name}.
+    code: |
+      rtems_clock_get_monotonic( &ts );
+      T_eq_u32( GetCounter( tc ), counter + 4 );
+    links:
+    - role: validation
+      uid: ../req/get-device
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Check that the timecounter was used by
+      ${/rtems/clock/if/get-monotonic-bintime:/name}.
+    code: |
+      rtems_clock_get_monotonic_bintime( &bt );
+      T_eq_u32( GetCounter( tc ), counter + 5 );
+    links:
+    - role: validation
+      uid: ../req/get-device
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Check that the timecounter was used by
+      ${/rtems/clock/if/get-monotonic-sbintime:/name}.
+    code: |
+      (void) rtems_clock_get_monotonic_sbintime();
+      T_eq_u32( GetCounter( tc ), counter + 6 );
+    links:
+    - role: validation
+      uid: ../req/get-device
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Check that the timecounter was used by
+      ${/rtems/clock/if/get-monotonic-timeval:/name}.
+    code: |
+      rtems_clock_get_monotonic_timeval( &tv );
+      T_eq_u32( GetCounter( tc ), counter + 7 );
+    links:
+    - role: validation
+      uid: ../req/get-device
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  links: []
+- action-brief: |
+    Call the directives to get the time in a coarse precision.
+  action-code: |
+    Timecounter    *tc;
+    uint32_t        counter;
+    struct bintime  bt;
+    struct timespec ts;
+    struct timeval  tv;
+
+    tc = &high_quality_high_frequency;
+    counter = GetCounter( tc );
+  checks:
+  - brief: |
+      Check that the timecounter was not used by
+      ${/rtems/clock/if/get-realtime-coarse:/name}.
+    code: |
+      rtems_clock_get_realtime_coarse( &ts );
+      T_eq_u32( GetCounter( tc ), counter );
+    links:
+    - role: validation
+      uid: ../req/get-coarse-no-device
+    - role: validation
+      uid: /rtems/clock/req/get-realtime-coarse
+  - brief: |
+      Check that the timecounter was not used by
+      ${/rtems/clock/if/get-realtime-coarse-bintime:/name}.
+    code: |
+      rtems_clock_get_realtime_coarse_bintime( &bt );
+      T_eq_u32( GetCounter( tc ), counter );
+    links:
+    - role: validation
+      uid: ../req/get-coarse-no-device
+    - role: validation
+      uid: /rtems/clock/req/get-realtime-coarse
+  - brief: |
+      Check that the timecounter was not used by
+      ${/rtems/clock/if/get-realtime-coarse-timeval:/name}.
+    code: |
+      rtems_clock_get_realtime_coarse_timeval( &tv );
+      T_eq_u32( GetCounter( tc ), counter );
+    links:
+    - role: validation
+      uid: ../req/get-coarse-no-device
+    - role: validation
+      uid: /rtems/clock/req/get-realtime-coarse
+  - brief: |
+      Check that the timecounter was not used by
+      ${/rtems/clock/if/get-monotonic-coarse:/name}.
+    code: |
+      rtems_clock_get_monotonic_coarse( &ts );
+      T_eq_u32( GetCounter( tc ), counter );
+    links:
+    - role: validation
+      uid: ../req/get-coarse-no-device
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic-coarse
+  - brief: |
+      Check that the timecounter was not used by
+      ${/rtems/clock/if/get-monotonic-coarse-bintime:/name}.
+    code: |
+      rtems_clock_get_monotonic_coarse_bintime( &bt );
+      T_eq_u32( GetCounter( tc ), counter );
+    links:
+    - role: validation
+      uid: ../req/get-coarse-no-device
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic-coarse
+  - brief: |
+      Check that the timecounter was not used by
+      ${/rtems/clock/if/get-monotonic-coarse-timeval:/name}.
+    code: |
+      rtems_clock_get_monotonic_coarse_timeval( &tv );
+      T_eq_u32( GetCounter( tc ), counter );
+    links:
+    - role: validation
+      uid: ../req/get-coarse-no-device
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic-coarse
+  - brief: |
+      Check that the timecounter was not used by
+      ${/rtems/clock/if/get-boot-time:/name}.
+    code: |
+      rtems_clock_get_boot_time( &ts );
+      T_eq_u32( GetCounter( tc ), counter );
+    links:
+    - role: validation
+      uid: ../req/get-coarse-no-device
+    - role: validation
+      uid: /rtems/clock/req/get-boot-time
+  - brief: |
+      Check that the timecounter was not used by
+      ${/rtems/clock/if/get-boot-time-bintime:/name}.
+    code: |
+      rtems_clock_get_boot_time_bintime( &bt );
+      T_eq_u32( GetCounter( tc ), counter );
+    links:
+    - role: validation
+      uid: ../req/get-coarse-no-device
+    - role: validation
+      uid: /rtems/clock/req/get-boot-time
+  - brief: |
+      Check that the timecounter was not used by
+      ${/rtems/clock/if/get-boot-time-timeval:/name}.
+    code: |
+      rtems_clock_get_boot_time_timeval( &tv );
+      T_eq_u32( GetCounter( tc ), counter );
+    links:
+    - role: validation
+      uid: ../req/get-coarse-no-device
+    - role: validation
+      uid: /rtems/clock/req/get-boot-time
+  links: []
+- action-brief: |
+    Call the directives to get the time in the highest precision available to
+    the system.
+  action-code: |
+    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;
+  checks:
+  - brief: |
+      Prepare the timecounter to get a large time difference.  Check that
+      ${/rtems/clock/if/get-realtime:/name} returns the correct time.
+    code: |
+      SetCounter( tc, counter );
+      rtems_clock_get_realtime( &ts );
+      T_eq_i64( ts.tv_sec, 567993603 );
+      T_eq_u64( ts.tv_nsec, 114978100 );
+    links:
+    - role: validation
+      uid: ../req/get-large-delta
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Prepare the timecounter to get a large time difference.  Check that
+      ${/rtems/clock/if/get-realtime-bintime:/name} returns the correct time.
+    code: |
+      SetCounter( tc, counter );
+      rtems_clock_get_realtime_bintime( &bt );
+      T_eq_i64( bt.sec, 567993603 );
+      T_eq_u64( bt.frac, 2120971587975905280 );
+    links:
+    - role: validation
+      uid: ../req/get-large-delta
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Prepare the timecounter to get a large time difference.  Check that
+      ${/rtems/clock/if/get-realtime-timeval:/name} returns the correct time.
+    code: |
+      SetCounter( tc, counter );
+      rtems_clock_get_realtime_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 567993603 );
+      T_eq_long( tv.tv_usec, 114978 );
+    links:
+    - role: validation
+      uid: ../req/get-large-delta
+    - role: validation
+      uid: /rtems/clock/req/get-realtime
+  - brief: |
+      Prepare the timecounter to get a large time difference.  Check that
+      ${/rtems/clock/if/get-monotonic:/name} returns the correct time.
+    code: |
+      SetCounter( tc, counter );
+      rtems_clock_get_monotonic( &ts );
+      T_eq_i64( ts.tv_sec, 4 );
+      T_eq_u64( ts.tv_nsec, 114978100 );
+    links:
+    - role: validation
+      uid: ../req/get-large-delta
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Prepare the timecounter to get a large time difference.  Check that
+      ${/rtems/clock/if/get-monotonic-bintime:/name} returns the correct time.
+    code: |
+      SetCounter( tc, counter );
+      rtems_clock_get_monotonic_bintime( &bt );
+      T_eq_i64( bt.sec, 4 );
+      T_eq_u64( bt.frac, 2120971587975905280 );
+    links:
+    - role: validation
+      uid: ../req/get-large-delta
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Prepare the timecounter to get a large time difference.  Check that
+      ${/rtems/clock/if/get-monotonic-sbintime:/name} returns the correct time.
+    code: |
+      SetCounter( tc, counter );
+      sb = rtems_clock_get_monotonic_sbintime();
+      T_eq_i64( sb, 17673696364 );
+    links:
+    - role: validation
+      uid: ../req/get-large-delta
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  - brief: |
+      Prepare the timecounter to get a large time difference.  Check that
+      ${/rtems/clock/if/get-monotonic-timeval:/name} returns the correct time.
+    code: |
+      SetCounter( tc, counter );
+      rtems_clock_get_monotonic_timeval( &tv );
+      T_eq_i64( tv.tv_sec, 4 );
+      T_eq_long( tv.tv_usec, 114978 );
+    links:
+    - role: validation
+      uid: ../req/get-large-delta
+    - role: validation
+      uid: /rtems/clock/req/get-monotonic
+  links: []
+test-brief: |
+  Tests timecounter installation related functions and directives of the Clock
+  Manager.
+test-context: []
+test-context-support: null
+test-description: null
+test-header: null
+test-includes:
+- rtems.h
+- rtems/timecounter.h
+- rtems/score/atomic.h
+test-local-includes:
+- tx-support.h
+test-setup: null
+test-stop: null
+test-support: |
+  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 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
+    );
+  }
+test-target: testsuites/validation/tc-timecounter-install.c
+test-teardown: null
+type: test-case
diff --git a/spec/testsuites/validation-timecounter-0.yml b/spec/testsuites/validation-timecounter-0.yml
new file mode 100644
index 0000000..8fdd326
--- /dev/null
+++ b/spec/testsuites/validation-timecounter-0.yml
@@ -0,0 +1,24 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: /req/test-suites
+test-brief: |
+  This validation test suite is intended test cases related to the installation
+  of timecouters.  The ${/glossary/clock-driver:/term} is disabled.
+test-code: |
+  const char rtems_test_name[] = "${.:/test-suite-name}";
+
+  #define CONFIGURE_MAXIMUM_PROCESSORS 1
+
+  #define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+
+  #include "ts-default.h"
+test-description: null
+test-includes: []
+test-local-includes: []
+test-suite-name: ValidationTimecounter0
+test-target: testsuites/validation/ts-validation-timecounter-0.c
+type: test-suite
diff --git a/spec/testsuites/validation-timecounter-1.yml b/spec/testsuites/validation-timecounter-1.yml
new file mode 100644
index 0000000..8324fea
--- /dev/null
+++ b/spec/testsuites/validation-timecounter-1.yml
@@ -0,0 +1,22 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: /req/test-suites
+test-brief: |
+  This validation test suite is intended test cases related to the use of
+  timecouters.  The ${/glossary/clock-driver:/term} is enabled.
+test-code: |
+  const char rtems_test_name[] = "${.:/test-suite-name}";
+
+  #define CONFIGURE_MAXIMUM_PROCESSORS 4
+
+  #include "ts-default.h"
+test-description: null
+test-includes: []
+test-local-includes: []
+test-suite-name: ValidationTimecounter1
+test-target: testsuites/validation/ts-validation-timecounter-1.c
+type: test-suite
diff --git a/spec/testsuites/validation-timecounter-smp-0.yml b/spec/testsuites/validation-timecounter-smp-0.yml
new file mode 100644
index 0000000..dc420a6
--- /dev/null
+++ b/spec/testsuites/validation-timecounter-smp-0.yml
@@ -0,0 +1,24 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+  uid: /req/test-suites
+test-brief: |
+  This validation test suite is intended test cases related to the use of
+  timecouters.  The ${/glossary/clock-driver:/term} is disabled.
+test-code: |
+  const char rtems_test_name[] = "${.:/test-suite-name}";
+
+  #define CONFIGURE_MAXIMUM_PROCESSORS 4
+
+  #define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+
+  #include "ts-default.h"
+test-description: null
+test-includes: []
+test-local-includes: []
+test-suite-name: ValidationTimecounterSmp0
+test-target: testsuites/validation/ts-validation-timecounter-smp-0.c
+type: test-suite



More information about the vc mailing list