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(), "Register count must be below U8 max");
27 static_assert(Svc::Fpy::MAX_SEQUENCE_STATEMENT_COUNT <= std::numeric_limits<U16>::max(),
28  "Sequence statement count must be below U16 max");
29 static_assert(Svc::Fpy::MAX_SERIALIZABLE_REGISTER_SIZE <= std::numeric_limits<FwSizeType>::max(),
30  "Local variable buffer size must be below FwSizeType max");
32  "Local variable buffer size must be greater than FW_TLM_BUFFER_MAX_SIZE");
34  "Local variable buffer size must be greater than FW_PARAM_BUFFER_MAX_SIZE");
35 
36 namespace Svc {
37 
41 
43  friend class FpySequencerTester;
44 
45  public:
61 
64  };
65 
66  // ----------------------------------------------------------------------
67  // Construction, initialization, and destruction
68  // ----------------------------------------------------------------------
69 
72  FpySequencer(const char* const compName
73  );
74 
77  ~FpySequencer();
78 
79  private:
83  void RUN_cmdHandler(FwOpcodeType opCode,
84  U32 cmdSeq,
85  const Fw::CmdStringArg& fileName,
87  ) override;
88 
92  void VALIDATE_cmdHandler(FwOpcodeType opCode,
93  U32 cmdSeq,
94  const Fw::CmdStringArg& fileName
95  ) override;
96 
100  void RUN_VALIDATED_cmdHandler(FwOpcodeType opCode,
101  U32 cmdSeq,
103  ) override;
104 
108  void CANCEL_cmdHandler(FwOpcodeType opCode,
109  U32 cmdSeq
110  ) override;
111 
118  void DEBUG_SET_BREAKPOINT_cmdHandler(FwOpcodeType opCode,
119  U32 cmdSeq,
120  U32 stmtIdx,
121  bool breakOnce
122  ) override;
123 
129  void DEBUG_BREAK_cmdHandler(FwOpcodeType opCode,
130  U32 cmdSeq,
131  bool breakOnce
132  ) override;
133 
138  void DEBUG_CONTINUE_cmdHandler(FwOpcodeType opCode,
139  U32 cmdSeq
140  ) override;
141 
146  void DEBUG_CLEAR_BREAKPOINT_cmdHandler(FwOpcodeType opCode,
147  U32 cmdSeq
148  ) override;
149 
150  // ----------------------------------------------------------------------
151  // Functions to implement for internal state machine actions
152  // ----------------------------------------------------------------------
153 
157  void Svc_FpySequencer_SequencerStateMachine_action_signalEntered(
158  SmId smId,
160  ) override;
161 
165  void Svc_FpySequencer_SequencerStateMachine_action_setSequenceFilePath(
166  SmId smId,
169  ) override;
170 
174  void Svc_FpySequencer_SequencerStateMachine_action_setSequenceBlockState(
175  SmId smId,
178  ) override;
179 
183  void Svc_FpySequencer_SequencerStateMachine_action_validate(
184  SmId smId,
186  ) override;
187 
191  void Svc_FpySequencer_SequencerStateMachine_action_report_seqSucceeded(
192  SmId smId,
194  ) override;
195 
199  void Svc_FpySequencer_SequencerStateMachine_action_report_seqCancelled(
200  SmId smId,
202  ) override;
203 
207  void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_RUNNING(
208  SmId smId,
210  ) override;
211 
215  void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_VALID(
216  SmId smId,
218  ) override;
219 
223  void Svc_FpySequencer_SequencerStateMachine_action_setGoalState_IDLE(
224  SmId smId,
226  ) override;
227 
231  void Svc_FpySequencer_SequencerStateMachine_action_sendCmdResponse_OK(
232  SmId smId,
234  ) override;
235 
240  void Svc_FpySequencer_SequencerStateMachine_action_sendCmdResponse_EXECUTION_ERROR(
241  SmId smId,
243  ) override;
244 
248  void Svc_FpySequencer_SequencerStateMachine_action_dispatchStatement(
249  SmId smId,
251  ) override;
252 
256  void Svc_FpySequencer_SequencerStateMachine_action_clearSequenceFile(
257  SmId smId,
259  ) override;
260 
264  void Svc_FpySequencer_SequencerStateMachine_action_checkShouldWake(
265  SmId smId,
267  ) override;
268 
272  void Svc_FpySequencer_SequencerStateMachine_action_resetRuntime(
273  SmId smId,
275  ) override;
276 
280  void Svc_FpySequencer_SequencerStateMachine_action_checkStatementTimeout(
281  SmId smId,
283  ) override;
284 
288  void Svc_FpySequencer_SequencerStateMachine_action_incrementSequenceCounter(
289  SmId smId,
291  ) override;
292 
296  void Svc_FpySequencer_SequencerStateMachine_action_clearDebugBreakpoint(
297  SmId smId,
299  ) override;
300 
304  void Svc_FpySequencer_SequencerStateMachine_action_report_debugBroken(
305  SmId smId,
307  ) override;
308 
312  void Svc_FpySequencer_SequencerStateMachine_action_setDebugBreakpoint(
313  SmId smId,
316  ) override;
317 
321  void Svc_FpySequencer_SequencerStateMachine_action_report_seqFailed(
322  SmId smId,
324  ) override;
325 
329  void Svc_FpySequencer_SequencerStateMachine_action_report_seqStarted(
330  SmId smId,
332  ) override;
333 
334  protected:
335  // ----------------------------------------------------------------------
336  // Functions to implement for internal state machine guards
337  // ----------------------------------------------------------------------
338 
343  SmId smId,
345  ) const override;
346 
352  SmId smId,
354  ) const override;
355 
360  SmId smId,
362  ) const override;
363 
364  // ----------------------------------------------------------------------
365  // Handlers to implement for typed input ports
366  // ----------------------------------------------------------------------
367 
369  void checkTimers_handler(FwIndexType portNum,
370  U32 context
371  ) override;
372 
374  void cmdResponseIn_handler(FwIndexType portNum,
375  FwOpcodeType opCode,
376  U32 cmdSeq,
377  const Fw::CmdResponse& response
378  ) override;
379 
381  void seqRunIn_handler(FwIndexType portNum, const Fw::StringBase& filename) override;
382 
384  void pingIn_handler(FwIndexType portNum,
385  U32 key
386  ) override;
387 
389  void tlmWrite_handler(FwIndexType portNum,
390  U32 context
391  ) override;
392 
395 
398 
401 
404 
407 
410 
413 
416 
419 
422  const Svc::FpySequencer_DeserSerRegDirective& directive) override;
423 
426 
429  const Svc::FpySequencer_BinaryRegOpDirective& directive) override;
430 
433 
436 
437  void parametersLoaded() override;
438  void parameterUpdated(FwPrmIdType id) override;
439 
440  public:
441  void allocateBuffer(FwEnumStoreType identifier, Fw::MemAllocator& allocator, FwSizeType bytes);
442 
443  void deallocateBuffer(Fw::MemAllocator& allocator);
444 
445  private:
446  static constexpr U32 CRC_INITIAL_VALUE = 0xFFFFFFFFU;
447 
448  // allocated at startup
449  Fw::ExternalSerializeBuffer m_sequenceBuffer;
450  // id of allocator that gave us m_sequenceBuffer
451  FwEnumStoreType m_allocatorId;
452 
453  // assigned by the user via cmd
454  Fw::String m_sequenceFilePath;
455  // the sequence, loaded in memory
456  Fpy::Sequence m_sequenceObj;
457  // live running computation of CRC (updated as we read)
458  U32 m_computedCRC;
459 
460  // whether or not the sequence we're about to run should return immediately or
461  // block on completion
462  FpySequencer_BlockState m_sequenceBlockState;
463  // if we are to block on completion, save the opCode and cmdSeq we should
464  // return
465  FwOpcodeType m_savedOpCode;
466  U32 m_savedCmdSeq;
467 
468  // the goal state is the state that we're trying to reach in the sequencer
469  // if it's RUNNING, then we should promptly go to RUNNING once we validate the
470  // sequence. if it's VALID, we should wait after VALIDATING
471  FpySequencer_GoalState m_goalState;
472 
473  // the total number of sequences this sequencer has started since construction
474  U64 m_sequencesStarted;
475  // the total number of statements this sequencer has dispatched, successfully or
476  // otherwise, since construction
477  U64 m_statementsDispatched;
478 
479  // the runtime state of the sequence. encapsulates all state
480  // needed to run the sequence.
481  // this is distinct from the state of the sequencer. the
482  // sequencer and all its state is really just a shell to load
483  // and execute this runtime.
484  struct Runtime {
485  // the index of the next statement to be executed
486  U32 nextStatementIndex = 0;
487 
488  // the opcode of the statement that is currently executing
489  U8 currentStatementOpcode = Fpy::DirectiveId::INVALID;
490  // the opcode of the command that we are currently awaiting, or 0 if we are executing a directive
491  FwOpcodeType currentCmdOpcode = 0;
492  // the time we dispatched the statement that is currently executing
493  Fw::Time currentStatementDispatchTime = Fw::Time();
494 
495  // the absolute time we should wait for until returning
496  // a statement response
497  Fw::Time wakeupTime = Fw::Time();
498 
499  // all the serializable registers in the sequence
501  // the value buffer of the serReg
503  // the size of the data in the serReg buf
505  } serRegs[Fpy::NUM_SERIALIZABLE_REGISTERS] = {};
506 
507  // all the regs in the sequence. regs are 8 byte
508  // values of unspecified type
509  I64 regs[Fpy::NUM_REGISTERS] = {0};
510 
511  } m_runtime;
512 
513  // the state of the debugger. debugger is separate from runtime
514  // because it can be set up before running the sequence.
515  struct Debug {
516  // whether or not to break at the debug breakpoint index
517  bool breakOnBreakpoint = false;
518  // whether or not to remove the breakpoint after breaking on it
519  bool breakOnlyOnceOnBreakpoint = false;
520  // the statement index at which to break, before dispatching
521  U32 breakpointIndex = 0;
522  } m_debug;
523 
524  struct Telemetry {
525  // the number of statements that failed to execute
526  U64 statementsFailed = 0;
527 
528  // the number of sequences successfully completed
529  U64 sequencesSucceeded = 0;
530 
531  // the number of sequences that failed to validate or execute
532  U64 sequencesFailed = 0;
533 
534  // the number of sequences that have been cancelled
535  U64 sequencesCancelled = 0;
536 
537  // the error code of the last directive that ran
538  DirectiveError lastDirectiveError = DirectiveError::NO_ERROR;
539  } m_tlm;
540 
541  // ----------------------------------------------------------------------
542  // Validation state
543  // ----------------------------------------------------------------------
544 
545  static void updateCrc(U32& crc,
546  const U8* buffer,
547  FwSizeType bufferSize
548  );
549 
550  // loads the sequence in memory, and does header/crc/integrity checks.
551  // return success if sequence is valid
552  Fw::Success validate();
553  // reads and validates the header from the m_sequenceBuffer
554  // return success if header is valid
555  Fw::Success readHeader();
556  // reads and validates the body from the m_sequenceBuffer
557  // return success if body is valid
558  Fw::Success readBody();
559  // reads and validates the footer from the m_sequenceBuffer
560  // return success if footer is valid
561  Fw::Success readFooter();
562 
563  // reads some bytes from the open file into the m_sequenceBuffer.
564  // updates the CRC by default, but can be turned off if the contents
565  // aren't included in CRC.
566  // return success if successful
567  Fw::Success readBytes(Os::File& file,
568  FwSizeType readLen,
569  const FpySequencer_FileReadStage& readStage,
570  bool updateCrc = true);
571 
572  // ----------------------------------------------------------------------
573  // Run state
574  // ----------------------------------------------------------------------
575 
576  // dispatches the next statement
577  Signal dispatchStatement();
578 
579  // deserializes a directive from bytes into the Fpy type
580  // returns success if able to deserialize, and returns the Fpy type object
581  // as a reference, in a union of all the possible directive type objects
582  Fw::Success deserializeDirective(const Fpy::Statement& stmt, DirectiveUnion& deserializedDirective);
583 
584  // dispatches a deserialized sequencer directive to the right handler.
585  void dispatchDirective(const DirectiveUnion& directive, const Fpy::DirectiveId& id);
586 
587  // checks whether the currently executing statement timed out
588  Signal checkStatementTimeout();
589 
590  // checks whether the sequencer should wake from sleeping
591  Signal checkShouldWake();
592 
593  // return true if state is a substate of RUNNING
594  bool isRunningState(State state);
595 
596  // return a struct containing debug telemetry, or defaults if not in debug break
597  FpySequencer_DebugTelemetry getDebugTelemetry();
598 
599  // ----------------------------------------------------------------------
600  // Directives
601  // ----------------------------------------------------------------------
602 
603  // sends a signal based on a signal id
604  void sendSignal(Signal signal);
605 
606  // helper function to get a reference to a register from an index
607  // saves a bunch of typing
608  I64& reg(U8 idx);
609 
610  // we split these functions up into the internalInterfaceInvoke and these custom member funcs
611  // so that we can unit test them easier
612  Signal waitRel_directiveHandler(const FpySequencer_WaitRelDirective& directive, DirectiveError& error);
613  Signal waitAbs_directiveHandler(const FpySequencer_WaitAbsDirective& directive, DirectiveError& error);
614  Signal setSerReg_directiveHandler(const FpySequencer_SetSerRegDirective& directive, DirectiveError& error);
615  Signal goto_directiveHandler(const FpySequencer_GotoDirective& directive, DirectiveError& error);
616  Signal if_directiveHandler(const FpySequencer_IfDirective& directive, DirectiveError& error);
617  Signal noOp_directiveHandler(const FpySequencer_NoOpDirective& directive, DirectiveError& error);
618  Signal getTlm_directiveHandler(const FpySequencer_GetTlmDirective& directive, DirectiveError& error);
619  Signal getPrm_directiveHandler(const FpySequencer_GetPrmDirective& directive, DirectiveError& error);
620  Signal cmd_directiveHandler(const FpySequencer_CmdDirective& directive, DirectiveError& error);
621  Signal deserSerReg_directiveHandler(const FpySequencer_DeserSerRegDirective& directive, DirectiveError& error);
622  Signal setReg_directiveHandler(const FpySequencer_SetRegDirective& directive, DirectiveError& error);
623 
624  Signal binaryRegOp_directiveHandler(const FpySequencer_BinaryRegOpDirective& directive, DirectiveError& error);
625  I64 binaryRegOp_or(I64 lhs, I64 rhs);
626  I64 binaryRegOp_and(I64 lhs, I64 rhs);
627  I64 binaryRegOp_ieq(I64 lhs, I64 rhs);
628  I64 binaryRegOp_ine(I64 lhs, I64 rhs);
629  I64 binaryRegOp_ult(I64 lhs, I64 rhs);
630  I64 binaryRegOp_ule(I64 lhs, I64 rhs);
631  I64 binaryRegOp_ugt(I64 lhs, I64 rhs);
632  I64 binaryRegOp_uge(I64 lhs, I64 rhs);
633  I64 binaryRegOp_slt(I64 lhs, I64 rhs);
634  I64 binaryRegOp_sle(I64 lhs, I64 rhs);
635  I64 binaryRegOp_sgt(I64 lhs, I64 rhs);
636  I64 binaryRegOp_sge(I64 lhs, I64 rhs);
637  I64 binaryRegOp_feq(I64 lhs, I64 rhs);
638  I64 binaryRegOp_fne(I64 lhs, I64 rhs);
639  I64 binaryRegOp_flt(I64 lhs, I64 rhs);
640  I64 binaryRegOp_fle(I64 lhs, I64 rhs);
641  I64 binaryRegOp_fgt(I64 lhs, I64 rhs);
642  I64 binaryRegOp_fge(I64 lhs, I64 rhs);
643 
644  Signal unaryRegOp_directiveHandler(const FpySequencer_UnaryRegOpDirective& directive, DirectiveError& error);
645  I64 unaryRegOp_not(I64 src);
646  I64 unaryRegOp_fpext(I64 src);
647  I64 unaryRegOp_fptrunc(I64 src);
648  I64 unaryRegOp_fptoui(I64 src);
649  I64 unaryRegOp_fptosi(I64 src);
650  I64 unaryRegOp_sitofp(I64 src);
651  I64 unaryRegOp_uitofp(I64 src);
652 
653  Signal exit_directiveHandler(const FpySequencer_ExitDirective& directive, DirectiveError& error);
654 };
655 
656 } // namespace Svc
657 
658 #endif
FpySequencer_SetSerRegDirective setSerReg
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:212
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:227
void allocateBuffer(FwEnumStoreType identifier, Fw::MemAllocator &allocator, FwSizeType bytes)
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:53
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