From 6b80daab0a998b380f296567ab1e1f467e7aaab1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 20 Feb 2023 18:12:33 +0100 Subject: [PATCH] maybe this caused the hangup issue? --- linux/ipcore/PdecHandler.cpp | 29 ++++++++++++++++++++++++----- linux/ipcore/PdecHandler.h | 9 ++++++++- mission/tmtc/CfdpTmFunnel.cpp | 6 +++--- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/linux/ipcore/PdecHandler.cpp b/linux/ipcore/PdecHandler.cpp index 3244280e..8eb2d00a 100644 --- a/linux/ipcore/PdecHandler.cpp +++ b/linux/ipcore/PdecHandler.cpp @@ -1,6 +1,7 @@ #include "PdecHandler.h" #include +#include #include #include #include @@ -113,7 +114,7 @@ ReturnValue_t PdecHandler::polledOperation() { // Requires reconfiguration and reinitialization of PDEC triggerEvent(INVALID_FAR); state = State::WAIT_FOR_RECOVERY; - return result; + break; } state = State::RUNNING; break; @@ -147,6 +148,9 @@ ReturnValue_t PdecHandler::irqOperation() { uint32_t info = 1; ssize_t nb = 0; int ret = 0; + + interruptWindowCd.resetTimer(); + // Clear interrupts with dummy read before unmasking the interrupt. Use a volatile to prevent // read being optimized away. volatile uint32_t dummy = *(registerBaseAddress + PDEC_PIR_OFFSET); @@ -157,7 +161,7 @@ ReturnValue_t PdecHandler::irqOperation() { readCommandQueue(); switch (state) { case State::INIT: - resetFarStatFlag(); + result = resetFarStatFlag(); if (result != returnvalue::OK) { // Requires reconfiguration and reinitialization of PDEC triggerEvent(INVALID_FAR); @@ -180,9 +184,11 @@ ReturnValue_t PdecHandler::irqOperation() { if (ret == 0) { // No TCs for timeout period checkLocks(); - lockCheckCd.resetTimer(); + genericCheckCd.resetTimer(); + interruptWindowCd.resetTimer(); } else if (ret >= 1) { nb = read(fd, &info, sizeof(info)); + interruptCounter++; if (nb == static_cast(sizeof(info))) { uint32_t pisr = *(registerBaseAddress + PDEC_PISR_OFFSET); if ((pisr & TC_NEW_MASK) == TC_NEW_MASK) { @@ -197,9 +203,19 @@ ReturnValue_t PdecHandler::irqOperation() { CURRENT_FAR = readFar(); checkFrameAna(CURRENT_FAR); } - if (lockCheckCd.hasTimedOut()) { + if (genericCheckCd.hasTimedOut()) { checkLocks(); - lockCheckCd.resetTimer(); + genericCheckCd.resetTimer(); + if (interruptWindowCd.timeOut()) { + if (interruptCounter >= MAX_ALLOWED_IRQS_PER_WINDOW) { + sif::error << "PdecHandler::irqOperation: Possible IRQ storm" << std::endl; + triggerEvent(TOO_MANY_IRQS, MAX_ALLOWED_IRQS_PER_WINDOW); + TaskFactory::delayTask(400); + break; + } + interruptWindowCd.resetTimer(); + interruptCounter = 0; + } } // Clear interrupts with dummy read dummy = *(registerBaseAddress + PDEC_PIR_OFFSET); @@ -215,9 +231,12 @@ ReturnValue_t PdecHandler::irqOperation() { break; } case State::WAIT_FOR_RECOVERY: + TaskFactory::delayTask(400); break; default: + // Should never happen. sif::error << "PdecHandler::performOperation: Invalid state" << std::endl; + TaskFactory::delayTask(400); break; } } diff --git a/linux/ipcore/PdecHandler.h b/linux/ipcore/PdecHandler.h index b514f501..e6da7724 100644 --- a/linux/ipcore/PdecHandler.h +++ b/linux/ipcore/PdecHandler.h @@ -87,6 +87,8 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc static const Event LOST_CARRIER_LOCK_PDEC = MAKE_EVENT(5, severity::INFO); //! [EXPORT] : [COMMENT] Lost bit lock static const Event LOST_BIT_LOCK_PDEC = MAKE_EVENT(6, severity::INFO); + //! [EXPORT] : [COMMENT] Too many IRQs over the time window of one second. P1: Allowed TCs + static constexpr Event TOO_MANY_IRQS = MAKE_EVENT(7, severity::MEDIUM); static constexpr Event POLL_SYSCALL_ERROR_PDEC = event::makeEvent(SUBSYSTEM_ID, 7, severity::MEDIUM); static constexpr Event WRITE_SYSCALL_ERROR_PDEC = @@ -180,6 +182,8 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc // discarded static const uint8_t MAP_CLK_FREQ = 2; + static constexpr uint32_t MAX_ALLOWED_IRQS_PER_WINDOW = 500; + enum class FrameAna_t : uint8_t { ABANDONED_CLTU, FRAME_DIRTY, @@ -206,13 +210,16 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc static uint32_t CURRENT_FAR; - Countdown lockCheckCd = Countdown(IRQ_TIMEOUT_MS); + Countdown genericCheckCd = Countdown(IRQ_TIMEOUT_MS); object_id_t tcDestinationId; AcceptsTelecommandsIF* tcDestination = nullptr; LinuxLibgpioIF* gpioComIF = nullptr; + uint32_t interruptCounter = 0; + Countdown interruptWindowCd = Countdown(1000); + /** * Reset signal is required to hold PDEC in reset state until the configuration has been * written to the appropriate memory space. diff --git a/mission/tmtc/CfdpTmFunnel.cpp b/mission/tmtc/CfdpTmFunnel.cpp index c057295a..e687911f 100644 --- a/mission/tmtc/CfdpTmFunnel.cpp +++ b/mission/tmtc/CfdpTmFunnel.cpp @@ -55,8 +55,7 @@ ReturnValue_t CfdpTmFunnel::handlePacket(TmTcMessage& msg) { } size_t packetLen = 0; uint8_t* serPtr = newPacketData; - result = - spacePacketHeader.serializeBe(&serPtr, &packetLen, spacePacketHeader.getFullPacketLen()); + result = spacePacketHeader.serializeBe(&serPtr, &packetLen, spacePacketHeader.getFullPacketLen()); if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "CfdpTmFunnel::handlePacket: Error serializing packet" << std::endl; @@ -83,7 +82,8 @@ ReturnValue_t CfdpTmFunnel::handlePacket(TmTcMessage& msg) { } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "PusTmFunnel::handlePacket: Store too full to create data copy or store " - "error" << std::endl; + "error" + << std::endl; break; #endif }