diff --git a/.gitignore b/.gitignore index 630b0b8a..e22ed867 100644 --- a/.gitignore +++ b/.gitignore @@ -40,7 +40,8 @@ user.bazelrc .ruff_cache # docs:incremental and docs:ide_support build artifacts -/_build +_build +ubproject.toml # Vale - editorial style guide .vale.ini diff --git a/BUILD b/BUILD index 65931225..31ef4bbf 100644 --- a/BUILD +++ b/BUILD @@ -21,9 +21,25 @@ setup_starpls( ) docs( - data = [ - "@score_process//:needs_json", + bundles = [ + { + "bundle": "//score/time_slave:docs_bundle", + "mount_at": "components/time_slave", + }, + { + "bundle": "//score/time_daemon:docs_bundle", + "mount_at": "components/time_daemon", + }, + { + "bundle": "//score/time:docs_bundle", + "mount_at": "components/time", + }, ], + external_needs = [ + "@score_process//:needs_json_file", + ], + project = "S-CORE Time", + project_url = "https://eclipse-score.github.io/time", source_dir = "docs", ) diff --git a/MODULE.bazel b/MODULE.bazel index 4a01c4bc..35288c97 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -69,7 +69,7 @@ bazel_dep(name = "score_logging", version = "0.2.1") ### Modules that are used internally within the repository but not exposed as part of the public API -bazel_dep(name = "score_docs_as_code", version = "4.5.0") +bazel_dep(name = "score_docs_as_code", version = "7.0.1") bazel_dep(name = "score_cpp_policies", version = "0.0.1", dev_dependency = True) @@ -81,7 +81,7 @@ git_override( remote = "https://github.com/eclipse-score/score_cpp_policies.git", ) -bazel_dep(name = "score_process", version = "1.6.0", dev_dependency = True) +bazel_dep(name = "score_process", version = "2.0.3", dev_dependency = True) bazel_dep(name = "score_tooling", version = "1.2.0", dev_dependency = True) # cpp support in use_format_targets(languages=[...]) was added after 1.2.0. diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 96859963..67375180 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -539,6 +539,8 @@ "https://bcr.bazel.build/modules/rules_swift/1.18.0/MODULE.bazel": "a6aba73625d0dc64c7b4a1e831549b6e375fbddb9d2dde9d80c9de6ec45b24c9", "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046", "https://bcr.bazel.build/modules/rules_swift/2.1.1/source.json": "40fc69dfaac64deddbb75bd99cdac55f4427d9ca0afbe408576a65428427a186", + "https://bcr.bazel.build/modules/sphinxdocs/2.2.0/MODULE.bazel": "e046c573919d72605d62c352a08d9223a10aafef3a7cb70d0fe253ebdd97019e", + "https://bcr.bazel.build/modules/sphinxdocs/2.2.0/source.json": "b1da19a3d14a1dd8aa6a9ccaedc42bbe0313c8160a77ba5cca336cca1315298d", "https://bcr.bazel.build/modules/stardoc/0.5.0/MODULE.bazel": "f9f1f46ba8d9c3362648eea571c6f9100680efc44913618811b58cc9c02cd678", "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", @@ -1019,7 +1021,8 @@ "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_crates/0.0.9/MODULE.bazel": "8f581e0a658a6dab149f381d783443cb00b559f4e9623956f8ff3de06108c550", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_dash_license_checker/0.1.1/MODULE.bazel": "76681dbd2d45b5c540869a2337174086c56c54953aab1d02cd878b59d31d13a5", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_devcontainer/1.7.0/MODULE.bazel": "f9a5971fbd05f0ed14e7a373dbf58af72a5c58d081537a75c314daaf61c92ae9", - "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_devcontainer/1.7.0/source.json": "a3f55522fd9f63fae7a92f3cb5f91c25ae7474a39e9f9c633f0cf797fc0ca8e5", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_devcontainer/1.9.0/MODULE.bazel": "2a04a354eb7a77d478bb43ba20b1dac0758af858172a760e4290621bef1a2f28", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_devcontainer/1.9.0/source.json": "6f72c780f1fb167be7cbc01801b86534a9e7102003168dcdf2c8886cfb1bb209", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/0.2.4/MODULE.bazel": "ea4801e96c87e2b8650a0fa9e5fed9b8bdbef05c1bc3e30003ba527d5af60a43", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/0.2.6/MODULE.bazel": "1af2963e91c6472555e222f0aba3dc2f5492d04598298209a361978ee3e321e3", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/0.3.3/MODULE.bazel": "95d2b7d44d461c1cf9bd016605f740716fd4ea1303f5f2ed93de3566b90feb1b", @@ -1036,7 +1039,10 @@ "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/4.0.0/MODULE.bazel": "522dc070354e6be2f984468a4243fe4ab8bec690922df5f31f7f0916ee264e20", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/4.0.1/MODULE.bazel": "5955f4cf37228a9cdda7f6009b81db0446f005c618f4bc43665bfa45f2673ebc", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/4.5.0/MODULE.bazel": "4cfe52fe8b8dbeaf7e87500036391da278f72f1c2b41b689ffdd4337196dd8fe", - "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/4.5.0/source.json": "e01b29a3e9640a0d41d880d7da525e451115649d90f097ed66d09808c9135486", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/4.6.0/MODULE.bazel": "d5fbfed7b9bd65f10830e2290045dea639a8cfcaf9f9f0f7a1b12888c14e7d2b", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/6.0.0/MODULE.bazel": "ab2af2d8fab73e4512d2e2bd399a64d10c5c5463388322f7025637b13ec7585c", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/7.0.1/MODULE.bazel": "8ca16bc1143f4834e1ad061ddebb3b57dac966d46f890a07829f055dbb3a3d15", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_docs_as_code/7.0.1/source.json": "bf02ecf6e0bb5532d0654d3411fc7cbd97172f7e0daf979d901e83248a92991e", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_format_checker/0.1.1/MODULE.bazel": "1acc254faa90e9f97b79ac69af25b6c21c561f8d6079914f6352b9b20d26bd37", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_lifecycle_health/0.3.0/MODULE.bazel": "97c3ab10cafe3f519293fb1fab2de3c3970f9d70e55255c72f4dfe87ec55a240", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_lifecycle_health/0.3.0/source.json": "138d840f0ec2c7a915f935803426920b0f344f7e0038db885fe4ebd32829a514", @@ -1057,7 +1063,9 @@ "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_process/1.5.2/MODULE.bazel": "be52d29278d6671221f28921e8f1acfce29c3bfc3e6b4f503f0625ab2c61586f", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_process/1.5.3/MODULE.bazel": "65024b7f23ce5f72bd6ffd455a67c042ecf56d267f0bf63a90330a3241781b7a", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_process/1.6.0/MODULE.bazel": "2496bc24311f69f49449ee85d8bb38e3b970cbfcf10d0a7f19b2d5262ce80e8d", - "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_process/1.6.0/source.json": "093424aa8bfed8705a3d142b21fe1d053258f2dd5eb1944941f6439b2c7157e9", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_process/2.0.1/MODULE.bazel": "88bff0ed46da79d87f8c441a6bf6b760ee7c194b282e7e54a8b7db6ea2354db9", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_process/2.0.3/MODULE.bazel": "d9359f1cb7e460a5eb6b7e5d2185bcc6ed7c9f4a31f560d6a703549ca6366ed7", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_process/2.0.3/source.json": "0ea635f75ded5225494b709a441488f80be0db0ded4a9786367477ecdbcf42b0", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_python_basics/0.3.0/MODULE.bazel": "785ddd5295213e36c31ab86bdc34f29c0f7d1b72e9abd931bb08f42c0e48e2e9", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_python_basics/0.3.1/MODULE.bazel": "99c491109937542e61df090222666a8613ef946fa7bb2b2d5ba648b2baba03ad", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_python_basics/0.3.2/MODULE.bazel": "f25490f64035a0e3a0d53ad9cb6164e8325ce6cf2a7ee68c6ae153840cb2497e", @@ -1067,6 +1075,7 @@ "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_rust_policies/0.0.5/MODULE.bazel": "7de02547bdf121d3dedf5141b97f0fd9a545bd255ff5c7b699056b35816ffad9", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_rust_policies/0.0.5/source.json": "22c8bf0a5cbf7c7b06f774f3f66498e0bc14346a8b2208f7427a8fbb78a42547", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_starpls_lsp/0.1.0/MODULE.bazel": "b2f8c4c8d8e851706255ff9002b448bff6e040b8f0c6adedbde2a09375aa16cc", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/sphinxdocs/2.2.0/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/stardoc/0.5.0/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/stardoc/0.5.1/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/stardoc/0.5.3/MODULE.bazel": "not found", diff --git a/docs/components/index.rst b/docs/components/index.rst new file mode 100644 index 00000000..c8b334fe --- /dev/null +++ b/docs/components/index.rst @@ -0,0 +1,23 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _ components:: + +Components +~~~~~~~~~~ + +.. toctree will be filled by docs_bundle via bazel + +.. toctree:: + :maxdepth: 1 diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index a834ad1f..00000000 --- a/docs/conf.py +++ /dev/null @@ -1,57 +0,0 @@ -# ******************************************************************************* -# Copyright (c) 2026 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0 -# -# SPDX-License-Identifier: Apache-2.0 -# ******************************************************************************* - -# Configuration file for the Sphinx documentation builder. -# -# For the full list of built-in configuration values, see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - - -# -- Project information ----------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information - -project = "S-CORE Time" -project_url = "https://eclipse-score.github.io/time" -project_prefix = "TIME_" -author = "S-CORE" -version = "0.1" - -# -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration - - -extensions = [ - "sphinx_design", - "sphinx_needs", - "sphinxcontrib.plantuml", - "score_plantuml", - "score_metamodel", - "score_draw_uml_funcs", - "score_source_code_linker", - "score_layout", - "score_metrics", -] - -exclude_patterns = [ - # The following entries are not required when building the documentation via 'bazel - # build //docs:docs', as that command runs in a sandboxed environment. However, when - # building the documentation via 'bazel run //docs:incremental' or esbonio, these - # entries are required to prevent the build from failing. - "bazel-*", - ".venv_docs", -] - -templates_path = ["templates"] - -# Enable numref -numfig = True diff --git a/docs/index.rst b/docs/index.rst index e35c841d..4240ef21 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -43,6 +43,13 @@ For a detailed concept and architectural design, please refer to the :doc:`time_ :caption: Contents: features/index + module/index + +.. toctree:: + :maxdepth: 1 + :caption: Component Documentation: + + components/index Project Layout -------------- diff --git a/docs/module/index.rst b/docs/module/index.rst new file mode 100644 index 00000000..595cf092 --- /dev/null +++ b/docs/module/index.rst @@ -0,0 +1,48 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Module +====== + + + +.. code-block:: rst + + .. mod:: Time + :id: mod__time + :includes: comp__component_name_template + +Module View +----------- + +.. code-block:: rst + + .. mod_view_sta:: Time Module Static View + :id: mod_view_sta__time__time + :includes: comp__component_name_template + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_module(need(), needs) }} + +Module Documents +---------------- + +.. toctree:: + :maxdepth: 1 + + manuals/index diff --git a/docs/module/manuals/api_description/api_usage.rst b/docs/module/manuals/api_description/api_usage.rst new file mode 100644 index 00000000..1d9421d5 --- /dev/null +++ b/docs/module/manuals/api_description/api_usage.rst @@ -0,0 +1,186 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _manual_time_api_usage: + +API Usage: Accessing Vehicle Time +================================= + +The primary interface for applications to access synchronized time is the ``score::time`` client library. It provides a simple, robust, and testable way to get the current time without dealing with the underlying complexities of PTP and IPC. + +This section describes the most common use case: polling the current Vehicle Time. + +For more detail, see the :ref:`time library user manual`. + +Polling the Current Time +------------------------ + +This method involves actively requesting the current time from the ``score::time`` framework. It is the simplest way to get a timepoint when needed. + +.. code-block:: cpp + + #include "score/time/clock.h" + #include "score/time/vehicle_time.h" + #include + #include + + /** + * @brief Demonstrates how to poll the current Vehicle Time and check its status. + */ + void poll_vehicle_time() + { + // 1. Get a handle to the VehicleClock singleton instance. + auto& clock = score::time::Clock::GetInstance(); + + // 2. Request the current time snapshot. + // This call retrieves the latest time information from the TimeDaemon via IPC. + const auto snapshot = clock.Now(); + + // 3. Check the status of the snapshot. + // IsConsistent(): status flags are not contradictory. + // HasBeenSynchronized(): clock has synchronized at least once in this lifecycle. + // IsReliable(): synchronized now and no active timeout/leap fault. + const auto status = snapshot.Status(); + if (status.IsConsistent() && status.HasBeenSynchronized() && status.IsReliable()) + { + // 4. Use the timepoint. + // The timepoint is a std::chrono::time_point. + const auto current_time = snapshot.TimePoint(); + const auto ns_since_epoch = std::chrono::duration_cast( + current_time.time_since_epoch()).count(); + + std::cout << "Successfully retrieved reliable Vehicle Time: " + << ns_since_epoch << " ns since epoch." << std::endl; + } + else + { + // 5. Handle invalid or currently unusable status. + // Applications must not use TimePoint() if status is inconsistent, + // never synchronized, or currently unreliable. + std::cerr << "Warning: Vehicle Time status is not usable yet. " + << "Retrying later..." << std::endl; + } + } + +.. attention:: + + Never use ``TimePoint`` from ``ClockSnapshot`` before verifying status. + For robust handling, check ``Status().IsConsistent()``, ``Status().HasBeenSynchronized()``, and ``Status().IsReliable()``. + +Advanced API Usage: Subscribing to PTP Protocol Events +====================================================== + +For advanced use cases, such as diagnostics, network monitoring, or detailed performance analysis, the ``score::time`` framework allows applications to subscribe directly to low-level PTP protocol data events. Instead of polling for the final, processed time, an application can register a callback function that is invoked asynchronously whenever new data arrives from the ``TimeSlave``. + +.. warning:: + + This is an advanced feature. Most applications should use the simpler polling mechanism described in the previous chapter, as it provides the fully quality-assured time. Subscribing to raw PTP data bypasses some of the quality checks performed by the ``TimeDaemon``. + +Available Data Subscriptions +---------------------------- + +Two types of data events can be subscribed to: + +1. **`TimeSlaveSyncData`**: + This event is triggered whenever the ``TimeSlave`` successfully processes a PTP Sync/Follow-Up message pair from the Time Master. The data contains raw offset and rate correction information, as well as the underlying hardware and software timestamps. + +2. **`PDelayMeasurementData`**: + This event is triggered after the ``TimeSlave`` completes a peer-delay measurement cycle (PDelay_Req/Resp/FUp exchange). The data contains the calculated path delay to the communication partner. + +Subscribing to Events +--------------------- + +The following code example demonstrates how to register, handle, and unregister callbacks for these events. + +.. code-block:: cpp + + #include "score/time/clock.h" + #include "score/time/vehicle_time.h" + #include + #include + #include + + // A thread-safe data handler for our application + class PtpDataLogger + { + public: + void HandleSyncData(const score::time::TimeSlaveSyncData& data) + { + std::lock_guard lock(mutex_); + std::cout << "PTP Sync Event: Offset = " << data.offset_ns + << " ns, Rate Ratio = " << data.rate_ratio << std::endl; + // Further processing of the data... + } + + void HandlePDelayData(const score::time::PDelayMeasurementData& data) + { + std::lock_guard lock(mutex_); + std::cout << "PTP PDelay Event: Path Delay = " << data.path_delay_ns << " ns" << std::endl; + // Further processing of the data... + } + + private: + std::mutex mutex_; + }; + + /** + * @brief Demonstrates how to subscribe to and unsubscribe from PTP protocol events. + */ + void subscribe_to_ptp_events() + { + auto& clock = score::time::Clock::GetInstance(); + PtpDataLogger logger; + + // 1. Subscribe to Sync data events using a lambda that calls our thread-safe handler. + // The returned handle is used later to unsubscribe. + auto sync_subscription = clock.Subscribe>( + [&logger](const auto& data) { logger.HandleSyncData(data); }); + + std::cout << "Subscribed to TimeSlaveSyncData events." << std::endl; + + + // 2. Subscribe to Peer-Delay data events. + auto pdelay_subscription = clock.Subscribe>( + [&logger](const auto& data) { logger.HandlePDelayData(data); }); + + std::cout << "Subscribed to PDelayMeasurementData events." << std::endl; + + // ... application runs and receives callbacks asynchronously ... + std::this_thread::sleep_for(std::chrono::seconds(10)); + + + // 3. Unsubscribe when the data is no longer needed. + // The subscription handle is moved into the Unsubscribe call. + clock.Unsubscribe(std::move(sync_subscription)); + std::cout << "Unsubscribed from TimeSlaveSyncData events." << std::endl; + + clock.Unsubscribe(std::move(pdelay_subscription)); + std::cout << "Unsubscribed from PDelayMeasurementData events." << std::endl; + } + + +Threading and Safety Considerations +----------------------------------- + +.. attention:: + + Callback functions are executed on a **backend thread** owned by the ``score::time`` framework, not on the application's main thread. Therefore, all callback handlers **must be thread-safe**. + +* **Data Protection**: Use mutexes, atomics, or other synchronization primitives to protect any shared data that is accessed or modified within the callback. +* **Keep it Short**: Callbacks should be lightweight and non-blocking. Offload any time-consuming processing to a separate application-owned thread to avoid delaying the ``score::time`` backend. + +Unsubscribing +------------- + +It is crucial to unsubscribe from events when they are no longer needed to prevent resource leaks and dangling callbacks. The ``Subscribe`` method returns a handle object which must be passed to the ``Unsubscribe`` method. The handle is invalidated upon unsubscription. diff --git a/docs/manuals/.gitkeep b/docs/module/manuals/config/.gitkeep similarity index 100% rename from docs/manuals/.gitkeep rename to docs/module/manuals/config/.gitkeep diff --git a/docs/module/manuals/examples/basic_clocks.rst b/docs/module/manuals/examples/basic_clocks.rst new file mode 100644 index 00000000..47d900e0 --- /dev/null +++ b/docs/module/manuals/examples/basic_clocks.rst @@ -0,0 +1,280 @@ +.. ******************************************************************************* + Copyright (c) 2026 Contributors to the Eclipse Foundation + + See the NOTICE file(s) distributed with this work for additional + information regarding copyright ownership. + + This program and the accompanying materials are made available under the + terms of the Apache License Version 2.0 which is available at + https://www.apache.org/licenses/LICENSE-2.0 + + SPDX-License-Identifier: Apache-2.0 + ******************************************************************************* + +Basic Clock Examples +==================== + +Overview +-------- + +Three examples demonstrate the basic SCORE clock types: ``system_time``, ``steady_time``, +and ``high_res_steady_time``. All follow an identical pattern - a periodic time printer +that outputs time values once per second until interrupted. + +These examples show the fundamental pattern for using SCORE time APIs and can serve as +starting points for applications requiring simple time reading. + +Common Implementation Pattern +----------------------------- + +All three examples share the same structure: + +**Handler Class** + Wrapper around ``Clock::GetInstance()`` that provides a clean ``GetCurrentTime()`` + method returning a ``TimeReport`` struct. + +**Main Program** + - Signal handling for graceful shutdown (SIGINT/SIGTERM) + - Loop reading time every second + - Simple text output with sequence numbers + - Consistent error handling + +**Unit Tests** + Demonstrate mocking with ``ScopedClockOverride`` for dependency injection. + +Building and Running +-------------------- + +.. code-block:: bash + + # Build any of the basic examples + bazel build //examples/time/system_time + bazel build //examples/time/steady_time + bazel build //examples/time/high_res_steady_time + + # Run examples + bazel run //examples/time/system_time + bazel run //examples/time/steady_time + bazel run //examples/time/high_res_steady_time + + # Run tests + bazel test //examples/time/system_time/src:system_time_handler_test + bazel test //examples/time/steady_time/src:steady_time_handler_test + bazel test //examples/time/high_res_steady_time/src:high_res_steady_time_handler_test + +Example Output +-------------- + +Each example prints time in a similar format: + +**System Time:** + +.. code-block:: text + + SystemTime printer started. Press Ctrl+C to stop. + [0] unix=1720184400.123456789 s + [1] unix=1720184401.234567890 s + [2] unix=1720184402.345678901 s + ... + +**Steady Time:** + +.. code-block:: text + + SteadyTime printer started. Press Ctrl+C to stop. + [0] monotonic=12345.123456789 s + [1] monotonic=12346.234567890 s + [2] monotonic=12347.345678901 s + ... + +**High-Resolution Steady Time:** + +.. code-block:: text + + HighResSteadyTime printer started. Press Ctrl+C to stop. + [0] time=12345.123456789 s + [1] time=12346.234567890 s + [2] time=12347.345678901 s + ... + +Code Structure +-------------- + +Each example follows this pattern: + +**Handler Header** (``*_time_handler.h``): + +.. code-block:: cpp + + struct TimeReport { + std::int64_t time_field_ns{0}; // Field name varies by clock type + }; + + class TimeHandler { + public: + TimeReport GetCurrentTime() const noexcept { + const auto snapshot = ClockType::GetInstance().Now(); + return TimeReport{snapshot.TimePointNs().count()}; + } + }; + +**Main Program** (``main.cpp``): + +.. code-block:: cpp + + volatile std::sig_atomic_t gShutdownRequested{0}; + extern "C" void HandleSignal(int) noexcept { gShutdownRequested = 1; } + + int main() { + signal(SIGINT, HandleSignal); + signal(SIGTERM, HandleSignal); + + HandlerType handler; + std::uint64_t seq{0}; + + while (gShutdownRequested == 0) { + const auto report = handler.GetCurrentTime(); + PrintReport(report, seq++); + std::this_thread::sleep_for(std::chrono::seconds{1}); + } + return 0; + } + +Testing Pattern +--------------- + +All examples use the same mocking approach: + +.. code-block:: cpp + + TEST(HandlerTest, GetCurrentTime) { + auto mock = std::make_shared(); + score::time::test_utils::ScopedClockOverride guard{mock}; + + EXPECT_CALL(*mock, Now()).WillOnce(Return(test_snapshot)); + + HandlerType handler; + const auto report = handler.GetCurrentTime(); + + EXPECT_EQ(expected_value, report.time_field_ns); + } + +.. note:: + + Tests using ``ScopedClockOverride`` must declare ``tags = ["exclusive", "unit"]`` + in their Bazel BUILD file to prevent parallel execution conflicts. + +Bazel Build Setup +----------------- + +Understanding the dependency structure helps when adapting these examples for your application. + +Target Structure +~~~~~~~~~~~~~~~~ + +Each example has three Bazel targets in ``examples/time//src/BUILD``: + +.. code-block:: python + + cc_library( + name = "time_handler", + hdrs = ["system_time_handler.h"], + deps = ["//score/time/system_time:interface"], # Header-only dep + ) + + cc_binary( + name = "system_time", + srcs = ["main.cpp"], + deps = [ + ":time_handler", + "//score/time/system_time", # Production backend + ], + ) + + cc_test( + name = "system_time_handler_test", + srcs = ["system_time_handler_test.cpp"], + tags = ["exclusive", "unit"], # Required for ScopedClockOverride + deps = [ + ":time_handler", + "//score/time/system_time:system_time_mock", # Mock backend + "@googletest//:gtest", + "@googletest//:gtest_main", + ], + ) + +Dependency Layers +~~~~~~~~~~~~~~~~~ + +**Handler Library** (``time_handler``): + - Header-only wrapper around SCORE clock API + - Depends on ``:interface`` target (types only, no implementation) + - Can be tested without linking production backend + +**Binary** (``system_time``, ``steady_time``, ``high_res_steady_time``): + - Links production backend (``//score/time/``) + - Depends on handler library + - Minimal dependencies for deployment + +**Test** (``*_handler_test``): + - Links mock backend (``//score/time/:*_mock``) + - Uses ``ScopedClockOverride`` for dependency injection + - **Must** have ``tags = ["exclusive", "unit"]`` to prevent parallel test conflicts + +Key Dependency Targets +~~~~~~~~~~~~~~~~~~~~~~ + +For each clock type (``system_time``, ``steady_time``, ``high_res_steady_time``): + +.. list-table:: + :header-rows: 1 + :widths: 50 50 + + * - Target + - Purpose + * - ``//score/time/:interface`` + - Header-only, types and tag definitions + * - ``//score/time/`` + - Production backend implementation + * - ``//score/time/:_mock`` + - GMock test double for unit testing + +Adapting for Your Application +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To use these patterns in your code: + +1. **Production code** depends on ``:interface`` for headers, production target for binary: + + .. code-block:: python + + cc_library( + name = "my_component", + hdrs = ["my_component.h"], + deps = ["//score/time/steady_time:interface"], + ) + + cc_binary( + name = "my_app", + deps = [ + ":my_component", + "//score/time/steady_time", # Link production backend + ], + ) + +2. **Tests** depend on ``:interface`` and ``*_mock``: + + .. code-block:: python + + cc_test( + name = "my_component_test", + tags = ["exclusive", "unit"], # Required! + deps = [ + ":my_component", + "//score/time/steady_time:steady_time_mock", + "@googletest//:gtest_main", + ], + ) + +This layering keeps compile times fast (interface-only deps) and enables testing without +runtime dependencies. diff --git a/docs/module/manuals/examples/index.rst b/docs/module/manuals/examples/index.rst new file mode 100644 index 00000000..2c05373b --- /dev/null +++ b/docs/module/manuals/examples/index.rst @@ -0,0 +1,64 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Examples User Manual +==================== + +This manual explains the examples included in the ``examples/time/`` subdirectory and how they +can be used as patterns for building applications with the SCORE time library. + +Overview +-------- + +The ``examples/time/`` directory contains four working examples that demonstrate how to use +different SCORE time sources: + +- **Basic Clock Examples** (system_time, steady_time, high_res_steady_time): Simple periodic time printers showing the common pattern for reading time from SCORE clocks +- **Vehicle Time Example** (vehicle_time): More complex example showing PTP-synchronized time with initialization, status monitoring, and dual time sources + +All examples follow consistent patterns and can be used as starting points for real applications. + +Building and Running Examples +------------------------------ + +All examples use Bazel: + +.. code-block:: bash + + # Build all examples + bazel build //examples/... + + # Run specific example + bazel run //examples/time/system_time + + # Run tests + bazel test //examples/time/system_time/src:system_time_handler_test + +Common Patterns +--------------- + +All examples share these implementation patterns: + +- **Handler wrapper classes** providing clean APIs over SCORE Clock types +- **TimeReport structs** containing time data with consistent field naming +- **Signal handling** for graceful shutdown on SIGINT/SIGTERM +- **Unit test patterns** using ScopedClockOverride for dependency injection +- **Nanosecond precision** throughout all time calculations + +.. toctree:: + :maxdepth: 2 + :caption: Examples: + + basic_clocks + vehicle_time diff --git a/docs/module/manuals/examples/vehicle_time.rst b/docs/module/manuals/examples/vehicle_time.rst new file mode 100644 index 00000000..ec2b1d71 --- /dev/null +++ b/docs/module/manuals/examples/vehicle_time.rst @@ -0,0 +1,289 @@ +.. ******************************************************************************* + Copyright (c) 2026 Contributors to the Eclipse Foundation + + See the NOTICE file(s) distributed with this work for additional + information regarding copyright ownership. + + This program and the accompanying materials are made available under the + terms of the Apache License Version 2.0 which is available at + https://www.apache.org/licenses/LICENSE-2.0 + + SPDX-License-Identifier: Apache-2.0 + ******************************************************************************* + +Vehicle Time Example +==================== + +Overview +-------- + +The ``vehicle_time`` example demonstrates how to use the SCORE library's VehicleClock +in combination with HighResSteadyClock. This example shows how to work with +PTP-synchronized vehicle time alongside local monotonic time, which is essential +for automotive applications requiring distributed time synchronization. + +What it does +------------ + +This example creates a ``VehicleTimeHandler`` wrapper class that: + +- Provides access to both SCORE ``VehicleClock`` and ``HighResSteadyClock`` +- Returns combined time reports with status information +- Demonstrates initialization patterns for vehicle time backends +- Shows how to monitor time synchronization quality +- Can be unit tested with independent clock mocks + +The main program: + +- Initializes the vehicle time backend +- Runs a loop reading both time sources simultaneously +- Displays time values, reliability, and synchronization status +- Handles SIGINT/SIGTERM for clean shutdown + +Building and Running +-------------------- + +To build and run the example: + +.. code-block:: bash + + # Build the example + bazel build //examples/time/vehicle_time + + # Run the example + bazel run //examples/time/vehicle_time + + # Or run the built binary directly + ./bazel-bin/examples/time/vehicle_time/src/vehicle_time + +**Note**: The vehicle time backend requires proper initialization. The example will +exit with error code 1 if initialization fails (e.g., no PTP service available). + +Output Format +------------- + +The program outputs lines in this format: + +.. code-block:: text + + VehicleTime + HighResSteadyTime printer started. Press Ctrl+C to stop. + [0] vehicle=1720184400.123456789 s hirs=12345.234567890 s is_reliable=yes is_consistent=yes rate_deviation=1.23e-09 + [1] vehicle=1720184401.234567890 s hirs=12346.345678901 s is_reliable=yes is_consistent=yes rate_deviation=1.24e-09 + ... + Shutdown requested. Exiting. + +Where: +- ``vehicle=`` shows the PTP-synchronized time in seconds.nanoseconds +- ``hirs=`` shows the local high-resolution steady time +- ``is_reliable=`` indicates if the vehicle time is synchronized and fault-free +- ``is_consistent=`` indicates if status flags are internally consistent +- ``rate_deviation=`` shows local clock deviation relative to PTP Grand Master + +Code Structure +-------------- + +VehicleTimeHandler Class +~~~~~~~~~~~~~~~~~~~~~~~~ + +Located in ``examples/time/vehicle_time/src/vehicle_time_handler.h``: + +.. code-block:: cpp + + class VehicleTimeHandler { + public: + bool Init() noexcept; + TimeReport GetCurrentTime() const noexcept; + void RegisterStatusCallback(VehicleTime::StatusChangedCallback callback) noexcept; + }; + + struct TimeReport { + std::int64_t vehicle_time_ns{0}; // PTP-synchronized time + std::int64_t high_res_steady_time_ns{0}; // Local monotonic time + bool is_reliable{false}; // Time sync quality + bool is_consistent{false}; // Status flag consistency + double rate_deviation{0.0}; // Clock drift rate + }; + +Key features: +- **Dual time sources**: Both vehicle and local time in single call +- **Status monitoring**: Reliability and consistency flags +- **Rate tracking**: Clock deviation measurement +- **Callback support**: Status change notifications (future feature) + +Main Program +~~~~~~~~~~~~ + +Located in ``examples/time/vehicle_time/src/main.cpp``: + +Key features: +- Initialization error handling with early exit +- Combined time display showing both sources +- Status information formatting for monitoring +- Same signal handling pattern as other examples + +Testing +------- + +Run the unit tests: + +.. code-block:: bash + + bazel test //examples/time/vehicle_time/src:vehicle_time_handler_test + +The test shows how to mock both time sources independently: + +.. code-block:: cpp + + auto vehicle_mock = std::make_shared(); + auto hirs_mock = std::make_shared(); + + score::time::test_utils::ScopedClockOverride vg{vehicle_mock}; + score::time::test_utils::ScopedClockOverride hg{hirs_mock}; + + EXPECT_CALL(*vehicle_mock, Init()).WillOnce(Return(true)); + EXPECT_CALL(*vehicle_mock, Now()).WillOnce(Return(...)); + EXPECT_CALL(*hirs_mock, Now()).WillOnce(Return(...)); + +Bazel Build Setup +----------------- + +The vehicle_time example has more complex dependencies due to dual time sources and initialization. + +Target Structure +~~~~~~~~~~~~~~~~ + +From ``examples/time/vehicle_time/src/BUILD``: + +.. code-block:: python + + cc_library( + name = "time_handler", + hdrs = ["vehicle_time_handler.h"], + deps = [ + "//score/time/vehicle_time:interface", + "//score/time/high_res_steady_time:interface", + ], + ) + + cc_binary( + name = "vehicle_time", + srcs = ["main.cpp"], + deps = [ + ":time_handler", + "//score/time/vehicle_time", # VehicleTime production backend + "//score/time/high_res_steady_time", # HIRS production backend + "@score_baselibs//score/mw/log:console_only_backend", + ], + ) + + cc_test( + name = "vehicle_time_handler_test", + srcs = ["vehicle_time_handler_test.cpp"], + tags = ["exclusive", "unit"], # Required for ScopedClockOverride + deps = [ + ":time_handler", + "//score/time/vehicle_time:vehicle_time_mock", + "//score/time/high_res_steady_time:high_res_steady_time_mock", + "@googletest//:gtest_main", + ], + ) + +Dual Clock Dependencies +~~~~~~~~~~~~~~~~~~~~~~~ + +The handler depends on **two** clock interfaces: + +- ``//score/time/vehicle_time:interface`` - VehicleTime tag and status types +- ``//score/time/high_res_steady_time:interface`` - HighResSteadyTime tag + +The binary links **both** production backends, while tests link **both** mocks. + +Key Targets +~~~~~~~~~~~ + +.. list-table:: + :header-rows: 1 + :widths: 50 50 + + * - Target + - Purpose + * - ``//score/time/vehicle_time:interface`` + - VehicleTime types, status flags, callback signatures + * - ``//score/time/vehicle_time`` + - Production backend with TimeDaemon IPC + * - ``//score/time/vehicle_time:vehicle_time_mock`` + - Mock for Init/Now/Subscribe testing + * - ``//score/time/high_res_steady_time:interface`` + - HighResSteadyTime tag + * - ``//score/time/high_res_steady_time`` + - Production HIRS clock backend + * - ``//score/time/high_res_steady_time:high_res_steady_time_mock`` + - Mock for HIRS in tests + +Testing with Dual Mocks +~~~~~~~~~~~~~~~~~~~~~~~ + +The test demonstrates independent mock control: + +.. code-block:: cpp + + auto vehicle_mock = std::make_shared(); + auto hirs_mock = std::make_shared(); + + ScopedClockOverride vg{vehicle_mock}; + ScopedClockOverride hg{hirs_mock}; + + EXPECT_CALL(*vehicle_mock, Init()).WillOnce(Return(true)); + EXPECT_CALL(*vehicle_mock, Now()).WillOnce(Return(vehicle_snapshot)); + EXPECT_CALL(*hirs_mock, Now()).WillOnce(Return(hirs_snapshot)); + +Each clock can be mocked separately with different return values and expectations. + +Adapting for Your Application +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When building components that use VehicleTime: + +1. **Header-only dependencies** use ``:interface``: + + .. code-block:: python + + cc_library( + name = "my_sync_component", + hdrs = ["my_sync_component.h"], + deps = [ + "//score/time/vehicle_time:interface", + "//score/time/high_res_steady_time:interface", + ], + ) + +2. **Binaries** link production backends: + + .. code-block:: python + + cc_binary( + name = "my_app", + deps = [ + ":my_sync_component", + "//score/time/vehicle_time", + "//score/time/high_res_steady_time", + ], + ) + +3. **Tests** link mocks and require exclusive tag: + + .. code-block:: python + + cc_test( + name = "my_sync_component_test", + tags = ["exclusive", "unit"], + deps = [ + ":my_sync_component", + "//score/time/vehicle_time:vehicle_time_mock", + "//score/time/high_res_steady_time:high_res_steady_time_mock", + "@googletest//:gtest_main", + ], + ) + +The layered dependency structure keeps compile times minimal while enabling comprehensive +testing with independent clock control. diff --git a/docs/module/manuals/index.rst b/docs/module/manuals/index.rst new file mode 100644 index 00000000..3c905d73 --- /dev/null +++ b/docs/module/manuals/index.rst @@ -0,0 +1,23 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Manuals +####### + +.. toctree:: + :titlesonly: + + user_manual + safety_manual + security_manual diff --git a/docs/release/.gitkeep b/docs/module/manuals/performance/.gitkeep similarity index 100% rename from docs/release/.gitkeep rename to docs/module/manuals/performance/.gitkeep diff --git a/docs/module/manuals/safety_manual.rst b/docs/module/manuals/safety_manual.rst new file mode 100644 index 00000000..f3d189a2 --- /dev/null +++ b/docs/module/manuals/safety_manual.rst @@ -0,0 +1,110 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Safety Manual +============= + +.. note:: Document header + +.. document:: Time Module Safety Manual + :id: doc__time_safety_manual + :status: draft + :version: 1 + :safety: ASIL_B + :security: NO + :realizes: wp__module_safety_manual + +.. attention:: + TBC — pending clarification of feature requirements (tracked in issue #33, #155). Content + below follows the module_template skeleton and is not yet reviewed + for the ``time`` module. + + The above directive must be updated according to your Module. + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Introduction/Scope +------------------ +| + +Assumed Platform Safety Requirements +------------------------------------ +| For the the following safety related stakeholder requirements are assumed to define the top level functionality (purpose) of the . I.e. from these all the feature and component requirements implemented are derived. +| + +Assumptions of Use +------------------ + +Assumptions on the Environment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +| Generally the assumption of the project platform SEooC is that it is integrated in a safe system, i.e. the POSIX OS it runs on is qualified and also the HW related failures are taken into account by the system integrator, if not otherwise stated in the module's safety concept. +| + +List of AoUs expected from the environment the platform / module runs on: + +.. needtable:: + :style: table + :columns: title;id;status + :colwidths: 25,25,25 + :sort: title + + results = [] + + for need in needs.filter_types(["aou_req"]): + if need and "environment" in need["tags"]: + results.append(need) + +.. attention:: + Make sure these AoU are here for a safety reason, i.e. every one "mitigates" a safety analysis entry. + +Assumptions on the User +^^^^^^^^^^^^^^^^^^^^^^^ +| As there is no assumption on which specific OS and HW is used, the integration testing of the stakeholder and feature requirements is expected to be performed by the user of the platform SEooC. Tests covering all stakeholder and feature requirements performed on a reference platform (tbd link to reference platform specification), reviewed and passed are included in the platform SEooC safety package. +| Additionally the components of the platform may have additional specific assumptions how they are used. These are part of every module documentation: . Assumptions from components to their users can be fulfilled in two ways: +| 1. There are assumption which need to be fulfilled by all SW components, e.g. "every user of an IPC mechanism needs to make sure that he provides correct data (including appropriate ASIL level)" - in this case the AoU is marked as "platform". +| 2. There are assumption which can be fulfilled by a safety mechanism realized by some other project platform component and are therefore not relevant for an user who uses the whole platform. But those are relevant if you chose to use the module SEooC stand-alone - in this case the AoU is marked as "module". An example would be the "JSON read" which requires "The user shall provide a string as input which is not corrupted due to HW or QM SW errors." - which is covered when using together with safe project platform persistency feature. + +List of AoUs on the user of the platform or the module of this safety manual: + +Note: Platform safety manual collects all platform wide AoU (have to be fulfilled by the user for any feature). +Module safety manual collects all AoUs specific to a feature and its realizing components. +This means for every feature the user selects, the platform safety manual and the related module manual has to be considered. + +.. needtable:: + :style: table + :columns: title;id;status + :colwidths: 25,25,25 + :sort: title + + results = [] + + for need in needs.filter_types(["aou_req"]): + if need and "environment" not in need["tags"]: + results.append(need) + +.. attention:: + Make sure these AoU are here for a safety reason, i.e. every one "mitigates" a safety analysis entry. + +Safety concept of the SEooC +--------------------------- +| + +Safety Anomalies +---------------- +| Anomalies (bugs in ASIL SW, detected by testing or by users, which could not be fixed) known before release are documented in the platform/module release notes . + +References +---------- +| +| diff --git a/docs/module/manuals/security_manual.rst b/docs/module/manuals/security_manual.rst new file mode 100644 index 00000000..5840dd7b --- /dev/null +++ b/docs/module/manuals/security_manual.rst @@ -0,0 +1,100 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Security Manual +=============== + +.. note:: Document header + +.. document:: Time Module Security Manual + :id: doc__time_security_manual + :status: draft + :version: 1 + :safety: ASIL_B + :security: YES + :realizes: wp__module_security_manual + +.. attention:: + TBC — placeholder skeleton, not yet reviewed for the ``time`` module. + The above directive must be updated according to your Module. + + - Adjust ``status`` to be ``valid`` + - Adjust ``security`` and ``tags`` according to your needs + +Introduction/Scope +------------------ +| + +Assumed Platform Security Requirements +-------------------------------------- +| For the the following security related stakeholder requirements are assumed to define the top level functionality (purpose) of the . I.e. from these all the feature and component requirements implemented are derived. +| + +Assumptions of Use +------------------ + +Assumptions on the Environment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +| The platform and its components are developed as Out of Context (OoC) with assumptions on the environment. + It is assumed that the platform/components are integrated in a secure system, i.e. qualified POSIX OS. + Also the HW related failures are taken into account by the system integrator, if not otherwise stated in the module's security concept. +| + +List of AoUs expected from the environment the platform / module runs on: + +.. needtable:: + :style: table + :columns: title;id;status + :colwidths: 25,25,25 + :sort: title + + results = [] + + for need in needs.filter_types(["aou_req"]): + if need and "environment" in need["tags"]: + results.append(need) + +Assumptions on the User +^^^^^^^^^^^^^^^^^^^^^^^ +| As there is no assumption on which specific OS and HW is used, the integration testing of the stakeholder and feature requirements is expected to be performed by the user of the platform OoC. Tests covering all stakeholder and feature requirements performed on a reference platform (tbd link to reference platform specification), reviewed and passed are included in the platform OoC security package. +| Additionally the components of the platform may have additional specific assumptions how they are used. These are part of every module documentation: . Assumptions from components to their users can be fulfilled in two ways: +| 1. There are assumption which need to be fulfilled by all SW components, e.g. "every user of an IPC mechanism needs to make sure that he provides correct data (e.g. including appropriate security (access) control)" - in this case the AoU is marked as "platform". +| 2. There are assumption which can be fulfilled by a security control realized by some other Project platform component and are therefore not relevant for an user who uses the whole platform. But those are relevant if you chose to use the module OcC stand-alone - in this case the AoU is marked as "module". An example would be the "JSON read" which requires "The user shall provide a string as input which is not corrupted due to HW or QM SW errors." - which is covered when using together with safe platform persistency feature. + +List of AoUs on the user of the platform features or the module of this Security Manual: + +.. needtable:: + :style: table + :columns: title;id;status + :colwidths: 25,25,25 + :sort: title + + results = [] + + for need in needs.filter_types(["aou_req"]): + if need and "environment" not in need["tags"]: + results.append(need) + +Security concept of the OoC +---------------------------- +| + +Security Weaknesses, Vulnerabilities +------------------------------------ +| Weaknesses, vulnerabilities (bugs in security relevant SW, detected by testing or by users, which could not be fixed) known before release are documented in the platform/module release notes . + +References +---------- +| +| diff --git a/docs/module/manuals/troubleshooting_guide.rst b/docs/module/manuals/troubleshooting_guide.rst new file mode 100644 index 00000000..cf236eb1 --- /dev/null +++ b/docs/module/manuals/troubleshooting_guide.rst @@ -0,0 +1,83 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _manual_time_troubleshooting: + +********************* +Troubleshooting Guide +********************* + +This guide provides solutions to common problems encountered when using or integrating the S-CORE ``time`` module. + +Clock is Not Reliable or Not Available +====================================== + +**Symptom:** +Your application calls ``clock.Now()``, but ``snapshot.Status().IsReliable()`` always returns `false`. Or, ``clock.WaitUntilAvailable()`` runs into a timeout. + +**Potential Causes and Solutions:** + +1. **TimeSlave Not Running or Not Synchronized:** + * **Check:** Is the `time_slave` process running on the ECU? + * **Check:** Is there a PTP Grandmaster Clock active on the network, in the same PTP domain as the `time_slave` (default domain: 0)? + * **Solution:** Ensure the `time_slave` is started correctly and that a PTP master is present and reachable on the specified network interface. Check the logs of the `time_slave` for messages related to master detection. + +2. **TimeDaemon Not Running:** + * **Check:** Is the `time_daemon` process running on the ECU? The `time_slave` can run, but if the `time_daemon` isn't there to process the data, client applications will not receive reliable time. + * **Solution:** Ensure the `time_daemon` process is started. + +3. **IPC Channel Mismatch:** + * **Check:** The `time_slave` and `time_daemon` communicate via a POSIX shared memory file. By default, this is ``/gptp_ptp_info``. + * **Solution:** Verify that this file exists in the shared memory file system (e.g., under `/dev/shm/` on Linux). Check for permission issues that might prevent one of the processes from accessing the file. + +4. **Sync Timeout:** + * **Check:** The `time_slave` has a built-in timeout (`sync_timeout_ms`, default: 3300 ms). If it doesn't receive PTP Sync messages within this period, it declares a timeout. + * **Solution:** Check the network for packet loss. If you are in a simulated environment (QEMU, Docker), ensure the virtual network bridge is configured correctly. + +"Permission Denied" on TimeSlave Startup +======================================== + +**Symptom:** +The `time_slave` process fails to start with an error message similar to "Permission denied", "Operation not permitted", or a socket creation error. + +**Cause & Solution:** + +The `time_slave` requires elevated network privileges to open a raw PTP socket on the specified network interface. + +* **On Linux:** Grant the ``CAP_NET_RAW`` capability to the ``time_slave`` binary instead of running it as root: + + .. code-block:: bash + + sudo setcap cap_net_raw+ep /path/to/time_slave + +* **On QNX:** The ``time_slave`` opens ``/dev/bpf`` (Berkeley Packet Filter device) to capture raw PTP frames. Ensure the process user has read/write permission on ``/dev/bpf``. If a PHC device is configured (``phc_device`` option), the process also needs read/write access to that device node. +* **Shared memory access:** If the error refers to ``/gptp_ptp_info``, verify that the user running ``time_slave`` has read/write permission on the shared memory path (``/dev/shm/`` on Linux). Adjust the file permissions or run both ``time_slave`` and ``time_daemon`` under the same user/group. + +Understanding Log Messages +========================== + +The `time` module components use specific logging contexts to identify the source of a message. This can help you pinpoint where a problem is occurring. + +.. list-table:: Logging Contexts + :widths: 20 80 + :header-rows: 1 + + * - Context ID + - Description + * - ``[TSAP]`` + - **Time Slave Application.** Relates to the main lifecycle (Initialize/Run) of the ``time_slave`` process. + * - ``[GTPS]`` + - **GPTP Slave.** Relates to the core gPTP protocol engine within the ``time_slave`` (e.g., parsing PTP messages, state machines). + * - ``[GPTP]`` + - **GPTP Machine Adapter.** Relates to the component within the ``time_daemon`` that receives and processes the data from shared memory. diff --git a/docs/module/manuals/user_manual.rst b/docs/module/manuals/user_manual.rst new file mode 100644 index 00000000..e3df59e1 --- /dev/null +++ b/docs/module/manuals/user_manual.rst @@ -0,0 +1,185 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _user_manual: + +User Manual +########### + +.. document:: User Manual Time Module + :id: doc__user_manual_time + :status: draft + :version: 1 + :safety: ASIL_B + :security: NO + :realizes: wp__training_path[version==1] + +Overview +======== + +This user manual provides comprehensive guidance for integrating and deploying the S-CORE ``time`` module from a system integrator perspective. + +The S-CORE ``time`` module provides a robust, high-precision time base for applications on an ECU, +synchronized to a network-wide PTP (Precision Time Protocol) Grandmaster Clock. The module consists of three components: + +* **Client Library** (``score::time``): C++ API for accessing synchronized time +* **TimeSlave**: System daemon that synchronizes with the PTP Grandmaster over the network +* **TimeDaemon**: System daemon that provides quality-assured time to client applications + +This module manual covers module-level integration, deployment, and troubleshooting. For component-specific usage and configuration, refer to the component manuals below. + +For build and test of the module itself, please refer to the main documentation. + +API Description +--------------- + +The primary interface for applications to access synchronized time is the ``score::time`` client library: + +.. toctree:: + :maxdepth: 2 + + api_description/api_usage + +.. _component_manuals: + +Component Manuals +----------------- + +For detailed component-specific user manuals: + +.. toctree:: + :maxdepth: 1 + + /components/time/manuals/user_manual + /components/time_slave/manuals/user_manual + /components/time_daemon/manuals/user_manual + +Examples +-------- + +Practical examples and tutorials for using the time module: + +.. toctree:: + :maxdepth: 2 + + examples/index + +Environment Needs +================= + +Basic needed software environment for the module: + +* **C++**: C++17 or later +* **Build System**: Bazel 6.0 or later +* **Operating Systems**: Linux, QNX + +Dependencies +------------ + +* Standard library (STL/Core) +* PTP Grandmaster Clock (external network time source) +* POSIX shared memory support +* Network hardware with PHC (PTP Hardware Clock) support + +See also MODULE.bazel files for more details on dependencies. + +Performance Considerations +========================== + +The ``time`` module is designed for high-performance, low-latency time access in automotive ECUs: + +* **VehicleTime access**: Sub-microsecond latency via POSIX shared memory with seqlock +* **Lock-free IPC**: TimeDaemon reads from TimeSlave without blocking +* **Hardware clock sync**: Direct PHC adjustment for nanosecond-precision synchronization +* **Minimal overhead**: Singleton pattern, zero allocations in time-critical paths + +For detailed performance analysis and benchmarks, this information will be added in future releases. + +Integration Guidelines +====================== + +Integrating with Your Project +------------------------------ + +1. Add the module to your Bazel workspace: + + .. code-block:: python + + # In your MODULE.bazel + bazel_dep(name = "score_time", version = "1.0") + +2. Reference in your build files: + + .. code-block:: python + + cc_library( + name = "my_target", + deps = ["@score_time//score/time/vehicle_time:vehicle_time"], + ) + +3. Include headers and compile your code + +System Services Deployment +--------------------------- + +The ``time`` module requires two system daemons to be running. These processes must be managed by the system's service manager (e.g., `systemd` on Linux, or a launch script on QNX). + +.. For detailed configuration of each daemon (OS privileges, network configuration, command-line arguments), refer to the :ref:`component_manuals` linked above. + +Version History, Compatibility, and Troubleshooting +=================================================== + +For comprehensive information on the following topics: + +* Version history and changes +* Compatibility notes and upgrade instructions +* Known issues and limitations +* Troubleshooting tips and solutions +* Security vulnerabilities (CVEs) + +.. toctree:: + :maxdepth: 1 + + troubleshooting_guide + +Safety and Security +=================== + +**Safety Classification**: ASIL-B (TBC) + +Safety classification details are currently being aligned with ongoing stakeholder and feature requirement clarifications. Current working classification is: + +* ``score::time`` library: ASIL-B (TBC) +* ``TimeDaemon``: ASIL-B +* ``TimeSlave``: QM + +For final safety-critical usage requirements and guidelines, refer to the safety manual updates in upcoming releases. + +**Security Considerations**: + +* The ``time`` module assumes a trusted network for PTP communication +* No authentication or encryption is provided for PTP messages (per IEEE 1588 standard) +* OS-level security controls limit attack surface for TimeSlave daemon (Linux Capabilities on Linux, equivalent least-privilege process configuration on QNX) + +License +======= + +This module is licensed under the Apache License Version 2.0. +See the LICENSE file in the repository for full license text. + +Feedback and Contributions +========================== + +Your feedback and contributions are welcome! Please report issues or suggestions through the +project's issue tracker or contribute directly to the repository. diff --git a/docs/safety_mgt/.gitkeep b/docs/safety_mgt/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/security_mgt/.gitkeep b/docs/security_mgt/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/score/time/BUILD b/score/time/BUILD index 1048941a..7f707a4b 100644 --- a/score/time/BUILD +++ b/score/time/BUILD @@ -13,6 +13,13 @@ load("@score_baselibs//:bazel/unit_tests.bzl", "cc_unit_test_suites_for_host_and_qnx") load("@score_baselibs//third_party/itf:py_unittest_qnx_test.bzl", "py_unittest_qnx_test") +load("@score_docs_as_code//:docs.bzl", "docs_bundle") + +docs_bundle( + name = "docs_bundle", + source_dir = "docs", + visibility = ["//visibility:public"], +) py_unittest_qnx_test( name = "qnx_unit_test_cases", diff --git a/score/time/docs/index.rst b/score/time/docs/index.rst new file mode 100644 index 00000000..74614a63 --- /dev/null +++ b/score/time/docs/index.rst @@ -0,0 +1,20 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Time Component +============== + +.. contents:: Table of Contents + :depth: 2 + :local: diff --git a/score/time/docs/manuals/api_description/lifecycle.rst b/score/time/docs/manuals/api_description/lifecycle.rst new file mode 100644 index 00000000..cddf8987 --- /dev/null +++ b/score/time/docs/manuals/api_description/lifecycle.rst @@ -0,0 +1,116 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _manual_time_lifecycle: + +Clock Lifecycle Management +========================== + +Before an application can read reliable time from clocks like ``VehicleClock``, the underlying backend service must be initialized and ready. The ``Clock`` API provides several functions to manage this lifecycle gracefully. + +.. attention:: + These lifecycle functions are primarily relevant for clocks that depend on external services, like ``VehicleClock``. Simpler clocks such as ``SystemClock`` or ``SteadyClock`` are always available and do not require these steps. + +Initializing the Clock +---------------------- + +The ``Init()`` method must be called once to establish the connection to the backend service (e.g., the ``TimeDaemon``). Until ``Init()`` succeeds, any call to ``Now()`` will return a snapshot with a "not ready" or "unknown" status. + +.. code-block:: cpp + + #include "score/time/clock.h" + #include "score/time/vehicle_time.h" + #include + + void initialize_clock() + { + auto& clock = score::time::Clock::GetInstance(); + + // Attempt to initialize the connection to the backend. + // This can be retried if it fails (e.g., if the TimeDaemon is not yet running). + if (clock.Init()) + { + std::cout << "Clock backend initialized successfully." << std::endl; + } + else + { + std::cerr << "Clock backend initialization failed. Please retry." << std::endl; + } + } + +Waiting for Availability +------------------------ + +After initialization, the clock might still not be "reliable" because the ``TimeDaemon`` itself is waiting for synchronization with the PTP master. Instead of polling in a loop, applications can use ``WaitUntilAvailable()`` to block efficiently until the clock is ready. + +This is the recommended approach for applications that cannot proceed without a valid time source at startup. + +.. code-block:: cpp + + #include "score/time/clock.h" + #include "score/time/vehicle_time.h" + #include + #include + #include + + void wait_for_reliable_time(const score::cpp::stop_token& stop_token) + { + auto& clock = score::time::Clock::GetInstance(); + + if (!clock.Init()) { + std::cerr << "Initialization failed. Cannot wait for time." << std::endl; + return; + } + + // Wait for a maximum of 30 seconds for the clock to become available. + // The wait will be interrupted if the application's stop_token is triggered. + const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(30); + + std::cout << "Waiting for VehicleTime to become available..." << std::endl; + + if (clock.WaitUntilAvailable(stop_token, deadline)) + { + std::cout << "VehicleTime is now available and synchronized!" << std::endl; + + // Now it is safe to start polling or using the time. + const auto snapshot = clock.Now(); + if (snapshot.Status().IsReliable()) { + // ... proceed with application logic ... + } + } + else + { + std::cerr << "Timed out waiting for VehicleTime. Is the TimeSlave running and synchronized?" << std::endl; + } + } + + +Checking Availability (Non-Blocking) +------------------------------------ + +For applications that need to perform other tasks while waiting for time, the non-blocking ``IsAvailable()`` method can be used to periodically check the status. + +.. code-block:: cpp + + // Inside an application's main loop + auto& clock = score::time::Clock::GetInstance(); + + if (clock.IsAvailable()) + { + // Time is ready, perform time-sensitive tasks. + } + else + { + // Time is not yet ready, perform other tasks. + } diff --git a/score/time/docs/manuals/api_description/testing_guide.rst b/score/time/docs/manuals/api_description/testing_guide.rst new file mode 100644 index 00000000..77a94852 --- /dev/null +++ b/score/time/docs/manuals/api_description/testing_guide.rst @@ -0,0 +1,138 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _manual_time_testing: + +Unit-Testing Time-Dependent Code +================================ + +Testing application logic that depends on time can be challenging. To solve this, the ``score::time`` framework provides a powerful mechanism to replace the real-time clock with a controllable "fake" clock during unit tests. This is achieved using the ``ScopedClockOverride`` helper. + +Using Existing Test Utilities +============================= + +The framework provides ``ClockTestFactory`` in +``score/time/clock/src/clock_test_factory.h`` for constructor-based mock injection. + +Use this helper when your component accepts ``Clock`` via constructor or setter injection. + +.. code-block:: cpp + + #include "score/time/clock/src/clock_test_factory.h" + #include "score/time/clock/src/clock_backend_mock.h" + #include "score/time/vehicle_time.h" + #include + + auto backend = std::make_shared>(); + auto clock = score::time::test_utils::ClockTestFactory::Make(backend); + +When code under test calls ``Clock::GetInstance()`` internally, use +``ScopedClockOverride`` as shown below. + + +Example: Testing a Timeout Handler +================================== + +This example demonstrates how to test a component that performs an action once a specific timeout duration has elapsed. + +**Component to be tested (`my_component.h`):** + +.. code-block:: cpp + + #include "score/time/clock.h" + #include "score/time/vehicle_time.h" + #include + + class MyTimeoutHandler { + public: + MyTimeoutHandler() + : clock_{score::time::Clock::GetInstance()} + , start_time_{clock_.Now().TimePoint()} {} + + bool HasTimedOut(std::chrono::seconds timeout_duration) { + const auto now = clock_.Now().TimePoint(); + return (now - start_time_) > timeout_duration; + } + + private: + score::time::Clock clock_; + score::time::VehicleTime::time_point start_time_; + }; + +**Unit Test (`my_component_test.cpp`):** + +.. code-block:: cpp + + #include "my_component.h" + #include "score/time/clock/src/clock_backend_mock.h" + #include "score/time/clock/src/scoped_clock_override.h" + #include + + TEST(MyTimeoutHandlerTest, DetectsTimeoutCorrectly) + { + auto fake_clock_backend = + std::make_shared>(); + score::time::VehicleTime::duration elapsed{0}; + + ON_CALL(*fake_clock_backend, Now()) + .WillByDefault(testing::Invoke([&elapsed]() { + return score::time::TimeSnapshot{ + score::time::VehicleTime::time_point{elapsed}}; + })); + + // 1. Activate override because component uses Clock::GetInstance(). + auto clock_override = score::time::test_utils::ScopedClockOverride( + fake_clock_backend); + + // 2. Instantiate component-under-test. It now uses fake backend. + MyTimeoutHandler handler; + const auto timeout = std::chrono::seconds{10}; + + // 3. Initially, no timeout should be detected. + EXPECT_FALSE(handler.HasTimedOut(timeout)); + + // 4. Advance fake time by 9 seconds. + elapsed += std::chrono::seconds{9}; + EXPECT_FALSE(handler.HasTimedOut(timeout)); + + // 5. Advance past 10-second threshold (total: 11 seconds). + elapsed += std::chrono::seconds{2}; + EXPECT_TRUE(handler.HasTimedOut(timeout)); + + } // clock_override is destroyed here + + +Bazel BUILD Setup +================= + +Because ``ScopedClockOverride`` modifies global state (the active backend for a given clock tag), tests utilizing it must be configured carefully in Bazel. + +To prevent parallel tests from overriding the clock simultaneously and interfering with each other, you **must** mark your test targets with the ``exclusive`` tag. + +.. code-block:: python + + cc_test( + name = "my_component_test", + srcs = [ + "my_component_test.cpp", + "clock_test_factory.h" + ], + tags = ["exclusive", "unit"], # "exclusive" prevents parallel execution conflicts + deps = [ + ":my_component", + "//score/time/vehicle_time:vehicle_time_mock", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], + ) diff --git a/score/time/docs/manuals/user_manual.rst b/score/time/docs/manuals/user_manual.rst new file mode 100644 index 00000000..e524f1a1 --- /dev/null +++ b/score/time/docs/manuals/user_manual.rst @@ -0,0 +1,139 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _time_component_user_manual: + +Time Library User Manual +######################## + +.. document:: User Manual Time Library Component + :id: doc__user_manual_time_lib + :status: draft + :version: 1 + :safety: QM + :security: NO + :realizes: wp__training_path[version==1] + +Overview +======== + +This user manual covers the ``score::time`` client library - the C++ API for accessing synchronized time in your applications. + +The library provides multiple clock types (``VehicleTime``, ``SystemTime``, ``SteadyTime``, ``HighResSteadyTime``) with a unified interface for time access, lifecycle management, and testing. + +For module-level integration and deployment information, see the main module manual. + +Choosing the Right Clock +========================= + +The S-CORE ``time`` module provides several clock types, each designed for a specific use case. Understanding their differences is crucial for writing robust and correct applications. + +Select clock type based on use case. No clock type is universally better; each has a different purpose. + +.. list-table:: Clock Types Overview + :widths: 20 40 40 + :header-rows: 1 + + * - Clock Type + - Key Characteristic + - Typical Use Case + * - ``VehicleTime`` + - High-precision, PTP-synchronized, quality-assured network time. + - Cross-ECU correlation, synchronized logging, and decisions that depend on vehicle-wide time consistency (for example: validating whether a vehicle-time-stamped frame is too old and should be discarded). + * - ``SystemTime`` + - The system's "wall clock" time (Unix time). Can jump forwards or backwards (e.g., due to NTP correction or manual changes). + - Displaying human-readable timestamps. Creating log entries where absolute time is more important than monotonic progression. + * - ``SteadyTime`` + - A clock that is guaranteed to only ever move forward (monotonic). Its starting point is arbitrary (e.g., system boot time). + - Measuring time intervals, implementing timeouts, scheduling tasks where guaranteed monotonic progression is essential. + * - ``HighResSteadyTime`` + - A monotonic clock that provides the highest possible resolution the underlying hardware can offer. + - High-precision performance measurements and profiling, or very short-interval timing. + +API Usage +========= + +This section covers how to use the ``score::time`` client library in your applications: + +.. toctree:: + :maxdepth: 2 + + api_description/lifecycle + api_description/testing_guide + +.. note:: + For a complete C++ API reference with full class and function documentation, + please refer to the generated Doxygen documentation (to be added in future releases). + +Build Integration +================= + +To use the ``score::time`` library in your application: + +1. Add the module to your Bazel workspace: + + .. code-block:: python + + # In your MODULE.bazel + bazel_dep(name = "score_time", version = "1.0") + +2. Reference the clock type you need in your build files: + + .. code-block:: python + + cc_library( + name = "my_target", + deps = [ + "@score_time//score/time/vehicle_time:vehicle_time", # For VehicleTime + # OR + "@score_time//score/time/system_time:system_time", # For SystemTime + # OR + "@score_time//score/time/steady_time:steady_time", # For SteadyTime + # OR + "@score_time//score/time/high_res_steady_time:high_res_steady_time", # For HighResSteadyTime + ], + ) + + For testing, use the mock variants: + + .. code-block:: python + + cc_test( + name = "my_test", + deps = [ + "@score_time//score/time/vehicle_time:vehicle_time_mock", + ], + ) + +3. Include headers in your code: + + .. code-block:: cpp + + #include "score/time/clock.h" + #include "score/time/vehicle_time.h" + + // Example usage + auto& clock = score::time::Clock::GetInstance(); + auto snapshot = clock.Now(); + if (snapshot.Status().IsReliable()) { + // Use snapshot.TimePoint() + } + +Runtime Requirements +==================== + +If using ``VehicleTime``, ``TimeSlave`` and ``TimeDaemon`` system services must be running. +``SystemTime``, ``SteadyTime``, and ``HighResSteadyTime`` do not depend on those daemons. +For deployment and configuration of these services, refer to the module manual and component manuals for +:doc:`/components/time_slave/manuals/user_manual` and :doc:`/components/time_daemon/manuals/user_manual`. diff --git a/score/time_daemon/BUILD b/score/time_daemon/BUILD index a1a29bac..c6430a3d 100644 --- a/score/time_daemon/BUILD +++ b/score/time_daemon/BUILD @@ -12,6 +12,13 @@ # ******************************************************************************* load("@score_baselibs//:bazel/unit_tests.bzl", "cc_unit_test_suites_for_host_and_qnx") +load("@score_docs_as_code//:docs.bzl", "docs_bundle") + +docs_bundle( + name = "docs_bundle", + source_dir = "docs", + visibility = ["//visibility:public"], +) cc_unit_test_suites_for_host_and_qnx( name = "unit_test_suite", diff --git a/score/time_daemon/docs/index.rst b/score/time_daemon/docs/index.rst new file mode 100644 index 00000000..027c3a8b --- /dev/null +++ b/score/time_daemon/docs/index.rst @@ -0,0 +1,20 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Time Daemon Component +===================== + +.. contents:: Table of Contents + :depth: 2 + :local: diff --git a/score/time_daemon/docs/manuals/config/configuration_guide.rst b/score/time_daemon/docs/manuals/config/configuration_guide.rst new file mode 100644 index 00000000..ecc450da --- /dev/null +++ b/score/time_daemon/docs/manuals/config/configuration_guide.rst @@ -0,0 +1,30 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _time_daemon_configuration: + +TimeDaemon Configuration +========================= + +The ``TimeDaemon`` process currently operates **without any external configuration**. It relies on default, built-in settings for IPC communication. + +Shared Memory Configuration +---------------------------- + +The daemon reads from the shared memory segment published by ``TimeSlave``: + +* **Shared memory path**: ``/gptp_ptp_info`` +* **IPC mechanism**: POSIX shared memory with seqlock protection + +No runtime configuration options are exposed at this time. All settings are compiled into the binary. diff --git a/score/time_daemon/docs/manuals/user_manual.rst b/score/time_daemon/docs/manuals/user_manual.rst new file mode 100644 index 00000000..81d38097 --- /dev/null +++ b/score/time_daemon/docs/manuals/user_manual.rst @@ -0,0 +1,50 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _time_daemon_user_manual: + +Time Daemon User Manual +####################### + +.. document:: User Manual Time Daemon Component + :id: doc__user_manual_time_daemon + :status: draft + :version: 1 + :safety: QM + :security: NO + :realizes: wp__training_path[version==1] + +Overview +======== + +The ``TimeDaemon`` component is a system daemon responsible for quality assurance and providing synchronized time to local applications on the ECU. It reads raw synchronization data from shared memory (published by ``TimeSlave``), performs quality checks and plausibility assessments, and provides the final ``score::time`` API to client applications. + +For module-level integration and deployment information, see the main module manual. + +Configuration +============= + +.. toctree:: + :maxdepth: 2 + + config/configuration_guide + +Runtime Requirements +==================== + +The ``TimeDaemon`` requires: + +* ``TimeSlave`` must be running and publishing data to shared memory +* Access to POSIX shared memory segment (``/gptp_ptp_info``) +* Managed by system service manager (e.g., `systemd` on Linux, launch script on QNX) diff --git a/score/time_slave/BUILD b/score/time_slave/BUILD index 4383af58..59c276e7 100644 --- a/score/time_slave/BUILD +++ b/score/time_slave/BUILD @@ -12,6 +12,13 @@ # ******************************************************************************* load("@score_baselibs//:bazel/unit_tests.bzl", "cc_unit_test_suites_for_host_and_qnx") +load("@score_docs_as_code//:docs.bzl", "docs_bundle") + +docs_bundle( + name = "docs_bundle", + source_dir = "docs", + visibility = ["//visibility:public"], +) cc_unit_test_suites_for_host_and_qnx( name = "unit_test_suite", diff --git a/score/time_slave/docs/index.rst b/score/time_slave/docs/index.rst index 6e07edcd..27df135f 100644 --- a/score/time_slave/docs/index.rst +++ b/score/time_slave/docs/index.rst @@ -19,9 +19,3 @@ time_slave Component :maxdepth: 1 component_classification - architecture/index - detailed_design/index - requirements/index - manuals/index - safety_analysis/index - security_analysis/index diff --git a/score/time_slave/docs/manuals/.gitkeep b/score/time_slave/docs/manuals/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/score/time_slave/docs/manuals/config/configuration_guide.rst b/score/time_slave/docs/manuals/config/configuration_guide.rst new file mode 100644 index 00000000..8ea3c983 --- /dev/null +++ b/score/time_slave/docs/manuals/config/configuration_guide.rst @@ -0,0 +1,83 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _time_slave_configuration: + +TimeSlave Configuration +======================= + +The behavior of the ``TimeSlave`` is controlled by the ``GptpEngineOptions`` structure. Currently, only a subset of these options can be overridden at runtime via command-line arguments. For all other options, the hard-coded default values are used. + +Command-Line Arguments +----------------------- + +The following argument is available to configure the ``TimeSlave`` at runtime: + +.. list-table:: + :widths: 25 15 60 + :header-rows: 1 + + * - Argument + - Overrides + - Description + * - ``-i, --interface `` + - ``iface_name`` + - **Mandatory Runtime Parameter.** Specifies the Ethernet network interface. Although the internal default is "emac0", this **must** be set correctly at runtime to match the target hardware. + + +Default Configuration (`GptpEngineOptions`) +-------------------------------------------- + +The following table lists all available options and their default values as defined in the source code. Currently, only ``iface_name`` can be changed without recompiling the application. + +.. list-table:: GptpEngineOptions Default Values + :widths: 25 15 60 + :header-rows: 1 + + * - Option + - Default Value + - Description + * - ``iface_name`` + - ``"emac0"`` + - The network interface to use for gPTP traffic. + * - ``pdelay_interval_ms`` + - ``1000`` + - The interval in milliseconds for sending Peer-Delay measurement requests. + * - ``pdelay_warmup_ms`` + - ``2000`` + - The initial delay in milliseconds before the first Peer-Delay request is sent. + * - ``sync_timeout_ms`` + - ``3300`` + - The time in milliseconds without receiving a PTP Sync message before a timeout is declared and the clock is considered unreliable. + * - ``jump_future_threshold_ns`` + - ``500'000'000`` + - The threshold in nanoseconds (500 ms) for detecting a significant forward time jump. + * - ``domain_number`` + - ``0`` + - The gPTP domain number. The TimeSlave will only interact with a PTP master in the same domain. + * - ``phc_config`` + - ``disabled`` + - Configuration for hardware clock (PHC) adjustments. Disabled by default. + + +Example Invocation +------------------ + +.. code-block:: bash + + # Start the TimeSlave, overriding the default interface name "emac0" + ./time_slave --interface eth1 + +.. attention:: + The command-line parsing is currently incomplete. To change parameters other than the interface name, you must modify the default values in the ``GptpEngineOptions`` structure and recompile the application. A comprehensive configuration mechanism (e.g., via a JSON file) is planned for future versions. diff --git a/score/time_slave/docs/manuals/user_manual.rst b/score/time_slave/docs/manuals/user_manual.rst new file mode 100644 index 00000000..6fcf6462 --- /dev/null +++ b/score/time_slave/docs/manuals/user_manual.rst @@ -0,0 +1,64 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _time_slave_user_manual: + +Time Slave User Manual +###################### + +.. document:: User Manual Time Slave Component + :id: doc__user_manual_time_slave + :status: draft + :version: 1 + :safety: QM + :security: NO + :realizes: wp__training_path[version==1] + +Overview +======== + +The ``TimeSlave`` component is a system daemon responsible for synchronizing with the PTP Grandmaster Clock over the network. It adjusts the hardware clock (PHC) and publishes synchronization data to shared memory for consumption by the ``TimeDaemon``. + +For module-level integration and deployment information, see the main module manual. + +Configuration +============= + +.. toctree:: + :maxdepth: 2 + + config/configuration_guide + +Runtime Requirements +==================== + +Operating System Privileges +--------------------------- + +The ``TimeSlave`` executable (``time_slave``) requires elevated privileges to access raw network sockets and control the hardware clock. It is strongly recommended **not** to run this process as the `root` user. Instead, grant the required Linux Capabilities to the executable: + +.. code-block:: bash + + sudo setcap cap_net_admin,cap_net_raw,cap_sys_time+eip /path/to/time_slave + +* ``cap_net_admin``: For network interface configuration. +* ``cap_net_raw``: For the use of raw sockets to listen to PTP traffic. +* ``cap_sys_time``: For adjusting the system's hardware clock. + +Network Requirements +-------------------- + +* The network interface used for PTP communication **must** be provided via the ``-i, --interface `` command-line argument. +* The ECU must have network connectivity to the PTP Grandmaster clock on this interface. +* Network hardware must support PHC (PTP Hardware Clock).