eive-obsw/mission/sysDefs.h
Robin Mueller 01ce1f154e
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
that should get the job done
2023-10-19 14:43:29 +02:00

341 lines
12 KiB
C++

#ifndef MISSION_SYSDEFS_H_
#define MISSION_SYSDEFS_H_
#include <fsfw/action/ActionMessage.h>
#include <fsfw/action/HasActionsIF.h>
#include <fsfw/modes/ModeMessage.h>
#include <fsfw/serialize/SerializeIF.h>
#include <atomic>
#include <cstring>
#include "eive/eventSubsystemIds.h"
namespace signals {
extern std::atomic_bool CFDP_CHANNEL_THROTTLE_SIGNAL;
extern std::atomic_uint16_t I2C_FATAL_ERRORS;
extern std::atomic_uint32_t CFDP_MSG_COUNTER;
} // namespace signals
namespace satsystem {
enum Mode : Mode_t {
BOOT = 5,
// DO NOT CHANGE THE ORDER starting from here, breaks ACS mode checks.
SAFE = 10,
PTG_IDLE = 11,
PTG_NADIR = 12,
PTG_TARGET = 13,
PTG_TARGET_GS = 14,
PTG_INERTIAL = 15,
};
}
namespace xsc {
enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP };
enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
} // namespace xsc
namespace core {
extern std::atomic_bool SAVE_PUS_SEQUENCE_COUNT;
extern std::atomic_bool SAVE_CFDP_SEQUENCE_COUNT;
// TODO: Support for status? Or maybe some command to quickly get information whether a unit
// is running.
enum SystemctlCmd : uint8_t { START = 0, STOP = 1, RESTART = 2, NUM_CMDS = 3 };
static constexpr char CONF_FOLDER[] = "conf";
static constexpr char VERSION_FILE_NAME[] = "version.txt";
static constexpr char LEGACY_REBOOT_WATCHDOG_FILE_NAME[] = "reboot.txt";
static constexpr char REBOOT_WATCHDOG_FILE_NAME[] = "reboot_watchdog.txt";
static constexpr char REBOOT_COUNTER_FILE_NAME[] = "reboot_counters.txt";
static constexpr char TIME_FILE_NAME[] = "time_backup.txt";
static constexpr uint32_t SYS_ROM_BASE_ADDR = 0x80000000;
static constexpr ActionId_t ANNOUNCE_VERSION = 1;
static constexpr ActionId_t ANNOUNCE_CURRENT_IMAGE = 2;
static constexpr ActionId_t ANNOUNCE_BOOT_COUNTS = 3;
static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5;
static constexpr ActionId_t RESET_REBOOT_COUNTERS = 6;
static constexpr ActionId_t SWITCH_IMG_LOCK = 7;
static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8;
static constexpr ActionId_t READ_REBOOT_MECHANISM_INFO = 9;
static constexpr ActionId_t OBSW_UPDATE_FROM_SD_0 = 10;
static constexpr ActionId_t OBSW_UPDATE_FROM_SD_1 = 11;
static constexpr ActionId_t OBSW_UPDATE_FROM_TMP = 12;
static constexpr ActionId_t SWITCH_TO_SD_0 = 16;
static constexpr ActionId_t SWITCH_TO_SD_1 = 17;
static constexpr ActionId_t SWITCH_TO_BOTH_SD_CARDS = 18;
static constexpr ActionId_t ENABLE_AUTO_SWITCH = 19;
static constexpr ActionId_t DISABLE_AUTO_SWITCH = 20;
//! Reboot using the xsc_boot_copy command
static constexpr ActionId_t XSC_REBOOT_OBC = 32;
static constexpr ActionId_t MOUNT_OTHER_COPY = 33;
//! Reboot using the reboot command
static constexpr ActionId_t REBOOT_OBC = 34;
static constexpr ActionId_t EXECUTE_SHELL_CMD_BLOCKING = 40;
static constexpr ActionId_t EXECUTE_SHELL_CMD_NON_BLOCKING = 41;
static constexpr ActionId_t SYSTEMCTL_CMD_EXECUTOR = 42;
static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 50;
static constexpr ActionId_t LIST_DIRECTORY_DUMP_DIRECTLY = 51;
static constexpr ActionId_t CP_HELPER = 52;
static constexpr ActionId_t MV_HELPER = 53;
static constexpr ActionId_t RM_HELPER = 54;
static constexpr ActionId_t MKDIR_HELPER = 55;
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE;
static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM);
//! [EXPORT] : [COMMENT] Software reboot occurred. Can also be a systemd reboot.
//! P1: Current Chip, P2: Current Copy
static constexpr Event REBOOT_SW = event::makeEvent(SUBSYSTEM_ID, 1, severity::LOW);
//! [EXPORT] : [COMMENT] The reboot mechanism was triggered.
//! P1: First 16 bits: Last Chip, Last 16 bits: Last Copy,
//! P2: Each byte is the respective reboot count for the slots
static constexpr Event REBOOT_MECHANISM_TRIGGERED =
event::makeEvent(SUBSYSTEM_ID, 2, severity::MEDIUM);
//! Trying to find a way how to determine that the reboot came from ProASIC3 or PCDU..
static constexpr Event REBOOT_HW = event::makeEvent(SUBSYSTEM_ID, 3, severity::MEDIUM);
//! [EXPORT] : [COMMENT] No SD card was active. Core controller will attempt to re-initialize
//! a SD card.
static constexpr Event NO_SD_CARD_ACTIVE = event::makeEvent(SUBSYSTEM_ID, 4, severity::HIGH);
//! [EXPORT] : [COMMENT]
//! P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash
//! P2: First four letters of Git SHA is the last byte of P1 is set.
static constexpr Event VERSION_INFO = event::makeEvent(SUBSYSTEM_ID, 5, severity::INFO);
//! [EXPORT] : [COMMENT] P1: Current Chip, P2: Current Copy
static constexpr Event CURRENT_IMAGE_INFO = event::makeEvent(SUBSYSTEM_ID, 6, severity::INFO);
//! [EXPORT] : [COMMENT] Total reboot counter, which is the sum of the boot count of all
//! individual images.
static constexpr Event REBOOT_COUNTER = event::makeEvent(SUBSYSTEM_ID, 7, severity::INFO);
//! [EXPORT] : [COMMENT] Get the boot count of the individual images.
//! P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1.
//! P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.
static constexpr Event INDIVIDUAL_BOOT_COUNTS = event::makeEvent(SUBSYSTEM_ID, 8, severity::INFO);
//! [EXPORT] : [COMMENT] I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C
//! devices.
static constexpr Event TRYING_I2C_RECOVERY = event::makeEvent(SUBSYSTEM_ID, 10, severity::HIGH);
//! [EXPORT] : [COMMENT] I2C is unavailable. Recovery did not work, performing full reboot.
static constexpr Event I2C_REBOOT = event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH);
//! [EXPORT] : [COMMENT] PDEC recovery through reset was not possible, performing full reboot.
static constexpr Event PDEC_REBOOT = event::makeEvent(SUBSYSTEM_ID, 12, severity::HIGH);
//! [EXPORT] : [COMMENT] Version information of the firmware (not OBSW).
//! P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash
//! P2: First four letters of Git SHA is the last byte of P1 is set.
static constexpr Event FIRMWARE_INFO = event::makeEvent(SUBSYSTEM_ID, 13, severity::INFO);
//! [EXPORT] : [COMMENT] Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED.
//! P1: Active SD Card Index, 0 if none is active
//! P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1
static constexpr Event ACTIVE_SD_INFO = event::makeEvent(SUBSYSTEM_ID, 14, severity::INFO);
class ListDirectoryCmdBase {
public: // TODO: Packet definition for clean deserialization
// 3 bytes for a and R flag, at least 5 bytes for minimum valid path /tmp with
// null termination
static constexpr size_t MIN_DATA_LEN = 8;
ListDirectoryCmdBase(const uint8_t* data, size_t maxSize) : data(data), maxSize(maxSize) {}
virtual ~ListDirectoryCmdBase() = default;
virtual ReturnValue_t parse() {
if (maxSize < MIN_DATA_LEN) {
return SerializeIF::STREAM_TOO_SHORT;
}
aFlag = data[0];
rFlag = data[1];
compressOption = data[2];
repoNameLen = strnlen(reinterpret_cast<const char*>(data + 3), maxSize - 3);
// Last byte MUST be null terminated!
if (repoNameLen >= maxSize - 3) {
return HasActionsIF::INVALID_PARAMETERS;
}
repoName = reinterpret_cast<const char*>(data + 3);
return returnvalue::OK;
}
bool aFlagSet() const { return this->aFlag; }
bool rFlagSet() const { return this->rFlag; }
bool compressionOptionSet() const { return this->compressOption; }
const char* getRepoName(size_t& repoNameLen) const {
repoNameLen = this->repoNameLen;
return this->repoName;
}
size_t getBaseSize() {
// Include NULL termination
if (repoName != nullptr) {
return 3 + repoNameLen + 1;
}
return 0;
}
protected:
const uint8_t* data;
size_t maxSize;
bool aFlag = false;
bool rFlag = false;
bool compressOption = false;
const char* repoName = nullptr;
size_t repoNameLen = 0;
};
class ListDirectoryIntoFile : public ListDirectoryCmdBase {
public:
// TODO: Packet definition for clean deserialization
// 3 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.
static constexpr size_t MIN_DATA_LEN = 15;
ListDirectoryIntoFile(const uint8_t* data, size_t maxSize)
: ListDirectoryCmdBase(data, maxSize) {}
ReturnValue_t parse() override {
if (maxSize < MIN_DATA_LEN) {
return SerializeIF::STREAM_TOO_SHORT;
}
ReturnValue_t result = ListDirectoryCmdBase::parse();
if (result != returnvalue::OK) {
return result;
}
targetNameLen =
strnlen(reinterpret_cast<const char*>(data + getBaseSize()), maxSize - getBaseSize());
if (targetNameLen >= maxSize - getBaseSize()) {
// Again: String MUST be null terminated.
return HasActionsIF::INVALID_PARAMETERS;
}
targetName = reinterpret_cast<const char*>(data + getBaseSize());
return result;
}
const char* getTargetName(size_t& targetNameLen) const {
targetNameLen = this->targetNameLen;
return this->targetName;
}
private:
const char* targetName = nullptr;
size_t targetNameLen = 0;
};
struct SourceTargetPair {
const char* sourceName = nullptr;
size_t sourceNameSize = 0;
const char* targetName = nullptr;
size_t targetNameSize = 0;
};
static ReturnValue_t parseDestTargetString(const uint8_t* data, size_t maxLen,
SourceTargetPair& destTgt) {
if (maxLen < 4) {
return SerializeIF::STREAM_TOO_SHORT;
}
destTgt.sourceNameSize = strnlen(reinterpret_cast<const char*>(data), maxLen);
if (destTgt.sourceNameSize >= maxLen) {
return HasActionsIF::INVALID_PARAMETERS;
}
destTgt.sourceName = reinterpret_cast<const char*>(data);
size_t remainingLen = maxLen - destTgt.sourceNameSize - 1;
if (remainingLen == 0) {
return HasActionsIF::INVALID_PARAMETERS;
}
destTgt.targetNameSize =
strnlen(reinterpret_cast<const char*>(data + destTgt.sourceNameSize + 1), remainingLen);
if (destTgt.targetNameSize >= remainingLen) {
return HasActionsIF::INVALID_PARAMETERS;
}
destTgt.targetName = reinterpret_cast<const char*>(data + destTgt.sourceNameSize + 1);
return returnvalue::OK;
}
class CpHelperParser {
public:
CpHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {}
ReturnValue_t parse() {
if (maxLen < 2) {
return SerializeIF::STREAM_TOO_SHORT;
}
recursiveOpt = data[0];
forceOpt = data[1];
return parseDestTargetString(data + 2, maxLen - 2, destTgt);
}
const SourceTargetPair& destTgtPair() const { return destTgt; }
bool isRecursiveOptSet() const { return recursiveOpt; }
bool isForceOptSet() const { return forceOpt; }
private:
const uint8_t* data;
size_t maxLen;
bool recursiveOpt = false;
bool forceOpt = false;
SourceTargetPair destTgt;
};
class MvHelperParser {
public:
MvHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {}
ReturnValue_t parse() { return parseDestTargetString(data, maxLen, destTgt); }
const SourceTargetPair& destTgtPair() const { return destTgt; }
private:
const uint8_t* data;
size_t maxLen;
SourceTargetPair destTgt;
};
class RmHelperParser {
public:
RmHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {}
ReturnValue_t parse() {
if (maxLen < 2) {
return SerializeIF::STREAM_TOO_SHORT;
}
recursiveOpt = data[0];
forceOpt = data[1];
removeTargetSize = strnlen(reinterpret_cast<const char*>(data + 2), maxLen - 2);
// Must be null-terminated
if (removeTargetSize >= maxLen - 2) {
return HasActionsIF::INVALID_PARAMETERS;
}
removeTarget = reinterpret_cast<const char*>(data + 2);
return returnvalue::OK;
}
bool isRecursiveOptSet() const { return recursiveOpt; }
bool isForceOptSet() const { return forceOpt; }
const char* getRemoveTarget(size_t& removeTargetSize) {
removeTargetSize = this->removeTargetSize;
return removeTarget;
}
private:
const uint8_t* data;
size_t maxLen;
bool recursiveOpt = false;
bool forceOpt = false;
const char* removeTarget = nullptr;
size_t removeTargetSize = 0;
};
} // namespace core
#endif /* MISSION_SYSDEFS_H_ */