From 4e686b4ad05627af84ca6d3377612b587f530ef7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 14 Apr 2023 13:11:11 +0200 Subject: [PATCH] better PDEC FDIR --- bsp_q7s/core/CoreController.cpp | 4 +- linux/ipcore/PdecHandler.cpp | 92 +++++++++++++++++++---------- linux/ipcore/PdecHandler.h | 53 +++-------------- linux/ipcore/pdec.h | 50 ++++++++++++++++ mission/system/EiveSystem.cpp | 15 ++++- mission/system/EiveSystem.h | 5 ++ mission/system/com/ComSubsystem.cpp | 10 ++-- 7 files changed, 146 insertions(+), 83 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index e1033943..49145f9f 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -369,7 +369,7 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ return actionReboot(data, size); } case (EXECUTE_SHELL_CMD_BLOCKING): { - std::string cmdToExecute = std::string(reinterpret_cast(data), size); + std::string cmdToExecute = std::string(reinterpret_cast(data), size); int result = std::system(cmdToExecute.c_str()); if (result != 0) { // TODO: Data reply with returnalue maybe? @@ -378,7 +378,7 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ return EXECUTION_FINISHED; } case (EXECUTE_SHELL_CMD_NON_BLOCKING): { - std::string cmdToExecute = std::string(reinterpret_cast(data), size); + std::string cmdToExecute = std::string(reinterpret_cast(data), size); if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING or shellCmdIsExecuting) { return HasActionsIF::IS_BUSY; diff --git a/linux/ipcore/PdecHandler.cpp b/linux/ipcore/PdecHandler.cpp index d5e5c0c8..8b6a0b2e 100644 --- a/linux/ipcore/PdecHandler.cpp +++ b/linux/ipcore/PdecHandler.cpp @@ -15,6 +15,7 @@ #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/tmtcservices/TmTcMessage.h" #include "fsfw_hal/linux/uio/UioMapper.h" +#include "linux/ipcore/PdecConfig.h" #include "pdec.h" using namespace pdec; @@ -103,7 +104,7 @@ ReturnValue_t PdecHandler::firstLoop() { result = releasePdec(); if (result != returnvalue::OK) { - return returnvalue::FAILED; + return result; } // This configuration must be done while the PDEC is not held in reset. @@ -141,7 +142,7 @@ ReturnValue_t PdecHandler::polledOperation() { if (newTcReceived()) { handleNewTc(); } - checkLocks(); + doPeriodicWork(); break; } case State::PDEC_RESET: { @@ -182,8 +183,13 @@ ReturnValue_t PdecHandler::irqOperation() { switch (state) { case State::INIT: { result = handleInitState(); - if (result == returnvalue::OK) { - openIrqFile(&fd); + if (result != returnvalue::OK) { + break; + } + openIrqFile(&fd); + if (ptmeResetWithReinitializationPending) { + actionHelper.finish(true, commandedBy, pdec::RESET_PDEC_WITH_REINIITALIZATION); + ptmeResetWithReinitializationPending = false; } break; } @@ -192,11 +198,12 @@ ReturnValue_t PdecHandler::irqOperation() { if (result != returnvalue::OK) { triggerEvent(PDEC_RESET_FAILED); } + usleep(10); state = State::INIT; break; } case State::RUNNING: { - checkLocks(); + doPeriodicWork(); checkAndHandleIrqs(fd, info); break; } @@ -219,18 +226,19 @@ ReturnValue_t PdecHandler::handleInitState() { ReturnValue_t result = firstLoop(); if (result != returnvalue::OK) { if (result == LocalParameterHandler::SD_NOT_READY) { - TaskFactory::delayTask(400); if (initTries == MAX_INIT_TRIES) { - sif::error << "PdecHandler::handleInitState: SD card never " - "becomes ready" - << std::endl; - state = State::WAIT_FOR_RECOVERY; - } else { - state = State::INIT; + sif::error << "PdecHandler::handleInitState: SD card never becomes ready" << std::endl; + initFailedHandler(result); + return result; } + state = State::INIT; + initTries++; + TaskFactory::delayTask(400); return result; } - state = State::WAIT_FOR_RECOVERY; + sif::error << "PDEC: Init failed with reason 0x" << std::hex << std::setw(4) << result + << std::endl; + initFailedHandler(result); return result; } state = State::RUNNING; @@ -335,6 +343,7 @@ MessageQueueId_t PdecHandler::getCommandQueue() const { return commandQueue->get ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { + using namespace pdec; switch (actionId) { case PRINT_CLCW: printClcw(); @@ -342,6 +351,18 @@ ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t c case PRINT_PDEC_MON: printPdecMon(); return EXECUTION_FINISHED; + case RESET_PDEC_NO_REINIITALIZATION: { + pdecToReset(); + usleep(20); + releasePdec(); + return EXECUTION_FINISHED; + } + case RESET_PDEC_WITH_REINIITALIZATION: { + state = State::PDEC_RESET; + ptmeResetWithReinitializationPending = true; + this->commandedBy = commandedBy; + return returnvalue::OK; + } default: return COMMAND_NOT_IMPLEMENTED; } @@ -449,23 +470,7 @@ bool PdecHandler::newTcReceived() { return true; } -void PdecHandler::checkLocks() { - uint32_t clcw = getClcw(); - if (not(clcw & NO_RF_MASK) && not carrierLock) { - triggerEvent(CARRIER_LOCK); - carrierLock = true; - } else if ((clcw & NO_RF_MASK) && carrierLock) { - carrierLock = false; - triggerEvent(LOST_CARRIER_LOCK_PDEC); - } - if (not(clcw & NO_BITLOCK_MASK) && not bitLock) { - triggerEvent(BIT_LOCK_PDEC); - bitLock = true; - } else if ((clcw & NO_BITLOCK_MASK) && bitLock) { - bitLock = false; - triggerEvent(LOST_BIT_LOCK_PDEC); - } -} +void PdecHandler::doPeriodicWork() { checkLocks(); } bool PdecHandler::checkFrameAna(uint32_t pdecFar) { bool frameValid = false; @@ -748,6 +753,33 @@ void PdecHandler::resetIrqLimiters() { interruptCounter = 0; } +void PdecHandler::checkLocks() { + uint32_t clcw = getClcw(); + if (not(clcw & NO_RF_MASK) && not carrierLock) { + triggerEvent(CARRIER_LOCK); + carrierLock = true; + } else if ((clcw & NO_RF_MASK) && carrierLock) { + carrierLock = false; + triggerEvent(LOST_CARRIER_LOCK_PDEC); + } + if (not(clcw & NO_BITLOCK_MASK) && not bitLock) { + triggerEvent(BIT_LOCK_PDEC); + bitLock = true; + } else if ((clcw & NO_BITLOCK_MASK) && bitLock) { + bitLock = false; + triggerEvent(LOST_BIT_LOCK_PDEC); + } +} + +void PdecHandler::initFailedHandler(ReturnValue_t reason) { + triggerEvent(pdec::PDEC_INIT_FAILED, reason, 0); + if (ptmeResetWithReinitializationPending) { + actionHelper.finish(false, commandedBy, pdec::RESET_PDEC_WITH_REINIITALIZATION, reason); + ptmeResetWithReinitializationPending = false; + } + state = State::WAIT_FOR_RECOVERY; +} + std::string PdecHandler::getMonStatusString(uint32_t status) { switch (status) { case TC_CHANNEL_INACTIVE: diff --git a/linux/ipcore/PdecHandler.h b/linux/ipcore/PdecHandler.h index 2f0bcca2..2c379099 100644 --- a/linux/ipcore/PdecHandler.h +++ b/linux/ipcore/PdecHandler.h @@ -3,6 +3,8 @@ #include +#include + #include "OBSWConfig.h" #include "PdecConfig.h" #include "eive/definitions.h" @@ -79,34 +81,6 @@ class PdecHandler : public SystemObject, ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, uint16_t startAtIndex) override; - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER; - - //! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame - //! P1: The frame analysis information (FrameAna field of PDEC_FAR register) - //! P2: When frame declared illegal this parameter this parameter gives information about the - //! reason (IReason field of the PDEC_FAR register) - static const Event INVALID_TC_FRAME = MAKE_EVENT(1, severity::HIGH); - //! [EXPORT] : [COMMENT] Read invalid FAR from PDEC after startup - static const Event INVALID_FAR = MAKE_EVENT(2, severity::HIGH); - //! [EXPORT] : [COMMENT] Carrier lock detected - static const Event CARRIER_LOCK = MAKE_EVENT(3, severity::INFO); - //! [EXPORT] : [COMMENT] Bit lock detected (data valid) - static const Event BIT_LOCK_PDEC = MAKE_EVENT(4, severity::INFO); - //! [EXPORT] : [COMMENT] Lost carrier lock - 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, 8, severity::MEDIUM); - static constexpr Event WRITE_SYSCALL_ERROR_PDEC = - event::makeEvent(SUBSYSTEM_ID, 9, severity::HIGH); - //! [EXPORT] : [COMMENT] Failed to pull PDEC reset to low - static constexpr Event PDEC_RESET_FAILED = event::makeEvent(SUBSYSTEM_ID, 10, severity::HIGH); - //! [EXPORT] : [COMMENT] Failed to open the IRQ uio file - static constexpr Event OPEN_IRQ_FILE_FAILED = event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH); - private: static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER; @@ -141,11 +115,6 @@ class PdecHandler : public SystemObject, static const uint32_t QUEUE_SIZE = config::CCSDS_HANDLER_QUEUE_SIZE; - // Action IDs - static const ActionId_t PRINT_CLCW = 0; - // Print PDEC monitor register - static const ActionId_t PRINT_PDEC_MON = 1; - #ifdef TE0720_1CFA static const int CONFIG_MEMORY_MAP_SIZE = 0x400; static const int RAM_MAP_SIZE = 0x4000; @@ -185,17 +154,6 @@ class PdecHandler : public SystemObject, static constexpr uint32_t MAX_ALLOWED_IRQS_PER_WINDOW = 800; - enum class FrameAna_t : uint8_t { - ABANDONED_CLTU, - FRAME_DIRTY, - FRAME_ILLEGAL, - FRAME_ILLEGAL_MULTI_REASON, - AD_DISCARDED_LOCKOUT, - AD_DISCARDED_WAIT, - AD_DISCARDED_NS_VR, - FRAME_ACCEPTED - }; - enum class IReason_t : uint8_t { NO_REPORT, ERROR_VERSION_NUMBER, @@ -258,6 +216,9 @@ class PdecHandler : public SystemObject, bool carrierLock = false; bool bitLock = false; + MessageQueueId_t commandedBy = MessageQueueIF::NO_QUEUE; + bool ptmeResetWithReinitializationPending = false; + UioNames uioNames; ParameterHelper paramHelper; @@ -325,6 +286,8 @@ class PdecHandler : public SystemObject, * @brief Checks if carrier lock or bit lock has been detected and triggers appropriate * event. */ + void doPeriodicWork(); + void checkLocks(); void resetIrqLimiters(); @@ -400,6 +363,8 @@ class PdecHandler : public SystemObject, */ void printPdecMon(); + void initFailedHandler(ReturnValue_t reason); + std::string getMonStatusString(uint32_t status); }; diff --git a/linux/ipcore/pdec.h b/linux/ipcore/pdec.h index 7485f744..656250a7 100644 --- a/linux/ipcore/pdec.h +++ b/linux/ipcore/pdec.h @@ -1,10 +1,60 @@ #ifndef LINUX_OBC_PDEC_H_ #define LINUX_OBC_PDEC_H_ +#include + #include namespace pdec { +static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER; + +//! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame +//! P1: The frame analysis information (FrameAna field of PDEC_FAR register) +//! P2: When frame declared illegal this parameter this parameter gives information about the +//! reason (IReason field of the PDEC_FAR register) +static const Event INVALID_TC_FRAME = MAKE_EVENT(1, severity::HIGH); +//! [EXPORT] : [COMMENT] Read invalid FAR from PDEC after startup +static const Event INVALID_FAR = MAKE_EVENT(2, severity::HIGH); +//! [EXPORT] : [COMMENT] Carrier lock detected +static const Event CARRIER_LOCK = MAKE_EVENT(3, severity::INFO); +//! [EXPORT] : [COMMENT] Bit lock detected (data valid) +static const Event BIT_LOCK_PDEC = MAKE_EVENT(4, severity::INFO); +//! [EXPORT] : [COMMENT] Lost carrier lock +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, 8, severity::MEDIUM); +static constexpr Event WRITE_SYSCALL_ERROR_PDEC = event::makeEvent(SUBSYSTEM_ID, 9, severity::HIGH); +//! [EXPORT] : [COMMENT] Failed to pull PDEC reset to low +static constexpr Event PDEC_RESET_FAILED = event::makeEvent(SUBSYSTEM_ID, 10, severity::HIGH); +//! [EXPORT] : [COMMENT] Failed to open the IRQ uio file +static constexpr Event OPEN_IRQ_FILE_FAILED = event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH); +//! [EXPORT] : [COMMENT] PDEC initialization failed. This might also be due to the persistent +//! confiuration never becoming available, for example due to SD card issues. +static constexpr Event PDEC_INIT_FAILED = event::makeEvent(SUBSYSTEM_ID, 12, severity::HIGH); + +// Action IDs +static constexpr ActionId_t PRINT_CLCW = 0; +// Print PDEC monitor register +static constexpr ActionId_t PRINT_PDEC_MON = 1; +static constexpr ActionId_t RESET_PDEC_NO_REINIITALIZATION = 2; +static constexpr ActionId_t RESET_PDEC_WITH_REINIITALIZATION = 3; + +enum class FrameAna_t : uint8_t { + ABANDONED_CLTU, + FRAME_DIRTY, + FRAME_ILLEGAL, + FRAME_ILLEGAL_MULTI_REASON, + AD_DISCARDED_LOCKOUT, + AD_DISCARDED_WAIT, + AD_DISCARDED_NS_VR, + FRAME_ACCEPTED +}; + static const uint8_t STAT_POSITION = 31; static const uint8_t FRAME_ANA_POSITION = 28; static const uint8_t IREASON_POSITION = 25; diff --git a/mission/system/EiveSystem.cpp b/mission/system/EiveSystem.cpp index f93aa099..a8035c3a 100644 --- a/mission/system/EiveSystem.cpp +++ b/mission/system/EiveSystem.cpp @@ -8,6 +8,7 @@ #include #include +#include "linux/ipcore/pdec.h" #include "mission/power/bpxBattDefs.h" #include "mission/power/defs.h" #include "mission/sysDefs.h" @@ -62,6 +63,11 @@ void EiveSystem::performChildOperation() { performSafeRecovery = false; return; } + if (frameDirtyCheckCd.hasTimedOut()) { + if (frameDirtyErrorCounter >= 4) { + } + frameDirtyErrorCounter = 0; + } i2cRecoveryLogic(); } @@ -105,8 +111,7 @@ ReturnValue_t EiveSystem::initialize() { manager->subscribeToEvent(eventQueue->getId(), event::getEventId(tcsCtrl::PCDU_SYSTEM_OVERHEATING)); manager->subscribeToEvent(eventQueue->getId(), event::getEventId(tcsCtrl::OBC_OVERHEATING)); - - // manager->subscribeToEvent(eventQueue->getId(), event::getEventId(CoreController::)) + manager->subscribeToEvent(eventQueue->getId(), event::getEventId(pdec::INVALID_TC_FRAME)); return Subsystem::initialize(); } @@ -117,6 +122,12 @@ void EiveSystem::handleEventMessages() { switch (event.getMessageId()) { case EventMessage::EVENT_MESSAGE: switch (event.getEvent()) { + case pdec::INVALID_TC_FRAME: { + if (event.getParameter1() == static_cast(pdec::FrameAna_t::FRAME_DIRTY)) { + frameDirtyErrorCounter++; + } + break; + } case tcsCtrl::OBC_OVERHEATING: case tcsCtrl::PCDU_SYSTEM_OVERHEATING: { if (isInTransition) { diff --git a/mission/system/EiveSystem.h b/mission/system/EiveSystem.h index 504d4317..8ad11e0d 100644 --- a/mission/system/EiveSystem.h +++ b/mission/system/EiveSystem.h @@ -9,6 +9,8 @@ class EiveSystem : public Subsystem, public HasActionsIF { public: + static constexpr uint8_t FRAME_DIRTY_COM_REBOOT_LIMIT = 4; + static constexpr ActionId_t EXECUTE_I2C_REBOOT = 10; EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables, @@ -33,6 +35,9 @@ class EiveSystem : public Subsystem, public HasActionsIF { bool performI2cReboot = false; bool alreadyTriedI2cRecovery = false; + uint8_t frameDirtyErrorCounter = 0; + Countdown frameDirtyCheckCd = Countdown(10000); + ActionHelper actionHelper; PowerSwitchIF* powerSwitcher = nullptr; std::atomic_uint16_t& i2cErrors; diff --git a/mission/system/com/ComSubsystem.cpp b/mission/system/com/ComSubsystem.cpp index fa2c31d3..dfcbbd42 100644 --- a/mission/system/com/ComSubsystem.cpp +++ b/mission/system/com/ComSubsystem.cpp @@ -105,9 +105,9 @@ ReturnValue_t ComSubsystem::initialize() { if (result != returnvalue::OK) { return ObjectManager::CHILD_INIT_FAILED; } - result = manager->subscribeToEventRange(eventQueue->getId(), - event::getEventId(PdecHandler::CARRIER_LOCK), - event::getEventId(PdecHandler::BIT_LOCK_PDEC)); + result = + manager->subscribeToEventRange(eventQueue->getId(), event::getEventId(pdec::CARRIER_LOCK), + event::getEventId(pdec::BIT_LOCK_PDEC)); if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "ComSubsystem::initialize: Failed to subscribe to events from PDEC " @@ -167,11 +167,11 @@ void ComSubsystem::handleEventMessage(EventMessage *eventMessage) { startRxOnlyRecovery(true); break; } - case PdecHandler::BIT_LOCK_PDEC: { + case pdec::BIT_LOCK_PDEC: { handleBitLockEvent(); break; } - case PdecHandler::CARRIER_LOCK: { + case pdec::CARRIER_LOCK: { handleCarrierLockEvent(); break; }