GCC Code Coverage Report


Directory: Svc/CmdDispatcher/
File: CommandDispatcherImpl.cpp
Date: 2026-09-03 21:16:43
Exec Total Coverage
Lines: 97 100 97.0%
Functions: 11 12 91.7%
Branches: 86 94 91.5%

Line Branch Exec Source
1 /*
2 * CommandDispatcherImpl.cpp
3 *
4 * Created on: May 13, 2014
5 * Author: Timothy Canham
6 */
7
8 #include <Fw/Cmd/CmdPacket.hpp>
9 #include <Fw/Types/Assert.hpp>
10 #include <Svc/CmdDispatcher/CommandDispatcherImpl.hpp>
11 #include <cstdio>
12 #include <cstring>
13
14 // Check the CMD_DISPATCHER_DISPATCH_TABLE_SIZE and CMD_DISPATCHER_SEQUENCER_TABLE_SIZE for overflow
15 static_assert(CMD_DISPATCHER_DISPATCH_TABLE_SIZE <= std::numeric_limits<FwOpcodeType>::max(),
16 "Opcode table limited to opcode range");
17 static_assert(CMD_DISPATCHER_SEQUENCER_TABLE_SIZE <= std::numeric_limits<U32>::max(),
18 "Sequencer table limited to range of U32");
19
20 namespace Svc {
21 10 CommandDispatcherImpl::CommandDispatcherImpl(const char* name)
22
2/2
✓ Branch 9 taken 10 times.
✓ Branch 15 taken 10 times.
10 : CommandDispatcherComponentBase(name), m_seq(0), m_numCmdsDispatched(0), m_numCmdErrors(0), m_numCmdsDropped(0) {}
23
24 20 CommandDispatcherImpl::~CommandDispatcherImpl() {}
25
26 45 void CommandDispatcherImpl::compCmdReg_handler(FwIndexType portNum, FwOpcodeType opCode) {
27 45 FwIndexType existingPort;
28
3/3
✓ Branch 4 taken 45 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 44 times.
45 if (this->m_entryTable.find(opCode, existingPort) == Fw::Success::SUCCESS) {
29 // Opcode already present — must be the same port (re-registration)
30 1 FW_ASSERT(existingPort == portNum, static_cast<FwAssertArgType>(opCode));
31
1/1
✓ Branch 6 taken 1 times.
1 this->log_DIAGNOSTIC_OpCodeReregistered(CmdDispatcherCfg::getEventOpcode(opCode), portNum);
32 } else {
33
1/1
✓ Branch 6 taken 44 times.
44 const I32 slot = static_cast<I32>(this->m_entryTable.getSize());
34
1/1
✓ Branch 4 taken 44 times.
44 const Fw::Success status = this->m_entryTable.insert(opCode, portNum);
35 44 FW_ASSERT(status == Fw::Success::SUCCESS, static_cast<FwAssertArgType>(opCode));
36
1/1
✓ Branch 6 taken 44 times.
44 this->log_DIAGNOSTIC_OpCodeRegistered(CmdDispatcherCfg::getEventOpcode(opCode), portNum, slot);
37 44 }
38 45 }
39
40 19 void CommandDispatcherImpl::compCmdStat_handler(FwIndexType portNum,
41 FwOpcodeType opCode,
42 U32 cmdSeq,
43 const Fw::CmdResponse& response) {
44 // check response and log
45
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 3 times.
19 if (Fw::CmdResponse::OK == response.e) {
46
1/1
✓ Branch 6 taken 16 times.
16 this->log_COMMAND_OpCodeCompleted(CmdDispatcherCfg::getEventOpcode(opCode));
47 } else {
48 3 this->m_numCmdErrors++;
49 3 FW_ASSERT(response.e != Fw::CmdResponse::OK);
50
1/1
✓ Branch 6 taken 3 times.
3 this->log_COMMAND_OpCodeError(CmdDispatcherCfg::getEventOpcode(opCode), response);
51 }
52 // look for command source
53 19 SequenceTrackerEntry trackedCmd;
54
1/1
✓ Branch 4 taken 19 times.
19 const Fw::Success removeStatus = this->m_sequenceTracker.remove(cmdSeq, trackedCmd);
55
2/2
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 1 times.
19 if (removeStatus == Fw::Success::SUCCESS) {
56 18 const FwIndexType portToCall = trackedCmd.callerPort;
57 18 const U32 context = trackedCmd.context;
58 18 FW_ASSERT(opCode == trackedCmd.opCode);
59 18 FW_ASSERT(portToCall < this->getNum_seqCmdStatus_OutputPorts());
60
61 // call port to report status
62
2/3
✓ Branch 5 taken 18 times.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
18 if (this->isConnected_seqCmdStatus_OutputPort(portToCall)) {
63 // NOTE: seqCmdStatus port forwards three arguments: (opCode, cmdSeq, response).
64 // However, the cmdSeq value has no meaning for the calling sequencer.
65 // Instead, the context value is forwarded to allow the caller to utilize it if needed.
66
1/1
✓ Branch 5 taken 18 times.
18 this->seqCmdStatus_out(portToCall, opCode, context, response);
67 }
68 }
69 38 }
70
71 51 void CommandDispatcherImpl::seqCmdBuff_handler(FwIndexType portNum, Fw::ComBuffer& data, U32 context) {
72
1/1
✓ Branch 2 taken 51 times.
51 Fw::CmdPacket cmdPkt;
73
1/1
✓ Branch 4 taken 51 times.
51 Fw::SerializeStatus stat = cmdPkt.deserializeFrom(data);
74
75
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 50 times.
51 if (stat != Fw::FW_SERIALIZE_OK) {
76
1/1
✓ Branch 2 taken 1 times.
1 Fw::DeserialStatus serErr(static_cast<Fw::DeserialStatus::t>(stat));
77
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_HI_MalformedCommand(serErr);
78
2/3
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 if (this->isConnected_seqCmdStatus_OutputPort(portNum)) {
79
3/3
✓ Branch 6 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 14 taken 1 times.
1 this->seqCmdStatus_out(portNum, cmdPkt.getOpCode(), context, Fw::CmdResponse::VALIDATION_ERROR);
80 }
81 1 return;
82 1 }
83
84 // look up opcode in dispatch map
85 50 FwIndexType entryPort;
86
2/2
✓ Branch 6 taken 50 times.
✓ Branch 10 taken 50 times.
50 Fw::Success findStatus = this->m_entryTable.find(cmdPkt.getOpCode(), entryPort);
87
6/7
✓ Branch 2 taken 49 times.
✓ Branch 3 taken 1 times.
✓ Branch 9 taken 49 times.
✓ Branch 11 taken 49 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 49 times.
✓ Branch 14 taken 1 times.
50 if (findStatus == Fw::Success::SUCCESS and this->isConnected_compCmdSend_OutputPort(entryPort)) {
88 // register command in command tracker only if response port is connect
89
2/3
✓ Branch 5 taken 49 times.
✓ Branch 7 taken 49 times.
✗ Branch 8 not taken.
49 if (this->isConnected_seqCmdStatus_OutputPort(portNum)) {
90 49 SequenceTrackerEntry pendingCmd;
91
1/1
✓ Branch 2 taken 49 times.
49 pendingCmd.opCode = cmdPkt.getOpCode();
92 49 pendingCmd.context = context;
93 49 pendingCmd.callerPort = portNum;
94
95
1/1
✓ Branch 7 taken 49 times.
49 const Fw::Success pendingInsertStatus = this->m_sequenceTracker.insert(this->m_seq, pendingCmd);
96
97 // if we couldn't find a slot to track the command, quit
98
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 48 times.
49 if (pendingInsertStatus != Fw::Success::SUCCESS) {
99
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_TooManyCommands(CmdDispatcherCfg::getEventOpcode(cmdPkt.getOpCode()));
100
2/3
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 if (this->isConnected_seqCmdStatus_OutputPort(portNum)) {
101
3/3
✓ Branch 6 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 14 taken 1 times.
1 this->seqCmdStatus_out(portNum, cmdPkt.getOpCode(), context, Fw::CmdResponse::EXECUTION_ERROR);
102 }
103 1 return;
104 }
105 49 } // end if status port connected
106 // pass arguments to argument buffer
107
3/3
✓ Branch 6 taken 48 times.
✓ Branch 14 taken 48 times.
✓ Branch 17 taken 48 times.
48 this->compCmdSend_out(entryPort, cmdPkt.getOpCode(), this->m_seq, cmdPkt.getArgBuffer());
108 // log dispatched command
109
2/2
✓ Branch 6 taken 48 times.
✓ Branch 10 taken 48 times.
48 this->log_COMMAND_OpCodeDispatched(CmdDispatcherCfg::getEventOpcode(cmdPkt.getOpCode()), entryPort);
110
111 // increment command count
112 48 this->m_numCmdsDispatched++;
113 } else {
114
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_InvalidCommand(CmdDispatcherCfg::getEventOpcode(cmdPkt.getOpCode()));
115 1 this->m_numCmdErrors++;
116 // Fail command back to port, if connected
117
2/3
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 if (this->isConnected_seqCmdStatus_OutputPort(portNum)) {
118
3/3
✓ Branch 6 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 14 taken 1 times.
1 this->seqCmdStatus_out(portNum, cmdPkt.getOpCode(), context, Fw::CmdResponse::INVALID_OPCODE);
119 }
120 }
121
122 // increment sequence number
123 49 this->m_seq++;
124 52 }
125
126 3 void CommandDispatcherImpl ::run_handler(FwIndexType portNum, U32 context) {
127
2/2
✓ Branch 6 taken 3 times.
✓ Branch 13 taken 3 times.
3 this->tlmWrite_CommandsDropped(this->m_numCmdsDropped);
128
2/2
✓ Branch 6 taken 3 times.
✓ Branch 13 taken 3 times.
3 this->tlmWrite_CommandErrors(this->m_numCmdErrors);
129
2/2
✓ Branch 6 taken 3 times.
✓ Branch 13 taken 3 times.
3 this->tlmWrite_CommandsDispatched(this->m_numCmdsDispatched);
130 3 }
131
132 14 void CommandDispatcherImpl::CMD_NO_OP_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
133
1/1
✓ Branch 2 taken 14 times.
14 Fw::LogStringArg no_op_string("Hello, World!");
134 // Log event for NO_OP here.
135
1/1
✓ Branch 5 taken 14 times.
14 this->log_ACTIVITY_HI_NoOpReceived();
136
2/2
✓ Branch 6 taken 14 times.
✓ Branch 9 taken 14 times.
14 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
137 28 }
138
139 1 void CommandDispatcherImpl::CMD_NO_OP_STRING_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, const Fw::CmdStringArg& arg1) {
140
1/1
✓ Branch 6 taken 1 times.
1 Fw::LogStringArg msg(arg1.toChar());
141 // Echo the NO_OP_STRING args here.
142
1/1
✓ Branch 5 taken 1 times.
1 this->log_ACTIVITY_HI_NoOpStringReceived(msg);
143
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
144 2 }
145
146 1 void CommandDispatcherImpl::CMD_TEST_CMD_1_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, I32 arg1, F32 arg2, U8 arg3) {
147 1 this->log_ACTIVITY_HI_TestCmd1Args(arg1, arg2, arg3);
148
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
149 1 }
150
151 1 void CommandDispatcherImpl::CMD_CLEAR_TRACKING_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
152 // clear tracking table
153 1 this->m_sequenceTracker.clear();
154
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
155 1 }
156
157 void CommandDispatcherImpl::pingIn_handler(FwIndexType portNum, U32 key) {
158 // respond to ping
159 this->pingOut_out(0, key);
160 }
161
162 6 void CommandDispatcherImpl::seqCmdBuff_overflowHook(FwIndexType portNum, Fw::ComBuffer& data, U32 context) {
163 6 FwOpcodeType opcode = 0; // Note: 0 = Reserved opcode
164 if (CmdDispatcherCfg::IncludeCommandOpcodesInEvents) {
165
1/1
✓ Branch 2 taken 6 times.
6 Fw::CmdPacket cmdPkt;
166
1/1
✓ Branch 4 taken 6 times.
6 const Fw::SerializeStatus stat = cmdPkt.deserializeFrom(data);
167
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (stat == Fw::FW_SERIALIZE_OK) {
168
1/1
✓ Branch 2 taken 6 times.
6 opcode = cmdPkt.getOpCode();
169 }
170 6 }
171
172 6 this->log_WARNING_HI_CommandDroppedQueueOverflow(CmdDispatcherCfg::getEventOpcode(opcode), context);
173 // Increment CommandsDroppedBufOverflow counter
174 6 this->m_numCmdsDropped++;
175 6 }
176
177 } // namespace Svc
178