mirror of
https://github.com/nasa/fprime.git
synced 2025-12-15 14:05:24 -06:00
* Add initiali fpy sequencer * Get ready to use internal state machines * Start modeling state machine in fpp * Little more work on fpy sequencer * Little more drafting on fpy sequencer * State machine review with bocchino * Remove unnecessary sm stuff * Update docstgrings * Start implementing actions for SM * Little more work on fpy seq * Get compiling again, rework how errors are handled, start actually reading header from disk * Much more work on getting the state machine up and working * Little more work * More changes to SM. Mostly combine validation into one state * A little more work on the readXYZ funcs * Start working on the actual runtime! * Little more work on sending out cmds * Some work on handling statement results * Get waits working hopefully. Also refactor cmd signals and responses * remove the two states for cmd vs directive * Some progress in converting to fprime types * Get seq compiling with new fprime types * refactor validation a little * Fix final bugs with seq parsing. First seq rangits add to ref * Add StatementARgBuf * Add some tlm, get wait directives working * Check timebase/ctx, increase allocated size * Some fixes for removing NATIVE_X * use handlestmt result * Fix some types, clean up some errors, add tlm * Move more stuff to RUN state * Start pulling seq dirs into internal ports * Use internal interfaces for directives * Add timeout to dispatcher * Fix a lil bug with seq too large * Sequencer working! Passing all int tests * Add seq path tlm, timeout, return signals in directives * Fix several pr feedback items * More pr feedback * More fixes from PR feedback * Remove printf * Add basic unit tests * Respond to more feedback * Do most feedback from comments * Little more event fixes, add more docs * Some work on proper cmd response off nominal behavior * Add all events and conditions to cmdresponsein * Small fix to unexpected cmd repsonse, remove from ref * Fix some small compiler warnings * Fix one more warning * Fix a comment * spelling * Remove unused types from test * Cast assert arg --------- Co-authored-by: Zimri Leisher <zimri.leisher@fireflyspace.com>
403 lines
18 KiB
C++
403 lines
18 KiB
C++
// ======================================================================
|
|
// \title FpySequencer.hpp
|
|
// \author zimri.leisher
|
|
// \brief hpp file for FpySequencer component implementation class
|
|
// ======================================================================
|
|
|
|
#ifndef FpySequencer_HPP
|
|
#define FpySequencer_HPP
|
|
|
|
#include "FppConstantsAc.hpp"
|
|
#include "Fw/Types/MemAllocator.hpp"
|
|
#include "Fw/Types/StringBase.hpp"
|
|
#include "Fw/Types/WaitEnumAc.hpp"
|
|
#include "Fw/Types/SuccessEnumAc.hpp"
|
|
#include "Os/File.hpp"
|
|
#include "Svc/FpySequencer/DirectiveIdEnumAc.hpp"
|
|
#include "Svc/FpySequencer/FooterSerializableAc.hpp"
|
|
#include "Svc/FpySequencer/FpySequencerComponentAc.hpp"
|
|
#include "Svc/FpySequencer/FpySequencer_GoalStateEnumAc.hpp"
|
|
#include "Svc/FpySequencer/HeaderSerializableAc.hpp"
|
|
#include "Svc/FpySequencer/SequenceSerializableAc.hpp"
|
|
#include "Svc/FpySequencer/StatementSerializableAc.hpp"
|
|
|
|
static_assert(Svc::Fpy::MAX_SEQUENCE_ARG_COUNT <= std::numeric_limits<U8>::max(), "Sequence arg count must be below U8 max");
|
|
static_assert(Svc::Fpy::MAX_SEQUENCE_STATEMENT_COUNT <= std::numeric_limits<U16>::max(), "Sequence statement count must be below U16 max");
|
|
|
|
namespace Svc {
|
|
|
|
using Signal = FpySequencer_SequencerStateMachineStateMachineBase::Signal;
|
|
using State = FpySequencer_SequencerStateMachineStateMachineBase::State;
|
|
|
|
class FpySequencer : public FpySequencerComponentBase {
|
|
public:
|
|
// ----------------------------------------------------------------------
|
|
// Construction, initialization, and destruction
|
|
// ----------------------------------------------------------------------
|
|
|
|
//! Construct object FpySequencer
|
|
//!
|
|
FpySequencer(const char* const compName /*!< The component name*/
|
|
);
|
|
|
|
//! Destroy object FpySequencer
|
|
//!
|
|
~FpySequencer();
|
|
|
|
PRIVATE :
|
|
|
|
//! Handler for command RUN
|
|
//!
|
|
//! Loads, validates and runs a sequence
|
|
void
|
|
RUN_cmdHandler(FwOpcodeType opCode, //!< The opcode
|
|
U32 cmdSeq, //!< The command sequence number
|
|
const Fw::CmdStringArg& fileName, //!< The name of the sequence file
|
|
FpySequencer_BlockState block //!< Return command status when complete or not
|
|
) override;
|
|
|
|
//! Handler for command VALIDATE
|
|
//!
|
|
//! Loads and validates a sequence
|
|
void VALIDATE_cmdHandler(FwOpcodeType opCode, //!< The opcode
|
|
U32 cmdSeq, //!< The command sequence number
|
|
const Fw::CmdStringArg& fileName //!< The name of the sequence file
|
|
) override;
|
|
|
|
//! Handler for command RUN_VALIDATED
|
|
//!
|
|
//! Runs a previously validated sequence
|
|
void RUN_VALIDATED_cmdHandler(FwOpcodeType opCode, //!< The opcode
|
|
U32 cmdSeq, //!< The command sequence number
|
|
FpySequencer_BlockState block //!< Return command status when complete or not
|
|
) override;
|
|
|
|
//! Handler for command CANCEL
|
|
//!
|
|
//! Cancels a running or validated sequence
|
|
void CANCEL_cmdHandler(FwOpcodeType opCode, //!< The opcode
|
|
U32 cmdSeq //!< The command sequence number
|
|
) override;
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Functions to implement for internal state machine actions
|
|
// ----------------------------------------------------------------------
|
|
|
|
//! Implementation for action signalEntered of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! simply raises the "entered" signal
|
|
void Svc_FpySequencer_SequencerStateMachine_action_signalEntered(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action setSequenceFilePath of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! sets the current sequence file path member var
|
|
void Svc_FpySequencer_SequencerStateMachine_action_setSequenceFilePath(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal, //!< The signal
|
|
const Svc::FpySequencer_SequenceExecutionArgs& value //!< The value
|
|
) override;
|
|
|
|
//! Implementation for action setSequenceBlockState of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! sets the block state of the sequence to be run
|
|
void Svc_FpySequencer_SequencerStateMachine_action_setSequenceBlockState(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal, //!< The signal
|
|
const Svc::FpySequencer_SequenceExecutionArgs& value //!< The value
|
|
) override;
|
|
|
|
//! Implementation for action validate of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! performs all steps necessary for sequence validation, and raises a signal result_success or result_failure
|
|
void Svc_FpySequencer_SequencerStateMachine_action_validate(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action report_seqSucceeded of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! reports that a sequence succeeded
|
|
void Svc_FpySequencer_SequencerStateMachine_action_report_seqSucceeded(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action report_seqCancelled of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! reports that a sequence was cancelled
|
|
void Svc_FpySequencer_SequencerStateMachine_action_report_seqCancelled(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action setGoalState_RUNNING of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! sets the goal state to RUNNING
|
|
void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_RUNNING(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action setGoalState_VALID of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! sets the goal state to VALID
|
|
void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_VALID(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action setGoalState_IDLE of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! sets the goal state to IDLE
|
|
void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_IDLE(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action sendCmdResponse_OK of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! responds to the calling command with OK
|
|
void Svc_FpySequencer_SequencerStateMachine_action_sendCmdResponse_OK(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action sendCmdResponse_EXECUTION_ERROR of state machine
|
|
//! Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! responds to the calling command with EXECUTION_ERROR
|
|
void Svc_FpySequencer_SequencerStateMachine_action_sendCmdResponse_EXECUTION_ERROR(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action dispatchStatement of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! iterates to the next statement and dispatches it
|
|
void Svc_FpySequencer_SequencerStateMachine_action_dispatchStatement(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action clearSequenceFile of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! clears all variables related to the loading/validating of the sequence file
|
|
void Svc_FpySequencer_SequencerStateMachine_action_clearSequenceFile(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action checkShouldWake of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! checks if sequencer should wake from sleep
|
|
void Svc_FpySequencer_SequencerStateMachine_action_checkShouldWake(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action resetRuntime of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! resets the sequence runtime
|
|
void Svc_FpySequencer_SequencerStateMachine_action_resetRuntime(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action checkStatementTimeout of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! checks if the current statement has timed out
|
|
void Svc_FpySequencer_SequencerStateMachine_action_checkStatementTimeout(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
//! Implementation for action incrementSequenceCounter of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! increments the m_sequencesStarted counter
|
|
void Svc_FpySequencer_SequencerStateMachine_action_incrementSequenceCounter(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) override;
|
|
|
|
PROTECTED :
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Functions to implement for internal state machine guards
|
|
// ----------------------------------------------------------------------
|
|
|
|
//! Implementation for guard goalStateIs_RUNNING of state machine Svc_FpySequencer_SequencerStateMachine
|
|
//!
|
|
//! return true if the goal state is RUNNING
|
|
bool
|
|
Svc_FpySequencer_SequencerStateMachine_guard_goalStateIs_RUNNING(
|
|
SmId smId, //!< The state machine id
|
|
Svc_FpySequencer_SequencerStateMachine::Signal signal //!< The signal
|
|
) const override;
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Handlers to implement for typed input ports
|
|
// ----------------------------------------------------------------------
|
|
|
|
//! Handler for input port checkTimers
|
|
void checkTimers_handler(FwIndexType portNum, //!< The port number
|
|
U32 context //!< The call order
|
|
) override;
|
|
|
|
//! Handler for input port cmdResponseIn
|
|
void cmdResponseIn_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 for input port pingIn
|
|
void pingIn_handler(FwIndexType portNum, //!< The port number
|
|
U32 key //!< Value to return to pinger
|
|
) override;
|
|
|
|
//! Handler for input port tlmWrite
|
|
void tlmWrite_handler(FwIndexType portNum, //!< The port number
|
|
U32 context //!< The call order
|
|
) override;
|
|
|
|
//! Internal interface handler for directive_waitAbs
|
|
void directive_waitAbs_internalInterfaceHandler(const FpySequencer_WaitAbsDirective& directive) override;
|
|
|
|
//! Internal interface handler for directive_waitRel
|
|
void directive_waitRel_internalInterfaceHandler(const FpySequencer_WaitRelDirective& directive) override;
|
|
|
|
void parametersLoaded() override;
|
|
void parameterUpdated(FwPrmIdType id) override;
|
|
|
|
public:
|
|
void allocateBuffer(FwEnumStoreType identifier, Fw::MemAllocator& allocator, FwSizeType bytes);
|
|
|
|
void deallocateBuffer(Fw::MemAllocator& allocator);
|
|
PRIVATE :
|
|
|
|
static constexpr U32 CRC_INITIAL_VALUE = 0xFFFFFFFFU;
|
|
|
|
// allocated at startup
|
|
Fw::ExternalSerializeBuffer m_sequenceBuffer;
|
|
// id of allocator that gave us m_sequenceBuffer
|
|
FwEnumStoreType m_allocatorId;
|
|
|
|
// assigned by the user via cmd
|
|
Fw::String m_sequenceFilePath;
|
|
// the sequence, loaded in memory
|
|
Fpy::Sequence m_sequenceObj;
|
|
// live running computation of CRC (updated as we read)
|
|
U32 m_computedCRC;
|
|
|
|
// whether or not the sequence we're about to run should return immediately or
|
|
// block on completion
|
|
FpySequencer_BlockState m_sequenceBlockState;
|
|
// if we are to block on completion, save the opCode and cmdSeq we should
|
|
// return
|
|
FwOpcodeType m_savedOpCode;
|
|
U32 m_savedCmdSeq;
|
|
|
|
// the goal state is the state that we're trying to reach in the sequencer
|
|
// if it's RUNNING, then we should promptly go to RUNNING once we validate the
|
|
// sequence. if it's VALID, we should wait after VALIDATING
|
|
FpySequencer_GoalState m_goalState;
|
|
|
|
// the total number of sequences this sequencer has started since construction
|
|
U64 m_sequencesStarted;
|
|
// the total number of statements this sequencer has dispatched, successfully or
|
|
// otherwise, since construction
|
|
U64 m_statementsDispatched;
|
|
|
|
// the runtime state of the sequence. encapsulates all state
|
|
// needed to run the sequence.
|
|
// this is distinct from the state of the sequencer. the
|
|
// sequencer and all its state is really just a shell to load
|
|
// and execute this runtime.
|
|
struct Runtime {
|
|
// the index of the next statement to be executed
|
|
U32 nextStatementIndex = 0;
|
|
|
|
// the opcode of the statement that is currently executing
|
|
FwOpcodeType currentStatementOpcode = Fpy::DirectiveId::INVALID;
|
|
// the stmt type of the stmt currently executing (cmd or directive)
|
|
Fpy::StatementType currentStatementType = Fpy::StatementType::DIRECTIVE;
|
|
// the time we dispatched the statement that is currently executing
|
|
Fw::Time currentStatementDispatchTime = Fw::Time();
|
|
|
|
// the absolute time we should wait for until returning
|
|
// a statement response
|
|
Fw::Time wakeupTime = Fw::Time();
|
|
} m_runtime;
|
|
|
|
struct Telemetry {
|
|
// the number of statements that failed to execute
|
|
U64 statementsFailed = 0;
|
|
|
|
// the number of sequences successfully completed
|
|
U64 sequencesSucceeded = 0;
|
|
|
|
// the number of sequences that failed to validate or execute
|
|
U64 sequencesFailed = 0;
|
|
|
|
// the number of sequences that have been cancelled
|
|
U64 sequencesCancelled = 0;
|
|
} m_tlm;
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Validation state
|
|
// ----------------------------------------------------------------------
|
|
|
|
void updateComputedCRC(const U8* buffer, //!< The buffer
|
|
FwSizeType bufferSize //!< The buffer size
|
|
);
|
|
|
|
// loads the sequence in memory, and does header/crc/integrity checks.
|
|
// return success if sequence is valid
|
|
Fw::Success validate();
|
|
|
|
// reads some bytes from the open file into the m_sequenceBuffer.
|
|
// updates the CRC by default, but can be turned off if the contents
|
|
// aren't included in CRC.
|
|
// return success if successful
|
|
Fw::Success readBytes(Os::File& file, FwSizeType readLen, bool updateCRC = true);
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Run state
|
|
// ----------------------------------------------------------------------
|
|
|
|
// dispatches the next statement
|
|
Signal dispatchStatement();
|
|
|
|
// dispatches a command out via port.
|
|
// return success if successfully dispatched.
|
|
Fw::Success dispatchCommand(const Fpy::Statement& stmt);
|
|
|
|
// dispatches a sequencer directive to the right handler.
|
|
// return success if successfully handled.
|
|
Fw::Success dispatchDirective(const Fpy::Statement& stmt);
|
|
|
|
// checks whether the currently executing statement timed out
|
|
Signal checkStatementTimeout();
|
|
// checks whether the sequencer should wake from sleeping
|
|
Signal checkShouldWake();
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Directives
|
|
// ----------------------------------------------------------------------
|
|
|
|
// sends a signal based on a signal id
|
|
void sendSignal(Signal signal);
|
|
|
|
// we split these functions up into the internalInterfaceInvoke and these custom member funcs
|
|
// so that we can unit test them easier
|
|
Signal waitRel_directiveHandler(const FpySequencer_WaitRelDirective& directive);
|
|
Signal waitAbs_directiveHandler(const FpySequencer_WaitAbsDirective& directive);
|
|
};
|
|
|
|
} // namespace Svc
|
|
|
|
#endif
|