Merge branch 'development' into mueller/cmake-fixes

This commit is contained in:
Robin Müller 2020-12-15 23:05:32 +01:00
commit c48f1c8ee6
74 changed files with 662 additions and 2876 deletions

View File

@ -1,14 +0,0 @@
#include <fsfw/datapoolglob/ControllerSet.h>
ControllerSet::ControllerSet() {
}
ControllerSet::~ControllerSet() {
}
void ControllerSet::setInvalid() {
read();
setToDefault();
commit(PoolVariableIF::INVALID);
}

View File

@ -1,15 +0,0 @@
#ifndef FSFW_DATAPOOLGLOB_CONTROLLERSET_H_
#define FSFW_DATAPOOLGLOB_CONTROLLERSET_H_
#include "../datapoolglob/GlobalDataSet.h"
class ControllerSet :public GlobDataSet {
public:
ControllerSet();
virtual ~ControllerSet();
virtual void setToDefault() = 0;
void setInvalid();
};
#endif /* FSFW_DATAPOOLGLOB_CONTROLLERSET_H_ */

View File

@ -1,301 +0,0 @@
#include "DataPoolAdmin.h"
#include "GlobalDataSet.h"
#include "GlobalDataPool.h"
#include "PoolRawAccess.h"
#include "../ipc/CommandMessage.h"
#include "../ipc/QueueFactory.h"
#include "../parameters/ParameterMessage.h"
DataPoolAdmin::DataPoolAdmin(object_id_t objectId) :
SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper(
this, NULL), actionHelper(this, NULL) {
commandQueue = QueueFactory::instance()->createMessageQueue();
}
DataPoolAdmin::~DataPoolAdmin() {
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
ReturnValue_t DataPoolAdmin::performOperation(uint8_t opCode) {
handleCommand();
return RETURN_OK;
}
MessageQueueId_t DataPoolAdmin::getCommandQueue() const {
return commandQueue->getId();
}
ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
if (actionId != SET_VALIDITY) {
return INVALID_ACTION_ID;
}
if (size != 5) {
return INVALID_PARAMETERS;
}
uint32_t address = (data[0] << 24) | (data[1] << 16) | (data[2] << 8)
| data[3];
uint8_t valid = data[4];
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
GlobDataSet mySet;
PoolRawAccess variable(poolId, 0, &mySet, PoolVariableIF::VAR_READ_WRITE);
ReturnValue_t status = mySet.read();
if (status != RETURN_OK) {
return INVALID_ADDRESS;
}
if (valid != 0) {
variable.setValid(PoolVariableIF::VALID);
} else {
variable.setValid(PoolVariableIF::INVALID);
}
mySet.commit();
return EXECUTION_FINISHED;
}
ReturnValue_t DataPoolAdmin::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) {
return HasReturnvaluesIF::RETURN_FAILED;
}
void DataPoolAdmin::handleCommand() {
CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result != RETURN_OK) {
return;
}
result = actionHelper.handleActionMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
return;
}
result = handleParameterCommand(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
return;
}
result = memoryHelper.handleMemoryCommand(&command);
if (result != RETURN_OK) {
command.setToUnknownCommand();
commandQueue->reply(&command);
}
}
ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address,
const uint8_t* data, size_t size, uint8_t** dataPointer) {
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address);
GlobDataSet testSet;
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
PoolVariableIF::VAR_READ);
ReturnValue_t status = testSet.read();
if (status != RETURN_OK) {
return INVALID_ADDRESS;
}
uint8_t typeSize = varToGetSize.getSizeOfType();
if (size % typeSize != 0) {
return INVALID_SIZE;
}
if (size > varToGetSize.getSizeTillEnd()) {
return INVALID_SIZE;
}
const uint8_t* readPosition = data;
for (; size > 0; size -= typeSize) {
GlobDataSet rawSet;
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
PoolVariableIF::VAR_READ_WRITE);
status = rawSet.read();
if (status == RETURN_OK) {
status = variable.setEntryFromBigEndian(readPosition, typeSize);
if (status == RETURN_OK) {
status = rawSet.commit();
}
}
arrayIndex += 1;
readPosition += typeSize;
}
return ACTIVITY_COMPLETED;
}
ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, size_t size,
uint8_t** dataPointer, uint8_t* copyHere) {
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address);
GlobDataSet testSet;
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
PoolVariableIF::VAR_READ);
ReturnValue_t status = testSet.read();
if (status != RETURN_OK) {
return INVALID_ADDRESS;
}
uint8_t typeSize = varToGetSize.getSizeOfType();
if (size > varToGetSize.getSizeTillEnd()) {
return INVALID_SIZE;
}
uint8_t* ptrToCopy = copyHere;
for (; size > 0; size -= typeSize) {
GlobDataSet rawSet;
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
PoolVariableIF::VAR_READ);
status = rawSet.read();
if (status == RETURN_OK) {
size_t temp = 0;
status = variable.getEntryEndianSafe(ptrToCopy, &temp, size);
if (status != RETURN_OK) {
return RETURN_FAILED;
}
} else {
//Error reading parameter.
}
arrayIndex += 1;
ptrToCopy += typeSize;
}
return ACTIVITY_COMPLETED;
}
ReturnValue_t DataPoolAdmin::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = memoryHelper.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (storage == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
result = actionHelper.initialize(commandQueue);
return result;
}
//mostly identical to ParameterHelper::handleParameterMessage()
ReturnValue_t DataPoolAdmin::handleParameterCommand(CommandMessage* command) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
switch (command->getCommand()) {
case ParameterMessage::CMD_PARAMETER_DUMP: {
uint8_t domain = HasParametersIF::getDomain(
ParameterMessage::getParameterId(command));
uint16_t parameterId = HasParametersIF::getMatrixId(
ParameterMessage::getParameterId(command));
DataPoolParameterWrapper wrapper;
result = wrapper.set(domain, parameterId);
if (result == HasReturnvaluesIF::RETURN_OK) {
result = sendParameter(command->getSender(),
ParameterMessage::getParameterId(command), &wrapper);
}
}
break;
case ParameterMessage::CMD_PARAMETER_LOAD: {
uint8_t domain = HasParametersIF::getDomain(
ParameterMessage::getParameterId(command));
uint16_t parameterId = HasParametersIF::getMatrixId(
ParameterMessage::getParameterId(command));
uint8_t index = HasParametersIF::getIndex(
ParameterMessage::getParameterId(command));
const uint8_t *storedStream;
size_t storedStreamSize;
result = storage->getData(ParameterMessage::getStoreId(command),
&storedStream, &storedStreamSize);
if (result != HasReturnvaluesIF::RETURN_OK) {
break;
}
ParameterWrapper streamWrapper;
result = streamWrapper.set(storedStream, storedStreamSize);
if (result != HasReturnvaluesIF::RETURN_OK) {
storage->deleteData(ParameterMessage::getStoreId(command));
break;
}
DataPoolParameterWrapper poolWrapper;
result = poolWrapper.set(domain, parameterId);
if (result != HasReturnvaluesIF::RETURN_OK) {
storage->deleteData(ParameterMessage::getStoreId(command));
break;
}
result = poolWrapper.copyFrom(&streamWrapper, index);
storage->deleteData(ParameterMessage::getStoreId(command));
if (result == HasReturnvaluesIF::RETURN_OK) {
result = sendParameter(command->getSender(),
ParameterMessage::getParameterId(command), &poolWrapper);
}
}
break;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
if (result != HasReturnvaluesIF::RETURN_OK) {
rejectCommand(command->getSender(), result, command->getCommand());
}
return HasReturnvaluesIF::RETURN_OK;
}
//identical to ParameterHelper::sendParameter()
ReturnValue_t DataPoolAdmin::sendParameter(MessageQueueId_t to, uint32_t id,
const DataPoolParameterWrapper* wrapper) {
size_t serializedSize = wrapper->getSerializedSize();
uint8_t *storeElement;
store_address_t address;
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
&storeElement);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t storeElementSize = 0;
result = wrapper->serialize(&storeElement, &storeElementSize,
serializedSize, SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) {
storage->deleteData(address);
return result;
}
CommandMessage reply;
ParameterMessage::setParameterDumpReply(&reply, id, address);
commandQueue->sendMessage(to, &reply);
return HasReturnvaluesIF::RETURN_OK;
}
//identical to ParameterHelper::rejectCommand()
void DataPoolAdmin::rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
Command_t initialCommand) {
CommandMessage reply;
reply.setReplyRejected(reason, initialCommand);
commandQueue->sendMessage(to, &reply);
}

View File

@ -1,60 +0,0 @@
#ifndef FSFW_DATAPOOLGLOB_DATAPOOLADMIN_H_
#define FSFW_DATAPOOLGLOB_DATAPOOLADMIN_H_
#include "DataPoolParameterWrapper.h"
#include "../objectmanager/SystemObject.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../action/HasActionsIF.h"
#include "../ipc/MessageQueueIF.h"
#include "../parameters/ReceivesParameterMessagesIF.h"
#include "../action/SimpleActionHelper.h"
#include "../memory/MemoryHelper.h"
class DataPoolAdmin: public HasActionsIF,
public ExecutableObjectIF,
public AcceptsMemoryMessagesIF,
public HasReturnvaluesIF,
public ReceivesParameterMessagesIF,
public SystemObject {
public:
static const ActionId_t SET_VALIDITY = 1;
DataPoolAdmin(object_id_t objectId);
~DataPoolAdmin();
ReturnValue_t performOperation(uint8_t opCode);
MessageQueueId_t getCommandQueue() const;
ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data,
size_t size, uint8_t** dataPointer);
ReturnValue_t handleMemoryDump(uint32_t address, size_t size,
uint8_t** dataPointer, uint8_t* copyHere);
ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size);
//not implemented as ParameterHelper is no used
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
ReturnValue_t initialize();
private:
StorageManagerIF *storage;
MessageQueueIF* commandQueue;
MemoryHelper memoryHelper;
SimpleActionHelper actionHelper;
void handleCommand();
ReturnValue_t handleParameterCommand(CommandMessage *command);
ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id,
const DataPoolParameterWrapper* wrapper);
void rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
Command_t initialCommand);
};
#endif /* FSFW_DATAPOOLGLOB_DATAPOOLADMIN_H_ */

View File

@ -1,179 +0,0 @@
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/DataPoolParameterWrapper.h"
#include "../datapoolglob/PoolRawAccess.h"
#include "../parameters/HasParametersIF.h"
DataPoolParameterWrapper::DataPoolParameterWrapper() :
type(Type::UNKNOWN_TYPE), rows(0), columns(0), poolId(
PoolVariableIF::NO_PARAMETER) {
}
DataPoolParameterWrapper::~DataPoolParameterWrapper() {
}
ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId,
uint16_t parameterId) {
poolId = (domainId << 16) + parameterId;
GlobDataSet mySet;
PoolRawAccess raw(poolId, 0, &mySet, PoolVariableIF::VAR_READ);
ReturnValue_t status = mySet.read();
if (status != HasReturnvaluesIF::RETURN_OK) {
//should only fail for invalid pool id
return HasParametersIF::INVALID_MATRIX_ID;
}
type = raw.getType();
rows = raw.getArraySize();
columns = 1;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer,
size_t* size, size_t maxSize, Endianness streamEndianness) const {
ReturnValue_t result;
result = SerializeAdapter::serialize(&type, buffer, size, maxSize,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&columns, buffer, size,
maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&rows, buffer, size, maxSize,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
for (uint8_t index = 0; index < rows; index++){
GlobDataSet mySet;
PoolRawAccess raw(poolId, index, &mySet,PoolVariableIF::VAR_READ);
mySet.read();
result = raw.serialize(buffer,size,maxSize,streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK){
return result;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
//same as ParameterWrapper
size_t DataPoolParameterWrapper::getSerializedSize() const {
size_t serializedSize = 0;
serializedSize += type.getSerializedSize();
serializedSize += sizeof(rows);
serializedSize += sizeof(columns);
serializedSize += rows * columns * type.getSize();
return serializedSize;
}
ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer,
size_t* size, Endianness streamEndianness) {
return HasReturnvaluesIF::RETURN_FAILED;
}
template<typename T>
ReturnValue_t DataPoolParameterWrapper::deSerializeData(uint8_t startingRow,
uint8_t startingColumn, const void* from, uint8_t fromRows) {
//treat from as a continuous Stream as we copy all of it
const uint8_t *fromAsStream = (const uint8_t *) from;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) {
GlobDataSet mySet;
PoolRawAccess raw(poolId, startingRow + fromRow, &mySet,
PoolVariableIF::VAR_READ_WRITE);
mySet.read();
result = raw.setEntryFromBigEndian(fromAsStream, sizeof(T));
fromAsStream += sizeof(T);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
mySet.commit();
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t DataPoolParameterWrapper::copyFrom(const ParameterWrapper* from,
uint16_t startWritingAtIndex) {
if (poolId == PoolVariableIF::NO_PARAMETER) {
return ParameterWrapper::NOT_SET;
}
if (type != from->type) {
return ParameterWrapper::DATATYPE_MISSMATCH;
}
//check if from fits into this
uint8_t startingRow = startWritingAtIndex / columns;
uint8_t startingColumn = startWritingAtIndex % columns;
if ((from->rows > (rows - startingRow))
|| (from->columns > (columns - startingColumn))) {
return ParameterWrapper::TOO_BIG;
}
ReturnValue_t result;
//copy data
if (from->pointsToStream) {
switch (type) {
case Type::UINT8_T:
result = deSerializeData<uint8_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT8_T:
result = deSerializeData<int8_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::UINT16_T:
result = deSerializeData<uint16_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT16_T:
result = deSerializeData<int16_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::UINT32_T:
result = deSerializeData<uint32_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT32_T:
result = deSerializeData<int32_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::FLOAT:
result = deSerializeData<float>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::DOUBLE:
result = deSerializeData<double>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
default:
result = ParameterWrapper::UNKNOW_DATATYPE;
break;
}
} else {
//not supported
return HasReturnvaluesIF::RETURN_FAILED;
}
return result;
}

View File

@ -1,38 +0,0 @@
#ifndef DATAPOOLPARAMETERWRAPPER_H_
#define DATAPOOLPARAMETERWRAPPER_H_
#include "../globalfunctions/Type.h"
#include "../parameters/ParameterWrapper.h"
class DataPoolParameterWrapper: public SerializeIF {
public:
DataPoolParameterWrapper();
virtual ~DataPoolParameterWrapper();
ReturnValue_t set(uint8_t domainId, uint16_t parameterId);
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
ReturnValue_t copyFrom(const ParameterWrapper *from,
uint16_t startWritingAtIndex);
private:
Type type;
uint8_t rows;
uint8_t columns;
uint32_t poolId;
template<typename T>
ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn,
const void *from, uint8_t fromRows);
};
#endif /* DATAPOOLPARAMETERWRAPPER_H_ */

View File

@ -1,133 +0,0 @@
#include "../datapoolglob/GlobalDataPool.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../ipc/MutexFactory.h"
GlobalDataPool::GlobalDataPool(
void(*initFunction)(GlobPoolMap* pool_map)) {
mutex = MutexFactory::instance()->createMutex();
if (initFunction != NULL ) {
initFunction( &this->globDataPool );
}
}
GlobalDataPool::~GlobalDataPool() {
MutexFactory::instance()->deleteMutex(mutex);
for(GlobPoolMapIter it = this->globDataPool.begin();
it != this->globDataPool.end(); ++it )
{
delete it->second;
}
}
// The function checks PID, type and array length before returning a copy of
// the PoolEntry. In failure case, it returns a temp-Entry with size 0 and NULL-ptr.
template <typename T> PoolEntry<T>* GlobalDataPool::getData( uint32_t data_pool_id,
uint8_t sizeOrPosition ) {
GlobPoolMapIter it = this->globDataPool.find( data_pool_id );
if ( it != this->globDataPool.end() ) {
PoolEntry<T>* entry = dynamic_cast< PoolEntry<T>* >( it->second );
if (entry != nullptr ) {
if ( sizeOrPosition <= entry->length ) {
return entry;
}
}
}
return nullptr;
}
PoolEntryIF* GlobalDataPool::getRawData( uint32_t data_pool_id ) {
GlobPoolMapIter it = this->globDataPool.find( data_pool_id );
if ( it != this->globDataPool.end() ) {
return it->second;
} else {
return nullptr;
}
}
ReturnValue_t GlobalDataPool::unlockDataPool() {
ReturnValue_t status = mutex->unlockMutex();
if(status != RETURN_OK) {
sif::error << "DataPool::DataPool: unlock of mutex failed with"
" error code: " << status << std::endl;
}
return status;
}
ReturnValue_t GlobalDataPool::lockDataPool(uint32_t timeoutMs) {
ReturnValue_t status = mutex->lockMutex(MutexIF::TimeoutType::WAITING,
timeoutMs);
if(status != RETURN_OK) {
sif::error << "DataPool::DataPool: lock of mutex failed "
"with error code: " << status << std::endl;
}
return status;
}
void GlobalDataPool::print() {
sif::debug << "DataPool contains: " << std::endl;
std::map<uint32_t, PoolEntryIF*>::iterator dataPoolIt;
dataPoolIt = this->globDataPool.begin();
while( dataPoolIt != this->globDataPool.end() ) {
sif::debug << std::hex << dataPoolIt->first << std::dec << " |";
dataPoolIt->second->print();
dataPoolIt++;
}
}
uint32_t GlobalDataPool::PIDToDataPoolId(uint32_t parameter_id) {
return (parameter_id >> 8) & 0x00FFFFFF;
}
uint8_t GlobalDataPool::PIDToArrayIndex(uint32_t parameter_id) {
return (parameter_id & 0x000000FF);
}
uint32_t GlobalDataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) {
return (poolId << 8) + index;
}
//SHOULDDO: Do we need a mutex lock here... I don't think so,
//as we only check static const values of elements in a list that do not change.
//there is no guarantee in the standard, but it seems to me that the implementation is safe -UM
ReturnValue_t GlobalDataPool::getType(uint32_t parameter_id, Type* type) {
GlobPoolMapIter it = this->globDataPool.find( PIDToDataPoolId(parameter_id));
if ( it != this->globDataPool.end() ) {
*type = it->second->getType();
return RETURN_OK;
} else {
*type = Type::UNKNOWN_TYPE;
return RETURN_FAILED;
}
}
bool GlobalDataPool::exists(uint32_t parameterId) {
uint32_t poolId = PIDToDataPoolId(parameterId);
uint32_t index = PIDToArrayIndex(parameterId);
GlobPoolMapIter it = this->globDataPool.find( poolId );
if (it != globDataPool.end()) {
if (it->second->getSize() >= index) {
return true;
}
}
return false;
}
template PoolEntry<uint8_t>* GlobalDataPool::getData<uint8_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint16_t>* GlobalDataPool::getData<uint16_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint32_t>* GlobalDataPool::getData<uint32_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint64_t>* GlobalDataPool::getData<uint64_t>(
uint32_t data_pool_id, uint8_t size);
template PoolEntry<int8_t>* GlobalDataPool::getData<int8_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<int16_t>* GlobalDataPool::getData<int16_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<int32_t>* GlobalDataPool::getData<int32_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<float>* GlobalDataPool::getData<float>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<double>* GlobalDataPool::getData<double>(
uint32_t data_pool_id, uint8_t size);

View File

@ -1,149 +0,0 @@
#ifndef GLOBALDATAPOOL_H_
#define GLOBALDATAPOOL_H_
#include "../datapool/PoolEntry.h"
#include "../globalfunctions/Type.h"
#include "../ipc/MutexIF.h"
#include <map>
/**
* @defgroup data_pool Global data pool
* This is the group, where all classes associated with global
* data pool handling belong to.
* This includes classes to access Data Pool variables.
*/
/**
* Typedefs for the global pool representations
*/
using GlobPoolMap = std::map<uint32_t, PoolEntryIF*>;
using GlobPoolMapIter = GlobPoolMap::iterator;
/**
* @brief This class represents the OBSW global data-pool.
*
* @details
* All variables are registered and space is allocated in an initialization
* function, which is passed do the constructor. Space for the variables is
* allocated on the heap (with a new call).
*
* The data is found by a data pool id, which uniquely represents a variable.
* Data pool variables should be used with a blackboard logic in mind,
* which means read data is valid (if flagged so),
* but not necessarily up-to-date.
*
* Variables are either single values or arrays.
* @author Bastian Baetz
* @ingroup data_pool
*/
class GlobalDataPool : public HasReturnvaluesIF {
private:
/**
* @brief This is the actual data pool itself.
* @details It is represented by a map with the data pool id as index
* and a pointer to a single PoolEntry as value.
*/
GlobPoolMap globDataPool;
/**
* @brief The mutex is created in the constructor and makes
* access mutual exclusive.
* @details Locking and unlocking the pool is only done by the DataSet class.
*/
MutexIF* mutex;
public:
/**
* @brief In the classes constructor,
* the passed initialization function is called.
* @details
* To enable filling the pool, a pointer to the map is passed,
* allowing direct access to the pool's content.
* On runtime, adding or removing variables is forbidden.
*/
GlobalDataPool( void ( *initFunction )( GlobPoolMap* pool_map ) );
/**
* @brief The destructor iterates through the data_pool map and
* calls all entries destructors to clean up the heap.
*/
~GlobalDataPool();
/**
* @brief This is the default call to access the pool.
* @details
* A pointer to the PoolEntry object is returned.
* The call checks data pool id, type and array size.
* Returns NULL in case of failure.
* @param data_pool_id The data pool id to search.
* @param sizeOrPosition The array size (not byte size!) of the pool entry,
* or the position the user wants to read.
* If smaller than the entry size, everything's ok.
*/
template <typename T> PoolEntry<T>* getData( uint32_t data_pool_id,
uint8_t sizeOrPosition );
/**
* @brief An alternative call to get a data pool entry in case the type is not implicitly known
* (i.e. in Housekeeping Telemetry).
* @details It returns a basic interface and does NOT perform
* a size check. The caller has to assure he does not copy too much data.
* Returns NULL in case the entry is not found.
* @param data_pool_id The data pool id to search.
*/
PoolEntryIF* getRawData( uint32_t data_pool_id );
/**
* @brief This is a small helper function to facilitate locking the global data pool.
* @details It fetches the pool's mutex id and tries to acquire the mutex.
*/
ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::BLOCKING);
/**
* @brief This is a small helper function to facilitate unlocking the global data pool.
* @details It fetches the pool's mutex id and tries to free the mutex.
*/
ReturnValue_t unlockDataPool();
/**
* @brief The print call is a simple debug method.
* @details It prints the current content of the data pool.
* It iterates through the data_pool map and calls each entry's print() method.
*/
void print();
/**
* Extracts the data pool id from a SCOS 2000 PID.
* @param parameter_id The passed Parameter ID.
* @return The data pool id as used within the OBSW.
*/
static uint32_t PIDToDataPoolId( uint32_t parameter_id );
/**
* Extracts an array index out of a SCOS 2000 PID.
* @param parameter_id The passed Parameter ID.
* @return The index of the corresponding data pool entry.
*/
static uint8_t PIDToArrayIndex( uint32_t parameter_id );
/**
* Retransforms a data pool id and an array index to a SCOS 2000 PID.
*/
static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index );
/**
* Method to return the type of a pool variable.
* @param parameter_id A parameterID (not pool id) of a DP member.
* @param type Returns the type or TYPE::UNKNOWN_TYPE
* @return RETURN_OK if parameter exists, RETURN_FAILED else.
*/
ReturnValue_t getType( uint32_t parameter_id, Type* type );
/**
* Method to check if a PID exists. Does not lock, as there's no
* possibility to alter the list that is checked during run-time.
* @param parameterId The PID (not pool id!) of a parameter.
* @return true if exists, false else.
*/
bool exists(uint32_t parameterId);
};
//We assume someone globally instantiates a DataPool.
namespace glob {
extern GlobalDataPool dataPool;
}
#endif /* DATAPOOL_H_ */

View File

@ -1,48 +0,0 @@
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
GlobDataSet::GlobDataSet(): PoolDataSetBase(
reinterpret_cast<PoolVariableIF**>(&registeredVariables),
DATA_SET_MAX_SIZE) {}
// Don't do anything with your variables, they are dead already!
// (Destructor is already called)
GlobDataSet::~GlobDataSet() {}
ReturnValue_t GlobDataSet::commit(bool valid, uint32_t lockTimeout) {
setEntriesValid(valid);
setSetValid(valid);
return commit(lockTimeout);
}
ReturnValue_t GlobDataSet::commit(uint32_t lockTimeout) {
return PoolDataSetBase::commit(lockTimeout);
}
bool GlobDataSet::isValid() const {
return this->valid;
}
ReturnValue_t GlobDataSet::unlockDataPool() {
return glob::dataPool.unlockDataPool();
}
ReturnValue_t GlobDataSet::lockDataPool(uint32_t timeoutMs) {
return glob::dataPool.lockDataPool(timeoutMs);
}
void GlobDataSet::setEntriesValid(bool valid) {
for (uint16_t count = 0; count < fillCount; count++) {
if (registeredVariables[count]->getReadWriteMode()
!= PoolVariableIF::VAR_READ) {
registeredVariables[count]->setValid(valid);
}
}
}
void GlobDataSet::setSetValid(bool valid) {
this->valid = valid;
}

View File

@ -1,98 +0,0 @@
#ifndef FRAMEWORK_DATAPOOLGLOB_DATASET_H_
#define FRAMEWORK_DATAPOOLGLOB_DATASET_H_
#include "../datapool/PoolDataSetBase.h"
/**
* @brief The DataSet class manages a set of locally checked out variables
* for the global data pool.
* @details
* This class uses the read-commit() semantic provided by the DataSetBase class.
* It extends the base class by using the global data pool,
* having a valid state and implementing lock und unlock calls for the global
* datapool.
*
* For more information on how this class works, see the DataSetBase
* documentation.
* @author Bastian Baetz
* @ingroup data_pool
*/
class GlobDataSet: public PoolDataSetBase {
public:
/**
* @brief Creates an empty GlobDataSet. Use registerVariable or
* supply a pointer to this dataset to PoolVariable
* initializations to register pool variables.
*/
GlobDataSet();
/**
* @brief The destructor automatically manages writing the valid
* information of variables.
* @details
* In case the data set was read out, but not committed(indicated by state),
* the destructor parses all variables that are still registered to the set.
* For each, the valid flag in the data pool is set to "invalid".
*/
~GlobDataSet();
/**
* Variant of method above which sets validity of all elements of the set.
* @param valid Validity information from PoolVariableIF.
* @return - @c RETURN_OK if all variables were read successfully.
* - @c COMMITING_WITHOUT_READING if set was not read yet and
* contains non write-only variables
*/
ReturnValue_t commit(bool valid, uint32_t lockTimeout = MutexIF::BLOCKING);
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
/**
* Set all entries
* @param valid
*/
void setSetValid(bool valid);
bool isValid() const override;
/**
* Set the valid information of all variables contained in the set which
* are not read-only
*
* @param valid Validity information from PoolVariableIF.
*/
void setEntriesValid(bool valid);
//!< This definition sets the maximum number of variables to
//! register in one DataSet.
static const uint8_t DATA_SET_MAX_SIZE = 63;
private:
/**
* If the valid state of a dataset is always relevant to the whole
* data set we can use this flag.
*/
bool valid = false;
/**
* @brief This is a small helper function to facilitate locking
* the global data pool.
* @details
* It makes use of the lockDataPool method offered by the DataPool class.
*/
ReturnValue_t lockDataPool(uint32_t timeoutMs) override;
/**
* @brief This is a small helper function to facilitate
* unlocking the global data pool
* @details
* It makes use of the freeDataPoolLock method offered by the DataPool class.
*/
ReturnValue_t unlockDataPool() override;
void handleAlreadyReadDatasetCommit();
ReturnValue_t handleUnreadDatasetCommit();
PoolVariableIF* registeredVariables[DATA_SET_MAX_SIZE];
};
#endif /* FRAMEWORK_DATAPOOLGLOB_DATASET_H_ */

View File

@ -1,213 +0,0 @@
#ifndef GLOBALPOOLVARIABLE_H_
#define GLOBALPOOLVARIABLE_H_
#include "../datapool/DataSetIF.h"
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapool/PoolVariableIF.h"
#include "../datapool/PoolEntry.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
template<typename T, uint8_t n_var> class PoolVarList;
/**
* @brief This is the access class for non-array data pool entries.
*
* @details
* To ensure safe usage of the data pool, operation is not done directly
* on the data pool entries, but on local copies. This class provides simple
* type-safe access to single data pool entries (i.e. entries with length = 1).
* The class can be instantiated as read-write and read only.
* It provides a commit-and-roll-back semantic, which means that the
* variable's value in the data pool is not changed until the
* commit call is executed.
* @tparam T The template parameter sets the type of the variable.
* Currently, all plain data types are supported, but in principle
* any type is possible.
* @ingroup data_pool
*/
template<typename T>
class GlobPoolVar: public PoolVariableIF {
template<typename U, uint8_t n_var> friend class PoolVarList;
static_assert(not std::is_same<T, bool>::value,
"Do not use boolean for the PoolEntry type, use uint8_t instead!"
"There is no boolean type in CCSDS.");
public:
/**
* @brief In the constructor, the variable can register itself in a
* DataSet (if nullptr is not passed).
* @details
* It DOES NOT fetch the current value from the data pool, but
* sets the value attribute to default (0).
* The value is fetched within the read() operation.
* @param set_id This is the id in the global data pool
* this instance of the access class corresponds to.
* @param dataSet The data set in which the variable shall register
* itself. If NULL, the variable is not registered.
* @param setWritable If this flag is set to true, changes in the value
* attribute can be written back to the data pool, otherwise not.
*/
GlobPoolVar(uint32_t set_id, DataSetIF* dataSet,
ReadWriteMode_t setReadWriteMode);
/**
* @brief This is the local copy of the data pool entry.
* @details The user can work on this attribute
* just like he would on a simple local variable.
*/
T value = 0;
/**
* @brief Copy ctor to copy classes containing Pool Variables.
* (Robin): This only copies member variables, which is done
* by the default copy ctor. maybe we can ommit this ctor?
*/
GlobPoolVar(const GlobPoolVar& rhs);
/**
* @brief The classes destructor is empty.
* @details If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~GlobPoolVar() {}
/**
* @brief This is a call to read the value from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t read(uint32_t lockTimeout) override;
/**
* @brief The commit call writes back the variable's value to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The operation does NOT provide any mutual exclusive protection by itself.
* The commit call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(uint32_t lockTimeout) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
/**
* @brief To access the correct data pool entry on read and commit calls,
* the data pool is stored.
*/
uint32_t dataPoolId;
/**
* @brief The valid information as it was stored in the data pool is
* copied to this attribute.
*/
uint8_t valid;
/**
* @brief The information whether the class is read-write or read-only
* is stored here.
*/
pool_rwm_t readWriteMode;
/**
* Empty ctor for List initialization
*/
GlobPoolVar();
public:
/**
* \brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const override;
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const override;
/**
* This operation sets the data pool id of the variable.
* The method is necessary to set id's of data pool member variables with bad initialization.
*/
void setDataPoolId(uint32_t poolId);
/**
* \brief With this call, the valid information of the variable is returned.
*/
bool isValid() const override;
uint8_t getValid();
void setValid(bool valid) override;
operator T() {
return value;
}
operator T() const {
return value;
}
GlobPoolVar<T> &operator=(T newValue) {
value = newValue;
return *this;
}
GlobPoolVar<T> &operator=(GlobPoolVar<T> newPoolVariable) {
value = newPoolVariable.value;
return *this;
}
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t max_size,
SerializeIF::Endianness streamEndianness) const override {
return SerializeAdapter::serialize(&value, buffer, size, max_size,
streamEndianness);
}
virtual size_t getSerializedSize() const {
return SerializeAdapter::getSerializedSize(&value);
}
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) {
return SerializeAdapter::deSerialize(&value, buffer, size,
streamEndianness);
}
};
#include "../datapoolglob/GlobalPoolVariable.tpp"
typedef GlobPoolVar<uint8_t> gp_bool_t;
typedef GlobPoolVar<uint8_t> gp_uint8_t;
typedef GlobPoolVar<uint16_t> gp_uint16_t;
typedef GlobPoolVar<uint32_t> gp_uint32_t;
typedef GlobPoolVar<int8_t> gp_int8_t;
typedef GlobPoolVar<int16_t> gp_int16_t;
typedef GlobPoolVar<int32_t> gp_int32_t;
typedef GlobPoolVar<float> gp_float_t;
typedef GlobPoolVar<double> gp_double_t;
#endif /* POOLVARIABLE_H_ */

View File

@ -1,117 +0,0 @@
#ifndef GLOBALPOOLVARIABLE_TPP_
#define GLOBALPOOLVARIABLE_TPP_
template <class T>
inline GlobPoolVar<T>::GlobPoolVar(uint32_t set_id,
DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode):
dataPoolId(set_id), valid(PoolVariableIF::INVALID),
readWriteMode(setReadWriteMode)
{
if (dataSet != nullptr) {
dataSet->registerVariable(this);
}
}
template<typename T>
inline ReturnValue_t GlobPoolVar<T>::read(uint32_t lockTimeout) {
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = readWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
<< std::endl;
}
return result;
}
template<typename T>
inline ReturnValue_t GlobPoolVar<T>::commit(uint32_t lockTimeout) {
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = commitWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
<< std::endl;
}
return result;
}
template <class T>
inline ReturnValue_t GlobPoolVar<T>::readWithoutLock() {
PoolEntry<T>* read_out = glob::dataPool.getData<T>(dataPoolId, 1);
if (read_out != NULL) {
valid = read_out->valid;
value = *(read_out->address);
return HasReturnvaluesIF::RETURN_OK;
} else {
value = 0;
valid = false;
sif::error << "PoolVariable: read of DP Variable 0x" << std::hex
<< dataPoolId << std::dec << " failed." << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
}
template <class T>
inline ReturnValue_t GlobPoolVar<T>::commitWithoutLock() {
PoolEntry<T>* write_back = glob::dataPool.getData<T>(dataPoolId, 1);
if ((write_back != NULL) && (readWriteMode != VAR_READ)) {
write_back->valid = valid;
*(write_back->address) = value;
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
template <class T>
inline GlobPoolVar<T>::GlobPoolVar():
dataPoolId(PoolVariableIF::NO_PARAMETER),
valid(PoolVariableIF::INVALID),
readWriteMode(VAR_READ), value(0) {}
template <class T>
inline GlobPoolVar<T>::GlobPoolVar(const GlobPoolVar& rhs) :
dataPoolId(rhs.dataPoolId), valid(rhs.valid), readWriteMode(
rhs.readWriteMode), value(rhs.value) {}
template <class T>
inline pool_rwm_t GlobPoolVar<T>::getReadWriteMode() const {
return readWriteMode;
}
template <class T>
inline uint32_t GlobPoolVar<T>::getDataPoolId() const {
return dataPoolId;
}
template <class T>
inline void GlobPoolVar<T>::setDataPoolId(uint32_t poolId) {
dataPoolId = poolId;
}
template <class T>
inline bool GlobPoolVar<T>::isValid() const {
if (valid)
return true;
else
return false;
}
template <class T>
inline uint8_t GlobPoolVar<T>::getValid() {
return valid;
}
template <class T>
inline void GlobPoolVar<T>::setValid(bool valid) {
this->valid = valid;
}
#endif

View File

@ -1,185 +0,0 @@
#ifndef FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_H_
#define FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_H_
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h"
#include "../datapool/PoolVariableIF.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
/**
* @brief This is the access class for array-type data pool entries.
*
* @details
* To ensure safe usage of the data pool, operation is not done directly on the
* data pool entries, but on local copies. This class provides simple type-
* and length-safe access to vector-style data pool entries (i.e. entries with
* length > 1). The class can be instantiated as read-write and read only.
*
* It provides a commit-and-roll-back semantic, which means that no array
* entry in the data pool is changed until the commit call is executed.
* There are two template parameters:
* @tparam T
* This template parameter specifies the data type of an array entry. Currently,
* all plain data types are supported, but in principle any type is possible.
* @tparam vector_size
* This template parameter specifies the vector size of this entry. Using a
* template parameter for this is not perfect, but avoids
* dynamic memory allocation.
* @ingroup data_pool
*/
template<typename T, uint16_t vectorSize>
class GlobPoolVector: public PoolVariableIF {
public:
/**
* @brief In the constructor, the variable can register itself in a
* DataSet (if no nullptr is passed).
* @details
* It DOES NOT fetch the current value from the data pool, but sets the
* value attribute to default (0). The value is fetched within the
* read() operation.
* @param set_id
* This is the id in the global data pool this instance of the access
* class corresponds to.
* @param dataSet
* The data set in which the variable shall register itself. If nullptr,
* the variable is not registered.
* @param setWritable
* If this flag is set to true, changes in the value attribute can be
* written back to the data pool, otherwise not.
*/
GlobPoolVector(uint32_t set_id, DataSetIF* set,
ReadWriteMode_t setReadWriteMode);
/**
* @brief This is the local copy of the data pool entry.
* @details The user can work on this attribute
* just like he would on a local array of this type.
*/
T value[vectorSize];
/**
* @brief The classes destructor is empty.
* @details If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~GlobPoolVector() {};
/**
* @brief The operation returns the number of array entries
* in this variable.
*/
uint8_t getSize() {
return vectorSize;
}
/**
* @brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const {
return dataPoolId;
}
/**
* @brief This operation sets the data pool id of the variable.
* @details
* The method is necessary to set id's of data pool member variables
* with bad initialization.
*/
void setDataPoolId(uint32_t poolId) {
dataPoolId = poolId;
}
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const {
return readWriteMode;
}
/**
* @brief With this call, the valid information of the variable is returned.
*/
bool isValid() const {
if (valid != INVALID)
return true;
else
return false;
}
void setValid(bool valid) {this->valid = valid;}
uint8_t getValid() {return valid;}
T &operator [](int i) {return value[i];}
const T &operator [](int i) const {return value[i];}
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t max_size, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
/**
* @brief This is a call to read the array's values
* from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies all array values
* and the valid information to its local attributes.
* In case of a failure (wrong type, size or pool id not found), the
* variable is set to zero and invalid.
* The read call is protected by a lock of the global data pool.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
/**
* @brief The commit call copies the array values back to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The commit call is protected by a lock of the global data pool.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
private:
/**
* @brief To access the correct data pool entry on read and commit calls,
* the data pool id is stored.
*/
uint32_t dataPoolId;
/**
* @brief The valid information as it was stored in the data pool
* is copied to this attribute.
*/
uint8_t valid;
/**
* @brief The information whether the class is read-write or
* read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
};
#include "../datapoolglob/GlobalPoolVector.tpp"
template<typename T, uint16_t vectorSize>
using gp_vec_t = GlobPoolVector<T, vectorSize>;
#endif /* FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_H_ */

View File

@ -1,117 +0,0 @@
#ifndef FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_TPP_
#define FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_TPP_
template<typename T, uint16_t vectorSize>
inline GlobPoolVector<T, vectorSize>::GlobPoolVector(uint32_t set_id,
DataSetIF* set, ReadWriteMode_t setReadWriteMode) :
dataPoolId(set_id), valid(false), readWriteMode(setReadWriteMode) {
memset(this->value, 0, vectorSize * sizeof(T));
if (set != nullptr) {
set->registerVariable(this);
}
}
template<typename T, uint16_t vectorSize>
inline ReturnValue_t GlobPoolVector<T, vectorSize>::read(uint32_t lockTimeout) {
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = readWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
<< std::endl;
}
return result;
}
template<typename T, uint16_t vectorSize>
inline ReturnValue_t GlobPoolVector<T, vectorSize>::commit(
uint32_t lockTimeout) {
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = commitWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
<< std::endl;
}
return result;
}
template<typename T, uint16_t vectorSize>
inline ReturnValue_t GlobPoolVector<T, vectorSize>::readWithoutLock() {
PoolEntry<T>* read_out = glob::dataPool.getData<T>(this->dataPoolId,
vectorSize);
if (read_out != nullptr) {
this->valid = read_out->valid;
memcpy(this->value, read_out->address, read_out->getByteSize());
return HasReturnvaluesIF::RETURN_OK;
} else {
memset(this->value, 0, vectorSize * sizeof(T));
sif::error << "PoolVector: Read of DP Variable 0x" << std::hex
<< std::setw(8) << std::setfill('0') << dataPoolId <<
std::dec << " failed." << std::endl;
this->valid = INVALID;
return HasReturnvaluesIF::RETURN_FAILED;
}
}
template<typename T, uint16_t vectorSize>
inline ReturnValue_t GlobPoolVector<T, vectorSize>::commitWithoutLock() {
PoolEntry<T>* writeBack = glob::dataPool.getData<T>(this->dataPoolId,
vectorSize);
if ((writeBack != nullptr) && (this->readWriteMode != VAR_READ)) {
writeBack->valid = valid;
memcpy(writeBack->address, this->value, writeBack->getByteSize());
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
template<typename T, uint16_t vectorSize>
inline ReturnValue_t GlobPoolVector<T, vectorSize>::serialize(uint8_t** buffer,
size_t* size, size_t max_size,
SerializeIF::Endianness streamEndianness) const {
uint16_t i;
ReturnValue_t result;
for (i = 0; i < vectorSize; i++) {
result = SerializeAdapter::serialize(&(value[i]), buffer, size,
max_size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
return result;
}
template<typename T, uint16_t vectorSize>
inline size_t GlobPoolVector<T, vectorSize>::getSerializedSize() const {
return vectorSize * SerializeAdapter::getSerializedSize(value);
}
template<typename T, uint16_t vectorSize>
inline ReturnValue_t GlobPoolVector<T, vectorSize>::deSerialize(
const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) {
uint16_t i;
ReturnValue_t result;
for (i = 0; i < vectorSize; i++) {
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
return result;
}
#endif

View File

@ -1,164 +0,0 @@
#ifndef PIDREADER_H_
#define PIDREADER_H_
#include "../datapool/DataSetIF.h"
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapool/PoolEntry.h"
#include "../datapool/PoolVariableIF.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
template<typename U, uint8_t n_var> class PIDReaderList;
template<typename T>
class PIDReader: public PoolVariableIF {
template<typename U, uint8_t n_var> friend class PIDReaderList;
protected:
uint32_t parameterId;
uint8_t valid;
ReturnValue_t readWithoutLock() {
uint8_t arrayIndex = GlobalDataPool::PIDToArrayIndex(parameterId);
PoolEntry<T> *read_out = glob::dataPool.getData<T>(
GlobalDataPool::PIDToDataPoolId(parameterId), arrayIndex);
if (read_out != NULL) {
valid = read_out->valid;
value = read_out->address[arrayIndex];
return HasReturnvaluesIF::RETURN_OK;
} else {
value = 0;
valid = false;
sif::error << "PIDReader: read of PID 0x" << std::hex << parameterId
<< std::dec << " failed." << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
}
/**
* Never commit, is read-only.
* Reason is the possibility to access a single DP vector element, but if we commit,
* we set validity of the whole vector.
*/
ReturnValue_t commit(uint32_t lockTimeout) override {
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t commitWithoutLock() override {
return HasReturnvaluesIF::RETURN_FAILED;
}
/**
* Empty ctor for List initialization
*/
PIDReader() :
parameterId(PoolVariableIF::NO_PARAMETER), valid(
PoolVariableIF::INVALID), value(0) {
}
public:
/**
* \brief This is the local copy of the data pool entry.
*/
T value;
/**
* \brief In the constructor, the variable can register itself in a DataSet (if not NULL is
* passed).
* \details It DOES NOT fetch the current value from the data pool, but sets the value
* attribute to default (0). The value is fetched within the read() operation.
* \param set_id This is the id in the global data pool this instance of the access class
* corresponds to.
* \param dataSet The data set in which the variable shall register itself. If NULL,
* the variable is not registered.
* \param setWritable If this flag is set to true, changes in the value attribute can be
* written back to the data pool, otherwise not.
*/
PIDReader(uint32_t setParameterId, DataSetIF *dataSet) :
parameterId(setParameterId), valid(PoolVariableIF::INVALID), value(
0) {
if (dataSet != NULL) {
dataSet->registerVariable(this);
}
}
ReturnValue_t read(uint32_t lockTimeout) override {
ReturnValue_t result = glob::dataPool.lockDataPool();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = readWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "PIDReader::read: Could not unlock data pool!"
<< std::endl;
}
return result;
}
/**
* Copy ctor to copy classes containing Pool Variables.
*/
PIDReader(const PIDReader &rhs) :
parameterId(rhs.parameterId), valid(rhs.valid), value(rhs.value) {
}
/**
* \brief The classes destructor is empty.
*/
~PIDReader() {
}
/**
* \brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const {
return GlobalDataPool::PIDToDataPoolId(parameterId);
}
uint32_t getParameterId() const {
return parameterId;
}
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const {
return VAR_READ;
}
/**
* \brief With this call, the valid information of the variable is returned.
*/
bool isValid() const {
if (valid)
return true;
else
return false;
}
uint8_t getValid() {
return valid;
}
void setValid(bool valid) {
this->valid = valid;
}
operator T() {
return value;
}
PIDReader<T>& operator=(T newValue) {
value = newValue;
return *this;
}
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override {
return SerializeAdapter::serialize(&value, buffer, size, maxSize,
streamEndianness);
}
virtual size_t getSerializedSize() const override {
return SerializeAdapter::getSerializedSize(&value);
}
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override {
return SerializeAdapter::deSerialize(&value, buffer, size,
streamEndianness);
}
};
#endif /* PIDREADER_H_ */

View File

@ -1,27 +0,0 @@
#ifndef FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_
#define FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_
#include "../datapool/PoolVariableIF.h"
#include "../datapoolglob/PIDReader.h"
template <class T, uint8_t n_var>
class PIDReaderList {
private:
PIDReader<T> variables[n_var];
public:
PIDReaderList( const uint32_t setPid[n_var], DataSetIF* dataSet) {
//I really should have a look at the new init list c++ syntax.
if (dataSet == NULL) {
return;
}
for (uint8_t count = 0; count < n_var; count++) {
variables[count].parameterId = setPid[count];
dataSet->registerVariable(&variables[count]);
}
}
PIDReader<T> &operator [](int i) { return variables[i]; }
};
#endif /* FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ */

View File

@ -1,239 +0,0 @@
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapoolglob/PoolRawAccess.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../serialize/EndianConverter.h"
#include <cstring>
PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry,
DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode) :
dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false),
type(Type::UNKNOWN_TYPE), typeSize(0), arraySize(0), sizeTillEnd(0),
readWriteMode(setReadWriteMode) {
memset(value, 0, sizeof(value));
if (dataSet != nullptr) {
dataSet->registerVariable(this);
}
}
PoolRawAccess::~PoolRawAccess() {}
ReturnValue_t PoolRawAccess::read(uint32_t lockTimeout) {
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = readWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
<< std::endl;
}
return result;
}
ReturnValue_t PoolRawAccess::readWithoutLock() {
ReturnValue_t result = RETURN_FAILED;
PoolEntryIF* readOut = glob::dataPool.getRawData(dataPoolId);
if (readOut != nullptr) {
result = handleReadOut(readOut);
if(result == RETURN_OK) {
return result;
}
} else {
result = READ_ENTRY_NON_EXISTENT;
}
handleReadError(result);
return result;
}
ReturnValue_t PoolRawAccess::handleReadOut(PoolEntryIF* readOut) {
ReturnValue_t result = RETURN_FAILED;
valid = readOut->getValid();
if (readOut->getSize() > arrayEntry) {
arraySize = readOut->getSize();
typeSize = readOut->getByteSize() / readOut->getSize();
type = readOut->getType();
if (typeSize <= sizeof(value)) {
uint16_t arrayPosition = arrayEntry * typeSize;
sizeTillEnd = readOut->getByteSize() - arrayPosition;
uint8_t* ptr = &((uint8_t*) readOut->getRawData())[arrayPosition];
memcpy(value, ptr, typeSize);
return RETURN_OK;
} else {
result = READ_TYPE_TOO_LARGE;
}
} else {
//debug << "PoolRawAccess: Size: " << (int)read_out->getSize() << std::endl;
result = READ_INDEX_TOO_LARGE;
}
return result;
}
void PoolRawAccess::handleReadError(ReturnValue_t result) {
sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId
<< std::dec << " failed, ";
if(result == READ_TYPE_TOO_LARGE) {
sif::error << "type too large." << std::endl;
}
else if(result == READ_INDEX_TOO_LARGE) {
sif::error << "index too large." << std::endl;
}
else if(result == READ_ENTRY_NON_EXISTENT) {
sif::error << "entry does not exist." << std::endl;
}
valid = INVALID;
typeSize = 0;
sizeTillEnd = 0;
memset(value, 0, sizeof(value));
}
ReturnValue_t PoolRawAccess::commit(uint32_t lockTimeout) {
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = commitWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
<< std::endl;
}
return result;
}
ReturnValue_t PoolRawAccess::commitWithoutLock() {
PoolEntryIF* write_back = glob::dataPool.getRawData(dataPoolId);
if ((write_back != NULL) && (readWriteMode != VAR_READ)) {
write_back->setValid(valid);
uint8_t array_position = arrayEntry * typeSize;
uint8_t* ptr = &((uint8_t*) write_back->getRawData())[array_position];
memcpy(ptr, value, typeSize);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
uint8_t* PoolRawAccess::getEntry() {
return value;
}
ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
size_t* writtenBytes, size_t max_size) {
uint8_t* data_ptr = getEntry();
// debug << "PoolRawAccess::getEntry: Array position: " <<
// index * size_of_type << " Size of T: " << (int)size_of_type <<
// " ByteSize: " << byte_size << " Position: " << *size << std::endl;
if (typeSize == 0)
return DATA_POOL_ACCESS_FAILED;
if (typeSize > max_size)
return INCORRECT_SIZE;
EndianConverter::convertBigEndian(buffer, data_ptr, typeSize);
*writtenBytes = typeSize;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const {
if (typeSize + *size <= maxSize) {
switch(streamEndianness) {
case(Endianness::BIG):
EndianConverter::convertBigEndian(*buffer, value, typeSize);
break;
case(Endianness::LITTLE):
EndianConverter::convertLittleEndian(*buffer, value, typeSize);
break;
case(Endianness::MACHINE):
default:
memcpy(*buffer, value, typeSize);
break;
}
*size += typeSize;
(*buffer) += typeSize;
return HasReturnvaluesIF::RETURN_OK;
} else {
return SerializeIF::BUFFER_TOO_SHORT;
}
}
Type PoolRawAccess::getType() {
return type;
}
size_t PoolRawAccess::getSizeOfType() {
return typeSize;
}
size_t PoolRawAccess::getArraySize(){
return arraySize;
}
uint32_t PoolRawAccess::getDataPoolId() const {
return dataPoolId;
}
PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const {
return readWriteMode;
}
ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer,
size_t setSize) {
if (typeSize == setSize) {
EndianConverter::convertBigEndian(value, buffer, typeSize);
return HasReturnvaluesIF::RETURN_OK;
} else {
sif::error << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: "
"Internal" << (uint32_t) typeSize << ", Requested: " << setSize
<< std::endl;
return INCORRECT_SIZE;
}
}
bool PoolRawAccess::isValid() const {
if (valid != INVALID)
return true;
else
return false;
}
void PoolRawAccess::setValid(bool valid) {
this->valid = valid;
}
size_t PoolRawAccess::getSizeTillEnd() const {
return sizeTillEnd;
}
size_t PoolRawAccess::getSerializedSize() const {
return typeSize;
}
ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
if (*size >= typeSize) {
switch(streamEndianness) {
case(Endianness::BIG):
EndianConverter::convertBigEndian(value, *buffer, typeSize);
break;
case(Endianness::LITTLE):
EndianConverter::convertLittleEndian(value, *buffer, typeSize);
break;
case(Endianness::MACHINE):
default:
memcpy(value, *buffer, typeSize);
break;
}
*size -= typeSize;
*buffer += typeSize;
return HasReturnvaluesIF::RETURN_OK;
}
else {
return SerializeIF::STREAM_TOO_SHORT;
}
}

View File

@ -1,220 +0,0 @@
#ifndef POOLRAWACCESS_H_
#define POOLRAWACCESS_H_
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntryIF.h"
#include "../datapool/PoolVariableIF.h"
#include "../globalfunctions/Type.h"
/**
* @brief This class allows accessing Data Pool variables as raw bytes.
* @details
* This is necessary to have an access method for HK data, as the PID's alone
* do not provide type information. Please note that the the raw pool access
* read() and commit() calls are not thread-safe.
*
* Please supply a data set and use the data set read(), commit() calls for
* thread-safe data pool access.
* @ingroup data_pool
*/
class PoolRawAccess: public PoolVariableIF, HasReturnvaluesIF {
public:
/**
* This constructor is used to access a data pool entry with a
* given ID if the target type is not known. A DataSet object is supplied
* and the data pool entry with the given ID is registered to that data set.
* Please note that a pool raw access buffer only has a buffer
* with a size of double. As such, for vector entries which have
* @param data_pool_id Target data pool entry ID
* @param arrayEntry
* @param data_set Dataset to register data pool entry to
* @param setReadWriteMode
* @param registerVectors If set to true, the constructor checks if
* there are multiple vector entries to registers
* and registers all of them recursively into the data_set
*
*/
PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry,
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode =
PoolVariableIF::VAR_READ);
/**
* @brief This operation returns a pointer to the entry fetched.
* @details Return pointer to the buffer containing the raw data
* Size and number of data can be retrieved by other means.
*/
uint8_t* getEntry();
/**
* @brief This operation returns the fetched entry from the data pool and
* flips the bytes, if necessary.
* @details It makes use of the getEntry call of this function, but additionally flips the
* bytes to big endian, which is the default for external communication (as House-
* keeping telemetry). To achieve this, the data is copied directly to the passed
* buffer, if it fits in the given max_size.
* @param buffer A pointer to a buffer to write to
* @param writtenBytes The number of bytes written is returned with this value.
* @param max_size The maximum size that the function may write to buffer.
* @return - @c RETURN_OK if entry could be acquired
* - @c RETURN_FAILED else.
*/
ReturnValue_t getEntryEndianSafe(uint8_t *buffer, size_t *size,
size_t maxSize);
/**
* @brief Serialize raw pool entry into provided buffer directly
* @param buffer Provided buffer. Raw pool data will be copied here
* @param size [out] Increment provided size value by serialized size
* @param max_size Maximum allowed serialization size
* @param bigEndian Specify endianess
* @return - @c RETURN_OK if serialization was successfull
* - @c SerializeIF::BUFFER_TOO_SHORT if range check failed
*/
ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
/**
* With this method, the content can be set from a big endian buffer safely.
* @param buffer Pointer to the data to set
* @param size Size of the data to write. Must fit this->size.
* @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure
*/
ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer,
size_t setSize);
/**
* @brief This operation returns the type of the entry currently stored.
*/
Type getType();
/**
* @brief This operation returns the size of the entry currently stored.
*/
size_t getSizeOfType();
/**
*
* @return the size of the datapool array
*/
size_t getArraySize();
/**
* @brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const;
static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS;
static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t READ_TYPE_TOO_LARGE = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t READ_INDEX_TOO_LARGE = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t READ_ENTRY_NON_EXISTENT = MAKE_RETURN_CODE(0x05);
static const uint8_t RAW_MAX_SIZE = sizeof(double);
uint8_t value[RAW_MAX_SIZE];
/**
* @brief The classes destructor is empty. If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~PoolRawAccess();
/**
* This method returns if the variable is read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const;
/**
* @brief With this call, the valid information of the variable is returned.
*/
bool isValid() const;
void setValid(bool valid);
/**
* Getter for the remaining size.
*/
size_t getSizeTillEnd() const;
/**
* @brief This is a call to read the value from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The call is protected by a lock of the global data pool.
* @return -@c RETURN_OK Read successfull
* -@c READ_TYPE_TOO_LARGE
* -@c READ_INDEX_TOO_LARGE
* -@c READ_ENTRY_NON_EXISTENT
*/
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
/**
* @brief The commit call writes back the variable's value to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The call is protected by a lock of the global data pool.
*
*/
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
ReturnValue_t handleReadOut(PoolEntryIF* read_out);
void handleReadError(ReturnValue_t result);
private:
/**
* @brief To access the correct data pool entry on read and commit calls, the data pool id
* is stored.
*/
uint32_t dataPoolId;
/**
* @brief The array entry that is fetched from the data pool.
*/
uint8_t arrayEntry;
/**
* @brief The valid information as it was stored in the data pool is copied to this attribute.
*/
uint8_t valid;
/**
* @brief This value contains the type of the data pool entry.
*/
Type type;
/**
* @brief This value contains the size of the data pool entry type in bytes.
*/
size_t typeSize;
/**
* The size of the DP array (single values return 1)
*/
size_t arraySize;
/**
* The size (in bytes) from the selected entry till the end of this DataPool variable.
*/
size_t sizeTillEnd;
/**
* @brief The information whether the class is read-write or read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
};
#endif /* POOLRAWACCESS_H_ */

View File

@ -27,13 +27,11 @@
#define FSFW_OBJ_EVENT_TRANSLATION 0
#if FSFW_OBJ_EVENT_TRANSLATION == 1
#define FSFW_DEBUG_OUTPUT 1
//! Specify whether info events are printed too.
#define FSFW_DEBUG_INFO 1
#include <translateObjects.h>
#include <translateEvents.h>
#else
#define FSFW_DEBUG_OUTPUT 0
#endif
//! When using the newlib nano library, C99 support for stdio facilities

View File

@ -22,154 +22,154 @@ using DeviceCommandId_t = uint32_t;
*/
class DeviceHandlerIF {
public:
static constexpr DeviceCommandId_t NO_COMMAND = -1;
static constexpr DeviceCommandId_t NO_COMMAND = -1;
static constexpr uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static constexpr uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
static constexpr uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static constexpr uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
using dh_heater_request_t = uint8_t;
using dh_thermal_state_t = int8_t;
using dh_heater_request_t = uint8_t;
using dh_thermal_state_t = int8_t;
/**
* @brief This is the mode the <strong>device handler</strong> is in.
*
* @details The mode of the device handler must not be confused with the mode the device is in.
* The mode of the device itself is transparent to the user but related to the mode of the handler.
* MODE_ON and MODE_OFF are included in hasModesIF.h
*/
/**
* @brief This is the mode the <strong>device handler</strong> is in.
*
* @details The mode of the device handler must not be confused with the mode the device is in.
* The mode of the device itself is transparent to the user but related to the mode of the handler.
* MODE_ON and MODE_OFF are included in hasModesIF.h
*/
// MODE_ON = 0, //!< The device is powered and ready to perform operations. In this mode, no commands are sent by the device handler itself, but direct commands van be commanded and will be interpreted
// MODE_OFF = 1, //!< The device is powered off. The only command accepted in this mode is a mode change to on.
//! The device is powered on and the device handler periodically sends
//! commands. The commands to be sent are selected by the handler
//! according to the submode.
static const Mode_t MODE_NORMAL = 2;
//! The device is powered on and ready to perform operations. In this mode,
//! raw commands can be sent. The device handler will send all replies
//! received from the command back to the commanding object.
static const Mode_t MODE_RAW = 3;
//! The device is shut down but the switch could not be turned off, so the
//! device still is powered. In this mode, only a mode change to @c MODE_OFF
//! can be commanded, which tries to switch off the device again.
static const Mode_t MODE_ERROR_ON = 4;
//! This is a transitional state which can not be commanded. The device
//! handler performs all commands to get the device in a state ready to
//! perform commands. When this is completed, the mode changes to @c MODE_ON.
static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5;
//! This is a transitional state which can not be commanded.
//! The device handler performs all actions and commands to get the device
//! shut down. When the device is off, the mode changes to @c MODE_OFF.
//! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off
//! transition if available.
static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6;
//! It is possible to set the mode to _MODE_TO_ON to use the to on
//! transition if available.
static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON;
//! It is possible to set the mode to _MODE_TO_RAW to use the to raw
//! transition if available.
static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW;
//! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal
//! transition if available.
static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL;
//! This is a transitional state which can not be commanded.
//! The device is shut down and ready to be switched off.
//! After the command to set the switch off has been sent,
//! the mode changes to @c MODE_WAIT_OFF
static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1;
//! This is a transitional state which can not be commanded. The device
//! will be switched on in this state. After the command to set the switch
//! on has been sent, the mode changes to @c MODE_WAIT_ON.
static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and the handler waits for it to be off.
//! When the switch is off, the mode changes to @c MODE_OFF.
static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3;
//! This is a transitional state which can not be commanded. The switch
//! has been commanded on and the handler waits for it to be on.
//! When the switch is on, the mode changes to @c MODE_TO_ON.
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and is off now. This state is only to do an RMAP
//! cycle once more where the doSendRead() function will set the mode to
//! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board.
static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5;
// MODE_ON = 0, //!< The device is powered and ready to perform operations. In this mode, no commands are sent by the device handler itself, but direct commands van be commanded and will be interpreted
// MODE_OFF = 1, //!< The device is powered off. The only command accepted in this mode is a mode change to on.
//! The device is powered on and the device handler periodically sends
//! commands. The commands to be sent are selected by the handler
//! according to the submode.
static const Mode_t MODE_NORMAL = 2;
//! The device is powered on and ready to perform operations. In this mode,
//! raw commands can be sent. The device handler will send all replies
//! received from the command back to the commanding object.
static const Mode_t MODE_RAW = 3;
//! The device is shut down but the switch could not be turned off, so the
//! device still is powered. In this mode, only a mode change to @c MODE_OFF
//! can be commanded, which tries to switch off the device again.
static const Mode_t MODE_ERROR_ON = 4;
//! This is a transitional state which can not be commanded. The device
//! handler performs all commands to get the device in a state ready to
//! perform commands. When this is completed, the mode changes to @c MODE_ON.
static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5;
//! This is a transitional state which can not be commanded.
//! The device handler performs all actions and commands to get the device
//! shut down. When the device is off, the mode changes to @c MODE_OFF.
//! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off
//! transition if available.
static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6;
//! It is possible to set the mode to _MODE_TO_ON to use the to on
//! transition if available.
static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON;
//! It is possible to set the mode to _MODE_TO_RAW to use the to raw
//! transition if available.
static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW;
//! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal
//! transition if available.
static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL;
//! This is a transitional state which can not be commanded.
//! The device is shut down and ready to be switched off.
//! After the command to set the switch off has been sent,
//! the mode changes to @c MODE_WAIT_OFF
static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1;
//! This is a transitional state which can not be commanded. The device
//! will be switched on in this state. After the command to set the switch
//! on has been sent, the mode changes to @c MODE_WAIT_ON.
static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and the handler waits for it to be off.
//! When the switch is off, the mode changes to @c MODE_OFF.
static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3;
//! This is a transitional state which can not be commanded. The switch
//! has been commanded on and the handler waits for it to be on.
//! When the switch is on, the mode changes to @c MODE_TO_ON.
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and is off now. This state is only to do an RMAP
//! cycle once more where the doSendRead() function will set the mode to
//! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board.
static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH;
static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, severity::LOW);
static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, severity::LOW);
static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, severity::LOW);
static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, severity::LOW);
static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, severity::LOW);
static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, severity::LOW);
static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, severity::LOW);
static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, severity::LOW);
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW); //!< Indicates a SW bug in child class.
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH;
static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, severity::LOW);
static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, severity::LOW);
static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, severity::LOW);
static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, severity::LOW);
static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, severity::LOW);
static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, severity::LOW);
static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, severity::LOW);
static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, severity::LOW);
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW); //!< Indicates a SW bug in child class.
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
// Standard codes used when building commands.
static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected.
static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB
static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB
static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3);
static const ReturnValue_t CANT_SWITCH_ADDRESS = MAKE_RETURN_CODE(0xA4);
static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5);
static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6);
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xA7);
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8); //!< Used to indicate that this is a command-only command.
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9);
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA);
// Standard codes used when building commands.
static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected.
static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB
static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB
static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3);
static const ReturnValue_t CANT_SWITCH_ADDRESS = MAKE_RETURN_CODE(0xA4);
static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5);
static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6);
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xA7);
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8); //!< Used to indicate that this is a command-only command.
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9);
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA);
// Standard codes used in scanForReply
static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB0);
static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB1);
static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB2);
static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB3);
// Standard codes used in scanForReply
static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB0);
static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB1);
static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB2);
static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB3);
// Standard codes used in interpretDeviceReply
static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC0); //the device reported, that it did not execute the command
static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC1);
static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC2); //the deviceCommandId reported by scanforReply is unknown
static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC3); //syntax etc is correct but still not ok, eg parameters where none are expected
// Standard codes used in interpretDeviceReply
static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC0); //the device reported, that it did not execute the command
static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC1);
static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC2); //the deviceCommandId reported by scanforReply is unknown
static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC3); //syntax etc is correct but still not ok, eg parameters where none are expected
// Standard codes used in buildCommandFromCommand
static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE(0xD0);
static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1);
// Standard codes used in buildCommandFromCommand
static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE(0xD0);
static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1);
/**
* Communication action that will be executed.
*
* This is used by the child class to tell the base class what to do.
*/
enum CommunicationAction: uint8_t {
PERFORM_OPERATION,
SEND_WRITE,//!< Send write
GET_WRITE, //!< Get write
SEND_READ, //!< Send read
GET_READ, //!< Get read
NOTHING //!< Do nothing.
};
/**
* Communication action that will be executed.
*
* This is used by the child class to tell the base class what to do.
*/
enum CommunicationAction: uint8_t {
PERFORM_OPERATION,
SEND_WRITE,//!< Send write
GET_WRITE, //!< Get write
SEND_READ, //!< Send read
GET_READ, //!< Get read
NOTHING //!< Do nothing.
};
static constexpr uint32_t DEFAULT_THERMAL_SET_ID = sid_t::INVALID_SET_ID - 1;
static constexpr uint32_t DEFAULT_THERMAL_SET_ID = sid_t::INVALID_SET_ID - 1;
static constexpr lp_id_t DEFAULT_THERMAL_STATE_POOL_ID =
localpool::INVALID_LPID - 2;
static constexpr lp_id_t DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID =
localpool::INVALID_LPID - 1;
static constexpr lp_id_t DEFAULT_THERMAL_STATE_POOL_ID =
localpool::INVALID_LPID - 2;
static constexpr lp_id_t DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID =
localpool::INVALID_LPID - 1;
/**
* Default Destructor
*/
virtual ~DeviceHandlerIF() {}
/**
* Default Destructor
*/
virtual ~DeviceHandlerIF() {}
/**
* This MessageQueue is used to command the device handler.
* @return the id of the MessageQueue
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
/**
* This MessageQueue is used to command the device handler.
* @return the id of the MessageQueue
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
};

View File

@ -1,7 +1,7 @@
#include "EventManager.h"
#include "EventMessage.h"
#include <FSFWConfig.h>
#include <FSFWConfig.h>
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../ipc/QueueFactory.h"
#include "../ipc/MutexFactory.h"
@ -43,7 +43,7 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
EventMessage message;
result = eventReportQueue->receiveMessage(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
#ifdef DEBUG
#if FSFW_OBJ_EVENT_TRANSLATION == 1
printEvent(&message);
#endif
notifyListeners(&message);
@ -114,13 +114,13 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener,
return result;
}
#if FSFW_DEBUG_OUTPUT == 1
#if FSFW_OBJ_EVENT_TRANSLATION == 1
void EventManager::printEvent(EventMessage* message) {
const char *string = 0;
switch (message->getSeverity()) {
case severity::INFO:
#ifdef DEBUG_INFO_EVENT
#if DEBUG_INFO_EVENT == 1
string = translateObject(message->getReporter());
sif::info << "EVENT: ";
if (string != 0) {

View File

@ -1,18 +1,20 @@
#ifndef EVENTMANAGER_H_
#define EVENTMANAGER_H_
#ifndef FSFW_EVENT_EVENTMANAGER_H_
#define FSFW_EVENT_EVENTMANAGER_H_
#include "eventmatching/EventMatchTree.h"
#include "EventManagerIF.h"
#include "eventmatching/EventMatchTree.h"
#include <FSFWConfig.h>
#include "../objectmanager/SystemObject.h"
#include "../storagemanager/LocalPool.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../ipc/MessageQueueIF.h"
#include "../ipc/MutexIF.h"
#include <FSFWConfig.h>
#include <map>
#if FSFW_DEBUG_OUTPUT == 1
#if FSFW_OBJ_EVENT_TRANSLATION == 1
// forward declaration, should be implemented by mission
extern const char* translateObject(object_id_t object);
extern const char* translateEvents(Event event);
@ -59,7 +61,7 @@ protected:
void notifyListeners(EventMessage *message);
#if FSFW_DEBUG_OUTPUT == 1
#if FSFW_OBJ_EVENT_TRANSLATION == 1
void printEvent(EventMessage *message);
#endif
@ -68,4 +70,4 @@ protected:
void unlockMutex();
};
#endif /* EVENTMANAGER_H_ */
#endif /* FSFW_EVENT_EVENTMANAGER_H_ */

View File

@ -1,10 +1,11 @@
#ifndef EVENTMANAGERIF_H_
#define EVENTMANAGERIF_H_
#include "eventmatching/eventmatching.h"
#include "EventMessage.h"
#include "eventmatching/eventmatching.h"
#include "../objectmanager/ObjectManagerIF.h"
#include "../ipc/MessageQueueSenderIF.h"
#include "../ipc/MessageQueueIF.h"
class EventManagerIF {
public:
@ -16,7 +17,8 @@ public:
virtual MessageQueueId_t getEventReportQueue() = 0;
virtual ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false) = 0;
virtual ReturnValue_t registerListener(MessageQueueId_t listener,
bool forwardAllButSelected = false) = 0;
virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener,
EventId_t event) = 0;
virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener,
@ -31,18 +33,22 @@ public:
bool reporterInverted = false) = 0;
static void triggerEvent(object_id_t reportingObject, Event event,
uint32_t parameter1 = 0, uint32_t parameter2 = 0, MessageQueueId_t sentFrom = 0) {
uint32_t parameter1 = 0, uint32_t parameter2 = 0,
MessageQueueId_t sentFrom = 0) {
EventMessage message(event, reportingObject, parameter1, parameter2);
triggerEvent(&message, sentFrom);
}
static void triggerEvent(EventMessage* message, MessageQueueId_t sentFrom = 0) {
static MessageQueueId_t eventmanagerQueue = 0;
if (eventmanagerQueue == 0) {
static void triggerEvent(EventMessage* message,
MessageQueueId_t sentFrom = 0) {
static MessageQueueId_t eventmanagerQueue = MessageQueueIF::NO_QUEUE;
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
EventManagerIF *eventmanager = objectManager->get<EventManagerIF>(
objects::EVENT_MANAGER);
if (eventmanager != NULL) {
eventmanagerQueue = eventmanager->getEventReportQueue();
if (eventmanager == nullptr) {
return;
}
eventmanagerQueue = eventmanager->getEventReportQueue();
}
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
}

View File

@ -1,4 +1,3 @@
#include "../serialize/SerializeAdapter.h"
#include "Type.h"
#include "../serialize/SerializeAdapter.h"

View File

@ -1,9 +1,13 @@
#ifndef TYPE_H_
#define TYPE_H_
#ifndef FSFW_GLOBALFUNCTIONS_TYPE_H_
#define FSFW_GLOBALFUNCTIONS_TYPE_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeIF.h"
#include <type_traits>
/**
* @brief Type definition for CCSDS or ECSS.
*/
class Type: public SerializeIF {
public:
enum ActualType_t {
@ -53,6 +57,11 @@ private:
template<typename T>
struct PodTypeConversion {
static_assert(not std::is_same<T, bool>::value,
"Do not use boolean for the PoolEntry type, use uint8_t "
"instead! The ECSS standard defines a boolean as a one bit "
"field. Therefore it is preferred to store a boolean as an "
"uint8_t");
static const Type::ActualType_t type = Type::UNKNOWN_TYPE;
};
template<>
@ -88,4 +97,4 @@ struct PodTypeConversion<double> {
static const Type::ActualType_t type = Type::DOUBLE;
};
#endif /* TYPE_H_ */
#endif /* FSFW_GLOBALFUNCTIONS_TYPE_H_ */

View File

@ -3,6 +3,7 @@
#include "MessageQueueIF.h"
#include "MessageQueueMessage.h"
#include <cstdint>
/**

View File

@ -1,7 +1,10 @@
#include "../../osal/FreeRTOS/BinSemaphUsingTask.h"
#include "../../osal/FreeRTOS/TaskManagement.h"
#include "BinSemaphUsingTask.h"
#include "TaskManagement.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#if (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8
BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() {
handle = TaskManagement::getCurrentTaskHandle();
if(handle == nullptr) {
@ -16,6 +19,10 @@ BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() {
xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr);
}
void BinarySemaphoreUsingTask::refreshTaskHandle() {
handle = TaskManagement::getCurrentTaskHandle();
}
ReturnValue_t BinarySemaphoreUsingTask::acquire(TimeoutType timeoutType,
uint32_t timeoutMs) {
TickType_t timeout = 0;
@ -93,3 +100,6 @@ uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR(
higherPriorityTaskWoken);
return notificationValue;
}
#endif /* (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8 */

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_
#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_
#ifndef FSFW_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_
#define FSFW_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_
#include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../tasks/SemaphoreIF.h"
@ -7,13 +7,20 @@
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#if (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8
/**
* @brief Binary Semaphore implementation using the task notification value.
* The notification value should therefore not be used
* for other purposes.
* for other purposes!
* @details
* Additional information: https://www.freertos.org/RTOS-task-notifications.html
* and general semaphore documentation.
* This semaphore is bound to the task it is created in!
* Take care of building this class with the correct executing task,
* (for example in the initializeAfterTaskCreation() function) or
* by calling refreshTaskHandle() with the correct executing task.
*/
class BinarySemaphoreUsingTask: public SemaphoreIF,
public HasReturnvaluesIF {
@ -25,6 +32,16 @@ public:
//! @brief Default dtor
virtual~ BinarySemaphoreUsingTask();
/**
* This function can be used to get the correct task handle from the
* currently executing task.
*
* This is required because the task notification value will be used
* as a binary semaphore, and the semaphore might be created by another
* task.
*/
void refreshTaskHandle();
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING,
uint32_t timeoutMs = portMAX_DELAY) override;
ReturnValue_t release() override;
@ -67,10 +84,13 @@ public:
* - @c RETURN_FAILED on failure
*/
static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify,
BaseType_t * higherPriorityTaskWoken);
BaseType_t* higherPriorityTaskWoken);
protected:
TaskHandle_t handle;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */
#endif /* (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8 */
#endif /* FSFW_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */

View File

@ -1,5 +1,5 @@
#include "../../osal/FreeRTOS/BinarySemaphore.h"
#include "../../osal/FreeRTOS/TaskManagement.h"
#include "BinarySemaphore.h"
#include "TaskManagement.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
BinarySemaphore::BinarySemaphore() {

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
#ifndef FSFW_OSAL_FREERTOS_BINARYSEMPAHORE_H_
#define FSFW_OSAL_FREERTOS_BINARYSEMPAHORE_H_
#include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../tasks/SemaphoreIF.h"
@ -104,4 +104,4 @@ protected:
SemaphoreHandle_t handle;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */
#endif /* FSFW_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */

View File

@ -1,6 +1,7 @@
#include "Timekeeper.h"
#include "../../timemanager/Clock.h"
#include "../../globalfunctions/timevalOperations.h"
#include "Timekeeper.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
@ -67,6 +68,13 @@ ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
return HasReturnvaluesIF::RETURN_OK;
}
//uint32_t Clock::getUptimeSeconds() {
// timeval uptime = getUptime();
// return uptime.tv_sec;
//}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval time_timeval;
ReturnValue_t result = getClock_timeval(&time_timeval);

View File

@ -1,7 +1,11 @@
#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h"
#include "../../osal/FreeRTOS/TaskManagement.h"
#include "CountingSemaphUsingTask.h"
#include "TaskManagement.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#if (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8
CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount,
uint8_t initCount): maxCount(maxCount) {
if(initCount > maxCount) {
@ -112,3 +116,5 @@ uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR(
uint8_t CountingSemaphoreUsingTask::getMaxCount() const {
return maxCount;
}
#endif

View File

@ -1,13 +1,14 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#ifndef FSFW_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#define FSFW_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h"
#include "CountingSemaphUsingTask.h"
#include "../../tasks/SemaphoreIF.h"
extern "C" {
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
}
#if (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8
/**
* @brief Couting Semaphore implementation which uses the notification value
@ -16,6 +17,9 @@ extern "C" {
* @details
* Additional information: https://www.freertos.org/RTOS-task-notifications.html
* and general semaphore documentation.
* This semaphore is bound to the task it is created in!
* Take care of calling this function with the correct executing task,
* (for example in the initializeAfterTaskCreation() function).
*/
class CountingSemaphoreUsingTask: public SemaphoreIF {
public:
@ -99,4 +103,7 @@ private:
const uint8_t maxCount;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */
#endif /* (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8 */
#endif /* FSFW_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */

View File

@ -1,6 +1,7 @@
#include "../../osal/FreeRTOS/CountingSemaphore.h"
#include "CountingSemaphore.h"
#include "TaskManagement.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../osal/FreeRTOS/TaskManagement.h"
#include <freertos/semphr.h>

View File

@ -1,6 +1,7 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_
#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_
#include "../../osal/FreeRTOS/BinarySemaphore.h"
#include "BinarySemaphore.h"
/**
* @brief Counting semaphores, which can be acquire more than once.

View File

@ -114,38 +114,24 @@ void FixedTimeslotTask::taskFunctionality() {
intervalMs = this->pst.getIntervalToPreviousSlotMs();
interval = pdMS_TO_TICKS(intervalMs);
checkMissedDeadline(xLastWakeTime, interval);
// Wait for the interval. This exits immediately if a deadline was
// missed while also updating the last wake time.
vTaskDelayUntil(&xLastWakeTime, interval);
#if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || \
tskKERNEL_VERSION_MAJOR > 10
BaseType_t wasDelayed = xTaskDelayUntil(&xLastWakeTime, interval);
if(wasDelayed == pdFALSE) {
handleMissedDeadline();
}
#else
if(checkMissedDeadline(xLastWakeTime, interval)) {
handleMissedDeadline();
}
// Wait for the interval. This exits immediately if a deadline was
// missed while also updating the last wake time.
vTaskDelayUntil(&xLastWakeTime, interval);
#endif
}
}
}
void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime,
const TickType_t interval) {
/* Check whether deadline was missed while also taking overflows
* into account. Drawing this on paper with a timeline helps to understand
* it. */
TickType_t currentTickCount = xTaskGetTickCount();
TickType_t timeToWake = xLastWakeTime + interval;
// Time to wake has not overflown.
if(timeToWake > xLastWakeTime) {
/* If the current time has overflown exclusively or the current
* tick count is simply larger than the time to wake, a deadline was
* missed */
if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) {
handleMissedDeadline();
}
}
/* Time to wake has overflown. A deadline was missed if the current time
* is larger than the time to wake */
else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) {
handleMissedDeadline();
}
}
void FixedTimeslotTask::handleMissedDeadline() {
if(deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();

View File

@ -93,8 +93,6 @@ protected:
*/
void taskFunctionality(void);
void checkMissedDeadline(const TickType_t xLastWakeTime,
const TickType_t interval);
void handleMissedDeadline();
};

View File

@ -1,13 +1,41 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_FREERTOSTASKIF_H_
#define FRAMEWORK_OSAL_FREERTOS_FREERTOSTASKIF_H_
#ifndef FSFW_OSAL_FREERTOS_FREERTOSTASKIF_H_
#define FSFW_OSAL_FREERTOS_FREERTOSTASKIF_H_
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
class FreeRTOSTaskIF {
public:
virtual~ FreeRTOSTaskIF() {}
virtual TaskHandle_t getTaskHandle() = 0;
virtual~ FreeRTOSTaskIF() {}
virtual TaskHandle_t getTaskHandle() = 0;
protected:
bool checkMissedDeadline(const TickType_t xLastWakeTime,
const TickType_t interval) {
/* Check whether deadline was missed while also taking overflows
* into account. Drawing this on paper with a timeline helps to understand
* it. */
TickType_t currentTickCount = xTaskGetTickCount();
TickType_t timeToWake = xLastWakeTime + interval;
// Time to wake has not overflown.
if(timeToWake > xLastWakeTime) {
/* If the current time has overflown exclusively or the current
* tick count is simply larger than the time to wake, a deadline was
* missed */
if((currentTickCount < xLastWakeTime) or
(currentTickCount > timeToWake)) {
return true;
}
}
/* Time to wake has overflown. A deadline was missed if the current time
* is larger than the time to wake */
else if((timeToWake < xLastWakeTime) and
(currentTickCount > timeToWake)) {
return true;
}
return false;
}
};
#endif /* FRAMEWORK_OSAL_FREERTOS_FREERTOSTASKIF_H_ */
#endif /* FSFW_OSAL_FREERTOS_FREERTOSTASKIF_H_ */

View File

@ -11,7 +11,12 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize):
maxMessageSize(maxMessageSize) {
handle = xQueueCreate(messageDepth, maxMessageSize);
if (handle == nullptr) {
sif::error << "MessageQueue::MessageQueue Creation failed" << std::endl;
sif::error << "MessageQueue::MessageQueue:"
<< " Creation failed." << std::endl;
sif::error << "Specified Message Depth: " << messageDepth
<< std::endl;
sif::error << "Specified Maximum Message Size: "
<< maxMessageSize << std::endl;
}
}

View File

@ -1,10 +1,11 @@
#ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
#include "TaskManagement.h"
#include "../../internalError/InternalErrorReporterIF.h"
#include "../../ipc/MessageQueueIF.h"
#include "../../ipc/MessageQueueMessageIF.h"
#include "../../osal/FreeRTOS/TaskManagement.h"
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>

View File

@ -1,10 +1,12 @@
#include "Mutex.h"
#include "../../ipc/MutexFactory.h"
#include "../FreeRTOS/Mutex.h"
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why? -> one is on heap the other on bss/data
//TODO: Different variant than the lazy loading in QueueFactory.
//What's better and why? -> one is on heap the other on bss/data
//MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
MutexFactory* MutexFactory::factoryInstance = NULL;
MutexFactory* MutexFactory::factoryInstance = nullptr;
MutexFactory::MutexFactory() {
}
@ -13,7 +15,7 @@ MutexFactory::~MutexFactory() {
}
MutexFactory* MutexFactory::instance() {
if (factoryInstance == NULL){
if (factoryInstance == nullptr){
factoryInstance = new MutexFactory();
}
return MutexFactory::factoryInstance;

View File

@ -80,10 +80,18 @@ void PeriodicTask::taskFunctionality() {
object->performOperation();
}
checkMissedDeadline(xLastWakeTime, xPeriod);
vTaskDelayUntil(&xLastWakeTime, xPeriod);
#if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || \
tskKERNEL_VERSION_MAJOR > 10
BaseType_t wasDelayed = xTaskDelayUntil(&xLastWakeTime, xPeriod);
if(wasDelayed == pdFALSE) {
handleMissedDeadline();
}
#else
if(checkMissedDeadline(xLastWakeTime, xPeriod)) {
handleMissedDeadline();
}
vTaskDelayUntil(&xLastWakeTime, xPeriod);
#endif
}
}
@ -105,29 +113,6 @@ uint32_t PeriodicTask::getPeriodMs() const {
return period * 1000;
}
void PeriodicTask::checkMissedDeadline(const TickType_t xLastWakeTime,
const TickType_t interval) {
/* Check whether deadline was missed while also taking overflows
* into account. Drawing this on paper with a timeline helps to understand
* it. */
TickType_t currentTickCount = xTaskGetTickCount();
TickType_t timeToWake = xLastWakeTime + interval;
// Time to wake has not overflown.
if(timeToWake > xLastWakeTime) {
/* If the current time has overflown exclusively or the current
* tick count is simply larger than the time to wake, a deadline was
* missed */
if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) {
handleMissedDeadline();
}
}
/* Time to wake has overflown. A deadline was missed if the current time
* is larger than the time to wake */
else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) {
handleMissedDeadline();
}
}
TaskHandle_t PeriodicTask::getTaskHandle() {
return handle;
}

View File

@ -71,6 +71,7 @@ public:
TaskHandle_t getTaskHandle() override;
protected:
bool started;
TaskHandle_t handle;
@ -118,8 +119,6 @@ protected:
*/
void taskFunctionality(void);
void checkMissedDeadline(const TickType_t xLastWakeTime,
const TickType_t interval);
void handleMissedDeadline();
};

View File

@ -13,32 +13,30 @@ TaskFactory::~TaskFactory() {
TaskFactory* TaskFactory::instance() {
return TaskFactory::factoryInstance;
}
/***
* Keep in Mind that you need to call before this vTaskStartScheduler()!
* High taskPriority_ number means high priority.
*/
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_,
TaskPriority taskPriority_, TaskStackSize stackSize_,
TaskPeriod period_,
TaskDeadlineMissedFunction deadLineMissedFunction_) {
return (PeriodicTaskIF*) (new PeriodicTask(name_, taskPriority_, stackSize_,
period_, deadLineMissedFunction_));
return dynamic_cast<PeriodicTaskIF*>(new PeriodicTask(name_, taskPriority_,
stackSize_, period_, deadLineMissedFunction_));
}
/***
/**
* Keep in Mind that you need to call before this vTaskStartScheduler()!
*/
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,
TaskPriority taskPriority_, TaskStackSize stackSize_,
TaskPeriod period_,
TaskDeadlineMissedFunction deadLineMissedFunction_) {
return (FixedTimeslotTaskIF*) (new FixedTimeslotTask(name_, taskPriority_,
stackSize_, period_, deadLineMissedFunction_));
return dynamic_cast<FixedTimeslotTaskIF*>(new FixedTimeslotTask(name_,
taskPriority_,stackSize_, period_, deadLineMissedFunction_));
}
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
if (task == NULL) {
if (task == nullptr) {
//delete self
vTaskDelete(NULL);
vTaskDelete(nullptr);
return HasReturnvaluesIF::RETURN_OK;
} else {
//TODO not implemented

View File

@ -1,4 +1,4 @@
#include "../../osal/FreeRTOS/TaskManagement.h"
#include "TaskManagement.h"
void TaskManagement::vRequestContextSwitchFromTask() {
vTaskDelay(0);
@ -22,3 +22,4 @@ size_t TaskManagement::getTaskStackHighWatermark(
TaskHandle_t task) {
return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t);
}

View File

@ -3,10 +3,9 @@
#include "../../returnvalues/HasReturnvaluesIF.h"
extern "C" {
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
}
#include <cstdint>
/**
@ -27,38 +26,37 @@ enum class CallContext {
};
class TaskManagement {
public:
/**
* @brief In this function, a function dependant on the portmacro.h header
* function calls to request a context switch can be specified.
* This can be used if sending to the queue from an ISR caused a task
* to unblock and a context switch is required.
*/
static void requestContextSwitch(CallContext callContext);
namespace TaskManagement {
/**
* @brief In this function, a function dependant on the portmacro.h header
* function calls to request a context switch can be specified.
* This can be used if sending to the queue from an ISR caused a task
* to unblock and a context switch is required.
*/
void requestContextSwitch(CallContext callContext);
/**
* If task preemption in FreeRTOS is disabled, a context switch
* can be requested manually by calling this function.
*/
static void vRequestContextSwitchFromTask(void);
/**
* If task preemption in FreeRTOS is disabled, a context switch
* can be requested manually by calling this function.
*/
void vRequestContextSwitchFromTask(void);
/**
* @return The current task handle
*/
static TaskHandle_t getCurrentTaskHandle();
/**
* @return The current task handle
*/
TaskHandle_t getCurrentTaskHandle();
/**
* Get returns the minimum amount of remaining stack space in words
* that was a available to the task since the task started executing.
* Please note that the actual value in bytes depends
* on the stack depth type.
* E.g. on a 32 bit machine, a value of 200 means 800 bytes.
* @return Smallest value of stack remaining since the task was started in
* words.
*/
size_t getTaskStackHighWatermark(TaskHandle_t task = nullptr);
/**
* Get returns the minimum amount of remaining stack space in words
* that was a available to the task since the task started executing.
* Please note that the actual value in bytes depends
* on the stack depth type.
* E.g. on a 32 bit machine, a value of 200 means 800 bytes.
* @return Smallest value of stack remaining since the task was started in
* words.
*/
static size_t getTaskStackHighWatermark(
TaskHandle_t task = nullptr);
};
#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */

View File

@ -1,6 +1,6 @@
#include "Timekeeper.h"
#include "FreeRTOSConfig.h"
#include <FreeRTOSConfig.h>
Timekeeper * Timekeeper::myinstance = nullptr;

View File

@ -1,8 +1,10 @@
#include "../devicehandlers/DeviceCommunicationIF.h"
#include "rmapStructs.h"
#include "RMAP.h"
#include "rmapStructs.h"
#include "RMAPChannelIF.h"
#include <stddef.h>
#include "../devicehandlers/DeviceCommunicationIF.h"
#include <cstddef>
ReturnValue_t RMAP::reset(RMAPCookie* cookie) {
return cookie->getChannel()->reset();
@ -12,8 +14,8 @@ RMAP::RMAP(){
}
ReturnValue_t RMAP::sendWriteCommand(RMAPCookie *cookie, uint8_t* buffer,
uint32_t length) {
ReturnValue_t RMAP::sendWriteCommand(RMAPCookie *cookie, const uint8_t* buffer,
size_t length) {
uint8_t instruction;
if ((buffer == NULL) && (length != 0)) {
@ -61,7 +63,7 @@ ReturnValue_t RMAP::sendReadCommand(RMAPCookie *cookie, uint32_t expLength) {
}
ReturnValue_t RMAP::getReadReply(RMAPCookie *cookie, uint8_t **buffer,
uint32_t *size) {
size_t *size) {
if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL;
}

View File

@ -1,8 +1,8 @@
#ifndef RMAPpp_H_
#define RMAPpp_H_
#ifndef FSFW_RMAP_RMAP_H_
#define FSFW_RMAP_RMAP_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "RMAPCookie.h"
#include "../rmap/RMAPCookie.h"
//SHOULDTODO: clean up includes for RMAP, should be enough to include RMAP.h but right now it's quite chaotic...
@ -153,8 +153,8 @@ public:
* - @c COMMAND_NULLPOINTER datalen was != 0 but data was == NULL in write command
* - return codes of RMAPChannelIF::sendCommand()
*/
static ReturnValue_t sendWriteCommand(RMAPCookie *cookie, uint8_t* buffer,
uint32_t length);
static ReturnValue_t sendWriteCommand(RMAPCookie *cookie, const uint8_t* buffer,
size_t length);
/**
* get the reply to a write command
@ -204,7 +204,7 @@ public:
* - return codes of RMAPChannelIF::getReply()
*/
static ReturnValue_t getReadReply(RMAPCookie *cookie, uint8_t **buffer,
uint32_t *size);
size_t *size);
/**
* @see sendReadCommand()

View File

@ -1,8 +1,9 @@
#ifndef RMAPCHANNELIF_H_
#define RMAPCHANNELIF_H_
#ifndef FSFW_RMAP_RMAPCHANNELIF_H_
#define FSFW_RMAP_RMAPCHANNELIF_H_
#include "RMAPCookie.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef>
class RMAPChannelIF {
public:
@ -73,7 +74,7 @@ public:
* - @c NOT_SUPPORTED if you dont feel like implementing something...
*/
virtual ReturnValue_t sendCommand(RMAPCookie *cookie, uint8_t instruction,
uint8_t *data, uint32_t datalen)=0;
const uint8_t *data, size_t datalen)=0;
/**
* get the reply to an rmap command
@ -92,7 +93,7 @@ public:
* - all RMAP standard replies
*/
virtual ReturnValue_t getReply(RMAPCookie *cookie, uint8_t **databuffer,
uint32_t *len)=0;
size_t *len)=0;
/**
*
@ -112,4 +113,4 @@ public:
};
#endif /* RMAPCHANNELIF_H_ */
#endif /* FSFW_RMAP_RMAPCHANNELIF_H_ */

View File

@ -1,6 +1,6 @@
#include "RMAPChannelIF.h"
#include "RMAPCookie.h"
#include <stddef.h>
#include <cstddef>
RMAPCookie::RMAPCookie() {
@ -31,7 +31,8 @@ RMAPCookie::RMAPCookie() {
RMAPCookie::RMAPCookie(uint32_t set_address, uint8_t set_extended_address,
RMAPChannelIF *set_channel, uint8_t set_command_mask, uint32_t maxReplyLen) {
RMAPChannelIF *set_channel, uint8_t set_command_mask,
size_t maxReplyLen) {
this->header.dest_address = 0;
this->header.protocol = 0x01;
this->header.instruction = 0;
@ -93,11 +94,11 @@ RMAPCookie::~RMAPCookie() {
}
uint32_t RMAPCookie::getMaxReplyLen() const {
size_t RMAPCookie::getMaxReplyLen() const {
return maxReplyLen;
}
void RMAPCookie::setMaxReplyLen(uint32_t maxReplyLen) {
void RMAPCookie::setMaxReplyLen(size_t maxReplyLen) {
this->maxReplyLen = maxReplyLen;
}

View File

@ -1,8 +1,9 @@
#ifndef RMAPCOOKIE_H_
#define RMAPCOOKIE_H_
#ifndef FSFW_RMAP_RMAPCOOKIE_H_
#define FSFW_RMAP_RMAPCOOKIE_H_
#include "../devicehandlers/CookieIF.h"
#include "rmapStructs.h"
#include "../devicehandlers/CookieIF.h"
#include <cstddef>
class RMAPChannelIF;
@ -12,7 +13,8 @@ public:
RMAPCookie();
RMAPCookie(uint32_t set_address, uint8_t set_extended_address,
RMAPChannelIF *set_channel, uint8_t set_command_mask, uint32_t maxReplyLen = 0);
RMAPChannelIF *set_channel, uint8_t set_command_mask,
size_t maxReplyLen = 0);
virtual ~RMAPCookie();
@ -28,8 +30,8 @@ public:
void setCommandMask(uint8_t commandMask);
uint8_t getCommandMask();
uint32_t getMaxReplyLen() const;
void setMaxReplyLen(uint32_t maxReplyLen);
size_t getMaxReplyLen() const;
void setMaxReplyLen(size_t maxReplyLen);
uint16_t getTransactionIdentifier() const;
void setTransactionIdentifier(uint16_t id_);
@ -55,4 +57,4 @@ protected:
uint8_t dataCRC;
};
#endif /* RMAPCOOKIE_H_ */
#endif /* FSFW_RMAP_RMAPCOOKIE_H_ */

View File

@ -5,9 +5,9 @@
RmapDeviceCommunicationIF::~RmapDeviceCommunicationIF() {
}
ReturnValue_t RmapDeviceCommunicationIF::sendMessage(CookieIF* cookie,
uint8_t* data, uint32_t len) {
return RMAP::sendWriteCommand((RMAPCookie *) cookie, data, len);
ReturnValue_t RmapDeviceCommunicationIF::sendMessage(CookieIF *cookie,
const uint8_t * sendData, size_t sendLen) {
return RMAP::sendWriteCommand((RMAPCookie *) cookie, sendData, sendLen);
}
ReturnValue_t RmapDeviceCommunicationIF::getSendSuccess(CookieIF* cookie) {
@ -15,13 +15,13 @@ ReturnValue_t RmapDeviceCommunicationIF::getSendSuccess(CookieIF* cookie) {
}
ReturnValue_t RmapDeviceCommunicationIF::requestReceiveMessage(
CookieIF* cookie) {
CookieIF *cookie, size_t requestLen) {
return RMAP::sendReadCommand((RMAPCookie *) cookie,
((RMAPCookie *) cookie)->getMaxReplyLen());
}
ReturnValue_t RmapDeviceCommunicationIF::readReceivedMessage(CookieIF* cookie,
uint8_t** buffer, uint32_t* size) {
uint8_t** buffer, size_t * size) {
return RMAP::getReadReply((RMAPCookie *) cookie, buffer, size);
}

View File

@ -1,10 +1,11 @@
#ifndef MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_
#define MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_
#ifndef FSFW_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_
#define FSFW_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_
#include "../devicehandlers/DeviceCommunicationIF.h"
/**
* @brief This class is a implementation of a DeviceCommunicationIF for RMAP calls. It expects RMAPCookies or a derived class of RMAPCookies
* @brief This class is a implementation of a DeviceCommunicationIF for RMAP calls.
* It expects RMAPCookies or a derived class of RMAPCookies
*
* @details The open, close and reOpen calls are mission specific
* The open call might return any child of RMAPCookies
@ -16,65 +17,73 @@ class RmapDeviceCommunicationIF: public DeviceCommunicationIF {
public:
virtual ~RmapDeviceCommunicationIF();
/**
* This method is mission specific as the open call will return a mission specific cookie
*
* @param cookie A cookie, can be mission specific subclass of RMAP Cookie
* @param address The address of the RMAP Cookie
* @param maxReplyLen Maximum length of expected reply
* @return
*/
virtual ReturnValue_t open(CookieIF **cookie, uint32_t address,
uint32_t maxReplyLen) = 0;
/**
* Use an existing cookie to open a connection to a new DeviceCommunication.
* The previous connection must not be closed.
* If the returnvalue is not RETURN_OK, the cookie is unchanged and
* can be used with the previous connection.
*
* @brief Device specific initialization, using the cookie.
* @details
* The cookie is already prepared in the factory. If the communication
* interface needs to be set up in some way and requires cookie information,
* this can be performed in this function, which is called on device handler
* initialization.
* @param cookie
* @param address
* @param maxReplyLen
* @return
* @return -@c RETURN_OK if initialization was successfull
* - Everything else triggers failure event with returnvalue as parameter 1
*/
virtual ReturnValue_t reOpen(CookieIF *cookie, uint32_t address,
uint32_t maxReplyLen) = 0;
virtual ReturnValue_t initializeInterface(CookieIF * cookie) = 0;
/**
* Closing call of connection and memory free of cookie. Mission dependent call
* Called by DHB in the SEND_WRITE doSendWrite().
* This function is used to send data to the physical device
* by implementing and calling related drivers or wrapper functions.
* @param cookie
* @param data
* @param len
* @return -@c RETURN_OK for successfull send
* - Everything else triggers failure event with returnvalue as parameter 1
*/
virtual void close(CookieIF *cookie) = 0;
virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t * sendData,
size_t sendLen);
//SHOULDDO can data be const?
/**
*
*
* @param cookie Expects an RMAPCookie or derived from RMAPCookie Class
* @param data Data to be send
* @param len Length of the data to be send
* @return - Return codes of RMAP::sendWriteCommand()
* Called by DHB in the GET_WRITE doGetWrite().
* Get send confirmation that the data in sendMessage() was sent successfully.
* @param cookie
* @return -@c RETURN_OK if data was sent successfull
* - Everything else triggers falure event with returnvalue as parameter 1
*/
virtual ReturnValue_t sendMessage(CookieIF *cookie, uint8_t *data,
uint32_t len);
virtual ReturnValue_t getSendSuccess(CookieIF *cookie);
virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie);
/**
* Called by DHB in the SEND_WRITE doSendRead().
* It is assumed that it is always possible to request a reply
* from a device.
*
* @param cookie
* @return -@c RETURN_OK to confirm the request for data has been sent.
* -@c NO_READ_REQUEST if no request shall be made. readReceivedMessage()
* will not be called in the respective communication cycle.
* - Everything else triggers failure event with returnvalue as parameter 1
*/
virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen);
/**
* Called by DHB in the GET_WRITE doGetRead().
* This function is used to receive data from the physical device
* by implementing and calling related drivers or wrapper functions.
* @param cookie
* @param data
* @param len
* @return @c RETURN_OK for successfull receive
* - Everything else triggers failure event with returnvalue as parameter 1
*/
virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
uint32_t *size);
size_t *size);
virtual ReturnValue_t setAddress(CookieIF *cookie, uint32_t address);
virtual uint32_t getAddress(CookieIF *cookie);
virtual ReturnValue_t setParameter(CookieIF *cookie, uint32_t parameter);
virtual uint32_t getParameter(CookieIF *cookie);
ReturnValue_t setAddress(CookieIF* cookie,
uint32_t address);
uint32_t getAddress(CookieIF* cookie);
ReturnValue_t setParameter(CookieIF* cookie,
uint32_t parameter);
uint32_t getParameter(CookieIF* cookie);
};
#endif /* MISSION_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_ */
#endif /* FSFW_RMAP_RMAPDEVICECOMMUNICATIONINTERFACE_H_ */

View File

@ -1,7 +1,7 @@
#ifndef RMAPSTRUCTS_H_
#define RMAPSTRUCTS_H_
#ifndef FSFW_RMAP_RMAPSTRUCTS_H_
#define FSFW_RMAP_RMAPSTRUCTS_H_
#include <stdint.h>
#include <cstdint>
//SHOULDDO: having the defines within a namespace would be nice. Problem are the defines referencing the previous define, eg RMAP_COMMAND_WRITE
@ -95,4 +95,4 @@ struct rmap_write_reply_header {
}
#endif /* RMAPSTRUCTS_H_ */
#endif /* FSFW_RMAP_RMAPSTRUCTS_H_ */

View File

@ -1,29 +1,21 @@
#include "Subsystem.h"
#include "../health/HealthMessage.h"
#include "../objectmanager/ObjectManagerIF.h"
#include "../serialize/SerialArrayListAdapter.h"
#include "../serialize/SerialFixedArrayListAdapter.h"
#include "../serialize/SerializeElement.h"
#include "../serialize/SerialLinkedListAdapter.h"
#include "Subsystem.h"
#include <string>
Subsystem::Subsystem(object_id_t setObjectId, object_id_t parent,
uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables) :
SubsystemBase(setObjectId, parent, 0), isInTransition(false), childrenChangedHealth(
false), uptimeStartTable(0), currentTargetTable(), targetMode(
0), targetSubmode(SUBMODE_NONE), initialMode(0), currentSequenceIterator(), modeTables(
maxNumberOfTables), modeSequences(maxNumberOfSequences), IPCStore(
NULL)
#ifdef USE_MODESTORE
,modeStore(NULL)
#endif
{
SubsystemBase(setObjectId, parent, 0), isInTransition(false),
childrenChangedHealth(false), currentTargetTable(),
targetSubmode(SUBMODE_NONE), currentSequenceIterator(),
modeTables(maxNumberOfTables), modeSequences(maxNumberOfSequences) {}
}
Subsystem::~Subsystem() {
//Auto-generated destructor stub
}
Subsystem::~Subsystem() {}
ReturnValue_t Subsystem::checkSequence(HybridIterator<ModeListEntry> iter,
Mode_t fallbackSequence) {
@ -349,7 +341,8 @@ ReturnValue_t Subsystem::addSequence(ArrayList<ModeListEntry> *sequence,
ReturnValue_t result;
//Before initialize() is called, tables must not be checked as the children are not added yet.
//Before initialize() is called, tables must not be checked as the
//children are not added yet.
//Sequences added before are checked by initialize()
if (!preInit) {
result = checkSequence(
@ -374,7 +367,7 @@ ReturnValue_t Subsystem::addSequence(ArrayList<ModeListEntry> *sequence,
}
if (inStore) {
#ifdef USE_MODESTORE
#if FSFW_USE_MODESTORE == 1
result = modeStore->storeArray(sequence,
&(modeSequences.find(id)->entries.firstLinkedElement));
if (result != RETURN_OK) {
@ -395,8 +388,8 @@ ReturnValue_t Subsystem::addTable(ArrayList<ModeListEntry> *table, Mode_t id,
ReturnValue_t result;
//Before initialize() is called, tables must not be checked as the children are not added yet.
//Tables added before are checked by initialize()
//Before initialize() is called, tables must not be checked as the children
//are not added yet. Tables added before are checked by initialize()
if (!preInit) {
result = checkTable(
HybridIterator<ModeListEntry>(table->front(), table->back()));
@ -417,7 +410,7 @@ ReturnValue_t Subsystem::addTable(ArrayList<ModeListEntry> *table, Mode_t id,
}
if (inStore) {
#ifdef USE_MODESTORE
#if FSFW_USE_MODESTORE == 1
result = modeStore->storeArray(table,
&(modeTables.find(id)->firstLinkedElement));
if (result != RETURN_OK) {
@ -447,7 +440,7 @@ ReturnValue_t Subsystem::deleteSequence(Mode_t id) {
return ACCESS_DENIED;
}
#ifdef USE_MODESTORE
#if FSFW_USE_MODESTORE == 1
modeStore->deleteList(sequenceInfo->entries.firstLinkedElement);
#endif
modeSequences.erase(id);
@ -470,7 +463,7 @@ ReturnValue_t Subsystem::deleteTable(Mode_t id) {
return ACCESS_DENIED;
}
#ifdef USE_MODESTORE
#if FSFW_USE_MODESTORE == 1
modeStore->deleteList(pointer->firstLinkedElement);
#endif
modeSequences.erase(id);
@ -489,10 +482,10 @@ ReturnValue_t Subsystem::initialize() {
return RETURN_FAILED;
}
#ifdef USE_MODESTORE
#if FSFW_USE_MODESTORE == 1
modeStore = objectManager->get<ModeStoreIF>(objects::MODE_STORE);
if (modeStore == NULL) {
if (modeStore == nullptr) {
return RETURN_FAILED;
}
#endif
@ -587,12 +580,14 @@ void Subsystem::transitionFailed(ReturnValue_t failureCode,
triggerEvent(MODE_TRANSITION_FAILED, failureCode, parameter);
if (mode == targetMode) {
//already tried going back to the current mode
//go into fallback mode, also set current mode to fallback mode, so we come here at the next fail
//go into fallback mode, also set current mode to fallback mode,
//so we come here at the next fail
modeHelper.setForced(true);
ReturnValue_t result;
if ((result = checkSequence(getFallbackSequence(mode))) != RETURN_OK) {
triggerEvent(FALLBACK_FAILED, result, getFallbackSequence(mode));
isInTransition = false; //keep still and allow arbitrary mode commands to recover
//keep still and allow arbitrary mode commands to recover
isInTransition = false;
return;
}
mode = getFallbackSequence(mode);
@ -656,8 +651,10 @@ void Subsystem::cantKeepMode() {
modeHelper.setForced(true);
//already set the mode, so that we do not try to go back in our old mode when the transition fails
//already set the mode, so that we do not try to go back in our old mode
//when the transition fails
mode = getFallbackSequence(mode);
//SHOULDDO: We should store submodes for fallback sequence as well, otherwise we should get rid of submodes completely.
//SHOULDDO: We should store submodes for fallback sequence as well,
//otherwise we should get rid of submodes completely.
startTransition(mode, SUBMODE_NONE);
}

View File

@ -1,14 +1,21 @@
#ifndef SUBSYSTEM_H_
#define SUBSYSTEM_H_
#ifndef FSFW_SUBSYSTEM_SUBSYSTEM_H_
#define FSFW_SUBSYSTEM_SUBSYSTEM_H_
#include "SubsystemBase.h"
#include "modes/ModeDefinitions.h"
#include "../container/FixedArrayList.h"
#include "../container/FixedMap.h"
#include "../container/HybridIterator.h"
#include "../container/SinglyLinkedList.h"
#include "../serialize/SerialArrayListAdapter.h"
#include "modes/ModeDefinitions.h"
#include "SubsystemBase.h"
#include <FSFWConfig.h>
/**
* @brief TODO: documentation missing
* @details
*/
class Subsystem: public SubsystemBase, public HasModeSequenceIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::SUBSYSTEM;
@ -30,8 +37,13 @@ public:
static const ReturnValue_t TARGET_TABLE_NOT_REACHED = MAKE_RETURN_CODE(0xA1);
static const ReturnValue_t TABLE_CHECK_FAILED = MAKE_RETURN_CODE(0xA2);
/**
* TODO: Doc for constructor
* @param setObjectId
* @param parent
* @param maxNumberOfSequences
* @param maxNumberOfTables
*/
Subsystem(object_id_t setObjectId, object_id_t parent,
uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables);
virtual ~Subsystem();
@ -44,31 +56,12 @@ public:
void setInitialMode(Mode_t mode);
virtual ReturnValue_t initialize();
virtual ReturnValue_t initialize() override;
virtual ReturnValue_t checkObjectConnections();
virtual ReturnValue_t checkObjectConnections() override;
virtual MessageQueueId_t getSequenceCommandQueue() const;
virtual MessageQueueId_t getSequenceCommandQueue() const override;
/**
*
*
* IMPORTANT: Do not call on non existing sequence! Use existsSequence() first
*
* @param sequence
* @return
*/
ReturnValue_t checkSequence(Mode_t sequence);
/**
*
*
* IMPORTANT: Do not call on non existing sequence! Use existsSequence() first
*
* @param iter
* @return
*/
ReturnValue_t checkSequence(HybridIterator<ModeListEntry> iter, Mode_t fallbackSequence);
protected:
struct EntryPointer {
@ -92,15 +85,15 @@ protected:
bool childrenChangedHealth;
uint32_t uptimeStartTable;
uint32_t uptimeStartTable = 0;
HybridIterator<ModeListEntry> currentTargetTable;
Mode_t targetMode;
Mode_t targetMode = 0;
Submode_t targetSubmode;
Mode_t initialMode;
Mode_t initialMode = 0;
HybridIterator<ModeListEntry> currentSequenceIterator;
@ -108,10 +101,10 @@ protected:
FixedMap<Mode_t, SequenceInfo> modeSequences;
StorageManagerIF *IPCStore;
StorageManagerIF *IPCStore = nullptr;
#ifdef USE_MODESTORE
ModeStoreIF *modeStore;
#if FSFW_USE_MODESTORE == 1
ModeStoreIF *modeStore = nullptr;
#endif
bool existsModeSequence(Mode_t id);
@ -124,8 +117,6 @@ protected:
HybridIterator<ModeListEntry> getCurrentTable();
// void startSequence(Mode_t sequence);
/**
* DO NOT USE ON NON EXISTING SEQUENCE
*
@ -153,12 +144,29 @@ protected:
virtual void startTransition(Mode_t mode, Submode_t submode);
void sendSerializablesAsCommandMessage(Command_t command, SerializeIF **elements, uint8_t count);
void sendSerializablesAsCommandMessage(Command_t command,
SerializeIF **elements, uint8_t count);
void transitionFailed(ReturnValue_t failureCode, uint32_t parameter);
void cantKeepMode();
/**
* @brief Checks whether a sequence, identified by a mode.
* @param sequence
* @return
*/
ReturnValue_t checkSequence(Mode_t sequence);
/**
* @brief Checks whether a sequence, identified by a mode list iterator
* and a fallback sequence. Iterator needs to point to a valid
* sequence.
* @param iter
* @return
*/
ReturnValue_t checkSequence(HybridIterator<ModeListEntry> iter,
Mode_t fallbackSequence);
};
#endif /* SUBSYSTEM_H_ */
#endif /* FSFW_SUBSYSTEM_SUBSYSTEM_H_ */

View File

@ -1,15 +1,15 @@
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "SubsystemBase.h"
#include "../subsystem/SubsystemBase.h"
#include "../ipc/QueueFactory.h"
SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent,
Mode_t initialMode, uint16_t commandQueueDepth) :
SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE), childrenChangedMode(
false), commandsOutstanding(0), commandQueue(NULL), healthHelper(this,
setObjectId), modeHelper(this), parentId(parent) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth,
CommandMessage::MAX_MESSAGE_SIZE);
SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE),
childrenChangedMode(false),
commandQueue(QueueFactory::instance()->createMessageQueue(
commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE)),
healthHelper(this, setObjectId), modeHelper(this), parentId(parent) {
}
SubsystemBase::~SubsystemBase() {
@ -21,10 +21,11 @@ ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) {
ChildInfo info;
HasModesIF *child = objectManager->get<HasModesIF>(objectId);
//This is a rather ugly hack to have the changedHealth info for all children available. (needed for FOGs).
// This is a rather ugly hack to have the changedHealth info for all
// children available.
HasHealthIF* healthChild = objectManager->get<HasHealthIF>(objectId);
if (child == NULL) {
if (healthChild == NULL) {
if (child == nullptr) {
if (healthChild == nullptr) {
return CHILD_DOESNT_HAVE_MODES;
} else {
info.commandQueue = healthChild->getCommandQueue();
@ -38,14 +39,11 @@ ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) {
info.submode = SUBMODE_NONE;
info.healthChanged = false;
std::pair<std::map<object_id_t, ChildInfo>::iterator, bool> returnValue =
childrenMap.insert(
std::pair<object_id_t, ChildInfo>(objectId, info));
if (!(returnValue.second)) {
auto resultPair = childrenMap.emplace(objectId, info);
if (not resultPair.second) {
return COULD_NOT_INSERT_CHILD;
} else {
return RETURN_OK;
}
return RETURN_OK;
}
ReturnValue_t SubsystemBase::checkStateAgainstTable(
@ -76,15 +74,15 @@ ReturnValue_t SubsystemBase::checkStateAgainstTable(
return RETURN_OK;
}
void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submode_t targetSubmode) {
CommandMessage message;
void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter,
Submode_t targetSubmode) {
CommandMessage command;
std::map<object_id_t, ChildInfo>::iterator iter;
commandsOutstanding = 0;
for (; tableIter.value != NULL; ++tableIter) {
for (; tableIter.value != nullptr; ++tableIter) {
object_id_t object = tableIter.value->getObject();
if ((iter = childrenMap.find(object)) == childrenMap.end()) {
//illegal table entry, should only happen due to misconfigured mode table
@ -100,17 +98,17 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
if (healthHelper.healthTable->hasHealth(object)) {
if (healthHelper.healthTable->isFaulty(object)) {
ModeMessage::setModeMessage(&message,
ModeMessage::setModeMessage(&command,
ModeMessage::CMD_MODE_COMMAND, HasModesIF::MODE_OFF,
SUBMODE_NONE);
} else {
if (modeHelper.isForced()) {
ModeMessage::setModeMessage(&message,
ModeMessage::setModeMessage(&command,
ModeMessage::CMD_MODE_COMMAND_FORCED,
tableIter.value->getMode(), submodeToCommand);
} else {
if (healthHelper.healthTable->isCommandable(object)) {
ModeMessage::setModeMessage(&message,
ModeMessage::setModeMessage(&command,
ModeMessage::CMD_MODE_COMMAND,
tableIter.value->getMode(), submodeToCommand);
} else {
@ -119,17 +117,17 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
}
}
} else {
ModeMessage::setModeMessage(&message, ModeMessage::CMD_MODE_COMMAND,
ModeMessage::setModeMessage(&command, ModeMessage::CMD_MODE_COMMAND,
tableIter.value->getMode(), submodeToCommand);
}
if ((iter->second.mode == ModeMessage::getMode(&message))
&& (iter->second.submode == ModeMessage::getSubmode(&message))
if ((iter->second.mode == ModeMessage::getMode(&command))
&& (iter->second.submode == ModeMessage::getSubmode(&command))
&& !modeHelper.isForced()) {
continue; //don't send redundant mode commands (produces event spam), but still command if mode is forced to reach lower levels
}
ReturnValue_t result = commandQueue->sendMessage(
iter->second.commandQueue, &message);
iter->second.commandQueue, &command);
if (result == RETURN_OK) {
++commandsOutstanding;
}
@ -306,31 +304,31 @@ void SubsystemBase::announceMode(bool recursive) {
void SubsystemBase::checkCommandQueue() {
ReturnValue_t result;
CommandMessage message;
CommandMessage command;
for (result = commandQueue->receiveMessage(&message); result == RETURN_OK;
result = commandQueue->receiveMessage(&message)) {
for (result = commandQueue->receiveMessage(&command); result == RETURN_OK;
result = commandQueue->receiveMessage(&command)) {
result = healthHelper.handleHealthCommand(&message);
result = healthHelper.handleHealthCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = modeHelper.handleModeCommand(&message);
result = modeHelper.handleModeCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = handleModeReply(&message);
result = handleModeReply(&command);
if (result == RETURN_OK) {
continue;
}
result = handleCommandMessage(&message);
result = handleCommandMessage(&command);
if (result != RETURN_OK) {
CommandMessage reply;
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND,
message.getCommand());
command.getCommand());
replyToCommand(&reply);
}
}

View File

@ -1,5 +1,7 @@
#ifndef SUBSYSTEMBASE_H_
#define SUBSYSTEMBASE_H_
#ifndef FSFW_SUBSYSTEM_SUBSYSTEMBASE_H_
#define FSFW_SUBSYSTEM_SUBSYSTEMBASE_H_
#include "modes/HasModeSequenceIF.h"
#include "../container/HybridIterator.h"
#include "../health/HasHealthIF.h"
@ -7,11 +9,14 @@
#include "../modes/HasModesIF.h"
#include "../objectmanager/SystemObject.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "modes/HasModeSequenceIF.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../ipc/MessageQueueIF.h"
#include <map>
/**
* @defgroup subsystems Subsystem Objects
* Contains all Subsystem and Assemblies
*/
class SubsystemBase: public SystemObject,
public HasModesIF,
public HasHealthIF,
@ -30,17 +35,17 @@ public:
Mode_t initialMode = 0, uint16_t commandQueueDepth = 8);
virtual ~SubsystemBase();
virtual MessageQueueId_t getCommandQueue() const;
virtual MessageQueueId_t getCommandQueue() const override;
ReturnValue_t registerChild(object_id_t objectId);
virtual ReturnValue_t initialize();
virtual ReturnValue_t initialize() override;
virtual ReturnValue_t performOperation(uint8_t opCode);
virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual ReturnValue_t setHealth(HealthState health);
virtual ReturnValue_t setHealth(HealthState health) override;
virtual HasHealthIF::HealthState getHealth();
virtual HasHealthIF::HealthState getHealth() override;
protected:
struct ChildInfo {
@ -58,9 +63,9 @@ protected:
/**
* Always check this against <=0, so you are robust against too many replies
*/
int32_t commandsOutstanding;
int32_t commandsOutstanding = 0;
MessageQueueIF* commandQueue;
MessageQueueIF* commandQueue = nullptr;
HealthHelper healthHelper;
@ -122,4 +127,4 @@ protected:
virtual void modeChanged();
};
#endif /* SUBSYSTEMBASE_H_ */
#endif /* FSFW_SUBSYSTEM_SUBSYSTEMBASE_H_ */

View File

@ -1,22 +1,19 @@
#ifndef MODEDEFINITIONS_H_
#define MODEDEFINITIONS_H_
#ifndef FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
#define FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
#include "../../modes/HasModesIF.h"
#include "../../objectmanager/SystemObjectIF.h"
#include "../../serialize/SerializeIF.h"
#include "../../serialize/SerialLinkedListAdapter.h"
class ModeListEntry: public SerializeIF, public LinkedElement<ModeListEntry> {
public:
ModeListEntry() :
LinkedElement<ModeListEntry>(this), value1(0), value2(0), value3(0), value4(
0) {
ModeListEntry(): LinkedElement<ModeListEntry>(this) {}
}
uint32_t value1;
uint32_t value2;
uint8_t value3;
uint8_t value4;
uint32_t value1 = 0;
uint32_t value2 = 0;
uint8_t value3 = 0;
uint8_t value4 = 0;
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const {
@ -149,4 +146,4 @@ public:
}
};
#endif //MODEDEFINITIONS_H_
#endif /* FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_ */

View File

@ -1,8 +1,7 @@
#include "../../objectmanager/ObjectManagerIF.h"
#include "../../objectmanager/ObjectManagerIF.h"
#include "ModeSequenceMessage.h"
#include "../../objectmanager/ObjectManagerIF.h"
#include "../../storagemanager/StorageManagerIF.h"
#include "ModeSequenceMessage.h"
void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
Command_t command, Mode_t sequence, store_address_t storeAddress) {
@ -11,25 +10,12 @@ void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
message->setParameter2(sequence);
}
//void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
// Command_t command, ModeTableId_t table, store_address_t storeAddress) {
// message->setCommand(command);
// message->setParameter(storeAddress.raw);
// message->setParameter2(table);
//}
void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
Command_t command, Mode_t sequence) {
message->setCommand(command);
message->setParameter2(sequence);
}
//void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
// Command_t command, ModeTableId_t table) {
// message->setCommand(command);
// message->setParameter2(table);
//}
void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
Command_t command, store_address_t storeAddress) {
message->setCommand(command);
@ -63,9 +49,10 @@ void ModeSequenceMessage::clear(CommandMessage *message) {
case SEQUENCE_LIST:
case TABLE_LIST:
case TABLE:
case SEQUENCE:{
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore != NULL){
case SEQUENCE: {
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
objects::IPC_STORE);
if (ipcStore != nullptr){
ipcStore->deleteData(ModeSequenceMessage::getStoreAddress(message));
}
}

View File

@ -1,9 +1,11 @@
#ifndef MODESEQUENCEMESSAGE_H_
#define MODESEQUENCEMESSAGE_H_
#ifndef FSFW_SUBSYSTEM_MODES_MODESEQUENCEMESSAGE_H_
#define FSFW_SUBSYSTEM_MODES_MODESEQUENCEMESSAGE_H_
#include "ModeDefinitions.h"
#include "../../ipc/CommandMessage.h"
#include "../../storagemanager/StorageManagerIF.h"
#include "ModeDefinitions.h"
class ModeSequenceMessage {
public:
@ -45,4 +47,4 @@ private:
ModeSequenceMessage();
};
#endif /* MODESEQUENCEMESSAGE_H_ */
#endif /* FSFW_SUBSYSTEM_MODES_MODESEQUENCEMESSAGE_H_ */

View File

@ -1,6 +1,8 @@
#include "ModeStore.h"
#ifdef USE_MODESTORE
// todo: I think some parts are deprecated. If this is used, the define
// USE_MODESTORE could be part of the new FSFWConfig.h file.
#if FSFW_USE_MODESTORE == 1
ModeStore::ModeStore(object_id_t objectId, uint32_t slots) :
SystemObject(objectId), store(slots), emptySlot(store.front()) {

View File

@ -1,12 +1,15 @@
#ifndef MODESTORE_H_
#define MODESTORE_H_
#ifndef FSFW_SUBSYSTEM_MODES_MODESTORE_H_
#define FSFW_SUBSYSTEM_MODES_MODESTORE_H_
#ifdef USE_MODESTORE
#include <FSFWConfig.h>
#if FSFW_USE_MODESTORE == 1
#include "ModeStoreIF.h"
#include "../../container/ArrayList.h"
#include "../../container/SinglyLinkedList.h"
#include "../../objectmanager/SystemObject.h"
#include "ModeStoreIF.h"
class ModeStore: public ModeStoreIF, public SystemObject {
public:
@ -41,5 +44,5 @@ private:
#endif
#endif /* MODESTORE_H_ */
#endif /* FSFW_SUBSYSTEM_MODES_MODESTORE_H_ */

View File

@ -1,12 +1,15 @@
#ifndef MODESTOREIF_H_
#define MODESTOREIF_H_
#ifdef USE_MODESTORE
#include <FSFWConfig.h>
#if FSFW_USE_MODESTORE == 1
#include "ModeDefinitions.h"
#include "../../container/ArrayList.h"
#include "../../container/SinglyLinkedList.h"
#include "../../returnvalues/HasReturnvaluesIF.h"
#include "ModeDefinitions.h"
class ModeStoreIF {
public:

View File

@ -1,16 +1,32 @@
#ifndef FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_
#define FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_
#include "../objectmanager/ObjectManagerIF.h"
#include "PeriodicTaskIF.h"
#include "../objectmanager/ObjectManagerIF.h"
/**
* Following the same principle as the base class IF. This is the interface for a Fixed timeslot task
* @brief Following the same principle as the base class IF.
* This is the interface for a Fixed timeslot task
*/
class FixedTimeslotTaskIF : public PeriodicTaskIF {
public:
virtual ~FixedTimeslotTaskIF() {}
virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) = 0;
/**
* Add an object with a slot time and the execution step to the task.
* The execution step will be passed to the object (e.g. as an operation
* code in #performOperation)
* @param componentId
* @param slotTimeMs
* @param executionStep
* @return
*/
virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep) = 0;
/**
* Check whether the sequence is valid and perform all other required
* initialization steps which are needed after task creation
*/
virtual ReturnValue_t checkSequence() const = 0;
};

View File

@ -1,10 +1,11 @@
#ifndef FRAMEWORK_TASKS_TASKFACTORY_H_
#define FRAMEWORK_TASKS_TASKFACTORY_H_
#ifndef FSFW_TASKS_TASKFACTORY_H_
#define FSFW_TASKS_TASKFACTORY_H_
#include <stdlib.h>
#include "FixedTimeslotTaskIF.h"
#include "Typedef.h"
#include <cstdlib>
/**
* Singleton Class that produces Tasks.
*/
@ -48,10 +49,11 @@ public:
/**
* Function to be called to delete a task
* @param task The pointer to the task that shall be deleted, NULL specifies current Task
* @param task The pointer to the task that shall be deleted,
* nullptr specifies current Task
* @return Success of deletion
*/
static ReturnValue_t deleteTask(PeriodicTaskIF* task = NULL);
static ReturnValue_t deleteTask(PeriodicTaskIF* task = nullptr);
/**
* Function to be called to delay current task
@ -69,4 +71,4 @@ private:
};
#endif /* FRAMEWORK_TASKS_TASKFACTORY_H_ */
#endif /* FSFW_TASKS_TASKFACTORY_H_ */

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_TIMEMANAGER_CLOCK_H_
#define FRAMEWORK_TIMEMANAGER_CLOCK_H_
#ifndef FSFW_TIMEMANAGER_CLOCK_H_
#define FSFW_TIMEMANAGER_CLOCK_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../ipc/MutexHelper.h"
@ -151,4 +151,4 @@ private:
};
#endif /* FRAMEWORK_TIMEMANAGER_CLOCK_H_ */
#endif /* FSFW_TIMEMANAGER_CLOCK_H_ */

View File

@ -1,8 +1,8 @@
#include "IntTestMq.h"
#include "../UnittDefinitions.h"
#include "../../ipc/MessageQueueIF.h"
#include "../../ipc/QueueFactory.h"
#include "../../../ipc/MessageQueueIF.h"
#include "../../../ipc/QueueFactory.h"
#include <array>

View File

@ -1,6 +1,6 @@
#include "IntTestMutex.h"
#include "../../ipc/MutexFactory.h"
#include "../../../ipc/MutexFactory.h"
#include "../UnittDefinitions.h"
#if defined(hosted)

View File

@ -1,9 +1,9 @@
#include "IntTestSemaphore.h"
#include "../UnittDefinitions.h"
#include "../../tasks/SemaphoreFactory.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../timemanager/Stopwatch.h"
#include "../../../tasks/SemaphoreFactory.h"
#include "../../../serviceinterface/ServiceInterfaceStream.h"
#include "../../../timemanager/Stopwatch.h"
void testsemaph::testBinSemaph() {

View File

@ -1,8 +1,9 @@
#include "IntTestSerialization.h"
#include "../UnittDefinitions.h"
#include "../../serialize/SerializeElement.h"
#include "../../serialize/SerialBufferAdapter.h"
#include "../../serialize/SerializeIF.h"
#include "../../../serialize/SerializeElement.h"
#include "../../../serialize/SerialBufferAdapter.h"
#include "../../../serialize/SerializeIF.h"
#include <array>

View File

@ -1,7 +1,7 @@
#ifndef FSFW_UNITTEST_INTERNAL_INTTESTSERIALIZATION_H_
#define FSFW_UNITTEST_INTERNAL_INTTESTSERIALIZATION_H_
#include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../../returnvalues/HasReturnvaluesIF.h"
#include <array>
namespace testserialize {

View File

@ -29,13 +29,11 @@
//! additional output which requires the translation files translateObjects
//! and translateEvents (and their compiles source files)
#if FSFW_OBJ_EVENT_TRANSLATION == 1
#define FSFW_DEBUG_OUTPUT 1
//! Specify whether info events are printed too.
#define FSFW_DEBUG_INFO 1
#define FSFW_DEBUG_INFO 1
#include <translateObjects.h>
#include <translateEvents.h>
#else
#define FSFW_DEBUG_OUTPUT 0
#endif
//! When using the newlib nano library, C99 support for stdio facilities