diff --git a/.nav.yml b/.nav.yml index 3664281b627..b960a5b7405 100644 --- a/.nav.yml +++ b/.nav.yml @@ -34,7 +34,7 @@ nav: - APIs: - C++: docs/reference/api/cpp/html/ - CMake: docs/reference/api/cmake/ - - Component SDDs: + - Software Design Documents: - Svc: - "Svc/**/docs/sdd.md" - Fw: @@ -43,6 +43,8 @@ nav: - "Fw/**/docs/sdd.md" - Drv: - "Drv/**/docs/sdd.md" + - Os: + - "Os/**/docs/sdd.md" - Specifications: - FPP Language Spec: 'https://nasa.github.io/fpp/fpp-spec.html' - GDS Plugins: docs/reference/gds-plugins/ diff --git a/Svc/ActiveRateGroup/ActiveRateGroup.fpp b/Svc/ActiveRateGroup/ActiveRateGroup.fpp index 3ee1488e375..2fe8d9fd187 100644 --- a/Svc/ActiveRateGroup/ActiveRateGroup.fpp +++ b/Svc/ActiveRateGroup/ActiveRateGroup.fpp @@ -14,8 +14,9 @@ module Svc { @ Scheduler output port to rate group members output port RateGroupMemberOut: [ActiveRateGroupOutputPorts] Sched - @ Ping input port for health - async input port PingIn: Ping + @ Ping input port for health. Droppable: queue-full during overload must + @ not FATAL; a missed ping surfaces as a late-ping health warning instead. + async input port PingIn: Ping drop @ Ping output port for health output port PingOut: Ping diff --git a/Svc/Ccsds/SpacePacketFramer/SpacePacketFramer.cpp b/Svc/Ccsds/SpacePacketFramer/SpacePacketFramer.cpp index cd40e5de469..f4051d00017 100644 --- a/Svc/Ccsds/SpacePacketFramer/SpacePacketFramer.cpp +++ b/Svc/Ccsds/SpacePacketFramer/SpacePacketFramer.cpp @@ -36,6 +36,21 @@ void SpacePacketFramer ::dataIn_handler(FwIndexType portNum, Fw::Buffer& data, c // Allocate frame buffer Fw::Buffer frameBuffer = this->bufferAllocate_out(0, static_cast(frameSize)); + if ((not frameBuffer.isValid()) || (frameBuffer.getSize() < frameSize)) { + // Buffer pool exhausted: drop this frame instead of asserting. Return the + // original data upstream and emit a substitute com status so the com queue + // handshake keeps flowing (the dropped frame will never produce one). + this->log_WARNING_HI_FrameDropped(static_cast(frameSize)); + if (frameBuffer.isValid()) { + this->bufferDeallocate_out(0, frameBuffer); + } + this->dataReturnOut_out(0, data, context); + if (this->isConnected_comStatusOut_OutputPort(0)) { + Fw::Success status = Fw::Success::SUCCESS; + this->comStatusOut_out(0, status); + } + return; + } auto frameSerializer = frameBuffer.getSerializer(); // ----------------------------------------------- diff --git a/Svc/Ccsds/SpacePacketFramer/SpacePacketFramer.fpp b/Svc/Ccsds/SpacePacketFramer/SpacePacketFramer.fpp index 39ca9a2caff..62c8ce1af41 100644 --- a/Svc/Ccsds/SpacePacketFramer/SpacePacketFramer.fpp +++ b/Svc/Ccsds/SpacePacketFramer/SpacePacketFramer.fpp @@ -14,6 +14,13 @@ module Ccsds { @ Port to retrieve the current sequence count for a given APID output port getApidSeqCount: Ccsds.ApidSequenceCount + @ Frame dropped because no buffer of sufficient size was available + event FrameDropped( + requestedSize: U32 @< Size of the frame buffer that could not be allocated + ) severity warning high \ + format "Dropped frame: could not allocate {} byte frame buffer" \ + throttle 10 + ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/Svc/CmdSequencer/CmdSequencer.fpp b/Svc/CmdSequencer/CmdSequencer.fpp index f1c4012784f..9434b6c422d 100644 --- a/Svc/CmdSequencer/CmdSequencer.fpp +++ b/Svc/CmdSequencer/CmdSequencer.fpp @@ -67,8 +67,9 @@ module Svc { @ Command response in port async input port cmdResponseIn: Fw.CmdResponse - @ Ping in port - async input port pingIn: Svc.Ping + @ Ping in port. Droppable: queue-full during overload must not FATAL; + @ a missed ping surfaces as a late-ping health warning instead. + async input port pingIn: Svc.Ping drop @ Ping out port output port pingOut: Svc.Ping @@ -85,8 +86,10 @@ module Svc { @ Port for sending sequence commands output port comCmdOut: Fw.Com - @ Schedule in port - async input port schedIn: Svc.Sched + @ Schedule in port. Ticks are droppable: a full queue during transient + @ overload must not FW_ASSERT (FATAL) the deployment; the next tick + @ resumes timer/timeout bookkeeping. + async input port schedIn: Svc.Sched drop @ Notifies that a sequence has started running output port seqStartOut: Svc.CmdSeqIn diff --git a/Svc/FileWorker/CMakeLists.txt b/Svc/FileWorker/CMakeLists.txt index 787321c1cae..f4d1af8951b 100644 --- a/Svc/FileWorker/CMakeLists.txt +++ b/Svc/FileWorker/CMakeLists.txt @@ -10,7 +10,6 @@ # #### -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/test/FileTester") register_fprime_module( AUTOCODER_INPUTS @@ -37,18 +36,31 @@ register_fprime_ut( "${CMAKE_CURRENT_LIST_DIR}" ) -register_fprime_ut( - FileWorkerTestError - AUTOCODER_INPUTS - "${CMAKE_CURRENT_LIST_DIR}/FileWorker.fpp" - SOURCES - "${CMAKE_CURRENT_LIST_DIR}/test/ut/FileWorkerErrTestMain.cpp" - "${CMAKE_CURRENT_LIST_DIR}/test/ut/FileWorkerErrTester.cpp" - CHOOSES_IMPLEMENTATIONS - Svc_FileWorker_test_FileTester - DEPENDS - STest - UT_AUTO_HELPERS - WORKING_DIRECTORY - "${CMAKE_CURRENT_LIST_DIR}" -) +# FileTester is a test dependency and only supported on Posix platforms, therefore: +# - only attempt to add the FileTester module in BUILD_TESTING +# - only add the FileWorkerTestError test if the FileTester module was successfully added +if (BUILD_TESTING AND NOT __FPRIME_NO_UT_GEN__) + add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/test/FileTester") + + # Target will not exist on non-Posix platforms, so guard against its existence + if (TARGET Svc_FileWorker_test_FileTester) + register_fprime_ut( + FileWorkerTestError + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/FileWorker.fpp" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/test/ut/FileWorkerErrTestMain.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test/ut/FileWorkerErrTester.cpp" + CHOOSES_IMPLEMENTATIONS + Svc_FileWorker_test_FileTester + DEPENDS + STest + UT_AUTO_HELPERS + WORKING_DIRECTORY + "${CMAKE_CURRENT_LIST_DIR}" + ) + else() + # Only print message if we're in BUILD_TESTING *and* FileTester isn't available + message(STATUS "Svc/FileWorker: FileTester test dependency is only supported on Posix, skipping FileWorkerTestError") + endif() +endif() diff --git a/Svc/FileWorker/FileWorker.hpp b/Svc/FileWorker/FileWorker.hpp index 4858df02a32..8c8bbfa6e65 100644 --- a/Svc/FileWorker/FileWorker.hpp +++ b/Svc/FileWorker/FileWorker.hpp @@ -68,7 +68,7 @@ class FileWorker : public FileWorkerComponentBase { void writeIn_handler(FwIndexType portNum, //!< The port number const Fw::StringBase& path, Fw::Buffer& buffer, - U64 offsetBytes, + FwSizeType offsetBytes, bool append) override; // ---------------------------------------------------------------------- diff --git a/Svc/FileWorker/test/FileTester/CMakeLists.txt b/Svc/FileWorker/test/FileTester/CMakeLists.txt index fedbbffbdba..ec07bb1a17a 100644 --- a/Svc/FileWorker/test/FileTester/CMakeLists.txt +++ b/Svc/FileWorker/test/FileTester/CMakeLists.txt @@ -1,3 +1,5 @@ +restrict_platforms(Posix) + register_fprime_implementation( Svc_FileWorker_test_FileTester IMPLEMENTS diff --git a/Svc/TlmPacketizer/TlmPacketizer.fpp b/Svc/TlmPacketizer/TlmPacketizer.fpp index ac433d7cd7e..1655c3e2eb7 100644 --- a/Svc/TlmPacketizer/TlmPacketizer.fpp +++ b/Svc/TlmPacketizer/TlmPacketizer.fpp @@ -14,7 +14,7 @@ module Svc { } array GroupConfigs = [NUM_CONFIGURABLE_TLMPACKETIZER_GROUPS] GroupConfig - array SectionConfigs = [TelemetrySection.NUM_SECTIONS] GroupConfigs + array SectionConfigs = [TelemetrySection.NUM_SECTIONS] GroupConfigs default TELEMETRY_SECTION_DEFAULTS array SectionEnabled = [TelemetrySection.NUM_SECTIONS] Fw.Enabled default TELEMETRY_SECTION_ENABLED_DEFAULTS # ---------------------------------------------------------------------- diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000000..1cec8423e17 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,2 @@ +docs-venv +mkdocs.local.yml diff --git a/docs/local-website-build.sh b/docs/local-website-build.sh new file mode 100644 index 00000000000..2a5bc608e41 --- /dev/null +++ b/docs/local-website-build.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +######################################################################## +# README: +# +# This script is a convenience tool for building and serving the docs part +# of the F´ website locally. It will NOT look like the actual F´ website +# since themes and other content is no included in the core F´ repository +# +# DISCLAIMER: This script is experimental and has been authored by AI, +# then reviewed and edited by a human +# +# How-To Run: +# 0. Side effects: this script will create a Python virtual environment at `docs/docs-venv` +# and an output directory at `../fprime-docs-site-local` relative to the fprime/ root. +# 1. Change working directory to the parent of the root of the fprime repository +# e.g. `cd path/to/fprime && cd ..` +# 2. Run this script: `./fprime/docs/local-website-build.sh` +# +######################################################################## + +set -euo pipefail + +# Colors +GREEN='\033[0;32m' +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +# This script is intended to work from an fprime/ checkout alone. +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +VENV_DIR="$SCRIPT_DIR/docs-venv" +# mkdocs.yml sets docs_dir to the fprime/ root, so site_dir must be outside it. +SITE_DIR="$REPO_ROOT/../fprime-docs-site-local" +PORT=8000 + +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}F Prime Nested Docs Local Build${NC}" +echo -e "${BLUE}========================================${NC}" +echo "" + +if ! command -v python3 >/dev/null 2>&1; then + echo -e "${RED}Error: python3 is required but was not found.${NC}" + exit 1 +fi + +if [ ! -d "$VENV_DIR" ]; then + echo -e "${GREEN}Creating isolated virtual environment at docs/docs-venv...${NC}" + python3 -m venv "$VENV_DIR" +else + echo -e "${GREEN}Using existing virtual environment at docs/docs-venv...${NC}" +fi + +# shellcheck disable=SC1091 +source "$VENV_DIR/bin/activate" + +echo -e "${GREEN}Installing/updating Python dependencies...${NC}" +python -m pip install --upgrade pip +python -m pip install -Ur "$REPO_ROOT/requirements.txt" +python -m pip install \ + mkdocs \ + mkdocs-material \ + mkdocs-awesome-nav \ + mike \ + mkdocs-open-in-new-tab \ + mkdocs-multirepo-plugin \ + pymdown-extensions \ + markdown-callouts \ + pygments==2.18.0 + +echo -e "${GREEN}Building nested docs website only...${NC}" +rm -rf "$SITE_DIR" + +# Temporarily disable custom_dir since overrides/ doesn't exist in standalone fprime/ checkout +sed 's/custom_dir:/#custom_dir:/' "$SCRIPT_DIR/mkdocs.yml" > "$SCRIPT_DIR/mkdocs.local.yml" + +mkdocs build --clean --config-file "$SCRIPT_DIR/mkdocs.local.yml" --site-dir "$SITE_DIR" + +if [ $? -ne 0 ]; then + echo -e "${RED}Error: Documentation build failed${NC}" + exit 1 +fi + +if [ ! -d "$SITE_DIR" ] || [ -z "$(ls -A "$SITE_DIR")" ]; then + echo -e "${RED}Error: build output directory is empty: $SITE_DIR${NC}" + exit 1 +fi + +if lsof -Pi :$PORT -sTCP:LISTEN -t >/dev/null 2>&1; then + PORT=8001 +fi + +echo "" +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN}Nested docs build successful!${NC}" +echo -e "${GREEN}========================================${NC}" +echo -e "${BLUE}Site directory:${NC} $SITE_DIR" +echo -e "${BLUE}Serving at:${NC} http://localhost:$PORT" +echo "" +echo -e "${BLUE}Press Ctrl+C to stop the server${NC}" +echo "" + +cd "$SITE_DIR" +python -m webbrowser "http://localhost:$PORT/docs" +python -m http.server "$PORT" \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 6bfd7e24a1c..cb2627e2c10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,8 +20,8 @@ Flask-RESTful==0.3.10 fprime-fpl-layout==1.0.4 fprime-fpl-write-pic==1.0.4 fprime-fpp==3.2.0 -fprime-gds==4.2.0 -fprime-tools==4.2.0 +fprime-gds==4.2.1 +fprime-tools==4.2.1 fprime-visual==1.0.2 gcovr==8.2 idna==3.10