From 261d68a9964a31ede92fbee1a760bf5626135082 Mon Sep 17 00:00:00 2001 From: "Ludwig Weise (ETAS-E2E/XPC-Hi3)" Date: Wed, 15 Jul 2026 15:42:16 +0200 Subject: [PATCH 1/3] feat(docs): Create public user manual for time module It includes - An overall architecture introduction and a guide for choosing the right clock. - A detailed API description covering basic usage, lifecycle management, advanced subscriptions, and unit-testing patterns. - A dedicated integration guide for system integrators. - A troubleshooting guide for diagnosing common runtime issues. --- docs/manuals/.gitkeep | 0 docs/manuals/api_description/advanced_api.rst | 122 ++++++++++++++ docs/manuals/api_description/api_usage.rst | 88 ++++++++++ docs/manuals/api_description/lifecycle.rst | 116 +++++++++++++ .../manuals/api_description/testing_guide.rst | 153 ++++++++++++++++++ docs/manuals/config/configuration_guide.rst | 94 +++++++++++ docs/manuals/index_user_manual.rst | 32 ++++ docs/manuals/integration_guide.rst | 57 +++++++ docs/manuals/introduction.rst | 92 +++++++++++ docs/manuals/troubleshooting_guide.rst | 73 +++++++++ 10 files changed, 827 insertions(+) delete mode 100644 docs/manuals/.gitkeep create mode 100644 docs/manuals/api_description/advanced_api.rst create mode 100644 docs/manuals/api_description/api_usage.rst create mode 100644 docs/manuals/api_description/lifecycle.rst create mode 100644 docs/manuals/api_description/testing_guide.rst create mode 100644 docs/manuals/config/configuration_guide.rst create mode 100644 docs/manuals/index_user_manual.rst create mode 100644 docs/manuals/integration_guide.rst create mode 100644 docs/manuals/introduction.rst create mode 100644 docs/manuals/troubleshooting_guide.rst diff --git a/docs/manuals/.gitkeep b/docs/manuals/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/manuals/api_description/advanced_api.rst b/docs/manuals/api_description/advanced_api.rst new file mode 100644 index 00000000..dd1270dd --- /dev/null +++ b/docs/manuals/api_description/advanced_api.rst @@ -0,0 +1,122 @@ +.. + # ******************************************************************************* + # 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_advanced_api + +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/api_description/api_usage.rst b/docs/manuals/api_description/api_usage.rst new file mode 100644 index 00000000..91456cba --- /dev/null +++ b/docs/manuals/api_description/api_usage.rst @@ -0,0 +1,88 @@ +.. + # ******************************************************************************* + # 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. + +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. + // The IsReliable() flag indicates if the time is currently synchronized + // to a master and has passed all quality checks in the TimeDaemon. + if (snapshot.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 the "not synchronized" case. + // If the time is not reliable, applications must not use the timepoint value. + // This can happen during startup or if the connection to the Time Master is lost. + // The application should implement a retry-logic or fallback. + std::cerr << "Warning: Vehicle Time is not synchronized or not reliable. " + << "Retrying later..." << std::endl; + } + } + +Workflow Explanation +-------------------- + +The sequence diagram "VT1 — VehicleTime: Time Polling with Status Check" illustrates the following steps: + +1. **Get Instance**: The application first obtains a singleton instance of the ``VehicleClock``. This is a lightweight operation and the clock handle can be stored and reused. +2. **Now()**: The application calls the ``Now()`` method on the clock instance. This triggers an IPC call to the ``TimeDaemon`` to fetch the latest synchronized time data. +3. **Return Snapshot**: The framework returns a ``ClockSnapshot`` object. This object contains not just the timepoint, but also a crucial ``VehicleTimeStatus`` payload. +4. **Status Check**: The application **must** call the ``Status().IsReliable()`` method on the snapshot. This boolean flag consolidates all underlying quality metrics (e.g., is PTP master available? is shared memory data fresh? has the time passed plausibility checks?). +5. **Conditional Logic**: + * If ``IsReliable()`` returns ``true``, the timepoint is valid and can be safely used by the application logic. + * If ``IsReliable()`` returns ``false``, the application must discard the timepoint value and handle the failure case (e.g., by logging a warning and retrying the operation after a short delay). + +.. attention:: + + Never use the ``TimePoint`` from a ``ClockSnapshot`` without first verifying that ``Status().IsReliable()`` is true. Using an unreliable timepoint can lead to incorrect or inconsistent behavior in safety-critical applications. diff --git a/docs/manuals/api_description/lifecycle.rst b/docs/manuals/api_description/lifecycle.rst new file mode 100644 index 00000000..a5eec71c --- /dev/null +++ b/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/docs/manuals/api_description/testing_guide.rst b/docs/manuals/api_description/testing_guide.rst new file mode 100644 index 00000000..dbd0b81c --- /dev/null +++ b/docs/manuals/api_description/testing_guide.rst @@ -0,0 +1,153 @@ +.. + # ******************************************************************************* + # 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. + +A Helper for Controllable Time: The `ClockTestFactory` +====================================================== + +To make tests cleaner and more readable, it is a recommended practice to create a small test factory helper class. This class encapsulates the creation of the fake clock and provides a simple API to control the time within a test. + +Here is a minimal implementation of such a factory. You can add this helper to your own test utilities. + +**`clock_test_factory.h` (Example Implementation):** + +.. code-block:: cpp + + #include "score/time/clock/src/clock_backend_mock.h" + #include "score/time/vehicle_time.h" + #include + #include + + // A helper class to manage a fake clock backend in tests. + class ClockTestFactory { + public: + // Creates the backend and returns a shared_ptr to it. + // This backend is then passed to the ScopedClockOverride. + std::shared_ptr> + CreateFakeClock() { + fake_clock_backend_ = std::make_shared>(); + return fake_clock_backend_; + } + + // Advances the time on the created fake clock. + void AdvanceTime(std::chrono::nanoseconds duration) { + // We simulate a monotonic clock by shifting the offset of the mock + // to return a progressively advanced timestamp on every subsequent call. + current_time_ += duration; + ON_CALL(*fake_clock_backend_, Now()) + .WillByDefault(testing::Return(score::time::TimeSnapshot( + score::time::VehicleTime::time_point(current_time_)))); + } + + private: + std::shared_ptr> fake_clock_backend_; + std::chrono::nanoseconds current_time_{0}; + }; + + +Example: Testing a Timeout Handler +================================== + +This example demonstrates how to use the custom `ClockTestFactory` helper 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 "clock_test_factory.h" // Our custom helper + #include "score/time/clock/src/scoped_clock_override.h" + #include + + TEST(MyTimeoutHandlerTest, DetectsTimeoutCorrectly) + { + // 1. Create our test factory helper. + ClockTestFactory test_factory; + auto fake_clock_backend = test_factory.CreateFakeClock(); + + // 2. Activate the override with the backend from our factory. + auto clock_override = score::time::test_utils::ScopedClockOverride( + fake_clock_backend); + + // 3. Instantiate the component-under-test. It will now automatically use the fake clock. + MyTimeoutHandler handler; + const auto timeout = std::chrono::seconds{10}; + + // 4. Initially, no timeout should be detected. + EXPECT_FALSE(handler.HasTimedOut(timeout)); + + // 5. Advance the fake clock's time via our factory helper by 9 seconds. + test_factory.AdvanceTime(std::chrono::seconds{9}); + EXPECT_FALSE(handler.HasTimedOut(timeout)); + + // 6. Advance the time past the 10 seconds timeout threshold (Total: 11 seconds). + test_factory.AdvanceTime(std::chrono::seconds{2}); + EXPECT_TRUE(handler.HasTimedOut(timeout)); + + } // <-- 7. Here, `clock_override` is destroyed, and the real clock backend is automatically restored. + + +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/docs/manuals/config/configuration_guide.rst b/docs/manuals/config/configuration_guide.rst new file mode 100644 index 00000000..fe9dab7a --- /dev/null +++ b/docs/manuals/config/configuration_guide.rst @@ -0,0 +1,94 @@ +.. + # ******************************************************************************* + # 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_configuration: + +Configuration Guide +=================== + +This guide describes the configuration of the sCore ``time`` module components. + +TimeSlave Daemon (`time_slave`) +=============================== + +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. + + +TimeDaemon (`time_daemon`) & Client Applications +================================================ + +The ``TimeDaemon`` process and all client applications using the ``score::time`` library currently operate **without any external configuration**. They rely on the default, built-in settings for IPC communication. diff --git a/docs/manuals/index_user_manual.rst b/docs/manuals/index_user_manual.rst new file mode 100644 index 00000000..2c0b2251 --- /dev/null +++ b/docs/manuals/index_user_manual.rst @@ -0,0 +1,32 @@ +.. + # ******************************************************************************* + # 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 + # ******************************************************************************* + +sCore::time User Manual +======================= + +This manual describes the architecture, usage, and configuration of the sCore ``time`` module. + +.. toctree:: + :maxdepth: 2 + :caption: Chapters: + + introduction + api_description/choosing_a_clock + api_description/api_usage + api_description/lifecycle + api_description/testing_guide + api_description/advanced_api + config/configuration_guide + integration_guide + troubleshooting_guide diff --git a/docs/manuals/integration_guide.rst b/docs/manuals/integration_guide.rst new file mode 100644 index 00000000..c4b03e3f --- /dev/null +++ b/docs/manuals/integration_guide.rst @@ -0,0 +1,57 @@ +.. + # ******************************************************************************* + # 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_integration: + +***************** +Integration Guide +***************** + +This guide is intended for system integrators who are responsible for deploying and configuring the ``time`` module services on an ECU. + +System Services +=============== + +The sCore ``time`` module consists of two essential system services that must be running for the client library to function: + +1. ``time_slave``: The PTP slave process that communicates with the network master clock. +2. ``time_daemon``: The daemon that processes the data from the ``time_slave`` and provides it to client applications. + +These two processes must be managed by the system's service manager (e.g., `systemd` on Linux, or a launch script on QNX). + +Runtime Requirements +==================== + +Operating System Privileges +--------------------------- +The ``time_slave`` process 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/your/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 Configuration +--------------------- +* The network interface used for PTP communication **must** be provided to the ``time_slave`` via the ``-i, --interface `` command-line argument. +* The ECU must have network connectivity to the PTP Grandmaster clock on this interface. + +Build-Time Dependencies (Bazel) +------------------------------- +For an application to successfully link against the ``score::time`` client library, its ``cc_binary`` or ``cc_library`` target in the `BUILD` file must include the `vehicle_time` dependencies. + +Please refer to the **Bazel Build Setup** section in the examples documentation for a detailed explanation of the required ``deps``. diff --git a/docs/manuals/introduction.rst b/docs/manuals/introduction.rst new file mode 100644 index 00000000..3fe485f6 --- /dev/null +++ b/docs/manuals/introduction.rst @@ -0,0 +1,92 @@ +.. + # ******************************************************************************* + # 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_introduction + +Architecture and Components +=========================== + +The sCore ``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 architecture is split into two main processes, the **TimeSlave** and the **TimeDaemon**, which communicate via a highly efficient shared memory channel. + +.. figure:: /docs/features/time_slave/_assets/timeslave_deployment.png + :align: center + :alt: TimeSlave Deployment View + + The deployment view shows the key components and their interactions. + +Component Overview +------------------ + +**1. Time Master (External)** + +* The **PTP Grandmaster Clock** is the authoritative time source for the entire vehicle network. It periodically sends PTP synchronization messages (EtherType ``0x88F7``) over the Ethernet network. + +**2. TimeSlave Process** + +* The ``TimeSlave`` is a standalone process responsible for all network-related PTP activities. It is the direct counterpart to the Time Master. +* **GptpEngine**: The core of the TimeSlave. It runs two main threads: + * **RxThread**: Listens for incoming PTP messages from the Time Master. + * **PdelayThread**: Actively measures the network latency (path delay) to the communication partner, as specified by the gPTP standard. +* **PhcAdjuster**: Receives the calculated time offset and frequency deviation from the ``GptpEngine``. It then directly adjusts the hardware clock of the network card (PHC Device) using kernel system calls like ``clock_adjtime``. This ensures the hardware clock is precisely synchronized. +* **GptpIpcPublisher**: Publishes the raw synchronization data, including timestamps and quality metrics, into a POSIX shared memory segment (``/gptp_ptp_info``). +* **ProbeManager + Recorder**: An instrumentation component for diagnostics and performance monitoring. + +**3. TimeDaemon Process** + +* The ``TimeDaemon`` is responsible for quality assurance and providing the synchronized time to all local applications on the ECU. It acts as the server for the sCore time service. +* **GptpIpcReceiver**: Reads the raw data from the shared memory segment published by the ``TimeSlave``. +* **ShmPTPEngine**: The core of the TimeDaemon. It wraps the ``GptpIpcReceiver``, processes the raw ``GptpIpcData``, performs quality checks and plausibility assessments, and converts it into the final, high-level ``PtpTimeInfo`` format that client applications will consume. + +**4. Shared Memory (IPC Channel)** + +* A POSIX shared memory segment, typically ``/gptp_ptp_info``, serves as a high-performance, lock-free communication channel between the ``TimeSlave`` and the ``TimeDaemon``. +* **seqlock**: The communication is protected by a seqlock (sequence lock) mechanism. This allows the ``GptpIpcReceiver`` to read the data without ever being blocked, ensuring real-time safety, while also guaranteeing that it never receives partially updated (torn) data. + +Data Flow Summary +----------------- + +1. The **Time Master** sends PTP messages over the Ethernet network. +2. The **GptpEngine** in the ``TimeSlave`` process receives these messages. +3. The ``GptpEngine`` calculates the time offset and adjusts the **PHC Device** (hardware clock) via the ``PhcAdjuster``. +4. Simultaneously, the ``GptpEngine`` passes the raw synchronization data to the **GptpIpcPublisher**. +5. The publisher writes the data into **Shared Memory** using a seqlock. +6. The **GptpIpcReceiver** in the ``TimeDaemon`` process reads the data from shared memory, also using the seqlock mechanism. +7. The **ShmPTPEngine** processes this data, turning it into the final, quality-assured time base for the system. + +Choosing the Right Clock +======================== + +The sCore ``time`` module provides several clock types, each designed for a specific use case. Understanding their differences is crucial for writing robust and correct applications. + +In general, you should **always prefer ``VehicleTime``** unless you have a specific reason to measure a local time interval or need a simple wall-clock timestamp for purely informational purposes. + +.. 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. **This is the recommended clock for almost all applications.** + - Synchronized logging across ECUs, event timestamping, any logic that depends on a common time base in the vehicle. + * - ``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. diff --git a/docs/manuals/troubleshooting_guide.rst b/docs/manuals/troubleshooting_guide.rst new file mode 100644 index 00000000..b1044092 --- /dev/null +++ b/docs/manuals/troubleshooting_guide.rst @@ -0,0 +1,73 @@ +.. + # ******************************************************************************* + # 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 sCore ``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:** +This typically indicates that the ``time_slave`` executable is missing the required Linux Capabilities to run. Please refer to the section on **Operating System Privileges** in the :ref:`Integration Guide ` for detailed setup instructions. + +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. From c3fd62aa4fcda41e1ed8880aaebaa8d44e1a7223 Mon Sep 17 00:00:00 2001 From: "Ludwig Weise (ETAS-E2E/XPC-Hi3)" Date: Thu, 16 Jul 2026 12:30:05 +0200 Subject: [PATCH 2/3] fix(docs): Correct RST structure and apply review feedback --- docs/manuals/api_description/advanced_api.rst | 2 +- docs/manuals/api_description/api_usage.rst | 2 +- docs/manuals/api_description/lifecycle.rst | 2 +- docs/manuals/config/configuration_guide.rst | 2 +- .../{index_user_manual.rst => index.rst} | 21 ++++++++++++++----- docs/manuals/integration_guide.rst | 2 +- docs/manuals/introduction.rst | 13 ++++++------ docs/manuals/troubleshooting_guide.rst | 4 ++-- 8 files changed, 29 insertions(+), 19 deletions(-) rename docs/manuals/{index_user_manual.rst => index.rst} (66%) diff --git a/docs/manuals/api_description/advanced_api.rst b/docs/manuals/api_description/advanced_api.rst index dd1270dd..679e53d7 100644 --- a/docs/manuals/api_description/advanced_api.rst +++ b/docs/manuals/api_description/advanced_api.rst @@ -12,7 +12,7 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _manual_time_advanced_api +.. _manual_time_advanced_api: Advanced API Usage: Subscribing to PTP Protocol Events ====================================================== diff --git a/docs/manuals/api_description/api_usage.rst b/docs/manuals/api_description/api_usage.rst index 91456cba..d81b9400 100644 --- a/docs/manuals/api_description/api_usage.rst +++ b/docs/manuals/api_description/api_usage.rst @@ -12,7 +12,7 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _manual_time_api_usage +.. _manual_time_api_usage: API Usage: Accessing Vehicle Time ================================= diff --git a/docs/manuals/api_description/lifecycle.rst b/docs/manuals/api_description/lifecycle.rst index a5eec71c..cddf8987 100644 --- a/docs/manuals/api_description/lifecycle.rst +++ b/docs/manuals/api_description/lifecycle.rst @@ -12,7 +12,7 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _manual_time_lifecycle +.. _manual_time_lifecycle: Clock Lifecycle Management ========================== diff --git a/docs/manuals/config/configuration_guide.rst b/docs/manuals/config/configuration_guide.rst index fe9dab7a..6c5ad308 100644 --- a/docs/manuals/config/configuration_guide.rst +++ b/docs/manuals/config/configuration_guide.rst @@ -17,7 +17,7 @@ Configuration Guide =================== -This guide describes the configuration of the sCore ``time`` module components. +This guide describes the configuration of the S-CORE ``time`` module components. TimeSlave Daemon (`time_slave`) =============================== diff --git a/docs/manuals/index_user_manual.rst b/docs/manuals/index.rst similarity index 66% rename from docs/manuals/index_user_manual.rst rename to docs/manuals/index.rst index 2c0b2251..1fd4ae07 100644 --- a/docs/manuals/index_user_manual.rst +++ b/docs/manuals/index.rst @@ -12,17 +12,18 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -sCore::time User Manual -======================= +.. _manuals_main: -This manual describes the architecture, usage, and configuration of the sCore ``time`` module. +Manuals +======= + +This section contains all user-facing manuals for the sCore ``time`` module, combining the main User Manual with all relevant examples. .. toctree:: :maxdepth: 2 - :caption: Chapters: + :caption: User Manual: introduction - api_description/choosing_a_clock api_description/api_usage api_description/lifecycle api_description/testing_guide @@ -30,3 +31,13 @@ This manual describes the architecture, usage, and configuration of the sCore `` config/configuration_guide integration_guide troubleshooting_guide + +.. +.. The following toctree is for the examples manual. It is commented out +.. temporarily until the corresponding files are checked in. +.. +.. .. toctree:: +.. :maxdepth: 2 +.. :caption: Examples: +.. +.. examples/index diff --git a/docs/manuals/integration_guide.rst b/docs/manuals/integration_guide.rst index c4b03e3f..d9032e0f 100644 --- a/docs/manuals/integration_guide.rst +++ b/docs/manuals/integration_guide.rst @@ -23,7 +23,7 @@ This guide is intended for system integrators who are responsible for deploying System Services =============== -The sCore ``time`` module consists of two essential system services that must be running for the client library to function: +The S-CORE ``time`` module consists of two essential system services that must be running for the client library to function: 1. ``time_slave``: The PTP slave process that communicates with the network master clock. 2. ``time_daemon``: The daemon that processes the data from the ``time_slave`` and provides it to client applications. diff --git a/docs/manuals/introduction.rst b/docs/manuals/introduction.rst index 3fe485f6..9dc9e5a1 100644 --- a/docs/manuals/introduction.rst +++ b/docs/manuals/introduction.rst @@ -12,16 +12,15 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _manual_time_introduction +.. _manual_time_introduction: Architecture and Components =========================== -The sCore ``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 architecture is split into two main processes, the **TimeSlave** and the **TimeDaemon**, which communicate via a highly efficient shared memory channel. +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 architecture is split into two main processes, the **TimeSlave** and the **TimeDaemon**, which communicate via a highly efficient shared memory channel. -.. figure:: /docs/features/time_slave/_assets/timeslave_deployment.png - :align: center - :alt: TimeSlave Deployment View +.. uml:: ../features/time_slave/_assets/timeslave_deployment.puml + :alt: Deployment Diagram The deployment view shows the key components and their interactions. @@ -44,7 +43,7 @@ Component Overview **3. TimeDaemon Process** -* The ``TimeDaemon`` is responsible for quality assurance and providing the synchronized time to all local applications on the ECU. It acts as the server for the sCore time service. +* The ``TimeDaemon`` is responsible for quality assurance and providing the synchronized time to all local applications on the ECU. It acts as the server for the S-CORE time service. * **GptpIpcReceiver**: Reads the raw data from the shared memory segment published by the ``TimeSlave``. * **ShmPTPEngine**: The core of the TimeDaemon. It wraps the ``GptpIpcReceiver``, processes the raw ``GptpIpcData``, performs quality checks and plausibility assessments, and converts it into the final, high-level ``PtpTimeInfo`` format that client applications will consume. @@ -67,7 +66,7 @@ Data Flow Summary Choosing the Right Clock ======================== -The sCore ``time`` module provides several clock types, each designed for a specific use case. Understanding their differences is crucial for writing robust and correct applications. +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. In general, you should **always prefer ``VehicleTime``** unless you have a specific reason to measure a local time interval or need a simple wall-clock timestamp for purely informational purposes. diff --git a/docs/manuals/troubleshooting_guide.rst b/docs/manuals/troubleshooting_guide.rst index b1044092..c3c6e6c5 100644 --- a/docs/manuals/troubleshooting_guide.rst +++ b/docs/manuals/troubleshooting_guide.rst @@ -12,13 +12,13 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _manual_time_troubleshooting +.. _manual_time_troubleshooting: ********************* Troubleshooting Guide ********************* -This guide provides solutions to common problems encountered when using or integrating the sCore ``time`` module. +This guide provides solutions to common problems encountered when using or integrating the S-CORE ``time`` module. Clock is Not Reliable or Not Available ====================================== From 094c15e902161ddfb8f9b4ff796e9d6fffe88aed Mon Sep 17 00:00:00 2001 From: "Ludwig Weise (ETAS-E2E/XPC-Hi3)" Date: Thu, 16 Jul 2026 12:51:06 +0200 Subject: [PATCH 3/3] fix(docs): Integrate user manual into main documentation toctree --- docs/index.rst | 1 + docs/manuals/introduction.rst | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index e35c841d..6007e6f8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -43,6 +43,7 @@ For a detailed concept and architectural design, please refer to the :doc:`time_ :caption: Contents: features/index + manuals/index Project Layout -------------- diff --git a/docs/manuals/introduction.rst b/docs/manuals/introduction.rst index 9dc9e5a1..5ee50ff6 100644 --- a/docs/manuals/introduction.rst +++ b/docs/manuals/introduction.rst @@ -22,8 +22,6 @@ The S-CORE ``time`` module provides a robust, high-precision time base for appli .. uml:: ../features/time_slave/_assets/timeslave_deployment.puml :alt: Deployment Diagram - The deployment view shows the key components and their interactions. - Component Overview ------------------