Added OBSW Watchdog #67

Merged
meierj merged 20 commits from mueller/added-watchdog into develop 2021-07-31 08:51:56 +02:00
8 changed files with 179 additions and 45 deletions
Showing only changes of commit ff86c8af73 - Show all commits

View File

@ -96,17 +96,20 @@ if(TGT_BSP)
endif() endif()
endif() endif()
if(${TGT_BSP} MATCHES "arm/raspberrypi") if(${TGT_BSP} MATCHES "arm/raspberrypi")
add_definitions(-DRASPBERRY_PI) # Used by configure file
set(RASPBERRY_PI ON)
set(FSFW_HAL_ADD_RASPBERRY_PI ON) set(FSFW_HAL_ADD_RASPBERRY_PI ON)
endif() endif()
if(${TGT_BSP} MATCHES "arm/beagleboneblack") if(${TGT_BSP} MATCHES "arm/beagleboneblack")
add_definitions(-DBEAGLEBONEBLACK) # Used by configure file
set(BEAGLEBONEBLACK ON)
endif() endif()
if(${TGT_BSP} MATCHES "arm/q7s") if(${TGT_BSP} MATCHES "arm/q7s")
add_definitions(-DXIPHOS_Q7S) # Used by configure file
set(XIPHOS_Q7S ON)
endif() endif()
else() else()
# Required by FSFW library # Required by FSFW library

View File

@ -1,6 +1,7 @@
#include "CoreController.h" #include "CoreController.h"
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "OBSWVersion.h" #include "OBSWVersion.h"
#include "watchdogConf.h"
#include "fsfw/FSFWVersion.h" #include "fsfw/FSFWVersion.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
@ -13,6 +14,9 @@
#include "bsp_q7s/memory/scratchApi.h" #include "bsp_q7s/memory/scratchApi.h"
#include "bsp_q7s/memory/SdCardManager.h" #include "bsp_q7s/memory/SdCardManager.h"
#include <fcntl.h>
#include <unistd.h>
#include <filesystem> #include <filesystem>
CoreController::Chip CoreController::currentChip = Chip::NO_CHIP; CoreController::Chip CoreController::currentChip = Chip::NO_CHIP;
@ -22,6 +26,11 @@ CoreController::CoreController(object_id_t objectId):
ExtendedControllerBase(objectId, objects::NO_OBJECT, 5) { ExtendedControllerBase(objectId, objects::NO_OBJECT, 5) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
try { try {
result = initWatchdogFifo();
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "CoreController::CoreController: Watchdog FIFO init failed" <<
std::endl;
}
result = initSdCard(); result = initSdCard();
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "CoreController::CoreController: SD card init failed" << std::endl; 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) { if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "CoreController::CoreController: Boot copy init" << std::endl; sif::warning << "CoreController::CoreController: Boot copy init" << std::endl;
} }
} }
catch(const std::filesystem::filesystem_error& e) { catch(const std::filesystem::filesystem_error& e) {
sif::error << "CoreController::CoreController: Failed with exception " << sif::error << "CoreController::CoreController: Failed with exception " <<
@ -42,6 +52,16 @@ ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) {
} }
void CoreController::performControlOperation() { 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, ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
@ -406,6 +426,23 @@ void CoreController::getCurrentBootCopy(Chip &chip, Copy &copy) {
copy = currentCopy; 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() { void CoreController::initPrint() {
#if OBSW_VERBOSE_LEVEL >= 1 #if OBSW_VERBOSE_LEVEL >= 1
#if OBSW_USE_TMTC_TCP_BRIDGE == 0 #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 " << sif::info << "Created TCP server for TMTC commanding with listener port " <<
TcpTmTcBridge::DEFAULT_SERVER_PORT << std::endl; TcpTmTcBridge::DEFAULT_SERVER_PORT << std::endl;
#endif #endif
if(watchdogFifoFd != 0) {
sif::info << "Opened watchdog FIFO successfully.." << std::endl;
}
#endif #endif
} }

View File

@ -63,12 +63,14 @@ private:
ReturnValue_t initVersionFile(); ReturnValue_t initVersionFile();
ReturnValue_t initBootCopy(); ReturnValue_t initBootCopy();
ReturnValue_t initWatchdogFifo();
ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy, ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size); const uint8_t *data, size_t size);
void initPrint(); void initPrint();
int watchdogFifoFd = 0;
}; };

View File

@ -2,11 +2,15 @@
#include "OBSWVersion.h" #include "OBSWVersion.h"
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "InitMission.h" #include "InitMission.h"
#include "watchdogConf.h"
#include "fsfw/tasks/TaskFactory.h" #include "fsfw/tasks/TaskFactory.h"
#include "fsfw/FSFWVersion.h" #include "fsfw/FSFWVersion.h"
#include <iostream> #include <iostream>
#include <filesystem>
static int OBSW_ALREADY_RUNNING = -2;
int obsw::obsw() { int obsw::obsw() {
std::cout << "-- EIVE OBSW --" << std::endl; std::cout << "-- EIVE OBSW --" << std::endl;
@ -21,7 +25,13 @@ int obsw::obsw() {
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;
#if Q7S_CHECK_FOR_ALREADY_RUNNING_IMG == 1 #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 #endif
initmission::initMission(); initmission::initMission();

View File

@ -6,6 +6,10 @@
#ifndef FSFWCONFIG_OBSWCONFIG_H_ #ifndef FSFWCONFIG_OBSWCONFIG_H_
#define FSFWCONFIG_OBSWCONFIG_H_ #define FSFWCONFIG_OBSWCONFIG_H_
#cmakedefine RASPBERRY_Pi
#cmakedefine XIPHOS_Q7S
#cmakedefine BEAGLEBONEBLACK
#ifdef RASPBERRY_PI #ifdef RASPBERRY_PI
#include "rpiConfig.h" #include "rpiConfig.h"
#elif defined(XIPHOS_Q7S) #elif defined(XIPHOS_Q7S)

View File

@ -9,6 +9,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <iostream> #include <iostream>
#include <fstream>
#include <thread> #include <thread>
#include <cstring> #include <cstring>
#include <filesystem> #include <filesystem>
@ -54,21 +55,34 @@ int WatchdogTask::performOperation() {
break; break;
} }
case(LoopResult::CANCEL_RQ): { 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; state = States::SUSPENDED;
} }
break; break;
} }
case(LoopResult::TIMEOUT): { case(LoopResult::TIMEOUT): {
std::cout << "eive-watchdog: The FIFO timed out!" << std::endl; std::cout << "eive-watchdog: The FIFO timed out!" << std::endl;
performTimeoutOperation();
break; break;
} }
case(LoopResult::RESTART_RQ): { case(LoopResult::RESTART_RQ): {
if(state == States::SUSPENDED) { if(state == States::SUSPENDED or state == States::FAULTY) {
state = States::RUNNING; state = States::RUNNING;
watchdogRunning = true;
performRunningOperation();
} }
break; break;
} }
case(LoopResult::FAULT): {
// Configuration error
std::cerr << "Fault has occured in watchdog loop" << std::endl;
}
} }
} }
if (close(fd) < 0) { if (close(fd) < 0) {
@ -81,7 +95,6 @@ int WatchdogTask::performOperation() {
WatchdogTask::LoopResult WatchdogTask::watchdogLoop() { WatchdogTask::LoopResult WatchdogTask::watchdogLoop() {
using namespace std::chrono_literals; using namespace std::chrono_literals;
char readChar;
struct pollfd waiter = {}; struct pollfd waiter = {};
waiter.fd = fd; waiter.fd = fd;
waiter.events = POLLIN; waiter.events = POLLIN;
@ -113,41 +126,7 @@ WatchdogTask::LoopResult WatchdogTask::watchdogLoop() {
return LoopResult::TIMEOUT; return LoopResult::TIMEOUT;
} }
case(1): { case(1): {
if (waiter.revents & POLLIN) { return pollEvent(waiter);
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: { default: {
std::cerr << "eive-watchdog: Unknown poll error at " << watchdog::FIFO_NAME << ", error " << std::cerr << "eive-watchdog: Unknown poll error at " << watchdog::FIFO_NAME << ", error " <<
@ -157,3 +136,81 @@ WatchdogTask::LoopResult WatchdogTask::watchdogLoop() {
} }
return LoopResult::OK; 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;
}

View File

@ -15,9 +15,11 @@ public:
enum class LoopResult { enum class LoopResult {
OK, OK,
SUSPEND_RQ,
CANCEL_RQ, CANCEL_RQ,
RESTART_RQ, RESTART_RQ,
TIMEOUT TIMEOUT,
FAULT
}; };
WatchdogTask(); WatchdogTask();
@ -28,10 +30,17 @@ public:
private: private:
int fd = 0; int fd = 0;
bool obswRunning = false;
bool watchdogRunning = false;
std::array<uint8_t, 64> buf; std::array<uint8_t, 64> buf;
States state = States::NOT_STARTED; States state = States::NOT_STARTED;
LoopResult watchdogLoop(); LoopResult watchdogLoop();
LoopResult pollEvent(struct pollfd& waiter);
LoopResult parseCommandByte(ssize_t readLen);
int performRunningOperation();
int performTimeoutOperation();
}; };
#endif /* WATCHDOG_WATCHDOG_H_ */ #endif /* WATCHDOG_WATCHDOG_H_ */

View File

@ -1,4 +1,5 @@
#include <cstdint> #include <cstdint>
#include <string>
#define WATCHDOG_VERBOSE_LEVEL 1 #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 FIFO_NAME = "/tmp/watchdog-pipe";
const std::string RUNNING_FILE_NAME = "/tmp/obsw-running"; 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';
} }