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);
|
result = queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeAddress);
|
ipcStore->deleteData(storeAddress);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -99,7 +99,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setQueueToUse(MessageQueueIF *queue);
|
void setQueueToUse(MessageQueueIF *queue);
|
||||||
protected:
|
protected:
|
||||||
//!< Increase of value of this per step
|
//! Increase of value of this per step
|
||||||
static const uint8_t STEP_OFFSET = 1;
|
static const uint8_t STEP_OFFSET = 1;
|
||||||
HasActionsIF* owner;//!< Pointer to the owner
|
HasActionsIF* owner;//!< Pointer to the owner
|
||||||
//! Queue to be used as response sender, has to be set in ctor or with
|
//! Queue to be used as response sender, has to be set in ctor or with
|
||||||
|
@ -18,7 +18,7 @@ public:
|
|||||||
* This function is protected because it should only be used by the
|
* This function is protected because it should only be used by the
|
||||||
* class imlementing the interface.
|
* class imlementing the interface.
|
||||||
*/
|
*/
|
||||||
virtual LocalDataPoolManager* getHkManagerHandle() = 0;
|
virtual LocalDataPoolManager* getPoolManagerHandle() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#include "internal/LocalPoolDataSetAttorney.h"
|
#include "internal/LocalPoolDataSetAttorney.h"
|
||||||
#include "internal/HasLocalDpIFManagerAttorney.h"
|
#include "internal/HasLocalDpIFManagerAttorney.h"
|
||||||
|
|
||||||
#include "../housekeeping/HousekeepingPacketUpdate.h"
|
|
||||||
#include "../housekeeping/HousekeepingSetPacket.h"
|
#include "../housekeeping/HousekeepingSetPacket.h"
|
||||||
|
#include "../housekeeping/HousekeepingSnapshot.h"
|
||||||
#include "../housekeeping/AcceptsHkPacketsIF.h"
|
#include "../housekeeping/AcceptsHkPacketsIF.h"
|
||||||
#include "../timemanager/CCSDSTime.h"
|
#include "../timemanager/CCSDSTime.h"
|
||||||
#include "../ipc/MutexFactory.h"
|
#include "../ipc/MutexFactory.h"
|
||||||
@ -226,7 +226,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
|||||||
Clock::getClock_timeval(&now);
|
Clock::getClock_timeval(&now);
|
||||||
CCSDSTime::CDS_short cds;
|
CCSDSTime::CDS_short cds;
|
||||||
CCSDSTime::convertToCcsds(&cds, &now);
|
CCSDSTime::convertToCcsds(&cds, &now);
|
||||||
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||||
sizeof(cds), HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
|
sizeof(cds), HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
|
||||||
receiver.dataId.localPoolId));
|
receiver.dataId.localPoolId));
|
||||||
|
|
||||||
@ -264,7 +264,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
|||||||
Clock::getClock_timeval(&now);
|
Clock::getClock_timeval(&now);
|
||||||
CCSDSTime::CDS_short cds;
|
CCSDSTime::CDS_short cds;
|
||||||
CCSDSTime::convertToCcsds(&cds, &now);
|
CCSDSTime::convertToCcsds(&cds, &now);
|
||||||
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||||
sizeof(cds), HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
|
sizeof(cds), HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
|
||||||
receiver.dataId.sid));
|
receiver.dataId.sid));
|
||||||
|
|
||||||
@ -292,7 +292,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalDataPoolManager::addUpdateToStore(
|
ReturnValue_t LocalDataPoolManager::addUpdateToStore(
|
||||||
HousekeepingPacketUpdate& updatePacket, store_address_t& storeId) {
|
HousekeepingSnapshot& updatePacket, store_address_t& storeId) {
|
||||||
size_t updatePacketSize = updatePacket.getSerializedSize();
|
size_t updatePacketSize = updatePacket.getSerializedSize();
|
||||||
uint8_t *storePtr = nullptr;
|
uint8_t *storePtr = nullptr;
|
||||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId,
|
ReturnValue_t result = ipcStore->getFreeElement(&storeId,
|
||||||
@ -890,7 +890,7 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
|||||||
<< std::dec << std::setfill(' ') << std::endl;
|
<< std::dec << std::setfill(' ') << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
||||||
owner->getObjectId(), errorPrint);
|
functionName, owner->getObjectId(), errorPrint);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if(outputType == sif::OutputTypes::OUT_ERROR) {
|
else if(outputType == sif::OutputTypes::OUT_ERROR) {
|
||||||
@ -901,11 +901,11 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
|||||||
<< std::dec << std::setfill(' ') << std::endl;
|
<< std::dec << std::setfill(' ') << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
||||||
owner->getObjectId(), errorPrint);
|
functionName, owner->getObjectId(), errorPrint);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalDataPoolManager* LocalDataPoolManager::getHkManagerHandle() {
|
LocalDataPoolManager* LocalDataPoolManager::getPoolManagerHandle() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ void setStaticFrameworkObjectIds();
|
|||||||
}
|
}
|
||||||
|
|
||||||
class LocalPoolDataSetBase;
|
class LocalPoolDataSetBase;
|
||||||
class HousekeepingPacketUpdate;
|
class HousekeepingSnapshot;
|
||||||
class HasLocalDataPoolIF;
|
class HasLocalDataPoolIF;
|
||||||
class LocalDataPool;
|
class LocalDataPool;
|
||||||
|
|
||||||
@ -52,7 +52,8 @@ class LocalDataPool;
|
|||||||
* Each pool entry has a valid state too.
|
* Each pool entry has a valid state too.
|
||||||
* @author R. Mueller
|
* @author R. Mueller
|
||||||
*/
|
*/
|
||||||
class LocalDataPoolManager: public ProvidesDataPoolSubscriptionIF,
|
class LocalDataPoolManager:
|
||||||
|
public ProvidesDataPoolSubscriptionIF,
|
||||||
public AccessPoolManagerIF {
|
public AccessPoolManagerIF {
|
||||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||||
//! Some classes using the pool manager directly need to access class internals of the
|
//! Some classes using the pool manager directly need to access class internals of the
|
||||||
@ -62,7 +63,6 @@ public:
|
|||||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
|
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
|
||||||
|
|
||||||
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0);
|
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0);
|
||||||
|
|
||||||
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1);
|
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1);
|
||||||
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
|
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
|
||||||
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
|
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
|
||||||
@ -179,8 +179,6 @@ public:
|
|||||||
MessageQueueId_t targetQueueId,
|
MessageQueueId_t targetQueueId,
|
||||||
bool generateSnapshot) override;
|
bool generateSnapshot) override;
|
||||||
|
|
||||||
MutexIF* getLocalPoolMutex() override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
||||||
* than diagnostic packets.
|
* than diagnostic packets.
|
||||||
@ -243,12 +241,9 @@ public:
|
|||||||
UPDATE_SNAPSHOT,
|
UPDATE_SNAPSHOT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/** Different data types are possible in the HK receiver map. For example, updates can be
|
||||||
* Different data types are possible in the HK receiver map.
|
requested for full datasets or for single pool variables. Periodic reporting is only possible
|
||||||
* For example, updates can be requested for full datasets or
|
for data sets. */
|
||||||
* for single pool variables. Periodic reporting is only possible for
|
|
||||||
* data sets.
|
|
||||||
*/
|
|
||||||
enum class DataType: uint8_t {
|
enum class DataType: uint8_t {
|
||||||
LOCAL_POOL_VARIABLE,
|
LOCAL_POOL_VARIABLE,
|
||||||
DATA_SET
|
DATA_SET
|
||||||
@ -267,11 +262,19 @@ public:
|
|||||||
|
|
||||||
object_id_t getCreatorObjectId() const;
|
object_id_t getCreatorObjectId() const;
|
||||||
|
|
||||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
/**
|
||||||
|
* Get the pointer to the mutex. Can be used to lock the data pool
|
||||||
|
* externally. Use with care and don't forget to unlock locked mutexes!
|
||||||
|
* For now, only friend classes can accss this function.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
MutexIF* getMutexHandle();
|
||||||
|
|
||||||
|
virtual LocalDataPoolManager* getPoolManagerHandle() override;
|
||||||
private:
|
private:
|
||||||
localpool::DataPool localPoolMap;
|
localpool::DataPool localPoolMap;
|
||||||
//! Every housekeeping data manager has a mutex to protect access
|
/** Every housekeeping data manager has a mutex to protect access
|
||||||
//! to it's data pool.
|
to it's data pool. */
|
||||||
MutexIF* mutex = nullptr;
|
MutexIF* mutex = nullptr;
|
||||||
|
|
||||||
/** The class which actually owns the manager (and its datapool). */
|
/** The class which actually owns the manager (and its datapool). */
|
||||||
@ -333,13 +336,6 @@ private:
|
|||||||
|
|
||||||
/** Global IPC store is used to store all packets. */
|
/** Global IPC store is used to store all packets. */
|
||||||
StorageManagerIF* ipcStore = nullptr;
|
StorageManagerIF* ipcStore = nullptr;
|
||||||
/**
|
|
||||||
* Get the pointer to the mutex. Can be used to lock the data pool
|
|
||||||
* externally. Use with care and don't forget to unlock locked mutexes!
|
|
||||||
* For now, only friend classes can accss this function.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
MutexIF* getMutexHandle();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a variable by supplying its local pool ID and assign the pool
|
* Read a variable by supplying its local pool ID and assign the pool
|
||||||
@ -364,6 +360,8 @@ private:
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t initializeHousekeepingPoolEntriesOnce();
|
ReturnValue_t initializeHousekeepingPoolEntriesOnce();
|
||||||
|
|
||||||
|
MutexIF* getLocalPoolMutex() override;
|
||||||
|
|
||||||
ReturnValue_t serializeHkPacketIntoStore(
|
ReturnValue_t serializeHkPacketIntoStore(
|
||||||
HousekeepingPacketDownlink& hkPacket,
|
HousekeepingPacketDownlink& hkPacket,
|
||||||
store_address_t& storeId, bool forDownlink, size_t* serializedSize);
|
store_address_t& storeId, bool forDownlink, size_t* serializedSize);
|
||||||
@ -386,7 +384,7 @@ private:
|
|||||||
ReturnValue_t& status);
|
ReturnValue_t& status);
|
||||||
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver,
|
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver,
|
||||||
ReturnValue_t& status);
|
ReturnValue_t& status);
|
||||||
ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket,
|
ReturnValue_t addUpdateToStore(HousekeepingSnapshot& updatePacket,
|
||||||
store_address_t& storeId);
|
store_address_t& storeId);
|
||||||
|
|
||||||
void printWarningOrError(sif::OutputTypes outputType,
|
void printWarningOrError(sif::OutputTypes outputType,
|
||||||
@ -401,14 +399,14 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
|
|||||||
PoolEntry<T> **poolEntry) {
|
PoolEntry<T> **poolEntry) {
|
||||||
auto poolIter = localPoolMap.find(localPoolId);
|
auto poolIter = localPoolMap.find(localPoolId);
|
||||||
if (poolIter == localPoolMap.end()) {
|
if (poolIter == localPoolMap.end()) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
|
||||||
localpool::POOL_ENTRY_NOT_FOUND);
|
localpool::POOL_ENTRY_NOT_FOUND);
|
||||||
return localpool::POOL_ENTRY_NOT_FOUND;
|
return localpool::POOL_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
|
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
|
||||||
if(*poolEntry == nullptr) {
|
if(*poolEntry == nullptr) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
|
||||||
localpool::POOL_ENTRY_TYPE_CONFLICT);
|
localpool::POOL_ENTRY_TYPE_CONFLICT);
|
||||||
return localpool::POOL_ENTRY_TYPE_CONFLICT;
|
return localpool::POOL_ENTRY_TYPE_CONFLICT;
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,26 @@
|
|||||||
#include "LocalPoolDataSetBase.h"
|
#include "LocalPoolDataSetBase.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This dataset type can be used to group related pool variables if the number of
|
||||||
|
* variables should not be fixed.
|
||||||
|
* @details
|
||||||
|
* This will is the primary data structure to organize pool variables into
|
||||||
|
* sets which can be accessed via the housekeeping service interface or
|
||||||
|
* which can be sent to other software objects.
|
||||||
|
*
|
||||||
|
* It is recommended to read the documentation of the LocalPoolDataSetBase
|
||||||
|
* class for more information on how this class works and how to use it.
|
||||||
|
* @tparam capacity Capacity of the static dataset, which is usually known
|
||||||
|
* beforehand.
|
||||||
|
*/
|
||||||
class LocalDataSet: public LocalPoolDataSetBase {
|
class LocalDataSet: public LocalPoolDataSetBase {
|
||||||
public:
|
public:
|
||||||
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
|
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
|
||||||
const size_t maxSize);
|
const size_t maxSize);
|
||||||
|
|
||||||
LocalDataSet(sid_t sid, const size_t maxSize);
|
LocalDataSet(sid_t sid, const size_t maxSize);
|
||||||
|
|
||||||
virtual~ LocalDataSet();
|
virtual~ LocalDataSet();
|
||||||
|
|
||||||
//! Copying forbidden for now.
|
//! Copying forbidden for now.
|
||||||
|
@ -28,7 +28,7 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
|
|||||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||||
|
|
||||||
if(accessor != nullptr) {
|
if(accessor != nullptr) {
|
||||||
poolManager = accessor->getHkManagerHandle();
|
poolManager = accessor->getPoolManagerHandle();
|
||||||
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkO
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||||
hkManager = poolManAccessor->getHkManagerHandle();
|
hkManager = poolManAccessor->getPoolManagerHandle();
|
||||||
|
|
||||||
if (dataSet != nullptr) {
|
if (dataSet != nullptr) {
|
||||||
dataSet->registerVariable(this);
|
dataSet->registerVariable(this);
|
||||||
@ -50,7 +50,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
|
|||||||
|
|
||||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||||
if(accessor != nullptr) {
|
if(accessor != nullptr) {
|
||||||
hkManager = accessor->getHkManagerHandle();
|
hkManager = accessor->getPoolManagerHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dataSet != nullptr) {
|
if(dataSet != nullptr) {
|
||||||
|
@ -77,8 +77,7 @@ public:
|
|||||||
* @param dataSet
|
* @param dataSet
|
||||||
* @param setReadWriteMode
|
* @param setReadWriteMode
|
||||||
*/
|
*/
|
||||||
LocalPoolVector(gp_id_t globalPoolId,
|
LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
|
||||||
DataSetIF* dataSet = nullptr,
|
|
||||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,7 +86,7 @@ public:
|
|||||||
* The user can work on this attribute just like he would on a local
|
* The user can work on this attribute just like he would on a local
|
||||||
* array of this type.
|
* array of this type.
|
||||||
*/
|
*/
|
||||||
T value[vectorSize];
|
T value[vectorSize]= {};
|
||||||
/**
|
/**
|
||||||
* @brief The classes destructor is empty.
|
* @brief The classes destructor is empty.
|
||||||
* @details If commit() was not called, the local value is
|
* @details If commit() was not called, the local value is
|
||||||
|
@ -16,7 +16,6 @@ inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner,
|
|||||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template<typename T, uint16_t vectorSize>
|
||||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
||||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
|
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
|
||||||
|
|
||||||
#include "LocalPoolDataSetBase.h"
|
#include "LocalPoolDataSetBase.h"
|
||||||
|
#include "LocalPoolVariable.h"
|
||||||
|
#include "LocalPoolVector.h"
|
||||||
|
|
||||||
#include "../objectmanager/SystemObjectIF.h"
|
#include "../objectmanager/SystemObjectIF.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This local dataset type is created on the stack.
|
* @brief This dataset type can be used to group related pool variables if the number of
|
||||||
|
* variables is fixed.
|
||||||
* @details
|
* @details
|
||||||
* This will is the primary data structure to organize pool variables into
|
* This will is the primary data structure to organize pool variables into
|
||||||
* sets which can be accessed via the housekeeping service interface or
|
* sets which can be accessed via the housekeeping service interface or
|
||||||
|
@ -17,16 +17,15 @@ object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
|||||||
object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT;
|
object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT;
|
||||||
object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT;
|
object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT;
|
||||||
|
|
||||||
DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId,
|
DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
|
||||||
object_id_t deviceCommunication, CookieIF * comCookie,
|
CookieIF* comCookie, FailureIsolationBase* fdirInstance, size_t cmdQueueSize):
|
||||||
FailureIsolationBase* fdirInstance, size_t cmdQueueSize) :
|
|
||||||
SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE),
|
SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE),
|
||||||
wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS),
|
wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS),
|
||||||
deviceCommunicationId(deviceCommunication), comCookie(comCookie),
|
deviceCommunicationId(deviceCommunication), comCookie(comCookie),
|
||||||
healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this),
|
healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this),
|
||||||
actionHelper(this, nullptr), poolManager(this, nullptr),
|
actionHelper(this, nullptr), poolManager(this, nullptr),
|
||||||
childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance),
|
childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance),
|
||||||
hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr),
|
defaultFDIRUsed(fdirInstance == nullptr),
|
||||||
switchOffWasReported(false), childTransitionDelay(5000),
|
switchOffWasReported(false), childTransitionDelay(5000),
|
||||||
transitionSourceMode(_MODE_POWER_DOWN),
|
transitionSourceMode(_MODE_POWER_DOWN),
|
||||||
transitionSourceSubMode(SUBMODE_NONE) {
|
transitionSourceSubMode(SUBMODE_NONE) {
|
||||||
@ -80,7 +79,6 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
|||||||
checkSwitchState();
|
checkSwitchState();
|
||||||
decrementDeviceReplyMap();
|
decrementDeviceReplyMap();
|
||||||
fdirInstance->checkForFailures();
|
fdirInstance->checkForFailures();
|
||||||
hkSwitcher.performOperation();
|
|
||||||
performOperationHook();
|
performOperationHook();
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
@ -92,7 +90,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
|||||||
switch (getComAction()) {
|
switch (getComAction()) {
|
||||||
case CommunicationAction::SEND_WRITE:
|
case CommunicationAction::SEND_WRITE:
|
||||||
if (cookieInfo.state == COOKIE_UNUSED) {
|
if (cookieInfo.state == COOKIE_UNUSED) {
|
||||||
// if no external command was specified, build internal command.
|
/* If no external command was specified, build internal command. */
|
||||||
buildInternalCommand();
|
buildInternalCommand();
|
||||||
}
|
}
|
||||||
doSendWrite();
|
doSendWrite();
|
||||||
@ -105,8 +103,8 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
|||||||
break;
|
break;
|
||||||
case CommunicationAction::GET_READ:
|
case CommunicationAction::GET_READ:
|
||||||
doGetRead();
|
doGetRead();
|
||||||
// This will be performed after datasets have been updated by the
|
/* This will be performed after datasets have been updated by the
|
||||||
// custom device implementation.
|
custom device implementation. */
|
||||||
poolManager.performHkOperation();
|
poolManager.performHkOperation();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -205,11 +203,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = hkSwitcher.initialize();
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = poolManager.initialize(commandQueue);
|
result = poolManager.initialize(commandQueue);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
@ -506,7 +499,8 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
||||||
changeHK(mode, submode, false);
|
/* TODO: This will probably be done by the LocalDataPoolManager now */
|
||||||
|
//changeHK(mode, submode, false);
|
||||||
submode = newSubmode;
|
submode = newSubmode;
|
||||||
mode = newMode;
|
mode = newMode;
|
||||||
modeChanged();
|
modeChanged();
|
||||||
@ -529,7 +523,8 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
changeHK(mode, submode, true);
|
/* TODO: This will probably be done by the LocalDataPoolManager now */
|
||||||
|
//changeHK(mode, submode, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::setMode(Mode_t newMode) {
|
void DeviceHandlerBase::setMode(Mode_t newMode) {
|
||||||
@ -1202,61 +1197,62 @@ ReturnValue_t DeviceHandlerBase::letChildHandleMessage(
|
|||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::handleDeviceTM(SerializeIF* data,
|
void DeviceHandlerBase::handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId,
|
||||||
DeviceCommandId_t replyId, bool neverInDataPool, bool forceDirectTm) {
|
bool forceDirectTm) {
|
||||||
|
if(dataSet == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId);
|
DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId);
|
||||||
if (iter == deviceReplyMap.end()) {
|
if (iter == deviceReplyMap.end()) {
|
||||||
triggerEvent(DEVICE_UNKNOWN_REPLY, replyId);
|
triggerEvent(DEVICE_UNKNOWN_REPLY, replyId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data);
|
|
||||||
//replies to a command
|
/* Regular replies to a command */
|
||||||
if (iter->second.command != deviceCommandMap.end())
|
if (iter->second.command != deviceCommandMap.end())
|
||||||
{
|
{
|
||||||
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
|
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
|
||||||
|
|
||||||
if (queueId != NO_COMMANDER) {
|
if (queueId != NO_COMMANDER) {
|
||||||
//This may fail, but we'll ignore the fault.
|
/* This may fail, but we'll ignore the fault. */
|
||||||
actionHelper.reportData(queueId, replyId, data);
|
actionHelper.reportData(queueId, replyId, dataSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
//This check should make sure we get any TM but don't get anything doubled.
|
/* This check should make sure we get any TM but don't get anything doubled. */
|
||||||
if (wiretappingMode == TM && (requestedRawTraffic != queueId)) {
|
if (wiretappingMode == TM && (requestedRawTraffic != queueId)) {
|
||||||
|
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet);
|
||||||
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
|
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (forceDirectTm and (defaultRawReceiver != queueId) and
|
else if (forceDirectTm and (defaultRawReceiver != queueId) and
|
||||||
(defaultRawReceiver != MessageQueueIF::NO_QUEUE))
|
(defaultRawReceiver != MessageQueueIF::NO_QUEUE))
|
||||||
{
|
{
|
||||||
// hiding of sender needed so the service will handle it as
|
// hiding of sender needed so the service will handle it as
|
||||||
// unexpected Data, no matter what state (progress or completed)
|
// unexpected Data, no matter what state (progress or completed)
|
||||||
// it is in
|
// it is in
|
||||||
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper,
|
actionHelper.reportData(defaultRawReceiver, replyId, dataSet, true);
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//unrequested/aperiodic replies
|
/* Unrequested or aperiodic replies */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet);
|
||||||
if (wiretappingMode == TM) {
|
if (wiretappingMode == TM) {
|
||||||
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
|
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
|
||||||
}
|
}
|
||||||
else if (forceDirectTm and defaultRawReceiver !=
|
if (forceDirectTm and defaultRawReceiver != MessageQueueIF::NO_QUEUE)
|
||||||
MessageQueueIF::NO_QUEUE)
|
|
||||||
{
|
{
|
||||||
|
// sid_t setSid = sid_t(this->getObjectId(), replyId);
|
||||||
|
// LocalPoolDataSetBase* dataset = getDataSetHandle(setSid);
|
||||||
|
// if(dataset != nullptr) {
|
||||||
|
// poolManager.generateHousekeepingPacket(setSid, dataset, true);
|
||||||
|
// }
|
||||||
|
|
||||||
// hiding of sender needed so the service will handle it as
|
// hiding of sender needed so the service will handle it as
|
||||||
// unexpected Data, no matter what state (progress or completed)
|
// unexpected Data, no matter what state (progress or completed)
|
||||||
// it is in
|
// it is in
|
||||||
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper,
|
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper, true);
|
||||||
true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Try to cast to GlobDataSet and commit data.
|
|
||||||
if (not neverInDataPool) {
|
|
||||||
LocalPoolDataSetBase* dataSet =
|
|
||||||
dynamic_cast<LocalPoolDataSetBase*>(data);
|
|
||||||
if (dataSet != nullptr) {
|
|
||||||
dataSet->setValidity(true, true);
|
|
||||||
dataSet->commit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1285,18 +1281,17 @@ ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::buildInternalCommand(void) {
|
void DeviceHandlerBase::buildInternalCommand(void) {
|
||||||
//Neither Raw nor Direct could build a command
|
/* Neither raw nor direct could build a command */
|
||||||
ReturnValue_t result = NOTHING_TO_SEND;
|
ReturnValue_t result = NOTHING_TO_SEND;
|
||||||
DeviceCommandId_t deviceCommandId = NO_COMMAND_ID;
|
DeviceCommandId_t deviceCommandId = NO_COMMAND_ID;
|
||||||
if (mode == MODE_NORMAL) {
|
if (mode == MODE_NORMAL) {
|
||||||
result = buildNormalDeviceCommand(&deviceCommandId);
|
result = buildNormalDeviceCommand(&deviceCommandId);
|
||||||
if (result == BUSY) {
|
if (result == BUSY) {
|
||||||
// so we can track misconfigurations
|
/* So we can track misconfigurations */
|
||||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "buildInternalCommand",
|
||||||
"buildInternalCommand",
|
HasReturnvaluesIF::RETURN_FAILED, "Busy.");
|
||||||
HasReturnvaluesIF::RETURN_FAILED,
|
/* No need to report this */
|
||||||
"Busy.");
|
result = NOTHING_TO_SEND;
|
||||||
result = NOTHING_TO_SEND; //no need to report this
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mode == MODE_RAW) {
|
else if (mode == MODE_RAW) {
|
||||||
@ -1318,7 +1313,8 @@ void DeviceHandlerBase::buildInternalCommand(void) {
|
|||||||
deviceCommandId);
|
deviceCommandId);
|
||||||
if (iter == deviceCommandMap.end()) {
|
if (iter == deviceCommandMap.end()) {
|
||||||
result = COMMAND_NOT_SUPPORTED;
|
result = COMMAND_NOT_SUPPORTED;
|
||||||
} else if (iter->second.isExecuting) {
|
}
|
||||||
|
else if (iter->second.isExecuting) {
|
||||||
#if FSFW_DISABLE_PRINTOUT == 0
|
#if FSFW_DISABLE_PRINTOUT == 0
|
||||||
char output[36];
|
char output[36];
|
||||||
sprintf(output, "Command 0x%08x is executing",
|
sprintf(output, "Command 0x%08x is executing",
|
||||||
@ -1378,11 +1374,11 @@ void DeviceHandlerBase::forwardEvent(Event event, uint32_t parameter1,
|
|||||||
void DeviceHandlerBase::doOffActivity() {
|
void DeviceHandlerBase::doOffActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::getParameter(uint8_t domainId,
|
ReturnValue_t DeviceHandlerBase::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = fdirInstance->getParameter(domainId, parameterId,
|
ReturnValue_t result = fdirInstance->getParameter(domainId, uniqueId, parameterWrapper,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
newValues, startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1406,14 +1402,10 @@ bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task){
|
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task){
|
||||||
executingTask = task;
|
executingTask = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default implementations empty.
|
|
||||||
void DeviceHandlerBase::debugInterface(uint8_t positionTracker,
|
void DeviceHandlerBase::debugInterface(uint8_t positionTracker,
|
||||||
object_id_t objectId, uint32_t parameter) {}
|
object_id_t objectId, uint32_t parameter) {}
|
||||||
|
|
||||||
@ -1531,3 +1523,11 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
|
|||||||
LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() {
|
LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() {
|
||||||
return &poolManager;
|
return &poolManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t DeviceHandlerBase::getCommanderId(DeviceCommandId_t replyId) const {
|
||||||
|
auto commandIter = deviceCommandMap.find(replyId);
|
||||||
|
if(commandIter == deviceCommandMap.end()) {
|
||||||
|
return MessageQueueIF::NO_QUEUE;
|
||||||
|
}
|
||||||
|
return commandIter->second.sendReplyTo;
|
||||||
|
}
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include "../action/ActionHelper.h"
|
#include "../action/ActionHelper.h"
|
||||||
#include "../health/HealthHelper.h"
|
#include "../health/HealthHelper.h"
|
||||||
#include "../parameters/ParameterHelper.h"
|
#include "../parameters/ParameterHelper.h"
|
||||||
#include "../datapool/HkSwitchHelper.h"
|
|
||||||
#include "../datapoollocal/HasLocalDataPoolIF.h"
|
#include "../datapoollocal/HasLocalDataPoolIF.h"
|
||||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||||
|
|
||||||
@ -80,14 +79,14 @@ class StorageManagerIF;
|
|||||||
* @ingroup devices
|
* @ingroup devices
|
||||||
*/
|
*/
|
||||||
class DeviceHandlerBase: public DeviceHandlerIF,
|
class DeviceHandlerBase: public DeviceHandlerIF,
|
||||||
public HasReturnvaluesIF,
|
public HasReturnvaluesIF,
|
||||||
public ExecutableObjectIF,
|
public ExecutableObjectIF,
|
||||||
public SystemObject,
|
public SystemObject,
|
||||||
public HasModesIF,
|
public HasModesIF,
|
||||||
public HasHealthIF,
|
public HasHealthIF,
|
||||||
public HasActionsIF,
|
public HasActionsIF,
|
||||||
public ReceivesParameterMessagesIF,
|
public ReceivesParameterMessagesIF,
|
||||||
public HasLocalDataPoolIF {
|
public HasLocalDataPoolIF {
|
||||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -148,8 +147,7 @@ public:
|
|||||||
* 4. Decrements counter for timeout of replies by calling
|
* 4. Decrements counter for timeout of replies by calling
|
||||||
* decrementDeviceReplyMap()
|
* decrementDeviceReplyMap()
|
||||||
* 5. Performs FDIR check for failures
|
* 5. Performs FDIR check for failures
|
||||||
* 6. Calls hkSwitcher.performOperation()
|
* 6. If the device mode is MODE_OFF, return RETURN_OK.
|
||||||
* 7. If the device mode is MODE_OFF, return RETURN_OK.
|
|
||||||
* Otherwise, perform the Action property and performs depending
|
* Otherwise, perform the Action property and performs depending
|
||||||
* on value specified by input value counter (incremented in PST).
|
* on value specified by input value counter (incremented in PST).
|
||||||
* The child class tells base class what to do by setting this value.
|
* The child class tells base class what to do by setting this value.
|
||||||
@ -189,6 +187,37 @@ public:
|
|||||||
/** Destructor. */
|
/** Destructor. */
|
||||||
virtual ~DeviceHandlerBase();
|
virtual ~DeviceHandlerBase();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ExecutableObjectIF function
|
||||||
|
* Used to setup the reference of the task, that executes this component
|
||||||
|
* @param task_ Pointer to the taskIF of this task
|
||||||
|
*/
|
||||||
|
virtual void setTaskIF(PeriodicTaskIF* task_) override;
|
||||||
|
virtual MessageQueueId_t getCommandQueue(void) const override;
|
||||||
|
|
||||||
|
/** Explicit interface implementation of getObjectId */
|
||||||
|
virtual object_id_t getObjectId() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param parentQueueId
|
||||||
|
*/
|
||||||
|
virtual void setParentQueue(MessageQueueId_t parentQueueId);
|
||||||
|
|
||||||
|
/** @brief Implementation required for HasActionIF */
|
||||||
|
ReturnValue_t executeAction(ActionId_t actionId,
|
||||||
|
MessageQueueId_t commandedBy, const uint8_t* data,
|
||||||
|
size_t size) override;
|
||||||
|
|
||||||
|
Mode_t getTransitionSourceMode() const;
|
||||||
|
Submode_t getTransitionSourceSubMode() const;
|
||||||
|
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||||
|
HealthState getHealth();
|
||||||
|
ReturnValue_t setHealth(HealthState health);
|
||||||
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
|
uint16_t startAtIndex) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief This is used to let the child class handle the transition from
|
* @brief This is used to let the child class handle the transition from
|
||||||
@ -216,7 +245,6 @@ protected:
|
|||||||
* for a failed transition
|
* for a failed transition
|
||||||
*/
|
*/
|
||||||
virtual void doStartUp() = 0;
|
virtual void doStartUp() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is used to let the child class handle the transition
|
* @brief This is used to let the child class handle the transition
|
||||||
* from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN
|
* from mode @c _MODE_SHUT_DOWN to @c _MODE_POWER_DOWN
|
||||||
@ -242,6 +270,7 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual void doShutDown() = 0;
|
virtual void doShutDown() = 0;
|
||||||
|
|
||||||
|
/* Command handling */
|
||||||
/**
|
/**
|
||||||
* Build the device command to send for normal mode.
|
* Build the device command to send for normal mode.
|
||||||
*
|
*
|
||||||
@ -262,7 +291,6 @@ protected:
|
|||||||
* - Anything else triggers an even with the returnvalue as a parameter.
|
* - Anything else triggers an even with the returnvalue as a parameter.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0;
|
virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the device command to send for a transitional mode.
|
* Build the device command to send for a transitional mode.
|
||||||
*
|
*
|
||||||
@ -286,29 +314,35 @@ protected:
|
|||||||
* - Anything else triggers an even with the returnvalue as a parameter
|
* - Anything else triggers an even with the returnvalue as a parameter
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0;
|
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Build a device command packet from data supplied by a
|
* @brief Build a device command packet from data supplied by a direct
|
||||||
* direct command.
|
* command (PUS Service 8)
|
||||||
*
|
|
||||||
* @details
|
* @details
|
||||||
* #rawPacket and #rawPacketLen should be set by this method to the packet
|
* This will be called if an functional command via PUS Service 8 is received and is
|
||||||
* to be sent. The existence of the command in the command map and the
|
* the primary interface for functional command instead of #executeAction for users. The
|
||||||
* command size check against 0 are done by the base class.
|
* supplied ActionId_t action ID will be converted to a DeviceCommandId_t command ID after
|
||||||
|
* an internal check whether the action ID is a key in the device command map.
|
||||||
*
|
*
|
||||||
* @param deviceCommand the command to build, already checked against
|
* #rawPacket and #rawPacketLen should be set by this method to the packet to be sent.
|
||||||
* deviceCommandMap
|
* The existence of the command in the command map and the command size check against 0 are
|
||||||
* @param commandData pointer to the data from the direct command
|
* done by the base class.
|
||||||
* @param commandDataLen length of commandData
|
*
|
||||||
|
* @param deviceCommand The command to build, already checked against deviceCommandMap
|
||||||
|
* @param commandData Pointer to the data from the direct command
|
||||||
|
* @param commandDataLen Length of commandData
|
||||||
* @return
|
* @return
|
||||||
* - @c RETURN_OK to send command after #rawPacket and #rawPacketLen
|
* - @c RETURN_OK to send command after #rawPacket and #rawPacketLen
|
||||||
* have been set.
|
* have been set.
|
||||||
* - Anything else triggers an event with the
|
* - @c HasActionsIF::EXECUTION_COMPLETE to generate a finish reply immediately. This can
|
||||||
* returnvalue as a parameter
|
* be used if no reply is expected. Otherwise, the developer can call #actionHelper.finish
|
||||||
|
* to finish the command handling.
|
||||||
|
* - Anything else triggers an event with the return code as a parameter as well as a
|
||||||
|
* step reply failed with the return code
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||||
const uint8_t * commandData, size_t commandDataLen) = 0;
|
const uint8_t * commandData, size_t commandDataLen) = 0;
|
||||||
|
|
||||||
|
/* Reply handling */
|
||||||
/**
|
/**
|
||||||
* @brief Scans a buffer for a valid reply.
|
* @brief Scans a buffer for a valid reply.
|
||||||
* @details
|
* @details
|
||||||
@ -344,7 +378,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t scanForReply(const uint8_t *start, size_t len,
|
virtual ReturnValue_t scanForReply(const uint8_t *start, size_t len,
|
||||||
DeviceCommandId_t *foundId, size_t *foundLen) = 0;
|
DeviceCommandId_t *foundId, size_t *foundLen) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Interpret a reply from the device.
|
* @brief Interpret a reply from the device.
|
||||||
* @details
|
* @details
|
||||||
@ -366,10 +399,19 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
|
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
|
||||||
const uint8_t *packet) = 0;
|
const uint8_t *packet) = 0;
|
||||||
|
MessageQueueId_t getCommanderId(DeviceCommandId_t replyId) const;
|
||||||
/**
|
/**
|
||||||
* @brief fill the #DeviceCommandMap and #DeviceReplyMap
|
* Helper function to get pending command. This is useful for devices
|
||||||
* called by the initialize() of the base class
|
* like SPI sensors to identify the last sent command.
|
||||||
|
* This only returns the command sent in the last SEND_WRITE cycle.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
DeviceCommandId_t getPendingCommand() const;
|
||||||
|
|
||||||
|
/* Specifying commands and replies */
|
||||||
|
/**
|
||||||
|
* @brief Fill the #DeviceCommandMap and #DeviceReplyMap called by the #initialize
|
||||||
|
* of the base class
|
||||||
* @details
|
* @details
|
||||||
* This is used to let the base class know which replies are expected.
|
* This is used to let the base class know which replies are expected.
|
||||||
* There are different scenarios regarding this:
|
* There are different scenarios regarding this:
|
||||||
@ -399,7 +441,6 @@ protected:
|
|||||||
* handled by returning @c APERIODIC_REPLY in scanForReply().
|
* handled by returning @c APERIODIC_REPLY in scanForReply().
|
||||||
*/
|
*/
|
||||||
virtual void fillCommandAndReplyMap() = 0;
|
virtual void fillCommandAndReplyMap() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a helper method to facilitate inserting entries in the command map.
|
* This is a helper method to facilitate inserting entries in the command map.
|
||||||
* @param deviceCommand Identifier of the command to add.
|
* @param deviceCommand Identifier of the command to add.
|
||||||
@ -417,7 +458,6 @@ protected:
|
|||||||
LocalPoolDataSetBase* replyDataSet = nullptr,
|
LocalPoolDataSetBase* replyDataSet = nullptr,
|
||||||
size_t replyLen = 0, bool periodic = false,
|
size_t replyLen = 0, bool periodic = false,
|
||||||
bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0);
|
bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is a helper method to insert replies in the reply map.
|
* @brief This is a helper method to insert replies in the reply map.
|
||||||
* @param deviceCommand Identifier of the reply to add.
|
* @param deviceCommand Identifier of the reply to add.
|
||||||
@ -431,7 +471,6 @@ protected:
|
|||||||
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand,
|
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand,
|
||||||
uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr,
|
uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr,
|
||||||
size_t replyLen = 0, bool periodic = false);
|
size_t replyLen = 0, bool periodic = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A simple command to add a command to the commandList.
|
* @brief A simple command to add a command to the commandList.
|
||||||
* @param deviceCommand The command to add
|
* @param deviceCommand The command to add
|
||||||
@ -457,25 +496,14 @@ protected:
|
|||||||
ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply,
|
ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply,
|
||||||
uint16_t delayCycles, uint16_t maxDelayCycles,
|
uint16_t delayCycles, uint16_t maxDelayCycles,
|
||||||
bool periodic = false);
|
bool periodic = false);
|
||||||
|
/**
|
||||||
|
* @brief Can be used to set the dataset corresponding to a reply ID manually.
|
||||||
|
* @details
|
||||||
|
* Used by the local data pool manager.
|
||||||
|
*/
|
||||||
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId,
|
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId,
|
||||||
LocalPoolDataSetBase* dataset);
|
LocalPoolDataSetBase* dataset);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Can be implemented by child handler to
|
|
||||||
* perform debugging
|
|
||||||
* @details Example: Calling this in performOperation
|
|
||||||
* to track values like mode.
|
|
||||||
* @param positionTracker Provide the child handler a way to know
|
|
||||||
* where the debugInterface was called
|
|
||||||
* @param objectId Provide the child handler object Id to
|
|
||||||
* specify actions for spefic devices
|
|
||||||
* @param parameter Supply a parameter of interest
|
|
||||||
* Please delete all debugInterface calls in DHB after debugging is finished !
|
|
||||||
*/
|
|
||||||
virtual void debugInterface(uint8_t positionTracker = 0,
|
|
||||||
object_id_t objectId = 0, uint32_t parameter = 0);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the time needed to transit from modeFrom to modeTo.
|
* Get the time needed to transit from modeFrom to modeTo.
|
||||||
*
|
*
|
||||||
@ -494,6 +522,73 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) = 0;
|
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) = 0;
|
||||||
|
|
||||||
|
/* Functions used by the local data pool manager */
|
||||||
|
/**
|
||||||
|
* This function is used to initialize the local housekeeping pool
|
||||||
|
* entries. The default implementation leaves the pool empty.
|
||||||
|
* @param localDataPoolMap
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||||
|
LocalDataPoolManager& poolManager) override;
|
||||||
|
/**
|
||||||
|
* @brief Set all datapool variables that are update periodically in
|
||||||
|
* normal mode invalid
|
||||||
|
* @details
|
||||||
|
* The default implementation will set all datasets which have been added
|
||||||
|
* in #fillCommandAndReplyMap to invalid. It will also set all pool
|
||||||
|
* variables inside the dataset to invalid. The user can override this
|
||||||
|
* method optionally.
|
||||||
|
*/
|
||||||
|
virtual void setNormalDatapoolEntriesInvalid();
|
||||||
|
/**
|
||||||
|
* @brief Get the dataset handle for a given SID.
|
||||||
|
* @details
|
||||||
|
* The default implementation will use the deviceCommandMap to look for the corresponding
|
||||||
|
* dataset handle. The user can override this function if this is not desired.
|
||||||
|
* @param sid
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||||
|
|
||||||
|
/* HasModesIF overrides */
|
||||||
|
virtual void startTransition(Mode_t mode, Submode_t submode) override;
|
||||||
|
virtual void setToExternalControl() override;
|
||||||
|
virtual void announceMode(bool recursive) override;
|
||||||
|
/**
|
||||||
|
* @brief Set the device handler mode
|
||||||
|
* @details
|
||||||
|
* Sets #timeoutStart with every call Also sets #transitionTargetMode if necessary so
|
||||||
|
* transitional states can be entered from everywhere without breaking the state machine
|
||||||
|
* (which relies on a correct #transitionTargetMode).
|
||||||
|
* The submode is left unchanged.
|
||||||
|
*
|
||||||
|
* @param newMode
|
||||||
|
*/
|
||||||
|
void setMode(Mode_t newMode);
|
||||||
|
/**
|
||||||
|
* @overload
|
||||||
|
* @param submode
|
||||||
|
*/
|
||||||
|
void setMode(Mode_t newMode, Submode_t submode);
|
||||||
|
/**
|
||||||
|
* @brief Should be implemented properly by child class.
|
||||||
|
* @param mode
|
||||||
|
* @param submode
|
||||||
|
* @return
|
||||||
|
* - @c RETURN_OK if valid
|
||||||
|
* - @c RETURN_FAILED if invalid
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
|
||||||
|
Submode_t submode);
|
||||||
|
/**
|
||||||
|
* @brief Notify child about mode change.
|
||||||
|
* @details
|
||||||
|
* Can be overriden to be used like a callback.
|
||||||
|
*/
|
||||||
|
virtual void modeChanged();
|
||||||
|
|
||||||
|
/* Power handling functions */
|
||||||
/**
|
/**
|
||||||
* Return the switches connected to the device.
|
* Return the switches connected to the device.
|
||||||
*
|
*
|
||||||
@ -509,82 +604,60 @@ protected:
|
|||||||
uint8_t *numberOfSwitches);
|
uint8_t *numberOfSwitches);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is used to initialize the local housekeeping pool
|
* @brief Helper function to report a missed reply
|
||||||
* entries. The default implementation leaves the pool empty.
|
* @details Can be overwritten by children to act on missed replies or to fake reporting Id.
|
||||||
* @param localDataPoolMap
|
* @param id of the missed reply
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
virtual void missedReply(DeviceCommandId_t id);
|
||||||
LocalDataPoolManager& poolManager) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Required for HasLocalDataPoolIF, return a handle to the local pool manager.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
LocalDataPoolManager* getHkManagerHandle() override;
|
|
||||||
|
|
||||||
|
/* Miscellaneous functions */
|
||||||
/**
|
/**
|
||||||
* @brief Hook function for child handlers which is called once per
|
* @brief Hook function for child handlers which is called once per
|
||||||
* performOperation(). Default implementation is empty.
|
* performOperation(). Default implementation is empty.
|
||||||
*/
|
*/
|
||||||
virtual void performOperationHook();
|
virtual void performOperationHook();
|
||||||
|
|
||||||
public:
|
|
||||||
/** Explicit interface implementation of getObjectId */
|
|
||||||
virtual object_id_t getObjectId() const override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parentQueueId
|
* @brief Can be implemented by child handler to
|
||||||
|
* perform debugging
|
||||||
|
* @details Example: Calling this in performOperation
|
||||||
|
* to track values like mode.
|
||||||
|
* @param positionTracker Provide the child handler a way to know
|
||||||
|
* where the debugInterface was called
|
||||||
|
* @param objectId Provide the child handler object Id to
|
||||||
|
* specify actions for spefic devices
|
||||||
|
* @param parameter Supply a parameter of interest
|
||||||
|
* Please delete all debugInterface calls in DHB after debugging is finished !
|
||||||
*/
|
*/
|
||||||
virtual void setParentQueue(MessageQueueId_t parentQueueId);
|
virtual void debugInterface(uint8_t positionTracker = 0,
|
||||||
|
object_id_t objectId = 0, uint32_t parameter = 0);
|
||||||
/** @brief Implementation required for HasActionIF */
|
|
||||||
ReturnValue_t executeAction(ActionId_t actionId,
|
|
||||||
MessageQueueId_t commandedBy, const uint8_t* data,
|
|
||||||
size_t size) override;
|
|
||||||
|
|
||||||
Mode_t getTransitionSourceMode() const;
|
|
||||||
Submode_t getTransitionSourceSubMode() const;
|
|
||||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
|
||||||
HealthState getHealth();
|
|
||||||
ReturnValue_t setHealth(HealthState health);
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
|
||||||
ParameterWrapper *parameterWrapper,
|
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex) override;
|
|
||||||
/**
|
|
||||||
* Implementation of ExecutableObjectIF function
|
|
||||||
*
|
|
||||||
* Used to setup the reference of the task, that executes this component
|
|
||||||
* @param task_ Pointer to the taskIF of this task
|
|
||||||
*/
|
|
||||||
virtual void setTaskIF(PeriodicTaskIF* task_);
|
|
||||||
virtual MessageQueueId_t getCommandQueue(void) const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
|
||||||
* The Returnvalues id of this class, required by HasReturnvaluesIF
|
|
||||||
*/
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
|
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
|
||||||
|
|
||||||
static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(0xA0);
|
static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(0xA0);
|
||||||
// Returnvalues for scanForReply()
|
/* Return codes for scanForReply */
|
||||||
static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB0); //!< This is used to specify for replies from a device which are not replies to requests
|
//! This is used to specify for replies from a device which are not replies to requests
|
||||||
static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB1); //!< Ignore parts of the received packet
|
static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB0);
|
||||||
static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB2); //!< Ignore full received packet
|
//! Ignore parts of the received packet
|
||||||
// Returnvalues for command building
|
static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB1);
|
||||||
static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xC0); //!< Return this if no command sending in required
|
//! Ignore full received packet
|
||||||
|
static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB2);
|
||||||
|
/* Return codes for command building */
|
||||||
|
//! Return this if no command sending in required
|
||||||
|
static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xC0);
|
||||||
static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(0xC2);
|
static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(0xC2);
|
||||||
// Returnvalues for getSwitches()
|
// Return codes for getSwitches */
|
||||||
static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xD0);
|
static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xD0);
|
||||||
// Mode handling error Codes
|
/* Mode handling error Codes */
|
||||||
static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE0);
|
static const ReturnValue_t CHILD_TIMEOUT = MAKE_RETURN_CODE(0xE0);
|
||||||
static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE1);
|
static const ReturnValue_t SWITCH_FAILED = MAKE_RETURN_CODE(0xE1);
|
||||||
|
|
||||||
static const MessageQueueId_t NO_COMMANDER = 0;
|
static const MessageQueueId_t NO_COMMANDER = 0;
|
||||||
|
|
||||||
/** Pointer to the raw packet that will be sent.*/
|
//! Pointer to the raw packet that will be sent.
|
||||||
uint8_t *rawPacket = nullptr;
|
uint8_t *rawPacket = nullptr;
|
||||||
/** Size of the #rawPacket. */
|
//! Size of the #rawPacket.
|
||||||
uint32_t rawPacketLen = 0;
|
uint32_t rawPacketLen = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -642,15 +715,15 @@ protected:
|
|||||||
/** Cookie used for communication */
|
/** Cookie used for communication */
|
||||||
CookieIF * comCookie;
|
CookieIF * comCookie;
|
||||||
|
|
||||||
/** Health helper for HasHealthIF */
|
/* Health helper for HasHealthIF */
|
||||||
HealthHelper healthHelper;
|
HealthHelper healthHelper;
|
||||||
/** Mode helper for HasModesIF */
|
/* Mode helper for HasModesIF */
|
||||||
ModeHelper modeHelper;
|
ModeHelper modeHelper;
|
||||||
/** Parameter helper for ReceivesParameterMessagesIF */
|
/* Parameter helper for ReceivesParameterMessagesIF */
|
||||||
ParameterHelper parameterHelper;
|
ParameterHelper parameterHelper;
|
||||||
/** Action helper for HasActionsIF */
|
/* Action helper for HasActionsIF */
|
||||||
ActionHelper actionHelper;
|
ActionHelper actionHelper;
|
||||||
/** Housekeeping Manager */
|
/* Housekeeping Manager */
|
||||||
LocalDataPoolManager poolManager;
|
LocalDataPoolManager poolManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -733,88 +806,41 @@ protected:
|
|||||||
* default class is instantiated. */
|
* default class is instantiated. */
|
||||||
FailureIsolationBase* fdirInstance;
|
FailureIsolationBase* fdirInstance;
|
||||||
|
|
||||||
HkSwitchHelper hkSwitcher;
|
//! To correctly delete the default instance.
|
||||||
|
bool defaultFDIRUsed;
|
||||||
|
|
||||||
bool defaultFDIRUsed; //!< To correctly delete the default instance.
|
//! Indicates if SWITCH_WENT_OFF was already thrown.
|
||||||
|
bool switchOffWasReported;
|
||||||
|
|
||||||
bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown.
|
/** Pointer to the task which executes this component,
|
||||||
|
is invalid before setTaskIF was called. */
|
||||||
//! Pointer to the task which executes this component, is invalid
|
|
||||||
//! before setTaskIF was called.
|
|
||||||
PeriodicTaskIF* executingTask = nullptr;
|
PeriodicTaskIF* executingTask = nullptr;
|
||||||
|
|
||||||
//!< Object which switches power on and off.
|
//! Object which switches power on and off.
|
||||||
static object_id_t powerSwitcherId;
|
static object_id_t powerSwitcherId;
|
||||||
|
|
||||||
//!< Object which receives RAW data by default.
|
//! Object which receives RAW data by default.
|
||||||
static object_id_t rawDataReceiverId;
|
static object_id_t rawDataReceiverId;
|
||||||
|
|
||||||
//!< Object which may be the root cause of an identified fault.
|
//! Object which may be the root cause of an identified fault.
|
||||||
static object_id_t defaultFdirParentId;
|
static object_id_t defaultFdirParentId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set all datapool variables that are update periodically in
|
* @brief Send a reply to a received device handler command.
|
||||||
* normal mode invalid
|
|
||||||
* @details
|
|
||||||
* The default implementation will set all datasets which have been added
|
|
||||||
* in #fillCommandAndReplyMap to invalid. It will also set all pool
|
|
||||||
* variables inside the dataset to invalid. The user can override this
|
|
||||||
* method optionally.
|
|
||||||
*/
|
|
||||||
virtual void setNormalDatapoolEntriesInvalid();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to get pending command. This is useful for devices
|
|
||||||
* like SPI sensors to identify the last sent command.
|
|
||||||
* This only returns the command sent in the last SEND_WRITE cycle.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
DeviceCommandId_t getPendingCommand() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to report a missed reply
|
|
||||||
*
|
|
||||||
* Can be overwritten by children to act on missed replies or to fake
|
|
||||||
* reporting Id.
|
|
||||||
*
|
|
||||||
* @param id of the missed reply
|
|
||||||
*/
|
|
||||||
virtual void missedReply(DeviceCommandId_t id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a reply to a received device handler command.
|
|
||||||
*
|
*
|
||||||
* This also resets #DeviceHandlerCommand to 0.
|
* This also resets #DeviceHandlerCommand to 0.
|
||||||
*
|
*
|
||||||
* @param reply the reply type
|
* @param reply the reply type
|
||||||
* @param parameter parameter for the reply
|
* @param parameter parameter for the reply
|
||||||
*/
|
*/
|
||||||
void replyReturnvalueToCommand(ReturnValue_t status,
|
void replyReturnvalueToCommand(ReturnValue_t status, uint32_t parameter = 0);
|
||||||
uint32_t parameter = 0);
|
/**
|
||||||
|
* TODO: Whats the difference between this and the upper command?
|
||||||
|
* @param status
|
||||||
|
* @param parameter
|
||||||
|
*/
|
||||||
void replyToCommand(ReturnValue_t status, uint32_t parameter = 0);
|
void replyToCommand(ReturnValue_t status, uint32_t parameter = 0);
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the device handler mode
|
|
||||||
*
|
|
||||||
* Sets #timeoutStart with every call.
|
|
||||||
*
|
|
||||||
* Sets #transitionTargetMode if necessary so transitional states can be
|
|
||||||
* entered from everywhere without breaking the state machine
|
|
||||||
* (which relies on a correct #transitionTargetMode).
|
|
||||||
*
|
|
||||||
* The submode is left unchanged.
|
|
||||||
*
|
|
||||||
* @param newMode
|
|
||||||
*/
|
|
||||||
void setMode(Mode_t newMode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @overload
|
|
||||||
* @param submode
|
|
||||||
*/
|
|
||||||
void setMode(Mode_t newMode, Submode_t submode);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW).
|
* Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW).
|
||||||
*
|
*
|
||||||
@ -856,16 +882,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom);
|
virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom);
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mode
|
|
||||||
* @param submode
|
|
||||||
* @return
|
|
||||||
* - @c RETURN_OK if valid
|
|
||||||
* - @c RETURN_FAILED if invalid
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
|
|
||||||
Submode_t submode);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the communication action for the current step.
|
* Get the communication action for the current step.
|
||||||
* The step number can be read from #pstStep.
|
* The step number can be read from #pstStep.
|
||||||
@ -874,27 +890,28 @@ protected:
|
|||||||
virtual CommunicationAction getComAction();
|
virtual CommunicationAction getComAction();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the device command to send for raw mode.
|
* Checks state of switches in conjunction with mode and triggers an event
|
||||||
*
|
* if they don't fit.
|
||||||
* This is only called in @c MODE_RAW. It is for the rare case that in
|
|
||||||
* raw mode packets are to be sent by the handler itself. It is NOT needed
|
|
||||||
* for the raw commanding service. Its only current use is in the STR
|
|
||||||
* handler which gets its raw packets from a different source.
|
|
||||||
* Also it can be used for transitional commands, to get the device ready
|
|
||||||
* for @c MODE_RAW
|
|
||||||
*
|
|
||||||
* As it is almost never used, there is a default implementation
|
|
||||||
* returning @c NOTHING_TO_SEND.
|
|
||||||
*
|
|
||||||
* #rawPacket and #rawPacketLen must be set by this method to the packet
|
|
||||||
* to be sent.
|
|
||||||
*
|
|
||||||
* @param[out] id the device command id built
|
|
||||||
* @return
|
|
||||||
* - @c RETURN_OK when a command is to be sent
|
|
||||||
* - not @c NOTHING_TO_SEND when no command is to be sent
|
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t buildChildRawCommand();
|
virtual void checkSwitchState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserved for the rare case where a device needs to perform additional
|
||||||
|
* operation cyclically in OFF mode.
|
||||||
|
*/
|
||||||
|
virtual void doOffActivity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserved for the rare case where a device needs to perform additional
|
||||||
|
* operation cyclically in ON mode.
|
||||||
|
*/
|
||||||
|
virtual void doOnActivity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required for HasLocalDataPoolIF, return a handle to the local pool manager.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
LocalDataPoolManager* getHkManagerHandle() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the delay cycle count of a reply.
|
* Returns the delay cycle count of a reply.
|
||||||
@ -906,24 +923,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand);
|
uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand);
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a command reply containing a raw reply.
|
|
||||||
*
|
|
||||||
* It gets space in the #IPCStore, copies data there, then sends a raw reply
|
|
||||||
* containing the store address.
|
|
||||||
*
|
|
||||||
* This method is virtual, as devices can have different channels to send
|
|
||||||
* raw replies
|
|
||||||
*
|
|
||||||
* @param data data to send
|
|
||||||
* @param len length of @c data
|
|
||||||
* @param sendTo the messageQueueId of the one to send to
|
|
||||||
* @param isCommand marks the raw data as a command, the message then
|
|
||||||
* will be of type raw_command
|
|
||||||
*/
|
|
||||||
virtual void replyRawData(const uint8_t *data, size_t len,
|
|
||||||
MessageQueueId_t sendTo, bool isCommand = false);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping
|
* Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping
|
||||||
* is active and if so, does not send the data as the wiretapping will have
|
* is active and if so, does not send the data as the wiretapping will have
|
||||||
@ -931,11 +930,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
|
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Notify child about mode change.
|
|
||||||
*/
|
|
||||||
virtual void modeChanged(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable the reply checking for a command
|
* Enable the reply checking for a command
|
||||||
*
|
*
|
||||||
@ -963,6 +957,45 @@ protected:
|
|||||||
uint8_t expectedReplies = 1, bool useAlternateId = false,
|
uint8_t expectedReplies = 1, bool useAlternateId = false,
|
||||||
DeviceCommandId_t alternateReplyID = 0);
|
DeviceCommandId_t alternateReplyID = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Build the device command to send for raw mode.
|
||||||
|
* @details
|
||||||
|
* This is only called in @c MODE_RAW. It is for the rare case that in
|
||||||
|
* raw mode packets are to be sent by the handler itself. It is NOT needed
|
||||||
|
* for the raw commanding service. Its only current use is in the STR
|
||||||
|
* handler which gets its raw packets from a different source.
|
||||||
|
* Also it can be used for transitional commands, to get the device ready
|
||||||
|
* for @c MODE_RAW
|
||||||
|
*
|
||||||
|
* As it is almost never used, there is a default implementation
|
||||||
|
* returning @c NOTHING_TO_SEND.
|
||||||
|
*
|
||||||
|
* #rawPacket and #rawPacketLen must be set by this method to the packet
|
||||||
|
* to be sent.
|
||||||
|
*
|
||||||
|
* @param[out] id the device command id built
|
||||||
|
* @return
|
||||||
|
* - @c RETURN_OK when a command is to be sent
|
||||||
|
* - not @c NOTHING_TO_SEND when no command is to be sent
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t buildChildRawCommand();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Construct a command reply containing a raw reply.
|
||||||
|
* @details
|
||||||
|
* It gets space in the #IPCStore, copies data there, then sends a raw reply
|
||||||
|
* containing the store address. This method is virtual, as devices can have different channels
|
||||||
|
* to send raw replies
|
||||||
|
*
|
||||||
|
* @param data data to send
|
||||||
|
* @param len length of @c data
|
||||||
|
* @param sendTo the messageQueueId of the one to send to
|
||||||
|
* @param isCommand marks the raw data as a command, the message then
|
||||||
|
* will be of type raw_command
|
||||||
|
*/
|
||||||
|
virtual void replyRawData(const uint8_t *data, size_t len,
|
||||||
|
MessageQueueId_t sendTo, bool isCommand = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the state of the PCDU switches in the local datapool
|
* Get the state of the PCDU switches in the local datapool
|
||||||
* @return
|
* @return
|
||||||
@ -972,12 +1005,7 @@ protected:
|
|||||||
* #switches are off
|
* #switches are off
|
||||||
* - @c PowerSwitchIF::RETURN_FAILED if an error occured
|
* - @c PowerSwitchIF::RETURN_FAILED if an error occured
|
||||||
*/
|
*/
|
||||||
ReturnValue_t getStateOfSwitches(void);
|
ReturnValue_t getStateOfSwitches();
|
||||||
|
|
||||||
/**
|
|
||||||
* build a list of sids and pass it to the #hkSwitcher
|
|
||||||
*/
|
|
||||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Children can overwrite this function to suppress checking of the
|
* Children can overwrite this function to suppress checking of the
|
||||||
@ -995,17 +1023,14 @@ protected:
|
|||||||
|
|
||||||
bool isAwaitingReply();
|
bool isAwaitingReply();
|
||||||
|
|
||||||
void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t commandId,
|
void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId,
|
||||||
bool neverInDataPool = false, bool forceDirectTm = false);
|
bool forceDirectTm = false);
|
||||||
|
// void handleDeviceTM(uint8_t* data, size_t dataSize, DeviceCommandId_t replyId,
|
||||||
|
// bool forceDirectTm);
|
||||||
|
|
||||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode);
|
uint32_t *msToReachTheMode);
|
||||||
|
|
||||||
/* HasModesIF overrides */
|
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode) override;
|
|
||||||
virtual void setToExternalControl() override;
|
|
||||||
virtual void announceMode(bool recursive) override;
|
|
||||||
|
|
||||||
virtual ReturnValue_t letChildHandleMessage(CommandMessage *message);
|
virtual ReturnValue_t letChildHandleMessage(CommandMessage *message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1023,23 +1048,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
||||||
uint32_t parameter2 = 0) const;
|
uint32_t parameter2 = 0) const;
|
||||||
/**
|
|
||||||
* Checks state of switches in conjunction with mode and triggers an event
|
|
||||||
* if they don't fit.
|
|
||||||
*/
|
|
||||||
virtual void checkSwitchState();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reserved for the rare case where a device needs to perform additional
|
|
||||||
* operation cyclically in OFF mode.
|
|
||||||
*/
|
|
||||||
virtual void doOffActivity();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reserved for the rare case where a device needs to perform additional
|
|
||||||
* operation cyclically in ON mode.
|
|
||||||
*/
|
|
||||||
virtual void doOnActivity();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if current mode is transitional mode.
|
* Checks if current mode is transitional mode.
|
||||||
@ -1062,6 +1070,7 @@ protected:
|
|||||||
* @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON
|
* @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON
|
||||||
*/
|
*/
|
||||||
void commandSwitch(ReturnValue_t onOff);
|
void commandSwitch(ReturnValue_t onOff);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1151,7 +1160,6 @@ private:
|
|||||||
|
|
||||||
void buildRawDeviceCommand(CommandMessage* message);
|
void buildRawDeviceCommand(CommandMessage* message);
|
||||||
void buildInternalCommand(void);
|
void buildInternalCommand(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrement the counter for the timout of replies.
|
* Decrement the counter for the timout of replies.
|
||||||
*
|
*
|
||||||
@ -1159,7 +1167,6 @@ private:
|
|||||||
* reply has timed out (that means a reply was expected but not received).
|
* reply has timed out (that means a reply was expected but not received).
|
||||||
*/
|
*/
|
||||||
void decrementDeviceReplyMap(void);
|
void decrementDeviceReplyMap(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience function to handle a reply.
|
* Convenience function to handle a reply.
|
||||||
*
|
*
|
||||||
@ -1174,8 +1181,8 @@ private:
|
|||||||
* @foundLen the length of the packet
|
* @foundLen the length of the packet
|
||||||
*/
|
*/
|
||||||
void handleReply(const uint8_t *data, DeviceCommandId_t id, uint32_t foundLen);
|
void handleReply(const uint8_t *data, DeviceCommandId_t id, uint32_t foundLen);
|
||||||
|
|
||||||
void replyToReply(DeviceReplyMap::iterator iter, ReturnValue_t status);
|
void replyToReply(DeviceReplyMap::iterator iter, ReturnValue_t status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build and send a command to the device.
|
* Build and send a command to the device.
|
||||||
*
|
*
|
||||||
@ -1190,7 +1197,6 @@ private:
|
|||||||
* sends the command via RMAP.
|
* sends the command via RMAP.
|
||||||
*/
|
*/
|
||||||
void doSendWrite(void);
|
void doSendWrite(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the RMAP sendWrite action was successful.
|
* Check if the RMAP sendWrite action was successful.
|
||||||
*
|
*
|
||||||
@ -1200,7 +1206,6 @@ private:
|
|||||||
* - if the action was successful, the reply timout counter is initialized
|
* - if the action was successful, the reply timout counter is initialized
|
||||||
*/
|
*/
|
||||||
void doGetWrite(void);
|
void doGetWrite(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a RMAP getRead command.
|
* Send a RMAP getRead command.
|
||||||
*
|
*
|
||||||
@ -1208,7 +1213,6 @@ private:
|
|||||||
* This is always executed, independently from the current mode.
|
* This is always executed, independently from the current mode.
|
||||||
*/
|
*/
|
||||||
void doSendRead(void);
|
void doSendRead(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the getRead reply and the contained data.
|
* Check the getRead reply and the contained data.
|
||||||
*
|
*
|
||||||
@ -1238,14 +1242,12 @@ private:
|
|||||||
void setTransition(Mode_t modeTo, Submode_t submodeTo);
|
void setTransition(Mode_t modeTo, Submode_t submodeTo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* calls the right child function for the transitional submodes
|
* Calls the right child function for the transitional submodes
|
||||||
*/
|
*/
|
||||||
void callChildStatemachine();
|
void callChildStatemachine();
|
||||||
|
|
||||||
ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message);
|
ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message);
|
||||||
|
|
||||||
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
|
||||||
|
|
||||||
virtual dur_millis_t getPeriodicOperationFrequency() const override;
|
virtual dur_millis_t getPeriodicOperationFrequency() const override;
|
||||||
|
|
||||||
void parseReply(const uint8_t* receivedData,
|
void parseReply(const uint8_t* receivedData,
|
||||||
@ -1254,6 +1256,13 @@ private:
|
|||||||
void handleTransitionToOnMode(Mode_t commandedMode,
|
void handleTransitionToOnMode(Mode_t commandedMode,
|
||||||
Submode_t commandedSubmode);
|
Submode_t commandedSubmode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic internal printer function which also handles printing the object ID.
|
||||||
|
* @param errorType
|
||||||
|
* @param functionName
|
||||||
|
* @param errorCode
|
||||||
|
* @param errorPrint
|
||||||
|
*/
|
||||||
void printWarningOrError(sif::OutputTypes errorType,
|
void printWarningOrError(sif::OutputTypes errorType,
|
||||||
const char* functionName,
|
const char* functionName,
|
||||||
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
||||||
|
@ -209,20 +209,20 @@ void DeviceHandlerFailureIsolation::startRecovery(Event reason) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
|
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
|
||||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = strangeReplyCount.getParameter(domainId, parameterId,
|
ReturnValue_t result = strangeReplyCount.getParameter(domainId, uniqueId,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
parameterWrapper, newValues, startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = missedReplyCount.getParameter(domainId, parameterId,
|
result = missedReplyCount.getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = recoveryCounter.getParameter(domainId, parameterId,
|
result = recoveryCounter.getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,9 @@ public:
|
|||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize();
|
||||||
void triggerEvent(Event event, uint32_t parameter1 = 0,
|
void triggerEvent(Event event, uint32_t parameter1 = 0,
|
||||||
uint32_t parameter2 = 0);bool isFdirActionInProgress();
|
uint32_t parameter2 = 0);bool isFdirActionInProgress();
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
uint16_t startAtIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FaultCounter strangeReplyCount;
|
FaultCounter strangeReplyCount;
|
||||||
|
3
doc/doxy/.gitignore
vendored
Normal file
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/QueueFactory.h"
|
||||||
#include "../ipc/MutexFactory.h"
|
#include "../ipc/MutexFactory.h"
|
||||||
|
|
||||||
|
MessageQueueId_t EventManagerIF::eventmanagerQueue = MessageQueueIF::NO_QUEUE;
|
||||||
|
|
||||||
// If one checks registerListener calls, there are around 40 (to max 50)
|
// If one checks registerListener calls, there are around 40 (to max 50)
|
||||||
// objects registering for certain events.
|
// objects registering for certain events.
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#ifndef EVENTMANAGERIF_H_
|
#ifndef FSFW_EVENTS_EVENTMANAGERIF_H_
|
||||||
#define EVENTMANAGERIF_H_
|
#define FSFW_EVENTS_EVENTMANAGERIF_H_
|
||||||
|
|
||||||
#include "EventMessage.h"
|
#include "EventMessage.h"
|
||||||
#include "eventmatching/eventmatching.h"
|
#include "eventmatching/eventmatching.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManagerIF.h"
|
||||||
#include "../ipc/MessageQueueSenderIF.h"
|
#include "../ipc/MessageQueueSenderIF.h"
|
||||||
#include "../ipc/MessageQueueIF.h"
|
#include "../ipc/MessageQueueIF.h"
|
||||||
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
class EventManagerIF {
|
class EventManagerIF {
|
||||||
public:
|
public:
|
||||||
@ -41,11 +42,19 @@ public:
|
|||||||
|
|
||||||
static void triggerEvent(EventMessage* message,
|
static void triggerEvent(EventMessage* message,
|
||||||
MessageQueueId_t sentFrom = 0) {
|
MessageQueueId_t sentFrom = 0) {
|
||||||
static MessageQueueId_t eventmanagerQueue = MessageQueueIF::NO_QUEUE;
|
|
||||||
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
|
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
|
||||||
EventManagerIF *eventmanager = objectManager->get<EventManagerIF>(
|
EventManagerIF *eventmanager = objectManager->get<EventManagerIF>(
|
||||||
objects::EVENT_MANAGER);
|
objects::EVENT_MANAGER);
|
||||||
if (eventmanager == nullptr) {
|
if (eventmanager == nullptr) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "EventManagerIF::triggerEvent: EventManager invalid or not found!"
|
||||||
|
<< std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("EventManagerIF::triggerEvent: "
|
||||||
|
"EventManager invalid or not found!");
|
||||||
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eventmanagerQueue = eventmanager->getEventReportQueue();
|
eventmanagerQueue = eventmanager->getEventReportQueue();
|
||||||
@ -53,6 +62,10 @@ public:
|
|||||||
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
|
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Initialized by EventManager (C++11 does not allow header-only static member initialization).
|
||||||
|
static MessageQueueId_t eventmanagerQueue;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EVENTMANAGERIF_H_ */
|
#endif /* FSFW_EVENTS_EVENTMANAGERIF_H_ */
|
||||||
|
@ -58,14 +58,14 @@ FaultCounter::FaultCounter() :
|
|||||||
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
|
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
if (domainId != parameterDomain) {
|
if (domainId != parameterDomain) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set(failureThreshold);
|
parameterWrapper->set(failureThreshold);
|
||||||
break;
|
break;
|
||||||
|
@ -23,7 +23,7 @@ public:
|
|||||||
void setFailureThreshold(uint32_t failureThreshold);
|
void setFailureThreshold(uint32_t failureThreshold);
|
||||||
void setFaultDecrementTimeMs(uint32_t timeMs);
|
void setFaultDecrementTimeMs(uint32_t timeMs);
|
||||||
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ void HousekeepingMessage::setUpdateNotificationVariableCommand(
|
|||||||
|
|
||||||
void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
|
void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
|
||||||
sid_t sid, store_address_t storeId) {
|
sid_t sid, store_address_t storeId) {
|
||||||
command->setCommand(UPDATE_SNAPSHOT_VARIABLE);
|
command->setCommand(UPDATE_SNAPSHOT_SET);
|
||||||
setSid(command, sid);
|
setSid(command, sid);
|
||||||
command->setParameter3(storeId.raw);
|
command->setParameter3(storeId.raw);
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,37 @@
|
|||||||
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_
|
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
|
||||||
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_
|
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
|
||||||
|
|
||||||
#include "../serialize/SerialBufferAdapter.h"
|
#include "../serialize/SerialBufferAdapter.h"
|
||||||
#include "../serialize/SerialLinkedListAdapter.h"
|
#include "../serialize/SerialLinkedListAdapter.h"
|
||||||
#include "../datapoollocal/LocalPoolDataSetBase.h"
|
#include "../datapoollocal/LocalPoolDataSetBase.h"
|
||||||
|
#include "../datapoollocal/LocalPoolObjectBase.h"
|
||||||
|
#include "../timemanager/CCSDSTime.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This helper class will be used to serialize and deserialize
|
* @brief This helper class will be used to serialize and deserialize update housekeeping packets
|
||||||
* update housekeeping packets into the store.
|
* into the store.
|
||||||
*/
|
*/
|
||||||
class HousekeepingPacketUpdate: public SerializeIF {
|
class HousekeepingSnapshot: public SerializeIF {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update packet constructor for datasets
|
* Update packet constructor for datasets.
|
||||||
* @param timeStamp
|
* @param cdsShort If a CSD short timestamp is used, a reference should be
|
||||||
* @param timeStampSize
|
* supplied here
|
||||||
* @param hkData
|
* @param dataSetPtr Pointer to the dataset instance to serialize or deserialize the
|
||||||
* @param hkDataSize
|
* data into
|
||||||
*/
|
*/
|
||||||
HousekeepingPacketUpdate(uint8_t* timeStamp, size_t timeStampSize,
|
HousekeepingSnapshot(CCSDSTime::CDS_short* cdsShort, LocalPoolDataSetBase* dataSetPtr):
|
||||||
|
timeStamp(reinterpret_cast<uint8_t*>(cdsShort)),
|
||||||
|
timeStampSize(sizeof(CCSDSTime::CDS_short)), updateData(dataSetPtr) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update packet constructor for datasets.
|
||||||
|
* @param timeStamp Pointer to the buffer where the timestamp will be stored.
|
||||||
|
* @param timeStampSize Size of the timestamp
|
||||||
|
* @param dataSetPtr Pointer to the dataset instance to deserialize the data into
|
||||||
|
*/
|
||||||
|
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize,
|
||||||
LocalPoolDataSetBase* dataSetPtr):
|
LocalPoolDataSetBase* dataSetPtr):
|
||||||
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
||||||
updateData(dataSetPtr) {};
|
updateData(dataSetPtr) {};
|
||||||
@ -29,7 +42,7 @@ public:
|
|||||||
* @param timeStampSize
|
* @param timeStampSize
|
||||||
* @param dataSetPtr
|
* @param dataSetPtr
|
||||||
*/
|
*/
|
||||||
HousekeepingPacketUpdate(uint8_t* timeStamp, size_t timeStampSize,
|
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize,
|
||||||
LocalPoolObjectBase* dataSetPtr):
|
LocalPoolObjectBase* dataSetPtr):
|
||||||
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
||||||
updateData(dataSetPtr) {};
|
updateData(dataSetPtr) {};
|
||||||
@ -89,4 +102,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_ */
|
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_ */
|
@ -37,16 +37,16 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId,
|
ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId,
|
||||||
parameterId, parameterWrapper, newValues, startAtIndex);
|
uniqueId, parameterWrapper, newValues, startAtIndex);
|
||||||
//We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there.
|
//We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there.
|
||||||
if (result != this->INVALID_IDENTIFIER_ID) {
|
if (result != this->INVALID_IDENTIFIER_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 10:
|
case 10:
|
||||||
parameterWrapper->set(this->lowerLimit);
|
parameterWrapper->set(this->lowerLimit);
|
||||||
break;
|
break;
|
||||||
|
@ -51,13 +51,13 @@ public:
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
if (domainId != monitorId) {
|
if (domainId != monitorId) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set(this->confirmationLimit);
|
parameterWrapper->set(this->confirmationLimit);
|
||||||
break;
|
break;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "../serialize/SerialFixedArrayListAdapter.h"
|
#include "../serialize/SerialFixedArrayListAdapter.h"
|
||||||
#include "../serialize/SerializeElement.h"
|
#include "../serialize/SerializeElement.h"
|
||||||
#include "../serialize/SerialLinkedListAdapter.h"
|
#include "../serialize/SerialLinkedListAdapter.h"
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
#include "../timemanager/TimeStamperIF.h"
|
#include "../timemanager/TimeStamperIF.h"
|
||||||
|
|
||||||
namespace Factory{
|
namespace Factory{
|
||||||
|
@ -71,13 +71,13 @@ public:
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
if (domainId != this->domainId) {
|
if (domainId != this->domainId) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set(limit);
|
parameterWrapper->set(limit);
|
||||||
break;
|
break;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "ObjectManager.h"
|
#include "ObjectManager.h"
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@ -75,6 +75,8 @@ void ObjectManager::initialize() {
|
|||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "ObjectManager::initialize: Passed produceObjects "
|
sif::error << "ObjectManager::initialize: Passed produceObjects "
|
||||||
"functions is nullptr!" << std::endl;
|
"functions is nullptr!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("ObjectManager::initialize: Passed produceObjects functions is nullptr!\n");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,18 @@
|
|||||||
SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) :
|
SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) :
|
||||||
objectId(setObjectId), registered(doRegister) {
|
objectId(setObjectId), registered(doRegister) {
|
||||||
if (registered) {
|
if (registered) {
|
||||||
|
if(objectManager != nullptr) {
|
||||||
objectManager->insert(objectId, this);
|
objectManager->insert(objectId, this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemObject::~SystemObject() {
|
SystemObject::~SystemObject() {
|
||||||
if (registered) {
|
if (registered) {
|
||||||
|
if(objectManager != nullptr) {
|
||||||
objectManager->remove(objectId);
|
objectManager->remove(objectId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object_id_t SystemObject::getObjectId() const {
|
object_id_t SystemObject::getObjectId() const {
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
#ifndef FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
|
#ifndef FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
|
||||||
#define FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
|
#define FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
|
||||||
|
|
||||||
|
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||||
|
|
||||||
namespace objects {
|
namespace objects {
|
||||||
enum framework_objects {
|
enum framework_objects: object_id_t {
|
||||||
|
FSFW_OBJECTS_START = 0x53000000,
|
||||||
// Default verification reporter.
|
// Default verification reporter.
|
||||||
PUS_SERVICE_1_VERIFICATION = 0x53000001,
|
PUS_SERVICE_1_VERIFICATION = 0x53000001,
|
||||||
PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002,
|
PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002,
|
||||||
@ -11,11 +14,12 @@ enum framework_objects {
|
|||||||
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
||||||
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
||||||
PUS_SERVICE_17_TEST = 0x53000017,
|
PUS_SERVICE_17_TEST = 0x53000017,
|
||||||
|
PUS_SERVICE_20_PARAMETERS = 0x53000020,
|
||||||
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
|
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
|
||||||
|
|
||||||
//Generic IDs for IPC, modes, health, events
|
//Generic IDs for IPC, modes, health, events
|
||||||
HEALTH_TABLE = 0x53010000,
|
HEALTH_TABLE = 0x53010000,
|
||||||
// MODE_STORE = 0x53010100,
|
// MODE_STORE = 0x53010100,
|
||||||
EVENT_MANAGER = 0x53030000,
|
EVENT_MANAGER = 0x53030000,
|
||||||
INTERNAL_ERROR_REPORTER = 0x53040000,
|
INTERNAL_ERROR_REPORTER = 0x53040000,
|
||||||
IPC_STORE = 0x534f0300,
|
IPC_STORE = 0x534f0300,
|
||||||
@ -24,6 +28,7 @@ enum framework_objects {
|
|||||||
TM_STORE = 0x534f0200,
|
TM_STORE = 0x534f0200,
|
||||||
TIME_STAMPER = 0x53500010,
|
TIME_STAMPER = 0x53500010,
|
||||||
|
|
||||||
|
FSFW_OBJECTS_END = 0x53ffffff,
|
||||||
NO_OBJECT = 0xFFFFFFFF
|
NO_OBJECT = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,8 @@
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <Windows.h>
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
|
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
|
||||||
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
|
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
|
||||||
#else
|
#else
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#include <windows.h>
|
#include <sysinfoapi.h>
|
||||||
#elif defined(LINUX)
|
#elif defined(LINUX)
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#endif
|
#endif
|
||||||
@ -15,35 +15,34 @@ using SystemClock = std::chrono::system_clock;
|
|||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void){
|
uint32_t Clock::getTicksPerSecond(void){
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl;
|
sif::warning << "Clock::getTicksPerSecond: Not implemented for host OSAL" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Clock::getTicksPerSecond: Not implemented for host OSAL\n");
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
/* To avoid division by zero */
|
||||||
//return CLOCKS_PER_SEC;
|
return 1;
|
||||||
//uint32_t ticks = sysconf(_SC_CLK_TCK);
|
|
||||||
//return ticks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||||
// do some magic with chrono
|
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
|
||||||
|
host system with internet access so this is not implemented for now. */
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Clock::setClock: not implemented yet" << std::endl;
|
sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
|
||||||
#endif
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::setClock(const timeval* time) {
|
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||||
// do some magic with chrono
|
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
|
||||||
#if defined(WIN32)
|
host system with internet access so this is not implemented for now. */
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
#elif defined(LINUX)
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
#else
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
|
sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
|
||||||
#endif
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||||
@ -53,8 +52,7 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
|||||||
auto epoch = now.time_since_epoch();
|
auto epoch = now.time_since_epoch();
|
||||||
time->tv_sec = std::chrono::duration_cast<std::chrono::seconds>(epoch).count();
|
time->tv_sec = std::chrono::duration_cast<std::chrono::seconds>(epoch).count();
|
||||||
auto fraction = now - secondsChrono;
|
auto fraction = now - secondsChrono;
|
||||||
time->tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
|
time->tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(fraction).count();
|
||||||
fraction).count();
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
#elif defined(LINUX)
|
#elif defined(LINUX)
|
||||||
timespec timeUnix;
|
timespec timeUnix;
|
||||||
@ -67,7 +65,9 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
#else
|
#else
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
|
sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Clock::getUptime: Not implemented for found OS!\n");
|
||||||
#endif
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
#endif
|
#endif
|
||||||
@ -75,10 +75,11 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||||
// do some magic with chrono
|
if(time == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl;
|
}
|
||||||
#endif
|
using namespace std::chrono;
|
||||||
|
*time = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,9 +121,9 @@ ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
|
|||||||
|
|
||||||
|
|
||||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||||
// do some magic with chrono (C++20!)
|
/* Do some magic with chrono (C++20!) */
|
||||||
// Right now, the library doesn't have the new features yet.
|
/* Right now, the library doesn't have the new features to get the required values yet.
|
||||||
// so we work around that for now.
|
so we work around that for now. */
|
||||||
auto now = SystemClock::now();
|
auto now = SystemClock::now();
|
||||||
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
||||||
auto fraction = now - seconds;
|
auto fraction = now - seconds;
|
||||||
@ -137,10 +138,6 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
|||||||
time->second = timeInfo->tm_sec;
|
time->second = timeInfo->tm_sec;
|
||||||
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
|
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
|
||||||
time->usecond = usecond.count();
|
time->usecond = usecond.count();
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
//sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl;
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#include <windows.h>
|
#include <processthreadsapi.h>
|
||||||
#elif defined(LINUX)
|
#elif defined(LINUX)
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,13 +5,13 @@ target_sources(${LIB_FSFW_NAME}
|
|||||||
InitTask.cpp
|
InitTask.cpp
|
||||||
InternalErrorCodes.cpp
|
InternalErrorCodes.cpp
|
||||||
MessageQueue.cpp
|
MessageQueue.cpp
|
||||||
MultiObjectTask.cpp
|
PeriodicTask.cpp
|
||||||
Mutex.cpp
|
Mutex.cpp
|
||||||
MutexFactory.cpp
|
MutexFactory.cpp
|
||||||
PollingTask.cpp
|
FixedTimeslotTask.cpp
|
||||||
QueueFactory.cpp
|
QueueFactory.cpp
|
||||||
RtemsBasic.cpp
|
RtemsBasic.cpp
|
||||||
TaskBase.cpp
|
RTEMSTaskBase.cpp
|
||||||
TaskFactory.cpp
|
TaskFactory.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -104,9 +104,13 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||||
// TIsn't this a bug? Are RTEMS ticks always microseconds?
|
/* For all but the last field, the struct will be filled with the correct values */
|
||||||
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time);
|
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time);
|
||||||
rtems_status_code status = rtems_clock_get_tod(timeRtems);
|
rtems_status_code status = rtems_clock_get_tod(timeRtems);
|
||||||
|
/* The last field now contains the RTEMS ticks of the seconds from 0
|
||||||
|
to rtems_clock_get_ticks_per_second() minus one. We calculate the microseconds accordingly */
|
||||||
|
timeRtems->ticks = static_cast<float>(timeRtems->ticks) /
|
||||||
|
rtems_clock_get_ticks_per_second() * 1e6;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case RTEMS_SUCCESSFUL:
|
case RTEMS_SUCCESSFUL:
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
@ -164,7 +164,7 @@ ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer,
|
|||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if ((*size = *size - MAX_LENGTH_OF_THREAD_NAME) < 0) {
|
if (*size < MAX_LENGTH_OF_THREAD_NAME) {
|
||||||
return STREAM_TOO_SHORT;
|
return STREAM_TOO_SHORT;
|
||||||
}
|
}
|
||||||
memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME);
|
memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME);
|
||||||
|
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 "Mutex.h"
|
||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
#include "../../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
uint8_t Mutex::count = 0;
|
uint8_t Mutex::count = 0;
|
||||||
|
|
||||||
Mutex::Mutex() :
|
Mutex::Mutex() {
|
||||||
mutexId(0) {
|
|
||||||
rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++;
|
rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++;
|
||||||
rtems_status_code status = rtems_semaphore_create(mutexName, 1,
|
rtems_status_code status = rtems_semaphore_create(mutexName, 1,
|
||||||
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
|
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
|
||||||
&mutexId);
|
&mutexId);
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "Mutex: creation with name, id " << mutexName << ", " << mutexId
|
sif::error << "Mutex::Mutex: Creation with name, id " << mutexName << ", " << mutexId <<
|
||||||
<< " failed with " << status << std::endl;
|
" failed with " << status << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("Mutex::Mutex: Creation with name, id %s, %d failed with %d\n", mutexName,
|
||||||
|
static_cast<int>(mutexId), static_cast<int>(status));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ public:
|
|||||||
ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0);
|
ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0);
|
||||||
ReturnValue_t unlockMutex();
|
ReturnValue_t unlockMutex();
|
||||||
private:
|
private:
|
||||||
rtems_id mutexId;
|
rtems_id mutexId = 0;
|
||||||
static uint8_t count;
|
static uint8_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "../../ipc/MutexFactory.h"
|
|
||||||
#include "Mutex.h"
|
#include "Mutex.h"
|
||||||
#include "RtemsBasic.h"
|
|
||||||
|
#include "../../ipc/MutexFactory.h"
|
||||||
|
|
||||||
|
|
||||||
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
||||||
|
|
||||||
|
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_
|
#ifndef FSFW_OSAL_RTEMS_PERIODICTASK_H_
|
||||||
#define FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_
|
#define FSFW_OSAL_RTEMS_PERIODICTASK_H_
|
||||||
|
|
||||||
|
#include "RTEMSTaskBase.h"
|
||||||
#include "../../objectmanager/ObjectManagerIF.h"
|
#include "../../objectmanager/ObjectManagerIF.h"
|
||||||
#include "../../tasks/PeriodicTaskIF.h"
|
#include "../../tasks/PeriodicTaskIF.h"
|
||||||
|
|
||||||
#include "TaskBase.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class ExecutableObjectIF;
|
class ExecutableObjectIF;
|
||||||
@ -18,7 +18,7 @@ class ExecutableObjectIF;
|
|||||||
* @author baetz
|
* @author baetz
|
||||||
* @ingroup task_handling
|
* @ingroup task_handling
|
||||||
*/
|
*/
|
||||||
class MultiObjectTask: public TaskBase, public PeriodicTaskIF {
|
class PeriodicTask: public RTEMSTaskBase, public PeriodicTaskIF {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Standard constructor of the class.
|
* @brief Standard constructor of the class.
|
||||||
@ -35,13 +35,13 @@ public:
|
|||||||
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
|
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
|
||||||
* that shall be assigned.
|
* that shall be assigned.
|
||||||
*/
|
*/
|
||||||
MultiObjectTask(const char *name, rtems_task_priority setPriority, size_t setStack, rtems_interval setPeriod,
|
PeriodicTask(const char *name, rtems_task_priority setPriority, size_t setStack,
|
||||||
void (*setDeadlineMissedFunc)());
|
rtems_interval setPeriod, void (*setDeadlineMissedFunc)());
|
||||||
/**
|
/**
|
||||||
* @brief Currently, the executed object's lifetime is not coupled with the task object's
|
* @brief Currently, the executed object's lifetime is not coupled with the task object's
|
||||||
* lifetime, so the destructor is empty.
|
* lifetime, so the destructor is empty.
|
||||||
*/
|
*/
|
||||||
virtual ~MultiObjectTask(void);
|
virtual ~PeriodicTask(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The method to start the task.
|
* @brief The method to start the task.
|
||||||
@ -76,7 +76,7 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* @brief id of the associated OS period
|
* @brief id of the associated OS period
|
||||||
*/
|
*/
|
||||||
rtems_id periodId;
|
rtems_id periodId = 0;
|
||||||
/**
|
/**
|
||||||
* @brief The pointer to the deadline-missed function.
|
* @brief The pointer to the deadline-missed function.
|
||||||
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
||||||
@ -104,4 +104,4 @@ protected:
|
|||||||
void taskFunctionality(void);
|
void taskFunctionality(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ */
|
#endif /* FSFW_OSAL_RTEMS_PERIODICTASK_H_ */
|
@ -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 "RTEMSTaskBase.h"
|
||||||
#include "TaskBase.h"
|
#include "../../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE=RTEMS_MINIMUM_STACK_SIZE;
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = RTEMS_MINIMUM_STACK_SIZE;
|
||||||
|
|
||||||
TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
|
RTEMSTaskBase::RTEMSTaskBase(rtems_task_priority set_priority, size_t stack_size,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
rtems_name osalName = 0;
|
rtems_name osalName = 0;
|
||||||
for (uint8_t i = 0; i < 4; i++) {
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
@ -14,7 +14,7 @@ TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
|
|||||||
}
|
}
|
||||||
//The task is created with the operating system's system call.
|
//The task is created with the operating system's system call.
|
||||||
rtems_status_code status = RTEMS_UNSATISFIED;
|
rtems_status_code status = RTEMS_UNSATISFIED;
|
||||||
if (set_priority >= 0 && set_priority <= 99) {
|
if (set_priority <= 99) {
|
||||||
status = rtems_task_create(osalName,
|
status = rtems_task_create(osalName,
|
||||||
(0xFF - 2 * set_priority), stack_size,
|
(0xFF - 2 * set_priority), stack_size,
|
||||||
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
|
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
|
||||||
@ -31,21 +31,21 @@ TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskBase::~TaskBase() {
|
RTEMSTaskBase::~RTEMSTaskBase() {
|
||||||
rtems_task_delete(id);
|
rtems_task_delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
rtems_id TaskBase::getId() {
|
rtems_id RTEMSTaskBase::getId() {
|
||||||
return this->id;
|
return this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TaskBase::sleepFor(uint32_t ms) {
|
ReturnValue_t RTEMSTaskBase::sleepFor(uint32_t ms) {
|
||||||
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
|
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
|
||||||
return convertReturnCode(status);
|
return convertReturnCode(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t TaskBase::convertReturnCode(rtems_status_code inValue) {
|
ReturnValue_t RTEMSTaskBase::convertReturnCode(rtems_status_code inValue) {
|
||||||
switch (inValue) {
|
switch (inValue) {
|
||||||
case RTEMS_SUCCESSFUL:
|
case RTEMS_SUCCESSFUL:
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
@ -68,7 +68,7 @@ ReturnValue_t TaskBase::convertReturnCode(rtems_status_code inValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t TaskBase::setAndStartPeriod(rtems_interval period, rtems_id *periodId) {
|
ReturnValue_t RTEMSTaskBase::setAndStartPeriod(rtems_interval period, rtems_id *periodId) {
|
||||||
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
|
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
|
||||||
rtems_status_code status = rtems_rate_monotonic_create(periodName, periodId);
|
rtems_status_code status = rtems_rate_monotonic_create(periodName, periodId);
|
||||||
if (status == RTEMS_SUCCESSFUL) {
|
if (status == RTEMS_SUCCESSFUL) {
|
||||||
@ -77,7 +77,7 @@ ReturnValue_t TaskBase::setAndStartPeriod(rtems_interval period, rtems_id *perio
|
|||||||
return convertReturnCode(status);
|
return convertReturnCode(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
rtems_status_code TaskBase::restartPeriod(rtems_interval period, rtems_id periodId){
|
rtems_status_code RTEMSTaskBase::restartPeriod(rtems_interval period, rtems_id periodId){
|
||||||
//This is necessary to avoid a call with period = 0, which does not start the period.
|
//This is necessary to avoid a call with period = 0, which does not start the period.
|
||||||
rtems_status_code status = rtems_rate_monotonic_period(periodId, period + 1);
|
rtems_status_code status = rtems_rate_monotonic_period(periodId, period + 1);
|
||||||
return status;
|
return status;
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef FSFW_OSAL_RTEMS_TASKBASE_H_
|
#ifndef FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_
|
||||||
#define FSFW_OSAL_RTEMS_TASKBASE_H_
|
#define FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_
|
||||||
|
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
#include "../../tasks/PeriodicTaskIF.h"
|
#include "../../tasks/PeriodicTaskIF.h"
|
||||||
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* @details Task creation base class for rtems.
|
* @details Task creation base class for rtems.
|
||||||
*/
|
*/
|
||||||
class TaskBase {
|
class RTEMSTaskBase {
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief The class stores the task id it got assigned from the operating system in this attribute.
|
* @brief The class stores the task id it got assigned from the operating system in this attribute.
|
||||||
@ -26,11 +26,11 @@ public:
|
|||||||
* @param stack_size The stack size reserved by the operating system for the task.
|
* @param stack_size The stack size reserved by the operating system for the task.
|
||||||
* @param nam The name of the Task, as a null-terminated String. Currently max 4 chars supported (excluding Null-terminator), rest will be truncated
|
* @param nam The name of the Task, as a null-terminated String. Currently max 4 chars supported (excluding Null-terminator), rest will be truncated
|
||||||
*/
|
*/
|
||||||
TaskBase( rtems_task_priority priority, size_t stack_size, const char *name);
|
RTEMSTaskBase( rtems_task_priority priority, size_t stack_size, const char *name);
|
||||||
/**
|
/**
|
||||||
* @brief In the destructor, the created task is deleted.
|
* @brief In the destructor, the created task is deleted.
|
||||||
*/
|
*/
|
||||||
virtual ~TaskBase();
|
virtual ~RTEMSTaskBase();
|
||||||
/**
|
/**
|
||||||
* @brief This method returns the task id of this class.
|
* @brief This method returns the task id of this class.
|
||||||
*/
|
*/
|
||||||
@ -44,4 +44,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_RTEMS_TASKBASE_H_ */
|
#endif /* FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_ */
|
@ -1,5 +1,6 @@
|
|||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
|
|
||||||
|
// TODO: Can this be removed?
|
||||||
|
|
||||||
//ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
|
//ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
|
||||||
// if (inValue == RTEMS_SUCCESSFUL) {
|
// if (inValue == RTEMS_SUCCESSFUL) {
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_
|
#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_
|
||||||
|
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
#include <rtems/libio.h>
|
#include <rtems/libio.h>
|
||||||
#include <rtems/error.h>
|
#include <rtems/error.h>
|
||||||
#include <rtems/stackchk.h>
|
#include <rtems/stackchk.h>
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
class RtemsBasic {
|
class RtemsBasic {
|
||||||
public:
|
public:
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "../../tasks/TaskFactory.h"
|
#include "FixedTimeslotTask.h"
|
||||||
#include "MultiObjectTask.h"
|
#include "PeriodicTask.h"
|
||||||
#include "PollingTask.h"
|
|
||||||
#include "InitTask.h"
|
#include "InitTask.h"
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
|
|
||||||
|
#include "../../tasks/TaskFactory.h"
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
||||||
@ -15,15 +16,21 @@ TaskFactory* TaskFactory::instance() {
|
|||||||
return TaskFactory::factoryInstance;
|
return TaskFactory::factoryInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
|
||||||
|
TaskStackSize stackSize_,TaskPeriod periodInSeconds_,
|
||||||
|
TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||||
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
||||||
|
|
||||||
return static_cast<PeriodicTaskIF*>(new MultiObjectTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_));
|
return static_cast<PeriodicTaskIF*>(new PeriodicTask(name_, taskPriority_, stackSize_,
|
||||||
|
taskPeriod,deadLineMissedFunction_));
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,
|
||||||
|
TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,
|
||||||
|
TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||||
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
||||||
return static_cast<FixedTimeslotTaskIF*>(new PollingTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_));
|
return static_cast<FixedTimeslotTaskIF*>(new FixedTimeslotTask(name_, taskPriority_,
|
||||||
|
stackSize_, taskPeriod, deadLineMissedFunction_));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
||||||
|
@ -52,9 +52,8 @@ public:
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t getFullParameterId(uint8_t domainId,
|
static uint32_t getFullParameterId(uint8_t domainId, uint8_t uniqueId, uint16_t linearIndex) {
|
||||||
uint8_t uniqueIdentifier, uint16_t linearIndex) {
|
return (domainId << 24) + (uniqueId << 16) + linearIndex;
|
||||||
return (domainId << 24) + (uniqueIdentifier << 16) + linearIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~HasParametersIF() {}
|
virtual ~HasParametersIF() {}
|
||||||
@ -74,9 +73,9 @@ public:
|
|||||||
* matrix indexes.
|
* matrix indexes.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||||
uint16_t uniqueIdentifier, ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex) = 0;
|
uint16_t startAtIndex) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_PARAMETERS_HASPARAMETERSIF_H_ */
|
#endif /* FSFW_PARAMETERS_HASPARAMETERSIF_H_ */
|
||||||
|
@ -90,7 +90,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id,
|
|||||||
const ParameterWrapper* description) {
|
const ParameterWrapper* description) {
|
||||||
size_t serializedSize = description->getSerializedSize();
|
size_t serializedSize = description->getSerializedSize();
|
||||||
|
|
||||||
uint8_t *storeElement;
|
uint8_t *storeElement = nullptr;
|
||||||
store_address_t address;
|
store_address_t address;
|
||||||
|
|
||||||
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
|
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
|
||||||
|
@ -38,7 +38,7 @@ void ParameterMessage::setParameterLoadCommand(CommandMessage* message,
|
|||||||
store_address_t ParameterMessage::getParameterLoadCommand(
|
store_address_t ParameterMessage::getParameterLoadCommand(
|
||||||
const CommandMessage *message, ParameterId_t* parameterId, uint8_t *ptc,
|
const CommandMessage *message, ParameterId_t* parameterId, uint8_t *ptc,
|
||||||
uint8_t *pfc, uint8_t *rows, uint8_t *columns) {
|
uint8_t *pfc, uint8_t *rows, uint8_t *columns) {
|
||||||
*parameterId = message->getParameter2();
|
*parameterId = message->getParameter();
|
||||||
uint32_t packedParamSettings = message->getParameter3();
|
uint32_t packedParamSettings = message->getParameter3();
|
||||||
*ptc = packedParamSettings >> 24 & 0xff;
|
*ptc = packedParamSettings >> 24 & 0xff;
|
||||||
*pfc = packedParamSettings >> 16 & 0xff;
|
*pfc = packedParamSettings >> 16 & 0xff;
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
#include "ParameterWrapper.h"
|
#include "ParameterWrapper.h"
|
||||||
|
#include <FSFWConfig.h>
|
||||||
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||||
|
|
||||||
ParameterWrapper::ParameterWrapper() :
|
ParameterWrapper::ParameterWrapper() :
|
||||||
pointsToStream(false), type(Type::UNKNOWN_TYPE) {
|
pointsToStream(false), type(Type::UNKNOWN_TYPE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
||||||
void *data) :
|
void *data):
|
||||||
pointsToStream(false), type(type), rows(rows), columns(columns),
|
pointsToStream(false), type(type), rows(rows), columns(columns),
|
||||||
data(data), readonlyData(data) {
|
data(data), readonlyData(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
||||||
const void *data) :
|
const void *data):
|
||||||
pointsToStream(false), type(type), rows(rows), columns(columns),
|
pointsToStream(false), type(type), rows(rows), columns(columns),
|
||||||
data(nullptr), readonlyData(data) {
|
data(nullptr), readonlyData(data) {
|
||||||
}
|
}
|
||||||
@ -40,8 +42,8 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//serialize uses readonlyData, as it is always valid
|
/* serialize uses readonlyData, as it is always valid */
|
||||||
if (readonlyData == NULL) {
|
if (readonlyData == nullptr) {
|
||||||
return NOT_SET;
|
return NOT_SET;
|
||||||
}
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -75,7 +77,7 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size,
|
|||||||
result = serializeData<double>(buffer, size, maxSize, streamEndianness);
|
result = serializeData<double>(buffer, size, maxSize, streamEndianness);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = UNKNOW_DATATYPE;
|
result = UNKNOWN_DATATYPE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -220,22 +222,48 @@ ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize,
|
|||||||
|
|
||||||
ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
||||||
uint16_t startWritingAtIndex) {
|
uint16_t startWritingAtIndex) {
|
||||||
// TODO: Optional diagnostic output (which can be disabled in FSFWConfig)
|
|
||||||
// to determined faulty implementations and configuration errors quickly.
|
|
||||||
if (data == nullptr) {
|
if (data == nullptr) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ParameterWrapper::copyFrom: Called on read-only variable!\n");
|
||||||
|
#endif
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return READONLY;
|
return READONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from->readonlyData == nullptr) {
|
if (from->readonlyData == nullptr) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ParameterWrapper::copyFrom: Source not set!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ParameterWrapper::copyFrom: Source not set!\n");
|
||||||
|
#endif
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return SOURCE_NOT_SET;
|
return SOURCE_NOT_SET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != from->type) {
|
if (type != from->type) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch!\n");
|
||||||
|
#endif
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return DATATYPE_MISSMATCH;
|
return DATATYPE_MISSMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The smallest allowed value for rows and columns is one.
|
// The smallest allowed value for rows and columns is one.
|
||||||
if(rows == 0 or columns == 0) {
|
if(rows == 0 or columns == 0) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero!\n");
|
||||||
|
#endif
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return COLUMN_OR_ROWS_ZERO;
|
return COLUMN_OR_ROWS_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +317,7 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
|||||||
from->readonlyData, from->rows, from->columns);
|
from->readonlyData, from->rows, from->columns);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = UNKNOW_DATATYPE;
|
result = UNKNOWN_DATATYPE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,23 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief This wrapper encapsulates the access to parameters provided by HasParametersIF.
|
||||||
* @details
|
* @details
|
||||||
|
* This wrapper is used by the ParameterHelper to interface with the on-board parameters
|
||||||
|
* exposed by the software via the HasParametersIF. A handle of this wrapper is passed
|
||||||
|
* to the user which then can be used to set or dump the parameters.
|
||||||
|
*
|
||||||
|
* The wrapper provides a set of setter functions. The user should call those setter functions,
|
||||||
|
* supplying an address to the local parameters. The user can also deserialize or
|
||||||
|
* serialize the parameter data. Please note that this will also serialize and deserialize
|
||||||
|
* the parameter information field (4 bytes) containing the ECSS PTC, PFC and rows and columns
|
||||||
|
* number.
|
||||||
*/
|
*/
|
||||||
class ParameterWrapper: public SerializeIF {
|
class ParameterWrapper: public SerializeIF {
|
||||||
friend class DataPoolParameterWrapper;
|
friend class DataPoolParameterWrapper;
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::PARAMETER_WRAPPER;
|
static const uint8_t INTERFACE_ID = CLASS_ID::PARAMETER_WRAPPER;
|
||||||
static const ReturnValue_t UNKNOW_DATATYPE = MAKE_RETURN_CODE(0x01);
|
static const ReturnValue_t UNKNOWN_DATATYPE = MAKE_RETURN_CODE(0x01);
|
||||||
static const ReturnValue_t DATATYPE_MISSMATCH = MAKE_RETURN_CODE(0x02);
|
static const ReturnValue_t DATATYPE_MISSMATCH = MAKE_RETURN_CODE(0x02);
|
||||||
static const ReturnValue_t READONLY = MAKE_RETURN_CODE(0x03);
|
static const ReturnValue_t READONLY = MAKE_RETURN_CODE(0x03);
|
||||||
static const ReturnValue_t TOO_BIG = MAKE_RETURN_CODE(0x04);
|
static const ReturnValue_t TOO_BIG = MAKE_RETURN_CODE(0x04);
|
||||||
@ -26,8 +35,7 @@ public:
|
|||||||
|
|
||||||
ParameterWrapper();
|
ParameterWrapper();
|
||||||
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data);
|
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data);
|
||||||
ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, const void *data);
|
||||||
const void *data);
|
|
||||||
virtual ~ParameterWrapper();
|
virtual ~ParameterWrapper();
|
||||||
|
|
||||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||||
@ -77,11 +85,23 @@ public:
|
|||||||
this->pointsToStream = false;
|
this->pointsToStream = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter function for scalar non-const entries
|
||||||
|
* @tparam T
|
||||||
|
* @param member
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void set(T& member) {
|
void set(T& member) {
|
||||||
this->set(&member, 1, 1);
|
this->set(&member, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter function for scalar const entries.
|
||||||
|
* TODO: This is confusing, it should not be called set. Maybe we should call all functions
|
||||||
|
* assign instead?
|
||||||
|
* @tparam T
|
||||||
|
* @param readonlyMember
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void set(const T& readonlyMember) {
|
void set(const T& readonlyMember) {
|
||||||
this->set(&readonlyMember, 1, 1);
|
this->set(&readonlyMember, 1, 1);
|
||||||
@ -89,12 +109,16 @@ public:
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void setVector(T& member) {
|
void setVector(T& member) {
|
||||||
this->set(member, sizeof(member)/sizeof(member[0]), 1);
|
/* For a vector entry, the number of rows will be one
|
||||||
|
(left to right, top to bottom indexing) */
|
||||||
|
this->set(member, 1, sizeof(member) / sizeof(member[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void setVector(const T& member) {
|
void setVector(const T& member) {
|
||||||
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>
|
template<typename T>
|
||||||
void setMatrix(T& member) {
|
void setMatrix(T& member) {
|
||||||
|
@ -210,15 +210,15 @@ void Fuse::setDataPoolEntriesInvalid() {
|
|||||||
set.commit();
|
set.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Fuse::getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t Fuse::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = currentLimit.getParameter(domainId, parameterId,
|
ReturnValue_t result = currentLimit.getParameter(domainId, uniqueId,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
parameterWrapper, newValues, startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = powerMonitor.getParameter(domainId, parameterId, parameterWrapper,
|
result = powerMonitor.getParameter(domainId, uniqueId, parameterWrapper,
|
||||||
newValues, startAtIndex);
|
newValues, startAtIndex);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,9 @@ public:
|
|||||||
ReturnValue_t setHealth(HealthState health);
|
ReturnValue_t setHealth(HealthState health);
|
||||||
HasHealthIF::HealthState getHealth();
|
HasHealthIF::HealthState getHealth();
|
||||||
|
|
||||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
uint16_t startAtIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t oldFuseState;
|
uint8_t oldFuseState;
|
||||||
|
@ -61,13 +61,13 @@ ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, size_t* size,
|
|||||||
return SerializeAdapter::deSerialize(&max, buffer, size, streamEndianness);
|
return SerializeAdapter::deSerialize(&max, buffer, size, streamEndianness);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PowerComponent::getParameter(uint8_t domainId,
|
ReturnValue_t PowerComponent::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
if (domainId != moduleId) {
|
if (domainId != moduleId) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set<>(min);
|
parameterWrapper->set<>(min);
|
||||||
break;
|
break;
|
||||||
|
@ -31,9 +31,9 @@ public:
|
|||||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
Endianness streamEndianness) override;
|
Endianness streamEndianness) override;
|
||||||
|
|
||||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
uint16_t startAtIndex);
|
||||||
private:
|
private:
|
||||||
const object_id_t deviceObjectId = objects::NO_OBJECT;
|
const object_id_t deviceObjectId = objects::NO_OBJECT;
|
||||||
const uint8_t switchId1;
|
const uint8_t switchId1;
|
||||||
|
@ -119,15 +119,15 @@ HasHealthIF::HealthState PowerSensor::getHealth() {
|
|||||||
return healthHelper.getHealth();
|
return healthHelper.getHealth();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PowerSensor::getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t PowerSensor::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = currentLimit.getParameter(domainId, parameterId,
|
ReturnValue_t result = currentLimit.getParameter(domainId, uniqueId,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
parameterWrapper, newValues, startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = voltageLimit.getParameter(domainId, parameterId, parameterWrapper,
|
result = voltageLimit.getParameter(domainId, uniqueId, parameterWrapper,
|
||||||
newValues, startAtIndex);
|
newValues, startAtIndex);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ public:
|
|||||||
float getPower();
|
float getPower();
|
||||||
ReturnValue_t setHealth(HealthState health);
|
ReturnValue_t setHealth(HealthState health);
|
||||||
HasHealthIF::HealthState getHealth();
|
HasHealthIF::HealthState getHealth();
|
||||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||||
private:
|
private:
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
PRIVATE
|
|
||||||
CService200ModeCommanding.cpp
|
|
||||||
CService201HealthCommanding.cpp
|
|
||||||
Service17Test.cpp
|
|
||||||
Service1TelecommandVerification.cpp
|
Service1TelecommandVerification.cpp
|
||||||
Service2DeviceAccess.cpp
|
Service2DeviceAccess.cpp
|
||||||
Service3Housekeeping.cpp
|
Service3Housekeeping.cpp
|
||||||
Service5EventReporting.cpp
|
Service5EventReporting.cpp
|
||||||
Service8FunctionManagement.cpp
|
Service8FunctionManagement.cpp
|
||||||
Service9TimeManagement.cpp
|
Service9TimeManagement.cpp
|
||||||
|
Service17Test.cpp
|
||||||
|
Service20ParameterManagement.cpp
|
||||||
|
CService200ModeCommanding.cpp
|
||||||
|
CService201HealthCommanding.cpp
|
||||||
)
|
)
|
@ -15,7 +15,7 @@ Service17Test::~Service17Test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
|
ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
|
||||||
switch(subservice){
|
switch(subservice) {
|
||||||
case Subservice::CONNECTION_TEST: {
|
case Subservice::CONNECTION_TEST: {
|
||||||
TmPacketStored connectionPacket(apid, serviceId,
|
TmPacketStored connectionPacket(apid, serviceId,
|
||||||
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case ActionMessage::DATA_REPLY: {
|
case ActionMessage::DATA_REPLY: {
|
||||||
|
/* Multiple data replies are possible, so declare data reply as step */
|
||||||
|
*isStep = true;
|
||||||
result = handleDataReply(reply, objectId, actionId);
|
result = handleDataReply(reply, objectId, actionId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ActionMessage::STEP_FAILED:
|
case ActionMessage::STEP_FAILED:
|
||||||
*isStep = true;
|
*isStep = true;
|
||||||
/*No break, falls through*/
|
/* No break, falls through */
|
||||||
case ActionMessage::COMPLETION_FAILED:
|
case ActionMessage::COMPLETION_FAILED:
|
||||||
result = ActionMessage::getReturnCode(reply);
|
result = ActionMessage::getReturnCode(reply);
|
||||||
break;
|
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 FSFW_COLORED_OUTPUT == 1
|
||||||
if(setMessage.find("DEBUG") != std::string::npos) {
|
if(setMessage.find("DEBUG") != std::string::npos) {
|
||||||
colorPrefix = sif::ANSI_COLOR_MAGENTA;
|
colorPrefix = sif::ANSI_COLOR_CYAN;
|
||||||
}
|
}
|
||||||
else if(setMessage.find("INFO") != std::string::npos) {
|
else if(setMessage.find("INFO") != std::string::npos) {
|
||||||
colorPrefix = sif::ANSI_COLOR_GREEN;
|
colorPrefix = sif::ANSI_COLOR_GREEN;
|
||||||
|
@ -45,7 +45,7 @@ void fsfwPrint(sif::PrintLevel printType, const char* fmt, va_list arg) {
|
|||||||
len += sprintf(bufferPosition, sif::ANSI_COLOR_GREEN);
|
len += sprintf(bufferPosition, sif::ANSI_COLOR_GREEN);
|
||||||
}
|
}
|
||||||
else if(printType == sif::PrintLevel::DEBUG_LEVEL) {
|
else if(printType == sif::PrintLevel::DEBUG_LEVEL) {
|
||||||
len += sprintf(bufferPosition, sif::ANSI_COLOR_MAGENTA);
|
len += sprintf(bufferPosition, sif::ANSI_COLOR_CYAN);
|
||||||
}
|
}
|
||||||
else if(printType == sif::PrintLevel::WARNING_LEVEL) {
|
else if(printType == sif::PrintLevel::WARNING_LEVEL) {
|
||||||
len += sprintf(bufferPosition, sif::ANSI_COLOR_YELLOW);
|
len += sprintf(bufferPosition, sif::ANSI_COLOR_YELLOW);
|
||||||
|
@ -39,6 +39,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::string* getPreamble();
|
std::string* getPreamble();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to determine if the stream was configured to add CR characters in addition
|
||||||
|
* to newline characters.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
bool crAdditionEnabled() const;
|
bool crAdditionEnabled() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -5,15 +5,15 @@
|
|||||||
LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig,
|
LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig,
|
||||||
bool registered, bool spillsToHigherPools):
|
bool registered, bool spillsToHigherPools):
|
||||||
SystemObject(setObjectId, registered),
|
SystemObject(setObjectId, registered),
|
||||||
NUMBER_OF_POOLS(poolConfig.size()),
|
NUMBER_OF_SUBPOOLS(poolConfig.size()),
|
||||||
spillsToHigherPools(spillsToHigherPools) {
|
spillsToHigherPools(spillsToHigherPools) {
|
||||||
if(NUMBER_OF_POOLS == 0) {
|
if(NUMBER_OF_SUBPOOLS == 0) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "LocalPool::LocalPool: Passed pool configuration is "
|
sif::error << "LocalPool::LocalPool: Passed pool configuration is "
|
||||||
<< " invalid!" << std::endl;
|
<< " invalid!" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
max_pools_t index = 0;
|
max_subpools_t index = 0;
|
||||||
for (const auto& currentPoolConfig: poolConfig) {
|
for (const auto& currentPoolConfig: poolConfig) {
|
||||||
this->numberOfElements[index] = currentPoolConfig.first;
|
this->numberOfElements[index] = currentPoolConfig.first;
|
||||||
this->elementSizes[index] = currentPoolConfig.second;
|
this->elementSizes[index] = currentPoolConfig.second;
|
||||||
@ -98,7 +98,7 @@ ReturnValue_t LocalPool::modifyData(store_address_t storeId,
|
|||||||
ReturnValue_t LocalPool::modifyData(store_address_t storeId,
|
ReturnValue_t LocalPool::modifyData(store_address_t storeId,
|
||||||
uint8_t **packetPtr, size_t *size) {
|
uint8_t **packetPtr, size_t *size) {
|
||||||
ReturnValue_t status = RETURN_FAILED;
|
ReturnValue_t status = RETURN_FAILED;
|
||||||
if (storeId.poolIndex >= NUMBER_OF_POOLS) {
|
if (storeId.poolIndex >= NUMBER_OF_SUBPOOLS) {
|
||||||
return ILLEGAL_STORAGE_ID;
|
return ILLEGAL_STORAGE_ID;
|
||||||
}
|
}
|
||||||
if ((storeId.packetIndex >= numberOfElements[storeId.poolIndex])) {
|
if ((storeId.packetIndex >= numberOfElements[storeId.poolIndex])) {
|
||||||
@ -127,7 +127,7 @@ ReturnValue_t LocalPool::deleteData(store_address_t storeId) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
ReturnValue_t status = RETURN_OK;
|
ReturnValue_t status = RETURN_OK;
|
||||||
size_type pageSize = getPageSize(storeId.poolIndex);
|
size_type pageSize = getSubpoolElementSize(storeId.poolIndex);
|
||||||
if ((pageSize != 0) and
|
if ((pageSize != 0) and
|
||||||
(storeId.packetIndex < numberOfElements[storeId.poolIndex])) {
|
(storeId.packetIndex < numberOfElements[storeId.poolIndex])) {
|
||||||
uint16_t packetPosition = getRawPosition(storeId);
|
uint16_t packetPosition = getRawPosition(storeId);
|
||||||
@ -151,7 +151,7 @@ ReturnValue_t LocalPool::deleteData(uint8_t *ptr, size_t size,
|
|||||||
store_address_t *storeId) {
|
store_address_t *storeId) {
|
||||||
store_address_t localId;
|
store_address_t localId;
|
||||||
ReturnValue_t result = ILLEGAL_ADDRESS;
|
ReturnValue_t result = ILLEGAL_ADDRESS;
|
||||||
for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) {
|
for (uint16_t n = 0; n < NUMBER_OF_SUBPOOLS; n++) {
|
||||||
//Not sure if new allocates all stores in order. so better be careful.
|
//Not sure if new allocates all stores in order. so better be careful.
|
||||||
if ((store[n].data() <= ptr) and
|
if ((store[n].data() <= ptr) and
|
||||||
(&store[n][numberOfElements[n]*elementSizes[n]] > ptr)) {
|
(&store[n][numberOfElements[n]*elementSizes[n]] > ptr)) {
|
||||||
@ -192,7 +192,7 @@ ReturnValue_t LocalPool::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Check if any pool size is large than the maximum allowed.
|
//Check if any pool size is large than the maximum allowed.
|
||||||
for (uint8_t count = 0; count < NUMBER_OF_POOLS; count++) {
|
for (uint8_t count = 0; count < NUMBER_OF_SUBPOOLS; count++) {
|
||||||
if (elementSizes[count] >= STORAGE_FREE) {
|
if (elementSizes[count] >= STORAGE_FREE) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "LocalPool::initialize: Pool is too large! "
|
sif::error << "LocalPool::initialize: Pool is too large! "
|
||||||
@ -217,7 +217,7 @@ void LocalPool::clearStore() {
|
|||||||
|
|
||||||
ReturnValue_t LocalPool::reserveSpace(const size_t size,
|
ReturnValue_t LocalPool::reserveSpace(const size_t size,
|
||||||
store_address_t *storeId, bool ignoreFault) {
|
store_address_t *storeId, bool ignoreFault) {
|
||||||
ReturnValue_t status = getPoolIndex(size, &storeId->poolIndex);
|
ReturnValue_t status = getSubPoolIndex(size, &storeId->poolIndex);
|
||||||
if (status != RETURN_OK) {
|
if (status != RETURN_OK) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "LocalPool( " << std::hex << getObjectId() << std::dec
|
sif::error << "LocalPool( " << std::hex << getObjectId() << std::dec
|
||||||
@ -227,7 +227,7 @@ ReturnValue_t LocalPool::reserveSpace(const size_t size,
|
|||||||
}
|
}
|
||||||
status = findEmpty(storeId->poolIndex, &storeId->packetIndex);
|
status = findEmpty(storeId->poolIndex, &storeId->packetIndex);
|
||||||
while (status != RETURN_OK && spillsToHigherPools) {
|
while (status != RETURN_OK && spillsToHigherPools) {
|
||||||
status = getPoolIndex(size, &storeId->poolIndex, storeId->poolIndex + 1);
|
status = getSubPoolIndex(size, &storeId->poolIndex, storeId->poolIndex + 1);
|
||||||
if (status != RETURN_OK) {
|
if (status != RETURN_OK) {
|
||||||
//We don't find any fitting pool anymore.
|
//We don't find any fitting pool anymore.
|
||||||
break;
|
break;
|
||||||
@ -263,9 +263,9 @@ void LocalPool::write(store_address_t storeId, const uint8_t *data,
|
|||||||
sizeLists[storeId.poolIndex][storeId.packetIndex] = size;
|
sizeLists[storeId.poolIndex][storeId.packetIndex] = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalPool::size_type LocalPool::getPageSize(max_pools_t poolIndex) {
|
LocalPool::size_type LocalPool::getSubpoolElementSize(max_subpools_t subpoolIndex) {
|
||||||
if (poolIndex < NUMBER_OF_POOLS) {
|
if (subpoolIndex < NUMBER_OF_SUBPOOLS) {
|
||||||
return elementSizes[poolIndex];
|
return elementSizes[subpoolIndex];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
@ -276,9 +276,9 @@ void LocalPool::setToSpillToHigherPools(bool enable) {
|
|||||||
this->spillsToHigherPools = enable;
|
this->spillsToHigherPools = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalPool::getPoolIndex(size_t packetSize, uint16_t *poolIndex,
|
ReturnValue_t LocalPool::getSubPoolIndex(size_t packetSize, uint16_t *subpoolIndex,
|
||||||
uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
for (uint16_t n = startAtIndex; n < NUMBER_OF_POOLS; n++) {
|
for (uint16_t n = startAtIndex; n < NUMBER_OF_SUBPOOLS; n++) {
|
||||||
#if FSFW_VERBOSE_PRINTOUT == 2
|
#if FSFW_VERBOSE_PRINTOUT == 2
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::debug << "LocalPool " << getObjectId() << "::getPoolIndex: Pool: "
|
sif::debug << "LocalPool " << getObjectId() << "::getPoolIndex: Pool: "
|
||||||
@ -286,7 +286,7 @@ ReturnValue_t LocalPool::getPoolIndex(size_t packetSize, uint16_t *poolIndex,
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
if (elementSizes[n] >= packetSize) {
|
if (elementSizes[n] >= packetSize) {
|
||||||
*poolIndex = n;
|
*subpoolIndex = n;
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +313,7 @@ ReturnValue_t LocalPool::findEmpty(n_pool_elem_t poolIndex, uint16_t *element) {
|
|||||||
size_t LocalPool::getTotalSize(size_t* additionalSize) {
|
size_t LocalPool::getTotalSize(size_t* additionalSize) {
|
||||||
size_t totalSize = 0;
|
size_t totalSize = 0;
|
||||||
size_t sizesSize = 0;
|
size_t sizesSize = 0;
|
||||||
for(uint8_t idx = 0; idx < NUMBER_OF_POOLS; idx ++) {
|
for(uint8_t idx = 0; idx < NUMBER_OF_SUBPOOLS; idx ++) {
|
||||||
totalSize += elementSizes[idx] * numberOfElements[idx];
|
totalSize += elementSizes[idx] * numberOfElements[idx];
|
||||||
sizesSize += numberOfElements[idx] * sizeof(size_type);
|
sizesSize += numberOfElements[idx] * sizeof(size_type);
|
||||||
}
|
}
|
||||||
@ -331,7 +331,7 @@ void LocalPool::getFillCount(uint8_t *buffer, uint8_t *bytesWritten) {
|
|||||||
uint16_t reservedHits = 0;
|
uint16_t reservedHits = 0;
|
||||||
uint8_t idx = 0;
|
uint8_t idx = 0;
|
||||||
uint16_t sum = 0;
|
uint16_t sum = 0;
|
||||||
for(; idx < NUMBER_OF_POOLS; idx ++) {
|
for(; idx < NUMBER_OF_SUBPOOLS; idx ++) {
|
||||||
for(const auto& size: sizeLists[idx]) {
|
for(const auto& size: sizeLists[idx]) {
|
||||||
if(size != STORAGE_FREE) {
|
if(size != STORAGE_FREE) {
|
||||||
reservedHits++;
|
reservedHits++;
|
||||||
@ -343,21 +343,25 @@ void LocalPool::getFillCount(uint8_t *buffer, uint8_t *bytesWritten) {
|
|||||||
sum += buffer[idx];
|
sum += buffer[idx];
|
||||||
reservedHits = 0;
|
reservedHits = 0;
|
||||||
}
|
}
|
||||||
buffer[idx] = sum / NUMBER_OF_POOLS;
|
buffer[idx] = sum / NUMBER_OF_SUBPOOLS;
|
||||||
*bytesWritten += 1;
|
*bytesWritten += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LocalPool::clearPage(max_pools_t pageIndex) {
|
void LocalPool::clearSubPool(max_subpools_t subpoolIndex) {
|
||||||
if(pageIndex >= NUMBER_OF_POOLS) {
|
if(subpoolIndex >= NUMBER_OF_SUBPOOLS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the storage as free
|
// Mark the storage as free
|
||||||
for(auto& size: sizeLists[pageIndex]) {
|
for(auto& size: sizeLists[subpoolIndex]) {
|
||||||
size = STORAGE_FREE;
|
size = STORAGE_FREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set all the page content to 0.
|
// Set all the page content to 0.
|
||||||
std::memset(store[pageIndex].data(), 0, elementSizes[pageIndex]);
|
std::memset(store[subpoolIndex].data(), 0, elementSizes[subpoolIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalPool::max_subpools_t LocalPool::getNumberOfSubPools() const {
|
||||||
|
return NUMBER_OF_SUBPOOLS;
|
||||||
}
|
}
|
||||||
|
@ -60,15 +60,6 @@ public:
|
|||||||
};
|
};
|
||||||
using LocalPoolConfig = std::multiset<LocalPoolCfgPair, LocalPoolConfigCmp>;
|
using LocalPoolConfig = std::multiset<LocalPoolCfgPair, LocalPoolConfigCmp>;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This definition generally sets the number of
|
|
||||||
* different sized pools. It is derived from the number of pairs
|
|
||||||
* inside the LocalPoolConfig set on object creation.
|
|
||||||
* @details
|
|
||||||
* This must be less than the maximum number of pools (currently 0xff).
|
|
||||||
*/
|
|
||||||
const max_pools_t NUMBER_OF_POOLS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the default constructor for a pool manager instance.
|
* @brief This is the default constructor for a pool manager instance.
|
||||||
* @details
|
* @details
|
||||||
@ -143,9 +134,15 @@ public:
|
|||||||
void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) override;
|
void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) override;
|
||||||
|
|
||||||
void clearStore() override;
|
void clearStore() override;
|
||||||
void clearPage(max_pools_t pageIndex) override;
|
void clearSubPool(max_subpools_t poolIndex) override;
|
||||||
|
|
||||||
ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get number sub pools. Each pool has pages with a specific bucket size.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
max_subpools_t getNumberOfSubPools() const override;
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* With this helper method, a free element of @c size is reserved.
|
* With this helper method, a free element of @c size is reserved.
|
||||||
@ -158,6 +155,16 @@ protected:
|
|||||||
store_address_t* address, bool ignoreFault);
|
store_address_t* address, bool ignoreFault);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This definition generally sets the number of
|
||||||
|
* different sized pools. It is derived from the number of pairs
|
||||||
|
* inside the LocalPoolConfig set on object creation.
|
||||||
|
* @details
|
||||||
|
* This must be less than the maximum number of pools (currently 0xff).
|
||||||
|
*/
|
||||||
|
const max_subpools_t NUMBER_OF_SUBPOOLS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that this element is free.
|
* Indicates that this element is free.
|
||||||
* This value limits the maximum size of a pool.
|
* This value limits the maximum size of a pool.
|
||||||
@ -170,20 +177,20 @@ private:
|
|||||||
* must be set in ascending order on construction.
|
* must be set in ascending order on construction.
|
||||||
*/
|
*/
|
||||||
std::vector<size_type> elementSizes =
|
std::vector<size_type> elementSizes =
|
||||||
std::vector<size_type>(NUMBER_OF_POOLS);
|
std::vector<size_type>(NUMBER_OF_SUBPOOLS);
|
||||||
/**
|
/**
|
||||||
* @brief n_elements stores the number of elements per pool.
|
* @brief n_elements stores the number of elements per pool.
|
||||||
* @details These numbers are maintained for internal pool management.
|
* @details These numbers are maintained for internal pool management.
|
||||||
*/
|
*/
|
||||||
std::vector<uint16_t> numberOfElements =
|
std::vector<uint16_t> numberOfElements =
|
||||||
std::vector<uint16_t>(NUMBER_OF_POOLS);
|
std::vector<uint16_t>(NUMBER_OF_SUBPOOLS);
|
||||||
/**
|
/**
|
||||||
* @brief store represents the actual memory pool.
|
* @brief store represents the actual memory pool.
|
||||||
* @details It is an array of pointers to memory, which was allocated with
|
* @details It is an array of pointers to memory, which was allocated with
|
||||||
* a @c new call on construction.
|
* a @c new call on construction.
|
||||||
*/
|
*/
|
||||||
std::vector<std::vector<uint8_t>> store =
|
std::vector<std::vector<uint8_t>> store =
|
||||||
std::vector<std::vector<uint8_t>>(NUMBER_OF_POOLS);
|
std::vector<std::vector<uint8_t>>(NUMBER_OF_SUBPOOLS);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The size_list attribute stores the size values of every pool element.
|
* @brief The size_list attribute stores the size values of every pool element.
|
||||||
@ -191,7 +198,7 @@ private:
|
|||||||
* is also dynamically allocated there.
|
* is also dynamically allocated there.
|
||||||
*/
|
*/
|
||||||
std::vector<std::vector<size_type>> sizeLists =
|
std::vector<std::vector<size_type>> sizeLists =
|
||||||
std::vector<std::vector<size_type>>(NUMBER_OF_POOLS);
|
std::vector<std::vector<size_type>>(NUMBER_OF_SUBPOOLS);
|
||||||
|
|
||||||
//! A variable to determine whether higher n pools are used if
|
//! A variable to determine whether higher n pools are used if
|
||||||
//! the store is full.
|
//! the store is full.
|
||||||
@ -210,7 +217,7 @@ private:
|
|||||||
* @param pool_index The pool in which to look.
|
* @param pool_index The pool in which to look.
|
||||||
* @return Returns the size of an element or 0.
|
* @return Returns the size of an element or 0.
|
||||||
*/
|
*/
|
||||||
size_type getPageSize(max_pools_t poolIndex);
|
size_type getSubpoolElementSize(max_subpools_t subpoolIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This helper method looks up a fitting pool for a given size.
|
* @brief This helper method looks up a fitting pool for a given size.
|
||||||
@ -221,7 +228,7 @@ private:
|
|||||||
* @return - @c RETURN_OK on success,
|
* @return - @c RETURN_OK on success,
|
||||||
* - @c DATA_TOO_LARGE otherwise.
|
* - @c DATA_TOO_LARGE otherwise.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t getPoolIndex(size_t packetSize, uint16_t* poolIndex,
|
ReturnValue_t getSubPoolIndex(size_t packetSize, uint16_t* subpoolIndex,
|
||||||
uint16_t startAtIndex = 0);
|
uint16_t startAtIndex = 0);
|
||||||
/**
|
/**
|
||||||
* @brief This helper method calculates the true array position in store
|
* @brief This helper method calculates the true array position in store
|
||||||
|
@ -29,7 +29,7 @@ using ConstAccessorPair = std::pair<ReturnValue_t, ConstStorageAccessor>;
|
|||||||
class StorageManagerIF : public HasReturnvaluesIF {
|
class StorageManagerIF : public HasReturnvaluesIF {
|
||||||
public:
|
public:
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
using max_pools_t = uint8_t;
|
using max_subpools_t = uint8_t;
|
||||||
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface.
|
static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface.
|
||||||
static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store.
|
static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store.
|
||||||
@ -149,10 +149,10 @@ public:
|
|||||||
virtual ReturnValue_t modifyData(store_address_t packet_id,
|
virtual ReturnValue_t modifyData(store_address_t packet_id,
|
||||||
uint8_t** packet_ptr, size_t* size) = 0;
|
uint8_t** packet_ptr, size_t* size) = 0;
|
||||||
/**
|
/**
|
||||||
* This method reserves an element of \c size.
|
* This method reserves an element of @c size.
|
||||||
*
|
*
|
||||||
* It returns the packet id of this element as well as a direct pointer to the
|
* It returns the packet id of this element as well as a direct pointer to the
|
||||||
* data of the element. It must be assured that exactly \c size data is
|
* data of the element. It must be assured that exactly @c size data is
|
||||||
* written to p_data!
|
* written to p_data!
|
||||||
* @param storageId A pointer to the storageId to retrieve.
|
* @param storageId A pointer to the storageId to retrieve.
|
||||||
* @param size The size of the space to be reserved.
|
* @param size The size of the space to be reserved.
|
||||||
@ -171,20 +171,29 @@ public:
|
|||||||
virtual void clearStore() = 0;
|
virtual void clearStore() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears a page in the store. Use with care!
|
* Clears a pool in the store with the given pool index. Use with care!
|
||||||
* @param pageIndex
|
* @param pageIndex
|
||||||
*/
|
*/
|
||||||
virtual void clearPage(uint8_t pageIndex) = 0;
|
virtual void clearSubPool(uint8_t poolIndex) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the fill count of the pool. The exact form will be implementation
|
* Get the fill count of the pool. Each character inside the provided
|
||||||
* dependant.
|
* buffer will be assigned to a rounded percentage fill count for each
|
||||||
|
* page. The last written byte (at the index bytesWritten - 1)
|
||||||
|
* will contain the total fill count of the pool as a mean of the
|
||||||
|
* percentages of single pages.
|
||||||
* @param buffer
|
* @param buffer
|
||||||
* @param bytesWritten
|
* @param maxSize
|
||||||
*/
|
*/
|
||||||
virtual void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) = 0;
|
virtual void getFillCount(uint8_t* buffer, uint8_t* bytesWritten) = 0;
|
||||||
|
|
||||||
virtual size_t getTotalSize(size_t* additionalSize) = 0;
|
virtual size_t getTotalSize(size_t* additionalSize) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get number of pools.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual max_subpools_t getNumberOfSubPools() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ */
|
#endif /* FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ */
|
||||||
|
@ -290,13 +290,13 @@ void Heater::handleQueue() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Heater::getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t Heater::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
if (domainId != DOMAIN_ID_BASE) {
|
if (domainId != DOMAIN_ID_BASE) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set(heaterOnCountdown.timeout);
|
parameterWrapper->set(heaterOnCountdown.timeout);
|
||||||
break;
|
break;
|
||||||
|
@ -34,7 +34,7 @@ public:
|
|||||||
|
|
||||||
MessageQueueId_t getCommandQueue() const;
|
MessageQueueId_t getCommandQueue() const;
|
||||||
|
|
||||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||||
|
|
||||||
|
@ -183,10 +183,10 @@ public:
|
|||||||
|
|
||||||
static const uint8_t DOMAIN_ID_SENSOR = 1;
|
static const uint8_t DOMAIN_ID_SENSOR = 1;
|
||||||
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = sensorMonitor.getParameter(domainId, parameterId,
|
ReturnValue_t result = sensorMonitor.getParameter(domainId, uniqueId,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
parameterWrapper, newValues, startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
@ -194,7 +194,7 @@ public:
|
|||||||
if (domainId != this->DOMAIN_ID_BASE) {
|
if (domainId != this->DOMAIN_ID_BASE) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case ADDRESS_A:
|
case ADDRESS_A:
|
||||||
parameterWrapper->set(parameters.a);
|
parameterWrapper->set(parameters.a);
|
||||||
break;
|
break;
|
||||||
|
@ -148,14 +148,14 @@ ThermalComponentIF::State ThermalComponent::getIgnoredState(int8_t state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ThermalComponent::getParameter(uint8_t domainId,
|
ReturnValue_t ThermalComponent::getParameter(uint8_t domainId,
|
||||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = ThermalComponentCore::getParameter(domainId, parameterId,
|
ReturnValue_t result = ThermalComponentCore::getParameter(domainId, uniqueId,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
parameterWrapper, newValues, startAtIndex);
|
||||||
if (result != INVALID_IDENTIFIER_ID) {
|
if (result != INVALID_IDENTIFIER_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 12:
|
case 12:
|
||||||
parameterWrapper->set(nopParameters.lowerNopLimit);
|
parameterWrapper->set(nopParameters.lowerNopLimit);
|
||||||
break;
|
break;
|
||||||
|
@ -58,7 +58,7 @@ public:
|
|||||||
|
|
||||||
virtual ReturnValue_t setLimits( const uint8_t* data, size_t size);
|
virtual ReturnValue_t setLimits( const uint8_t* data, size_t size);
|
||||||
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||||
|
|
||||||
|
@ -247,17 +247,17 @@ ThermalComponentCore::Parameters ThermalComponentCore::getParameters() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ThermalComponentCore::getParameter(uint8_t domainId,
|
ReturnValue_t ThermalComponentCore::getParameter(uint8_t domainId,
|
||||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = temperatureMonitor.getParameter(domainId,
|
ReturnValue_t result = temperatureMonitor.getParameter(domainId,
|
||||||
parameterId, parameterWrapper, newValues, startAtIndex);
|
uniqueId, parameterWrapper, newValues, startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (domainId != this->domainId) {
|
if (domainId != this->domainId) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set(parameters.heaterOn);
|
parameterWrapper->set(parameters.heaterOn);
|
||||||
break;
|
break;
|
||||||
|
@ -68,7 +68,7 @@ public:
|
|||||||
|
|
||||||
virtual void setOutputInvalid();
|
virtual void setOutputInvalid();
|
||||||
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#include "Stopwatch.h"
|
#include "Stopwatch.h"
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#endif
|
||||||
|
|
||||||
Stopwatch::Stopwatch(bool displayOnDestruction,
|
Stopwatch::Stopwatch(bool displayOnDestruction,
|
||||||
StopwatchDisplayMode displayMode): displayOnDestruction(
|
StopwatchDisplayMode displayMode): displayOnDestruction(
|
||||||
@ -28,9 +31,13 @@ double Stopwatch::stopSeconds() {
|
|||||||
|
|
||||||
void Stopwatch::display() {
|
void Stopwatch::display() {
|
||||||
if(displayMode == StopwatchDisplayMode::MILLIS) {
|
if(displayMode == StopwatchDisplayMode::MILLIS) {
|
||||||
|
dur_millis_t timeMillis = static_cast<dur_millis_t>(
|
||||||
|
elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000);
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::info << "Stopwatch: Operation took " << (elapsedTime.tv_sec * 1000 +
|
sif::info << "Stopwatch: Operation took " << timeMillis << " milliseconds" << std::endl;
|
||||||
elapsedTime.tv_usec / 1000) << " milliseconds" << std::endl;
|
#else
|
||||||
|
sif::printInfo("Stopwatch: Operation took %lu milliseconds\n\r",
|
||||||
|
static_cast<unsigned int>(timeMillis));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if(displayMode == StopwatchDisplayMode::SECONDS) {
|
else if(displayMode == StopwatchDisplayMode::SECONDS) {
|
||||||
@ -38,6 +45,9 @@ void Stopwatch::display() {
|
|||||||
sif::info <<"Stopwatch: Operation took " << std::setprecision(3)
|
sif::info <<"Stopwatch: Operation took " << std::setprecision(3)
|
||||||
<< std::fixed << timevalOperations::toDouble(elapsedTime)
|
<< std::fixed << timevalOperations::toDouble(elapsedTime)
|
||||||
<< " seconds" << std::endl;
|
<< " seconds" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printInfo("Stopwatch: Operation took %.3f seconds\n\r",
|
||||||
|
static_cast<float>(timevalOperations::toDouble(elapsedTime)));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "TmTcBridge.h"
|
#include "TmTcBridge.h"
|
||||||
|
|
||||||
#include "../ipc/QueueFactory.h"
|
#include "../ipc/QueueFactory.h"
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
#include "../globalfunctions/arrayprinter.h"
|
#include "../globalfunctions/arrayprinter.h"
|
||||||
|
|
||||||
TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
@ -109,9 +109,8 @@ ReturnValue_t TmTcBridge::handleTm() {
|
|||||||
ReturnValue_t result = handleTmQueue();
|
ReturnValue_t result = handleTmQueue();
|
||||||
if(result != RETURN_OK) {
|
if(result != RETURN_OK) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "TmTcBridge::handleTm: Error handling TM queue with "
|
sif::error << "TmTcBridge::handleTm: Error handling TM queue with error code 0x" <<
|
||||||
<< "error code 0x" << std::hex << result << std::dec
|
std::hex << result << std::dec << "!" << std::endl;
|
||||||
<< "!" << std::endl;
|
|
||||||
#endif
|
#endif
|
||||||
status = result;
|
status = result;
|
||||||
}
|
}
|
||||||
@ -121,8 +120,7 @@ ReturnValue_t TmTcBridge::handleTm() {
|
|||||||
result = handleStoredTm();
|
result = handleStoredTm();
|
||||||
if(result != RETURN_OK) {
|
if(result != RETURN_OK) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "TmTcBridge::handleTm: Error handling stored TMs!"
|
sif::error << "TmTcBridge::handleTm: Error handling stored TMs!" << std::endl;
|
||||||
<< std::endl;
|
|
||||||
#endif
|
#endif
|
||||||
status = result;
|
status = result;
|
||||||
}
|
}
|
||||||
@ -140,9 +138,15 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
|
|||||||
result == HasReturnvaluesIF::RETURN_OK;
|
result == HasReturnvaluesIF::RETURN_OK;
|
||||||
result = tmTcReceptionQueue->receiveMessage(&message))
|
result = tmTcReceptionQueue->receiveMessage(&message))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 3
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
//sif::info << (int) packetSentCounter << std::endl;
|
sif::info << "Sent packet counter: " << static_cast<int>(packetSentCounter) << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printInfo("Sent packet counter: %d\n", packetSentCounter);
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
|
||||||
|
|
||||||
if(communicationLinkUp == false or
|
if(communicationLinkUp == false or
|
||||||
packetSentCounter >= sentPacketsPerCycle) {
|
packetSentCounter >= sentPacketsPerCycle) {
|
||||||
storeDownlinkData(&message);
|
storeDownlinkData(&message);
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
#include "LocalPoolOwnerBase.h"
|
#include "LocalPoolOwnerBase.h"
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include <catch2/catch_approx.hpp>
|
||||||
|
|
||||||
|
#include <fsfw/datapool/PoolReadHelper.h>
|
||||||
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
|
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
|
||||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||||
|
#include <fsfw/housekeeping/HousekeepingSnapshot.h>
|
||||||
#include <fsfw/ipc/CommandMessageCleaner.h>
|
#include <fsfw/ipc/CommandMessageCleaner.h>
|
||||||
|
#include <fsfw/timemanager/CCSDSTime.h>
|
||||||
#include <unittest/core/CatchDefinitions.h>
|
#include <unittest/core/CatchDefinitions.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
||||||
@ -14,7 +20,7 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
|||||||
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
|
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
|
||||||
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
|
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation()
|
||||||
== retval::CATCH_OK);
|
== retval::CATCH_OK);
|
||||||
REQUIRE(poolOwner->dataset.assignPointers() == retval::CATCH_OK);
|
//REQUIRE(poolOwner->dataset.assignPointers() == retval::CATCH_OK);
|
||||||
MessageQueueMockBase* mqMock = poolOwner->getMockQueueHandle();
|
MessageQueueMockBase* mqMock = poolOwner->getMockQueueHandle();
|
||||||
REQUIRE(mqMock != nullptr);
|
REQUIRE(mqMock != nullptr);
|
||||||
CommandMessage messageSent;
|
CommandMessage messageSent;
|
||||||
@ -22,11 +28,11 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
|||||||
|
|
||||||
|
|
||||||
SECTION("BasicTest") {
|
SECTION("BasicTest") {
|
||||||
// Subscribe for message generation on update.
|
/* Subscribe for message generation on update. */
|
||||||
REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK);
|
REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK);
|
||||||
// Subscribe for an update message.
|
/* Subscribe for an update message. */
|
||||||
poolOwner->dataset.setChanged(true);
|
poolOwner->dataset.setChanged(true);
|
||||||
// Now the update message should be generated.
|
/* Now the update message should be generated. */
|
||||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||||
REQUIRE(mqMock->wasMessageSent() == true);
|
REQUIRE(mqMock->wasMessageSent() == true);
|
||||||
|
|
||||||
@ -34,9 +40,9 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
|||||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||||
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
|
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
|
||||||
|
|
||||||
// Should have been reset.
|
/* Should have been reset. */
|
||||||
CHECK(poolOwner->dataset.hasChanged() == false);
|
CHECK(poolOwner->dataset.hasChanged() == false);
|
||||||
// Set changed again, result should be the same.
|
/* Set changed again, result should be the same. */
|
||||||
poolOwner->dataset.setChanged(true);
|
poolOwner->dataset.setChanged(true);
|
||||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||||
|
|
||||||
@ -46,14 +52,14 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
|||||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||||
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
|
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
|
||||||
|
|
||||||
// now subscribe for set update HK as well.
|
/* Now subscribe for set update HK as well. */
|
||||||
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
|
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
|
||||||
poolOwner->dataset.setChanged(true);
|
poolOwner->dataset.setChanged(true);
|
||||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||||
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
||||||
CHECK(messagesSent == 2);
|
CHECK(messagesSent == 2);
|
||||||
// first message sent should be the update notification, considering
|
/* first message sent should be the update notification, considering
|
||||||
// the internal list is a vector checked in insertion order.
|
the internal list is a vector checked in insertion order. */
|
||||||
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
||||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||||
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
|
HousekeepingMessage::UPDATE_NOTIFICATION_SET));
|
||||||
@ -61,16 +67,82 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
|||||||
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
||||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||||
HousekeepingMessage::HK_REPORT));
|
HousekeepingMessage::HK_REPORT));
|
||||||
// clear message to avoid memory leak, our mock won't do it for us (yet)
|
/* Clear message to avoid memory leak, our mock won't do it for us (yet) */
|
||||||
CommandMessageCleaner::clearCommandMessage(&messageSent);
|
CommandMessageCleaner::clearCommandMessage(&messageSent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("SnapshotUpdateTests") {
|
||||||
|
/* Set the variables in the set to certain values. These are checked later. */
|
||||||
|
{
|
||||||
|
PoolReadHelper readHelper(&poolOwner->dataset);
|
||||||
|
REQUIRE(readHelper.getReadResult() == retval::CATCH_OK);
|
||||||
|
poolOwner->dataset.localPoolVarUint8.value = 5;
|
||||||
|
poolOwner->dataset.localPoolVarFloat.value = -12.242;
|
||||||
|
poolOwner->dataset.localPoolUint16Vec.value[0] = 2;
|
||||||
|
poolOwner->dataset.localPoolUint16Vec.value[1] = 32;
|
||||||
|
poolOwner->dataset.localPoolUint16Vec.value[2] = 42932;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subscribe for snapshot generation on update. */
|
||||||
|
REQUIRE(poolOwner->subscribeWrapperSetUpdateSnapshot() == retval::CATCH_OK);
|
||||||
|
poolOwner->dataset.setChanged(true);
|
||||||
|
|
||||||
|
/* Store current time, we are going to check the (approximate) time equality later */
|
||||||
|
CCSDSTime::CDS_short timeCdsNow;
|
||||||
|
timeval now;
|
||||||
|
Clock::getClock_timeval(&now);
|
||||||
|
CCSDSTime::convertToCcsds(&timeCdsNow, &now);
|
||||||
|
|
||||||
|
/* Trigger generation of snapshot */
|
||||||
|
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||||
|
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
||||||
|
CHECK(messagesSent == 1);
|
||||||
|
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
||||||
|
/* Check that snapshot was generated */
|
||||||
|
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||||
|
HousekeepingMessage::UPDATE_SNAPSHOT_SET));
|
||||||
|
/* Now we deserialize the snapshot into a new dataset instance */
|
||||||
|
CCSDSTime::CDS_short cdsShort;
|
||||||
|
LocalPoolTestDataSet newSet;
|
||||||
|
HousekeepingSnapshot snapshot(&cdsShort, &newSet);
|
||||||
|
store_address_t storeId;
|
||||||
|
HousekeepingMessage::getUpdateSnapshotSetCommand(&messageSent, &storeId);
|
||||||
|
ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId);
|
||||||
|
REQUIRE(accessorPair.first == retval::CATCH_OK);
|
||||||
|
const uint8_t* readOnlyPtr = accessorPair.second.data();
|
||||||
|
size_t sizeToDeserialize = accessorPair.second.size();
|
||||||
|
CHECK(newSet.localPoolVarFloat.value == 0);
|
||||||
|
CHECK(newSet.localPoolVarUint8 == 0);
|
||||||
|
CHECK(newSet.localPoolUint16Vec.value[0] == 0);
|
||||||
|
CHECK(newSet.localPoolUint16Vec.value[1] == 0);
|
||||||
|
CHECK(newSet.localPoolUint16Vec.value[2] == 0);
|
||||||
|
/* Fill the dataset and timestamp */
|
||||||
|
REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize,
|
||||||
|
SerializeIF::Endianness::MACHINE) == retval::CATCH_OK);
|
||||||
|
/* Now we check that the snapshot is actually correct */
|
||||||
|
CHECK(newSet.localPoolVarFloat.value == Catch::Approx(-12.242));
|
||||||
|
CHECK(newSet.localPoolVarUint8 == 5);
|
||||||
|
CHECK(newSet.localPoolUint16Vec.value[0] == 2);
|
||||||
|
CHECK(newSet.localPoolUint16Vec.value[1] == 32);
|
||||||
|
CHECK(newSet.localPoolUint16Vec.value[2] == 42932);
|
||||||
|
|
||||||
|
/* Now we check that both times are equal */
|
||||||
|
CHECK(cdsShort.pField == timeCdsNow.pField);
|
||||||
|
CHECK(cdsShort.dayLSB == Catch::Approx(timeCdsNow.dayLSB).margin(1));
|
||||||
|
CHECK(cdsShort.dayMSB == Catch::Approx(timeCdsNow.dayMSB).margin(1));
|
||||||
|
CHECK(cdsShort.msDay_h == Catch::Approx(timeCdsNow.msDay_h).margin(1));
|
||||||
|
CHECK(cdsShort.msDay_hh == Catch::Approx(timeCdsNow.msDay_hh).margin(1));
|
||||||
|
CHECK(cdsShort.msDay_l == Catch::Approx(timeCdsNow.msDay_l).margin(1));
|
||||||
|
CHECK(cdsShort.msDay_ll == Catch::Approx(timeCdsNow.msDay_ll).margin(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("AdvancedTests") {
|
SECTION("AdvancedTests") {
|
||||||
// we need to reset the subscription list because the pool owner
|
/* Acquire subscription interface */
|
||||||
// is a global object.
|
ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner->getSubscriptionInterface();
|
||||||
poolOwner->resetSubscriptionList();
|
REQUIRE(subscriptionIF != nullptr);
|
||||||
// Subscribe for variable update as well
|
|
||||||
REQUIRE(not poolOwner->dataset.hasChanged());
|
/* Subscribe for variable update */
|
||||||
REQUIRE(poolOwner->subscribeWrapperVariableUpdate(lpool::uint8VarId) ==
|
REQUIRE(poolOwner->subscribeWrapperVariableUpdate(lpool::uint8VarId) ==
|
||||||
retval::CATCH_OK);
|
retval::CATCH_OK);
|
||||||
lp_var_t<uint8_t>* poolVar = dynamic_cast<lp_var_t<uint8_t>*>(
|
lp_var_t<uint8_t>* poolVar = dynamic_cast<lp_var_t<uint8_t>*>(
|
||||||
@ -79,22 +151,22 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
|||||||
poolVar->setChanged(true);
|
poolVar->setChanged(true);
|
||||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||||
|
|
||||||
// Check update notification was sent.
|
/* Check update notification was sent. */
|
||||||
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
||||||
CHECK(messagesSent == 1);
|
CHECK(messagesSent == 1);
|
||||||
// Should have been reset.
|
/* Should have been reset. */
|
||||||
CHECK(poolVar->hasChanged() == false);
|
CHECK(poolVar->hasChanged() == false);
|
||||||
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
||||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||||
HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
|
HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
|
||||||
|
/* Now subscribe for the dataset update (HK and update) again with subscription interface */
|
||||||
// now subscribe for the dataset update (HK and update) again
|
REQUIRE(subscriptionIF->subscribeForSetUpdateMessages(lpool::testSetId,
|
||||||
REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK);
|
objects::NO_OBJECT, objects::HK_RECEIVER_MOCK, false) == retval::CATCH_OK);
|
||||||
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
|
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
|
||||||
|
|
||||||
poolOwner->dataset.setChanged(true);
|
poolOwner->dataset.setChanged(true);
|
||||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||||
// now two messages should be sent.
|
/* Now two messages should be sent. */
|
||||||
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
||||||
CHECK(messagesSent == 2);
|
CHECK(messagesSent == 2);
|
||||||
mqMock->clearMessages(true);
|
mqMock->clearMessages(true);
|
||||||
@ -102,7 +174,7 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
|||||||
poolOwner->dataset.setChanged(true);
|
poolOwner->dataset.setChanged(true);
|
||||||
poolVar->setChanged(true);
|
poolVar->setChanged(true);
|
||||||
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
|
||||||
// now three messages should be sent.
|
/* Now three messages should be sent. */
|
||||||
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
|
||||||
CHECK(messagesSent == 3);
|
CHECK(messagesSent == 3);
|
||||||
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
|
||||||
@ -115,8 +187,12 @@ TEST_CASE("LocalPoolManagerTest" , "[LocManTest]") {
|
|||||||
CHECK(messageSent.getCommand() == static_cast<int>(
|
CHECK(messageSent.getCommand() == static_cast<int>(
|
||||||
HousekeepingMessage::HK_REPORT));
|
HousekeepingMessage::HK_REPORT));
|
||||||
CommandMessageCleaner::clearCommandMessage(&messageSent);
|
CommandMessageCleaner::clearCommandMessage(&messageSent);
|
||||||
REQUIRE(mqMock->receiveMessage(&messageSent) ==
|
REQUIRE(mqMock->receiveMessage(&messageSent) == static_cast<int>(MessageQueueIF::EMPTY));
|
||||||
static_cast<int>(MessageQueueIF::EMPTY));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we need to reset the subscription list because the pool owner
|
||||||
|
is a global object. */
|
||||||
|
poolOwner->resetSubscriptionList();
|
||||||
|
mqMock->clearMessages(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,33 +20,43 @@ static constexpr lp_id_t int64Vec2Id = 4;
|
|||||||
|
|
||||||
static constexpr uint32_t testSetId = 0;
|
static constexpr uint32_t testSetId = 0;
|
||||||
static constexpr uint8_t dataSetMaxVariables = 10;
|
static constexpr uint8_t dataSetMaxVariables = 10;
|
||||||
static const sid_t testSid = sid_t(objects::TEST_LOCAL_POOL_OWNER_BASE,
|
|
||||||
testSetId);
|
static const sid_t testSid = sid_t(objects::TEST_LOCAL_POOL_OWNER_BASE, testSetId);
|
||||||
|
|
||||||
|
static const gp_id_t uint8VarGpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, uint8VarId);
|
||||||
|
static const gp_id_t floatVarGpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, floatVarId);
|
||||||
|
static const gp_id_t uint32Gpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, uint32VarId);
|
||||||
|
static const gp_id_t uint16Vec3Gpid = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, uint16Vec3Id);
|
||||||
|
static const gp_id_t uint64Vec2Id = gp_id_t(objects::TEST_LOCAL_POOL_OWNER_BASE, int64Vec2Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LocalPoolTestDataSet: public LocalDataSet {
|
class LocalPoolTestDataSet: public LocalDataSet {
|
||||||
public:
|
public:
|
||||||
|
LocalPoolTestDataSet():
|
||||||
|
LocalDataSet(lpool::testSid, lpool::dataSetMaxVariables) {
|
||||||
|
}
|
||||||
|
|
||||||
LocalPoolTestDataSet(HasLocalDataPoolIF* owner, uint32_t setId):
|
LocalPoolTestDataSet(HasLocalDataPoolIF* owner, uint32_t setId):
|
||||||
LocalDataSet(owner, setId, lpool::dataSetMaxVariables) {
|
LocalDataSet(owner, setId, lpool::dataSetMaxVariables) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t assignPointers() {
|
// ReturnValue_t assignPointers() {
|
||||||
PoolVariableIF** rawVarArray = getContainer();
|
// PoolVariableIF** rawVarArray = getContainer();
|
||||||
localPoolVarUint8 = dynamic_cast<lp_var_t<uint8_t>*>(rawVarArray[0]);
|
// localPoolVarUint8 = dynamic_cast<lp_var_t<uint8_t>*>(rawVarArray[0]);
|
||||||
localPoolVarFloat = dynamic_cast<lp_var_t<float>*>(rawVarArray[1]);
|
// localPoolVarFloat = dynamic_cast<lp_var_t<float>*>(rawVarArray[1]);
|
||||||
localPoolUint16Vec = dynamic_cast<lp_vec_t<uint16_t, 3>*>(
|
// localPoolUint16Vec = dynamic_cast<lp_vec_t<uint16_t, 3>*>(
|
||||||
rawVarArray[2]);
|
// rawVarArray[2]);
|
||||||
if(localPoolVarUint8 == nullptr or localPoolVarFloat == nullptr or
|
// if(localPoolVarUint8 == nullptr or localPoolVarFloat == nullptr or
|
||||||
localPoolUint16Vec == nullptr) {
|
// localPoolUint16Vec == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
// return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
// }
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
// return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
// }
|
||||||
|
|
||||||
lp_var_t<uint8_t>* localPoolVarUint8 = nullptr;
|
lp_var_t<uint8_t> localPoolVarUint8 = lp_var_t<uint8_t>(lpool::uint8VarGpid, this);
|
||||||
lp_var_t<float>* localPoolVarFloat = nullptr;
|
lp_var_t<float> localPoolVarFloat = lp_var_t<float>(lpool::floatVarGpid, this);
|
||||||
lp_vec_t<uint16_t, 3>* localPoolUint16Vec = nullptr;
|
lp_vec_t<uint16_t, 3> localPoolUint16Vec = lp_vec_t<uint16_t, 3>(lpool::uint16Vec3Gpid, this);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
@ -155,7 +165,12 @@ public:
|
|||||||
|
|
||||||
ReturnValue_t subscribeWrapperSetUpdate() {
|
ReturnValue_t subscribeWrapperSetUpdate() {
|
||||||
return poolManager.subscribeForSetUpdateMessages(lpool::testSetId,
|
return poolManager.subscribeForSetUpdateMessages(lpool::testSetId,
|
||||||
objects::NO_OBJECT, MessageQueueIF::NO_QUEUE, false);
|
objects::NO_OBJECT, objects::HK_RECEIVER_MOCK, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t subscribeWrapperSetUpdateSnapshot() {
|
||||||
|
return poolManager.subscribeForSetUpdateMessages(lpool::testSetId,
|
||||||
|
objects::NO_OBJECT, objects::HK_RECEIVER_MOCK, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t subscribeWrapperSetUpdateHk(bool diagnostics = false) {
|
ReturnValue_t subscribeWrapperSetUpdateHk(bool diagnostics = false) {
|
||||||
@ -165,7 +180,7 @@ public:
|
|||||||
|
|
||||||
ReturnValue_t subscribeWrapperVariableUpdate(lp_id_t localPoolId) {
|
ReturnValue_t subscribeWrapperVariableUpdate(lp_id_t localPoolId) {
|
||||||
return poolManager.subscribeForVariableUpdateMessages(localPoolId,
|
return poolManager.subscribeForVariableUpdateMessages(localPoolId,
|
||||||
MessageQueueIF::NO_QUEUE, objects::NO_OBJECT, false);
|
MessageQueueIF::NO_QUEUE, objects::HK_RECEIVER_MOCK, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetSubscriptionList() {
|
void resetSubscriptionList() {
|
||||||
|
@ -14,7 +14,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
|
|||||||
== retval::CATCH_OK);
|
== retval::CATCH_OK);
|
||||||
|
|
||||||
SECTION("Basic Tests") {
|
SECTION("Basic Tests") {
|
||||||
// very basic test.
|
/* very basic test. */
|
||||||
lp_var_t<uint8_t> testVariable = lp_var_t<uint8_t>(
|
lp_var_t<uint8_t> testVariable = lp_var_t<uint8_t>(
|
||||||
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
|
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
|
||||||
REQUIRE(testVariable.read() == retval::CATCH_OK);
|
REQUIRE(testVariable.read() == retval::CATCH_OK);
|
||||||
@ -77,7 +77,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
|
|||||||
|
|
||||||
SECTION("ErrorHandling") {
|
SECTION("ErrorHandling") {
|
||||||
|
|
||||||
// not try to use a local pool variable which does not exist
|
/* now try to use a local pool variable which does not exist */
|
||||||
lp_var_t<uint8_t> invalidVariable = lp_var_t<uint8_t>(
|
lp_var_t<uint8_t> invalidVariable = lp_var_t<uint8_t>(
|
||||||
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
|
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
|
||||||
REQUIRE(invalidVariable.read() ==
|
REQUIRE(invalidVariable.read() ==
|
||||||
@ -85,7 +85,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
|
|||||||
|
|
||||||
REQUIRE(invalidVariable.commit() ==
|
REQUIRE(invalidVariable.commit() ==
|
||||||
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
|
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
|
||||||
// now try to access with wrong type
|
/* now try to access with wrong type */
|
||||||
lp_var_t<int8_t> invalidVariable2 = lp_var_t<int8_t>(
|
lp_var_t<int8_t> invalidVariable2 = lp_var_t<int8_t>(
|
||||||
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
|
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId);
|
||||||
REQUIRE(invalidVariable2.read() ==
|
REQUIRE(invalidVariable2.read() ==
|
||||||
@ -108,7 +108,7 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") {
|
|||||||
sif::info << "LocalPoolVariable printout: " <<uint32tVar << std::endl;
|
sif::info << "LocalPoolVariable printout: " <<uint32tVar << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// for code coverage. If program does not crash -> OK
|
/* for code coverage. If program does not crash -> OK */
|
||||||
lp_var_t<uint8_t> invalidObjectVar = lp_var_t<uint8_t>(
|
lp_var_t<uint8_t> invalidObjectVar = lp_var_t<uint8_t>(
|
||||||
0xffffffff, lpool::uint8VarId);
|
0xffffffff, lpool::uint8VarId);
|
||||||
gp_id_t globPoolId(0xffffffff,
|
gp_id_t globPoolId(0xffffffff,
|
||||||
|
@ -35,13 +35,13 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
|
|||||||
|
|
||||||
CHECK(testVector[0] == 5);
|
CHECK(testVector[0] == 5);
|
||||||
|
|
||||||
// This is invalid access, so the last value will be set instead.
|
/* This is invalid access, so the last value will be set instead.
|
||||||
// (we can't throw exceptions)
|
(we can't throw exceptions) */
|
||||||
testVector[4] = 12;
|
testVector[4] = 12;
|
||||||
CHECK(testVector[2] == 12);
|
CHECK(testVector[2] == 12);
|
||||||
CHECK(testVector.commit() == retval::CATCH_OK);
|
CHECK(testVector.commit() == retval::CATCH_OK);
|
||||||
|
|
||||||
// Use read-only reference.
|
/* Use read-only reference. */
|
||||||
const lp_vec_t<uint16_t, 3>& roTestVec = testVector;
|
const lp_vec_t<uint16_t, 3>& roTestVec = testVector;
|
||||||
uint16_t valueOne = roTestVec[0];
|
uint16_t valueOne = roTestVec[0];
|
||||||
CHECK(valueOne == 5);
|
CHECK(valueOne == 5);
|
||||||
@ -87,7 +87,7 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("ErrorHandling") {
|
SECTION("ErrorHandling") {
|
||||||
// not try to use a local pool variable which does not exist
|
/* Now try to use a local pool variable which does not exist */
|
||||||
lp_vec_t<uint16_t, 3> invalidVector = lp_vec_t<uint16_t, 3>(
|
lp_vec_t<uint16_t, 3> invalidVector = lp_vec_t<uint16_t, 3>(
|
||||||
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
|
objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff);
|
||||||
REQUIRE(invalidVector.read() ==
|
REQUIRE(invalidVector.read() ==
|
||||||
@ -95,7 +95,7 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") {
|
|||||||
REQUIRE(invalidVector.commit() ==
|
REQUIRE(invalidVector.commit() ==
|
||||||
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
|
static_cast<int>(localpool::POOL_ENTRY_NOT_FOUND));
|
||||||
|
|
||||||
// now try to access with wrong type
|
/* Now try to access with wrong type */
|
||||||
lp_vec_t<uint32_t, 3> invalidVector2 = lp_vec_t<uint32_t, 3>(
|
lp_vec_t<uint32_t, 3> invalidVector2 = lp_vec_t<uint32_t, 3>(
|
||||||
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id);
|
objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id);
|
||||||
REQUIRE(invalidVector2.read() ==
|
REQUIRE(invalidVector2.read() ==
|
||||||
|
@ -276,7 +276,7 @@ TEST_CASE( "Local Pool Extended Tests [3 Pools]" , "[TestPool2]") {
|
|||||||
CHECK(receptionArray[3] == 66);
|
CHECK(receptionArray[3] == 66);
|
||||||
|
|
||||||
// now clear first page
|
// now clear first page
|
||||||
simplePool.clearPage(0);
|
simplePool.clearSubPool(0);
|
||||||
bytesWritten = 0;
|
bytesWritten = 0;
|
||||||
simplePool.getFillCount(receptionArray.data(), &bytesWritten);
|
simplePool.getFillCount(receptionArray.data(), &bytesWritten);
|
||||||
// Second page full, median fill count is 33 %
|
// Second page full, median fill count is 33 %
|
||||||
|
Loading…
Reference in New Issue
Block a user