F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
SeqDispatcher.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title SeqDispatcher.cpp
3 // \author zimri.leisher
4 // \brief cpp file for SeqDispatcher component implementation class
5 // ======================================================================
6 
8 
9 namespace Svc {
10 
11 // ----------------------------------------------------------------------
12 // Construction, initialization, and destruction
13 // ----------------------------------------------------------------------
14 
15 SeqDispatcher ::SeqDispatcher(const char* const compName)
16  : SeqDispatcherComponentBase(compName) {}
17 
19 
20 FwIndexType SeqDispatcher::getNextAvailableSequencerIdx() {
21  for (FwIndexType i = 0; i < SeqDispatcherSequencerPorts; i++) {
22  if (this->isConnected_seqRunOut_OutputPort(i) &&
23  this->m_entryTable[i].state == SeqDispatcher_CmdSequencerState::AVAILABLE) {
24  return i;
25  }
26  }
27  return -1;
28 }
29 
30 void SeqDispatcher::runSequence(FwIndexType sequencerIdx,
31  const Fw::StringBase& fileName,
32  Fw::Wait block) {
33  // this function is only designed for internal usage
34  // we can guarantee it cannot be called with input that would fail
35  FW_ASSERT(sequencerIdx >= 0 && sequencerIdx < SeqDispatcherSequencerPorts,
36  sequencerIdx);
37  FW_ASSERT(this->isConnected_seqRunOut_OutputPort(sequencerIdx));
38  FW_ASSERT(this->m_entryTable[sequencerIdx].state ==
40  this->m_entryTable[sequencerIdx].state);
41 
42  if (block == Fw::Wait::NO_WAIT) {
43  this->m_entryTable[sequencerIdx].state =
45  } else {
46  this->m_entryTable[sequencerIdx].state =
48  }
49 
50  this->m_sequencersAvailable--;
51  this->tlmWrite_sequencersAvailable(this->m_sequencersAvailable);
52  this->m_entryTable[sequencerIdx].sequenceRunning = fileName;
53 
54  this->m_dispatchedCount++;
55  this->tlmWrite_dispatchedCount(this->m_dispatchedCount);
56  this->seqRunOut_out(sequencerIdx,
57  this->m_entryTable[sequencerIdx].sequenceRunning);
58 }
59 
61  NATIVE_INT_TYPE portNum,
62  const Fw::StringBase& fileName
63 ) {
64  FW_ASSERT(portNum >= 0 && portNum < SeqDispatcherSequencerPorts, portNum);
65  if (this->m_entryTable[portNum].state ==
67  this->m_entryTable[portNum].state ==
69  // we were aware of this sequencer running a sequence
70  if (this->m_entryTable[portNum].sequenceRunning != fileName) {
71  // uh oh. entry table is wrong
72  // let's just update it to be correct. nothing we can do about
73  // it except raise a warning and update our state
74  this->log_WARNING_HI_ConflictingSequenceStarted(static_cast<U16>(portNum), fileName, this->m_entryTable[portNum].sequenceRunning);
75  this->m_entryTable[portNum].sequenceRunning = fileName;
76  }
77  } else {
78  // we were not aware that this sequencer was running. ground must have
79  // directly commanded that specific sequencer
80 
81  // warn because this may be unintentional
82  this->log_WARNING_LO_UnexpectedSequenceStarted(static_cast<U16>(portNum), fileName);
83 
84  // update the state
85  this->m_entryTable[portNum].state =
87  this->m_entryTable[portNum].sequenceRunning = fileName;
88  this->m_sequencersAvailable--;
89  this->tlmWrite_sequencersAvailable(this->m_sequencersAvailable);
90  }
91 }
92 
94  NATIVE_INT_TYPE portNum,
95  FwOpcodeType opCode,
96  U32 cmdSeq,
97  const Fw::CmdResponse& response
98 ) {
99  FW_ASSERT(portNum >= 0 && portNum < SeqDispatcherSequencerPorts, portNum);
100  if (this->m_entryTable[portNum].state !=
102  this->m_entryTable[portNum].state !=
104  // this sequencer was not running a sequence that we were aware of.
105 
106  // we should have caught this in seqStartIn and updated the state
107  // accordingly, but somehow we didn't? very sad and shouldn't happen
108 
109  // anyways, don't have to do anything cuz now that this seq we didn't know
110  // about is done, the sequencer is available again (which is its current
111  // state in our internal entry table already)
112  this->log_WARNING_LO_UnknownSequenceFinished(static_cast<U16>(portNum));
113  } else {
114  // ok, a sequence has finished that we knew about
115  if (this->m_entryTable[portNum].state ==
117  // we need to give a cmd response cuz some other sequence is being blocked
118  // by this
119  this->cmdResponse_out(this->m_entryTable[portNum].opCode,
120  this->m_entryTable[portNum].cmdSeq, response);
121 
122  if (response == Fw::CmdResponse::EXECUTION_ERROR) {
123  // dispatched sequence errored
124  this->m_errorCount++;
125  this->tlmWrite_errorCount(this->m_errorCount);
126  }
127  }
128  }
129 
130  // all command responses mean the sequence is no longer running
131  // so component should be available
132  this->m_entryTable[portNum].state = SeqDispatcher_CmdSequencerState::AVAILABLE;
133  this->m_entryTable[portNum].sequenceRunning = "<no seq>";
134  this->m_sequencersAvailable++;
135  this->tlmWrite_sequencersAvailable(this->m_sequencersAvailable);
136 }
137 
140  const Fw::StringBase& fileName) {
141  FwIndexType idx = this->getNextAvailableSequencerIdx();
142  // no available sequencers
143  if (idx == -1) {
145  return;
146  }
147 
148  this->runSequence(idx, fileName, Fw::Wait::NO_WAIT);
149 }
150 // ----------------------------------------------------------------------
151 // Command handler implementations
152 // ----------------------------------------------------------------------
153 
154 void SeqDispatcher ::RUN_cmdHandler(const FwOpcodeType opCode,
155  const U32 cmdSeq,
156  const Fw::CmdStringArg& fileName,
157  Fw::Wait block) {
158  FwIndexType idx = this->getNextAvailableSequencerIdx();
159  // no available sequencers
160  if (idx == -1) {
162  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
163  return;
164  }
165 
166  this->runSequence(idx, fileName, block);
167 
168  if (block == Fw::Wait::NO_WAIT) {
169  // return instantly
170  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
171  } else {
172  // otherwise don't return a response yet. just save the opCode and cmdSeq
173  // so we can return a response later
174  this->m_entryTable[idx].opCode = opCode;
175  this->m_entryTable[idx].cmdSeq = cmdSeq;
176  }
177 }
178 
179 void SeqDispatcher::LOG_STATUS_cmdHandler(
180  const FwOpcodeType opCode,
181  const U32 cmdSeq) {
182  for(FwIndexType idx = 0; idx < SeqDispatcherSequencerPorts; idx++) {
183  this->log_ACTIVITY_LO_LogSequencerStatus(static_cast<U16>(idx), this->m_entryTable[idx].state, Fw::LogStringArg(this->m_entryTable[idx].sequenceRunning));
184  }
185 }
186 } // end namespace components
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:55
U32 FwOpcodeType
Definition: FpConfig.h:91
PlatformIndexType FwIndexType
Definition: FpConfig.h:25
@ SeqDispatcherSequencerPorts
Enum representing a command response.
@ EXECUTION_ERROR
Command had execution error.
@ OK
Command successfully executed.
Wait or don't wait for something.
Definition: WaitEnumAc.hpp:19
Auto-generated base for SeqDispatcher component.
void log_WARNING_LO_UnexpectedSequenceStarted(U16 idx, const Fw::StringBase &newSequence)
Log event UnexpectedSequenceStarted.
void tlmWrite_errorCount(U32 arg, Fw::Time _tlmTime=Fw::Time())
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
void log_WARNING_HI_ConflictingSequenceStarted(U16 idx, const Fw::StringBase &newSequence, const Fw::StringBase &sequenceInInternalState)
Log event ConflictingSequenceStarted.
void tlmWrite_dispatchedCount(U32 arg, Fw::Time _tlmTime=Fw::Time())
void log_WARNING_HI_NoAvailableSequencers()
Log event NoAvailableSequencers.
void log_ACTIVITY_LO_LogSequencerStatus(U16 idx, Svc::SeqDispatcher_CmdSequencerState state, const Fw::StringBase &filename)
Log event LogSequencerStatus.
bool isConnected_seqRunOut_OutputPort(FwIndexType portNum)
void seqRunOut_out(FwIndexType portNum, const Fw::StringBase &filename)
Invoke output port seqRunOut.
void log_WARNING_LO_UnknownSequenceFinished(U16 idx)
Log event UnknownSequenceFinished.
void tlmWrite_sequencersAvailable(U32 arg, Fw::Time _tlmTime=Fw::Time())
void seqDoneIn_handler(NATIVE_INT_TYPE portNum, FwOpcodeType opCode, U32 cmdSeq, const Fw::CmdResponse &response)
Handler for input port seqDoneIn.
void seqStartIn_handler(NATIVE_INT_TYPE portNum, const Fw::StringBase &fileName)
Handler for input port seqStartIn.
void seqRunIn_handler(NATIVE_INT_TYPE portNum, const Fw::StringBase &fileName)
Handler for input port seqRunIn.
SeqDispatcher(const char *const compName)