Merge remote-tracking branch 'upstream/mueller/master' into mueller/master
This commit is contained in:
commit
8c5e261a0d
@ -155,7 +155,7 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||
result = queueToUse->sendMessage(reportTo, &reply);
|
||||
}
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeAddress);
|
||||
}
|
||||
return result;
|
||||
|
@ -99,7 +99,7 @@ public:
|
||||
*/
|
||||
void setQueueToUse(MessageQueueIF *queue);
|
||||
protected:
|
||||
//!< Increase of value of this per step
|
||||
//! Increase of value of this per step
|
||||
static const uint8_t STEP_OFFSET = 1;
|
||||
HasActionsIF* owner;//!< Pointer to the owner
|
||||
//! Queue to be used as response sender, has to be set in ctor or with
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
* This function is protected because it should only be used by the
|
||||
* class imlementing the interface.
|
||||
*/
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() = 0;
|
||||
virtual LocalDataPoolManager* getPoolManagerHandle() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include "internal/LocalPoolDataSetAttorney.h"
|
||||
#include "internal/HasLocalDpIFManagerAttorney.h"
|
||||
|
||||
#include "../housekeeping/HousekeepingPacketUpdate.h"
|
||||
#include "../housekeeping/HousekeepingSetPacket.h"
|
||||
#include "../housekeeping/HousekeepingSnapshot.h"
|
||||
#include "../housekeeping/AcceptsHkPacketsIF.h"
|
||||
#include "../timemanager/CCSDSTime.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
@ -226,7 +226,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
Clock::getClock_timeval(&now);
|
||||
CCSDSTime::CDS_short cds;
|
||||
CCSDSTime::convertToCcsds(&cds, &now);
|
||||
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||
HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||
sizeof(cds), HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
|
||||
receiver.dataId.localPoolId));
|
||||
|
||||
@ -264,7 +264,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
Clock::getClock_timeval(&now);
|
||||
CCSDSTime::CDS_short cds;
|
||||
CCSDSTime::convertToCcsds(&cds, &now);
|
||||
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||
HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||
sizeof(cds), HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
|
||||
receiver.dataId.sid));
|
||||
|
||||
@ -292,7 +292,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
}
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::addUpdateToStore(
|
||||
HousekeepingPacketUpdate& updatePacket, store_address_t& storeId) {
|
||||
HousekeepingSnapshot& updatePacket, store_address_t& storeId) {
|
||||
size_t updatePacketSize = updatePacket.getSerializedSize();
|
||||
uint8_t *storePtr = nullptr;
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId,
|
||||
@ -890,7 +890,7 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
||||
<< std::dec << std::setfill(' ') << std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
||||
owner->getObjectId(), errorPrint);
|
||||
functionName, owner->getObjectId(), errorPrint);
|
||||
#endif
|
||||
}
|
||||
else if(outputType == sif::OutputTypes::OUT_ERROR) {
|
||||
@ -901,11 +901,11 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
||||
<< std::dec << std::setfill(' ') << std::endl;
|
||||
#else
|
||||
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
||||
owner->getObjectId(), errorPrint);
|
||||
functionName, owner->getObjectId(), errorPrint);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
LocalDataPoolManager* LocalDataPoolManager::getHkManagerHandle() {
|
||||
LocalDataPoolManager* LocalDataPoolManager::getPoolManagerHandle() {
|
||||
return this;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ void setStaticFrameworkObjectIds();
|
||||
}
|
||||
|
||||
class LocalPoolDataSetBase;
|
||||
class HousekeepingPacketUpdate;
|
||||
class HousekeepingSnapshot;
|
||||
class HasLocalDataPoolIF;
|
||||
class LocalDataPool;
|
||||
|
||||
@ -52,7 +52,8 @@ class LocalDataPool;
|
||||
* Each pool entry has a valid state too.
|
||||
* @author R. Mueller
|
||||
*/
|
||||
class LocalDataPoolManager: public ProvidesDataPoolSubscriptionIF,
|
||||
class LocalDataPoolManager:
|
||||
public ProvidesDataPoolSubscriptionIF,
|
||||
public AccessPoolManagerIF {
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
//! 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 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 REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
|
||||
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
|
||||
@ -179,8 +179,6 @@ public:
|
||||
MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot) override;
|
||||
|
||||
MutexIF* getLocalPoolMutex() override;
|
||||
|
||||
/**
|
||||
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
||||
* than diagnostic packets.
|
||||
@ -243,12 +241,9 @@ public:
|
||||
UPDATE_SNAPSHOT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Different data types are possible in the HK receiver map.
|
||||
* For example, updates can be requested for full datasets or
|
||||
* for single pool variables. Periodic reporting is only possible for
|
||||
* data sets.
|
||||
*/
|
||||
/** Different data types are possible in the HK receiver map. For example, updates can be
|
||||
requested for full datasets or for single pool variables. Periodic reporting is only possible
|
||||
for data sets. */
|
||||
enum class DataType: uint8_t {
|
||||
LOCAL_POOL_VARIABLE,
|
||||
DATA_SET
|
||||
@ -267,11 +262,19 @@ public:
|
||||
|
||||
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:
|
||||
localpool::DataPool localPoolMap;
|
||||
//! Every housekeeping data manager has a mutex to protect access
|
||||
//! to it's data pool.
|
||||
/** Every housekeeping data manager has a mutex to protect access
|
||||
to it's data pool. */
|
||||
MutexIF* mutex = nullptr;
|
||||
|
||||
/** The class which actually owns the manager (and its datapool). */
|
||||
@ -333,13 +336,6 @@ private:
|
||||
|
||||
/** Global IPC store is used to store all packets. */
|
||||
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
|
||||
@ -364,6 +360,8 @@ private:
|
||||
*/
|
||||
ReturnValue_t initializeHousekeepingPoolEntriesOnce();
|
||||
|
||||
MutexIF* getLocalPoolMutex() override;
|
||||
|
||||
ReturnValue_t serializeHkPacketIntoStore(
|
||||
HousekeepingPacketDownlink& hkPacket,
|
||||
store_address_t& storeId, bool forDownlink, size_t* serializedSize);
|
||||
@ -386,7 +384,7 @@ private:
|
||||
ReturnValue_t& status);
|
||||
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver,
|
||||
ReturnValue_t& status);
|
||||
ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket,
|
||||
ReturnValue_t addUpdateToStore(HousekeepingSnapshot& updatePacket,
|
||||
store_address_t& storeId);
|
||||
|
||||
void printWarningOrError(sif::OutputTypes outputType,
|
||||
@ -401,14 +399,14 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
|
||||
PoolEntry<T> **poolEntry) {
|
||||
auto poolIter = localPoolMap.find(localPoolId);
|
||||
if (poolIter == localPoolMap.end()) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
|
||||
localpool::POOL_ENTRY_NOT_FOUND);
|
||||
return localpool::POOL_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
|
||||
if(*poolEntry == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
|
||||
localpool::POOL_ENTRY_TYPE_CONFLICT);
|
||||
return localpool::POOL_ENTRY_TYPE_CONFLICT;
|
||||
}
|
||||
|
@ -4,11 +4,26 @@
|
||||
#include "LocalPoolDataSetBase.h"
|
||||
#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 {
|
||||
public:
|
||||
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
|
||||
const size_t maxSize);
|
||||
|
||||
LocalDataSet(sid_t sid, const size_t maxSize);
|
||||
|
||||
virtual~ LocalDataSet();
|
||||
|
||||
//! Copying forbidden for now.
|
||||
|
@ -28,7 +28,7 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
|
||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||
|
||||
if(accessor != nullptr) {
|
||||
poolManager = accessor->getHkManagerHandle();
|
||||
poolManager = accessor->getPoolManagerHandle();
|
||||
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkO
|
||||
return;
|
||||
}
|
||||
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||
hkManager = poolManAccessor->getHkManagerHandle();
|
||||
hkManager = poolManAccessor->getPoolManagerHandle();
|
||||
|
||||
if (dataSet != nullptr) {
|
||||
dataSet->registerVariable(this);
|
||||
@ -50,7 +50,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
|
||||
|
||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||
if(accessor != nullptr) {
|
||||
hkManager = accessor->getHkManagerHandle();
|
||||
hkManager = accessor->getPoolManagerHandle();
|
||||
}
|
||||
|
||||
if(dataSet != nullptr) {
|
||||
|
@ -77,8 +77,7 @@ public:
|
||||
* @param dataSet
|
||||
* @param setReadWriteMode
|
||||
*/
|
||||
LocalPoolVector(gp_id_t globalPoolId,
|
||||
DataSetIF* dataSet = nullptr,
|
||||
LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
|
||||
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
|
||||
* array of this type.
|
||||
*/
|
||||
T value[vectorSize];
|
||||
T value[vectorSize]= {};
|
||||
/**
|
||||
* @brief The classes destructor is empty.
|
||||
* @details If commit() was not called, the local value is
|
||||
|
@ -16,7 +16,6 @@ inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner,
|
||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
|
@ -2,11 +2,15 @@
|
||||
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
|
||||
|
||||
#include "LocalPoolDataSetBase.h"
|
||||
#include "LocalPoolVariable.h"
|
||||
#include "LocalPoolVector.h"
|
||||
|
||||
#include "../objectmanager/SystemObjectIF.h"
|
||||
#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
|
||||
* This will is the primary data structure to organize pool variables into
|
||||
* sets which can be accessed via the housekeeping service interface or
|
||||
|
@ -17,16 +17,15 @@ object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
||||
object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT;
|
||||
object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT;
|
||||
|
||||
DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId,
|
||||
object_id_t deviceCommunication, CookieIF * comCookie,
|
||||
FailureIsolationBase* fdirInstance, size_t cmdQueueSize) :
|
||||
DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
|
||||
CookieIF* comCookie, FailureIsolationBase* fdirInstance, size_t cmdQueueSize):
|
||||
SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE),
|
||||
wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS),
|
||||
deviceCommunicationId(deviceCommunication), comCookie(comCookie),
|
||||
healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this),
|
||||
actionHelper(this, nullptr), poolManager(this, nullptr),
|
||||
childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance),
|
||||
hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr),
|
||||
defaultFDIRUsed(fdirInstance == nullptr),
|
||||
switchOffWasReported(false), childTransitionDelay(5000),
|
||||
transitionSourceMode(_MODE_POWER_DOWN),
|
||||
transitionSourceSubMode(SUBMODE_NONE) {
|
||||
@ -80,7 +79,6 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
||||
checkSwitchState();
|
||||
decrementDeviceReplyMap();
|
||||
fdirInstance->checkForFailures();
|
||||
hkSwitcher.performOperation();
|
||||
performOperationHook();
|
||||
return RETURN_OK;
|
||||
}
|
||||
@ -92,7 +90,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
||||
switch (getComAction()) {
|
||||
case CommunicationAction::SEND_WRITE:
|
||||
if (cookieInfo.state == COOKIE_UNUSED) {
|
||||
// if no external command was specified, build internal command.
|
||||
/* If no external command was specified, build internal command. */
|
||||
buildInternalCommand();
|
||||
}
|
||||
doSendWrite();
|
||||
@ -105,8 +103,8 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
||||
break;
|
||||
case CommunicationAction::GET_READ:
|
||||
doGetRead();
|
||||
// This will be performed after datasets have been updated by the
|
||||
// custom device implementation.
|
||||
/* This will be performed after datasets have been updated by the
|
||||
custom device implementation. */
|
||||
poolManager.performHkOperation();
|
||||
break;
|
||||
default:
|
||||
@ -205,11 +203,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = hkSwitcher.initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = poolManager.initialize(commandQueue);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
@ -506,7 +499,8 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) {
|
||||
}
|
||||
|
||||
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;
|
||||
mode = newMode;
|
||||
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) {
|
||||
@ -1202,61 +1197,62 @@ ReturnValue_t DeviceHandlerBase::letChildHandleMessage(
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::handleDeviceTM(SerializeIF* data,
|
||||
DeviceCommandId_t replyId, bool neverInDataPool, bool forceDirectTm) {
|
||||
void DeviceHandlerBase::handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId,
|
||||
bool forceDirectTm) {
|
||||
if(dataSet == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId);
|
||||
if (iter == deviceReplyMap.end()) {
|
||||
triggerEvent(DEVICE_UNKNOWN_REPLY, replyId);
|
||||
return;
|
||||
}
|
||||
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data);
|
||||
//replies to a command
|
||||
|
||||
/* Regular replies to a command */
|
||||
if (iter->second.command != deviceCommandMap.end())
|
||||
{
|
||||
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
|
||||
|
||||
if (queueId != NO_COMMANDER) {
|
||||
//This may fail, but we'll ignore the fault.
|
||||
actionHelper.reportData(queueId, replyId, data);
|
||||
/* This may fail, but we'll ignore the fault. */
|
||||
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)) {
|
||||
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet);
|
||||
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
|
||||
}
|
||||
|
||||
else if (forceDirectTm and (defaultRawReceiver != queueId) and
|
||||
(defaultRawReceiver != MessageQueueIF::NO_QUEUE))
|
||||
{
|
||||
// hiding of sender needed so the service will handle it as
|
||||
// unexpected Data, no matter what state (progress or completed)
|
||||
// it is in
|
||||
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper,
|
||||
true);
|
||||
actionHelper.reportData(defaultRawReceiver, replyId, dataSet, true);
|
||||
}
|
||||
}
|
||||
//unrequested/aperiodic replies
|
||||
/* Unrequested or aperiodic replies */
|
||||
else
|
||||
{
|
||||
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet);
|
||||
if (wiretappingMode == TM) {
|
||||
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
|
||||
}
|
||||
else if (forceDirectTm and defaultRawReceiver !=
|
||||
MessageQueueIF::NO_QUEUE)
|
||||
if (forceDirectTm and defaultRawReceiver != 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
|
||||
// unexpected Data, no matter what state (progress or completed)
|
||||
// it is in
|
||||
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper,
|
||||
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();
|
||||
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1285,18 +1281,17 @@ ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId,
|
||||
}
|
||||
|
||||
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;
|
||||
DeviceCommandId_t deviceCommandId = NO_COMMAND_ID;
|
||||
if (mode == MODE_NORMAL) {
|
||||
result = buildNormalDeviceCommand(&deviceCommandId);
|
||||
if (result == BUSY) {
|
||||
// so we can track misconfigurations
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
"buildInternalCommand",
|
||||
HasReturnvaluesIF::RETURN_FAILED,
|
||||
"Busy.");
|
||||
result = NOTHING_TO_SEND; //no need to report this
|
||||
/* So we can track misconfigurations */
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "buildInternalCommand",
|
||||
HasReturnvaluesIF::RETURN_FAILED, "Busy.");
|
||||
/* No need to report this */
|
||||
result = NOTHING_TO_SEND;
|
||||
}
|
||||
}
|
||||
else if (mode == MODE_RAW) {
|
||||
@ -1318,7 +1313,8 @@ void DeviceHandlerBase::buildInternalCommand(void) {
|
||||
deviceCommandId);
|
||||
if (iter == deviceCommandMap.end()) {
|
||||
result = COMMAND_NOT_SUPPORTED;
|
||||
} else if (iter->second.isExecuting) {
|
||||
}
|
||||
else if (iter->second.isExecuting) {
|
||||
#if FSFW_DISABLE_PRINTOUT == 0
|
||||
char output[36];
|
||||
sprintf(output, "Command 0x%08x is executing",
|
||||
@ -1378,11 +1374,11 @@ void DeviceHandlerBase::forwardEvent(Event event, uint32_t parameter1,
|
||||
void DeviceHandlerBase::doOffActivity() {
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::getParameter(uint8_t domainId,
|
||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t result = fdirInstance->getParameter(domainId, parameterId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
ReturnValue_t DeviceHandlerBase::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||
uint16_t startAtIndex) {
|
||||
ReturnValue_t result = fdirInstance->getParameter(domainId, uniqueId, parameterWrapper,
|
||||
newValues, startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
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){
|
||||
executingTask = task;
|
||||
}
|
||||
|
||||
// Default implementations empty.
|
||||
void DeviceHandlerBase::debugInterface(uint8_t positionTracker,
|
||||
object_id_t objectId, uint32_t parameter) {}
|
||||
|
||||
@ -1531,3 +1523,11 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
|
||||
LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() {
|
||||
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;
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "../action/ActionHelper.h"
|
||||
#include "../health/HealthHelper.h"
|
||||
#include "../parameters/ParameterHelper.h"
|
||||
#include "../datapool/HkSwitchHelper.h"
|
||||
#include "../datapoollocal/HasLocalDataPoolIF.h"
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
|
||||
@ -80,14 +79,14 @@ class StorageManagerIF;
|
||||
* @ingroup devices
|
||||
*/
|
||||
class DeviceHandlerBase: public DeviceHandlerIF,
|
||||
public HasReturnvaluesIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject,
|
||||
public HasModesIF,
|
||||
public HasHealthIF,
|
||||
public HasActionsIF,
|
||||
public ReceivesParameterMessagesIF,
|
||||
public HasLocalDataPoolIF {
|
||||
public HasReturnvaluesIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject,
|
||||
public HasModesIF,
|
||||
public HasHealthIF,
|
||||
public HasActionsIF,
|
||||
public ReceivesParameterMessagesIF,
|
||||
public HasLocalDataPoolIF {
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
public:
|
||||
/**
|
||||
@ -148,8 +147,7 @@ public:
|
||||
* 4. Decrements counter for timeout of replies by calling
|
||||
* decrementDeviceReplyMap()
|
||||
* 5. Performs FDIR check for failures
|
||||
* 6. Calls hkSwitcher.performOperation()
|
||||
* 7. If the device mode is MODE_OFF, return RETURN_OK.
|
||||
* 6. If the device mode is MODE_OFF, return RETURN_OK.
|
||||
* Otherwise, perform the Action property and performs depending
|
||||
* on value specified by input value counter (incremented in PST).
|
||||
* The child class tells base class what to do by setting this value.
|
||||
@ -189,6 +187,37 @@ public:
|
||||
/** Destructor. */
|
||||
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:
|
||||
/**
|
||||
* @brief This is used to let the child class handle the transition from
|
||||
@ -216,7 +245,6 @@ protected:
|
||||
* for a failed transition
|
||||
*/
|
||||
virtual void doStartUp() = 0;
|
||||
|
||||
/**
|
||||
* @brief This is used to let the child class handle the transition
|
||||
* from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN
|
||||
@ -242,6 +270,7 @@ protected:
|
||||
*/
|
||||
virtual void doShutDown() = 0;
|
||||
|
||||
/* Command handling */
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0;
|
||||
|
||||
/**
|
||||
* @brief Build a device command packet from data supplied by a
|
||||
* direct command.
|
||||
*
|
||||
* @brief Build a device command packet from data supplied by a direct
|
||||
* command (PUS Service 8)
|
||||
* @details
|
||||
* #rawPacket and #rawPacketLen should be set by this method to the packet
|
||||
* to be sent. The existence of the command in the command map and the
|
||||
* command size check against 0 are done by the base class.
|
||||
* This will be called if an functional command via PUS Service 8 is received and is
|
||||
* the primary interface for functional command instead of #executeAction for users. The
|
||||
* 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
|
||||
* deviceCommandMap
|
||||
* @param commandData pointer to the data from the direct command
|
||||
* @param commandDataLen length of commandData
|
||||
* #rawPacket and #rawPacketLen should be set by this method to the packet to be sent.
|
||||
* The existence of the command in the command map and the command size check against 0 are
|
||||
* done by the base class.
|
||||
*
|
||||
* @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
|
||||
* - @c RETURN_OK to send command after #rawPacket and #rawPacketLen
|
||||
* have been set.
|
||||
* - Anything else triggers an event with the
|
||||
* returnvalue as a parameter
|
||||
* - @c HasActionsIF::EXECUTION_COMPLETE to generate a finish reply immediately. This can
|
||||
* 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,
|
||||
const uint8_t * commandData, size_t commandDataLen) = 0;
|
||||
|
||||
/* Reply handling */
|
||||
/**
|
||||
* @brief Scans a buffer for a valid reply.
|
||||
* @details
|
||||
@ -344,7 +378,6 @@ protected:
|
||||
*/
|
||||
virtual ReturnValue_t scanForReply(const uint8_t *start, size_t len,
|
||||
DeviceCommandId_t *foundId, size_t *foundLen) = 0;
|
||||
|
||||
/**
|
||||
* @brief Interpret a reply from the device.
|
||||
* @details
|
||||
@ -366,10 +399,19 @@ protected:
|
||||
*/
|
||||
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
|
||||
const uint8_t *packet) = 0;
|
||||
|
||||
MessageQueueId_t getCommanderId(DeviceCommandId_t replyId) const;
|
||||
/**
|
||||
* @brief fill the #DeviceCommandMap and #DeviceReplyMap
|
||||
* called by the initialize() of the base class
|
||||
* 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;
|
||||
|
||||
/* Specifying commands and replies */
|
||||
/**
|
||||
* @brief Fill the #DeviceCommandMap and #DeviceReplyMap called by the #initialize
|
||||
* of the base class
|
||||
* @details
|
||||
* This is used to let the base class know which replies are expected.
|
||||
* There are different scenarios regarding this:
|
||||
@ -399,7 +441,6 @@ protected:
|
||||
* handled by returning @c APERIODIC_REPLY in scanForReply().
|
||||
*/
|
||||
virtual void fillCommandAndReplyMap() = 0;
|
||||
|
||||
/**
|
||||
* This is a helper method to facilitate inserting entries in the command map.
|
||||
* @param deviceCommand Identifier of the command to add.
|
||||
@ -417,7 +458,6 @@ protected:
|
||||
LocalPoolDataSetBase* replyDataSet = nullptr,
|
||||
size_t replyLen = 0, bool periodic = false,
|
||||
bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0);
|
||||
|
||||
/**
|
||||
* @brief This is a helper method to insert replies in the reply map.
|
||||
* @param deviceCommand Identifier of the reply to add.
|
||||
@ -431,7 +471,6 @@ protected:
|
||||
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand,
|
||||
uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr,
|
||||
size_t replyLen = 0, bool periodic = false);
|
||||
|
||||
/**
|
||||
* @brief A simple command to add a command to the commandList.
|
||||
* @param deviceCommand The command to add
|
||||
@ -457,25 +496,14 @@ protected:
|
||||
ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply,
|
||||
uint16_t delayCycles, uint16_t maxDelayCycles,
|
||||
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,
|
||||
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.
|
||||
*
|
||||
@ -494,6 +522,73 @@ protected:
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@ -509,82 +604,60 @@ protected:
|
||||
uint8_t *numberOfSwitches);
|
||||
|
||||
/**
|
||||
* This function is used to initialize the local housekeeping pool
|
||||
* entries. The default implementation leaves the pool empty.
|
||||
* @param localDataPoolMap
|
||||
* @return
|
||||
* @brief Helper function to report a missed reply
|
||||
* @details Can be overwritten by children to act on missed replies or to fake reporting Id.
|
||||
* @param id of the missed reply
|
||||
*/
|
||||
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
|
||||
/**
|
||||
* Required for HasLocalDataPoolIF, return a handle to the local pool manager.
|
||||
* @return
|
||||
*/
|
||||
LocalDataPoolManager* getHkManagerHandle() override;
|
||||
virtual void missedReply(DeviceCommandId_t id);
|
||||
|
||||
/* Miscellaneous functions */
|
||||
/**
|
||||
* @brief Hook function for child handlers which is called once per
|
||||
* performOperation(). Default implementation is empty.
|
||||
*/
|
||||
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);
|
||||
|
||||
/** @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;
|
||||
virtual void debugInterface(uint8_t positionTracker = 0,
|
||||
object_id_t objectId = 0, uint32_t parameter = 0);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The Returnvalues id of this class, required by HasReturnvaluesIF
|
||||
*/
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
|
||||
|
||||
static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(0xA0);
|
||||
// Returnvalues 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
|
||||
static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB1); //!< Ignore parts of the received packet
|
||||
static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB2); //!< Ignore full received packet
|
||||
// Returnvalues for command building
|
||||
static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xC0); //!< Return this if no command sending in required
|
||||
/* Return codes for scanForReply */
|
||||
//! This is used to specify for replies from a device which are not replies to requests
|
||||
static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB0);
|
||||
//! Ignore parts of the received packet
|
||||
static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB1);
|
||||
//! 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);
|
||||
// Returnvalues for getSwitches()
|
||||
// Return codes for getSwitches */
|
||||
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 SWITCH_FAILED = MAKE_RETURN_CODE(0xE1);
|
||||
|
||||
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;
|
||||
/** Size of the #rawPacket. */
|
||||
//! Size of the #rawPacket.
|
||||
uint32_t rawPacketLen = 0;
|
||||
|
||||
/**
|
||||
@ -642,15 +715,15 @@ protected:
|
||||
/** Cookie used for communication */
|
||||
CookieIF * comCookie;
|
||||
|
||||
/** Health helper for HasHealthIF */
|
||||
/* Health helper for HasHealthIF */
|
||||
HealthHelper healthHelper;
|
||||
/** Mode helper for HasModesIF */
|
||||
/* Mode helper for HasModesIF */
|
||||
ModeHelper modeHelper;
|
||||
/** Parameter helper for ReceivesParameterMessagesIF */
|
||||
/* Parameter helper for ReceivesParameterMessagesIF */
|
||||
ParameterHelper parameterHelper;
|
||||
/** Action helper for HasActionsIF */
|
||||
/* Action helper for HasActionsIF */
|
||||
ActionHelper actionHelper;
|
||||
/** Housekeeping Manager */
|
||||
/* Housekeeping Manager */
|
||||
LocalDataPoolManager poolManager;
|
||||
|
||||
/**
|
||||
@ -733,88 +806,41 @@ protected:
|
||||
* default class is instantiated. */
|
||||
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;
|
||||
|
||||
//!< Object which switches power on and off.
|
||||
//! Object which switches power on and off.
|
||||
static object_id_t powerSwitcherId;
|
||||
|
||||
//!< Object which receives RAW data by default.
|
||||
//! Object which receives RAW data by default.
|
||||
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;
|
||||
|
||||
/**
|
||||
* @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();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @brief Send a reply to a received device handler command.
|
||||
*
|
||||
* This also resets #DeviceHandlerCommand to 0.
|
||||
*
|
||||
* @param reply the reply type
|
||||
* @param parameter parameter for the reply
|
||||
*/
|
||||
void replyReturnvalueToCommand(ReturnValue_t status,
|
||||
uint32_t parameter = 0);
|
||||
|
||||
void replyReturnvalueToCommand(ReturnValue_t status, 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);
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*
|
||||
@ -856,16 +882,6 @@ protected:
|
||||
*/
|
||||
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.
|
||||
* The step number can be read from #pstStep.
|
||||
@ -874,27 +890,28 @@ protected:
|
||||
virtual CommunicationAction getComAction();
|
||||
|
||||
/**
|
||||
* Build the device command to send for raw mode.
|
||||
*
|
||||
* 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
|
||||
* Checks state of switches in conjunction with mode and triggers an event
|
||||
* if they don't fit.
|
||||
*/
|
||||
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.
|
||||
@ -906,24 +923,6 @@ protected:
|
||||
*/
|
||||
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
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* @brief Notify child about mode change.
|
||||
*/
|
||||
virtual void modeChanged(void);
|
||||
|
||||
/**
|
||||
* Enable the reply checking for a command
|
||||
*
|
||||
@ -963,6 +957,45 @@ protected:
|
||||
uint8_t expectedReplies = 1, bool useAlternateId = false,
|
||||
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
|
||||
* @return
|
||||
@ -972,12 +1005,7 @@ protected:
|
||||
* #switches are off
|
||||
* - @c PowerSwitchIF::RETURN_FAILED if an error occured
|
||||
*/
|
||||
ReturnValue_t getStateOfSwitches(void);
|
||||
|
||||
/**
|
||||
* build a list of sids and pass it to the #hkSwitcher
|
||||
*/
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
ReturnValue_t getStateOfSwitches();
|
||||
|
||||
/**
|
||||
* Children can overwrite this function to suppress checking of the
|
||||
@ -995,17 +1023,14 @@ protected:
|
||||
|
||||
bool isAwaitingReply();
|
||||
|
||||
void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t commandId,
|
||||
bool neverInDataPool = false, bool forceDirectTm = false);
|
||||
void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId,
|
||||
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,
|
||||
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);
|
||||
|
||||
/**
|
||||
@ -1023,23 +1048,6 @@ protected:
|
||||
*/
|
||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
||||
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.
|
||||
@ -1062,6 +1070,7 @@ protected:
|
||||
* @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON
|
||||
*/
|
||||
void commandSwitch(ReturnValue_t onOff);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
@ -1151,7 +1160,6 @@ private:
|
||||
|
||||
void buildRawDeviceCommand(CommandMessage* message);
|
||||
void buildInternalCommand(void);
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
void decrementDeviceReplyMap(void);
|
||||
|
||||
/**
|
||||
* Convenience function to handle a reply.
|
||||
*
|
||||
@ -1174,8 +1181,8 @@ private:
|
||||
* @foundLen the length of the packet
|
||||
*/
|
||||
void handleReply(const uint8_t *data, DeviceCommandId_t id, uint32_t foundLen);
|
||||
|
||||
void replyToReply(DeviceReplyMap::iterator iter, ReturnValue_t status);
|
||||
|
||||
/**
|
||||
* Build and send a command to the device.
|
||||
*
|
||||
@ -1190,7 +1197,6 @@ private:
|
||||
* sends the command via RMAP.
|
||||
*/
|
||||
void doSendWrite(void);
|
||||
|
||||
/**
|
||||
* Check if the RMAP sendWrite action was successful.
|
||||
*
|
||||
@ -1200,7 +1206,6 @@ private:
|
||||
* - if the action was successful, the reply timout counter is initialized
|
||||
*/
|
||||
void doGetWrite(void);
|
||||
|
||||
/**
|
||||
* Send a RMAP getRead command.
|
||||
*
|
||||
@ -1208,7 +1213,6 @@ private:
|
||||
* This is always executed, independently from the current mode.
|
||||
*/
|
||||
void doSendRead(void);
|
||||
|
||||
/**
|
||||
* Check the getRead reply and the contained data.
|
||||
*
|
||||
@ -1238,14 +1242,12 @@ private:
|
||||
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();
|
||||
|
||||
ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message);
|
||||
|
||||
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
|
||||
virtual dur_millis_t getPeriodicOperationFrequency() const override;
|
||||
|
||||
void parseReply(const uint8_t* receivedData,
|
||||
@ -1254,6 +1256,13 @@ private:
|
||||
void handleTransitionToOnMode(Mode_t commandedMode,
|
||||
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,
|
||||
const char* functionName,
|
||||
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
||||
|
@ -209,20 +209,20 @@ void DeviceHandlerFailureIsolation::startRecovery(Event reason) {
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
|
||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
||||
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t result = strangeReplyCount.getParameter(domainId, parameterId,
|
||||
ReturnValue_t result = strangeReplyCount.getParameter(domainId, uniqueId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
return result;
|
||||
}
|
||||
result = missedReplyCount.getParameter(domainId, parameterId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
result = missedReplyCount.getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||
startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
return result;
|
||||
}
|
||||
result = recoveryCounter.getParameter(domainId, parameterId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
result = recoveryCounter.getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||
startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
return result;
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ public:
|
||||
ReturnValue_t initialize();
|
||||
void triggerEvent(Event event, uint32_t parameter1 = 0,
|
||||
uint32_t parameter2 = 0);bool isFdirActionInProgress();
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex);
|
||||
|
||||
protected:
|
||||
FaultCounter strangeReplyCount;
|
||||
|
3
doc/doxy/.gitignore
vendored
Normal file
3
doc/doxy/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
html
|
||||
latex
|
||||
rtf
|
2609
doc/doxy/OPUS.doxyfile
Normal file
2609
doc/doxy/OPUS.doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
|
||||
MessageQueueId_t EventManagerIF::eventmanagerQueue = MessageQueueIF::NO_QUEUE;
|
||||
|
||||
// If one checks registerListener calls, there are around 40 (to max 50)
|
||||
// objects registering for certain events.
|
||||
|
@ -1,11 +1,12 @@
|
||||
#ifndef EVENTMANAGERIF_H_
|
||||
#define EVENTMANAGERIF_H_
|
||||
#ifndef FSFW_EVENTS_EVENTMANAGERIF_H_
|
||||
#define FSFW_EVENTS_EVENTMANAGERIF_H_
|
||||
|
||||
#include "EventMessage.h"
|
||||
#include "eventmatching/eventmatching.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../ipc/MessageQueueSenderIF.h"
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
|
||||
class EventManagerIF {
|
||||
public:
|
||||
@ -41,11 +42,19 @@ public:
|
||||
|
||||
static void triggerEvent(EventMessage* message,
|
||||
MessageQueueId_t sentFrom = 0) {
|
||||
static MessageQueueId_t eventmanagerQueue = MessageQueueIF::NO_QUEUE;
|
||||
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
|
||||
EventManagerIF *eventmanager = objectManager->get<EventManagerIF>(
|
||||
objects::EVENT_MANAGER);
|
||||
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;
|
||||
}
|
||||
eventmanagerQueue = eventmanager->getEventReportQueue();
|
||||
@ -53,6 +62,10 @@ public:
|
||||
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_ */
|
||||
|
@ -58,14 +58,14 @@ FaultCounter::FaultCounter() :
|
||||
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,
|
||||
uint16_t startAtIndex) {
|
||||
if (domainId != parameterDomain) {
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
|
||||
switch (parameterId) {
|
||||
switch (uniqueId) {
|
||||
case 0:
|
||||
parameterWrapper->set(failureThreshold);
|
||||
break;
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
void setFailureThreshold(uint32_t failureThreshold);
|
||||
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,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
|
@ -176,7 +176,7 @@ void HousekeepingMessage::setUpdateNotificationVariableCommand(
|
||||
|
||||
void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
|
||||
sid_t sid, store_address_t storeId) {
|
||||
command->setCommand(UPDATE_SNAPSHOT_VARIABLE);
|
||||
command->setCommand(UPDATE_SNAPSHOT_SET);
|
||||
setSid(command, sid);
|
||||
command->setParameter3(storeId.raw);
|
||||
}
|
||||
|
@ -1,24 +1,37 @@
|
||||
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_
|
||||
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_
|
||||
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
|
||||
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
|
||||
|
||||
#include "../serialize/SerialBufferAdapter.h"
|
||||
#include "../serialize/SerialLinkedListAdapter.h"
|
||||
#include "../datapoollocal/LocalPoolDataSetBase.h"
|
||||
#include "../datapoollocal/LocalPoolObjectBase.h"
|
||||
#include "../timemanager/CCSDSTime.h"
|
||||
|
||||
/**
|
||||
* @brief This helper class will be used to serialize and deserialize
|
||||
* update housekeeping packets into the store.
|
||||
* @brief This helper class will be used to serialize and deserialize update housekeeping packets
|
||||
* into the store.
|
||||
*/
|
||||
class HousekeepingPacketUpdate: public SerializeIF {
|
||||
class HousekeepingSnapshot: public SerializeIF {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Update packet constructor for datasets
|
||||
* @param timeStamp
|
||||
* @param timeStampSize
|
||||
* @param hkData
|
||||
* @param hkDataSize
|
||||
* Update packet constructor for datasets.
|
||||
* @param cdsShort If a CSD short timestamp is used, a reference should be
|
||||
* supplied here
|
||||
* @param dataSetPtr Pointer to the dataset instance to serialize or deserialize the
|
||||
* 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):
|
||||
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
||||
updateData(dataSetPtr) {};
|
||||
@ -29,7 +42,7 @@ public:
|
||||
* @param timeStampSize
|
||||
* @param dataSetPtr
|
||||
*/
|
||||
HousekeepingPacketUpdate(uint8_t* timeStamp, size_t timeStampSize,
|
||||
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize,
|
||||
LocalPoolObjectBase* dataSetPtr):
|
||||
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
||||
updateData(dataSetPtr) {};
|
||||
@ -89,4 +102,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_ */
|
||||
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_ */
|
@ -37,16 +37,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex) {
|
||||
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.
|
||||
if (result != this->INVALID_IDENTIFIER_ID) {
|
||||
return result;
|
||||
}
|
||||
switch (parameterId) {
|
||||
switch (uniqueId) {
|
||||
case 10:
|
||||
parameterWrapper->set(this->lowerLimit);
|
||||
break;
|
||||
|
@ -51,13 +51,13 @@ public:
|
||||
return state;
|
||||
}
|
||||
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex) {
|
||||
if (domainId != monitorId) {
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
switch (parameterId) {
|
||||
switch (uniqueId) {
|
||||
case 0:
|
||||
parameterWrapper->set(this->confirmationLimit);
|
||||
break;
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "../serialize/SerialFixedArrayListAdapter.h"
|
||||
#include "../serialize/SerializeElement.h"
|
||||
#include "../serialize/SerialLinkedListAdapter.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include "../timemanager/TimeStamperIF.h"
|
||||
|
||||
namespace Factory{
|
||||
|
@ -71,13 +71,13 @@ public:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex) {
|
||||
if (domainId != this->domainId) {
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
switch (parameterId) {
|
||||
switch (uniqueId) {
|
||||
case 0:
|
||||
parameterWrapper->set(limit);
|
||||
break;
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "ObjectManager.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
#include <iomanip>
|
||||
@ -75,6 +75,8 @@ void ObjectManager::initialize() {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "ObjectManager::initialize: Passed produceObjects "
|
||||
"functions is nullptr!" << std::endl;
|
||||
#else
|
||||
sif::printError("ObjectManager::initialize: Passed produceObjects functions is nullptr!\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -5,14 +5,18 @@
|
||||
SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) :
|
||||
objectId(setObjectId), registered(doRegister) {
|
||||
if (registered) {
|
||||
if(objectManager != nullptr) {
|
||||
objectManager->insert(objectId, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SystemObject::~SystemObject() {
|
||||
if (registered) {
|
||||
if(objectManager != nullptr) {
|
||||
objectManager->remove(objectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object_id_t SystemObject::getObjectId() const {
|
||||
|
@ -1,8 +1,11 @@
|
||||
#ifndef FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
|
||||
#define FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
|
||||
|
||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||
|
||||
namespace objects {
|
||||
enum framework_objects {
|
||||
enum framework_objects: object_id_t {
|
||||
FSFW_OBJECTS_START = 0x53000000,
|
||||
// Default verification reporter.
|
||||
PUS_SERVICE_1_VERIFICATION = 0x53000001,
|
||||
PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002,
|
||||
@ -11,11 +14,12 @@ enum framework_objects {
|
||||
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
||||
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
||||
PUS_SERVICE_17_TEST = 0x53000017,
|
||||
PUS_SERVICE_20_PARAMETERS = 0x53000020,
|
||||
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
|
||||
|
||||
//Generic IDs for IPC, modes, health, events
|
||||
HEALTH_TABLE = 0x53010000,
|
||||
// MODE_STORE = 0x53010100,
|
||||
// MODE_STORE = 0x53010100,
|
||||
EVENT_MANAGER = 0x53030000,
|
||||
INTERNAL_ERROR_REPORTER = 0x53040000,
|
||||
IPC_STORE = 0x534f0300,
|
||||
@ -24,6 +28,7 @@ enum framework_objects {
|
||||
TM_STORE = 0x534f0200,
|
||||
TIME_STAMPER = 0x53500010,
|
||||
|
||||
FSFW_OBJECTS_END = 0x53ffffff,
|
||||
NO_OBJECT = 0xFFFFFFFF
|
||||
};
|
||||
}
|
||||
|
@ -25,7 +25,8 @@
|
||||
#else
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
|
||||
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
|
||||
#else
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#if defined(WIN32)
|
||||
#include <windows.h>
|
||||
#include <sysinfoapi.h>
|
||||
#elif defined(LINUX)
|
||||
#include <fstream>
|
||||
#endif
|
||||
@ -15,35 +15,34 @@ using SystemClock = std::chrono::system_clock;
|
||||
|
||||
uint32_t Clock::getTicksPerSecond(void){
|
||||
#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
|
||||
return 0;
|
||||
//return CLOCKS_PER_SEC;
|
||||
//uint32_t ticks = sysconf(_SC_CLK_TCK);
|
||||
//return ticks;
|
||||
/* To avoid division by zero */
|
||||
return 1;
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||
// do some magic with chrono
|
||||
#if defined(WIN32)
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
#elif defined(LINUX)
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
#else
|
||||
|
||||
#endif
|
||||
/* 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
|
||||
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
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
@ -53,8 +52,7 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
auto epoch = now.time_since_epoch();
|
||||
time->tv_sec = std::chrono::duration_cast<std::chrono::seconds>(epoch).count();
|
||||
auto fraction = now - secondsChrono;
|
||||
time->tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
fraction).count();
|
||||
time->tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(fraction).count();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
#elif defined(LINUX)
|
||||
timespec timeUnix;
|
||||
@ -67,7 +65,9 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
#else
|
||||
#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
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
#endif
|
||||
@ -75,10 +75,11 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||
// do some magic with chrono
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl;
|
||||
#endif
|
||||
if(time == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
using namespace std::chrono;
|
||||
*time = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
@ -120,9 +121,9 @@ ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
|
||||
|
||||
|
||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
// do some magic with chrono (C++20!)
|
||||
// Right now, the library doesn't have the new features yet.
|
||||
// so we work around that for now.
|
||||
/* Do some magic with chrono (C++20!) */
|
||||
/* Right now, the library doesn't have the new features to get the required values yet.
|
||||
so we work around that for now. */
|
||||
auto now = SystemClock::now();
|
||||
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
||||
auto fraction = now - seconds;
|
||||
@ -137,10 +138,6 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
time->second = timeInfo->tm_sec;
|
||||
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
|
||||
time->usecond = usecond.count();
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
//sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl;
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <chrono>
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <windows.h>
|
||||
#include <processthreadsapi.h>
|
||||
#elif defined(LINUX)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
@ -5,13 +5,13 @@ target_sources(${LIB_FSFW_NAME}
|
||||
InitTask.cpp
|
||||
InternalErrorCodes.cpp
|
||||
MessageQueue.cpp
|
||||
MultiObjectTask.cpp
|
||||
PeriodicTask.cpp
|
||||
Mutex.cpp
|
||||
MutexFactory.cpp
|
||||
PollingTask.cpp
|
||||
FixedTimeslotTask.cpp
|
||||
QueueFactory.cpp
|
||||
RtemsBasic.cpp
|
||||
TaskBase.cpp
|
||||
RTEMSTaskBase.cpp
|
||||
TaskFactory.cpp
|
||||
)
|
||||
|
||||
|
@ -104,9 +104,13 @@ ReturnValue_t Clock::getClock_usecs(uint64_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_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) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
|
@ -164,7 +164,7 @@ ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer,
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
if ((*size = *size - MAX_LENGTH_OF_THREAD_NAME) < 0) {
|
||||
if (*size < MAX_LENGTH_OF_THREAD_NAME) {
|
||||
return STREAM_TOO_SHORT;
|
||||
}
|
||||
memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME);
|
||||
|
140
osal/rtems/FixedTimeslotTask.cpp
Normal file
140
osal/rtems/FixedTimeslotTask.cpp
Normal 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);
|
||||
};
|
81
osal/rtems/FixedTimeslotTask.h
Normal file
81
osal/rtems/FixedTimeslotTask.h
Normal 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_ */
|
@ -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);
|
||||
}
|
@ -1,18 +1,20 @@
|
||||
#include "Mutex.h"
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../../serviceinterface/ServiceInterface.h"
|
||||
|
||||
uint8_t Mutex::count = 0;
|
||||
|
||||
Mutex::Mutex() :
|
||||
mutexId(0) {
|
||||
Mutex::Mutex() {
|
||||
rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++;
|
||||
rtems_status_code status = rtems_semaphore_create(mutexName, 1,
|
||||
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
|
||||
&mutexId);
|
||||
if (status != RTEMS_SUCCESSFUL) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Mutex: creation with name, id " << mutexName << ", " << mutexId
|
||||
<< " failed with " << status << std::endl;
|
||||
sif::error << "Mutex::Mutex: Creation with name, id " << mutexName << ", " << mutexId <<
|
||||
" 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
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ public:
|
||||
ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0);
|
||||
ReturnValue_t unlockMutex();
|
||||
private:
|
||||
rtems_id mutexId;
|
||||
rtems_id mutexId = 0;
|
||||
static uint8_t count;
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "../../ipc/MutexFactory.h"
|
||||
#include "Mutex.h"
|
||||
#include "RtemsBasic.h"
|
||||
|
||||
#include "../../ipc/MutexFactory.h"
|
||||
|
||||
|
||||
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
||||
|
||||
|
83
osal/rtems/PeriodicTask.cpp
Normal file
83
osal/rtems/PeriodicTask.cpp
Normal 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);
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
#ifndef FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_
|
||||
#define FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_
|
||||
#ifndef FSFW_OSAL_RTEMS_PERIODICTASK_H_
|
||||
#define FSFW_OSAL_RTEMS_PERIODICTASK_H_
|
||||
|
||||
#include "RTEMSTaskBase.h"
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../tasks/PeriodicTaskIF.h"
|
||||
|
||||
#include "TaskBase.h"
|
||||
#include <vector>
|
||||
|
||||
class ExecutableObjectIF;
|
||||
@ -18,7 +18,7 @@ class ExecutableObjectIF;
|
||||
* @author baetz
|
||||
* @ingroup task_handling
|
||||
*/
|
||||
class MultiObjectTask: public TaskBase, public PeriodicTaskIF {
|
||||
class PeriodicTask: public RTEMSTaskBase, public PeriodicTaskIF {
|
||||
public:
|
||||
/**
|
||||
* @brief Standard constructor of the class.
|
||||
@ -35,13 +35,13 @@ public:
|
||||
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
|
||||
* that shall be assigned.
|
||||
*/
|
||||
MultiObjectTask(const char *name, rtems_task_priority setPriority, size_t setStack, rtems_interval setPeriod,
|
||||
void (*setDeadlineMissedFunc)());
|
||||
PeriodicTask(const char *name, rtems_task_priority setPriority, size_t setStack,
|
||||
rtems_interval setPeriod, void (*setDeadlineMissedFunc)());
|
||||
/**
|
||||
* @brief Currently, the executed object's lifetime is not coupled with the task object's
|
||||
* lifetime, so the destructor is empty.
|
||||
*/
|
||||
virtual ~MultiObjectTask(void);
|
||||
virtual ~PeriodicTask(void);
|
||||
|
||||
/**
|
||||
* @brief The method to start the task.
|
||||
@ -76,7 +76,7 @@ protected:
|
||||
/**
|
||||
* @brief id of the associated OS period
|
||||
*/
|
||||
rtems_id periodId;
|
||||
rtems_id periodId = 0;
|
||||
/**
|
||||
* @brief The pointer to the deadline-missed function.
|
||||
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
||||
@ -104,4 +104,4 @@ protected:
|
||||
void taskFunctionality(void);
|
||||
};
|
||||
|
||||
#endif /* FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ */
|
||||
#endif /* FSFW_OSAL_RTEMS_PERIODICTASK_H_ */
|
@ -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);
|
||||
};
|
@ -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_ */
|
@ -1,9 +1,9 @@
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "TaskBase.h"
|
||||
#include "RTEMSTaskBase.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) {
|
||||
rtems_name osalName = 0;
|
||||
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.
|
||||
rtems_status_code status = RTEMS_UNSATISFIED;
|
||||
if (set_priority >= 0 && set_priority <= 99) {
|
||||
if (set_priority <= 99) {
|
||||
status = rtems_task_create(osalName,
|
||||
(0xFF - 2 * set_priority), stack_size,
|
||||
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_id TaskBase::getId() {
|
||||
rtems_id RTEMSTaskBase::getId() {
|
||||
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));
|
||||
return convertReturnCode(status);
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t TaskBase::convertReturnCode(rtems_status_code inValue) {
|
||||
ReturnValue_t RTEMSTaskBase::convertReturnCode(rtems_status_code inValue) {
|
||||
switch (inValue) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
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_status_code status = rtems_rate_monotonic_create(periodName, periodId);
|
||||
if (status == RTEMS_SUCCESSFUL) {
|
||||
@ -77,7 +77,7 @@ ReturnValue_t TaskBase::setAndStartPeriod(rtems_interval period, rtems_id *perio
|
||||
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.
|
||||
rtems_status_code status = rtems_rate_monotonic_period(periodId, period + 1);
|
||||
return status;
|
@ -1,5 +1,5 @@
|
||||
#ifndef FSFW_OSAL_RTEMS_TASKBASE_H_
|
||||
#define FSFW_OSAL_RTEMS_TASKBASE_H_
|
||||
#ifndef FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_
|
||||
#define FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_
|
||||
|
||||
#include "RtemsBasic.h"
|
||||
#include "../../tasks/PeriodicTaskIF.h"
|
||||
@ -9,7 +9,7 @@
|
||||
*
|
||||
* @details Task creation base class for rtems.
|
||||
*/
|
||||
class TaskBase {
|
||||
class RTEMSTaskBase {
|
||||
protected:
|
||||
/**
|
||||
* @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 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.
|
||||
*/
|
||||
virtual ~TaskBase();
|
||||
virtual ~RTEMSTaskBase();
|
||||
/**
|
||||
* @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_ */
|
@ -1,5 +1,6 @@
|
||||
#include "RtemsBasic.h"
|
||||
|
||||
// TODO: Can this be removed?
|
||||
|
||||
//ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
|
||||
// if (inValue == RTEMS_SUCCESSFUL) {
|
||||
|
@ -2,12 +2,13 @@
|
||||
#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_
|
||||
|
||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/error.h>
|
||||
#include <rtems/stackchk.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
class RtemsBasic {
|
||||
public:
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "../../tasks/TaskFactory.h"
|
||||
#include "MultiObjectTask.h"
|
||||
#include "PollingTask.h"
|
||||
#include "FixedTimeslotTask.h"
|
||||
#include "PeriodicTask.h"
|
||||
#include "InitTask.h"
|
||||
#include "RtemsBasic.h"
|
||||
|
||||
#include "../../tasks/TaskFactory.h"
|
||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
||||
@ -15,15 +16,21 @@ TaskFactory* TaskFactory::instance() {
|
||||
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();
|
||||
|
||||
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();
|
||||
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) {
|
||||
|
@ -52,9 +52,8 @@ public:
|
||||
return id;
|
||||
}
|
||||
|
||||
static uint32_t getFullParameterId(uint8_t domainId,
|
||||
uint8_t uniqueIdentifier, uint16_t linearIndex) {
|
||||
return (domainId << 24) + (uniqueIdentifier << 16) + linearIndex;
|
||||
static uint32_t getFullParameterId(uint8_t domainId, uint8_t uniqueId, uint16_t linearIndex) {
|
||||
return (domainId << 24) + (uniqueId << 16) + linearIndex;
|
||||
}
|
||||
|
||||
virtual ~HasParametersIF() {}
|
||||
@ -74,9 +73,9 @@ public:
|
||||
* matrix indexes.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId,
|
||||
uint16_t uniqueIdentifier, ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) = 0;
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex) = 0;
|
||||
};
|
||||
|
||||
#endif /* FSFW_PARAMETERS_HASPARAMETERSIF_H_ */
|
||||
|
@ -90,7 +90,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id,
|
||||
const ParameterWrapper* description) {
|
||||
size_t serializedSize = description->getSerializedSize();
|
||||
|
||||
uint8_t *storeElement;
|
||||
uint8_t *storeElement = nullptr;
|
||||
store_address_t address;
|
||||
|
||||
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
|
||||
|
@ -38,7 +38,7 @@ void ParameterMessage::setParameterLoadCommand(CommandMessage* message,
|
||||
store_address_t ParameterMessage::getParameterLoadCommand(
|
||||
const CommandMessage *message, ParameterId_t* parameterId, uint8_t *ptc,
|
||||
uint8_t *pfc, uint8_t *rows, uint8_t *columns) {
|
||||
*parameterId = message->getParameter2();
|
||||
*parameterId = message->getParameter();
|
||||
uint32_t packedParamSettings = message->getParameter3();
|
||||
*ptc = packedParamSettings >> 24 & 0xff;
|
||||
*pfc = packedParamSettings >> 16 & 0xff;
|
||||
|
@ -1,17 +1,19 @@
|
||||
#include "ParameterWrapper.h"
|
||||
#include <FSFWConfig.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
ParameterWrapper::ParameterWrapper() :
|
||||
pointsToStream(false), type(Type::UNKNOWN_TYPE) {
|
||||
}
|
||||
|
||||
ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
||||
void *data) :
|
||||
void *data):
|
||||
pointsToStream(false), type(type), rows(rows), columns(columns),
|
||||
data(data), readonlyData(data) {
|
||||
}
|
||||
|
||||
ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
||||
const void *data) :
|
||||
const void *data):
|
||||
pointsToStream(false), type(type), rows(rows), columns(columns),
|
||||
data(nullptr), readonlyData(data) {
|
||||
}
|
||||
@ -40,8 +42,8 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size,
|
||||
return result;
|
||||
}
|
||||
|
||||
//serialize uses readonlyData, as it is always valid
|
||||
if (readonlyData == NULL) {
|
||||
/* serialize uses readonlyData, as it is always valid */
|
||||
if (readonlyData == nullptr) {
|
||||
return NOT_SET;
|
||||
}
|
||||
switch (type) {
|
||||
@ -75,7 +77,7 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size,
|
||||
result = serializeData<double>(buffer, size, maxSize, streamEndianness);
|
||||
break;
|
||||
default:
|
||||
result = UNKNOW_DATATYPE;
|
||||
result = UNKNOWN_DATATYPE;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
@ -220,22 +222,48 @@ ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize,
|
||||
|
||||
ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
||||
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 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// The smallest allowed value for rows and columns is one.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -289,7 +317,7 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
||||
from->readonlyData, from->rows, from->columns);
|
||||
break;
|
||||
default:
|
||||
result = UNKNOW_DATATYPE;
|
||||
result = UNKNOWN_DATATYPE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,23 @@
|
||||
#include <cstddef>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @brief This wrapper encapsulates the access to parameters provided by HasParametersIF.
|
||||
* @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 {
|
||||
friend class DataPoolParameterWrapper;
|
||||
public:
|
||||
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 READONLY = MAKE_RETURN_CODE(0x03);
|
||||
static const ReturnValue_t TOO_BIG = MAKE_RETURN_CODE(0x04);
|
||||
@ -26,8 +35,7 @@ public:
|
||||
|
||||
ParameterWrapper();
|
||||
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data);
|
||||
ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
||||
const void *data);
|
||||
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, const void *data);
|
||||
virtual ~ParameterWrapper();
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
@ -77,11 +85,23 @@ public:
|
||||
this->pointsToStream = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter function for scalar non-const entries
|
||||
* @tparam T
|
||||
* @param member
|
||||
*/
|
||||
template<typename T>
|
||||
void set(T& member) {
|
||||
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>
|
||||
void set(const T& readonlyMember) {
|
||||
this->set(&readonlyMember, 1, 1);
|
||||
@ -89,12 +109,16 @@ public:
|
||||
|
||||
template<typename T>
|
||||
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>
|
||||
void setVector(const T& member) {
|
||||
this->set(member, 1, sizeof(member)/sizeof(member[0]));
|
||||
/* 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>
|
||||
void setMatrix(T& member) {
|
||||
|
@ -210,15 +210,15 @@ void Fuse::setDataPoolEntriesInvalid() {
|
||||
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,
|
||||
uint16_t startAtIndex) {
|
||||
ReturnValue_t result = currentLimit.getParameter(domainId, parameterId,
|
||||
ReturnValue_t result = currentLimit.getParameter(domainId, uniqueId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
return result;
|
||||
}
|
||||
result = powerMonitor.getParameter(domainId, parameterId, parameterWrapper,
|
||||
result = powerMonitor.getParameter(domainId, uniqueId, parameterWrapper,
|
||||
newValues, startAtIndex);
|
||||
return result;
|
||||
}
|
||||
|
@ -62,9 +62,9 @@ public:
|
||||
ReturnValue_t setHealth(HealthState health);
|
||||
HasHealthIF::HealthState getHealth();
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex);
|
||||
|
||||
private:
|
||||
uint8_t oldFuseState;
|
||||
|
@ -61,13 +61,13 @@ ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, size_t* size,
|
||||
return SerializeAdapter::deSerialize(&max, buffer, size, streamEndianness);
|
||||
}
|
||||
|
||||
ReturnValue_t PowerComponent::getParameter(uint8_t domainId,
|
||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t PowerComponent::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||
uint16_t startAtIndex) {
|
||||
if (domainId != moduleId) {
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
switch (parameterId) {
|
||||
switch (uniqueId) {
|
||||
case 0:
|
||||
parameterWrapper->set<>(min);
|
||||
break;
|
||||
|
@ -31,9 +31,9 @@ public:
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex);
|
||||
private:
|
||||
const object_id_t deviceObjectId = objects::NO_OBJECT;
|
||||
const uint8_t switchId1;
|
||||
|
@ -119,15 +119,15 @@ HasHealthIF::HealthState PowerSensor::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,
|
||||
uint16_t startAtIndex) {
|
||||
ReturnValue_t result = currentLimit.getParameter(domainId, parameterId,
|
||||
ReturnValue_t result = currentLimit.getParameter(domainId, uniqueId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
return result;
|
||||
}
|
||||
result = voltageLimit.getParameter(domainId, parameterId, parameterWrapper,
|
||||
result = voltageLimit.getParameter(domainId, uniqueId, parameterWrapper,
|
||||
newValues, startAtIndex);
|
||||
return result;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
float getPower();
|
||||
ReturnValue_t setHealth(HealthState health);
|
||||
HasHealthIF::HealthState getHealth();
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
private:
|
||||
|
@ -1,12 +1,12 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
CService200ModeCommanding.cpp
|
||||
CService201HealthCommanding.cpp
|
||||
Service17Test.cpp
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
Service1TelecommandVerification.cpp
|
||||
Service2DeviceAccess.cpp
|
||||
Service3Housekeeping.cpp
|
||||
Service5EventReporting.cpp
|
||||
Service8FunctionManagement.cpp
|
||||
Service9TimeManagement.cpp
|
||||
Service17Test.cpp
|
||||
Service20ParameterManagement.cpp
|
||||
CService200ModeCommanding.cpp
|
||||
CService201HealthCommanding.cpp
|
||||
)
|
@ -15,7 +15,7 @@ Service17Test::~Service17Test() {
|
||||
}
|
||||
|
||||
ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
|
||||
switch(subservice){
|
||||
switch(subservice) {
|
||||
case Subservice::CONNECTION_TEST: {
|
||||
TmPacketStored connectionPacket(apid, serviceId,
|
||||
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);
|
||||
|
186
pus/Service20ParameterManagement.cpp
Normal file
186
pus/Service20ParameterManagement.cpp
Normal 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(¶meterId, &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), ¶meterReply);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
default:
|
||||
return CommandingServiceBase::INVALID_REPLY;
|
||||
}
|
||||
}
|
60
pus/Service20ParameterManagement.h
Normal file
60
pus/Service20ParameterManagement.h
Normal 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_ */
|
@ -104,12 +104,14 @@ ReturnValue_t Service8FunctionManagement::handleReply(
|
||||
break;
|
||||
}
|
||||
case ActionMessage::DATA_REPLY: {
|
||||
/* Multiple data replies are possible, so declare data reply as step */
|
||||
*isStep = true;
|
||||
result = handleDataReply(reply, objectId, actionId);
|
||||
break;
|
||||
}
|
||||
case ActionMessage::STEP_FAILED:
|
||||
*isStep = true;
|
||||
/*No break, falls through*/
|
||||
/* No break, falls through */
|
||||
case ActionMessage::COMPLETION_FAILED:
|
||||
result = ActionMessage::getReturnCode(reply);
|
||||
break;
|
||||
|
142
pus/servicepackets/Service20Packets.h
Normal file
142
pus/servicepackets/Service20Packets.h
Normal 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(¶meterId);
|
||||
parameterId.setNext(&ccsdsType);
|
||||
ccsdsType.setNext(&rows);
|
||||
rows.setNext(&columns);
|
||||
columns.setNext(¶meterBuffer);
|
||||
}
|
||||
|
||||
void setDumpReplyLinks() {
|
||||
/* For a dump reply, the parameter information is contained in the parameter buffer
|
||||
with the actual parameters */
|
||||
setStart(&objectId);
|
||||
objectId.setNext(¶meterId);
|
||||
parameterId.setNext(¶meterBuffer);
|
||||
}
|
||||
|
||||
void setDumpRequestLinks() {
|
||||
setStart(&objectId);
|
||||
objectId.setNext(¶meterId);
|
||||
}
|
||||
|
||||
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_ */
|
@ -29,7 +29,7 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage,
|
||||
|
||||
#if FSFW_COLORED_OUTPUT == 1
|
||||
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) {
|
||||
colorPrefix = sif::ANSI_COLOR_GREEN;
|
||||
|
@ -45,7 +45,7 @@ void fsfwPrint(sif::PrintLevel printType, const char* fmt, va_list arg) {
|
||||
len += sprintf(bufferPosition, sif::ANSI_COLOR_GREEN);
|
||||
}
|
||||
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) {
|
||||
len += sprintf(bufferPosition, sif::ANSI_COLOR_YELLOW);
|
||||
|
@ -39,6 +39,11 @@ public:
|
||||
*/
|
||||
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;
|
||||
|
||||
protected:
|
||||
|
@ -5,15 +5,15 @@
|
||||
LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig,
|
||||
bool registered, bool spillsToHigherPools):
|
||||
SystemObject(setObjectId, registered),
|
||||
NUMBER_OF_POOLS(poolConfig.size()),
|
||||
NUMBER_OF_SUBPOOLS(poolConfig.size()),
|
||||
spillsToHigherPools(spillsToHigherPools) {
|
||||
if(NUMBER_OF_POOLS == 0) {
|
||||
if(NUMBER_OF_SUBPOOLS == 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LocalPool::LocalPool: Passed pool configuration is "
|
||||
<< " invalid!" << std::endl;
|
||||
#endif
|
||||
}
|
||||
max_pools_t index = 0;
|
||||
max_subpools_t index = 0;
|
||||
for (const auto& currentPoolConfig: poolConfig) {
|
||||
this->numberOfElements[index] = currentPoolConfig.first;
|
||||
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,
|
||||
uint8_t **packetPtr, size_t *size) {
|
||||
ReturnValue_t status = RETURN_FAILED;
|
||||
if (storeId.poolIndex >= NUMBER_OF_POOLS) {
|
||||
if (storeId.poolIndex >= NUMBER_OF_SUBPOOLS) {
|
||||
return ILLEGAL_STORAGE_ID;
|
||||
}
|
||||
if ((storeId.packetIndex >= numberOfElements[storeId.poolIndex])) {
|
||||
@ -127,7 +127,7 @@ ReturnValue_t LocalPool::deleteData(store_address_t storeId) {
|
||||
|
||||
#endif
|
||||
ReturnValue_t status = RETURN_OK;
|
||||
size_type pageSize = getPageSize(storeId.poolIndex);
|
||||
size_type pageSize = getSubpoolElementSize(storeId.poolIndex);
|
||||
if ((pageSize != 0) and
|
||||
(storeId.packetIndex < numberOfElements[storeId.poolIndex])) {
|
||||
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 localId;
|
||||
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.
|
||||
if ((store[n].data() <= ptr) and
|
||||
(&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.
|
||||
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 FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LocalPool::initialize: Pool is too large! "
|
||||
@ -217,7 +217,7 @@ void LocalPool::clearStore() {
|
||||
|
||||
ReturnValue_t LocalPool::reserveSpace(const size_t size,
|
||||
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 FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
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);
|
||||
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) {
|
||||
//We don't find any fitting pool anymore.
|
||||
break;
|
||||
@ -263,9 +263,9 @@ void LocalPool::write(store_address_t storeId, const uint8_t *data,
|
||||
sizeLists[storeId.poolIndex][storeId.packetIndex] = size;
|
||||
}
|
||||
|
||||
LocalPool::size_type LocalPool::getPageSize(max_pools_t poolIndex) {
|
||||
if (poolIndex < NUMBER_OF_POOLS) {
|
||||
return elementSizes[poolIndex];
|
||||
LocalPool::size_type LocalPool::getSubpoolElementSize(max_subpools_t subpoolIndex) {
|
||||
if (subpoolIndex < NUMBER_OF_SUBPOOLS) {
|
||||
return elementSizes[subpoolIndex];
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
@ -276,9 +276,9 @@ void LocalPool::setToSpillToHigherPools(bool 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) {
|
||||
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_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "LocalPool " << getObjectId() << "::getPoolIndex: Pool: "
|
||||
@ -286,7 +286,7 @@ ReturnValue_t LocalPool::getPoolIndex(size_t packetSize, uint16_t *poolIndex,
|
||||
#endif
|
||||
#endif
|
||||
if (elementSizes[n] >= packetSize) {
|
||||
*poolIndex = n;
|
||||
*subpoolIndex = n;
|
||||
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 totalSize = 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];
|
||||
sizesSize += numberOfElements[idx] * sizeof(size_type);
|
||||
}
|
||||
@ -331,7 +331,7 @@ void LocalPool::getFillCount(uint8_t *buffer, uint8_t *bytesWritten) {
|
||||
uint16_t reservedHits = 0;
|
||||
uint8_t idx = 0;
|
||||
uint16_t sum = 0;
|
||||
for(; idx < NUMBER_OF_POOLS; idx ++) {
|
||||
for(; idx < NUMBER_OF_SUBPOOLS; idx ++) {
|
||||
for(const auto& size: sizeLists[idx]) {
|
||||
if(size != STORAGE_FREE) {
|
||||
reservedHits++;
|
||||
@ -343,21 +343,25 @@ void LocalPool::getFillCount(uint8_t *buffer, uint8_t *bytesWritten) {
|
||||
sum += buffer[idx];
|
||||
reservedHits = 0;
|
||||
}
|
||||
buffer[idx] = sum / NUMBER_OF_POOLS;
|
||||
buffer[idx] = sum / NUMBER_OF_SUBPOOLS;
|
||||
*bytesWritten += 1;
|
||||
}
|
||||
|
||||
|
||||
void LocalPool::clearPage(max_pools_t pageIndex) {
|
||||
if(pageIndex >= NUMBER_OF_POOLS) {
|
||||
void LocalPool::clearSubPool(max_subpools_t subpoolIndex) {
|
||||
if(subpoolIndex >= NUMBER_OF_SUBPOOLS) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark the storage as free
|
||||
for(auto& size: sizeLists[pageIndex]) {
|
||||
for(auto& size: sizeLists[subpoolIndex]) {
|
||||
size = STORAGE_FREE;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
@ -60,15 +60,6 @@ public:
|
||||
};
|
||||
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.
|
||||
* @details
|
||||
@ -143,9 +134,15 @@ public:
|
||||
void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) override;
|
||||
|
||||
void clearStore() override;
|
||||
void clearPage(max_pools_t pageIndex) override;
|
||||
void clearSubPool(max_subpools_t poolIndex) 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:
|
||||
/**
|
||||
* With this helper method, a free element of @c size is reserved.
|
||||
@ -158,6 +155,16 @@ protected:
|
||||
store_address_t* address, bool ignoreFault);
|
||||
|
||||
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.
|
||||
* This value limits the maximum size of a pool.
|
||||
@ -170,20 +177,20 @@ private:
|
||||
* must be set in ascending order on construction.
|
||||
*/
|
||||
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.
|
||||
* @details These numbers are maintained for internal pool management.
|
||||
*/
|
||||
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.
|
||||
* @details It is an array of pointers to memory, which was allocated with
|
||||
* a @c new call on construction.
|
||||
*/
|
||||
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.
|
||||
@ -191,7 +198,7 @@ private:
|
||||
* is also dynamically allocated there.
|
||||
*/
|
||||
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
|
||||
//! the store is full.
|
||||
@ -210,7 +217,7 @@ private:
|
||||
* @param pool_index The pool in which to look.
|
||||
* @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.
|
||||
@ -221,7 +228,7 @@ private:
|
||||
* @return - @c RETURN_OK on success,
|
||||
* - @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);
|
||||
/**
|
||||
* @brief This helper method calculates the true array position in store
|
||||
|
@ -29,7 +29,7 @@ using ConstAccessorPair = std::pair<ReturnValue_t, ConstStorageAccessor>;
|
||||
class StorageManagerIF : public HasReturnvaluesIF {
|
||||
public:
|
||||
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 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,
|
||||
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
|
||||
* 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!
|
||||
* @param storageId A pointer to the storageId to retrieve.
|
||||
* @param size The size of the space to be reserved.
|
||||
@ -171,20 +171,29 @@ public:
|
||||
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
|
||||
*/
|
||||
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
|
||||
* dependant.
|
||||
* Get the fill count of the pool. Each character inside the provided
|
||||
* 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 bytesWritten
|
||||
* @param maxSize
|
||||
*/
|
||||
virtual void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) = 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_ */
|
||||
|
@ -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,
|
||||
uint16_t startAtIndex) {
|
||||
if (domainId != DOMAIN_ID_BASE) {
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
switch (parameterId) {
|
||||
switch (uniqueId) {
|
||||
case 0:
|
||||
parameterWrapper->set(heaterOnCountdown.timeout);
|
||||
break;
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
|
||||
MessageQueueId_t getCommandQueue() const;
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
|
@ -183,10 +183,10 @@ public:
|
||||
|
||||
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,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t result = sensorMonitor.getParameter(domainId, parameterId,
|
||||
ReturnValue_t result = sensorMonitor.getParameter(domainId, uniqueId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
return result;
|
||||
@ -194,7 +194,7 @@ public:
|
||||
if (domainId != this->DOMAIN_ID_BASE) {
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
switch (parameterId) {
|
||||
switch (uniqueId) {
|
||||
case ADDRESS_A:
|
||||
parameterWrapper->set(parameters.a);
|
||||
break;
|
||||
|
@ -148,14 +148,14 @@ ThermalComponentIF::State ThermalComponent::getIgnoredState(int8_t state) {
|
||||
}
|
||||
|
||||
ReturnValue_t ThermalComponent::getParameter(uint8_t domainId,
|
||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
||||
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t result = ThermalComponentCore::getParameter(domainId, parameterId,
|
||||
ReturnValue_t result = ThermalComponentCore::getParameter(domainId, uniqueId,
|
||||
parameterWrapper, newValues, startAtIndex);
|
||||
if (result != INVALID_IDENTIFIER_ID) {
|
||||
return result;
|
||||
}
|
||||
switch (parameterId) {
|
||||
switch (uniqueId) {
|
||||
case 12:
|
||||
parameterWrapper->set(nopParameters.lowerNopLimit);
|
||||
break;
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
|
||||
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,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
|
@ -247,17 +247,17 @@ ThermalComponentCore::Parameters ThermalComponentCore::getParameters() {
|
||||
}
|
||||
|
||||
ReturnValue_t ThermalComponentCore::getParameter(uint8_t domainId,
|
||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
||||
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t result = temperatureMonitor.getParameter(domainId,
|
||||
parameterId, parameterWrapper, newValues, startAtIndex);
|
||||
uniqueId, parameterWrapper, newValues, startAtIndex);
|
||||
if (result != INVALID_DOMAIN_ID) {
|
||||
return result;
|
||||
}
|
||||
if (domainId != this->domainId) {
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
switch (parameterId) {
|
||||
switch (uniqueId) {
|
||||
case 0:
|
||||
parameterWrapper->set(parameters.heaterOn);
|
||||
break;
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
|
||||
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,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "Stopwatch.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
#include <iomanip>
|
||||
#endif
|
||||
|
||||
Stopwatch::Stopwatch(bool displayOnDestruction,
|
||||
StopwatchDisplayMode displayMode): displayOnDestruction(
|
||||
@ -28,9 +31,13 @@ double Stopwatch::stopSeconds() {
|
||||
|
||||
void Stopwatch::display() {
|
||||
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
|
||||
sif::info << "Stopwatch: Operation took " << (elapsedTime.tv_sec * 1000 +
|
||||
elapsedTime.tv_usec / 1000) << " milliseconds" << std::endl;
|
||||
sif::info << "Stopwatch: Operation took " << timeMillis << " milliseconds" << std::endl;
|
||||
#else
|
||||
sif::printInfo("Stopwatch: Operation took %lu milliseconds\n\r",
|
||||
static_cast<unsigned int>(timeMillis));
|
||||
#endif
|
||||
}
|
||||
else if(displayMode == StopwatchDisplayMode::SECONDS) {
|
||||
@ -38,6 +45,9 @@ void Stopwatch::display() {
|
||||
sif::info <<"Stopwatch: Operation took " << std::setprecision(3)
|
||||
<< std::fixed << timevalOperations::toDouble(elapsedTime)
|
||||
<< " seconds" << std::endl;
|
||||
#else
|
||||
sif::printInfo("Stopwatch: Operation took %.3f seconds\n\r",
|
||||
static_cast<float>(timevalOperations::toDouble(elapsedTime)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "TmTcBridge.h"
|
||||
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
#include "../globalfunctions/arrayprinter.h"
|
||||
|
||||
TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||
@ -109,9 +109,8 @@ ReturnValue_t TmTcBridge::handleTm() {
|
||||
ReturnValue_t result = handleTmQueue();
|
||||
if(result != RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmTcBridge::handleTm: Error handling TM queue with "
|
||||
<< "error code 0x" << std::hex << result << std::dec
|
||||
<< "!" << std::endl;
|
||||
sif::error << "TmTcBridge::handleTm: Error handling TM queue with error code 0x" <<
|
||||
std::hex << result << std::dec << "!" << std::endl;
|
||||
#endif
|
||||
status = result;
|
||||
}
|
||||
@ -121,8 +120,7 @@ ReturnValue_t TmTcBridge::handleTm() {
|
||||
result = handleStoredTm();
|
||||
if(result != RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "TmTcBridge::handleTm: Error handling stored TMs!"
|
||||
<< std::endl;
|
||||
sif::error << "TmTcBridge::handleTm: Error handling stored TMs!" << std::endl;
|
||||
#endif
|
||||
status = result;
|
||||
}
|
||||
@ -140,9 +138,15 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
|
||||
result == HasReturnvaluesIF::RETURN_OK;
|
||||
result = tmTcReceptionQueue->receiveMessage(&message))
|
||||
{
|
||||
|
||||
#if FSFW_VERBOSE_LEVEL >= 3
|
||||
#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 /* FSFW_VERBOSE_LEVEL >= 3 */
|
||||
|
||||
if(communicationLinkUp == false or
|
||||
packetSentCounter >= sentPacketsPerCycle) {
|
||||
storeDownlinkData(&message);
|
||||
|
@ -1,10 +1,16 @@
|
||||
#include "LocalPoolOwnerBase.h"
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/catch_approx.hpp>
|
||||
|
||||
#include <fsfw/datapool/PoolReadHelper.h>
|
||||
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
#include <fsfw/housekeeping/HousekeepingSnapshot.h>
|
||||
#include <fsfw/ipc/CommandMessageCleaner.h>
|
||||
#include <fsfw/timemanager/CCSDSTime.h>
|
||||
#include <unittest/core/CatchDefinitions.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
||||
@ -14,7 +20,7 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
||||
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
|
||||
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
|
||||
== retval::CATCH_OK);
|
||||
REQUIRE(poolOwner->dataset.assignPointers() == retval::CATCH_OK);
|
||||
//REQUIRE(poolOwner->dataset.assignPointers() == retval::CATCH_OK);
|
||||
MessageQueueMockBase* mqMock = poolOwner->getMockQueueHandle();
|
||||
REQUIRE(mqMock != nullptr);
|
||||
CommandMessage messageSent;
|
||||
@ -22,11 +28,11 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
||||
|
||||
|
||||
SECTION("BasicTest") {
|
||||
// Subscribe for message generation on update.
|
||||
/* Subscribe for message generation on update. */
|
||||
REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK);
|
||||
// Subscribe for an update message.
|
||||
/* Subscribe for an update message. */
|
||||
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(mqMock->wasMessageSent() == true);
|
||||
|
||||
@ -34,9 +40,9 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
|
||||
|
||||
// Should have been reset.
|
||||
/* Should have been reset. */
|
||||
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);
|
||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||
|
||||
@ -46,14 +52,14 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||
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);
|
||||
poolOwner->dataset.setChanged(true);
|
||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
||||
CHECK(messagesSent == 2);
|
||||
// first message sent should be the update notification, considering
|
||||
// the internal list is a vector checked in insertion order.
|
||||
/* first message sent should be the update notification, considering
|
||||
the internal list is a vector checked in insertion order. */
|
||||
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
|
||||
@ -61,16 +67,82 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
||||
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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") {
|
||||
// we need to reset the subscription list because the pool owner
|
||||
// is a global object.
|
||||
poolOwner->resetSubscriptionList();
|
||||
// Subscribe for variable update as well
|
||||
REQUIRE(not poolOwner->dataset.hasChanged());
|
||||
/* Acquire subscription interface */
|
||||
ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner->getSubscriptionInterface();
|
||||
REQUIRE(subscriptionIF != nullptr);
|
||||
|
||||
/* Subscribe for variable update */
|
||||
REQUIRE(poolOwner->subscribeWrapperVariableUpdate(lpool::uint8VarId) ==
|
||||
retval::CATCH_OK);
|
||||
lp_var_t<uint8_t>* poolVar = dynamic_cast<lp_var_t<uint8_t>*>(
|
||||
@ -79,22 +151,22 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
||||
poolVar->setChanged(true);
|
||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||
|
||||
// Check update notification was sent.
|
||||
/* Check update notification was sent. */
|
||||
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
||||
CHECK(messagesSent == 1);
|
||||
// Should have been reset.
|
||||
/* Should have been reset. */
|
||||
CHECK(poolVar->hasChanged() == false);
|
||||
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||
HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
|
||||
|
||||
// now subscribe for the dataset update (HK and update) again
|
||||
REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK);
|
||||
/* Now subscribe for the dataset update (HK and update) again with subscription interface */
|
||||
REQUIRE(subscriptionIF->subscribeForSetUpdateMessages(lpool::testSetId,
|
||||
objects::NO_OBJECT, objects::HK_RECEIVER_MOCK, false) == retval::CATCH_OK);
|
||||
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
|
||||
|
||||
poolOwner->dataset.setChanged(true);
|
||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||
// now two messages should be sent.
|
||||
/* Now two messages should be sent. */
|
||||
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
||||
CHECK(messagesSent == 2);
|
||||
mqMock->clearMessages(true);
|
||||
@ -102,7 +174,7 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
||||
poolOwner->dataset.setChanged(true);
|
||||
poolVar->setChanged(true);
|
||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||
// now three messages should be sent.
|
||||
/* Now three messages should be sent. */
|
||||
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
||||
CHECK(messagesSent == 3);
|
||||
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
||||
@ -115,8 +187,12 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||
HousekeepingMessage::HK_REPORT));
|
||||
CommandMessageCleaner::clearCommandMessage(&messageSent);
|
||||
REQUIRE(mqMock->receiveMessage(&messageSent) ==
|
||||
static_cast<int>(MessageQueueIF::EMPTY));
|
||||
REQUIRE(mqMock->receiveMessage(&messageSent) == 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);
|
||||
}
|
||||
|
||||
|
@ -20,33 +20,43 @@ static constexpr lp_id_t int64Vec2Id = 4;
|
||||
|
||||
static constexpr uint32_t testSetId = 0;
|
||||
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 {
|
||||
public:
|
||||
LocalPoolTestDataSet():
|
||||
LocalDataSet(lpool::testSid, lpool::dataSetMaxVariables) {
|
||||
}
|
||||
|
||||
LocalPoolTestDataSet(HasLocalDataPoolIF* owner, uint32_t setId):
|
||||
LocalDataSet(owner, setId, lpool::dataSetMaxVariables) {
|
||||
}
|
||||
|
||||
ReturnValue_t assignPointers() {
|
||||
PoolVariableIF** rawVarArray = getContainer();
|
||||
localPoolVarUint8 = dynamic_cast<lp_var_t<uint8_t>*>(rawVarArray[0]);
|
||||
localPoolVarFloat = dynamic_cast<lp_var_t<float>*>(rawVarArray[1]);
|
||||
localPoolUint16Vec = dynamic_cast<lp_vec_t<uint16_t, 3>*>(
|
||||
rawVarArray[2]);
|
||||
if(localPoolVarUint8 == nullptr or localPoolVarFloat == nullptr or
|
||||
localPoolUint16Vec == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
// ReturnValue_t assignPointers() {
|
||||
// PoolVariableIF** rawVarArray = getContainer();
|
||||
// localPoolVarUint8 = dynamic_cast<lp_var_t<uint8_t>*>(rawVarArray[0]);
|
||||
// localPoolVarFloat = dynamic_cast<lp_var_t<float>*>(rawVarArray[1]);
|
||||
// localPoolUint16Vec = dynamic_cast<lp_vec_t<uint16_t, 3>*>(
|
||||
// rawVarArray[2]);
|
||||
// if(localPoolVarUint8 == nullptr or localPoolVarFloat == nullptr or
|
||||
// localPoolUint16Vec == nullptr) {
|
||||
// return HasReturnvaluesIF::RETURN_FAILED;
|
||||
// }
|
||||
// return HasReturnvaluesIF::RETURN_OK;
|
||||
// }
|
||||
|
||||
lp_var_t<uint8_t>* localPoolVarUint8 = nullptr;
|
||||
lp_var_t<float>* localPoolVarFloat = nullptr;
|
||||
lp_vec_t<uint16_t, 3>* localPoolUint16Vec = nullptr;
|
||||
lp_var_t<uint8_t> localPoolVarUint8 = lp_var_t<uint8_t>(lpool::uint8VarGpid, this);
|
||||
lp_var_t<float> localPoolVarFloat = lp_var_t<float>(lpool::floatVarGpid, this);
|
||||
lp_vec_t<uint16_t, 3> localPoolUint16Vec = lp_vec_t<uint16_t, 3>(lpool::uint16Vec3Gpid, this);
|
||||
|
||||
private:
|
||||
};
|
||||
@ -155,7 +165,12 @@ public:
|
||||
|
||||
ReturnValue_t subscribeWrapperSetUpdate() {
|
||||
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) {
|
||||
@ -165,7 +180,7 @@ public:
|
||||
|
||||
ReturnValue_t subscribeWrapperVariableUpdate(lp_id_t localPoolId) {
|
||||
return poolManager.subscribeForVariableUpdateMessages(localPoolId,
|
||||
MessageQueueIF::NO_QUEUE, objects::NO_OBJECT, false);
|
||||
MessageQueueIF::NO_QUEUE, objects::HK_RECEIVER_MOCK, false);
|
||||
}
|
||||
|
||||
void resetSubscriptionList() {
|
||||
|
@ -14,7 +14,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
|
||||
== retval::CATCH_OK);
|
||||
|
||||
SECTION("Basic Tests") {
|
||||
// very basic test.
|
||||
/* very basic test. */
|
||||
lp_var_t<uint8_t> testVariable = lp_var_t<uint8_t>(
|
||||
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
|
||||
REQUIRE(testVariable.read() == retval::CATCH_OK);
|
||||
@ -77,7 +77,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
|
||||
|
||||
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>(
|
||||
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
|
||||
REQUIRE(invalidVariable.read() ==
|
||||
@ -85,7 +85,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
|
||||
|
||||
REQUIRE(invalidVariable.commit() ==
|
||||
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>(
|
||||
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
|
||||
REQUIRE(invalidVariable2.read() ==
|
||||
@ -108,7 +108,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
|
||||
sif::info << "LocalPoolVariable printout: " <<uint32tVar << std::endl;
|
||||
#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>(
|
||||
0xffffffff, lpool::uint8VarId);
|
||||
gp_id_t globPoolId(0xffffffff,
|
||||
|
@ -35,13 +35,13 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
|
||||
|
||||
CHECK(testVector[0] == 5);
|
||||
|
||||
// This is invalid access, so the last value will be set instead.
|
||||
// (we can't throw exceptions)
|
||||
/* This is invalid access, so the last value will be set instead.
|
||||
(we can't throw exceptions) */
|
||||
testVector[4] = 12;
|
||||
CHECK(testVector[2] == 12);
|
||||
CHECK(testVector.commit() == retval::CATCH_OK);
|
||||
|
||||
// Use read-only reference.
|
||||
/* Use read-only reference. */
|
||||
const lp_vec_t<uint16_t, 3>& roTestVec = testVector;
|
||||
uint16_t valueOne = roTestVec[0];
|
||||
CHECK(valueOne == 5);
|
||||
@ -87,7 +87,7 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
|
||||
}
|
||||
|
||||
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>(
|
||||
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
|
||||
REQUIRE(invalidVector.read() ==
|
||||
@ -95,7 +95,7 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
|
||||
REQUIRE(invalidVector.commit() ==
|
||||
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>(
|
||||
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id);
|
||||
REQUIRE(invalidVector2.read() ==
|
||||
|
@ -276,7 +276,7 @@ TEST_CASE( "Local Pool Extended Tests [3 Pools]" , "[TestPool2]") {
|
||||
CHECK(receptionArray[3] == 66);
|
||||
|
||||
// now clear first page
|
||||
simplePool.clearPage(0);
|
||||
simplePool.clearSubPool(0);
|
||||
bytesWritten = 0;
|
||||
simplePool.getFillCount(receptionArray.data(), &bytesWritten);
|
||||
// Second page full, median fill count is 33 %
|
||||
|
Loading…
Reference in New Issue
Block a user