F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
FpySequencer.hpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title FpySequencer.hpp
3 // \author zimri.leisher
4 // \brief hpp file for FpySequencer component implementation class
5 // ======================================================================
6 
7 #ifndef FpySequencer_HPP
8 #define FpySequencer_HPP
9 
11 #include "Fw/Types/StringBase.hpp"
13 #include "Fw/Types/WaitEnumAc.hpp"
14 #include "Os/File.hpp"
23 
24 static_assert(Svc::Fpy::MAX_SEQUENCE_ARG_COUNT <= std::numeric_limits<U8>::max(),
25  "Sequence arg count must be below U8 max");
26 static_assert(Svc::Fpy::NUM_REGISTERS <= std::numeric_limits<U8>::max(),
27  "Register count must be below U8 max");
28 static_assert(Svc::Fpy::MAX_SEQUENCE_STATEMENT_COUNT <= std::numeric_limits<U16>::max(),
29  "Sequence statement count must be below U16 max");
30 static_assert(Svc::Fpy::MAX_SERIALIZABLE_REGISTER_SIZE <= std::numeric_limits<FwSizeType>::max(),
31  "Local variable buffer size must be below FwSizeType max");
33  "Local variable buffer size must be greater than FW_TLM_BUFFER_MAX_SIZE");
35  "Local variable buffer size must be greater than FW_PARAM_BUFFER_MAX_SIZE");
36 
37 namespace Svc {
38 
42 
44 
45  friend class FpySequencerTester;
46 
47  public:
63 
66  };
67 
68  // ----------------------------------------------------------------------
69  // Construction, initialization, and destruction
70  // ----------------------------------------------------------------------
71 
74  FpySequencer(const char* const compName
75  );
76 
79  ~FpySequencer();
80 
81  private:
82 
86  void
87  RUN_cmdHandler(FwOpcodeType opCode,
88  U32 cmdSeq,
89  const Fw::CmdStringArg& fileName,
91  ) override;
92 
96  void VALIDATE_cmdHandler(FwOpcodeType opCode,
97  U32 cmdSeq,
98  const Fw::CmdStringArg& fileName
99  ) override;
100 
104  void RUN_VALIDATED_cmdHandler(FwOpcodeType opCode,
105  U32 cmdSeq,
107  ) override;
108 
112  void CANCEL_cmdHandler(FwOpcodeType opCode,
113  U32 cmdSeq
114  ) override;
115 
122  void DEBUG_SET_BREAKPOINT_cmdHandler(FwOpcodeType opCode,
123  U32 cmdSeq,
124  U32 stmtIdx,
125  bool breakOnce
126  ) override;
127 
133  void DEBUG_BREAK_cmdHandler(FwOpcodeType opCode,
134  U32 cmdSeq,
135  bool breakOnce
136  ) override;
137 
142  void DEBUG_CONTINUE_cmdHandler(FwOpcodeType opCode,
143  U32 cmdSeq
144  ) override;
145 
150  void DEBUG_CLEAR_BREAKPOINT_cmdHandler(FwOpcodeType opCode,
151  U32 cmdSeq
152  ) override;
153 
154  // ----------------------------------------------------------------------
155  // Functions to implement for internal state machine actions
156  // ----------------------------------------------------------------------
157 
161  void Svc_FpySequencer_SequencerStateMachine_action_signalEntered(
162  SmId smId,
164  ) override;
165 
169  void Svc_FpySequencer_SequencerStateMachine_action_setSequenceFilePath(
170  SmId smId,
173  ) override;
174 
178  void Svc_FpySequencer_SequencerStateMachine_action_setSequenceBlockState(
179  SmId smId,
182  ) override;
183 
187  void Svc_FpySequencer_SequencerStateMachine_action_validate(
188  SmId smId,
190  ) override;
191 
195  void Svc_FpySequencer_SequencerStateMachine_action_report_seqSucceeded(
196  SmId smId,
198  ) override;
199 
203  void Svc_FpySequencer_SequencerStateMachine_action_report_seqCancelled(
204  SmId smId,
206  ) override;
207 
211  void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_RUNNING(
212  SmId smId,
214  ) override;
215 
219  void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_VALID(
220  SmId smId,
222  ) override;
223 
227  void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_IDLE(
228  SmId smId,
230  ) override;
231 
235  void Svc_FpySequencer_SequencerStateMachine_action_sendCmdResponse_OK(
236  SmId smId,
238  ) override;
239 
244  void Svc_FpySequencer_SequencerStateMachine_action_sendCmdResponse_EXECUTION_ERROR(
245  SmId smId,
247  ) override;
248 
252  void Svc_FpySequencer_SequencerStateMachine_action_dispatchStatement(
253  SmId smId,
255  ) override;
256 
260  void Svc_FpySequencer_SequencerStateMachine_action_clearSequenceFile(
261  SmId smId,
263  ) override;
264 
268  void Svc_FpySequencer_SequencerStateMachine_action_checkShouldWake(
269  SmId smId,
271  ) override;
272 
276  void Svc_FpySequencer_SequencerStateMachine_action_resetRuntime(
277  SmId smId,
279  ) override;
280 
284  void Svc_FpySequencer_SequencerStateMachine_action_checkStatementTimeout(
285  SmId smId,
287  ) override;
288 
292  void Svc_FpySequencer_SequencerStateMachine_action_incrementSequenceCounter(
293  SmId smId,
295  ) override;
296 
300  void Svc_FpySequencer_SequencerStateMachine_action_clearDebugBreakpoint(
301  SmId smId,
303  ) override;
304 
308  void Svc_FpySequencer_SequencerStateMachine_action_report_debugBroken(
309  SmId smId,
311  ) override;
312 
316  void Svc_FpySequencer_SequencerStateMachine_action_setDebugBreakpoint(
317  SmId smId,
320  ) override;
321 
325  void Svc_FpySequencer_SequencerStateMachine_action_report_seqFailed(
326  SmId smId,
328  ) override;
329 
333  void Svc_FpySequencer_SequencerStateMachine_action_report_seqStarted(
334  SmId smId,
336  ) override;
337 
338  protected:
339 
340  // ----------------------------------------------------------------------
341  // Functions to implement for internal state machine guards
342  // ----------------------------------------------------------------------
343 
347  bool
349  SmId smId,
351  ) const override;
352 
358  SmId smId,
360  ) const override;
361 
366  SmId smId,
368  ) const override;
369 
370  // ----------------------------------------------------------------------
371  // Handlers to implement for typed input ports
372  // ----------------------------------------------------------------------
373 
375  void checkTimers_handler(FwIndexType portNum,
376  U32 context
377  ) override;
378 
380  void cmdResponseIn_handler(FwIndexType portNum,
381  FwOpcodeType opCode,
382  U32 cmdSeq,
383  const Fw::CmdResponse& response
384  ) override;
385 
387  void seqRunIn_handler(FwIndexType portNum,
388  const Fw::StringBase& filename
389  ) override;
390 
392  void pingIn_handler(FwIndexType portNum,
393  U32 key
394  ) override;
395 
397  void tlmWrite_handler(FwIndexType portNum,
398  U32 context
399  ) override;
400 
403 
406 
409 
412 
415 
418 
421 
424 
427 
430 
433 
436 
439 
442 
443  void parametersLoaded() override;
444  void parameterUpdated(FwPrmIdType id) override;
445 
446  public:
447  void allocateBuffer(FwEnumStoreType identifier, Fw::MemAllocator& allocator, FwSizeType bytes);
448 
449  void deallocateBuffer(Fw::MemAllocator& allocator);
450  private :
451 
452  static constexpr U32 CRC_INITIAL_VALUE = 0xFFFFFFFFU;
453 
454  // allocated at startup
455  Fw::ExternalSerializeBuffer m_sequenceBuffer;
456  // id of allocator that gave us m_sequenceBuffer
457  FwEnumStoreType m_allocatorId;
458 
459  // assigned by the user via cmd
460  Fw::String m_sequenceFilePath;
461  // the sequence, loaded in memory
462  Fpy::Sequence m_sequenceObj;
463  // live running computation of CRC (updated as we read)
464  U32 m_computedCRC;
465 
466  // whether or not the sequence we're about to run should return immediately or
467  // block on completion
468  FpySequencer_BlockState m_sequenceBlockState;
469  // if we are to block on completion, save the opCode and cmdSeq we should
470  // return
471  FwOpcodeType m_savedOpCode;
472  U32 m_savedCmdSeq;
473 
474  // the goal state is the state that we're trying to reach in the sequencer
475  // if it's RUNNING, then we should promptly go to RUNNING once we validate the
476  // sequence. if it's VALID, we should wait after VALIDATING
477  FpySequencer_GoalState m_goalState;
478 
479  // the total number of sequences this sequencer has started since construction
480  U64 m_sequencesStarted;
481  // the total number of statements this sequencer has dispatched, successfully or
482  // otherwise, since construction
483  U64 m_statementsDispatched;
484 
485  // the runtime state of the sequence. encapsulates all state
486  // needed to run the sequence.
487  // this is distinct from the state of the sequencer. the
488  // sequencer and all its state is really just a shell to load
489  // and execute this runtime.
490  struct Runtime {
491  // the index of the next statement to be executed
492  U32 nextStatementIndex = 0;
493 
494  // the opcode of the statement that is currently executing
495  U8 currentStatementOpcode = Fpy::DirectiveId::INVALID;
496  // the opcode of the command that we are currently awaiting, or 0 if we are executing a directive
497  FwOpcodeType currentCmdOpcode = 0;
498  // the time we dispatched the statement that is currently executing
499  Fw::Time currentStatementDispatchTime = Fw::Time();
500 
501  // the absolute time we should wait for until returning
502  // a statement response
503  Fw::Time wakeupTime = Fw::Time();
504 
505  // all the serializable registers in the sequence
507  // the value buffer of the serReg
509  // the size of the data in the serReg buf
511  } serRegs[Fpy::NUM_SERIALIZABLE_REGISTERS] = {};
512 
513  // all the regs in the sequence. regs are 8 byte
514  // values of unspecified type
515  I64 regs[Fpy::NUM_REGISTERS] = {0};
516 
517  } m_runtime;
518 
519  // the state of the debugger. debugger is separate from runtime
520  // because it can be set up before running the sequence.
521  struct Debug {
522  // whether or not to break at the debug breakpoint index
523  bool breakOnBreakpoint = false;
524  // whether or not to remove the breakpoint after breaking on it
525  bool breakOnlyOnceOnBreakpoint = false;
526  // the statement index at which to break, before dispatching
527  U32 breakpointIndex = 0;
528  } m_debug;
529 
530  struct Telemetry {
531  // the number of statements that failed to execute
532  U64 statementsFailed = 0;
533 
534  // the number of sequences successfully completed
535  U64 sequencesSucceeded = 0;
536 
537  // the number of sequences that failed to validate or execute
538  U64 sequencesFailed = 0;
539 
540  // the number of sequences that have been cancelled
541  U64 sequencesCancelled = 0;
542 
543  // the error code of the last directive that ran
544  DirectiveError lastDirectiveError = DirectiveError::NO_ERROR;
545  } m_tlm;
546 
547  // ----------------------------------------------------------------------
548  // Validation state
549  // ----------------------------------------------------------------------
550 
551  static void updateCrc(U32& crc,
552  const U8* buffer,
553  FwSizeType bufferSize
554  );
555 
556  // loads the sequence in memory, and does header/crc/integrity checks.
557  // return success if sequence is valid
558  Fw::Success validate();
559  // reads and validates the header from the m_sequenceBuffer
560  // return success if header is valid
561  Fw::Success readHeader();
562  // reads and validates the body from the m_sequenceBuffer
563  // return success if body is valid
564  Fw::Success readBody();
565  // reads and validates the footer from the m_sequenceBuffer
566  // return success if footer is valid
567  Fw::Success readFooter();
568 
569  // reads some bytes from the open file into the m_sequenceBuffer.
570  // updates the CRC by default, but can be turned off if the contents
571  // aren't included in CRC.
572  // return success if successful
573  Fw::Success readBytes(Os::File& file, FwSizeType readLen, bool updateCrc = true);
574 
575  // ----------------------------------------------------------------------
576  // Run state
577  // ----------------------------------------------------------------------
578 
579  // dispatches the next statement
580  Signal dispatchStatement();
581 
582  // deserializes a directive from bytes into the Fpy type
583  // returns success if able to deserialize, and returns the Fpy type object
584  // as a reference, in a union of all the possible directive type objects
585  Fw::Success deserializeDirective(const Fpy::Statement& stmt, DirectiveUnion& deserializedDirective);
586 
587  // dispatches a deserialized sequencer directive to the right handler.
588  void dispatchDirective(const DirectiveUnion& directive, const Fpy::DirectiveId& id);
589 
590  // checks whether the currently executing statement timed out
591  Signal checkStatementTimeout();
592 
593  // checks whether the sequencer should wake from sleeping
594  Signal checkShouldWake();
595 
596  // return true if state is a substate of RUNNING
597  bool isRunningState(State state);
598 
599  // return a struct containing debug telemetry, or defaults if not in debug break
600  FpySequencer_DebugTelemetry getDebugTelemetry();
601 
602  // ----------------------------------------------------------------------
603  // Directives
604  // ----------------------------------------------------------------------
605 
606  // sends a signal based on a signal id
607  void sendSignal(Signal signal);
608 
609  // helper function to get a reference to a register from an index
610  // saves a bunch of typing
611  I64& reg(U8 idx);
612 
613  // we split these functions up into the internalInterfaceInvoke and these custom member funcs
614  // so that we can unit test them easier
615  Signal waitRel_directiveHandler(const FpySequencer_WaitRelDirective& directive, DirectiveError& error);
616  Signal waitAbs_directiveHandler(const FpySequencer_WaitAbsDirective& directive, DirectiveError& error);
617  Signal setSerReg_directiveHandler(const FpySequencer_SetSerRegDirective& directive, DirectiveError& error);
618  Signal goto_directiveHandler(const FpySequencer_GotoDirective& directive, DirectiveError& error);
619  Signal if_directiveHandler(const FpySequencer_IfDirective& directive, DirectiveError& error);
620  Signal noOp_directiveHandler(const FpySequencer_NoOpDirective& directive, DirectiveError& error);
621  Signal getTlm_directiveHandler(const FpySequencer_GetTlmDirective& directive, DirectiveError& error);
622  Signal getPrm_directiveHandler(const FpySequencer_GetPrmDirective& directive, DirectiveError& error);
623  Signal cmd_directiveHandler(const FpySequencer_CmdDirective& directive, DirectiveError& error);
624  Signal deserSerReg_directiveHandler(const FpySequencer_DeserSerRegDirective& directive, DirectiveError& error);
625  Signal setReg_directiveHandler(const FpySequencer_SetRegDirective& directive, DirectiveError& error);
626 
627  Signal binaryRegOp_directiveHandler(const FpySequencer_BinaryRegOpDirective& directive, DirectiveError& error);
628  I64 binaryRegOp_or(I64 lhs, I64 rhs);
629  I64 binaryRegOp_and(I64 lhs, I64 rhs);
630  I64 binaryRegOp_ieq(I64 lhs, I64 rhs);
631  I64 binaryRegOp_ine(I64 lhs, I64 rhs);
632  I64 binaryRegOp_ult(I64 lhs, I64 rhs);
633  I64 binaryRegOp_ule(I64 lhs, I64 rhs);
634  I64 binaryRegOp_ugt(I64 lhs, I64 rhs);
635  I64 binaryRegOp_uge(I64 lhs, I64 rhs);
636  I64 binaryRegOp_slt(I64 lhs, I64 rhs);
637  I64 binaryRegOp_sle(I64 lhs, I64 rhs);
638  I64 binaryRegOp_sgt(I64 lhs, I64 rhs);
639  I64 binaryRegOp_sge(I64 lhs, I64 rhs);
640  I64 binaryRegOp_feq(I64 lhs, I64 rhs);
641  I64 binaryRegOp_fne(I64 lhs, I64 rhs);
642  I64 binaryRegOp_flt(I64 lhs, I64 rhs);
643  I64 binaryRegOp_fle(I64 lhs, I64 rhs);
644  I64 binaryRegOp_fgt(I64 lhs, I64 rhs);
645  I64 binaryRegOp_fge(I64 lhs, I64 rhs);
646 
647  Signal unaryRegOp_directiveHandler(const FpySequencer_UnaryRegOpDirective& directive, DirectiveError& error);
648  I64 unaryRegOp_not(I64 src);
649  I64 unaryRegOp_fpext(I64 src);
650  I64 unaryRegOp_fptrunc(I64 src);
651 
652  Signal exit_directiveHandler(const FpySequencer_ExitDirective& directive, DirectiveError& error);
653 };
654 
655 } // namespace Svc
656 
657 #endif
FpySequencer_SetSerRegDirective setSerReg
Definition: Time.hpp:9
FwIdType FwOpcodeType
The type of a command opcode.
void directive_if_internalInterfaceHandler(const Svc::FpySequencer_IfDirective &directive) override
Internal interface handler for directive_if.
PlatformSizeType FwSizeType
FpySequencer_GotoDirective gotoDirective
I32 FwEnumStoreType
bool Svc_FpySequencer_SequencerStateMachine_guard_goalStateIs_RUNNING(SmId smId, Svc_FpySequencer_SequencerStateMachine::Signal signal) const override
performs a unary reg operation on src reg, and stores in res reg
void pingIn_handler(FwIndexType portNum, U32 key) override
Handler for input port pingIn.
void directive_getPrm_internalInterfaceHandler(const Svc::FpySequencer_GetPrmDirective &directive) override
Internal interface handler for directive_getPrm.
FpySequencer_UnaryRegOpDirective unaryRegOp
FwIdType FwPrmIdType
The type of a parameter identifier.
void directive_binaryRegOp_internalInterfaceHandler(const Svc::FpySequencer_BinaryRegOpDirective &directive) override
Internal interface handler for directive_binaryRegOp.
U8 value[Fpy::MAX_SERIALIZABLE_REGISTER_SIZE]
void directive_cmd_internalInterfaceHandler(const Svc::FpySequencer_CmdDirective &directive) override
Internal interface handler for directive_cmd.
FpySequencer_WaitRelDirective waitRel
FpySequencer_WaitAbsDirective waitAbs
Enum representing a command response.
void directive_setReg_internalInterfaceHandler(const Svc::FpySequencer_SetRegDirective &directive) override
Internal interface handler for directive_setReg.
void directive_getTlm_internalInterfaceHandler(const Svc::FpySequencer_GetTlmDirective &directive) override
Internal interface handler for directive_getTlm.
FpySequencer_IfDirective ifDirective
FpySequencer_NoOpDirective noOp
void seqRunIn_handler(FwIndexType portNum, const Fw::StringBase &filename) override
Handler for input port seqRunIn.
FpySequencer_SetRegDirective setReg
void directive_waitRel_internalInterfaceHandler(const FpySequencer_WaitRelDirective &directive) override
Internal interface handler for directive_waitRel.
void directive_noOp_internalInterfaceHandler(const Svc::FpySequencer_NoOpDirective &directive) override
Internal interface handler for directive_noOp.
void directive_unaryRegOp_internalInterfaceHandler(const Svc::FpySequencer_UnaryRegOpDirective &directive) override
Internal interface handler for directive_unaryRegOp.
void parametersLoaded() override
Called whenever parameters are loaded.
FpySequencer_CmdDirective cmd
FpySequencer_DirectiveErrorCode DirectiveError
void tlmWrite_handler(FwIndexType portNum, U32 context) override
Handler for input port tlmWrite.
void directive_deserSerReg_internalInterfaceHandler(const Svc::FpySequencer_DeserSerRegDirective &directive) override
Internal interface handler for directive_deserSerReg.
void directive_exit_internalInterfaceHandler(const Svc::FpySequencer_ExitDirective &directive) override
Internal interface handler for directive_exit.
External serialize buffer with no copy semantics.
#define FW_TLM_BUFFER_MAX_SIZE
Definition: FpConfig.h:224
FpySequencer_SequencerStateMachineStateMachineBase::State State
void directive_waitAbs_internalInterfaceHandler(const FpySequencer_WaitAbsDirective &directive) override
Internal interface handler for directive_waitAbs.
void parameterUpdated(FwPrmIdType id) override
Called whenever a parameter is updated.
void directive_goto_internalInterfaceHandler(const Svc::FpySequencer_GotoDirective &directive) override
Internal interface handler for directive_goto.
#define FW_PARAM_BUFFER_MAX_SIZE
Definition: FpConfig.h:239
void allocateBuffer(FwEnumStoreType identifier, Fw::MemAllocator &allocator, FwSizeType bytes)
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:56
friend class FpySequencerTester
FpySequencer_GetPrmDirective getPrm
void cmdResponseIn_handler(FwIndexType portNum, FwOpcodeType opCode, U32 cmdSeq, const Fw::CmdResponse &response) override
Handler for input port cmdResponseIn.
performs a binary reg operation on the lhs and rhs regs, and stores the result in the third register ...
void checkTimers_handler(FwIndexType portNum, U32 context) override
Handler for input port checkTimers.
PlatformIndexType FwIndexType
FpySequencer_GetTlmDirective getTlm
RateGroupDivider component implementation.
Defines a base class for a memory allocator for classes.
void directive_setSerReg_internalInterfaceHandler(const FpySequencer_SetSerRegDirective &directive) override
Internal interface handler for directive_setSerReg.
Declares F Prime string base class.
FpySequencer_DeserSerRegDirective deserSerReg
void deallocateBuffer(Fw::MemAllocator &allocator)
Auto-generated base for FpySequencer component.
FpySequencer_ExitDirective exit
FpySequencer_SequencerStateMachineStateMachineBase::Signal Signal
Success/Failure.
bool Svc_FpySequencer_SequencerStateMachine_guard_shouldDebugBreak(SmId smId, Svc_FpySequencer_SequencerStateMachine::Signal signal) const override
bool Svc_FpySequencer_SequencerStateMachine_guard_debugBreakOnce(SmId smId, Svc_FpySequencer_SequencerStateMachine::Signal signal) const override
FpySequencer(const char *const compName)
FpySequencer_BinaryRegOpDirective binaryRegOp
#define U64(C)
Definition: sha.h:180