Merge remote-tracking branch 'upstream/development' into development

This commit is contained in:
Robin Müller 2020-12-16 12:00:59 +01:00
commit 086cbe1e39
68 changed files with 519 additions and 2734 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

@ -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) {
#if FSFW_DEBUG_OUTPUT == 1
#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);
#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,5 +1,5 @@
#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>
@ -8,6 +8,34 @@ class FreeRTOSTaskIF {
public:
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);
#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,28 +26,27 @@ enum class CallContext {
};
class TaskManagement {
public:
/**
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.
*/
static void requestContextSwitch(CallContext callContext);
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);
void vRequestContextSwitchFromTask(void);
/**
/**
* @return The current task handle
*/
static TaskHandle_t getCurrentTaskHandle();
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
@ -57,8 +55,8 @@ public:
* @return Smallest value of stack remaining since the task was started in
* words.
*/
static size_t getTaskStackHighWatermark(
TaskHandle_t task = nullptr);
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

@ -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
#include <translateObjects.h>
#include <translateEvents.h>
#else
#define FSFW_DEBUG_OUTPUT 0
#endif
//! When using the newlib nano library, C99 support for stdio facilities