Merge remote-tracking branch 'origin/develop' into thermal_controller
EIVE/eive-obsw/pipeline/pr-develop This commit looks good Details

This commit is contained in:
Robin Müller 2023-02-28 19:17:45 +01:00
commit 88db78fed9
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
139 changed files with 4458 additions and 1404 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

@ -16,6 +16,66 @@ will consitute of a breaking change warranting a new major release:
# [unreleased]
## Changed
- Move ACS board polling to separate worker thread.
## Fixed
- Linux GPS handler now checks the individual `*_SET` flags when analysing the `gpsd` struct.
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/400
# [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]
## Fixed
- ADIS1650X configuration set was empty because the local pool variables were not registered.
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/402
- ACS Controller: Correction for size of MEKF dataset and some optimization and fixes
for actuator control which lead to a crash.
PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/403
# [v1.31.0]
eive-tmtc: v2.16.0

View File

@ -10,7 +10,7 @@
cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR 1)
set(OBSW_VERSION_MINOR 31)
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/power/PowerSwitchIF.h"
@ -30,7 +31,6 @@
#include <dummies/CoreControllerDummy.h>
#include "dummies/helpers.h"
#include "mission/utility/GlobalConfigHandler.h"
#ifdef PLATFORM_UNIX
#include <fsfw_hal/linux/serial/SerialComIF.h>
@ -59,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);
}
@ -225,11 +219,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

@ -49,6 +49,8 @@ CoreController::CoreController(object_id_t objectId)
}
getCurrentBootCopy(CURRENT_CHIP, CURRENT_COPY);
initClockFromTimeFile();
} catch (const std::filesystem::filesystem_error &e) {
sif::error << "CoreController::CoreController: Failed with exception " << e.what() << std::endl;
}
@ -159,6 +161,9 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() {
}
sdcMan->setActiveSdCard(sdInfo.active);
currMntPrefix = sdcMan->getCurrentMountPrefix();
if (currMntPrefix == "") {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
if (BLOCKING_SD_INIT) {
result = initSdCardBlocking();
if (result != returnvalue::OK and result != SdCardManager::ALREADY_MOUNTED) {
@ -389,7 +394,7 @@ ReturnValue_t CoreController::sdStateMachine() {
sdInfo.cycleCount = 0;
return true;
} else if (sdInfo.cycleCount > 4) {
sif::warning << "CoreController::sdInitStateMachine: " << opPrintout << " takes too long"
sif::warning << "CoreController::sdStateMachine: " << opPrintout << " takes too long"
<< std::endl;
return false;
}
@ -401,7 +406,7 @@ ReturnValue_t CoreController::sdStateMachine() {
// Create updated status file
result = sdcMan->updateSdCardStateFile();
if (result != returnvalue::OK) {
sif::warning << "CoreController::initialize: Updating SD card state file failed"
sif::warning << "CoreController::sdStateMachine: Updating SD card state file failed"
<< std::endl;
}
sdInfo.commandExecuted = true;
@ -1219,6 +1224,9 @@ ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) {
}
}
wordIdx++;
if(wordIdx >= 10) {
break;
}
}
return returnvalue::OK;
}
@ -1266,10 +1274,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)) {
@ -1783,7 +1793,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()) {
@ -1793,14 +1803,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;
}
@ -1808,8 +1818,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);
@ -1837,6 +1847,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;
// Designated value for rechecking FIFO open
@ -221,6 +223,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
@ -258,7 +261,7 @@ class CoreController : public ExtendedControllerBase {
ReturnValue_t initClockFromTimeFile();
ReturnValue_t performSdCardCheck();
ReturnValue_t timeFileHandler();
ReturnValue_t backupTimeFileHandler();
ReturnValue_t initBootCopyFile();
ReturnValue_t initWatchdogFifo();
ReturnValue_t initSdCardBlocking();

View File

@ -1,8 +1,12 @@
#include "ObjectFactory.h"
#include <fsfw/subsystem/Subsystem.h>
#include <linux/devices/AcsBoardPolling.h>
#include <linux/devices/ImtqPollingTask.h>
#include <linux/devices/RwPollingTask.h>
#include <mission/devices/GyrL3gCustomHandler.h>
#include <mission/devices/MgmLis3CustomHandler.h>
#include <mission/devices/MgmRm3100CustomHandler.h>
#include <mission/system/objects/CamSwitcher.h>
#include "OBSWConfig.h"
@ -40,6 +44,7 @@
#include "linux/ipcore/PdecHandler.h"
#include "linux/ipcore/Ptme.h"
#include "linux/ipcore/PtmeConfig.h"
#include "mission/config/configfile.h"
#include "mission/csp/CspCookie.h"
#include "mission/system/fdir/AcsBoardFdir.h"
#include "mission/system/fdir/GomspacePowerFdir.h"
@ -53,10 +58,12 @@
#include "mission/system/tree/comModeTree.h"
#include "mission/system/tree/payloadModeTree.h"
#include "mission/system/tree/tcsModeTree.h"
#include "mission/utility/GlobalConfigHandler.h"
#include "tmtc/pusIds.h"
#if OBSW_TEST_LIBGPIOD == 1
#include "linux/boardtest/LibgpiodTest.h"
#endif
#include <mission/devices/GyrAdis1650XHandler.h>
#include <mission/devices/ImtqHandler.h>
#include <mission/devices/PcduHandler.h>
#include <mission/devices/SyrlinksHandler.h>
@ -83,7 +90,6 @@
#include "mission/core/GenericFactory.h"
#include "mission/devices/ACUHandler.h"
#include "mission/devices/BpxBatteryHandler.h"
#include "mission/devices/GyroADIS1650XHandler.h"
#include "mission/devices/HeaterHandler.h"
#include "mission/devices/Max31865PT1000Handler.h"
#include "mission/devices/P60DockHandler.h"
@ -239,8 +245,8 @@ ReturnValue_t ObjectFactory::createRadSensorComponent(LinuxLibgpioIF* gpioComIF,
return returnvalue::OK;
}
void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialComIF* uartComIF,
PowerSwitchIF& pwrSwitcher) {
void ObjectFactory::createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF* gpioComIF,
SerialComIF* uartComIF, PowerSwitchIF& pwrSwitcher) {
using namespace gpio;
GpioCookie* gpioCookieAcsBoard = new GpioCookie();
@ -343,14 +349,16 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialCo
static_cast<void>(fdir);
#if OBSW_ADD_ACS_BOARD == 1
new AcsBoardPolling(objects::ACS_BOARD_POLLING_TASK, spiComIF, *gpioComIF);
std::string spiDev = q7s::SPI_DEFAULT_DEV;
std::array<DeviceHandlerBase*, 8> assemblyChildren;
SpiCookie* spiCookie =
new SpiCookie(addresses::MGM_0_LIS3, gpioIds::MGM_0_LIS3_CS, MGMLIS3MDL::MAX_BUFFER_SIZE,
new SpiCookie(addresses::MGM_0_LIS3, gpioIds::MGM_0_LIS3_CS, mgmLis3::MAX_BUFFER_SIZE,
spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED);
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::ACS_BOARD_CS_TIMEOUT);
auto mgmLis3Handler0 = new MgmLIS3MDLHandler(
objects::MGM_0_LIS3_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, spi::LIS3_TRANSITION_DELAY);
auto mgmLis3Handler0 =
new MgmLis3CustomHandler(objects::MGM_0_LIS3_HANDLER, objects::ACS_BOARD_POLLING_TASK,
spiCookie, spi::LIS3_TRANSITION_DELAY);
fdir = new AcsBoardFdir(objects::MGM_0_LIS3_HANDLER);
mgmLis3Handler0->setCustomFdir(fdir);
assemblyChildren[0] = mgmLis3Handler0;
@ -362,12 +370,12 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialCo
mgmLis3Handler->enablePeriodicPrintouts(true, 10);
#endif
spiCookie =
new SpiCookie(addresses::MGM_1_RM3100, gpioIds::MGM_1_RM3100_CS, RM3100::MAX_BUFFER_SIZE,
new SpiCookie(addresses::MGM_1_RM3100, gpioIds::MGM_1_RM3100_CS, mgmRm3100::MAX_BUFFER_SIZE,
spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED);
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::ACS_BOARD_CS_TIMEOUT);
auto mgmRm3100Handler1 =
new MgmRM3100Handler(objects::MGM_1_RM3100_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie,
spi::RM3100_TRANSITION_DELAY);
new MgmRm3100CustomHandler(objects::MGM_1_RM3100_HANDLER, objects::ACS_BOARD_POLLING_TASK,
spiCookie, spi::RM3100_TRANSITION_DELAY);
fdir = new AcsBoardFdir(objects::MGM_1_RM3100_HANDLER);
mgmRm3100Handler1->setCustomFdir(fdir);
assemblyChildren[1] = mgmRm3100Handler1;
@ -378,12 +386,12 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialCo
#if OBSW_DEBUG_ACS == 1
mgmRm3100Handler->enablePeriodicPrintouts(true, 10);
#endif
spiCookie =
new SpiCookie(addresses::MGM_2_LIS3, gpioIds::MGM_2_LIS3_CS, MGMLIS3MDL::MAX_BUFFER_SIZE,
spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED);
spiCookie = new SpiCookie(addresses::MGM_2_LIS3, gpioIds::MGM_2_LIS3_CS, mgmLis3::MAX_BUFFER_SIZE,
spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED);
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::ACS_BOARD_CS_TIMEOUT);
auto* mgmLis3Handler2 = new MgmLIS3MDLHandler(
objects::MGM_2_LIS3_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, spi::LIS3_TRANSITION_DELAY);
auto* mgmLis3Handler2 =
new MgmLis3CustomHandler(objects::MGM_2_LIS3_HANDLER, objects::ACS_BOARD_POLLING_TASK,
spiCookie, spi::LIS3_TRANSITION_DELAY);
fdir = new AcsBoardFdir(objects::MGM_2_LIS3_HANDLER);
mgmLis3Handler2->setCustomFdir(fdir);
assemblyChildren[2] = mgmLis3Handler2;
@ -395,12 +403,12 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialCo
mgmLis3Handler->enablePeriodicPrintouts(true, 10);
#endif
spiCookie =
new SpiCookie(addresses::MGM_3_RM3100, gpioIds::MGM_3_RM3100_CS, RM3100::MAX_BUFFER_SIZE,
new SpiCookie(addresses::MGM_3_RM3100, gpioIds::MGM_3_RM3100_CS, mgmRm3100::MAX_BUFFER_SIZE,
spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED);
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::ACS_BOARD_CS_TIMEOUT);
auto* mgmRm3100Handler3 =
new MgmRM3100Handler(objects::MGM_3_RM3100_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie,
spi::RM3100_TRANSITION_DELAY);
new MgmRm3100CustomHandler(objects::MGM_3_RM3100_HANDLER, objects::ACS_BOARD_POLLING_TASK,
spiCookie, spi::RM3100_TRANSITION_DELAY);
fdir = new AcsBoardFdir(objects::MGM_3_RM3100_HANDLER);
mgmRm3100Handler3->setCustomFdir(fdir);
assemblyChildren[3] = mgmRm3100Handler3;
@ -414,12 +422,12 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialCo
// Commented until ACS board V2 in in clean room again
// Gyro 0 Side A
spiCookie =
new SpiCookie(addresses::GYRO_0_ADIS, gpioIds::GYRO_0_ADIS_CS, ADIS1650X::MAXIMUM_REPLY_SIZE,
new SpiCookie(addresses::GYRO_0_ADIS, gpioIds::GYRO_0_ADIS_CS, adis1650x::MAXIMUM_REPLY_SIZE,
spi::DEFAULT_ADIS16507_MODE, spi::DEFAULT_ADIS16507_SPEED);
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::ACS_BOARD_CS_TIMEOUT);
auto adisHandler =
new GyroADIS1650XHandler(objects::GYRO_0_ADIS_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie,
ADIS1650X::Type::ADIS16505);
new GyrAdis1650XHandler(objects::GYRO_0_ADIS_HANDLER, objects::ACS_BOARD_POLLING_TASK,
spiCookie, adis1650x::Type::ADIS16505);
fdir = new AcsBoardFdir(objects::GYRO_0_ADIS_HANDLER);
adisHandler->setCustomFdir(fdir);
assemblyChildren[4] = adisHandler;
@ -431,11 +439,12 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialCo
adisHandler->enablePeriodicPrintouts(true, 10);
#endif
// Gyro 1 Side A
spiCookie = new SpiCookie(addresses::GYRO_1_L3G, gpioIds::GYRO_1_L3G_CS, L3GD20H::MAX_BUFFER_SIZE,
spiCookie = new SpiCookie(addresses::GYRO_1_L3G, gpioIds::GYRO_1_L3G_CS, l3gd20h::MAX_BUFFER_SIZE,
spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::ACS_BOARD_CS_TIMEOUT);
auto gyroL3gHandler1 = new GyroHandlerL3GD20H(
objects::GYRO_1_L3G_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, spi::L3G_TRANSITION_DELAY);
auto gyroL3gHandler1 =
new GyrL3gCustomHandler(objects::GYRO_1_L3G_HANDLER, objects::ACS_BOARD_POLLING_TASK,
spiCookie, spi::L3G_TRANSITION_DELAY);
fdir = new AcsBoardFdir(objects::GYRO_1_L3G_HANDLER);
gyroL3gHandler1->setCustomFdir(fdir);
assemblyChildren[5] = gyroL3gHandler1;
@ -448,11 +457,12 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialCo
#endif
// Gyro 2 Side B
spiCookie =
new SpiCookie(addresses::GYRO_2_ADIS, gpioIds::GYRO_2_ADIS_CS, ADIS1650X::MAXIMUM_REPLY_SIZE,
new SpiCookie(addresses::GYRO_2_ADIS, gpioIds::GYRO_2_ADIS_CS, adis1650x::MAXIMUM_REPLY_SIZE,
spi::DEFAULT_ADIS16507_MODE, spi::DEFAULT_ADIS16507_SPEED);
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::ACS_BOARD_CS_TIMEOUT);
adisHandler = new GyroADIS1650XHandler(objects::GYRO_2_ADIS_HANDLER, objects::SPI_MAIN_COM_IF,
spiCookie, ADIS1650X::Type::ADIS16505);
adisHandler =
new GyrAdis1650XHandler(objects::GYRO_2_ADIS_HANDLER, objects::ACS_BOARD_POLLING_TASK,
spiCookie, adis1650x::Type::ADIS16505);
fdir = new AcsBoardFdir(objects::GYRO_2_ADIS_HANDLER);
adisHandler->setCustomFdir(fdir);
assemblyChildren[6] = adisHandler;
@ -461,11 +471,12 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialCo
adisHandler->setToGoToNormalModeImmediately();
#endif
// Gyro 3 Side B
spiCookie = new SpiCookie(addresses::GYRO_3_L3G, gpioIds::GYRO_3_L3G_CS, L3GD20H::MAX_BUFFER_SIZE,
spiCookie = new SpiCookie(addresses::GYRO_3_L3G, gpioIds::GYRO_3_L3G_CS, l3gd20h::MAX_BUFFER_SIZE,
spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
spiCookie->setMutexParams(MutexIF::TimeoutType::WAITING, spi::ACS_BOARD_CS_TIMEOUT);
auto gyroL3gHandler3 = new GyroHandlerL3GD20H(
objects::GYRO_3_L3G_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, spi::L3G_TRANSITION_DELAY);
auto gyroL3gHandler3 =
new GyrL3gCustomHandler(objects::GYRO_3_L3G_HANDLER, objects::ACS_BOARD_POLLING_TASK,
spiCookie, spi::L3G_TRANSITION_DELAY);
fdir = new AcsBoardFdir(objects::GYRO_3_L3G_HANDLER);
gyroL3gHandler3->setCustomFdir(fdir);
assemblyChildren[7] = gyroL3gHandler3;

View File

@ -2,6 +2,7 @@
#define BSP_Q7S_OBJECTFACTORY_H_
#include <fsfw/returnvalues/returnvalue.h>
#include <fsfw_hal/linux/spi/SpiComIF.h>
#include <mission/devices/HeaterHandler.h>
#include <mission/system/objects/Stack5VHandler.h>
#include <mission/tmtc/CcsdsIpCoreHandler.h>
@ -31,7 +32,7 @@ void createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF,
PowerSwitchIF* pwrSwitcher, Stack5VHandler& stackHandler);
void createTmpComponents();
ReturnValue_t createRadSensorComponent(LinuxLibgpioIF* gpioComIF, Stack5VHandler& handler);
void createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialComIF* uartComIF,
void createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF* gpioComIF, SerialComIF* uartComIF,
PowerSwitchIF& pwrSwitcher);
void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable,
HeaterHandler*& heaterHandler);

View File

@ -187,14 +187,21 @@ 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_ACS_BOARD == 1
PeriodicTaskIF* acsBrdPolling = factory->createPeriodicTask(
"ACS_BOARD_POLLING", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc);
result = acsBrdPolling->addComponent(objects::ACS_BOARD_POLLING_TASK);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("ACS_BOARD_POLLING", objects::ACS_BOARD_POLLING_TASK);
}
#endif
#if OBSW_ADD_RW == 1
PeriodicTaskIF* rwPolling = factory->createPeriodicTask(
@ -353,6 +360,9 @@ void scheduling::initTasks() {
#if OBSW_ADD_SA_DEPL == 1
solarArrayDeplTask->startTask();
#endif
#if OBSW_ADD_ACS_BOARD == 1
acsBrdPolling->startTask();
#endif
#if OBSW_ADD_MGT == 1
imtqPolling->startTask();
#endif
@ -378,9 +388,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;
@ -42,7 +43,7 @@ void ObjectFactory::produce(void* args) {
#endif
#if OBSW_ADD_ACS_BOARD == 1
createAcsBoardComponents(gpioComIF, uartComIF, *pwrSwitcher);
createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher);
#endif
HeaterHandler* heaterHandler;
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);

View File

@ -22,7 +22,7 @@ ReturnValue_t FilesystemHelper::checkPath(std::string path) {
}
} else if (path.substr(0, sizeof(config::SD_1_MOUNT_POINT)) ==
std::string(config::SD_1_MOUNT_POINT)) {
if (!sdcMan->isSdCardUsable(sd::SLOT_0)) {
if (!sdcMan->isSdCardUsable(sd::SLOT_1)) {
sif::warning << "FilesystemHelper::checkPath: SD card 1 not mounted" << std::endl;
return SD_NOT_MOUNTED;
}

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) {
@ -505,9 +508,9 @@ bool SdCardManager::isSdCardUsable(std::optional<sd::SdCard> sdCard) {
ReturnValue_t SdCardManager::isSdCardMountedReadOnly(sd::SdCard sdcard, bool& readOnly) {
std::ostringstream command;
if (sdcard == sd::SdCard::SLOT_0) {
command << "grep -q '" << config::SD_0_MOUNT_POINT << " ext4 ro,' /proc/mounts";
command << "grep -q '" << config::SD_0_MOUNT_POINT << " ext4 rw,' /proc/mounts";
} else if (sdcard == sd::SdCard::SLOT_1) {
command << "grep -q '" << config::SD_1_MOUNT_POINT << " ext4 ro,' /proc/mounts";
command << "grep -q '" << config::SD_1_MOUNT_POINT << " ext4 rw,' /proc/mounts";
} else {
return returnvalue::FAILED;
}
@ -516,18 +519,9 @@ ReturnValue_t SdCardManager::isSdCardMountedReadOnly(sd::SdCard sdcard, bool& re
return result;
}
result = cmdExecutor.execute();
if (result != returnvalue::OK) {
int exitStatus = cmdExecutor.getLastError();
if (exitStatus == 1) {
readOnly = false;
return returnvalue::OK;
}
return result;
}
auto& readVec = cmdExecutor.getReadVector();
size_t readLen = strnlen(readVec.data(), readVec.size());
if (readLen == 0) {
if (result == returnvalue::OK) {
readOnly = false;
return result;
}
readOnly = true;
return returnvalue::OK;

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

@ -1 +1 @@
target_sources(${OBSW_NAME} PRIVATE scratchApi.cpp)
target_sources(${OBSW_NAME} PRIVATE scratchApi.cpp LocalParameterHandler.cpp)

View File

@ -0,0 +1,41 @@
#include "LocalParameterHandler.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
LocalParameterHandler::LocalParameterHandler(std::string sdRelativeName, SdCardMountedIF* sdcMan)
: NVMParameterBase(), sdRelativeName(sdRelativeName), sdcMan(sdcMan) {}
LocalParameterHandler::~LocalParameterHandler() {}
ReturnValue_t LocalParameterHandler::initialize() {
ReturnValue_t result = updateFullName();
if (result != returnvalue::OK) {
return result;
}
result = readJsonFile();
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
ReturnValue_t LocalParameterHandler::writeJsonFile() {
ReturnValue_t result = updateFullName();
if (result != returnvalue::OK) {
return result;
}
return NVMParameterBase::writeJsonFile();
}
ReturnValue_t LocalParameterHandler::updateFullName() {
std::string mountPrefix;
auto activeSd = sdcMan->getActiveSdCard();
if (activeSd and sdcMan->isSdCardUsable(activeSd.value())) {
mountPrefix = sdcMan->getCurrentMountPrefix();
} else {
return SD_NOT_READY;
}
std::string fullname = mountPrefix + "/" + sdRelativeName;
NVMParameterBase::setFullName(fullname);
return returnvalue::OK;
}

View File

@ -0,0 +1,106 @@
#ifndef BSP_Q7S_MEMORY_LOCALPARAMETERHANDLER_H_
#define BSP_Q7S_MEMORY_LOCALPARAMETERHANDLER_H_
#include <mission/memory/NVMParameterBase.h>
#include <mission/memory/SdCardMountedIF.h>
#include <string>
/**
* @brief Class to handle persistent parameters
*
*/
class LocalParameterHandler : public NVMParameterBase {
public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_PARAM_HANDLER;
static constexpr ReturnValue_t SD_NOT_READY = returnvalue::makeCode(INTERFACE_ID, 0);
/**
* @brief Constructor
*
* @param sdRelativeName Absolute name of json file relative to mount
* directory of SD card.
* E.g. conf/example.json
* @param sdcMan Pointer to SD card manager
*/
LocalParameterHandler(std::string sdRelativeName, SdCardMountedIF* sdcMan);
virtual ~LocalParameterHandler();
/**
* @brief Will initialize the local parameter handler
*
* @return OK if successful, otherwise error return value
*/
ReturnValue_t initialize();
/**
* @brief Function to add parameter to json file. If the json file does
* not yet exist it will be created here.
*
* @param key The string to identify the parameter
* @param value The value to set for this parameter
*
* @return OK if successful, otherwise error return value
*
* @details The function will add the parameter only if it is not already
* present in the json file
*/
template <typename T>
ReturnValue_t addParameter(std::string key, T value);
/**
* @brief Function will update a parameter which already exists in the json
* file
*
* @param key The unique string to identify the parameter to update
* @param value The new new value to set
*
* @return OK if successful, otherwise error return value
*/
template <typename T>
ReturnValue_t updateParameter(std::string key, T value);
private:
// Name relative to mount point of SD card where parameters will be stored
std::string sdRelativeName;
SdCardMountedIF* sdcMan;
virtual ReturnValue_t writeJsonFile();
/**
* @brief This function sets the name of the json file dependent on the
* currently active SD card
*
* @return OK if successful, otherwise error return value
*/
ReturnValue_t updateFullName();
};
template <typename T>
inline ReturnValue_t LocalParameterHandler::addParameter(std::string key, T value) {
ReturnValue_t result = insertValue(key, value);
if (result != returnvalue::OK) {
return result;
}
result = writeJsonFile();
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
template <typename T>
inline ReturnValue_t LocalParameterHandler::updateParameter(std::string key, T value) {
ReturnValue_t result = setValue(key, value);
if (result != returnvalue::OK) {
return result;
}
result = writeJsonFile();
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
#endif /* BSP_Q7S_MEMORY_LOCALPARAMETERHANDLER_H_ */

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

@ -37,6 +37,8 @@ enum : uint8_t {
CONFIGHANDLER = 139,
CORE = 140,
TCS_CONTROLLER = 141,
COM_SUBSYSTEM = 142,
PERSISTENT_TM_STORE = 143,
COMMON_SUBSYSTEM_ID_END
};

View File

@ -123,7 +123,9 @@ enum commonObjects : uint32_t {
// CCSDS_IP_CORE_BRIDGE = 0x73500000,
/* 0x49 ('I') for Communication Interfaces */
SPI_RTD_COM_IF = 0x49020006,
ACS_BOARD_POLLING_TASK = 0x49060004,
RW_POLLING_TASK = 0x49060005,
SPI_RTD_COM_IF = 0x49060006,
// 0x60 for other stuff
HEATER_0_PLOC_PROC_BRD = 0x60000000,
@ -152,6 +154,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,15 @@ 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
SD_CARD_MANAGER, // SDMA
LOCAL_PARAM_HANDLER, // LPH
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

@ -1,6 +1,6 @@
#include "GyroAdisDummy.h"
#include "mission/devices/devicedefinitions/GyroADIS1650XDefinitions.h"
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
GyroAdisDummy::GyroAdisDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie), dataset(this) {}
@ -40,13 +40,13 @@ uint32_t GyroAdisDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { r
ReturnValue_t GyroAdisDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(ADIS1650X::ANG_VELOC_X, new PoolEntry<double>({-0.5}, true));
localDataPoolMap.emplace(ADIS1650X::ANG_VELOC_Y, new PoolEntry<double>({0.2}, true));
localDataPoolMap.emplace(ADIS1650X::ANG_VELOC_Z, new PoolEntry<double>({-1.2}, true));
localDataPoolMap.emplace(ADIS1650X::ACCELERATION_X, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(ADIS1650X::ACCELERATION_Y, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(ADIS1650X::ACCELERATION_Z, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(ADIS1650X::TEMPERATURE, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(adis1650x::ANG_VELOC_X, new PoolEntry<double>({-0.5}, true));
localDataPoolMap.emplace(adis1650x::ANG_VELOC_Y, new PoolEntry<double>({0.2}, true));
localDataPoolMap.emplace(adis1650x::ANG_VELOC_Z, new PoolEntry<double>({-1.2}, true));
localDataPoolMap.emplace(adis1650x::ACCELERATION_X, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(adis1650x::ACCELERATION_Y, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(adis1650x::ACCELERATION_Z, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(adis1650x::TEMPERATURE, new PoolEntry<float>({0.0}));
return returnvalue::OK;
}

View File

@ -2,8 +2,7 @@
#define DUMMIES_GYROADISDUMMY_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include "mission/devices/devicedefinitions/GyroADIS1650XDefinitions.h"
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
class GyroAdisDummy : public DeviceHandlerBase {
public:

View File

@ -1,6 +1,6 @@
#include "GyroL3GD20Dummy.h"
#include "fsfw_hal/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h"
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
GyroL3GD20Dummy::GyroL3GD20Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie) {}
@ -40,9 +40,9 @@ uint32_t GyroL3GD20Dummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
ReturnValue_t GyroL3GD20Dummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X, new PoolEntry<float>({1.2}, true));
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, new PoolEntry<float>({-0.1}, true));
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Z, new PoolEntry<float>({0.7}, true));
localDataPoolMap.emplace(L3GD20H::TEMPERATURE, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(l3gd20h::ANG_VELOC_X, new PoolEntry<float>({1.2}, true));
localDataPoolMap.emplace(l3gd20h::ANG_VELOC_Y, new PoolEntry<float>({-0.1}, true));
localDataPoolMap.emplace(l3gd20h::ANG_VELOC_Z, new PoolEntry<float>({0.7}, true));
localDataPoolMap.emplace(l3gd20h::TEMPERATURE, new PoolEntry<float>({0.0}));
return returnvalue::OK;
}

View File

@ -1,6 +1,6 @@
#include "MgmLIS3MDLDummy.h"
#include "fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h"
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h>
MgmLIS3MDLDummy::MgmLIS3MDLDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie), dataset(this) {}
@ -40,8 +40,8 @@ uint32_t MgmLIS3MDLDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
ReturnValue_t MgmLIS3MDLDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(MGMLIS3MDL::TEMPERATURE_CELCIUS, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTHS,
localDataPoolMap.emplace(mgmLis3::TEMPERATURE_CELCIUS, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(mgmLis3::FIELD_STRENGTHS,
new PoolEntry<float>({1.02, 0.56, -0.78}, true));
return returnvalue::OK;
}

View File

@ -2,8 +2,7 @@
#define DUMMIES_MGMLIS3MDLDUMMY_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include "fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h"
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h>
class MgmLIS3MDLDummy : public DeviceHandlerBase {
public:
@ -17,7 +16,7 @@ class MgmLIS3MDLDummy : public DeviceHandlerBase {
virtual ~MgmLIS3MDLDummy();
protected:
MGMLIS3MDL::MgmPrimaryDataset dataset;
mgmLis3::MgmPrimaryDataset dataset;
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;

View File

@ -36,7 +36,7 @@ uint32_t MgmRm3100Dummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
ReturnValue_t MgmRm3100Dummy::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
localDataPoolMap.emplace(RM3100::FIELD_STRENGTHS,
localDataPoolMap.emplace(mgmRm3100::FIELD_STRENGTHS,
new PoolEntry<float>({0.87, -0.95, 0.11}, true));
return returnvalue::OK;
}

View File

@ -1,8 +1,9 @@
#ifndef DUMMIES_MGMRM3100DUMMY_H_
#define DUMMIES_MGMRM3100DUMMY_H_
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmRm3100Helpers.h>
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw_hal/devicehandlers/devicedefinitions/MgmRM3100HandlerDefs.h"
class MgmRm3100Dummy : public DeviceHandlerBase {
public:
@ -10,7 +11,7 @@ class MgmRm3100Dummy : public DeviceHandlerBase {
virtual ~MgmRm3100Dummy();
protected:
RM3100::Rm3100PrimaryDataset dataset;
mgmRm3100::Rm3100PrimaryDataset dataset;
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;

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,6 +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_CURRENTS, new PoolEntry<int16_t>(9));
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 511d07c0c78de7b1850e341dfcf8be7589f3c523

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

@ -0,0 +1,730 @@
#include "AcsBoardPolling.h"
#include <fcntl.h>
#include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/tasks/SemaphoreFactory.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h>
#include <fsfw_hal/linux/UnixFileGuard.h>
#include <fsfw_hal/linux/spi/SpiCookie.h>
#include <fsfw_hal/linux/utility.h>
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
#include <sys/ioctl.h>
#include "devices/gpioIds.h"
using namespace returnvalue;
AcsBoardPolling::AcsBoardPolling(object_id_t objectId, SpiComIF& lowLevelComIF, GpioIF& gpioIF)
: SystemObject(objectId), spiComIF(lowLevelComIF), gpioIF(gpioIF) {
semaphore = SemaphoreFactory::instance()->createBinarySemaphore();
semaphore->acquire();
ipcLock = MutexFactory::instance()->createMutex();
}
ReturnValue_t AcsBoardPolling::performOperation(uint8_t operationCode) {
while (true) {
ipcLock->lockMutex();
state = InternalState::IDLE;
ipcLock->unlockMutex();
semaphore->acquire();
// Give all tasks or the PST some time to submit all consecutive requests.
TaskFactory::delayTask(2);
gyroAdisHandler(gyro0Adis);
gyroAdisHandler(gyro2Adis);
gyroL3gHandler(gyro1L3g);
gyroL3gHandler(gyro3L3g);
mgmRm3100Handler(mgm1Rm3100);
mgmRm3100Handler(mgm3Rm3100);
mgmLis3Handler(mgm0Lis3);
mgmLis3Handler(mgm2Lis3);
// To prevent task being not reactivated by tardy tasks
TaskFactory::delayTask(20);
}
return returnvalue::OK;
}
ReturnValue_t AcsBoardPolling::initialize() { return returnvalue::OK; }
ReturnValue_t AcsBoardPolling::initializeInterface(CookieIF* cookie) {
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
if (spiCookie == nullptr) {
return returnvalue::FAILED;
}
switch (spiCookie->getChipSelectPin()) {
case (gpioIds::MGM_0_LIS3_CS): {
mgm0Lis3.cookie = spiCookie;
break;
}
case (gpioIds::MGM_1_RM3100_CS): {
mgm1Rm3100.cookie = spiCookie;
break;
}
case (gpioIds::MGM_2_LIS3_CS): {
mgm2Lis3.cookie = spiCookie;
break;
}
case (gpioIds::MGM_3_RM3100_CS): {
mgm3Rm3100.cookie = spiCookie;
break;
}
case (gpioIds::GYRO_0_ADIS_CS): {
gyro0Adis.cookie = spiCookie;
break;
}
case (gpioIds::GYRO_1_L3G_CS): {
gyro1L3g.cookie = spiCookie;
break;
}
case (gpioIds::GYRO_2_ADIS_CS): {
gyro2Adis.cookie = spiCookie;
break;
}
case (gpioIds::GYRO_3_L3G_CS): {
gyro3L3g.cookie = spiCookie;
break;
}
default: {
sif::error << "AcsBoardPollingTask: invalid spi cookie" << std::endl;
}
}
return spiComIF.initializeInterface(cookie);
}
ReturnValue_t AcsBoardPolling::sendMessage(CookieIF* cookie, const uint8_t* sendData,
size_t sendLen) {
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
if (spiCookie == nullptr) {
return returnvalue::FAILED;
}
auto handleAdisRequest = [&](GyroAdis& adis) {
if (sendLen != sizeof(acs::Adis1650XRequest)) {
sif::error << "AcsBoardPolling: invalid adis request send length";
adis.replyResult = returnvalue::FAILED;
return returnvalue::FAILED;
}
auto* req = reinterpret_cast<const acs::Adis1650XRequest*>(sendData);
MutexGuard mg(ipcLock);
if (req->mode != adis.mode) {
if (req->mode == acs::SimpleSensorMode::NORMAL) {
adis.type = req->type;
adis.countdown.setTimeout(adis1650x::START_UP_TIME);
adis.countdown.resetTimer();
if (adis.type == adis1650x::Type::ADIS16507) {
adis.ownReply.data.accelScaling = adis1650x::ACCELEROMETER_RANGE_16507;
} else if (adis.type == adis1650x::Type::ADIS16505) {
adis.ownReply.data.accelScaling = adis1650x::ACCELEROMETER_RANGE_16505;
} else {
sif::warning << "AcsBoardPolling: Unknown ADIS type" << std::endl;
}
adis.performStartup = true;
} else if (req->mode == acs::SimpleSensorMode::OFF) {
adis.performStartup = false;
adis.ownReply.cfgWasSet = false;
adis.ownReply.dataWasSet = false;
}
adis.mode = req->mode;
}
return returnvalue::OK;
};
auto handleL3gRequest = [&](GyroL3g& gyro) {
if (sendLen != sizeof(acs::GyroL3gRequest)) {
sif::error << "AcsBoardPolling: invalid l3g request send length";
gyro.replyResult = returnvalue::FAILED;
return returnvalue::FAILED;
}
auto* req = reinterpret_cast<const acs::GyroL3gRequest*>(sendData);
MutexGuard mg(ipcLock);
if (req->mode != gyro.mode) {
if (req->mode == acs::SimpleSensorMode::NORMAL) {
std::memcpy(gyro.sensorCfg, req->ctrlRegs, 5);
gyro.performStartup = true;
} else {
gyro.ownReply.cfgWasSet = false;
}
gyro.mode = req->mode;
}
return returnvalue::OK;
};
auto handleLis3Request = [&](MgmLis3& mgm) {
if (sendLen != sizeof(acs::MgmLis3Request)) {
sif::error << "AcsBoardPolling: invalid lis3 request send length";
mgm.replyResult = returnvalue::FAILED;
return returnvalue::FAILED;
}
auto* req = reinterpret_cast<const acs::MgmLis3Request*>(sendData);
MutexGuard mg(ipcLock);
if (req->mode != mgm.mode) {
if (req->mode == acs::SimpleSensorMode::NORMAL) {
mgm.performStartup = true;
} else {
mgm.ownReply.dataWasSet = false;
mgm.ownReply.temperatureWasSet = false;
}
mgm.mode = req->mode;
}
return returnvalue::OK;
};
auto handleRm3100Request = [&](MgmRm3100& mgm) {
if (sendLen != sizeof(acs::MgmRm3100Request)) {
sif::error << "AcsBoardPolling: invalid rm3100 request send length";
mgm.replyResult = returnvalue::FAILED;
return returnvalue::FAILED;
}
auto* req = reinterpret_cast<const acs::MgmRm3100Request*>(sendData);
MutexGuard mg(ipcLock);
if (req->mode != mgm.mode) {
if (req->mode == acs::SimpleSensorMode::NORMAL) {
mgm.performStartup = true;
} else {
mgm.ownReply.dataWasRead = false;
}
mgm.mode = req->mode;
}
return returnvalue::OK;
};
switch (spiCookie->getChipSelectPin()) {
case (gpioIds::MGM_0_LIS3_CS): {
handleLis3Request(mgm0Lis3);
break;
}
case (gpioIds::MGM_1_RM3100_CS): {
handleRm3100Request(mgm1Rm3100);
break;
}
case (gpioIds::MGM_2_LIS3_CS): {
handleLis3Request(mgm2Lis3);
break;
}
case (gpioIds::MGM_3_RM3100_CS): {
handleRm3100Request(mgm3Rm3100);
break;
}
case (gpioIds::GYRO_0_ADIS_CS): {
handleAdisRequest(gyro0Adis);
break;
}
case (gpioIds::GYRO_2_ADIS_CS): {
handleAdisRequest(gyro2Adis);
break;
}
case (gpioIds::GYRO_1_L3G_CS): {
handleL3gRequest(gyro1L3g);
break;
}
case (gpioIds::GYRO_3_L3G_CS): {
handleL3gRequest(gyro3L3g);
break;
}
}
MutexGuard mg(ipcLock);
if (state == InternalState::IDLE) {
state = InternalState::BUSY;
semaphore->release();
}
return returnvalue::OK;
}
ReturnValue_t AcsBoardPolling::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
ReturnValue_t AcsBoardPolling::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
return returnvalue::OK;
}
ReturnValue_t AcsBoardPolling::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
size_t* size) {
SpiCookie* spiCookie = dynamic_cast<SpiCookie*>(cookie);
if (spiCookie == nullptr) {
return returnvalue::FAILED;
}
MutexGuard mg(ipcLock);
auto handleAdisReply = [&](GyroAdis& gyro) {
std::memcpy(&gyro.readerReply, &gyro.ownReply, sizeof(acs::Adis1650XReply));
*buffer = reinterpret_cast<uint8_t*>(&gyro.readerReply);
*size = sizeof(acs::Adis1650XReply);
return gyro.replyResult;
};
auto handleL3gReply = [&](GyroL3g& gyro) {
std::memcpy(&gyro.readerReply, &gyro.ownReply, sizeof(acs::GyroL3gReply));
*buffer = reinterpret_cast<uint8_t*>(&gyro.readerReply);
*size = sizeof(acs::GyroL3gReply);
return gyro.replyResult;
};
auto handleRm3100Reply = [&](MgmRm3100& mgm) {
std::memcpy(&mgm.readerReply, &mgm.ownReply, sizeof(acs::MgmRm3100Reply));
*buffer = reinterpret_cast<uint8_t*>(&mgm.readerReply);
*size = sizeof(acs::MgmRm3100Reply);
return mgm.replyResult;
};
auto handleLis3Reply = [&](MgmLis3& mgm) {
std::memcpy(&mgm.readerReply, &mgm.ownReply, sizeof(acs::MgmLis3Reply));
*buffer = reinterpret_cast<uint8_t*>(&mgm.readerReply);
*size = sizeof(acs::MgmLis3Reply);
return mgm.replyResult;
};
switch (spiCookie->getChipSelectPin()) {
case (gpioIds::MGM_0_LIS3_CS): {
return handleLis3Reply(mgm0Lis3);
}
case (gpioIds::MGM_1_RM3100_CS): {
return handleRm3100Reply(mgm1Rm3100);
}
case (gpioIds::MGM_2_LIS3_CS): {
return handleLis3Reply(mgm2Lis3);
}
case (gpioIds::MGM_3_RM3100_CS): {
return handleRm3100Reply(mgm3Rm3100);
}
case (gpioIds::GYRO_0_ADIS_CS): {
return handleAdisReply(gyro0Adis);
}
case (gpioIds::GYRO_2_ADIS_CS): {
return handleAdisReply(gyro2Adis);
}
case (gpioIds::GYRO_1_L3G_CS): {
return handleL3gReply(gyro1L3g);
}
case (gpioIds::GYRO_3_L3G_CS): {
return handleL3gReply(gyro3L3g);
}
}
return returnvalue::OK;
}
void AcsBoardPolling::gyroL3gHandler(GyroL3g& l3g) {
ReturnValue_t result;
acs::SimpleSensorMode mode;
bool gyroPerformStartup;
{
MutexGuard mg(ipcLock);
mode = l3g.mode;
gyroPerformStartup = l3g.performStartup;
}
if (mode == acs::SimpleSensorMode::NORMAL) {
if (gyroPerformStartup) {
cmdBuf[0] = l3gd20h::CTRL_REG_1 | l3gd20h::AUTO_INCREMENT_MASK;
std::memcpy(cmdBuf.data() + 1, l3g.sensorCfg, 5);
result = spiComIF.sendMessage(l3g.cookie, cmdBuf.data(), 6);
if (result != returnvalue::OK) {
l3g.replyResult = returnvalue::OK;
}
// Ignore useless reply and red config
cmdBuf[0] = l3gd20h::CTRL_REG_1 | l3gd20h::AUTO_INCREMENT_MASK | l3gd20h::READ_MASK;
std::memset(cmdBuf.data() + 1, 0, 5);
result = spiComIF.sendMessage(l3g.cookie, cmdBuf.data(), 6);
if (result != returnvalue::OK) {
l3g.replyResult = returnvalue::OK;
}
result = spiComIF.readReceivedMessage(l3g.cookie, &rawReply, &dummy);
if (result != returnvalue::OK) {
l3g.replyResult = returnvalue::OK;
}
MutexGuard mg(ipcLock);
// Cross check configuration as verification that communication is working
for (uint8_t idx = 0; idx < 5; idx++) {
if (rawReply[idx + 1] != l3g.sensorCfg[idx]) {
sif::warning << "AcsBoardPolling: l3g config check missmatch" << std::endl;
l3g.replyResult = returnvalue::FAILED;
return;
}
}
l3g.performStartup = false;
l3g.ownReply.cfgWasSet = true;
l3g.ownReply.sensitivity = l3gd20h::ctrlReg4ToSensitivity(l3g.sensorCfg[3]);
}
cmdBuf[0] = l3gd20h::READ_START | l3gd20h::AUTO_INCREMENT_MASK | l3gd20h::READ_MASK;
std::memset(cmdBuf.data() + 1, 0, l3gd20h::READ_LEN);
result = spiComIF.sendMessage(l3g.cookie, cmdBuf.data(), l3gd20h::READ_LEN + 1);
if (result != returnvalue::OK) {
l3g.replyResult = returnvalue::FAILED;
return;
}
result = spiComIF.readReceivedMessage(l3g.cookie, &rawReply, &dummy);
if (result != returnvalue::OK) {
l3g.replyResult = returnvalue::FAILED;
return;
}
MutexGuard mg(ipcLock);
// The regular read function always returns the full sensor config as well. Use that
// to verify communications.
for (uint8_t idx = 0; idx < 5; idx++) {
if (rawReply[idx + 1] != l3g.sensorCfg[idx]) {
sif::warning << "AcsBoardPolling: l3g config check missmatch" << std::endl;
l3g.replyResult = returnvalue::FAILED;
return;
}
}
l3g.ownReply.statusReg = rawReply[l3gd20h::STATUS_IDX];
l3g.ownReply.angVelocities[0] = (rawReply[l3gd20h::OUT_X_H] << 8) | rawReply[l3gd20h::OUT_X_L];
l3g.ownReply.angVelocities[1] = (rawReply[l3gd20h::OUT_Y_H] << 8) | rawReply[l3gd20h::OUT_Y_L];
l3g.ownReply.angVelocities[2] = (rawReply[l3gd20h::OUT_Z_H] << 8) | rawReply[l3gd20h::OUT_Z_L];
l3g.ownReply.tempOffsetRaw = rawReply[l3gd20h::TEMPERATURE_IDX];
}
}
ReturnValue_t AcsBoardPolling::readAdisCfg(SpiCookie& cookie, size_t transferLen) {
ReturnValue_t result = returnvalue::OK;
int retval = 0;
// Prepare transfer
int fileDescriptor = 0;
std::string device = spiComIF.getSpiDev();
UnixFileGuard fileHelper(device, fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return SpiComIF::OPENING_FILE_FAILED;
}
spi::SpiModes spiMode = spi::SpiModes::MODE_0;
uint32_t spiSpeed = 0;
cookie.getSpiParameters(spiMode, spiSpeed, nullptr);
spiComIF.setSpiSpeedAndMode(fileDescriptor, spiMode, spiSpeed);
cookie.assignWriteBuffer(cmdBuf.data());
cookie.setTransferSize(2);
gpioId_t gpioId = cookie.getChipSelectPin();
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 0;
MutexIF* mutex = spiComIF.getCsMutex();
cookie.getMutexParams(timeoutType, timeoutMs);
if (mutex == nullptr) {
sif::warning << "GyroADIS16507Handler::spiSendCallback: "
"Mutex or GPIO interface invalid"
<< std::endl;
return returnvalue::FAILED;
}
size_t idx = 0;
spi_ioc_transfer* transferStruct = cookie.getTransferStructHandle();
uint64_t origTx = transferStruct->tx_buf;
uint64_t origRx = transferStruct->rx_buf;
while (idx < transferLen) {
result = mutex->lockMutex(timeoutType, timeoutMs);
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "AcsBoardPolling: Failed to lock mutex" << std::endl;
#endif
return result;
}
// Pull SPI CS low. For now, no support for active high given
if (gpioId != gpio::NO_GPIO) {
gpioIF.pullLow(gpioId);
}
// Execute transfer
// Initiate a full duplex SPI transfer.
retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie.getTransferStructHandle());
if (retval < 0) {
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED;
}
#if FSFW_HAL_SPI_WIRETAPPING == 1
comIf->performSpiWiretapping(cookie);
#endif /* FSFW_LINUX_SPI_WIRETAPPING == 1 */
if (gpioId != gpio::NO_GPIO) {
gpioIF.pullHigh(gpioId);
}
mutex->unlockMutex();
idx += 2;
transferStruct->tx_buf += 2;
transferStruct->rx_buf += 2;
if (idx < transferLen) {
usleep(adis1650x::STALL_TIME_MICROSECONDS);
}
}
transferStruct->tx_buf = origTx;
transferStruct->rx_buf = origRx;
cookie.setTransferSize(transferLen);
return returnvalue::OK;
}
void AcsBoardPolling::gyroAdisHandler(GyroAdis& gyro) {
ReturnValue_t result;
acs::SimpleSensorMode mode;
bool cdHasTimedOut = false;
bool mustPerformStartup = false;
{
MutexGuard mg(ipcLock);
mode = gyro.mode;
cdHasTimedOut = gyro.countdown.hasTimedOut();
mustPerformStartup = gyro.performStartup;
}
if (mode == acs::SimpleSensorMode::NORMAL and cdHasTimedOut) {
if (mustPerformStartup) {
uint8_t regList[6];
// Read configuration
regList[0] = adis1650x::DIAG_STAT_REG;
regList[1] = adis1650x::FILTER_CTRL_REG;
regList[2] = adis1650x::RANG_MDL_REG;
regList[3] = adis1650x::MSC_CTRL_REG;
regList[4] = adis1650x::DEC_RATE_REG;
regList[5] = adis1650x::PROD_ID_REG;
size_t transferLen =
adis1650x::prepareReadCommand(regList, sizeof(regList), cmdBuf.data(), cmdBuf.size());
result = readAdisCfg(*gyro.cookie, transferLen);
if (result != returnvalue::OK) {
gyro.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(gyro.cookie, &rawReply, &dummy);
if (result != returnvalue::OK or rawReply == nullptr) {
gyro.replyResult = result;
return;
}
uint16_t prodId = (rawReply[12] << 8) | rawReply[13];
if (((gyro.type == adis1650x::Type::ADIS16505) and (prodId != adis1650x::PROD_ID_16505)) or
((gyro.type == adis1650x::Type::ADIS16507) and (prodId != adis1650x::PROD_ID_16507))) {
sif::warning << "AcsPollingTask: Invalid ADIS product ID " << prodId << std::endl;
gyro.replyResult = returnvalue::FAILED;
return;
}
MutexGuard mg(ipcLock);
gyro.ownReply.cfgWasSet = true;
gyro.ownReply.cfg.diagStat = (rawReply[2] << 8) | rawReply[3];
gyro.ownReply.cfg.filterSetting = (rawReply[4] << 8) | rawReply[5];
gyro.ownReply.cfg.rangMdl = (rawReply[6] << 8) | rawReply[7];
gyro.ownReply.cfg.mscCtrlReg = (rawReply[8] << 8) | rawReply[9];
gyro.ownReply.cfg.decRateReg = (rawReply[10] << 8) | rawReply[11];
gyro.ownReply.cfg.prodId = prodId;
gyro.ownReply.data.sensitivity = adis1650x::rangMdlToSensitivity(gyro.ownReply.cfg.rangMdl);
gyro.performStartup = false;
}
// Read regular registers
std::memcpy(cmdBuf.data(), adis1650x::BURST_READ_ENABLE.data(),
adis1650x::BURST_READ_ENABLE.size());
std::memset(cmdBuf.data() + 2, 0, 10 * 2);
result = spiComIF.sendMessage(gyro.cookie, cmdBuf.data(), adis1650x::SENSOR_READOUT_SIZE);
if (result != returnvalue::OK) {
gyro.replyResult = returnvalue::FAILED;
return;
}
result = spiComIF.readReceivedMessage(gyro.cookie, &rawReply, &dummy);
if (result != returnvalue::OK or rawReply == nullptr) {
gyro.replyResult = returnvalue::FAILED;
return;
}
uint16_t checksum = (rawReply[20] << 8) | rawReply[21];
// Now verify the read checksum with the expected checksum according to datasheet p. 20
uint16_t calcChecksum = 0;
for (size_t idx = 2; idx < 20; idx++) {
calcChecksum += rawReply[idx];
}
if (checksum != calcChecksum) {
sif::warning << "AcsPollingTask: Invalid ADIS reply checksum" << std::endl;
gyro.replyResult = returnvalue::FAILED;
return;
}
auto burstMode = adis1650x::burstModeFromMscCtrl(gyro.ownReply.cfg.mscCtrlReg);
if (burstMode != adis1650x::BurstModes::BURST_16_BURST_SEL_0) {
sif::error << "GyroADIS1650XHandler::interpretDeviceReply: Analysis for select burst mode"
" not implemented!"
<< std::endl;
gyro.replyResult = returnvalue::FAILED;
return;
}
MutexGuard mg(ipcLock);
gyro.ownReply.dataWasSet = true;
gyro.ownReply.cfg.diagStat = rawReply[2] << 8 | rawReply[3];
gyro.ownReply.data.angVelocities[0] = (rawReply[4] << 8) | rawReply[5];
gyro.ownReply.data.angVelocities[1] = (rawReply[6] << 8) | rawReply[7];
gyro.ownReply.data.angVelocities[2] = (rawReply[8] << 8) | rawReply[9];
gyro.ownReply.data.accelerations[0] = (rawReply[10] << 8) | rawReply[11];
gyro.ownReply.data.accelerations[1] = (rawReply[12] << 8) | rawReply[13];
gyro.ownReply.data.accelerations[2] = (rawReply[14] << 8) | rawReply[15];
gyro.ownReply.data.temperatureRaw = (rawReply[16] << 8) | rawReply[17];
}
}
void AcsBoardPolling::mgmLis3Handler(MgmLis3& mgm) {
ReturnValue_t result;
acs::SimpleSensorMode mode;
bool mustPerformStartup = false;
{
MutexGuard mg(ipcLock);
mode = mgm.mode;
mustPerformStartup = mgm.performStartup;
}
if (mode == acs::SimpleSensorMode::NORMAL) {
if (mustPerformStartup) {
// To check valid communication, read back identification
// register which should always be the same value.
cmdBuf[0] = mgmLis3::readCommand(mgmLis3::IDENTIFY_DEVICE_REG_ADDR);
cmdBuf[1] = 0x00;
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
if (result != OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != OK) {
mgm.replyResult = result;
return;
}
if (rawReply[1] != mgmLis3::DEVICE_ID) {
sif::error << "AcsPollingTask: invalid MGM lis3 device ID" << std::endl;
mgm.replyResult = result;
return;
}
mgm.cfg[0] = mgmLis3::CTRL_REG1_DEFAULT;
mgm.cfg[1] = mgmLis3::CTRL_REG2_DEFAULT;
mgm.cfg[2] = mgmLis3::CTRL_REG3_DEFAULT;
mgm.cfg[3] = mgmLis3::CTRL_REG4_DEFAULT;
mgm.cfg[4] = mgmLis3::CTRL_REG5_DEFAULT;
cmdBuf[0] = mgmLis3::writeCommand(mgmLis3::CTRL_REG1, true);
std::memcpy(cmdBuf.data() + 1, mgm.cfg, 5);
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 6);
if (result != OK) {
mgm.replyResult = result;
return;
}
// Done here. We can always read back config and data during periodic handling
mgm.performStartup = false;
}
cmdBuf[0] = mgmLis3::readCommand(mgmLis3::CTRL_REG1, true);
std::memset(cmdBuf.data() + 1, 0, mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS);
result =
spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS + 1);
if (result != returnvalue::OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != returnvalue::OK) {
mgm.replyResult = result;
return;
}
// Verify communication by re-checking config
if (rawReply[1] != mgm.cfg[0] or rawReply[2] != mgm.cfg[1] or rawReply[3] != mgm.cfg[2] or
rawReply[4] != mgm.cfg[3] or rawReply[5] != mgm.cfg[4]) {
mgm.replyResult = result;
return;
}
{
MutexGuard mg(ipcLock);
mgm.ownReply.dataWasSet = true;
mgm.ownReply.sensitivity = mgmLis3::getSensitivityFactor(mgmLis3::getSensitivity(mgm.cfg[1]));
mgm.ownReply.mgmValuesRaw[0] =
(rawReply[mgmLis3::X_HIGHBYTE_IDX] << 8) | rawReply[mgmLis3::X_LOWBYTE_IDX];
mgm.ownReply.mgmValuesRaw[1] =
(rawReply[mgmLis3::Y_HIGHBYTE_IDX] << 8) | rawReply[mgmLis3::Y_LOWBYTE_IDX];
mgm.ownReply.mgmValuesRaw[2] =
(rawReply[mgmLis3::Z_HIGHBYTE_IDX] << 8) | rawReply[mgmLis3::Z_LOWBYTE_IDX];
}
// Read tempetature
cmdBuf[0] = mgmLis3::readCommand(mgmLis3::TEMP_LOWBYTE, true);
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 3);
if (result != returnvalue::OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != returnvalue::OK) {
mgm.replyResult = result;
return;
}
MutexGuard mg(ipcLock);
mgm.ownReply.temperatureWasSet = true;
mgm.ownReply.temperatureRaw = (rawReply[2] << 8) | rawReply[1];
}
}
void AcsBoardPolling::mgmRm3100Handler(MgmRm3100& mgm) {
ReturnValue_t result;
acs::SimpleSensorMode mode;
bool mustPerformStartup = false;
{
MutexGuard mg(ipcLock);
mode = mgm.mode;
mustPerformStartup = mgm.performStartup;
}
if (mode == acs::SimpleSensorMode::NORMAL) {
if (mustPerformStartup) {
// Configure CMM first
cmdBuf[0] = mgmRm3100::CMM_REGISTER;
cmdBuf[1] = mgmRm3100::CMM_VALUE;
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
if (result != OK) {
mgm.replyResult = result;
return;
}
// Read back register
cmdBuf[0] = mgmRm3100::CMM_REGISTER | mgmRm3100::READ_MASK;
cmdBuf[1] = 0;
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
if (result != OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != OK) {
mgm.replyResult = result;
return;
}
if (rawReply[1] != mgmRm3100::CMM_VALUE) {
sif::error << "AcsBoardPolling: MGM RM3100 read back CMM invalid" << std::endl;
mgm.replyResult = result;
return;
}
// Configure TMRC register
cmdBuf[0] = mgmRm3100::TMRC_REGISTER;
// hardcoded for now
cmdBuf[1] = mgm.tmrcValue;
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
if (result != OK) {
mgm.replyResult = result;
return;
}
// Read back and verify value
cmdBuf[0] = mgmRm3100::TMRC_REGISTER | mgmRm3100::READ_MASK;
cmdBuf[1] = 0;
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 2);
if (result != OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != OK) {
mgm.replyResult = result;
return;
}
if (rawReply[1] != mgm.tmrcValue) {
sif::error << "AcsBoardPolling: MGM RM3100 read back TMRC invalid" << std::endl;
mgm.replyResult = result;
return;
}
mgm.performStartup = false;
}
// Regular read operation
cmdBuf[0] = mgmRm3100::MEASUREMENT_REG_START | mgmRm3100::READ_MASK;
std::memset(cmdBuf.data() + 1, 0, 9);
result = spiComIF.sendMessage(mgm.cookie, cmdBuf.data(), 10);
if (result != OK) {
mgm.replyResult = result;
return;
}
result = spiComIF.readReceivedMessage(mgm.cookie, &rawReply, &dummy);
if (result != OK) {
mgm.replyResult = result;
return;
}
MutexGuard mg(ipcLock);
for (uint8_t idx = 0; idx < 3; idx++) {
// Hardcoded, but note that the gain depends on the cycle count
// value which is configurable!
mgm.ownReply.scaleFactors[idx] = 1.0 / mgmRm3100::DEFAULT_GAIN;
}
mgm.ownReply.dataWasRead = true;
// Bitshift trickery to account for 24 bit signed value.
mgm.ownReply.mgmValuesRaw[0] =
((rawReply[1] << 24) | (rawReply[2] << 16) | (rawReply[3] << 8)) >> 8;
mgm.ownReply.mgmValuesRaw[1] =
((rawReply[4] << 24) | (rawReply[5] << 16) | (rawReply[6] << 8)) >> 8;
mgm.ownReply.mgmValuesRaw[2] =
((rawReply[7] << 24) | (rawReply[8] << 16) | (rawReply[9] << 8)) >> 8;
}
}

View File

@ -0,0 +1,89 @@
#ifndef LINUX_DEVICES_ACSBOARDPOLLING_H_
#define LINUX_DEVICES_ACSBOARDPOLLING_H_
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/tasks/SemaphoreIF.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmRm3100Helpers.h>
#include <fsfw_hal/linux/spi/SpiComIF.h>
#include <mission/devices/devicedefinitions/acsPolling.h>
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
class AcsBoardPolling : public SystemObject,
public ExecutableObjectIF,
public DeviceCommunicationIF {
public:
AcsBoardPolling(object_id_t objectId, SpiComIF& lowLevelComIF, GpioIF& gpioIF);
ReturnValue_t performOperation(uint8_t operationCode) override;
ReturnValue_t initialize() override;
private:
enum class InternalState { IDLE, BUSY } state = InternalState::IDLE;
MutexIF* ipcLock;
SemaphoreIF* semaphore;
std::array<uint8_t, 32> cmdBuf;
std::array<uint8_t, 32> replyBuf;
struct DevBase {
SpiCookie* cookie = nullptr;
bool performStartup = false;
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
ReturnValue_t replyResult = returnvalue::OK;
};
struct GyroAdis : public DevBase {
adis1650x::Type type;
Countdown countdown;
acs::Adis1650XReply ownReply;
acs::Adis1650XReply readerReply;
};
GyroAdis gyro0Adis{};
GyroAdis gyro2Adis{};
struct GyroL3g : public DevBase {
uint8_t sensorCfg[5];
acs::GyroL3gReply ownReply;
acs::GyroL3gReply readerReply;
};
GyroL3g gyro1L3g{};
GyroL3g gyro3L3g{};
struct MgmRm3100 : public DevBase {
uint8_t tmrcValue = mgmRm3100::TMRC_DEFAULT_37HZ_VALUE;
acs::MgmRm3100Reply ownReply;
acs::MgmRm3100Reply readerReply;
};
MgmRm3100 mgm1Rm3100;
MgmRm3100 mgm3Rm3100;
struct MgmLis3 : public DevBase {
uint8_t cfg[5]{};
acs::MgmLis3Reply ownReply;
acs::MgmLis3Reply readerReply;
};
MgmLis3 mgm0Lis3;
MgmLis3 mgm2Lis3;
uint8_t* rawReply = nullptr;
size_t dummy = 0;
SpiComIF& spiComIF;
GpioIF& gpioIF;
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;
void gyroL3gHandler(GyroL3g& l3g);
void gyroAdisHandler(GyroAdis& gyro);
void mgmLis3Handler(MgmLis3& mgm);
void mgmRm3100Handler(MgmRm3100& mgm);
// Special readout: 16us stall time between small 2 byte transfers.
ReturnValue_t readAdisCfg(SpiCookie& spiCookie, size_t transferLen);
};
#endif /* LINUX_DEVICES_ACSBOARDPOLLING_H_ */

View File

@ -4,8 +4,13 @@ endif()
target_sources(
${OBSW_NAME}
PRIVATE Max31865RtdPolling.cpp ScexUartReader.cpp ImtqPollingTask.cpp
ScexDleParser.cpp ScexHelper.cpp RwPollingTask.cpp)
PRIVATE Max31865RtdPolling.cpp
ScexUartReader.cpp
ImtqPollingTask.cpp
ScexDleParser.cpp
ScexHelper.cpp
RwPollingTask.cpp
AcsBoardPolling.cpp)
add_subdirectory(ploc)

View File

@ -172,20 +172,10 @@ bool GpsHyperionLinuxController::readGpsDataFromGpsd() {
return false;
}
oneShotSwitches.gpsReadFailedSwitch = true;
// did not event get mode, nothing to see.
if (MODE_SET != (MODE_SET & gps.set)) {
if (mode != MODE_OFF) {
if (maxTimeToReachFix.hasTimedOut() and oneShotSwitches.cantGetFixSwitch) {
sif::warning
<< "GPSHyperionHandler::readGpsDataFromGpsd: No mode could be set in allowed "
<< maxTimeToReachFix.timeout / 1000 << " seconds" << std::endl;
triggerEvent(GpsHyperion::CANT_GET_FIX, maxTimeToReachFix.timeout);
oneShotSwitches.cantGetFixSwitch = false;
}
// Mode is on, so do next read immediately
return true;
}
// GPS device is off anyway, so do other handling
ReturnValue_t result = handleGpsReadData();
if (result == returnvalue::OK) {
return true;
} else {
return false;
}
noModeSetCntr = 0;
@ -197,11 +187,26 @@ bool GpsHyperionLinuxController::readGpsDataFromGpsd() {
"SHM read not implemented"
<< std::endl;
}
handleGpsReadData();
return true;
}
ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
bool modeIsSet = true;
if (MODE_SET != (MODE_SET & gps.set)) {
if (mode != MODE_OFF) {
if (maxTimeToReachFix.hasTimedOut() and oneShotSwitches.cantGetFixSwitch) {
sif::warning << "GpsHyperionLinuxController: No mode could be set in allowed "
<< maxTimeToReachFix.timeout / 1000 << " seconds" << std::endl;
triggerEvent(GpsHyperion::CANT_GET_FIX, maxTimeToReachFix.timeout);
oneShotSwitches.cantGetFixSwitch = false;
}
modeIsSet = false;
} else {
// GPS device is off anyway, so do other handling
return returnvalue::FAILED;
}
}
PoolReadGuard pg(&gpsSet);
if (pg.getReadResult() != returnvalue::OK) {
#if FSFW_VERBOSE_LEVEL >= 1
@ -211,66 +216,93 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
}
bool validFix = false;
// 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix
if (gps.fix.mode == 2 or gps.fix.mode == 3) {
validFix = true;
}
if (gpsSet.fixMode.value != gps.fix.mode) {
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, gps.fix.mode);
}
gpsSet.fixMode.value = gps.fix.mode;
if (gps.fix.mode == 0 or gps.fix.mode == 1) {
if (modeCommanded and maxTimeToReachFix.hasTimedOut()) {
// We are supposed to be on and functioning, but no fix was found
if (mode == MODE_ON or mode == MODE_NORMAL) {
mode = MODE_OFF;
}
modeCommanded = false;
if (modeIsSet) {
// 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix
if (gps.fix.mode == 2 or gps.fix.mode == 3) {
validFix = true;
}
if (gpsSet.fixMode.value != gps.fix.mode) {
triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, gps.fix.mode);
}
gpsSet.fixMode.value = gps.fix.mode;
if (gps.fix.mode == 0 or gps.fix.mode == 1) {
if (modeCommanded and maxTimeToReachFix.hasTimedOut()) {
// We are supposed to be on and functioning, but no fix was found
if (mode == MODE_ON or mode == MODE_NORMAL) {
mode = MODE_OFF;
}
modeCommanded = false;
}
}
}
gpsSet.fixMode.setValid(modeIsSet);
// Only set on specific messages, so only set a valid flag to invalid
// if not set for more than a full message set (10 messages here)
if (SATELLITE_SET == (SATELLITE_SET & gps.set)) {
gpsSet.satInUse.value = gps.satellites_used;
gpsSet.satInView.value = gps.satellites_visible;
if (not gpsSet.satInUse.isValid()) {
gpsSet.satInUse.setValid(true);
gpsSet.satInView.setValid(true);
}
satNotSetCounter = 0;
} else {
satNotSetCounter++;
if (gpsSet.satInUse.isValid() and satNotSetCounter >= 10) {
gpsSet.satInUse.setValid(false);
gpsSet.satInView.setValid(false);
}
gpsSet.setValidity(false, true);
} else if (gps.satellites_used > 0 && validFix && mode != MODE_OFF) {
gpsSet.setValidity(true, true);
}
gpsSet.satInUse.value = gps.satellites_used;
gpsSet.satInView.value = gps.satellites_visible;
// LATLON is set for every message, no need for a counter
bool latValid = false;
if (std::isfinite(gps.fix.latitude)) {
// Negative latitude -> South direction
gpsSet.latitude.value = gps.fix.latitude;
if (gps.fix.mode >= 2) {
latValid = true;
bool longValid = false;
if (LATLON_SET == (LATLON_SET & gps.set)) {
if (std::isfinite(gps.fix.latitude)) {
// Negative latitude -> South direction
gpsSet.latitude.value = gps.fix.latitude;
// As specified in gps.h: Only valid if mode >= 2
if (gps.fix.mode >= 2) {
latValid = true;
}
}
if (std::isfinite(gps.fix.longitude)) {
// Negative longitude -> West direction
gpsSet.longitude.value = gps.fix.longitude;
// As specified in gps.h: Only valid if mode >= 2
if (gps.fix.mode >= 2) {
longValid = true;
}
}
}
gpsSet.latitude.setValid(latValid);
gpsSet.longitude.setValid(longValid);
bool longValid = false;
if (std::isfinite(gps.fix.longitude)) {
// Negative longitude -> West direction
gpsSet.longitude.value = gps.fix.longitude;
if (gps.fix.mode >= 2) {
longValid = true;
}
}
gpsSet.latitude.setValid(longValid);
// ALTITUDE is set for every message, no need for a counter
bool altitudeValid = false;
if (std::isfinite(gps.fix.altitude)) {
if (ALTITUDE_SET == (ALTITUDE_SET & gps.set) && std::isfinite(gps.fix.altitude)) {
gpsSet.altitude.value = gps.fix.altitude;
// As specified in gps.h: Only valid if mode == 3
if (gps.fix.mode == 3) {
altitudeValid = true;
}
}
gpsSet.altitude.setValid(altitudeValid);
if (std::isfinite(gps.fix.speed)) {
// SPEED is set for every message, no need for a counter
bool speedValid = false;
if (SPEED_SET == (SPEED_SET & gps.set) && std::isfinite(gps.fix.speed)) {
gpsSet.speed.value = gps.fix.speed;
} else {
gpsSet.speed.setValid(false);
speedValid = true;
}
gpsSet.speed.setValid(speedValid);
// TIME is set for every message, no need for a counter
bool timeValid = false;
if (TIME_SET == (TIME_SET & gps.set)) {
timeValid = true;
timeval time = {};
#if LIBGPS_VERSION_MINOR <= 17
gpsSet.unixSeconds.value = std::floor(gps.fix.time);
@ -294,15 +326,14 @@ ReturnValue_t GpsHyperionLinuxController::handleGpsReadData() {
gpsSet.hours = timeOfDay.hour;
gpsSet.minutes = timeOfDay.minute;
gpsSet.seconds = timeOfDay.second;
} else {
gpsSet.unixSeconds.setValid(false);
gpsSet.year.setValid(false);
gpsSet.month.setValid(false);
gpsSet.day.setValid(false);
gpsSet.hours.setValid(false);
gpsSet.minutes.setValid(false);
gpsSet.seconds.setValid(false);
}
gpsSet.unixSeconds.setValid(timeValid);
gpsSet.year.setValid(timeValid);
gpsSet.month.setValid(timeValid);
gpsSet.day.setValid(timeValid);
gpsSet.hours.setValid(timeValid);
gpsSet.minutes.setValid(timeValid);
gpsSet.seconds.setValid(timeValid);
if (debugHyperionGps) {
sif::info << "-- Hyperion GPS Data --" << std::endl;

View File

@ -61,6 +61,8 @@ class GpsHyperionLinuxController : public ExtendedControllerBase {
Countdown maxTimeToReachFix = Countdown(MAX_SECONDS_TO_REACH_FIX * 1000);
bool modeCommanded = false;
bool timeInit = false;
uint8_t satNotSetCounter = 0;
#if OBSW_THREAD_TRACING == 1
uint32_t opCounter = 0;
#endif

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

@ -47,7 +47,6 @@ enum sourceObjects : uint32_t {
GPIO_IF = 0x49010005,
/* Custom device handler */
RW_POLLING_TASK = 0x49020005,
/* 0x54 ('T') for test handlers */
TEST_TASK = 0x54694269,

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

@ -13,9 +13,8 @@
namespace CLASS_ID {
enum {
CLASS_ID_START = COMMON_CLASS_ID_END,
SD_CARD_MANAGER, // SDMA
SCRATCH_BUFFER, // SCBU
CLASS_ID_END // [EXPORT] : [END]
SCRATCH_BUFFER, // SCBU
CLASS_ID_END // [EXPORT] : [END]
};
}

View File

@ -1,12 +1,120 @@
#include "PdecConfig.h"
#include "fsfw/filesystem/HasFileSystemIF.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "pdecconfigdefs.h"
PdecConfig::PdecConfig() { initialize(); }
PdecConfig::PdecConfig()
: localParameterHandler("conf/pdecconfig.json", SdCardManager::instance()) {}
PdecConfig::~PdecConfig() {}
void PdecConfig::initialize() {
void PdecConfig::setMemoryBaseAddress(uint32_t* memoryBaseAddress_) {
memoryBaseAddress = memoryBaseAddress_;
}
ReturnValue_t PdecConfig::write() {
if (memoryBaseAddress == nullptr) {
sif::error << "PdecConfig::write: Memory base address not set" << std::endl;
return returnvalue::FAILED;
}
ReturnValue_t result = initializePersistentParameters();
if (result != returnvalue::OK) {
return result;
}
result = writeFrameHeaderFirstOctet();
if (result != returnvalue::OK) {
return result;
}
result = writeFrameHeaderSecondOctet();
if (result != returnvalue::OK) {
return result;
}
writeMapConfig();
return returnvalue::OK;
}
ReturnValue_t PdecConfig::initializePersistentParameters() {
ReturnValue_t result = localParameterHandler.initialize();
if (result == HasFileSystemIF::FILE_DOES_NOT_EXIST) {
result = createPersistentConfig();
if (result != returnvalue::OK) {
return result;
}
}
return result;
}
ReturnValue_t PdecConfig::createPersistentConfig() {
ReturnValue_t result = localParameterHandler.addParameter(
pdecconfigdefs::paramkeys::POSITIVE_WINDOW, pdecconfigdefs::defaultvalue::positiveWindow);
if (result != returnvalue::OK) {
sif::error << "PdecConfig::createPersistentConfig: Failed to set positive window" << std::endl;
return result;
}
result = localParameterHandler.addParameter(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW,
pdecconfigdefs::defaultvalue::negativeWindow);
if (result != returnvalue::OK) {
sif::error << "PdecConfig::createPersistentConfig: Failed to set negative window" << std::endl;
return result;
}
return returnvalue::OK;
}
uint32_t PdecConfig::getImrReg() {
return static_cast<uint32_t>(enableNewFarIrq << 2) |
static_cast<uint32_t>(enableTcAbortIrq << 1) | static_cast<uint32_t>(enableTcNewIrq);
}
ReturnValue_t PdecConfig::setPositiveWindow(uint8_t pw) {
if (memoryBaseAddress == nullptr) {
sif::error << "PdecConfig::setPositiveWindow: Memory base address not set" << std::endl;
return returnvalue::FAILED;
}
ReturnValue_t result =
localParameterHandler.updateParameter(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, pw);
if (result != returnvalue::OK) {
return result;
}
// Rewrite second config word which contains the positive window parameter
writeFrameHeaderSecondOctet();
return returnvalue::OK;
}
ReturnValue_t PdecConfig::setNegativeWindow(uint8_t nw) {
if (memoryBaseAddress == nullptr) {
sif::error << "PdecConfig::setPositiveWindow: Memory base address not set" << std::endl;
return returnvalue::FAILED;
}
ReturnValue_t result =
localParameterHandler.updateParameter(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, nw);
if (result != returnvalue::OK) {
return result;
}
// Rewrite second config word which contains the negative window parameter
writeFrameHeaderSecondOctet();
return returnvalue::OK;
}
ReturnValue_t PdecConfig::getPositiveWindow(uint8_t& positiveWindow) {
ReturnValue_t result =
localParameterHandler.getValue(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, positiveWindow);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
ReturnValue_t PdecConfig::getNegativeWindow(uint8_t& negativeWindow) {
ReturnValue_t result =
localParameterHandler.getValue(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, negativeWindow);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
ReturnValue_t PdecConfig::writeFrameHeaderFirstOctet() {
uint32_t word = 0;
word |= (VERSION_ID << 30);
@ -19,24 +127,65 @@ void PdecConfig::initialize() {
word |= (SPACECRAFT_ID << 16);
word |= (VIRTUAL_CHANNEL << 10);
word |= (DUMMY_BITS << 8);
word |= POSITIVE_WINDOW;
configWords[0] = word;
uint8_t positiveWindow = 0;
ReturnValue_t result =
localParameterHandler.getValue(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, positiveWindow);
if (result != returnvalue::OK) {
return result;
}
word |= static_cast<uint32_t>(positiveWindow);
*(memoryBaseAddress + FRAME_HEADER_OFFSET) = word;
return returnvalue::OK;
}
ReturnValue_t PdecConfig::writeFrameHeaderSecondOctet() {
uint8_t negativeWindow = 0;
ReturnValue_t result =
localParameterHandler.getValue(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, negativeWindow);
if (result != returnvalue::OK) {
return result;
}
uint32_t word = 0;
word = 0;
word |= (static_cast<uint32_t>(NEGATIVE_WINDOW) << 24);
word |= (static_cast<uint32_t>(negativeWindow) << 24);
word |= (HIGH_AU_MAP_ID << 16);
word |= (ENABLE_DERANDOMIZER << 8);
configWords[1] = word;
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = word;
return returnvalue::OK;
}
uint32_t PdecConfig::getConfigWord(uint8_t wordNo) {
if (wordNo >= CONFIG_WORDS_NUM) {
sif::error << "PdecConfig::getConfigWord: Invalid word number" << std::endl;
return 0;
void PdecConfig::writeMapConfig() {
// Configure all MAP IDs as invalid
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx / 4) =
NO_DESTINATION << 24 | NO_DESTINATION << 16 | NO_DESTINATION << 8 | NO_DESTINATION;
}
// All TCs with MAP ID 7 will be routed to the PM module (can then be read from memory)
uint8_t routeToPm = calcMapAddrEntry(PM_BUFFER);
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + 1) =
(NO_DESTINATION << 24) | (NO_DESTINATION << 16) | (NO_DESTINATION << 8) | routeToPm;
// Write map id clock frequencies
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
*(memoryBaseAddress + MAP_CLK_FREQ_OFFSET + idx / 4) =
MAP_CLK_FREQ << 24 | MAP_CLK_FREQ << 16 | MAP_CLK_FREQ << 8 | MAP_CLK_FREQ;
}
return configWords[wordNo];
}
uint32_t PdecConfig::getImrReg() {
return static_cast<uint32_t>(enableNewFarIrq << 2) |
static_cast<uint32_t>(enableTcAbortIrq << 1) | static_cast<uint32_t>(enableTcNewIrq);
uint8_t PdecConfig::calcMapAddrEntry(uint8_t moduleId) {
uint8_t lutEntry = 0;
uint8_t parity = getOddParity(moduleId | (1 << VALID_POSITION));
lutEntry = (parity << PARITY_POSITION) | (1 << VALID_POSITION) | moduleId;
return lutEntry;
}
uint8_t PdecConfig::getOddParity(uint8_t number) {
uint8_t parityBit = 0;
uint8_t countBits = 0;
for (unsigned int idx = 0; idx < sizeof(number) * 8; idx++) {
countBits += (number >> idx) & 0x1;
}
parityBit = ~(countBits & 0x1) & 0x1;
return parityBit;
}

View File

@ -1,30 +1,53 @@
#ifndef LINUX_OBC_PDECCONFIG_H_
#define LINUX_OBC_PDECCONFIG_H_
#include <cstring>
#include <string>
#include "bsp_q7s/fs/SdCardManager.h"
#include "bsp_q7s/memory/LocalParameterHandler.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "pdec.h"
/**
* @brief This class generates the configuration words for the configuration memory of the PDEC
* IP Cores.
*
* @details Fields are initialized according to pecification in PDEC datasheet section 6.11.3.1
* @details Fields are initialized according to specification in PDEC datasheet section 6.11.3.1
* PROM usage.
*
* @author J. Meier
*/
class PdecConfig {
public:
/**
* @brief Constructor
*/
PdecConfig();
virtual ~PdecConfig();
/**
* @brief Returns the configuration word by specifying the position.
* @brief Sets the memory base address pointer
*/
void setMemoryBaseAddress(uint32_t* memoryBaseAddress_);
/**
* @brief Will write the config to the PDEC configuration memory. New config
* becomes active after resetting PDEC.
*/
ReturnValue_t write();
/**
* @brief Returns the value to write to the interrupt mask register. This
* value defines which interrupts should be enabled/disabled.
*/
uint32_t getConfigWord(uint8_t wordNo);
uint32_t getImrReg();
ReturnValue_t setPositiveWindow(uint8_t pw);
ReturnValue_t setNegativeWindow(uint8_t nw);
ReturnValue_t getPositiveWindow(uint8_t& positiveWindow);
ReturnValue_t getNegativeWindow(uint8_t& negativeWindow);
private:
// TC transfer frame configuration parameters
static const uint8_t VERSION_ID = 0;
@ -36,21 +59,73 @@ class PdecConfig {
static const uint8_t RESERVED_FIELD_A = 0;
static const uint16_t SPACECRAFT_ID = 0x3DC;
static const uint16_t DUMMY_BITS = 0;
// Parameters to control the FARM for AD frames
// Set here for future use
static const uint8_t POSITIVE_WINDOW = 10;
static const uint8_t NEGATIVE_WINDOW = 151;
static const uint8_t HIGH_AU_MAP_ID = 0xF;
static const uint8_t ENABLE_DERANDOMIZER = 1;
static const uint8_t CONFIG_WORDS_NUM = 2;
// 0x200 / 4 = 0x80
static const uint32_t FRAME_HEADER_OFFSET = 0x80;
static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0;
static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90;
// MAP clock frequency. Must be a value between 1 and 13 otherwise the TC segment will be
// discarded
static const uint8_t MAP_CLK_FREQ = 2;
static const uint8_t MAX_MAP_ADDR = 63;
// Writing this to the map address in the look up table will invalidate a MAP ID.
static const uint8_t NO_DESTINATION = 0;
static const uint8_t VALID_POSITION = 6;
static const uint8_t PARITY_POSITION = 7;
/**
* TCs with map addresses (also know as Map IDs) assigned to this channel will be stored in
* the PDEC memory.
*/
static const uint8_t PM_BUFFER = 7;
uint32_t* memoryBaseAddress = nullptr;
// Pointer to object providing access to persistent configuration parameters
LocalParameterHandler localParameterHandler;
uint32_t configWords[CONFIG_WORDS_NUM];
bool enableTcNewIrq = true;
bool enableTcAbortIrq = true;
bool enableNewFarIrq = true;
void initialize();
ReturnValue_t initializePersistentParameters();
/**
* @brief If the json file containing the persistent config parameters does
* not exist it will be created here.
*/
ReturnValue_t createPersistentConfig();
ReturnValue_t writeFrameHeaderFirstOctet();
ReturnValue_t writeFrameHeaderSecondOctet();
void writeMapConfig();
/**
* @brief This function calculates the entry for the configuration of the MAP ID routing.
*
* @param mapAddr The MAP ID to configure
* @param moduleId The destination module where all TCs with the map id mapAddr will be routed
* to.
*
* @details The PDEC has different modules where the TCs can be routed to. A lookup table is
* used which links the MAP ID field to the destination module. The entry for this
* lookup table is created by this function and must be stored in the configuration
* memory region of the PDEC. The entry has a specific format
*/
uint8_t calcMapAddrEntry(uint8_t moduleId);
/**
* @brief This functions calculates the odd parity of the bits in number.
*
* @param number The number from which to calculate the odd parity.
*/
uint8_t getOddParity(uint8_t number);
};
#endif /* LINUX_OBC_PDECCONFIG_H_ */

View File

@ -29,7 +29,8 @@ PdecHandler::PdecHandler(object_id_t objectId, object_id_t tcDestinationId,
gpioComIF(gpioComIF),
pdecReset(pdecReset),
actionHelper(this, nullptr),
uioNames(names) {
uioNames(names),
paramHelper(this) {
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
@ -62,6 +63,8 @@ ReturnValue_t PdecHandler::initialize() {
result = configMemMapper.getMappedAdress(&memoryBaseAddress, UioMapper::Permissions::READ_WRITE);
if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
} else {
pdecConfig.setMemoryBaseAddress(memoryBaseAddress);
}
UioMapper ramMapper(uioNames.ramMemory);
result = ramMapper.getMappedAdress(&ramBaseAddress, UioMapper::Permissions::READ_WRITE);
@ -73,12 +76,34 @@ ReturnValue_t PdecHandler::initialize() {
sif::error << "Can not use IRQ mode if IRQ UIO name is invalid" << std::endl;
return returnvalue::FAILED;
}
PdecConfig pdecConfig;
writePdecConfigDuringReset(pdecConfig);
result = actionHelper.initialize(commandQueue);
if (result != returnvalue::OK) {
return result;
}
result = paramHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
ReturnValue_t PdecHandler::firstLoop() {
ReturnValue_t result = pdecConfig.write();
if (result != returnvalue::OK) {
if (result == LocalParameterHandler::SD_NOT_READY) {
return result;
} else {
sif::error << "PdecHandler::firstLoop: Failed to write PDEC config" << std::endl;
}
return returnvalue::FAILED;
}
result = releasePdec();
if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
return returnvalue::FAILED;
}
// This configuration must be done while the PDEC is not held in reset.
@ -86,11 +111,12 @@ ReturnValue_t PdecHandler::initialize() {
// Configure interrupt mask register to enable interrupts
*(registerBaseAddress + PDEC_IMR_OFFSET) = pdecConfig.getImrReg();
}
result = actionHelper.initialize(commandQueue);
result = resetFarStatFlag();
if (result != returnvalue::OK) {
// Requires reconfiguration and reinitialization of PDEC
triggerEvent(INVALID_FAR);
return result;
}
return returnvalue::OK;
}
@ -104,26 +130,28 @@ ReturnValue_t PdecHandler::performOperation(uint8_t operationCode) {
}
ReturnValue_t PdecHandler::polledOperation() {
ReturnValue_t result = returnvalue::OK;
readCommandQueue();
switch (state) {
case State::INIT:
resetFarStatFlag();
if (result != returnvalue::OK) {
// Requires reconfiguration and reinitialization of PDEC
triggerEvent(INVALID_FAR);
state = State::WAIT_FOR_RECOVERY;
break;
}
state = State::RUNNING;
case State::INIT: {
handleInitState();
break;
case State::RUNNING:
}
case State::RUNNING: {
if (newTcReceived()) {
handleNewTc();
}
checkLocks();
break;
}
case State::PDEC_RESET: {
ReturnValue_t result = pdecToReset();
if (result != returnvalue::OK) {
triggerEvent(PDEC_RESET_FAILED);
}
state = State::INIT;
break;
}
case State::WAIT_FOR_RECOVERY:
break;
default:
@ -136,14 +164,8 @@ ReturnValue_t PdecHandler::polledOperation() {
// See https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt.html for more information.
ReturnValue_t PdecHandler::irqOperation() {
ReturnValue_t result = returnvalue::OK;
int fd = open(uioNames.irq, O_RDWR);
if (fd < 0) {
sif::error << "PdecHandler::irqOperation: Opening UIO IRQ file" << uioNames.irq << " failed"
<< std::endl;
return returnvalue::FAILED;
}
ReturnValue_t result = returnvalue::OK;
int fd = -1;
// Used to unmask IRQ
uint32_t info = 1;
@ -158,18 +180,23 @@ ReturnValue_t PdecHandler::irqOperation() {
info = 1;
readCommandQueue();
switch (state) {
case State::INIT:
result = resetFarStatFlag();
if (result != returnvalue::OK) {
// Requires reconfiguration and reinitialization of PDEC
triggerEvent(INVALID_FAR);
state = State::WAIT_FOR_RECOVERY;
return result;
case State::INIT: {
result = handleInitState();
if (result == returnvalue::OK) {
openIrqFile(&fd);
}
state = State::RUNNING;
checkLocks();
break;
}
case State::PDEC_RESET: {
result = pdecToReset();
if (result != returnvalue::OK) {
triggerEvent(PDEC_RESET_FAILED);
}
state = State::INIT;
break;
}
case State::RUNNING: {
checkLocks();
checkAndHandleIrqs(fd, info);
break;
}
@ -188,6 +215,38 @@ ReturnValue_t PdecHandler::irqOperation() {
return returnvalue::OK;
}
ReturnValue_t PdecHandler::handleInitState() {
ReturnValue_t result = firstLoop();
if (result != returnvalue::OK) {
if (result == LocalParameterHandler::SD_NOT_READY) {
TaskFactory::delayTask(400);
if (initTries == MAX_INIT_TRIES) {
sif::error << "PdecHandler::handleInitState: SD card never "
"becomes ready"
<< std::endl;
state = State::WAIT_FOR_RECOVERY;
} else {
state = State::INIT;
}
return result;
}
state = State::WAIT_FOR_RECOVERY;
return result;
}
state = State::RUNNING;
return returnvalue::OK;
}
void PdecHandler::openIrqFile(int* fd) {
*fd = open(uioNames.irq, O_RDWR);
if (*fd < 0) {
sif::error << "PdecHandler::irqOperation: Opening UIO IRQ file" << uioNames.irq << " failed"
<< std::endl;
triggerEvent(OPEN_IRQ_FILE_FAILED);
state = State::WAIT_FOR_RECOVERY;
}
}
ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
ssize_t nb = write(fd, &info, sizeof(info));
if (nb != static_cast<ssize_t>(sizeof(info))) {
@ -201,7 +260,6 @@ ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
int ret = poll(&fds, 1, IRQ_TIMEOUT_MS);
if (ret == 0) {
// No TCs for timeout period
checkLocks();
genericCheckCd.resetTimer();
resetIrqLimiters();
} else if (ret >= 1) {
@ -228,7 +286,6 @@ ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
static_cast<void>(dummy);
if (genericCheckCd.hasTimedOut()) {
checkLocks();
genericCheckCd.resetTimer();
if (interruptWindowCd.hasTimedOut()) {
if (interruptCounter >= MAX_ALLOWED_IRQS_PER_WINDOW) {
@ -254,17 +311,21 @@ ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
}
void PdecHandler::readCommandQueue(void) {
CommandMessage commandMessage;
CommandMessage message;
ReturnValue_t result = returnvalue::FAILED;
result = commandQueue->receiveMessage(&commandMessage);
result = commandQueue->receiveMessage(&message);
if (result == returnvalue::OK) {
result = actionHelper.handleActionMessage(&commandMessage);
result = actionHelper.handleActionMessage(&message);
if (result == returnvalue::OK) {
return;
}
result = paramHelper.handleParameterMessage(&message);
if (result == returnvalue::OK) {
return;
}
CommandMessage reply;
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, commandMessage.getCommand());
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, message.getCommand());
commandQueue->reply(&reply);
return;
}
@ -272,26 +333,69 @@ void PdecHandler::readCommandQueue(void) {
MessageQueueId_t PdecHandler::getCommandQueue() const { return commandQueue->getId(); }
void PdecHandler::writePdecConfigDuringReset(PdecConfig& pdecConfig) {
*(memoryBaseAddress + FRAME_HEADER_OFFSET) = pdecConfig.getConfigWord(0);
*(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = pdecConfig.getConfigWord(1);
// Configure all MAP IDs as invalid
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + idx / 4) =
NO_DESTINATION << 24 | NO_DESTINATION << 16 | NO_DESTINATION << 8 | NO_DESTINATION;
ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
switch (actionId) {
case PRINT_CLCW:
printClcw();
return EXECUTION_FINISHED;
case PRINT_PDEC_MON:
printPdecMon();
return EXECUTION_FINISHED;
default:
return COMMAND_NOT_IMPLEMENTED;
}
}
// All TCs with MAP ID 7 will be routed to the PM module (can then be read from memory)
uint8_t routeToPm = calcMapAddrEntry(PM_BUFFER);
*(memoryBaseAddress + MAP_ADDR_LUT_OFFSET + 1) =
(NO_DESTINATION << 24) | (NO_DESTINATION << 16) | (NO_DESTINATION << 8) | routeToPm;
// Write map id clock frequencies
for (int idx = 0; idx <= MAX_MAP_ADDR; idx += 4) {
*(memoryBaseAddress + MAP_CLK_FREQ_OFFSET + idx / 4) =
MAP_CLK_FREQ << 24 | MAP_CLK_FREQ << 16 | MAP_CLK_FREQ << 8 | MAP_CLK_FREQ;
ReturnValue_t PdecHandler::getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) {
if ((domainId == 0) and (uniqueIdentifier == ParameterId::POSITIVE_WINDOW)) {
uint8_t newVal = 0;
ReturnValue_t result = newValues->getElement(&newVal);
if (result != returnvalue::OK) {
return result;
}
uint8_t positiveWindow = 0;
result = pdecConfig.getPositiveWindow(positiveWindow);
if (result != returnvalue::OK) {
sif::warning << "PdecHandler::getParameter: Failed to get positive window from pdec config"
<< std::endl;
return returnvalue::FAILED;
}
parameterWrapper->set(positiveWindow);
result = pdecConfig.setPositiveWindow(newVal);
if (result != returnvalue::OK) {
sif::warning << "PdecHandler::getParameter: Failed to set positive window" << std::endl;
return returnvalue::FAILED;
}
// PDEC needs reset to apply this parameter change
state = State::PDEC_RESET;
return returnvalue::OK;
} else if ((domainId == 0) and (uniqueIdentifier == ParameterId::NEGATIVE_WINDOW)) {
uint8_t newVal = 0;
ReturnValue_t result = newValues->getElement(&newVal);
if (result != returnvalue::OK) {
return result;
}
uint8_t negativeWindow = 0;
result = pdecConfig.getNegativeWindow(negativeWindow);
if (result != returnvalue::OK) {
sif::warning << "PdecHandler::getParameter: Failed to get negative window from pdec config"
<< std::endl;
return returnvalue::FAILED;
}
parameterWrapper->set(negativeWindow);
result = pdecConfig.setNegativeWindow(newVal);
if (result != returnvalue::OK) {
sif::warning << "PdecHandler::getParameter: Failed to set negative window" << std::endl;
return returnvalue::FAILED;
}
// PDEC needs reset to apply this parameter change
state = State::PDEC_RESET;
return returnvalue::OK;
}
return returnvalue::OK;
}
ReturnValue_t PdecHandler::resetFarStatFlag() {
@ -320,6 +424,17 @@ ReturnValue_t PdecHandler::releasePdec() {
return result;
}
ReturnValue_t PdecHandler::pdecToReset() {
ReturnValue_t result = returnvalue::OK;
result = gpioComIF->pullLow(pdecReset);
if (result != returnvalue::OK) {
sif::error << "PdecHandler::pdecToReset: Failed to pull PDEC reset line"
" to low"
<< std::endl;
}
return result;
}
bool PdecHandler::newTcReceived() {
uint32_t pdecFar = readFar();
@ -557,23 +672,6 @@ void PdecHandler::printTC(uint32_t tcLength) {
sif::info << tcSegmentStream.str() << std::endl;
}
uint8_t PdecHandler::calcMapAddrEntry(uint8_t moduleId) {
uint8_t lutEntry = 0;
uint8_t parity = getOddParity(moduleId | (1 << VALID_POSITION));
lutEntry = (parity << PARITY_POSITION) | (1 << VALID_POSITION) | moduleId;
return lutEntry;
}
uint8_t PdecHandler::getOddParity(uint8_t number) {
uint8_t parityBit = 0;
uint8_t countBits = 0;
for (unsigned int idx = 0; idx < sizeof(number) * 8; idx++) {
countBits += (number >> idx) & 0x1;
}
parityBit = ~(countBits & 0x1) & 0x1;
return parityBit;
}
uint32_t PdecHandler::getClcw() { return *(registerBaseAddress + PDEC_CLCW_OFFSET); }
uint32_t PdecHandler::getPdecMon() { return *(registerBaseAddress + PDEC_MON_OFFSET); }
@ -664,17 +762,3 @@ std::string PdecHandler::getMonStatusString(uint32_t status) {
break;
}
}
ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
switch (actionId) {
case PRINT_CLCW:
printClcw();
return EXECUTION_FINISHED;
case PRINT_PDEC_MON:
printPdecMon();
return EXECUTION_FINISHED;
default:
return COMMAND_NOT_IMPLEMENTED;
}
}

View File

@ -9,6 +9,8 @@
#include "fsfw/action/ActionHelper.h"
#include "fsfw/action/HasActionsIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/parameters/ParameterHelper.h"
#include "fsfw/parameters/ReceivesParameterMessagesIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
@ -41,7 +43,10 @@ struct UioNames {
*
* @author J. Meier
*/
class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasActionsIF {
class PdecHandler : public SystemObject,
public ExecutableObjectIF,
public HasActionsIF,
public ReceivesParameterMessagesIF {
public:
static constexpr dur_millis_t IRQ_TIMEOUT_MS = 500;
@ -70,6 +75,10 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override;
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) override;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER;
//! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame
@ -92,7 +101,12 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
static constexpr Event POLL_SYSCALL_ERROR_PDEC =
event::makeEvent(SUBSYSTEM_ID, 8, severity::MEDIUM);
static constexpr Event WRITE_SYSCALL_ERROR_PDEC =
event::makeEvent(SUBSYSTEM_ID, 9, severity::MEDIUM);
event::makeEvent(SUBSYSTEM_ID, 9, severity::HIGH);
//! [EXPORT] : [COMMENT] Failed to pull PDEC reset to low
static constexpr Event PDEC_RESET_FAILED = event::makeEvent(SUBSYSTEM_ID, 10, severity::HIGH);
//! [EXPORT] : [COMMENT] Failed to open the IRQ uio file
static constexpr Event OPEN_IRQ_FILE_FAILED =
event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH);
private:
static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER;
@ -143,9 +157,6 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
static const int REGISTER_MAP_SIZE = 0x4000;
#endif /* BOARD_TE0720 == 1 */
// 0x200 / 4 = 0x80
static const uint32_t FRAME_HEADER_OFFSET = 0x80;
static const size_t MAX_TC_SEGMENT_SIZE = 1017;
static const uint8_t MAP_ID_MASK = 0x3F;
@ -155,15 +166,6 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
static const uint32_t PHYSICAL_RAM_BASE_ADDRESS = 0x26000000;
#endif
static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0;
static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90;
static const uint8_t MAX_MAP_ADDR = 63;
// Writing this to the map address in the look up table will invalidate a MAP ID.
static const uint8_t NO_DESTINATION = 0;
static const uint8_t VALID_POSITION = 6;
static const uint8_t PARITY_POSITION = 7;
// Expected value stored in FAR register after reset
static const uint32_t FAR_RESET = 0x7FE0;
@ -172,15 +174,15 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
static const uint32_t NO_RF_MASK = 0x8000;
static const uint32_t NO_BITLOCK_MASK = 0x4000;
/**
* TCs with map addresses (also know as Map IDs) assigned to this channel will be stored in
* the PDEC memory.
*/
static const uint8_t PM_BUFFER = 7;
static const uint32_t MAX_INIT_TRIES = 20;
// MAP clock frequency. Must be a value between 1 and 13 otherwise the TC segment will be
// discarded
static const uint8_t MAP_CLK_FREQ = 2;
class ParameterId {
public:
// ID of the parameter to update the positive window of AD frames
static const uint8_t POSITIVE_WINDOW = 0;
// ID of the parameter to update the negative window of AD frames
static const uint8_t NEGATIVE_WINDOW = 1;
};
static constexpr uint32_t MAX_ALLOWED_IRQS_PER_WINDOW = 800;
@ -206,7 +208,7 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
INCORRECT_BC_CC
};
enum class State : uint8_t { INIT, RUNNING, WAIT_FOR_RECOVERY };
enum class State : uint8_t { INIT, PDEC_RESET, RUNNING, WAIT_FOR_RECOVERY };
static uint32_t CURRENT_FAR;
@ -259,6 +261,20 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
UioNames uioNames;
ParameterHelper paramHelper;
PdecConfig pdecConfig;
uint32_t initTries = 0;
/**
* @brief Performs initialization stuff which must be performed in first
* loop of running task
*
* @return OK if successful, otherwise FAILED
*/
ReturnValue_t firstLoop();
/**
* @brief Reads and handles messages stored in the commandQueue
*/
@ -266,6 +282,8 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
ReturnValue_t polledOperation();
ReturnValue_t irqOperation();
ReturnValue_t handleInitState();
void openIrqFile(int* fd);
ReturnValue_t checkAndHandleIrqs(int fd, uint32_t& info);
uint32_t readFar();
@ -291,6 +309,14 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
*/
ReturnValue_t releasePdec();
/**
* @brief Will set PDEC in reset state. Use releasePdec() to release PDEC
* from reset state
*
* @return OK if successful, otherwise error return value
*/
ReturnValue_t pdecToReset();
/**
* @brief Reads the FAR register and checks if a new TC has been received.
*/
@ -354,13 +380,6 @@ class PdecHandler : public SystemObject, public ExecutableObjectIF, public HasAc
*/
uint8_t calcMapAddrEntry(uint8_t moduleId);
/**
* @brief This functions calculates the odd parity of the bits in number.
*
* @param number The number from which to calculate the odd parity.
*/
uint8_t getOddParity(uint8_t number);
/**
* brief Returns the 32-bit wide communication link control word (CLCW)
*/

View File

@ -0,0 +1,20 @@
#ifndef LINUX_IPCORE_PDECCONFIGDEFS_H_
#define LINUX_IPCORE_PDECCONFIGDEFS_H_
#include <string>
namespace pdecconfigdefs {
namespace paramkeys {
static const std::string POSITIVE_WINDOW = "positive_window";
static const std::string NEGATIVE_WINDOW = "negattive_window";
} // namespace paramkeys
namespace defaultvalue {
static const uint8_t positiveWindow = 10;
static const uint8_t negativeWindow = 151;
} // namespace defaultvalue
} // namespace pdecconfigdefs
#endif /* LINUX_IPCORE_PDECCONFIGDEFS_H_ */

View File

@ -0,0 +1,9 @@
#ifndef MISSION_CONFIG_CONFIGFILE_H_
#define MISSION_CONFIG_CONFIGFILE_H_
namespace configfile {
// Name of global config file relative to currently mounted SD card
static const char sdrelative[] = "config/global_config.json";
} // namespace configfile
#endif /* MISSION_CONFIG_CONFIGFILE_H_ */

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],
@ -432,64 +452,57 @@ ReturnValue_t AcsController::commandActuators(int16_t xDipole, int16_t yDipole,
return returnvalue::OK;
}
void AcsController::updateActuatorCmdData(int16_t mtqTargetDipole[3]) {
double rwTargetTorque[4] = {0.0, 0.0, 0.0, 0.0};
int32_t rwTargetSpeed[4] = {0, 0, 0, 0};
updateActuatorCmdData(rwTargetTorque, rwTargetSpeed, mtqTargetDipole);
void AcsController::updateActuatorCmdData(const int16_t *mtqTargetDipole) {
updateActuatorCmdData(RW_OFF_TORQUE, RW_OFF_SPEED, mtqTargetDipole);
}
void AcsController::updateActuatorCmdData(double rwTargetTorque[4], int32_t rwTargetSpeed[4],
int16_t mtqTargetDipole[3]) {
{
PoolReadGuard pg(&actuatorCmdData);
if (pg.getReadResult() == returnvalue::OK) {
std::memcpy(actuatorCmdData.rwTargetTorque.value, rwTargetTorque, 4 * sizeof(double));
std::memcpy(actuatorCmdData.rwTargetSpeed.value, rwTargetSpeed, 4 * sizeof(int32_t));
std::memcpy(actuatorCmdData.mtqTargetDipole.value, mtqTargetDipole, 3 * sizeof(int16_t));
actuatorCmdData.setValidity(true, true);
}
void AcsController::updateActuatorCmdData(const double *rwTargetTorque,
const int32_t *rwTargetSpeed,
const int16_t *mtqTargetDipole) {
PoolReadGuard pg(&actuatorCmdData);
if (pg.getReadResult() == returnvalue::OK) {
std::memcpy(actuatorCmdData.rwTargetTorque.value, rwTargetTorque, 4 * sizeof(double));
std::memcpy(actuatorCmdData.rwTargetSpeed.value, rwTargetSpeed, 4 * sizeof(int32_t));
std::memcpy(actuatorCmdData.mtqTargetDipole.value, mtqTargetDipole, 3 * sizeof(int16_t));
actuatorCmdData.setValidity(true, true);
}
}
void AcsController::updateCtrlValData(double errAng) {
double unitQuat[4] = {0, 0, 0, 1};
{
PoolReadGuard pg(&ctrlValData);
if (pg.getReadResult() == returnvalue::OK) {
std::memcpy(ctrlValData.tgtQuat.value, unitQuat, 4 * sizeof(double));
ctrlValData.tgtQuat.setValid(false);
std::memcpy(ctrlValData.errQuat.value, unitQuat, 4 * sizeof(double));
ctrlValData.errQuat.setValid(false);
ctrlValData.errAng.value = errAng;
ctrlValData.errAng.setValid(true);
ctrlValData.setValidity(true, false);
}
PoolReadGuard pg(&ctrlValData);
if (pg.getReadResult() == returnvalue::OK) {
std::memcpy(ctrlValData.tgtQuat.value, UNIT_QUAT, 4 * sizeof(double));
ctrlValData.tgtQuat.setValid(false);
std::memcpy(ctrlValData.errQuat.value, UNIT_QUAT, 4 * sizeof(double));
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(double tgtQuat[4], double errQuat[4], double errAng) {
{
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;
ctrlValData.setValidity(true, true);
}
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);
}
}
void AcsController::disableCtrlValData() {
double unitQuat[4] = {0, 0, 0, 1};
double errAng = 0;
{
PoolReadGuard pg(&ctrlValData);
if (pg.getReadResult() == returnvalue::OK) {
std::memcpy(ctrlValData.tgtQuat.value, unitQuat, 4 * sizeof(double));
std::memcpy(ctrlValData.errQuat.value, unitQuat, 4 * sizeof(double));
ctrlValData.errAng.value = errAng;
ctrlValData.setValidity(false, true);
}
PoolReadGuard pg(&ctrlValData);
if (pg.getReadResult() == returnvalue::OK) {
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:
@ -40,6 +40,11 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
void performPointingCtrl();
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};
AcsParameters acsParameters;
SensorProcessing sensorProcessing;
Navigation navigation;
@ -54,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};
@ -64,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;
@ -84,11 +99,12 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
ReturnValue_t commandActuators(int16_t xDipole, int16_t yDipole, int16_t zDipole,
uint16_t dipoleTorqueDuration, int32_t rw1Speed, int32_t rw2Speed,
int32_t rw3Speed, int32_t rw4Speed, uint16_t rampTime);
void updateActuatorCmdData(int16_t mtqTargetDipole[3]);
void updateActuatorCmdData(double rwTargetTorque[4], int32_t rwTargetSpeed[4],
int16_t mtqTargetDipole[3]);
void updateActuatorCmdData(const int16_t* mtqTargetDipole);
void updateActuatorCmdData(const double* rwTargetTorque, const int32_t* rwTargetSpeed,
const int16_t* mtqTargetDipole);
void updateCtrlValData(double errAng);
void updateCtrlValData(double tgtQuat[4], double errQuat[4], double errAng);
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng,
const double* tgtRotRate);
void disableCtrlValData();
/* ACS Sensor Values */
@ -187,7 +203,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
PoolEntry<double> tgtQuat = PoolEntry<double>(4);
PoolEntry<double> errQuat = PoolEntry<double>(4);
PoolEntry<double> errAng = PoolEntry<double>();
PoolEntry<double> tgtRotRate = PoolEntry<double>(4);
PoolEntry<double> tgtRotRate = PoolEntry<double>(3);
// Actuator CMD
acsctrl::ActuatorCmdData actuatorCmdData;

View File

@ -3,13 +3,13 @@
#include <bsp_q7s/core/CoreDefinitions.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/thermal/ThermalComponentIF.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h>
#include <linux/devices/devicedefinitions/StarTrackerDefinitions.h>
#include <mission/devices/devicedefinitions/BpxBatteryDefinitions.h>
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
#include <mission/devices/devicedefinitions/GyroADIS1650XDefinitions.h>
#include <mission/devices/devicedefinitions/GyroL3GD20Definitions.h>
#include <mission/devices/devicedefinitions/SyrlinksDefinitions.h>
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
#include <mission/devices/devicedefinitions/imtqHelpers.h>
#include <mission/devices/devicedefinitions/payloadPcduDefinitions.h>
#include <mission/devices/devicedefinitions/rwHelpers.h>
@ -855,7 +855,7 @@ void ThermalController::copyDevices() {
{
lp_var_t<float> tempGyro0 =
lp_var_t<float>(objects::GYRO_0_ADIS_HANDLER, ADIS1650X::TEMPERATURE);
lp_var_t<float>(objects::GYRO_0_ADIS_HANDLER, adis1650x::TEMPERATURE);
PoolReadGuard pg(&tempGyro0, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
if (pg.getReadResult() != returnvalue::OK) {
sif::warning << "ThermalController: Failed to read gyro 0 temperature" << std::endl;
@ -868,7 +868,7 @@ void ThermalController::copyDevices() {
}
{
lp_var_t<float> tempGyro1 = lp_var_t<float>(objects::GYRO_1_L3G_HANDLER, L3GD20H::TEMPERATURE);
lp_var_t<float> tempGyro1 = lp_var_t<float>(objects::GYRO_1_L3G_HANDLER, l3gd20h::TEMPERATURE);
PoolReadGuard pg(&tempGyro1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
if (pg.getReadResult() != returnvalue::OK) {
sif::warning << "ThermalController: Failed to read gyro 1 temperature" << std::endl;
@ -882,7 +882,7 @@ void ThermalController::copyDevices() {
{
lp_var_t<float> tempGyro2 =
lp_var_t<float>(objects::GYRO_2_ADIS_HANDLER, ADIS1650X::TEMPERATURE);
lp_var_t<float>(objects::GYRO_2_ADIS_HANDLER, adis1650x::TEMPERATURE);
PoolReadGuard pg(&tempGyro2, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
if (pg.getReadResult() != returnvalue::OK) {
sif::warning << "ThermalController: Failed to read gyro 2 temperature" << std::endl;
@ -895,7 +895,7 @@ void ThermalController::copyDevices() {
}
{
lp_var_t<float> tempGyro3 = lp_var_t<float>(objects::GYRO_3_L3G_HANDLER, L3GD20H::TEMPERATURE);
lp_var_t<float> tempGyro3 = lp_var_t<float>(objects::GYRO_3_L3G_HANDLER, l3gd20h::TEMPERATURE);
PoolReadGuard pg(&tempGyro3, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
if (pg.getReadResult() != returnvalue::OK) {
sif::warning << "ThermalController: Failed to read gyro 3 temperature" << std::endl;
@ -909,7 +909,7 @@ void ThermalController::copyDevices() {
{
lp_var_t<float> tempMgm0 =
lp_var_t<float>(objects::MGM_0_LIS3_HANDLER, MGMLIS3MDL::TEMPERATURE_CELCIUS);
lp_var_t<float>(objects::MGM_0_LIS3_HANDLER, mgmLis3::TEMPERATURE_CELCIUS);
PoolReadGuard pg(&tempMgm0, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
if (pg.getReadResult() != returnvalue::OK) {
sif::warning << "ThermalController: Failed to read MGM 0 temperature" << std::endl;
@ -923,7 +923,7 @@ void ThermalController::copyDevices() {
{
lp_var_t<float> tempMgm2 =
lp_var_t<float>(objects::MGM_2_LIS3_HANDLER, MGMLIS3MDL::TEMPERATURE_CELCIUS);
lp_var_t<float>(objects::MGM_2_LIS3_HANDLER, mgmLis3::TEMPERATURE_CELCIUS);
PoolReadGuard pg(&tempMgm2, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
if (pg.getReadResult() != returnvalue::OK) {
sif::warning << "ThermalController: Failed to read MGM 2 temperature" << std::endl;

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,6 +1,7 @@
#ifndef SENSORVALUES_H_
#define SENSORVALUES_H_
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
#include <mission/devices/devicedefinitions/imtqHelpers.h>
#include <mission/devices/devicedefinitions/rwHelpers.h>
@ -9,7 +10,6 @@
#include "fsfw_hal/devicehandlers/MgmRM3100Handler.h"
#include "linux/devices/devicedefinitions/StarTrackerDefinitions.h"
#include "mission/devices/devicedefinitions/GPSDefinitions.h"
#include "mission/devices/devicedefinitions/GyroADIS1650XDefinitions.h"
#include "mission/devices/devicedefinitions/SusDefinitions.h"
namespace ACS {
@ -27,14 +27,12 @@ class SensorValues {
ReturnValue_t updateStr();
ReturnValue_t updateRw();
MGMLIS3MDL::MgmPrimaryDataset mgm0Lis3Set =
MGMLIS3MDL::MgmPrimaryDataset(objects::MGM_0_LIS3_HANDLER);
RM3100::Rm3100PrimaryDataset mgm1Rm3100Set =
RM3100::Rm3100PrimaryDataset(objects::MGM_1_RM3100_HANDLER);
MGMLIS3MDL::MgmPrimaryDataset mgm2Lis3Set =
MGMLIS3MDL::MgmPrimaryDataset(objects::MGM_2_LIS3_HANDLER);
RM3100::Rm3100PrimaryDataset mgm3Rm3100Set =
RM3100::Rm3100PrimaryDataset(objects::MGM_3_RM3100_HANDLER);
mgmLis3::MgmPrimaryDataset mgm0Lis3Set = mgmLis3::MgmPrimaryDataset(objects::MGM_0_LIS3_HANDLER);
mgmRm3100::Rm3100PrimaryDataset mgm1Rm3100Set =
mgmRm3100::Rm3100PrimaryDataset(objects::MGM_1_RM3100_HANDLER);
mgmLis3::MgmPrimaryDataset mgm2Lis3Set = mgmLis3::MgmPrimaryDataset(objects::MGM_2_LIS3_HANDLER);
mgmRm3100::Rm3100PrimaryDataset mgm3Rm3100Set =
mgmRm3100::Rm3100PrimaryDataset(objects::MGM_3_RM3100_HANDLER);
imtq::RawMtmMeasurementNoTorque imtqMgmSet =
imtq::RawMtmMeasurementNoTorque(objects::IMTQ_HANDLER);

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

@ -110,7 +110,7 @@ static constexpr uint8_t SUS_SET_PROCESSED_ENTRIES = 15;
static constexpr uint8_t GYR_SET_RAW_ENTRIES = 4;
static constexpr uint8_t GYR_SET_PROCESSED_ENTRIES = 5;
static constexpr uint8_t GPS_SET_PROCESSED_ENTRIES = 4;
static constexpr uint8_t MEKF_SET_ENTRIES = 2;
static constexpr uint8_t MEKF_SET_ENTRIES = 3;
static constexpr uint8_t CTRL_VAL_SET_ENTRIES = 4;
static constexpr uint8_t ACT_CMD_SET_ENTRIES = 3;

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

@ -189,110 +189,7 @@ ReturnValue_t pst::pstTest(FixedTimeslotTaskIF *thisSequence) {
ReturnValue_t pst::pstTcsAndAcs(FixedTimeslotTaskIF *thisSequence, AcsPstCfg cfg) {
/* Length of a communication cycle */
uint32_t length = thisSequence->getPeriodMs();
bool enableAside = true;
bool enableBside = true;
if (cfg.scheduleAcsBoard) {
if (enableAside) {
// A side
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_READ);
}
if (enableBside) {
// B side
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_READ);
}
}
// SUS: 16 ms
bool addSus0 = true;
bool addSus1 = true;
@ -583,6 +480,113 @@ ReturnValue_t pst::pstTcsAndAcs(FixedTimeslotTaskIF *thisSequence, AcsPstCfg cfg
thisSequence->addSlot(objects::STAR_TRACKER, length * 0, DeviceHandlerIF::GET_READ);
}
bool enableAside = true;
bool enableBside = true;
if (cfg.scheduleAcsBoard) {
if (enableAside) {
// A side
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_3_PERIOD,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_3_PERIOD,
DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_3_PERIOD, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_3_PERIOD, DeviceHandlerIF::GET_READ);
}
if (enableBside) {
// B side
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_3_PERIOD,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * config::acs::SCHED_BLOCK_3_PERIOD,
DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_3_PERIOD, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER,
length * config::acs::SCHED_BLOCK_3_PERIOD, DeviceHandlerIF::GET_READ);
}
if (enableAside) {
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_3_PERIOD, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_0_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_3_PERIOD, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * config::acs::SCHED_BLOCK_3_PERIOD,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * config::acs::SCHED_BLOCK_3_PERIOD,
DeviceHandlerIF::GET_READ);
}
if (enableBside) {
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_2_PERIOD, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_3_PERIOD, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_2_ADIS_HANDLER,
length * config::acs::SCHED_BLOCK_3_PERIOD, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * config::acs::SCHED_BLOCK_2_PERIOD,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * config::acs::SCHED_BLOCK_3_PERIOD,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_3_L3G_HANDLER, length * config::acs::SCHED_BLOCK_3_PERIOD,
DeviceHandlerIF::GET_READ);
}
}
if (cfg.scheduleImtq) {
// This is the MTM measurement cycle
thisSequence->addSlot(objects::IMTQ_HANDLER, length * config::acs::SCHED_BLOCK_1_PERIOD,

View File

@ -14,7 +14,10 @@ target_sources(
ImtqHandler.cpp
HeaterHandler.cpp
RadiationSensorHandler.cpp
GyroADIS1650XHandler.cpp
GyrAdis1650XHandler.cpp
GyrL3gCustomHandler.cpp
MgmRm3100CustomHandler.cpp
MgmLis3CustomHandler.cpp
RwHandler.cpp
max1227.cpp
SusHandler.cpp

View File

@ -0,0 +1,225 @@
#include "mission/devices/GyrAdis1650XHandler.h"
#include "fsfw/action/HasActionsIF.h"
#include "fsfw/datapool/PoolReadGuard.h"
#include "mission/devices/devicedefinitions/acsPolling.h"
GyrAdis1650XHandler::GyrAdis1650XHandler(object_id_t objectId, object_id_t deviceCommunication,
CookieIF *comCookie, adis1650x::Type type)
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
adisType(type),
primaryDataset(this),
configDataset(this),
breakCountdown() {
adisRequest.type = adisType;
}
void GyrAdis1650XHandler::doStartUp() {
if (internalState != InternalState::STARTUP) {
internalState = InternalState::STARTUP;
commandExecuted = false;
}
// Initial 310 ms start up time after power-up
if (internalState == InternalState::STARTUP) {
if (not commandExecuted) {
warningSwitch = true;
breakCountdown.setTimeout(adis1650x::START_UP_TIME);
commandExecuted = true;
}
if (breakCountdown.hasTimedOut()) {
updatePeriodicReply(true, adis1650x::REPLY);
if (goToNormalMode) {
setMode(MODE_NORMAL);
} else {
setMode(MODE_ON);
}
internalState = InternalState::NONE;
}
}
}
void GyrAdis1650XHandler::doShutDown() {
if (internalState != InternalState::SHUTDOWN) {
commandExecuted = false;
primaryDataset.setValidity(false, true);
internalState = InternalState::SHUTDOWN;
}
if (internalState == InternalState::SHUTDOWN and commandExecuted) {
updatePeriodicReply(false, adis1650x::REPLY);
internalState = InternalState::NONE;
commandExecuted = false;
setMode(_MODE_POWER_DOWN);
}
}
ReturnValue_t GyrAdis1650XHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) {
*id = adis1650x::REQUEST;
return preparePeriodicRequest(acs::SimpleSensorMode::NORMAL);
}
ReturnValue_t GyrAdis1650XHandler::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
switch (internalState) {
case (InternalState::STARTUP): {
*id = adis1650x::REQUEST;
return preparePeriodicRequest(acs::SimpleSensorMode::NORMAL);
}
case (InternalState::SHUTDOWN): {
*id = adis1650x::REQUEST;
acs::Adis1650XRequest *request = reinterpret_cast<acs::Adis1650XRequest *>(cmdBuf.data());
request->mode = acs::SimpleSensorMode::OFF;
request->type = adisType;
return returnvalue::OK;
}
default: {
return NOTHING_TO_SEND;
}
}
return returnvalue::OK;
}
ReturnValue_t GyrAdis1650XHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {
return NOTHING_TO_SEND;
}
void GyrAdis1650XHandler::fillCommandAndReplyMap() {
insertInCommandMap(adis1650x::REQUEST);
insertInReplyMap(adis1650x::REPLY, 5, nullptr, 0, true);
}
ReturnValue_t GyrAdis1650XHandler::scanForReply(const uint8_t *start, size_t remainingSize,
DeviceCommandId_t *foundId, size_t *foundLen) {
if (breakCountdown.isBusy() or getMode() == _MODE_WAIT_OFF or getMode() == _MODE_WAIT_ON) {
return IGNORE_FULL_PACKET;
}
if (remainingSize != sizeof(acs::Adis1650XReply)) {
*foundLen = remainingSize;
return returnvalue::FAILED;
}
*foundId = adis1650x::REPLY;
*foundLen = remainingSize;
if (internalState == InternalState::SHUTDOWN) {
commandExecuted = true;
}
return returnvalue::OK;
}
ReturnValue_t GyrAdis1650XHandler::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) {
using namespace adis1650x;
const acs::Adis1650XReply *reply = reinterpret_cast<const acs::Adis1650XReply *>(packet);
if (internalState == InternalState::STARTUP and reply->cfgWasSet) {
switch (adisType) {
case (adis1650x::Type::ADIS16507): {
if (reply->cfg.prodId != adis1650x::PROD_ID_16507) {
sif::error << "GyroADIS1650XHandler::interpretDeviceReply: Invalid product ID "
<< reply->cfg.prodId << "for ADIS type 16507" << std::endl;
return returnvalue::FAILED;
}
break;
}
case (adis1650x::Type::ADIS16505): {
if (reply->cfg.prodId != adis1650x::PROD_ID_16505) {
sif::error << "GyroADIS1650XHandler::interpretDeviceReply: Invalid product ID "
<< reply->cfg.prodId << "for ADIS type 16505" << std::endl;
return returnvalue::FAILED;
}
break;
}
}
PoolReadGuard rg(&configDataset);
configDataset.setValidity(true, true);
configDataset.mscCtrlReg = reply->cfg.mscCtrlReg;
configDataset.rangMdl = reply->cfg.rangMdl;
configDataset.diagStatReg = reply->cfg.diagStat;
configDataset.filterSetting = reply->cfg.filterSetting;
configDataset.decRateReg = reply->cfg.decRateReg;
commandExecuted = true;
}
if (reply->dataWasSet) {
{
PoolReadGuard rg(&configDataset);
configDataset.diagStatReg = reply->cfg.diagStat;
}
auto sensitivity = reply->data.sensitivity;
auto accelSensitivity = reply->data.accelScaling;
PoolReadGuard pg(&primaryDataset);
primaryDataset.setValidity(true, true);
primaryDataset.angVelocX = static_cast<double>(reply->data.angVelocities[0]) * sensitivity;
primaryDataset.angVelocY = static_cast<double>(reply->data.angVelocities[1]) * sensitivity;
primaryDataset.angVelocZ = static_cast<double>(reply->data.angVelocities[2]) * sensitivity;
// TODO: Check whether we need to divide by INT16_MAX
primaryDataset.accelX = static_cast<double>(reply->data.accelerations[0]) * accelSensitivity;
primaryDataset.accelY = static_cast<double>(reply->data.accelerations[1]) * accelSensitivity;
primaryDataset.accelZ = static_cast<double>(reply->data.accelerations[2]) * accelSensitivity;
primaryDataset.temperature.value = static_cast<float>(reply->data.temperatureRaw) * 0.1;
}
return returnvalue::OK;
}
LocalPoolDataSetBase *GyrAdis1650XHandler::getDataSetHandle(sid_t sid) {
if (sid.ownerSetId == adis1650x::ADIS_DATASET_ID) {
return &primaryDataset;
} else if (sid.ownerSetId == adis1650x::ADIS_CFG_DATASET_ID) {
return &configDataset;
}
return nullptr;
}
uint32_t GyrAdis1650XHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 6000; }
void GyrAdis1650XHandler::prepareWriteCommand(uint8_t startReg, uint8_t valueOne,
uint8_t valueTwo) {
uint8_t secondReg = startReg + 1;
startReg |= adis1650x::WRITE_MASK;
secondReg |= adis1650x::WRITE_MASK;
cmdBuf[0] = startReg;
cmdBuf[1] = valueOne;
cmdBuf[2] = secondReg;
cmdBuf[3] = valueTwo;
this->rawPacketLen = 4;
this->rawPacket = cmdBuf.data();
}
ReturnValue_t GyrAdis1650XHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(adis1650x::ANG_VELOC_X, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(adis1650x::ANG_VELOC_Y, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(adis1650x::ANG_VELOC_Z, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(adis1650x::ACCELERATION_X, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(adis1650x::ACCELERATION_Y, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(adis1650x::ACCELERATION_Z, new PoolEntry<double>({0.0}));
localDataPoolMap.emplace(adis1650x::TEMPERATURE, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(adis1650x::DIAG_STAT_REGISTER, new PoolEntry<uint16_t>());
localDataPoolMap.emplace(adis1650x::FILTER_SETTINGS, new PoolEntry<uint8_t>());
localDataPoolMap.emplace(adis1650x::RANG_MDL, &rangMdl);
localDataPoolMap.emplace(adis1650x::MSC_CTRL_REGISTER, new PoolEntry<uint16_t>());
localDataPoolMap.emplace(adis1650x::DEC_RATE_REGISTER, new PoolEntry<uint16_t>());
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(primaryDataset.getSid(), false, 5.0));
return returnvalue::OK;
}
adis1650x::BurstModes GyrAdis1650XHandler::getBurstMode() {
using namespace adis1650x;
configDataset.mscCtrlReg.read();
uint16_t currentCtrlReg = configDataset.mscCtrlReg.value;
configDataset.mscCtrlReg.commit();
return adis1650x::burstModeFromMscCtrl(currentCtrlReg);
}
void GyrAdis1650XHandler::setToGoToNormalModeImmediately() { goToNormalMode = true; }
void GyrAdis1650XHandler::enablePeriodicPrintouts(bool enable, uint8_t divider) {
periodicPrintout = enable;
debugDivider.setDivider(divider);
}
ReturnValue_t GyrAdis1650XHandler::preparePeriodicRequest(acs::SimpleSensorMode mode) {
adisRequest.mode = mode;
rawPacket = reinterpret_cast<uint8_t *>(&adisRequest);
rawPacketLen = sizeof(acs::Adis1650XRequest);
return returnvalue::OK;
}

View File

@ -1,27 +1,24 @@
#ifndef MISSION_DEVICES_GYROADIS16507HANDLER_H_
#define MISSION_DEVICES_GYROADIS16507HANDLER_H_
#include <mission/devices/devicedefinitions/acsPolling.h>
#include <mission/devices/devicedefinitions/gyroAdisHelpers.h>
#include "FSFWConfig.h"
#include "OBSWConfig.h"
#include "devicedefinitions/GyroADIS1650XDefinitions.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
#ifdef FSFW_OSAL_LINUX
class SpiComIF;
class SpiCookie;
#endif
/**
* @brief Device handle for the ADIS16507 Gyroscope by Analog Devices
* @details
* Flight manual:
* https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/ADIS16507_Gyro
*/
class GyroADIS1650XHandler : public DeviceHandlerBase {
class GyrAdis1650XHandler : public DeviceHandlerBase {
public:
GyroADIS1650XHandler(object_id_t objectId, object_id_t deviceCommunication, CookieIF *comCookie,
ADIS1650X::Type type);
GyrAdis1650XHandler(object_id_t objectId, object_id_t deviceCommunication, CookieIF *comCookie,
adis1650x::Type type);
void enablePeriodicPrintouts(bool enable, uint8_t divider);
void setToGoToNormalModeImmediately();
@ -40,40 +37,31 @@ class GyroADIS1650XHandler : public DeviceHandlerBase {
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
private:
std::array<uint8_t, 32> commandBuffer;
ADIS1650X::Type adisType;
std::array<uint8_t, 32> cmdBuf;
acs::Adis1650XRequest adisRequest;
adis1650x::Type adisType;
AdisGyroPrimaryDataset primaryDataset;
AdisGyroConfigDataset configDataset;
double sensitivity = ADIS1650X::SENSITIVITY_UNSET;
double sensitivity = adis1650x::SENSITIVITY_UNSET;
bool goToNormalMode = false;
bool warningSwitch = true;
enum class InternalState { STARTUP, CONFIG, IDLE };
enum class BurstModes {
BURST_16_BURST_SEL_0,
BURST_16_BURST_SEL_1,
BURST_32_BURST_SEL_0,
BURST_32_BURST_SEL_1
};
enum class InternalState { NONE, STARTUP, SHUTDOWN };
InternalState internalState = InternalState::STARTUP;
bool commandExecuted = false;
void prepareReadCommand(uint8_t *regList, size_t len);
PoolEntry<uint16_t> rangMdl = PoolEntry<uint16_t>();
BurstModes getBurstMode();
#ifdef FSFW_OSAL_LINUX
static ReturnValue_t spiSendCallback(SpiComIF *comIf, SpiCookie *cookie, const uint8_t *sendData,
size_t sendLen, void *args);
#endif
adis1650x::BurstModes getBurstMode();
Countdown breakCountdown;
void prepareWriteCommand(uint8_t startReg, uint8_t valueOne, uint8_t valueTwo);
ReturnValue_t preparePeriodicRequest(acs::SimpleSensorMode mode);
ReturnValue_t handleSensorData(const uint8_t *packet);

View File

@ -0,0 +1,191 @@
#include <mission/devices/GyrL3gCustomHandler.h>
#include <cmath>
#include "fsfw/datapool/PoolReadGuard.h"
#include "mission/devices/devicedefinitions/acsPolling.h"
GyrL3gCustomHandler::GyrL3gCustomHandler(object_id_t objectId, object_id_t deviceCommunication,
CookieIF *comCookie, uint32_t transitionDelayMs)
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
transitionDelayMs(transitionDelayMs),
dataset(this) {}
GyrL3gCustomHandler::~GyrL3gCustomHandler() = default;
void GyrL3gCustomHandler::doStartUp() {
if (internalState != InternalState::STARTUP) {
internalState = InternalState::STARTUP;
updatePeriodicReply(true, l3gd20h::REPLY);
commandExecuted = false;
}
if (internalState == InternalState::STARTUP) {
if (commandExecuted) {
if (goNormalModeImmediately) {
setMode(MODE_NORMAL);
} else {
setMode(_MODE_TO_ON);
}
internalState = InternalState::NONE;
commandExecuted = false;
}
}
}
void GyrL3gCustomHandler::doShutDown() {
if (internalState != InternalState::SHUTDOWN) {
internalState = InternalState::SHUTDOWN;
dataset.setValidity(false, true);
commandExecuted = false;
}
if (internalState == InternalState::SHUTDOWN and commandExecuted) {
internalState = InternalState::NONE;
updatePeriodicReply(false, l3gd20h::REPLY);
commandExecuted = false;
setMode(_MODE_POWER_DOWN);
}
}
ReturnValue_t GyrL3gCustomHandler::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
switch (internalState) {
case (InternalState::NONE):
case (InternalState::NORMAL): {
return NOTHING_TO_SEND;
}
case (InternalState::STARTUP): {
*id = l3gd20h::REQUEST;
gyrRequest.ctrlRegs[0] = l3gd20h::CTRL_REG_1_VAL;
gyrRequest.ctrlRegs[1] = l3gd20h::CTRL_REG_2_VAL;
gyrRequest.ctrlRegs[2] = l3gd20h::CTRL_REG_3_VAL;
gyrRequest.ctrlRegs[3] = l3gd20h::CTRL_REG_4_VAL;
gyrRequest.ctrlRegs[4] = l3gd20h::CTRL_REG_5_VAL;
return doPeriodicRequest(acs::SimpleSensorMode::NORMAL);
}
case (InternalState::SHUTDOWN): {
*id = l3gd20h::REQUEST;
return doPeriodicRequest(acs::SimpleSensorMode::OFF);
}
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
/* Might be a configuration error. */
sif::warning << "GyroL3GD20Handler::buildTransitionDeviceCommand: "
"Unknown internal state!"
<< std::endl;
#else
sif::printDebug(
"GyroL3GD20Handler::buildTransitionDeviceCommand: "
"Unknown internal state!\n");
#endif
return returnvalue::OK;
}
return returnvalue::OK;
}
ReturnValue_t GyrL3gCustomHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) {
*id = l3gd20h::REQUEST;
return doPeriodicRequest(acs::SimpleSensorMode::NORMAL);
}
ReturnValue_t GyrL3gCustomHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {
switch (deviceCommand) {
default:
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
return returnvalue::OK;
}
ReturnValue_t GyrL3gCustomHandler::scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) {
if (getMode() == _MODE_WAIT_OFF or getMode() == _MODE_WAIT_ON) {
return IGNORE_FULL_PACKET;
}
if (len != sizeof(acs::GyroL3gReply)) {
*foundLen = len;
return returnvalue::FAILED;
}
*foundId = l3gd20h::REPLY;
*foundLen = len;
if (internalState == InternalState::SHUTDOWN) {
commandExecuted = true;
}
return returnvalue::OK;
}
ReturnValue_t GyrL3gCustomHandler::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) {
const acs::GyroL3gReply *reply = reinterpret_cast<const acs::GyroL3gReply *>(packet);
if (reply->cfgWasSet) {
if (internalState == InternalState::STARTUP) {
commandExecuted = true;
}
PoolReadGuard pg(&dataset);
dataset.setValidity(true, true);
dataset.angVelocX = static_cast<float>(reply->angVelocities[0]) * reply->sensitivity;
dataset.angVelocY = static_cast<float>(reply->angVelocities[1]) * reply->sensitivity;
dataset.angVelocZ = static_cast<float>(reply->angVelocities[2]) * reply->sensitivity;
if (std::abs(dataset.angVelocX.value) > absLimitX) {
dataset.angVelocX.setValid(false);
}
if (std::abs(dataset.angVelocY.value) > absLimitY) {
dataset.angVelocY.setValid(false);
}
if (std::abs(dataset.angVelocZ.value) > absLimitZ) {
dataset.angVelocZ.setValid(false);
}
dataset.temperature = 25.0 - reply->tempOffsetRaw;
}
return returnvalue::OK;
}
uint32_t GyrL3gCustomHandler::getTransitionDelayMs(Mode_t from, Mode_t to) {
return this->transitionDelayMs;
}
void GyrL3gCustomHandler::setToGoToNormalMode(bool enable) { this->goNormalModeImmediately = true; }
ReturnValue_t GyrL3gCustomHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(l3gd20h::ANG_VELOC_X, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(l3gd20h::ANG_VELOC_Y, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(l3gd20h::ANG_VELOC_Z, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(l3gd20h::TEMPERATURE, new PoolEntry<float>({0.0}));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(dataset.getSid(), false, 10.0));
return returnvalue::OK;
}
void GyrL3gCustomHandler::fillCommandAndReplyMap() {
insertInCommandMap(l3gd20h::REQUEST);
insertInReplyMap(l3gd20h::REPLY, 5, nullptr, 0, true);
}
void GyrL3gCustomHandler::modeChanged() { internalState = InternalState::NONE; }
void GyrL3gCustomHandler::setAbsoluteLimits(float limitX, float limitY, float limitZ) {
this->absLimitX = limitX;
this->absLimitY = limitY;
this->absLimitZ = limitZ;
}
void GyrL3gCustomHandler::enablePeriodicPrintouts(bool enable, uint8_t divider) {
periodicPrintout = enable;
debugDivider.setDivider(divider);
}
LocalPoolDataSetBase *GyrL3gCustomHandler::getDataSetHandle(sid_t sid) {
if (sid == dataset.getSid()) {
return &dataset;
}
return nullptr;
}
ReturnValue_t GyrL3gCustomHandler::doPeriodicRequest(acs::SimpleSensorMode mode) {
gyrRequest.mode = mode;
rawPacket = reinterpret_cast<uint8_t *>(&gyrRequest);
rawPacketLen = sizeof(acs::GyroL3gRequest);
return returnvalue::OK;
}

View File

@ -0,0 +1,91 @@
#ifndef MISSION_DEVICES_GYROL3GD20HANDLER_H_
#define MISSION_DEVICES_GYROL3GD20HANDLER_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
#include <mission/devices/devicedefinitions/acsPolling.h>
/**
* @brief Device Handler for the L3GD20H gyroscope sensor
* (https://www.st.com/en/mems-and-sensors/l3gd20h.html)
* @details
* Advanced documentation:
* https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/L3GD20H_Gyro
*
* Data is read big endian with the smallest possible range of 245 degrees per second.
*/
class GyrL3gCustomHandler : public DeviceHandlerBase {
public:
GyrL3gCustomHandler(object_id_t objectId, object_id_t deviceCommunication, CookieIF *comCookie,
uint32_t transitionDelayMs);
virtual ~GyrL3gCustomHandler();
void enablePeriodicPrintouts(bool enable, uint8_t divider);
/**
* Set the absolute limit for the values on the axis in degrees per second.
* The dataset values will be marked as invalid if that limit is exceeded
* @param xLimit
* @param yLimit
* @param zLimit
*/
void setAbsoluteLimits(float limitX, float limitY, float limitZ);
/**
* @brief Configure device handler to go to normal mode immediately
*/
void setToGoToNormalMode(bool enable);
protected:
/* DeviceHandlerBase overrides */
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t *start, size_t len, DeviceCommandId_t *foundId,
size_t *foundLen) override;
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
void fillCommandAndReplyMap() override;
void modeChanged() override;
virtual uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
private:
uint32_t transitionDelayMs = 0;
GyroPrimaryDataset dataset;
float absLimitX = l3gd20h::RANGE_DPS_00;
float absLimitY = l3gd20h::RANGE_DPS_00;
float absLimitZ = l3gd20h::RANGE_DPS_00;
enum class InternalState { NONE, STARTUP, SHUTDOWN, NORMAL };
InternalState internalState = InternalState::NONE;
bool commandExecuted = false;
uint8_t statusReg = 0;
bool goNormalModeImmediately = false;
uint8_t ctrlReg1Value = l3gd20h::CTRL_REG_1_VAL;
uint8_t ctrlReg2Value = l3gd20h::CTRL_REG_2_VAL;
uint8_t ctrlReg3Value = l3gd20h::CTRL_REG_3_VAL;
uint8_t ctrlReg4Value = l3gd20h::CTRL_REG_4_VAL;
uint8_t ctrlReg5Value = l3gd20h::CTRL_REG_5_VAL;
acs::GyroL3gRequest gyrRequest{};
// Set default value
float sensitivity = l3gd20h::SENSITIVITY_00;
bool periodicPrintout = false;
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
ReturnValue_t doPeriodicRequest(acs::SimpleSensorMode mode);
};
#endif /* MISSION_DEVICES_GYROL3GD20HANDLER_H_ */

Some files were not shown because too many files have changed in this diff Show More