F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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.