diff --git a/FprimeZephyrReference/Components/CMakeLists.txt b/FprimeZephyrReference/Components/CMakeLists.txt index 26405d0..302ed0f 100644 --- a/FprimeZephyrReference/Components/CMakeLists.txt +++ b/FprimeZephyrReference/Components/CMakeLists.txt @@ -10,3 +10,4 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Burnwire/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/BootloaderTrigger/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/AntennaDeployer/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FsSpace/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/StartupManager/") diff --git a/FprimeZephyrReference/Components/StartupManager/CMakeLists.txt b/FprimeZephyrReference/Components/StartupManager/CMakeLists.txt new file mode 100644 index 0000000..362c49b --- /dev/null +++ b/FprimeZephyrReference/Components/StartupManager/CMakeLists.txt @@ -0,0 +1,36 @@ +#### +# F Prime CMakeLists.txt: +# +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/ +# +#### + +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. + +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/StartupManager.fpp" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/StartupManager.cpp" +# DEPENDS +# MyPackage_MyOtherModule +) + +### Unit Tests ### +# register_fprime_ut( +# AUTOCODER_INPUTS +# "${CMAKE_CURRENT_LIST_DIR}/StartupManager.fpp" +# SOURCES +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/StartupManagerTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/StartupManagerTester.cpp" +# DEPENDS +# STest # For rules-based testing +# UT_AUTO_HELPERS +# ) diff --git a/FprimeZephyrReference/Components/StartupManager/StartupManager.cpp b/FprimeZephyrReference/Components/StartupManager/StartupManager.cpp new file mode 100644 index 0000000..b4c480f --- /dev/null +++ b/FprimeZephyrReference/Components/StartupManager/StartupManager.cpp @@ -0,0 +1,200 @@ +// ====================================================================== +// \title StartupManager.cpp +// \author starchmd +// \brief cpp file for StartupManager component implementation class +// ====================================================================== + +#include "FprimeZephyrReference/Components/StartupManager/StartupManager.hpp" +#include "Os/File.hpp" + +namespace Components { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +StartupManager ::StartupManager(const char* const compName) : StartupManagerComponentBase(compName) {} + +StartupManager ::~StartupManager() {} + +// ---------------------------------------------------------------------- +// Handler implementations for typed input ports +// ---------------------------------------------------------------------- + +//! \brief Template function to read a type T from a file at file_path +//! +//! This will read a type T with size 'size' from the file located at file_path. It will return SUCCESS if +//! the read and deserialization were successful, and FAILURE otherwise. +//! +//! The file will be opened and closed within this function. value will not be modified by this function unless +//! the read operation is successful. +//! +//! \warning this function is only safe to use for types T with size `size` that fit well in stack memory. +//! +//! \param file_path: path to the file to read from +//! \param value: reference to the variable to read into +//! \return Status of the read operation +template +StartupManager::Status read(const Fw::StringBase& file_path, T& value) { + // Create the necessary file and deserializer objects for reading a type from a file + StartupManager::Status return_status = StartupManager::FAILURE; + Os::File file; + U8 data_buffer[BUFFER_SIZE]; + Fw::ExternalSerializeBuffer deserializer(data_buffer, sizeof(data_buffer)); + + // Open the file for reading, and continue only if successful + Os::File::Status status = file.open(file_path.toChar(), Os::File::OPEN_READ); + if (status == Os::File::OP_OK) { + FwSizeType size = sizeof(data_buffer); + status = file.read(data_buffer, size); + if (status == Os::File::OP_OK && size == sizeof(data_buffer)) { + // When the read is successful, and the size is correct then the buffer must absolutely contain the + // serialized data and thus it is safe to assert on the deserialization status + deserializer.setBuffLen(size); + Fw::SerializeStatus serialize_status = deserializer.deserializeTo(value); + FW_ASSERT(serialize_status == Fw::SerializeStatus::FW_SERIALIZE_OK, + static_cast(serialize_status)); + return_status = StartupManager::SUCCESS; + } + } + (void)file.close(); + return return_status; +} + +//! \brief Template function to write a type T to a file at file_path +//! +//! This will write a type T with size 'size' to the file located at file_path. It will return SUCCESS if +//! the serialization and write were successful, and FAILURE otherwise. +//! +//! The file will be opened and closed within this function. +//! +//! \warning this function is only safe to use for types T with size `size` that fit well in stack memory. +//! +//! \param file_path: path to the file to write to +//! \param value: reference to the variable to write +//! \return Status of the write operation +template +StartupManager::Status write(const Fw::StringBase& file_path, const T& value) { + // Create the necessary file and deserializer objects for reading a type from a file + StartupManager::Status return_status = StartupManager::FAILURE; + Os::File file; + U8 data_buffer[BUFFER_SIZE]; + + // Serialize the value into the data buffer. Since the buffer is created here it is safe to assert on the + // serialization status. + Fw::ExternalSerializeBuffer serializer(data_buffer, sizeof(data_buffer)); + Fw::SerializeStatus serialize_status = serializer.serializeFrom(value); + FW_ASSERT(serialize_status == Fw::SerializeStatus::FW_SERIALIZE_OK, static_cast(serialize_status)); + + // Open the file for writing, and continue only if successful + Os::File::Status status = file.open(file_path.toChar(), Os::File::OPEN_CREATE, Os::File::OVERWRITE); + if (status == Os::File::OP_OK) { + FwSizeType size = sizeof(data_buffer); + status = file.write(data_buffer, size); + if (status == Os::File::OP_OK && size == sizeof(data_buffer)) { + return_status = StartupManager::SUCCESS; + } + } + (void)file.close(); + return return_status; +} + +FwSizeType StartupManager ::update_boot_count() { + // Read the boot count file path from parameter and assert that it is either valid or the default value + FwSizeType boot_count = 0; + Fw::ParamValid is_valid; + auto boot_count_file = this->paramGet_BOOT_COUNT_FILE(is_valid); + FW_ASSERT(is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT); + + // Open the boot count file and add one to the current boot count ensuring a minimum of 1 in the case + // of read failure. Since read will retain the `0` initial value on read failure, we can ignore the error + // status returned by the read. + (void)read(boot_count_file, boot_count); + boot_count = FW_MAX(1, boot_count + 1); + // Rewrite the updated boot count back to the file, and on failure emit a warning about the inability to + // persist the boot count. + StartupManager::Status status = write(boot_count_file, boot_count); + if (status != StartupManager::SUCCESS) { + this->log_WARNING_LO_BootCountUpdateFailure(); + } + return boot_count; +} + +Fw::Time StartupManager ::update_quiescence_start() { + Fw::ParamValid is_valid; + auto time_file = this->paramGet_QUIESCENCE_START_FILE(is_valid); + FW_ASSERT(is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT); + + Fw::Time time = this->getTime(); + // Open the quiescence start time file and read the current time. On read failure, return the current time. + StartupManager::Status status = read(time_file, time); + // On read failure, write the current time to the file for future reads. This only happens on read failure because + // there is a singular quiescence start time for the whole mission. + if (status != StartupManager::SUCCESS) { + status = write(time_file, time); + if (status != StartupManager::SUCCESS) { + this->log_WARNING_LO_QuiescenceFileInitFailure(); + } + } + return time; +} + +void StartupManager ::completeSequence_handler(FwIndexType portNum, + FwOpcodeType opCode, + U32 cmdSeq, + const Fw::CmdResponse& response) { + // Respond to the completion status of the start-up sequence + if (response == Fw::CmdResponse::OK) { + this->log_ACTIVITY_LO_StartupSequenceFinished(); + } else { + this->log_WARNING_LO_StartupSequenceFailed(response); + } +} + +void StartupManager ::run_handler(FwIndexType portNum, U32 context) { + Fw::ParamValid is_valid; + + // On the first call, update the boot count, set the quiescence start time, and dispatch the start-up sequence + if (this->m_boot_count == 0) { + this->m_boot_count = this->update_boot_count(); + this->m_quiescence_start = this->update_quiescence_start(); + + Fw::ParamString first_sequence = this->paramGet_STARTUP_SEQUENCE_FILE(is_valid); + FW_ASSERT(is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT); + this->runSequence_out(0, first_sequence); + } + + // Calculate the quiescence end time based on the quiescence period parameter + Fw::TimeIntervalValue quiescence_period = this->paramGet_QUIESCENCE_TIME(is_valid); + Fw::Time quiescence_interval(quiescence_period.get_seconds(), quiescence_period.get_useconds()); + FW_ASSERT(is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT); + Fw::Time end_time = Fw::Time::add(this->m_quiescence_start, quiescence_interval); + + // Are we waiting for quiescence? + if (this->m_waiting) { + // Check if the system is armed or if this is not the first boot. In both cases, we skip waiting. + bool armed = this->paramGet_ARMED(is_valid); + FW_ASSERT(is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT); + + // If not armed or this is not the first boot, we skip waiting + if (!armed || end_time <= this->getTime()) { + this->m_waiting = false; + this->cmdResponse_out(this->m_stored_opcode, this->m_stored_sequence, Fw::CmdResponse::OK); + } + } + this->tlmWrite_QuiescenceEndTime( + Fw::TimeValue(end_time.getTimeBase(), end_time.getContext(), end_time.getSeconds(), end_time.getUSeconds())); + this->tlmWrite_BootCount(this->m_boot_count); +} + +// ---------------------------------------------------------------------- +// Handler implementations for commands +// ---------------------------------------------------------------------- + +void StartupManager ::WAIT_FOR_QUIESCENCE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { + this->m_stored_opcode = opCode; + this->m_stored_sequence = cmdSeq; + this->m_waiting = true; +} + +} // namespace Components diff --git a/FprimeZephyrReference/Components/StartupManager/StartupManager.fpp b/FprimeZephyrReference/Components/StartupManager/StartupManager.fpp new file mode 100644 index 0000000..71c717b --- /dev/null +++ b/FprimeZephyrReference/Components/StartupManager/StartupManager.fpp @@ -0,0 +1,84 @@ +module Components { + @ Manages the start-up sequencing + passive component StartupManager { + @ Check RTC time diff + sync input port run: Svc.Sched + + @ Port for sending sequence dispatches + output port runSequence: Svc.CmdSeqIn + + @ Port for receiving the status of the start-up sequence + sync input port completeSequence: Fw.CmdResponse + + @ Command to wait for system quiescence before proceeding with start-up + sync command WAIT_FOR_QUIESCENCE() + + @ Telemetry for boot count + telemetry BootCount: FwSizeType update on change + + @ Telemetry for quiescence end time + telemetry QuiescenceEndTime: Fw.TimeValue update on change + + @ Event emitted when failing to update the boot count file + event BootCountUpdateFailure() severity warning low \ + format "Failed to update boot count file" + + @ Event emitted when the quiescence file was not updated + event QuiescenceFileInitFailure() severity warning low \ + format "Failed to initialize quiescence start time file" + + @ Event emitted when the start-up sequence succeeds + event StartupSequenceFinished() severity activity low \ + format "Start-up sequence finished successfully" + + @ Event emitted when the start-up sequence fails + event StartupSequenceFailed(response: Fw.CmdResponse @< Response code + ) severity warning low format "Start-up sequence failed with response code {}" + + @ Whether the start-up manager is armed to wait for quiescence + param ARMED: bool default true + + @ Time to wait before allowing start-up to proceed + param QUIESCENCE_TIME: Fw.TimeIntervalValue default {seconds = 45 * 60, useconds = 0} + + @ File storing the quiescence start time + param QUIESCENCE_START_FILE: string default "/quiescence_start.bin" + + @ Path to the start-up sequence file + param STARTUP_SEQUENCE_FILE: string default "/startup.bin" + + @ File to store the boot count + param BOOT_COUNT_FILE: string default "/boot_count.bin" + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port to return the value of a parameter + param get port prmGetOut + + @Port to set the value of a parameter + param set port prmSetOut + + @ Port for sending command registrations + command reg port cmdRegOut + + @ Port for receiving commands + command recv port cmdIn + + @ Port for sending command responses + command resp port cmdResponseOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + } +} diff --git a/FprimeZephyrReference/Components/StartupManager/StartupManager.hpp b/FprimeZephyrReference/Components/StartupManager/StartupManager.hpp new file mode 100644 index 0000000..b0f91d7 --- /dev/null +++ b/FprimeZephyrReference/Components/StartupManager/StartupManager.hpp @@ -0,0 +1,93 @@ +// ====================================================================== +// \title StartupManager.hpp +// \author starchmd +// \brief hpp file for StartupManager component implementation class +// ====================================================================== + +#ifndef Components_StartupManager_HPP +#define Components_StartupManager_HPP + +#include +#include "FprimeZephyrReference/Components/StartupManager/StartupManagerComponentAc.hpp" + +namespace Components { + +class StartupManager final : public StartupManagerComponentBase { + public: + enum Status { + SUCCESS, + FAILURE, + }; + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct StartupManager object + StartupManager(const char* const compName //!< The component name + ); + + //! Destroy StartupManager object + ~StartupManager(); + + //! \brief read and increment the boot count + //! + //! Reads the boot count from the boot count file, increments it, and writes it back to the file. If the read + //! fails, the boot count will be initialized to 1. If the write fails, a warning will be emitted. + //! + //! \warning this function will modify the boot count file on disk. + //! + //! \return The updated boot count + FwSizeType update_boot_count(); + + //! \brief get and possibly initialize the quiescence start time + //! + //! Reads the quiescence start time from the quiescence start time file. If the read fails, the current time is + //! written to the file and returned. + //! + //! \warning this function will modify the quiescence start time file on disk if it does not already exist. + //! + //! \return The quiescence start time + Fw::Time update_quiescence_start(); + + private: + // ---------------------------------------------------------------------- + // Handler implementations for typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for completeSequence + void completeSequence_handler(FwIndexType portNum, //!< The port number + FwOpcodeType opCode, //!< Command Op Code + U32 cmdSeq, //!< Command Sequence + const Fw::CmdResponse& response //!< The command response argument + ) override; + + //! Handler implementation for run + //! + //! Check RTC time diff + void run_handler(FwIndexType portNum, //!< The port number + U32 context //!< The call order + ) override; + + private: + // ---------------------------------------------------------------------- + // Handler implementations for commands + // ---------------------------------------------------------------------- + + //! Handler implementation for command WAIT_FOR_QUIESCENCE + //! + //! Command to wait for system quiescence before proceeding with start-up + void WAIT_FOR_QUIESCENCE_cmdHandler(FwOpcodeType opCode, //!< The opcode + U32 cmdSeq //!< The command sequence number + ) override; + + private: + Fw::Time m_quiescence_start; //!< Time of the start of the quiescence wait + FwOpcodeType m_stored_opcode; //!< Stored opcode for delayed response + FwSizeType m_boot_count; //!< Current boot count + U32 m_stored_sequence; //!< Stored sequence number for delayed response + std::atomic m_waiting; //!< Indicates if waiting for quiescence +}; + +} // namespace Components + +#endif diff --git a/FprimeZephyrReference/Components/StartupManager/docs/sdd.md b/FprimeZephyrReference/Components/StartupManager/docs/sdd.md new file mode 100644 index 0000000..2b0b194 --- /dev/null +++ b/FprimeZephyrReference/Components/StartupManager/docs/sdd.md @@ -0,0 +1,66 @@ +# Components::StartupManager + +Manages the start-up sequencing + +## Usage Examples +Add usage examples here + +### Diagrams +Add diagrams here + +### Typical Usage +And the typical usage of the component here + +## Class Diagram +Add a class diagram here + +## Port Descriptions +| Name | Description | +|---|---| +|---|---| + +## Component States +Add component states in the chart below +| Name | Description | +|---|---| +|---|---| + +## Sequence Diagrams +Add sequence diagrams here + +## Parameters +| Name | Description | +|---|---| +|---|---| + +## Commands +| Name | Description | +|---|---| +|---|---| + +## Events +| Name | Description | +|---|---| +|---|---| + +## Telemetry +| Name | Description | +|---|---| +|---|---| + +## Unit Tests +Add unit test descriptions in the chart below +| Name | Description | Output | Coverage | +|---|---|---|---| +|---|---|---|---| + +## Requirements +Add requirements in the chart below +| Name | Description | Validation | +|---|---|---| +|---|---|---| + +## Change Log +| Date | Description | +|---|---| +|---| Initial Draft | diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi index 43f0bbf..b230eef 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi @@ -9,6 +9,8 @@ telemetry packets ReferenceDeploymentPackets { ComCcsdsUart.commsBufferManager.HiBuffs ReferenceDeployment.rateGroup10Hz.RgMaxTime ReferenceDeployment.rateGroup1Hz.RgMaxTime + ReferenceDeployment.startupManager.BootCount + ReferenceDeployment.startupManager.QuiescenceEndTime } packet HealthWarnings id 2 group 1 { @@ -83,4 +85,17 @@ telemetry packets ReferenceDeploymentPackets { CdhCore.version.CustomVersion08 CdhCore.version.CustomVersion09 CdhCore.version.CustomVersion10 + ReferenceDeployment.cmdSeq.CS_LoadCommands + ReferenceDeployment.cmdSeq.CS_CancelCommands + ReferenceDeployment.cmdSeq.CS_CommandsExecuted + ReferenceDeployment.cmdSeq.CS_SequencesCompleted + ReferenceDeployment.cmdSeq.CS_Errors + FileHandling.fileUplink.FilesReceived + FileHandling.fileUplink.PacketsReceived + FileHandling.fileDownlink.FilesSent + FileHandling.fileDownlink.PacketsSent + FileHandling.fileManager.CommandsExecuted + FileHandling.fileManager.Errors + FileHandling.fileUplink.Warnings + FileHandling.fileDownlink.Warnings } diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp index ccef907..3c8f6bc 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp @@ -50,7 +50,7 @@ U32 rateGroup1HzContext[Svc::ActiveRateGroup::CONNECTION_COUNT_MAX] = {getRateGr * desired, but is extracted here for clarity. */ void configureTopology() { - prmDb.configure("/prmDb.dat"); + FileHandling::prmDb.configure("/prmDb.dat"); // Rate group driver needs a divisor list rateGroupDriver.configure(rateGroupDivisorsSet); // Rate groups require context arrays. @@ -60,6 +60,8 @@ void configureTopology() { gpioDriver.open(ledGpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); gpioBurnwire0.open(burnwire0Gpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); gpioBurnwire1.open(burnwire1Gpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); + + cmdSeq.allocateBuffer(0, mallocator, 5 * 1024); } // Public functions for use in main program are namespaced with deployment name ReferenceDeployment @@ -78,7 +80,6 @@ void setupTopology(const TopologyState& state) { // Project-specific component configuration. Function provided above. May be inlined, if desired. configureTopology(); // Autocoded parameter loading. Function provided by autocoder. - prmDb.readParamFile(); loadParameters(); // Autocoded task kick-off (active components). Function provided by autocoder. startTasks(state); @@ -106,5 +107,6 @@ void teardownTopology(const TopologyState& state) { stopTasks(state); freeThreads(state); tearDownComponents(state); + cmdSeq.deallocateBuffer(mallocator); } }; // namespace ReferenceDeployment diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp index 81064f6..37abd26 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp @@ -15,6 +15,7 @@ // SubtopologyTopologyDefs includes #include "Svc/Subtopologies/CdhCore/SubtopologyTopologyDefs.hpp" #include "Svc/Subtopologies/ComCcsds/SubtopologyTopologyDefs.hpp" +#include "Svc/Subtopologies/FileHandling/SubtopologyTopologyDefs.hpp" // ComCcsds Enum Includes #include "Svc/Subtopologies/ComCcsds/Ports_ComBufferQueueEnumAc.hpp" @@ -53,7 +54,7 @@ enum { WARN = 3, FATAL = 5 }; namespace ReferenceDeployment_rateGroup1Hz { enum { WARN = 3, FATAL = 5 }; } -namespace ReferenceDeployment_prmDb { +namespace ReferenceDeployment_cmdSeq { enum { WARN = 3, FATAL = 5 }; } } // namespace PingEntries @@ -69,11 +70,12 @@ namespace ReferenceDeployment { * autocoder. The contents are entirely up to the definition of the project. This deployment uses subtopologies. */ struct TopologyState { - const device* uartDevice; //!< UART device path for communication - const device* loraDevice; //!< LoRa device path for communication - U32 baudRate; //!< Baud rate for UART communication - CdhCore::SubtopologyState cdhCore; //!< Subtopology state for CdhCore - ComCcsds::SubtopologyState comCcsds; //!< Subtopology state for ComCcsds + const device* uartDevice; //!< UART device path for communication + const device* loraDevice; //!< LoRa device path for communication + U32 baudRate; //!< Baud rate for UART communication + CdhCore::SubtopologyState cdhCore; //!< Subtopology state for CdhCore + ComCcsds::SubtopologyState comCcsds; //!< Subtopology state for ComCcsds + FileHandling::SubtopologyState fileHandling; //!< Subtopology state for FileHandling }; namespace PingEntries = ::PingEntries; diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp index 26eebbf..be24c70 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp @@ -30,17 +30,17 @@ module ReferenceDeployment { instance rateGroup10Hz: Svc.ActiveRateGroup base id 0x10001000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ - priority 3 + priority 2 instance rateGroup1Hz: Svc.ActiveRateGroup base id 0x10002000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ - priority 4 + priority 3 - instance prmDb: Svc.PrmDb base id 0x10003000 \ + instance cmdSeq: Svc.CmdSequencer base id 0x10006000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ - priority 5 + priority 14 # ---------------------------------------------------------------------- # Queued component instances @@ -89,4 +89,6 @@ module ReferenceDeployment { instance antennaDeployer: Components.AntennaDeployer base id 0x10029000 instance fsSpace: Components.FsSpace base id 0x10030000 + + instance startupManager: Components.StartupManager base id 0x10031000 } diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index ec3bcfb..5aa7e31 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -17,6 +17,7 @@ module ReferenceDeployment { import CdhCore.Subtopology import ComCcsds.FramingSubtopology import ComCcsdsUart.Subtopology + import FileHandling.Subtopology # ---------------------------------------------------------------------- # Instances used in the topology @@ -30,7 +31,6 @@ module ReferenceDeployment { instance gpioBurnwire0 instance gpioBurnwire1 instance watchdog - instance prmDb instance rtcManager instance imuManager instance lis2mdlManager @@ -44,6 +44,8 @@ module ReferenceDeployment { # For UART sideband communication instance comDriver instance fsSpace + instance cmdSeq + instance startupManager # ---------------------------------------------------------------------- @@ -56,7 +58,7 @@ module ReferenceDeployment { health connections instance CdhCore.$health time connections instance rtcManager telemetry connections instance CdhCore.tlmSend - param connections instance prmDb + param connections instance FileHandling.prmDb # ---------------------------------------------------------------------- # Telemetry packets (only used when TlmPacketizer is used) @@ -84,6 +86,9 @@ module ReferenceDeployment { ComCcsdsUart.fprimeRouter.commandOut -> CdhCore.cmdDisp.seqCmdBuff CdhCore.cmdDisp.seqCmdStatus -> ComCcsdsUart.fprimeRouter.cmdResponseIn + + cmdSeq.comCmdOut -> CdhCore.cmdDisp.seqCmdBuff + CdhCore.cmdDisp.seqCmdStatus -> cmdSeq.cmdResponseIn } connections CommunicationsRadio { @@ -99,6 +104,9 @@ module ReferenceDeployment { lora.dataReturnOut -> ComCcsds.framer.dataReturnIn lora.comStatusOut -> comDelay.comStatusIn comDelay.comStatusOut ->ComCcsds.framer.comStatusIn + + startupManager.runSequence -> cmdSeq.seqRunIn + cmdSeq.seqDone -> startupManager.completeSequence } connections CommunicationsUart { @@ -124,6 +132,8 @@ module ReferenceDeployment { rateGroup10Hz.RateGroupMemberOut[0] -> comDriver.schedIn rateGroup10Hz.RateGroupMemberOut[1] -> ComCcsdsUart.aggregator.timeout rateGroup10Hz.RateGroupMemberOut[2] -> ComCcsds.aggregator.timeout + rateGroup10Hz.RateGroupMemberOut[3] -> FileHandling.fileManager.schedIn + rateGroup10Hz.RateGroupMemberOut[4] -> cmdSeq.schedIn # Slow rate (1Hz) rate group rateGroupDriver.CycleOut[Ports_RateGroups.rateGroup1Hz] -> rateGroup1Hz.CycleIn @@ -137,6 +147,8 @@ module ReferenceDeployment { rateGroup1Hz.RateGroupMemberOut[7] -> burnwire.schedIn rateGroup1Hz.RateGroupMemberOut[8] -> antennaDeployer.schedIn rateGroup1Hz.RateGroupMemberOut[9] -> fsSpace.run + rateGroup1Hz.RateGroupMemberOut[10] -> FileHandling.fileDownlink.Run + rateGroup1Hz.RateGroupMemberOut[11] -> startupManager.run } @@ -161,5 +173,17 @@ module ReferenceDeployment { imuManager.magneticFieldGet -> lis2mdlManager.magneticFieldGet imuManager.temperatureGet -> lsm6dsoManager.temperatureGet } + + connections ComCcsds_FileHandling { + # File Downlink <-> ComQueue + FileHandling.fileDownlink.bufferSendOut -> ComCcsdsUart.comQueue.bufferQueueIn[ComCcsds.Ports_ComBufferQueue.FILE] + ComCcsdsUart.comQueue.bufferReturnOut[ComCcsds.Ports_ComBufferQueue.FILE] -> FileHandling.fileDownlink.bufferReturn + + # Router <-> FileUplink + ComCcsdsUart.fprimeRouter.fileOut -> FileHandling.fileUplink.bufferSendIn + FileHandling.fileUplink.bufferSendOut -> ComCcsdsUart.fprimeRouter.fileBufferReturnIn + } + + } } diff --git a/FprimeZephyrReference/project/config/AcConstants.fpp b/FprimeZephyrReference/project/config/AcConstants.fpp new file mode 100644 index 0000000..8eeefb4 --- /dev/null +++ b/FprimeZephyrReference/project/config/AcConstants.fpp @@ -0,0 +1,70 @@ +# ====================================================================== +# AcConstants.fpp +# F Prime configuration constants +# ====================================================================== + +@ Number of rate group member output ports for ActiveRateGroup +constant ActiveRateGroupOutputPorts = 15 + +@ Number of rate group member output ports for PassiveRateGroup +constant PassiveRateGroupOutputPorts = 10 + +@ Used to drive rate groups +constant RateGroupDriverRateGroupPorts = 3 + +@ Used for command and registration ports +constant CmdDispatcherComponentCommandPorts = 30 + +@ Used for uplink/sequencer buffer/response ports +constant CmdDispatcherSequencePorts = 5 + +@ Used for dispatching sequences to command sequencers +constant SeqDispatcherSequencerPorts = 2 + +@ Used for sizing the command splitter input arrays +constant CmdSplitterPorts = CmdDispatcherSequencePorts + +@ Number of static memory allocations +constant StaticMemoryAllocations = 4 + +@ Used to ping active components +constant HealthPingPorts = 25 + +@ Used for broadcasting completed file downlinks +constant FileDownCompletePorts = 1 + +@ Used for number of Fw::Com type ports supported by Svc::ComQueue +constant ComQueueComPorts = 2 + +@ Used for number of Fw::Buffer type ports supported by Svc::ComQueue +constant ComQueueBufferPorts = 1 + +@ Used for maximum number of connected buffer repeater consumers +constant BufferRepeaterOutputPorts = 10 + +@ Size of port array for DpManager +constant DpManagerNumPorts = 5 + +@ Size of processing port array for DpWriter +constant DpWriterNumProcPorts = 5 + +@ The size of a file name string +constant FileNameStringSize = 200 + +@ The size of an assert text string +constant FwAssertTextSize = 256 + +@ The size of a file name in an AssertFatalAdapter event +@ Note: File names in assertion failures are also truncated by +@ the constants FW_ASSERT_TEXT_SIZE and FW_LOG_STRING_MAX_SIZE, set +@ in FpConfig.h. +constant AssertFatalAdapterEventFileSize = FileNameStringSize + +# ---------------------------------------------------------------------- +# Hub connections. Connections on all deployments should mirror these settings. +# ---------------------------------------------------------------------- + +constant GenericHubInputPorts = 10 +constant GenericHubOutputPorts = 10 +constant GenericHubInputBuffers = 10 +constant GenericHubOutputBuffers = 10 diff --git a/FprimeZephyrReference/project/config/CMakeLists.txt b/FprimeZephyrReference/project/config/CMakeLists.txt index cf115d7..5287e6f 100644 --- a/FprimeZephyrReference/project/config/CMakeLists.txt +++ b/FprimeZephyrReference/project/config/CMakeLists.txt @@ -11,8 +11,10 @@ register_fprime_config( "${CMAKE_CURRENT_LIST_DIR}/ComCcsdsConfig.fpp" "${CMAKE_CURRENT_LIST_DIR}/ComCfg.fpp" "${CMAKE_CURRENT_LIST_DIR}/CommandDispatcherImplCfg.hpp" + "${CMAKE_CURRENT_LIST_DIR}/FileHandlingConfig.fpp" "${CMAKE_CURRENT_LIST_DIR}/LoRaCfg.hpp" "${CMAKE_CURRENT_LIST_DIR}/FpConfig.h" "${CMAKE_CURRENT_LIST_DIR}/TlmPacketizerCfg.hpp" + "${CMAKE_CURRENT_LIST_DIR}/AcConstants.fpp" INTERFACE ) diff --git a/FprimeZephyrReference/project/config/CdhCoreConfig.fpp b/FprimeZephyrReference/project/config/CdhCoreConfig.fpp index 40ad28a..36c77be 100644 --- a/FprimeZephyrReference/project/config/CdhCoreConfig.fpp +++ b/FprimeZephyrReference/project/config/CdhCoreConfig.fpp @@ -17,10 +17,10 @@ module CdhCoreConfig { } module Priorities { - constant cmdDisp = 10 - constant $health = 11 - constant events = 12 - constant tlmSend = 13 + constant cmdDisp = 7 + constant $health = 8 + constant events = 9 + constant tlmSend = 10 } } diff --git a/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp b/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp index ab88a46..350367d 100644 --- a/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp +++ b/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp @@ -11,7 +11,7 @@ // Define configuration values for dispatcher enum { - CMD_DISPATCHER_DISPATCH_TABLE_SIZE = 50, // !< The size of the table holding opcodes to dispatch + CMD_DISPATCHER_DISPATCH_TABLE_SIZE = 100, // !< The size of the table holding opcodes to dispatch CMD_DISPATCHER_SEQUENCER_TABLE_SIZE = 10, // !< The size of the table holding commands in progress }; diff --git a/FprimeZephyrReference/project/config/FileHandlingConfig.fpp b/FprimeZephyrReference/project/config/FileHandlingConfig.fpp new file mode 100644 index 0000000..1074f62 --- /dev/null +++ b/FprimeZephyrReference/project/config/FileHandlingConfig.fpp @@ -0,0 +1,33 @@ +module FileHandlingConfig { + #Base ID for the FileHandling Subtopology, all components are offsets from this base ID + constant BASE_ID = 0x05000000 + + module QueueSizes { + constant fileUplink = 10 + constant fileDownlink = 10 + constant fileManager = 10 + constant prmDb = 10 + } + + module StackSizes { + constant fileUplink = 8 * 1024 + constant fileDownlink = 8 * 1024 + constant fileManager = 8 * 1024 + constant prmDb = 8 * 1024 + } + + module Priorities { + constant fileUplink = 11 + constant fileDownlink = 12 + constant fileManager = 13 + constant prmDb = 14 + } + + # File downlink configuration constants + module DownlinkConfig { + constant timeout = 1000 # File downlink timeout in ms + constant cooldown = 1000 # File downlink cooldown in ms + constant cycleTime = 1000 # File downlink cycle time in ms + constant fileQueueDepth = 3 # File downlink queue depth + } +} diff --git a/lib/fprime-zephyr b/lib/fprime-zephyr index 11c2a10..c07730a 160000 --- a/lib/fprime-zephyr +++ b/lib/fprime-zephyr @@ -1 +1 @@ -Subproject commit 11c2a109c0225745237c46a0f45902ffc598500b +Subproject commit c07730af640261afee9fc0cd8861c2b075110621 diff --git a/prj.conf b/prj.conf index b1e3567..a422ba5 100644 --- a/prj.conf +++ b/prj.conf @@ -36,7 +36,7 @@ CONFIG_DYNAMIC_THREAD=y CONFIG_KERNEL_MEM_POOL=y CONFIG_DYNAMIC_THREAD_ALLOC=n CONFIG_DYNAMIC_THREAD_PREFER_POOL=y -CONFIG_DYNAMIC_THREAD_POOL_SIZE=15 +CONFIG_DYNAMIC_THREAD_POOL_SIZE=20 # Num threads in the thread pool CONFIG_DYNAMIC_THREAD_STACK_SIZE=8192 # Size of thread stack in thread pool, must be >= Thread Pool size in F'