diff --git a/Svc/CmdSequencer/CMakeLists.txt b/Svc/CmdSequencer/CMakeLists.txt
index 6b98cf3f05..f6b44958b1 100644
--- a/Svc/CmdSequencer/CMakeLists.txt
+++ b/Svc/CmdSequencer/CMakeLists.txt
@@ -55,6 +55,7 @@ set(UT_SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/test/ut/SequenceFiles/SizeFieldTooSmallFile.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/SequenceFiles/TooLargeFile.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/SequenceFiles/USecFieldTooShortFile.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/test/ut/JoinWait.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/Main.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/Tester.cpp"
)
diff --git a/Svc/CmdSequencer/CmdSequencerImpl.cpp b/Svc/CmdSequencer/CmdSequencerImpl.cpp
index ca1dbf8696..f49c7d3747 100644
--- a/Svc/CmdSequencer/CmdSequencerImpl.cpp
+++ b/Svc/CmdSequencer/CmdSequencerImpl.cpp
@@ -38,7 +38,8 @@ namespace Svc {
m_timeout(0),
m_blockState(SEQ_NO_BLOCK),
m_opCode(0),
- m_cmdSeq(0)
+ m_cmdSeq(0),
+ m_join_waiting(false)
{
}
@@ -98,6 +99,10 @@ namespace Svc {
SeqBlkState block) {
if (not this->requireRunMode(STOPPED)) {
+ if (m_join_waiting) {
+ // Inform user previous seq file is not complete
+ this->log_WARNING_HI_CS_JoinWaitingNotComplete();
+ }
this->cmdResponse_out(opCode, cmdSeq, Fw::COMMAND_EXECUTION_ERROR);
return;
}
@@ -218,6 +223,23 @@ namespace Svc {
this->cmdResponse_out(opCode, cmdSeq, Fw::COMMAND_OK);
}
+ void CmdSequencerComponentImpl::CS_JOIN_WAIT_cmdHandler(
+ const FwOpcodeType opCode, const U32 cmdSeq) {
+
+ // If there is no running sequence do not wait
+ if (m_runMode != RUNNING) {
+ this->log_WARNING_LO_CS_NoSequenceActive();
+ this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_OK);
+ return;
+ } else {
+ m_join_waiting = true;
+ Fw::LogStringArg& logFileName = this->m_sequence->getLogFileName();
+ this->log_ACTIVITY_HI_CS_JoinWaiting(logFileName, m_cmdSeq, m_opCode);
+ m_cmdSeq = cmdSeq;
+ m_opCode = opCode;
+ }
+ }
+
// ----------------------------------------------------------------------
// Private helper methods
// ----------------------------------------------------------------------
@@ -251,7 +273,9 @@ namespace Svc {
this->seqDone_out(0,0,0,Fw::COMMAND_EXECUTION_ERROR);
}
- if (SEQ_BLOCK == this->m_blockState) {
+ if (SEQ_BLOCK == this->m_blockState || m_join_waiting) {
+ // Do not wait if sequence was canceled or a cmd failed
+ this->m_join_waiting = false;
this->cmdResponse_out(this->m_opCode, this->m_cmdSeq, Fw::COMMAND_EXECUTION_ERROR);
}
@@ -446,10 +470,11 @@ namespace Svc {
this->seqDone_out(0,0,0,Fw::COMMAND_OK);
}
- if (SEQ_BLOCK == this->m_blockState) {
+ if (SEQ_BLOCK == this->m_blockState || m_join_waiting) {
this->cmdResponse_out(this->m_opCode, this->m_cmdSeq, Fw::COMMAND_OK);
}
+ m_join_waiting = false;
this->m_blockState = SEQ_NO_BLOCK;
}
diff --git a/Svc/CmdSequencer/CmdSequencerImpl.hpp b/Svc/CmdSequencer/CmdSequencerImpl.hpp
index 2a034f54dd..93e7cbe05d 100644
--- a/Svc/CmdSequencer/CmdSequencerImpl.hpp
+++ b/Svc/CmdSequencer/CmdSequencerImpl.hpp
@@ -679,6 +679,15 @@ namespace Svc {
const Fw::CmdStringArg& fileName //!< The name of the sequence file
);
+ //! Implementation for CS_JOIN command handler
+ //! Wait for sequences that are running to finish.
+ //! Allow user to run multiple seq files in SEQ_NO_BLOCK mode
+ //! then wait for them to finish before allowing more seq run request.
+ void CS_JOIN_WAIT_cmdHandler(
+ const FwOpcodeType opCode, /*!< The opcode*/
+ const U32 cmdSeq /*!< The command sequence number*/
+ );
+
PRIVATE:
// ----------------------------------------------------------------------
@@ -788,7 +797,7 @@ namespace Svc {
SeqBlkState m_blockState;
FwOpcodeType m_opCode;
U32 m_cmdSeq;
-
+ bool m_join_waiting;
};
};
diff --git a/Svc/CmdSequencer/Commands.xml b/Svc/CmdSequencer/Commands.xml
index 116daea188..225510bd12 100755
--- a/Svc/CmdSequencer/Commands.xml
+++ b/Svc/CmdSequencer/Commands.xml
@@ -48,4 +48,7 @@ acknowledged.
Set the run mode to MANUAL.
+
+ Wait for sequences that are running to finish. Allow user to run multiple seq files in SEQ_NO_BLOCK mode then wait for them to finish before allowing more seq run request.
+
diff --git a/Svc/CmdSequencer/Events.xml b/Svc/CmdSequencer/Events.xml
index d7feafd8b4..38ec11c60c 100755
--- a/Svc/CmdSequencer/Events.xml
+++ b/Svc/CmdSequencer/Events.xml
@@ -285,4 +285,26 @@ acknowledged.
+
+ Wait for the current running sequence file complete
+
+
+
+ The name of the sequence file
+
+
+ The record number
+
+
+ The opcode
+
+
+
+
+
+ Cannot run new sequence when current sequence file is still running.
+
+
diff --git a/Svc/CmdSequencer/test/ut/JoinWait.cpp b/Svc/CmdSequencer/test/ut/JoinWait.cpp
new file mode 100644
index 0000000000..59ee7e9f51
--- /dev/null
+++ b/Svc/CmdSequencer/test/ut/JoinWait.cpp
@@ -0,0 +1,97 @@
+// ======================================================================
+// \title JoinWait.hpp
+// \author janamian
+// \brief cpp file for CmdSequencer test harness implementation class
+//
+// \copyright
+// Copyright 2009-2021, by the California Institute of Technology.
+// ALL RIGHTS RESERVED. United States Government Sponsorship
+// acknowledged.
+//
+// ======================================================================
+
+#include "Svc/CmdSequencer/test/ut/JoinWait.hpp"
+#include "Svc/CmdSequencer/test/ut/Relative.hpp"
+
+namespace Svc {
+
+ namespace JoinWait {
+
+ // ----------------------------------------------------------------------
+ // Constructors
+ // ----------------------------------------------------------------------
+
+ Tester ::
+ Tester(const SequenceFiles::File::Format::t format) :
+ Svc::Tester(format)
+ {
+
+ }
+ // ----------------------------------------------------------------------
+ // Tests
+ // ----------------------------------------------------------------------
+
+ void Tester ::
+ test_join_wait_without_active_seq()
+ {
+ // Send join wait command when there is no active seq
+ this->sendCmd_CS_JOIN_WAIT(0, 0);
+ this->clearAndDispatch();
+ // Assert events
+ ASSERT_EVENTS_SIZE(1);
+ ASSERT_EVENTS_CS_NoSequenceActive_SIZE(1);
+ }
+
+ void Tester ::test_join_wait_with_active_seq() {
+ const U32 numRecords = 1;
+ SequenceFiles::RelativeFile file(numRecords, this->format);
+ // Set the time
+ Fw::Time testTime(TB_WORKSTATION_TIME, 0, 0);
+ this->setTestTime(testTime);
+ // Write the file
+ const char *const fileName = file.getName().toChar();
+ file.write();
+ // Validate the file
+ this->validateFile(0, fileName);
+ // Run the sequence
+ this->runSequence(0, fileName);
+
+ // Assert that timer is set
+ ASSERT_EQ(
+ CmdSequencerComponentImpl::Timer::SET,
+ this->component.m_cmdTimer.m_state
+ );
+
+ // Run one cycle to make sure nothing is dispatched yet
+ this->invoke_to_schedIn(0, 0);
+ this->clearAndDispatch();
+ ASSERT_from_comCmdOut_SIZE(0);
+ ASSERT_EVENTS_SIZE(0);
+
+ // Assert that timer hasn't expired
+ ASSERT_EQ(
+ CmdSequencerComponentImpl::Timer::SET,
+ this->component.m_cmdTimer.m_state
+ );
+
+ // Request join wait
+ this->sendCmd_CS_JOIN_WAIT(0, 0);
+ this->clearAndDispatch();
+ // Make sure JOIN_WAIT is active
+ ASSERT_EVENTS_CS_NoSequenceActive_SIZE(0);
+ ASSERT_TRUE(this->component.m_join_waiting);
+
+ // Send status back
+ this->invoke_to_cmdResponseIn(0, 0, 0, Fw::COMMAND_OK);
+ this->clearAndDispatch();
+
+ // Make sure we received completion for both command and join_wait
+ ASSERT_EVENTS_SIZE(2);
+ // Make sure join wait has been cleared
+ ASSERT_FALSE(this->component.m_join_waiting);
+
+ }
+
+ }
+
+}
diff --git a/Svc/CmdSequencer/test/ut/JoinWait.hpp b/Svc/CmdSequencer/test/ut/JoinWait.hpp
new file mode 100644
index 0000000000..fdc77da958
--- /dev/null
+++ b/Svc/CmdSequencer/test/ut/JoinWait.hpp
@@ -0,0 +1,55 @@
+// ======================================================================
+// \title JoinWait.hpp
+// \author janamian
+// \brief hpp file for CmdSequencer test harness implementation class
+//
+// \copyright
+// Copyright 2009-2021, by the California Institute of Technology.
+// ALL RIGHTS RESERVED. United States Government Sponsorship
+// acknowledged.
+//
+// ======================================================================
+
+#ifndef JOIN_WAIT_HPP
+#define JOIN_WAIT_HPP
+
+#include "Svc/CmdSequencer/test/ut/Tester.hpp"
+
+namespace Svc {
+
+ namespace JoinWait {
+
+ class Tester :
+ public Svc::Tester
+ {
+
+ public:
+
+ // ----------------------------------------------------------------------
+ // Constructors
+ // ----------------------------------------------------------------------
+
+ //! Construct object Tester
+ Tester(
+ const SequenceFiles::File::Format::t format =
+ SequenceFiles::File::Format::F_PRIME //!< The file format to use
+ );
+
+ public:
+
+ // ----------------------------------------------------------------------
+ // Tests
+ // ----------------------------------------------------------------------
+
+ //! Test
+ void test_join_wait_without_active_seq();
+
+ void test_join_wait_with_active_seq();
+
+ };
+
+ }
+
+}
+
+#endif
diff --git a/Svc/CmdSequencer/test/ut/Main.cpp b/Svc/CmdSequencer/test/ut/Main.cpp
index ae6b91a4ba..739becdbd9 100644
--- a/Svc/CmdSequencer/test/ut/Main.cpp
+++ b/Svc/CmdSequencer/test/ut/Main.cpp
@@ -19,6 +19,7 @@
#include "Svc/CmdSequencer/test/ut/Tester.hpp"
#include "Svc/CmdSequencer/test/ut/Mixed.hpp"
#include "Svc/CmdSequencer/test/ut/UnitTest.hpp"
+#include "Svc/CmdSequencer/test/ut/JoinWait.hpp"
TEST(AMPCS, MissingCRC) {
Svc::AMPCS::Tester tester;
@@ -379,6 +380,17 @@ TEST(Relative, ValidateAMPCS) {
tester.Validate();
}
+TEST(JoinWait, JoinWaitNoActiveSeq) {
+ Svc::JoinWait::Tester tester;
+ tester.test_join_wait_without_active_seq();
+}
+
+TEST(JoinWait, JoinWaitWithActiveSeq) {
+ Svc::JoinWait::Tester tester;
+ tester.test_join_wait_with_active_seq();
+}
+
+
int main(int argc, char **argv) {
// Create ./bin directory for test files
Os::FileSystem::createDirectory("./bin");