Compare commits

...

11 Commits

10 changed files with 180 additions and 98 deletions

View File

@@ -565,6 +565,9 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
*/ */
if (newMode == MODE_ON and continueToNormal) { if (newMode == MODE_ON and continueToNormal) {
continueToNormal = false; continueToNormal = false;
// TODO: Check whether the following two lines are okay to do so.
transitionSourceMode = MODE_ON;
transitionSourceSubMode = submode;
mode = _MODE_TO_NORMAL; mode = _MODE_TO_NORMAL;
return; return;
} }

View File

@@ -100,9 +100,7 @@ ReturnValue_t Clock::getClock(timeval* time) {
#endif #endif
} }
ReturnValue_t Clock::getClock_timeval(timeval* time) { ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); }
return Clock::getClock(time);
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) { ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
if (time == nullptr) { if (time == nullptr) {

View File

@@ -42,7 +42,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getClock(timeval *time) { ReturnValue_t Clock::getClock(timeval* time) {
timespec timeUnix{}; timespec timeUnix{};
int status = clock_gettime(CLOCK_REALTIME, &timeUnix); int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) { if (status != 0) {
@@ -53,9 +53,7 @@ ReturnValue_t Clock::getClock(timeval *time) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getClock_timeval(timeval* time) { ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); }
return Clock::getClock(time);
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) { ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval timeVal{}; timeval timeVal{};
@@ -68,7 +66,7 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getClockMonotonic(timeval *time) { ReturnValue_t Clock::getClockMonotonic(timeval* time) {
timespec timeMonotonic{}; timespec timeMonotonic{};
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic); int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic);
if (status != 0) { if (status != 0) {

View File

@@ -68,7 +68,7 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message,
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
switch (subservice) { switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH): { case (Subservice::COMMAND_SET_HEALTH): {
if(tcDataLen != sizeof(object_id_t) + sizeof(HasHealthIF::HealthState)) { if (tcDataLen != sizeof(object_id_t) + sizeof(HasHealthIF::HealthState)) {
return CommandingServiceBase::INVALID_TC; return CommandingServiceBase::INVALID_TC;
} }
HealthSetCommand healthCommand; HealthSetCommand healthCommand;

View File

@@ -21,6 +21,7 @@ SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(c
ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry> tableIter, ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry> tableIter,
Submode_t targetSubmode) { Submode_t targetSubmode) {
using namespace mode;
std::map<object_id_t, ChildInfo>::iterator childIter; std::map<object_id_t, ChildInfo>::iterator childIter;
for (; tableIter.value != NULL; ++tableIter) { for (; tableIter.value != NULL; ++tableIter) {
@@ -34,15 +35,23 @@ ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry
return returnvalue::FAILED; return returnvalue::FAILED;
} }
Submode_t submodeToCheckAgainst = tableIter.value->getSubmode(); // Check submodes here.
uint8_t mask;
bool submodesAllowedMask = tableIter.value->submodesAllowed(&mask);
uint8_t submodeToCheckAgainst = tableIter.value->getSubmode();
if (tableIter.value->inheritSubmode()) { if (tableIter.value->inheritSubmode()) {
submodeToCheckAgainst = targetSubmode; submodeToCheckAgainst = targetSubmode;
} }
if (submodesAllowedMask) {
if ((childIter->second.submode | mask) != mask) {
return returnvalue::FAILED;
}
} else {
if (childIter->second.submode != submodeToCheckAgainst) { if (childIter->second.submode != submodeToCheckAgainst) {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
} }
}
return returnvalue::OK; return returnvalue::OK;
} }

View File

@@ -1,111 +1,126 @@
#ifndef FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_ #ifndef FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
#define FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_ #define FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
#include "../../modes/HasModesIF.h" #include "fsfw/modes/HasModesIF.h"
#include "../../objectmanager/SystemObjectIF.h" #include "fsfw/objectmanager/SystemObjectIF.h"
#include "../../serialize/SerialLinkedListAdapter.h" #include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "../../serialize/SerializeIF.h" #include "fsfw/serialize/SerializeIF.h"
class ModeListEntry : public SerializeIF, public LinkedElement<ModeListEntry> { namespace mode {
enum SpecialSubmodeFlags : uint8_t { INHERIT = 1 << 0, ALLOWED_MASK = 1 << 1 };
}
class ModeListEntry : public SerialLinkedListAdapter<SerializeIF>,
public LinkedElement<ModeListEntry> {
public: public:
ModeListEntry() : LinkedElement<ModeListEntry>(this) {} static constexpr uint8_t ALL_SUBMODES_ALLOWED_MASK = 0xff;
uint32_t value1 = 0; ModeListEntry() : SerialLinkedListAdapter(), LinkedElement<ModeListEntry>(this) { setLinks(); }
uint32_t value2 = 0;
uint8_t value3 = 0;
uint8_t value4 = 0;
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, SerializeElement<uint32_t> value1 = 0;
Endianness streamEndianness) const { SerializeElement<uint32_t> value2 = 0;
ReturnValue_t result; SerializeElement<uint8_t> value3 = 0;
SerializeElement<uint8_t> value4 = 0;
SerializeElement<uint8_t> value5 = 0;
result = SerializeAdapter::serialize(&value1, buffer, size, maxSize, streamEndianness); ModeListEntry(const ModeListEntry& other)
: SerialLinkedListAdapter(), LinkedElement<ModeListEntry>(this) {
if (result != returnvalue::OK) { value1.entry = other.value1.entry;
return result; value2.entry = other.value2.entry;
} value3.entry = other.value3.entry;
result = SerializeAdapter::serialize(&value2, buffer, size, maxSize, streamEndianness); value4.entry = other.value4.entry;
value5.entry = other.value5.entry;
if (result != returnvalue::OK) { setLinks();
return result;
}
result = SerializeAdapter::serialize(&value3, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
} }
result = SerializeAdapter::serialize(&value4, buffer, size, maxSize, streamEndianness); ModeListEntry& operator=(const ModeListEntry& other) {
this->value1.entry = other.value1.entry;
return result; this->value2.entry = other.value2.entry;
this->value3.entry = other.value3.entry;
this->value4.entry = other.value4.entry;
this->value5.entry = other.value5.entry;
return *this;
} }
virtual size_t getSerializedSize() const { void setLinks() {
return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4); setStart(&value1);
} value1.setNext(&value2);
value2.setNext(&value3);
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, value3.setNext(&value4);
Endianness streamEndianness) { value4.setNext(&value5);
ReturnValue_t result;
result = SerializeAdapter::deSerialize(&value1, buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&value2, buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&value3, buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&value4, buffer, size, streamEndianness);
return result;
} }
// for Sequences // for Sequences
Mode_t getTableId() const { return value1; } Mode_t getTableId() const { return value1.entry; }
void setTableId(Mode_t tableId) { this->value1 = tableId; } void setTableId(Mode_t tableId) { this->value1.entry = tableId; }
uint8_t getWaitSeconds() const { return value2; } uint8_t getWaitSeconds() const { return value2.entry; }
void setWaitSeconds(uint8_t waitSeconds) { this->value2 = waitSeconds; } void setWaitSeconds(uint8_t waitSeconds) { this->value2.entry = waitSeconds; }
bool checkSuccess() const { return value3 == 1; } bool checkSuccess() const { return value3.entry == 1; }
void setCheckSuccess(bool checkSuccess) { this->value3 = checkSuccess; } void setCheckSuccess(bool checkSuccess) { this->value3.entry = checkSuccess; }
// for Tables // for Tables
object_id_t getObject() const { return value1; } object_id_t getObject() const { return value1.entry; }
void setObject(object_id_t object) { this->value1 = object; } void setObject(object_id_t object) { this->value1.entry = object; }
Mode_t getMode() const { return value2; } Mode_t getMode() const { return value2.entry; }
void setMode(Mode_t mode) { this->value2 = mode; } void setMode(Mode_t mode) { this->value2.entry = mode; }
Submode_t getSubmode() const { return value3; } Submode_t getSubmode() const { return value3.entry; }
void setSubmode(Submode_t submode) { this->value3 = submode; } void setSubmode(Submode_t submode) { this->value3.entry = submode; }
bool inheritSubmode() const { return value4 == 1; } bool inheritSubmode() const {
return (value4.entry & mode::SpecialSubmodeFlags::INHERIT) ==
void setInheritSubmode(bool inherit) { mode::SpecialSubmodeFlags::INHERIT;
if (inherit) {
value4 = 1;
} else {
value4 = 0;
} }
bool submodesAllowed(uint8_t* mask) const {
bool submodesAllowed = (value4.entry & mode::SpecialSubmodeFlags::ALLOWED_MASK) ==
mode::SpecialSubmodeFlags::ALLOWED_MASK;
if (submodesAllowed and mask != nullptr) {
*mask = value5.entry;
}
return submodesAllowed;
} }
bool operator==(ModeListEntry other) { /**
return ((value1 == other.value1) && (value2 == other.value2) && (value3 == other.value3)); * Enable the inheritance of submodes. This is relevant for both the execution
* of mode tables and for mode checking.
*/
void enableInheritSubmode() { value4.entry |= mode::SpecialSubmodeFlags::INHERIT; }
/**
* Disable the inheritance of submodes. This is relevant for both the execution
* of mode tables and for mode checking.
*/
void disableInheritSubmode() { value4.entry &= ~mode::SpecialSubmodeFlags::INHERIT; }
/**
* Specialization of @enableSubmodeAllowed which allows all submodes.
*/
void allowAllSubmodes() { enableSubmodeAllowed(ALL_SUBMODES_ALLOWED_MASK); }
/**
* Enable an allowed submode mask for mode checks. Any submode which contains bits
* outside of the mask will be declined.
*
* For example, for a mask of 0b11, only the modes 0b00, 0b01 and 0b11 will be accepted.
*/
void enableSubmodeAllowed(uint8_t mask) {
value4.entry |= mode::SpecialSubmodeFlags::ALLOWED_MASK;
value5.entry = mask;
}
/**
* Enforce the equality of submodes for mode checks. This is the default.
*/
void disableSubmodeAllowed() {
value4.entry &= ~mode::SpecialSubmodeFlags::ALLOWED_MASK;
value5.entry = 0;
} }
}; };

View File

@@ -15,7 +15,8 @@ ReturnValue_t HostFilesystem::writeToFile(FileOpParams params, const uint8_t *da
return returnvalue::FAILED; return returnvalue::FAILED;
} }
path path(params.path()); path path(params.path());
if (not exists(path)) { std::error_code e;
if (not exists(path, e)) {
return HasFileSystemIF::FILE_DOES_NOT_EXIST; return HasFileSystemIF::FILE_DOES_NOT_EXIST;
} }
// This is equivalent to "r+" mode, which is what we need here. Only using ::out would truncate // This is equivalent to "r+" mode, which is what we need here. Only using ::out would truncate
@@ -35,7 +36,8 @@ ReturnValue_t HostFilesystem::readFromFile(FileOpParams params, uint8_t **buffer
return returnvalue::FAILED; return returnvalue::FAILED;
} }
path path(params.path()); path path(params.path());
if (not exists(path)) { std::error_code e;
if (not exists(path, e)) {
return HasFileSystemIF::FILE_DOES_NOT_EXIST; return HasFileSystemIF::FILE_DOES_NOT_EXIST;
} }
ifstream file(path); ifstream file(path);
@@ -59,7 +61,8 @@ ReturnValue_t HostFilesystem::createFile(FilesystemParams params, const uint8_t
return returnvalue::FAILED; return returnvalue::FAILED;
} }
path path(params.path); path path(params.path);
if (exists(path)) { std::error_code e;
if (exists(path, e)) {
return HasFileSystemIF::FILE_ALREADY_EXISTS; return HasFileSystemIF::FILE_ALREADY_EXISTS;
} }
ofstream file(path); ofstream file(path);
@@ -74,7 +77,8 @@ ReturnValue_t HostFilesystem::removeFile(const char *path_, FileSystemArgsIF *ar
return returnvalue::FAILED; return returnvalue::FAILED;
} }
path path(path_); path path(path_);
if (not exists(path)) { std::error_code e;
if (not exists(path, e)) {
return HasFileSystemIF::FILE_DOES_NOT_EXIST; return HasFileSystemIF::FILE_DOES_NOT_EXIST;
} }
if (remove(path, errorCode)) { if (remove(path, errorCode)) {
@@ -89,7 +93,8 @@ ReturnValue_t HostFilesystem::createDirectory(FilesystemParams params, bool crea
} }
path dirPath(params.path); path dirPath(params.path);
if (exists(dirPath)) { std::error_code e;
if (exists(dirPath, e)) {
return HasFileSystemIF::DIRECTORY_ALREADY_EXISTS; return HasFileSystemIF::DIRECTORY_ALREADY_EXISTS;
} }
@@ -110,7 +115,8 @@ ReturnValue_t HostFilesystem::removeDirectory(FilesystemParams params, bool dele
return returnvalue::FAILED; return returnvalue::FAILED;
} }
path dirPath(params.path); path dirPath(params.path);
if (not exists(dirPath)) { std::error_code e;
if (not exists(dirPath, e)) {
return HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST; return HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST;
} }
if (is_regular_file(dirPath)) { if (is_regular_file(dirPath)) {
@@ -149,12 +155,14 @@ ReturnValue_t HostFilesystem::rename(const char *oldPath_, const char *newPath_,
bool HostFilesystem::fileExists(FilesystemParams params) { bool HostFilesystem::fileExists(FilesystemParams params) {
path path(params.path); path path(params.path);
return filesystem::exists(path); std::error_code e;
return filesystem::exists(path, e);
} }
ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) { ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) {
path path(params.path); path path(params.path);
if (not filesystem::exists(path)) { std::error_code e;
if (not filesystem::exists(path, e)) {
return FILE_DOES_NOT_EXIST; return FILE_DOES_NOT_EXIST;
} }
ofstream of(path); ofstream of(path);

View File

@@ -13,6 +13,7 @@ add_subdirectory(util)
add_subdirectory(container) add_subdirectory(container)
add_subdirectory(osal) add_subdirectory(osal)
add_subdirectory(pus) add_subdirectory(pus)
add_subdirectory(subsystem)
add_subdirectory(serialize) add_subdirectory(serialize)
add_subdirectory(datapoollocal) add_subdirectory(datapoollocal)
add_subdirectory(storagemanager) add_subdirectory(storagemanager)

View File

@@ -0,0 +1 @@
target_sources(${FSFW_TEST_TGT} PRIVATE testModeDef.cpp)

View File

@@ -0,0 +1,49 @@
#include <array>
#include <catch2/catch_test_macros.hpp>
#include "fsfw/subsystem/modes/ModeDefinitions.h"
TEST_CASE("Mode Definitions", "[mode]") {
ModeListEntry entry;
SECTION("Basic") {
entry.setMode(HasModesIF::MODE_OFF);
entry.setSubmode(2);
CHECK(entry.getMode() == HasModesIF::MODE_OFF);
CHECK(entry.getSubmode() == 2);
uint8_t mask;
CHECK(entry.submodesAllowed(&mask) == false);
}
SECTION("Allowed submode mask") {
entry.allowAllSubmodes();
uint8_t mask;
CHECK(entry.submodesAllowed(&mask) == true);
CHECK(mask == 0xff);
}
SECTION("Serialization") {
std::array<uint8_t, 32> buf{};
entry.setObject(0x1f2f3f4f);
entry.setMode(HasModesIF::MODE_ON);
entry.setSubmode(2);
entry.enableInheritSubmode();
entry.enableSubmodeAllowed(0x1f);
uint8_t* serPtr = buf.data();
size_t serLen = 0;
REQUIRE(entry.serialize(&serPtr, &serLen, buf.size(), SerializeIF::Endianness::NETWORK) ==
returnvalue::OK);
CHECK(buf[0] == 0x1f);
CHECK(buf[1] == 0x2f);
CHECK(buf[2] == 0x3f);
CHECK(buf[3] == 0x4f);
CHECK(buf[4] == 0);
CHECK(buf[5] == 0);
CHECK(buf[6] == 0);
CHECK(buf[7] == HasModesIF::MODE_ON);
CHECK(buf[8] == 2);
CHECK(buf[9] == (mode::SpecialSubmodeFlags::ALLOWED_MASK | mode::SpecialSubmodeFlags::INHERIT));
CHECK(buf[10] == 0x1f);
}
}