From 590d5e11e1e89ceb4185a0e4fa60620ce25809aa Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jul 2021 13:41:45 +0200 Subject: [PATCH 01/38] tmtc update --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index 6352a6f2..2e942ec2 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 6352a6f272b3138257831fcd1f5d9ffcd4902681 +Subproject commit 2e942ec21e47485b9ab6416a0341b9ab8ec30543 From 261fc8b58f746bb64cbb0bff9692240622bf0660 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jul 2021 13:51:00 +0200 Subject: [PATCH 02/38] moved config flag to cmmon config --- bsp_hosted/InitMission.cpp | 14 +++++++------- bsp_hosted/ObjectFactory.cpp | 21 +++++++++++++++++---- bsp_q7s/core/CoreController.cpp | 4 ++-- common/config/commonConfig.h.in | 4 ++++ fsfw | 2 +- linux/fsfwconfig/OBSWConfig.h.in | 4 ---- 6 files changed, 31 insertions(+), 18 deletions(-) diff --git a/bsp_hosted/InitMission.cpp b/bsp_hosted/InitMission.cpp index 8ef40d06..ed6b8820 100644 --- a/bsp_hosted/InitMission.cpp +++ b/bsp_hosted/InitMission.cpp @@ -70,15 +70,15 @@ void initmission::initTasks() { } /* UDP bridge */ - PeriodicTaskIF* udpBridgeTask = factory->createPeriodicTask( - "UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); - result = udpBridgeTask->addComponent(objects::TMTC_BRIDGE); + PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask( + "TMTC_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); + result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE); if(result != HasReturnvaluesIF::RETURN_OK) { sif::error << "Add component UDP Unix Bridge failed" << std::endl; } - PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask( + PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask( "UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); - result = udpPollingTask->addComponent(objects::TMTC_POLLING_TASK); + result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK); if(result != HasReturnvaluesIF::RETURN_OK) { sif::error << "Add component UDP Polling failed" << std::endl; } @@ -142,8 +142,8 @@ void initmission::initTasks() { sif::info << "Starting tasks.." << std::endl; tmTcDistributor->startTask(); - udpBridgeTask->startTask(); - udpPollingTask->startTask(); + tmtcBridgeTask->startTask(); + tmtcPollingTask->startTask(); pusVerification->startTask(); pusEvents->startTask(); diff --git a/bsp_hosted/ObjectFactory.cpp b/bsp_hosted/ObjectFactory.cpp index 0933df5b..c5b9ded7 100644 --- a/bsp_hosted/ObjectFactory.cpp +++ b/bsp_hosted/ObjectFactory.cpp @@ -1,6 +1,5 @@ #include "ObjectFactory.h" - -#include +#include "OBSWConfig.h" #include #include #include @@ -11,8 +10,13 @@ #include #include -#include -#include +#if OBSW_USE_TMTC_TCP_BRIDGE == 0 +#include "fsfw/osal/common/UdpTcPollingTask.h" +#include "fsfw/osal/common/UdpTmTcBridge.h" +#else +#include "fsfw/osal/common/TcpTmTcBridge.h" +#include "fsfw/osal/common/TcpTmTcServer.h" +#endif #include @@ -40,7 +44,16 @@ void ObjectFactory::produce(void* args){ Factory::setStaticFrameworkObjectIds(); ObjectFactory::produceGenericObjects(); +#if OBSW_USE_TMTC_TCP_BRIDGE == 0 + sif::info << "Setting up UDP TMTC bridge with listener port " << + UdpTmTcBridge::DEFAULT_SERVER_PORT << std::endl; new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); +#else + sif::info << "Setting up TCP TMTC bridge with listener port " << + TcpTmTcBridge::DEFAULT_SERVER_PORT << std::endl; + new TcpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); + new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); +#endif } diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 1285a56b..2351c9be 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -360,10 +360,10 @@ void CoreController::initPrint() { #if OBSW_VERBOSE_LEVEL >= 1 #if OBSW_USE_TMTC_TCP_BRIDGE == 0 sif::info << "Created UDP server for TMTC commanding with listener port " << - UdpTmTcBridge::DEFAULT_UDP_SERVER_PORT << std::endl; + UdpTmTcBridge::DEFAULT_SERVER_PORT << std::endl; #else sif::info << "Created TCP server for TMTC commanding with listener port " << - TcpTmTcBridge::DEFAULT_TCP_SERVER_PORT << std::endl; + TcpTmTcBridge::DEFAULT_SERVER_PORT << std::endl; #endif #endif } diff --git a/common/config/commonConfig.h.in b/common/config/commonConfig.h.in index 3d741bcf..eaf68b2d 100644 --- a/common/config/commonConfig.h.in +++ b/common/config/commonConfig.h.in @@ -3,4 +3,8 @@ #define OBSW_ADD_LWGPS_TEST 0 +// Use TCP instead of UDP for the TMTC bridge. This allows using the TMTC client locally +// because UDP packets are not allowed in the VPN +#define OBSW_USE_TMTC_TCP_BRIDGE 0 + #endif /* COMMON_CONFIG_COMMONCONFIG_H_ */ diff --git a/fsfw b/fsfw index 1f6a5e63..54c028f9 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 1f6a5e635fcd6bd812e262cc65a15a8a054f7ecf +Subproject commit 54c028f913e81077855aa1ed727bac43e7efea82 diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index 7a798717..16eacccf 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -18,10 +18,6 @@ debugging. */ #define OBSW_VERBOSE_LEVEL 1 -// Use TCP instead of UDP for the TMTC bridge. This allows using the TMTC client locally -// because UDP packets are not allowed in the VPN -#define OBSW_USE_TMTC_TCP_BRIDGE 0 - #define OBSW_PRINT_MISSED_DEADLINES 1 #define OBSW_ADD_TEST_CODE 1 #define OBSW_ADD_TEST_PST 1 From 5018b24cfcd08f6ffeb81157475aa9df5570b91a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jul 2021 13:55:58 +0200 Subject: [PATCH 03/38] storing RTD value now as well --- mission/devices/Max31865PT1000Handler.cpp | 29 ++++++------------- .../devicedefinitions/Max31865Definitions.h | 3 ++ 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/mission/devices/Max31865PT1000Handler.cpp b/mission/devices/Max31865PT1000Handler.cpp index 12fd5102..2a779ee7 100644 --- a/mission/devices/Max31865PT1000Handler.cpp +++ b/mission/devices/Max31865PT1000Handler.cpp @@ -1,5 +1,7 @@ #include "Max31865PT1000Handler.h" +#include "fsfw/datapool/PoolReadGuard.h" + #include #include @@ -360,7 +362,6 @@ ReturnValue_t Max31865PT1000Handler::interpretDeviceReply( // do something with rtd value, will propably be stored in // dataset. float rtdValue = adcCode * RTD_RREF_PT1000 / INT16_MAX; - // calculate approximation float approxTemp = adcCode / 32.0 - 256.0; @@ -369,7 +370,7 @@ ReturnValue_t Max31865PT1000Handler::interpretDeviceReply( #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "Max31865PT1000Handler::interpretDeviceReply: Measured " << "resistance is " << rtdValue << " Ohms." << std::endl; - sif::info << "Approximated temperature is " << approxTemp << " °C" + sif::info << "Approximated temperature is " << approxTemp << " C" << std::endl; #else sif::printInfo("Max31865PT1000Handler::interpretDeviceReply: Measured resistance is %f" @@ -380,8 +381,8 @@ ReturnValue_t Max31865PT1000Handler::interpretDeviceReply( } #endif - ReturnValue_t result = sensorDataset.read(); - if(result != HasReturnvaluesIF::RETURN_OK) { + PoolReadGuard pg(&sensorDataset); + if(pg.getReadResult() != HasReturnvaluesIF::RETURN_OK) { // Configuration error #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::debug << "Max31865PT1000Handler::interpretDeviceReply: Error reading dataset!" @@ -389,29 +390,17 @@ ReturnValue_t Max31865PT1000Handler::interpretDeviceReply( #else sif::printDebug("Max31865PT1000Handler::interpretDeviceReply: Error reading dataset!\n"); #endif - return result; + return pg.getReadResult(); } if(not sensorDataset.isValid()) { + sensorDataset.setValidity(true, false); + sensorDataset.rtdValue.setValid(true); sensorDataset.temperatureCelcius.setValid(true); } + sensorDataset.rtdValue = rtdValue; sensorDataset.temperatureCelcius = approxTemp; - - result = sensorDataset.commit(); - - if(result != HasReturnvaluesIF::RETURN_OK) { - // Configuration error -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "Max31865PT1000Handler::interpretDeviceReply: " - "Error commiting dataset!" << std::endl; -#else - sif::printDebug("Max31865PT1000Handler::interpretDeviceReply: " - "Error commiting dataset!\n"); -#endif - return result; - } - break; } case(Max31865Definitions::REQUEST_FAULT_BYTE): { diff --git a/mission/devices/devicedefinitions/Max31865Definitions.h b/mission/devices/devicedefinitions/Max31865Definitions.h index 26c702a3..9b2aa3a2 100644 --- a/mission/devices/devicedefinitions/Max31865Definitions.h +++ b/mission/devices/devicedefinitions/Max31865Definitions.h @@ -9,6 +9,7 @@ namespace Max31865Definitions { enum PoolIds: lp_id_t { + RTD_VALUE, TEMPERATURE_C, FAULT_BYTE }; @@ -46,6 +47,8 @@ public: StaticLocalDataSet(sid_t(objectId, MAX31865_SET_ID)) { } + lp_var_t rtdValue = lp_var_t(sid.objectId, + PoolIds::RTD_VALUE, this); lp_var_t temperatureCelcius = lp_var_t(sid.objectId, PoolIds::TEMPERATURE_C, this); lp_var_t errorByte = lp_var_t(sid.objectId, From 96c9069a69053c906b4b70c33ea14aa35db7607f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jul 2021 13:56:53 +0200 Subject: [PATCH 04/38] new pool entry for rtd value --- mission/devices/Max31865PT1000Handler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/mission/devices/Max31865PT1000Handler.cpp b/mission/devices/Max31865PT1000Handler.cpp index 2a779ee7..751d36eb 100644 --- a/mission/devices/Max31865PT1000Handler.cpp +++ b/mission/devices/Max31865PT1000Handler.cpp @@ -474,6 +474,7 @@ void Max31865PT1000Handler::doTransition(Mode_t modeFrom, ReturnValue_t Max31865PT1000Handler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { + localDataPoolMap.emplace(Max31865Definitions::PoolIds::RTD_VALUE, new PoolEntry({0})); localDataPoolMap.emplace(Max31865Definitions::PoolIds::TEMPERATURE_C, new PoolEntry({0}, 1, true)); localDataPoolMap.emplace(Max31865Definitions::PoolIds::FAULT_BYTE, From f7ac3824987a54a0a8b2b3d14fbb6235f4f485da Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jul 2021 14:00:15 +0200 Subject: [PATCH 05/38] fixes for host build --- bsp_hosted/ObjectFactory.cpp | 2 ++ bsp_hosted/main.cpp | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/bsp_hosted/ObjectFactory.cpp b/bsp_hosted/ObjectFactory.cpp index c5b9ded7..9ea97fd1 100644 --- a/bsp_hosted/ObjectFactory.cpp +++ b/bsp_hosted/ObjectFactory.cpp @@ -56,4 +56,6 @@ void ObjectFactory::produce(void* args){ new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); #endif + new TestTask(objects::TEST_TASK); + } diff --git a/bsp_hosted/main.cpp b/bsp_hosted/main.cpp index 5b43da1e..153cc447 100644 --- a/bsp_hosted/main.cpp +++ b/bsp_hosted/main.cpp @@ -1,9 +1,10 @@ #include "InitMission.h" +#include "OBSWVersion.h" + +#include "fsfw/FSFWVersion.h" +#include "fsfw/tasks/TaskFactory.h" -#include -#include #include - #ifdef WIN32 static const char* COMPILE_PRINTOUT = "Windows"; #elif LINUX @@ -20,8 +21,9 @@ int main(void) { std::cout << "-- EIVE OBSW --" << std::endl; std::cout << "-- Compiled for " << COMPILE_PRINTOUT << " --" << std::endl; - std::cout << "-- Software version " << SW_NAME << " v" << SW_VERSION << "." - << SW_SUBVERSION << "." << SW_REVISION << " -- " << std::endl; + std::cout << "-- OBSW " << SW_NAME << " v" << SW_VERSION << "." << SW_SUBVERSION << + "." << SW_REVISION << ", FSFW v" << FSFW_VERSION << "." << FSFW_SUBVERSION << "." << + FSFW_REVISION << "--" << std::endl; std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; initmission::initMission(); From 292bfaad16f418e0863f361af3cb104e48f0c8b4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jul 2021 14:23:22 +0200 Subject: [PATCH 06/38] readme extended --- README.md | 6 ++++++ common/config/commonConfig.h.in | 2 +- tmtc | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fc218749..a174fbf1 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,12 @@ tmux new -s q7s-serial q7s_serial ``` +Other useful tmux commands: +- Enable scroll mode: You can press `ctrl + b` and then `[` (`AltGr + 8`) to enable scroll mode. + You can quit scroll mode with `q`. +- Kill a tmux session: run `ctrl + b` and then `k`. +- Detach from a tmux session: run `ctrl + b` and then `d` + ### SSH console You can use the following command to connect to the Q7S with `ssh`: diff --git a/common/config/commonConfig.h.in b/common/config/commonConfig.h.in index eaf68b2d..2b0590c8 100644 --- a/common/config/commonConfig.h.in +++ b/common/config/commonConfig.h.in @@ -1,7 +1,7 @@ #ifndef COMMON_CONFIG_COMMONCONFIG_H_ #define COMMON_CONFIG_COMMONCONFIG_H_ -#define OBSW_ADD_LWGPS_TEST 0 +#define OBSW_ADD_LWGPS_TEST 0 // Use TCP instead of UDP for the TMTC bridge. This allows using the TMTC client locally // because UDP packets are not allowed in the VPN diff --git a/tmtc b/tmtc index 2e942ec2..6758ecef 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 2e942ec21e47485b9ab6416a0341b9ab8ec30543 +Subproject commit 6758ecef0d59d6918a7d91e6a6e01f57edb23151 From 2a5cc62af7a424af36eb568dad776ae77884210f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jul 2021 17:25:11 +0200 Subject: [PATCH 07/38] tmtc update --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index 6758ecef..a81b8b60 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 6758ecef0d59d6918a7d91e6a6e01f57edb23151 +Subproject commit a81b8b608df8f991540bc26748f0b86507ed76ef From 0abc854567b6bdc4745e8e9e9f3e18c1dfbb8d15 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jul 2021 17:29:59 +0200 Subject: [PATCH 08/38] tmtc update --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index a81b8b60..9aaf3cfa 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit a81b8b608df8f991540bc26748f0b86507ed76ef +Subproject commit 9aaf3cfa7a9bcd0bfbdb28d1fd92de151f1e6987 From 6625d562e93056f6da1e600ef77d7199f72309d1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jul 2021 17:55:45 +0200 Subject: [PATCH 09/38] tmtc update --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index 9aaf3cfa..2a6c0a6c 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 9aaf3cfa7a9bcd0bfbdb28d1fd92de151f1e6987 +Subproject commit 2a6c0a6cab9be37a80e17ed98e300c8743dd4dd3 From 3824daa865c4208e4ea9f8dcc98c9a7b079f5886 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jul 2021 18:00:14 +0200 Subject: [PATCH 10/38] tmtc update --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index 2a6c0a6c..1f990e96 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 2a6c0a6cab9be37a80e17ed98e300c8743dd4dd3 +Subproject commit 1f990e9647e3f513cf1b3073e94774d530645073 From d511903872162b1d9a13e05ac4f01694f4f7afd8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Jul 2021 15:24:48 +0200 Subject: [PATCH 11/38] tmtc update --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index 1f990e96..31bc3d86 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 1f990e9647e3f513cf1b3073e94774d530645073 +Subproject commit 31bc3d86895dfabf59002880376e9ebfd9015923 From dd61af5bb39aa6d28542cc203c485fdccf51186c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Jul 2021 15:28:51 +0200 Subject: [PATCH 12/38] tmtc update --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index 31bc3d86..8b7331c2 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 31bc3d86895dfabf59002880376e9ebfd9015923 +Subproject commit 8b7331c210e44bf2a60e5834f5f253514dae29fe From c0b91a48796832fc73079b06376f10458e0fdcf0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Jul 2021 16:37:08 +0200 Subject: [PATCH 13/38] added functions to get current boot copy --- bsp_q7s/core/CoreController.cpp | 136 +++++++++++++++++++++----------- bsp_q7s/core/CoreController.h | 28 ++++++- 2 files changed, 117 insertions(+), 47 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 2351c9be..d6555f95 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -15,8 +15,12 @@ #include +CoreController::Chip CoreController::currentChip = Chip::NO_CHIP; +CoreController::Copy CoreController::currentCopy = Copy::NO_COPY; + CoreController::CoreController(object_id_t objectId): ExtendedControllerBase(objectId, objects::NO_OBJECT, 5) { + initBootCopy(); } ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) { @@ -136,51 +140,11 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ const uint8_t *data, size_t size) { switch(actionId) { case(LIST_DIRECTORY_INTO_FILE): { - // TODO: Packet definition for clean deserialization - // 2 bytes for a and R flag, at least 5 bytes for minimum valid path /tmp with - // null termination, at least 7 bytes for minimum target file name /tmp/a with - // null termination. - if(size < 14) { - return HasActionsIF::INVALID_PARAMETERS; - } - // We could also make -l optional, but I can't think of a reason why to not use -l.. - - // This flag specifies to run ls with -a - bool aFlag = data[0]; - data += 1; - // This flag specifies to run ls with -R - bool RFlag = data[1]; - data += 1; - - size_t remainingSize = size - 2; - // One larger for null termination, which prevents undefined behaviour if the sent - // strings are not 0 terminated properly - std::vector repoAndTargetFileBuffer(remainingSize + 1, 0); - std::memcpy(repoAndTargetFileBuffer.data(), data, remainingSize); - const char* currentCharPtr = reinterpret_cast(repoAndTargetFileBuffer.data()); - // Full target file name - std::string repoName(currentCharPtr); - size_t repoLength = repoName.length(); - // The other string needs to be at least one letter plus NULL termination to be valid at all - // The first string also needs to be NULL terminated, but the termination is not included - // in the string length, so this is subtracted from the remaining size as well - if(repoLength > remainingSize - 3) { - return HasActionsIF::INVALID_PARAMETERS; - } - // The file length will not include the NULL termination, so we skip it - currentCharPtr += repoLength + 1; - std::string targetFileName(currentCharPtr); - std::ostringstream oss; - oss << "ls -l"; - if(aFlag) { - oss << "a"; - } - if(RFlag) { - oss << "R"; - } - oss << " " << repoName << " > " << targetFileName; - std::system(oss.str().c_str()); + return actionListDirectoryIntoFile(actionId, commandedBy, data, size); + } + case(REBOOT_OBC): { return HasReturnvaluesIF::RETURN_OK; + break; } default: { return HasActionsIF::INVALID_ACTION_ID; @@ -189,7 +153,7 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ } ReturnValue_t CoreController::initializeAfterTaskCreation() { - ReturnValue_t result = versionFileInit(); + ReturnValue_t result = initVersionFile(); if(result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "CoreController::initialize: Version initialization failed" << std::endl; } @@ -272,7 +236,7 @@ ReturnValue_t CoreController::incrementAllocationFailureCount() { return scratch::writeNumber(scratch::ALLOC_FAILURE_COUNT, count); } -ReturnValue_t CoreController::versionFileInit() { +ReturnValue_t CoreController::initVersionFile() { std::string unameFileName = "/tmp/uname_version.txt"; // TODO: No -v flag for now. If the kernel version is used, need to cut off first few letters @@ -356,6 +320,86 @@ ReturnValue_t CoreController::versionFileInit() { return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t *data, size_t size) { + // TODO: Packet definition for clean deserialization + // 2 bytes for a and R flag, at least 5 bytes for minimum valid path /tmp with + // null termination, at least 7 bytes for minimum target file name /tmp/a with + // null termination. + if(size < 14) { + return HasActionsIF::INVALID_PARAMETERS; + } + // We could also make -l optional, but I can't think of a reason why to not use -l.. + + // This flag specifies to run ls with -a + bool aFlag = data[0]; + data += 1; + // This flag specifies to run ls with -R + bool RFlag = data[1]; + data += 1; + + size_t remainingSize = size - 2; + // One larger for null termination, which prevents undefined behaviour if the sent + // strings are not 0 terminated properly + std::vector repoAndTargetFileBuffer(remainingSize + 1, 0); + std::memcpy(repoAndTargetFileBuffer.data(), data, remainingSize); + const char* currentCharPtr = reinterpret_cast(repoAndTargetFileBuffer.data()); + // Full target file name + std::string repoName(currentCharPtr); + size_t repoLength = repoName.length(); + // The other string needs to be at least one letter plus NULL termination to be valid at all + // The first string also needs to be NULL terminated, but the termination is not included + // in the string length, so this is subtracted from the remaining size as well + if(repoLength > remainingSize - 3) { + return HasActionsIF::INVALID_PARAMETERS; + } + // The file length will not include the NULL termination, so we skip it + currentCharPtr += repoLength + 1; + std::string targetFileName(currentCharPtr); + std::ostringstream oss; + oss << "ls -l"; + if(aFlag) { + oss << "a"; + } + if(RFlag) { + oss << "R"; + } + oss << " " << repoName << " > " << targetFileName; + int result = std::system(oss.str().c_str()); + if(result != 0) { + utility::handleSystemError(result, "CoreController::actionListDirectoryIntoFile"); + actionHelper.finish(false, commandedBy, actionId); + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t CoreController::initBootCopy() { + std::string fileName = "/tmp/curr_copy.txt"; + std::string cmd = "xsc_boot_copy > " + fileName; + int result = std::system(cmd.c_str()); + if(result != 0) { + utility::handleSystemError(result, "CoreController::initBootCopy"); + } + std::ifstream file(fileName); + std::string line; + std::getline(file, line); + std::istringstream iss(line); + int value = 0; + iss >> value; + currentChip = static_cast(value); + sif::debug << "Current chip: " << currentChip << std::endl; + iss >> value; + currentCopy = static_cast(value); + sif::debug << "Current chip: " << currentCopy << std::endl; + return HasReturnvaluesIF::RETURN_OK; +} + +void CoreController::getCurrentBootCopy(Chip &chip, Copy ©) { + // Not really thread-safe but it does not need to be + chip = currentChip; + copy = currentCopy; +} + void CoreController::initPrint() { #if OBSW_VERBOSE_LEVEL >= 1 #if OBSW_USE_TMTC_TCP_BRIDGE == 0 diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 88415949..5576f7ca 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -6,14 +6,30 @@ #include "events/subsystemIdRanges.h" + + class CoreController: public ExtendedControllerBase { public: + enum Chip: uint8_t { + CHIP_0, + CHIP_1, + NO_CHIP + }; + + enum Copy: uint8_t { + COPY_0, + COPY_1, + NO_COPY + }; + static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; + static constexpr ActionId_t REBOOT_OBC = 1; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE; static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM); + CoreController(object_id_t objectId); ReturnValue_t initialize() override; @@ -27,7 +43,12 @@ public: void performControlOperation() override; static ReturnValue_t incrementAllocationFailureCount(); + static void getCurrentBootCopy(Chip& chip, Copy& copy); + private: + static Chip currentChip; + static Copy currentCopy; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) override; LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; @@ -40,7 +61,12 @@ private: ReturnValue_t sdCardColdRedundantInit(SdCardManager* sdcMan, SdCardManager::SdStatusPair& statusPair); - ReturnValue_t versionFileInit(); + ReturnValue_t initVersionFile(); + ReturnValue_t initBootCopy(); + + ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t *data, size_t size); + void initPrint(); }; From 1a4f907925af1c414cad1b89d05fb0ebd3021587 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Jul 2021 17:48:08 +0200 Subject: [PATCH 14/38] moved sd card init, more functions static now --- README.md | 2 +- bsp_q7s/core/CoreController.cpp | 23 +++++++++++++---------- bsp_q7s/core/CoreController.h | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a174fbf1..d71db451 100644 --- a/README.md +++ b/README.md @@ -318,7 +318,7 @@ wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/rfoaistRd67yBbH/downloa or the following command for Linux (could be useful for CI/CD) ```sh -wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/2Fp2ag6NGnbtAsK/download/gcc-arm-linux-gnueabi.tar.gz +wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/MRaeA2XnMXpZ5Pp/download/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.xz ``` ## Installing CMake and MSYS2 on Windows diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index d6555f95..5d99d3ec 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -20,6 +20,18 @@ CoreController::Copy CoreController::currentCopy = Copy::NO_COPY; CoreController::CoreController(object_id_t objectId): ExtendedControllerBase(objectId, objects::NO_OBJECT, 5) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + try { + result = sdCardInit(); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::CoreController: SD card init failed" << std::endl; + } + } + catch(const std::filesystem::filesystem_error& e) { + sif::error << "CoreController::CoreController: sdCardInit failed with exception " << + e.what() << std::endl; + } + initBootCopy(); } @@ -41,16 +53,6 @@ LocalPoolDataSetBase* CoreController::getDataSetHandle(sid_t sid) { ReturnValue_t CoreController::initialize() { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - try { - result = sdCardInit(); - if(result != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "CoreController::initialize: SD card init failed" << std::endl; - } - } - catch(const std::filesystem::filesystem_error& e) { - sif::error << "CoreController::initialize: sdCardInit failed with exception " << e.what() - << std::endl; - } result = scratch::writeNumber(scratch::ALLOC_FAILURE_COUNT, 0); if(result != HasReturnvaluesIF::RETURN_OK) { @@ -374,6 +376,7 @@ ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId, } ReturnValue_t CoreController::initBootCopy() { + // We could create this file even before the OBSW is started.. std::string fileName = "/tmp/curr_copy.txt"; std::string cmd = "xsc_boot_copy > " + fileName; int result = std::system(cmd.c_str()); diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 5576f7ca..add107e7 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -62,7 +62,7 @@ private: SdCardManager::SdStatusPair& statusPair); ReturnValue_t initVersionFile(); - ReturnValue_t initBootCopy(); + static ReturnValue_t initBootCopy(); ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t *data, size_t size); From 1e6ea91438147734330869512577324ca4eb0fa4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Jul 2021 18:43:11 +0200 Subject: [PATCH 15/38] README update --- README.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d71db451..b8ecdde6 100644 --- a/README.md +++ b/README.md @@ -591,6 +591,10 @@ More detailed information about the used q7s commands can be found in the Q7S us ## Launching an application at start-up +You can also do the steps performed here on a host computer inside the `q7s-rootfs` directory +of the [Q7S base repository](https://egit.irs.uni-stuttgart.de/eive/q7s-base). This might +be more convenient while also allowing to update all images at once with the finished `rootfs.xdi`. + Load the root partiton from the flash memory (there are to nor-flash memories and each flash holds two xdi images). Note: It is not possible to modify the currently loaded root partition, e.g. creating directories. To do this, the parition needs to be mounted. @@ -616,7 +620,7 @@ creating directories. To do this, the parition needs to be mounted. chmod +x application ``` -5. Create systemd service in /lib/systemd/system. The following shows an example service. +5. Create systemd service in `/etc/systemd/system`. The following shows an example service. ```sh cat > example.service @@ -634,11 +638,19 @@ creating directories. To do this, the parition needs to be mounted. [Install] WantedBy=multi-user.target ``` -6. Enable the service. This is normally done with systemctl enable. However, this is not possible - when the service is created for a mounted root partition. Therefore create a symlink as follows. + +6. Enable the service. This is normally done with `systemctl enable ` which would create + a symlink in the `multi-user.target.wants` directory. However, this is not possible + when the service is created for a mounted root partition. It is also not possible during run + time because symlinks can't be created in a read-only filesystem. Therefore, relative symlinks + are used like this: + ```sh - ln -s '/tmp/the-mounted-xdi-image/lib/systemd/system/example.service' '/tmp/the-mounted-xdi-image/etc/systemd/system/multi-user.target.wants/example.service' + cd etc/systemd/system/multi-user.target.wants/ + ln -s ../example.service example.service ``` + + You can check the symlinnks with `ls -l` 7. The modified root partition is written back when the partion is locked again. ```sh From b846a936b439a12e5a23faffe587ab32e42deb13 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Jul 2021 18:50:50 +0200 Subject: [PATCH 16/38] README update --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index b8ecdde6..4865885d 100644 --- a/README.md +++ b/README.md @@ -666,6 +666,29 @@ creating directories. To do this, the parition needs to be mounted. systemctl status example ``` + +## Current user systemd services + +The following custom `systemd` services are currently running on the Q7S and can be found in +the `/etc/systemd/system` folder. +You can query that status of a service by running `systemctl status `. + +### `tcfagent` + +This starts the `/usr/bin/agent` program to allows remote debugging. Might not be part of +the mission code + +### `eive-early-config` + +This is a configuration script which runs early after `local-fs.target` and `sysinit.target` +Currently only pipes the output of `xsc_boot_copy` into the file `/tmp/curr_copy.txt` which can be +used by other software components to read the current chip and copy. + +### `eive-post-ntpd-config` + +This is a configuration scripts which runs after the Network Time Protocol has run. This script +currently sets the static IP address `192.168.133.10` and starts the `can` interface. + ## PCDU Connect to serial console of P60 Dock From fc769be7894605459dedd2fe57ba800ceba7aa6f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Jul 2021 18:56:36 +0200 Subject: [PATCH 17/38] updated cp script --- scripts/q7s-cp.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/q7s-cp.py b/scripts/q7s-cp.py index 9de9d661..0c8c1a79 100755 --- a/scripts/q7s-cp.py +++ b/scripts/q7s-cp.py @@ -8,7 +8,13 @@ def main(): cmd = build_cmd(args) # Run the command print(f'Running command: {cmd}') - os.system(cmd) + result = os.system(cmd) + if result != 0: + print('') + print('Removing problematic SSH key and trying again..') + remove_ssh_key_cmd = 'ssh-keygen -f "${HOME}/.ssh/known_hosts" -R "[localhost]:1535"' + os.system(remove_ssh_key_cmd) + result = os.system(cmd) def handle_args(): From 125593be21cdf4f9211f926adac1b3cbf8077a65 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Jul 2021 19:46:19 +0200 Subject: [PATCH 18/38] reading chip and copy works --- bsp_q7s/core/CoreController.cpp | 27 +++++++++++++++------------ bsp_q7s/core/CoreController.h | 4 ++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 5d99d3ec..a37db440 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -22,17 +22,19 @@ CoreController::CoreController(object_id_t objectId): ExtendedControllerBase(objectId, objects::NO_OBJECT, 5) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; try { - result = sdCardInit(); + result = initSdCard(); if(result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "CoreController::CoreController: SD card init failed" << std::endl; } + result = initBootCopy(); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::CoreController: Boot copy init" << std::endl; + } } catch(const std::filesystem::filesystem_error& e) { - sif::error << "CoreController::CoreController: sdCardInit failed with exception " << + sif::error << "CoreController::CoreController: Failed with exception " << e.what() << std::endl; } - - initBootCopy(); } ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) { @@ -68,7 +70,7 @@ ReturnValue_t CoreController::checkModeCommand(Mode_t mode, Submode_t submode, return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t CoreController::sdCardInit() { +ReturnValue_t CoreController::initSdCard() { #if Q7S_SD_CARD_CONFIG == Q7S_SD_NONE sif::info << "No SD card initialization will be performed" << std::endl; return HasReturnvaluesIF::RETURN_OK; @@ -376,12 +378,15 @@ ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId, } ReturnValue_t CoreController::initBootCopy() { - // We could create this file even before the OBSW is started.. std::string fileName = "/tmp/curr_copy.txt"; - std::string cmd = "xsc_boot_copy > " + fileName; - int result = std::system(cmd.c_str()); - if(result != 0) { - utility::handleSystemError(result, "CoreController::initBootCopy"); + if(not std::filesystem::exists(fileName)) { + // Thils file is created by the systemd service eive-early-config so this should + // not happen normally + std::string cmd = "xsc_boot_copy > " + fileName; + int result = std::system(cmd.c_str()); + if(result != 0) { + utility::handleSystemError(result, "CoreController::initBootCopy"); + } } std::ifstream file(fileName); std::string line; @@ -390,10 +395,8 @@ ReturnValue_t CoreController::initBootCopy() { int value = 0; iss >> value; currentChip = static_cast(value); - sif::debug << "Current chip: " << currentChip << std::endl; iss >> value; currentCopy = static_cast(value); - sif::debug << "Current chip: " << currentCopy << std::endl; return HasReturnvaluesIF::RETURN_OK; } diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index add107e7..34d72be4 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -55,14 +55,14 @@ private: ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode); - ReturnValue_t sdCardInit(); + ReturnValue_t initSdCard(); ReturnValue_t sdCardSetup(SdCardManager& sdcMan, SdCardManager::SdStatusPair& statusPair, sd::SdCard sdCard, sd::SdStatus status, std::string sdString); ReturnValue_t sdCardColdRedundantInit(SdCardManager* sdcMan, SdCardManager::SdStatusPair& statusPair); ReturnValue_t initVersionFile(); - static ReturnValue_t initBootCopy(); + ReturnValue_t initBootCopy(); ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t *data, size_t size); From 190590e1b5270377e770bf337cc6f94e07702279 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Jul 2021 20:11:22 +0200 Subject: [PATCH 19/38] new conf option --- bsp_q7s/boardconfig/q7sConfig.h.in | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bsp_q7s/boardconfig/q7sConfig.h.in b/bsp_q7s/boardconfig/q7sConfig.h.in index 2fd52eb7..61e924d8 100644 --- a/bsp_q7s/boardconfig/q7sConfig.h.in +++ b/bsp_q7s/boardconfig/q7sConfig.h.in @@ -5,9 +5,9 @@ #cmakedefine01 Q7S_SIMPLE_MODE -#define Q7S_SD_NONE 0 -#define Q7S_SD_COLD_REDUNDANT 1 -#define Q7S_SD_HOT_REDUNDANT 2 +#define Q7S_SD_NONE 0 +#define Q7S_SD_COLD_REDUNDANT 1 +#define Q7S_SD_HOT_REDUNDANT 2 // The OBSW will perform different actions to set up the SD cards depending on the flag set here // Set to Q7S_SD_NONE: Don't do anything // Set to Q7S_COLD_REDUNDANT: On startup, get the prefered SD card, turn it on and mount it, and @@ -15,7 +15,9 @@ // Set to Q7S_HOT_REDUNDANT: On startup, turn on both SD cards and mount them #define Q7S_SD_CARD_CONFIG Q7S_SD_COLD_REDUNDANT -#define Q7S_ADD_RTD_DEVICES 0 +// Probably better if this is disabled for mission code. Convenient for development +#define Q7S_CHECK_FOR_ALREADY_RUNNING_IMG 1 +#define Q7S_ADD_RTD_DEVICES 0 /* Only one of those 2 should be enabled! */ /* Add code for ACS board */ From 59bcf6cec20baf94114cd4211c39d886e2f7c3bb Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 11:35:20 +0200 Subject: [PATCH 20/38] added eive-watchdog --- CMakeLists.txt | 74 +++++--- .../Q7S/simple/simple_make_debug_cfg.sh | 2 +- .../Q7S/simple/simple_ninja_debug_cfg.sh | 2 +- watchdog/CMakeLists.txt | 4 + watchdog/Watchdog.cpp | 161 ++++++++++++++++++ watchdog/Watchdog.h | 37 ++++ watchdog/main.cpp | 15 ++ watchdog/watchdogConf.h.in | 16 ++ 8 files changed, 283 insertions(+), 28 deletions(-) create mode 100644 watchdog/CMakeLists.txt create mode 100644 watchdog/Watchdog.cpp create mode 100644 watchdog/Watchdog.h create mode 100644 watchdog/main.cpp create mode 100644 watchdog/watchdogConf.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index b7dbea87..49d0d42b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,8 @@ cmake_minimum_required(VERSION 3.13) set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") if(TGT_BSP MATCHES "arm/q7s") - option(Q7S_SIMPLE_MODE OFF "Simple mode with a minimal main function") + option(BUILD_WATCHDOG "Compile the OBSW watchdog insted" OFF) + option(BUILD_Q7S_SIMPLE_MODE OFF "Simple mode with a minimal main function") endif() option(ADD_ETL_LIB "Add ETL library" ON) @@ -32,8 +33,13 @@ endif() include(${CMAKE_SCRIPT_PATH}/PreProjectConfig.cmake) pre_project_config() +set(PROJECT_NAME_TO_SET eive-obsw) +if(BUILD_WATCHDOG) + set(PROJECT_NAME_TO_SET eive-watchdog) +endif() + # Project Name -project(eive_obsw ASM C CXX) +project(${PROJECT_NAME_TO_SET} ASM C CXX) ################################################################################ # Pre-Sources preparation @@ -60,6 +66,7 @@ set(MISSION_PATH mission) set(TEST_PATH test/testtasks) set(LINUX_PATH linux) set(COMMON_PATH common) +set(WATCHDOG_PATH watchdog) set(COMMON_CONFIG_PATH ${COMMON_PATH}/config) set(FSFW_HAL_LIB_PATH fsfw_hal) @@ -82,7 +89,7 @@ if(TGT_BSP) OR TGT_BSP MATCHES "arm/beagleboneblack" ) set(FSFW_CONFIG_PATH "linux/fsfwconfig") - if(NOT Q7S_SIMPLE_MODE) + if(NOT BUILD_Q7S_SIMPLE_MODE) set(ADD_LINUX_FILES TRUE) set(ADD_CSP_LIB TRUE) set(FSFW_HAL_ADD_LINUX ON) @@ -107,13 +114,17 @@ else() endif() # Configuration files -configure_file(${COMMON_CONFIG_PATH}/commonConfig.h.in commonConfig.h) -configure_file(${FSFW_CONFIG_PATH}/FSFWConfig.h.in FSFWConfig.h) -configure_file(${FSFW_CONFIG_PATH}/OBSWConfig.h.in OBSWConfig.h) -if(${TGT_BSP} MATCHES "arm/q7s") - configure_file(${BSP_PATH}/boardconfig/q7sConfig.h.in q7sConfig.h) -elseif(${TGT_BSP} MATCHES "arm/raspberrypi") - configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h) +if(NOT BUILD_WATCHDOG) + configure_file(${COMMON_CONFIG_PATH}/commonConfig.h.in commonConfig.h) + configure_file(${FSFW_CONFIG_PATH}/FSFWConfig.h.in FSFWConfig.h) + configure_file(${FSFW_CONFIG_PATH}/OBSWConfig.h.in OBSWConfig.h) + if(${TGT_BSP} MATCHES "arm/q7s") + configure_file(${BSP_PATH}/boardconfig/q7sConfig.h.in q7sConfig.h) + elseif(${TGT_BSP} MATCHES "arm/raspberrypi") + configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h) + endif() +else() + configure_file(${WATCHDOG_PATH}/watchdogConf.h.in watchdogConf.h) endif() # Set common config path for FSFW @@ -131,26 +142,27 @@ set(LWGPS_CONFIG_PATH "${COMMON_PATH}/config") # Add executable add_executable(${TARGET_NAME}) -if(ADD_CSP_LIB) - add_subdirectory(${CSP_LIB_PATH}) -endif() - if(ADD_ETL_LIB) add_subdirectory(${ETL_LIB_PATH}) endif() -if(ADD_LINUX_FILES) - add_subdirectory(${LINUX_PATH}) -endif() - if(ADD_JSON_LIB) add_subdirectory(${LIB_JSON_PATH}) endif() -add_subdirectory(${BSP_PATH}) -add_subdirectory(${COMMON_PATH}) +if(ADD_CSP_LIB) + add_subdirectory(${CSP_LIB_PATH}) +endif() -if(NOT Q7S_SIMPLE_MODE) +if(NOT BUILD_WATCHDOG) + if(ADD_LINUX_FILES) + add_subdirectory(${LINUX_PATH}) + endif() + add_subdirectory(${BSP_PATH}) + add_subdirectory(${COMMON_PATH}) +endif() + +if((NOT BUILD_Q7S_SIMPLE_MODE) AND (NOT BUILD_WATCHDOG)) add_subdirectory(${LWGPS_LIB_PATH}) add_subdirectory(${FSFW_PATH}) add_subdirectory(${MISSION_PATH}) @@ -158,6 +170,9 @@ if(NOT Q7S_SIMPLE_MODE) add_subdirectory(${ARCSEC_LIB_PATH}) endif() +if(BUILD_WATCHDOG) + add_subdirectory(${WATCHDOG_PATH}) +endif() ################################################################################ # Post-Sources preparation @@ -165,14 +180,13 @@ endif() set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux) -if(NOT Q7S_SIMPLE_MODE) +if((NOT BUILD_Q7S_SIMPLE_MODE) AND (NOT BUILD_WATCHDOG)) # Add libraries for all sources. target_link_libraries(${TARGET_NAME} PRIVATE ${LIB_FSFW_NAME} ${LIB_OS_NAME} ${LIB_LWGPS_NAME} ${LIB_ARCSEC} - ${LIB_CXX_FS} ) endif() @@ -194,6 +208,10 @@ if(ADD_JSON_LIB) ) endif() +target_link_libraries(${TARGET_NAME} PRIVATE + ${LIB_CXX_FS} +) + # Add include paths for all sources. target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} @@ -249,10 +267,14 @@ if(NOT CMAKE_SIZE) endif() endif() -if(TGT_BSP) - set(TARGET_STRING "Target BSP: ${TGT_BSP}") +if(BUILD_WATCHDOG) + set(TARGET_STRING "OBSW Watchdog") else() - set(TARGET_STRING "Target BSP: Hosted") + if(TGT_BSP) + set(TARGET_STRING "Target BSP: ${TGT_BSP}") + else() + set(TARGET_STRING "Target BSP: Hosted") + endif() endif() string(CONCAT POST_BUILD_COMMENT diff --git a/cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh b/cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh index 8a6c7b3f..50b87101 100755 --- a/cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh +++ b/cmake/scripts/Q7S/simple/simple_make_debug_cfg.sh @@ -18,7 +18,7 @@ os_fsfw="linux" tgt_bsp="arm/q7s" build_dir="build-Simple-Q7S" build_generator="" -definitions="Q7S_SIMPLE_MODE=On" +definitions="BUILD_Q7S_SIMPLE_MODE=On" if [ "${OS}" = "Windows_NT" ]; then build_generator="MinGW Makefiles" python="py" diff --git a/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh b/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh index 965aae45..c97b1e54 100755 --- a/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh +++ b/cmake/scripts/Q7S/simple/simple_ninja_debug_cfg.sh @@ -18,7 +18,7 @@ os_fsfw="linux" tgt_bsp="arm/q7s" build_dir="build-Simple-Q7S" build_generator="Ninja" -definitions="Q7S_SIMPLE_MODE=On" +definitions="BUILD_Q7S_SIMPLE_MODE=On" if [ "${OS}" = "Windows_NT" ]; then python="py" # Could be other OS but this works for now. diff --git a/watchdog/CMakeLists.txt b/watchdog/CMakeLists.txt new file mode 100644 index 00000000..0179053c --- /dev/null +++ b/watchdog/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(${TARGET_NAME} PRIVATE + main.cpp + Watchdog.cpp +) diff --git a/watchdog/Watchdog.cpp b/watchdog/Watchdog.cpp new file mode 100644 index 00000000..e66a2545 --- /dev/null +++ b/watchdog/Watchdog.cpp @@ -0,0 +1,161 @@ +#include "Watchdog.h" +#include "watchdogConf.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + + +WatchdogTask::WatchdogTask (): fd(0) { + +} + +WatchdogTask::~WatchdogTask() { + +} + +int WatchdogTask::performOperation() { + int result = 0; + // Only create the FIFO if it does not exist yet + if(not std::filesystem::exists(watchdog::FIFO_NAME)) { + // Permission 666 or rw-rw-rw- + mode_t mode = DEFFILEMODE; + result = mkfifo(watchdog::FIFO_NAME.c_str(), mode); + if(result != 0) { + std::cerr << "eive-watchdog: Could not created named pipe at " << + watchdog::FIFO_NAME << ", error " << errno << ": " << strerror(errno) << + std::endl; + return -2; + } +#if WATCHDOG_VERBOSE_LEVEL >= 1 + std::cout << "eive-watchdog: Pipe at " << watchdog::FIFO_NAME << + " created successfully" << std::endl; +#endif + } + + // Open FIFO read only and non-blocking + fd = open(watchdog::FIFO_NAME.c_str(), O_RDONLY | O_NONBLOCK); + if(fd < 0) { + std::cerr << "eive-watchdog: Opening pipe " << watchdog::FIFO_NAME << + "read-only failed with " << errno << ": " << strerror(errno) << std::endl; + } + + while(true) { + WatchdogTask::LoopResult loopResult = watchdogLoop(); + switch(loopResult) { + case(LoopResult::OK): { + break; + } + case(LoopResult::CANCEL_RQ): { + if(state == States::RUNNING) { + state = States::SUSPENDED; + } + break; + } + case(LoopResult::TIMEOUT): { + std::cout << "eive-watchdog: The FIFO timed out!" << std::endl; + break; + } + case(LoopResult::RESTART_RQ): { + if(state == States::SUSPENDED) { + state = States::RUNNING; + } + break; + } + } + } + if (close(fd) < 0) { + std::cerr << "eive-watchdog: Closing named pipe at " << watchdog::FIFO_NAME << + "failed, error " << errno << ": " << strerror(errno) << std::endl; + } + std::cout << "eive-watchdog: Finished" << std::endl; + return 0; +} + +WatchdogTask::LoopResult WatchdogTask::watchdogLoop() { + using namespace std::chrono_literals; + char readChar; + struct pollfd waiter = {}; + waiter.fd = fd; + waiter.events = POLLIN; + + switch(state) { + case(States::SUSPENDED): { + // Sleep, then check whether a restart request was received + std::this_thread::sleep_for(1000ms); + break; + } + case(States::RUNNING): { + // Continue as usual + break; + } + case(States::NOT_STARTED): { + // This should not happen + std::cerr << "eive-watchdog: State is NOT_STARTED, configuration error" << std::endl; + break; + } + case(States::FAULTY): { + // TODO: Not sure what to do yet. Continue for now + break; + } + } + + // 10 seconds timeout, only poll one file descriptor + switch(poll(&waiter, 1, watchdog::TIMEOUT_MS)) { + case(0): { + return LoopResult::TIMEOUT; + } + case(1): { + if (waiter.revents & POLLIN) { + ssize_t readLen = read(fd, buf.data(), buf.size()); + if (readLen < 0) { + std::cerr << "eive-watchdog: Read error on pipe " << watchdog::FIFO_NAME << + ", error " << errno << ": " << strerror(errno) << std::endl; + break; + } + for(ssize_t idx = 0; idx < readLen; idx++) { + readChar = buf[idx]; + // Cancel request + if(readChar == 'c') { + return LoopResult::CANCEL_RQ; + } + // Begin request. Does not work if the operation was not suspended before + else if(readChar == 'b') { + return LoopResult::RESTART_RQ; + } + // Everything else: All working as expected + else { + + } + } +#if WATCHDOG_VERBOSE_LEVEL == 2 + std::cout << "Read " << readLen << " byte(s) on the pipe " << FIFO_NAME + << std::endl; +#endif + } + else if(waiter.revents & POLLERR) { + std::cerr << "eive-watchdog: Poll error error on pipe " << watchdog::FIFO_NAME << + std::endl; + } + else if (waiter.revents & POLLHUP) { + // Writer closed its end + } + break; + } + default: { + std::cerr << "eive-watchdog: Unknown poll error at " << watchdog::FIFO_NAME << ", error " << + errno << ": " << strerror(errno) << std::endl; + break; + } + } + return LoopResult::OK; +} diff --git a/watchdog/Watchdog.h b/watchdog/Watchdog.h new file mode 100644 index 00000000..53935fc2 --- /dev/null +++ b/watchdog/Watchdog.h @@ -0,0 +1,37 @@ +#ifndef WATCHDOG_WATCHDOG_H_ +#define WATCHDOG_WATCHDOG_H_ + +#include + + +class WatchdogTask { +public: + enum class States { + NOT_STARTED, + RUNNING, + SUSPENDED, + FAULTY + }; + + enum class LoopResult { + OK, + CANCEL_RQ, + RESTART_RQ, + TIMEOUT + }; + + WatchdogTask(); + + virtual ~WatchdogTask(); + + int performOperation(); +private: + int fd = 0; + + std::array buf; + States state = States::NOT_STARTED; + + LoopResult watchdogLoop(); +}; + +#endif /* WATCHDOG_WATCHDOG_H_ */ diff --git a/watchdog/main.cpp b/watchdog/main.cpp new file mode 100644 index 00000000..eea608f1 --- /dev/null +++ b/watchdog/main.cpp @@ -0,0 +1,15 @@ +#include "Watchdog.h" + +#include + +/** + * @brief This watchdog application uses a FIFO to check whether the OBSW is still running. + * It checks whether the OBSW writes to the the FIFO regularly. + */ +int main() { + std::cout << "Starting OBSW watchdog.." << std::endl; + WatchdogTask watchdogTask; + watchdogTask.performOperation(); + return 0; +} + diff --git a/watchdog/watchdogConf.h.in b/watchdog/watchdogConf.h.in new file mode 100644 index 00000000..8b9a0afc --- /dev/null +++ b/watchdog/watchdogConf.h.in @@ -0,0 +1,16 @@ +#include + +#define WATCHDOG_VERBOSE_LEVEL 1 +/** + * This flag instructs the watchdog to create a special file in /tmp if the OBSW is running + * or to delete it if it is not running + */ +#define WATCHDOG_CREATE_FILE_IF_RUNNING 1 + +namespace watchdog { + +static constexpr int TIMEOUT_MS = 10 * 1000; +const std::string FIFO_NAME = "/tmp/obsw-watchdog"; +const std::string RUNNING_FILE_NAME = "/tmp/obsw-running"; + +} From 55727accf5e35f81371214f74ac18faaa9a33e95 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 11:59:32 +0200 Subject: [PATCH 21/38] minor tweaks --- watchdog/Watchdog.cpp | 18 ++++++++---------- watchdog/main.cpp | 11 ++++++++--- watchdog/watchdogConf.h.in | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/watchdog/Watchdog.cpp b/watchdog/Watchdog.cpp index e66a2545..f4f8c03c 100644 --- a/watchdog/Watchdog.cpp +++ b/watchdog/Watchdog.cpp @@ -14,16 +14,7 @@ #include - WatchdogTask::WatchdogTask (): fd(0) { - -} - -WatchdogTask::~WatchdogTask() { - -} - -int WatchdogTask::performOperation() { int result = 0; // Only create the FIFO if it does not exist yet if(not std::filesystem::exists(watchdog::FIFO_NAME)) { @@ -34,20 +25,27 @@ int WatchdogTask::performOperation() { std::cerr << "eive-watchdog: Could not created named pipe at " << watchdog::FIFO_NAME << ", error " << errno << ": " << strerror(errno) << std::endl; - return -2; + throw std::runtime_error("eive-watchdog: FIFO creation failed"); } #if WATCHDOG_VERBOSE_LEVEL >= 1 std::cout << "eive-watchdog: Pipe at " << watchdog::FIFO_NAME << " created successfully" << std::endl; #endif } +} +WatchdogTask::~WatchdogTask() { + +} + +int WatchdogTask::performOperation() { // Open FIFO read only and non-blocking fd = open(watchdog::FIFO_NAME.c_str(), O_RDONLY | O_NONBLOCK); if(fd < 0) { std::cerr << "eive-watchdog: Opening pipe " << watchdog::FIFO_NAME << "read-only failed with " << errno << ": " << strerror(errno) << std::endl; } + state = States::RUNNING; while(true) { WatchdogTask::LoopResult loopResult = watchdogLoop(); diff --git a/watchdog/main.cpp b/watchdog/main.cpp index eea608f1..a1ae3ae8 100644 --- a/watchdog/main.cpp +++ b/watchdog/main.cpp @@ -7,9 +7,14 @@ * It checks whether the OBSW writes to the the FIFO regularly. */ int main() { - std::cout << "Starting OBSW watchdog.." << std::endl; - WatchdogTask watchdogTask; - watchdogTask.performOperation(); + std::cout << "eive-watchdog: Starting OBSW watchdog.." << std::endl; + try { + WatchdogTask watchdogTask; + watchdogTask.performOperation(); + } + catch(const std::runtime_error& e) { + std::cerr << "eive-watchdog: Run time exception " << e.what() << std::endl; + } return 0; } diff --git a/watchdog/watchdogConf.h.in b/watchdog/watchdogConf.h.in index 8b9a0afc..daa9f248 100644 --- a/watchdog/watchdogConf.h.in +++ b/watchdog/watchdogConf.h.in @@ -10,7 +10,7 @@ namespace watchdog { static constexpr int TIMEOUT_MS = 10 * 1000; -const std::string FIFO_NAME = "/tmp/obsw-watchdog"; +const std::string FIFO_NAME = "/tmp/watchdog-pipe"; const std::string RUNNING_FILE_NAME = "/tmp/obsw-running"; } From 6361fcb6bb32a3c150a6e82538393d11f8957e79 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Thu, 29 Jul 2021 12:06:14 +0200 Subject: [PATCH 22/38] added Jenkinsfile, moved together with Dockerfile into automation folder having the automation files in an empty folder accelerates docker build. Also, I think these files are not related to the source code and as such should live in their own space --- automation/Dockerfile-q7s | 18 ++++++++++++++ automation/Jenkinsfile | 49 +++++++++++++++++++++++++++++++++++++++ bsp_q7s/Dockerfile | 35 ---------------------------- 3 files changed, 67 insertions(+), 35 deletions(-) create mode 100644 automation/Dockerfile-q7s create mode 100644 automation/Jenkinsfile delete mode 100644 bsp_q7s/Dockerfile diff --git a/automation/Dockerfile-q7s b/automation/Dockerfile-q7s new file mode 100644 index 00000000..207afa04 --- /dev/null +++ b/automation/Dockerfile-q7s @@ -0,0 +1,18 @@ +FROM ubuntu:focal + +RUN apt-get update +RUN apt-get --yes upgrade +RUN apt-get --yes install cmake libgpiod-dev xz-utils nano curl + +# Q7S root filesystem, required for cross-compilation. +RUN mkdir -p /usr/rootfs; \ +curl https://buggy.irs.uni-stuttgart.de/eive/tools/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz \ + | tar -xz -C /usr/rootfs + +# Cross compiler +RUN mkdir -p /usr/tools; \ +curl https://buggy.irs.uni-stuttgart.de/eive/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.gz \ + | tar -xz -C /usr/tools + +ENV Q7S_SYSROOT="/usr/rootfs/cortexa9hf-neon-xiphos-linux-gnueabi" +ENV PATH=$PATH:"/usr/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin" diff --git a/automation/Jenkinsfile b/automation/Jenkinsfile new file mode 100644 index 00000000..8b735710 --- /dev/null +++ b/automation/Jenkinsfile @@ -0,0 +1,49 @@ +pipeline { + agent any + stages { + stage('Build Container') { + when { + changeset "automation/Dockerfile-q7s" + branch 'develop' + } + steps { + sh 'docker build -t eive-fsw-build-q7s:gcc8 - < automation/Dockerfile-q7s' + + } + } + stage('Clean') { + when { + anyof { + changelog 'cleanCI' + changeset '*.cmake' + changeset 'CMakeLists.txt' + } + } + steps { + sh 'rm -rf build-q7s-debug' + } + } + stage('Build Q7S') { + agent { + docker { + image 'eive-fsw-build-q7s:gcc8' + reuseNode true + } + } + steps { + dir('build-q7s-debug') { + sh 'cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DFSFW_OSAL=linux ..' + sh 'cmake --build . -j' + } + } + } + stage('Deploy') { + when { + tag 'v*.*.*' + } + steps { + sh 'echo Deploying' + } + } + } +} diff --git a/bsp_q7s/Dockerfile b/bsp_q7s/Dockerfile deleted file mode 100644 index 04184c4a..00000000 --- a/bsp_q7s/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -FROM ubuntu:latest -# FROM alpine:latest - -ENV TZ=Europe/Berlin -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - -RUN apt-get update && apt-get install -y curl cmake g++ - -# Q7S root filesystem, required for cross-compilation. Use IPv6 for curl -RUN mkdir -p /usr/rootfs; \ - curl -6 https://eive-cloud.irs.uni-stuttgart.de/index.php/s/dnfMy9kGpgynN6J/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz \ - | tar xvz -C /usr/rootfs -# Q7S C++ cross-compiler. Use IPv6 for curl -RUN mkdir -p /usr/tools; \ - curl -6 https://eive-cloud.irs.uni-stuttgart.de/index.php/s/RMsbHydJc6PSqcz/download/gcc-arm-linux-gnueabi.tar.gz \ - | tar xvz -C /usr/tools - -# RUN apk add cmake make g++ - -# Required for cmake build -ENV Q7S_SYSROOT="/usr/rootfs/cortexa9hf-neon-xiphos-linux-gnueabi" -ENV PATH=$PATH:"/usr/tools/gcc-arm-linux-gnueabi/bin" - -WORKDIR /usr/src/app -COPY . . - -RUN set -ex; \ - rm -rf build-q7s; \ - mkdir build-q7s; \ - cd build-q7s; \ - cmake -DCMAKE_BUILD_TYPE=Release -DOS_FSFW=linux -DTGT_BSP="arm/q7s" ..; - -ENTRYPOINT ["cmake", "--build", "build-q7s"] -CMD ["-j"] -# CMD ["bash"] From afb7a2008f8267d118e34e23b1e90deb8d5e1d0f Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Thu, 29 Jul 2021 12:14:37 +0200 Subject: [PATCH 23/38] typo in Jenkinsfile --- automation/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automation/Jenkinsfile b/automation/Jenkinsfile index 8b735710..52cd895b 100644 --- a/automation/Jenkinsfile +++ b/automation/Jenkinsfile @@ -13,7 +13,7 @@ pipeline { } stage('Clean') { when { - anyof { + anyOf { changelog 'cleanCI' changeset '*.cmake' changeset 'CMakeLists.txt' From acaf87095aa504c8ceb603e3e4eca9516eecbc47 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Thu, 29 Jul 2021 12:17:30 +0200 Subject: [PATCH 24/38] forcing docker build --- automation/Dockerfile-q7s | 1 + 1 file changed, 1 insertion(+) diff --git a/automation/Dockerfile-q7s b/automation/Dockerfile-q7s index 207afa04..21b56439 100644 --- a/automation/Dockerfile-q7s +++ b/automation/Dockerfile-q7s @@ -14,5 +14,6 @@ RUN mkdir -p /usr/tools; \ curl https://buggy.irs.uni-stuttgart.de/eive/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.gz \ | tar -xz -C /usr/tools + ENV Q7S_SYSROOT="/usr/rootfs/cortexa9hf-neon-xiphos-linux-gnueabi" ENV PATH=$PATH:"/usr/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin" From af6f24d66866c4cc6e512bfab35cf89ccb9c94d6 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Thu, 29 Jul 2021 12:18:32 +0200 Subject: [PATCH 25/38] forcing docker build #2 --- automation/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automation/Jenkinsfile b/automation/Jenkinsfile index 52cd895b..70db7d41 100644 --- a/automation/Jenkinsfile +++ b/automation/Jenkinsfile @@ -4,7 +4,7 @@ pipeline { stage('Build Container') { when { changeset "automation/Dockerfile-q7s" - branch 'develop' + branch 'mohr_ci' } steps { sh 'docker build -t eive-fsw-build-q7s:gcc8 - < automation/Dockerfile-q7s' From 6c8336bcfedc629b0ae95694cd00ec6269da1963 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Thu, 29 Jul 2021 12:20:02 +0200 Subject: [PATCH 26/38] something's broken with the automatic docker build, reverting change, will look into it later --- automation/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automation/Jenkinsfile b/automation/Jenkinsfile index 70db7d41..52cd895b 100644 --- a/automation/Jenkinsfile +++ b/automation/Jenkinsfile @@ -4,7 +4,7 @@ pipeline { stage('Build Container') { when { changeset "automation/Dockerfile-q7s" - branch 'mohr_ci' + branch 'develop' } steps { sh 'docker build -t eive-fsw-build-q7s:gcc8 - < automation/Dockerfile-q7s' From 93fa82c4135b173de84efa34226ecfe51b788dc5 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Thu, 29 Jul 2021 12:23:17 +0200 Subject: [PATCH 27/38] copy pasted wrong cmake line --- automation/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automation/Jenkinsfile b/automation/Jenkinsfile index 52cd895b..7b184280 100644 --- a/automation/Jenkinsfile +++ b/automation/Jenkinsfile @@ -32,7 +32,7 @@ pipeline { } steps { dir('build-q7s-debug') { - sh 'cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DFSFW_OSAL=linux ..' + sh 'cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug -DFSFW_OSAL=linux ..' sh 'cmake --build . -j' } } From 12be969ca2562649228caba9f043f087f56a1107 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Thu, 29 Jul 2021 12:34:01 +0200 Subject: [PATCH 28/38] jenkins seems to overwrite out PATH --- automation/Jenkinsfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/automation/Jenkinsfile b/automation/Jenkinsfile index 7b184280..43bf8728 100644 --- a/automation/Jenkinsfile +++ b/automation/Jenkinsfile @@ -32,6 +32,8 @@ pipeline { } steps { dir('build-q7s-debug') { + sh 'echo $PATH' + sh 'export PATH=$PATH:/usr/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin' sh 'cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug -DFSFW_OSAL=linux ..' sh 'cmake --build . -j' } From 4fbfbe8bb86f5908374f2674398ee1bb8d88dff3 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Thu, 29 Jul 2021 12:38:24 +0200 Subject: [PATCH 29/38] cleanCI --- automation/Jenkinsfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/automation/Jenkinsfile b/automation/Jenkinsfile index 43bf8728..7b184280 100644 --- a/automation/Jenkinsfile +++ b/automation/Jenkinsfile @@ -32,8 +32,6 @@ pipeline { } steps { dir('build-q7s-debug') { - sh 'echo $PATH' - sh 'export PATH=$PATH:/usr/tools/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin' sh 'cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug -DFSFW_OSAL=linux ..' sh 'cmake --build . -j' } From 983ce045a9af75eae0d9ebcab469c1c3b46c764f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 13:07:07 +0200 Subject: [PATCH 30/38] continued --- CMakeLists.txt | 3 +-- bsp_q7s/core/obsw.cpp | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 49d0d42b..5e49dd9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,9 +123,8 @@ if(NOT BUILD_WATCHDOG) elseif(${TGT_BSP} MATCHES "arm/raspberrypi") configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h) endif() -else() - configure_file(${WATCHDOG_PATH}/watchdogConf.h.in watchdogConf.h) endif() +configure_file(${WATCHDOG_PATH}/watchdogConf.h.in watchdogConf.h) # Set common config path for FSFW set(FSFW_ADDITIONAL_INC_PATHS diff --git a/bsp_q7s/core/obsw.cpp b/bsp_q7s/core/obsw.cpp index 4a13e178..64b0b422 100644 --- a/bsp_q7s/core/obsw.cpp +++ b/bsp_q7s/core/obsw.cpp @@ -20,6 +20,9 @@ int obsw::obsw() { FSFW_REVISION << "--" << std::endl; std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; +#if Q7S_CHECK_FOR_ALREADY_RUNNING_IMG == 1 + // Check special file here +#endif initmission::initMission(); for(;;) { From ff86c8af7385a13cd64141a27e7d1de4fe0eb051 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 16:31:04 +0200 Subject: [PATCH 31/38] watchdog handling finished --- CMakeLists.txt | 13 +-- bsp_q7s/core/CoreController.cpp | 41 ++++++++++ bsp_q7s/core/CoreController.h | 2 + bsp_q7s/core/obsw.cpp | 12 ++- linux/fsfwconfig/OBSWConfig.h.in | 4 + watchdog/Watchdog.cpp | 133 ++++++++++++++++++++++--------- watchdog/Watchdog.h | 11 ++- watchdog/watchdogConf.h.in | 8 ++ 8 files changed, 179 insertions(+), 45 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e49dd9a..7e5e4482 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,17 +96,20 @@ if(TGT_BSP) endif() endif() - if(${TGT_BSP} MATCHES "arm/raspberrypi") - add_definitions(-DRASPBERRY_PI) + if(${TGT_BSP} MATCHES "arm/raspberrypi") + # Used by configure file + set(RASPBERRY_PI ON) set(FSFW_HAL_ADD_RASPBERRY_PI ON) endif() - if(${TGT_BSP} MATCHES "arm/beagleboneblack") - add_definitions(-DBEAGLEBONEBLACK) + if(${TGT_BSP} MATCHES "arm/beagleboneblack") + # Used by configure file + set(BEAGLEBONEBLACK ON) endif() if(${TGT_BSP} MATCHES "arm/q7s") - add_definitions(-DXIPHOS_Q7S) + # Used by configure file + set(XIPHOS_Q7S ON) endif() else() # Required by FSFW library diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index a37db440..bdfac5f8 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1,6 +1,7 @@ #include "CoreController.h" #include "OBSWConfig.h" #include "OBSWVersion.h" +#include "watchdogConf.h" #include "fsfw/FSFWVersion.h" #include "fsfw/serviceinterface/ServiceInterface.h" @@ -13,6 +14,9 @@ #include "bsp_q7s/memory/scratchApi.h" #include "bsp_q7s/memory/SdCardManager.h" +#include +#include + #include CoreController::Chip CoreController::currentChip = Chip::NO_CHIP; @@ -22,6 +26,11 @@ CoreController::CoreController(object_id_t objectId): ExtendedControllerBase(objectId, objects::NO_OBJECT, 5) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; try { + result = initWatchdogFifo(); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::CoreController: Watchdog FIFO init failed" << + std::endl; + } result = initSdCard(); if(result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "CoreController::CoreController: SD card init failed" << std::endl; @@ -30,6 +39,7 @@ CoreController::CoreController(object_id_t objectId): if(result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "CoreController::CoreController: Boot copy init" << std::endl; } + } catch(const std::filesystem::filesystem_error& e) { sif::error << "CoreController::CoreController: Failed with exception " << @@ -42,6 +52,16 @@ ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) { } void CoreController::performControlOperation() { + if(watchdogFifoFd != 0) { + // Write to OBSW watchdog FIFO here + const char writeChar = 'a'; + std::cout << "Writing to FIFO.." << std::endl; + ssize_t writtenBytes = write(watchdogFifoFd, &writeChar, 1); + if(writtenBytes < 0) { + sif::error << "Errors writing to watchdog FIFO, code " << errno << ": " << + strerror(errno) << std::endl; + } + } } ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, @@ -406,6 +426,23 @@ void CoreController::getCurrentBootCopy(Chip &chip, Copy ©) { copy = currentCopy; } +ReturnValue_t CoreController::initWatchdogFifo() { + if(not std::filesystem::exists(watchdog::FIFO_NAME)) { + // Still return RETURN_OK for now + sif::info << "Watchdog FIFO " << watchdog::FIFO_NAME << " does not exist, can't initiate" << + " watchdog" << std::endl; + return HasReturnvaluesIF::RETURN_OK; + } + // Open FIFO write only and non-blocking + watchdogFifoFd = open(watchdog::FIFO_NAME.c_str(), O_WRONLY); + if(watchdogFifoFd < 0) { + std::cerr << "Opening pipe " << watchdog::FIFO_NAME << "write-only failed with " << + errno << ": " << strerror(errno) << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + void CoreController::initPrint() { #if OBSW_VERBOSE_LEVEL >= 1 #if OBSW_USE_TMTC_TCP_BRIDGE == 0 @@ -415,5 +452,9 @@ void CoreController::initPrint() { sif::info << "Created TCP server for TMTC commanding with listener port " << TcpTmTcBridge::DEFAULT_SERVER_PORT << std::endl; #endif + + if(watchdogFifoFd != 0) { + sif::info << "Opened watchdog FIFO successfully.." << std::endl; + } #endif } diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 34d72be4..ea212a16 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -63,12 +63,14 @@ private: ReturnValue_t initVersionFile(); ReturnValue_t initBootCopy(); + ReturnValue_t initWatchdogFifo(); ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t *data, size_t size); void initPrint(); + int watchdogFifoFd = 0; }; diff --git a/bsp_q7s/core/obsw.cpp b/bsp_q7s/core/obsw.cpp index 64b0b422..47b7b9d2 100644 --- a/bsp_q7s/core/obsw.cpp +++ b/bsp_q7s/core/obsw.cpp @@ -2,11 +2,15 @@ #include "OBSWVersion.h" #include "OBSWConfig.h" #include "InitMission.h" +#include "watchdogConf.h" #include "fsfw/tasks/TaskFactory.h" #include "fsfw/FSFWVersion.h" #include +#include + +static int OBSW_ALREADY_RUNNING = -2; int obsw::obsw() { std::cout << "-- EIVE OBSW --" << std::endl; @@ -21,7 +25,13 @@ int obsw::obsw() { std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; #if Q7S_CHECK_FOR_ALREADY_RUNNING_IMG == 1 - // Check special file here + // Check special file here. This file is created or deleted by the eive-watchdog application + // or systemd service! + if(std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) { + sif::warning << "File " << watchdog::RUNNING_FILE_NAME << " exists so the software might " + "already be running. Aborting.." << std::endl; + return OBSW_ALREADY_RUNNING; + } #endif initmission::initMission(); diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index 16eacccf..778a1611 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -6,6 +6,10 @@ #ifndef FSFWCONFIG_OBSWCONFIG_H_ #define FSFWCONFIG_OBSWCONFIG_H_ +#cmakedefine RASPBERRY_Pi +#cmakedefine XIPHOS_Q7S +#cmakedefine BEAGLEBONEBLACK + #ifdef RASPBERRY_PI #include "rpiConfig.h" #elif defined(XIPHOS_Q7S) diff --git a/watchdog/Watchdog.cpp b/watchdog/Watchdog.cpp index f4f8c03c..21be1e1d 100644 --- a/watchdog/Watchdog.cpp +++ b/watchdog/Watchdog.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -54,21 +55,34 @@ int WatchdogTask::performOperation() { break; } case(LoopResult::CANCEL_RQ): { - if(state == States::RUNNING) { + std::cout << "eive-watchdog: Received cancel request, closing watchdog.." << std::endl; + return 0; + } + case(LoopResult::SUSPEND_RQ): { + std::cout << "eive-watchdog: Suspending watchdog operations" << std::endl; + if(state == States::RUNNING or state == States::FAULTY) { + watchdogRunning = false; state = States::SUSPENDED; } break; } case(LoopResult::TIMEOUT): { std::cout << "eive-watchdog: The FIFO timed out!" << std::endl; + performTimeoutOperation(); break; } case(LoopResult::RESTART_RQ): { - if(state == States::SUSPENDED) { + if(state == States::SUSPENDED or state == States::FAULTY) { state = States::RUNNING; + watchdogRunning = true; + performRunningOperation(); } break; } + case(LoopResult::FAULT): { + // Configuration error + std::cerr << "Fault has occured in watchdog loop" << std::endl; + } } } if (close(fd) < 0) { @@ -81,7 +95,6 @@ int WatchdogTask::performOperation() { WatchdogTask::LoopResult WatchdogTask::watchdogLoop() { using namespace std::chrono_literals; - char readChar; struct pollfd waiter = {}; waiter.fd = fd; waiter.events = POLLIN; @@ -113,41 +126,7 @@ WatchdogTask::LoopResult WatchdogTask::watchdogLoop() { return LoopResult::TIMEOUT; } case(1): { - if (waiter.revents & POLLIN) { - ssize_t readLen = read(fd, buf.data(), buf.size()); - if (readLen < 0) { - std::cerr << "eive-watchdog: Read error on pipe " << watchdog::FIFO_NAME << - ", error " << errno << ": " << strerror(errno) << std::endl; - break; - } - for(ssize_t idx = 0; idx < readLen; idx++) { - readChar = buf[idx]; - // Cancel request - if(readChar == 'c') { - return LoopResult::CANCEL_RQ; - } - // Begin request. Does not work if the operation was not suspended before - else if(readChar == 'b') { - return LoopResult::RESTART_RQ; - } - // Everything else: All working as expected - else { - - } - } -#if WATCHDOG_VERBOSE_LEVEL == 2 - std::cout << "Read " << readLen << " byte(s) on the pipe " << FIFO_NAME - << std::endl; -#endif - } - else if(waiter.revents & POLLERR) { - std::cerr << "eive-watchdog: Poll error error on pipe " << watchdog::FIFO_NAME << - std::endl; - } - else if (waiter.revents & POLLHUP) { - // Writer closed its end - } - break; + return pollEvent(waiter); } default: { std::cerr << "eive-watchdog: Unknown poll error at " << watchdog::FIFO_NAME << ", error " << @@ -157,3 +136,81 @@ WatchdogTask::LoopResult WatchdogTask::watchdogLoop() { } return LoopResult::OK; } + +WatchdogTask::LoopResult WatchdogTask::pollEvent(struct pollfd& waiter) { + if (waiter.revents & POLLIN) { + ssize_t readLen = read(fd, buf.data(), buf.size()); + if (readLen < 0) { + std::cerr << "eive-watchdog: Read error on pipe " << watchdog::FIFO_NAME << + ", error " << errno << ": " << strerror(errno) << std::endl; + return LoopResult::OK; + } +#if WATCHDOG_VERBOSE_LEVEL == 2 + std::cout << "Read " << readLen << " byte(s) on the pipe " << FIFO_NAME + << std::endl; +#endif + return parseCommandByte(readLen); + + } + else if(waiter.revents & POLLERR) { + std::cerr << "eive-watchdog: Poll error error on pipe " << watchdog::FIFO_NAME << + std::endl; + return LoopResult::FAULT; + } + else if (waiter.revents & POLLHUP) { + // Writer closed its end + } + return LoopResult::FAULT; +} + +WatchdogTask::LoopResult WatchdogTask::parseCommandByte(ssize_t readLen) { + for(ssize_t idx = 0; idx < readLen; idx++) { + char readChar = buf[idx]; + // Cancel request + if(readChar == watchdog::CANCEL_CHAR) { + return LoopResult::CANCEL_RQ; + } + // Begin request. Does not work if the operation was not suspended before + else if(readChar == watchdog::RESTART_CHAR) { + return LoopResult::RESTART_RQ; + } + // Suspend request + else if(readChar == watchdog::SUSPEND_CHAR) { + return LoopResult::SUSPEND_RQ; + } + // Everything else: All working as expected + } + return LoopResult::OK; +} + +int WatchdogTask::performRunningOperation() { + if(not obswRunning) { + obswRunning = true; +#if WATCHDOG_CREATE_FILE_IF_RUNNING == 1 + if (not std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) { + std::ofstream obswRunningFile(watchdog::RUNNING_FILE_NAME); + if(not obswRunningFile.good()) { + std::cerr << "Creating file " << watchdog::RUNNING_FILE_NAME << " failed" + << std::endl; + } + } +#endif + } + return 0; +} + +int WatchdogTask::performTimeoutOperation() { +#if WATCHDOG_CREATE_FILE_IF_RUNNING == 1 + if (std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) { + int result = std::remove(watchdog::RUNNING_FILE_NAME.c_str()); + if(result != 0) { + std::cerr << "Removing " << watchdog::RUNNING_FILE_NAME << " failed with code " << + errno << ": " << strerror(errno) << std::endl; + } + } +#endif + if(obswRunning) { + obswRunning = false; + } + return 0; +} diff --git a/watchdog/Watchdog.h b/watchdog/Watchdog.h index 53935fc2..088acc5e 100644 --- a/watchdog/Watchdog.h +++ b/watchdog/Watchdog.h @@ -15,9 +15,11 @@ public: enum class LoopResult { OK, + SUSPEND_RQ, CANCEL_RQ, RESTART_RQ, - TIMEOUT + TIMEOUT, + FAULT }; WatchdogTask(); @@ -28,10 +30,17 @@ public: private: int fd = 0; + bool obswRunning = false; + bool watchdogRunning = false; std::array buf; States state = States::NOT_STARTED; LoopResult watchdogLoop(); + LoopResult pollEvent(struct pollfd& waiter); + LoopResult parseCommandByte(ssize_t readLen); + + int performRunningOperation(); + int performTimeoutOperation(); }; #endif /* WATCHDOG_WATCHDOG_H_ */ diff --git a/watchdog/watchdogConf.h.in b/watchdog/watchdogConf.h.in index daa9f248..81faf572 100644 --- a/watchdog/watchdogConf.h.in +++ b/watchdog/watchdogConf.h.in @@ -1,4 +1,5 @@ #include +#include #define WATCHDOG_VERBOSE_LEVEL 1 /** @@ -13,4 +14,11 @@ static constexpr int TIMEOUT_MS = 10 * 1000; const std::string FIFO_NAME = "/tmp/watchdog-pipe"; const std::string RUNNING_FILE_NAME = "/tmp/obsw-running"; +// Suspend watchdog operations temporarily +static constexpr char SUSPEND_CHAR = 's'; +// Resume watchdog operations +static constexpr char RESTART_CHAR = 'b'; +// Causes the watchdog to close down +static constexpr char CANCEL_CHAR = 'c'; + } From dba620baf2c526e79758090e7b64ca5e32fe88de Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 17:21:27 +0200 Subject: [PATCH 32/38] various bugfixes, watchdog working now --- CMakeLists.txt | 2 +- bsp_q7s/core/CoreController.cpp | 1 - linux/boardtest/SpiTestClass.cpp | 1 + watchdog/Watchdog.cpp | 44 +++++++++++++++++++++++++------- watchdog/Watchdog.h | 2 ++ watchdog/watchdogConf.h.in | 2 +- 6 files changed, 40 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e5e4482..cc476dcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,7 @@ endif() include(${CMAKE_SCRIPT_PATH}/PreProjectConfig.cmake) pre_project_config() -set(PROJECT_NAME_TO_SET eive-obsw) +set(PROJECT_NAME_TO_SET eive-obsw-$ENV{USERNAME}) if(BUILD_WATCHDOG) set(PROJECT_NAME_TO_SET eive-watchdog) endif() diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index bdfac5f8..02e0adea 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -55,7 +55,6 @@ void CoreController::performControlOperation() { if(watchdogFifoFd != 0) { // Write to OBSW watchdog FIFO here const char writeChar = 'a'; - std::cout << "Writing to FIFO.." << std::endl; ssize_t writtenBytes = write(watchdogFifoFd, &writeChar, 1); if(writtenBytes < 0) { sif::error << "Errors writing to watchdog FIFO, code " << errno << ": " << diff --git a/linux/boardtest/SpiTestClass.cpp b/linux/boardtest/SpiTestClass.cpp index 71313f25..6f634168 100644 --- a/linux/boardtest/SpiTestClass.cpp +++ b/linux/boardtest/SpiTestClass.cpp @@ -1,4 +1,5 @@ #include "SpiTestClass.h" +#include "OBSWConfig.h" #include "devices/gpioIds.h" diff --git a/watchdog/Watchdog.cpp b/watchdog/Watchdog.cpp index 21be1e1d..9e316451 100644 --- a/watchdog/Watchdog.cpp +++ b/watchdog/Watchdog.cpp @@ -52,6 +52,7 @@ int WatchdogTask::performOperation() { WatchdogTask::LoopResult loopResult = watchdogLoop(); switch(loopResult) { case(LoopResult::OK): { + performRunningOperation(); break; } case(LoopResult::CANCEL_RQ): { @@ -59,29 +60,26 @@ int WatchdogTask::performOperation() { return 0; } case(LoopResult::SUSPEND_RQ): { - std::cout << "eive-watchdog: Suspending watchdog operations" << std::endl; - if(state == States::RUNNING or state == States::FAULTY) { - watchdogRunning = false; - state = States::SUSPENDED; - } + performSuspendOperation(); break; } case(LoopResult::TIMEOUT): { - std::cout << "eive-watchdog: The FIFO timed out!" << std::endl; performTimeoutOperation(); break; } case(LoopResult::RESTART_RQ): { if(state == States::SUSPENDED or state == States::FAULTY) { - state = States::RUNNING; - watchdogRunning = true; performRunningOperation(); } break; } case(LoopResult::FAULT): { + using namespace std::chrono_literals; // Configuration error std::cerr << "Fault has occured in watchdog loop" << std::endl; + // Prevent spam + std::this_thread::sleep_for(2000ms); + } } } @@ -149,7 +147,9 @@ WatchdogTask::LoopResult WatchdogTask::pollEvent(struct pollfd& waiter) { std::cout << "Read " << readLen << " byte(s) on the pipe " << FIFO_NAME << std::endl; #endif - return parseCommandByte(readLen); + else if(readLen >= 1) { + return parseCommandByte(readLen); + } } else if(waiter.revents & POLLERR) { @@ -184,9 +184,20 @@ WatchdogTask::LoopResult WatchdogTask::parseCommandByte(ssize_t readLen) { } int WatchdogTask::performRunningOperation() { + if(state != States::RUNNING) { + state = States::RUNNING; + } + if(not obswRunning) { + if(printTimeoutLatch) { + // Reset latch so user can see timeouts + printTimeoutLatch = false; + } + obswRunning = true; + std::cout << "eive-watchdog: Running OBSW detected.." << std::endl; #if WATCHDOG_CREATE_FILE_IF_RUNNING == 1 + std::cout << "eive-watchdog: Creating " << watchdog::RUNNING_FILE_NAME << std::endl; if (not std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) { std::ofstream obswRunningFile(watchdog::RUNNING_FILE_NAME); if(not obswRunningFile.good()) { @@ -200,6 +211,12 @@ int WatchdogTask::performRunningOperation() { } int WatchdogTask::performTimeoutOperation() { + // Latch prevents spam on console + if(not printTimeoutLatch) { + std::cout << "eive-watchdog: The FIFO timed out!" << std::endl; + printTimeoutLatch = true; + } + #if WATCHDOG_CREATE_FILE_IF_RUNNING == 1 if (std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) { int result = std::remove(watchdog::RUNNING_FILE_NAME.c_str()); @@ -214,3 +231,12 @@ int WatchdogTask::performTimeoutOperation() { } return 0; } + +int WatchdogTask::performSuspendOperation() { + if(state == States::RUNNING or state == States::FAULTY) { + std::cout << "eive-watchdog: Suspending watchdog operations" << std::endl; + watchdogRunning = false; + state = States::SUSPENDED; + } + return 0; +} diff --git a/watchdog/Watchdog.h b/watchdog/Watchdog.h index 088acc5e..649fca6e 100644 --- a/watchdog/Watchdog.h +++ b/watchdog/Watchdog.h @@ -32,6 +32,7 @@ private: bool obswRunning = false; bool watchdogRunning = false; + bool printTimeoutLatch = false; std::array buf; States state = States::NOT_STARTED; @@ -41,6 +42,7 @@ private: int performRunningOperation(); int performTimeoutOperation(); + int performSuspendOperation(); }; #endif /* WATCHDOG_WATCHDOG_H_ */ diff --git a/watchdog/watchdogConf.h.in b/watchdog/watchdogConf.h.in index 81faf572..02d84e70 100644 --- a/watchdog/watchdogConf.h.in +++ b/watchdog/watchdogConf.h.in @@ -10,7 +10,7 @@ namespace watchdog { -static constexpr int TIMEOUT_MS = 10 * 1000; +static constexpr int TIMEOUT_MS = 5 * 1000; const std::string FIFO_NAME = "/tmp/watchdog-pipe"; const std::string RUNNING_FILE_NAME = "/tmp/obsw-running"; From 34d3479e81a2da79d1d68e4b53e0e7eb7f6b406e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 18:09:54 +0200 Subject: [PATCH 33/38] various bugfixes and improvements --- bsp_q7s/core/CoreController.cpp | 63 +++++++++++++++++++++++++-------- bsp_q7s/core/CoreController.h | 6 ++++ watchdog/Watchdog.cpp | 47 +++++++++++++++--------- watchdog/Watchdog.h | 5 +-- 4 files changed, 88 insertions(+), 33 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 02e0adea..4a9db02a 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -23,7 +23,8 @@ CoreController::Chip CoreController::currentChip = Chip::NO_CHIP; CoreController::Copy CoreController::currentCopy = Copy::NO_COPY; CoreController::CoreController(object_id_t objectId): - ExtendedControllerBase(objectId, objects::NO_OBJECT, 5) { + ExtendedControllerBase(objectId, objects::NO_OBJECT, 5), + opDivider(5) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; try { result = initWatchdogFifo(); @@ -52,15 +53,7 @@ ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) { } void CoreController::performControlOperation() { - if(watchdogFifoFd != 0) { - // Write to OBSW watchdog FIFO here - const char writeChar = 'a'; - ssize_t writtenBytes = write(watchdogFifoFd, &writeChar, 1); - if(writtenBytes < 0) { - sif::error << "Errors writing to watchdog FIFO, code " << errno << ": " << - strerror(errno) << std::endl; - } - } + performWatchdogControlOperation(); } ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, @@ -432,12 +425,18 @@ ReturnValue_t CoreController::initWatchdogFifo() { " watchdog" << std::endl; return HasReturnvaluesIF::RETURN_OK; } - // Open FIFO write only and non-blocking - watchdogFifoFd = open(watchdog::FIFO_NAME.c_str(), O_WRONLY); + // Open FIFO write only and non-blocking to prevent SW from killing itself. + watchdogFifoFd = open(watchdog::FIFO_NAME.c_str(), O_WRONLY | O_NONBLOCK); if(watchdogFifoFd < 0) { - std::cerr << "Opening pipe " << watchdog::FIFO_NAME << "write-only failed with " << - errno << ": " << strerror(errno) << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; + if(errno == ENXIO) { + watchdogFifoFd = RETRY_FIFO_OPEN; + sif::info << "eive-watchdog not running. FIFO can not be opened" << std::endl; + } + else { + sif::error << "Opening pipe " << watchdog::FIFO_NAME << " write-only failed with " << + errno << ": " << strerror(errno) << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } } return HasReturnvaluesIF::RETURN_OK; } @@ -457,3 +456,37 @@ void CoreController::initPrint() { } #endif } + +void CoreController::performWatchdogControlOperation() { + // Only perform each fifth iteration + if(watchdogFifoFd != 0 and opDivider.checkAndIncrement()) { + if(watchdogFifoFd == RETRY_FIFO_OPEN) { + // Open FIFO write only and non-blocking + watchdogFifoFd = open(watchdog::FIFO_NAME.c_str(), O_WRONLY | O_NONBLOCK); + if(watchdogFifoFd < 0) { + if(errno == ENXIO) { + watchdogFifoFd = RETRY_FIFO_OPEN; + // No printout for now, would be spam + return; + } + else { + sif::error << "Opening pipe " << watchdog::FIFO_NAME << + " write-only failed with " << errno << ": " << + strerror(errno) << std::endl; + return; + } + } + sif::info << "Opened " << watchdog::FIFO_NAME << " successfully" << std::endl; + } + else if(watchdogFifoFd > 0) { + // Write to OBSW watchdog FIFO here + const char writeChar = 'a'; + ssize_t writtenBytes = write(watchdogFifoFd, &writeChar, 1); + if(writtenBytes < 0) { + sif::error << "Errors writing to watchdog FIFO, code " << errno << ": " << + strerror(errno) << std::endl; + } + } + } + +} diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index ea212a16..92b22dd4 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -1,6 +1,7 @@ #ifndef BSP_Q7S_CORE_CORECONTROLLER_H_ #define BSP_Q7S_CORE_CORECONTROLLER_H_ +#include #include "fsfw/controller/ExtendedControllerBase.h" #include "bsp_q7s/memory/SdCardManager.h" @@ -70,7 +71,12 @@ private: void initPrint(); + // Designated value for rechecking FIFO open + static constexpr int RETRY_FIFO_OPEN = -2; int watchdogFifoFd = 0; + + PeriodicOperationDivider opDivider; + void performWatchdogControlOperation(); }; diff --git a/watchdog/Watchdog.cpp b/watchdog/Watchdog.cpp index 9e316451..f3627a75 100644 --- a/watchdog/Watchdog.cpp +++ b/watchdog/Watchdog.cpp @@ -64,7 +64,11 @@ int WatchdogTask::performOperation() { break; } case(LoopResult::TIMEOUT): { - performTimeoutOperation(); + performNotRunningOperation(loopResult); + break; + } + case(LoopResult::HUNG_UP): { + performNotRunningOperation(loopResult); break; } case(LoopResult::RESTART_RQ): { @@ -159,6 +163,7 @@ WatchdogTask::LoopResult WatchdogTask::pollEvent(struct pollfd& waiter) { } else if (waiter.revents & POLLHUP) { // Writer closed its end + return LoopResult::HUNG_UP; } return LoopResult::FAULT; } @@ -189,9 +194,9 @@ int WatchdogTask::performRunningOperation() { } if(not obswRunning) { - if(printTimeoutLatch) { + if(printNotRunningLatch) { // Reset latch so user can see timeouts - printTimeoutLatch = false; + printNotRunningLatch = false; } obswRunning = true; @@ -210,25 +215,35 @@ int WatchdogTask::performRunningOperation() { return 0; } -int WatchdogTask::performTimeoutOperation() { +int WatchdogTask::performNotRunningOperation(LoopResult type) { // Latch prevents spam on console - if(not printTimeoutLatch) { - std::cout << "eive-watchdog: The FIFO timed out!" << std::endl; - printTimeoutLatch = true; + if(not printNotRunningLatch) { + if(type == LoopResult::HUNG_UP) { + std::cout << "eive-watchdog: FIFO writer hung up!" << std::endl; + } + else { + std::cout << "eive-watchdog: The FIFO timed out!" << std::endl; + } + printNotRunningLatch = true; } -#if WATCHDOG_CREATE_FILE_IF_RUNNING == 1 - if (std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) { - int result = std::remove(watchdog::RUNNING_FILE_NAME.c_str()); - if(result != 0) { - std::cerr << "Removing " << watchdog::RUNNING_FILE_NAME << " failed with code " << - errno << ": " << strerror(errno) << std::endl; - } - } -#endif if(obswRunning) { +#if WATCHDOG_CREATE_FILE_IF_RUNNING == 1 + if (std::filesystem::exists(watchdog::RUNNING_FILE_NAME)) { + int result = std::remove(watchdog::RUNNING_FILE_NAME.c_str()); + if(result != 0) { + std::cerr << "Removing " << watchdog::RUNNING_FILE_NAME << " failed with code " << + errno << ": " << strerror(errno) << std::endl; + } + } +#endif obswRunning = false; } + if(type == LoopResult::HUNG_UP) { + using namespace std::chrono_literals; + // Prevent spam + std::this_thread::sleep_for(2000ms); + } return 0; } diff --git a/watchdog/Watchdog.h b/watchdog/Watchdog.h index 649fca6e..fb7ac65b 100644 --- a/watchdog/Watchdog.h +++ b/watchdog/Watchdog.h @@ -19,6 +19,7 @@ public: CANCEL_RQ, RESTART_RQ, TIMEOUT, + HUNG_UP, FAULT }; @@ -32,7 +33,7 @@ private: bool obswRunning = false; bool watchdogRunning = false; - bool printTimeoutLatch = false; + bool printNotRunningLatch = false; std::array buf; States state = States::NOT_STARTED; @@ -41,7 +42,7 @@ private: LoopResult parseCommandByte(ssize_t readLen); int performRunningOperation(); - int performTimeoutOperation(); + int performNotRunningOperation(LoopResult type); int performSuspendOperation(); }; From 208aeb66406b96d0a34edd49eb69b1d3316e5a7c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 18:17:14 +0200 Subject: [PATCH 34/38] added build scripts, updated proj files --- cmake/scripts/Q7S/watchdog/make_debug_cfg.sh | 36 ++ .../scripts/Q7S/watchdog/make_release_cfg.sh | 36 ++ cmake/scripts/Q7S/watchdog/ninja_debug_cfg.sh | 34 ++ .../scripts/Q7S/watchdog/ninja_release_cfg.sh | 34 ++ misc/eclipse/.cproject | 332 +++++++++++++++++- 5 files changed, 471 insertions(+), 1 deletion(-) create mode 100755 cmake/scripts/Q7S/watchdog/make_debug_cfg.sh create mode 100755 cmake/scripts/Q7S/watchdog/make_release_cfg.sh create mode 100755 cmake/scripts/Q7S/watchdog/ninja_debug_cfg.sh create mode 100755 cmake/scripts/Q7S/watchdog/ninja_release_cfg.sh diff --git a/cmake/scripts/Q7S/watchdog/make_debug_cfg.sh b/cmake/scripts/Q7S/watchdog/make_debug_cfg.sh new file mode 100755 index 00000000..d5b58df9 --- /dev/null +++ b/cmake/scripts/Q7S/watchdog/make_debug_cfg.sh @@ -0,0 +1,36 @@ +#!/bin/sh +counter=0 +while [ ${counter} -lt 5 ] +do + cd .. + if [ -f "cmake_build_config.py" ];then + break + fi + counter=$((counter=counter + 1)) +done + +if [ "${counter}" -ge 5 ];then + echo "cmake_build_config.py not found in upper directories!" + exit 1 +fi + +os_fsfw="linux" +tgt_bsp="arm/q7s" +build_dir="build-Debug-Watchdog" +build_generator="" +definitions="BUILD_WATCHDOG=ON" +if [ "${OS}" = "Windows_NT" ]; then + build_generator="MinGW Makefiles" + python="py" +# Could be other OS but this works for now. +else + build_generator="Unix Makefiles" + python="python3" +fi + +echo "Running command (without the leading +):" +set -x # Print command +${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}" \ + -d "${definitions}" -l"${build_dir}" +# set +x + diff --git a/cmake/scripts/Q7S/watchdog/make_release_cfg.sh b/cmake/scripts/Q7S/watchdog/make_release_cfg.sh new file mode 100755 index 00000000..726e82ed --- /dev/null +++ b/cmake/scripts/Q7S/watchdog/make_release_cfg.sh @@ -0,0 +1,36 @@ +#!/bin/sh +counter=0 +while [ ${counter} -lt 5 ] +do + cd .. + if [ -f "cmake_build_config.py" ];then + break + fi + counter=$((counter=counter + 1)) +done + +if [ "${counter}" -ge 5 ];then + echo "cmake_build_config.py not found in upper directories!" + exit 1 +fi + +os_fsfw="linux" +tgt_bsp="arm/q7s" +build_dir="build-Release-Watchdog" +build_generator="" +definitions="BUILD_WATCHDOG=ON" +if [ "${OS}" = "Windows_NT" ]; then + build_generator="MinGW Makefiles" + python="py" +# Could be other OS but this works for now. +else + build_generator="Unix Makefiles" + python="python3" +fi + +echo "Running command (without the leading +):" +set -x # Print command +${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "release" -t "${tgt_bsp}" \ + -d "${definitions} -l"${build_dir}" +# set +x + diff --git a/cmake/scripts/Q7S/watchdog/ninja_debug_cfg.sh b/cmake/scripts/Q7S/watchdog/ninja_debug_cfg.sh new file mode 100755 index 00000000..99a414e7 --- /dev/null +++ b/cmake/scripts/Q7S/watchdog/ninja_debug_cfg.sh @@ -0,0 +1,34 @@ +#!/bin/sh +counter=0 +while [ ${counter} -lt 5 ] +do + cd .. + if [ -f "cmake_build_config.py" ];then + break + fi + counter=$((counter=counter + 1)) +done + +if [ "${counter}" -ge 5 ];then + echo "cmake_build_config.py not found in upper directories!" + exit 1 +fi + +os_fsfw="linux" +tgt_bsp="arm/q7s" +build_dir="build-Debug-Watchdog" +build_generator="Ninja" +definitions="-DBUILD_WATCHDOG=ON" +if [ "${OS}" = "Windows_NT" ]; then + python="py" +# Could be other OS but this works for now. +else + python="python3" +fi + +echo "Running command (without the leading +):" +set -x # Print command +${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "debug" -t "${tgt_bsp}" \ + -d "${definitions}" -l "${build_dir}" +# set +x + diff --git a/cmake/scripts/Q7S/watchdog/ninja_release_cfg.sh b/cmake/scripts/Q7S/watchdog/ninja_release_cfg.sh new file mode 100755 index 00000000..3e6beac3 --- /dev/null +++ b/cmake/scripts/Q7S/watchdog/ninja_release_cfg.sh @@ -0,0 +1,34 @@ +#!/bin/sh +counter=0 +while [ ${counter} -lt 5 ] +do + cd .. + if [ -f "cmake_build_config.py" ];then + break + fi + counter=$((counter=counter + 1)) +done + +if [ "${counter}" -ge 5 ];then + echo "cmake_build_config.py not found in upper directories!" + exit 1 +fi + +os_fsfw="linux" +tgt_bsp="arm/q7s" +build_dir="build-Release-Watchdog" +build_generator="Ninja" +definitions="BUILD_WATCHDOG=ON" +if [ "${OS}" = "Windows_NT" ]; then + python="py" +# Could be other OS but this works for now. +else + python="python3" +fi + +echo "Running command (without the leading +):" +set -x # Print command +${python} cmake_build_config.py -o "${os_fsfw}" -g "${build_generator}" -b "release" -t "${tgt_bsp}" \ + -d "${definitions}" -l"${build_dir}" +# set +x + diff --git a/misc/eclipse/.cproject b/misc/eclipse/.cproject index 84814acc..fe0208b8 100644 --- a/misc/eclipse/.cproject +++ b/misc/eclipse/.cproject @@ -254,7 +254,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1044,6 +1370,9 @@ + + + @@ -1060,6 +1389,7 @@ + From df971d4ec59d5cf39388e1a70b3fe788654223e2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 18:21:05 +0200 Subject: [PATCH 35/38] dont need csp lib in watchdog --- CMakeLists.txt | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc476dcc..5f56a4fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,9 +152,7 @@ if(ADD_JSON_LIB) add_subdirectory(${LIB_JSON_PATH}) endif() -if(ADD_CSP_LIB) - add_subdirectory(${CSP_LIB_PATH}) -endif() + if(NOT BUILD_WATCHDOG) if(ADD_LINUX_FILES) @@ -162,6 +160,9 @@ if(NOT BUILD_WATCHDOG) endif() add_subdirectory(${BSP_PATH}) add_subdirectory(${COMMON_PATH}) + if(ADD_CSP_LIB) + add_subdirectory(${CSP_LIB_PATH}) + endif() endif() if((NOT BUILD_Q7S_SIMPLE_MODE) AND (NOT BUILD_WATCHDOG)) @@ -192,24 +193,28 @@ if((NOT BUILD_Q7S_SIMPLE_MODE) AND (NOT BUILD_WATCHDOG)) ) endif() +if(NOT BUILD_WATCHDOG) + if(ADD_CSP_LIB) + target_link_libraries(${TARGET_NAME} PRIVATE + ${LIB_CSP_NAME} + ) + endif() +endif() + if(ADD_ETL_LIB) target_link_libraries(${TARGET_NAME} PRIVATE ${LIB_ETL_NAME} ) endif() -if(ADD_CSP_LIB) - target_link_libraries(${TARGET_NAME} PRIVATE - ${LIB_CSP_NAME} - ) -endif() - if(ADD_JSON_LIB) target_link_libraries(${TARGET_NAME} PRIVATE ${LIB_JSON_NAME} ) endif() + + target_link_libraries(${TARGET_NAME} PRIVATE ${LIB_CXX_FS} ) From 940d4965bcf1727f0a2cfbd44e1c9e2e42e5ddbd Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 18:32:02 +0200 Subject: [PATCH 36/38] small corrections --- bsp_q7s/core/CoreController.cpp | 2 +- watchdog/main.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 4a9db02a..72171c65 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -451,7 +451,7 @@ void CoreController::initPrint() { TcpTmTcBridge::DEFAULT_SERVER_PORT << std::endl; #endif - if(watchdogFifoFd != 0) { + if(watchdogFifoFd > 0) { sif::info << "Opened watchdog FIFO successfully.." << std::endl; } #endif diff --git a/watchdog/main.cpp b/watchdog/main.cpp index a1ae3ae8..f297f429 100644 --- a/watchdog/main.cpp +++ b/watchdog/main.cpp @@ -14,6 +14,7 @@ int main() { } catch(const std::runtime_error& e) { std::cerr << "eive-watchdog: Run time exception " << e.what() << std::endl; + return -1; } return 0; } From d8acf94a02d17b939ac7e92457d61f878299f9f4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 18:33:15 +0200 Subject: [PATCH 37/38] more corrections --- watchdog/Watchdog.cpp | 1 + watchdog/main.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/watchdog/Watchdog.cpp b/watchdog/Watchdog.cpp index f3627a75..9ae60548 100644 --- a/watchdog/Watchdog.cpp +++ b/watchdog/Watchdog.cpp @@ -45,6 +45,7 @@ int WatchdogTask::performOperation() { if(fd < 0) { std::cerr << "eive-watchdog: Opening pipe " << watchdog::FIFO_NAME << "read-only failed with " << errno << ": " << strerror(errno) << std::endl; + return -1; } state = States::RUNNING; diff --git a/watchdog/main.cpp b/watchdog/main.cpp index f297f429..ba75dc30 100644 --- a/watchdog/main.cpp +++ b/watchdog/main.cpp @@ -10,7 +10,10 @@ int main() { std::cout << "eive-watchdog: Starting OBSW watchdog.." << std::endl; try { WatchdogTask watchdogTask; - watchdogTask.performOperation(); + int result = watchdogTask.performOperation(); + if(result != 0) { + return result; + } } catch(const std::runtime_error& e) { std::cerr << "eive-watchdog: Run time exception " << e.what() << std::endl; From 8c3d25f62db70b2aafa9bb4886b7ba6921b2a215 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 29 Jul 2021 19:43:00 +0200 Subject: [PATCH 38/38] updated README --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4865885d..fc4163e1 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,29 @@ When using Windows, run theses steps in MSYS2. # Useful and Common Commands (Host) +## Build generation + +Replace `Debug` with `Release` for release build. Add `-G "MinGW Makefiles` or `-G "Ninja"` +on Windows or when `ninja` should be used. You can build with `cmake --build . -j` after +build generation. You can finds scripts in `cmake/scripts` to perform the build commands +automatically. + +### Q7S OBSW + +```sh +mkdir build-Debug-Q7S && cd build-Debug-Q7S +cmake -DTGT_BSP=arm/q7s -DFSFW_OSAL=linux -DCMAKE_BUILD_TYPE=Debug .. +cmake --build . -j +``` + +### Q7S Watchdog + +```sh +mkdir build-Debug-Q7S && cd build-Debug-Q7S +cmake -DTGT_BSP=arm/q7s -DFSFW_OSAL=linux -DBUILD_WATCHDOG=ON -DCMAKE_BUILD_TYPE=Debug .. +cmake --build . -j +``` + ## Connect to EIVE flatsat ### DNS @@ -192,6 +215,12 @@ Other useful tmux commands: You can quit scroll mode with `q`. - Kill a tmux session: run `ctrl + b` and then `k`. - Detach from a tmux session: run `ctrl + b` and then `d` +- [Pipe last 3000 lines](https://unix.stackexchange.com/questions/26548/write-all-tmux-scrollback-to-a-file) + into file for copying or analysis: + 1. `ctrl + b` and `:` + 2. `capture-pane -S -3000` + `enter` + 3. `save-buffer /tmp/tmux-output.txt` + `enter` + ### SSH console @@ -587,7 +616,7 @@ pscp -scp -P 22 eive@192.168.199.227:/example-file More detailed information about the used q7s commands can be found in the Q7S user manual. -# Q7S +# Q7S OBC ## Launching an application at start-up @@ -666,13 +695,31 @@ creating directories. To do this, the parition needs to be mounted. systemctl status example ``` - ## Current user systemd services The following custom `systemd` services are currently running on the Q7S and can be found in the `/etc/systemd/system` folder. You can query that status of a service by running `systemctl status `. +### `eive-watchdog` + +The watchdog will create a pipe at `/tmp/watchdog-pipe` which can be used both by the watchdog and +the EIVE OBSW. The watchdog will only read from this pipe while the OBSW will only write +to this pipe. The watchdog checks for basic ASCII commands as a first basic feature set. +The most important functionality is that the watchdog cant detect if a timeout +has happened. This can happen beause the OBSW is hanging (or at least the CoreController thread) or +there is simply now OBSW running on the system. It does to by checking whether the FIFO is +regulary written to, which means the EIVE OBSW is alive. + +If the EIVE OBSW is alive, a special file called `/tmp/obsw-running` will be created. +This file can be used by any other software component to query whether the EIVE OBSW is running. +The EIVE OBSW itself can be configured to check whether this file exists, which prevents two +EIVE OBSW instances running on the Q7S at once. + +If a timeout occurs, this special file will be deleted as well. +The watchdog and its configuration will be directly integrated into this repostory, which +makes adaptions easy. + ### `tcfagent` This starts the `/usr/bin/agent` program to allows remote debugging. Might not be part of