From 817d7276b7d58e2b0230aa6aa68735f2232256f0 Mon Sep 17 00:00:00 2001 From: Martino Ferrari Date: Sat, 21 Feb 2026 20:33:29 +0100 Subject: [PATCH] Added tutorial and fixed issues on debugservice --- Source/DebugService.cpp | 4 +++ TUTORIAL.md | 56 ++++++++++++++++++++++++++++++ Test/Configurations/debug_test.cfg | 36 +++++++++---------- run_debug_app.sh | 40 +++++++++++++++++++++ 4 files changed, 118 insertions(+), 18 deletions(-) create mode 100644 TUTORIAL.md create mode 100755 run_debug_app.sh diff --git a/Source/DebugService.cpp b/Source/DebugService.cpp index ec1b2b6..5456e55 100644 --- a/Source/DebugService.cpp +++ b/Source/DebugService.cpp @@ -158,17 +158,20 @@ bool DebugService::Initialise(StructuredDataI & data) { REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to Listen on port %u", controlPort); return false; } + printf("[DebugService] TCP Server listening on port %u\n", controlPort); if (!udpSocket.Open()) { REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to open UDP Socket"); return false; } + printf("[DebugService] UDP Streamer socket opened\n"); if (!logServer.Open()) { REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to open Log Server Socket"); return false; } (void)logServer.Listen(logPort); + printf("[DebugService] Log Server listening on port %u\n", logPort); if (threadService.Start() != ErrorManagement::NoError) { REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to start Server thread"); @@ -182,6 +185,7 @@ bool DebugService::Initialise(StructuredDataI & data) { REPORT_ERROR(ErrorManagement::FatalError, "DebugService: Failed to start LogStreamer thread"); return false; } + printf("[DebugService] All worker threads started.\n"); } return true; diff --git a/TUTORIAL.md b/TUTORIAL.md new file mode 100644 index 0000000..79b9076 --- /dev/null +++ b/TUTORIAL.md @@ -0,0 +1,56 @@ +# Tutorial: High-Speed Observability with MARTe2 Debug GUI + +This guide will walk you through the process of tracing and forcing signals in a real-time MARTe2 application using the native Rust GUI client. + +## 1. Environment Setup + +### Launch the MARTe2 Application +First, start your application using the provided debug runner. This script launches the standard `MARTeApp.ex` while injecting the debugging layer: +```bash +./run_debug_app.sh +``` +*Note: You should see logs indicating the `DebugService` has started on port 8080.* + +### Start the GUI Client +In a new terminal window, navigate to the client directory and run the GUI: +```bash +cd Tools/gui_client +cargo run --release +``` + +## 2. Exploring the Object Tree +Once connected, the left panel (**Application Tree**) displays the live hierarchy of your application. + +1. **Navigate to Data:** Expand `Root` -> `App` -> `Data`. +2. **Inspect Nodes:** Click the **ℹ Info** button next to any node (like `Timer` or `DDB`). +3. **View Metadata:** The bottom-left pane will display the full JSON configuration of that object, including its class, parameters, and signals. + +## 3. Real-Time Signal Tracing (Oscilloscope) +Tracing allows you to see signal values exactly as they exist in the real-time memory map. + +1. **Find a Signal:** In the tree, locate `Root.App.Data.Timer.Counter`. +2. **Activate Trace:** Click the **📈 Trace** button. +3. **Monitor the Scope:** The central **Oscilloscope** panel will begin plotting the signal. +4. **Verify Data Flow:** Check the **UDP Packets** counter in the top bar; it should be increasing rapidly, confirming high-speed data reception (Port 8081). +5. **Multi-Signal Trace:** You can click **📈 Trace** on other signals (like `Time`) to overlay multiple plots. + +## 4. Signal Forcing (Manual Override) +Forcing allows you to bypass the framework logic and manually set a signal's value in memory. + +1. **Locate Target:** Find a signal that is being written by a GAM, such as `Root.App.Data.DDB.Counter`. +2. **Open Force Dialog:** Click the **⚡ Force** button next to the signal. +3. **Inject Value:** In the popup dialog, enter a new value (e.g., `9999`) and click **Apply Force**. +4. **Observe Effect:** If you are tracing the same signal, the oscilloscope plot will immediately jump to and hold at `9999`. +5. **Release Control:** To stop forcing, click the **❌** button in the **Active Controls** (Right Panel) under "Forced Signals". The framework will resume writing its own values to that memory location. + +## 5. Advanced Controls + +### Global Pause +If you need to "freeze" the entire application to inspect a specific state: +- Click **⏸ Pause** in the top bar. The real-time threads will halt at the start of their next cycle. +- Click **▶ Resume** to restart the execution. + +### Log Terminal +The bottom panel displays every `REPORT_ERROR` event from the C++ framework. +- **Regex Filter:** Type a keyword like `Timer` in the filter box to isolate relevant events. +- **Pause Logs:** Toggle **⏸ Pause Logs** to stop the scrolling view while data continues to be captured in the background. diff --git a/Test/Configurations/debug_test.cfg b/Test/Configurations/debug_test.cfg index da337d8..419ebe7 100644 --- a/Test/Configurations/debug_test.cfg +++ b/Test/Configurations/debug_test.cfg @@ -1,19 +1,4 @@ -+DebugService = { - Class = DebugService - ControlPort = 8080 - StreamPort = 8081 - StreamIP = "127.0.0.1" -} - -+LoggerService = { - Class = LoggerService - CPUs = 0x1 - +DebugConsumer = { - Class = DebugService - } -} - -+App = { +$App = { Class = RealTimeApplication +Functions = { Class = ReferenceContainer @@ -23,7 +8,7 @@ Counter = { DataSource = Timer Type = uint32 - Frequency = 10 + Frequency = 1 } Time = { DataSource = Timer @@ -47,7 +32,7 @@ DefaultDataSource = DDB +Timer = { Class = LinuxTimer - SleepTime = 1000000 // 1 second + SleepTime = 1000000 // 1 second cycle to reduce log spam Signals = { Counter = { Type = uint32 @@ -99,3 +84,18 @@ TimingDataSource = DAMS } } + ++DebugService = { + Class = DebugService + ControlPort = 8080 + UdpPort = 8081 + StreamIP = "127.0.0.1" +} + ++LoggerService = { + Class = LoggerService + CPUs = 0x1 + +DebugConsumer = { + Class = DebugService + } +} diff --git a/run_debug_app.sh b/run_debug_app.sh new file mode 100755 index 0000000..03657ec --- /dev/null +++ b/run_debug_app.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# run_debug_app.sh - Launch the MARTe2 Debugging Environment using standard MARTeApp.ex + +# 1. Environment Setup +if [ -f "./env.sh" ]; then + source ./env.sh +else + echo "ERROR: env.sh not found. Ensure you are in the project root." + exit 1 +fi + +# 2. Paths +MARTE_EX="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex" +DEBUG_LIB="$(pwd)/Build/libmarte_dev.so" + +# Component library base search path +COMPONENTS_BUILD_DIR="${MARTe2_Components_DIR}/Build/${TARGET}/Components" + +# DYNAMICALLY FIND ALL COMPONENT DIRS +# MARTe2 Loader needs the specific directories containing .so files in LD_LIBRARY_PATH +ALL_COMPONENT_DIRS=$(find "$COMPONENTS_BUILD_DIR" -type d) +for dir in $ALL_COMPONENT_DIRS; do + if ls "$dir"/*.so >/dev/null 2>&1; then + export LD_LIBRARY_PATH="$dir:$LD_LIBRARY_PATH" + fi +done + +# Ensure our build dir and core dir are included +export LD_LIBRARY_PATH="$(pwd)/Build:${MARTe2_DIR}/Build/${TARGET}/Core:${LD_LIBRARY_PATH}" + +# 3. Cleanup +echo "Cleaning up lingering processes..." +pkill -9 MARTeApp.ex +sleep 1 + +# 4. Launch Application +echo "Launching standard MARTeApp.ex with debug_test.cfg..." +# PRELOAD ensures our DebugService class is available to the registry early +export LD_PRELOAD="${DEBUG_LIB}" +"$MARTE_EX" -f Test/Configurations/debug_test.cfg -l RealTimeLoader -s State1