Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions Svc/Ccsds/CfdpManager/CfdpManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ void CfdpManager ::configure(void)
this->m_engine = new Engine(this);
FW_ASSERT(this->m_engine != nullptr);
this->m_engine->init();

// Initialize telemetry counters to zero
for (U8 i = 0; i < Cfdp::NumChannels; i++) {
this->m_channelTelemetry[i] = Cfdp::ChannelTelemetry();
}
}

// ----------------------------------------------------------------------
Expand All @@ -49,6 +54,9 @@ void CfdpManager ::run1Hz_handler(FwIndexType portNum, U32 context)
// The timer logic built into the CFDP engine requires it to be driven at 1 Hz
FW_ASSERT(this->m_engine != NULL);
this->m_engine->cycle();

// Emit telemetry once per second
this->tlmWrite_ChannelTelemetry(this->m_channelTelemetry);
}

void CfdpManager ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& data, const ComCfg::FrameContext& context)
Expand Down Expand Up @@ -425,6 +433,37 @@ void CfdpManager ::AbandonTransaction_cmdHandler(
this->cmdResponse_out(opCode, cmdSeq, rspStatus);
}

void CfdpManager ::ResetCounters_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U8 channelId)
{
// 0xFF means reset all channels
if (channelId == 0xFF)
{
for (U8 i = 0; i < Cfdp::NumChannels; i++)
{
this->m_channelTelemetry[i] = Cfdp::ChannelTelemetry();
}
this->log_ACTIVITY_HI_ResetCounters(0xFF);
}
// Otherwise reset specific channel
else if (channelId < Cfdp::NumChannels)
{
this->m_channelTelemetry[channelId] = Cfdp::ChannelTelemetry();
this->log_ACTIVITY_HI_ResetCounters(channelId);
}
else
{
// Invalid channel ID
this->log_WARNING_LO_InvalidChannel(channelId, Cfdp::NumChannels - 1);
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
return;
}

// Emit updated telemetry
this->tlmWrite_ChannelTelemetry(this->m_channelTelemetry);

this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
}

// ----------------------------------------------------------------------
// Private command helper functions
// ----------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions Svc/Ccsds/CfdpManager/CfdpManager.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module Cfdp {
include "Commands.fppi"
include "Events.fppi"
include "Parameters.fppi"
include "Telemetry.fppi"

##############################################################################
# Custom ports
Expand Down
142 changes: 142 additions & 0 deletions Svc/Ccsds/CfdpManager/CfdpManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,136 @@ class CfdpManager final : public CfdpManagerComponentBase {
//! \param status Transaction completion status
void sendFileComplete(Svc::SendFileStatus::T status);

// ----------------------------------------------------------------
// Telemetry helper methods (public for Engine/Transaction access)
// ----------------------------------------------------------------

//! Increment receive error counter
void incrementRecvErrors(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_recvErrors(m_channelTelemetry[chanId].get_recvErrors() + 1);
}

//! Increment receive dropped counter
void incrementRecvDropped(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_recvDropped(m_channelTelemetry[chanId].get_recvDropped() + 1);
}

//! Increment receive spurious counter
void incrementRecvSpurious(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_recvSpurious(m_channelTelemetry[chanId].get_recvSpurious() + 1);
}

//! Add to received file data bytes
void addRecvFileDataBytes(U8 chanId, U32 bytes) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_recvFileDataBytes(m_channelTelemetry[chanId].get_recvFileDataBytes() + bytes);
}

//! Add to received NAK segment requests
void addRecvNakSegmentRequests(U8 chanId, U32 count) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_recvNakSegmentRequests(m_channelTelemetry[chanId].get_recvNakSegmentRequests() + count);
}

//! Increment received PDU counter
void incrementRecvPdu(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_recvPdu(m_channelTelemetry[chanId].get_recvPdu() + 1);
}

//! Add to sent NAK segment requests
void addSentNakSegmentRequests(U8 chanId, U32 count) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_sentNakSegmentRequests(m_channelTelemetry[chanId].get_sentNakSegmentRequests() + count);
}

//! Add sent file data bytes
void addSentFileDataBytes(U8 chanId, U32 bytes) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_sentFileDataBytes(m_channelTelemetry[chanId].get_sentFileDataBytes() + bytes);
}

//! Increment sent PDU counter
void incrementSentPdu(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_sentPdu(m_channelTelemetry[chanId].get_sentPdu() + 1);
}

//! Increment fault ACK limit counter
void incrementFaultAckLimit(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultAckLimit(m_channelTelemetry[chanId].get_faultAckLimit() + 1);
}

//! Increment fault NAK limit counter
void incrementFaultNakLimit(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultNakLimit(m_channelTelemetry[chanId].get_faultNakLimit() + 1);
}

//! Increment fault inactivity timer counter
void incrementFaultInactivityTimer(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultInactivityTimer(m_channelTelemetry[chanId].get_faultInactivityTimer() + 1);
}

//! Increment fault CRC mismatch counter
void incrementFaultCrcMismatch(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultCrcMismatch(m_channelTelemetry[chanId].get_faultCrcMismatch() + 1);
}

//! Increment fault file size mismatch counter
void incrementFaultFileSizeMismatch(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultFileSizeMismatch(m_channelTelemetry[chanId].get_faultFileSizeMismatch() + 1);
}

//! Increment fault file open counter
void incrementFaultFileOpen(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultFileOpen(m_channelTelemetry[chanId].get_faultFileOpen() + 1);
}

//! Increment fault file read counter
void incrementFaultFileRead(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultFileRead(m_channelTelemetry[chanId].get_faultFileRead() + 1);
}

//! Increment fault file write counter
void incrementFaultFileWrite(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultFileWrite(m_channelTelemetry[chanId].get_faultFileWrite() + 1);
}

//! Increment fault file seek counter
void incrementFaultFileSeek(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultFileSeek(m_channelTelemetry[chanId].get_faultFileSeek() + 1);
}

//! Increment fault file rename counter
void incrementFaultFileRename(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultFileRename(m_channelTelemetry[chanId].get_faultFileRename() + 1);
}

//! Increment fault directory read counter
void incrementFaultDirectoryRead(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
m_channelTelemetry[chanId].set_faultDirectoryRead(m_channelTelemetry[chanId].get_faultDirectoryRead() + 1);
}

//! Get reference to channel telemetry for queue depth updates
Cfdp::ChannelTelemetry& getChannelTelemetryRef(U8 chanId) {
FW_ASSERT(chanId < Cfdp::NumChannels);
return m_channelTelemetry[chanId];
}

private:
// ----------------------------------------------------------------------
// Handler implementations for typed input ports
Expand Down Expand Up @@ -232,6 +362,15 @@ class CfdpManager final : public CfdpManagerComponentBase {
EntityId entityId //!< Entity ID of the transaction
) override;

//! Handler for command ResetCounters
//!
//! Command to reset telemetry counters
void ResetCounters_cmdHandler(
FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
U8 channelId //!< Channel ID to reset (0xFF for all channels)
) override;

private:
// ----------------------------------------------------------------------
// Private command helper functions
Expand Down Expand Up @@ -326,6 +465,9 @@ class CfdpManager final : public CfdpManagerComponentBase {
// CFDP Engine - owns all protocol state and operations
Engine* m_engine;

//! Telemetry array for all CFDP channels
Cfdp::ChannelTelemetryArray m_channelTelemetry;

};

} // namespace Cfdp
Expand Down
119 changes: 104 additions & 15 deletions Svc/Ccsds/CfdpManager/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,31 +321,38 @@ void Channel::tickTransactions()
void Channel::processPlaybackDirectories()
{
U32 i;
// const int chan_index = (m_channel - m_engine->m_engineData.channels);
U8 playback_count = 0;

for (i = 0; i < CFDP_MAX_COMMANDED_PLAYBACK_DIRECTORIES_PER_CHAN; ++i)
{
this->processPlaybackDirectory(&m_playback[i]);
// this->updatePollPbCounted(&m_playback[i], m_playback[i].busy,
// &CF_AppData.hk.Payload.channel_hk[chan_index].playback_counter);
// Count active playback operations
if (m_playback[i].busy)
{
playback_count++;
}
}

// Update playback counter telemetry
Cfdp::ChannelTelemetry& tlm = m_engine->getChannelTelemetryRef(m_channelId);
tlm.set_playbackCounter(playback_count);
}

void Channel::processPollingDirectories()
{
CfdpPollDir* pd;
U32 i;
// TODO BPC: count_check is only used for telemetry
// I32 count_check;
U8 poll_count = 0;
Status::T status;

for (i = 0; i < CFDP_MAX_POLLING_DIR_PER_CHAN; ++i)
{
pd = &m_polldir[i];
// count_check = 0;

if (pd->enabled)
{
poll_count++;

if ((pd->pb.busy == false) && (pd->pb.num_ts == 0))
{
if ((pd->intervalTimer.getStatus() != Timer::Status::RUNNING) && (pd->intervalSec > 0))
Expand Down Expand Up @@ -377,12 +384,12 @@ void Channel::processPollingDirectories()
// playback is active, so step it
this->processPlaybackDirectory(&pd->pb);
}

// count_check = 1;
}

// this->updatePollPbCounted(&poll->pb, count_check, &CF_AppData.hk.Payload.channel_hk[chan_index].poll_counter);
}

// Update poll counter telemetry
Cfdp::ChannelTelemetry& tlm = m_engine->getChannelTelemetryRef(m_channelId);
tlm.set_pollCounter(poll_count);
}

// ----------------------------------------------------------------------
Expand Down Expand Up @@ -492,19 +499,101 @@ void Channel::dequeueTransaction(Transaction* txn)
{
FW_ASSERT(txn);
CfdpCListRemove(&m_qs[txn->m_flags.com.q_index], &txn->m_cl_node);
// FW_ASSERT(CF_AppData.hk.Payload.channel_hk[txn->chan_num].q_size[txn->flags.com.q_index]); /* sanity check */
// --CF_AppData.hk.Payload.channel_hk[txn->chan_num].q_size[txn->flags.com.q_index];

// Update queue depth telemetry
Cfdp::ChannelTelemetry& tlm = m_engine->getChannelTelemetryRef(m_channelId);
switch (txn->m_flags.com.q_index) {
case Cfdp::QueueId::FREE:

tlm.set_queueFree(tlm.get_queueFree() - 1);
break;
case Cfdp::QueueId::TXA:

tlm.set_queueTxActive(tlm.get_queueTxActive() - 1);
break;
case Cfdp::QueueId::TXW:

tlm.set_queueTxWaiting(tlm.get_queueTxWaiting() - 1);
break;
case Cfdp::QueueId::RX:

tlm.set_queueRx(tlm.get_queueRx() - 1);
break;
case Cfdp::QueueId::HIST:

tlm.set_queueHistory(tlm.get_queueHistory() - 1);
break;
case Cfdp::QueueId::PEND:
case Cfdp::QueueId::HIST_FREE:
// PEND and HIST_FREE queues are not tracked in telemetry
break;
default:
FW_ASSERT(0, txn->m_flags.com.q_index);
}
}

void Channel::moveTransaction(Transaction* txn, QueueId::T queue)
{
FW_ASSERT(txn);
Cfdp::ChannelTelemetry& tlm = m_engine->getChannelTelemetryRef(m_channelId);

// Decrement old queue
CfdpCListRemove(&m_qs[txn->m_flags.com.q_index], &txn->m_cl_node);
// FW_ASSERT(CF_AppData.hk.Payload.channel_hk[txn->chan_num].q_size[txn->flags.com.q_index]); /* sanity check */
// --CF_AppData.hk.Payload.channel_hk[txn->chan_num].q_size[txn->flags.com.q_index];
switch (txn->m_flags.com.q_index) {
case Cfdp::QueueId::FREE:

tlm.set_queueFree(tlm.get_queueFree() - 1);
break;
case Cfdp::QueueId::TXA:

tlm.set_queueTxActive(tlm.get_queueTxActive() - 1);
break;
case Cfdp::QueueId::TXW:

tlm.set_queueTxWaiting(tlm.get_queueTxWaiting() - 1);
break;
case Cfdp::QueueId::RX:

tlm.set_queueRx(tlm.get_queueRx() - 1);
break;
case Cfdp::QueueId::HIST:

tlm.set_queueHistory(tlm.get_queueHistory() - 1);
break;
case Cfdp::QueueId::PEND:
case Cfdp::QueueId::HIST_FREE:
// PEND and HIST_FREE queues are not tracked in telemetry
break;
default:
FW_ASSERT(0, txn->m_flags.com.q_index);
}

// Increment new queue
CfdpCListInsertBack(&m_qs[queue], &txn->m_cl_node);
txn->m_flags.com.q_index = queue;
// ++CF_AppData.hk.Payload.channel_hk[txn->chan_num].q_size[txn->flags.com.q_index];
switch (queue) {
case Cfdp::QueueId::FREE:
tlm.set_queueFree(tlm.get_queueFree() + 1);
break;
case Cfdp::QueueId::TXA:
tlm.set_queueTxActive(tlm.get_queueTxActive() + 1);
break;
case Cfdp::QueueId::TXW:
tlm.set_queueTxWaiting(tlm.get_queueTxWaiting() + 1);
break;
case Cfdp::QueueId::RX:
tlm.set_queueRx(tlm.get_queueRx() + 1);
break;
case Cfdp::QueueId::HIST:
tlm.set_queueHistory(tlm.get_queueHistory() + 1);
break;
case Cfdp::QueueId::PEND:
case Cfdp::QueueId::HIST_FREE:
// PEND and HIST_FREE queues are not tracked in telemetry
break;
default:
FW_ASSERT(0, queue);
}
}

void Channel::freeTransaction(Transaction* txn)
Expand Down
Loading
Loading