F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
Loading...
Searching...
No Matches
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 {
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
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));
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.
bool isConnected_seqCmdStatus_OutputPort(FwIndexType portNum)
void log_ACTIVITY_HI_TestCmd1Args(I32 arg1, F32 arg2, U8 arg3) const
void log_ACTIVITY_HI_NoOpStringReceived(const Fw::StringBase &message) const
void tlmWrite_CommandErrors(U32 arg, Fw::Time _tlmTime=Fw::Time())
void log_DIAGNOSTIC_OpCodeReregistered(U32 Opcode, I32 port) const
void log_COMMAND_OpCodeDispatched(U32 Opcode, I32 port) const
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
void log_DIAGNOSTIC_OpCodeRegistered(U32 Opcode, I32 port, I32 slot) const
Log event OpCodeRegistered.
void pingOut_out(FwIndexType portNum, U32 key)
Invoke output port pingOut.
void log_WARNING_HI_MalformedCommand(Fw::DeserialStatus Status) const
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) const
CommandDispatcherImpl(const char *name)
Command Dispatcher constructor.
virtual ~CommandDispatcherImpl()
Component destructor.
SerializeStatus
forward declaration for string
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.