F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
PassiveRateGroup.cpp
Go to the documentation of this file.
1 /*
2  * \author: Tim Canham
3  * \file:
4  * \brief
5  *
6  * This file implements the PassiveRateGroup component,
7  * which invokes a set of components the comprise the rate group.
8  *
9  * Copyright 2014-2015, by the California Institute of Technology.
10  * ALL RIGHTS RESERVED. United States Government Sponsorship
11  * acknowledged.
12  */
13 
14 #include <Fw/FPrimeBasicTypes.hpp>
15 #include <Fw/Types/Assert.hpp>
16 #include <Os/Console.hpp>
18 #include <config/PassiveRateGroupCfg.hpp>
20 
21 namespace Svc {
24  m_cycles(0),
25  m_maxTime(0),
26  m_portCycleTimeHWMUsec{}, // Zero-initialize atomic array
27  m_rawTimeSource(Os::RAWTIME_DEFAULT),
28  m_numContexts(0) {}
29 
31 
32 Os::RawTime PassiveRateGroup::createRawTime() const {
33  return Os::RawTime(this->m_rawTimeSource);
34 }
35 
36 void PassiveRateGroup::configure(const ContextArray& contexts, const Os::RawTimeSource rawTimeSource) {
38  "Context table size must match the number of rate group member output ports");
39 
40  this->m_numContexts = CONNECTION_COUNT_MAX;
41  // copy context values
42  for (FwIndexType entry = 0; entry < this->m_numContexts; entry++) {
43  this->m_contexts[entry] = contexts[static_cast<FwSizeType>(entry)];
44  }
45 
46  this->m_rawTimeSource = rawTimeSource;
47 }
48 
49 void PassiveRateGroup::configure(const U32 contexts[], const FwIndexType numContexts) {
50  FW_ASSERT(contexts != nullptr);
51  FW_ASSERT(numContexts == this->getNum_RateGroupMemberOut_OutputPorts(), static_cast<FwAssertArgType>(numContexts),
52  static_cast<FwAssertArgType>(this->getNum_RateGroupMemberOut_OutputPorts()));
53 
54  ContextArray contextArray;
55  for (FwIndexType entry = 0; entry < numContexts; entry++) {
56  contextArray[static_cast<FwSizeType>(entry)] = static_cast<U32>(contexts[entry]);
57  }
58  this->configure(contextArray);
59 }
60 
61 void PassiveRateGroup::CycleIn_handler(FwIndexType portNum, Os::RawTime& cycleStart) {
62  Os::RawTime endTime = this->createRawTime();
63  FW_ASSERT(this->m_numContexts != 0);
64 
65  // Pre-allocate RawTime objects outside loop to avoid repeated constructor calls
66  Os::RawTime portStart = this->createRawTime();
67  Os::RawTime portEnd = this->createRawTime();
68  PassiveRateGroup_CycleTime portTimes;
69 
70  // invoke any members of the rate group
71  for (FwIndexType port = 0; port < this->getNum_RateGroupMemberOut_OutputPorts(); port++) {
74  (void)portStart.now();
75  }
76 
77  this->RateGroupMemberOut_out(port, this->m_contexts[port]);
78 
80  (void)portEnd.now();
81  U32 cycleTime;
82  (void)portEnd.getDiffUsec(portStart, cycleTime);
83  portTimes[static_cast<FwSizeType>(port)] = cycleTime;
84  // Update high water mark if current cycle time exceeds it (lock-free atomic)
85  U32 currentHWM =
86  this->m_portCycleTimeHWMUsec[static_cast<FwSizeType>(port)].load(std::memory_order_relaxed);
87  while (cycleTime > currentHWM) {
88  if (this->m_portCycleTimeHWMUsec[static_cast<FwSizeType>(port)].compare_exchange_weak(
89  currentHWM, cycleTime, std::memory_order_relaxed)) {
90  break;
91  }
92  }
93  }
94  }
95  }
96 
97  // grab timer for endTime of cycle
98  (void)endTime.now();
99 
100  // get rate group execution time
101  U32 cycleTime;
102  // Cast to void as the only possible error is overflow, which we can't handle other
103  // than capping cycleTime to max value of U32 (which is done in getDiffUsec anyways)
104  (void)endTime.getDiffUsec(cycleStart, cycleTime);
105 
106  // Update max time atomically (lock-free, ISR-safe)
107  U32 currentMax = this->m_maxTime.load(std::memory_order_relaxed);
108  while (cycleTime > currentMax) {
109  if (this->m_maxTime.compare_exchange_weak(currentMax, cycleTime, std::memory_order_relaxed)) {
110  break;
111  }
112  }
113 
114  U32 maxTime = this->m_maxTime.load(std::memory_order_relaxed);
115  U32 cycles = ++this->m_cycles;
116 
118  // Copy atomic array to telemetry structure for sending
119  PassiveRateGroup_CycleTime portCycleTimeHWM;
120  for (FwIndexType port = 0; port < this->getNum_RateGroupMemberOut_OutputPorts(); port++) {
121  portCycleTimeHWM[static_cast<FwSizeType>(port)] =
122  this->m_portCycleTimeHWMUsec[static_cast<FwSizeType>(port)].load(std::memory_order_relaxed);
123  }
124  this->tlmWrite_PortCycleTime(portTimes);
125  this->tlmWrite_PortCycleTimeHWM(portCycleTimeHWM);
126  }
127 
128  this->tlmWrite_MaxCycleTime(maxTime);
129  this->tlmWrite_CycleTime(cycleTime);
130  this->tlmWrite_CycleCount(cycles);
131 }
132 
133 void PassiveRateGroup::CLEAR_STATISTICS_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
134  // Clear max cycle time (lock-free atomic)
135  this->m_maxTime.store(0, std::memory_order_relaxed);
136  // Note: m_cycles is intentionally NOT cleared - it's a running total
137 
138  // Clear all port cycle time high water marks (lock-free atomic)
139  for (FwIndexType port = 0; port < this->getNum_RateGroupMemberOut_OutputPorts(); port++) {
140  this->m_portCycleTimeHWMUsec[static_cast<FwSizeType>(port)].store(0, std::memory_order_relaxed);
141  }
142 
143  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
144 }
145 
146 } // namespace Svc
RawTimeSource
Timer source selection for RawTime.
PassiveRateGroup(const char *compName)
PassiveRateGroupImpl constructor.
Platform&#39;s default timer (maintains current behavior)
FwIdType FwOpcodeType
The type of a command opcode.
PlatformSizeType FwSizeType
bool isConnected_RateGroupMemberOut_OutputPort(FwIndexType portNum) const
static constexpr FwIndexType getNum_RateGroupMemberOut_OutputPorts()
Status now() override
Get the current time.
void RateGroupMemberOut_out(FwIndexType portNum, U32 context) const
Invoke output port RateGroupMemberOut.
void tlmWrite_CycleTime(U32 arg, Fw::Time _tlmTime=Fw::Time()) const
Fw::Array< U32, CONNECTION_COUNT_MAX > ContextArray
Array of context values for rate group members, indexed by output port number.
static constexpr FwIndexType CONNECTION_COUNT_MAX
Auto-generated base for PassiveRateGroup component.
void configure(const ContextArray &contexts, const Os::RawTimeSource rawTimeSource=Os::RAWTIME_DEFAULT)
PassiveRateGroupImpl initialization function.
Command successfully executed.
void tlmWrite_MaxCycleTime(U32 arg, Fw::Time _tlmTime=Fw::Time())
void tlmWrite_PortCycleTimeHWM(const Svc::PassiveRateGroup_CycleTime &arg, Fw::Time _tlmTime=Fw::Time())
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
void tlmWrite_CycleCount(U32 arg, Fw::Time _tlmTime=Fw::Time()) const
PlatformIndexType FwIndexType
Status getDiffUsec(const RawTime &other, U32 &result) const override
Calculate the difference in microseconds between two RawTime objects.
#define FW_NUM_ARRAY_ELEMENTS(a)
number of elements in an array
Definition: BasicTypes.h:94
~PassiveRateGroup()
PassiveRateGroupImpl destructor.
DelegateRawTime RawTime
RateGroupDivider component implementation.
void tlmWrite_PortCycleTime(const Svc::PassiveRateGroup_CycleTime &arg, Fw::Time _tlmTime=Fw::Time()) const
Write telemetry channel PortCycleTime.
#define FW_ASSERT(...)
Definition: Assert.hpp:14