Merge branch 'development' into mueller/doc-update

This commit is contained in:
Steffen Gaisser 2020-12-22 15:29:05 +01:00
commit afad130918
223 changed files with 4579 additions and 4721 deletions

View File

@ -15,10 +15,50 @@ a C file without issues
- The same is possible for the event reporting service (PUS5)
- PUS Health Service added, which allows to command and retrieve health via PUS packets
### EnhancedControllerBase
- New base class for a controller which also implements HasActionsIF and HasLocalDataPoolIF
### Local Pool
- Interface of LocalPools has changed. LocalPool is not a template anymore. Instead the size and bucket number of the pools per page and the number of pages are passed to the ctor instead of two ctor arguments and a template parameter
### Parameter Service
- The API of the parameter service has been changed to prevent inconsistencies
between documentation and actual code and to clarify usage.
- The parameter ID now consists of:
1. Domain ID (1 byte)
2. Unique Identifier (1 byte)
3. Linear Index (2 bytes)
The linear index can be used for arrays as well as matrices.
The parameter load command now explicitely expects the ECSS PTC and PFC
information as well as the rows and column number. Rows and column will
default to one, which is equivalent to one scalar parameter (the most
important use-case)
### File System Interface
- A new interfaces specifies the functions for a software object which exposes the file system of a given hardware to use message based file handling (e.g. PUS commanding)
### Internal Error Reporter
- The new internal error reporter uses the local data pools. The pool IDs for
the exisiting three error values and the new error set will be hardcoded for
now, the the constructor for the internal error reporter just takes an object
ID for now.
### Device Handler Base
- There is an additional `PERFORM_OPERATION` step for the device handler base. It is important
that DHB users adapt their polling sequence tables to perform this step. This steps allows for aclear distinction between operation and communication steps
- setNormalDatapoolEntriesInvalid is not an abstract method and a default implementation was provided
- getTransitionDelayMs is now an abstract method
### DeviceHandlerIF
- Typo for UNKNOWN_DEVICE_REPLY
### Events

143
CMakeLists.txt Normal file
View File

@ -0,0 +1,143 @@
cmake_minimum_required(VERSION 3.13)
set(LIB_FSFW_NAME fsfw)
add_library(${LIB_FSFW_NAME})
set_property(CACHE OS_FSFW PROPERTY STRINGS host linux rtems freertos)
if(NOT OS_FSFW)
message(STATUS "No OS for FSFW via OS_FSFW set. Assuming host OS")
# Assume host OS and autodetermine from OS_FSFW
if(UNIX)
set(OS_FSFW "linux"
CACHE STRING
"OS abstraction layer used in the FSFW"
)
elseif(WIN32)
set(OS_FSFW "host"
CACHE STRING "OS abstraction layer used in the FSFW"
)
endif()
endif()
if(${OS_FSFW} STREQUAL host)
set(OS_FSFW_NAME "Host")
elseif(${OS_FSFW} STREQUAL linux)
set(OS_FSFW_NAME "Linux")
elseif(${OS_FSFW} STREQUAL freertos)
set(OS_FSFW_NAME "FreeRTOS")
target_link_libraries(${LIB_FSFW_NAME} ${LIB_OS_NAME})
elseif(${OS_FSFW} STREQUAL rtems)
set(OS_FSFW_NAME "RTEMS")
else()
message(WARNING
"Invalid operating system for FSFW specified! Setting to host.."
)
set(OS_FSFW_NAME "Host")
set(OS_FSFW "host")
endif()
message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system.")
# Options to exclude parts of the FSFW from compilation.
option(FSFW_USE_RMAP "Compile with RMAP" ON)
option(FSFW_USE_DATALINKLAYER "Compile with Data Link Layer" ON)
add_subdirectory(action)
add_subdirectory(container)
add_subdirectory(controller)
add_subdirectory(coordinates)
if(FSFW_USE_DATALINKLAYER)
add_subdirectory(datalinklayer)
endif()
add_subdirectory(datapool)
add_subdirectory(datapoollocal)
add_subdirectory(housekeeping)
add_subdirectory(devicehandlers)
add_subdirectory(events)
add_subdirectory(fdir)
add_subdirectory(globalfunctions)
add_subdirectory(health)
add_subdirectory(internalError)
add_subdirectory(ipc)
add_subdirectory(memory)
add_subdirectory(modes)
add_subdirectory(monitoring)
add_subdirectory(objectmanager)
add_subdirectory(osal)
add_subdirectory(parameters)
add_subdirectory(power)
add_subdirectory(pus)
if(FSFW_USE_RMAP)
add_subdirectory(rmap)
endif()
add_subdirectory(serialize)
add_subdirectory(serviceinterface)
add_subdirectory(storagemanager)
add_subdirectory(subsystem)
add_subdirectory(tasks)
add_subdirectory(tcdistribution)
add_subdirectory(thermal)
add_subdirectory(timemanager)
add_subdirectory(tmstorage)
add_subdirectory(tmtcpacket)
add_subdirectory(tmtcservices)
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it.
# If this is not given, we include the default configuration and emit a warning.
if(NOT FSFW_CONFIG_PATH)
message(WARNING "Flight Software Framework configuration path not set!")
message(WARNING "Setting default configuration!")
add_subdirectory(defaultcfg/fsfwconfig)
endif()
# FSFW might be part of a possibly complicated folder structure, so we
# extract the absolute path of the fsfwconfig folder.
if(IS_ABSOLUTE ${FSFW_CONFIG_PATH})
set(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH})
else()
get_filename_component(FSFW_CONFIG_PATH_ABSOLUTE
${FSFW_CONFIG_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}
)
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
set(WARNING_FLAGS
-Wall
-Wextra
-Wshadow=local
-Wimplicit-fallthrough=1
-Wno-unused-parameter
-Wno-psabi
)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(COMPILER_FLAGS "/permissive-")
endif()
# Required include paths to compile the FSFW
target_include_directories(${LIB_FSFW_NAME} INTERFACE
${CMAKE_SOURCE_DIR}
${FSFW_CONFIG_PATH_ABSOLUTE}
)
# Includes path required to compile FSFW itself as well
# We assume that the fsfwconfig folder uses include relative to the project
# root here!
target_include_directories(${LIB_FSFW_NAME} PRIVATE
${CMAKE_SOURCE_DIR}
${FSFW_CONFIG_PATH_ABSOLUTE}
)
# Machine specific options can be set with the ABI_FLAGS variable.
target_compile_options(${LIB_FSFW_NAME} PRIVATE
${WARNING_FLAGS}
${COMPILER_FLAGS}
${ABI_FLAGS}
)

7
action/CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
ActionHelper.cpp
ActionMessage.cpp
CommandActionHelper.cpp
SimpleActionHelper.cpp
)

5
container/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
SharedRingBuffer.cpp
SimpleRingBuffer.cpp
)

View File

@ -0,0 +1,4 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
ControllerBase.cpp
)

View File

@ -1,16 +1,16 @@
#include "../subsystem/SubsystemBase.h"
#include "ControllerBase.h"
#include "../subsystem/SubsystemBase.h"
#include "../ipc/QueueFactory.h"
#include "../action/HasActionsIF.h"
ControllerBase::ControllerBase(uint32_t setObjectId, uint32_t parentId,
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth) :
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), submode(
SUBMODE_NONE), commandQueue(NULL), modeHelper(
this), healthHelper(this, setObjectId),hkSwitcher(this),executingTask(NULL) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
submode(SUBMODE_NONE), modeHelper(this),
healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth);
}
ControllerBase::~ControllerBase() {
@ -24,9 +24,9 @@ ReturnValue_t ControllerBase::initialize() {
}
MessageQueueId_t parentQueue = 0;
if (parentId != 0) {
if (parentId != objects::NO_OBJECT) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == NULL) {
if (parent == nullptr) {
return RETURN_FAILED;
}
parentQueue = parent->getCommandQueue();
@ -44,10 +44,6 @@ ReturnValue_t ControllerBase::initialize() {
return result;
}
result = hkSwitcher.initialize();
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
@ -56,26 +52,27 @@ MessageQueueId_t ControllerBase::getCommandQueue() const {
}
void ControllerBase::handleQueue() {
CommandMessage message;
ReturnValue_t result;
for (result = commandQueue->receiveMessage(&message); result == RETURN_OK;
result = commandQueue->receiveMessage(&message)) {
CommandMessage command;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (result = commandQueue->receiveMessage(&command);
result == RETURN_OK;
result = commandQueue->receiveMessage(&command)) {
result = modeHelper.handleModeCommand(&message);
result = modeHelper.handleModeCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = healthHelper.handleHealthCommand(&message);
result = healthHelper.handleHealthCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = handleCommandMessage(&message);
result = handleCommandMessage(&command);
if (result == RETURN_OK) {
continue;
}
message.setToUnknownCommand();
commandQueue->reply(&message);
command.setToUnknownCommand();
commandQueue->reply(&command);
}
}
@ -106,7 +103,6 @@ void ControllerBase::announceMode(bool recursive) {
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
handleQueue();
hkSwitcher.performOperation();
performControlOperation();
return RETURN_OK;
}
@ -135,3 +131,7 @@ void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
}
ReturnValue_t ControllerBase::initializeAfterTaskCreation() {
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,5 +1,5 @@
#ifndef CONTROLLERBASE_H_
#define CONTROLLERBASE_H_
#ifndef FSFW_CONTROLLER_CONTROLLERBASE_H_
#define FSFW_CONTROLLER_CONTROLLERBASE_H_
#include "../health/HasHealthIF.h"
#include "../health/HealthHelper.h"
@ -7,73 +7,88 @@
#include "../modes/ModeHelper.h"
#include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../tasks/PeriodicTaskIF.h"
#include "../datapool/HkSwitchHelper.h"
/**
* @brief Generic base class for controller classes
* @details
* Implements common interfaces for controllers, which generally have
* a mode and a health state. This avoids boilerplate code.
*/
class ControllerBase: public HasModesIF,
public HasHealthIF,
public ExecutableObjectIF,
public SystemObject,
public HasReturnvaluesIF {
public:
static const Mode_t MODE_NORMAL = 2;
ControllerBase(uint32_t setObjectId, uint32_t parentId,
ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth = 3);
virtual ~ControllerBase();
ReturnValue_t initialize();
/** SystemObject override */
virtual ReturnValue_t initialize() override;
virtual MessageQueueId_t getCommandQueue() const;
virtual MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t performOperation(uint8_t opCode);
virtual ReturnValue_t setHealth(HealthState health);
virtual HasHealthIF::HealthState getHealth();
/**
* Implementation of ExecutableObjectIF function
*
* Used to setup the reference of the task, that executes this component
* @param task_ Pointer to the taskIF of this task
*/
virtual void setTaskIF(PeriodicTaskIF* task_);
/** HasHealthIF overrides */
virtual ReturnValue_t setHealth(HealthState health) override;
virtual HasHealthIF::HealthState getHealth() override;
/** ExecutableObjectIF overrides */
virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual void setTaskIF(PeriodicTaskIF* task) override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
protected:
const uint32_t parentId;
/**
* Implemented by child class. Handle command messages which are not
* mode or health messages.
* @param message
* @return
*/
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
/**
* Periodic helper, implemented by child class.
*/
virtual void performControlOperation() = 0;
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) = 0;
const object_id_t parentId;
Mode_t mode;
Submode_t submode;
MessageQueueIF* commandQueue;
MessageQueueIF* commandQueue = nullptr;
ModeHelper modeHelper;
HealthHelper healthHelper;
HkSwitchHelper hkSwitcher;
/**
* Pointer to the task which executes this component, is invalid before setTaskIF was called.
* Pointer to the task which executes this component,
* is invalid before setTaskIF was called.
*/
PeriodicTaskIF* executingTask;
PeriodicTaskIF* executingTask = nullptr;
void handleQueue();
/** Handle mode and health messages */
virtual void handleQueue();
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
virtual void performControlOperation() = 0;
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) = 0;
/** Mode helpers */
virtual void modeChanged(Mode_t mode, Submode_t submode);
virtual void startTransition(Mode_t mode, Submode_t submode);
virtual void getMode(Mode_t *mode, Submode_t *submode);
virtual void setToExternalControl();
virtual void announceMode(bool recursive);
/** HK helpers */
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
};
#endif /* CONTROLLERBASE_H_ */
#endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */

View File

@ -0,0 +1,113 @@
#include "ExtendedControllerBase.h"
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId,
object_id_t parentId, size_t commandQueueDepth):
ControllerBase(objectId, parentId, commandQueueDepth),
localPoolManager(this, commandQueue),
actionHelper(this, commandQueue) {
}
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t *data, size_t size) {
// needs to be overriden and implemented by child class.
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t ExtendedControllerBase::initializeLocalDataPool(
LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
// needs to be overriden and implemented by child class.
return HasReturnvaluesIF::RETURN_OK;
}
object_id_t ExtendedControllerBase::getObjectId() const {
return SystemObject::getObjectId();
}
LocalDataPoolManager* ExtendedControllerBase::getHkManagerHandle() {
return &localPoolManager;
}
uint32_t ExtendedControllerBase::getPeriodicOperationFrequency() const {
return this->executingTask->getPeriodMs();
}
ReturnValue_t ExtendedControllerBase::handleCommandMessage(
CommandMessage *message) {
ReturnValue_t result = actionHelper.handleActionMessage(message);
if(result == HasReturnvaluesIF::RETURN_OK) {
return result;
}
return localPoolManager.handleHousekeepingMessage(message);
}
void ExtendedControllerBase::handleQueue() {
CommandMessage command;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (result = commandQueue->receiveMessage(&command);
result == RETURN_OK;
result = commandQueue->receiveMessage(&command)) {
result = actionHelper.handleActionMessage(&command);
if (result == RETURN_OK) {
continue;
}
result = modeHelper.handleModeCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = healthHelper.handleHealthCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = localPoolManager.handleHousekeepingMessage(&command);
if (result == RETURN_OK) {
continue;
}
result = handleCommandMessage(&command);
if (result == RETURN_OK) {
continue;
}
command.setToUnknownCommand();
commandQueue->reply(&command);
}
}
ReturnValue_t ExtendedControllerBase::initialize() {
ReturnValue_t result = ControllerBase::initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return localPoolManager.initialize(commandQueue);
}
ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
return localPoolManager.initializeAfterTaskCreation();
}
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
handleQueue();
localPoolManager.performHkOperation();
performControlOperation();
return RETURN_OK;
}
MessageQueueId_t ExtendedControllerBase::getCommandQueue() const {
return commandQueue->getId();
}
LocalPoolDataSetBase* ExtendedControllerBase::getDataSetHandle(sid_t sid) {
sif::warning << "ExtendedControllerBase::getDataSetHandle: No child "
<< " implementation provided, returning nullptr!" << std::endl;
return nullptr;
}

View File

@ -0,0 +1,72 @@
#ifndef FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_
#define FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_
#include "ControllerBase.h"
#include "../action/HasActionsIF.h"
#include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../action/ActionHelper.h"
#include "../datapoollocal/LocalDataPoolManager.h"
/**
* @brief Extendes the basic ControllerBase with the common components
* HasActionsIF for commandability and HasLocalDataPoolIF to keep
* a pool of local data pool variables.
* @details
* Default implementations required for the interfaces will be empty and have
* to be implemented by child class.
*/
class ExtendedControllerBase: public ControllerBase,
public HasActionsIF,
public HasLocalDataPoolIF {
public:
ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
size_t commandQueueDepth = 3);
/** SystemObjectIF overrides */
virtual ReturnValue_t initialize() override;
virtual MessageQueueId_t getCommandQueue() const override;
/** ExecutableObjectIF overrides */
virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
protected:
LocalDataPoolManager localPoolManager;
ActionHelper actionHelper;
/**
* Implemented by child class. Handle all command messages which are
* not health, mode, action or housekeeping messages.
* @param message
* @return
*/
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
/**
* Periodic helper from ControllerBase, implemented by child class.
*/
virtual void performControlOperation() = 0;
/** Handle the four messages mentioned above */
void handleQueue() override;
/** HasActionsIF overrides */
virtual ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data,
size_t size) override;
/** HasLocalDatapoolIF overrides */
virtual object_id_t getObjectId() const override;
virtual ReturnValue_t initializeLocalDataPool(
LocalDataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
virtual LocalDataPoolManager* getHkManagerHandle() override;
virtual uint32_t getPeriodicOperationFrequency() const override;
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
};
#endif /* FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_ */

View File

@ -0,0 +1,5 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
CoordinateTransformations.cpp
Sgp4Propagator.cpp
)

View File

@ -1,7 +1,9 @@
#ifndef SGP4PROPAGATOR_H_
#define SGP4PROPAGATOR_H_
#ifndef WIN32
#include <sys/time.h>
#endif
#include "../contrib/sgp4/sgp4unit.h"
#include "../returnvalues/HasReturnvaluesIF.h"

View File

@ -0,0 +1,12 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
Clcw.cpp
DataLinkLayer.cpp
Farm1StateLockout.cpp
Farm1StateOpen.cpp
Farm1StateWait.cpp
MapPacketExtraction.cpp
TcTransferFrame.cpp
TcTransferFrameLocal.cpp
VirtualChannelReception.cpp
)

View File

@ -1,10 +1,3 @@
/**
* @file MapPacketExtraction.cpp
* @brief This file defines the MapPacketExtraction class.
* @date 26.03.2013
* @author baetz
*/
#include "MapPacketExtraction.h"
#include "../ipc/QueueFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
@ -12,14 +5,14 @@
#include "../tmtcpacket/SpacePacketBase.h"
#include "../tmtcservices/AcceptsTelecommandsIF.h"
#include "../tmtcservices/TmTcMessage.h"
#include <string.h>
#include <cstring>
MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
object_id_t setPacketDestination) :
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition(
packetBuffer), packetDestination(setPacketDestination), packetStore(
NULL), tcQueueId(MessageQueueIF::NO_QUEUE) {
memset(packetBuffer, 0, sizeof(packetBuffer));
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId),
bufferPosition(packetBuffer), packetDestination(setPacketDestination),
tcQueueId(MessageQueueIF::NO_QUEUE) {
std::memset(packetBuffer, 0, sizeof(packetBuffer));
}
ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) {

View File

@ -1,12 +1,5 @@
/**
* @file MapPacketExtraction.h
* @brief This file defines the MapPacketExtraction class.
* @date 26.03.2013
* @author baetz
*/
#ifndef MAPPACKETEXTRACTION_H_
#define MAPPACKETEXTRACTION_H_
#ifndef FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_
#define FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_
#include "MapPacketExtractionIF.h"
#include "../objectmanager/ObjectManagerIF.h"
@ -20,17 +13,19 @@ class StorageManagerIF;
* The class implements the full MAP Packet Extraction functionality as described in the CCSDS
* TC Space Data Link Protocol. It internally stores incomplete segmented packets until they are
* fully received. All found packets are forwarded to a single distribution entity.
* @author B. Baetz
*/
class MapPacketExtraction: public MapPacketExtractionIF {
private:
static const uint32_t MAX_PACKET_SIZE = 4096;
uint8_t lastSegmentationFlag; //!< The segmentation flag of the last received frame.
uint8_t mapId; //!< MAP ID of this MAP Channel.
uint32_t packetLength; //!< Complete length of the current Space Packet.
uint32_t packetLength = 0; //!< Complete length of the current Space Packet.
uint8_t* bufferPosition; //!< Position to write to in the internal Packet buffer.
uint8_t packetBuffer[MAX_PACKET_SIZE]; //!< The internal Space Packet Buffer.
object_id_t packetDestination;
StorageManagerIF* packetStore; //!< Pointer to the store where full TC packets are stored.
//!< Pointer to the store where full TC packets are stored.
StorageManagerIF* packetStore = nullptr;
MessageQueueId_t tcQueueId; //!< QueueId to send found packets to the distributor.
/**
* Debug method to print the packet Buffer's content.
@ -75,4 +70,4 @@ public:
uint8_t getMapId() const;
};
#endif /* MAPPACKETEXTRACTION_H_ */
#endif /* FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_ */

6
datapool/CMakeLists.txt Normal file
View File

@ -0,0 +1,6 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
HkSwitchHelper.cpp
PoolDataSetBase.cpp
PoolEntry.cpp
)

View File

@ -59,6 +59,11 @@ uint16_t PoolDataSetBase::getFillCount() const {
ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if(registeredVariables[count] == nullptr) {
// configuration error.
return HasReturnvaluesIF::RETURN_FAILED;
}
// These checks are often performed by the respective
// variable implementation too, but I guess a double check does not hurt.
if (registeredVariables[count]->getReadWriteMode() !=

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

@ -0,0 +1,8 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
LocalDataPoolManager.cpp
LocalDataSet.cpp
LocalPoolDataSetBase.cpp
LocalPoolObjectBase.cpp
SharedLocalDataSet.cpp
)

View File

@ -48,7 +48,7 @@ class HousekeepingPacketUpdate;
* @author R. Mueller
*/
class LocalDataPoolManager {
template<typename T> friend class LocalPoolVar;
template<typename T> friend class LocalPoolVariable;
template<typename T, uint16_t vecSize> friend class LocalPoolVector;
friend class LocalPoolDataSetBase;
friend void (Factory::setStaticFrameworkObjectIds)();

View File

@ -22,10 +22,10 @@
* @ingroup data_pool
*/
template<typename T>
class LocalPoolVar: public LocalPoolObjectBase {
class LocalPoolVariable: public LocalPoolObjectBase {
public:
//! Default ctor is forbidden.
LocalPoolVar() = delete;
LocalPoolVariable() = delete;
/**
* This constructor is used by the data creators to have pool variable
@ -43,7 +43,7 @@ public:
* If nullptr, the variable is not registered.
* @param setReadWriteMode Specify the read-write mode of the pool variable.
*/
LocalPoolVar(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
LocalPoolVariable(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
@ -64,7 +64,7 @@ public:
* @param setReadWriteMode Specify the read-write mode of the pool variable.
*
*/
LocalPoolVar(object_id_t poolOwner, lp_id_t poolId,
LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId,
DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
/**
@ -73,10 +73,10 @@ public:
* @param dataSet
* @param setReadWriteMode
*/
LocalPoolVar(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
LocalPoolVariable(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
virtual~ LocalPoolVar() {};
virtual~ LocalPoolVariable() {};
/**
* @brief This is the local copy of the data pool entry.
@ -118,23 +118,23 @@ public:
ReturnValue_t commit(dur_millis_t lockTimeout = MutexIF::BLOCKING) override;
LocalPoolVar<T> &operator=(const T& newValue);
LocalPoolVar<T> &operator=(const LocalPoolVar<T>& newPoolVariable);
LocalPoolVariable<T> &operator=(const T& newValue);
LocalPoolVariable<T> &operator=(const LocalPoolVariable<T>& newPoolVariable);
//! Explicit type conversion operator. Allows casting the class to
//! its template type to perform operations on value.
explicit operator T() const;
bool operator==(const LocalPoolVar<T>& other) const;
bool operator==(const LocalPoolVariable<T>& other) const;
bool operator==(const T& other) const;
bool operator!=(const LocalPoolVar<T>& other) const;
bool operator!=(const LocalPoolVariable<T>& other) const;
bool operator!=(const T& other) const;
bool operator<(const LocalPoolVar<T>& other) const;
bool operator<(const LocalPoolVariable<T>& other) const;
bool operator<(const T& other) const;
bool operator>(const LocalPoolVar<T>& other) const;
bool operator>(const LocalPoolVariable<T>& other) const;
bool operator>(const T& other) const;
protected:
@ -160,7 +160,7 @@ protected:
// std::ostream is the type for object std::cout
template <typename U>
friend std::ostream& operator<< (std::ostream &out,
const LocalPoolVar<U> &var);
const LocalPoolVariable<U> &var);
private:
};
@ -168,18 +168,18 @@ private:
#include "LocalPoolVariable.tpp"
template<class T>
using lp_var_t = LocalPoolVar<T>;
using lp_var_t = LocalPoolVariable<T>;
using lp_bool_t = LocalPoolVar<uint8_t>;
using lp_uint8_t = LocalPoolVar<uint8_t>;
using lp_uint16_t = LocalPoolVar<uint16_t>;
using lp_uint32_t = LocalPoolVar<uint32_t>;
using lp_uint64_t = LocalPoolVar<uint64_t>;
using lp_int8_t = LocalPoolVar<int8_t>;
using lp_int16_t = LocalPoolVar<int16_t>;
using lp_int32_t = LocalPoolVar<int32_t>;
using lp_int64_t = LocalPoolVar<int64_t>;
using lp_float_t = LocalPoolVar<float>;
using lp_double_t = LocalPoolVar<double>;
using lp_bool_t = LocalPoolVariable<uint8_t>;
using lp_uint8_t = LocalPoolVariable<uint8_t>;
using lp_uint16_t = LocalPoolVariable<uint16_t>;
using lp_uint32_t = LocalPoolVariable<uint32_t>;
using lp_uint64_t = LocalPoolVariable<uint64_t>;
using lp_int8_t = LocalPoolVariable<int8_t>;
using lp_int16_t = LocalPoolVariable<int16_t>;
using lp_int32_t = LocalPoolVariable<int32_t>;
using lp_int64_t = LocalPoolVariable<int64_t>;
using lp_float_t = LocalPoolVariable<float>;
using lp_double_t = LocalPoolVariable<double>;
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ */

View File

@ -6,32 +6,32 @@
#endif
template<typename T>
inline LocalPoolVar<T>::LocalPoolVar(HasLocalDataPoolIF* hkOwner,
inline LocalPoolVariable<T>::LocalPoolVariable(HasLocalDataPoolIF* hkOwner,
lp_id_t poolId, DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
template<typename T>
inline LocalPoolVar<T>::LocalPoolVar(object_id_t poolOwner, lp_id_t poolId,
inline LocalPoolVariable<T>::LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId,
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
template<typename T>
inline LocalPoolVar<T>::LocalPoolVar(gp_id_t globalPoolId, DataSetIF *dataSet,
inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId, DataSetIF *dataSet,
pool_rwm_t setReadWriteMode):
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
dataSet, setReadWriteMode){}
template<typename T>
inline ReturnValue_t LocalPoolVar<T>::read(dur_millis_t lockTimeout) {
inline ReturnValue_t LocalPoolVariable<T>::read(dur_millis_t lockTimeout) {
MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING,
lockTimeout);
return readWithoutLock();
}
template<typename T>
inline ReturnValue_t LocalPoolVar<T>::readWithoutLock() {
inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
sif::debug << "LocalPoolVar: Invalid read write "
"mode for read() call." << std::endl;
@ -53,14 +53,14 @@ inline ReturnValue_t LocalPoolVar<T>::readWithoutLock() {
}
template<typename T>
inline ReturnValue_t LocalPoolVar<T>::commit(dur_millis_t lockTimeout) {
inline ReturnValue_t LocalPoolVariable<T>::commit(dur_millis_t lockTimeout) {
MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING,
lockTimeout);
return commitWithoutLock();
}
template<typename T>
inline ReturnValue_t LocalPoolVar<T>::commitWithoutLock() {
inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() {
if(readWriteMode == pool_rwm_t::VAR_READ) {
sif::debug << "LocalPoolVar: Invalid read write "
"mode for commit() call." << std::endl;
@ -81,88 +81,88 @@ inline ReturnValue_t LocalPoolVar<T>::commitWithoutLock() {
}
template<typename T>
inline ReturnValue_t LocalPoolVar<T>::serialize(uint8_t** buffer, size_t* size,
inline ReturnValue_t LocalPoolVariable<T>::serialize(uint8_t** buffer, size_t* size,
const size_t max_size, SerializeIF::Endianness streamEndianness) const {
return SerializeAdapter::serialize(&value,
buffer, size ,max_size, streamEndianness);
}
template<typename T>
inline size_t LocalPoolVar<T>::getSerializedSize() const {
inline size_t LocalPoolVariable<T>::getSerializedSize() const {
return SerializeAdapter::getSerializedSize(&value);
}
template<typename T>
inline ReturnValue_t LocalPoolVar<T>::deSerialize(const uint8_t** buffer,
inline ReturnValue_t LocalPoolVariable<T>::deSerialize(const uint8_t** buffer,
size_t* size, SerializeIF::Endianness streamEndianness) {
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
}
template<typename T>
inline std::ostream& operator<< (std::ostream &out,
const LocalPoolVar<T> &var) {
const LocalPoolVariable<T> &var) {
out << var.value;
return out;
}
template<typename T>
inline LocalPoolVar<T>::operator T() const {
inline LocalPoolVariable<T>::operator T() const {
return value;
}
template<typename T>
inline LocalPoolVar<T> & LocalPoolVar<T>::operator=(const T& newValue) {
inline LocalPoolVariable<T> & LocalPoolVariable<T>::operator=(const T& newValue) {
value = newValue;
return *this;
}
template<typename T>
inline LocalPoolVar<T>& LocalPoolVar<T>::operator =(
const LocalPoolVar<T>& newPoolVariable) {
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator =(
const LocalPoolVariable<T>& newPoolVariable) {
value = newPoolVariable.value;
return *this;
}
template<typename T>
inline bool LocalPoolVar<T>::operator ==(const LocalPoolVar<T> &other) const {
inline bool LocalPoolVariable<T>::operator ==(const LocalPoolVariable<T> &other) const {
return this->value == other.value;
}
template<typename T>
inline bool LocalPoolVar<T>::operator ==(const T &other) const {
inline bool LocalPoolVariable<T>::operator ==(const T &other) const {
return this->value == other;
}
template<typename T>
inline bool LocalPoolVar<T>::operator !=(const LocalPoolVar<T> &other) const {
inline bool LocalPoolVariable<T>::operator !=(const LocalPoolVariable<T> &other) const {
return not (*this == other);
}
template<typename T>
inline bool LocalPoolVar<T>::operator !=(const T &other) const {
inline bool LocalPoolVariable<T>::operator !=(const T &other) const {
return not (*this == other);
}
template<typename T>
inline bool LocalPoolVar<T>::operator <(const LocalPoolVar<T> &other) const {
inline bool LocalPoolVariable<T>::operator <(const LocalPoolVariable<T> &other) const {
return this->value < other.value;
}
template<typename T>
inline bool LocalPoolVar<T>::operator <(const T &other) const {
inline bool LocalPoolVariable<T>::operator <(const T &other) const {
return this->value < other;
}
template<typename T>
inline bool LocalPoolVar<T>::operator >(const LocalPoolVar<T> &other) const {
inline bool LocalPoolVariable<T>::operator >(const LocalPoolVariable<T> &other) const {
return not (*this < other);
}
template<typename T>
inline bool LocalPoolVar<T>::operator >(const T &other) const {
inline bool LocalPoolVariable<T>::operator >(const T &other) const {
return not (*this < other);
}

View File

@ -0,0 +1,15 @@
target_sources(${TARGET_NAME}
PRIVATE
)
# Add include paths for the executable
target_include_directories(${TARGET_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
# Add include paths for the FSFW library
target_include_directories(${LIB_FSFW_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -15,25 +15,17 @@
//! Can be used to enable additional debugging printouts for developing the FSFW
#define FSFW_PRINT_VERBOSITY_LEVEL 0
//! Defines the FIFO depth of each commanding service base which
//! also determines how many commands a CSB service can handle in one cycle
//! simulataneously. This will increase the required RAM for
//! each CSB service !
#define FSFW_CSB_FIFO_DEPTH 6
//! If FSFW_OBJ_EVENT_TRANSLATION is set to one,
//! additional output which requires the translation files translateObjects
//! and translateEvents (and their compiled source files)
#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>
#include "objects/translateObjects.h"
#include "events/translateEvents.h"
#else
#define FSFW_DEBUG_OUTPUT 0
#endif
//! When using the newlib nano library, C99 support for stdio facilities
@ -52,6 +44,12 @@ static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8;
static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120;
static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
//! Defines the FIFO depth of each commanding service base which
//! also determines how many commands a CSB service can handle in one cycle
//! simulataneously. This will increase the required RAM for
//! each CSB service !
static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6;
}
#endif /* CONFIG_FSFWCONFIG_H_ */

View File

@ -3,6 +3,10 @@
#include "OBSWVersion.h"
#include "objects/systemObjectList.h"
#include "events/subsystemIdRanges.h"
#include "returnvalues/classIds.h"
#ifdef __cplusplus
namespace config {
#endif

View File

@ -0,0 +1,11 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
AssemblyBase.cpp
ChildHandlerBase.cpp
ChildHandlerFDIR.cpp
DeviceHandlerBase.cpp
DeviceHandlerFailureIsolation.cpp
DeviceHandlerMessage.cpp
DeviceTmReportingWrapper.cpp
HealthDevice.cpp
)

View File

@ -3,8 +3,6 @@
#include "DeviceTmReportingWrapper.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../objectmanager/ObjectManager.h"
#include "../storagemanager/StorageManagerIF.h"
#include "../thermal/ThermalComponentIF.h"
@ -13,9 +11,11 @@
#include "../ipc/MessageQueueMessage.h"
#include "../ipc/QueueFactory.h"
#include "../subsystem/SubsystemBase.h"
#include "../datapoollocal/LocalPoolVariable.h"
#include <iomanip>
object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT;
object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT;
@ -56,9 +56,10 @@ void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
}
void DeviceHandlerBase::setThermalStateRequestPoolIds(
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId) {
this->deviceThermalRequestPoolId = thermalStatePoolId;
this->deviceThermalRequestPoolId = thermalRequestPoolId;
lp_id_t thermalStatePoolId, lp_id_t heaterRequestPoolId,
uint32_t thermalSetId) {
thermalSet = new DeviceHandlerThermalSet(this, thermalSetId,
thermalStatePoolId, heaterRequestPoolId);
}
@ -86,7 +87,6 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
decrementDeviceReplyMap();
fdirInstance->checkForFailures();
hkSwitcher.performOperation();
hkManager.performHkOperation();
performOperationHook();
return RETURN_OK;
}
@ -111,6 +111,9 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
break;
case CommunicationAction::GET_READ:
doGetRead();
// This will be performed after datasets have been updated by the
// custom device implementation.
hkManager.performHkOperation();
break;
default:
break;
@ -208,16 +211,18 @@ ReturnValue_t DeviceHandlerBase::initialize() {
fillCommandAndReplyMap();
//Set temperature target state to NON_OP.
GlobDataSet mySet;
gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet,
PoolVariableIF::VAR_WRITE);
mySet.read();
thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
mySet.commit(PoolVariableIF::VALID);
if(thermalSet != nullptr) {
//Set temperature target state to NON_OP.
result = thermalSet->read();
if(result == HasReturnvaluesIF::RETURN_OK) {
thermalSet->heaterRequest.value =
ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
thermalSet->commit(PoolVariableIF::VALID);
}
}
return RETURN_OK;
}
void DeviceHandlerBase::decrementDeviceReplyMap() {
@ -505,15 +510,17 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
}
Clock::getUptime(&timeoutStart);
if (mode == MODE_OFF) {
GlobDataSet mySet;
gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
mySet.read();
if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
if (mode == MODE_OFF and thermalSet != nullptr) {
ReturnValue_t result = thermalSet->read();
if(result == HasReturnvaluesIF::RETURN_OK) {
if (thermalSet->heaterRequest.value !=
ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalSet->heaterRequest.value = ThermalComponentIF::
STATE_REQUEST_NON_OPERATIONAL;
}
thermalSet->heaterRequest.commit(PoolVariableIF::VALID);
}
mySet.commit(PoolVariableIF::VALID);
}
changeHK(mode, submode, true);
}
@ -919,11 +926,6 @@ void DeviceHandlerBase::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
setMode(getBaseMode(mode));
}
uint32_t DeviceHandlerBase::getTransitionDelayMs(Mode_t modeFrom,
Mode_t modeTo) {
return 0;
}
ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) {
if(powerSwitcher == nullptr) {
return NO_SWITCH;
@ -976,17 +978,15 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode,
}
if ((commandedMode == MODE_ON) && (mode == MODE_OFF)
&& (deviceThermalStatePoolId != PoolVariableIF::NO_PARAMETER)) {
GlobDataSet mySet;
gp_uint8_t thermalState(deviceThermalStatePoolId, &mySet,
PoolVariableIF::VAR_READ);
gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet,
PoolVariableIF::VAR_READ);
mySet.read();
if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
if (!ThermalComponentIF::isOperational(thermalState)) {
and (thermalSet != nullptr)) {
ReturnValue_t result = thermalSet->read();
if(result == HasReturnvaluesIF::RETURN_OK) {
if((thermalSet->heaterRequest.value !=
ThermalComponentIF::STATE_REQUEST_IGNORE) and (not
ThermalComponentIF::isOperational(
thermalSet->thermalState.value))) {
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE,
thermalState);
thermalSet->thermalState.value);
return NON_OP_TEMPERATURE;
}
}
@ -999,32 +999,15 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode,
Submode_t commandedSubmode) {
switch (commandedMode) {
case MODE_ON:
if (mode == MODE_OFF) {
transitionSourceMode = _MODE_POWER_DOWN;
transitionSourceSubMode = SUBMODE_NONE;
setMode(_MODE_POWER_ON, commandedSubmode);
//already set the delay for the child transition so we don't need to call it twice
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP,
MODE_ON);
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
GlobDataSet mySet;
gp_int8_t thermalRequest(deviceThermalRequestPoolId,
&mySet, PoolVariableIF::VAR_READ_WRITE);
mySet.read();
if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
mySet.commit(PoolVariableIF::VALID);
}
} else {
setTransition(MODE_ON, commandedSubmode);
}
handleTransitionToOnMode(commandedMode, commandedSubmode);
break;
case MODE_OFF:
if (mode == MODE_OFF) {
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
setMode(_MODE_POWER_DOWN, commandedSubmode);
} else {
//already set the delay for the child transition so we don't need to call it twice
// already set the delay for the child transition
// so we don't need to call it twice
childTransitionDelay = getTransitionDelayMs(mode, _MODE_POWER_DOWN);
transitionSourceMode = _MODE_POWER_DOWN;
transitionSourceSubMode = commandedSubmode;
@ -1050,6 +1033,33 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode,
}
}
void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode,
Submode_t commandedSubmode) {
if (mode == MODE_OFF) {
transitionSourceMode = _MODE_POWER_DOWN;
transitionSourceSubMode = SUBMODE_NONE;
setMode(_MODE_POWER_ON, commandedSubmode);
// already set the delay for the child transition so we don't
// need to call it twice
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP,
MODE_ON);
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
if(thermalSet != nullptr) {
ReturnValue_t result = thermalSet->read();
if(result == HasReturnvaluesIF::RETURN_OK) {
if(thermalSet->heaterRequest !=
ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalSet->heaterRequest =
ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
thermalSet->commit();
}
}
}
} else {
setTransition(MODE_ON, commandedSubmode);
}
}
void DeviceHandlerBase::getMode(Mode_t* mode, Submode_t* submode) {
*mode = this->mode;
*submode = this->submode;
@ -1222,10 +1232,12 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data,
}
}
//Try to cast to GlobDataSet and commit data.
if (!neverInDataPool) {
GlobDataSet* dataSet = dynamic_cast<GlobDataSet*>(data);
if (dataSet != NULL) {
dataSet->commit(PoolVariableIF::VALID);
if (not neverInDataPool) {
LocalPoolDataSetBase* dataSet =
dynamic_cast<LocalPoolDataSetBase*>(data);
if (dataSet != nullptr) {
dataSet->setValidity(true, true);
dataSet->commit();
}
}
}
@ -1262,7 +1274,8 @@ void DeviceHandlerBase::buildInternalCommand(void) {
if (result == BUSY) {
//so we can track misconfigurations
sif::debug << std::hex << getObjectId()
<< ": DHB::buildInternalCommand: Busy" << std::dec << std::endl;
<< ": DHB::buildInternalCommand: Busy" << std::dec
<< std::endl;
result = NOTHING_TO_SEND; //no need to report this
}
}
@ -1371,8 +1384,8 @@ bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) {
void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
}
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){
executingTask = task_;
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task){
executingTask = task;
}
// Default implementations empty.
@ -1385,6 +1398,12 @@ void DeviceHandlerBase::performOperationHook() {
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(
LocalDataPool &localDataPoolMap,
LocalDataPoolManager& poolManager) {
if(thermalSet != nullptr) {
localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>);
localDataPoolMap.emplace(thermalSet->heaterRequestPoolId,
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>);
}
return RETURN_OK;
}
@ -1429,3 +1448,17 @@ dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const {
return pstIntervalMs;
}
DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
if(cookieInfo.pendingCommand != deviceCommandMap.end()) {
return cookieInfo.pendingCommand->first;
}
return DeviceHandlerIF::NO_COMMAND;
}
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
for(const auto& reply: deviceReplyMap) {
if(reply.second.dataSet != nullptr) {
reply.second.dataSet->setValidity(false, true);
}
}
}

View File

@ -4,6 +4,7 @@
#include "DeviceHandlerIF.h"
#include "DeviceCommunicationIF.h"
#include "DeviceHandlerFailureIsolation.h"
#include "DeviceHandlerThermalSet.h"
#include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h"
@ -103,8 +104,21 @@ public:
size_t cmdQueueSize = 20);
void setHkDestination(object_id_t hkDestination);
void setThermalStateRequestPoolIds(uint32_t thermalStatePoolId,
uint32_t thermalRequestPoolId);
/**
* If the device handler is controlled by the FSFW thermal building blocks,
* this function should be called to initialize all required components.
* The device handler will then take care of creating local pool entries
* for the device thermal state and device heating request.
* Custom local pool IDs can be assigned as well.
* @param thermalStatePoolId
* @param thermalRequestPoolId
*/
void setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId =
DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t thermalRequestPoolId =
DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID,
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID);
/**
* @brief Helper function to ease device handler development.
* This will instruct the transition to MODE_ON immediately
@ -240,9 +254,10 @@ protected:
*
* @param[out] id the device command id that has been built
* @return
* - @c RETURN_OK to send command after setting #rawPacket and #rawPacketLen.
* - @c NOTHING_TO_SEND when no command is to be sent.
* - Anything else triggers an even with the returnvalue as a parameter.
* - @c RETURN_OK to send command after setting #rawPacket and
* #rawPacketLen.
* - @c NOTHING_TO_SEND when no command is to be sent.
* - Anything else triggers an even with the returnvalue as a parameter.
*/
virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) = 0;
@ -259,7 +274,8 @@ protected:
* and filling them in doStartUp(), doShutDown() and doTransition() so no
* modes have to be checked here.
*
* #rawPacket and #rawPacketLen must be set by this method to the packet to be sent.
* #rawPacket and #rawPacketLen must be set by this method to the
* packet to be sent.
*
* @param[out] id the device command id built
* @return
@ -270,19 +286,23 @@ protected:
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0;
/**
* @brief Build a device command packet from data supplied by a direct command.
* @brief Build a device command packet from data supplied by a
* direct command.
*
* @details
* #rawPacket and #rawPacketLen should be set by this method to the packet to be sent.
* The existence of the command in the command map and the command size check
* against 0 are done by the base class.
* #rawPacket and #rawPacketLen should be set by this method to the packet
* to be sent. The existence of the command in the command map and the
* command size check against 0 are done by the base class.
*
* @param deviceCommand the command to build, already checked against deviceCommandMap
* @param deviceCommand the command to build, already checked against
* deviceCommandMap
* @param commandData pointer to the data from the direct command
* @param commandDataLen length of commandData
* @return
* - @c RETURN_OK to send command after #rawPacket and #rawPacketLen have been set.
* - Anything else triggers an event with the returnvalue as a parameter
* - @c RETURN_OK to send command after #rawPacket and #rawPacketLen
* have been set.
* - Anything else triggers an event with the
* returnvalue as a parameter
*/
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t * commandData, size_t commandDataLen) = 0;
@ -470,7 +490,7 @@ protected:
* @param modeTo
* @return time in ms
*/
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo);
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) = 0;
/**
* Return the switches connected to the device.
@ -667,7 +687,7 @@ protected:
//! The dataset used to access housekeeping data related to the
//! respective device reply. Will point to a dataset held by
//! the child handler (if one is specified)
LocalPoolDataSetBase* dataSet;
LocalPoolDataSetBase* dataSet = nullptr;
//! The command that expects this reply.
DeviceCommandMap::iterator command;
};
@ -694,19 +714,7 @@ protected:
//! and to send replies.
MessageQueueIF* commandQueue = nullptr;
/**
* this is the datapool variable with the thermal state of the device
*
* can be set to PoolVariableIF::NO_PARAMETER to deactivate thermal checking
*/
uint32_t deviceThermalStatePoolId = PoolVariableIF::NO_PARAMETER;
/**
* this is the datapool variable with the thermal request of the device
*
* can be set to PoolVariableIF::NO_PARAMETER to deactivate thermal checking
*/
uint32_t deviceThermalRequestPoolId = PoolVariableIF::NO_PARAMETER;
DeviceHandlerThermalSet* thermalSet = nullptr;
/**
* Optional Error code. Can be set in doStartUp(), doShutDown() and
@ -732,15 +740,39 @@ protected:
//! before setTaskIF was called.
PeriodicTaskIF* executingTask = nullptr;
static object_id_t powerSwitcherId; //!< Object which switches power on and off.
//!< Object which switches power on and off.
static object_id_t powerSwitcherId;
static object_id_t rawDataReceiverId; //!< Object which receives RAW data by default.
//!< Object which receives RAW data by default.
static object_id_t rawDataReceiverId;
//!< Object which may be the root cause of an identified fault.
static object_id_t defaultFdirParentId;
/**
* @brief Set all datapool variables that are update periodically in
* normal mode invalid
* @details
* The default implementation will set all datasets which have been added
* in #fillCommandAndReplyMap to invalid. It will also set all pool
* variables inside the dataset to invalid. The user can override this
* method optionally.
*/
virtual void setNormalDatapoolEntriesInvalid();
/**
* Helper function to get pending command. This is useful for devices
* like SPI sensors to identify the last sent command.
* This only returns the command sent in the last SEND_WRITE cycle.
* @return
*/
DeviceCommandId_t getPendingCommand() const;
static object_id_t defaultFdirParentId; //!< Object which may be the root cause of an identified fault.
/**
* Helper function to report a missed reply
*
* Can be overwritten by children to act on missed replies or to fake reporting Id.
* Can be overwritten by children to act on missed replies or to fake
* reporting Id.
*
* @param id of the missed reply
*/
@ -770,7 +802,6 @@ protected:
*
* The submode is left unchanged.
*
*
* @param newMode
*/
void setMode(Mode_t newMode);
@ -823,8 +854,6 @@ protected:
virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom);
/**
* Is the combination of mode and submode valid?
*
* @param mode
* @param submode
* @return
@ -835,27 +864,27 @@ protected:
Submode_t submode);
/**
* Get the Rmap action for the current step.
*
* Get the communication action for the current step.
* The step number can be read from #pstStep.
*
* @return The Rmap action to execute in this step
* @return The communication action to execute in this step
*/
virtual CommunicationAction getComAction();
/**
* Build the device command to send for raw mode.
*
* This is only called in @c MODE_RAW. It is for the rare case that in raw mode packets
* are to be sent by the handler itself. It is NOT needed for the raw commanding service.
* Its only current use is in the STR handler which gets its raw packets from a different
* source.
* Also it can be used for transitional commands, to get the device ready for @c MODE_RAW
* This is only called in @c MODE_RAW. It is for the rare case that in
* raw mode packets are to be sent by the handler itself. It is NOT needed
* for the raw commanding service. Its only current use is in the STR
* handler which gets its raw packets from a different source.
* Also it can be used for transitional commands, to get the device ready
* for @c MODE_RAW
*
* As it is almost never used, there is a default implementation returning @c NOTHING_TO_SEND.
* As it is almost never used, there is a default implementation
* returning @c NOTHING_TO_SEND.
*
* #rawPacket and #rawPacketLen must be set by this method to the packet to be sent.
* #rawPacket and #rawPacketLen must be set by this method to the packet
* to be sent.
*
* @param[out] id the device command id built
* @return
@ -868,7 +897,9 @@ protected:
* Returns the delay cycle count of a reply.
* A count != 0 indicates that the command is already executed.
* @param deviceCommand The command to look for
* @return The current delay count. If the command does not exist (should never happen) it returns 0.
* @return
* The current delay count. If the command does not exist (should never
* happen) it returns 0.
*/
uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand);
@ -878,42 +909,46 @@ protected:
* It gets space in the #IPCStore, copies data there, then sends a raw reply
* containing the store address.
*
* This method is virtual, as the STR has a different channel to send raw replies
* and overwrites it accordingly.
* This method is virtual, as devices can have different channels to send
* raw replies
*
* @param data data to send
* @param len length of @c data
* @param sendTo the messageQueueId of the one to send to
* @param isCommand marks the raw data as a command, the message then will be of type raw_command
* @param isCommand marks the raw data as a command, the message then
* will be of type raw_command
*/
virtual void replyRawData(const uint8_t *data, size_t len,
MessageQueueId_t sendTo, bool isCommand = false);
/**
* Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping is active and if so,
* does not send the Data as the wiretapping will have sent it already
* Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping
* is active and if so, does not send the data as the wiretapping will have
* sent it already
*/
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
/**
* notify child about mode change
* @brief Notify child about mode change.
*/
virtual void modeChanged(void);
/**
* Enable the reply checking for a command
*
* Is only called, if the command was sent (ie the getWriteReply was successful).
* Must ensure that all replies are activated and correctly linked to the command that initiated it.
* The default implementation looks for a reply with the same id as the command id in the replyMap or
* uses the alternativeReplyId if flagged so.
* When found, copies maxDelayCycles to delayCycles in the reply information and sets the command to
* expect one reply.
* Is only called, if the command was sent (i.e. the getWriteReply was
* successful). Must ensure that all replies are activated and correctly
* linked to the command that initiated it.
* The default implementation looks for a reply with the same id as the
* command id in the replyMap or uses the alternativeReplyId if flagged so.
* When found, copies maxDelayCycles to delayCycles in the reply information
* and sets the command to expect one reply.
*
* Can be overwritten by the child, if a command activates multiple replies
* or replyId differs from commandId.
* Notes for child implementations:
* - If the command was not found in the reply map, NO_REPLY_EXPECTED MUST be returned.
* - If the command was not found in the reply map,
* NO_REPLY_EXPECTED MUST be returned.
* - A failure code may be returned if something went fundamentally wrong.
*
* @param deviceCommand
@ -926,34 +961,28 @@ protected:
DeviceCommandId_t alternateReplyID = 0);
/**
* get the state of the PCDU switches in the datapool
*
* Get the state of the PCDU switches in the local datapool
* @return
* - @c PowerSwitchIF::SWITCH_ON if all switches specified by #switches are on
* - @c PowerSwitchIF::SWITCH_OFF one of the switches specified by #switches are off
* - @c PowerSwitchIF::RETURN_FAILED if an error occured
* - @c PowerSwitchIF::SWITCH_ON if all switches specified
* by #switches are on
* - @c PowerSwitchIF::SWITCH_OFF one of the switches specified by
* #switches are off
* - @c PowerSwitchIF::RETURN_FAILED if an error occured
*/
ReturnValue_t getStateOfSwitches(void);
/**
* set all datapool variables that are update periodically in normal mode invalid
*
* Child classes should provide an implementation which sets all those variables invalid
* which are set periodically during any normal mode.
*/
virtual void setNormalDatapoolEntriesInvalid() = 0;
/**
* build a list of sids and pass it to the #hkSwitcher
*/
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
/**
* Children can overwrite this function to suppress checking of the command Queue
* Children can overwrite this function to suppress checking of the
* command Queue
*
* This can be used when the child does not want to receive a command in a certain
* situation. Care must be taken that checking is not permanentely disabled as this
* would render the handler unusable.
* This can be used when the child does not want to receive a command in
* a certain situation. Care must be taken that checking is not
* permanentely disabled as this would render the handler unusable.
*
* @return whether checking the queue should NOT be done
*/
@ -992,17 +1021,20 @@ protected:
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) const;
/**
* Checks state of switches in conjunction with mode and triggers an event if they don't fit.
* Checks state of switches in conjunction with mode and triggers an event
* if they don't fit.
*/
virtual void checkSwitchState();
/**
* Reserved for the rare case where a device needs to perform additional operation cyclically in OFF mode.
* Reserved for the rare case where a device needs to perform additional
* operation cyclically in OFF mode.
*/
virtual void doOffActivity();
/**
* Reserved for the rare case where a device needs to perform additional operation cyclically in ON mode.
* Reserved for the rare case where a device needs to perform additional
* operation cyclically in ON mode.
*/
virtual void doOnActivity();
@ -1043,9 +1075,10 @@ private:
/**
* Information about a cookie.
*
* This is stored in a map for each cookie, to not only track the state, but also information
* about the sent command. Tracking this information is needed as
* the state of a commandId (waiting for reply) is done when a RMAP write reply is received.
* This is stored in a map for each cookie, to not only track the state,
* but also information about the sent command. Tracking this information
* is needed as the state of a commandId (waiting for reply) is done when a
* write reply is received.
*/
struct CookieInfo {
CookieState_t state;
@ -1102,10 +1135,14 @@ private:
/**
* Handle the device handler mode.
*
* - checks whether commands are valid for the current mode, rejects them accordingly
* - checks whether commanded mode transitions are required and calls handleCommandedModeTransition()
* - does the necessary action for the current mode or calls doChildStateMachine in modes @c MODE_TO_ON and @c MODE_TO_OFF
* - actions that happen in transitions (eg setting a timeout) are handled in setMode()
* - checks whether commands are valid for the current mode, rejects
* them accordingly
* - checks whether commanded mode transitions are required and calls
* handleCommandedModeTransition()
* - does the necessary action for the current mode or calls
* doChildStateMachine in modes @c MODE_TO_ON and @c MODE_TO_OFF
* - actions that happen in transitions (e.g. setting a timeout) are
* handled in setMode()
*/
void doStateMachine(void);
@ -1115,16 +1152,17 @@ private:
/**
* Decrement the counter for the timout of replies.
*
* This is called at the beginning of each cycle. It checks whether a reply has timed out (that means a reply was expected
* but not received).
* This is called at the beginning of each cycle. It checks whether a
* reply has timed out (that means a reply was expected but not received).
*/
void decrementDeviceReplyMap(void);
/**
* Convenience function to handle a reply.
*
* Called after scanForReply() has found a packet. Checks if the found id is in the #deviceCommandMap, if so,
* calls interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) for further action.
* Called after scanForReply() has found a packet. Checks if the found ID
* is in the #deviceCommandMap, if so, calls
* #interpretDeviceReply for further action.
*
* It also resets the timeout counter for the command id.
*
@ -1184,7 +1222,7 @@ private:
* @param[out] len
* @return
* - @c RETURN_OK @c data is valid
* - @c RETURN_FAILED IPCStore is NULL
* - @c RETURN_FAILED IPCStore is nullptr
* - the return value from the IPCStore if it was not @c RETURN_OK
*/
ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data,
@ -1208,6 +1246,9 @@ private:
void parseReply(const uint8_t* receivedData,
size_t receivedDataLen);
void handleTransitionToOnMode(Mode_t commandedMode,
Submode_t commandedSubmode);
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */

View File

@ -4,6 +4,7 @@
#include "DeviceHandlerMessage.h"
#include "../action/HasActionsIF.h"
#include "../datapoollocal/locPoolDefinitions.h"
#include "../events/Event.h"
#include "../modes/HasModesIF.h"
#include "../ipc/MessageQueueSenderIF.h"
@ -21,12 +22,13 @@ using DeviceCommandId_t = uint32_t;
*/
class DeviceHandlerIF {
public:
static constexpr DeviceCommandId_t NO_COMMAND = -1;
static constexpr uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static constexpr uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
static constexpr Command_t NO_COMMAND = -1;
using dh_heater_request_t = uint8_t;
using dh_thermal_state_t = int8_t;
/**
* @brief This is the mode the <strong>device handler</strong> is in.
@ -129,7 +131,7 @@ public:
// Standard codes used in interpretDeviceReply
static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC0); //the device reported, that it did not execute the command
static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC1);
static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC2); //the deviceCommandId reported by scanforReply is unknown
static const ReturnValue_t UNKNOWN_DEVICE_REPLY = MAKE_RETURN_CODE(0xC2); //the deviceCommandId reported by scanforReply is unknown
static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC3); //syntax etc is correct but still not ok, eg parameters where none are expected
// Standard codes used in buildCommandFromCommand
@ -142,7 +144,7 @@ public:
* This is used by the child class to tell the base class what to do.
*/
enum CommunicationAction: uint8_t {
PERFORM_OPERATION,
PERFORM_OPERATION,
SEND_WRITE,//!< Send write
GET_WRITE, //!< Get write
SEND_READ, //!< Send read
@ -150,6 +152,14 @@ public:
NOTHING //!< Do nothing.
};
static constexpr uint32_t DEFAULT_THERMAL_SET_ID = sid_t::INVALID_SET_ID - 1;
static constexpr lp_id_t DEFAULT_THERMAL_STATE_POOL_ID =
localpool::INVALID_LPID - 2;
static constexpr lp_id_t DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID =
localpool::INVALID_LPID - 1;
/**
* Default Destructor
*/

View File

@ -0,0 +1,44 @@
#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_
#include "DeviceHandlerIF.h"
#include "../datapoollocal/StaticLocalDataSet.h"
#include "../datapoollocal/LocalPoolVariable.h"
class DeviceHandlerThermalSet: public StaticLocalDataSet<2> {
public:
DeviceHandlerThermalSet(HasLocalDataPoolIF* hkOwner, uint32_t setId =
DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
lp_id_t thermalStateId =
DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t heaterRequestId =
DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID):
DeviceHandlerThermalSet(hkOwner->getObjectId(), setId,
thermalStateId, heaterRequestId) {}
DeviceHandlerThermalSet(object_id_t deviceHandler, uint32_t setId =
DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
lp_id_t thermalStateId =
DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t thermalStateRequestId =
DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID):
StaticLocalDataSet(sid_t(deviceHandler, setId)),
thermalStatePoolId(thermalStateId),
heaterRequestPoolId(thermalStateRequestId) {}
const lp_id_t thermalStatePoolId;
const lp_id_t heaterRequestPoolId;
lp_var_t<DeviceHandlerIF::dh_thermal_state_t> thermalState =
lp_var_t<DeviceHandlerIF::dh_thermal_state_t>(
thermalStatePoolId, sid.objectId, this);
lp_var_t<DeviceHandlerIF::dh_heater_request_t> heaterRequest =
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(
heaterRequestPoolId, sid.objectId, this);
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_ */

7
events/CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
EventManager.cpp
EventMessage.cpp
)
add_subdirectory(eventmatching)

View File

@ -1,27 +1,28 @@
#include "EventManager.h"
#include "EventMessage.h"
#include <FSFWConfig.h>
#include <FSFWConfig.h>
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../ipc/QueueFactory.h"
#include "../ipc/MutexFactory.h"
const uint16_t EventManager::POOL_SIZES[N_POOLS] = {
sizeof(EventMatchTree::Node), sizeof(EventIdRangeMatcher),
sizeof(ReporterRangeMatcher) };
// If one checks registerListener calls, there are around 40 (to max 50)
// objects registering for certain events.
// Each listener requires 1 or 2 EventIdMatcher and 1 or 2 ReportRangeMatcher.
// So a good guess is 75 to a max of 100 pools required for each, which fits well.
const uint16_t EventManager::N_ELEMENTS[N_POOLS] = {
fsfwconfig::FSFW_EVENTMGMR_MATCHTREE_NODES ,
fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS,
fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS };
const LocalPool::LocalPoolConfig EventManager::poolConfig = {
{fsfwconfig::FSFW_EVENTMGMR_MATCHTREE_NODES,
sizeof(EventMatchTree::Node)},
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS,
sizeof(EventIdRangeMatcher)},
{fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS,
sizeof(ReporterRangeMatcher)}
};
EventManager::EventManager(object_id_t setObjectId) :
SystemObject(setObjectId),
factoryBackend(0, POOL_SIZES, N_ELEMENTS, false, true) {
factoryBackend(0, poolConfig, false, true) {
mutex = MutexFactory::instance()->createMutex();
eventReportQueue = QueueFactory::instance()->createMessageQueue(
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE);
@ -42,7 +43,7 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
EventMessage message;
result = eventReportQueue->receiveMessage(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
#ifdef DEBUG
#if FSFW_OBJ_EVENT_TRANSLATION == 1
printEvent(&message);
#endif
notifyListeners(&message);
@ -113,13 +114,13 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener,
return result;
}
#ifdef DEBUG
#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,16 +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 <map>
#ifdef DEBUG
#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);
@ -49,13 +53,15 @@ protected:
MutexIF* mutex = nullptr;
static const uint8_t N_POOLS = 3;
LocalPool<N_POOLS> factoryBackend;
LocalPool factoryBackend;
static const LocalPool::LocalPoolConfig poolConfig;
static const uint16_t POOL_SIZES[N_POOLS];
static const uint16_t N_ELEMENTS[N_POOLS];
void notifyListeners(EventMessage *message);
#ifdef DEBUG
#if FSFW_OBJ_EVENT_TRANSLATION == 1
void printEvent(EventMessage *message);
#endif
@ -64,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

@ -0,0 +1,7 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
EventIdRangeMatcher.cpp
EventMatchTree.cpp
ReporterRangeMatcher.cpp
SeverityRangeMatcher.cpp
)

6
fdir/CMakeLists.txt Normal file
View File

@ -0,0 +1,6 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
EventCorrelation.cpp
FailureIsolationBase.cpp
FaultCounter.cpp
)

View File

@ -76,7 +76,7 @@ ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint16_t parameterId,
parameterWrapper->set(timer.timeout);
break;
default:
return INVALID_MATRIX_ID;
return INVALID_IDENTIFIER_ID;
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -9,7 +9,6 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoolglob/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapoollocal/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/housekeeping/*.cpp)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp)

View File

@ -0,0 +1,12 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
arrayprinter.cpp
AsciiConverter.cpp
CRC.cpp
DleEncoder.cpp
PeriodicOperationDivider.cpp
timevalOperations.cpp
Type.cpp
)
add_subdirectory(math)

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

@ -0,0 +1,4 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
QuaternionOperations.cpp
)

View File

@ -2,7 +2,12 @@
#define TIMEVALOPERATIONS_H_
#include <stdint.h>
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/time.h>
#endif
timeval& operator+=(timeval& lhs, const timeval& rhs);

6
health/CMakeLists.txt Normal file
View File

@ -0,0 +1,6 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
HealthHelper.cpp
HealthMessage.cpp
HealthTable.cpp
)

View File

@ -0,0 +1,5 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
HousekeepingMessage.cpp
PeriodicHousekeepingHelper.cpp
)

View File

@ -0,0 +1,4 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
InternalErrorReporter.cpp
)

View File

@ -0,0 +1,34 @@
#ifndef FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
#define FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/datapoollocal/LocalPoolVariable.h>
enum errorPoolIds {
TM_HITS,
QUEUE_HITS,
STORE_HITS
};
class InternalErrorDataset: public StaticLocalDataSet<3 * sizeof(uint32_t)> {
public:
static constexpr uint8_t ERROR_SET_ID = 0;
InternalErrorDataset(HasLocalDataPoolIF* owner):
StaticLocalDataSet(owner, ERROR_SET_ID) {}
InternalErrorDataset(object_id_t objectId):
StaticLocalDataSet(sid_t(objectId , ERROR_SET_ID)) {}
lp_var_t<uint32_t> tmHits = lp_var_t<uint32_t>(hkManager->getOwner(),
TM_HITS, this);
lp_var_t<uint32_t> queueHits = lp_var_t<uint32_t>(hkManager->getOwner(),
QUEUE_HITS, this);
lp_var_t<uint32_t> storeHits = lp_var_t<uint32_t>(hkManager->getOwner(),
STORE_HITS, this);
};
#endif /* FSFW_INTERNALERROR_INTERNALERRORDATASET_H_ */

View File

@ -1,16 +1,16 @@
#include "../datapoolglob/GlobalDataSet.h"
#include "InternalErrorReporter.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../ipc/QueueFactory.h"
#include "../ipc/MutexFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId,
uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) :
SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId),
tmPoolId(tmPoolId),storePoolId(storePoolId), queueHits(0), tmHits(0),
storeHits(0) {
uint32_t messageQueueDepth): SystemObject(setObjectId),
commandQueue(QueueFactory::instance()->
createMessageQueue(messageQueueDepth)),
poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
mutex = MutexFactory::instance()->createMutex();
}
@ -18,28 +18,42 @@ InternalErrorReporter::~InternalErrorReporter() {
MutexFactory::instance()->deleteMutex(mutex);
}
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
this->diagnosticPrintout = enable;
}
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
GlobDataSet mySet;
gp_uint32_t queueHitsInPool(queuePoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
gp_uint32_t tmHitsInPool(tmPoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
gp_uint32_t storeHitsInPool(storePoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
mySet.read();
internalErrorDataset.read(INTERNAL_ERROR_MUTEX_TIMEOUT);
uint32_t newQueueHits = getAndResetQueueHits();
uint32_t newTmHits = getAndResetTmHits();
uint32_t newStoreHits = getAndResetStoreHits();
queueHitsInPool.value += newQueueHits;
tmHitsInPool.value += newTmHits;
storeHitsInPool.value += newStoreHits;
#ifdef DEBUG
if(diagnosticPrintout) {
if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
sif::debug << "InternalErrorReporter::performOperation: Errors "
<< "occured!" << std::endl;
sif::debug << "Queue errors: " << newQueueHits << std::endl;
sif::debug << "TM errors: " << newTmHits << std::endl;
sif::debug << "Store errors: " << newStoreHits << std::endl;
}
}
#endif
mySet.commit(PoolVariableIF::VALID);
internalErrorDataset.queueHits.value += newQueueHits;
internalErrorDataset.storeHits.value += newStoreHits;
internalErrorDataset.tmHits.value += newTmHits;
internalErrorDataset.commit(INTERNAL_ERROR_MUTEX_TIMEOUT);
poolManager.performHkOperation();
CommandMessage message;
ReturnValue_t result = commandQueue->receiveMessage(&message);
if(result != MessageQueueIF::EMPTY) {
poolManager.handleHousekeepingMessage(&message);
}
return HasReturnvaluesIF::RETURN_OK;
}
@ -53,7 +67,7 @@ void InternalErrorReporter::lostTm() {
uint32_t InternalErrorReporter::getAndResetQueueHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = queueHits;
queueHits = 0;
mutex->unlockMutex();
@ -62,21 +76,21 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() {
uint32_t InternalErrorReporter::getQueueHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = queueHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementQueueHits() {
mutex->lockMutex(MutexIF::BLOCKING);
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
queueHits++;
mutex->unlockMutex();
}
uint32_t InternalErrorReporter::getAndResetTmHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = tmHits;
tmHits = 0;
mutex->unlockMutex();
@ -85,14 +99,14 @@ uint32_t InternalErrorReporter::getAndResetTmHits() {
uint32_t InternalErrorReporter::getTmHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = tmHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementTmHits() {
mutex->lockMutex(MutexIF::BLOCKING);
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
tmHits++;
mutex->unlockMutex();
}
@ -103,7 +117,7 @@ void InternalErrorReporter::storeFull() {
uint32_t InternalErrorReporter::getAndResetStoreHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = storeHits;
storeHits = 0;
mutex->unlockMutex();
@ -112,14 +126,65 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() {
uint32_t InternalErrorReporter::getStoreHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
value = storeHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementStoreHits() {
mutex->lockMutex(MutexIF::BLOCKING);
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
storeHits++;
mutex->unlockMutex();
}
object_id_t InternalErrorReporter::getObjectId() const {
return SystemObject::getObjectId();
}
MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
return this->commandQueue->getId();
}
ReturnValue_t InternalErrorReporter::initializeLocalDataPool(
LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(errorPoolIds::TM_HITS,
new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS,
new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::STORE_HITS,
new PoolEntry<uint32_t>());
poolManager.subscribeForPeriodicPacket(internalErrorSid, false,
getPeriodicOperationFrequency(), true);
internalErrorDataset.setValidity(true, true);
return HasReturnvaluesIF::RETURN_OK;
}
LocalDataPoolManager* InternalErrorReporter::getHkManagerHandle() {
return &poolManager;
}
dur_millis_t InternalErrorReporter::getPeriodicOperationFrequency() const {
return this->executingTask->getPeriodMs();
}
LocalPoolDataSetBase* InternalErrorReporter::getDataSetHandle(sid_t sid) {
return &internalErrorDataset;
}
void InternalErrorReporter::setTaskIF(PeriodicTaskIF *task) {
this->executingTask = task;
}
ReturnValue_t InternalErrorReporter::initialize() {
ReturnValue_t result = poolManager.initialize(commandQueue);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return SystemObject::initialize();
}
ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() {
return poolManager.initializeAfterTaskCreation();
}

View File

@ -1,37 +1,75 @@
#ifndef INTERNALERRORREPORTER_H_
#define INTERNALERRORREPORTER_H_
#ifndef FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_
#define FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_
#include "InternalErrorReporterIF.h"
#include "../tasks/PeriodicTaskIF.h"
#include "../internalError/InternalErrorDataset.h"
#include "../datapoollocal/LocalDataPoolManager.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../objectmanager/SystemObject.h"
#include "../ipc/MutexIF.h"
/**
* @brief This class is used to track internal errors like lost telemetry,
* failed message sending or a full store.
* @details
* All functions were kept virtual so this class can be extended easily
* to store custom internal errors (e.g. communication interface errors).
*/
class InternalErrorReporter: public SystemObject,
public ExecutableObjectIF,
public InternalErrorReporterIF {
public InternalErrorReporterIF,
public HasLocalDataPoolIF {
public:
InternalErrorReporter(object_id_t setObjectId, uint32_t queuePoolId,
uint32_t tmPoolId, uint32_t storePoolId);
static constexpr uint8_t INTERNAL_ERROR_MUTEX_TIMEOUT = 20;
InternalErrorReporter(object_id_t setObjectId,
uint32_t messageQueueDepth = 5);
/**
* Enable diagnostic printout. Please note that this feature will
* only work if DEBUG has been supplied to the build defines.
* @param enable
*/
void setDiagnosticPrintout(bool enable);
virtual ~InternalErrorReporter();
virtual ReturnValue_t performOperation(uint8_t opCode);
virtual object_id_t getObjectId() const override;
virtual MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t initializeLocalDataPool(
LocalDataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
virtual LocalDataPoolManager* getHkManagerHandle() override;
virtual dur_millis_t getPeriodicOperationFrequency() const override;
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
virtual ReturnValue_t initialize() override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual void queueMessageNotSent();
virtual void lostTm();
virtual void storeFull();
virtual void setTaskIF(PeriodicTaskIF* task) override;
protected:
MutexIF* mutex;
MessageQueueIF* commandQueue;
LocalDataPoolManager poolManager;
uint32_t queuePoolId;
uint32_t tmPoolId;
uint32_t storePoolId;
PeriodicTaskIF* executingTask = nullptr;
MutexIF* mutex = nullptr;
sid_t internalErrorSid;
InternalErrorDataset internalErrorDataset;
uint32_t queueHits;
uint32_t tmHits;
uint32_t storeHits;
bool diagnosticPrintout = true;
uint32_t queueHits = 0;
uint32_t tmHits = 0;
uint32_t storeHits = 0;
uint32_t getAndResetQueueHits();
uint32_t getQueueHits();
@ -47,4 +85,4 @@ protected:
};
#endif /* INTERNALERRORREPORTER_H_ */
#endif /* FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_ */

6
ipc/CMakeLists.txt Normal file
View File

@ -0,0 +1,6 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
CommandMessage.cpp
CommandMessageCleaner.cpp
MessageQueueMessage.cpp
)

View File

@ -1,4 +1,4 @@
#include "../ipc/CommandMessageCleaner.h"
#include "CommandMessageCleaner.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../health/HealthMessage.h"
@ -7,11 +7,12 @@
#include "../monitoring/MonitoringMessage.h"
#include "../subsystem/modes/ModeSequenceMessage.h"
#include "../tmstorage/TmStoreMessage.h"
#include "../housekeeping/HousekeepingMessage.h"
#include "../parameters/ParameterMessage.h"
void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) {
switch(message->getMessageType()){
case messagetypes::MODE_COMMAND:
case messagetypes::MODE_COMMAND:
ModeMessage::clear(message);
break;
case messagetypes::HEALTH_COMMAND:
@ -38,6 +39,9 @@ void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) {
case messagetypes::PARAMETER:
ParameterMessage::clear(message);
break;
case messagetypes::HOUSEKEEPING:
HousekeepingMessage::clear(message);
break;
default:
messagetypes::clearMissionMessage(message);
break;

View File

@ -1,7 +1,7 @@
#ifndef FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_
#define FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_
#include <fsfw/ipc/messageQueueDefinitions.h>
#include "messageQueueDefinitions.h"
#include <cstddef>
#include <cstdint>

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_IPC_MUTEXFACTORY_H_
#define FRAMEWORK_IPC_MUTEXFACTORY_H_
#ifndef FSFW_IPC_MUTEXFACTORY_H_
#define FSFW_IPC_MUTEXFACTORY_H_
#include "MutexIF.h"
/**
@ -31,4 +31,4 @@ private:
#endif /* FRAMEWORK_IPC_MUTEXFACTORY_H_ */
#endif /* FSFW_IPC_MUTEXFACTORY_H_ */

View File

@ -16,8 +16,8 @@ public:
<< timeoutMs << " milliseconds!" << std::endl;
}
else if(status != HasReturnvaluesIF::RETURN_OK){
sif::error << "MutexHelper: Lock of Mutex failed with code " <<
status << std::endl;
sif::error << "MutexHelper: Lock of Mutex failed with code "
<< status << std::endl;
}
}

View File

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

5
memory/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
MemoryHelper.cpp
MemoryMessage.cpp
)

80
memory/HasFileSystemIF.h Normal file
View File

@ -0,0 +1,80 @@
#ifndef FSFW_MEMORY_HASFILESYSTEMIF_H_
#define FSFW_MEMORY_HASFILESYSTEMIF_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../returnvalues/FwClassIds.h"
#include "../ipc/messageQueueDefinitions.h"
#include <cstddef>
/**
* @brief Generic interface for objects which expose a file system to enable
* message based file handling.
* @author J. Meier, R. Mueller
*/
class HasFileSystemIF {
public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::FILE_SYSTEM;
static constexpr ReturnValue_t FILE_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x00);
static constexpr ReturnValue_t FILE_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static constexpr ReturnValue_t FILE_LOCKED = MAKE_RETURN_CODE(0x02);
static constexpr ReturnValue_t DIRECTORY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
static constexpr ReturnValue_t DIRECTORY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x04);
static constexpr ReturnValue_t DIRECTORY_NOT_EMPTY = MAKE_RETURN_CODE(0x05);
static constexpr ReturnValue_t SEQUENCE_PACKET_MISSING_WRITE = MAKE_RETURN_CODE(0x06); //! P1: Sequence number missing
static constexpr ReturnValue_t SEQUENCE_PACKET_MISSING_READ = MAKE_RETURN_CODE(0x07); //! P1: Sequence number missing
virtual ~HasFileSystemIF() {}
/**
* Function to get the MessageQueueId_t of the implementing object
* @return MessageQueueId_t of the object
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
/**
* Generic function to append to file.
* @param dirname Directory of the file
* @param filename The filename of the file
* @param data The data to write to the file
* @param size The size of the data to write
* @param packetNumber Current packet number. Can be used to verify that
* there are no missing packets.
* @param args Any other arguments which an implementation might require.
* @param bytesWritten Actual bytes written to file
* For large files the write procedure must be split in multiple calls
* to writeToFile
*/
virtual ReturnValue_t appendToFile(const char* repositoryPath,
const char* filename, const uint8_t* data, size_t size,
uint16_t packetNumber, void* args = nullptr) = 0;
/**
* Generic function to create a new file.
* @param repositoryPath
* @param filename
* @param data
* @param size
* @param args Any other arguments which an implementation might require.
* @return
*/
virtual ReturnValue_t createFile(const char* repositoryPath,
const char* filename, const uint8_t* data = nullptr,
size_t size = 0, void* args = nullptr) = 0;
/**
* Generic function to delete a file.
* @param repositoryPath
* @param filename
* @param args
* @return
*/
virtual ReturnValue_t deleteFile(const char* repositoryPath,
const char* filename, void* args = nullptr) = 0;
};
#endif /* FSFW_MEMORY_HASFILESYSTEMIF_H_ */

5
modes/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
ModeHelper.cpp
ModeMessage.cpp
)

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_MONITORING_ABSLIMITMONITOR_H_
#define FRAMEWORK_MONITORING_ABSLIMITMONITOR_H_
#ifndef FSFW_MONITORING_ABSLIMITMONITOR_H_
#define FSFW_MONITORING_ABSLIMITMONITOR_H_
#include "MonitorBase.h"
#include <cmath>
@ -7,9 +7,14 @@
template<typename T>
class AbsLimitMonitor: public MonitorBase<T> {
public:
AbsLimitMonitor(object_id_t reporterId, uint8_t monitorId, uint32_t parameterId,
uint16_t confirmationLimit, T limit, Event violationEvent = MonitoringIF::VALUE_OUT_OF_RANGE, bool aboveIsViolation = true) :
MonitorBase<T>(reporterId, monitorId, parameterId, confirmationLimit), limit(limit), violationEvent(violationEvent), aboveIsViolation(aboveIsViolation) {
AbsLimitMonitor(object_id_t reporterId, uint8_t monitorId,
gp_id_t globalPoolId, uint16_t confirmationLimit, T limit,
Event violationEvent = MonitoringIF::VALUE_OUT_OF_RANGE,
bool aboveIsViolation = true) :
MonitorBase<T>(reporterId, monitorId, globalPoolId,
confirmationLimit),
limit(limit), violationEvent(violationEvent),
aboveIsViolation(aboveIsViolation) {
}
virtual ~AbsLimitMonitor() {
}
@ -32,8 +37,9 @@ public:
const ParameterWrapper *newValues, uint16_t startAtIndex) {
ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId,
parameterId, parameterWrapper, newValues, startAtIndex);
//We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there.
if (result != this->INVALID_MATRIX_ID) {
// We'll reuse the DOMAIN_ID of MonitorReporter,
// as we know the parameterIds used there.
if (result != this->INVALID_IDENTIFIER_ID) {
return result;
}
switch (parameterId) {
@ -41,7 +47,7 @@ public:
parameterWrapper->set(this->limit);
break;
default:
return this->INVALID_MATRIX_ID;
return this->INVALID_IDENTIFIER_ID;
}
return HasReturnvaluesIF::RETURN_OK;
}
@ -59,7 +65,9 @@ protected:
void sendTransitionEvent(T currentValue, ReturnValue_t state) {
switch (state) {
case MonitoringIF::OUT_OF_RANGE:
EventManagerIF::triggerEvent(this->reportingId, violationEvent, this->parameterId);
EventManagerIF::triggerEvent(this->reportingId,
violationEvent, this->globalPoolId.objectId,
this->globalPoolId.localPoolId);
break;
default:
break;
@ -70,4 +78,4 @@ protected:
const bool aboveIsViolation;
};
#endif /* FRAMEWORK_MONITORING_ABSLIMITMONITOR_H_ */
#endif /* FSFW_MONITORING_ABSLIMITMONITOR_H_ */

View File

@ -0,0 +1,5 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
LimitViolationReporter.cpp
MonitoringMessage.cpp
)

View File

@ -1,11 +1,5 @@
/**
* @file HasMonitorsIF.h
* @brief This file defines the HasMonitorsIF class.
* @date 28.07.2014
* @author baetz
*/
#ifndef HASMONITORSIF_H_
#define HASMONITORSIF_H_
#ifndef FSFW_MONITORING_HASMONITORSIF_H_
#define FSFW_MONITORING_HASMONITORSIF_H_
#include "../events/EventReportingProxyIF.h"
#include "../objectmanager/ObjectManagerIF.h"
@ -27,4 +21,4 @@ public:
}
};
#endif /* HASMONITORSIF_H_ */
#endif /* FSFW_MONITORING_HASMONITORSIF_H_ */

View File

@ -12,13 +12,15 @@
template<typename T>
class LimitMonitor: public MonitorBase<T> {
public:
LimitMonitor(object_id_t reporterId, uint8_t monitorId, uint32_t parameterId,
uint16_t confirmationLimit, T lowerLimit, T upperLimit,
Event belowLowEvent = MonitoringIF::VALUE_BELOW_LOW_LIMIT,
LimitMonitor(object_id_t reporterId, uint8_t monitorId,
gp_id_t globalPoolId, uint16_t confirmationLimit, T lowerLimit,
T upperLimit, Event belowLowEvent =
MonitoringIF::VALUE_BELOW_LOW_LIMIT,
Event aboveHighEvent = MonitoringIF::VALUE_ABOVE_HIGH_LIMIT) :
MonitorBase<T>(reporterId, monitorId, parameterId, confirmationLimit), lowerLimit(
lowerLimit), upperLimit(upperLimit), belowLowEvent(
belowLowEvent), aboveHighEvent(aboveHighEvent) {
MonitorBase<T>(reporterId, monitorId, globalPoolId,
confirmationLimit),
lowerLimit(lowerLimit), upperLimit(upperLimit),
belowLowEvent(belowLowEvent), aboveHighEvent(aboveHighEvent) {
}
virtual ~LimitMonitor() {
}
@ -41,7 +43,7 @@ public:
ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId,
parameterId, parameterWrapper, newValues, startAtIndex);
//We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there.
if (result != this->INVALID_MATRIX_ID) {
if (result != this->INVALID_IDENTIFIER_ID) {
return result;
}
switch (parameterId) {
@ -52,12 +54,13 @@ public:
parameterWrapper->set(this->upperLimit);
break;
default:
return this->INVALID_MATRIX_ID;
return this->INVALID_IDENTIFIER_ID;
}
return HasReturnvaluesIF::RETURN_OK;
}
bool isOutOfLimits() {
if (this->oldState == MonitoringIF::ABOVE_HIGH_LIMIT || this->oldState == MonitoringIF::BELOW_LOW_LIMIT) {
if (this->oldState == MonitoringIF::ABOVE_HIGH_LIMIT or
this->oldState == MonitoringIF::BELOW_LOW_LIMIT) {
return true;
} else {
return false;
@ -76,10 +79,12 @@ protected:
void sendTransitionEvent(T currentValue, ReturnValue_t state) {
switch (state) {
case MonitoringIF::BELOW_LOW_LIMIT:
EventManagerIF::triggerEvent(this->reportingId, belowLowEvent, this->parameterId);
EventManagerIF::triggerEvent(this->reportingId, belowLowEvent,
this->globalPoolId.objectId, this->globalPoolId.localPoolId);
break;
case MonitoringIF::ABOVE_HIGH_LIMIT:
EventManagerIF::triggerEvent(this->reportingId, aboveHighEvent, this->parameterId);
EventManagerIF::triggerEvent(this->reportingId, aboveHighEvent,
this->globalPoolId.objectId, this->globalPoolId.localPoolId);
break;
default:
break;

View File

@ -1,39 +1,50 @@
#ifndef MONITORBASE_H_
#define MONITORBASE_H_
#ifndef FSFW_MONITORING_MONITORBASE_H_
#define FSFW_MONITORING_MONITORBASE_H_
#include "LimitViolationReporter.h"
#include "MonitoringIF.h"
#include "MonitoringMessageContent.h"
#include "MonitorReporter.h"
#include "../datapoollocal/LocalPoolVariable.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/PIDReader.h"
#include "../monitoring/LimitViolationReporter.h"
#include "../monitoring/MonitoringIF.h"
#include "../monitoring/MonitoringMessageContent.h"
#include "../monitoring/MonitorReporter.h"
/**
* Base class for monitoring of parameters.
* Can be used anywhere, specializations need to implement checkSample and should override sendTransitionEvent.
* Manages state handling, enabling and disabling of events/reports and forwarding of transition
* reports via MonitorReporter. In addition, it provides default implementations for fetching the parameter sample from
* the data pool and a simple confirmation counter.
* @brief Base class for monitoring of parameters.
* @details
* Can be used anywhere, specializations need to implement checkSample and
* should override sendTransitionEvent.
* Manages state handling, enabling and disabling of events/reports and
* forwarding of transition reports via MonitorReporter.
*
* In addition, it provides default implementations for fetching the
* parameter sample from the data pool and a simple confirmation counter.
*/
template<typename T>
class MonitorBase: public MonitorReporter<T> {
public:
MonitorBase(object_id_t reporterId, uint8_t monitorId,
uint32_t parameterId, uint16_t confirmationLimit) :
MonitorReporter<T>(reporterId, monitorId, parameterId, confirmationLimit) {
gp_id_t globalPoolId, uint16_t confirmationLimit):
MonitorReporter<T>(reporterId, monitorId, globalPoolId,
confirmationLimit),
poolVariable(globalPoolId) {
}
virtual ~MonitorBase() {
}
virtual ReturnValue_t check() {
//1. Fetch sample of type T, return validity.
// 1. Fetch sample of type T, return validity.
T sample = 0;
ReturnValue_t validity = fetchSample(&sample);
//2. If returning from fetch != OK, parameter is invalid. Report (if oldState is != invalidity).
// 2. If returning from fetch != OK, parameter is invalid.
// Report (if oldState is != invalidity).
if (validity != HasReturnvaluesIF::RETURN_OK) {
this->monitorStateIs(validity, sample, 0);
//3. Otherwise, check sample.
} else {
//3. Otherwise, check sample.
this->oldState = doCheck(sample);
}
return this->oldState;
@ -43,20 +54,25 @@ public:
ReturnValue_t currentState = checkSample(sample, &crossedLimit);
return this->monitorStateIs(currentState,sample, crossedLimit);
}
//Abstract or default.
// Abstract or default.
virtual ReturnValue_t checkSample(T sample, T* crossedLimit) = 0;
protected:
virtual ReturnValue_t fetchSample(T* sample) {
GlobDataSet mySet;
PIDReader<T> parameter(this->parameterId, &mySet);
mySet.read();
if (!parameter.isValid()) {
return MonitoringIF::INVALID;
}
*sample = parameter.value;
return HasReturnvaluesIF::RETURN_OK;
ReturnValue_t result = poolVariable.read();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (not poolVariable.isValid()) {
return MonitoringIF::INVALID;
}
*sample = poolVariable.value;
return HasReturnvaluesIF::RETURN_OK;
}
LocalPoolVariable<T> poolVariable;
};
#endif /* MONITORBASE_H_ */
#endif /* FSFW_MONITORING_MONITORBASE_H_ */

View File

@ -1,10 +1,12 @@
#ifndef FRAMEWORK_MONITORING_MONITORREPORTER_H_
#define FRAMEWORK_MONITORING_MONITORREPORTER_H_
#ifndef FSFW_MONITORING_MONITORREPORTER_H_
#define FSFW_MONITORING_MONITORREPORTER_H_
#include "../events/EventManagerIF.h"
#include "LimitViolationReporter.h"
#include "MonitoringIF.h"
#include "MonitoringMessageContent.h"
#include "../datapoollocal/locPoolDefinitions.h"
#include "../events/EventManagerIF.h"
#include "../parameters/HasParametersIF.h"
template<typename T>
@ -14,11 +16,14 @@ public:
static const uint8_t ENABLED = 1;
static const uint8_t DISABLED = 0;
MonitorReporter(object_id_t reportingId, uint8_t monitorId, uint32_t parameterId, uint16_t confirmationLimit) :
monitorId(monitorId), parameterId(parameterId), reportingId(
reportingId), oldState(MonitoringIF::UNCHECKED), reportingEnabled(
ENABLED), eventEnabled(ENABLED), currentCounter(0), confirmationLimit(
confirmationLimit) {
// TODO: Adapt to use SID instead of parameter ID.
MonitorReporter(object_id_t reportingId, uint8_t monitorId,
gp_id_t globalPoolId, uint16_t confirmationLimit) :
monitorId(monitorId), globalPoolId(globalPoolId),
reportingId(reportingId), oldState(MonitoringIF::UNCHECKED),
reportingEnabled(ENABLED), eventEnabled(ENABLED), currentCounter(0),
confirmationLimit(confirmationLimit) {
}
virtual ~MonitorReporter() {
@ -63,7 +68,7 @@ public:
parameterWrapper->set(this->eventEnabled);
break;
default:
return INVALID_MATRIX_ID;
return INVALID_IDENTIFIER_ID;
}
return HasReturnvaluesIF::RETURN_OK;
}
@ -91,7 +96,7 @@ public:
protected:
const uint8_t monitorId;
const uint32_t parameterId;
const gp_id_t globalPoolId;
object_id_t reportingId;
ReturnValue_t oldState;
@ -148,7 +153,8 @@ protected:
case HasReturnvaluesIF::RETURN_OK:
break;
default:
EventManagerIF::triggerEvent(reportingId, MonitoringIF::MONITOR_CHANGED_STATE, state);
EventManagerIF::triggerEvent(reportingId,
MonitoringIF::MONITOR_CHANGED_STATE, state);
break;
}
}
@ -159,14 +165,15 @@ protected:
* @param crossedLimit The limit crossed (if applicable).
* @param state Current state the monitor is in.
*/
virtual void sendTransitionReport(T parameterValue, T crossedLimit, ReturnValue_t state) {
MonitoringReportContent<T> report(parameterId,
virtual void sendTransitionReport(T parameterValue, T crossedLimit,
ReturnValue_t state) {
MonitoringReportContent<T> report(globalPoolId,
parameterValue, crossedLimit, oldState, state);
LimitViolationReporter::sendLimitViolationReport(&report);
}
ReturnValue_t setToState(ReturnValue_t state) {
if (oldState != state && reportingEnabled) {
MonitoringReportContent<T> report(parameterId, 0, 0, oldState,
MonitoringReportContent<T> report(globalPoolId, 0, 0, oldState,
state);
LimitViolationReporter::sendLimitViolationReport(&report);
oldState = state;
@ -175,4 +182,4 @@ protected:
}
};
#endif /* FRAMEWORK_MONITORING_MONITORREPORTER_H_ */
#endif /* FSFW_MONITORING_MONITORREPORTER_H_ */

View File

@ -1,8 +1,8 @@
#ifndef MONITORINGIF_H_
#define MONITORINGIF_H_
#ifndef FSFW_MONITORING_MONITORINGIF_H_
#define FSFW_MONITORING_MONITORINGIF_H_
#include "../memory/HasMemoryIF.h"
#include "MonitoringMessage.h"
#include "../memory/HasMemoryIF.h"
#include "../serialize/SerializeIF.h"
class MonitoringIF : public SerializeIF {
@ -64,4 +64,4 @@ public:
#endif /* MONITORINGIF_H_ */
#endif /* FSFW_MONITORING_MONITORINGIF_H_ */

View File

@ -3,6 +3,7 @@
#include "HasMonitorsIF.h"
#include "MonitoringIF.h"
#include "../datapoollocal/locPoolDefinitions.h"
#include "../objectmanager/ObjectManagerIF.h"
#include "../serialize/SerialBufferAdapter.h"
#include "../serialize/SerialFixedArrayListAdapter.h"
@ -16,12 +17,17 @@ void setStaticFrameworkObjectIds();
}
//PID(uint32_t), TYPE, LIMIT_ID, value,limitValue, previous, later, timestamp
/**
* @brief Does magic.
* @tparam T
*/
template<typename T>
class MonitoringReportContent: public SerialLinkedListAdapter<SerializeIF> {
friend void (Factory::setStaticFrameworkObjectIds)();
public:
SerializeElement<uint8_t> monitorId;
SerializeElement<uint32_t> parameterId;
SerializeElement<uint32_t> parameterObjectId;
SerializeElement<lp_id_t> localPoolId;
SerializeElement<T> parameterValue;
SerializeElement<T> limitValue;
SerializeElement<ReturnValue_t> oldState;
@ -30,20 +36,23 @@ public:
SerializeElement<SerialBufferAdapter<uint8_t>> timestampSerializer;
TimeStamperIF* timeStamper;
MonitoringReportContent() :
SerialLinkedListAdapter<SerializeIF>(
LinkedElement<SerializeIF>::Iterator(&parameterId)), monitorId(0), parameterId(
0), parameterValue(0), limitValue(0), oldState(0), newState(
0), rawTimestamp( { 0 }), timestampSerializer(rawTimestamp,
SerialLinkedListAdapter<SerializeIF>(&parameterObjectId),
monitorId(0), parameterObjectId(0),
localPoolId(0), parameterValue(0),
limitValue(0), oldState(0), newState(0),
rawTimestamp( { 0 }), timestampSerializer(rawTimestamp,
sizeof(rawTimestamp)), timeStamper(NULL) {
setAllNext();
}
MonitoringReportContent(uint32_t setPID, T value, T limitValue,
MonitoringReportContent(gp_id_t globalPoolId, T value, T limitValue,
ReturnValue_t oldState, ReturnValue_t newState) :
SerialLinkedListAdapter<SerializeIF>(
LinkedElement<SerializeIF>::Iterator(&parameterId)), monitorId(0), parameterId(
setPID), parameterValue(value), limitValue(limitValue), oldState(
oldState), newState(newState), timestampSerializer(rawTimestamp,
sizeof(rawTimestamp)), timeStamper(NULL) {
SerialLinkedListAdapter<SerializeIF>(&parameterObjectId),
monitorId(0), parameterObjectId(globalPoolId.objectId),
localPoolId(globalPoolId.localPoolId),
parameterValue(value), limitValue(limitValue),
oldState(oldState), newState(newState),
timestampSerializer(rawTimestamp, sizeof(rawTimestamp)),
timeStamper(NULL) {
setAllNext();
if (checkAndSetStamper()) {
timeStamper->addTimeStamp(rawTimestamp, sizeof(rawTimestamp));
@ -53,16 +62,16 @@ private:
static object_id_t timeStamperId;
void setAllNext() {
parameterId.setNext(&parameterValue);
parameterObjectId.setNext(&parameterValue);
parameterValue.setNext(&limitValue);
limitValue.setNext(&oldState);
oldState.setNext(&newState);
newState.setNext(&timestampSerializer);
}
bool checkAndSetStamper() {
if (timeStamper == NULL) {
if (timeStamper == nullptr) {
timeStamper = objectManager->get<TimeStamperIF>( timeStamperId );
if ( timeStamper == NULL ) {
if ( timeStamper == nullptr ) {
sif::error << "MonitoringReportContent::checkAndSetStamper: "
"Stamper not found!" << std::endl;
return false;

View File

@ -82,7 +82,7 @@ public:
parameterWrapper->set(limit);
break;
default:
return INVALID_MATRIX_ID;
return INVALID_IDENTIFIER_ID;
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -0,0 +1,5 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
ObjectManager.cpp
SystemObject.cpp
)

34
osal/CMakeLists.txt Normal file
View File

@ -0,0 +1,34 @@
# Check the OS_FSFW variable
if(${OS_FSFW} STREQUAL "freertos")
add_subdirectory(FreeRTOS)
elseif(${OS_FSFW} STREQUAL "rtems")
add_subdirectory(rtems)
elseif(${OS_FSFW} STREQUAL "linux")
add_subdirectory(linux)
elseif(${OS_FSFW} STREQUAL "host")
add_subdirectory(host)
if (WIN32)
add_subdirectory(windows)
elseif(UNIX)
target_sources(${LIB_FSFW_NAME}
PUBLIC
linux/TcUnixUdpPollingTask.cpp
linux/TmTcUnixUdpBridge.cpp
)
endif ()
else()
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
# Not set. Assumuing this is a host build, try to determine host OS
if (WIN32)
add_subdirectory(host)
add_subdirectory(windows)
elseif (UNIX)
add_subdirectory(linux)
else ()
# MacOS or other OSes have not been tested yet / are not supported.
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
endif()
endif()

View File

@ -22,9 +22,23 @@
#else
#error "Can't decide which end is which!"
#endif
#else
#ifdef WIN32
#include <Windows.h>
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
#else
#define BYTE_ORDER_SYSTEM BIG_ENDIAN
#endif
#else
#error __BYTE_ORDER__ not defined
#endif
#endif
#endif

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

@ -0,0 +1,30 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
Clock.cpp
FixedTimeslotTask.cpp
BinarySemaphore.cpp
BinSemaphUsingTask.cpp
CountingSemaphore.cpp
CountingSemaphUsingTask.cpp
MessageQueue.cpp
Mutex.cpp
MutexFactory.cpp
PeriodicTask.cpp
QueueFactory.cpp
SemaphoreFactory.cpp
TaskFactory.cpp
Timekeeper.cpp
TaskManagement.cpp
)
# FreeRTOS is required to link the FSFW now. It is recommended to compile
# FreeRTOS as a static library and set LIB_OS_NAME to the target name of the
# library.
if(NOT LIB_OS_NAME)
message(FATAL_ERROR
"FreeRTOS needs to be linked as a target and "
"LIB_OS_NAME needs to be set to the target"
)
endif()
target_link_libraries(${LIB_FSWFW_NAME} ${LIB_OS_NAME})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More