Merge remote-tracking branch 'upstream/mueller/master' into mueller/master

This commit is contained in:
Robin Müller 2021-02-03 13:39:09 +01:00
commit 8c5e261a0d
119 changed files with 9240 additions and 5985 deletions

View File

@ -99,7 +99,7 @@ public:
*/ */
void setQueueToUse(MessageQueueIF *queue); void setQueueToUse(MessageQueueIF *queue);
protected: protected:
//!< Increase of value of this per step //! Increase of value of this per step
static const uint8_t STEP_OFFSET = 1; static const uint8_t STEP_OFFSET = 1;
HasActionsIF* owner;//!< Pointer to the owner HasActionsIF* owner;//!< Pointer to the owner
//! Queue to be used as response sender, has to be set in ctor or with //! Queue to be used as response sender, has to be set in ctor or with

View File

@ -18,7 +18,7 @@ public:
* This function is protected because it should only be used by the * This function is protected because it should only be used by the
* class imlementing the interface. * class imlementing the interface.
*/ */
virtual LocalDataPoolManager* getHkManagerHandle() = 0; virtual LocalDataPoolManager* getPoolManagerHandle() = 0;
protected: protected:

View File

@ -5,8 +5,8 @@
#include "internal/LocalPoolDataSetAttorney.h" #include "internal/LocalPoolDataSetAttorney.h"
#include "internal/HasLocalDpIFManagerAttorney.h" #include "internal/HasLocalDpIFManagerAttorney.h"
#include "../housekeeping/HousekeepingPacketUpdate.h"
#include "../housekeeping/HousekeepingSetPacket.h" #include "../housekeeping/HousekeepingSetPacket.h"
#include "../housekeeping/HousekeepingSnapshot.h"
#include "../housekeeping/AcceptsHkPacketsIF.h" #include "../housekeeping/AcceptsHkPacketsIF.h"
#include "../timemanager/CCSDSTime.h" #include "../timemanager/CCSDSTime.h"
#include "../ipc/MutexFactory.h" #include "../ipc/MutexFactory.h"
@ -226,7 +226,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
Clock::getClock_timeval(&now); Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds; CCSDSTime::CDS_short cds;
CCSDSTime::convertToCcsds(&cds, &now); CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds), HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds),
sizeof(cds), HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner, sizeof(cds), HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
receiver.dataId.localPoolId)); receiver.dataId.localPoolId));
@ -264,7 +264,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
Clock::getClock_timeval(&now); Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds; CCSDSTime::CDS_short cds;
CCSDSTime::convertToCcsds(&cds, &now); CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds), HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds),
sizeof(cds), HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sizeof(cds), HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
receiver.dataId.sid)); receiver.dataId.sid));
@ -292,7 +292,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
} }
ReturnValue_t LocalDataPoolManager::addUpdateToStore( ReturnValue_t LocalDataPoolManager::addUpdateToStore(
HousekeepingPacketUpdate& updatePacket, store_address_t& storeId) { HousekeepingSnapshot& updatePacket, store_address_t& storeId) {
size_t updatePacketSize = updatePacket.getSerializedSize(); size_t updatePacketSize = updatePacket.getSerializedSize();
uint8_t *storePtr = nullptr; uint8_t *storePtr = nullptr;
ReturnValue_t result = ipcStore->getFreeElement(&storeId, ReturnValue_t result = ipcStore->getFreeElement(&storeId,
@ -890,7 +890,7 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
<< std::dec << std::setfill(' ') << std::endl; << std::dec << std::setfill(' ') << std::endl;
#else #else
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
owner->getObjectId(), errorPrint); functionName, owner->getObjectId(), errorPrint);
#endif #endif
} }
else if(outputType == sif::OutputTypes::OUT_ERROR) { else if(outputType == sif::OutputTypes::OUT_ERROR) {
@ -901,11 +901,11 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
<< std::dec << std::setfill(' ') << std::endl; << std::dec << std::setfill(' ') << std::endl;
#else #else
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
owner->getObjectId(), errorPrint); functionName, owner->getObjectId(), errorPrint);
#endif #endif
} }
} }
LocalDataPoolManager* LocalDataPoolManager::getHkManagerHandle() { LocalDataPoolManager* LocalDataPoolManager::getPoolManagerHandle() {
return this; return this;
} }

View File

@ -24,7 +24,7 @@ void setStaticFrameworkObjectIds();
} }
class LocalPoolDataSetBase; class LocalPoolDataSetBase;
class HousekeepingPacketUpdate; class HousekeepingSnapshot;
class HasLocalDataPoolIF; class HasLocalDataPoolIF;
class LocalDataPool; class LocalDataPool;
@ -52,7 +52,8 @@ class LocalDataPool;
* Each pool entry has a valid state too. * Each pool entry has a valid state too.
* @author R. Mueller * @author R. Mueller
*/ */
class LocalDataPoolManager: public ProvidesDataPoolSubscriptionIF, class LocalDataPoolManager:
public ProvidesDataPoolSubscriptionIF,
public AccessPoolManagerIF { public AccessPoolManagerIF {
friend void (Factory::setStaticFrameworkObjectIds)(); friend void (Factory::setStaticFrameworkObjectIds)();
//! Some classes using the pool manager directly need to access class internals of the //! Some classes using the pool manager directly need to access class internals of the
@ -62,7 +63,6 @@ public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER; static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0); static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0);
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1); static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1);
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2); static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3); static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
@ -179,8 +179,6 @@ public:
MessageQueueId_t targetQueueId, MessageQueueId_t targetQueueId,
bool generateSnapshot) override; bool generateSnapshot) override;
MutexIF* getLocalPoolMutex() override;
/** /**
* Non-Diagnostics packets usually have a lower minimum sampling frequency * Non-Diagnostics packets usually have a lower minimum sampling frequency
* than diagnostic packets. * than diagnostic packets.
@ -243,12 +241,9 @@ public:
UPDATE_SNAPSHOT, UPDATE_SNAPSHOT,
}; };
/** /** Different data types are possible in the HK receiver map. For example, updates can be
* Different data types are possible in the HK receiver map. requested for full datasets or for single pool variables. Periodic reporting is only possible
* For example, updates can be requested for full datasets or for data sets. */
* for single pool variables. Periodic reporting is only possible for
* data sets.
*/
enum class DataType: uint8_t { enum class DataType: uint8_t {
LOCAL_POOL_VARIABLE, LOCAL_POOL_VARIABLE,
DATA_SET DATA_SET
@ -267,11 +262,19 @@ public:
object_id_t getCreatorObjectId() const; object_id_t getCreatorObjectId() const;
virtual LocalDataPoolManager* getHkManagerHandle() override; /**
* Get the pointer to the mutex. Can be used to lock the data pool
* externally. Use with care and don't forget to unlock locked mutexes!
* For now, only friend classes can accss this function.
* @return
*/
MutexIF* getMutexHandle();
virtual LocalDataPoolManager* getPoolManagerHandle() override;
private: private:
localpool::DataPool localPoolMap; localpool::DataPool localPoolMap;
//! Every housekeeping data manager has a mutex to protect access /** Every housekeeping data manager has a mutex to protect access
//! to it's data pool. to it's data pool. */
MutexIF* mutex = nullptr; MutexIF* mutex = nullptr;
/** The class which actually owns the manager (and its datapool). */ /** The class which actually owns the manager (and its datapool). */
@ -333,13 +336,6 @@ private:
/** Global IPC store is used to store all packets. */ /** Global IPC store is used to store all packets. */
StorageManagerIF* ipcStore = nullptr; StorageManagerIF* ipcStore = nullptr;
/**
* Get the pointer to the mutex. Can be used to lock the data pool
* externally. Use with care and don't forget to unlock locked mutexes!
* For now, only friend classes can accss this function.
* @return
*/
MutexIF* getMutexHandle();
/** /**
* Read a variable by supplying its local pool ID and assign the pool * Read a variable by supplying its local pool ID and assign the pool
@ -364,6 +360,8 @@ private:
*/ */
ReturnValue_t initializeHousekeepingPoolEntriesOnce(); ReturnValue_t initializeHousekeepingPoolEntriesOnce();
MutexIF* getLocalPoolMutex() override;
ReturnValue_t serializeHkPacketIntoStore( ReturnValue_t serializeHkPacketIntoStore(
HousekeepingPacketDownlink& hkPacket, HousekeepingPacketDownlink& hkPacket,
store_address_t& storeId, bool forDownlink, size_t* serializedSize); store_address_t& storeId, bool forDownlink, size_t* serializedSize);
@ -386,7 +384,7 @@ private:
ReturnValue_t& status); ReturnValue_t& status);
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver, ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver,
ReturnValue_t& status); ReturnValue_t& status);
ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket, ReturnValue_t addUpdateToStore(HousekeepingSnapshot& updatePacket,
store_address_t& storeId); store_address_t& storeId);
void printWarningOrError(sif::OutputTypes outputType, void printWarningOrError(sif::OutputTypes outputType,
@ -401,14 +399,14 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
PoolEntry<T> **poolEntry) { PoolEntry<T> **poolEntry) {
auto poolIter = localPoolMap.find(localPoolId); auto poolIter = localPoolMap.find(localPoolId);
if (poolIter == localPoolMap.end()) { if (poolIter == localPoolMap.end()) {
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry", printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
localpool::POOL_ENTRY_NOT_FOUND); localpool::POOL_ENTRY_NOT_FOUND);
return localpool::POOL_ENTRY_NOT_FOUND; return localpool::POOL_ENTRY_NOT_FOUND;
} }
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second); *poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
if(*poolEntry == nullptr) { if(*poolEntry == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry", printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
localpool::POOL_ENTRY_TYPE_CONFLICT); localpool::POOL_ENTRY_TYPE_CONFLICT);
return localpool::POOL_ENTRY_TYPE_CONFLICT; return localpool::POOL_ENTRY_TYPE_CONFLICT;
} }

View File

@ -4,11 +4,26 @@
#include "LocalPoolDataSetBase.h" #include "LocalPoolDataSetBase.h"
#include <vector> #include <vector>
/**
* @brief This dataset type can be used to group related pool variables if the number of
* variables should not be fixed.
* @details
* This will is the primary data structure to organize pool variables into
* sets which can be accessed via the housekeeping service interface or
* which can be sent to other software objects.
*
* It is recommended to read the documentation of the LocalPoolDataSetBase
* class for more information on how this class works and how to use it.
* @tparam capacity Capacity of the static dataset, which is usually known
* beforehand.
*/
class LocalDataSet: public LocalPoolDataSetBase { class LocalDataSet: public LocalPoolDataSetBase {
public: public:
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId, LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
const size_t maxSize); const size_t maxSize);
LocalDataSet(sid_t sid, const size_t maxSize); LocalDataSet(sid_t sid, const size_t maxSize);
virtual~ LocalDataSet(); virtual~ LocalDataSet();
//! Copying forbidden for now. //! Copying forbidden for now.

View File

@ -28,7 +28,7 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner); AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
if(accessor != nullptr) { if(accessor != nullptr) {
poolManager = accessor->getHkManagerHandle(); poolManager = accessor->getPoolManagerHandle();
mutexIfSingleDataCreator = accessor->getLocalPoolMutex(); mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
} }

View File

@ -22,7 +22,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkO
return; return;
} }
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner); AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
hkManager = poolManAccessor->getHkManagerHandle(); hkManager = poolManAccessor->getPoolManagerHandle();
if (dataSet != nullptr) { if (dataSet != nullptr) {
dataSet->registerVariable(this); dataSet->registerVariable(this);
@ -50,7 +50,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner); AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
if(accessor != nullptr) { if(accessor != nullptr) {
hkManager = accessor->getHkManagerHandle(); hkManager = accessor->getPoolManagerHandle();
} }
if(dataSet != nullptr) { if(dataSet != nullptr) {

View File

@ -77,8 +77,7 @@ public:
* @param dataSet * @param dataSet
* @param setReadWriteMode * @param setReadWriteMode
*/ */
LocalPoolVector(gp_id_t globalPoolId, LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE); pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
/** /**
@ -87,7 +86,7 @@ public:
* The user can work on this attribute just like he would on a local * The user can work on this attribute just like he would on a local
* array of this type. * array of this type.
*/ */
T value[vectorSize]; T value[vectorSize]= {};
/** /**
* @brief The classes destructor is empty. * @brief The classes destructor is empty.
* @details If commit() was not called, the local value is * @details If commit() was not called, the local value is

View File

@ -16,7 +16,6 @@ inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner,
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode): lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {} LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId, inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
DataSetIF *dataSet, pool_rwm_t setReadWriteMode): DataSetIF *dataSet, pool_rwm_t setReadWriteMode):

View File

@ -2,11 +2,15 @@
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_ #define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
#include "LocalPoolDataSetBase.h" #include "LocalPoolDataSetBase.h"
#include "LocalPoolVariable.h"
#include "LocalPoolVector.h"
#include "../objectmanager/SystemObjectIF.h" #include "../objectmanager/SystemObjectIF.h"
#include <array> #include <array>
/** /**
* @brief This local dataset type is created on the stack. * @brief This dataset type can be used to group related pool variables if the number of
* variables is fixed.
* @details * @details
* This will is the primary data structure to organize pool variables into * This will is the primary data structure to organize pool variables into
* sets which can be accessed via the housekeeping service interface or * sets which can be accessed via the housekeeping service interface or

View File

@ -17,16 +17,15 @@ object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT;
object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT;
DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
object_id_t deviceCommunication, CookieIF * comCookie, CookieIF* comCookie, FailureIsolationBase* fdirInstance, size_t cmdQueueSize):
FailureIsolationBase* fdirInstance, size_t cmdQueueSize) :
SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE), SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE),
wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS), wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS),
deviceCommunicationId(deviceCommunication), comCookie(comCookie), deviceCommunicationId(deviceCommunication), comCookie(comCookie),
healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this), healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this),
actionHelper(this, nullptr), poolManager(this, nullptr), actionHelper(this, nullptr), poolManager(this, nullptr),
childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance), childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance),
hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr), defaultFDIRUsed(fdirInstance == nullptr),
switchOffWasReported(false), childTransitionDelay(5000), switchOffWasReported(false), childTransitionDelay(5000),
transitionSourceMode(_MODE_POWER_DOWN), transitionSourceMode(_MODE_POWER_DOWN),
transitionSourceSubMode(SUBMODE_NONE) { transitionSourceSubMode(SUBMODE_NONE) {
@ -80,7 +79,6 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
checkSwitchState(); checkSwitchState();
decrementDeviceReplyMap(); decrementDeviceReplyMap();
fdirInstance->checkForFailures(); fdirInstance->checkForFailures();
hkSwitcher.performOperation();
performOperationHook(); performOperationHook();
return RETURN_OK; return RETURN_OK;
} }
@ -92,7 +90,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
switch (getComAction()) { switch (getComAction()) {
case CommunicationAction::SEND_WRITE: case CommunicationAction::SEND_WRITE:
if (cookieInfo.state == COOKIE_UNUSED) { if (cookieInfo.state == COOKIE_UNUSED) {
// if no external command was specified, build internal command. /* If no external command was specified, build internal command. */
buildInternalCommand(); buildInternalCommand();
} }
doSendWrite(); doSendWrite();
@ -105,8 +103,8 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
break; break;
case CommunicationAction::GET_READ: case CommunicationAction::GET_READ:
doGetRead(); doGetRead();
// This will be performed after datasets have been updated by the /* This will be performed after datasets have been updated by the
// custom device implementation. custom device implementation. */
poolManager.performHkOperation(); poolManager.performHkOperation();
break; break;
default: default:
@ -205,11 +203,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
return result; return result;
} }
result = hkSwitcher.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = poolManager.initialize(commandQueue); result = poolManager.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
@ -506,7 +499,8 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) {
} }
void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
changeHK(mode, submode, false); /* TODO: This will probably be done by the LocalDataPoolManager now */
//changeHK(mode, submode, false);
submode = newSubmode; submode = newSubmode;
mode = newMode; mode = newMode;
modeChanged(); modeChanged();
@ -529,7 +523,8 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
} }
} }
changeHK(mode, submode, true); /* TODO: This will probably be done by the LocalDataPoolManager now */
//changeHK(mode, submode, true);
} }
void DeviceHandlerBase::setMode(Mode_t newMode) { void DeviceHandlerBase::setMode(Mode_t newMode) {
@ -1202,61 +1197,62 @@ ReturnValue_t DeviceHandlerBase::letChildHandleMessage(
return RETURN_FAILED; return RETURN_FAILED;
} }
void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, void DeviceHandlerBase::handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId,
DeviceCommandId_t replyId, bool neverInDataPool, bool forceDirectTm) { bool forceDirectTm) {
if(dataSet == nullptr) {
return;
}
DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId);
if (iter == deviceReplyMap.end()) { if (iter == deviceReplyMap.end()) {
triggerEvent(DEVICE_UNKNOWN_REPLY, replyId); triggerEvent(DEVICE_UNKNOWN_REPLY, replyId);
return; return;
} }
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data);
//replies to a command /* Regular replies to a command */
if (iter->second.command != deviceCommandMap.end()) if (iter->second.command != deviceCommandMap.end())
{ {
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo; MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
if (queueId != NO_COMMANDER) { if (queueId != NO_COMMANDER) {
//This may fail, but we'll ignore the fault. /* This may fail, but we'll ignore the fault. */
actionHelper.reportData(queueId, replyId, data); actionHelper.reportData(queueId, replyId, dataSet);
} }
//This check should make sure we get any TM but don't get anything doubled. /* This check should make sure we get any TM but don't get anything doubled. */
if (wiretappingMode == TM && (requestedRawTraffic != queueId)) { if (wiretappingMode == TM && (requestedRawTraffic != queueId)) {
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet);
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper); actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
} }
else if (forceDirectTm and (defaultRawReceiver != queueId) and else if (forceDirectTm and (defaultRawReceiver != queueId) and
(defaultRawReceiver != MessageQueueIF::NO_QUEUE)) (defaultRawReceiver != MessageQueueIF::NO_QUEUE))
{ {
// hiding of sender needed so the service will handle it as // hiding of sender needed so the service will handle it as
// unexpected Data, no matter what state (progress or completed) // unexpected Data, no matter what state (progress or completed)
// it is in // it is in
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper, actionHelper.reportData(defaultRawReceiver, replyId, dataSet, true);
true);
} }
} }
//unrequested/aperiodic replies /* Unrequested or aperiodic replies */
else else
{ {
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet);
if (wiretappingMode == TM) { if (wiretappingMode == TM) {
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper); actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
} }
else if (forceDirectTm and defaultRawReceiver != if (forceDirectTm and defaultRawReceiver != MessageQueueIF::NO_QUEUE)
MessageQueueIF::NO_QUEUE)
{ {
// sid_t setSid = sid_t(this->getObjectId(), replyId);
// LocalPoolDataSetBase* dataset = getDataSetHandle(setSid);
// if(dataset != nullptr) {
// poolManager.generateHousekeepingPacket(setSid, dataset, true);
// }
// hiding of sender needed so the service will handle it as // hiding of sender needed so the service will handle it as
// unexpected Data, no matter what state (progress or completed) // unexpected Data, no matter what state (progress or completed)
// it is in // it is in
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper, actionHelper.reportData(defaultRawReceiver, replyId, &wrapper, true);
true);
}
}
//Try to cast to GlobDataSet and commit data.
if (not neverInDataPool) {
LocalPoolDataSetBase* dataSet =
dynamic_cast<LocalPoolDataSetBase*>(data);
if (dataSet != nullptr) {
dataSet->setValidity(true, true);
dataSet->commit();
} }
} }
} }
@ -1285,18 +1281,17 @@ ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId,
} }
void DeviceHandlerBase::buildInternalCommand(void) { void DeviceHandlerBase::buildInternalCommand(void) {
//Neither Raw nor Direct could build a command /* Neither raw nor direct could build a command */
ReturnValue_t result = NOTHING_TO_SEND; ReturnValue_t result = NOTHING_TO_SEND;
DeviceCommandId_t deviceCommandId = NO_COMMAND_ID; DeviceCommandId_t deviceCommandId = NO_COMMAND_ID;
if (mode == MODE_NORMAL) { if (mode == MODE_NORMAL) {
result = buildNormalDeviceCommand(&deviceCommandId); result = buildNormalDeviceCommand(&deviceCommandId);
if (result == BUSY) { if (result == BUSY) {
// so we can track misconfigurations /* So we can track misconfigurations */
printWarningOrError(sif::OutputTypes::OUT_WARNING, printWarningOrError(sif::OutputTypes::OUT_WARNING, "buildInternalCommand",
"buildInternalCommand", HasReturnvaluesIF::RETURN_FAILED, "Busy.");
HasReturnvaluesIF::RETURN_FAILED, /* No need to report this */
"Busy."); result = NOTHING_TO_SEND;
result = NOTHING_TO_SEND; //no need to report this
} }
} }
else if (mode == MODE_RAW) { else if (mode == MODE_RAW) {
@ -1318,7 +1313,8 @@ void DeviceHandlerBase::buildInternalCommand(void) {
deviceCommandId); deviceCommandId);
if (iter == deviceCommandMap.end()) { if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED; result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) { }
else if (iter->second.isExecuting) {
#if FSFW_DISABLE_PRINTOUT == 0 #if FSFW_DISABLE_PRINTOUT == 0
char output[36]; char output[36];
sprintf(output, "Command 0x%08x is executing", sprintf(output, "Command 0x%08x is executing",
@ -1378,11 +1374,11 @@ void DeviceHandlerBase::forwardEvent(Event event, uint32_t parameter1,
void DeviceHandlerBase::doOffActivity() { void DeviceHandlerBase::doOffActivity() {
} }
ReturnValue_t DeviceHandlerBase::getParameter(uint8_t domainId, ReturnValue_t DeviceHandlerBase::getParameter(uint8_t domainId, uint8_t uniqueId,
uint16_t parameterId, ParameterWrapper* parameterWrapper, ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
const ParameterWrapper* newValues, uint16_t startAtIndex) { uint16_t startAtIndex) {
ReturnValue_t result = fdirInstance->getParameter(domainId, parameterId, ReturnValue_t result = fdirInstance->getParameter(domainId, uniqueId, parameterWrapper,
parameterWrapper, newValues, startAtIndex); newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) { if (result != INVALID_DOMAIN_ID) {
return result; return result;
} }
@ -1406,14 +1402,10 @@ bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) {
} }
void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
}
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task){ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task){
executingTask = task; executingTask = task;
} }
// Default implementations empty.
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, void DeviceHandlerBase::debugInterface(uint8_t positionTracker,
object_id_t objectId, uint32_t parameter) {} object_id_t objectId, uint32_t parameter) {}
@ -1531,3 +1523,11 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() { LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() {
return &poolManager; return &poolManager;
} }
MessageQueueId_t DeviceHandlerBase::getCommanderId(DeviceCommandId_t replyId) const {
auto commandIter = deviceCommandMap.find(replyId);
if(commandIter == deviceCommandMap.end()) {
return MessageQueueIF::NO_QUEUE;
}
return commandIter->second.sendReplyTo;
}

View File

@ -20,7 +20,6 @@
#include "../action/ActionHelper.h" #include "../action/ActionHelper.h"
#include "../health/HealthHelper.h" #include "../health/HealthHelper.h"
#include "../parameters/ParameterHelper.h" #include "../parameters/ParameterHelper.h"
#include "../datapool/HkSwitchHelper.h"
#include "../datapoollocal/HasLocalDataPoolIF.h" #include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../datapoollocal/LocalDataPoolManager.h" #include "../datapoollocal/LocalDataPoolManager.h"
@ -148,8 +147,7 @@ public:
* 4. Decrements counter for timeout of replies by calling * 4. Decrements counter for timeout of replies by calling
* decrementDeviceReplyMap() * decrementDeviceReplyMap()
* 5. Performs FDIR check for failures * 5. Performs FDIR check for failures
* 6. Calls hkSwitcher.performOperation() * 6. If the device mode is MODE_OFF, return RETURN_OK.
* 7. If the device mode is MODE_OFF, return RETURN_OK.
* Otherwise, perform the Action property and performs depending * Otherwise, perform the Action property and performs depending
* on value specified by input value counter (incremented in PST). * on value specified by input value counter (incremented in PST).
* The child class tells base class what to do by setting this value. * The child class tells base class what to do by setting this value.
@ -189,6 +187,37 @@ public:
/** Destructor. */ /** Destructor. */
virtual ~DeviceHandlerBase(); virtual ~DeviceHandlerBase();
/**
* Implementation of ExecutableObjectIF function
* Used to setup the reference of the task, that executes this component
* @param task_ Pointer to the taskIF of this task
*/
virtual void setTaskIF(PeriodicTaskIF* task_) override;
virtual MessageQueueId_t getCommandQueue(void) const override;
/** Explicit interface implementation of getObjectId */
virtual object_id_t getObjectId() const override;
/**
* @param parentQueueId
*/
virtual void setParentQueue(MessageQueueId_t parentQueueId);
/** @brief Implementation required for HasActionIF */
ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data,
size_t size) override;
Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const;
virtual void getMode(Mode_t *mode, Submode_t *submode);
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
uint16_t startAtIndex) override;
protected: protected:
/** /**
* @brief This is used to let the child class handle the transition from * @brief This is used to let the child class handle the transition from
@ -216,7 +245,6 @@ protected:
* for a failed transition * for a failed transition
*/ */
virtual void doStartUp() = 0; virtual void doStartUp() = 0;
/** /**
* @brief This is used to let the child class handle the transition * @brief This is used to let the child class handle the transition
* from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN * from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN
@ -242,6 +270,7 @@ protected:
*/ */
virtual void doShutDown() = 0; virtual void doShutDown() = 0;
/* Command handling */
/** /**
* Build the device command to send for normal mode. * Build the device command to send for normal mode.
* *
@ -262,7 +291,6 @@ protected:
* - Anything else triggers an even with the returnvalue as a parameter. * - Anything else triggers an even with the returnvalue as a parameter.
*/ */
virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0; virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0;
/** /**
* Build the device command to send for a transitional mode. * Build the device command to send for a transitional mode.
* *
@ -286,29 +314,35 @@ protected:
* - Anything else triggers an even with the returnvalue as a parameter * - Anything else triggers an even with the returnvalue as a parameter
*/ */
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0; virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0;
/** /**
* @brief Build a device command packet from data supplied by a * @brief Build a device command packet from data supplied by a direct
* direct command. * command (PUS Service 8)
*
* @details * @details
* #rawPacket and #rawPacketLen should be set by this method to the packet * This will be called if an functional command via PUS Service 8 is received and is
* to be sent. The existence of the command in the command map and the * the primary interface for functional command instead of #executeAction for users. The
* command size check against 0 are done by the base class. * supplied ActionId_t action ID will be converted to a DeviceCommandId_t command ID after
* an internal check whether the action ID is a key in the device command map.
* *
* @param deviceCommand the command to build, already checked against * #rawPacket and #rawPacketLen should be set by this method to the packet to be sent.
* deviceCommandMap * The existence of the command in the command map and the command size check against 0 are
* @param commandData pointer to the data from the direct command * done by the base class.
* @param commandDataLen length of commandData *
* @param deviceCommand The command to build, already checked against deviceCommandMap
* @param commandData Pointer to the data from the direct command
* @param commandDataLen Length of commandData
* @return * @return
* - @c RETURN_OK to send command after #rawPacket and #rawPacketLen * - @c RETURN_OK to send command after #rawPacket and #rawPacketLen
* have been set. * have been set.
* - Anything else triggers an event with the * - @c HasActionsIF::EXECUTION_COMPLETE to generate a finish reply immediately. This can
* returnvalue as a parameter * be used if no reply is expected. Otherwise, the developer can call #actionHelper.finish
* to finish the command handling.
* - Anything else triggers an event with the return code as a parameter as well as a
* step reply failed with the return code
*/ */
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t * commandData, size_t commandDataLen) = 0; const uint8_t * commandData, size_t commandDataLen) = 0;
/* Reply handling */
/** /**
* @brief Scans a buffer for a valid reply. * @brief Scans a buffer for a valid reply.
* @details * @details
@ -344,7 +378,6 @@ protected:
*/ */
virtual ReturnValue_t scanForReply(const uint8_t *start, size_t len, virtual ReturnValue_t scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) = 0; DeviceCommandId_t *foundId, size_t *foundLen) = 0;
/** /**
* @brief Interpret a reply from the device. * @brief Interpret a reply from the device.
* @details * @details
@ -366,10 +399,19 @@ protected:
*/ */
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) = 0; const uint8_t *packet) = 0;
MessageQueueId_t getCommanderId(DeviceCommandId_t replyId) const;
/** /**
* @brief fill the #DeviceCommandMap and #DeviceReplyMap * Helper function to get pending command. This is useful for devices
* called by the initialize() of the base class * like SPI sensors to identify the last sent command.
* This only returns the command sent in the last SEND_WRITE cycle.
* @return
*/
DeviceCommandId_t getPendingCommand() const;
/* Specifying commands and replies */
/**
* @brief Fill the #DeviceCommandMap and #DeviceReplyMap called by the #initialize
* of the base class
* @details * @details
* This is used to let the base class know which replies are expected. * This is used to let the base class know which replies are expected.
* There are different scenarios regarding this: * There are different scenarios regarding this:
@ -399,7 +441,6 @@ protected:
* handled by returning @c APERIODIC_REPLY in scanForReply(). * handled by returning @c APERIODIC_REPLY in scanForReply().
*/ */
virtual void fillCommandAndReplyMap() = 0; virtual void fillCommandAndReplyMap() = 0;
/** /**
* This is a helper method to facilitate inserting entries in the command map. * This is a helper method to facilitate inserting entries in the command map.
* @param deviceCommand Identifier of the command to add. * @param deviceCommand Identifier of the command to add.
@ -417,7 +458,6 @@ protected:
LocalPoolDataSetBase* replyDataSet = nullptr, LocalPoolDataSetBase* replyDataSet = nullptr,
size_t replyLen = 0, bool periodic = false, size_t replyLen = 0, bool periodic = false,
bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0);
/** /**
* @brief This is a helper method to insert replies in the reply map. * @brief This is a helper method to insert replies in the reply map.
* @param deviceCommand Identifier of the reply to add. * @param deviceCommand Identifier of the reply to add.
@ -431,7 +471,6 @@ protected:
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand,
uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr, uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr,
size_t replyLen = 0, bool periodic = false); size_t replyLen = 0, bool periodic = false);
/** /**
* @brief A simple command to add a command to the commandList. * @brief A simple command to add a command to the commandList.
* @param deviceCommand The command to add * @param deviceCommand The command to add
@ -457,25 +496,14 @@ protected:
ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply, ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply,
uint16_t delayCycles, uint16_t maxDelayCycles, uint16_t delayCycles, uint16_t maxDelayCycles,
bool periodic = false); bool periodic = false);
/**
* @brief Can be used to set the dataset corresponding to a reply ID manually.
* @details
* Used by the local data pool manager.
*/
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId, ReturnValue_t setReplyDataset(DeviceCommandId_t replyId,
LocalPoolDataSetBase* dataset); LocalPoolDataSetBase* dataset);
/**
* @brief Can be implemented by child handler to
* perform debugging
* @details Example: Calling this in performOperation
* to track values like mode.
* @param positionTracker Provide the child handler a way to know
* where the debugInterface was called
* @param objectId Provide the child handler object Id to
* specify actions for spefic devices
* @param parameter Supply a parameter of interest
* Please delete all debugInterface calls in DHB after debugging is finished !
*/
virtual void debugInterface(uint8_t positionTracker = 0,
object_id_t objectId = 0, uint32_t parameter = 0);
/** /**
* Get the time needed to transit from modeFrom to modeTo. * Get the time needed to transit from modeFrom to modeTo.
* *
@ -494,6 +522,73 @@ protected:
*/ */
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) = 0; virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) = 0;
/* Functions used by the local data pool manager */
/**
* This function is used to initialize the local housekeeping pool
* entries. The default implementation leaves the pool empty.
* @param localDataPoolMap
* @return
*/
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
/**
* @brief Set all datapool variables that are update periodically in
* normal mode invalid
* @details
* The default implementation will set all datasets which have been added
* in #fillCommandAndReplyMap to invalid. It will also set all pool
* variables inside the dataset to invalid. The user can override this
* method optionally.
*/
virtual void setNormalDatapoolEntriesInvalid();
/**
* @brief Get the dataset handle for a given SID.
* @details
* The default implementation will use the deviceCommandMap to look for the corresponding
* dataset handle. The user can override this function if this is not desired.
* @param sid
* @return
*/
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
/* HasModesIF overrides */
virtual void startTransition(Mode_t mode, Submode_t submode) override;
virtual void setToExternalControl() override;
virtual void announceMode(bool recursive) override;
/**
* @brief Set the device handler mode
* @details
* Sets #timeoutStart with every call Also sets #transitionTargetMode if necessary so
* transitional states can be entered from everywhere without breaking the state machine
* (which relies on a correct #transitionTargetMode).
* The submode is left unchanged.
*
* @param newMode
*/
void setMode(Mode_t newMode);
/**
* @overload
* @param submode
*/
void setMode(Mode_t newMode, Submode_t submode);
/**
* @brief Should be implemented properly by child class.
* @param mode
* @param submode
* @return
* - @c RETURN_OK if valid
* - @c RETURN_FAILED if invalid
*/
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
Submode_t submode);
/**
* @brief Notify child about mode change.
* @details
* Can be overriden to be used like a callback.
*/
virtual void modeChanged();
/* Power handling functions */
/** /**
* Return the switches connected to the device. * Return the switches connected to the device.
* *
@ -509,82 +604,60 @@ protected:
uint8_t *numberOfSwitches); uint8_t *numberOfSwitches);
/** /**
* This function is used to initialize the local housekeeping pool * @brief Helper function to report a missed reply
* entries. The default implementation leaves the pool empty. * @details Can be overwritten by children to act on missed replies or to fake reporting Id.
* @param localDataPoolMap * @param id of the missed reply
* @return
*/ */
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, virtual void missedReply(DeviceCommandId_t id);
LocalDataPoolManager& poolManager) override;
/**
* Required for HasLocalDataPoolIF, return a handle to the local pool manager.
* @return
*/
LocalDataPoolManager* getHkManagerHandle() override;
/* Miscellaneous functions */
/** /**
* @brief Hook function for child handlers which is called once per * @brief Hook function for child handlers which is called once per
* performOperation(). Default implementation is empty. * performOperation(). Default implementation is empty.
*/ */
virtual void performOperationHook(); virtual void performOperationHook();
public:
/** Explicit interface implementation of getObjectId */
virtual object_id_t getObjectId() const override;
/** /**
* @param parentQueueId * @brief Can be implemented by child handler to
* perform debugging
* @details Example: Calling this in performOperation
* to track values like mode.
* @param positionTracker Provide the child handler a way to know
* where the debugInterface was called
* @param objectId Provide the child handler object Id to
* specify actions for spefic devices
* @param parameter Supply a parameter of interest
* Please delete all debugInterface calls in DHB after debugging is finished !
*/ */
virtual void setParentQueue(MessageQueueId_t parentQueueId); virtual void debugInterface(uint8_t positionTracker = 0,
object_id_t objectId = 0, uint32_t parameter = 0);
/** @brief Implementation required for HasActionIF */
ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data,
size_t size) override;
Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const;
virtual void getMode(Mode_t *mode, Submode_t *submode);
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) override;
/**
* Implementation of ExecutableObjectIF function
*
* Used to setup the reference of the task, that executes this component
* @param task_ Pointer to the taskIF of this task
*/
virtual void setTaskIF(PeriodicTaskIF* task_);
virtual MessageQueueId_t getCommandQueue(void) const;
protected: protected:
/**
* The Returnvalues id of this class, required by HasReturnvaluesIF
*/
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE; static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(0xA0); static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(0xA0);
// Returnvalues for scanForReply() /* Return codes for scanForReply */
static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB0); //!< This is used to specify for replies from a device which are not replies to requests //! This is used to specify for replies from a device which are not replies to requests
static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB1); //!< Ignore parts of the received packet static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB0);
static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB2); //!< Ignore full received packet //! Ignore parts of the received packet
// Returnvalues for command building static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB1);
static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xC0); //!< Return this if no command sending in required //! Ignore full received packet
static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB2);
/* Return codes for command building */
//! Return this if no command sending in required
static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xC0);
static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(0xC2); static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(0xC2);
// Returnvalues for getSwitches() // Return codes for getSwitches */
static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xD0); static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xD0);
// Mode handling error Codes /* Mode handling error Codes */
static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE0); static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE0);
static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE1); static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE1);
static const MessageQueueId_t NO_COMMANDER = 0; static const MessageQueueId_t NO_COMMANDER = 0;
/** Pointer to the raw packet that will be sent.*/ //! Pointer to the raw packet that will be sent.
uint8_t *rawPacket = nullptr; uint8_t *rawPacket = nullptr;
/** Size of the #rawPacket. */ //! Size of the #rawPacket.
uint32_t rawPacketLen = 0; uint32_t rawPacketLen = 0;
/** /**
@ -642,15 +715,15 @@ protected:
/** Cookie used for communication */ /** Cookie used for communication */
CookieIF * comCookie; CookieIF * comCookie;
/** Health helper for HasHealthIF */ /* Health helper for HasHealthIF */
HealthHelper healthHelper; HealthHelper healthHelper;
/** Mode helper for HasModesIF */ /* Mode helper for HasModesIF */
ModeHelper modeHelper; ModeHelper modeHelper;
/** Parameter helper for ReceivesParameterMessagesIF */ /* Parameter helper for ReceivesParameterMessagesIF */
ParameterHelper parameterHelper; ParameterHelper parameterHelper;
/** Action helper for HasActionsIF */ /* Action helper for HasActionsIF */
ActionHelper actionHelper; ActionHelper actionHelper;
/** Housekeeping Manager */ /* Housekeeping Manager */
LocalDataPoolManager poolManager; LocalDataPoolManager poolManager;
/** /**
@ -733,88 +806,41 @@ protected:
* default class is instantiated. */ * default class is instantiated. */
FailureIsolationBase* fdirInstance; FailureIsolationBase* fdirInstance;
HkSwitchHelper hkSwitcher; //! To correctly delete the default instance.
bool defaultFDIRUsed;
bool defaultFDIRUsed; //!< To correctly delete the default instance. //! Indicates if SWITCH_WENT_OFF was already thrown.
bool switchOffWasReported;
bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown. /** Pointer to the task which executes this component,
is invalid before setTaskIF was called. */
//! Pointer to the task which executes this component, is invalid
//! before setTaskIF was called.
PeriodicTaskIF* executingTask = nullptr; PeriodicTaskIF* executingTask = nullptr;
//!< Object which switches power on and off. //! Object which switches power on and off.
static object_id_t powerSwitcherId; static object_id_t powerSwitcherId;
//!< Object which receives RAW data by default. //! Object which receives RAW data by default.
static object_id_t rawDataReceiverId; static object_id_t rawDataReceiverId;
//!< Object which may be the root cause of an identified fault. //! Object which may be the root cause of an identified fault.
static object_id_t defaultFdirParentId; static object_id_t defaultFdirParentId;
/** /**
* @brief Set all datapool variables that are update periodically in * @brief Send a reply to a received device handler command.
* normal mode invalid
* @details
* The default implementation will set all datasets which have been added
* in #fillCommandAndReplyMap to invalid. It will also set all pool
* variables inside the dataset to invalid. The user can override this
* method optionally.
*/
virtual void setNormalDatapoolEntriesInvalid();
/**
* Helper function to get pending command. This is useful for devices
* like SPI sensors to identify the last sent command.
* This only returns the command sent in the last SEND_WRITE cycle.
* @return
*/
DeviceCommandId_t getPendingCommand() const;
/**
* Helper function to report a missed reply
*
* Can be overwritten by children to act on missed replies or to fake
* reporting Id.
*
* @param id of the missed reply
*/
virtual void missedReply(DeviceCommandId_t id);
/**
* Send a reply to a received device handler command.
* *
* This also resets #DeviceHandlerCommand to 0. * This also resets #DeviceHandlerCommand to 0.
* *
* @param reply the reply type * @param reply the reply type
* @param parameter parameter for the reply * @param parameter parameter for the reply
*/ */
void replyReturnvalueToCommand(ReturnValue_t status, void replyReturnvalueToCommand(ReturnValue_t status, uint32_t parameter = 0);
uint32_t parameter = 0); /**
* TODO: Whats the difference between this and the upper command?
* @param status
* @param parameter
*/
void replyToCommand(ReturnValue_t status, uint32_t parameter = 0); void replyToCommand(ReturnValue_t status, uint32_t parameter = 0);
/**
* Set the device handler mode
*
* Sets #timeoutStart with every call.
*
* Sets #transitionTargetMode if necessary so transitional states can be
* entered from everywhere without breaking the state machine
* (which relies on a correct #transitionTargetMode).
*
* The submode is left unchanged.
*
* @param newMode
*/
void setMode(Mode_t newMode);
/**
* @overload
* @param submode
*/
void setMode(Mode_t newMode, Submode_t submode);
/** /**
* Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW). * Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW).
* *
@ -856,16 +882,6 @@ protected:
*/ */
virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom); virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom);
/**
* @param mode
* @param submode
* @return
* - @c RETURN_OK if valid
* - @c RETURN_FAILED if invalid
*/
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
Submode_t submode);
/** /**
* Get the communication action for the current step. * Get the communication action for the current step.
* The step number can be read from #pstStep. * The step number can be read from #pstStep.
@ -874,27 +890,28 @@ protected:
virtual CommunicationAction getComAction(); virtual CommunicationAction getComAction();
/** /**
* Build the device command to send for raw mode. * Checks state of switches in conjunction with mode and triggers an event
* * if they don't fit.
* This is only called in @c MODE_RAW. It is for the rare case that in
* raw mode packets are to be sent by the handler itself. It is NOT needed
* for the raw commanding service. Its only current use is in the STR
* handler which gets its raw packets from a different source.
* Also it can be used for transitional commands, to get the device ready
* for @c MODE_RAW
*
* As it is almost never used, there is a default implementation
* returning @c NOTHING_TO_SEND.
*
* #rawPacket and #rawPacketLen must be set by this method to the packet
* to be sent.
*
* @param[out] id the device command id built
* @return
* - @c RETURN_OK when a command is to be sent
* - not @c NOTHING_TO_SEND when no command is to be sent
*/ */
virtual ReturnValue_t buildChildRawCommand(); virtual void checkSwitchState();
/**
* Reserved for the rare case where a device needs to perform additional
* operation cyclically in OFF mode.
*/
virtual void doOffActivity();
/**
* Reserved for the rare case where a device needs to perform additional
* operation cyclically in ON mode.
*/
virtual void doOnActivity();
/**
* Required for HasLocalDataPoolIF, return a handle to the local pool manager.
* @return
*/
LocalDataPoolManager* getHkManagerHandle() override;
/** /**
* Returns the delay cycle count of a reply. * Returns the delay cycle count of a reply.
@ -906,24 +923,6 @@ protected:
*/ */
uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand); uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand);
/**
* Construct a command reply containing a raw reply.
*
* It gets space in the #IPCStore, copies data there, then sends a raw reply
* containing the store address.
*
* This method is virtual, as devices can have different channels to send
* raw replies
*
* @param data data to send
* @param len length of @c data
* @param sendTo the messageQueueId of the one to send to
* @param isCommand marks the raw data as a command, the message then
* will be of type raw_command
*/
virtual void replyRawData(const uint8_t *data, size_t len,
MessageQueueId_t sendTo, bool isCommand = false);
/** /**
* Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping * Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping
* is active and if so, does not send the data as the wiretapping will have * is active and if so, does not send the data as the wiretapping will have
@ -931,11 +930,6 @@ protected:
*/ */
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len); void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
/**
* @brief Notify child about mode change.
*/
virtual void modeChanged(void);
/** /**
* Enable the reply checking for a command * Enable the reply checking for a command
* *
@ -963,6 +957,45 @@ protected:
uint8_t expectedReplies = 1, bool useAlternateId = false, uint8_t expectedReplies = 1, bool useAlternateId = false,
DeviceCommandId_t alternateReplyID = 0); DeviceCommandId_t alternateReplyID = 0);
/**
* @brief Build the device command to send for raw mode.
* @details
* This is only called in @c MODE_RAW. It is for the rare case that in
* raw mode packets are to be sent by the handler itself. It is NOT needed
* for the raw commanding service. Its only current use is in the STR
* handler which gets its raw packets from a different source.
* Also it can be used for transitional commands, to get the device ready
* for @c MODE_RAW
*
* As it is almost never used, there is a default implementation
* returning @c NOTHING_TO_SEND.
*
* #rawPacket and #rawPacketLen must be set by this method to the packet
* to be sent.
*
* @param[out] id the device command id built
* @return
* - @c RETURN_OK when a command is to be sent
* - not @c NOTHING_TO_SEND when no command is to be sent
*/
virtual ReturnValue_t buildChildRawCommand();
/**
* @brief Construct a command reply containing a raw reply.
* @details
* It gets space in the #IPCStore, copies data there, then sends a raw reply
* containing the store address. This method is virtual, as devices can have different channels
* to send raw replies
*
* @param data data to send
* @param len length of @c data
* @param sendTo the messageQueueId of the one to send to
* @param isCommand marks the raw data as a command, the message then
* will be of type raw_command
*/
virtual void replyRawData(const uint8_t *data, size_t len,
MessageQueueId_t sendTo, bool isCommand = false);
/** /**
* Get the state of the PCDU switches in the local datapool * Get the state of the PCDU switches in the local datapool
* @return * @return
@ -972,12 +1005,7 @@ protected:
* #switches are off * #switches are off
* - @c PowerSwitchIF::RETURN_FAILED if an error occured * - @c PowerSwitchIF::RETURN_FAILED if an error occured
*/ */
ReturnValue_t getStateOfSwitches(void); ReturnValue_t getStateOfSwitches();
/**
* build a list of sids and pass it to the #hkSwitcher
*/
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
/** /**
* Children can overwrite this function to suppress checking of the * Children can overwrite this function to suppress checking of the
@ -995,17 +1023,14 @@ protected:
bool isAwaitingReply(); bool isAwaitingReply();
void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t commandId, void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId,
bool neverInDataPool = false, bool forceDirectTm = false); bool forceDirectTm = false);
// void handleDeviceTM(uint8_t* data, size_t dataSize, DeviceCommandId_t replyId,
// bool forceDirectTm);
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode); uint32_t *msToReachTheMode);
/* HasModesIF overrides */
virtual void startTransition(Mode_t mode, Submode_t submode) override;
virtual void setToExternalControl() override;
virtual void announceMode(bool recursive) override;
virtual ReturnValue_t letChildHandleMessage(CommandMessage *message); virtual ReturnValue_t letChildHandleMessage(CommandMessage *message);
/** /**
@ -1023,23 +1048,6 @@ protected:
*/ */
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) const; uint32_t parameter2 = 0) const;
/**
* Checks state of switches in conjunction with mode and triggers an event
* if they don't fit.
*/
virtual void checkSwitchState();
/**
* Reserved for the rare case where a device needs to perform additional
* operation cyclically in OFF mode.
*/
virtual void doOffActivity();
/**
* Reserved for the rare case where a device needs to perform additional
* operation cyclically in ON mode.
*/
virtual void doOnActivity();
/** /**
* Checks if current mode is transitional mode. * Checks if current mode is transitional mode.
@ -1062,6 +1070,7 @@ protected:
* @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON * @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON
*/ */
void commandSwitch(ReturnValue_t onOff); void commandSwitch(ReturnValue_t onOff);
private: private:
/** /**
@ -1151,7 +1160,6 @@ private:
void buildRawDeviceCommand(CommandMessage* message); void buildRawDeviceCommand(CommandMessage* message);
void buildInternalCommand(void); void buildInternalCommand(void);
/** /**
* Decrement the counter for the timout of replies. * Decrement the counter for the timout of replies.
* *
@ -1159,7 +1167,6 @@ private:
* reply has timed out (that means a reply was expected but not received). * reply has timed out (that means a reply was expected but not received).
*/ */
void decrementDeviceReplyMap(void); void decrementDeviceReplyMap(void);
/** /**
* Convenience function to handle a reply. * Convenience function to handle a reply.
* *
@ -1174,8 +1181,8 @@ private:
* @foundLen the length of the packet * @foundLen the length of the packet
*/ */
void handleReply(const uint8_t *data, DeviceCommandId_t id, uint32_t foundLen); void handleReply(const uint8_t *data, DeviceCommandId_t id, uint32_t foundLen);
void replyToReply(DeviceReplyMap::iterator iter, ReturnValue_t status); void replyToReply(DeviceReplyMap::iterator iter, ReturnValue_t status);
/** /**
* Build and send a command to the device. * Build and send a command to the device.
* *
@ -1190,7 +1197,6 @@ private:
* sends the command via RMAP. * sends the command via RMAP.
*/ */
void doSendWrite(void); void doSendWrite(void);
/** /**
* Check if the RMAP sendWrite action was successful. * Check if the RMAP sendWrite action was successful.
* *
@ -1200,7 +1206,6 @@ private:
* - if the action was successful, the reply timout counter is initialized * - if the action was successful, the reply timout counter is initialized
*/ */
void doGetWrite(void); void doGetWrite(void);
/** /**
* Send a RMAP getRead command. * Send a RMAP getRead command.
* *
@ -1208,7 +1213,6 @@ private:
* This is always executed, independently from the current mode. * This is always executed, independently from the current mode.
*/ */
void doSendRead(void); void doSendRead(void);
/** /**
* Check the getRead reply and the contained data. * Check the getRead reply and the contained data.
* *
@ -1238,14 +1242,12 @@ private:
void setTransition(Mode_t modeTo, Submode_t submodeTo); void setTransition(Mode_t modeTo, Submode_t submodeTo);
/** /**
* calls the right child function for the transitional submodes * Calls the right child function for the transitional submodes
*/ */
void callChildStatemachine(); void callChildStatemachine();
ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message);
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
virtual dur_millis_t getPeriodicOperationFrequency() const override; virtual dur_millis_t getPeriodicOperationFrequency() const override;
void parseReply(const uint8_t* receivedData, void parseReply(const uint8_t* receivedData,
@ -1254,6 +1256,13 @@ private:
void handleTransitionToOnMode(Mode_t commandedMode, void handleTransitionToOnMode(Mode_t commandedMode,
Submode_t commandedSubmode); Submode_t commandedSubmode);
/**
* Generic internal printer function which also handles printing the object ID.
* @param errorType
* @param functionName
* @param errorCode
* @param errorPrint
*/
void printWarningOrError(sif::OutputTypes errorType, void printWarningOrError(sif::OutputTypes errorType,
const char* functionName, const char* functionName,
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED, ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,

View File

@ -209,20 +209,20 @@ void DeviceHandlerFailureIsolation::startRecovery(Event reason) {
} }
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId, ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) { const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t result = strangeReplyCount.getParameter(domainId, parameterId, ReturnValue_t result = strangeReplyCount.getParameter(domainId, uniqueId,
parameterWrapper, newValues, startAtIndex); parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) { if (result != INVALID_DOMAIN_ID) {
return result; return result;
} }
result = missedReplyCount.getParameter(domainId, parameterId, result = missedReplyCount.getParameter(domainId, uniqueId, parameterWrapper, newValues,
parameterWrapper, newValues, startAtIndex); startAtIndex);
if (result != INVALID_DOMAIN_ID) { if (result != INVALID_DOMAIN_ID) {
return result; return result;
} }
result = recoveryCounter.getParameter(domainId, parameterId, result = recoveryCounter.getParameter(domainId, uniqueId, parameterWrapper, newValues,
parameterWrapper, newValues, startAtIndex); startAtIndex);
if (result != INVALID_DOMAIN_ID) { if (result != INVALID_DOMAIN_ID) {
return result; return result;
} }

View File

@ -17,9 +17,9 @@ public:
ReturnValue_t initialize(); ReturnValue_t initialize();
void triggerEvent(Event event, uint32_t parameter1 = 0, void triggerEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0);bool isFdirActionInProgress(); uint32_t parameter2 = 0);bool isFdirActionInProgress();
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
const ParameterWrapper *newValues, uint16_t startAtIndex); uint16_t startAtIndex);
protected: protected:
FaultCounter strangeReplyCount; FaultCounter strangeReplyCount;

3
doc/doxy/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
html
latex
rtf

2609
doc/doxy/OPUS.doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,7 @@
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
#include "../ipc/MutexFactory.h" #include "../ipc/MutexFactory.h"
MessageQueueId_t EventManagerIF::eventmanagerQueue = MessageQueueIF::NO_QUEUE;
// If one checks registerListener calls, there are around 40 (to max 50) // If one checks registerListener calls, there are around 40 (to max 50)
// objects registering for certain events. // objects registering for certain events.

View File

@ -1,11 +1,12 @@
#ifndef EVENTMANAGERIF_H_ #ifndef FSFW_EVENTS_EVENTMANAGERIF_H_
#define EVENTMANAGERIF_H_ #define FSFW_EVENTS_EVENTMANAGERIF_H_
#include "EventMessage.h" #include "EventMessage.h"
#include "eventmatching/eventmatching.h" #include "eventmatching/eventmatching.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../ipc/MessageQueueSenderIF.h" #include "../ipc/MessageQueueSenderIF.h"
#include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueIF.h"
#include "../serviceinterface/ServiceInterface.h"
class EventManagerIF { class EventManagerIF {
public: public:
@ -41,11 +42,19 @@ public:
static void triggerEvent(EventMessage* message, static void triggerEvent(EventMessage* message,
MessageQueueId_t sentFrom = 0) { MessageQueueId_t sentFrom = 0) {
static MessageQueueId_t eventmanagerQueue = MessageQueueIF::NO_QUEUE;
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) { if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
EventManagerIF *eventmanager = objectManager->get<EventManagerIF>( EventManagerIF *eventmanager = objectManager->get<EventManagerIF>(
objects::EVENT_MANAGER); objects::EVENT_MANAGER);
if (eventmanager == nullptr) { if (eventmanager == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "EventManagerIF::triggerEvent: EventManager invalid or not found!"
<< std::endl;
#else
sif::printWarning("EventManagerIF::triggerEvent: "
"EventManager invalid or not found!");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return; return;
} }
eventmanagerQueue = eventmanager->getEventReportQueue(); eventmanagerQueue = eventmanager->getEventReportQueue();
@ -53,6 +62,10 @@ public:
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom); MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
} }
private:
//! Initialized by EventManager (C++11 does not allow header-only static member initialization).
static MessageQueueId_t eventmanagerQueue;
}; };
#endif /* EVENTMANAGERIF_H_ */ #endif /* FSFW_EVENTS_EVENTMANAGERIF_H_ */

View File

@ -58,14 +58,14 @@ FaultCounter::FaultCounter() :
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) { parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
} }
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) { uint16_t startAtIndex) {
if (domainId != parameterDomain) { if (domainId != parameterDomain) {
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
switch (parameterId) { switch (uniqueId) {
case 0: case 0:
parameterWrapper->set(failureThreshold); parameterWrapper->set(failureThreshold);
break; break;

View File

@ -23,7 +23,7 @@ public:
void setFailureThreshold(uint32_t failureThreshold); void setFailureThreshold(uint32_t failureThreshold);
void setFaultDecrementTimeMs(uint32_t timeMs); void setFaultDecrementTimeMs(uint32_t timeMs);
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); const ParameterWrapper *newValues, uint16_t startAtIndex);

View File

@ -176,7 +176,7 @@ void HousekeepingMessage::setUpdateNotificationVariableCommand(
void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command, void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
sid_t sid, store_address_t storeId) { sid_t sid, store_address_t storeId) {
command->setCommand(UPDATE_SNAPSHOT_VARIABLE); command->setCommand(UPDATE_SNAPSHOT_SET);
setSid(command, sid); setSid(command, sid);
command->setParameter3(storeId.raw); command->setParameter3(storeId.raw);
} }

View File

@ -1,24 +1,37 @@
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_ #ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_ #define FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
#include "../serialize/SerialBufferAdapter.h" #include "../serialize/SerialBufferAdapter.h"
#include "../serialize/SerialLinkedListAdapter.h" #include "../serialize/SerialLinkedListAdapter.h"
#include "../datapoollocal/LocalPoolDataSetBase.h" #include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../datapoollocal/LocalPoolObjectBase.h"
#include "../timemanager/CCSDSTime.h"
/** /**
* @brief This helper class will be used to serialize and deserialize * @brief This helper class will be used to serialize and deserialize update housekeeping packets
* update housekeeping packets into the store. * into the store.
*/ */
class HousekeepingPacketUpdate: public SerializeIF { class HousekeepingSnapshot: public SerializeIF {
public: public:
/** /**
* Update packet constructor for datasets * Update packet constructor for datasets.
* @param timeStamp * @param cdsShort If a CSD short timestamp is used, a reference should be
* @param timeStampSize * supplied here
* @param hkData * @param dataSetPtr Pointer to the dataset instance to serialize or deserialize the
* @param hkDataSize * data into
*/ */
HousekeepingPacketUpdate(uint8_t* timeStamp, size_t timeStampSize, HousekeepingSnapshot(CCSDSTime::CDS_short* cdsShort, LocalPoolDataSetBase* dataSetPtr):
timeStamp(reinterpret_cast<uint8_t*>(cdsShort)),
timeStampSize(sizeof(CCSDSTime::CDS_short)), updateData(dataSetPtr) {};
/**
* Update packet constructor for datasets.
* @param timeStamp Pointer to the buffer where the timestamp will be stored.
* @param timeStampSize Size of the timestamp
* @param dataSetPtr Pointer to the dataset instance to deserialize the data into
*/
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize,
LocalPoolDataSetBase* dataSetPtr): LocalPoolDataSetBase* dataSetPtr):
timeStamp(timeStamp), timeStampSize(timeStampSize), timeStamp(timeStamp), timeStampSize(timeStampSize),
updateData(dataSetPtr) {}; updateData(dataSetPtr) {};
@ -29,7 +42,7 @@ public:
* @param timeStampSize * @param timeStampSize
* @param dataSetPtr * @param dataSetPtr
*/ */
HousekeepingPacketUpdate(uint8_t* timeStamp, size_t timeStampSize, HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize,
LocalPoolObjectBase* dataSetPtr): LocalPoolObjectBase* dataSetPtr):
timeStamp(timeStamp), timeStampSize(timeStampSize), timeStamp(timeStamp), timeStampSize(timeStampSize),
updateData(dataSetPtr) {}; updateData(dataSetPtr) {};
@ -89,4 +102,4 @@ private:
}; };
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_ */ #endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_ */

View File

@ -37,16 +37,16 @@ public:
} }
} }
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
const ParameterWrapper *newValues, uint16_t startAtIndex) { uint16_t startAtIndex) {
ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId, ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId,
parameterId, parameterWrapper, newValues, startAtIndex); uniqueId, parameterWrapper, newValues, startAtIndex);
//We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there. //We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there.
if (result != this->INVALID_IDENTIFIER_ID) { if (result != this->INVALID_IDENTIFIER_ID) {
return result; return result;
} }
switch (parameterId) { switch (uniqueId) {
case 10: case 10:
parameterWrapper->set(this->lowerLimit); parameterWrapper->set(this->lowerLimit);
break; break;

View File

@ -51,13 +51,13 @@ public:
return state; return state;
} }
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
const ParameterWrapper *newValues, uint16_t startAtIndex) { uint16_t startAtIndex) {
if (domainId != monitorId) { if (domainId != monitorId) {
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
switch (parameterId) { switch (uniqueId) {
case 0: case 0:
parameterWrapper->set(this->confirmationLimit); parameterWrapper->set(this->confirmationLimit);
break; break;

View File

@ -10,7 +10,7 @@
#include "../serialize/SerialFixedArrayListAdapter.h" #include "../serialize/SerialFixedArrayListAdapter.h"
#include "../serialize/SerializeElement.h" #include "../serialize/SerializeElement.h"
#include "../serialize/SerialLinkedListAdapter.h" #include "../serialize/SerialLinkedListAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterface.h"
#include "../timemanager/TimeStamperIF.h" #include "../timemanager/TimeStamperIF.h"
namespace Factory{ namespace Factory{

View File

@ -71,13 +71,13 @@ public:
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
const ParameterWrapper *newValues, uint16_t startAtIndex) { uint16_t startAtIndex) {
if (domainId != this->domainId) { if (domainId != this->domainId) {
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
switch (parameterId) { switch (uniqueId) {
case 0: case 0:
parameterWrapper->set(limit); parameterWrapper->set(limit);
break; break;

View File

@ -1,5 +1,5 @@
#include "ObjectManager.h" #include "ObjectManager.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterface.h"
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
#include <iomanip> #include <iomanip>
@ -75,6 +75,8 @@ void ObjectManager::initialize() {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "ObjectManager::initialize: Passed produceObjects " sif::error << "ObjectManager::initialize: Passed produceObjects "
"functions is nullptr!" << std::endl; "functions is nullptr!" << std::endl;
#else
sif::printError("ObjectManager::initialize: Passed produceObjects functions is nullptr!\n");
#endif #endif
return; return;
} }

View File

@ -5,15 +5,19 @@
SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) : SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) :
objectId(setObjectId), registered(doRegister) { objectId(setObjectId), registered(doRegister) {
if (registered) { if (registered) {
if(objectManager != nullptr) {
objectManager->insert(objectId, this); objectManager->insert(objectId, this);
} }
} }
}
SystemObject::~SystemObject() { SystemObject::~SystemObject() {
if (registered) { if (registered) {
if(objectManager != nullptr) {
objectManager->remove(objectId); objectManager->remove(objectId);
} }
} }
}
object_id_t SystemObject::getObjectId() const { object_id_t SystemObject::getObjectId() const {
return objectId; return objectId;

View File

@ -1,8 +1,11 @@
#ifndef FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ #ifndef FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
#define FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ #define FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
#include <fsfw/objectmanager/SystemObjectIF.h>
namespace objects { namespace objects {
enum framework_objects { enum framework_objects: object_id_t {
FSFW_OBJECTS_START = 0x53000000,
// Default verification reporter. // Default verification reporter.
PUS_SERVICE_1_VERIFICATION = 0x53000001, PUS_SERVICE_1_VERIFICATION = 0x53000001,
PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002, PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002,
@ -11,6 +14,7 @@ enum framework_objects {
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008, PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
PUS_SERVICE_9_TIME_MGMT = 0x53000009, PUS_SERVICE_9_TIME_MGMT = 0x53000009,
PUS_SERVICE_17_TEST = 0x53000017, PUS_SERVICE_17_TEST = 0x53000017,
PUS_SERVICE_20_PARAMETERS = 0x53000020,
PUS_SERVICE_200_MODE_MGMT = 0x53000200, PUS_SERVICE_200_MODE_MGMT = 0x53000200,
//Generic IDs for IPC, modes, health, events //Generic IDs for IPC, modes, health, events
@ -24,6 +28,7 @@ enum framework_objects {
TM_STORE = 0x534f0200, TM_STORE = 0x534f0200,
TIME_STAMPER = 0x53500010, TIME_STAMPER = 0x53500010,
FSFW_OBJECTS_END = 0x53ffffff,
NO_OBJECT = 0xFFFFFFFF NO_OBJECT = 0xFFFFFFFF
}; };
} }

View File

@ -25,7 +25,8 @@
#else #else
#ifdef WIN32 #ifdef WIN32
#include <Windows.h> #include <winsock2.h>
#include <windows.h>
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN #if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN #define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
#else #else

View File

@ -3,7 +3,7 @@
#include <chrono> #include <chrono>
#if defined(WIN32) #if defined(WIN32)
#include <windows.h> #include <sysinfoapi.h>
#elif defined(LINUX) #elif defined(LINUX)
#include <fstream> #include <fstream>
#endif #endif
@ -15,35 +15,34 @@ using SystemClock = std::chrono::system_clock;
uint32_t Clock::getTicksPerSecond(void){ uint32_t Clock::getTicksPerSecond(void){
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl; sif::warning << "Clock::getTicksPerSecond: Not implemented for host OSAL" << std::endl;
#else
sif::printWarning("Clock::getTicksPerSecond: Not implemented for host OSAL\n");
#endif #endif
return 0; /* To avoid division by zero */
//return CLOCKS_PER_SEC; return 1;
//uint32_t ticks = sysconf(_SC_CLK_TCK);
//return ticks;
} }
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
// do some magic with chrono /* I don't know why someone would need to set a clock which is probably perfectly fine on a
host system with internet access so this is not implemented for now. */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::setClock: not implemented yet" << std::endl; sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
#else
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
#endif #endif
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Clock::setClock(const timeval* time) { ReturnValue_t Clock::setClock(const timeval* time) {
// do some magic with chrono /* I don't know why someone would need to set a clock which is probably perfectly fine on a
#if defined(WIN32) host system with internet access so this is not implemented for now. */
return HasReturnvaluesIF::RETURN_OK;
#elif defined(LINUX)
return HasReturnvaluesIF::RETURN_OK;
#else
#endif
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
#else
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Clock::getClock_timeval(timeval* time) { ReturnValue_t Clock::getClock_timeval(timeval* time) {
@ -53,8 +52,7 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
auto epoch = now.time_since_epoch(); auto epoch = now.time_since_epoch();
time->tv_sec = std::chrono::duration_cast<std::chrono::seconds>(epoch).count(); time->tv_sec = std::chrono::duration_cast<std::chrono::seconds>(epoch).count();
auto fraction = now - secondsChrono; auto fraction = now - secondsChrono;
time->tv_usec = std::chrono::duration_cast<std::chrono::microseconds>( time->tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(fraction).count();
fraction).count();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
#elif defined(LINUX) #elif defined(LINUX)
timespec timeUnix; timespec timeUnix;
@ -67,7 +65,9 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
#else #else
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
#else
sif::printWarning("Clock::getUptime: Not implemented for found OS!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
#endif #endif
@ -75,10 +75,11 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
} }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) { ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
// do some magic with chrono if(time == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 return HasReturnvaluesIF::RETURN_FAILED;
sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl; }
#endif using namespace std::chrono;
*time = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -120,9 +121,9 @@ ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
// do some magic with chrono (C++20!) /* Do some magic with chrono (C++20!) */
// Right now, the library doesn't have the new features yet. /* Right now, the library doesn't have the new features to get the required values yet.
// so we work around that for now. so we work around that for now. */
auto now = SystemClock::now(); auto now = SystemClock::now();
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now); auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto fraction = now - seconds; auto fraction = now - seconds;
@ -137,10 +138,6 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
time->second = timeInfo->tm_sec; time->second = timeInfo->tm_sec;
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction); auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
time->usecond = usecond.count(); time->usecond = usecond.count();
#if FSFW_CPP_OSTREAM_ENABLED == 1
//sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl;
#endif
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -9,7 +9,7 @@
#include <chrono> #include <chrono>
#if defined(WIN32) #if defined(WIN32)
#include <windows.h> #include <processthreadsapi.h>
#elif defined(LINUX) #elif defined(LINUX)
#include <pthread.h> #include <pthread.h>
#endif #endif

View File

@ -5,13 +5,13 @@ target_sources(${LIB_FSFW_NAME}
InitTask.cpp InitTask.cpp
InternalErrorCodes.cpp InternalErrorCodes.cpp
MessageQueue.cpp MessageQueue.cpp
MultiObjectTask.cpp PeriodicTask.cpp
Mutex.cpp Mutex.cpp
MutexFactory.cpp MutexFactory.cpp
PollingTask.cpp FixedTimeslotTask.cpp
QueueFactory.cpp QueueFactory.cpp
RtemsBasic.cpp RtemsBasic.cpp
TaskBase.cpp RTEMSTaskBase.cpp
TaskFactory.cpp TaskFactory.cpp
) )

View File

@ -104,9 +104,13 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
} }
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
// TIsn't this a bug? Are RTEMS ticks always microseconds? /* For all but the last field, the struct will be filled with the correct values */
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time); rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time);
rtems_status_code status = rtems_clock_get_tod(timeRtems); rtems_status_code status = rtems_clock_get_tod(timeRtems);
/* The last field now contains the RTEMS ticks of the seconds from 0
to rtems_clock_get_ticks_per_second() minus one. We calculate the microseconds accordingly */
timeRtems->ticks = static_cast<float>(timeRtems->ticks) /
rtems_clock_get_ticks_per_second() * 1e6;
switch (status) { switch (status) {
case RTEMS_SUCCESSFUL: case RTEMS_SUCCESSFUL:
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;

View File

@ -164,7 +164,7 @@ ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer,
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
if ((*size = *size - MAX_LENGTH_OF_THREAD_NAME) < 0) { if (*size < MAX_LENGTH_OF_THREAD_NAME) {
return STREAM_TOO_SHORT; return STREAM_TOO_SHORT;
} }
memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME); memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME);

View File

@ -0,0 +1,140 @@
#include "FixedTimeslotTask.h"
#include "RtemsBasic.h"
#include "../../tasks/FixedSequenceSlot.h"
#include "../../objectmanager/SystemObjectIF.h"
#include "../../objectmanager/ObjectManagerIF.h"
#include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../serviceinterface/ServiceInterface.h"
#include <rtems/bspIo.h>
#include <rtems/io.h>
#include <rtems/rtems/ratemon.h>
#include <rtems/rtems/status.h>
#include <rtems/rtems/tasks.h>
#include <rtems/rtems/types.h>
#include <sys/_stdint.h>
#if FSFW_CPP_OSTREAM_ENABLED == 1
#include <iostream>
#endif
#include <cstddef>
#include <list>
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
FixedTimeslotTask::FixedTimeslotTask(const char *name, rtems_task_priority setPriority,
size_t setStack, uint32_t setOverallPeriod, void (*setDeadlineMissedFunc)(void)):
RTEMSTaskBase(setPriority, setStack, name), periodId(0), pst(setOverallPeriod) {
// All additional attributes are applied to the object.
this->deadlineMissedFunc = setDeadlineMissedFunc;
}
FixedTimeslotTask::~FixedTimeslotTask() {
}
rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) {
/* The argument is re-interpreted as a FixedTimeslotTask */
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
/* The task's functionality is called. */
return originalTask->taskFunctionality();
/* Should never be reached */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Polling task " << originalTask->getId() << " returned from taskFunctionality." <<
std::endl;
#endif
}
void FixedTimeslotTask::missedDeadlineCounter() {
FixedTimeslotTask::deadlineMissedCount++;
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount
<< " deadlines." << std::endl;
#endif
}
}
ReturnValue_t FixedTimeslotTask::startTask() {
rtems_status_code status = rtems_task_start(id, FixedTimeslotTask::taskEntryPoint,
rtems_task_argument((void *) this));
if (status != RTEMS_SUCCESSFUL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PollingTask::startTask for " << std::hex << this->getId()
<< std::dec << " failed." << std::endl;
#endif
}
switch(status){
case RTEMS_SUCCESSFUL:
//ask started successfully
return HasReturnvaluesIF::RETURN_OK;
default:
/*
RTEMS_INVALID_ADDRESS - invalid task entry point
RTEMS_INVALID_ID - invalid task id
RTEMS_INCORRECT_STATE - task not in the dormant state
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) {
ExecutableObjectIF* object = objectManager->get<ExecutableObjectIF>(componentId);
if (object != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep, object, this);
return HasReturnvaluesIF::RETURN_OK;
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Component " << std::hex << componentId <<
" not found, not adding it to pst" << std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
uint32_t FixedTimeslotTask::getPeriodMs() const {
return pst.getLengthMs();
}
ReturnValue_t FixedTimeslotTask::checkSequence() const {
return pst.checkSequence();
}
void FixedTimeslotTask::taskFunctionality() {
/* A local iterator for the Polling Sequence Table is created to find the start time for
the first entry. */
FixedSlotSequence::SlotListIter it = pst.current;
/* Initialize the PST with the correct calling task */
pst.intializeSequenceAfterTaskCreation();
/* The start time for the first entry is read. */
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
RTEMSTaskBase::setAndStartPeriod(interval,&periodId);
//The task's "infinite" inner loop is entered.
while (1) {
if (pst.slotFollowsImmediately()) {
/* Do nothing */
}
else {
/* The interval for the next polling slot is selected. */
interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs());
/* The period is checked and restarted with the new interval.
If the deadline was missed, the deadlineMissedFunc is called. */
rtems_status_code status = RTEMSTaskBase::restartPeriod(interval,periodId);
if (status == RTEMS_TIMEOUT) {
if (this->deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();
}
}
}
/* The device handler for this slot is executed and the next one is chosen. */
this->pst.executeAndAdvance();
}
}
ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms){
return RTEMSTaskBase::sleepFor(ms);
};

View File

@ -0,0 +1,81 @@
#ifndef FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
#define FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
#include "RTEMSTaskBase.h"
#include "../../tasks/FixedSlotSequence.h"
#include "../../tasks/FixedTimeslotTaskIF.h"
class FixedTimeslotTask: public RTEMSTaskBase, public FixedTimeslotTaskIF {
public:
/**
* @brief The standard constructor of the class.
* @details
* This is the general constructor of the class. In addition to the TaskBase parameters,
* the following variables are passed:
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
* that shall be assigned.
* @param getPst The object id of the completely initialized polling sequence.
*/
FixedTimeslotTask( const char *name, rtems_task_priority setPriority, size_t setStackSize,
uint32_t overallPeriod, void (*setDeadlineMissedFunc)());
/**
* @brief The destructor of the class.
* @details
* The destructor frees all heap memory that was allocated on thread initialization
* for the PST andthe device handlers. This is done by calling the PST's destructor.
*/
virtual ~FixedTimeslotTask( void );
ReturnValue_t startTask( void );
/**
* This static function can be used as #deadlineMissedFunc.
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
*/
static void missedDeadlineCounter();
/**
* A helper variable to count missed deadlines.
*/
static uint32_t deadlineMissedCount;
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
uint32_t getPeriodMs() const;
ReturnValue_t checkSequence() const;
ReturnValue_t sleepFor(uint32_t ms);
protected:
/**
* @brief id of the associated OS period
*/
rtems_id periodId;
FixedSlotSequence pst;
/**
* @brief This attribute holds a function pointer that is executed when a deadline was missed.
*
* @details
* Another function may be announced to determine the actions to perform when a deadline
* was missed. Currently, only one function for missing any deadline is allowed.
* If not used, it shall be declared NULL.
*/
void ( *deadlineMissedFunc )( void ) = nullptr;
/**
* @brief This is the entry point in a new polling thread.
* @details This method is the entry point in the new thread
*/
static rtems_task taskEntryPoint( rtems_task_argument argument );
/**
* @brief This function holds the main functionality of the thread.
* @details
* Holding the main functionality of the task, this method is most important.
* It links the functionalities provided by FixedSlotSequence with the OS's system calls to
* keep the timing of the periods.
*/
void taskFunctionality( void );
};
#endif /* FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ */

View File

@ -1,92 +0,0 @@
/**
* @file MultiObjectTask.cpp
* @brief This file defines the MultiObjectTask class.
* @date 30.01.2014
* @author baetz
*/
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../tasks/ExecutableObjectIF.h"
#include "MultiObjectTask.h"
MultiObjectTask::MultiObjectTask(const char *name, rtems_task_priority setPriority,
size_t setStack, rtems_interval setPeriod, void (*setDeadlineMissedFunc)()) :
TaskBase(setPriority, setStack, name), periodTicks(
RtemsBasic::convertMsToTicks(setPeriod)), periodId(0), deadlineMissedFunc(
setDeadlineMissedFunc) {
}
MultiObjectTask::~MultiObjectTask(void) {
//Do not delete objects, we were responsible for ptrs only.
rtems_rate_monotonic_delete(periodId);
}
rtems_task MultiObjectTask::taskEntryPoint(rtems_task_argument argument) {
//The argument is re-interpreted as MultiObjectTask. The Task object is global, so it is found from any place.
MultiObjectTask *originalTask(reinterpret_cast<MultiObjectTask*>(argument));
originalTask->taskFunctionality();
}
ReturnValue_t MultiObjectTask::startTask() {
rtems_status_code status = rtems_task_start(id, MultiObjectTask::taskEntryPoint,
rtems_task_argument((void *) this));
if (status != RTEMS_SUCCESSFUL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "ObjectTask::startTask for " << std::hex << this->getId()
<< std::dec << " failed." << std::endl;
#endif
}
switch(status){
case RTEMS_SUCCESSFUL:
//ask started successfully
return HasReturnvaluesIF::RETURN_OK;
default:
/* RTEMS_INVALID_ADDRESS - invalid task entry point
RTEMS_INVALID_ID - invalid task id
RTEMS_INCORRECT_STATE - task not in the dormant state
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t MultiObjectTask::sleepFor(uint32_t ms) {
return TaskBase::sleepFor(ms);
}
void MultiObjectTask::taskFunctionality() {
TaskBase::setAndStartPeriod(periodTicks,&periodId);
//The task's "infinite" inner loop is entered.
while (1) {
for (ObjectList::iterator it = objectList.begin();
it != objectList.end(); ++it) {
(*it)->performOperation();
}
rtems_status_code status = TaskBase::restartPeriod(periodTicks,periodId);
if (status == RTEMS_TIMEOUT) {
char nameSpace[8] = { 0 };
char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace),
nameSpace);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "ObjectTask: " << ptr << " Deadline missed." << std::endl;
#endif
if (this->deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();
}
}
}
}
ReturnValue_t MultiObjectTask::addComponent(object_id_t object) {
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(
object);
if (newObject == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
objectList.push_back(newObject);
newObject->setTaskIF(this);
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t MultiObjectTask::getPeriodMs() const {
return RtemsBasic::convertTicksToMs(periodTicks);
}

View File

@ -1,18 +1,20 @@
#include "Mutex.h" #include "Mutex.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterface.h"
uint8_t Mutex::count = 0; uint8_t Mutex::count = 0;
Mutex::Mutex() : Mutex::Mutex() {
mutexId(0) {
rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++; rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++;
rtems_status_code status = rtems_semaphore_create(mutexName, 1, rtems_status_code status = rtems_semaphore_create(mutexName, 1,
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0, RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
&mutexId); &mutexId);
if (status != RTEMS_SUCCESSFUL) { if (status != RTEMS_SUCCESSFUL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Mutex: creation with name, id " << mutexName << ", " << mutexId sif::error << "Mutex::Mutex: Creation with name, id " << mutexName << ", " << mutexId <<
<< " failed with " << status << std::endl; " failed with " << status << std::endl;
#else
sif::printError("Mutex::Mutex: Creation with name, id %s, %d failed with %d\n", mutexName,
static_cast<int>(mutexId), static_cast<int>(status));
#endif #endif
} }
} }

View File

@ -11,7 +11,7 @@ public:
ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0); ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0);
ReturnValue_t unlockMutex(); ReturnValue_t unlockMutex();
private: private:
rtems_id mutexId; rtems_id mutexId = 0;
static uint8_t count; static uint8_t count;
}; };

View File

@ -1,6 +1,7 @@
#include "../../ipc/MutexFactory.h"
#include "Mutex.h" #include "Mutex.h"
#include "RtemsBasic.h"
#include "../../ipc/MutexFactory.h"
MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); MutexFactory* MutexFactory::factoryInstance = new MutexFactory();

View File

@ -0,0 +1,83 @@
#include "PeriodicTask.h"
#include "../../serviceinterface/ServiceInterface.h"
#include "../../tasks/ExecutableObjectIF.h"
PeriodicTask::PeriodicTask(const char *name, rtems_task_priority setPriority,
size_t setStack, rtems_interval setPeriod, void (*setDeadlineMissedFunc)()) :
RTEMSTaskBase(setPriority, setStack, name),
periodTicks(RtemsBasic::convertMsToTicks(setPeriod)),
deadlineMissedFunc(setDeadlineMissedFunc) {
}
PeriodicTask::~PeriodicTask(void) {
/* Do not delete objects, we were responsible for pointers only. */
rtems_rate_monotonic_delete(periodId);
}
rtems_task PeriodicTask::taskEntryPoint(rtems_task_argument argument) {
/* The argument is re-interpreted as MultiObjectTask. The Task object is global,
so it is found from any place. */
PeriodicTask *originalTask(reinterpret_cast<PeriodicTask*>(argument));
return originalTask->taskFunctionality();;
}
ReturnValue_t PeriodicTask::startTask() {
rtems_status_code status = rtems_task_start(id, PeriodicTask::taskEntryPoint,
rtems_task_argument((void *) this));
if (status != RTEMS_SUCCESSFUL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "ObjectTask::startTask for " << std::hex << this->getId()
<< std::dec << " failed." << std::endl;
#endif
}
switch(status){
case RTEMS_SUCCESSFUL:
/* Task started successfully */
return HasReturnvaluesIF::RETURN_OK;
default:
/* RTEMS_INVALID_ADDRESS - invalid task entry point
RTEMS_INVALID_ID - invalid task id
RTEMS_INCORRECT_STATE - task not in the dormant state
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) {
return RTEMSTaskBase::sleepFor(ms);
}
void PeriodicTask::taskFunctionality() {
RTEMSTaskBase::setAndStartPeriod(periodTicks,&periodId);
for (const auto& object: objectList) {
object->initializeAfterTaskCreation();
}
/* The task's "infinite" inner loop is entered. */
while (1) {
for (const auto& object: objectList) {
object->performOperation();
}
rtems_status_code status = RTEMSTaskBase::restartPeriod(periodTicks,periodId);
if (status == RTEMS_TIMEOUT) {
if (this->deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();
}
}
}
}
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(object);
if (newObject == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
objectList.push_back(newObject);
newObject->setTaskIF(this);
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t PeriodicTask::getPeriodMs() const {
return RtemsBasic::convertTicksToMs(periodTicks);
}

View File

@ -1,10 +1,10 @@
#ifndef FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ #ifndef FSFW_OSAL_RTEMS_PERIODICTASK_H_
#define FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ #define FSFW_OSAL_RTEMS_PERIODICTASK_H_
#include "RTEMSTaskBase.h"
#include "../../objectmanager/ObjectManagerIF.h" #include "../../objectmanager/ObjectManagerIF.h"
#include "../../tasks/PeriodicTaskIF.h" #include "../../tasks/PeriodicTaskIF.h"
#include "TaskBase.h"
#include <vector> #include <vector>
class ExecutableObjectIF; class ExecutableObjectIF;
@ -18,7 +18,7 @@ class ExecutableObjectIF;
* @author baetz * @author baetz
* @ingroup task_handling * @ingroup task_handling
*/ */
class MultiObjectTask: public TaskBase, public PeriodicTaskIF { class PeriodicTask: public RTEMSTaskBase, public PeriodicTaskIF {
public: public:
/** /**
* @brief Standard constructor of the class. * @brief Standard constructor of the class.
@ -35,13 +35,13 @@ public:
* @param setDeadlineMissedFunc The function pointer to the deadline missed function * @param setDeadlineMissedFunc The function pointer to the deadline missed function
* that shall be assigned. * that shall be assigned.
*/ */
MultiObjectTask(const char *name, rtems_task_priority setPriority, size_t setStack, rtems_interval setPeriod, PeriodicTask(const char *name, rtems_task_priority setPriority, size_t setStack,
void (*setDeadlineMissedFunc)()); rtems_interval setPeriod, void (*setDeadlineMissedFunc)());
/** /**
* @brief Currently, the executed object's lifetime is not coupled with the task object's * @brief Currently, the executed object's lifetime is not coupled with the task object's
* lifetime, so the destructor is empty. * lifetime, so the destructor is empty.
*/ */
virtual ~MultiObjectTask(void); virtual ~PeriodicTask(void);
/** /**
* @brief The method to start the task. * @brief The method to start the task.
@ -76,7 +76,7 @@ protected:
/** /**
* @brief id of the associated OS period * @brief id of the associated OS period
*/ */
rtems_id periodId; rtems_id periodId = 0;
/** /**
* @brief The pointer to the deadline-missed function. * @brief The pointer to the deadline-missed function.
* @details This pointer stores the function that is executed if the task's deadline is missed. * @details This pointer stores the function that is executed if the task's deadline is missed.
@ -104,4 +104,4 @@ protected:
void taskFunctionality(void); void taskFunctionality(void);
}; };
#endif /* FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ */ #endif /* FSFW_OSAL_RTEMS_PERIODICTASK_H_ */

View File

@ -1,131 +0,0 @@
#include "../../tasks/FixedSequenceSlot.h"
#include "../../objectmanager/SystemObjectIF.h"
#include "../../objectmanager/ObjectManagerIF.h"
#include "PollingTask.h"
#include "RtemsBasic.h"
#include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include <rtems/bspIo.h>
#include <rtems/rtems/ratemon.h>
#include <rtems/rtems/status.h>
#include <rtems/rtems/tasks.h>
#include <rtems/rtems/types.h>
#include <stddef.h>
#include <sys/_stdint.h>
#include <iostream>
#include <list>
uint32_t PollingTask::deadlineMissedCount = 0;
PollingTask::PollingTask(const char *name, rtems_task_priority setPriority,
size_t setStack, uint32_t setOverallPeriod,
void (*setDeadlineMissedFunc)()) :
TaskBase(setPriority, setStack, name), periodId(0), pst(
setOverallPeriod) {
// All additional attributes are applied to the object.
this->deadlineMissedFunc = setDeadlineMissedFunc;
}
PollingTask::~PollingTask() {
}
rtems_task PollingTask::taskEntryPoint(rtems_task_argument argument) {
//The argument is re-interpreted as PollingTask.
PollingTask *originalTask(reinterpret_cast<PollingTask*>(argument));
//The task's functionality is called.
originalTask->taskFunctionality();
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Polling task " << originalTask->getId()
<< " returned from taskFunctionality." << std::endl;
#endif
}
void PollingTask::missedDeadlineCounter() {
PollingTask::deadlineMissedCount++;
if (PollingTask::deadlineMissedCount % 10 == 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PST missed " << PollingTask::deadlineMissedCount
<< " deadlines." << std::endl;
#endif
}
}
ReturnValue_t PollingTask::startTask() {
rtems_status_code status = rtems_task_start(id, PollingTask::taskEntryPoint,
rtems_task_argument((void *) this));
if (status != RTEMS_SUCCESSFUL) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PollingTask::startTask for " << std::hex << this->getId()
<< std::dec << " failed." << std::endl;
#endif
}
switch(status){
case RTEMS_SUCCESSFUL:
//ask started successfully
return HasReturnvaluesIF::RETURN_OK;
default:
/* RTEMS_INVALID_ADDRESS - invalid task entry point
RTEMS_INVALID_ID - invalid task id
RTEMS_INCORRECT_STATE - task not in the dormant state
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t PollingTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) {
ExecutableObjectIF* object = objectManager->get<ExecutableObjectIF>(componentId);
if (object != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep, object, this);
return HasReturnvaluesIF::RETURN_OK;
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Component " << std::hex << componentId <<
" not found, not adding it to pst" << std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
uint32_t PollingTask::getPeriodMs() const {
return pst.getLengthMs();
}
ReturnValue_t PollingTask::checkSequence() const {
return pst.checkSequence();
}
#include <rtems/io.h>
void PollingTask::taskFunctionality() {
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
FixedSlotSequence::SlotListIter it = pst.current;
//The start time for the first entry is read.
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
TaskBase::setAndStartPeriod(interval,&periodId);
//The task's "infinite" inner loop is entered.
while (1) {
if (pst.slotFollowsImmediately()) {
//Do nothing
} else {
//The interval for the next polling slot is selected.
interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs());
//The period is checked and restarted with the new interval.
//If the deadline was missed, the deadlineMissedFunc is called.
rtems_status_code status = TaskBase::restartPeriod(interval,periodId);
if (status == RTEMS_TIMEOUT) {
if (this->deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();
}
}
}
//The device handler for this slot is executed and the next one is chosen.
this->pst.executeAndAdvance();
}
}
ReturnValue_t PollingTask::sleepFor(uint32_t ms){
return TaskBase::sleepFor(ms);
};

View File

@ -1,85 +0,0 @@
#ifndef FSFW_OSAL_RTEMS_POLLINGTASK_H_
#define FSFW_OSAL_RTEMS_POLLINGTASK_H_
#include "../../tasks/FixedSlotSequence.h"
#include "../../tasks/FixedTimeslotTaskIF.h"
#include "TaskBase.h"
class PollingTask: public TaskBase, public FixedTimeslotTaskIF {
public:
/**
* @brief The standard constructor of the class.
*
* @details This is the general constructor of the class. In addition to the TaskBase parameters,
* the following variables are passed:
*
* @param (*setDeadlineMissedFunc)() The function pointer to the deadline missed function that shall be assigned.
*
* @param getPst The object id of the completely initialized polling sequence.
*/
PollingTask( const char *name, rtems_task_priority setPriority, size_t setStackSize, uint32_t overallPeriod, void (*setDeadlineMissedFunc)());
/**
* @brief The destructor of the class.
*
* @details The destructor frees all heap memory that was allocated on thread initialization for the PST and
* the device handlers. This is done by calling the PST's destructor.
*/
virtual ~PollingTask( void );
ReturnValue_t startTask( void );
/**
* This static function can be used as #deadlineMissedFunc.
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
*/
static void missedDeadlineCounter();
/**
* A helper variable to count missed deadlines.
*/
static uint32_t deadlineMissedCount;
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
uint32_t getPeriodMs() const;
ReturnValue_t checkSequence() const;
ReturnValue_t sleepFor(uint32_t ms);
protected:
/**
* @brief id of the associated OS period
*/
rtems_id periodId;
FixedSlotSequence pst;
/**
* @brief This attribute holds a function pointer that is executed when a deadline was missed.
*
* @details Another function may be announced to determine the actions to perform when a deadline was missed.
* Currently, only one function for missing any deadline is allowed.
* If not used, it shall be declared NULL.
*/
void ( *deadlineMissedFunc )( void );
/**
* @brief This is the entry point in a new polling thread.
*
* @details This method, that is the generalOSAL::checkAndRestartPeriod( this->periodId, interval ); entry point in the new thread, is here set to generate
* and link the Polling Sequence Table to the thread object and start taskFunctionality()
* on success. If operation of the task is ended for some reason,
* the destructor is called to free allocated memory.
*/
static rtems_task taskEntryPoint( rtems_task_argument argument );
/**
* @brief This function holds the main functionality of the thread.
*
*
* @details Holding the main functionality of the task, this method is most important.
* It links the functionalities provided by FixedSlotSequence with the OS's System Calls
* to keep the timing of the periods.
*/
void taskFunctionality( void );
};
#endif /* FSFW_OSAL_RTEMS_POLLINGTASK_H_ */

View File

@ -1,9 +1,9 @@
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "RTEMSTaskBase.h"
#include "TaskBase.h" #include "../../serviceinterface/ServiceInterface.h"
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = RTEMS_MINIMUM_STACK_SIZE; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = RTEMS_MINIMUM_STACK_SIZE;
TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size, RTEMSTaskBase::RTEMSTaskBase(rtems_task_priority set_priority, size_t stack_size,
const char *name) { const char *name) {
rtems_name osalName = 0; rtems_name osalName = 0;
for (uint8_t i = 0; i < 4; i++) { for (uint8_t i = 0; i < 4; i++) {
@ -14,7 +14,7 @@ TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
} }
//The task is created with the operating system's system call. //The task is created with the operating system's system call.
rtems_status_code status = RTEMS_UNSATISFIED; rtems_status_code status = RTEMS_UNSATISFIED;
if (set_priority >= 0 && set_priority <= 99) { if (set_priority <= 99) {
status = rtems_task_create(osalName, status = rtems_task_create(osalName,
(0xFF - 2 * set_priority), stack_size, (0xFF - 2 * set_priority), stack_size,
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR, RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
@ -31,21 +31,21 @@ TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
} }
} }
TaskBase::~TaskBase() { RTEMSTaskBase::~RTEMSTaskBase() {
rtems_task_delete(id); rtems_task_delete(id);
} }
rtems_id TaskBase::getId() { rtems_id RTEMSTaskBase::getId() {
return this->id; return this->id;
} }
ReturnValue_t TaskBase::sleepFor(uint32_t ms) { ReturnValue_t RTEMSTaskBase::sleepFor(uint32_t ms) {
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms)); rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
return convertReturnCode(status); return convertReturnCode(status);
} }
ReturnValue_t TaskBase::convertReturnCode(rtems_status_code inValue) { ReturnValue_t RTEMSTaskBase::convertReturnCode(rtems_status_code inValue) {
switch (inValue) { switch (inValue) {
case RTEMS_SUCCESSFUL: case RTEMS_SUCCESSFUL:
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -68,7 +68,7 @@ ReturnValue_t TaskBase::convertReturnCode(rtems_status_code inValue) {
} }
ReturnValue_t TaskBase::setAndStartPeriod(rtems_interval period, rtems_id *periodId) { ReturnValue_t RTEMSTaskBase::setAndStartPeriod(rtems_interval period, rtems_id *periodId) {
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd'); rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
rtems_status_code status = rtems_rate_monotonic_create(periodName, periodId); rtems_status_code status = rtems_rate_monotonic_create(periodName, periodId);
if (status == RTEMS_SUCCESSFUL) { if (status == RTEMS_SUCCESSFUL) {
@ -77,7 +77,7 @@ ReturnValue_t TaskBase::setAndStartPeriod(rtems_interval period, rtems_id *perio
return convertReturnCode(status); return convertReturnCode(status);
} }
rtems_status_code TaskBase::restartPeriod(rtems_interval period, rtems_id periodId){ rtems_status_code RTEMSTaskBase::restartPeriod(rtems_interval period, rtems_id periodId){
//This is necessary to avoid a call with period = 0, which does not start the period. //This is necessary to avoid a call with period = 0, which does not start the period.
rtems_status_code status = rtems_rate_monotonic_period(periodId, period + 1); rtems_status_code status = rtems_rate_monotonic_period(periodId, period + 1);
return status; return status;

View File

@ -1,5 +1,5 @@
#ifndef FSFW_OSAL_RTEMS_TASKBASE_H_ #ifndef FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_
#define FSFW_OSAL_RTEMS_TASKBASE_H_ #define FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_
#include "RtemsBasic.h" #include "RtemsBasic.h"
#include "../../tasks/PeriodicTaskIF.h" #include "../../tasks/PeriodicTaskIF.h"
@ -9,7 +9,7 @@
* *
* @details Task creation base class for rtems. * @details Task creation base class for rtems.
*/ */
class TaskBase { class RTEMSTaskBase {
protected: protected:
/** /**
* @brief The class stores the task id it got assigned from the operating system in this attribute. * @brief The class stores the task id it got assigned from the operating system in this attribute.
@ -26,11 +26,11 @@ public:
* @param stack_size The stack size reserved by the operating system for the task. * @param stack_size The stack size reserved by the operating system for the task.
* @param nam The name of the Task, as a null-terminated String. Currently max 4 chars supported (excluding Null-terminator), rest will be truncated * @param nam The name of the Task, as a null-terminated String. Currently max 4 chars supported (excluding Null-terminator), rest will be truncated
*/ */
TaskBase( rtems_task_priority priority, size_t stack_size, const char *name); RTEMSTaskBase( rtems_task_priority priority, size_t stack_size, const char *name);
/** /**
* @brief In the destructor, the created task is deleted. * @brief In the destructor, the created task is deleted.
*/ */
virtual ~TaskBase(); virtual ~RTEMSTaskBase();
/** /**
* @brief This method returns the task id of this class. * @brief This method returns the task id of this class.
*/ */
@ -44,4 +44,4 @@ private:
}; };
#endif /* FSFW_OSAL_RTEMS_TASKBASE_H_ */ #endif /* FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_ */

View File

@ -1,5 +1,6 @@
#include "RtemsBasic.h" #include "RtemsBasic.h"
// TODO: Can this be removed?
//ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) { //ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
// if (inValue == RTEMS_SUCCESSFUL) { // if (inValue == RTEMS_SUCCESSFUL) {

View File

@ -2,12 +2,13 @@
#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_ #define FSFW_OSAL_RTEMS_RTEMSBASIC_H_
#include "../../returnvalues/HasReturnvaluesIF.h" #include "../../returnvalues/HasReturnvaluesIF.h"
#include <rtems.h> #include <rtems.h>
#include <rtems/libio.h> #include <rtems/libio.h>
#include <rtems/error.h> #include <rtems/error.h>
#include <rtems/stackchk.h> #include <rtems/stackchk.h>
#include <stddef.h>
#include <cstddef>
class RtemsBasic { class RtemsBasic {
public: public:

View File

@ -1,8 +1,9 @@
#include "../../tasks/TaskFactory.h" #include "FixedTimeslotTask.h"
#include "MultiObjectTask.h" #include "PeriodicTask.h"
#include "PollingTask.h"
#include "InitTask.h" #include "InitTask.h"
#include "RtemsBasic.h" #include "RtemsBasic.h"
#include "../../tasks/TaskFactory.h"
#include "../../returnvalues/HasReturnvaluesIF.h" #include "../../returnvalues/HasReturnvaluesIF.h"
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why? //TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
@ -15,15 +16,21 @@ TaskFactory* TaskFactory::instance() {
return TaskFactory::factoryInstance; return TaskFactory::factoryInstance;
} }
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) { PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
TaskStackSize stackSize_,TaskPeriod periodInSeconds_,
TaskDeadlineMissedFunction deadLineMissedFunction_) {
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond(); rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
return static_cast<PeriodicTaskIF*>(new MultiObjectTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_)); return static_cast<PeriodicTaskIF*>(new PeriodicTask(name_, taskPriority_, stackSize_,
taskPeriod,deadLineMissedFunction_));
} }
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) { FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,
TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,
TaskDeadlineMissedFunction deadLineMissedFunction_) {
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond(); rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
return static_cast<FixedTimeslotTaskIF*>(new PollingTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_)); return static_cast<FixedTimeslotTaskIF*>(new FixedTimeslotTask(name_, taskPriority_,
stackSize_, taskPeriod, deadLineMissedFunction_));
} }
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {

View File

@ -52,9 +52,8 @@ public:
return id; return id;
} }
static uint32_t getFullParameterId(uint8_t domainId, static uint32_t getFullParameterId(uint8_t domainId, uint8_t uniqueId, uint16_t linearIndex) {
uint8_t uniqueIdentifier, uint16_t linearIndex) { return (domainId << 24) + (uniqueId << 16) + linearIndex;
return (domainId << 24) + (uniqueIdentifier << 16) + linearIndex;
} }
virtual ~HasParametersIF() {} virtual ~HasParametersIF() {}
@ -74,9 +73,9 @@ public:
* matrix indexes. * matrix indexes.
* @return * @return
*/ */
virtual ReturnValue_t getParameter(uint8_t domainId, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
uint16_t uniqueIdentifier, ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
const ParameterWrapper *newValues, uint16_t startAtIndex) = 0; uint16_t startAtIndex) = 0;
}; };
#endif /* FSFW_PARAMETERS_HASPARAMETERSIF_H_ */ #endif /* FSFW_PARAMETERS_HASPARAMETERSIF_H_ */

View File

@ -90,7 +90,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id,
const ParameterWrapper* description) { const ParameterWrapper* description) {
size_t serializedSize = description->getSerializedSize(); size_t serializedSize = description->getSerializedSize();
uint8_t *storeElement; uint8_t *storeElement = nullptr;
store_address_t address; store_address_t address;
ReturnValue_t result = storage->getFreeElement(&address, serializedSize, ReturnValue_t result = storage->getFreeElement(&address, serializedSize,

View File

@ -38,7 +38,7 @@ void ParameterMessage::setParameterLoadCommand(CommandMessage* message,
store_address_t ParameterMessage::getParameterLoadCommand( store_address_t ParameterMessage::getParameterLoadCommand(
const CommandMessage *message, ParameterId_t* parameterId, uint8_t *ptc, const CommandMessage *message, ParameterId_t* parameterId, uint8_t *ptc,
uint8_t *pfc, uint8_t *rows, uint8_t *columns) { uint8_t *pfc, uint8_t *rows, uint8_t *columns) {
*parameterId = message->getParameter2(); *parameterId = message->getParameter();
uint32_t packedParamSettings = message->getParameter3(); uint32_t packedParamSettings = message->getParameter3();
*ptc = packedParamSettings >> 24 & 0xff; *ptc = packedParamSettings >> 24 & 0xff;
*pfc = packedParamSettings >> 16 & 0xff; *pfc = packedParamSettings >> 16 & 0xff;

View File

@ -1,4 +1,6 @@
#include "ParameterWrapper.h" #include "ParameterWrapper.h"
#include <FSFWConfig.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
ParameterWrapper::ParameterWrapper() : ParameterWrapper::ParameterWrapper() :
pointsToStream(false), type(Type::UNKNOWN_TYPE) { pointsToStream(false), type(Type::UNKNOWN_TYPE) {
@ -40,8 +42,8 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size,
return result; return result;
} }
//serialize uses readonlyData, as it is always valid /* serialize uses readonlyData, as it is always valid */
if (readonlyData == NULL) { if (readonlyData == nullptr) {
return NOT_SET; return NOT_SET;
} }
switch (type) { switch (type) {
@ -75,7 +77,7 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size,
result = serializeData<double>(buffer, size, maxSize, streamEndianness); result = serializeData<double>(buffer, size, maxSize, streamEndianness);
break; break;
default: default:
result = UNKNOW_DATATYPE; result = UNKNOWN_DATATYPE;
break; break;
} }
return result; return result;
@ -220,22 +222,48 @@ ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize,
ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from, ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
uint16_t startWritingAtIndex) { uint16_t startWritingAtIndex) {
// TODO: Optional diagnostic output (which can be disabled in FSFWConfig)
// to determined faulty implementations and configuration errors quickly.
if (data == nullptr) { if (data == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Called on read-only variable!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return READONLY; return READONLY;
} }
if (from->readonlyData == nullptr) { if (from->readonlyData == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Source not set!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Source not set!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return SOURCE_NOT_SET; return SOURCE_NOT_SET;
} }
if (type != from->type) { if (type != from->type) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return DATATYPE_MISSMATCH; return DATATYPE_MISSMATCH;
} }
// The smallest allowed value for rows and columns is one. // The smallest allowed value for rows and columns is one.
if(rows == 0 or columns == 0) { if(rows == 0 or columns == 0) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return COLUMN_OR_ROWS_ZERO; return COLUMN_OR_ROWS_ZERO;
} }
@ -289,7 +317,7 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
from->readonlyData, from->rows, from->columns); from->readonlyData, from->rows, from->columns);
break; break;
default: default:
result = UNKNOW_DATATYPE; result = UNKNOWN_DATATYPE;
break; break;
} }
} }

View File

@ -8,14 +8,23 @@
#include <cstddef> #include <cstddef>
/** /**
* @brief * @brief This wrapper encapsulates the access to parameters provided by HasParametersIF.
* @details * @details
* This wrapper is used by the ParameterHelper to interface with the on-board parameters
* exposed by the software via the HasParametersIF. A handle of this wrapper is passed
* to the user which then can be used to set or dump the parameters.
*
* The wrapper provides a set of setter functions. The user should call those setter functions,
* supplying an address to the local parameters. The user can also deserialize or
* serialize the parameter data. Please note that this will also serialize and deserialize
* the parameter information field (4 bytes) containing the ECSS PTC, PFC and rows and columns
* number.
*/ */
class ParameterWrapper: public SerializeIF { class ParameterWrapper: public SerializeIF {
friend class DataPoolParameterWrapper; friend class DataPoolParameterWrapper;
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::PARAMETER_WRAPPER; static const uint8_t INTERFACE_ID = CLASS_ID::PARAMETER_WRAPPER;
static const ReturnValue_t UNKNOW_DATATYPE = MAKE_RETURN_CODE(0x01); static const ReturnValue_t UNKNOWN_DATATYPE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t DATATYPE_MISSMATCH = MAKE_RETURN_CODE(0x02); static const ReturnValue_t DATATYPE_MISSMATCH = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t READONLY = MAKE_RETURN_CODE(0x03); static const ReturnValue_t READONLY = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t TOO_BIG = MAKE_RETURN_CODE(0x04); static const ReturnValue_t TOO_BIG = MAKE_RETURN_CODE(0x04);
@ -26,8 +35,7 @@ public:
ParameterWrapper(); ParameterWrapper();
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data); ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data);
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, ParameterWrapper(Type type, uint8_t rows, uint8_t columns, const void *data);
const void *data);
virtual ~ParameterWrapper(); virtual ~ParameterWrapper();
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
@ -77,11 +85,23 @@ public:
this->pointsToStream = false; this->pointsToStream = false;
} }
/**
* Setter function for scalar non-const entries
* @tparam T
* @param member
*/
template<typename T> template<typename T>
void set(T& member) { void set(T& member) {
this->set(&member, 1, 1); this->set(&member, 1, 1);
} }
/**
* Setter function for scalar const entries.
* TODO: This is confusing, it should not be called set. Maybe we should call all functions
* assign instead?
* @tparam T
* @param readonlyMember
*/
template<typename T> template<typename T>
void set(const T& readonlyMember) { void set(const T& readonlyMember) {
this->set(&readonlyMember, 1, 1); this->set(&readonlyMember, 1, 1);
@ -89,11 +109,15 @@ public:
template<typename T> template<typename T>
void setVector(T& member) { void setVector(T& member) {
this->set(member, sizeof(member)/sizeof(member[0]), 1); /* For a vector entry, the number of rows will be one
(left to right, top to bottom indexing) */
this->set(member, 1, sizeof(member) / sizeof(member[0]));
} }
template<typename T> template<typename T>
void setVector(const T& member) { void setVector(const T& member) {
/* For a vector entry, the number of rows will be one
(left to right, top to bottom indexing) */
this->set(member, 1, sizeof(member) / sizeof(member[0])); this->set(member, 1, sizeof(member) / sizeof(member[0]));
} }
template<typename T> template<typename T>

View File

@ -210,15 +210,15 @@ void Fuse::setDataPoolEntriesInvalid() {
set.commit(); set.commit();
} }
ReturnValue_t Fuse::getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t Fuse::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) { uint16_t startAtIndex) {
ReturnValue_t result = currentLimit.getParameter(domainId, parameterId, ReturnValue_t result = currentLimit.getParameter(domainId, uniqueId,
parameterWrapper, newValues, startAtIndex); parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) { if (result != INVALID_DOMAIN_ID) {
return result; return result;
} }
result = powerMonitor.getParameter(domainId, parameterId, parameterWrapper, result = powerMonitor.getParameter(domainId, uniqueId, parameterWrapper,
newValues, startAtIndex); newValues, startAtIndex);
return result; return result;
} }

View File

@ -62,9 +62,9 @@ public:
ReturnValue_t setHealth(HealthState health); ReturnValue_t setHealth(HealthState health);
HasHealthIF::HealthState getHealth(); HasHealthIF::HealthState getHealth();
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
const ParameterWrapper *newValues, uint16_t startAtIndex); uint16_t startAtIndex);
private: private:
uint8_t oldFuseState; uint8_t oldFuseState;

View File

@ -61,13 +61,13 @@ ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, size_t* size,
return SerializeAdapter::deSerialize(&max, buffer, size, streamEndianness); return SerializeAdapter::deSerialize(&max, buffer, size, streamEndianness);
} }
ReturnValue_t PowerComponent::getParameter(uint8_t domainId, ReturnValue_t PowerComponent::getParameter(uint8_t domainId, uint8_t uniqueId,
uint16_t parameterId, ParameterWrapper* parameterWrapper, ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
const ParameterWrapper* newValues, uint16_t startAtIndex) { uint16_t startAtIndex) {
if (domainId != moduleId) { if (domainId != moduleId) {
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
switch (parameterId) { switch (uniqueId) {
case 0: case 0:
parameterWrapper->set<>(min); parameterWrapper->set<>(min);
break; break;

View File

@ -31,9 +31,9 @@ public:
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override; Endianness streamEndianness) override;
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
const ParameterWrapper *newValues, uint16_t startAtIndex); uint16_t startAtIndex);
private: private:
const object_id_t deviceObjectId = objects::NO_OBJECT; const object_id_t deviceObjectId = objects::NO_OBJECT;
const uint8_t switchId1; const uint8_t switchId1;

View File

@ -119,15 +119,15 @@ HasHealthIF::HealthState PowerSensor::getHealth() {
return healthHelper.getHealth(); return healthHelper.getHealth();
} }
ReturnValue_t PowerSensor::getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t PowerSensor::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) { uint16_t startAtIndex) {
ReturnValue_t result = currentLimit.getParameter(domainId, parameterId, ReturnValue_t result = currentLimit.getParameter(domainId, uniqueId,
parameterWrapper, newValues, startAtIndex); parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) { if (result != INVALID_DOMAIN_ID) {
return result; return result;
} }
result = voltageLimit.getParameter(domainId, parameterId, parameterWrapper, result = voltageLimit.getParameter(domainId, uniqueId, parameterWrapper,
newValues, startAtIndex); newValues, startAtIndex);
return result; return result;
} }

View File

@ -48,7 +48,7 @@ public:
float getPower(); float getPower();
ReturnValue_t setHealth(HealthState health); ReturnValue_t setHealth(HealthState health);
HasHealthIF::HealthState getHealth(); HasHealthIF::HealthState getHealth();
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); const ParameterWrapper *newValues, uint16_t startAtIndex);
private: private:

View File

@ -1,12 +1,12 @@
target_sources(${LIB_FSFW_NAME} target_sources(${LIB_FSFW_NAME} PRIVATE
PRIVATE
CService200ModeCommanding.cpp
CService201HealthCommanding.cpp
Service17Test.cpp
Service1TelecommandVerification.cpp Service1TelecommandVerification.cpp
Service2DeviceAccess.cpp Service2DeviceAccess.cpp
Service3Housekeeping.cpp Service3Housekeeping.cpp
Service5EventReporting.cpp Service5EventReporting.cpp
Service8FunctionManagement.cpp Service8FunctionManagement.cpp
Service9TimeManagement.cpp Service9TimeManagement.cpp
Service17Test.cpp
Service20ParameterManagement.cpp
CService200ModeCommanding.cpp
CService201HealthCommanding.cpp
) )

View File

@ -0,0 +1,186 @@
#include "Service20ParameterManagement.h"
#include "servicepackets/Service20Packets.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/parameters/HasParametersIF.h>
#include <fsfw/parameters/ParameterMessage.h>
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
#include <tmtc/pusIds.h>
Service20ParameterManagement::Service20ParameterManagement(object_id_t objectId, uint16_t apid,
uint8_t serviceId, uint8_t numberOfParallelCommands, uint16_t commandTimeoutSeconds) :
CommandingServiceBase(objectId, apid, serviceId,
numberOfParallelCommands,commandTimeoutSeconds) {}
Service20ParameterManagement::~Service20ParameterManagement() {}
ReturnValue_t Service20ParameterManagement::isValidSubservice(
uint8_t subservice) {
switch(static_cast<Subservice>(subservice)) {
case Subservice::PARAMETER_LOAD:
case Subservice::PARAMETER_DUMP:
return HasReturnvaluesIF::RETURN_OK;
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Invalid Subservice for Service 20" << std::endl;
#else
sif::printError("Invalid Subservice for Service 20\n");
#endif
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}
}
ReturnValue_t Service20ParameterManagement::getMessageQueueAndObject(
uint8_t subservice, const uint8_t* tcData, size_t tcDataLen,
MessageQueueId_t* id, object_id_t* objectId) {
ReturnValue_t result = checkAndAcquireTargetID(objectId,tcData,tcDataLen);
if(result != RETURN_OK) {
return result;
}
return checkInterfaceAndAcquireMessageQueue(id,objectId);
}
ReturnValue_t Service20ParameterManagement::checkAndAcquireTargetID(
object_id_t* objectIdToSet, const uint8_t* tcData, size_t tcDataLen) {
if(SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen,
SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Service20ParameterManagement::checkAndAcquireTargetID: "
<< "Invalid data." << std::endl;
#else
sif::printError("Service20ParameterManagement::"
"checkAndAcquireTargetID: Invalid data.\n");
#endif
return CommandingServiceBase::INVALID_TC;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue(
MessageQueueId_t* messageQueueToSet, object_id_t* objectId) {
// check ReceivesParameterMessagesIF property of target
ReceivesParameterMessagesIF* possibleTarget =
objectManager->get<ReceivesParameterMessagesIF>(*objectId);
if(possibleTarget == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire"
<<"MessageQueue: Can't access object" << std::endl;
sif::error << "Object ID: " << std::hex << objectId << std::dec << std::endl;
sif::error << "Make sure it implements ReceivesParameterMessagesIF!" << std::endl;
#else
sif::printError("Service20ParameterManagement::checkInterfaceAndAcquire"
"MessageQueue: Can't access object\n");
sif::printError("Object ID: 0x%08x\n", objectId);
sif::printError("Make sure it implements "
"ReceivesParameterMessagesIF!\n");
#endif
return CommandingServiceBase::INVALID_OBJECT;
}
*messageQueueToSet = possibleTarget->getCommandQueue();
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Service20ParameterManagement::prepareCommand(
CommandMessage* message, uint8_t subservice, const uint8_t* tcData,
size_t tcDataLen, uint32_t* state, object_id_t objectId) {
switch(static_cast<Subservice>(subservice)){
case Subservice::PARAMETER_DUMP: {
return prepareDumpCommand(message, tcData, tcDataLen);
}
break;
case Subservice::PARAMETER_LOAD: {
return prepareLoadCommand(message, tcData, tcDataLen);
}
break;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t Service20ParameterManagement::prepareDumpCommand(
CommandMessage* message, const uint8_t* tcData, size_t tcDataLen) {
/* the first part is the objectId, but we have extracted that earlier
and only need the parameterId */
tcData += sizeof(object_id_t);
tcDataLen -= sizeof(object_id_t);
ParameterId_t parameterId;
if(SerializeAdapter::deSerialize(&parameterId, &tcData, &tcDataLen,
SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) {
return CommandingServiceBase::INVALID_TC;
}
/* The length should have been decremented to 0 by this point */
if(tcDataLen != 0) {
return CommandingServiceBase::INVALID_TC;
}
ParameterMessage::setParameterDumpCommand(message, parameterId);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Service20ParameterManagement::prepareLoadCommand(
CommandMessage* message, const uint8_t* tcData, size_t tcDataLen) {
if(tcDataLen < sizeof(object_id_t) + sizeof(ParameterId_t) +
sizeof(uint32_t)) {
return CommandingServiceBase::INVALID_TC;
}
uint8_t* storePointer = nullptr;
store_address_t storeAddress;
size_t parameterDataLen = tcDataLen - sizeof(object_id_t) - sizeof(ParameterId_t) -
sizeof(uint32_t);
ReturnValue_t result = IPCStore->getFreeElement(&storeAddress,
parameterDataLen, &storePointer);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
/* Following format is expected: The first 4 bytes in the TC data are the 4 byte
parameter ID (ParameterId_t). The second 4 bytes are the parameter information field,
containing the following 1 byte fields:
1. ECSS PTC field
2. ECSS PFC field
3. Number of rows
4. Number of columns */
ParameterLoadCommand command(storePointer, parameterDataLen);
result = command.deSerialize(&tcData, &tcDataLen,
SerializeIF::Endianness::BIG);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
ParameterMessage::setParameterLoadCommand(message, command.getParameterId(), storeAddress,
command.getPtc(), command.getPfc(), command.getRows(), command.getColumns());
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Service20ParameterManagement::handleReply(
const CommandMessage* reply, Command_t previousCommand, uint32_t* state,
CommandMessage* optionalNextCommand, object_id_t objectId,
bool* isStep) {
Command_t replyId = reply->getCommand();
switch(replyId) {
case ParameterMessage::REPLY_PARAMETER_DUMP: {
ConstAccessorPair parameterData = IPCStore->getData(
ParameterMessage::getStoreId(reply));
if(parameterData.first != HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_FAILED;
}
ParameterId_t parameterId = ParameterMessage::getParameterId(reply);
ParameterDumpReply parameterReply(objectId, parameterId,
parameterData.second.data(), parameterData.second.size());
sendTmPacket(static_cast<uint8_t>(
Subservice::PARAMETER_DUMP_REPLY), &parameterReply);
return HasReturnvaluesIF::RETURN_OK;
}
default:
return CommandingServiceBase::INVALID_REPLY;
}
}

View File

@ -0,0 +1,60 @@
#ifndef FSFW_PUS_SERVICE20PARAMETERMANAGEMENT_H_
#define FSFW_PUS_SERVICE20PARAMETERMANAGEMENT_H_
#include <fsfw/tmtcservices/CommandingServiceBase.h>
/**
* @brief PUS Service 20 Parameter Service implementation
* @details
* This service handles PUS service requests related to parameter management and forwards
* them to the internal software bus.
* @author J. Gerhards
*
*/
class Service20ParameterManagement : public CommandingServiceBase
{
public:
Service20ParameterManagement(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint8_t numberOfParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
virtual ~Service20ParameterManagement();
static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4;
static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60;
protected:
/* CommandingServiceBase (CSB) abstract functions. See CSB documentation. */
ReturnValue_t isValidSubservice(uint8_t subservice) override;
ReturnValue_t getMessageQueueAndObject(uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id,
object_id_t *objectId) override;
ReturnValue_t prepareCommand(CommandMessage* message, uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen, uint32_t *state,
object_id_t objectId) override;
ReturnValue_t handleReply(const CommandMessage* reply,
Command_t previousCommand, uint32_t *state,
CommandMessage* optionalNextCommand, object_id_t objectId,
bool *isStep) override;
private:
ReturnValue_t checkAndAcquireTargetID(object_id_t* objectIdToSet,
const uint8_t* tcData, size_t tcDataLen);
ReturnValue_t checkInterfaceAndAcquireMessageQueue(
MessageQueueId_t* messageQueueToSet, object_id_t* objectId);
ReturnValue_t prepareDirectCommand(CommandMessage* message,
const uint8_t* tcData, size_t tcDataLen);
ReturnValue_t prepareDumpCommand(CommandMessage* message,
const uint8_t* tcData, size_t tcDataLen);
ReturnValue_t prepareLoadCommand(CommandMessage* message,
const uint8_t* tcData, size_t tcDataLen);
enum class Subservice {
PARAMETER_LOAD = 128, //!< [EXPORT] : Load a Parameter
PARAMETER_DUMP = 129, //!< [EXPORT] : Dump a Parameter
PARAMETER_DUMP_REPLY = 130, //!< [EXPORT] : Dump a Parameter
};
};
#endif /* FSFW_PUS_SERVICE20PARAMETERMANAGEMENT_H_ */

View File

@ -104,6 +104,8 @@ ReturnValue_t Service8FunctionManagement::handleReply(
break; break;
} }
case ActionMessage::DATA_REPLY: { case ActionMessage::DATA_REPLY: {
/* Multiple data replies are possible, so declare data reply as step */
*isStep = true;
result = handleDataReply(reply, objectId, actionId); result = handleDataReply(reply, objectId, actionId);
break; break;
} }

View File

@ -0,0 +1,142 @@
#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE20PACKETS_H_
#define FSFW_PUS_SERVICEPACKETS_SERVICE20PACKETS_H_
#include <FSFWConfig.h>
#include <fsfw/parameters/HasParametersIF.h>
#include <fsfw/serialize/SerialBufferAdapter.h>
#include <fsfw/serialize/SerializeElement.h>
#include <fsfw/serialize/SerialLinkedListAdapter.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
/**
* @brief This class encapsulates the packets sent to the PUS service 20 or sent by the
* PUS service 20
* @details
* This command can be used to handle both load and dump commands as well.
* @author
*/
class ParameterCommand: public SerialLinkedListAdapter<SerializeIF> { //!< [EXPORT] : [SUBSERVICE] 128, 129, 130
public:
/**
* This constructor is used for load replies. The data is expected in the correct formast
* in the store pointer.
* @param storePointer
* @param parameterDataLen
*/
ParameterCommand(uint8_t* storePointer, size_t parameterDataLen):
parameterBuffer(storePointer, parameterDataLen) {
#if FSFW_VERBOSE_LEVEL >= 1
if(parameterDataLen < sizeof(object_id_t) + sizeof(ParameterId_t) + 4) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterCommand: Parameter data length is less than 12!"
<< std::endl;
#else
sif::printWarning("ParameterCommand: Parameter data length is less than 12!\n");
#endif
}
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
setLoadLinks();
}
/**
* This constructor is used for dump replies. It is assumed the 4 byte parameter
* information field is located inside the parameter buffer.
* @param objectId
* @param parameterId
* @param parameterBuffer
* @param parameterBufferSize
*/
ParameterCommand(object_id_t objectId, ParameterId_t parameterId,
const uint8_t* parameterBuffer, size_t parameterBufferSize):
objectId(objectId), parameterId(parameterId),
parameterBuffer(parameterBuffer, parameterBufferSize) {
setDumpReplyLinks();
}
ParameterId_t getParameterId() const {
return parameterId.entry;
}
const uint8_t* getParameterBuffer() {
return parameterBuffer.entry.getConstBuffer();
}
size_t getParameterBufferLen() const {
return parameterBuffer.getSerializedSize();
}
uint8_t getDomainId() const {
return (parameterId.entry >> 24) & 0xff;
}
uint8_t getUniqueId() const {
return (parameterId.entry >> 16) & 0xff;
}
uint16_t getLinearIndex() const {
return parameterId.entry & 0xffff;
}
uint8_t getPtc() const {
return ccsdsType.entry >> 8 & 0xff;
}
uint8_t getPfc() const {
return ccsdsType.entry & 0xff;
}
uint8_t getRows() const {
return rows.entry;
}
uint8_t getColumns() const {
return columns.entry;
}
private:
void setLoadLinks() {
setStart(&objectId);
objectId.setNext(&parameterId);
parameterId.setNext(&ccsdsType);
ccsdsType.setNext(&rows);
rows.setNext(&columns);
columns.setNext(&parameterBuffer);
}
void setDumpReplyLinks() {
/* For a dump reply, the parameter information is contained in the parameter buffer
with the actual parameters */
setStart(&objectId);
objectId.setNext(&parameterId);
parameterId.setNext(&parameterBuffer);
}
void setDumpRequestLinks() {
setStart(&objectId);
objectId.setNext(&parameterId);
}
SerializeElement<object_id_t> objectId = 0;
SerializeElement<ParameterId_t> parameterId = 0;
//! [EXPORT] : [COMMENT] Type consisting of one byte PTC and one byte PFC.
SerializeElement<uint16_t> ccsdsType = 0;
SerializeElement<uint8_t> rows = 0;
SerializeElement<uint8_t> columns = 0;
SerializeElement<SerialBufferAdapter<uint8_t>> parameterBuffer;
};
class ParameterLoadCommand: public ParameterCommand {
public:
ParameterLoadCommand(uint8_t* parameterPacket, size_t parameterDataLen):
ParameterCommand(parameterPacket, parameterDataLen) {}
};
class ParameterDumpReply: public ParameterCommand {
public:
ParameterDumpReply(object_id_t objectId, ParameterId_t parameterId,
const uint8_t* parameterBuffer, size_t parameterBufferSize):
ParameterCommand(objectId, parameterId, parameterBuffer, parameterBufferSize) {}
};
#endif /* FSFW_PUS_SERVICEPACKETS_SERVICE20PACKETS_H_ */

View File

@ -29,7 +29,7 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage,
#if FSFW_COLORED_OUTPUT == 1 #if FSFW_COLORED_OUTPUT == 1
if(setMessage.find("DEBUG") != std::string::npos) { if(setMessage.find("DEBUG") != std::string::npos) {
colorPrefix = sif::ANSI_COLOR_MAGENTA; colorPrefix = sif::ANSI_COLOR_CYAN;
} }
else if(setMessage.find("INFO") != std::string::npos) { else if(setMessage.find("INFO") != std::string::npos) {
colorPrefix = sif::ANSI_COLOR_GREEN; colorPrefix = sif::ANSI_COLOR_GREEN;

View File

@ -45,7 +45,7 @@ void fsfwPrint(sif::PrintLevel printType, const char* fmt, va_list arg) {
len += sprintf(bufferPosition, sif::ANSI_COLOR_GREEN); len += sprintf(bufferPosition, sif::ANSI_COLOR_GREEN);
} }
else if(printType == sif::PrintLevel::DEBUG_LEVEL) { else if(printType == sif::PrintLevel::DEBUG_LEVEL) {
len += sprintf(bufferPosition, sif::ANSI_COLOR_MAGENTA); len += sprintf(bufferPosition, sif::ANSI_COLOR_CYAN);
} }
else if(printType == sif::PrintLevel::WARNING_LEVEL) { else if(printType == sif::PrintLevel::WARNING_LEVEL) {
len += sprintf(bufferPosition, sif::ANSI_COLOR_YELLOW); len += sprintf(bufferPosition, sif::ANSI_COLOR_YELLOW);

View File

@ -39,6 +39,11 @@ public:
*/ */
std::string* getPreamble(); std::string* getPreamble();
/**
* Can be used to determine if the stream was configured to add CR characters in addition
* to newline characters.
* @return
*/
bool crAdditionEnabled() const; bool crAdditionEnabled() const;
protected: protected:

View File

@ -5,15 +5,15 @@
LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig, LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig,
bool registered, bool spillsToHigherPools): bool registered, bool spillsToHigherPools):
SystemObject(setObjectId, registered), SystemObject(setObjectId, registered),
NUMBER_OF_POOLS(poolConfig.size()), NUMBER_OF_SUBPOOLS(poolConfig.size()),
spillsToHigherPools(spillsToHigherPools) { spillsToHigherPools(spillsToHigherPools) {
if(NUMBER_OF_POOLS == 0) { if(NUMBER_OF_SUBPOOLS == 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPool::LocalPool: Passed pool configuration is " sif::error << "LocalPool::LocalPool: Passed pool configuration is "
<< " invalid!" << std::endl; << " invalid!" << std::endl;
#endif #endif
} }
max_pools_t index = 0; max_subpools_t index = 0;
for (const auto& currentPoolConfig: poolConfig) { for (const auto& currentPoolConfig: poolConfig) {
this->numberOfElements[index] = currentPoolConfig.first; this->numberOfElements[index] = currentPoolConfig.first;
this->elementSizes[index] = currentPoolConfig.second; this->elementSizes[index] = currentPoolConfig.second;
@ -98,7 +98,7 @@ ReturnValue_t LocalPool::modifyData(store_address_t storeId,
ReturnValue_t LocalPool::modifyData(store_address_t storeId, ReturnValue_t LocalPool::modifyData(store_address_t storeId,
uint8_t **packetPtr, size_t *size) { uint8_t **packetPtr, size_t *size) {
ReturnValue_t status = RETURN_FAILED; ReturnValue_t status = RETURN_FAILED;
if (storeId.poolIndex >= NUMBER_OF_POOLS) { if (storeId.poolIndex >= NUMBER_OF_SUBPOOLS) {
return ILLEGAL_STORAGE_ID; return ILLEGAL_STORAGE_ID;
} }
if ((storeId.packetIndex >= numberOfElements[storeId.poolIndex])) { if ((storeId.packetIndex >= numberOfElements[storeId.poolIndex])) {
@ -127,7 +127,7 @@ ReturnValue_t LocalPool::deleteData(store_address_t storeId) {
#endif #endif
ReturnValue_t status = RETURN_OK; ReturnValue_t status = RETURN_OK;
size_type pageSize = getPageSize(storeId.poolIndex); size_type pageSize = getSubpoolElementSize(storeId.poolIndex);
if ((pageSize != 0) and if ((pageSize != 0) and
(storeId.packetIndex < numberOfElements[storeId.poolIndex])) { (storeId.packetIndex < numberOfElements[storeId.poolIndex])) {
uint16_t packetPosition = getRawPosition(storeId); uint16_t packetPosition = getRawPosition(storeId);
@ -151,7 +151,7 @@ ReturnValue_t LocalPool::deleteData(uint8_t *ptr, size_t size,
store_address_t *storeId) { store_address_t *storeId) {
store_address_t localId; store_address_t localId;
ReturnValue_t result = ILLEGAL_ADDRESS; ReturnValue_t result = ILLEGAL_ADDRESS;
for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { for (uint16_t n = 0; n < NUMBER_OF_SUBPOOLS; n++) {
//Not sure if new allocates all stores in order. so better be careful. //Not sure if new allocates all stores in order. so better be careful.
if ((store[n].data() <= ptr) and if ((store[n].data() <= ptr) and
(&store[n][numberOfElements[n]*elementSizes[n]] > ptr)) { (&store[n][numberOfElements[n]*elementSizes[n]] > ptr)) {
@ -192,7 +192,7 @@ ReturnValue_t LocalPool::initialize() {
} }
//Check if any pool size is large than the maximum allowed. //Check if any pool size is large than the maximum allowed.
for (uint8_t count = 0; count < NUMBER_OF_POOLS; count++) { for (uint8_t count = 0; count < NUMBER_OF_SUBPOOLS; count++) {
if (elementSizes[count] >= STORAGE_FREE) { if (elementSizes[count] >= STORAGE_FREE) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPool::initialize: Pool is too large! " sif::error << "LocalPool::initialize: Pool is too large! "
@ -217,7 +217,7 @@ void LocalPool::clearStore() {
ReturnValue_t LocalPool::reserveSpace(const size_t size, ReturnValue_t LocalPool::reserveSpace(const size_t size,
store_address_t *storeId, bool ignoreFault) { store_address_t *storeId, bool ignoreFault) {
ReturnValue_t status = getPoolIndex(size, &storeId->poolIndex); ReturnValue_t status = getSubPoolIndex(size, &storeId->poolIndex);
if (status != RETURN_OK) { if (status != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPool( " << std::hex << getObjectId() << std::dec sif::error << "LocalPool( " << std::hex << getObjectId() << std::dec
@ -227,7 +227,7 @@ ReturnValue_t LocalPool::reserveSpace(const size_t size,
} }
status = findEmpty(storeId->poolIndex, &storeId->packetIndex); status = findEmpty(storeId->poolIndex, &storeId->packetIndex);
while (status != RETURN_OK && spillsToHigherPools) { while (status != RETURN_OK && spillsToHigherPools) {
status = getPoolIndex(size, &storeId->poolIndex, storeId->poolIndex + 1); status = getSubPoolIndex(size, &storeId->poolIndex, storeId->poolIndex + 1);
if (status != RETURN_OK) { if (status != RETURN_OK) {
//We don't find any fitting pool anymore. //We don't find any fitting pool anymore.
break; break;
@ -263,9 +263,9 @@ void LocalPool::write(store_address_t storeId, const uint8_t *data,
sizeLists[storeId.poolIndex][storeId.packetIndex] = size; sizeLists[storeId.poolIndex][storeId.packetIndex] = size;
} }
LocalPool::size_type LocalPool::getPageSize(max_pools_t poolIndex) { LocalPool::size_type LocalPool::getSubpoolElementSize(max_subpools_t subpoolIndex) {
if (poolIndex < NUMBER_OF_POOLS) { if (subpoolIndex < NUMBER_OF_SUBPOOLS) {
return elementSizes[poolIndex]; return elementSizes[subpoolIndex];
} }
else { else {
return 0; return 0;
@ -276,9 +276,9 @@ void LocalPool::setToSpillToHigherPools(bool enable) {
this->spillsToHigherPools = enable; this->spillsToHigherPools = enable;
} }
ReturnValue_t LocalPool::getPoolIndex(size_t packetSize, uint16_t *poolIndex, ReturnValue_t LocalPool::getSubPoolIndex(size_t packetSize, uint16_t *subpoolIndex,
uint16_t startAtIndex) { uint16_t startAtIndex) {
for (uint16_t n = startAtIndex; n < NUMBER_OF_POOLS; n++) { for (uint16_t n = startAtIndex; n < NUMBER_OF_SUBPOOLS; n++) {
#if FSFW_VERBOSE_PRINTOUT == 2 #if FSFW_VERBOSE_PRINTOUT == 2
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "LocalPool " << getObjectId() << "::getPoolIndex: Pool: " sif::debug << "LocalPool " << getObjectId() << "::getPoolIndex: Pool: "
@ -286,7 +286,7 @@ ReturnValue_t LocalPool::getPoolIndex(size_t packetSize, uint16_t *poolIndex,
#endif #endif
#endif #endif
if (elementSizes[n] >= packetSize) { if (elementSizes[n] >= packetSize) {
*poolIndex = n; *subpoolIndex = n;
return RETURN_OK; return RETURN_OK;
} }
} }
@ -313,7 +313,7 @@ ReturnValue_t LocalPool::findEmpty(n_pool_elem_t poolIndex, uint16_t *element) {
size_t LocalPool::getTotalSize(size_t* additionalSize) { size_t LocalPool::getTotalSize(size_t* additionalSize) {
size_t totalSize = 0; size_t totalSize = 0;
size_t sizesSize = 0; size_t sizesSize = 0;
for(uint8_t idx = 0; idx < NUMBER_OF_POOLS; idx ++) { for(uint8_t idx = 0; idx < NUMBER_OF_SUBPOOLS; idx ++) {
totalSize += elementSizes[idx] * numberOfElements[idx]; totalSize += elementSizes[idx] * numberOfElements[idx];
sizesSize += numberOfElements[idx] * sizeof(size_type); sizesSize += numberOfElements[idx] * sizeof(size_type);
} }
@ -331,7 +331,7 @@ void LocalPool::getFillCount(uint8_t *buffer, uint8_t *bytesWritten) {
uint16_t reservedHits = 0; uint16_t reservedHits = 0;
uint8_t idx = 0; uint8_t idx = 0;
uint16_t sum = 0; uint16_t sum = 0;
for(; idx < NUMBER_OF_POOLS; idx ++) { for(; idx < NUMBER_OF_SUBPOOLS; idx ++) {
for(const auto& size: sizeLists[idx]) { for(const auto& size: sizeLists[idx]) {
if(size != STORAGE_FREE) { if(size != STORAGE_FREE) {
reservedHits++; reservedHits++;
@ -343,21 +343,25 @@ void LocalPool::getFillCount(uint8_t *buffer, uint8_t *bytesWritten) {
sum += buffer[idx]; sum += buffer[idx];
reservedHits = 0; reservedHits = 0;
} }
buffer[idx] = sum / NUMBER_OF_POOLS; buffer[idx] = sum / NUMBER_OF_SUBPOOLS;
*bytesWritten += 1; *bytesWritten += 1;
} }
void LocalPool::clearPage(max_pools_t pageIndex) { void LocalPool::clearSubPool(max_subpools_t subpoolIndex) {
if(pageIndex >= NUMBER_OF_POOLS) { if(subpoolIndex >= NUMBER_OF_SUBPOOLS) {
return; return;
} }
// Mark the storage as free // Mark the storage as free
for(auto& size: sizeLists[pageIndex]) { for(auto& size: sizeLists[subpoolIndex]) {
size = STORAGE_FREE; size = STORAGE_FREE;
} }
// Set all the page content to 0. // Set all the page content to 0.
std::memset(store[pageIndex].data(), 0, elementSizes[pageIndex]); std::memset(store[subpoolIndex].data(), 0, elementSizes[subpoolIndex]);
}
LocalPool::max_subpools_t LocalPool::getNumberOfSubPools() const {
return NUMBER_OF_SUBPOOLS;
} }

View File

@ -60,15 +60,6 @@ public:
}; };
using LocalPoolConfig = std::multiset<LocalPoolCfgPair, LocalPoolConfigCmp>; using LocalPoolConfig = std::multiset<LocalPoolCfgPair, LocalPoolConfigCmp>;
/**
* @brief This definition generally sets the number of
* different sized pools. It is derived from the number of pairs
* inside the LocalPoolConfig set on object creation.
* @details
* This must be less than the maximum number of pools (currently 0xff).
*/
const max_pools_t NUMBER_OF_POOLS;
/** /**
* @brief This is the default constructor for a pool manager instance. * @brief This is the default constructor for a pool manager instance.
* @details * @details
@ -143,9 +134,15 @@ public:
void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) override; void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) override;
void clearStore() override; void clearStore() override;
void clearPage(max_pools_t pageIndex) override; void clearSubPool(max_subpools_t poolIndex) override;
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
/**
* Get number sub pools. Each pool has pages with a specific bucket size.
* @return
*/
max_subpools_t getNumberOfSubPools() const override;
protected: protected:
/** /**
* With this helper method, a free element of @c size is reserved. * With this helper method, a free element of @c size is reserved.
@ -158,6 +155,16 @@ protected:
store_address_t* address, bool ignoreFault); store_address_t* address, bool ignoreFault);
private: private:
/**
* @brief This definition generally sets the number of
* different sized pools. It is derived from the number of pairs
* inside the LocalPoolConfig set on object creation.
* @details
* This must be less than the maximum number of pools (currently 0xff).
*/
const max_subpools_t NUMBER_OF_SUBPOOLS;
/** /**
* Indicates that this element is free. * Indicates that this element is free.
* This value limits the maximum size of a pool. * This value limits the maximum size of a pool.
@ -170,20 +177,20 @@ private:
* must be set in ascending order on construction. * must be set in ascending order on construction.
*/ */
std::vector<size_type> elementSizes = std::vector<size_type> elementSizes =
std::vector<size_type>(NUMBER_OF_POOLS); std::vector<size_type>(NUMBER_OF_SUBPOOLS);
/** /**
* @brief n_elements stores the number of elements per pool. * @brief n_elements stores the number of elements per pool.
* @details These numbers are maintained for internal pool management. * @details These numbers are maintained for internal pool management.
*/ */
std::vector<uint16_t> numberOfElements = std::vector<uint16_t> numberOfElements =
std::vector<uint16_t>(NUMBER_OF_POOLS); std::vector<uint16_t>(NUMBER_OF_SUBPOOLS);
/** /**
* @brief store represents the actual memory pool. * @brief store represents the actual memory pool.
* @details It is an array of pointers to memory, which was allocated with * @details It is an array of pointers to memory, which was allocated with
* a @c new call on construction. * a @c new call on construction.
*/ */
std::vector<std::vector<uint8_t>> store = std::vector<std::vector<uint8_t>> store =
std::vector<std::vector<uint8_t>>(NUMBER_OF_POOLS); std::vector<std::vector<uint8_t>>(NUMBER_OF_SUBPOOLS);
/** /**
* @brief The size_list attribute stores the size values of every pool element. * @brief The size_list attribute stores the size values of every pool element.
@ -191,7 +198,7 @@ private:
* is also dynamically allocated there. * is also dynamically allocated there.
*/ */
std::vector<std::vector<size_type>> sizeLists = std::vector<std::vector<size_type>> sizeLists =
std::vector<std::vector<size_type>>(NUMBER_OF_POOLS); std::vector<std::vector<size_type>>(NUMBER_OF_SUBPOOLS);
//! A variable to determine whether higher n pools are used if //! A variable to determine whether higher n pools are used if
//! the store is full. //! the store is full.
@ -210,7 +217,7 @@ private:
* @param pool_index The pool in which to look. * @param pool_index The pool in which to look.
* @return Returns the size of an element or 0. * @return Returns the size of an element or 0.
*/ */
size_type getPageSize(max_pools_t poolIndex); size_type getSubpoolElementSize(max_subpools_t subpoolIndex);
/** /**
* @brief This helper method looks up a fitting pool for a given size. * @brief This helper method looks up a fitting pool for a given size.
@ -221,7 +228,7 @@ private:
* @return - @c RETURN_OK on success, * @return - @c RETURN_OK on success,
* - @c DATA_TOO_LARGE otherwise. * - @c DATA_TOO_LARGE otherwise.
*/ */
ReturnValue_t getPoolIndex(size_t packetSize, uint16_t* poolIndex, ReturnValue_t getSubPoolIndex(size_t packetSize, uint16_t* subpoolIndex,
uint16_t startAtIndex = 0); uint16_t startAtIndex = 0);
/** /**
* @brief This helper method calculates the true array position in store * @brief This helper method calculates the true array position in store

View File

@ -29,7 +29,7 @@ using ConstAccessorPair = std::pair<ReturnValue_t, ConstStorageAccessor>;
class StorageManagerIF : public HasReturnvaluesIF { class StorageManagerIF : public HasReturnvaluesIF {
public: public:
using size_type = size_t; using size_type = size_t;
using max_pools_t = uint8_t; using max_subpools_t = uint8_t;
static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface.
static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store.
@ -149,10 +149,10 @@ public:
virtual ReturnValue_t modifyData(store_address_t packet_id, virtual ReturnValue_t modifyData(store_address_t packet_id,
uint8_t** packet_ptr, size_t* size) = 0; uint8_t** packet_ptr, size_t* size) = 0;
/** /**
* This method reserves an element of \c size. * This method reserves an element of @c size.
* *
* It returns the packet id of this element as well as a direct pointer to the * It returns the packet id of this element as well as a direct pointer to the
* data of the element. It must be assured that exactly \c size data is * data of the element. It must be assured that exactly @c size data is
* written to p_data! * written to p_data!
* @param storageId A pointer to the storageId to retrieve. * @param storageId A pointer to the storageId to retrieve.
* @param size The size of the space to be reserved. * @param size The size of the space to be reserved.
@ -171,20 +171,29 @@ public:
virtual void clearStore() = 0; virtual void clearStore() = 0;
/** /**
* Clears a page in the store. Use with care! * Clears a pool in the store with the given pool index. Use with care!
* @param pageIndex * @param pageIndex
*/ */
virtual void clearPage(uint8_t pageIndex) = 0; virtual void clearSubPool(uint8_t poolIndex) = 0;
/** /**
* Get the fill count of the pool. The exact form will be implementation * Get the fill count of the pool. Each character inside the provided
* dependant. * buffer will be assigned to a rounded percentage fill count for each
* page. The last written byte (at the index bytesWritten - 1)
* will contain the total fill count of the pool as a mean of the
* percentages of single pages.
* @param buffer * @param buffer
* @param bytesWritten * @param maxSize
*/ */
virtual void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) = 0; virtual void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) = 0;
virtual size_t getTotalSize(size_t* additionalSize) = 0; virtual size_t getTotalSize(size_t* additionalSize) = 0;
/**
* Get number of pools.
* @return
*/
virtual max_subpools_t getNumberOfSubPools() const = 0;
}; };
#endif /* FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ */ #endif /* FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ */

View File

@ -290,13 +290,13 @@ void Heater::handleQueue() {
} }
} }
ReturnValue_t Heater::getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t Heater::getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) { uint16_t startAtIndex) {
if (domainId != DOMAIN_ID_BASE) { if (domainId != DOMAIN_ID_BASE) {
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
switch (parameterId) { switch (uniqueId) {
case 0: case 0:
parameterWrapper->set(heaterOnCountdown.timeout); parameterWrapper->set(heaterOnCountdown.timeout);
break; break;

View File

@ -34,7 +34,7 @@ public:
MessageQueueId_t getCommandQueue() const; MessageQueueId_t getCommandQueue() const;
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); const ParameterWrapper *newValues, uint16_t startAtIndex);

View File

@ -183,10 +183,10 @@ public:
static const uint8_t DOMAIN_ID_SENSOR = 1; static const uint8_t DOMAIN_ID_SENSOR = 1;
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) { const ParameterWrapper *newValues, uint16_t startAtIndex) {
ReturnValue_t result = sensorMonitor.getParameter(domainId, parameterId, ReturnValue_t result = sensorMonitor.getParameter(domainId, uniqueId,
parameterWrapper, newValues, startAtIndex); parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) { if (result != INVALID_DOMAIN_ID) {
return result; return result;
@ -194,7 +194,7 @@ public:
if (domainId != this->DOMAIN_ID_BASE) { if (domainId != this->DOMAIN_ID_BASE) {
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
switch (parameterId) { switch (uniqueId) {
case ADDRESS_A: case ADDRESS_A:
parameterWrapper->set(parameters.a); parameterWrapper->set(parameters.a);
break; break;

View File

@ -148,14 +148,14 @@ ThermalComponentIF::State ThermalComponent::getIgnoredState(int8_t state) {
} }
ReturnValue_t ThermalComponent::getParameter(uint8_t domainId, ReturnValue_t ThermalComponent::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) { const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t result = ThermalComponentCore::getParameter(domainId, parameterId, ReturnValue_t result = ThermalComponentCore::getParameter(domainId, uniqueId,
parameterWrapper, newValues, startAtIndex); parameterWrapper, newValues, startAtIndex);
if (result != INVALID_IDENTIFIER_ID) { if (result != INVALID_IDENTIFIER_ID) {
return result; return result;
} }
switch (parameterId) { switch (uniqueId) {
case 12: case 12:
parameterWrapper->set(nopParameters.lowerNopLimit); parameterWrapper->set(nopParameters.lowerNopLimit);
break; break;

View File

@ -58,7 +58,7 @@ public:
virtual ReturnValue_t setLimits( const uint8_t* data, size_t size); virtual ReturnValue_t setLimits( const uint8_t* data, size_t size);
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); const ParameterWrapper *newValues, uint16_t startAtIndex);

View File

@ -247,17 +247,17 @@ ThermalComponentCore::Parameters ThermalComponentCore::getParameters() {
} }
ReturnValue_t ThermalComponentCore::getParameter(uint8_t domainId, ReturnValue_t ThermalComponentCore::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) { const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t result = temperatureMonitor.getParameter(domainId, ReturnValue_t result = temperatureMonitor.getParameter(domainId,
parameterId, parameterWrapper, newValues, startAtIndex); uniqueId, parameterWrapper, newValues, startAtIndex);
if (result != INVALID_DOMAIN_ID) { if (result != INVALID_DOMAIN_ID) {
return result; return result;
} }
if (domainId != this->domainId) { if (domainId != this->domainId) {
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
switch (parameterId) { switch (uniqueId) {
case 0: case 0:
parameterWrapper->set(parameters.heaterOn); parameterWrapper->set(parameters.heaterOn);
break; break;

View File

@ -68,7 +68,7 @@ public:
virtual void setOutputInvalid(); virtual void setOutputInvalid();
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); const ParameterWrapper *newValues, uint16_t startAtIndex);

View File

@ -1,6 +1,9 @@
#include "Stopwatch.h" #include "Stopwatch.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterface.h"
#if FSFW_CPP_OSTREAM_ENABLED == 1
#include <iomanip> #include <iomanip>
#endif
Stopwatch::Stopwatch(bool displayOnDestruction, Stopwatch::Stopwatch(bool displayOnDestruction,
StopwatchDisplayMode displayMode): displayOnDestruction( StopwatchDisplayMode displayMode): displayOnDestruction(
@ -28,9 +31,13 @@ double Stopwatch::stopSeconds() {
void Stopwatch::display() { void Stopwatch::display() {
if(displayMode == StopwatchDisplayMode::MILLIS) { if(displayMode == StopwatchDisplayMode::MILLIS) {
dur_millis_t timeMillis = static_cast<dur_millis_t>(
elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000);
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Stopwatch: Operation took " << (elapsedTime.tv_sec * 1000 + sif::info << "Stopwatch: Operation took " << timeMillis << " milliseconds" << std::endl;
elapsedTime.tv_usec / 1000) << " milliseconds" << std::endl; #else
sif::printInfo("Stopwatch: Operation took %lu milliseconds\n\r",
static_cast<unsigned int>(timeMillis));
#endif #endif
} }
else if(displayMode == StopwatchDisplayMode::SECONDS) { else if(displayMode == StopwatchDisplayMode::SECONDS) {
@ -38,6 +45,9 @@ void Stopwatch::display() {
sif::info <<"Stopwatch: Operation took " << std::setprecision(3) sif::info <<"Stopwatch: Operation took " << std::setprecision(3)
<< std::fixed << timevalOperations::toDouble(elapsedTime) << std::fixed << timevalOperations::toDouble(elapsedTime)
<< " seconds" << std::endl; << " seconds" << std::endl;
#else
sif::printInfo("Stopwatch: Operation took %.3f seconds\n\r",
static_cast<float>(timevalOperations::toDouble(elapsedTime)));
#endif #endif
} }
} }

View File

@ -1,7 +1,7 @@
#include "TmTcBridge.h" #include "TmTcBridge.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterface.h"
#include "../globalfunctions/arrayprinter.h" #include "../globalfunctions/arrayprinter.h"
TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination, TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination,
@ -109,9 +109,8 @@ ReturnValue_t TmTcBridge::handleTm() {
ReturnValue_t result = handleTmQueue(); ReturnValue_t result = handleTmQueue();
if(result != RETURN_OK) { if(result != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcBridge::handleTm: Error handling TM queue with " sif::error << "TmTcBridge::handleTm: Error handling TM queue with error code 0x" <<
<< "error code 0x" << std::hex << result << std::dec std::hex << result << std::dec << "!" << std::endl;
<< "!" << std::endl;
#endif #endif
status = result; status = result;
} }
@ -121,8 +120,7 @@ ReturnValue_t TmTcBridge::handleTm() {
result = handleStoredTm(); result = handleStoredTm();
if(result != RETURN_OK) { if(result != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcBridge::handleTm: Error handling stored TMs!" sif::error << "TmTcBridge::handleTm: Error handling stored TMs!" << std::endl;
<< std::endl;
#endif #endif
status = result; status = result;
} }
@ -140,9 +138,15 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
result == HasReturnvaluesIF::RETURN_OK; result == HasReturnvaluesIF::RETURN_OK;
result = tmTcReceptionQueue->receiveMessage(&message)) result = tmTcReceptionQueue->receiveMessage(&message))
{ {
#if FSFW_VERBOSE_LEVEL >= 3
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
//sif::info << (int) packetSentCounter << std::endl; sif::info << "Sent packet counter: " << static_cast<int>(packetSentCounter) << std::endl;
#else
sif::printInfo("Sent packet counter: %d\n", packetSentCounter);
#endif #endif
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
if(communicationLinkUp == false or if(communicationLinkUp == false or
packetSentCounter >= sentPacketsPerCycle) { packetSentCounter >= sentPacketsPerCycle) {
storeDownlinkData(&message); storeDownlinkData(&message);

View File

@ -1,10 +1,16 @@
#include "LocalPoolOwnerBase.h" #include "LocalPoolOwnerBase.h"
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>
#include <fsfw/datapool/PoolReadHelper.h>
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h> #include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h> #include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/housekeeping/HousekeepingSnapshot.h>
#include <fsfw/ipc/CommandMessageCleaner.h> #include <fsfw/ipc/CommandMessageCleaner.h>
#include <fsfw/timemanager/CCSDSTime.h>
#include <unittest/core/CatchDefinitions.h> #include <unittest/core/CatchDefinitions.h>
#include <iostream>
TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") { TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
@ -14,7 +20,7 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
== retval::CATCH_OK); == retval::CATCH_OK);
REQUIRE(poolOwner->dataset.assignPointers() == retval::CATCH_OK); //REQUIRE(poolOwner->dataset.assignPointers() == retval::CATCH_OK);
MessageQueueMockBase* mqMock = poolOwner->getMockQueueHandle(); MessageQueueMockBase* mqMock = poolOwner->getMockQueueHandle();
REQUIRE(mqMock != nullptr); REQUIRE(mqMock != nullptr);
CommandMessage messageSent; CommandMessage messageSent;
@ -22,11 +28,11 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
SECTION("BasicTest") { SECTION("BasicTest") {
// Subscribe for message generation on update. /* Subscribe for message generation on update. */
REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK); REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK);
// Subscribe for an update message. /* Subscribe for an update message. */
poolOwner->dataset.setChanged(true); poolOwner->dataset.setChanged(true);
// Now the update message should be generated. /* Now the update message should be generated. */
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent() == true); REQUIRE(mqMock->wasMessageSent() == true);
@ -34,9 +40,9 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
CHECK(messageSent.getCommand() == static_cast<int>( CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET)); HousekeepingMessage::UPDATE_NOTIFICATION_SET));
// Should have been reset. /* Should have been reset. */
CHECK(poolOwner->dataset.hasChanged() == false); CHECK(poolOwner->dataset.hasChanged() == false);
// Set changed again, result should be the same. /* Set changed again, result should be the same. */
poolOwner->dataset.setChanged(true); poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
@ -46,14 +52,14 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
CHECK(messageSent.getCommand() == static_cast<int>( CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET)); HousekeepingMessage::UPDATE_NOTIFICATION_SET));
// now subscribe for set update HK as well. /* Now subscribe for set update HK as well. */
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK); REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
poolOwner->dataset.setChanged(true); poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true); REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 2); CHECK(messagesSent == 2);
// first message sent should be the update notification, considering /* first message sent should be the update notification, considering
// the internal list is a vector checked in insertion order. the internal list is a vector checked in insertion order. */
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK); REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>( CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_SET)); HousekeepingMessage::UPDATE_NOTIFICATION_SET));
@ -61,16 +67,82 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK); REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>( CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::HK_REPORT)); HousekeepingMessage::HK_REPORT));
// clear message to avoid memory leak, our mock won't do it for us (yet) /* Clear message to avoid memory leak, our mock won't do it for us (yet) */
CommandMessageCleaner::clearCommandMessage(&messageSent); CommandMessageCleaner::clearCommandMessage(&messageSent);
}
SECTION("SnapshotUpdateTests") {
/* Set the variables in the set to certain values. These are checked later. */
{
PoolReadHelper readHelper(&poolOwner->dataset);
REQUIRE(readHelper.getReadResult() == retval::CATCH_OK);
poolOwner->dataset.localPoolVarUint8.value = 5;
poolOwner->dataset.localPoolVarFloat.value = -12.242;
poolOwner->dataset.localPoolUint16Vec.value[0] = 2;
poolOwner->dataset.localPoolUint16Vec.value[1] = 32;
poolOwner->dataset.localPoolUint16Vec.value[2] = 42932;
}
/* Subscribe for snapshot generation on update. */
REQUIRE(poolOwner->subscribeWrapperSetUpdateSnapshot() == retval::CATCH_OK);
poolOwner->dataset.setChanged(true);
/* Store current time, we are going to check the (approximate) time equality later */
CCSDSTime::CDS_short timeCdsNow;
timeval now;
Clock::getClock_timeval(&now);
CCSDSTime::convertToCcsds(&timeCdsNow, &now);
/* Trigger generation of snapshot */
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
/* Check that snapshot was generated */
CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_SNAPSHOT_SET));
/* Now we deserialize the snapshot into a new dataset instance */
CCSDSTime::CDS_short cdsShort;
LocalPoolTestDataSet newSet;
HousekeepingSnapshot snapshot(&cdsShort, &newSet);
store_address_t storeId;
HousekeepingMessage::getUpdateSnapshotSetCommand(&messageSent, &storeId);
ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId);
REQUIRE(accessorPair.first == retval::CATCH_OK);
const uint8_t* readOnlyPtr = accessorPair.second.data();
size_t sizeToDeserialize = accessorPair.second.size();
CHECK(newSet.localPoolVarFloat.value == 0);
CHECK(newSet.localPoolVarUint8 == 0);
CHECK(newSet.localPoolUint16Vec.value[0] == 0);
CHECK(newSet.localPoolUint16Vec.value[1] == 0);
CHECK(newSet.localPoolUint16Vec.value[2] == 0);
/* Fill the dataset and timestamp */
REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize,
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
/* Now we check that the snapshot is actually correct */
CHECK(newSet.localPoolVarFloat.value == Catch::Approx(-12.242));
CHECK(newSet.localPoolVarUint8 == 5);
CHECK(newSet.localPoolUint16Vec.value[0] == 2);
CHECK(newSet.localPoolUint16Vec.value[1] == 32);
CHECK(newSet.localPoolUint16Vec.value[2] == 42932);
/* Now we check that both times are equal */
CHECK(cdsShort.pField == timeCdsNow.pField);
CHECK(cdsShort.dayLSB == Catch::Approx(timeCdsNow.dayLSB).margin(1));
CHECK(cdsShort.dayMSB == Catch::Approx(timeCdsNow.dayMSB).margin(1));
CHECK(cdsShort.msDay_h == Catch::Approx(timeCdsNow.msDay_h).margin(1));
CHECK(cdsShort.msDay_hh == Catch::Approx(timeCdsNow.msDay_hh).margin(1));
CHECK(cdsShort.msDay_l == Catch::Approx(timeCdsNow.msDay_l).margin(1));
CHECK(cdsShort.msDay_ll == Catch::Approx(timeCdsNow.msDay_ll).margin(1));
} }
SECTION("AdvancedTests") { SECTION("AdvancedTests") {
// we need to reset the subscription list because the pool owner /* Acquire subscription interface */
// is a global object. ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner->getSubscriptionInterface();
poolOwner->resetSubscriptionList(); REQUIRE(subscriptionIF != nullptr);
// Subscribe for variable update as well
REQUIRE(not poolOwner->dataset.hasChanged()); /* Subscribe for variable update */
REQUIRE(poolOwner->subscribeWrapperVariableUpdate(lpool::uint8VarId) == REQUIRE(poolOwner->subscribeWrapperVariableUpdate(lpool::uint8VarId) ==
retval::CATCH_OK); retval::CATCH_OK);
lp_var_t<uint8_t>* poolVar = dynamic_cast<lp_var_t<uint8_t>*>( lp_var_t<uint8_t>* poolVar = dynamic_cast<lp_var_t<uint8_t>*>(
@ -79,22 +151,22 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
poolVar->setChanged(true); poolVar->setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
// Check update notification was sent. /* Check update notification was sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true); REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1); CHECK(messagesSent == 1);
// Should have been reset. /* Should have been reset. */
CHECK(poolVar->hasChanged() == false); CHECK(poolVar->hasChanged() == false);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK); REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>( CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE)); HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
/* Now subscribe for the dataset update (HK and update) again with subscription interface */
// now subscribe for the dataset update (HK and update) again REQUIRE(subscriptionIF->subscribeForSetUpdateMessages(lpool::testSetId,
REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK); objects::NO_OBJECT, objects::HK_RECEIVER_MOCK, false) == retval::CATCH_OK);
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK); REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
poolOwner->dataset.setChanged(true); poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
// now two messages should be sent. /* Now two messages should be sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true); REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 2); CHECK(messagesSent == 2);
mqMock->clearMessages(true); mqMock->clearMessages(true);
@ -102,7 +174,7 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
poolOwner->dataset.setChanged(true); poolOwner->dataset.setChanged(true);
poolVar->setChanged(true); poolVar->setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
// now three messages should be sent. /* Now three messages should be sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true); REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 3); CHECK(messagesSent == 3);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK); REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
@ -115,8 +187,12 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
CHECK(messageSent.getCommand() == static_cast<int>( CHECK(messageSent.getCommand() == static_cast<int>(
HousekeepingMessage::HK_REPORT)); HousekeepingMessage::HK_REPORT));
CommandMessageCleaner::clearCommandMessage(&messageSent); CommandMessageCleaner::clearCommandMessage(&messageSent);
REQUIRE(mqMock->receiveMessage(&messageSent) == REQUIRE(mqMock->receiveMessage(&messageSent) == static_cast<int>(MessageQueueIF::EMPTY));
static_cast<int>(MessageQueueIF::EMPTY)); }
}
/* we need to reset the subscription list because the pool owner
is a global object. */
poolOwner->resetSubscriptionList();
mqMock->clearMessages(true);
} }

View File

@ -20,33 +20,43 @@ static constexpr lp_id_t int64Vec2Id = 4;
static constexpr uint32_t testSetId = 0; static constexpr uint32_t testSetId = 0;
static constexpr uint8_t dataSetMaxVariables = 10; static constexpr uint8_t dataSetMaxVariables = 10;
static const sid_t testSid = sid_t(objects::TEST_LOCAL_POOL_OWNER_BASE,
testSetId); static const sid_t testSid = sid_t(objects::TEST_LOCAL_POOL_OWNER_BASE, testSetId);
static const gp_id_t uint8VarGpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, uint8VarId);
static const gp_id_t floatVarGpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, floatVarId);
static const gp_id_t uint32Gpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, uint32VarId);
static const gp_id_t uint16Vec3Gpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, uint16Vec3Id);
static const gp_id_t uint64Vec2Id = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, int64Vec2Id);
} }
class LocalPoolTestDataSet: public LocalDataSet { class LocalPoolTestDataSet: public LocalDataSet {
public: public:
LocalPoolTestDataSet():
LocalDataSet(lpool::testSid, lpool::dataSetMaxVariables) {
}
LocalPoolTestDataSet(HasLocalDataPoolIF* owner, uint32_t setId): LocalPoolTestDataSet(HasLocalDataPoolIF* owner, uint32_t setId):
LocalDataSet(owner, setId, lpool::dataSetMaxVariables) { LocalDataSet(owner, setId, lpool::dataSetMaxVariables) {
} }
ReturnValue_t assignPointers() { // ReturnValue_t assignPointers() {
PoolVariableIF** rawVarArray = getContainer(); // PoolVariableIF** rawVarArray = getContainer();
localPoolVarUint8 = dynamic_cast<lp_var_t<uint8_t>*>(rawVarArray[0]); // localPoolVarUint8 = dynamic_cast<lp_var_t<uint8_t>*>(rawVarArray[0]);
localPoolVarFloat = dynamic_cast<lp_var_t<float>*>(rawVarArray[1]); // localPoolVarFloat = dynamic_cast<lp_var_t<float>*>(rawVarArray[1]);
localPoolUint16Vec = dynamic_cast<lp_vec_t<uint16_t, 3>*>( // localPoolUint16Vec = dynamic_cast<lp_vec_t<uint16_t, 3>*>(
rawVarArray[2]); // rawVarArray[2]);
if(localPoolVarUint8 == nullptr or localPoolVarFloat == nullptr or // if(localPoolVarUint8 == nullptr or localPoolVarFloat == nullptr or
localPoolUint16Vec == nullptr) { // localPoolUint16Vec == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; // return HasReturnvaluesIF::RETURN_FAILED;
} // }
return HasReturnvaluesIF::RETURN_OK; // return HasReturnvaluesIF::RETURN_OK;
} // }
lp_var_t<uint8_t>* localPoolVarUint8 = nullptr; lp_var_t<uint8_t> localPoolVarUint8 = lp_var_t<uint8_t>(lpool::uint8VarGpid, this);
lp_var_t<float>* localPoolVarFloat = nullptr; lp_var_t<float> localPoolVarFloat = lp_var_t<float>(lpool::floatVarGpid, this);
lp_vec_t<uint16_t, 3>* localPoolUint16Vec = nullptr; lp_vec_t<uint16_t, 3> localPoolUint16Vec = lp_vec_t<uint16_t, 3>(lpool::uint16Vec3Gpid, this);
private: private:
}; };
@ -155,7 +165,12 @@ public:
ReturnValue_t subscribeWrapperSetUpdate() { ReturnValue_t subscribeWrapperSetUpdate() {
return poolManager.subscribeForSetUpdateMessages(lpool::testSetId, return poolManager.subscribeForSetUpdateMessages(lpool::testSetId,
objects::NO_OBJECT, MessageQueueIF::NO_QUEUE, false); objects::NO_OBJECT, objects::HK_RECEIVER_MOCK, false);
}
ReturnValue_t subscribeWrapperSetUpdateSnapshot() {
return poolManager.subscribeForSetUpdateMessages(lpool::testSetId,
objects::NO_OBJECT, objects::HK_RECEIVER_MOCK, true);
} }
ReturnValue_t subscribeWrapperSetUpdateHk(bool diagnostics = false) { ReturnValue_t subscribeWrapperSetUpdateHk(bool diagnostics = false) {
@ -165,7 +180,7 @@ public:
ReturnValue_t subscribeWrapperVariableUpdate(lp_id_t localPoolId) { ReturnValue_t subscribeWrapperVariableUpdate(lp_id_t localPoolId) {
return poolManager.subscribeForVariableUpdateMessages(localPoolId, return poolManager.subscribeForVariableUpdateMessages(localPoolId,
MessageQueueIF::NO_QUEUE, objects::NO_OBJECT, false); MessageQueueIF::NO_QUEUE, objects::HK_RECEIVER_MOCK, false);
} }
void resetSubscriptionList() { void resetSubscriptionList() {

View File

@ -14,7 +14,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
== retval::CATCH_OK); == retval::CATCH_OK);
SECTION("Basic Tests") { SECTION("Basic Tests") {
// very basic test. /* very basic test. */
lp_var_t<uint8_t> testVariable = lp_var_t<uint8_t>( lp_var_t<uint8_t> testVariable = lp_var_t<uint8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
REQUIRE(testVariable.read() == retval::CATCH_OK); REQUIRE(testVariable.read() == retval::CATCH_OK);
@ -77,7 +77,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
SECTION("ErrorHandling") { SECTION("ErrorHandling") {
// not try to use a local pool variable which does not exist /* now try to use a local pool variable which does not exist */
lp_var_t<uint8_t> invalidVariable = lp_var_t<uint8_t>( lp_var_t<uint8_t> invalidVariable = lp_var_t<uint8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff); objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
REQUIRE(invalidVariable.read() == REQUIRE(invalidVariable.read() ==
@ -85,7 +85,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
REQUIRE(invalidVariable.commit() == REQUIRE(invalidVariable.commit() ==
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND)); static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
// now try to access with wrong type /* now try to access with wrong type */
lp_var_t<int8_t> invalidVariable2 = lp_var_t<int8_t>( lp_var_t<int8_t> invalidVariable2 = lp_var_t<int8_t>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
REQUIRE(invalidVariable2.read() == REQUIRE(invalidVariable2.read() ==
@ -108,7 +108,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
sif::info << "LocalPoolVariable printout: " <<uint32tVar << std::endl; sif::info << "LocalPoolVariable printout: " <<uint32tVar << std::endl;
#endif #endif
// for code coverage. If program does not crash -> OK /* for code coverage. If program does not crash -> OK */
lp_var_t<uint8_t> invalidObjectVar = lp_var_t<uint8_t>( lp_var_t<uint8_t> invalidObjectVar = lp_var_t<uint8_t>(
0xffffffff, lpool::uint8VarId); 0xffffffff, lpool::uint8VarId);
gp_id_t globPoolId(0xffffffff, gp_id_t globPoolId(0xffffffff,

View File

@ -35,13 +35,13 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
CHECK(testVector[0] == 5); CHECK(testVector[0] == 5);
// This is invalid access, so the last value will be set instead. /* This is invalid access, so the last value will be set instead.
// (we can't throw exceptions) (we can't throw exceptions) */
testVector[4] = 12; testVector[4] = 12;
CHECK(testVector[2] == 12); CHECK(testVector[2] == 12);
CHECK(testVector.commit() == retval::CATCH_OK); CHECK(testVector.commit() == retval::CATCH_OK);
// Use read-only reference. /* Use read-only reference. */
const lp_vec_t<uint16_t, 3>& roTestVec = testVector; const lp_vec_t<uint16_t, 3>& roTestVec = testVector;
uint16_t valueOne = roTestVec[0]; uint16_t valueOne = roTestVec[0];
CHECK(valueOne == 5); CHECK(valueOne == 5);
@ -87,7 +87,7 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
} }
SECTION("ErrorHandling") { SECTION("ErrorHandling") {
// not try to use a local pool variable which does not exist /* Now try to use a local pool variable which does not exist */
lp_vec_t<uint16_t, 3> invalidVector = lp_vec_t<uint16_t, 3>( lp_vec_t<uint16_t, 3> invalidVector = lp_vec_t<uint16_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff); objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
REQUIRE(invalidVector.read() == REQUIRE(invalidVector.read() ==
@ -95,7 +95,7 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
REQUIRE(invalidVector.commit() == REQUIRE(invalidVector.commit() ==
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND)); static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
// now try to access with wrong type /* Now try to access with wrong type */
lp_vec_t<uint32_t, 3> invalidVector2 = lp_vec_t<uint32_t, 3>( lp_vec_t<uint32_t, 3> invalidVector2 = lp_vec_t<uint32_t, 3>(
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id); objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id);
REQUIRE(invalidVector2.read() == REQUIRE(invalidVector2.read() ==

View File

@ -276,7 +276,7 @@ TEST_CASE( "Local Pool Extended Tests [3 Pools]" , "[TestPool2]") {
CHECK(receptionArray[3] == 66); CHECK(receptionArray[3] == 66);
// now clear first page // now clear first page
simplePool.clearPage(0); simplePool.clearSubPool(0);
bytesWritten = 0; bytesWritten = 0;
simplePool.getFillCount(receptionArray.data(), &bytesWritten); simplePool.getFillCount(receptionArray.data(), &bytesWritten);
// Second page full, median fill count is 33 % // Second page full, median fill count is 33 %