2023-03-14 14:44:32 +01:00
|
|
|
#ifndef MISSION_SYSDEFS_H_
|
|
|
|
#define MISSION_SYSDEFS_H_
|
|
|
|
|
2023-04-28 15:30:09 +02:00
|
|
|
#include <fsfw/action/ActionMessage.h>
|
|
|
|
#include <fsfw/action/HasActionsIF.h>
|
|
|
|
#include <fsfw/modes/ModeMessage.h>
|
|
|
|
#include <fsfw/serialize/SerializeIF.h>
|
2023-04-06 17:49:34 +02:00
|
|
|
|
2023-04-28 15:30:09 +02:00
|
|
|
#include <atomic>
|
|
|
|
#include <cstring>
|
2023-03-24 20:50:33 +01:00
|
|
|
|
2023-09-13 13:09:07 +02:00
|
|
|
#include "eive/eventSubsystemIds.h"
|
|
|
|
|
2023-09-11 19:23:48 +02:00
|
|
|
namespace signals {
|
|
|
|
|
|
|
|
extern std::atomic_bool CFDP_CHANNEL_THROTTLE_SIGNAL;
|
2023-04-06 17:49:34 +02:00
|
|
|
extern std::atomic_uint16_t I2C_FATAL_ERRORS;
|
2023-10-13 13:21:28 +02:00
|
|
|
extern std::atomic_uint32_t CFDP_MSG_COUNTER;
|
2023-04-06 17:49:34 +02:00
|
|
|
|
2023-09-11 19:23:48 +02:00
|
|
|
} // namespace signals
|
|
|
|
|
2023-03-14 14:44:32 +01:00
|
|
|
namespace satsystem {
|
|
|
|
|
2023-04-19 15:07:21 +02:00
|
|
|
enum Mode : Mode_t {
|
|
|
|
BOOT = 5,
|
2023-04-28 15:30:09 +02:00
|
|
|
// 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,
|
2023-04-19 15:07:21 +02:00
|
|
|
};
|
2023-03-14 14:44:32 +01:00
|
|
|
}
|
|
|
|
|
2023-04-13 23:24:32 +02:00
|
|
|
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
|
|
|
|
|
2023-04-06 17:49:34 +02:00
|
|
|
namespace core {
|
2023-04-13 23:24:32 +02:00
|
|
|
|
2023-06-25 12:41:20 +02:00
|
|
|
extern std::atomic_bool SAVE_PUS_SEQUENCE_COUNT;
|
|
|
|
extern std::atomic_bool SAVE_CFDP_SEQUENCE_COUNT;
|
|
|
|
|
2023-04-13 23:24:32 +02:00
|
|
|
// 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";
|
2023-06-24 18:37:58 +02:00
|
|
|
static constexpr char LEGACY_REBOOT_WATCHDOG_FILE_NAME[] = "reboot.txt";
|
2023-06-24 17:14:56 +02:00
|
|
|
static constexpr char REBOOT_WATCHDOG_FILE_NAME[] = "reboot_watchdog.txt";
|
|
|
|
static constexpr char REBOOT_COUNTER_FILE_NAME[] = "reboot_counters.txt";
|
2024-03-05 09:06:48 +01:00
|
|
|
static constexpr char LEAP_SECONDS_FILE_NAME[] = "leapseconds.txt";
|
2023-04-13 23:24:32 +02:00
|
|
|
static constexpr char TIME_FILE_NAME[] = "time_backup.txt";
|
|
|
|
|
2023-06-21 19:01:44 +02:00
|
|
|
static constexpr uint32_t SYS_ROM_BASE_ADDR = 0x80000000;
|
|
|
|
|
2023-04-06 17:49:34 +02:00
|
|
|
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;
|
2023-06-22 14:25:11 +02:00
|
|
|
static constexpr ActionId_t READ_REBOOT_MECHANISM_INFO = 9;
|
2023-04-06 17:49:34 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
//! 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;
|
|
|
|
|
2023-04-13 23:24:32 +02:00
|
|
|
static constexpr ActionId_t EXECUTE_SHELL_CMD_BLOCKING = 40;
|
2023-04-14 00:21:28 +02:00
|
|
|
static constexpr ActionId_t EXECUTE_SHELL_CMD_NON_BLOCKING = 41;
|
2023-04-13 23:24:32 +02:00
|
|
|
static constexpr ActionId_t SYSTEMCTL_CMD_EXECUTOR = 42;
|
2023-04-06 17:49:34 +02:00
|
|
|
|
2023-04-15 13:01:41 +02:00
|
|
|
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;
|
2023-04-15 22:17:50 +02:00
|
|
|
static constexpr ActionId_t MKDIR_HELPER = 55;
|
2023-04-15 13:01:41 +02:00
|
|
|
|
2024-03-05 09:06:48 +01:00
|
|
|
static constexpr ActionId_t UPDATE_LEAP_SECONDS = 60;
|
|
|
|
|
2023-04-06 17:49:34 +02:00
|
|
|
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);
|
2023-04-06 22:39:57 +02:00
|
|
|
//! [EXPORT] : [COMMENT] I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C
|
|
|
|
//! devices.
|
2023-04-14 20:08:05 +02:00
|
|
|
static constexpr Event TRYING_I2C_RECOVERY = event::makeEvent(SUBSYSTEM_ID, 10, severity::HIGH);
|
2023-04-06 22:39:57 +02:00
|
|
|
//! [EXPORT] : [COMMENT] I2C is unavailable. Recovery did not work, performing full reboot.
|
2023-04-14 20:08:05 +02:00
|
|
|
static constexpr Event I2C_REBOOT = event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH);
|
2023-04-14 20:04:51 +02:00
|
|
|
//! [EXPORT] : [COMMENT] PDEC recovery through reset was not possible, performing full reboot.
|
2023-04-14 20:08:05 +02:00
|
|
|
static constexpr Event PDEC_REBOOT = event::makeEvent(SUBSYSTEM_ID, 12, severity::HIGH);
|
2023-06-21 19:01:44 +02:00
|
|
|
//! [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);
|
2023-07-21 11:15:35 +02:00
|
|
|
//! [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
|
2023-07-21 10:23:35 +02:00
|
|
|
static constexpr Event ACTIVE_SD_INFO = event::makeEvent(SUBSYSTEM_ID, 14, severity::INFO);
|
2023-04-06 19:29:51 +02:00
|
|
|
|
2023-04-15 13:01:41 +02:00
|
|
|
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;
|
2023-04-16 02:56:46 +02:00
|
|
|
return this->repoName;
|
2023-04-15 13:01:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2023-04-16 02:56:46 +02:00
|
|
|
return this->targetName;
|
2023-04-15 13:01:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2023-04-15 22:17:50 +02:00
|
|
|
size_t remainingLen = maxLen - destTgt.sourceNameSize - 1;
|
2023-04-15 13:01:41 +02:00
|
|
|
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;
|
|
|
|
}
|
2023-04-15 22:17:50 +02:00
|
|
|
destTgt.targetName = reinterpret_cast<const char*>(data + destTgt.sourceNameSize + 1);
|
2023-04-15 13:01:41 +02:00
|
|
|
return returnvalue::OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
class CpHelperParser {
|
|
|
|
public:
|
|
|
|
CpHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {}
|
|
|
|
|
|
|
|
ReturnValue_t parse() {
|
2023-06-06 11:11:16 +02:00
|
|
|
if (maxLen < 2) {
|
2023-04-15 13:01:41 +02:00
|
|
|
return SerializeIF::STREAM_TOO_SHORT;
|
|
|
|
}
|
|
|
|
recursiveOpt = data[0];
|
2023-06-06 11:11:16 +02:00
|
|
|
forceOpt = data[1];
|
2023-06-06 14:05:44 +02:00
|
|
|
return parseDestTargetString(data + 2, maxLen - 2, destTgt);
|
2023-04-15 13:01:41 +02:00
|
|
|
}
|
|
|
|
const SourceTargetPair& destTgtPair() const { return destTgt; }
|
|
|
|
bool isRecursiveOptSet() const { return recursiveOpt; }
|
2023-06-06 11:11:16 +02:00
|
|
|
bool isForceOptSet() const { return forceOpt; }
|
2023-04-15 13:01:41 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
const uint8_t* data;
|
|
|
|
size_t maxLen;
|
|
|
|
bool recursiveOpt = false;
|
2023-06-06 11:11:16 +02:00
|
|
|
bool forceOpt = false;
|
2023-04-15 13:01:41 +02:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2023-04-06 17:49:34 +02:00
|
|
|
} // namespace core
|
|
|
|
|
2023-03-14 14:44:32 +01:00
|
|
|
#endif /* MISSION_SYSDEFS_H_ */
|