Merge remote-tracking branch 'origin/develop' into feature_watchdog_extension
All checks were successful
EIVE/eive-obsw/pipeline/pr-develop This commit looks good

This commit is contained in:
Robin Müller 2023-02-24 19:16:29 +01:00
commit cf42ca7835
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
87 changed files with 1371 additions and 359 deletions

7
.gitignore vendored
View File

@ -12,8 +12,13 @@
#vscode
/.vscode
# IntelliJ
/.idea/*
# Python
__pycache__
.idea
# CLion
!/.idea/cmake.xml
generators/*.db

10
.run/Q7S FM.run.xml Normal file
View File

@ -0,0 +1,10 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Q7S FM" type="com.jetbrains.cidr.remote.gdbserver.type" factoryName="com.jetbrains.cidr.remote.gdbserver.factory" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="eive-obsw" TARGET_NAME="eive-obsw" CONFIG_NAME="Debug" version="1" RUN_TARGET_PROJECT_NAME="eive-obsw" RUN_TARGET_NAME="eive-obsw">
<custom-gdb-server version="1" gdb-connect="localhost:1234" executable="" warmup-ms="0" download-type="NONE" sshConfigName="Q7S FM" uploadFile="/tmp/eive-obsw" defaultGdbServerArgs=":1234 /tmp/eive-obsw">
<debugger kind="GDB" isBundled="true" />
</custom-gdb-server>
<method v="2">
<option name="CLION.COMPOUND.BUILD" enabled="true" />
</method>
</configuration>
</component>

View File

@ -28,9 +28,46 @@ will consitute of a breaking change warranting a new major release:
- The SD card prefix is now set earlier inside the `CoreController` constructor
- The watchdog handling was moved outside the `CoreController` into the main loop.
# [v1.32.0]
eive-tmtc: v2.16.1
## Fixed
- ADIS1650X: Added missing MDL_RANG pool entry for configuration set
- Bumped FSFW for bugfix in health service: No execution complete for targeted health announce
command.
- Removed matrix determinant calculation as part of the `MEKF`, which would take about
300ms of runtime
- Resetting the `MEKF` now also actually resets its stored state
- Bumped FSFW for bugfix in destination handler: Better error handling and able to process
destination folder path.
## Changed
- Added basic persistent TM store for PUS telemetry and basic interface to dump and delete
telemetry. Implementation is based on a timed rotating files, with the addition that files
might be generated more often if the maximum file size of 8192 bytes is exceeded.
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/320/files
- Commented out commanding of actuators as part of the `AcsController`
- Collection sets of the `AcsController` now get updated before running the actual ACS
algorithm
- `GpsController` now always gets scheduled
- The `CoreController` now initializes the initial clock from the time file as early as possible
(in the constructor) if possible, which should usually be the case.
## Added
- Added basic persistent TM store for PUS telemetry and basic interface to dump and delete
telemetry.
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/320/files
- `ExecutableComIfDummy` class to have a dummy for classes like the RTD polling class.
- Added `AcsController` action command to confirm solar array deployment, which then deletes
two files
- Added `AcsController` action command to reset `MEKF`
- `GpsCtrlDummy` now initializes the `gpsSet`
- `RwDummy` now initializes with a non faulty state
# [v1.31.1]

View File

@ -10,8 +10,8 @@
cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR 1)
set(OBSW_VERSION_MINOR 31)
set(OBSW_VERSION_REVISION 1)
set(OBSW_VERSION_MINOR 32)
set(OBSW_VERSION_REVISION 0)
# set(CMAKE_VERBOSE TRUE)
@ -223,6 +223,7 @@ set(LIB_JSON_PATH ${THIRD_PARTY_FOLDER}/json)
set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF)
set(EIVE_ADD_LINUX_FILES OFF)
set(FSFW_ADD_TMSTORAGE ON)
# Analyse different OS and architecture/target options, determine BSP_PATH,
# display information about compiler etc.

View File

@ -18,6 +18,7 @@
11. [Q7S OBC](#q7s)
12. [Static Code Analysis](#static-code-analysis)
13. [Eclipse](#eclipse)
14. [CLion](#clion)
14. [Running the OBSW on a Raspberry Pi](#rpi)
15. [Running OBSW on EGSE](#egse)
16. [Manually preparing sysroots to compile gpsd](#gpsd)
@ -1229,6 +1230,22 @@ Finally, you can convert the generated `.xml` file to HTML with the following co
cppcheck-htmlreport --file=report.xml --report-dir=cppcheck --source-dir=..
```
# <a id="CLion"></a> CLion
CLion is the recommended IDE for the development of the hosted version of EIVE.
You can also set up CLion for cross-compilation of the primary OBSW.
There is a shared `.idea/cmake.xml` file to get started with this.
To make cross-compilation work, two special environment variables
need to be set:
- `ZYNQ_7020_ROOTFS` pointing to the root filesystem
- `CROSS_COMPILE` pointing to the the full path of the cross-compiler
without the specific tool suffix. For example, if the the cross-compiler
tools are located at `/opt/q7s-gcc/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin`,
this variable would be set
to `/opt/q7s-gcc/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf`
# <a id="eclipse"></a> Eclipse
When using Eclipse, there are two special build variables in the project properties

View File

@ -8,6 +8,7 @@
#include <mission/tmtc/TmFunnelHandler.h>
#include <objects/systemObjectList.h>
#include "../mission/utility/DummySdCardManager.h"
#include "OBSWConfig.h"
#include "fsfw/platform.h"
#include "fsfw_tests/integration/task/TestTask.h"
@ -58,7 +59,8 @@ void ObjectFactory::produce(void* args) {
Factory::setStaticFrameworkObjectIds();
PusTmFunnel* pusFunnel;
CfdpTmFunnel* cfdpFunnel;
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel);
auto sdcMan = new DummySdCardManager("/tmp");
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan);
auto* dummyGpioIF = new DummyGpioIF();
auto* dummySwitcher = new DummyPowerSwitcher(objects::PCDU_HANDLER, 18, 0);

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 260 translations.
* @brief Auto-generated event translation file. Contains 263 translations.
* @details
* Generated on: 2023-02-23 15:39:20
* Generated on: 2023-02-24 16:57:00
*/
#include "translateEvents.h"
@ -90,6 +90,8 @@ const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER";
const char *STORE_ERROR_STRING = "STORE_ERROR";
const char *MSG_QUEUE_ERROR_STRING = "MSG_QUEUE_ERROR";
const char *SERIALIZATION_ERROR_STRING = "SERIALIZATION_ERROR";
const char *FILESTORE_ERROR_STRING = "FILESTORE_ERROR";
const char *FILENAME_TOO_LARGE_ERROR_STRING = "FILENAME_TOO_LARGE_ERROR";
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
@ -253,6 +255,7 @@ const char *REBOOT_HW_STRING = "REBOOT_HW";
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
const char *VERSION_INFO_STRING = "VERSION_INFO";
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -433,6 +436,10 @@ const char *translateEvents(Event event) {
return MSG_QUEUE_ERROR_STRING;
case (10802):
return SERIALIZATION_ERROR_STRING;
case (10803):
return FILESTORE_ERROR_STRING;
case (10804):
return FILENAME_TOO_LARGE_ERROR_STRING;
case (11200):
return SAFE_RATE_VIOLATION_STRING;
case (11201):
@ -760,18 +767,20 @@ const char *translateEvents(Event event) {
case (14006):
return CURRENT_IMAGE_INFO_STRING;
case (14100):
return POSSIBLE_FILE_CORRUPTION_STRING;
case (14200):
return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101):
case (14201):
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
case (14102):
case (14202):
return SYRLINKS_OVERHEATING_STRING;
case (14103):
case (14203):
return PLOC_OVERHEATING_STRING;
case (14104):
case (14204):
return OBC_OVERHEATING_STRING;
case (14105):
case (14205):
return HPA_OVERHEATING_STRING;
case (14106):
case (14206):
return PLPCDU_OVERHEATING_STRING;
default:
return "UNKNOWN_EVENT";

View File

@ -1,8 +1,8 @@
/**
* @brief Auto-generated object translation file.
* @details
* Contains 148 translations.
* Generated on: 2023-02-23 15:39:20
* Contains 154 translations.
* Generated on: 2023-02-24 16:57:00
*/
#include "translateObjects.h"
@ -112,6 +112,7 @@ const char *PUS_SERVICE_5_EVENT_REPORTING_STRING = "PUS_SERVICE_5_EVENT_REPORTIN
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
const char *PUS_SERVICE_15_TM_STORAGE_STRING = "PUS_SERVICE_15_TM_STORAGE";
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
@ -150,6 +151,11 @@ const char *ACS_SUBSYSTEM_STRING = "ACS_SUBSYSTEM";
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
const char *MISC_TM_STORE_STRING = "MISC_TM_STORE";
const char *OK_TM_STORE_STRING = "OK_TM_STORE";
const char *NOT_OK_TM_STORE_STRING = "NOT_OK_TM_STORE";
const char *HK_TM_STORE_STRING = "HK_TM_STORE";
const char *CFDP_TM_STORE_STRING = "CFDP_TM_STORE";
const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE";
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE";
@ -369,6 +375,8 @@ const char *translateObject(object_id_t object) {
return PUS_SERVICE_9_TIME_MGMT_STRING;
case 0x53000011:
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
case 0x53000015:
return PUS_SERVICE_15_TM_STORAGE_STRING;
case 0x53000017:
return PUS_SERVICE_17_TEST_STRING;
case 0x53000020:
@ -445,6 +453,16 @@ const char *translateObject(object_id_t object) {
return TCS_SUBSYSTEM_STRING;
case 0x73010004:
return COM_SUBSYSTEM_STRING;
case 0x73020001:
return MISC_TM_STORE_STRING;
case 0x73020002:
return OK_TM_STORE_STRING;
case 0x73020003:
return NOT_OK_TM_STORE_STRING;
case 0x73020004:
return HK_TM_STORE_STRING;
case 0x73030000:
return CFDP_TM_STORE_STRING;
case 0x73500000:
return CCSDS_IP_CORE_BRIDGE_STRING;
case 0x90000003:

View File

@ -95,46 +95,43 @@ void scheduling::initTasks() {
sif::error << "Add component UDP Polling failed" << std::endl;
}
/* PUS Services */
PeriodicTaskIF* pusVerification = factory->createPeriodicTask(
"PUS_VERIF", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusVerification->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask(
"PUS_HIGH_PRIO", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_1_VERIFICATION);
if (result != returnvalue::OK) {
sif::error << "Object add component failed" << std::endl;
}
PeriodicTaskIF* eventHandling = factory->createPeriodicTask(
"EVENTS", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = eventHandling->addComponent(objects::EVENT_MANAGER);
result = pusHighPrio->addComponent(objects::EVENT_MANAGER);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("EVENT_MNGR", objects::EVENT_MANAGER);
scheduling::printAddObjectError("EVENT_MGMT", objects::EVENT_MANAGER);
}
result = eventHandling->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_5_EVENT_REPORTING);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS5", objects::PUS_SERVICE_5_EVENT_REPORTING);
}
PeriodicTaskIF* pusHighPrio = factory->createPeriodicTask(
"PUS_HIGH_PRIO", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS9", objects::PUS_SERVICE_9_TIME_MGMT);
}
PeriodicTaskIF* pusMedPrio = factory->createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS2", objects::PUS_SERVICE_2_DEVICE_ACCESS);
}
result = pusHighPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS3", objects::PUS_SERVICE_3_HOUSEKEEPING);
}
PeriodicTaskIF* pusMedPrio = factory->createPeriodicTask(
"PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS8", objects::PUS_SERVICE_8_FUNCTION_MGMT);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_15_TM_STORAGE);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS15", objects::PUS_SERVICE_15_TM_STORAGE);
}
result = pusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS200", objects::PUS_SERVICE_200_MODE_MGMT);
@ -143,10 +140,7 @@ void scheduling::initTasks() {
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS20", objects::PUS_SERVICE_20_PARAMETERS);
}
PeriodicTaskIF* pusLowPrio = factory->createPeriodicTask(
"PUS_LOW_PRIO", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, missedDeadlineFunc);
result = pusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST);
result = pusMedPrio->addComponent(objects::PUS_SERVICE_17_TEST);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("PUS17", objects::PUS_SERVICE_17_TEST);
}
@ -220,11 +214,8 @@ void scheduling::initTasks() {
udpPollingTask->startTask();
tcpPollingTask->startTask();
pusVerification->startTask();
eventHandling->startTask();
pusHighPrio->startTask();
pusMedPrio->startTask();
pusLowPrio->startTask();
pstTask->startTask();
thermalTask->startTask();

View File

@ -1,5 +1,5 @@
target_sources(${OBSW_NAME} PUBLIC InitMission.cpp main.cpp gpioInit.cpp
ObjectFactory.cpp RPiSdCardManager.cpp)
ObjectFactory.cpp)
add_subdirectory(boardconfig)
add_subdirectory(boardtest)

View File

@ -82,7 +82,7 @@ void ObjectFactory::produce(void* args) {
#endif
#if OBSW_ADD_SCEX_DEVICE == 1
auto* sdcMan = new RPiSdCardManager("/tmp");
auto* sdcMan = new DummySdCardManager("/tmp");
createScexComponents(uart::DEV, pwrSwitcher, *sdcMan, true, std::nullopt);
#endif

View File

@ -1,13 +0,0 @@
#include "RPiSdCardManager.h"
RPiSdCardManager::RPiSdCardManager(std::string prefix) : prefix(std::move(prefix)) {}
const std::string& RPiSdCardManager::getCurrentMountPrefix() const { return prefix; }
bool RPiSdCardManager::isSdCardUsable(sd::SdCard sdCard) { return true; }
std::optional<sd::SdCard> RPiSdCardManager::getPreferredSdCard() const { return std::nullopt; }
void RPiSdCardManager::setActiveSdCard(sd::SdCard sdCard) {}
std::optional<sd::SdCard> RPiSdCardManager::getActiveSdCard() const { return std::nullopt; }

View File

@ -54,6 +54,8 @@ CoreController::CoreController(object_id_t objectId)
currMntPrefix = sdcMan->getCurrentMountPrefix();
getCurrentBootCopy(CURRENT_CHIP, CURRENT_COPY);
initClockFromTimeFile();
} catch (const std::filesystem::filesystem_error &e) {
sif::error << "CoreController::CoreController: Failed with exception " << e.what() << std::endl;
}
@ -1196,10 +1198,12 @@ void CoreController::performMountedSdCardOperations() {
if (result != returnvalue::OK) {
sif::warning << "CoreController::CoreController: Boot copy init" << std::endl;
}
initClockFromTimeFile();
if (not timeFileInitDone) {
initClockFromTimeFile();
}
performRebootFileHandling(false);
}
timeFileHandler();
backupTimeFileHandler();
};
bool someSdCardActive = false;
if (sdInfo.active == sd::SdCard::SLOT_0 and sdcMan->isSdCardUsable(sd::SdCard::SLOT_0)) {
@ -1713,7 +1717,7 @@ void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::C
rewriteRebootFile(rebootFile);
}
ReturnValue_t CoreController::timeFileHandler() {
ReturnValue_t CoreController::backupTimeFileHandler() {
// Always set time. We could only set it if it is updated by GPS, but then the backup time would
// become obsolete on GPS problems.
if (opDivider10.check()) {
@ -1723,14 +1727,14 @@ ReturnValue_t CoreController::timeFileHandler() {
if (result != returnvalue::OK) {
return result;
}
std::string fileName = currMntPrefix + TIME_FILE;
std::string fileName = currMntPrefix + BACKUP_TIME_FILE;
std::ofstream timeFile(fileName);
if (not timeFile.good()) {
sif::error << "CoreController::timeFileHandler: Error opening time file: " << strerror(errno)
<< std::endl;
return returnvalue::FAILED;
}
timeFile << "UNIX SECONDS: " << currentTime.tv_sec << std::endl;
timeFile << "UNIX SECONDS: " << currentTime.tv_sec + BOOT_OFFSET_SECONDS << std::endl;
}
return returnvalue::OK;
}
@ -1738,8 +1742,8 @@ ReturnValue_t CoreController::timeFileHandler() {
ReturnValue_t CoreController::initClockFromTimeFile() {
using namespace GpsHyperion;
using namespace std;
std::string fileName = currMntPrefix + TIME_FILE;
if (std::filesystem::exists(fileName) and
std::string fileName = currMntPrefix + BACKUP_TIME_FILE;
if (sdcMan->isSdCardUsable(std::nullopt) and std::filesystem::exists(fileName) and
((gpsFix == FixMode::UNKNOWN or gpsFix == FixMode::NOT_SEEN) or
not utility::timeSanityCheck())) {
ifstream timeFile(fileName);
@ -1767,6 +1771,7 @@ ReturnValue_t CoreController::initClockFromTimeFile() {
sif::info << "Setting system time from time files: " << std::put_time(time, "%c %Z")
<< std::endl;
#endif
timeFileInitDone = true;
return Clock::setClock(&currentTime);
}
return returnvalue::OK;

View File

@ -58,13 +58,14 @@ class CoreController : public ExtendedControllerBase {
static constexpr char VERSION_FILE_NAME[] = "version.txt";
static constexpr char REBOOT_FILE_NAME[] = "reboot.txt";
static constexpr char TIME_FILE_NAME[] = "time.txt";
static constexpr char TIME_FILE_NAME[] = "time_backup.txt";
const std::string VERSION_FILE =
"/" + std::string(CONF_FOLDER) + "/" + std::string(VERSION_FILE_NAME);
const std::string REBOOT_FILE =
"/" + std::string(CONF_FOLDER) + "/" + std::string(REBOOT_FILE_NAME);
const std::string TIME_FILE = "/" + std::string(CONF_FOLDER) + "/" + std::string(TIME_FILE_NAME);
const std::string BACKUP_TIME_FILE =
"/" + std::string(CONF_FOLDER) + "/" + std::string(TIME_FILE_NAME);
static constexpr char CHIP_0_COPY_0_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-nom-rootfs";
static constexpr char CHIP_0_COPY_1_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-gold-rootfs";
@ -160,6 +161,7 @@ class CoreController : public ExtendedControllerBase {
bool sdInitFinished() const;
private:
static constexpr uint32_t BOOT_OFFSET_SECONDS = 15;
static constexpr MutexIF::TimeoutType TIMEOUT_TYPE = MutexIF::TimeoutType::WAITING;
static constexpr uint32_t MUTEX_TIMEOUT = 20;
GpsHyperion::FixMode gpsFix = GpsHyperion::FixMode::UNKNOWN;
@ -218,6 +220,7 @@ class CoreController : public ExtendedControllerBase {
RebootFile rebootFile = {};
std::string currMntPrefix;
bool timeFileInitDone = false;
bool performOneShotSdCardOpsSwitch = false;
uint8_t shortSdCardCdCounter = 0;
#if OBSW_THREAD_TRACING == 1
@ -255,7 +258,7 @@ class CoreController : public ExtendedControllerBase {
ReturnValue_t initClockFromTimeFile();
ReturnValue_t performSdCardCheck();
ReturnValue_t timeFileHandler();
ReturnValue_t backupTimeFileHandler();
ReturnValue_t initBootCopyFile();
ReturnValue_t initSdCardBlocking();
bool startSdStateMachine(sd::SdCard targetActiveSd, SdCfgMode mode, MessageQueueId_t commander,

View File

@ -187,14 +187,12 @@ void scheduling::initTasks() {
}
#endif
#if OBSW_ADD_GPS_CTRL == 1
PeriodicTaskIF* gpsTask = factory->createPeriodicTask(
"GPS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc);
result = gpsTask->addComponent(objects::GPS_CONTROLLER);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("GPS_CTRL", objects::GPS_CONTROLLER);
}
#endif /* OBSW_ADD_GPS_CTRL */
#if OBSW_ADD_RW == 1
PeriodicTaskIF* rwPolling = factory->createPeriodicTask(
@ -378,9 +376,7 @@ void scheduling::initTasks() {
#if OBSW_ADD_RW == 1
rwPolling->startTask();
#endif
#if OBSW_ADD_GPS_CTRL == 1
gpsTask->startTask();
#endif
acsSysTask->startTask();
if (not tcsSystemTask->isEmpty()) {
tcsSystemTask->startTask();

View File

@ -3,6 +3,7 @@
#include <fsfw/power/DummyPowerSwitcher.h>
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
#include <mission/system/tree/system.h>
#include <mission/utility/DummySdCardManager.h>
#include "OBSWConfig.h"
#include "bsp_q7s/core/CoreController.h"
@ -22,7 +23,8 @@ void ObjectFactory::produce(void* args) {
HealthTableIF* healthTable = nullptr;
PusTmFunnel* pusFunnel = nullptr;
CfdpTmFunnel* cfdpFunnel = nullptr;
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel);
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
*SdCardManager::instance());
LinuxLibgpioIF* gpioComIF = nullptr;
SerialComIF* uartComIF = nullptr;

View File

@ -18,7 +18,8 @@ void ObjectFactory::produce(void* args) {
HealthTableIF* healthTable = nullptr;
PusTmFunnel* pusFunnel = nullptr;
CfdpTmFunnel* cfdpFunnel = nullptr;
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel);
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
*SdCardManager::instance());
LinuxLibgpioIF* gpioComIF = nullptr;
SerialComIF* uartComIF = nullptr;

View File

@ -410,9 +410,12 @@ ReturnValue_t SdCardManager::updateSdCardStateFile() {
return result;
}
const std::string& SdCardManager::getCurrentMountPrefix() const {
const char* SdCardManager::getCurrentMountPrefix() const {
MutexGuard mg(mutex);
return currentPrefix;
if (currentPrefix.has_value()) {
return currentPrefix.value().c_str();
}
return nullptr;
}
SdCardManager::OpStatus SdCardManager::checkCurrentOp(Operations& currentOp) {

View File

@ -187,7 +187,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
* @param prefSdCardPtr
* @return
*/
const std::string& getCurrentMountPrefix() const override;
const char* getCurrentMountPrefix() const override;
OpStatus checkCurrentOp(Operations& currentOp);
@ -232,7 +232,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
void processSdStatusLine(SdStatePair& active, std::string& line, uint8_t& idx,
sd::SdCard& currentSd);
std::string currentPrefix;
std::optional<std::string> currentPrefix;
static SdCardManager* INSTANCE;
};

View File

@ -3,6 +3,9 @@
std::filesystem::path fshelpers::getPrefixedPath(SdCardManager &man,
std::filesystem::path pathWihtoutPrefix) {
auto prefix = man.getCurrentMountPrefix();
if (prefix == nullptr) {
return pathWihtoutPrefix;
}
auto resPath = prefix / pathWihtoutPrefix;
return resPath;
}

View File

@ -61,8 +61,8 @@ static constexpr uint32_t SCHED_BLOCK_1_SUS_READ_MS = 15;
static constexpr uint32_t SCHED_BLOCK_2_SENSOR_READ_MS = 30;
static constexpr uint32_t SCHED_BLOCK_3_READ_IMTQ_MGM_MS = 42;
static constexpr uint32_t SCHED_BLOCK_4_ACS_CTRL_MS = 45;
static constexpr uint32_t SCHED_BLOCK_5_ACTUATOR_MS = 50;
static constexpr uint32_t SCHED_BLOCK_6_IMTQ_BLOCK_2_MS = 90;
static constexpr uint32_t SCHED_BLOCK_5_ACTUATOR_MS = 55;
static constexpr uint32_t SCHED_BLOCK_6_IMTQ_BLOCK_2_MS = 95;
static constexpr uint32_t SCHED_BLOCK_RTD = 150;
static constexpr uint32_t SCHED_BLOCK_7_RW_READ_MS = 300;

View File

@ -36,7 +36,8 @@ enum : uint8_t {
SCEX_HANDLER = 138,
CONFIGHANDLER = 139,
CORE = 140,
TCS_CONTROLLER = 141,
PERSISTENT_TM_STORE = 141,
TCS_CONTROLLER = 142,
COMMON_SUBSYSTEM_ID_END
};

View File

@ -152,6 +152,11 @@ enum commonObjects : uint32_t {
CFDP_TM_FUNNEL = 0x73000102,
CFDP_HANDLER = 0x73000205,
CFDP_DISTRIBUTOR = 0x73000206,
MISC_TM_STORE = 0x73020001,
OK_TM_STORE = 0x73020002,
NOT_OK_TM_STORE = 0x73020003,
HK_TM_STORE = 0x73020004,
CFDP_TM_STORE = 0x73030000,
// Other stuff
THERMAL_TEMP_INSERTER = 0x90000003,

View File

@ -35,14 +35,13 @@ enum commonClassIds : uint8_t {
SA_DEPL_HANDLER, // SADPL
MPSOC_RETURN_VALUES_IF, // MPSOCRTVIF
SUPV_RETURN_VALUES_IF, // SPVRTVIF
ACS_KALMAN, // ACSKAL
ACS_CTRL, // ACSCTRL
ACS_MEKF, // ACSMEKF
ACS_SAFE, // ACSSAF
ACS_PTG, // ACSPTG
ACS_DETUMBLE, // ACSDTB
ACS_MEKF, // ACSMEK
COMMON_CLASS_ID_END // [EXPORT] : [END]
};
}
#endif /* COMMON_CONFIG_COMMONCLASSIDS_H_ */

View File

@ -12,6 +12,7 @@ enum Ids {
PUS_SERVICE_8 = 8,
PUS_SERVICE_9 = 9,
PUS_SERVICE_11 = 11,
PUS_SERVICE_15 = 15,
PUS_SERVICE_17 = 17,
PUS_SERVICE_19 = 19,
PUS_SERVICE_20 = 20,

View File

@ -20,6 +20,7 @@ target_sources(
GyroL3GD20Dummy.cpp
MgmLIS3MDLDummy.cpp
PlPcduDummy.cpp
ExecutableComIfDummy.cpp
ScexDummy.cpp
CoreControllerDummy.cpp
PlocMpsocDummy.cpp

View File

@ -0,0 +1,27 @@
#include <dummies/ExecutableComIfDummy.h>
ExecutableComIfDummy::ExecutableComIfDummy(object_id_t objectId) : SystemObject(objectId) {}
ReturnValue_t ExecutableComIfDummy::initializeInterface(CookieIF *cookie) {
return returnvalue::OK;
}
ReturnValue_t ExecutableComIfDummy::sendMessage(CookieIF *cookie, const uint8_t *sendData,
size_t sendLen) {
return returnvalue::OK;
}
ReturnValue_t ExecutableComIfDummy::getSendSuccess(CookieIF *cookie) { return returnvalue::OK; }
ReturnValue_t ExecutableComIfDummy::requestReceiveMessage(CookieIF *cookie, size_t requestLen) {
return returnvalue::OK;
}
ReturnValue_t ExecutableComIfDummy::performOperation(uint8_t operationCode) {
return returnvalue::OK;
}
ReturnValue_t ExecutableComIfDummy::readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
size_t *size) {
return returnvalue::OK;
}

View File

@ -0,0 +1,21 @@
#ifndef DUMMIES_EXECUTABLECOMIFDUMMY_H_
#define DUMMIES_EXECUTABLECOMIFDUMMY_H_
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
class ExecutableComIfDummy : public ExecutableObjectIF,
public DeviceCommunicationIF,
public SystemObject {
public:
ExecutableComIfDummy(object_id_t objectId);
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
ReturnValue_t initializeInterface(CookieIF *cookie) override;
ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) override;
ReturnValue_t getSendSuccess(CookieIF *cookie) override;
ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) override;
ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) override;
};
#endif /* DUMMIES_EXECUTABLECOMIFDUMMY_H_ */

View File

@ -1,6 +1,7 @@
#include "GpsCtrlDummy.h"
GpsCtrlDummy::GpsCtrlDummy(object_id_t objectId) : ExtendedControllerBase(objectId, 20) {}
GpsCtrlDummy::GpsCtrlDummy(object_id_t objectId)
: ExtendedControllerBase(objectId, 20), gpsSet(this) {}
ReturnValue_t GpsCtrlDummy::handleCommandMessage(CommandMessage* message) {
return returnvalue::OK;
@ -13,9 +14,23 @@ ReturnValue_t GpsCtrlDummy::checkModeCommand(Mode_t mode, Submode_t submode,
return returnvalue::OK;
}
LocalPoolDataSetBase* GpsCtrlDummy::getDataSetHandle(sid_t sid) { return &gpsSet; }
ReturnValue_t GpsCtrlDummy::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
localDataPoolMap.emplace(GpsHyperion::ALTITUDE, new PoolEntry<double>({537222.3469}, true));
localDataPoolMap.emplace(GpsHyperion::LONGITUDE, new PoolEntry<double>({-8.8579}, true));
localDataPoolMap.emplace(GpsHyperion::LATITUDE, new PoolEntry<double>({49.5952}, true));
localDataPoolMap.emplace(GpsHyperion::SPEED, new PoolEntry<double>({0}));
localDataPoolMap.emplace(GpsHyperion::YEAR, new PoolEntry<uint16_t>({2023}, true));
localDataPoolMap.emplace(GpsHyperion::MONTH, new PoolEntry<uint8_t>({5}, true));
localDataPoolMap.emplace(GpsHyperion::DAY, new PoolEntry<uint8_t>({16}, true));
localDataPoolMap.emplace(GpsHyperion::HOURS, new PoolEntry<uint8_t>({1}, true));
localDataPoolMap.emplace(GpsHyperion::MINUTES, new PoolEntry<uint8_t>({0}, true));
localDataPoolMap.emplace(GpsHyperion::SECONDS, new PoolEntry<uint8_t>({0}, true));
localDataPoolMap.emplace(GpsHyperion::UNIX_SECONDS, new PoolEntry<uint32_t>({1684191600}, true));
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
return returnvalue::OK;
}
LocalPoolDataSetBase* GpsCtrlDummy::getDataSetHandle(sid_t sid) { return nullptr; }

View File

@ -2,12 +2,15 @@
#define DUMMIES_GPSCTRLDUMMY_H_
#include <fsfw/controller/ExtendedControllerBase.h>
#include <mission/devices/devicedefinitions/GPSDefinitions.h>
class GpsCtrlDummy : public ExtendedControllerBase {
public:
GpsCtrlDummy(object_id_t objectId);
private:
GpsPrimaryDataset gpsSet;
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
void performControlOperation() override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,

View File

@ -3,7 +3,8 @@
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
PduDummy::PduDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie) {}
: DeviceHandlerBase(objectId, comif, comCookie),
coreHk(this, static_cast<uint32_t>(P60System::SetIds::CORE)) {}
PduDummy::~PduDummy() {}
@ -38,5 +39,7 @@ uint32_t PduDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return
ReturnValue_t PduDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(PDU::pool::PDU_TEMPERATURE, new PoolEntry<float>({0}));
localDataPoolMap.emplace(PDU::pool::PDU_VOLTAGES, &pduVoltages);
localDataPoolMap.emplace(PDU::pool::PDU_CURRENTS, &pduCurrents);
return returnvalue::OK;
}

View File

@ -3,6 +3,8 @@
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include "mission/devices/devicedefinitions/GomspaceDefinitions.h"
class PduDummy : public DeviceHandlerBase {
public:
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
@ -15,6 +17,10 @@ class PduDummy : public DeviceHandlerBase {
virtual ~PduDummy();
protected:
PDU::PduCoreHk coreHk;
PoolEntry<int16_t> pduVoltages = PoolEntry<int16_t>(9);
PoolEntry<int16_t> pduCurrents = PoolEntry<int16_t>(9);
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;

View File

@ -41,7 +41,7 @@ ReturnValue_t RwDummy::initializeLocalDataPool(localpool::DataPool &localDataPoo
localDataPoolMap.emplace(rws::CURR_SPEED, new PoolEntry<int32_t>({0}));
localDataPoolMap.emplace(rws::REFERENCE_SPEED, new PoolEntry<int32_t>({0}));
localDataPoolMap.emplace(rws::STATE, new PoolEntry<uint8_t>({0}));
localDataPoolMap.emplace(rws::STATE, new PoolEntry<uint8_t>({1}, true));
localDataPoolMap.emplace(rws::CLC_MODE, new PoolEntry<uint8_t>({0}));
localDataPoolMap.emplace(rws::LAST_RESET_STATUS, new PoolEntry<uint8_t>({0}));

View File

@ -37,7 +37,7 @@ ReturnValue_t SusDummy::initializeLocalDataPool(localpool::DataPool &localDataPo
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(SUS::SusPoolIds::TEMPERATURE_C, new PoolEntry<float>({0}, 1, true));
localDataPoolMap.emplace(SUS::SusPoolIds::CHANNEL_VEC,
new PoolEntry<uint16_t>({0, 0, 0, 0, 0, 0}, true));
new PoolEntry<uint16_t>({2603, 781, 2760, 2048, 4056, 0}, true));
return returnvalue::OK;
}

View File

@ -5,6 +5,7 @@
#include <dummies/ComCookieDummy.h>
#include <dummies/ComIFDummy.h>
#include <dummies/CoreControllerDummy.h>
#include <dummies/ExecutableComIfDummy.h>
#include <dummies/GpsCtrlDummy.h>
#include <dummies/GpsDhbDummy.h>
#include <dummies/GyroAdisDummy.h>
@ -45,7 +46,7 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
new CoreControllerDummy(objects::CORE_CONTROLLER);
}
if (cfg.addRtdComIFDummy) {
new ComIFDummy(objects::SPI_RTD_COM_IF);
new ExecutableComIfDummy(objects::SPI_RTD_COM_IF);
}
std::array<object_id_t, 4> rwIds = {objects::RW1, objects::RW2, objects::RW3, objects::RW4};
std::array<DeviceHandlerBase*, 4> rws;

2
fsfw

@ -1 +1 @@
Subproject commit bd208038dd85a94dce8c763397ad5ac7eae76402
Subproject commit bdfe31dba48039b60fe700e7d03bfb95e9549688

View File

@ -1,2 +1,4 @@
.~lock*
/venv
/.idea/*
!/.idea/runConfigurations

View File

@ -84,6 +84,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
10800;0x2a30;STORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
10801;0x2a31;MSG_QUEUE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
10802;0x2a32;SERIALIZATION_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
10803;0x2a33;FILESTORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
10804;0x2a34;FILENAME_TOO_LARGE_ERROR;LOW;P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name;fsfw/src/fsfw/cfdp/handler/defs.h
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;No description;mission/acsDefs.h
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;No description;mission/acsDefs.h
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;No description;mission/acsDefs.h
@ -252,10 +254,11 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;bsp_q7s/core/CoreController.h
14005;0x36b5;VERSION_INFO;INFO;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.;bsp_q7s/core/CoreController.h
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14103;0x3717;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14105;0x3719;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14106;0x371a;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14100;0x3714;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/tmtc/PersistentTmStore.h
14200;0x3778;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h
14201;0x3779;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h
14202;0x377a;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14203;0x377b;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14204;0x377c;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14205;0x377d;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14206;0x377e;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
84 10800 0x2a30 STORE_ERROR LOW No description fsfw/src/fsfw/cfdp/handler/defs.h
85 10801 0x2a31 MSG_QUEUE_ERROR LOW No description fsfw/src/fsfw/cfdp/handler/defs.h
86 10802 0x2a32 SERIALIZATION_ERROR LOW No description fsfw/src/fsfw/cfdp/handler/defs.h
87 10803 0x2a33 FILESTORE_ERROR LOW No description fsfw/src/fsfw/cfdp/handler/defs.h
88 10804 0x2a34 FILENAME_TOO_LARGE_ERROR LOW P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name fsfw/src/fsfw/cfdp/handler/defs.h
89 11200 0x2bc0 SAFE_RATE_VIOLATION MEDIUM No description mission/acsDefs.h
90 11201 0x2bc1 SAFE_RATE_RECOVERY MEDIUM No description mission/acsDefs.h
91 11202 0x2bc2 MULTIPLE_RW_INVALID HIGH No description mission/acsDefs.h
254 14004 0x36b4 NO_SD_CARD_ACTIVE HIGH No SD card was active. Core controller will attempt to re-initialize a SD card. bsp_q7s/core/CoreController.h
255 14005 0x36b5 VERSION_INFO INFO 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. bsp_q7s/core/CoreController.h
256 14006 0x36b6 CURRENT_IMAGE_INFO INFO P1: Current Chip, P2: Current Copy bsp_q7s/core/CoreController.h
257 14100 0x3714 NO_VALID_SENSOR_TEMPERATURE POSSIBLE_FILE_CORRUPTION MEDIUM LOW No description P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp. mission/controller/ThermalController.h mission/tmtc/PersistentTmStore.h
258 14101 14200 0x3715 0x3778 NO_HEALTHY_HEATER_AVAILABLE NO_VALID_SENSOR_TEMPERATURE MEDIUM No description mission/controller/ThermalController.h
259 14102 14201 0x3716 0x3779 SYRLINKS_OVERHEATING NO_HEALTHY_HEATER_AVAILABLE HIGH MEDIUM No description mission/controller/ThermalController.h
260 14103 14202 0x3717 0x377a PLOC_OVERHEATING SYRLINKS_OVERHEATING HIGH No description mission/controller/ThermalController.h
261 14104 14203 0x3718 0x377b OBC_OVERHEATING PLOC_OVERHEATING HIGH No description mission/controller/ThermalController.h
262 14105 14204 0x3719 0x377c HPA_OVERHEATING OBC_OVERHEATING HIGH No description mission/controller/ThermalController.h
263 14106 14205 0x371a 0x377d PLPCDU_OVERHEATING HPA_OVERHEATING HIGH No description mission/controller/ThermalController.h
264 14206 0x377e PLPCDU_OVERHEATING HIGH No description mission/controller/ThermalController.h

View File

@ -104,6 +104,7 @@
0x53000008;PUS_SERVICE_8_FUNCTION_MGMT
0x53000009;PUS_SERVICE_9_TIME_MGMT
0x53000011;PUS_SERVICE_11_TC_SCHEDULER
0x53000015;PUS_SERVICE_15_TM_STORAGE
0x53000017;PUS_SERVICE_17_TEST
0x53000020;PUS_SERVICE_20_PARAMETERS
0x53000200;PUS_SERVICE_200_MODE_MGMT
@ -142,6 +143,11 @@
0x73010002;PL_SUBSYSTEM
0x73010003;TCS_SUBSYSTEM
0x73010004;COM_SUBSYSTEM
0x73020001;MISC_TM_STORE
0x73020002;OK_TM_STORE
0x73020003;NOT_OK_TM_STORE
0x73020004;HK_TM_STORE
0x73030000;CFDP_TM_STORE
0x73500000;CCSDS_IP_CORE_BRIDGE
0x90000003;THERMAL_TEMP_INSERTER
0xCAFECAFE;DUMMY_INTERFACE

1 0x42694269 TEST_TASK
104 0x53000008 PUS_SERVICE_8_FUNCTION_MGMT
105 0x53000009 PUS_SERVICE_9_TIME_MGMT
106 0x53000011 PUS_SERVICE_11_TC_SCHEDULER
107 0x53000015 PUS_SERVICE_15_TM_STORAGE
108 0x53000017 PUS_SERVICE_17_TEST
109 0x53000020 PUS_SERVICE_20_PARAMETERS
110 0x53000200 PUS_SERVICE_200_MODE_MGMT
143 0x73010002 PL_SUBSYSTEM
144 0x73010003 TCS_SUBSYSTEM
145 0x73010004 COM_SUBSYSTEM
146 0x73020001 MISC_TM_STORE
147 0x73020002 OK_TM_STORE
148 0x73020003 NOT_OK_TM_STORE
149 0x73020004 HK_TM_STORE
150 0x73030000 CFDP_TM_STORE
151 0x73500000 CCSDS_IP_CORE_BRIDGE
152 0x90000003 THERMAL_TEMP_INSERTER
153 0xCAFECAFE DUMMY_INTERFACE

View File

@ -49,16 +49,17 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
0x4fa4;HEATER_MainSwitchSetTimeout;No description;164;HEATER_HANDLER;mission/devices/HeaterHandler.h
0x4fa5;HEATER_CommandAlreadyWaiting;No description;165;HEATER_HANDLER;mission/devices/HeaterHandler.h
0x60a0;CCSDS_CommandNotImplemented;Received action message with unknown action id;160;CCSDS_HANDLER;mission/tmtc/CcsdsIpCoreHandler.h
0x6a01;ACSSAF_SafectrlMekfInputInvalid;No description;1;ACS_SAFE;mission/controller/acs/control/SafeCtrl.h
0x6b01;ACSPTG_PtgctrlMekfInputInvalid;No description;1;ACS_PTG;mission/controller/acs/control/PtgCtrl.h
0x6c01;ACSDTB_DetumbleNoSensordata;No description;1;ACS_DETUMBLE;mission/controller/acs/control/Detumble.h
0x6902;ACSKAL_KalmanUninitialized;No description;2;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6903;ACSKAL_KalmanNoGyrData;No description;3;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6904;ACSKAL_KalmanNoModelVectors;No description;4;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6905;ACSKAL_KalmanNoSusMgmStrData;No description;5;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6906;ACSKAL_KalmanCovarianceInversionFailed;No description;6;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6907;ACSKAL_KalmanInitialized;No description;7;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6908;ACSKAL_KalmanRunning;No description;8;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6b01;ACSSAF_SafectrlMekfInputInvalid;No description;1;ACS_SAFE;mission/controller/acs/control/SafeCtrl.h
0x6c01;ACSPTG_PtgctrlMekfInputInvalid;No description;1;ACS_PTG;mission/controller/acs/control/PtgCtrl.h
0x6d01;ACSDTB_DetumbleNoSensordata;No description;1;ACS_DETUMBLE;mission/controller/acs/control/Detumble.h
0x6a02;ACSMEKF_MekfUninitialized;No description;2;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a03;ACSMEKF_MekfNoGyrData;No description;3;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a04;ACSMEKF_MekfNoModelVectors;No description;4;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a05;ACSMEKF_MekfNoSusMgmStrData;No description;5;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a06;ACSMEKF_MekfCovarianceInversionFailed;No description;6;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a07;ACSMEKF_MekfInitialized;No description;7;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a08;ACSMEKF_MekfRunning;No description;8;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6900;ACSCTRL_FileDeletionFailed;No description;0;ACS_CTRL;mission/controller/AcsController.h
0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h

1 Full ID (hex) Name Description Unique ID Subsytem Name File Path
49 0x4fa4 HEATER_MainSwitchSetTimeout No description 164 HEATER_HANDLER mission/devices/HeaterHandler.h
50 0x4fa5 HEATER_CommandAlreadyWaiting No description 165 HEATER_HANDLER mission/devices/HeaterHandler.h
51 0x60a0 CCSDS_CommandNotImplemented Received action message with unknown action id 160 CCSDS_HANDLER mission/tmtc/CcsdsIpCoreHandler.h
52 0x6a01 0x6b01 ACSSAF_SafectrlMekfInputInvalid No description 1 ACS_SAFE mission/controller/acs/control/SafeCtrl.h
53 0x6b01 0x6c01 ACSPTG_PtgctrlMekfInputInvalid No description 1 ACS_PTG mission/controller/acs/control/PtgCtrl.h
54 0x6c01 0x6d01 ACSDTB_DetumbleNoSensordata No description 1 ACS_DETUMBLE mission/controller/acs/control/Detumble.h
55 0x6902 0x6a02 ACSKAL_KalmanUninitialized ACSMEKF_MekfUninitialized No description 2 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
56 0x6903 0x6a03 ACSKAL_KalmanNoGyrData ACSMEKF_MekfNoGyrData No description 3 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
57 0x6904 0x6a04 ACSKAL_KalmanNoModelVectors ACSMEKF_MekfNoModelVectors No description 4 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
58 0x6905 0x6a05 ACSKAL_KalmanNoSusMgmStrData ACSMEKF_MekfNoSusMgmStrData No description 5 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
59 0x6906 0x6a06 ACSKAL_KalmanCovarianceInversionFailed ACSMEKF_MekfCovarianceInversionFailed No description 6 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
60 0x6907 0x6a07 ACSKAL_KalmanInitialized ACSMEKF_MekfInitialized No description 7 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
61 0x6908 0x6a08 ACSKAL_KalmanRunning ACSMEKF_MekfRunning No description 8 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
62 0x6900 ACSCTRL_FileDeletionFailed No description 0 ACS_CTRL mission/controller/AcsController.h
63 0x4500 HSPI_OpeningFileFailed No description 0 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
64 0x4501 HSPI_FullDuplexTransferFailed No description 1 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
65 0x4502 HSPI_HalfDuplexTransferFailed No description 2 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h

View File

@ -84,6 +84,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
10800;0x2a30;STORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
10801;0x2a31;MSG_QUEUE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
10802;0x2a32;SERIALIZATION_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
10803;0x2a33;FILESTORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
10804;0x2a34;FILENAME_TOO_LARGE_ERROR;LOW;P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name;fsfw/src/fsfw/cfdp/handler/defs.h
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;No description;mission/acsDefs.h
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;No description;mission/acsDefs.h
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;No description;mission/acsDefs.h
@ -252,10 +254,11 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;bsp_q7s/core/CoreController.h
14005;0x36b5;VERSION_INFO;INFO;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.;bsp_q7s/core/CoreController.h
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14103;0x3717;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14105;0x3719;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14106;0x371a;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14100;0x3714;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/tmtc/PersistentTmStore.h
14200;0x3778;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h
14201;0x3779;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h
14202;0x377a;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14203;0x377b;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14204;0x377c;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14205;0x377d;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
14206;0x377e;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
84 10800 0x2a30 STORE_ERROR LOW No description fsfw/src/fsfw/cfdp/handler/defs.h
85 10801 0x2a31 MSG_QUEUE_ERROR LOW No description fsfw/src/fsfw/cfdp/handler/defs.h
86 10802 0x2a32 SERIALIZATION_ERROR LOW No description fsfw/src/fsfw/cfdp/handler/defs.h
87 10803 0x2a33 FILESTORE_ERROR LOW No description fsfw/src/fsfw/cfdp/handler/defs.h
88 10804 0x2a34 FILENAME_TOO_LARGE_ERROR LOW P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name fsfw/src/fsfw/cfdp/handler/defs.h
89 11200 0x2bc0 SAFE_RATE_VIOLATION MEDIUM No description mission/acsDefs.h
90 11201 0x2bc1 SAFE_RATE_RECOVERY MEDIUM No description mission/acsDefs.h
91 11202 0x2bc2 MULTIPLE_RW_INVALID HIGH No description mission/acsDefs.h
254 14004 0x36b4 NO_SD_CARD_ACTIVE HIGH No SD card was active. Core controller will attempt to re-initialize a SD card. bsp_q7s/core/CoreController.h
255 14005 0x36b5 VERSION_INFO INFO 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. bsp_q7s/core/CoreController.h
256 14006 0x36b6 CURRENT_IMAGE_INFO INFO P1: Current Chip, P2: Current Copy bsp_q7s/core/CoreController.h
257 14100 0x3714 NO_VALID_SENSOR_TEMPERATURE POSSIBLE_FILE_CORRUPTION MEDIUM LOW No description P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp. mission/controller/ThermalController.h mission/tmtc/PersistentTmStore.h
258 14101 14200 0x3715 0x3778 NO_HEALTHY_HEATER_AVAILABLE NO_VALID_SENSOR_TEMPERATURE MEDIUM No description mission/controller/ThermalController.h
259 14102 14201 0x3716 0x3779 SYRLINKS_OVERHEATING NO_HEALTHY_HEATER_AVAILABLE HIGH MEDIUM No description mission/controller/ThermalController.h
260 14103 14202 0x3717 0x377a PLOC_OVERHEATING SYRLINKS_OVERHEATING HIGH No description mission/controller/ThermalController.h
261 14104 14203 0x3718 0x377b OBC_OVERHEATING PLOC_OVERHEATING HIGH No description mission/controller/ThermalController.h
262 14105 14204 0x3719 0x377c HPA_OVERHEATING OBC_OVERHEATING HIGH No description mission/controller/ThermalController.h
263 14106 14205 0x371a 0x377d PLPCDU_OVERHEATING HPA_OVERHEATING HIGH No description mission/controller/ThermalController.h
264 14206 0x377e PLPCDU_OVERHEATING HIGH No description mission/controller/ThermalController.h

View File

@ -102,6 +102,7 @@
0x53000008;PUS_SERVICE_8_FUNCTION_MGMT
0x53000009;PUS_SERVICE_9_TIME_MGMT
0x53000011;PUS_SERVICE_11_TC_SCHEDULER
0x53000015;PUS_SERVICE_15_TM_STORAGE
0x53000017;PUS_SERVICE_17_TEST
0x53000020;PUS_SERVICE_20_PARAMETERS
0x53000200;PUS_SERVICE_200_MODE_MGMT
@ -148,6 +149,11 @@
0x73010002;PL_SUBSYSTEM
0x73010003;TCS_SUBSYSTEM
0x73010004;COM_SUBSYSTEM
0x73020001;MISC_TM_STORE
0x73020002;OK_TM_STORE
0x73020003;NOT_OK_TM_STORE
0x73020004;HK_TM_STORE
0x73030000;CFDP_TM_STORE
0x73500000;CCSDS_IP_CORE_BRIDGE
0x90000003;THERMAL_TEMP_INSERTER
0xFFFFFFFF;NO_OBJECT

1 0x00005060 P60DOCK_TEST_TASK
102 0x53000008 PUS_SERVICE_8_FUNCTION_MGMT
103 0x53000009 PUS_SERVICE_9_TIME_MGMT
104 0x53000011 PUS_SERVICE_11_TC_SCHEDULER
105 0x53000015 PUS_SERVICE_15_TM_STORAGE
106 0x53000017 PUS_SERVICE_17_TEST
107 0x53000020 PUS_SERVICE_20_PARAMETERS
108 0x53000200 PUS_SERVICE_200_MODE_MGMT
149 0x73010002 PL_SUBSYSTEM
150 0x73010003 TCS_SUBSYSTEM
151 0x73010004 COM_SUBSYSTEM
152 0x73020001 MISC_TM_STORE
153 0x73020002 OK_TM_STORE
154 0x73020003 NOT_OK_TM_STORE
155 0x73020004 HK_TM_STORE
156 0x73030000 CFDP_TM_STORE
157 0x73500000 CCSDS_IP_CORE_BRIDGE
158 0x90000003 THERMAL_TEMP_INSERTER
159 0xFFFFFFFF NO_OBJECT

View File

@ -49,16 +49,17 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
0x4fa4;HEATER_MainSwitchSetTimeout;No description;164;HEATER_HANDLER;mission/devices/HeaterHandler.h
0x4fa5;HEATER_CommandAlreadyWaiting;No description;165;HEATER_HANDLER;mission/devices/HeaterHandler.h
0x60a0;CCSDS_CommandNotImplemented;Received action message with unknown action id;160;CCSDS_HANDLER;mission/tmtc/CcsdsIpCoreHandler.h
0x6a01;ACSSAF_SafectrlMekfInputInvalid;No description;1;ACS_SAFE;mission/controller/acs/control/SafeCtrl.h
0x6b01;ACSPTG_PtgctrlMekfInputInvalid;No description;1;ACS_PTG;mission/controller/acs/control/PtgCtrl.h
0x6c01;ACSDTB_DetumbleNoSensordata;No description;1;ACS_DETUMBLE;mission/controller/acs/control/Detumble.h
0x6902;ACSKAL_KalmanUninitialized;No description;2;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6903;ACSKAL_KalmanNoGyrData;No description;3;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6904;ACSKAL_KalmanNoModelVectors;No description;4;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6905;ACSKAL_KalmanNoSusMgmStrData;No description;5;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6906;ACSKAL_KalmanCovarianceInversionFailed;No description;6;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6907;ACSKAL_KalmanInitialized;No description;7;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6908;ACSKAL_KalmanRunning;No description;8;ACS_KALMAN;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6b01;ACSSAF_SafectrlMekfInputInvalid;No description;1;ACS_SAFE;mission/controller/acs/control/SafeCtrl.h
0x6c01;ACSPTG_PtgctrlMekfInputInvalid;No description;1;ACS_PTG;mission/controller/acs/control/PtgCtrl.h
0x6d01;ACSDTB_DetumbleNoSensordata;No description;1;ACS_DETUMBLE;mission/controller/acs/control/Detumble.h
0x6a02;ACSMEKF_MekfUninitialized;No description;2;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a03;ACSMEKF_MekfNoGyrData;No description;3;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a04;ACSMEKF_MekfNoModelVectors;No description;4;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a05;ACSMEKF_MekfNoSusMgmStrData;No description;5;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a06;ACSMEKF_MekfCovarianceInversionFailed;No description;6;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a07;ACSMEKF_MekfInitialized;No description;7;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6a08;ACSMEKF_MekfRunning;No description;8;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
0x6900;ACSCTRL_FileDeletionFailed;No description;0;ACS_CTRL;mission/controller/AcsController.h
0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h

1 Full ID (hex) Name Description Unique ID Subsytem Name File Path
49 0x4fa4 HEATER_MainSwitchSetTimeout No description 164 HEATER_HANDLER mission/devices/HeaterHandler.h
50 0x4fa5 HEATER_CommandAlreadyWaiting No description 165 HEATER_HANDLER mission/devices/HeaterHandler.h
51 0x60a0 CCSDS_CommandNotImplemented Received action message with unknown action id 160 CCSDS_HANDLER mission/tmtc/CcsdsIpCoreHandler.h
52 0x6a01 0x6b01 ACSSAF_SafectrlMekfInputInvalid No description 1 ACS_SAFE mission/controller/acs/control/SafeCtrl.h
53 0x6b01 0x6c01 ACSPTG_PtgctrlMekfInputInvalid No description 1 ACS_PTG mission/controller/acs/control/PtgCtrl.h
54 0x6c01 0x6d01 ACSDTB_DetumbleNoSensordata No description 1 ACS_DETUMBLE mission/controller/acs/control/Detumble.h
55 0x6902 0x6a02 ACSKAL_KalmanUninitialized ACSMEKF_MekfUninitialized No description 2 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
56 0x6903 0x6a03 ACSKAL_KalmanNoGyrData ACSMEKF_MekfNoGyrData No description 3 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
57 0x6904 0x6a04 ACSKAL_KalmanNoModelVectors ACSMEKF_MekfNoModelVectors No description 4 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
58 0x6905 0x6a05 ACSKAL_KalmanNoSusMgmStrData ACSMEKF_MekfNoSusMgmStrData No description 5 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
59 0x6906 0x6a06 ACSKAL_KalmanCovarianceInversionFailed ACSMEKF_MekfCovarianceInversionFailed No description 6 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
60 0x6907 0x6a07 ACSKAL_KalmanInitialized ACSMEKF_MekfInitialized No description 7 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
61 0x6908 0x6a08 ACSKAL_KalmanRunning ACSMEKF_MekfRunning No description 8 ACS_KALMAN ACS_MEKF mission/controller/acs/MultiplicativeKalmanFilter.h
62 0x6900 ACSCTRL_FileDeletionFailed No description 0 ACS_CTRL mission/controller/AcsController.h
63 0x4500 HSPI_OpeningFileFailed No description 0 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
64 0x4501 HSPI_FullDuplexTransferFailed No description 1 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h
65 0x4502 HSPI_HalfDuplexTransferFailed No description 2 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 260 translations.
* @brief Auto-generated event translation file. Contains 263 translations.
* @details
* Generated on: 2023-02-23 15:39:20
* Generated on: 2023-02-24 16:57:00
*/
#include "translateEvents.h"
@ -90,6 +90,8 @@ const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER";
const char *STORE_ERROR_STRING = "STORE_ERROR";
const char *MSG_QUEUE_ERROR_STRING = "MSG_QUEUE_ERROR";
const char *SERIALIZATION_ERROR_STRING = "SERIALIZATION_ERROR";
const char *FILESTORE_ERROR_STRING = "FILESTORE_ERROR";
const char *FILENAME_TOO_LARGE_ERROR_STRING = "FILENAME_TOO_LARGE_ERROR";
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
@ -253,6 +255,7 @@ const char *REBOOT_HW_STRING = "REBOOT_HW";
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
const char *VERSION_INFO_STRING = "VERSION_INFO";
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -433,6 +436,10 @@ const char *translateEvents(Event event) {
return MSG_QUEUE_ERROR_STRING;
case (10802):
return SERIALIZATION_ERROR_STRING;
case (10803):
return FILESTORE_ERROR_STRING;
case (10804):
return FILENAME_TOO_LARGE_ERROR_STRING;
case (11200):
return SAFE_RATE_VIOLATION_STRING;
case (11201):
@ -760,18 +767,20 @@ const char *translateEvents(Event event) {
case (14006):
return CURRENT_IMAGE_INFO_STRING;
case (14100):
return POSSIBLE_FILE_CORRUPTION_STRING;
case (14200):
return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101):
case (14201):
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
case (14102):
case (14202):
return SYRLINKS_OVERHEATING_STRING;
case (14103):
case (14203):
return PLOC_OVERHEATING_STRING;
case (14104):
case (14204):
return OBC_OVERHEATING_STRING;
case (14105):
case (14205):
return HPA_OVERHEATING_STRING;
case (14106):
case (14206):
return PLPCDU_OVERHEATING_STRING;
default:
return "UNKNOWN_EVENT";

View File

@ -1,8 +1,8 @@
/**
* @brief Auto-generated object translation file.
* @details
* Contains 153 translations.
* Generated on: 2023-02-23 15:39:20
* Contains 159 translations.
* Generated on: 2023-02-24 16:57:00
*/
#include "translateObjects.h"
@ -110,6 +110,7 @@ const char *PUS_SERVICE_5_EVENT_REPORTING_STRING = "PUS_SERVICE_5_EVENT_REPORTIN
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
const char *PUS_SERVICE_15_TM_STORAGE_STRING = "PUS_SERVICE_15_TM_STORAGE";
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
@ -156,6 +157,11 @@ const char *ACS_SUBSYSTEM_STRING = "ACS_SUBSYSTEM";
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
const char *MISC_TM_STORE_STRING = "MISC_TM_STORE";
const char *OK_TM_STORE_STRING = "OK_TM_STORE";
const char *NOT_OK_TM_STORE_STRING = "NOT_OK_TM_STORE";
const char *HK_TM_STORE_STRING = "HK_TM_STORE";
const char *CFDP_TM_STORE_STRING = "CFDP_TM_STORE";
const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE";
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
const char *NO_OBJECT_STRING = "NO_OBJECT";
@ -370,6 +376,8 @@ const char *translateObject(object_id_t object) {
return PUS_SERVICE_9_TIME_MGMT_STRING;
case 0x53000011:
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
case 0x53000015:
return PUS_SERVICE_15_TM_STORAGE_STRING;
case 0x53000017:
return PUS_SERVICE_17_TEST_STRING;
case 0x53000020:
@ -462,6 +470,16 @@ const char *translateObject(object_id_t object) {
return TCS_SUBSYSTEM_STRING;
case 0x73010004:
return COM_SUBSYSTEM_STRING;
case 0x73020001:
return MISC_TM_STORE_STRING;
case 0x73020002:
return OK_TM_STORE_STRING;
case 0x73020003:
return NOT_OK_TM_STORE_STRING;
case 0x73020004:
return HK_TM_STORE_STRING;
case 0x73030000:
return CFDP_TM_STORE_STRING;
case 0x73500000:
return CCSDS_IP_CORE_BRIDGE_STRING;
case 0x90000003:

View File

@ -1742,18 +1742,21 @@ ReturnValue_t PlocSupervisorHandler::createMramDumpFile() {
std::string filename = "mram-dump--" + timeStamp + ".bin";
#ifdef XIPHOS_Q7S
std::string currentMountPrefix = sdcMan->getCurrentMountPrefix();
const char* currentMountPrefix = sdcMan->getCurrentMountPrefix();
#else
std::string currentMountPrefix("/mnt/sd0");
const char* currentMountPrefix = "/mnt/sd0";
#endif /* BOARD_TE0720 == 0 */
if (currentMountPrefix == nullptr) {
return returnvalue::FAILED;
}
// Check if path to PLOC directory exists
if (not std::filesystem::exists(std::string(currentMountPrefix + "/" + supervisorFilePath))) {
if (not std::filesystem::exists(std::string(currentMountPrefix) + "/" + supervisorFilePath)) {
sif::warning << "PlocSupervisorHandler::createMramDumpFile: Supervisor path does not exist"
<< std::endl;
return result::PATH_DOES_NOT_EXIST;
}
activeMramFile = currentMountPrefix + "/" + supervisorFilePath + "/" + filename;
activeMramFile = std::string(currentMountPrefix) + "/" + supervisorFilePath + "/" + filename;
// Create new file
std::ofstream file(activeMramFile, std::ios_base::out);
file.close();

View File

@ -42,7 +42,7 @@
//! When using the newlib nano library, C99 support for stdio facilities
//! will not be provided. This define should be set to 1 if this is the case.
#define FSFW_NO_C99_IO 1
#define FSFW_NO_C99_IO 0
//! Specify whether a special mode store is used for Subsystem components.
#define FSFW_USE_MODESTORE 0

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 260 translations.
* @brief Auto-generated event translation file. Contains 263 translations.
* @details
* Generated on: 2023-02-23 15:39:20
* Generated on: 2023-02-24 16:57:00
*/
#include "translateEvents.h"
@ -90,6 +90,8 @@ const char *CHANGE_OF_SETUP_PARAMETER_STRING = "CHANGE_OF_SETUP_PARAMETER";
const char *STORE_ERROR_STRING = "STORE_ERROR";
const char *MSG_QUEUE_ERROR_STRING = "MSG_QUEUE_ERROR";
const char *SERIALIZATION_ERROR_STRING = "SERIALIZATION_ERROR";
const char *FILESTORE_ERROR_STRING = "FILESTORE_ERROR";
const char *FILENAME_TOO_LARGE_ERROR_STRING = "FILENAME_TOO_LARGE_ERROR";
const char *SAFE_RATE_VIOLATION_STRING = "SAFE_RATE_VIOLATION";
const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
@ -253,6 +255,7 @@ const char *REBOOT_HW_STRING = "REBOOT_HW";
const char *NO_SD_CARD_ACTIVE_STRING = "NO_SD_CARD_ACTIVE";
const char *VERSION_INFO_STRING = "VERSION_INFO";
const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -433,6 +436,10 @@ const char *translateEvents(Event event) {
return MSG_QUEUE_ERROR_STRING;
case (10802):
return SERIALIZATION_ERROR_STRING;
case (10803):
return FILESTORE_ERROR_STRING;
case (10804):
return FILENAME_TOO_LARGE_ERROR_STRING;
case (11200):
return SAFE_RATE_VIOLATION_STRING;
case (11201):
@ -760,18 +767,20 @@ const char *translateEvents(Event event) {
case (14006):
return CURRENT_IMAGE_INFO_STRING;
case (14100):
return POSSIBLE_FILE_CORRUPTION_STRING;
case (14200):
return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101):
case (14201):
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
case (14102):
case (14202):
return SYRLINKS_OVERHEATING_STRING;
case (14103):
case (14203):
return PLOC_OVERHEATING_STRING;
case (14104):
case (14204):
return OBC_OVERHEATING_STRING;
case (14105):
case (14205):
return HPA_OVERHEATING_STRING;
case (14106):
case (14206):
return PLPCDU_OVERHEATING_STRING;
default:
return "UNKNOWN_EVENT";

View File

@ -1,8 +1,8 @@
/**
* @brief Auto-generated object translation file.
* @details
* Contains 153 translations.
* Generated on: 2023-02-23 15:39:20
* Contains 159 translations.
* Generated on: 2023-02-24 16:57:00
*/
#include "translateObjects.h"
@ -110,6 +110,7 @@ const char *PUS_SERVICE_5_EVENT_REPORTING_STRING = "PUS_SERVICE_5_EVENT_REPORTIN
const char *PUS_SERVICE_8_FUNCTION_MGMT_STRING = "PUS_SERVICE_8_FUNCTION_MGMT";
const char *PUS_SERVICE_9_TIME_MGMT_STRING = "PUS_SERVICE_9_TIME_MGMT";
const char *PUS_SERVICE_11_TC_SCHEDULER_STRING = "PUS_SERVICE_11_TC_SCHEDULER";
const char *PUS_SERVICE_15_TM_STORAGE_STRING = "PUS_SERVICE_15_TM_STORAGE";
const char *PUS_SERVICE_17_TEST_STRING = "PUS_SERVICE_17_TEST";
const char *PUS_SERVICE_20_PARAMETERS_STRING = "PUS_SERVICE_20_PARAMETERS";
const char *PUS_SERVICE_200_MODE_MGMT_STRING = "PUS_SERVICE_200_MODE_MGMT";
@ -156,6 +157,11 @@ const char *ACS_SUBSYSTEM_STRING = "ACS_SUBSYSTEM";
const char *PL_SUBSYSTEM_STRING = "PL_SUBSYSTEM";
const char *TCS_SUBSYSTEM_STRING = "TCS_SUBSYSTEM";
const char *COM_SUBSYSTEM_STRING = "COM_SUBSYSTEM";
const char *MISC_TM_STORE_STRING = "MISC_TM_STORE";
const char *OK_TM_STORE_STRING = "OK_TM_STORE";
const char *NOT_OK_TM_STORE_STRING = "NOT_OK_TM_STORE";
const char *HK_TM_STORE_STRING = "HK_TM_STORE";
const char *CFDP_TM_STORE_STRING = "CFDP_TM_STORE";
const char *CCSDS_IP_CORE_BRIDGE_STRING = "CCSDS_IP_CORE_BRIDGE";
const char *THERMAL_TEMP_INSERTER_STRING = "THERMAL_TEMP_INSERTER";
const char *NO_OBJECT_STRING = "NO_OBJECT";
@ -370,6 +376,8 @@ const char *translateObject(object_id_t object) {
return PUS_SERVICE_9_TIME_MGMT_STRING;
case 0x53000011:
return PUS_SERVICE_11_TC_SCHEDULER_STRING;
case 0x53000015:
return PUS_SERVICE_15_TM_STORAGE_STRING;
case 0x53000017:
return PUS_SERVICE_17_TEST_STRING;
case 0x53000020:
@ -462,6 +470,16 @@ const char *translateObject(object_id_t object) {
return TCS_SUBSYSTEM_STRING;
case 0x73010004:
return COM_SUBSYSTEM_STRING;
case 0x73020001:
return MISC_TM_STORE_STRING;
case 0x73020002:
return OK_TM_STORE_STRING;
case 0x73020003:
return NOT_OK_TM_STORE_STRING;
case 0x73020004:
return HK_TM_STORE_STRING;
case 0x73030000:
return CFDP_TM_STORE_STRING;
case 0x73500000:
return CCSDS_IP_CORE_BRIDGE_STRING;
case 0x90000003:

View File

@ -1,9 +1,8 @@
#include "AcsController.h"
#include <fsfw/datapool/PoolReadGuard.h>
#include "mission/acsDefs.h"
#include "mission/config/torquer.h"
#include <mission/acsDefs.h>
#include <mission/config/torquer.h>
AcsController::AcsController(object_id_t objectId)
: ExtendedControllerBase(objectId),
@ -46,6 +45,26 @@ ReturnValue_t AcsController::handleCommandMessage(CommandMessage *message) {
return result;
}
ReturnValue_t AcsController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) {
switch (actionId) {
case SOLAR_ARRAY_DEPLOYMENT_SUCCESSFUL: {
ReturnValue_t result = guidance.solarArrayDeploymentComplete();
if (result == returnvalue::FAILED) {
return FILE_DELETION_FAILED;
}
return HasActionsIF::EXECUTION_FINISHED;
}
case RESET_MEKF: {
navigation.resetMekf(&mekfData);
return HasActionsIF::EXECUTION_FINISHED;
}
default: {
return HasActionsIF::INVALID_ACTION_ID;
}
}
}
MessageQueueId_t AcsController::getCommandQueue() const { return commandQueue->getId(); }
ReturnValue_t AcsController::getParameter(uint8_t domainId, uint8_t parameterId,
@ -60,6 +79,25 @@ void AcsController::performControlOperation() {
#if OBSW_THREAD_TRACING == 1
trace::threadTrace(opCounter, "ACS & TCS PST");
#endif
{
PoolReadGuard pg(&mgmDataRaw);
if (pg.getReadResult() == returnvalue::OK) {
copyMgmData();
}
}
{
PoolReadGuard pg(&susDataRaw);
if (pg.getReadResult() == returnvalue::OK) {
copySusData();
}
}
{
PoolReadGuard pg(&gyrDataRaw);
if (pg.getReadResult() == returnvalue::OK) {
copyGyrData();
}
}
switch (internalState) {
case InternalState::STARTUP: {
initialCountdown.resetTimer();
@ -95,25 +133,6 @@ void AcsController::performControlOperation() {
default:
break;
}
{
PoolReadGuard pg(&mgmDataRaw);
if (pg.getReadResult() == returnvalue::OK) {
copyMgmData();
}
}
{
PoolReadGuard pg(&susDataRaw);
if (pg.getReadResult() == returnvalue::OK) {
copySusData();
}
}
{
PoolReadGuard pg(&gyrDataRaw);
if (pg.getReadResult() == returnvalue::OK) {
copyGyrData();
}
}
}
void AcsController::performSafe() {
@ -124,8 +143,8 @@ void AcsController::performSafe() {
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
&susDataProcessed, &mekfData);
if (result != MultiplicativeKalmanFilter::KALMAN_RUNNING &&
result != MultiplicativeKalmanFilter::KALMAN_INITIALIZED) {
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
if (not mekfInvalidFlag) {
triggerEvent(acs::MEKF_INVALID_INFO);
mekfInvalidFlag = true;
@ -139,7 +158,7 @@ void AcsController::performSafe() {
// if MEKF is working
double magMomMtq[3] = {0, 0, 0}, errAng = 0.0;
bool magMomMtqValid = false;
if (result == MultiplicativeKalmanFilter::KALMAN_RUNNING) {
if (result == MultiplicativeKalmanFilter::MEKF_RUNNING) {
safeCtrl.safeMekf(now, mekfData.quatMekf.value, mekfData.quatMekf.isValid(),
mgmDataProcessed.magIgrfModel.value, mgmDataProcessed.magIgrfModel.isValid(),
susDataProcessed.sunIjkModel.value, susDataProcessed.isValid(),
@ -189,8 +208,8 @@ void AcsController::performDetumble() {
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
&susDataProcessed, &mekfData);
if (result != MultiplicativeKalmanFilter::KALMAN_RUNNING &&
result != MultiplicativeKalmanFilter::KALMAN_INITIALIZED) {
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
if (not mekfInvalidFlag) {
triggerEvent(acs::MEKF_INVALID_INFO);
mekfInvalidFlag = true;
@ -236,8 +255,8 @@ void AcsController::performPointingCtrl() {
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
&susDataProcessed, &mekfData);
if (result != MultiplicativeKalmanFilter::KALMAN_RUNNING &&
result != MultiplicativeKalmanFilter::KALMAN_INITIALIZED) {
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
if (not mekfInvalidFlag) {
triggerEvent(acs::MEKF_INVALID_INFO);
mekfInvalidFlag = true;
@ -246,9 +265,10 @@ void AcsController::performPointingCtrl() {
triggerEvent(acs::MEKF_INVALID_MODE_VIOLATION);
}
mekfInvalidCounter++;
commandActuators(0, 0, 0, acsParameters.magnetorquesParameter.torqueDuration, cmdSpeedRws[0],
cmdSpeedRws[1], cmdSpeedRws[2], cmdSpeedRws[3],
acsParameters.rwHandlingParameters.rampTime);
// commandActuators(0, 0, 0, acsParameters.magnetorquesParameter.torqueDuration,
// cmdSpeedRws[0],
// cmdSpeedRws[1], cmdSpeedRws[2], cmdSpeedRws[3],
// acsParameters.rwHandlingParameters.rampTime);
return;
} else {
mekfInvalidFlag = false;
@ -395,7 +415,7 @@ void AcsController::performPointingCtrl() {
sensorValues.rw4Set.currSpeed.value, torqueRwsScaled, cmdSpeedRws);
actuatorCmd.cmdDipolMtq(mgtDpDes, cmdDipolMtqs);
updateCtrlValData(targetQuat, errorQuat, errorAngle);
updateCtrlValData(targetQuat, errorQuat, errorAngle, targetSatRotRate);
updateActuatorCmdData(rwTrqNs, cmdSpeedRws, cmdDipolMtqs);
// commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
// acsParameters.magnetorquesParameter.torqueDuration, cmdSpeedRws[0],
@ -457,16 +477,20 @@ void AcsController::updateCtrlValData(double errAng) {
ctrlValData.errQuat.setValid(false);
ctrlValData.errAng.value = errAng;
ctrlValData.errAng.setValid(true);
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC, 3 * sizeof(double));
ctrlValData.tgtRotRate.setValid(false);
ctrlValData.setValidity(true, false);
}
}
void AcsController::updateCtrlValData(const double *tgtQuat, const double *errQuat, double errAng) {
void AcsController::updateCtrlValData(const double *tgtQuat, const double *errQuat, double errAng,
const double *tgtRotRate) {
PoolReadGuard pg(&ctrlValData);
if (pg.getReadResult() == returnvalue::OK) {
std::memcpy(ctrlValData.tgtQuat.value, tgtQuat, 4 * sizeof(double));
std::memcpy(ctrlValData.errQuat.value, errQuat, 4 * sizeof(double));
ctrlValData.errAng.value = errAng;
std::memcpy(ctrlValData.tgtRotRate.value, tgtRotRate, 3 * sizeof(double));
ctrlValData.setValidity(true, true);
}
}
@ -477,6 +501,7 @@ void AcsController::disableCtrlValData() {
std::memcpy(ctrlValData.tgtQuat.value, UNIT_QUAT, 4 * sizeof(double));
std::memcpy(ctrlValData.errQuat.value, UNIT_QUAT, 4 * sizeof(double));
ctrlValData.errAng.value = 0;
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC, 3 * sizeof(double));
ctrlValData.setValidity(false, true);
}
}

View File

@ -1,12 +1,17 @@
#ifndef MISSION_CONTROLLER_ACSCONTROLLER_H_
#define MISSION_CONTROLLER_ACSCONTROLLER_H_
#include <eive/objects.h>
#include <fsfw/controller/ExtendedControllerBase.h>
#include <fsfw/globalfunctions/math/VectorOperations.h>
#include <fsfw/parameters/ParameterHelper.h>
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
#include <fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h>
#include <fsfw_hal/devicehandlers/MgmRM3100Handler.h>
#include <mission/devices/devicedefinitions/SusDefinitions.h>
#include <mission/devices/devicedefinitions/imtqHelpers.h>
#include <mission/devices/devicedefinitions/rwHelpers.h>
#include <mission/trace.h>
#include "acs/ActuatorCmd.h"
#include "acs/Guidance.h"
@ -17,11 +22,6 @@
#include "acs/control/PtgCtrl.h"
#include "acs/control/SafeCtrl.h"
#include "controllerdefinitions/AcsCtrlDefinitions.h"
#include "eive/objects.h"
#include "fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h"
#include "fsfw_hal/devicehandlers/MgmRM3100Handler.h"
#include "mission/devices/devicedefinitions/SusDefinitions.h"
#include "mission/trace.h"
class AcsController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
public:
@ -41,6 +41,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
private:
static constexpr double UNIT_QUAT[4] = {0, 0, 0, 1};
static constexpr double ZERO_VEC[3] = {0, 0, 0};
static constexpr double RW_OFF_TORQUE[4] = {0.0, 0.0, 0.0, 0.0};
static constexpr int32_t RW_OFF_SPEED[4] = {0, 0, 0, 0};
@ -58,7 +59,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
uint8_t detumbleCounter = 0;
uint8_t multipleRwUnavailableCounter = 0;
bool mekfInvalidFlag = true;
bool mekfInvalidFlag = false;
uint8_t mekfInvalidCounter = 0;
int32_t cmdSpeedRws[4] = {0, 0, 0, 0};
int16_t cmdDipolMtqs[3] = {0, 0, 0};
@ -68,13 +69,23 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
#endif
enum class InternalState { STARTUP, INITIAL_DELAY, READY };
InternalState internalState = InternalState::STARTUP;
/** Device command IDs */
static const DeviceCommandId_t SOLAR_ARRAY_DEPLOYMENT_SUCCESSFUL = 0x0;
static const DeviceCommandId_t RESET_MEKF = 0x1;
static const uint8_t INTERFACE_ID = CLASS_ID::ACS_CTRL;
static constexpr ReturnValue_t FILE_DELETION_FAILED = MAKE_RETURN_CODE(0);
ReturnValue_t initialize() override;
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
void performControlOperation() override;
/* HasActionsIF overrides */
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
@ -92,7 +103,8 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
void updateActuatorCmdData(const double* rwTargetTorque, const int32_t* rwTargetSpeed,
const int16_t* mtqTargetDipole);
void updateCtrlValData(double errAng);
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng);
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng,
const double* tgtRotRate);
void disableCtrlValData();
/* ACS Sensor Values */

View File

@ -1,8 +1,3 @@
/*******************************
* EIVE Flight Software Framework (FSFW)
* (c) 2022 IRS, Uni Stuttgart
*******************************/
#ifndef ACSPARAMETERS_H_
#define ACSPARAMETERS_H_

View File

@ -551,3 +551,19 @@ void Guidance::getTargetParamsSafe(double sunTargetSafe[3], double satRateSafe[3
std::memcpy(satRateSafe, acsParameters.safeModeControllerParameters.satRateRef,
3 * sizeof(double));
}
ReturnValue_t Guidance::solarArrayDeploymentComplete() {
if (std::filesystem::exists(SD_0_SKEWED_PTG_FILE)) {
std::remove(SD_0_SKEWED_PTG_FILE);
if (std::filesystem::exists(SD_0_SKEWED_PTG_FILE)) {
return returnvalue::FAILED;
}
}
if (std::filesystem::exists(SD_1_SKEWED_PTG_FILE)) {
std::remove(SD_1_SKEWED_PTG_FILE);
if (std::filesystem::exists(SD_1_SKEWED_PTG_FILE)) {
return returnvalue::FAILED;
}
}
return returnvalue::OK;
}

View File

@ -13,6 +13,7 @@ class Guidance {
virtual ~Guidance();
void getTargetParamsSafe(double sunTargetSafe[3], double satRateRef[3]);
ReturnValue_t solarArrayDeploymentComplete();
// Function to get the target quaternion and refence rotation rate from gps position and
// position of the ground station

View File

@ -189,12 +189,12 @@ ReturnValue_t MultiplicativeKalmanFilter::init(
initialCovarianceMatrix[5][4] = initGyroCov[2][1];
initialCovarianceMatrix[5][5] = initGyroCov[2][2];
updateDataSetWithoutData(mekfData, MekfStatus::INITIALIZED);
return KALMAN_INITIALIZED;
return MEKF_INITIALIZED;
} else {
// no initialisation possible, no valid measurements
validInit = false;
updateDataSetWithoutData(mekfData, MekfStatus::UNINITIALIZED);
return KALMAN_UNINITIALIZED;
return MEKF_UNINITIALIZED;
}
}
@ -211,12 +211,12 @@ ReturnValue_t MultiplicativeKalmanFilter::mekfEst(const double *quaternionSTR, c
int MDF = 0; // Matrix Dimension Factor
if (!validGYRs_) {
updateDataSetWithoutData(mekfData, MekfStatus::NO_GYR_DATA);
return KALMAN_NO_GYR_DATA;
return MEKF_NO_GYR_DATA;
}
// Check for Model Calculations
else if (!validSSModel || !validMagModel) {
updateDataSetWithoutData(mekfData, MekfStatus::NO_MODEL_VECTORS);
return KALMAN_NO_MODEL_VECTORS;
return MEKF_NO_MODEL_VECTORS;
}
// Check Measurements available from SS, MAG, STR
if (validSS && validMagField_ && validSTR_) {
@ -854,7 +854,7 @@ ReturnValue_t MultiplicativeKalmanFilter::mekfEst(const double *quaternionSTR, c
int inversionFailed = MathOperations<double>::inverseMatrix(*residualCov, *invResidualCov, MDF);
if (inversionFailed) {
updateDataSetWithoutData(mekfData, MekfStatus::COVARIANCE_INVERSION_FAILED);
return KALMAN_COVARIANCE_INVERSION_FAILED; // RETURN VALUE ? -- Like: Kalman Inversion Failed
return MEKF_COVARIANCE_INVERSION_FAILED; // RETURN VALUE ? -- Like: Kalman Inversion Failed
}
// [K = P * H' / (H * P * H' + R)]
@ -1085,16 +1085,17 @@ ReturnValue_t MultiplicativeKalmanFilter::mekfEst(const double *quaternionSTR, c
MatrixOperations<double>::add(*cov0, *cov1, *initialCovarianceMatrix, 6, 6);
updateDataSet(mekfData, MekfStatus::RUNNING, quatBJ, rotRateEst);
return KALMAN_RUNNING;
return MEKF_RUNNING;
}
void MultiplicativeKalmanFilter::reset(acsctrl::MekfData *mekfData) {
ReturnValue_t MultiplicativeKalmanFilter::reset(acsctrl::MekfData *mekfData) {
double resetQuaternion[4] = {0, 0, 0, 1};
double resetCovarianceMatrix[6][6] = {{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}};
std::memcpy(initialQuaternion, resetQuaternion, 4 * sizeof(double));
std::memcpy(initialCovarianceMatrix, resetCovarianceMatrix, 6 * 6 * sizeof(double));
updateDataSetWithoutData(mekfData, MekfStatus::UNINITIALIZED);
return MEKF_UNINITIALIZED;
}
void MultiplicativeKalmanFilter::updateDataSetWithoutData(acsctrl::MekfData *mekfData,

View File

@ -1,17 +1,3 @@
/*
* MultiplicativeKalmanFilter.h
*
* Created on: 4 Feb 2022
* Author: Robin Marquardt
*
* @brief: This class handles the calculation of an estimated quaternion and the gyro bias by
* means of the spacecraft attitude sensors
*
* @note: A description of the used algorithms can be found in the bachelor thesis of Robin
* Marquardt
* https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_Studenten/Marquardt_Robin&openfile=500811
*/
#ifndef MULTIPLICATIVEKALMANFILTER_H_
#define MULTIPLICATIVEKALMANFILTER_H_
@ -22,6 +8,13 @@
#include "eive/resultClassIds.h"
class MultiplicativeKalmanFilter {
/* @brief: This class handles the calculation of an estimated quaternion and the gyro bias by
* means of the spacecraft attitude sensors
*
* @note: A description of the used algorithms can be found in the bachelor thesis of Robin
* Marquardt
* https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_Studenten/Marquardt_Robin&openfile=500811
*/
public:
/* @brief: Constructor
* @param: acsParameters_ Pointer to object which defines the ACS configuration parameters
@ -29,7 +22,7 @@ class MultiplicativeKalmanFilter {
MultiplicativeKalmanFilter(AcsParameters *acsParameters_);
virtual ~MultiplicativeKalmanFilter();
void reset(acsctrl::MekfData *mekfData);
ReturnValue_t reset(acsctrl::MekfData *mekfData);
/* @brief: init() - This function initializes the Kalman Filter and will provide the first
* quaternion through the QUEST algorithm
@ -74,15 +67,15 @@ class MultiplicativeKalmanFilter {
};
// resetting Mekf
static constexpr uint8_t IF_KAL_ID = CLASS_ID::ACS_KALMAN;
static constexpr ReturnValue_t KALMAN_UNINITIALIZED = returnvalue::makeCode(IF_KAL_ID, 2);
static constexpr ReturnValue_t KALMAN_NO_GYR_DATA = returnvalue::makeCode(IF_KAL_ID, 3);
static constexpr ReturnValue_t KALMAN_NO_MODEL_VECTORS = returnvalue::makeCode(IF_KAL_ID, 4);
static constexpr ReturnValue_t KALMAN_NO_SUS_MGM_STR_DATA = returnvalue::makeCode(IF_KAL_ID, 5);
static constexpr ReturnValue_t KALMAN_COVARIANCE_INVERSION_FAILED =
returnvalue::makeCode(IF_KAL_ID, 6);
static constexpr ReturnValue_t KALMAN_INITIALIZED = returnvalue::makeCode(IF_KAL_ID, 7);
static constexpr ReturnValue_t KALMAN_RUNNING = returnvalue::makeCode(IF_KAL_ID, 8);
static constexpr uint8_t IF_MEKF_ID = CLASS_ID::ACS_MEKF;
static constexpr ReturnValue_t MEKF_UNINITIALIZED = returnvalue::makeCode(IF_MEKF_ID, 2);
static constexpr ReturnValue_t MEKF_NO_GYR_DATA = returnvalue::makeCode(IF_MEKF_ID, 3);
static constexpr ReturnValue_t MEKF_NO_MODEL_VECTORS = returnvalue::makeCode(IF_MEKF_ID, 4);
static constexpr ReturnValue_t MEKF_NO_SUS_MGM_STR_DATA = returnvalue::makeCode(IF_MEKF_ID, 5);
static constexpr ReturnValue_t MEKF_COVARIANCE_INVERSION_FAILED =
returnvalue::makeCode(IF_MEKF_ID, 6);
static constexpr ReturnValue_t MEKF_INITIALIZED = returnvalue::makeCode(IF_MEKF_ID, 7);
static constexpr ReturnValue_t MEKF_RUNNING = returnvalue::makeCode(IF_MEKF_ID, 8);
private:
/*Parameters*/

View File

@ -25,26 +25,25 @@ ReturnValue_t Navigation::useMekf(ACS::SensorValues *sensorValues,
sensorValues->strSet.caliQy.isValid() &&
sensorValues->strSet.caliQz.isValid() && sensorValues->strSet.caliQw.isValid();
if (kalmanInit) {
return multiplicativeKalmanFilter.mekfEst(
if (mekfStatus == MultiplicativeKalmanFilter::MEKF_UNINITIALIZED) {
mekfStatus = multiplicativeKalmanFilter.init(
mgmDataProcessed->mgmVecTot.value, mgmDataProcessed->mgmVecTot.isValid(),
susDataProcessed->susVecTot.value, susDataProcessed->susVecTot.isValid(),
susDataProcessed->sunIjkModel.value, susDataProcessed->sunIjkModel.isValid(),
mgmDataProcessed->magIgrfModel.value, mgmDataProcessed->magIgrfModel.isValid(), mekfData);
return mekfStatus;
} else {
mekfStatus = multiplicativeKalmanFilter.mekfEst(
quatIB, quatIBValid, gyrDataProcessed->gyrVecTot.value,
gyrDataProcessed->gyrVecTot.isValid(), mgmDataProcessed->mgmVecTot.value,
mgmDataProcessed->mgmVecTot.isValid(), susDataProcessed->susVecTot.value,
susDataProcessed->susVecTot.isValid(), susDataProcessed->sunIjkModel.value,
susDataProcessed->sunIjkModel.isValid(), mgmDataProcessed->magIgrfModel.value,
mgmDataProcessed->magIgrfModel.isValid(), acsParameters.onBoardParams.sampleTime, mekfData);
} else {
ReturnValue_t result;
result = multiplicativeKalmanFilter.init(
mgmDataProcessed->mgmVecTot.value, mgmDataProcessed->mgmVecTot.isValid(),
susDataProcessed->susVecTot.value, susDataProcessed->susVecTot.isValid(),
susDataProcessed->sunIjkModel.value, susDataProcessed->sunIjkModel.isValid(),
mgmDataProcessed->magIgrfModel.value, mgmDataProcessed->magIgrfModel.isValid(), mekfData);
kalmanInit = true;
return result;
return mekfStatus;
}
}
void Navigation::resetMekf(acsctrl::MekfData *mekfData) {
multiplicativeKalmanFilter.reset(mekfData);
mekfStatus = multiplicativeKalmanFilter.reset(mekfData);
}

View File

@ -22,7 +22,7 @@ class Navigation {
private:
MultiplicativeKalmanFilter multiplicativeKalmanFilter;
AcsParameters acsParameters;
bool kalmanInit = false;
ReturnValue_t mekfStatus = MultiplicativeKalmanFilter::MEKF_UNINITIALIZED;
};
#endif /* ACS_NAVIGATION_H_ */

View File

@ -1,7 +1,3 @@
/*******************************
* EIVE Flight Software
* (c) 2022 IRS, Uni Stuttgart
*******************************/
#ifndef SENSORPROCESSING_H_
#define SENSORPROCESSING_H_

View File

@ -1,9 +1,3 @@
/*
* SensorValues.cpp
*
* Created on: 30 Mar 2022
* Author: rooob
*/
#include "SensorValues.h"
#include <fsfw/datapool/PoolReadGuard.h>

View File

@ -1,16 +1,9 @@
/*
* SusConverter.cpp
*
* Created on: 17.01.2022
* Author: Timon Schwarz
*/
#include "SusConverter.h"
#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/LocalPoolVector.h>
#include <fsfw/globalfunctions/math/VectorOperations.h>
#include <math.h> //for atan2
#include <math.h>
#include <iostream>

View File

@ -1,10 +1,3 @@
/*
* SusConverter.h
*
* Created on: Sep 22, 2022
* Author: marius
*/
#ifndef MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
#define MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
@ -28,8 +21,6 @@ class SusConverter {
private:
float alphaBetaRaw[2]; //[°]
// float coeffAlpha[9][10];
// float coeffBeta[9][10];
float alphaBetaCalibrated[2]; //[°]
float sunVectorSensorFrame[3]; //[-]

View File

@ -300,6 +300,7 @@ class MathOperations {
}
static float matrixDeterminant(const T1 *inputMatrix, uint8_t size) {
/* do not use this. takes 300ms */
float det = 0;
T1 matrix[size][size], submatrix[size - 1][size - 1];
for (uint8_t row = 0; row < size; row++) {
@ -329,9 +330,7 @@ class MathOperations {
}
static int inverseMatrix(const T1 *inputMatrix, T1 *inverse, uint8_t size) {
if (MathOperations<T1>::matrixDeterminant(inputMatrix, size) == 0) {
return 1; // Matrix is singular and not invertible
}
// Stopwatch stopwatch;
T1 matrix[size][size], identity[size][size];
// reformat array to matrix
for (uint8_t row = 0; row < size; row++) {
@ -346,7 +345,6 @@ class MathOperations {
}
// gauss-jordan algo
// sort matrix such as no diag entry shall be 0
// should not be needed as such a matrix has a det=0
for (uint8_t row = 0; row < size; row++) {
if (matrix[row][row] == 0.0) {
bool swaped = false;

View File

@ -58,6 +58,7 @@
// TCP server includes
#include "fsfw/osal/common/TcpTmTcBridge.h"
#include "fsfw/osal/common/TcpTmTcServer.h"
#include "mission/tmtc/Service15TmStorage.h"
#endif
#endif
@ -83,7 +84,7 @@ EiveFaultHandler EIVE_FAULT_HANDLER;
} // namespace cfdp
void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel,
CfdpTmFunnel** cfdpFunnel) {
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan) {
// Framework objects
new EventManager(objects::EVENT_MANAGER);
auto healthTable = new HealthTable(objects::HEALTH_TABLE);
@ -95,6 +96,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
auto* timeStamper = new CdsShortTimeStamper(objects::TIME_STAMPER);
StorageManagerIF* tcStore;
StorageManagerIF* tmStore;
StorageManagerIF* ipcStore;
{
PoolManager::LocalPoolConfig poolCfg = {{250, 16}, {250, 32}, {250, 64},
{150, 128}, {120, 1024}, {120, 2048}};
@ -109,8 +111,8 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
{
PoolManager::LocalPoolConfig poolCfg = {{300, 16}, {200, 32}, {150, 64}, {150, 128},
{100, 256}, {50, 512}, {50, 1024}, {50, 2048}};
new PoolManager(objects::IPC_STORE, poolCfg);
{100, 256}, {50, 512}, {50, 1024}, {10, 2048}};
ipcStore = new PoolManager(objects::IPC_STORE, poolCfg);
}
#if OBSW_ADD_TCPIP_SERVERS == 1
@ -137,9 +139,11 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
new CcsdsDistributor(config::EIVE_PUS_APID, objects::CCSDS_PACKET_DISTRIBUTOR);
new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib);
*cfdpFunnel = new CfdpTmFunnel(objects::CFDP_TM_FUNNEL, config::EIVE_CFDP_APID, *tmStore, 50);
*pusFunnel = new PusTmFunnel(objects::PUS_TM_FUNNEL, *timeStamper, *tmStore,
config::MAX_PUS_FUNNEL_QUEUE_DEPTH);
PusTmFunnel::FunnelCfg cfdpFunnelCfg(objects::CFDP_TM_FUNNEL, *tmStore, *ipcStore, 50);
*cfdpFunnel = new CfdpTmFunnel(cfdpFunnelCfg, config::EIVE_CFDP_APID);
PusTmFunnel::FunnelCfg pusFunnelCfg(objects::PUS_TM_FUNNEL, *tmStore, *ipcStore,
config::MAX_PUS_FUNNEL_QUEUE_DEPTH);
*pusFunnel = new PusTmFunnel(pusFunnelCfg, *timeStamper, sdcMan);
#if OBSW_ADD_TCPIP_SERVERS == 1
#if OBSW_ADD_TMTC_UDP_SERVER == 1
(*cfdpFunnel)->addDestination("UDP Server", *udpBridge, 0);
@ -171,6 +175,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
new Service11TelecommandScheduling<common::OBSW_MAX_SCHEDULED_TCS>(
PsbParams(objects::PUS_SERVICE_11_TC_SCHEDULER, config::EIVE_PUS_APID, pus::PUS_SERVICE_11),
ccsdsDistrib);
new Service15TmStorage(objects::PUS_SERVICE_15_TM_STORAGE, config::EIVE_PUS_APID, 10);
new Service17Test(
PsbParams(objects::PUS_SERVICE_17_TEST, config::EIVE_PUS_APID, pus::PUS_SERVICE_17));
new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, config::EIVE_PUS_APID,
@ -232,7 +237,7 @@ void ObjectFactory::createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t the
std::array<object_id_t, 4> rwIds) {
RwHelper rwHelper(rwIds);
auto* rwAss = new RwAssembly(objects::RW_ASS, &pwrSwitcher, theSwitch, rwHelper);
for (uint8_t idx = 0; idx < rwIds.size(); idx++) {
for (size_t idx = 0; idx < rwIds.size(); idx++) {
ReturnValue_t result = rws[idx]->connectModeTreeParent(*rwAss);
if (result != returnvalue::OK) {
sif::error << "Connecting RW " << static_cast<int>(idx) << " to RW assembly failed"
@ -251,7 +256,7 @@ void ObjectFactory::createSusAssy(PowerSwitchIF& pwrSwitcher,
objects::SUS_6_R_LOC_XFYBZM_PT_XF, objects::SUS_7_R_LOC_XBYBZM_PT_XB,
objects::SUS_8_R_LOC_XBYBZB_PT_YB, objects::SUS_9_R_LOC_XBYBZB_PT_YF,
objects::SUS_10_N_LOC_XMYBZF_PT_ZF, objects::SUS_11_R_LOC_XBYMZB_PT_ZB};
SusAssHelper susAssHelper = SusAssHelper(susIds);
auto susAssHelper = SusAssHelper(susIds);
auto susAss = new SusAssembly(objects::SUS_BOARD_ASS, &pwrSwitcher, susAssHelper);
for (auto& sus : suses) {
if (sus != nullptr) {
@ -287,8 +292,8 @@ void ObjectFactory::createAcsBoardAssy(PowerSwitchIF& pwrSwitcher,
TcsBoardAssembly* ObjectFactory::createTcsBoardAssy(PowerSwitchIF& pwrSwitcher) {
TcsBoardHelper helper(RTD_INFOS);
TcsBoardAssembly* tcsBoardAss = new TcsBoardAssembly(
objects::TCS_BOARD_ASS, &pwrSwitcher, pcdu::Switches::PDU1_CH0_TCS_BOARD_3V3, helper);
auto* tcsBoardAss = new TcsBoardAssembly(objects::TCS_BOARD_ASS, &pwrSwitcher,
pcdu::Switches::PDU1_CH0_TCS_BOARD_3V3, helper);
tcsBoardAss->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
return tcsBoardAss;
}

View File

@ -2,6 +2,7 @@
#define MISSION_CORE_GENERICFACTORY_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <mission/memory/SdCardMountedIF.h>
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/power/PowerSwitchIF.h"
@ -37,7 +38,7 @@ const std::array<std::pair<object_id_t, std::string>, EiveMax31855::NUM_RTDS> RT
namespace ObjectFactory {
void produceGenericObjects(HealthTableIF** healthTable, PusTmFunnel** pusFunnel,
CfdpTmFunnel** cfdpFunnel);
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan);
void createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& pwrSwitcher,
HeaterHandler*& heaterHandler);

View File

@ -517,6 +517,9 @@ void PayloadPcduHandler::checkJsonFileInit() {
if (not jsonFileInitComplete) {
auto activeSd = sdcMan->getActiveSdCard();
if (activeSd and sdcMan->isSdCardUsable(activeSd.value())) {
if (sdcMan->getCurrentMountPrefix() == nullptr) {
return;
}
params.initialize(sdcMan->getCurrentMountPrefix());
jsonFileInitComplete = true;
}

View File

@ -214,6 +214,9 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
fileId = date_time_string();
std::ostringstream oss;
auto prefix = sdcMan.getCurrentMountPrefix();
if (prefix == nullptr) {
return returnvalue::FAILED;
}
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
fileName = oss.str();
ofstream out(fileName, ofstream::binary);
@ -234,6 +237,9 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
fileId = date_time_string();
std::ostringstream oss;
auto prefix = sdcMan.getCurrentMountPrefix();
if (prefix == nullptr) {
return returnvalue::FAILED;
}
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
fileName = oss.str();
fileNameSet = true;
@ -310,6 +316,16 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
}
void ScexDeviceHandler::performOperationHook() {
auto mntPrefix = sdcMan.getCurrentMountPrefix();
if (mntPrefix != nullptr) {
std::filesystem::path fullFilePath = mntPrefix;
fullFilePath /= "scex";
bool fileExists = std::filesystem::exists(fullFilePath);
if (not fileExists) {
std::filesystem::create_directory(fullFilePath);
}
}
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
if (commandActive and finishCountdown.hasTimedOut()) {
triggerEvent(scex::EXPERIMENT_TIMEDOUT, currCmd, 0);
@ -373,13 +389,5 @@ void ScexDeviceHandler::setPowerSwitcher(PowerSwitchIF& powerSwitcher, power::Sw
}
ReturnValue_t ScexDeviceHandler::initializeAfterTaskCreation() {
auto mntPrefix = sdcMan.getCurrentMountPrefix();
std::filesystem::path fullFilePath = mntPrefix;
fullFilePath /= "scex";
bool fileExists = std::filesystem::exists(fullFilePath);
if (not fileExists) {
std::filesystem::create_directory(fullFilePath);
}
return DeviceHandlerBase::initializeAfterTaskCreation();
}

View File

@ -67,6 +67,7 @@ class GpsPrimaryDataset : public StaticLocalDataSet<18> {
private:
friend class GpsHyperionLinuxController;
friend class GpsCtrlDummy;
GpsPrimaryDataset(HasLocalDataPoolIF* hkOwner)
: StaticLocalDataSet(hkOwner, GpsHyperion::DATASET_ID) {}
};

View File

@ -9,7 +9,7 @@
class SdCardMountedIF {
public:
virtual ~SdCardMountedIF(){};
virtual const std::string& getCurrentMountPrefix() const = 0;
virtual const char* getCurrentMountPrefix() const = 0;
virtual bool isSdCardUsable(std::optional<sd::SdCard> sdCard) = 0;
virtual std::optional<sd::SdCard> getPreferredSdCard() const = 0;
virtual void setActiveSdCard(sd::SdCard sdCard) = 0;

View File

@ -1,4 +1,10 @@
target_sources(
${LIB_EIVE_MISSION}
PRIVATE CcsdsIpCoreHandler.cpp VirtualChannel.cpp TmFunnelHandler.cpp
TmFunnelBase.cpp CfdpTmFunnel.cpp PusTmFunnel.cpp)
PRIVATE CcsdsIpCoreHandler.cpp
VirtualChannel.cpp
TmFunnelHandler.cpp
TmFunnelBase.cpp
CfdpTmFunnel.cpp
Service15TmStorage.cpp
PersistentTmStore.cpp
PusTmFunnel.cpp)

View File

@ -4,9 +4,8 @@
#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
CfdpTmFunnel::CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid,
StorageManagerIF& tmStore, uint32_t messageDepth)
: TmFunnelBase(objectId, tmStore, messageDepth), cfdpInCcsdsApid(cfdpInCcsdsApid) {}
CfdpTmFunnel::CfdpTmFunnel(TmFunnelBase::FunnelCfg cfg, uint16_t cfdpInCcsdsApid)
: TmFunnelBase(cfg), cfdpInCcsdsApid(cfdpInCcsdsApid) {}
const char* CfdpTmFunnel::getName() const { return "CFDP TM Funnel"; }

View File

@ -12,8 +12,7 @@
class CfdpTmFunnel : public TmFunnelBase {
public:
CfdpTmFunnel(object_id_t objectId, uint16_t cfdpInCcsdsApid, StorageManagerIF& tmStore,
uint32_t messageDepth);
CfdpTmFunnel(TmFunnelBase::FunnelCfg cfg, uint16_t cfdpInCcsdsApid);
[[nodiscard]] const char* getName() const override;
ReturnValue_t performOperation(uint8_t opCode);
ReturnValue_t initialize() override;

View File

@ -0,0 +1,362 @@
#include "PersistentTmStore.h"
#include <mission/memory/SdCardMountedIF.h>
#include <algorithm>
#include <cinttypes>
#include <filesystem>
#include <fstream>
#include <utility>
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/tmstorage/TmStoreMessage.h"
using namespace returnvalue;
PersistentTmStore::PersistentTmStore(object_id_t objectId, const char* baseDir,
std::string baseName, RolloverInterval intervalUnit,
uint32_t intervalCount, StorageManagerIF& tmStore,
SdCardMountedIF& sdcMan)
: SystemObject(objectId),
baseDir(baseDir),
baseName(std::move(baseName)),
sdcMan(sdcMan),
tmStore(tmStore) {
tcQueue = QueueFactory::instance()->createMessageQueue();
calcDiffSeconds(intervalUnit, intervalCount);
}
ReturnValue_t PersistentTmStore::assignAndOrCreateMostRecentFile() {
using namespace std::filesystem;
for (auto const& file : directory_iterator(basePath)) {
if (file.is_directory()) {
continue;
}
auto pathStr = file.path().string();
if (pathStr.find(baseName) == std::string::npos) {
continue;
}
unsigned int underscorePos = pathStr.find_last_of('_');
std::string stampStr = pathStr.substr(underscorePos + 1);
struct tm time {};
if (nullptr == strptime(stampStr.c_str(), FILE_DATE_FORMAT, &time)) {
sif::error << "PersistentTmStore::assignOrCreateMostRecentFile: Error reading timestamp"
<< std::endl;
// Delete the file and re-create it.
activeFile = std::nullopt;
std::filesystem::remove(file.path());
break;
}
time_t fileEpoch = timegm(&time);
// There is still a file within the active time window, so re-use that file for new TMs to
// store.
if (fileEpoch + static_cast<time_t>(rolloverDiffSeconds) > currentTv.tv_sec) {
activeFileTv.tv_sec = fileEpoch;
activeFile = file.path();
break;
}
}
if (not activeFile.has_value()) {
return createMostRecentFile(std::nullopt);
}
return returnvalue::OK;
}
ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
TmFunnelBase& tmFunnel) {
CommandMessage cmdMessage;
ReturnValue_t result = tcQueue->receiveMessage(&cmdMessage);
if (result == MessageQueueIF::EMPTY) {
return returnvalue::OK;
}
if (result != returnvalue::OK) {
return result;
}
if (cmdMessage.getMessageType() == messagetypes::TM_STORE) {
Command_t cmd = cmdMessage.getCommand();
if (cmd == TmStoreMessage::DELETE_STORE_CONTENT_TIME) {
Clock::getClock_timeval(&currentTv);
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
auto accessor = ipcStore.getData(storeId);
uint32_t deleteUpToUnixSeconds = 0;
size_t size = accessor.second.size();
SerializeAdapter::deSerialize(&deleteUpToUnixSeconds, accessor.second.data(), &size,
SerializeIF::Endianness::NETWORK);
deleteUpTo(deleteUpToUnixSeconds);
} else if (cmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
Clock::getClock_timeval(&currentTv);
store_address_t storeId = TmStoreMessage::getStoreId(&cmdMessage);
auto accessor = ipcStore.getData(storeId);
if (accessor.second.size() < 8) {
return returnvalue::FAILED;
}
uint32_t dumpFromUnixSeconds;
uint32_t dumpUntilUnixSeconds;
size_t size = 8;
SerializeAdapter::deSerialize(&dumpFromUnixSeconds, accessor.second.data(), &size,
SerializeIF::Endianness::NETWORK);
SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size,
SerializeIF::Endianness::NETWORK);
dumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds, tmFunnel);
}
}
return returnvalue::OK;
}
ReturnValue_t PersistentTmStore::passPacket(PusTmReader& reader) {
bool inApidList = false;
if (filter.apid) {
auto& apidFilter = filter.apid.value();
if (std::find(apidFilter.begin(), apidFilter.end(), reader.getApid()) != apidFilter.end()) {
if (not filter.serviceSubservices and not filter.services) {
return storePacket(reader);
}
inApidList = true;
}
}
std::pair<uint8_t, uint8_t> serviceSubservice;
serviceSubservice.first = reader.getService();
serviceSubservice.second = reader.getSubService();
if (filter.services) {
auto& serviceFilter = filter.services.value();
if (std::find(serviceFilter.begin(), serviceFilter.end(), serviceSubservice.first) !=
serviceFilter.end()) {
if (filter.apid and inApidList) {
return storePacket(reader);
}
}
}
if (filter.serviceSubservices) {
auto& serviceSubserviceFilter = filter.serviceSubservices.value();
if (std::find(serviceSubserviceFilter.begin(), serviceSubserviceFilter.end(),
serviceSubservice) != serviceSubserviceFilter.end()) {
if (filter.apid and inApidList) {
return storePacket(reader);
}
}
}
return returnvalue::OK;
}
void PersistentTmStore::dumpFrom(uint32_t fromUnixSeconds, TmFunnelBase& tmFunnel) {
return dumpFromUpTo(fromUnixSeconds, currentTv.tv_sec, tmFunnel);
}
ReturnValue_t PersistentTmStore::storePacket(PusTmReader& reader) {
using namespace std::filesystem;
if (baseDirUninitialized) {
updateBaseDir();
}
Clock::getClock_timeval(&currentTv);
// It is assumed here that the filesystem is usable.
if (not activeFile.has_value()) {
ReturnValue_t result = assignAndOrCreateMostRecentFile();
if (result != returnvalue::OK) {
return result;
}
}
bool createNewFile = false;
std::optional<uint8_t> suffix = std::nullopt;
if (currentTv.tv_sec > activeFileTv.tv_sec + static_cast<int>(rolloverDiffSeconds)) {
createNewFile = true;
currentSameSecNumber = 0;
} else if (file_size(activeFile.value()) + reader.getFullPacketLen() > fileBuf.size()) {
createNewFile = true;
if (currentSameSecNumber >= MAX_FILES_IN_ONE_SECOND) {
currentSameSecNumber = 0;
}
if (currentTv.tv_sec == activeFileTv.tv_sec) {
suffix = currentSameSecNumber++;
} else {
currentSameSecNumber = 0;
}
}
if (createNewFile) {
createMostRecentFile(suffix);
}
// Rollover conditions were handled, write to file now
std::ofstream of(activeFile.value(), std::ios::app | std::ios::binary);
of.write(reinterpret_cast<const char*>(reader.getFullData()),
static_cast<std::streamsize>(reader.getFullPacketLen()));
return returnvalue::OK;
}
MessageQueueId_t PersistentTmStore::getCommandQueue() const { return tcQueue->getId(); }
void PersistentTmStore::calcDiffSeconds(RolloverInterval intervalUnit, uint32_t intervalCount) {
if (intervalUnit == RolloverInterval::MINUTELY) {
rolloverDiffSeconds = 60 * intervalCount;
} else if (intervalUnit == RolloverInterval::HOURLY) {
rolloverDiffSeconds = 60 * 60 * intervalCount;
} else if (intervalUnit == RolloverInterval::DAILY) {
rolloverDiffSeconds = 60 * 60 * 24 * intervalCount;
}
}
bool PersistentTmStore::updateBaseDir() {
using namespace std::filesystem;
const char* currentPrefix = sdcMan.getCurrentMountPrefix();
if (currentPrefix == nullptr) {
return false;
}
basePath = path(currentPrefix) / baseDir / baseName;
if (not exists(basePath)) {
create_directories(basePath);
}
baseDirUninitialized = false;
return true;
}
void PersistentTmStore::addApid(uint16_t apid) {
if (not filter.apid) {
filter.apid = std::vector<uint16_t>({apid});
return;
}
filter.apid.value().push_back(apid);
}
void PersistentTmStore::addService(uint8_t service) {
if (not filter.services) {
filter.services = std::vector<uint8_t>({service});
return;
}
filter.services.value().push_back(service);
}
void PersistentTmStore::addServiceSubservice(uint8_t service, uint8_t subservice) {
if (not filter.serviceSubservices) {
filter.serviceSubservices =
std::vector<std::pair<uint8_t, uint8_t>>({std::pair(service, subservice)});
return;
}
filter.serviceSubservices.value().emplace_back(service, subservice);
}
void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) {
using namespace std::filesystem;
for (auto const& file : directory_iterator(basePath)) {
if (file.is_directory() or (activeFile.has_value() and (activeFile.value() == file.path()))) {
continue;
}
// Convert file time to the UNIX epoch
struct tm fileTime {};
if (pathToTm(file.path(), fileTime) != returnvalue::OK) {
sif::error << "Time extraction for " << file << "failed" << std::endl;
continue;
}
time_t fileEpoch = timegm(&fileTime);
if (fileEpoch + rolloverDiffSeconds < unixSeconds) {
std::filesystem::remove(file.path());
}
}
}
void PersistentTmStore::dumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds,
TmFunnelBase& funnel) {
using namespace std::filesystem;
for (auto const& file : directory_iterator(basePath)) {
if (file.is_directory()) {
continue;
}
struct tm fileTime {};
if (pathToTm(file.path(), fileTime) != returnvalue::OK) {
sif::error << "Time extraction for file " << file << "failed" << std::endl;
continue;
}
auto fileEpoch = static_cast<uint32_t>(timegm(&fileTime));
if ((fileEpoch > fromUnixSeconds) and (fileEpoch + rolloverDiffSeconds <= upToUnixSeconds)) {
fileToPackets(file, fileEpoch, funnel);
}
}
}
ReturnValue_t PersistentTmStore::pathToTm(const std::filesystem::path& path, struct tm& time) {
auto pathStr = path.string();
size_t splitChar = pathStr.find('_');
auto timeOnlyStr = pathStr.substr(splitChar + 1);
if (nullptr == strptime(timeOnlyStr.c_str(), FILE_DATE_FORMAT, &time)) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
void PersistentTmStore::fileToPackets(const std::filesystem::path& path, uint32_t unixStamp,
TmFunnelBase& funnel) {
store_address_t storeId;
TmTcMessage message;
size_t size = std::filesystem::file_size(path);
if (size < 6) {
// Can't even read the CCSDS header
return;
}
std::ifstream ifile(path, std::ios::binary);
ifile.read(reinterpret_cast<char*>(fileBuf.data()), static_cast<std::streamsize>(size));
size_t currentIdx = 0;
while (currentIdx < size) {
PusTmReader reader(&timeReader, fileBuf.data(), fileBuf.size());
// CRC check to fully ensure this is a valid TM
ReturnValue_t result = reader.parseDataWithCrcCheck();
if (result == returnvalue::OK) {
result = tmStore.addData(&storeId, fileBuf.data() + currentIdx, reader.getFullPacketLen());
if (result != returnvalue::OK) {
continue;
}
funnel.sendPacketToDestinations(storeId, message, fileBuf.data() + currentIdx,
reader.getFullPacketLen());
currentIdx += reader.getFullPacketLen();
} else {
sif::error << "Parsing of PUS TM failed with code " << result << std::endl;
triggerEvent(POSSIBLE_FILE_CORRUPTION, result, unixStamp);
// Stop for now, do not really know where to continue and we do not trust the file anymore.
break;
}
}
}
ReturnValue_t PersistentTmStore::createMostRecentFile(std::optional<uint8_t> suffix) {
using namespace std::filesystem;
unsigned currentIdx = 0;
path pathStart = basePath / baseName;
memcpy(fileBuf.data() + currentIdx, pathStart.c_str(), pathStart.string().length());
currentIdx += pathStart.string().length();
fileBuf[currentIdx] = '_';
currentIdx += 1;
time_t epoch = currentTv.tv_sec;
struct tm* time = gmtime(&epoch);
size_t writtenBytes = strftime(reinterpret_cast<char*>(fileBuf.data() + currentIdx),
fileBuf.size(), FILE_DATE_FORMAT, time);
if (writtenBytes == 0) {
sif::error << "PersistentTmStore::createMostRecentFile: Could not create file timestamp"
<< std::endl;
return returnvalue::FAILED;
}
currentIdx += writtenBytes;
char* res = strcpy(reinterpret_cast<char*>(fileBuf.data() + currentIdx), ".bin");
if (res == nullptr) {
return returnvalue::FAILED;
}
currentIdx += 4;
if (suffix.has_value()) {
std::string fullSuffix = "." + std::to_string(suffix.value());
res = strcpy(reinterpret_cast<char*>(fileBuf.data() + currentIdx), fullSuffix.c_str());
if (res == nullptr) {
return returnvalue::FAILED;
}
currentIdx += fullSuffix.size();
}
path newPath(std::string(reinterpret_cast<const char*>(fileBuf.data()), currentIdx));
std::ofstream of(newPath, std::ios::binary);
activeFile = newPath;
activeFileTv = currentTv;
return returnvalue::OK;
}
ReturnValue_t PersistentTmStore::initializeTmStore() {
Clock::getClock_timeval(&currentTv);
updateBaseDir();
return assignAndOrCreateMostRecentFile();
}

View File

@ -0,0 +1,87 @@
#ifndef MISSION_TMTC_TMSTOREBACKEND_H_
#define MISSION_TMTC_TMSTOREBACKEND_H_
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/timemanager/CdsShortTimeStamper.h>
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
#include <fsfw/tmtcpacket/pus/tm/PusTmReader.h>
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
#include <mission/memory/SdCardMountedIF.h>
#include <filesystem>
#include "TmFunnelBase.h"
#include "eive/eventSubsystemIds.h"
struct PacketFilter {
std::optional<std::vector<uint16_t>> apid;
std::optional<std::vector<uint8_t>> services;
std::optional<std::vector<std::pair<uint8_t, uint8_t>>> serviceSubservices;
};
enum class RolloverInterval { MINUTELY, HOURLY, DAILY };
class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
public:
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PERSISTENT_TM_STORE;
//! [EXPORT] : [COMMENT]
//! P1: Result code of TM packet parser.
//! P2: Timestamp of possibly corrupt file as a unix timestamp.
static constexpr Event POSSIBLE_FILE_CORRUPTION =
event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW);
PersistentTmStore(object_id_t objectId, const char* baseDir, std::string baseName,
RolloverInterval intervalUnit, uint32_t intervalCount,
StorageManagerIF& tmStore, SdCardMountedIF& sdcMan);
ReturnValue_t initializeTmStore();
ReturnValue_t handleCommandQueue(StorageManagerIF& ipcStore, TmFunnelBase& tmFunnel);
void addApid(uint16_t apid);
void addService(uint8_t service);
void addServiceSubservice(uint8_t service, uint8_t subservice);
void deleteUpTo(uint32_t unixSeconds);
void dumpFrom(uint32_t fromUnixSeconds, TmFunnelBase& tmFunnel);
void dumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds, TmFunnelBase& tmFunnel);
ReturnValue_t passPacket(PusTmReader& reader);
private:
static constexpr uint8_t MAX_FILES_IN_ONE_SECOND = 10;
static constexpr size_t MAX_FILESIZE = 8192;
// ISO8601 timestamp.
static constexpr char FILE_DATE_FORMAT[] = "%FT%H%M%SZ";
MessageQueueIF* tcQueue;
PacketFilter filter;
CdsShortTimeStamper timeReader;
bool baseDirUninitialized = true;
const char* baseDir;
std::string baseName;
uint8_t currentSameSecNumber = 0;
std::filesystem::path basePath;
uint32_t rolloverDiffSeconds = 0;
std::array<uint8_t, MAX_FILESIZE> fileBuf{};
timeval currentTv;
timeval activeFileTv{};
std::optional<std::filesystem::path> activeFile;
SdCardMountedIF& sdcMan;
StorageManagerIF& tmStore;
/**
* To get the queue where commands shall be sent.
* @return Id of command queue.
*/
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
void calcDiffSeconds(RolloverInterval intervalUnit, uint32_t intervalCount);
ReturnValue_t createMostRecentFile(std::optional<uint8_t> suffix);
static ReturnValue_t pathToTm(const std::filesystem::path& path, struct tm& time);
void fileToPackets(const std::filesystem::path& path, uint32_t unixStamp, TmFunnelBase& funnel);
bool updateBaseDir();
ReturnValue_t assignAndOrCreateMostRecentFile();
ReturnValue_t storePacket(PusTmReader& reader);
};
#endif /* MISSION_TMTC_TMSTOREBACKEND_H_ */

View File

@ -1,22 +1,87 @@
#include "PusTmFunnel.h"
#include "eive/definitions.h"
#include "eive/objects.h"
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager.h"
#include "fsfw/pus/Service5EventReporting.h"
#include "fsfw/tmstorage/TmStoreMessage.h"
#include "fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h"
#include "tmtc/pusIds.h"
PusTmFunnel::PusTmFunnel(object_id_t objectId, TimeReaderIF &timeReader, StorageManagerIF &tmStore,
uint32_t messageDepth)
: TmFunnelBase(objectId, tmStore, messageDepth), timeReader(timeReader) {}
PusTmFunnel::PusTmFunnel(TmFunnelBase::FunnelCfg cfg, TimeReaderIF &timeReader,
SdCardMountedIF &sdcMan)
: TmFunnelBase(cfg),
timeReader(timeReader),
miscStore(objects::MISC_TM_STORE, "tm", "misc", RolloverInterval::HOURLY, 2, tmStore, sdcMan),
okStore(objects::OK_TM_STORE, "tm", "ok", RolloverInterval::MINUTELY, 30, tmStore, sdcMan),
notOkStore(objects::NOT_OK_TM_STORE, "tm", "nok", RolloverInterval::MINUTELY, 30, tmStore,
sdcMan),
hkStore(objects::HK_TM_STORE, "tm", "hk", RolloverInterval::MINUTELY, 15, tmStore, sdcMan),
sdcMan(sdcMan) {
Clock::getClock_timeval(&currentTv);
Clock::getUptime(&lastTvUpdate);
hkStore.addApid(config::EIVE_PUS_APID);
hkStore.addService(pus::PUS_SERVICE_3);
miscStore.addApid(config::EIVE_PUS_APID);
miscStore.addService(pus::PUS_SERVICE_17);
miscStore.addService(pus::PUS_SERVICE_2);
miscStore.addService(pus::PUS_SERVICE_200);
miscStore.addService(pus::PUS_SERVICE_201);
miscStore.addService(pus::PUS_SERVICE_9);
miscStore.addService(pus::PUS_SERVICE_20);
okStore.addApid(config::EIVE_PUS_APID);
okStore.addServiceSubservice(pus::PUS_SERVICE_5,
Service5EventReporting::Subservice::NORMAL_REPORT);
okStore.addService(pus::PUS_SERVICE_8);
okStore.addServiceSubservice(pus::PUS_SERVICE_1, 1);
okStore.addServiceSubservice(pus::PUS_SERVICE_1, 3);
okStore.addServiceSubservice(pus::PUS_SERVICE_1, 5);
okStore.addServiceSubservice(pus::PUS_SERVICE_1, 7);
notOkStore.addApid(config::EIVE_PUS_APID);
notOkStore.addServiceSubservice(pus::PUS_SERVICE_5, 2);
notOkStore.addServiceSubservice(pus::PUS_SERVICE_5, 3);
notOkStore.addServiceSubservice(pus::PUS_SERVICE_5, 4);
notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 2);
notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 4);
notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 6);
notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 8);
}
PusTmFunnel::~PusTmFunnel() = default;
ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
CommandMessage cmdMessage;
ReturnValue_t result;
try {
result = okStore.handleCommandQueue(ipcStore, *this);
if (result != returnvalue::OK) {
sif::error << "PusTmFunnel::performOperation: Issue handling OK store command" << std::endl;
}
result = notOkStore.handleCommandQueue(ipcStore, *this);
if (result != returnvalue::OK) {
sif::error << "PusTmFunnel::performOperation: Issue handling NOT OK store command"
<< std::endl;
}
result = hkStore.handleCommandQueue(ipcStore, *this);
if (result != returnvalue::OK) {
sif::error << "PusTmFunnel::performOperation: Issue handling HK store command" << std::endl;
}
result = miscStore.handleCommandQueue(ipcStore, *this);
if (result != returnvalue::OK) {
sif::error << "PusTmFunnel::performOperation: Issue handling MISC store command" << std::endl;
}
} catch (const std::bad_optional_access &e) {
sif::error << e.what() << "when handling TM store command" << std::endl;
}
TmTcMessage currentMessage;
unsigned int count = 0;
ReturnValue_t status = tmQueue->receiveMessage(&currentMessage);
while (status == returnvalue::OK) {
status = handlePacket(currentMessage);
if (status != returnvalue::OK) {
result = tmQueue->receiveMessage(&currentMessage);
while (result == returnvalue::OK) {
result = handleTmPacket(currentMessage);
if (result != returnvalue::OK) {
sif::warning << "TmFunnel packet handling failed" << std::endl;
break;
}
@ -25,16 +90,16 @@ ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
sif::error << "PusTmFunnel: Possible message storm detected" << std::endl;
break;
}
status = tmQueue->receiveMessage(&currentMessage);
result = tmQueue->receiveMessage(&currentMessage);
}
if (status == MessageQueueIF::EMPTY) {
if (result == MessageQueueIF::EMPTY) {
return returnvalue::OK;
}
return status;
return result;
}
ReturnValue_t PusTmFunnel::handlePacket(TmTcMessage &message) {
ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) {
uint8_t *packetData = nullptr;
size_t size = 0;
store_address_t origStoreId = message.getStorageId();
@ -54,36 +119,38 @@ ReturnValue_t PusTmFunnel::handlePacket(TmTcMessage &message) {
sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT;
packet.updateErrorControl();
for (unsigned int idx = 0; idx < destinations.size(); idx++) {
const auto &dest = destinations[idx];
if (destinations.size() > 1) {
if (idx < destinations.size() - 1) {
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
// to bother with send order and where the data is deleted.
store_address_t storeId;
result = tmStore.addData(&storeId, packetData, size);
if (result == returnvalue::OK) {
message.setStorageId(storeId);
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PusTmFunnel::handlePacket: Store too full to create data copy"
<< std::endl;
#endif
}
} else {
message.setStorageId(origStoreId);
}
}
result = tmQueue->sendMessage(dest.queueId, &message);
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PusTmFunnel::handlePacket: Error sending TM to downlink handler " << dest.name
<< " failed" << std::endl;
#endif
tmStore.deleteData(message.getStorageId());
}
timeval currentUptime{};
Clock::getUptime(&currentUptime);
if (currentUptime.tv_sec - lastTvUpdate.tv_sec >
static_cast<signed int>(TV_UPDATE_INTERVAL_SECS)) {
Clock::getClock_timeval(&currentTv);
lastTvUpdate = currentUptime;
}
return result;
bool sdcUsable = sdcMan.isSdCardUsable(std::nullopt);
initStoresIfPossible(sdcUsable);
if (sdcUsable) {
miscStore.passPacket(packet);
okStore.passPacket(packet);
notOkStore.passPacket(packet);
hkStore.passPacket(packet);
}
return sendPacketToDestinations(origStoreId, message, packetData, size);
}
const char *PusTmFunnel::getName() const { return "PUS TM Funnel"; }
void PusTmFunnel::initStoresIfPossible(bool sdCardUsable) {
if (not storesInitialized and sdCardUsable and sdcMan.getCurrentMountPrefix() != nullptr) {
miscStore.initializeTmStore();
okStore.initializeTmStore();
hkStore.initializeTmStore();
notOkStore.initializeTmStore();
storesInitialized = true;
}
}
ReturnValue_t PusTmFunnel::initialize() {
initStoresIfPossible(sdcMan.isSdCardUsable(std::nullopt));
return returnvalue::OK;
}

View File

@ -10,33 +10,43 @@
#include <vector>
#include "PersistentTmStore.h"
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/timemanager/TimeReaderIF.h"
/**
* @brief TM Recipient.
* @details
* TODO: Add support for TM storage by using the (or a) LIVE flag provided by the CCSDS or Syrlinks
* handler. If we are in LIVE TM mode, forward TM to downlink destination directly. Otherwise,
* forward to TM storage backend which stores TMs into files.
* Main telemetry receiver. All generated telemetry is funneled into
* this object.
* Main telemetry receiver. All generated telemetry is funneled into this object.
* @ingroup utility
* @author J. Meier, R. Mueller
*/
class PusTmFunnel : public TmFunnelBase {
public:
explicit PusTmFunnel(object_id_t objectId, TimeReaderIF &timeReader, StorageManagerIF &tmStore,
uint32_t messageDepth = 10);
PusTmFunnel(TmFunnelBase::FunnelCfg cfg, TimeReaderIF &timeReader, SdCardMountedIF &sdcMan);
[[nodiscard]] const char *getName() const override;
~PusTmFunnel() override;
ReturnValue_t performOperation(uint8_t operationCode);
private:
// Update TV stamp every 5 minutes
static constexpr dur_millis_t TV_UPDATE_INTERVAL_SECS = 60 * 5;
uint16_t sourceSequenceCount = 0;
TimeReaderIF &timeReader;
bool storesInitialized = false;
timeval currentTv{};
timeval lastTvUpdate{};
PersistentTmStore miscStore;
PersistentTmStore okStore;
PersistentTmStore notOkStore;
PersistentTmStore hkStore;
SdCardMountedIF &sdcMan;
ReturnValue_t handlePacket(TmTcMessage &message);
ReturnValue_t handleTmPacket(TmTcMessage &message);
void initStoresIfPossible(bool sdCardUsable);
ReturnValue_t initialize() override;
};
#endif // FSFW_EXAMPLE_COMMON_PUSTMFUNNEL_H

View File

@ -0,0 +1,85 @@
#include "Service15TmStorage.h"
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
#include "eive/objects.h"
#include "fsfw/tmstorage/TmStoreMessage.h"
using namespace returnvalue;
Service15TmStorage::Service15TmStorage(object_id_t objectId, uint16_t apid,
uint8_t numParallelCommands, uint16_t commandTimeoutSecs,
size_t queueDepth)
: CommandingServiceBase(objectId, apid, "PUS Service 15", 15, numParallelCommands,
commandTimeoutSecs, queueDepth) {}
ReturnValue_t Service15TmStorage::isValidSubservice(uint8_t subservice) {
switch (subservice) {
case (Subservices::DELETE_UP_TO):
case (Subservices::START_BY_TIME_RANGE_RETRIEVAL): {
return OK;
}
default: {
return FAILED;
}
}
}
ReturnValue_t Service15TmStorage::getMessageQueueAndObject(uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen,
MessageQueueId_t *id,
object_id_t *objectId) {
if (tcDataLen < 4) {
return CommandingServiceBase::INVALID_TC;
}
SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::NETWORK);
auto *frontendIF = ObjectManager::instance()->get<TmStoreFrontendSimpleIF>(*objectId);
if (frontendIF == nullptr) {
return CommandingServiceBase::INVALID_OBJECT;
}
*id = frontendIF->getCommandQueue();
return OK;
}
ReturnValue_t Service15TmStorage::prepareCommand(CommandMessage *message, uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen,
uint32_t *state, object_id_t objectId) {
if (subservice == Subservices::START_BY_TIME_RANGE_RETRIEVAL) {
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
// to time reading and reply handling
if (tcDataLen != 12) {
return INVALID_TC;
}
store_address_t storeId;
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
if (result != OK) {
return result;
}
// Store timestamps
TmStoreMessage::setDownlinkContentTimeMessage(message, storeId);
return CommandingServiceBase::EXECUTION_COMPLETE;
} else if (subservice == Subservices::DELETE_UP_TO) {
// TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
// to time reading and reply handling
if (tcDataLen != 8) {
return INVALID_TC;
}
store_address_t storeId;
ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
if (result != OK) {
return result;
}
// Store timestamps
TmStoreMessage::setDeleteContentTimeMessage(message, storeId);
return CommandingServiceBase::EXECUTION_COMPLETE;
}
return OK;
}
ReturnValue_t Service15TmStorage::handleReply(const CommandMessage *reply,
Command_t previousCommand, uint32_t *state,
CommandMessage *optionalNextCommand,
object_id_t objectId, bool *isStep) {
return OK;
}

View File

@ -0,0 +1,24 @@
#ifndef MISSION_TMTC_SERVICE15TMSTORAGE_H_
#define MISSION_TMTC_SERVICE15TMSTORAGE_H_
#include <fsfw/tmtcservices/CommandingServiceBase.h>
class Service15TmStorage : public CommandingServiceBase {
public:
enum Subservices : uint8_t { START_BY_TIME_RANGE_RETRIEVAL = 9, DELETE_UP_TO = 11 };
explicit Service15TmStorage(object_id_t objectId, uint16_t apid, uint8_t numParallelCommands,
uint16_t commandTimeoutSecs = 60, size_t queueDepth = 10);
private:
ReturnValue_t isValidSubservice(uint8_t subservice) override;
ReturnValue_t getMessageQueueAndObject(uint8_t subservice, const uint8_t* tcData,
size_t tcDataLen, MessageQueueId_t* id,
object_id_t* objectId) override;
ReturnValue_t prepareCommand(CommandMessage* message, uint8_t subservice, const uint8_t* tcData,
size_t tcDataLen, uint32_t* state, object_id_t objectId) override;
ReturnValue_t handleReply(const CommandMessage* reply, Command_t previousCommand, uint32_t* state,
CommandMessage* optionalNextCommand, object_id_t objectId,
bool* isStep) override;
};
#endif /* MISSION_TMTC_SERVICE15TMSTORAGE_H_ */

View File

@ -1,10 +1,12 @@
#include "TmFunnelBase.h"
#include <fsfw/tmtcservices/TmTcMessage.h>
#include "fsfw/ipc/QueueFactory.h"
TmFunnelBase::TmFunnelBase(object_id_t objectId, StorageManagerIF &tmStore, uint32_t tmMsgDepth)
: SystemObject(objectId), tmStore(tmStore) {
tmQueue = QueueFactory::instance()->createMessageQueue(tmMsgDepth);
TmFunnelBase::TmFunnelBase(FunnelCfg cfg)
: SystemObject(cfg.objectId), tmStore(cfg.tmStore), ipcStore(cfg.ipcStore) {
tmQueue = QueueFactory::instance()->createMessageQueue(cfg.tmMsgDepth);
}
TmFunnelBase::~TmFunnelBase() { QueueFactory::instance()->deleteMessageQueue(tmQueue); }
@ -18,3 +20,38 @@ void TmFunnelBase::addDestination(const char *name, const AcceptsTelemetryIF &do
auto queueId = downlinkDestination.getReportReceptionQueue(vcid);
destinations.emplace_back(name, queueId, vcid);
}
ReturnValue_t TmFunnelBase::sendPacketToDestinations(store_address_t origStoreId,
TmTcMessage &message,
const uint8_t *packetData, size_t size) {
ReturnValue_t result;
for (unsigned int idx = 0; idx < destinations.size(); idx++) {
const auto &dest = destinations[idx];
if (destinations.size() > 1) {
if (idx < destinations.size() - 1) {
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
// to bother with send order and where the data is deleted.
store_address_t storeId;
result = tmStore.addData(&storeId, packetData, size);
if (result == returnvalue::OK) {
message.setStorageId(storeId);
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PusTmFunnel::handlePacket: Store too full to create data copy"
<< std::endl;
#endif
}
} else {
message.setStorageId(origStoreId);
}
}
result = tmQueue->sendMessage(dest.queueId, &message);
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PusTmFunnel::handlePacket: Error sending TM to downlink handler" << std::endl;
#endif
tmStore.deleteData(message.getStorageId());
}
}
return result;
}

View File

@ -3,21 +3,36 @@
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/storagemanager/StorageManagerIF.h>
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
#include <fsfw/tmtcservices/TmTcMessage.h>
#include <vector>
class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
public:
TmFunnelBase(object_id_t objectId, StorageManagerIF& tmStore, uint32_t tmMsgDepth);
struct FunnelCfg {
FunnelCfg(object_id_t objId, StorageManagerIF& tmStore, StorageManagerIF& ipcStore,
uint32_t tmMsgDepth)
: objectId(objId), tmStore(tmStore), ipcStore(ipcStore), tmMsgDepth(tmMsgDepth) {}
object_id_t objectId;
StorageManagerIF& tmStore;
StorageManagerIF& ipcStore;
uint32_t tmMsgDepth;
};
explicit TmFunnelBase(FunnelCfg cfg);
void addDestination(const char* name, const AcceptsTelemetryIF& downlinkDestination,
uint8_t vcid = 0);
ReturnValue_t sendPacketToDestinations(store_address_t origStoreId, TmTcMessage& message,
const uint8_t* packetData, size_t size);
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
virtual ~TmFunnelBase();
~TmFunnelBase() override;
protected:
StorageManagerIF& tmStore;
StorageManagerIF& ipcStore;
struct Destination {
Destination(const char* name, MessageQueueId_t queueId, uint8_t virtualChannel)
: name(name), queueId(queueId), virtualChannel(virtualChannel) {}

View File

@ -1,3 +1,3 @@
target_sources(
${LIB_EIVE_MISSION} PRIVATE Timestamp.cpp ProgressPrinter.cpp Filenaming.cpp
GlobalConfigHandler.cpp)
GlobalConfigHandler.cpp DummySdCardManager.cpp)

View File

@ -0,0 +1,13 @@
#include "DummySdCardManager.h"
DummySdCardManager::DummySdCardManager(std::string prefix) : prefix(std::move(prefix)) {}
const char* DummySdCardManager::getCurrentMountPrefix() const { return prefix.c_str(); }
bool DummySdCardManager::isSdCardUsable(std::optional<sd::SdCard> sdCard) { return true; }
std::optional<sd::SdCard> DummySdCardManager::getPreferredSdCard() const { return std::nullopt; }
void DummySdCardManager::setActiveSdCard(sd::SdCard sdCard) {}
std::optional<sd::SdCard> DummySdCardManager::getActiveSdCard() const { return std::nullopt; }

View File

@ -2,11 +2,11 @@
#define BSP_LINUX_BOARD_RPISDCARDMANAGER_H_
#include <mission/memory/SdCardMountedIF.h>
class RPiSdCardManager : public SdCardMountedIF {
class DummySdCardManager : public SdCardMountedIF {
public:
RPiSdCardManager(std::string prefix);
const std::string& getCurrentMountPrefix() const override;
bool isSdCardUsable(sd::SdCard sdCard) override;
DummySdCardManager(std::string prefix);
const char* getCurrentMountPrefix() const override;
bool isSdCardUsable(std::optional<sd::SdCard> sdCard) override;
std::optional<sd::SdCard> getPreferredSdCard() const override;
void setActiveSdCard(sd::SdCard sdCard) override;
std::optional<sd::SdCard> getActiveSdCard() const override;

View File

@ -4,8 +4,10 @@ OBSW Release Checklist
# Pre-Release
1. Update version in `CMakeLists.txt`
2. Verify that the Q7S, Q7S EM and Host build are working
3. Wait for CI/CD results
2. Re-run the auto-formatters with the `scripts/auto-formatter.sh` script
3. Re-run the generators with `generators/gen.py all`
4. Verify that the Q7S, Q7S EM and Host build are working
5. Wait for CI/CD results
# Post-Release

2
tmtc

@ -1 +1 @@
Subproject commit 24f0d8e1a6a8ea1323623932e699326214c78159
Subproject commit 13014eb25053368f4fb9a445788aba71ff98de19

View File

@ -4,6 +4,7 @@ add_subdirectory(mocks)
target_sources(${UNITTEST_NAME} PRIVATE
main.cpp
testEnvironment.cpp
testStampInFilename.cpp
hdlcEncodingRw.cpp
printChar.cpp
)

View File

@ -0,0 +1,21 @@
#include <catch2/catch_test_macros.hpp>
#include <cinttypes>
#include "fsfw/timemanager/Clock.h"
TEST_CASE("Stamp in Filename", "[Stamp In Filename]") {
Clock::TimeOfDay_t tod;
std::string baseName = "verif";
std::string pathStr = "verif_2022-05-25T16:55:23Z.bin";
unsigned int underscorePos = pathStr.find_last_of('_');
std::string stampStr = pathStr.substr(underscorePos + 1);
float seconds = 0.0;
char* prefix = nullptr;
int count =
sscanf(stampStr.c_str(),
"%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32 "Z",
&tod.year, &tod.month, &tod.day, &tod.hour, &tod.minute, &tod.second);
static_cast<void>(count);
CHECK(count == 6);
}