Added OBSW Watchdog #67
@ -14,7 +14,8 @@ cmake_minimum_required(VERSION 3.13)
|
|||||||
set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
set(CMAKE_SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
if(TGT_BSP MATCHES "arm/q7s")
|
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()
|
endif()
|
||||||
|
|
||||||
option(ADD_ETL_LIB "Add ETL library" ON)
|
option(ADD_ETL_LIB "Add ETL library" ON)
|
||||||
@ -32,8 +33,13 @@ endif()
|
|||||||
include(${CMAKE_SCRIPT_PATH}/PreProjectConfig.cmake)
|
include(${CMAKE_SCRIPT_PATH}/PreProjectConfig.cmake)
|
||||||
pre_project_config()
|
pre_project_config()
|
||||||
|
|
||||||
|
set(PROJECT_NAME_TO_SET eive-obsw)
|
||||||
|
if(BUILD_WATCHDOG)
|
||||||
|
set(PROJECT_NAME_TO_SET eive-watchdog)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Project Name
|
# Project Name
|
||||||
project(eive_obsw ASM C CXX)
|
project(${PROJECT_NAME_TO_SET} ASM C CXX)
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Pre-Sources preparation
|
# Pre-Sources preparation
|
||||||
@ -60,6 +66,7 @@ set(MISSION_PATH mission)
|
|||||||
set(TEST_PATH test/testtasks)
|
set(TEST_PATH test/testtasks)
|
||||||
set(LINUX_PATH linux)
|
set(LINUX_PATH linux)
|
||||||
set(COMMON_PATH common)
|
set(COMMON_PATH common)
|
||||||
|
set(WATCHDOG_PATH watchdog)
|
||||||
set(COMMON_CONFIG_PATH ${COMMON_PATH}/config)
|
set(COMMON_CONFIG_PATH ${COMMON_PATH}/config)
|
||||||
|
|
||||||
set(FSFW_HAL_LIB_PATH fsfw_hal)
|
set(FSFW_HAL_LIB_PATH fsfw_hal)
|
||||||
@ -82,7 +89,7 @@ if(TGT_BSP)
|
|||||||
OR TGT_BSP MATCHES "arm/beagleboneblack"
|
OR TGT_BSP MATCHES "arm/beagleboneblack"
|
||||||
)
|
)
|
||||||
set(FSFW_CONFIG_PATH "linux/fsfwconfig")
|
set(FSFW_CONFIG_PATH "linux/fsfwconfig")
|
||||||
if(NOT Q7S_SIMPLE_MODE)
|
if(NOT BUILD_Q7S_SIMPLE_MODE)
|
||||||
set(ADD_LINUX_FILES TRUE)
|
set(ADD_LINUX_FILES TRUE)
|
||||||
set(ADD_CSP_LIB TRUE)
|
set(ADD_CSP_LIB TRUE)
|
||||||
set(FSFW_HAL_ADD_LINUX ON)
|
set(FSFW_HAL_ADD_LINUX ON)
|
||||||
@ -107,13 +114,17 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Configuration files
|
# Configuration files
|
||||||
configure_file(${COMMON_CONFIG_PATH}/commonConfig.h.in commonConfig.h)
|
if(NOT BUILD_WATCHDOG)
|
||||||
configure_file(${FSFW_CONFIG_PATH}/FSFWConfig.h.in FSFWConfig.h)
|
configure_file(${COMMON_CONFIG_PATH}/commonConfig.h.in commonConfig.h)
|
||||||
configure_file(${FSFW_CONFIG_PATH}/OBSWConfig.h.in OBSWConfig.h)
|
configure_file(${FSFW_CONFIG_PATH}/FSFWConfig.h.in FSFWConfig.h)
|
||||||
if(${TGT_BSP} MATCHES "arm/q7s")
|
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)
|
configure_file(${BSP_PATH}/boardconfig/q7sConfig.h.in q7sConfig.h)
|
||||||
elseif(${TGT_BSP} MATCHES "arm/raspberrypi")
|
elseif(${TGT_BSP} MATCHES "arm/raspberrypi")
|
||||||
configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h)
|
configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
configure_file(${WATCHDOG_PATH}/watchdogConf.h.in watchdogConf.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Set common config path for FSFW
|
# Set common config path for FSFW
|
||||||
@ -131,26 +142,27 @@ set(LWGPS_CONFIG_PATH "${COMMON_PATH}/config")
|
|||||||
# Add executable
|
# Add executable
|
||||||
add_executable(${TARGET_NAME})
|
add_executable(${TARGET_NAME})
|
||||||
|
|
||||||
if(ADD_CSP_LIB)
|
|
||||||
add_subdirectory(${CSP_LIB_PATH})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ADD_ETL_LIB)
|
if(ADD_ETL_LIB)
|
||||||
add_subdirectory(${ETL_LIB_PATH})
|
add_subdirectory(${ETL_LIB_PATH})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ADD_LINUX_FILES)
|
|
||||||
add_subdirectory(${LINUX_PATH})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ADD_JSON_LIB)
|
if(ADD_JSON_LIB)
|
||||||
add_subdirectory(${LIB_JSON_PATH})
|
add_subdirectory(${LIB_JSON_PATH})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(${BSP_PATH})
|
if(ADD_CSP_LIB)
|
||||||
add_subdirectory(${COMMON_PATH})
|
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(${LWGPS_LIB_PATH})
|
||||||
add_subdirectory(${FSFW_PATH})
|
add_subdirectory(${FSFW_PATH})
|
||||||
add_subdirectory(${MISSION_PATH})
|
add_subdirectory(${MISSION_PATH})
|
||||||
@ -158,6 +170,9 @@ if(NOT Q7S_SIMPLE_MODE)
|
|||||||
add_subdirectory(${ARCSEC_LIB_PATH})
|
add_subdirectory(${ARCSEC_LIB_PATH})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_WATCHDOG)
|
||||||
|
add_subdirectory(${WATCHDOG_PATH})
|
||||||
|
endif()
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Post-Sources preparation
|
# Post-Sources preparation
|
||||||
@ -165,14 +180,13 @@ endif()
|
|||||||
|
|
||||||
set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux)
|
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.
|
# Add libraries for all sources.
|
||||||
target_link_libraries(${TARGET_NAME} PRIVATE
|
target_link_libraries(${TARGET_NAME} PRIVATE
|
||||||
${LIB_FSFW_NAME}
|
${LIB_FSFW_NAME}
|
||||||
${LIB_OS_NAME}
|
${LIB_OS_NAME}
|
||||||
${LIB_LWGPS_NAME}
|
${LIB_LWGPS_NAME}
|
||||||
${LIB_ARCSEC}
|
${LIB_ARCSEC}
|
||||||
${LIB_CXX_FS}
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -194,6 +208,10 @@ if(ADD_JSON_LIB)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(${TARGET_NAME} PRIVATE
|
||||||
|
${LIB_CXX_FS}
|
||||||
|
)
|
||||||
|
|
||||||
# Add include paths for all sources.
|
# Add include paths for all sources.
|
||||||
target_include_directories(${TARGET_NAME} PRIVATE
|
target_include_directories(${TARGET_NAME} PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
@ -249,10 +267,14 @@ if(NOT CMAKE_SIZE)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(TGT_BSP)
|
if(BUILD_WATCHDOG)
|
||||||
set(TARGET_STRING "Target BSP: ${TGT_BSP}")
|
set(TARGET_STRING "OBSW Watchdog")
|
||||||
else()
|
else()
|
||||||
|
if(TGT_BSP)
|
||||||
|
set(TARGET_STRING "Target BSP: ${TGT_BSP}")
|
||||||
|
else()
|
||||||
set(TARGET_STRING "Target BSP: Hosted")
|
set(TARGET_STRING "Target BSP: Hosted")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
string(CONCAT POST_BUILD_COMMENT
|
string(CONCAT POST_BUILD_COMMENT
|
||||||
|
@ -18,7 +18,7 @@ os_fsfw="linux"
|
|||||||
tgt_bsp="arm/q7s"
|
tgt_bsp="arm/q7s"
|
||||||
build_dir="build-Simple-Q7S"
|
build_dir="build-Simple-Q7S"
|
||||||
build_generator=""
|
build_generator=""
|
||||||
definitions="Q7S_SIMPLE_MODE=On"
|
definitions="BUILD_Q7S_SIMPLE_MODE=On"
|
||||||
if [ "${OS}" = "Windows_NT" ]; then
|
if [ "${OS}" = "Windows_NT" ]; then
|
||||||
build_generator="MinGW Makefiles"
|
build_generator="MinGW Makefiles"
|
||||||
python="py"
|
python="py"
|
||||||
|
@ -18,7 +18,7 @@ os_fsfw="linux"
|
|||||||
tgt_bsp="arm/q7s"
|
tgt_bsp="arm/q7s"
|
||||||
build_dir="build-Simple-Q7S"
|
build_dir="build-Simple-Q7S"
|
||||||
build_generator="Ninja"
|
build_generator="Ninja"
|
||||||
definitions="Q7S_SIMPLE_MODE=On"
|
definitions="BUILD_Q7S_SIMPLE_MODE=On"
|
||||||
if [ "${OS}" = "Windows_NT" ]; then
|
if [ "${OS}" = "Windows_NT" ]; then
|
||||||
python="py"
|
python="py"
|
||||||
# Could be other OS but this works for now.
|
# Could be other OS but this works for now.
|
||||||
|
4
watchdog/CMakeLists.txt
Normal file
4
watchdog/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
target_sources(${TARGET_NAME} PRIVATE
|
||||||
|
main.cpp
|
||||||
|
Watchdog.cpp
|
||||||
|
)
|
161
watchdog/Watchdog.cpp
Normal file
161
watchdog/Watchdog.cpp
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
#include "Watchdog.h"
|
||||||
|
#include "watchdogConf.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <cstring>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
37
watchdog/Watchdog.h
Normal file
37
watchdog/Watchdog.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef WATCHDOG_WATCHDOG_H_
|
||||||
|
#define WATCHDOG_WATCHDOG_H_
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
|
||||||
|
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<uint8_t, 64> buf;
|
||||||
|
States state = States::NOT_STARTED;
|
||||||
|
|
||||||
|
LoopResult watchdogLoop();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* WATCHDOG_WATCHDOG_H_ */
|
15
watchdog/main.cpp
Normal file
15
watchdog/main.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "Watchdog.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
16
watchdog/watchdogConf.h.in
Normal file
16
watchdog/watchdogConf.h.in
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#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";
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user