Merge branch 'eive/develop' into meier/develop

This commit is contained in:
Jakob Meier
2022-04-28 11:45:27 +02:00
47 changed files with 1606 additions and 188 deletions

View File

@ -1,9 +1,11 @@
#ifndef FSFW_VERSION_H_
#define FSFW_VERSION_H_
// Versioning is kept in project CMakeLists.txt file
#define FSFW_VERSION_MAJOR @FSFW_VERSION@
#define FSFW_VERSION_MINOR @FSFW_SUBVERSION@
#define FSFW_VERSION_REVISION @FSFW_REVISION@
// Versioning is managed in project CMakeLists.txt file
static constexpr int FSFW_VERSION_MAJOR = @FSFW_VERSION@;
static constexpr int FSFW_VERSION_MINOR = @FSFW_SUBVERSION@;
static constexpr int FSFW_VERSION_REVISION = @FSFW_REVISION@;
// Also contains CST (Commits since tag) information
static const char FSFW_VERSION_CST_GIT_SHA1[] = "@FSFW_VERSION_CST_GIT_SHA1@";
#endif /* FSFW_VERSION_H_ */

View File

@ -11,14 +11,13 @@ class HybridIterator : public LinkedElement<T>::Iterator, public ArrayList<T, co
HybridIterator(typename LinkedElement<T>::Iterator *iter)
: LinkedElement<T>::Iterator(*iter), value(iter->value), linked(true) {
if(iter != nullptr) {
if (iter != nullptr) {
value = iter->value;
}
}
HybridIterator(LinkedElement<T> *start)
: LinkedElement<T>::Iterator(start), linked(true) {
if(start != nullptr) {
HybridIterator(LinkedElement<T> *start) : LinkedElement<T>::Iterator(start), linked(true) {
if (start != nullptr) {
value = start->value;
}
}

View File

@ -7,7 +7,7 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
template <typename T>
PoolEntry<T>::PoolEntry(uint8_t len, bool setValid): length(len), valid(setValid) {
PoolEntry<T>::PoolEntry(uint8_t len, bool setValid) : length(len), valid(setValid) {
this->address = new T[this->length]();
std::memset(this->address, 0, this->getByteSize());
}

View File

@ -787,6 +787,10 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i
// Serialize set packet into store.
size_t size = 0;
result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeId);
return result;
}
if (expectedSize != size) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket",
HasReturnvaluesIF::RETURN_FAILED,
@ -801,7 +805,10 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId);
}
hkQueue->reply(&reply);
result = hkQueue->reply(&reply);
if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeId);
}
return result;
}

View File

@ -187,7 +187,7 @@ void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) {
case (ErrorTypes::ENCODED_BUF_TOO_SMALL):
case (ErrorTypes::DECODING_BUF_TOO_SMALL): {
char opt[64];
snprintf(opt, sizeof(opt), ": Too small for packet with length %d", ctx.len);
snprintf(opt, sizeof(opt), ": Too small for packet with length %zu", ctx.len);
if (err == ErrorTypes::ENCODED_BUF_TOO_SMALL) {
errorPrinter("Encoded buf too small", opt);
} else {

View File

@ -179,7 +179,7 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
virtual ReturnValue_t cleanUpElement(iterator position) { return HasReturnvaluesIF::RETURN_OK; }
bool matchSubtree(iterator iter, T number) {
if(iter == nullptr) {
if (iter == nullptr) {
return false;
}
bool isMatch = iter->match(number);

View File

@ -1,9 +1,9 @@
#include "MessageQueueBase.h"
MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest,
MqArgs* args): id(id) {
MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* args)
: id(id) {
this->defaultDest = defaultDest;
if(args != nullptr) {
if (args != nullptr) {
this->args = *args;
}
}
@ -23,35 +23,25 @@ ReturnValue_t MessageQueueBase::reply(MessageQueueMessageIF* message) {
}
ReturnValue_t MessageQueueBase::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->last;
return status;
}
MessageQueueId_t MessageQueueBase::getLastPartner() const {
return last;
}
MessageQueueId_t MessageQueueBase::getLastPartner() const { return last; }
MessageQueueId_t MessageQueueBase::getId() const {
return id;
}
MessageQueueId_t MessageQueueBase::getId() const { return id; }
MqArgs& MessageQueueBase::getMqArgs() {
return args;
}
MqArgs& MessageQueueBase::getMqArgs() { return args; }
void MessageQueueBase::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDest = defaultDestination;
}
MessageQueueId_t MessageQueueBase::getDefaultDestination() const {
return defaultDest;
}
MessageQueueId_t MessageQueueBase::getDefaultDestination() const { return defaultDest; }
bool MessageQueueBase::isDefaultDestinationSet() const {
return (defaultDest != NO_QUEUE);
}
bool MessageQueueBase::isDefaultDestinationSet() const { return (defaultDest != NO_QUEUE); }
ReturnValue_t MessageQueueBase::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {

View File

@ -1,11 +1,11 @@
#ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
#define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
#include <fsfw/ipc/definitions.h>
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/ipc/definitions.h>
class MessageQueueBase: public MessageQueueIF {
public:
class MessageQueueBase : public MessageQueueIF {
public:
MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs);
virtual ~MessageQueueBase();
@ -17,25 +17,24 @@ public:
virtual MessageQueueId_t getDefaultDestination() const override;
virtual bool isDefaultDestinationSet() const override;
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) override;
bool ignoreFault) override;
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) override;
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) override;
MessageQueueId_t* receivedFrom) override;
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false) override;
// OSAL specific, forward the abstract function
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
protected:
protected:
MessageQueueId_t id = MessageQueueIF::NO_QUEUE;
MessageQueueId_t last = MessageQueueIF::NO_QUEUE;
MessageQueueId_t defaultDest = MessageQueueIF::NO_QUEUE;
MqArgs args = {};
};
#endif /* FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ */

View File

@ -2,6 +2,7 @@
#define FSFW_IPC_MESSAGEQUEUEIF_H_
#include <fsfw/ipc/definitions.h>
#include <cstdint>
#include "../returnvalues/HasReturnvaluesIF.h"
@ -45,7 +46,8 @@ class MessageQueueIF {
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
/**
* @brief This function reads available messages from the message queue and returns the sender.
* @brief This function reads available messages from the message queue and returns the
* sender.
* @details
* It works identically to the other receiveMessage call, but in addition
* returns the sender's queue id.

View File

@ -11,9 +11,6 @@
// TODO sanitize input?
// TODO much of this code can be reused for tick-only systems
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = nullptr;
uint32_t Clock::getTicksPerSecond(void) { return 1000; }
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {

View File

@ -2,6 +2,7 @@
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
#include <fsfw/ipc/MessageQueueBase.h>
#include "FreeRTOS.h"
#include "TaskManagement.h"
#include "fsfw/internalerror/InternalErrorReporterIF.h"

View File

@ -2,6 +2,7 @@
#include <chrono>
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/platform.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
@ -11,9 +12,6 @@
#include <fstream>
#endif
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
using SystemClock = std::chrono::system_clock;
uint32_t Clock::getTicksPerSecond(void) {
@ -127,6 +125,13 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto fraction = now - seconds;
time_t tt = SystemClock::to_time_t(now);
ReturnValue_t result = checkOrCreateClockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
MutexGuard helper(timeMutex);
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
struct tm* timeInfo;
timeInfo = gmtime(&tt);
time->year = timeInfo->tm_year + 1900;

View File

@ -1,17 +1,17 @@
#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
#include "fsfw/ipc/MessageQueueBase.h"
#include <memory>
#include <queue>
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueBase.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/ipc/definitions.h"
#include "fsfw/timemanager/Clock.h"
#include <memory>
#include <queue>
/**
* @brief This class manages sending and receiving of
* message queue messages.

View File

@ -1,5 +1,4 @@
#include "fsfw/timemanager/Clock.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include <linux/sysinfo.h>
#include <sys/sysinfo.h>
@ -8,12 +7,9 @@
#include <unistd.h>
#include <fstream>
#include <cstring>
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
void handleClockError(const char* func);
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
uint32_t Clock::getTicksPerSecond(void) {
uint32_t ticks = sysconf(_SC_CLK_TCK);
@ -29,7 +25,7 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
handleClockError("setClock");
// TODO errno
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
@ -41,7 +37,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
timeUnix.tv_nsec = (__syscall_slong_t)time->tv_usec * 1000;
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
handleClockError("setClock");
// TODO errno
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
@ -51,7 +47,6 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
timespec timeUnix;
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
handleClockError("getClock_timeval");
return HasReturnvaluesIF::RETURN_FAILED;
}
time->tv_sec = timeUnix.tv_sec;
@ -120,7 +115,13 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
// TODO errno
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t result = checkOrCreateClockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
MutexGuard helper(timeMutex);
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
struct tm* timeInfo;
timeInfo = gmtime(&timeUnix.tv_sec);
time->year = timeInfo->tm_year + 1900;
@ -154,15 +155,3 @@ ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return HasReturnvaluesIF::RETURN_OK;
}
void handleClockError(const char* func) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::" << func << ": Failed with code " << errno << ": " << strerror(errno)
<< std::endl;
#else
sif::printWarning("Clock::%s: Failed with code %d: %s\n", func, errno, strerror(errno));
#endif
#endif
}

View File

@ -61,8 +61,7 @@ class MessageQueue : public MessageQueueBase {
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
ReturnValue_t flush(uint32_t* count) override;
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom,
bool ignoreFault = false) override;
MessageQueueId_t sentFrom, bool ignoreFault = false) override;
protected:
/**

View File

@ -6,9 +6,6 @@
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/osal/rtems/RtemsBasic.h"
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = nullptr;
uint32_t Clock::getTicksPerSecond(void) {
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
return static_cast<uint32_t>(ticks_per_second);

View File

@ -2,6 +2,7 @@
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
#include <fsfw/ipc/MessageQueueBase.h>
#include "RtemsBasic.h"
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
@ -52,8 +53,8 @@ class MessageQueue : public MessageQueueBase {
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
ReturnValue_t flush(uint32_t* count) override;
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false) override;
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false) override;
private:
/**

View File

@ -59,14 +59,13 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
*/
ReturnValue_t addComponent(object_id_t object) override;
/**
/**
* Adds an object to the list of objects to be executed.
* The objects are executed in the order added.
* @param object pointer to the object to add.
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
*/
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
ReturnValue_t addComponent(ExecutableObjectIF *object) override;
uint32_t getPeriodMs() const override;

View File

@ -3,9 +3,12 @@
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/power/PowerSwitchIF.h>
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t pwrSwitch)
: SystemObject(objectId), switcher(pwrSwitcher, pwrSwitch), modeHelper(this),
healthHelper(this, objectId) {
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
power::Switch_t pwrSwitch)
: SystemObject(objectId),
switcher(pwrSwitcher, pwrSwitch),
modeHelper(this),
healthHelper(this, objectId) {
queue = QueueFactory::instance()->createMessageQueue();
}
@ -25,12 +28,12 @@ ReturnValue_t PowerSwitcherComponent::performOperation(uint8_t opCode) {
continue;
}
}
if(switcher.active()) {
if (switcher.active()) {
switcher.doStateMachine();
auto currState = switcher.getState();
if (currState == PowerSwitcher::SWITCH_IS_OFF) {
setMode(MODE_OFF, 0);
} else if(currState == PowerSwitcher::SWITCH_IS_ON) {
} else if (currState == PowerSwitcher::SWITCH_IS_ON) {
setMode(MODE_ON, 0);
}
}
@ -39,19 +42,17 @@ ReturnValue_t PowerSwitcherComponent::performOperation(uint8_t opCode) {
ReturnValue_t PowerSwitcherComponent::initialize() {
ReturnValue_t result = modeHelper.initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = healthHelper.initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return SystemObject::initialize();
}
MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const {
return queue->getId();
}
MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const { return queue->getId(); }
void PowerSwitcherComponent::getMode(Mode_t *mode, Submode_t *submode) {
*mode = this->mode;
@ -64,25 +65,25 @@ ReturnValue_t PowerSwitcherComponent::setHealth(HealthState health) {
}
ReturnValue_t PowerSwitcherComponent::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) {
uint32_t *msToReachTheMode) {
*msToReachTheMode = 5000;
if(mode != MODE_ON and mode != MODE_OFF) {
if (mode != MODE_ON and mode != MODE_OFF) {
return TRANS_NOT_ALLOWED;
}
return RETURN_OK;
}
void PowerSwitcherComponent::startTransition(Mode_t mode, Submode_t submode) {
if(mode == MODE_OFF) {
if (mode == MODE_OFF) {
switcher.turnOff(true);
switcher.doStateMachine();
if(switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
if (switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
setMode(MODE_OFF, 0);
}
} else if (mode == MODE_ON) {
switcher.turnOn(true);
switcher.doStateMachine();
if(switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
if (switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
setMode(MODE_ON, 0);
}
}
@ -103,6 +104,4 @@ void PowerSwitcherComponent::setMode(Mode_t newMode, Submode_t newSubmode) {
announceMode(false);
}
HasHealthIF::HealthState PowerSwitcherComponent::getHealth() {
return healthHelper.getHealth();
}
HasHealthIF::HealthState PowerSwitcherComponent::getHealth() { return healthHelper.getHealth(); }

View File

@ -6,8 +6,8 @@
#include <fsfw/modes/HasModesIF.h>
#include <fsfw/modes/ModeHelper.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/power/definitions.h>
#include <fsfw/power/PowerSwitcher.h>
#include <fsfw/power/definitions.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
class PowerSwitchIF;
@ -22,19 +22,17 @@ class PowerSwitchIF;
* Commanding this component to MODE_OFF will cause the switcher to turn the switch off while
* commanding in to MODE_ON will cause the switcher to turn the switch on.
*/
class PowerSwitcherComponent:
public SystemObject,
public HasReturnvaluesIF,
public ExecutableObjectIF,
public HasModesIF,
public HasHealthIF {
public:
PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
power::Switch_t pwrSwitch);
class PowerSwitcherComponent : public SystemObject,
public HasReturnvaluesIF,
public ExecutableObjectIF,
public HasModesIF,
public HasHealthIF {
public:
PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
power::Switch_t pwrSwitch);
private:
MessageQueueIF* queue = nullptr;
private:
MessageQueueIF *queue = nullptr;
PowerSwitcher switcher;
Mode_t mode = MODE_OFF;
@ -52,7 +50,7 @@ private:
MessageQueueId_t getCommandQueue() const override;
void getMode(Mode_t *mode, Submode_t *submode) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) override;
uint32_t *msToReachTheMode) override;
void startTransition(Mode_t mode, Submode_t submode) override;
void setToExternalControl() override;
void announceMode(bool recursive) override;

View File

@ -30,7 +30,7 @@ ReturnValue_t Subsystem::checkSequence(HybridIterator<ModeListEntry> iter,
return FALLBACK_SEQUENCE_DOES_NOT_EXIST;
}
if (iter.value ==nullptr) {
if (iter.value == nullptr) {
return NO_TARGET_TABLE;
}
@ -74,8 +74,8 @@ void Subsystem::performChildOperation() {
} else {
Mode_t tableId = 0;
auto seq = getSequence(targetMode);
if(seq.value != nullptr) {
tableId = seq->getTableId();
if (seq.value != nullptr) {
tableId = seq->getTableId();
}
transitionFailed(TARGET_TABLE_NOT_REACHED, tableId);
return;
@ -257,7 +257,7 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) {
result = modeTables.find(table, &entry);
if (result != RETURN_OK or entry == nullptr) {
replyToCommand(result, 0);
if(entry == nullptr) {
if (entry == nullptr) {
return result;
}
}

View File

@ -1,14 +1,13 @@
#ifndef FSFW_SUBSYSTEM_SUBSYSTEM_H_
#define FSFW_SUBSYSTEM_SUBSYSTEM_H_
#include "fsfw/FSFW.h"
#include "../container/FixedArrayList.h"
#include "../container/FixedMap.h"
#include "../container/HybridIterator.h"
#include "../container/SinglyLinkedList.h"
#include "../serialize/SerialArrayListAdapter.h"
#include "SubsystemBase.h"
#include "fsfw/FSFW.h"
#include "modes/ModeDefinitions.h"
/**

View File

@ -91,7 +91,7 @@ ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const uint8_t* f
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return convertTimevalToTimeOfDay(to, &time);
return Clock::convertTimevalToTimeOfDay(&time, to);
}
ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* from,
@ -489,11 +489,6 @@ ReturnValue_t CCSDSTime::checkTimeOfDay(const Clock::TimeOfDay_t* time) {
return RETURN_OK;
}
ReturnValue_t CCSDSTime::convertTimevalToTimeOfDay(Clock::TimeOfDay_t* to, timeval* from) {
// This is rather tricky. Implement only if needed. Also, if so, move to OSAL.
return UNSUPPORTED_TIME_FORMAT;
}
ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, size_t* foundLength,
size_t maxLength) {
uint8_t pField = *from;
@ -583,7 +578,7 @@ ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const CCSDSTime:
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return CCSDSTime::convertTimevalToTimeOfDay(to, &tempTimeval);
return Clock::convertTimevalToTimeOfDay(&tempTimeval, to);
}
ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, const uint8_t* from,

View File

@ -223,7 +223,6 @@ class CCSDSTime : public HasReturnvaluesIF {
uint8_t *day);
static bool isLeapYear(uint32_t year);
static ReturnValue_t convertTimevalToTimeOfDay(Clock::TimeOfDay_t *to, timeval *from);
};
#endif /* FSFW_TIMEMANAGER_CCSDSTIME_H_ */

View File

@ -173,6 +173,7 @@ class Clock {
static MutexIF *timeMutex;
static uint16_t leapSeconds;
static bool leapSecondsSet;
};
#endif /* FSFW_TIMEMANAGER_CLOCK_H_ */

View File

@ -3,6 +3,10 @@
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/timemanager/Clock.h"
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = nullptr;
bool Clock::leapSecondsSet = false;
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
uint16_t leapSeconds;
ReturnValue_t result = getLeapSeconds(&leapSeconds);
@ -29,12 +33,16 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
MutexGuard helper(timeMutex);
leapSeconds = leapSeconds_;
leapSecondsSet = true;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if (timeMutex == nullptr) {
if (not leapSecondsSet) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if (checkOrCreateClockMutex() != HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_FAILED;
}
MutexGuard helper(timeMutex);
@ -46,6 +54,16 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) {
struct tm* timeInfo;
// According to https://en.cppreference.com/w/c/chrono/gmtime, the implementation of gmtime_s
// in the Windows CRT is incompatible with the C standard but this should not be an issue for
// this implementation
ReturnValue_t result = checkOrCreateClockMutex();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
MutexGuard helper(timeMutex);
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
timeInfo = gmtime(&from->tv_sec);
to->year = timeInfo->tm_year + 1900;
to->month = timeInfo->tm_mon + 1;

View File

@ -12,12 +12,25 @@
#undef minor
#endif
const fsfw::Version fsfw::FSFW_VERSION = {FSFW_VERSION_MAJOR, FSFW_VERSION_MINOR,
FSFW_VERSION_REVISION};
const Version fsfw::FSFW_VERSION = {FSFW_VERSION_MAJOR, FSFW_VERSION_MINOR, FSFW_VERSION_REVISION,
FSFW_VERSION_CST_GIT_SHA1};
fsfw::Version::Version(uint32_t major, uint32_t minor, uint32_t revision)
: major(major), minor(minor), revision(revision) {}
Version::Version(int major, int minor, int revision, const char* addInfo)
: major(major), minor(minor), revision(revision), addInfo(addInfo) {}
void fsfw::Version::getVersion(char* str, size_t maxLen) const {
snprintf(str, maxLen, "%d.%d.%d", major, minor, revision);
void Version::getVersion(char* str, size_t maxLen) const {
size_t len = snprintf(str, maxLen, "%d.%d.%d", major, minor, revision);
if (addInfo != nullptr) {
snprintf(str + len, maxLen - len, "-%s", addInfo);
}
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
std::ostream& operator<<(std::ostream& os, const Version& v) {
os << v.major << "." << v.minor << "." << v.revision;
if (v.addInfo != nullptr) {
os << "-" << v.addInfo;
}
return os;
}
#endif

View File

@ -8,14 +8,15 @@
#endif
#include <cstdint>
namespace fsfw {
class Version {
public:
Version(uint32_t major, uint32_t minor, uint32_t revision);
uint32_t major = 0;
uint32_t minor = 0;
uint32_t revision = 0;
Version(int major, int minor, int revision, const char* addInfo = nullptr);
int major = -1;
int minor = -1;
int revision = -1;
// Additional information, e.g. a git SHA hash
const char* addInfo = nullptr;
friend bool operator==(const Version& v1, const Version& v2) {
return (v1.major == v2.major and v1.minor == v2.minor and v1.revision == v2.revision);
@ -43,10 +44,7 @@ class Version {
* @param v
* @return
*/
friend std::ostream& operator<<(std::ostream& os, const Version& v) {
os << v.major << "." << v.minor << "." << v.revision;
return os;
}
friend std::ostream& operator<<(std::ostream& os, const Version& v);
#endif
/**
@ -57,7 +55,9 @@ class Version {
void getVersion(char* str, size_t maxLen) const;
};
extern const fsfw::Version FSFW_VERSION;
namespace fsfw {
extern const Version FSFW_VERSION;
} // namespace fsfw