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