GCC Code Coverage Report


Directory: ./
File: Svc/CmdSequencer/CmdSequencerImpl.hpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 13 13 100.0%
Functions: 5 5 100.0%
Branches: 7 8 87.5%

Line Branch Exec Source
1 // ======================================================================
2 // \title CmdSequencerImpl.hpp
3 // \author Bocchino/Canham
4 // \brief hpp file for CmdSequencer component implementation class
5 //
6 // Copyright (C) 2009-2018 California Institute of Technology.
7 // ALL RIGHTS RESERVED. United States Government Sponsorship
8 // acknowledged.
9 // ======================================================================
10
11 #ifndef Svc_CmdSequencerImpl_HPP
12 #define Svc_CmdSequencerImpl_HPP
13
14 #include <Utils/Hash/Hash.hpp>
15 #include "Fw/Com/ComBuffer.hpp"
16 #include "Fw/Types/MemAllocator.hpp"
17 #include "Os/File.hpp"
18 #include "Os/ValidateFile.hpp"
19 #include "Svc/CmdSequencer/CmdSequencerComponentAc.hpp"
20 #include "Svc/Seq/BlockStateEnumAc.hpp"
21
22 namespace Svc {
23
24 // Forward declaration for UTs
25 namespace ImmediateBase {
26 class CmdSequencerTester;
27 }
28 namespace Immediate {
29 class CmdSequencerTester;
30 }
31 namespace ImmediateEOS {
32 class CmdSequencerTester;
33 }
34 namespace Mixed {
35 class CmdSequencerTester;
36 }
37 namespace MixedRelativeBase {
38 class CmdSequencerTester;
39 }
40 namespace Relative {
41 class CmdSequencerTester;
42 }
43 namespace JoinWait {
44 class CmdSequencerTester;
45 }
46
47 class CmdSequencerComponentImpl final : public CmdSequencerComponentBase {
48 friend class CmdSequencerTester;
49 friend class Svc::ImmediateBase::CmdSequencerTester;
50 friend class Svc::Immediate::CmdSequencerTester;
51 friend class Svc::ImmediateEOS::CmdSequencerTester;
52 friend class Svc::Mixed::CmdSequencerTester;
53 friend class Svc::MixedRelativeBase::CmdSequencerTester;
54 friend class Svc::Relative::CmdSequencerTester;
55 friend class Svc::JoinWait::CmdSequencerTester;
56
57 private:
58 // ----------------------------------------------------------------------
59 // Private enumerations
60 // ----------------------------------------------------------------------
61
62 //! The run mode
63 enum RunMode { STOPPED, RUNNING };
64
65 //! The step mode
66 enum StepMode { AUTO, MANUAL };
67
68 public:
69 // ----------------------------------------------------------------------
70 // Public classes
71 // ----------------------------------------------------------------------
72
73 //! \class Sequence
74 //! \brief A sequence with unspecified binary format
75 class Sequence {
76 public:
77 //! \class Events
78 //! \brief Sequence event reporting
79 class Events {
80 public:
81 //! Construct an Events object
82 Events(Sequence& sequence //!< The enclosing sequence
83 );
84
85 public:
86 //! File CRC failure
87 void fileCRCFailure(const U32 storedCRC, //!< The CRC stored in the file
88 const U32 computedCRC //!< The CRC computed over the file
89 );
90
91 //! File invalid
92 void fileInvalid(const CmdSequencer_FileReadStage::t stage, //!< The file read stage
93 const I32 error //!< The error
94 );
95
96 //! File not found
97 void fileNotFound();
98
99 //! File read error
100 void fileReadError();
101
102 //! File size error
103 void fileSizeError(const U32 size //!< The size
104 );
105
106 //! Record invalid
107 void recordInvalid(const U32 recordNumber, //!< The record number
108 const I32 error //!< The error
109 );
110
111 //! Record mismatch
112 void recordMismatch(const U32 numRecords, //!< The number of records in the header
113 const U32 extraBytes //!< The number of bytes beyond last record
114 );
115
116 //! Time base mismatch
117 void timeBaseMismatch(const TimeBase currTimeBase, //!< The current time base
118 const TimeBase seqTimeBase //!< The sequence file time base
119 );
120
121 //! Time context mismatch
122 void timeContextMismatch(const FwTimeContextStoreType currTimeContext, //!< The current time context
123 const FwTimeContextStoreType seqTimeContext //!< The sequence file time context
124 );
125
126 // No Records
127 void noRecords();
128
129 private:
130 //! The enclosing component
131 Sequence& m_sequence;
132 };
133
134 public:
135 //! Construct a Sequence object
136 Sequence(CmdSequencerComponentImpl& component //!< The enclosing component
137 );
138
139 //! Destroy a Sequence object
140 virtual ~Sequence();
141
142 public:
143 //! \class Header
144 //! \brief A sequence header
145 class Header {
146 public:
147 enum Constants {
148 //! Serialized size of header
149 SERIALIZED_SIZE =
150 sizeof(U32) + sizeof(U32) + sizeof(FwTimeBaseStoreType) + sizeof(FwTimeContextStoreType)
151 };
152
153 public:
154 //! Construct a Header object
155 Header();
156
157 public:
158 //! Validate the time field of the sequence header
159 //! \return Success or failure
160 bool validateTime(CmdSequencerComponentImpl& component //!< Component for time and events
161 );
162
163 public:
164 //! The file size
165 U32 m_fileSize;
166
167 //! The number of records in the sequence
168 U32 m_numRecords;
169
170 //! The time base of the sequence
171 TimeBase m_timeBase;
172
173 //! The context of the sequence
174 FwTimeContextStoreType m_timeContext;
175 };
176
177 public:
178 //! \class Record
179 //! \brief A sequence record
180 class Record {
181 public:
182 enum Descriptor {
183 ABSOLUTE, //!< Absolute time
184 RELATIVE, //!< Relative time
185 END_OF_SEQUENCE //!< end of sequence
186 };
187
188 public:
189 //! Construct a Record object
190
1/1
✓ Branch 9 taken 167 times.
167 Record() : m_descriptor(END_OF_SEQUENCE) {}
191
192 public:
193 //! The descriptor
194 Descriptor m_descriptor;
195
196 //! The time tag. NOTE: timeBase and context not filled in
197 Fw::Time m_timeTag;
198
199 //! The command
200 Fw::ComBuffer m_command;
201 };
202
203 public:
204 //! Give the sequence representation a memory buffer
205 void allocateBuffer(FwEnumStoreType identifier, //!< The identifier
206 Fw::MemAllocator& allocator, //!< The allocator
207 FwSizeType bytes //!< The number of bytes
208 );
209
210 //! Deallocate the buffer
211 void deallocateBuffer(Fw::MemAllocator& allocator //!< The allocator
212 );
213
214 //! Set the file name. Also sets the log file name.
215 void setFileName(const Fw::ConstStringBase& fileName);
216
217 //! Get the file name
218 //! \return The file name
219 Fw::CmdStringArg& getFileName();
220
221 //! Get the log file name
222 //! \return The log file name
223 Fw::LogStringArg& getLogFileName();
224
225 //! Get the normal string file name
226 //! \return The normal string file name
227 Fw::String& getStringFileName();
228
229 //! Get the sequence header
230 const Header& getHeader() const;
231
232 //! Load a sequence file
233 //! \return Success or failure
234 virtual bool loadFile(const Fw::ConstStringBase& fileName //!< The file name
235 ) = 0;
236
237 //! Query whether the sequence has any more records
238 //! \return Yes or no
239 virtual bool hasMoreRecords() const = 0;
240
241 //! Get the next record in the sequence
242 //! Asserts on failure
243 virtual void nextRecord(Record& record //!< The returned record
244 ) = 0;
245
246 //! Reset the sequence to the beginning.
247 //! After calling this, hasMoreRecords should return true,
248 //! unless the sequence has no records
249 virtual void reset() = 0;
250
251 //! Clear the sequence records.
252 //! After calling this, hasMoreRecords should return false
253 virtual void clear() = 0;
254
255 protected:
256 //! The enclosing component
257 CmdSequencerComponentImpl& m_component;
258
259 //! Event reporting
260 Events m_events;
261
262 //! The sequence file name
263 Fw::CmdStringArg m_fileName;
264
265 //! Copy of file name for events
266 Fw::LogStringArg m_logFileName;
267
268 //! Copy of file name for ports
269 Fw::String m_stringFileName;
270
271 //! Serialize buffer to hold the binary sequence data
272 Fw::ExternalSerializeBuffer m_buffer;
273
274 //! The allocator ID
275 FwEnumStoreType m_allocatorId;
276
277 //! The sequence header
278 Header m_header;
279 };
280
281 //! \class FPrimeSequence
282 //! \brief A sequence that uses the F Prime binary format
283 class FPrimeSequence : public Sequence {
284 private:
285 enum Constants { INITIAL_COMPUTED_VALUE = 0xFFFFFFFFU };
286
287 public:
288 //! \class CRC
289 //! \brief Container for computed and stored CRC values
290 struct CRC {
291 //! Construct a CRC
292 CRC();
293
294 //! Initialize computed CRC
295 void init();
296
297 //! Update computed CRC
298 void update(const BYTE* buffer, //!< The buffer
299 FwSizeType bufferSize //!< The buffer size
300 );
301
302 //! Return the finalized CRC
303 U32 finalize();
304
305 //! Computed CRC
306 Utils::Hash m_computed;
307
308 //! Stored CRC
309 U32 m_stored;
310 };
311
312 public:
313 //! Construct an FPrimeSequence
314 FPrimeSequence(CmdSequencerComponentImpl& component //!< The enclosing component
315 );
316
317 public:
318 //! Load a sequence file
319 //! \return Success or failure
320 bool loadFile(const Fw::ConstStringBase& fileName //!< The file name
321 );
322
323 //! Query whether the sequence has any more records
324 //! \return Yes or no
325 bool hasMoreRecords() const;
326
327 //! Get the next record in the sequence.
328 //! Asserts on failure
329 void nextRecord(Record& record //!< The returned record
330 );
331
332 //! Reset the sequence to the beginning.
333 //! After calling this, hasMoreRecords should return true, unless
334 //! the sequence has no records.
335 void reset();
336
337 //! Clear the sequence records.
338 //! After calling this, hasMoreRecords should return false.
339 void clear();
340
341 private:
342 //! Read a sequence file
343 //! \return Success or failure
344 bool readFile();
345
346 //! Read an open sequence file
347 //! \return Success or failure
348 bool readOpenFile();
349
350 //! Read a binary sequence header from the sequence file
351 //! into the buffer
352 //! \return Success or failure
353 bool readHeader();
354
355 //! Deserialize the binary sequence header from the buffer
356 //! \return Success or failure
357 bool deserializeHeader();
358
359 //! Read records and CRC into buffer
360 //! \return Success or failure
361 bool readRecordsAndCRC();
362
363 //! Extract CRC from record data
364 //! \return Success or failure
365 bool extractCRC();
366
367 //! Validate the CRC
368 //! \return Success or failure
369 bool validateCRC();
370
371 //! Deserialize a record from a buffer
372 //! \return Serialize status
373 Fw::SerializeStatus deserializeRecord(Record& record //!< The record
374 );
375
376 //! Deserialize a record descriptor
377 //! \return Serialize status
378 Fw::SerializeStatus deserializeDescriptor(Record::Descriptor& descriptor //!< The descriptor
379 );
380
381 //! Deserialize a time tag
382 //! \return Serialize status
383 Fw::SerializeStatus deserializeTimeTag(Fw::Time& timeTag //!< The time tag
384 );
385
386 //! Deserialize the record size
387 //! \return Serialize status
388 Fw::SerializeStatus deserializeRecordSize(U32& recordSize //!< The record size
389 );
390
391 //! Copy the serialized command into a com buffer
392 //! \return Serialize status
393 Fw::SerializeStatus copyCommand(Fw::ComBuffer& comBuffer, //!< The com buffer
394 const U32 recordSize //!< The record size
395 );
396
397 //! Validate the sequence records in the buffer
398 //! \return Success or failure
399 bool validateRecords();
400
401 private:
402 //! The CRC values
403 CRC m_crc;
404
405 //! The sequence file
406 Os::File m_sequenceFile;
407 };
408
409 private:
410 // ----------------------------------------------------------------------
411 // Private classes
412 // ----------------------------------------------------------------------
413
414 //! \class Timer
415 //! \brief A class representing a timer
416 class Timer {
417 friend class CmdSequencerTester;
418 friend class Svc::ImmediateBase::CmdSequencerTester;
419 friend class Svc::Immediate::CmdSequencerTester;
420 friend class Svc::ImmediateEOS::CmdSequencerTester;
421 friend class Svc::Mixed::CmdSequencerTester;
422 friend class Svc::MixedRelativeBase::CmdSequencerTester;
423 friend class Svc::Relative::CmdSequencerTester;
424 friend class Svc::JoinWait::CmdSequencerTester;
425
426 private:
427 //! The timer state
428 typedef enum { SET, CLEAR } State;
429
430 public:
431 //! Construct a Timer object
432 148 Timer() : m_state(CLEAR) {}
433
434 //! Set the expiration time
435 127 void set(Fw::Time time //!< The time
436 ) {
437 127 this->m_state = SET;
438 127 this->expirationTime = time;
439 127 }
440
441 //! Clear the timer
442 148 void clear() { this->m_state = CLEAR; }
443
444 //! Determine whether the timer is expired at a given time
445 //! \return Yes or no
446 42 bool isExpiredAt(Fw::Time time //!< The time
447 ) {
448
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 22 times.
42 if (this->m_state == CLEAR) {
449 20 return false;
450
3/3
✓ Branch 5 taken 22 times.
✓ Branch 14 taken 9 times.
✓ Branch 15 taken 13 times.
22 } else if (Fw::Time::compare(this->expirationTime, time) == Fw::TimeComparison::GT) {
451 9 return false;
452 }
453 13 return true;
454 }
455
456 private:
457 //! The timer state
458 State m_state;
459
460 //! The expiration time
461 Fw::Time expirationTime;
462 };
463
464 public:
465 // ----------------------------------------------------------------------
466 // Construction, initialization, and destruction
467 // ----------------------------------------------------------------------
468
469 //! Construct a CmdSequencer
470 CmdSequencerComponentImpl(const char* compName //!< The component name
471 );
472
473 //! (Optional) Set a timeout.
474 //! Sequence will quit if a command takes longer than the number of
475 //! seconds in the timeout value.
476 void setTimeout(const U32 seconds //!< The number of seconds
477 );
478
479 //! (Optional) Set the sequence format.
480 //! CmdSequencer will use the sequence object you pass in
481 //! to load and run sequences. By default, it uses an FPrimeSequence
482 //! object.
483 void setSequenceFormat(Sequence& sequence //!< The sequence object
484 );
485
486 //! Give the sequence a memory buffer.
487 //! Call this after constructor and init, and after setting
488 //! the sequence format, but before task is spawned.
489 void allocateBuffer(const FwEnumStoreType identifier, //!< The identifier
490 Fw::MemAllocator& allocator, //!< The allocator
491 const FwSizeType bytes //!< The number of bytes
492 );
493
494 //! (Optional) Load a sequence to run later.
495 //! When you call this function, the event ports must be connected.
496 void loadSequence(const Fw::ConstStringBase& fileName //!< The file name
497 );
498
499 //! Return allocated buffer. Call during shutdown.
500 void deallocateBuffer(Fw::MemAllocator& allocator //!< The allocator
501 );
502
503 //! Destroy a CmdDispatcherComponentBase
504 ~CmdSequencerComponentImpl();
505
506 private:
507 // ----------------------------------------------------------------------
508 // Handler implementations for input ports
509 // ----------------------------------------------------------------------
510
511 //! Handler for input port cmdResponseIn
512 void cmdResponseIn_handler(FwIndexType portNum, //!< The port number
513 FwOpcodeType opcode, //!< The command opcode
514 U32 cmdSeq, //!< The command sequence number
515 const Fw::CmdResponse& response //!< The command response
516 ) override;
517
518 //! Handler for input port schedIn
519 void schedIn_handler(FwIndexType portNum, //!< The port number
520 U32 order //!< The call order
521 ) override;
522
523 //! Handler for input port seqRunIn
524 void seqRunIn_handler(FwIndexType portNum, //!< The port number
525 const Fw::StringBase& filename, //!< The sequence file
526 const Svc::SeqArgs& args //!< Sequence arguments (not currently used)
527 ) override;
528
529 //! Handler implementation for seqDispatchIn
530 //!
531 //! Port for file dispatches to run sequences
532 void seqDispatchIn_handler(FwIndexType portNum, //!< The port number
533 Fw::StringBase& file_name //!< The file to dispatch
534 ) override;
535
536 //! Handler for ping port
537 void pingIn_handler(FwIndexType portNum, //!< The port number
538 U32 key //!< Value to return to pinger
539 ) override;
540
541 //! Handler implementation for seqCancelIn
542 //!
543 void seqCancelIn_handler(const FwIndexType portNum /*!< The port number*/
544 ) override;
545
546 private:
547 // ----------------------------------------------------------------------
548 // Command handler implementations
549 // ----------------------------------------------------------------------
550
551 //! Handler for command CS_AUTO
552 //! Set the run mode to AUTO.
553 void CS_AUTO_cmdHandler(FwOpcodeType opcode, //!< The opcode
554 U32 cmdSeq //!< The command sequence number
555 ) override;
556
557 //! Handler for command CS_CANCEL
558 //! Validate a command sequence file
559 void CS_CANCEL_cmdHandler(FwOpcodeType opCode, //!< The opcode
560 U32 cmdSeq //!< The command sequence number
561 ) override;
562
563 //! Handler for command CS_MANUAL
564 //! Set the run mode to MANUAL.
565 void CS_MANUAL_cmdHandler(FwOpcodeType opcode, //!< The opcode
566 U32 cmdSeq //!< The command sequence number
567 ) override;
568
569 //! Handler for command CS_RUN
570 void CS_RUN_cmdHandler(FwOpcodeType opCode, //!< The opcode
571 U32 cmdSeq, //!< The command sequence number
572 const Fw::CmdStringArg& fileName, //!< The file name
573 const Svc::BlockState& block /*!< Return command status when complete or not*/
574 ) override;
575
576 //! Handler for command CS_START
577 //! Start running a command sequence
578 void CS_START_cmdHandler(FwOpcodeType opcode, //!< The opcode
579 U32 cmdSeq //!< The command sequence number
580 ) override;
581
582 //! Handler for command CS_STEP
583 //! Perform one step in a command sequence.
584 //! Valid only if SequenceRunner is in MANUAL run mode.
585 void CS_STEP_cmdHandler(FwOpcodeType opcode, //!< The opcode
586 U32 cmdSeq //!< The command sequence number
587 ) override;
588
589 //! Handler for command CS_VALIDATE
590 //! Run a command sequence file
591 void CS_VALIDATE_cmdHandler(FwOpcodeType opCode, //!< The opcode
592 U32 cmdSeq, //!< The command sequence number
593 const Fw::CmdStringArg& fileName //!< The name of the sequence file
594 ) override;
595
596 //! Implementation for CS_JOIN command handler
597 //! Wait for sequences that are running to finish.
598 //! Allow user to run multiple seq files in SEQ_NO_BLOCK mode
599 //! then wait for them to finish before allowing more seq run request.
600 void CS_JOIN_WAIT_cmdHandler(const FwOpcodeType opCode, /*!< The opcode*/
601 const U32 cmdSeq /*!< The command sequence number*/
602 ) override;
603
604 private:
605 // ----------------------------------------------------------------------
606 // Private helper methods
607 // ----------------------------------------------------------------------
608
609 //! Load a sequence file
610 //! \return Success or failure
611 bool loadFile(const Fw::ConstStringBase& fileName //!< The file name
612 );
613
614 //! Perform a Cancel command
615 void performCmd_Cancel();
616
617 //! Perform a Step command
618 void performCmd_Step();
619
620 //! Perform a Step command with a relative time
621 void performCmd_Step_RELATIVE(Fw::Time& currentTime //!< The time
622 );
623
624 //! Perform a Step command with an absolute time
625 void performCmd_Step_ABSOLUTE(Fw::Time& currentTime //!< The time
626 );
627
628 //! Record a completed command
629 void commandComplete(const FwOpcodeType opCode //!< The opcode
630 );
631
632 //! Record a sequence complete event
633 void sequenceComplete();
634
635 //! Record an error
636 void error();
637
638 //! Record an error in executing a sequence command
639 void commandError(const U32 number, //!< The command number
640 const FwOpcodeType opCode, //!< The command opcode
641 const U32 error //!< The error code
642 );
643
644 //! Require a run mode
645 //! \return Whether we are in the correct mode
646 bool requireRunMode(RunMode mode //!< The required mode
647 );
648
649 //! Set command timeout timer
650 void setCmdTimeout(const Fw::Time& currentTime //!< The current time
651 );
652
653 //! Sequence run helper
654 void doSequenceRun(const Fw::StringBase& fileName);
655
656 private:
657 // ----------------------------------------------------------------------
658 // Private member variables
659 // ----------------------------------------------------------------------
660
661 //! The F Prime sequence
662 FPrimeSequence m_FPrimeSequence;
663
664 //! The abstract sequence
665 Sequence* m_sequence;
666
667 //! The number of Load commands executed
668 U32 m_loadCmdCount;
669
670 //! The number of Cancel commands executed
671 U32 m_cancelCmdCount;
672
673 //! The number of errors
674 U32 m_errorCount;
675
676 //! The run mode
677 RunMode m_runMode;
678
679 //! The step mode
680 StepMode m_stepMode;
681
682 //! The sequence record currently being processed
683 Sequence::Record m_record;
684
685 //! The command time timer
686 Timer m_cmdTimer;
687
688 //! The number of commands executed in this sequence
689 U32 m_executedCount;
690
691 //! The total number of commands executed across all sequences
692 U32 m_totalExecutedCount;
693
694 //! The total number of sequences completed
695 U32 m_sequencesCompletedCount;
696
697 //! timeout value
698 U32 m_timeout;
699
700 //! timeout timer
701 Timer m_cmdTimeoutTimer;
702
703 //! Block mode for command status
704 Svc::BlockState::t m_blockState;
705 FwOpcodeType m_opCode;
706 U32 m_cmdSeq;
707 bool m_join_waiting;
708
709 //! Telemetry to update sequence not running
710 const Fw::String NO_SEQ{"<no seq>"};
711 };
712
713 } // namespace Svc
714
715 #endif
716