Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ repos:
- id: cpplint
args:
- --config=cpplint.cfg

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.13.2
hooks:
- id: ruff-check
args: [--fix]
- id: ruff-check
args: [--fix, --select, I] # import sorting
- id: ruff-format
28 changes: 23 additions & 5 deletions FprimeZephyrReference/Components/Watchdog/Watchdog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ Watchdog ::~Watchdog() {}
// ----------------------------------------------------------------------

void Watchdog ::run_handler(FwIndexType portNum, U32 context) {
// Only perform actions when stop not requested
if (!this->m_stopRequested) {
// Only perform actions when run is enabled
if (this->m_run) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swapped logic from running when false to running when true. Helps me understand the state of the watchdog.

// Toggle state every rate group call
this->m_state = (this->m_state == Fw::On::ON) ? Fw::On::OFF : Fw::On::ON;
this->m_transitions++;
Expand All @@ -33,17 +33,35 @@ void Watchdog ::run_handler(FwIndexType portNum, U32 context) {
}
}

void Watchdog ::start_handler(FwIndexType portNum) {
// Start the watchdog
this->m_run = true;

// Report watchdog started
this->log_ACTIVITY_HI_WatchdogStart();
}

void Watchdog ::stop_handler(FwIndexType portNum) {
// Set the stop flag to stop watchdog petting
this->m_stopRequested = true;
// Stop the watchdog
this->m_run = false;

// Report watchdog stopped
this->log_ACTIVITY_HI_WatchdogStop();
}

// ----------------------------------------------------------------------
// Handler implementations for commands
// ----------------------------------------------------------------------

void Watchdog ::TEST_STOP_WATCHDOG_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
void Watchdog ::START_WATCHDOG_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
// call start handler
this->start_handler(0);

// Provide command response
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
}

void Watchdog ::STOP_WATCHDOG_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
// call stop handler
this->stop_handler(0);

Expand Down
25 changes: 18 additions & 7 deletions FprimeZephyrReference/Components/Watchdog/Watchdog.fpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
module Components {
@ Component to blink an LED as a watchdog petter, driven by a rate group
@ Component to pet the watchdog, driven by a rate group
passive component Watchdog {
@ Command to start the watchdog
sync command START_WATCHDOG(
)

@ Command to stop the watchdog petter
sync command TEST_STOP_WATCHDOG(
@ Command to stop the watchdog
sync command STOP_WATCHDOG(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed command name to no longer be prefixed by TEST_. I believe disabling the watchdog via command (causing a hard reboot) is one of the original requirements so it feels like it's no longer a "test command"

)

@ Telemetry channel counting watchdog petter transitions
@ Telemetry channel counting watchdog pet transitions
telemetry WatchdogTransitions: U32

@ Event logged when the watchdog petter LED turns on or off
@ Event logged when the watchdog is started
event WatchdogStart() \
severity activity high \
format "Watchdog started"

@ Event logged when the watchdog is stopped
event WatchdogStop() \
severity activity high \
format "Watchdog no longer being pet!"
format "Watchdog stopped"

@ Port receiving calls from the rate group
sync input port run: Svc.Sched

@ Port to stop the watchdog petting
@ Port to start the watchdog
sync input port start: Fw.Signal

@ Port to stop the watchdog
sync input port stop: Fw.Signal

@ Port sending calls to the GPIO driver
Expand Down
34 changes: 26 additions & 8 deletions FprimeZephyrReference/Components/Watchdog/Watchdog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,40 @@ class Watchdog : public WatchdogComponentBase {
U32 context //!< The call order
) override;

//! Handler implementation for start
//!
//! Port to start the watchdog
void start_handler(FwIndexType portNum //!< The port number
) override;

//! Handler implementation for stop
//!
//! Port to stop the watchdog petting
void stop_handler(FwIndexType portNum) override;
//! Port to stop the watchdog
void stop_handler(FwIndexType portNum //!< The port number
) override;

private:
// ----------------------------------------------------------------------
// Handler implementations for commands
// ----------------------------------------------------------------------

void TEST_STOP_WATCHDOG_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) override;
//! Handler implementation for command START_WATCHDOG
//!
//! Command to start the watchdog
void START_WATCHDOG_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq //!< The command sequence number
) override;

//! Handler implementation for command STOP_WATCHDOG
//!
//! Command to stop the watchdog
void STOP_WATCHDOG_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq //!< The command sequence number
) override;

std::atomic_bool m_stopRequested{false}; //! Flag to stop the watchdog petting
Fw::On m_state = Fw::On::OFF; //! Keeps track of GPIO state
U32 m_transitions = 0; //! The number of on/off transitions that have occurred
//! from FSW boot up
std::atomic_bool m_run{true}; //! Flag to start or stop the watchdog
Fw::On m_state = Fw::On::OFF; //! Keeps track of GPIO state
U32 m_transitions = 0; //! The number of on/off transitions that have occurred
//! from FSW boot up
};

} // namespace Components
Expand Down
19 changes: 12 additions & 7 deletions FprimeZephyrReference/Components/Watchdog/docs/sdd.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ Requirement | Description | Verification Method | Verified?
----------- | ----------- | ------------------- | ---------
WD-001 | The `Components::Watchdog` component shall activate upon startup. | Inspection | Yes
WD-002 | The `Components::Watchdog` component shall oscillate the watchdog GPIO pin (24) on/off on each rategroup tick. | Inspection | Yes
WD-003 | The `Components::Watchdog` component shall provide telemetry for watchdog transition count. | Integration Test | In Progress
WD-004 | The `Components::Watchdog` component shall respond to stop signals to halt the watchdog petting. | Integration Test | Yes
WD-005 | The `Components::Watchdog` component shall provide a test command to stop the watchdog petting. | Integration Test | Yes
WD-006 | The `Components::Watchdog` component shall emit an event when the watchdog petting stops. | Integration Test | Yes
WD-003 | The `Components::Watchdog` component shall provide telemetry for watchdog transition count. | Integration Test | Yes
WD-004 | The `Components::Watchdog` component shall respond to stop signals to halt the watchdog. | Integration Test | Yes
WD-005 | The `Components::Watchdog` component shall provide a test command to stop the watchdog. | Integration Test | Yes
WD-006 | The `Components::Watchdog` component shall emit an event when the watchdog stops. | Integration Test | Yes
WD-007 | The `Components::Watchdog` component shall provide a test command to start the watchdog. | Integration Test | Yes
WD-008 | The `Components::Watchdog` component shall emit an event when the watchdog starts. | Integration Test | Yes

## 3. Design

Expand All @@ -32,20 +34,23 @@ The `Components::Watchdog` component has the following component diagram:
Port Data Type | Name | Direction | Kind | Usage
-------------- | ---- | --------- | ---- | -----
[`Svc::Sched`]| run | Input | Synchronous | Receive periodic calls from rate group
[`Fw::Signal`]| stop | Input | Synchronous | Receive stop signal to stop watchdog petter
[`Fw::Signal`]| start | Input | Synchronous | Receive start signal to start watchdog
[`Fw::Signal`]| stop | Input | Synchronous | Receive stop signal to stop watchdog
[`Drv::GpioWrite`]| gpioSet | Output | n/a | Control GPIO state through driver

#### 3.1.3 Commands

Name | Kind | Description
---- | ---- | -----
TEST_STOP_WATCHDOG | Synchronous | calls the port `stop_runhandler` to stop the watchdog petter.
START_WATCHDOG | Synchronous | calls the port `start_runhandler` to start the watchdog.
STOP_WATCHDOG | Synchronous | calls the port `stop_runhandler` to stop the watchdog.

#### 3.1.4 Events

Name | Description
---- | -----
WatchdogStop | Emits once the watchdog petting has stopped. .
WatchdogStart | Emits once the watchdog has started.
WatchdogStop | Emits once the watchdog has stopped.

#### 3.1.5 Telemetry

Expand Down
7 changes: 0 additions & 7 deletions FprimeZephyrReference/test/int/README.md

This file was deleted.

64 changes: 0 additions & 64 deletions FprimeZephyrReference/test/int/integration_test.py

This file was deleted.

86 changes: 86 additions & 0 deletions FprimeZephyrReference/test/int/watchdog_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""
watchdog_test.py:

Integration tests for the Watchdog component.
"""

import time

import pytest
from fprime_gds.common.data_types.ch_data import ChData
from fprime_gds.common.testing_fw.api import IntegrationTestAPI


@pytest.fixture(autouse=True)
def ensure_watchdog_running(fprime_test_api: IntegrationTestAPI):
"""Fixture to ensure watchdog is started before and after each test"""
start_watchdog(fprime_test_api)
yield
start_watchdog(fprime_test_api)


def start_watchdog(fprime_test_api: IntegrationTestAPI):
"""Helper function to start the watchdog"""
fprime_test_api.send_and_assert_command(
"ReferenceDeployment.watchdog.START_WATCHDOG", max_delay=2
)
fprime_test_api.assert_event(
"ReferenceDeployment.watchdog.WatchdogStart", timeout=2
)


def get_watchdog_transitions(fprime_test_api: IntegrationTestAPI) -> int:
"""Helper function to request packet and get fresh WatchdogTransitions telemetry"""
fprime_test_api.clear_histories()
fprime_test_api.send_and_assert_command(
"CdhCore.tlmSend.SEND_PKT", ["5"], max_delay=2
)
result: ChData = fprime_test_api.assert_telemetry(
"ReferenceDeployment.watchdog.WatchdogTransitions", start="NOW", timeout=3
)
return result.get_val()


def test_01_watchdog_telemetry_basic(fprime_test_api: IntegrationTestAPI):
"""Test that we can read WatchdogTransitions telemetry"""
value = get_watchdog_transitions(fprime_test_api)
assert value >= 0, f"WatchdogTransitions should be >= 0, got {value}"


def test_02_watchdog_increments(fprime_test_api: IntegrationTestAPI):
"""Test that WatchdogTransitions increments over time"""

initial_value = get_watchdog_transitions(fprime_test_api)
time.sleep(2.0) # Wait for watchdog to run more cycles
updated_value = get_watchdog_transitions(fprime_test_api)

assert updated_value > initial_value, (
f"WatchdogTransitions should increase. Initial: {initial_value}, Updated: {updated_value}"
)


def test_03_stop_watchdog_command(fprime_test_api: IntegrationTestAPI):
"""
Test STOP_WATCHDOG command sends and emits WatchdogStop
event and WatchdogTransitions stops incrementing
"""
fprime_test_api.clear_histories()

# Send stop command
fprime_test_api.send_and_assert_command(
"ReferenceDeployment.watchdog.STOP_WATCHDOG", max_delay=2
)

# Check for watchdog stop event
fprime_test_api.assert_event("ReferenceDeployment.watchdog.WatchdogStop", timeout=2)

# Get watchdog transition count
initial_value = get_watchdog_transitions(fprime_test_api)

# Wait and check that it's no longer incrementing
time.sleep(2.0)
final_value = get_watchdog_transitions(fprime_test_api)

assert final_value == initial_value, (
f"Watchdog should remain stopped. Initial: {initial_value}, Final: {final_value}"
)
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ build: submodules zephyr-setup fprime-venv generate-if-needed ## Build FPrime-Ze
@echo "Building..."
@$(UV) run fprime-util build

.PHONY: test-integration
test-integration:
@$(UV) run pytest FprimeZephyrReference/test/int --deployment build-artifacts/zephyr/fprime-zephyr-deployment

.PHONY: clean
clean: ## Remove all gitignored files
git clean -dfX
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,15 @@ Finally, run the fprime-gds.
```shell
make gds
```

## Running Integration Tests

First, start GDS with:
```sh
make gds
```

Then, in another terminal, run the following command to execute the integration tests:
```sh
make test-integration
```