F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
CommandDispatcherImpl.cpp
Go to the documentation of this file.
1 /*
2  * CommandDispatcherImpl.cpp
3  *
4  * Created on: May 13, 2014
5  * Author: Timothy Canham
6  */
7 
9 #include <Fw/Cmd/CmdPacket.hpp>
10 #include <Fw/Types/Assert.hpp>
11 #include <cstdio>
12 
13 namespace Svc {
16  m_seq(0),
17  m_numCmdsDispatched(0),
18  m_numCmdErrors(0)
19  {
20  memset(this->m_entryTable,0,sizeof(this->m_entryTable));
21  memset(this->m_sequenceTracker,0,sizeof(this->m_sequenceTracker));
22  }
23 
25  }
26 
27  void CommandDispatcherImpl::compCmdReg_handler(NATIVE_INT_TYPE portNum, FwOpcodeType opCode) {
28  // search for an empty slot
29  bool slotFound = false;
30  for (U32 slot = 0; slot < FW_NUM_ARRAY_ELEMENTS(this->m_entryTable); slot++) {
31  if ((not this->m_entryTable[slot].used) and (not slotFound)) {
32  this->m_entryTable[slot].opcode = opCode;
33  this->m_entryTable[slot].port = portNum;
34  this->m_entryTable[slot].used = true;
35  this->log_DIAGNOSTIC_OpCodeRegistered(opCode,portNum,static_cast<I32>(slot));
36  slotFound = true;
37  } else if ((this->m_entryTable[slot].used) &&
38  (this->m_entryTable[slot].opcode == opCode) &&
39  (this->m_entryTable[slot].port == portNum) &&
40  (not slotFound)) {
41  slotFound = true;
42  this->log_DIAGNOSTIC_OpCodeReregistered(opCode,portNum);
43  } else if (this->m_entryTable[slot].used) { // make sure no duplicates
44  FW_ASSERT(this->m_entryTable[slot].opcode != opCode, static_cast<FwAssertArgType>(opCode));
45  }
46  }
47  FW_ASSERT(slotFound,static_cast<FwAssertArgType>(opCode));
48  }
49 
50  void CommandDispatcherImpl::compCmdStat_handler(NATIVE_INT_TYPE portNum, FwOpcodeType opCode, U32 cmdSeq, const Fw::CmdResponse &response) {
51  // check response and log
52  if (Fw::CmdResponse::OK == response.e) {
53  this->log_COMMAND_OpCodeCompleted(opCode);
54  } else {
55  this->m_numCmdErrors++;
56  this->tlmWrite_CommandErrors(this->m_numCmdErrors);
57  FW_ASSERT(response.e != Fw::CmdResponse::OK);
58  this->log_COMMAND_OpCodeError(opCode,response);
59  }
60  // look for command source
61  NATIVE_INT_TYPE portToCall = -1;
62  U32 context;
63  for (U32 pending = 0; pending < FW_NUM_ARRAY_ELEMENTS(this->m_sequenceTracker); pending++) {
64  if (
65  (this->m_sequenceTracker[pending].seq == cmdSeq) &&
66  (this->m_sequenceTracker[pending].used)
67  ) {
68  portToCall = this->m_sequenceTracker[pending].callerPort;
69  context = this->m_sequenceTracker[pending].context;
70  FW_ASSERT(opCode == this->m_sequenceTracker[pending].opCode);
71  FW_ASSERT(portToCall < this->getNum_seqCmdStatus_OutputPorts());
72  this->m_sequenceTracker[pending].used = false;
73  break;
74  }
75  }
76 
77  if (portToCall != -1) {
78  // call port to report status
79  if (this->isConnected_seqCmdStatus_OutputPort(portToCall)) {
80  this->seqCmdStatus_out(portToCall,opCode,context,response);
81  }
82  }
83  }
84 
85  void CommandDispatcherImpl::seqCmdBuff_handler(NATIVE_INT_TYPE portNum, Fw::ComBuffer &data, U32 context) {
86 
87  Fw::CmdPacket cmdPkt;
88  Fw::SerializeStatus stat = cmdPkt.deserialize(data);
89 
90  if (stat != Fw::FW_SERIALIZE_OK) {
91  Fw::DeserialStatus serErr(static_cast<Fw::DeserialStatus::t>(stat));
92  this->log_WARNING_HI_MalformedCommand(serErr);
93  if (this->isConnected_seqCmdStatus_OutputPort(portNum)) {
94  this->seqCmdStatus_out(portNum,cmdPkt.getOpCode(),context,Fw::CmdResponse::VALIDATION_ERROR);
95  }
96  return;
97  }
98 
99  // search for opcode in dispatch table
100  U32 entry;
101  bool entryFound = false;
102 
103  for (entry = 0; entry < FW_NUM_ARRAY_ELEMENTS(this->m_entryTable); entry++) {
104  if ((this->m_entryTable[entry].used) and (cmdPkt.getOpCode() == this->m_entryTable[entry].opcode)) {
105  entryFound = true;
106  break;
107  }
108  }
109  if (entryFound and this->isConnected_compCmdSend_OutputPort(this->m_entryTable[entry].port)) {
110  // register command in command tracker only if response port is connect
111  if (this->isConnected_seqCmdStatus_OutputPort(portNum)) {
112  bool pendingFound = false;
113 
114  for (U32 pending = 0; pending < FW_NUM_ARRAY_ELEMENTS(this->m_sequenceTracker); pending++) {
115  if (not this->m_sequenceTracker[pending].used) {
116  pendingFound = true;
117  this->m_sequenceTracker[pending].used = true;
118  this->m_sequenceTracker[pending].opCode = cmdPkt.getOpCode();
119  this->m_sequenceTracker[pending].seq = this->m_seq;
120  this->m_sequenceTracker[pending].context = context;
121  this->m_sequenceTracker[pending].callerPort = portNum;
122  break;
123  }
124  }
125 
126  // if we couldn't find a slot to track the command, quit
127  if (not pendingFound) {
129  if (this->isConnected_seqCmdStatus_OutputPort(portNum)) {
130  this->seqCmdStatus_out(portNum,cmdPkt.getOpCode(),context,Fw::CmdResponse::EXECUTION_ERROR);
131  }
132  return;
133  }
134  } // end if status port connected
135  // pass arguments to argument buffer
136  this->compCmdSend_out(
137  this->m_entryTable[entry].port,
138  cmdPkt.getOpCode(),
139  this->m_seq,
140  cmdPkt.getArgBuffer());
141  // log dispatched command
142  this->log_COMMAND_OpCodeDispatched(cmdPkt.getOpCode(),this->m_entryTable[entry].port);
143 
144  // increment command count
145  this->m_numCmdsDispatched++;
146  // write telemetry channel for dispatched commands
147  this->tlmWrite_CommandsDispatched(this->m_numCmdsDispatched);
148  } else {
150  this->m_numCmdErrors++;
151  // Fail command back to port, if connected
152  if (this->isConnected_seqCmdStatus_OutputPort(portNum)) {
153  this->seqCmdStatus_out(portNum,cmdPkt.getOpCode(),context,Fw::CmdResponse::INVALID_OPCODE);
154  }
155  this->tlmWrite_CommandErrors(this->m_numCmdErrors);
156  }
157 
158  // increment sequence number
159  this->m_seq++;
160  }
161 
162  void CommandDispatcherImpl::CMD_NO_OP_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
163  Fw::LogStringArg no_op_string("Hello, World!");
164  // Log event for NO_OP here.
166  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::OK);
167  }
168 
169  void CommandDispatcherImpl::CMD_NO_OP_STRING_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, const Fw::CmdStringArg& arg1) {
170  Fw::LogStringArg msg(arg1.toChar());
171  // Echo the NO_OP_STRING args here.
173  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::OK);
174  }
175 
176  void CommandDispatcherImpl::CMD_TEST_CMD_1_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, I32 arg1, F32 arg2, U8 arg3) {
177  this->log_ACTIVITY_HI_TestCmd1Args(arg1,arg2,arg3);
178  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::OK);
179  }
180 
181  void CommandDispatcherImpl::CMD_CLEAR_TRACKING_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
182  // clear tracking table
183  for (NATIVE_INT_TYPE entry = 0; entry < CMD_DISPATCHER_SEQUENCER_TABLE_SIZE; entry++) {
184  this->m_sequenceTracker[entry].used = false;
185  }
186  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::OK);
187  }
188 
189  void CommandDispatcherImpl::pingIn_handler(NATIVE_INT_TYPE portNum, U32 key) {
190  // respond to ping
191  this->pingOut_out(0,key);
192  }
193 
194 }
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:55
float F32
32-bit floating point
Definition: BasicTypes.h:49
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:30
#define FW_NUM_ARRAY_ELEMENTS(a)
number of elements in an array
Definition: BasicTypes.h:70
Component responsible for dispatching incoming commands to registered components.
@ CMD_DISPATCHER_SEQUENCER_TABLE_SIZE
PlatformAssertArgType FwAssertArgType
Definition: FpConfig.h:39
U32 FwOpcodeType
Definition: FpConfig.h:91
FwOpcodeType getOpCode() const
Definition: CmdPacket.cpp:55
SerializeStatus deserialize(SerializeBufferBase &buffer)
deserialize to contents
Definition: CmdPacket.cpp:29
CmdArgBuffer & getArgBuffer()
Definition: CmdPacket.cpp:59
Enum representing a command response.
@ EXECUTION_ERROR
Command had execution error.
@ VALIDATION_ERROR
Command failed validation.
@ OK
Command successfully executed.
@ INVALID_OPCODE
Invalid opcode dispatched.
T e
The raw enum value.
const char * toChar() const
Definition: CmdString.hpp:50
Deserialization status.
Auto-generated base for CommandDispatcher component.
void log_DIAGNOSTIC_OpCodeReregistered(U32 Opcode, I32 port)
bool isConnected_seqCmdStatus_OutputPort(FwIndexType portNum)
void log_ACTIVITY_HI_TestCmd1Args(I32 arg1, F32 arg2, U8 arg3)
void log_DIAGNOSTIC_OpCodeRegistered(U32 Opcode, I32 port, I32 slot)
Log event OpCodeRegistered.
void tlmWrite_CommandErrors(U32 arg, Fw::Time _tlmTime=Fw::Time())
bool isConnected_compCmdSend_OutputPort(FwIndexType portNum)
void log_WARNING_HI_MalformedCommand(Fw::DeserialStatus Status)
void log_ACTIVITY_HI_NoOpStringReceived(const Fw::StringBase &message)
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
void pingOut_out(FwIndexType portNum, U32 key)
Invoke output port pingOut.
void seqCmdStatus_out(FwIndexType portNum, FwOpcodeType opCode, U32 cmdSeq, const Fw::CmdResponse &response)
Invoke output port seqCmdStatus.
void compCmdSend_out(FwIndexType portNum, FwOpcodeType opCode, U32 cmdSeq, Fw::CmdArgBuffer &args)
Invoke output port compCmdSend.
void tlmWrite_CommandsDispatched(U32 arg, Fw::Time _tlmTime=Fw::Time())
void log_COMMAND_OpCodeError(U32 Opcode, Fw::CmdResponse error)
CommandDispatcherImpl(const char *name)
Command Dispatcher constructor.
virtual ~CommandDispatcherImpl()
Component destructor.
SerializeStatus
forward declaration for string
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.