Update to new FSFW release. Minor changes to include path
This commit is contained in:
commit
f094558f11
0
.gitmodules
vendored
Normal file
0
.gitmodules
vendored
Normal file
12
FSFWVersion.h
Normal file
12
FSFWVersion.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef FSFW_DEFAULTCFG_VERSION_H_
|
||||||
|
#define FSFW_DEFAULTCFG_VERSION_H_
|
||||||
|
|
||||||
|
const char* const FSFW_VERSION_NAME = "ASTP";
|
||||||
|
|
||||||
|
#define FSFW_VERSION 0
|
||||||
|
#define FSFW_SUBVERSION 0
|
||||||
|
#define FSFW_REVISION 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSFW_DEFAULTCFG_VERSION_H_ */
|
2
NOTICE
2
NOTICE
@ -4,6 +4,8 @@ The initial version of the Flight Software Framework was developed during
|
|||||||
the Flying Laptop Project by the Universität Stuttgart in coorporation
|
the Flying Laptop Project by the Universität Stuttgart in coorporation
|
||||||
with Airbus Defence and Space GmbH.
|
with Airbus Defence and Space GmbH.
|
||||||
|
|
||||||
|
The supreme FSFW Logo was designed by Markus Koller and Luise Trilsbach.
|
||||||
|
|
||||||
Copyrights in the Flight Software Framework are retained by their contributors.
|
Copyrights in the Flight Software Framework are retained by their contributors.
|
||||||
No copyright assignment is required to contribute to the Flight Software Framework.
|
No copyright assignment is required to contribute to the Flight Software Framework.
|
||||||
|
|
||||||
|
159
README.md
Normal file
159
README.md
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
![FSFW Logo](logo/FSFW_Logo_V3_bw.png)
|
||||||
|
# Flight Software Framework (FSFW)
|
||||||
|
|
||||||
|
The Flight Software Framework is a C++ Object Oriented Framework for unmanned,
|
||||||
|
automated systems like Satellites.
|
||||||
|
|
||||||
|
The initial version of the Flight Software Framework was developed during
|
||||||
|
the Flying Laptop Project by the University of Stuttgart in cooperation
|
||||||
|
with Airbus Defence and Space GmbH.
|
||||||
|
|
||||||
|
## Intended Use
|
||||||
|
|
||||||
|
The framework is designed for systems, which communicate with external devices, perform control loops, receive telecommands and send telemetry, and need to maintain a high level of availability.
|
||||||
|
Therefore, a mode and health system provides control over the states of the software and the controlled devices.
|
||||||
|
In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well.
|
||||||
|
|
||||||
|
The recommended hardware is a microprocessor with more than 2 MB of RAM and 1 MB of non-volatile Memory.
|
||||||
|
For reference, current Applications use a Cobham Gaisler UT699 (LEON3FT), a ISISPACE IOBC or a Zynq-7020 SoC.
|
||||||
|
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
The general structure is driven by the usage of interfaces provided by objects. The FSFW uses C++11 as baseline. The intention behind this is that this C++ Standard should be widely available, even with older compilers.
|
||||||
|
The FSFW uses dynamic allocation during the initialization but provides static containers during runtime.
|
||||||
|
This simplifies the instantiation of objects and allows the usage of some standard containers.
|
||||||
|
Dynamic Allocation after initialization is discouraged and different solutions are provided in the FSFW to achieve that.
|
||||||
|
The fsfw uses Run-time type information.
|
||||||
|
Exceptions are not allowed.
|
||||||
|
|
||||||
|
### Failure Handling
|
||||||
|
|
||||||
|
Functions should return a defined ReturnValue_t to signal to the caller that something is gone wrong.
|
||||||
|
Returnvalues must be unique. For this the function HasReturnvaluesIF::makeReturnCode or the Macro MAKE_RETURN can be used.
|
||||||
|
The CLASS_ID is a unique id for that type of object. See returnvalues/FwClassIds.
|
||||||
|
|
||||||
|
### OSAL
|
||||||
|
The FSFW provides operation system abstraction layers for Linux, FreeRTOS and RTEMS. A independent OSAL called "host" is currently not finished. This aims to be running on windows as well.
|
||||||
|
The OSAL provides periodic tasks, message queues, clocks and Semaphores as well as Mutexes.
|
||||||
|
|
||||||
|
### Core Components
|
||||||
|
|
||||||
|
Clock:
|
||||||
|
* This is a class of static functions that can be used at anytime
|
||||||
|
* Leap Seconds must be set if any time conversions from UTC to other times is used
|
||||||
|
|
||||||
|
ObjectManager (must be created):
|
||||||
|
|
||||||
|
* The component which handles all references. All SystemObjects register at this component.
|
||||||
|
* Any SystemObject needs to have a unique ObjectId. Those can be managed like objects::framework_objects.
|
||||||
|
* A reference to an object can be get by calling the following function. T must be the specific Interface you want to call.
|
||||||
|
A nullptr check of the returning Pointer must be done. This function is based on Run-time type information.
|
||||||
|
|
||||||
|
``` c++
|
||||||
|
template <typename T> T* ObjectManagerIF::get( object_id_t id )
|
||||||
|
|
||||||
|
```
|
||||||
|
* A typical way to create all objects on startup is a handing a static produce function to the ObjectManager on creation.
|
||||||
|
By calling objectManager->initialize() the produce function will be called and all SystemObjects will be initialized afterwards.
|
||||||
|
|
||||||
|
Event Manager:
|
||||||
|
|
||||||
|
* Component which allows routing of events
|
||||||
|
* Other objects can subscribe to specific events, ranges of events or all events of an object.
|
||||||
|
* Subscriptions can be done during runtime but should be done during initialization
|
||||||
|
* Amounts of allowed subscriptions must be configured by setting this parameters:
|
||||||
|
|
||||||
|
``` c++
|
||||||
|
namespace fsfwconfig {
|
||||||
|
//! Configure the allocated pool sizes for the event manager.
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Health Table:
|
||||||
|
|
||||||
|
* A component which holds every health state
|
||||||
|
* Provides a thread safe way to access all health states without the need of message exchanges
|
||||||
|
|
||||||
|
Stores
|
||||||
|
|
||||||
|
* The message based communication can only exchange a few bytes of information inside the message itself. Therefore, additional information can be exchanged with Stores. With this, only the store address must be exchanged in the message.
|
||||||
|
* Internally, the FSFW uses an IPC Store to exchange data between processes. For incoming TCs a TC Store is used. For outgoing TM a TM store is used.
|
||||||
|
* All of them should use the Thread Safe Class storagemanager/PoolManager
|
||||||
|
|
||||||
|
Tasks
|
||||||
|
|
||||||
|
There are two different types of tasks:
|
||||||
|
* The PeriodicTask just executes objects that are of type ExecutableObjectIF in the order of the insertion to the Tasks.
|
||||||
|
* FixedTimeslotTask executes a list of calls in the order of the given list. This is intended for DeviceHandlers, where polling should be in a defined order. An example can be found in defaultcfg/fsfwconfig/pollingSequence
|
||||||
|
|
||||||
|
|
||||||
|
### Static Ids in the framework
|
||||||
|
|
||||||
|
Some parts of the framework use a static routing address for communication.
|
||||||
|
An example setup of ids can be found in the example config in "defaultcft/fsfwconfig/objects/Factory::setStaticFrameworkObjectIds()".
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
Events are tied to objects. EventIds can be generated by calling the Macro MAKE_EVENT. This works analog to the returnvalues.
|
||||||
|
Every object that needs own EventIds has to get a unique SUBSYSTEM_ID.
|
||||||
|
Every SystemObject can call triggerEvent from the parent class.
|
||||||
|
Therefore, event messages contain the specific EventId and the objectId of the object that has triggered.
|
||||||
|
|
||||||
|
### Internal Communication
|
||||||
|
|
||||||
|
Components communicate mostly over Message through Queues.
|
||||||
|
Those queues are created by calling the singleton QueueFactory::instance()->create().
|
||||||
|
|
||||||
|
### External Communication
|
||||||
|
|
||||||
|
The external communication with the mission control system is mostly up to the user implementation.
|
||||||
|
The FSFW provides PUS Services which can be used to but don't need to be used.
|
||||||
|
The services can be seen as a conversion from a TC to a message based communication and back.
|
||||||
|
|
||||||
|
#### CCSDS Frames, CCSDS Space Packets and PUS
|
||||||
|
|
||||||
|
If the communication is based on CCSDS Frames and Space Packets, several classes can be used to distributed the packets to the corresponding services. Those can be found in tcdistribution.
|
||||||
|
If Space Packets are used, a timestamper must be created.
|
||||||
|
An example can be found in the timemanager folder, this uses CCSDSTime::CDS_short.
|
||||||
|
|
||||||
|
#### DeviceHandling
|
||||||
|
|
||||||
|
DeviceHandlers are a core component of the FSFW.
|
||||||
|
The idea is, to have a software counterpart of every physical device to provide a simple mode, health and commanding interface.
|
||||||
|
By separating the underlying Communication Interface with DeviceCommunicationIF, a DH can be tested on different hardware.
|
||||||
|
The DH has mechanisms to monitor the communication with the physical device which allow for FDIR reaction.
|
||||||
|
A standard FDIR component for the DH will be created automatically but can be overwritten by the user.
|
||||||
|
|
||||||
|
#### Modes, Health
|
||||||
|
|
||||||
|
The two interfaces HasModesIF and HasHealthIF provide access for commanding and monitoring of components.
|
||||||
|
On-board Mode Management is implement in hierarchy system.
|
||||||
|
DeviceHandlers and Controllers are the lowest part of the hierarchy.
|
||||||
|
The next layer are Assemblies. Those assemblies act as a component which handle redundancies of handlers.
|
||||||
|
Assemblies share a common core with the next level which are the Subsystems.
|
||||||
|
|
||||||
|
Those Assemblies are intended to act as auto-generated components from a database which describes the subsystem modes.
|
||||||
|
The definitions contain transition and target tables which contain the DH, Assembly and Controller Modes to be commanded.
|
||||||
|
Transition tables contain as many steps as needed to reach the mode from any other mode, e.g. a switch into any higher AOCS mode might first turn on the sensors, than the actuators and the controller as last component.
|
||||||
|
The target table is used to describe the state that is checked continuously by the subsystem.
|
||||||
|
All of this allows System Modes to be generated as Subsystem object as well from the same database.
|
||||||
|
This System contains list of subsystem modes in the transition and target tables.
|
||||||
|
Therefore, it allows a modular system to create system modes and easy commanding of those, because only the highest components must be commanded.
|
||||||
|
|
||||||
|
The health state represents if the component is able to perform its tasks.
|
||||||
|
This can be used to signal the system to avoid using this component instead of a redundant one.
|
||||||
|
The on-board FDIR uses the health state for isolation and recovery.
|
||||||
|
|
||||||
|
## Example config
|
||||||
|
|
||||||
|
A example config can be found in defaultcfg/fsfwconfig.
|
||||||
|
|
||||||
|
## Unit Tests
|
||||||
|
|
||||||
|
Unit Tests are provided in the unittest folder. Those use the catch2 framework but do not include catch2 itself.
|
||||||
|
See README.md in the unittest Folder.
|
@ -1,10 +1,12 @@
|
|||||||
#include "ActionHelper.h"
|
#include "ActionHelper.h"
|
||||||
#include "HasActionsIF.h"
|
#include "HasActionsIF.h"
|
||||||
|
|
||||||
#include "../ipc/MessageQueueSenderIF.h"
|
#include "../ipc/MessageQueueSenderIF.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManagerIF.h"
|
||||||
|
|
||||||
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) :
|
ActionHelper::ActionHelper(HasActionsIF* setOwner,
|
||||||
owner(setOwner), queueToUse(useThisQueue), ipcStore(nullptr) {
|
MessageQueueIF* useThisQueue) :
|
||||||
|
owner(setOwner), queueToUse(useThisQueue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionHelper::~ActionHelper() {
|
ActionHelper::~ActionHelper() {
|
||||||
@ -33,13 +35,15 @@ ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) {
|
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo,
|
||||||
|
ActionId_t commandId, ReturnValue_t result) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
||||||
queueToUse->sendMessage(reportTo, &reply);
|
queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) {
|
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
||||||
|
ReturnValue_t result) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setCompletionReply(&reply, commandId, result);
|
ActionMessage::setCompletionReply(&reply, commandId, result);
|
||||||
queueToUse->sendMessage(reportTo, &reply);
|
queueToUse->sendMessage(reportTo, &reply);
|
||||||
@ -49,8 +53,8 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
|
|||||||
queueToUse = queue;
|
queueToUse = queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
||||||
store_address_t dataAddress) {
|
ActionId_t actionId, store_address_t dataAddress) {
|
||||||
const uint8_t* dataPtr = NULL;
|
const uint8_t* dataPtr = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||||
@ -62,6 +66,11 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act
|
|||||||
}
|
}
|
||||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||||
ipcStore->deleteData(dataAddress);
|
ipcStore->deleteData(dataAddress);
|
||||||
|
if(result == HasActionsIF::EXECUTION_FINISHED) {
|
||||||
|
CommandMessage reply;
|
||||||
|
ActionMessage::setCompletionReply(&reply, actionId, result);
|
||||||
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
|
}
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
@ -86,21 +95,27 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
|||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = data->serialize(&dataPtr, &size, maxSize, SerializeIF::Endianness::BIG);
|
result = data->serialize(&dataPtr, &size, maxSize,
|
||||||
|
SerializeIF::Endianness::BIG);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeAddress);
|
ipcStore->deleteData(storeAddress);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
//We don't need to report the objectId, as we receive REQUESTED data before the completion success message.
|
// We don't need to report the objectId, as we receive REQUESTED data
|
||||||
//True aperiodic replies need to be reported with another dedicated message.
|
// before the completion success message.
|
||||||
|
// True aperiodic replies need to be reported with
|
||||||
|
// another dedicated message.
|
||||||
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
||||||
|
|
||||||
//TODO Service Implementation sucks at the moment
|
// If the sender needs to be hidden, for example to handle packet
|
||||||
|
// as unrequested reply, this will be done here.
|
||||||
if (hideSender) {
|
if (hideSender) {
|
||||||
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
result = queueToUse->sendMessage(reportTo, &reply);
|
result = queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||||
ipcStore->deleteData(storeAddress);
|
ipcStore->deleteData(storeAddress);
|
||||||
}
|
}
|
||||||
@ -109,3 +124,39 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
|||||||
|
|
||||||
void ActionHelper::resetHelper() {
|
void ActionHelper::resetHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||||
|
ActionId_t replyId, const uint8_t *data, size_t dataSize,
|
||||||
|
bool hideSender) {
|
||||||
|
CommandMessage reply;
|
||||||
|
store_address_t storeAddress;
|
||||||
|
ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
ipcStore->deleteData(storeAddress);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't need to report the objectId, as we receive REQUESTED data
|
||||||
|
// before the completion success message.
|
||||||
|
// True aperiodic replies need to be reported with
|
||||||
|
// another dedicated message.
|
||||||
|
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
||||||
|
|
||||||
|
// If the sender needs to be hidden, for example to handle packet
|
||||||
|
// as unrequested reply, this will be done here.
|
||||||
|
if (hideSender) {
|
||||||
|
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = queueToUse->sendMessage(reportTo, &reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||||
|
ipcStore->deleteData(storeAddress);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
#ifndef ACTIONHELPER_H_
|
#ifndef FSFW_ACTION_ACTIONHELPER_H_
|
||||||
#define ACTIONHELPER_H_
|
#define FSFW_ACTION_ACTIONHELPER_H_
|
||||||
|
|
||||||
#include "ActionMessage.h"
|
#include "ActionMessage.h"
|
||||||
#include "../serialize/SerializeIF.h"
|
#include "../serialize/SerializeIF.h"
|
||||||
#include "../ipc/MessageQueueIF.h"
|
#include "../ipc/MessageQueueIF.h"
|
||||||
/**
|
/**
|
||||||
* \brief Action Helper is a helper class which handles action messages
|
* @brief Action Helper is a helper class which handles action messages
|
||||||
*
|
*
|
||||||
* Components which use the HasActionIF this helper can be used to handle the action messages.
|
* Components which use the HasActionIF this helper can be used to handle
|
||||||
* It does handle step messages as well as other answers to action calls. It uses the executeAction function
|
* the action messages.
|
||||||
* of its owner as callback. The call of the initialize function is mandatory and it needs a valid messageQueueIF pointer!
|
* It does handle step messages as well as other answers to action calls.
|
||||||
|
* It uses the executeAction function of its owner as callback.
|
||||||
|
* The call of the initialize function is mandatory and needs a
|
||||||
|
* valid MessageQueueIF pointer!
|
||||||
*/
|
*/
|
||||||
class HasActionsIF;
|
class HasActionsIF;
|
||||||
|
|
||||||
@ -18,7 +21,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Constructor of the action helper
|
* Constructor of the action helper
|
||||||
* @param setOwner Pointer to the owner of the interface
|
* @param setOwner Pointer to the owner of the interface
|
||||||
* @param useThisQueue messageQueue to be used, can be set during initialize function as well.
|
* @param useThisQueue messageQueue to be used, can be set during
|
||||||
|
* initialize function as well.
|
||||||
*/
|
*/
|
||||||
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||||
|
|
||||||
@ -26,28 +30,36 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Function to be called from the owner with a new command message
|
* Function to be called from the owner with a new command message
|
||||||
*
|
*
|
||||||
* If the message is a valid action message the helper will use the executeAction function from HasActionsIF.
|
* If the message is a valid action message the helper will use the
|
||||||
* If the message is invalid or the callback fails a message reply will be send to the sender of the message automatically.
|
* executeAction function from HasActionsIF.
|
||||||
|
* If the message is invalid or the callback fails a message reply will be
|
||||||
|
* send to the sender of the message automatically.
|
||||||
*
|
*
|
||||||
* @param command Pointer to a command message received by the owner
|
* @param command Pointer to a command message received by the owner
|
||||||
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message, CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message,
|
||||||
|
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
||||||
*/
|
*/
|
||||||
ReturnValue_t handleActionMessage(CommandMessage* command);
|
ReturnValue_t handleActionMessage(CommandMessage* command);
|
||||||
/**
|
/**
|
||||||
* Helper initialize function. Must be called before use of any other helper function
|
* Helper initialize function. Must be called before use of any other
|
||||||
* @param queueToUse_ Pointer to the messageQueue to be used, optional if queue was set in constructor
|
* helper function
|
||||||
|
* @param queueToUse_ Pointer to the messageQueue to be used, optional
|
||||||
|
* if queue was set in constructor
|
||||||
* @return Returns RETURN_OK if successful
|
* @return Returns RETURN_OK if successful
|
||||||
*/
|
*/
|
||||||
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
||||||
/**
|
/**
|
||||||
* Function to be called from the owner to send a step message. Success or failure will be determined by the result value.
|
* Function to be called from the owner to send a step message.
|
||||||
|
* Success or failure will be determined by the result value.
|
||||||
*
|
*
|
||||||
* @param step Number of steps already done
|
* @param step Number of steps already done
|
||||||
* @param reportTo The messageQueueId to report the step message to
|
* @param reportTo The messageQueueId to report the step message to
|
||||||
* @param commandId ID of the executed command
|
* @param commandId ID of the executed command
|
||||||
* @param result Result of the execution
|
* @param result Result of the execution
|
||||||
*/
|
*/
|
||||||
void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
void step(uint8_t step, MessageQueueId_t reportTo,
|
||||||
|
ActionId_t commandId,
|
||||||
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
/**
|
/**
|
||||||
* Function to be called by the owner to send a action completion message
|
* Function to be called by the owner to send a action completion message
|
||||||
*
|
*
|
||||||
@ -55,39 +67,59 @@ public:
|
|||||||
* @param commandId ID of the executed command
|
* @param commandId ID of the executed command
|
||||||
* @param result Result of the execution
|
* @param result Result of the execution
|
||||||
*/
|
*/
|
||||||
void finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
void finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
||||||
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
/**
|
/**
|
||||||
* Function to be called by the owner if an action does report data
|
* Function to be called by the owner if an action does report data.
|
||||||
*
|
* Takes a SerializeIF* pointer and serializes it into the IPC store.
|
||||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
* @param reportTo MessageQueueId_t to report the action completion
|
||||||
|
* message to
|
||||||
* @param replyId ID of the executed command
|
* @param replyId ID of the executed command
|
||||||
* @param data Pointer to the data
|
* @param data Pointer to the data
|
||||||
* @return Returns RETURN_OK if successful, otherwise failure code
|
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||||
*/
|
*/
|
||||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false);
|
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
||||||
|
SerializeIF* data, bool hideSender = false);
|
||||||
/**
|
/**
|
||||||
* Function to setup the MessageQueueIF* of the helper. Can be used to set the messageQueueIF* if
|
* Function to be called by the owner if an action does report data.
|
||||||
* message queue is unavailable at construction and initialize but must be setup before first call of other functions.
|
* Takes the raw data and writes it into the IPC store.
|
||||||
|
* @param reportTo MessageQueueId_t to report the action completion
|
||||||
|
* message to
|
||||||
|
* @param replyId ID of the executed command
|
||||||
|
* @param data Pointer to the data
|
||||||
|
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||||
|
*/
|
||||||
|
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
||||||
|
const uint8_t* data, size_t dataSize, bool hideSender = false);
|
||||||
|
/**
|
||||||
|
* Function to setup the MessageQueueIF* of the helper. Can be used to
|
||||||
|
* set the MessageQueueIF* if message queue is unavailable at construction
|
||||||
|
* and initialize but must be setup before first call of other functions.
|
||||||
* @param queue Queue to be used by the helper
|
* @param queue Queue to be used by the helper
|
||||||
*/
|
*/
|
||||||
void setQueueToUse(MessageQueueIF *queue);
|
void setQueueToUse(MessageQueueIF *queue);
|
||||||
protected:
|
protected:
|
||||||
static const uint8_t STEP_OFFSET = 1;//!< Increase of value of this per step
|
//!< Increase of value of this per step
|
||||||
|
static const uint8_t STEP_OFFSET = 1;
|
||||||
HasActionsIF* owner;//!< Pointer to the owner
|
HasActionsIF* owner;//!< Pointer to the owner
|
||||||
MessageQueueIF* queueToUse;//!< Queue to be used as response sender, has to be set with
|
//! Queue to be used as response sender, has to be set in ctor or with
|
||||||
StorageManagerIF* ipcStore;//!< Pointer to an IPC Store, initialized during construction or initialize(MessageQueueIF* queueToUse_) or with setQueueToUse(MessageQueueIF *queue)
|
//! setQueueToUse
|
||||||
|
MessageQueueIF* queueToUse;
|
||||||
|
//! Pointer to an IPC Store, initialized during construction or
|
||||||
|
StorageManagerIF* ipcStore = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Internal function called by handleActionMessage(CommandMessage* command)
|
* Internal function called by handleActionMessage
|
||||||
*
|
|
||||||
* @param commandedBy MessageQueueID of Commander
|
* @param commandedBy MessageQueueID of Commander
|
||||||
* @param actionId ID of action to be done
|
* @param actionId ID of action to be done
|
||||||
* @param dataAddress Address of additional data in IPC Store
|
* @param dataAddress Address of additional data in IPC Store
|
||||||
*/
|
*/
|
||||||
virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
|
virtual void prepareExecution(MessageQueueId_t commandedBy,
|
||||||
|
ActionId_t actionId, store_address_t dataAddress);
|
||||||
/**
|
/**
|
||||||
*
|
* @brief Default implementation is empty.
|
||||||
*/
|
*/
|
||||||
virtual void resetHelper();
|
virtual void resetHelper();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ACTIONHELPER_H_ */
|
#endif /* FSFW_ACTION_ACTIONHELPER_H_ */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef ACTIONMESSAGE_H_
|
#ifndef FSFW_ACTION_ACTIONMESSAGE_H_
|
||||||
#define ACTIONMESSAGE_H_
|
#define FSFW_ACTION_ACTIONMESSAGE_H_
|
||||||
|
|
||||||
#include "../ipc/CommandMessage.h"
|
#include "../ipc/CommandMessage.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManagerIF.h"
|
||||||
@ -18,15 +18,19 @@ public:
|
|||||||
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
|
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
|
||||||
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
||||||
virtual ~ActionMessage();
|
virtual ~ActionMessage();
|
||||||
static void setCommand(CommandMessage* message, ActionId_t fid, store_address_t parameters);
|
static void setCommand(CommandMessage* message, ActionId_t fid,
|
||||||
|
store_address_t parameters);
|
||||||
static ActionId_t getActionId(const CommandMessage* message );
|
static ActionId_t getActionId(const CommandMessage* message );
|
||||||
static store_address_t getStoreId(const CommandMessage* message );
|
static store_address_t getStoreId(const CommandMessage* message );
|
||||||
static void setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
static void setStepReply(CommandMessage* message, ActionId_t fid,
|
||||||
|
uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
static uint8_t getStep(const CommandMessage* message );
|
static uint8_t getStep(const CommandMessage* message );
|
||||||
static ReturnValue_t getReturnCode(const CommandMessage* message );
|
static ReturnValue_t getReturnCode(const CommandMessage* message );
|
||||||
static void setDataReply(CommandMessage* message, ActionId_t actionId, store_address_t data);
|
static void setDataReply(CommandMessage* message, ActionId_t actionId,
|
||||||
static void setCompletionReply(CommandMessage* message, ActionId_t fid, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
store_address_t data);
|
||||||
|
static void setCompletionReply(CommandMessage* message, ActionId_t fid,
|
||||||
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
static void clear(CommandMessage* message);
|
static void clear(CommandMessage* message);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ACTIONMESSAGE_H_ */
|
#endif /* FSFW_ACTION_ACTIONMESSAGE_H_ */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef COMMANDSACTIONSIF_H_
|
#ifndef FSFW_ACTION_COMMANDSACTIONSIF_H_
|
||||||
#define COMMANDSACTIONSIF_H_
|
#define FSFW_ACTION_COMMANDSACTIONSIF_H_
|
||||||
|
|
||||||
#include "CommandActionHelper.h"
|
#include "CommandActionHelper.h"
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
@ -24,11 +24,14 @@ public:
|
|||||||
virtual MessageQueueIF* getCommandQueuePtr() = 0;
|
virtual MessageQueueIF* getCommandQueuePtr() = 0;
|
||||||
protected:
|
protected:
|
||||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
|
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
|
||||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) = 0;
|
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) = 0;
|
ReturnValue_t returnCode) = 0;
|
||||||
|
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||||
|
uint32_t size) = 0;
|
||||||
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
|
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
|
||||||
virtual void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) = 0;
|
virtual void completionFailedReceived(ActionId_t actionId,
|
||||||
|
ReturnValue_t returnCode) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* COMMANDSACTIONSIF_H_ */
|
#endif /* FSFW_ACTION_COMMANDSACTIONSIF_H_ */
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#ifndef FRAMEWORK_ACTION_HASACTIONSIF_H_
|
#ifndef FSFW_ACTION_HASACTIONSIF_H_
|
||||||
#define FRAMEWORK_ACTION_HASACTIONSIF_H_
|
#define FSFW_ACTION_HASACTIONSIF_H_
|
||||||
|
|
||||||
#include "ActionHelper.h"
|
#include "ActionHelper.h"
|
||||||
#include "ActionMessage.h"
|
#include "ActionMessage.h"
|
||||||
#include "SimpleActionHelper.h"
|
#include "SimpleActionHelper.h"
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
#include "../ipc/MessageQueueIF.h"
|
#include "../ipc/MessageQueueIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* Interface for component which uses actions
|
* Interface for component which uses actions
|
||||||
@ -47,14 +48,16 @@ public:
|
|||||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
/**
|
/**
|
||||||
* Execute or initialize the execution of a certain function.
|
* Execute or initialize the execution of a certain function.
|
||||||
* Returning #EXECUTION_FINISHED or a failure code, nothing else needs to
|
* The ActionHelpers will execute this function and behave differently
|
||||||
* be done. When needing more steps, return RETURN_OK and issue steps and
|
* depending on the returnvalue.
|
||||||
* completion manually.
|
*
|
||||||
* One "step failed" or completion report must be issued!
|
* @return
|
||||||
|
* -@c EXECUTION_FINISHED Finish reply will be generated
|
||||||
|
* -@c Not RETURN_OK Step failure reply will be generated
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
||||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
|
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* FRAMEWORK_ACTION_HASACTIONSIF_H_ */
|
#endif /* FSFW_ACTION_HASACTIONSIF_H_ */
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
#include "HasActionsIF.h"
|
#include "HasActionsIF.h"
|
||||||
#include "SimpleActionHelper.h"
|
#include "SimpleActionHelper.h"
|
||||||
|
|
||||||
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
|
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
|
||||||
MessageQueueIF* useThisQueue) :
|
MessageQueueIF* useThisQueue) :
|
||||||
ActionHelper(setOwner, useThisQueue), isExecuting(false), lastCommander(
|
ActionHelper(setOwner, useThisQueue), isExecuting(false) {
|
||||||
0), lastAction(0), stepCount(0) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleActionHelper::~SimpleActionHelper() {
|
SimpleActionHelper::~SimpleActionHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleActionHelper::step(ReturnValue_t result) {
|
void SimpleActionHelper::step(ReturnValue_t result) {
|
||||||
//STEP_OFFESET is subtracted to compensate for adding offset in base method, which is not necessary here.
|
// STEP_OFFESET is subtracted to compensate for adding offset in base
|
||||||
|
// method, which is not necessary here.
|
||||||
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
|
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
|
||||||
result);
|
result);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
#ifndef SIMPLEACTIONHELPER_H_
|
#ifndef FSFW_ACTION_SIMPLEACTIONHELPER_H_
|
||||||
#define SIMPLEACTIONHELPER_H_
|
#define FSFW_ACTION_SIMPLEACTIONHELPER_H_
|
||||||
|
|
||||||
#include "ActionHelper.h"
|
#include "ActionHelper.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This is an action helper which is only able to service one action
|
||||||
|
* at a time but remembers last commander and last action which
|
||||||
|
* simplifies usage
|
||||||
|
*/
|
||||||
class SimpleActionHelper: public ActionHelper {
|
class SimpleActionHelper: public ActionHelper {
|
||||||
public:
|
public:
|
||||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||||
@ -12,13 +17,14 @@ public:
|
|||||||
ReturnValue_t reportData(SerializeIF* data);
|
ReturnValue_t reportData(SerializeIF* data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
|
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||||
|
store_address_t dataAddress);
|
||||||
virtual void resetHelper();
|
virtual void resetHelper();
|
||||||
private:
|
private:
|
||||||
bool isExecuting;
|
bool isExecuting;
|
||||||
MessageQueueId_t lastCommander;
|
MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE;
|
||||||
ActionId_t lastAction;
|
ActionId_t lastAction = 0;
|
||||||
uint8_t stepCount;
|
uint8_t stepCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SIMPLEACTIONHELPER_H_ */
|
#endif /* SIMPLEACTIONHELPER_H_ */
|
||||||
|
@ -9,6 +9,7 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
|
|||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
|
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
|
||||||
const size_t size, bool overwriteOld, size_t maxExcessBytes):
|
const size_t size, bool overwriteOld, size_t maxExcessBytes):
|
||||||
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
|
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
|
||||||
@ -16,6 +17,11 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
|
|||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) {
|
||||||
|
this->fifoDepth = fifoDepth;
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
|
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
|
||||||
MutexIF::TimeoutType timeoutType, dur_millis_t timeout) {
|
MutexIF::TimeoutType timeoutType, dur_millis_t timeout) {
|
||||||
return mutex->lockMutex(timeoutType, timeout);
|
return mutex->lockMutex(timeoutType, timeout);
|
||||||
@ -25,6 +31,25 @@ ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() {
|
|||||||
return mutex->unlockMutex();
|
return mutex->unlockMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MutexIF* SharedRingBuffer::getMutexHandle() const {
|
MutexIF* SharedRingBuffer::getMutexHandle() const {
|
||||||
return mutex;
|
return mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t SharedRingBuffer::initialize() {
|
||||||
|
if(fifoDepth > 0) {
|
||||||
|
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
|
||||||
|
}
|
||||||
|
return SystemObject::initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
|
||||||
|
if(receiveSizesFIFO == nullptr) {
|
||||||
|
// Configuration error.
|
||||||
|
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
|
||||||
|
<< " was not configured to have sizes FIFO, returning nullptr!"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
return receiveSizesFIFO;
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define FSFW_CONTAINER_SHAREDRINGBUFFER_H_
|
#define FSFW_CONTAINER_SHAREDRINGBUFFER_H_
|
||||||
|
|
||||||
#include "SimpleRingBuffer.h"
|
#include "SimpleRingBuffer.h"
|
||||||
|
#include "DynamicFIFO.h"
|
||||||
#include "../ipc/MutexIF.h"
|
#include "../ipc/MutexIF.h"
|
||||||
#include "../objectmanager/SystemObject.h"
|
#include "../objectmanager/SystemObject.h"
|
||||||
#include "../timemanager/Clock.h"
|
#include "../timemanager/Clock.h"
|
||||||
@ -26,6 +27,16 @@ public:
|
|||||||
SharedRingBuffer(object_id_t objectId, const size_t size,
|
SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||||
bool overwriteOld, size_t maxExcessBytes);
|
bool overwriteOld, size_t maxExcessBytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function can be used to add an optional FIFO to the class
|
||||||
|
* @details
|
||||||
|
* This FIFO will be allocated in the initialize function (and will
|
||||||
|
* have a fixed maximum size after that). It can be used to store
|
||||||
|
* values like packet sizes, for example for a shared ring buffer
|
||||||
|
* used by producer/consumer tasks.
|
||||||
|
*/
|
||||||
|
void setToUseReceiveSizeFIFO(size_t fifoDepth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor takes an external buffer with the specified size.
|
* This constructor takes an external buffer with the specified size.
|
||||||
* @param buffer
|
* @param buffer
|
||||||
@ -59,8 +70,21 @@ public:
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
MutexIF* getMutexHandle() const;
|
MutexIF* getMutexHandle() const;
|
||||||
|
|
||||||
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the shared ring buffer was configured to have a sizes FIFO, a handle
|
||||||
|
* to that FIFO can be retrieved with this function.
|
||||||
|
* Do not forget to protect access with a lock if required!
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
DynamicFIFO<size_t>* getReceiveSizesFIFO();
|
||||||
private:
|
private:
|
||||||
MutexIF* mutex = nullptr;
|
MutexIF* mutex = nullptr;
|
||||||
|
|
||||||
|
size_t fifoDepth = 0;
|
||||||
|
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
6
defaultcfg/README.md
Normal file
6
defaultcfg/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# How to setup configuration folder for FSFW
|
||||||
|
|
||||||
|
It is recommended to copy the content of the defaultcfg folder
|
||||||
|
into a config folder which is in the same directory as the Flight
|
||||||
|
Software Framework submodule. After that, the config.mk folder should be
|
||||||
|
included by the primary Makefile with CURRENTPATH set correctly.
|
55
defaultcfg/fsfwconfig/FSFWConfig.h
Normal file
55
defaultcfg/fsfwconfig/FSFWConfig.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef CONFIG_FSFWCONFIG_H_
|
||||||
|
#define CONFIG_FSFWCONFIG_H_
|
||||||
|
|
||||||
|
#include <FSFWVersion.h>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
//! Used to determine whether C++ ostreams are used
|
||||||
|
//! Those can lead to code bloat.
|
||||||
|
#define FSFW_CPP_OSTREAM_ENABLED 1
|
||||||
|
|
||||||
|
//! Reduced printout to further decrese code size
|
||||||
|
//! Be careful, this also turns off most diagnostic prinouts!
|
||||||
|
#define FSFW_REDUCED_PRINTOUT 0
|
||||||
|
|
||||||
|
//! Can be used to enable debugging printouts for developing the FSFW
|
||||||
|
#define FSFW_DEBUGGING 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>
|
||||||
|
#else
|
||||||
|
#define FSFW_DEBUG_OUTPUT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! When using the newlib nano library, C99 support for stdio facilities
|
||||||
|
//! will not be provided. This define should be set to 1 if this is the case.
|
||||||
|
#define FSFW_NO_C99_IO 1
|
||||||
|
|
||||||
|
namespace fsfwconfig {
|
||||||
|
//! Default timestamp size. The default timestamp will be an eight byte CDC
|
||||||
|
//! short timestamp.
|
||||||
|
static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8;
|
||||||
|
|
||||||
|
//! Configure the allocated pool sizes for the event manager.
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_FSFWCONFIG_H_ */
|
16
defaultcfg/fsfwconfig/OBSWConfig.h
Normal file
16
defaultcfg/fsfwconfig/OBSWConfig.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef CONFIG_OBSWCONFIG_H_
|
||||||
|
#define CONFIG_OBSWCONFIG_H_
|
||||||
|
|
||||||
|
#include "OBSWVersion.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
namespace config {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Add mission configuration flags here */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_OBSWCONFIG_H_ */
|
9
defaultcfg/fsfwconfig/OBSWVersion.h
Normal file
9
defaultcfg/fsfwconfig/OBSWVersion.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef CONFIG_VERSION_H_
|
||||||
|
#define CONFIG_VERSION_H_
|
||||||
|
|
||||||
|
/* OBSW versioning can be specified in this file */
|
||||||
|
|
||||||
|
#define OBSW_VERSION 0
|
||||||
|
#define OBSW_SUBVERSION 0
|
||||||
|
|
||||||
|
#endif /* CONFIG_VERSION_H_ */
|
5
defaultcfg/fsfwconfig/devices/logicalAddresses.cpp
Normal file
5
defaultcfg/fsfwconfig/devices/logicalAddresses.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "logicalAddresses.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
18
defaultcfg/fsfwconfig/devices/logicalAddresses.h
Normal file
18
defaultcfg/fsfwconfig/devices/logicalAddresses.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef CONFIG_DEVICES_LOGICALADDRESSES_H_
|
||||||
|
#define CONFIG_DEVICES_LOGICALADDRESSES_H_
|
||||||
|
|
||||||
|
#include <fsfw/devicehandlers/CookieIF.h>
|
||||||
|
#include "../objects/systemObjectList.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used for addresses for physical devices like I2C adresses.
|
||||||
|
*/
|
||||||
|
namespace addresses {
|
||||||
|
/* Logical addresses have uint32_t datatype */
|
||||||
|
enum logicalAddresses: address_t {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CONFIG_DEVICES_LOGICALADDRESSES_H_ */
|
4
defaultcfg/fsfwconfig/devices/powerSwitcherList.cpp
Normal file
4
defaultcfg/fsfwconfig/devices/powerSwitcherList.cpp
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#include "powerSwitcherList.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
12
defaultcfg/fsfwconfig/devices/powerSwitcherList.h
Normal file
12
defaultcfg/fsfwconfig/devices/powerSwitcherList.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef CONFIG_DEVICES_POWERSWITCHERLIST_H_
|
||||||
|
#define CONFIG_DEVICES_POWERSWITCHERLIST_H_
|
||||||
|
|
||||||
|
namespace switches {
|
||||||
|
/* Switches are uint8_t datatype and go from 0 to 255 */
|
||||||
|
enum switcherList {
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CONFIG_DEVICES_POWERSWITCHERLIST_H_ */
|
18
defaultcfg/fsfwconfig/events/subsystemIdRanges.h
Normal file
18
defaultcfg/fsfwconfig/events/subsystemIdRanges.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_
|
||||||
|
#define CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fsfw/events/fwSubsystemIdRanges.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Custom subsystem IDs can be added here
|
||||||
|
* @details
|
||||||
|
* Subsystem IDs are used to create unique events.
|
||||||
|
*/
|
||||||
|
namespace SUBSYSTEM_ID {
|
||||||
|
enum: uint8_t {
|
||||||
|
SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_ */
|
15
defaultcfg/fsfwconfig/fsfwconfig.mk
Normal file
15
defaultcfg/fsfwconfig/fsfwconfig.mk
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
CXXSRC += $(wildcard $(CURRENTPATH)/ipc/*.cpp)
|
||||||
|
CXXSRC += $(wildcard $(CURRENTPATH)/objects/*.cpp)
|
||||||
|
CXXSRC += $(wildcard $(CURRENTPATH)/pollingsequence/*.cpp)
|
||||||
|
CXXSRC += $(wildcard $(CURRENTPATH)/events/*.cpp)
|
||||||
|
CXXSRC += $(wildcard $(CURRENTPATH)/tmtc/*.cpp)
|
||||||
|
CXXSRC += $(wildcard $(CURRENTPATH)/devices/*.cpp)
|
||||||
|
|
||||||
|
INCLUDES += $(CURRENTPATH)
|
||||||
|
INCLUDES += $(CURRENTPATH)/objects
|
||||||
|
INCLUDES += $(CURRENTPATH)/returnvalues
|
||||||
|
INCLUDES += $(CURRENTPATH)/tmtc
|
||||||
|
INCLUDES += $(CURRENTPATH)/events
|
||||||
|
INCLUDES += $(CURRENTPATH)/devices
|
||||||
|
INCLUDES += $(CURRENTPATH)/pollingsequence
|
||||||
|
INCLUDES += $(CURRENTPATH)/ipc
|
12
defaultcfg/fsfwconfig/ipc/missionMessageTypes.cpp
Normal file
12
defaultcfg/fsfwconfig/ipc/missionMessageTypes.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "missionMessageTypes.h"
|
||||||
|
|
||||||
|
#include <fsfw/ipc/CommandMessageIF.h>
|
||||||
|
|
||||||
|
void messagetypes::clearMissionMessage(CommandMessage* message) {
|
||||||
|
switch(message->getMessageType()) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
21
defaultcfg/fsfwconfig/ipc/missionMessageTypes.h
Normal file
21
defaultcfg/fsfwconfig/ipc/missionMessageTypes.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef CONFIG_IPC_MISSIONMESSAGETYPES_H_
|
||||||
|
#define CONFIG_IPC_MISSIONMESSAGETYPES_H_
|
||||||
|
|
||||||
|
#include <fsfw/ipc/CommandMessage.h>
|
||||||
|
#include <fsfw/ipc/FwMessageTypes.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom command messages are specified here.
|
||||||
|
* Most messages needed to use FSFW are already located in
|
||||||
|
* <fsfw/ipc/FwMessageTypes.h>
|
||||||
|
* @param message Generic Command Message
|
||||||
|
*/
|
||||||
|
namespace messagetypes {
|
||||||
|
enum CustomMessageTypes {
|
||||||
|
MISSION_MESSAGE_TYPE_START = FW_MESSAGES_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
void clearMissionMessage(CommandMessage* message);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_IPC_MISSIONMESSAGETYPES_H_ */
|
54
defaultcfg/fsfwconfig/objects/Factory.cpp
Normal file
54
defaultcfg/fsfwconfig/objects/Factory.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "Factory.h"
|
||||||
|
#include "../tmtc/apid.h"
|
||||||
|
#include "../tmtc/pusIds.h"
|
||||||
|
#include "../objects/systemObjectList.h"
|
||||||
|
#include "../devices/logicalAddresses.h"
|
||||||
|
#include "../devices/powerSwitcherList.h"
|
||||||
|
|
||||||
|
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||||
|
#include <fsfw/events/EventManager.h>
|
||||||
|
#include <fsfw/health/HealthTable.h>
|
||||||
|
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
|
||||||
|
#include <fsfw/tmtcservices/CommandingServiceBase.h>
|
||||||
|
#include <fsfw/tmtcservices/PusServiceBase.h>
|
||||||
|
#include <internalError/InternalErrorReporter.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class should be used to create all system objects required for
|
||||||
|
* the on-board software, using the object ID list from the configuration
|
||||||
|
* folder.
|
||||||
|
*
|
||||||
|
* The objects are registered in the internal object manager automatically.
|
||||||
|
* This is used later to add objects to tasks.
|
||||||
|
*
|
||||||
|
* This file also sets static framework IDs.
|
||||||
|
*
|
||||||
|
* Framework objects are created first.
|
||||||
|
* @ingroup init
|
||||||
|
*/
|
||||||
|
void Factory::produce(void) {
|
||||||
|
setStaticFrameworkObjectIds();
|
||||||
|
new EventManager(objects::EVENT_MANAGER);
|
||||||
|
new HealthTable(objects::HEALTH_TABLE);
|
||||||
|
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Factory::setStaticFrameworkObjectIds() {
|
||||||
|
PusServiceBase::packetSource = objects::NO_OBJECT;
|
||||||
|
PusServiceBase::packetDestination = objects::NO_OBJECT;
|
||||||
|
|
||||||
|
CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT;
|
||||||
|
CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT;
|
||||||
|
|
||||||
|
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
|
||||||
|
|
||||||
|
DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
||||||
|
DeviceHandlerBase::rawDataReceiverId = objects::PUS_SERVICE_2_DEVICE_ACCESS;
|
||||||
|
|
||||||
|
DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
|
||||||
|
|
||||||
|
TmPacketStored::timeStamperId = objects::NO_OBJECT;
|
||||||
|
}
|
||||||
|
|
17
defaultcfg/fsfwconfig/objects/Factory.h
Normal file
17
defaultcfg/fsfwconfig/objects/Factory.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef FACTORY_H_
|
||||||
|
#define FACTORY_H_
|
||||||
|
|
||||||
|
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace Factory {
|
||||||
|
/**
|
||||||
|
* @brief Creates all SystemObject elements which are persistent
|
||||||
|
* during execution.
|
||||||
|
*/
|
||||||
|
void produce();
|
||||||
|
void setStaticFrameworkObjectIds();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FACTORY_H_ */
|
16
defaultcfg/fsfwconfig/objects/systemObjectList.h
Normal file
16
defaultcfg/fsfwconfig/objects/systemObjectList.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
|
||||||
|
#define CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fsfw/objectmanager/frameworkObjects.h>
|
||||||
|
|
||||||
|
// The objects will be instantiated in the ID order
|
||||||
|
namespace objects {
|
||||||
|
enum sourceObjects: uint32_t {
|
||||||
|
/* All addresses between start and end are reserved for the FSFW */
|
||||||
|
FSFW_CONFIG_RESERVED_START = PUS_SERVICE_1_VERIFICATION,
|
||||||
|
FSFW_CONFIG_RESERVED_END = TM_STORE
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* BSP_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */
|
@ -0,0 +1,23 @@
|
|||||||
|
#include "PollingSequenceFactory.h"
|
||||||
|
|
||||||
|
#include <fsfw/serviceinterface/ServiceInterfaceStream.h>
|
||||||
|
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||||
|
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
|
||||||
|
|
||||||
|
ReturnValue_t pst::pollingSequenceInitDefault(
|
||||||
|
FixedTimeslotTaskIF *thisSequence) {
|
||||||
|
/* Length of a communication cycle */
|
||||||
|
uint32_t length = thisSequence->getPeriodMs();
|
||||||
|
|
||||||
|
/* Add polling sequence table here */
|
||||||
|
|
||||||
|
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sif::error << "pst::pollingSequenceInitDefault: Sequence invalid!"
|
||||||
|
<< std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef POLLINGSEQUENCEFACTORY_H_
|
||||||
|
#define POLLINGSEQUENCEFACTORY_H_
|
||||||
|
|
||||||
|
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||||
|
|
||||||
|
class FixedTimeslotTaskIF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All device handlers are scheduled by adding them into Polling Sequence Tables (PST)
|
||||||
|
* to satisfy stricter timing requirements of device communication,
|
||||||
|
* A device handler has four different communication steps:
|
||||||
|
* 1. DeviceHandlerIF::SEND_WRITE -> Send write via interface
|
||||||
|
* 2. DeviceHandlerIF::GET_WRITE -> Get confirmation for write
|
||||||
|
* 3. DeviceHandlerIF::SEND_READ -> Send read request
|
||||||
|
* 4. DeviceHandlerIF::GET_READ -> Read from interface
|
||||||
|
* The PST specifies precisely when the respective ComIF functions are called
|
||||||
|
* during the communication cycle time.
|
||||||
|
* The task is created using the FixedTimeslotTaskIF,
|
||||||
|
* which utilises the underlying Operating System Abstraction Layer (OSAL)
|
||||||
|
*
|
||||||
|
* @param thisSequence FixedTimeslotTaskIF * object is passed inside the Factory class when creating the PST
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
namespace pst {
|
||||||
|
|
||||||
|
/* Default PST */
|
||||||
|
ReturnValue_t pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* POLLINGSEQUENCEINIT_H_ */
|
16
defaultcfg/fsfwconfig/returnvalues/classIds.h
Normal file
16
defaultcfg/fsfwconfig/returnvalues/classIds.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef CONFIG_RETURNVALUES_CLASSIDS_H_
|
||||||
|
#define CONFIG_RETURNVALUES_CLASSIDS_H_
|
||||||
|
|
||||||
|
#include <fsfw/returnvalues/FwClassIds.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CLASS_ID defintions which are required for custom returnvalues.
|
||||||
|
*/
|
||||||
|
namespace CLASS_ID {
|
||||||
|
enum {
|
||||||
|
MISSION_CLASS_ID_START = FW_CLASS_ID_COUNT,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CONFIG_RETURNVALUES_CLASSIDS_H_ */
|
18
defaultcfg/fsfwconfig/tmtc/apid.h
Normal file
18
defaultcfg/fsfwconfig/tmtc/apid.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef CONFIG_TMTC_APID_H_
|
||||||
|
#define CONFIG_TMTC_APID_H_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application Process Definition: entity, uniquely identified by an
|
||||||
|
* application process ID (APID), capable of generating telemetry source
|
||||||
|
* packets and receiving telecommand packets.
|
||||||
|
*
|
||||||
|
* Chose APID(s) for mission and define it here.
|
||||||
|
*/
|
||||||
|
namespace apid {
|
||||||
|
static const uint16_t DEFAULT_APID = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CONFIG_TMTC_APID_H_ */
|
23
defaultcfg/fsfwconfig/tmtc/pusIds.h
Normal file
23
defaultcfg/fsfwconfig/tmtc/pusIds.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef CONFIG_TMTC_PUSIDS_HPP_
|
||||||
|
#define CONFIG_TMTC_PUSIDS_HPP_
|
||||||
|
|
||||||
|
namespace pus {
|
||||||
|
enum Ids: uint8_t {
|
||||||
|
PUS_SERVICE_1 = 1,
|
||||||
|
PUS_SERVICE_2 = 2,
|
||||||
|
PUS_SERVICE_3 = 3,
|
||||||
|
PUS_SERVICE_5 = 5,
|
||||||
|
PUS_SERVICE_6 = 6,
|
||||||
|
PUS_SERVICE_8 = 8,
|
||||||
|
PUS_SERVICE_9 = 9,
|
||||||
|
PUS_SERVICE_11 = 11,
|
||||||
|
PUS_SERVICE_17 = 17,
|
||||||
|
PUS_SERVICE_19 = 19,
|
||||||
|
PUS_SERVICE_20 = 20,
|
||||||
|
PUS_SERVICE_23 = 23,
|
||||||
|
PUS_SERVICE_200 = 200,
|
||||||
|
PUS_SERVICE_201 = 201,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CONFIG_TMTC_PUSIDS_HPP_ */
|
@ -1235,7 +1235,7 @@ void DeviceHandlerBase::buildInternalCommand(void) {
|
|||||||
if (result == BUSY) {
|
if (result == BUSY) {
|
||||||
//so we can track misconfigurations
|
//so we can track misconfigurations
|
||||||
sif::debug << std::hex << getObjectId()
|
sif::debug << std::hex << getObjectId()
|
||||||
<< ": DHB::buildInternalCommand: Busy" << std::endl;
|
<< ": DHB::buildInternalCommand: Busy" << std::dec << std::endl;
|
||||||
result = NOTHING_TO_SEND; //no need to report this
|
result = NOTHING_TO_SEND; //no need to report this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "EventManager.h"
|
#include "EventManager.h"
|
||||||
#include "EventMessage.h"
|
#include "EventMessage.h"
|
||||||
|
#include <FSFWConfig.h>
|
||||||
|
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||||
#include "../ipc/QueueFactory.h"
|
#include "../ipc/QueueFactory.h"
|
||||||
#include "../ipc/MutexFactory.h"
|
#include "../ipc/MutexFactory.h"
|
||||||
@ -12,8 +14,10 @@ const uint16_t EventManager::POOL_SIZES[N_POOLS] = {
|
|||||||
// objects registering for certain events.
|
// objects registering for certain events.
|
||||||
// Each listener requires 1 or 2 EventIdMatcher and 1 or 2 ReportRangeMatcher.
|
// 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.
|
// So a good guess is 75 to a max of 100 pools required for each, which fits well.
|
||||||
// SHOULDDO: Shouldn't this be in the config folder and passed via ctor?
|
const uint16_t EventManager::N_ELEMENTS[N_POOLS] = {
|
||||||
const uint16_t EventManager::N_ELEMENTS[N_POOLS] = { 240, 120, 120 };
|
fsfwconfig::FSFW_EVENTMGMR_MATCHTREE_NODES ,
|
||||||
|
fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS,
|
||||||
|
fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS };
|
||||||
|
|
||||||
EventManager::EventManager(object_id_t setObjectId) :
|
EventManager::EventManager(object_id_t setObjectId) :
|
||||||
SystemObject(setObjectId),
|
SystemObject(setObjectId),
|
||||||
|
13
fsfw.mk
13
fsfw.mk
@ -28,12 +28,25 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp)
|
|||||||
# select the OS
|
# select the OS
|
||||||
ifeq ($(OS_FSFW),rtems)
|
ifeq ($(OS_FSFW),rtems)
|
||||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp)
|
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp)
|
||||||
|
|
||||||
else ifeq ($(OS_FSFW),linux)
|
else ifeq ($(OS_FSFW),linux)
|
||||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp)
|
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp)
|
||||||
|
|
||||||
else ifeq ($(OS_FSFW),freeRTOS)
|
else ifeq ($(OS_FSFW),freeRTOS)
|
||||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp)
|
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp)
|
||||||
|
|
||||||
else ifeq ($(OS_FSFW),host)
|
else ifeq ($(OS_FSFW),host)
|
||||||
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp)
|
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp)
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/windows/*.cpp)
|
||||||
|
else
|
||||||
|
# For now, the linux UDP bridge sources needs to be included manually by upper makefile
|
||||||
|
# for host OS because we can't be sure the OS is linux.
|
||||||
|
# Following lines can be used to do this:
|
||||||
|
# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TcUnixUdpPollingTask.cpp
|
||||||
|
# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TmTcUnixUdpBridge.cpp
|
||||||
|
endif
|
||||||
|
|
||||||
else
|
else
|
||||||
$(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host)
|
$(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host)
|
||||||
endif
|
endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef HASHEALTHIF_H_
|
#ifndef FSFW_HEALTH_HASHEALTHIF_H_
|
||||||
#define HASHEALTHIF_H_
|
#define FSFW_HEALTH_HASHEALTHIF_H_
|
||||||
|
|
||||||
#include "../events/Event.h"
|
#include "../events/Event.h"
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
@ -8,9 +8,13 @@
|
|||||||
class HasHealthIF {
|
class HasHealthIF {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef enum {
|
enum HealthState: uint8_t {
|
||||||
HEALTHY = 1, FAULTY = 0, EXTERNAL_CONTROL = 2, NEEDS_RECOVERY = 3, PERMANENT_FAULTY = 4
|
HEALTHY = 1,
|
||||||
} HealthState;
|
FAULTY = 0,
|
||||||
|
EXTERNAL_CONTROL = 2,
|
||||||
|
NEEDS_RECOVERY = 3,
|
||||||
|
PERMANENT_FAULTY = 4
|
||||||
|
};
|
||||||
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
|
||||||
static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
|
||||||
@ -31,20 +35,17 @@ public:
|
|||||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the Health State
|
* @brief Set the Health State
|
||||||
*
|
|
||||||
* The parent will be informed, if the Health changes
|
* The parent will be informed, if the Health changes
|
||||||
*
|
|
||||||
* @param health
|
* @param health
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t setHealth(HealthState health) = 0;
|
virtual ReturnValue_t setHealth(HealthState health) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get Health State
|
* @brief Get Health State
|
||||||
*
|
|
||||||
* @return Health State of the object
|
* @return Health State of the object
|
||||||
*/
|
*/
|
||||||
virtual HasHealthIF::HealthState getHealth() = 0;
|
virtual HasHealthIF::HealthState getHealth() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HASHEALTHIF_H_ */
|
#endif /* FSFW_HEALTH_HASHEALTHIF_H_ */
|
||||||
|
@ -12,13 +12,15 @@
|
|||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for Objects that implement HasHealthIF
|
* @brief Helper class for Objects that implement HasHealthIF
|
||||||
|
* @details
|
||||||
|
* It takes care of registering with the Health Table as well as handling
|
||||||
|
* health commands (including replying to the sender) and updating
|
||||||
|
* the Health Table.
|
||||||
*
|
*
|
||||||
* It takes care of registering with the Health Table as well as handling health commands
|
* If a parent is set in the ctor, the parent will be informed with a
|
||||||
* (including replying to the sender) and updating the Health Table.
|
* @c HEALTH_INFO message about changes in the health state.
|
||||||
*
|
* Note that a @c HEALTH_INFO is only generated if the Health
|
||||||
* If a parent is set in the ctor, the parent will be informed with a @c HEALTH_INFO message
|
|
||||||
* about changes in the health state. Note that a @c HEALTH_INFO is only generated if the Health
|
|
||||||
* changes, not for all @c HEALTH_SET commands received.
|
* changes, not for all @c HEALTH_SET commands received.
|
||||||
*
|
*
|
||||||
* It does NOT handle @c HEALTH_INFO messages
|
* It does NOT handle @c HEALTH_INFO messages
|
||||||
@ -27,10 +29,9 @@ class HealthHelper {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ctor
|
|
||||||
*
|
|
||||||
* @param owner
|
* @param owner
|
||||||
* @param objectId the object Id to use when communication with the HealthTable
|
* @param objectId The object Id to use when communication with
|
||||||
|
* the HealthTable
|
||||||
*/
|
*/
|
||||||
HealthHelper(HasHealthIF* owner, object_id_t objectId);
|
HealthHelper(HasHealthIF* owner, object_id_t objectId);
|
||||||
|
|
||||||
@ -57,7 +58,8 @@ public:
|
|||||||
* @param message
|
* @param message
|
||||||
* @return
|
* @return
|
||||||
* -@c RETURN_OK if the message was handled
|
* -@c RETURN_OK if the message was handled
|
||||||
* -@c RETURN_FAILED if the message could not be handled (ie it was not a @c HEALTH_SET or @c HEALTH_READ message)
|
* -@c RETURN_FAILED if the message could not be handled
|
||||||
|
* (ie it was not a @c HEALTH_SET or @c HEALTH_READ message)
|
||||||
*/
|
*/
|
||||||
ReturnValue_t handleHealthCommand(CommandMessage *message);
|
ReturnValue_t handleHealthCommand(CommandMessage *message);
|
||||||
|
|
||||||
@ -78,15 +80,18 @@ public:
|
|||||||
HasHealthIF::HealthState getHealth();
|
HasHealthIF::HealthState getHealth();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parentQueue the Queue id of the parent object. Set to 0 if no parent present
|
* @param parentQueue The queue ID of the parent object.
|
||||||
|
* Set to 0 if no parent present
|
||||||
*/
|
*/
|
||||||
void setParentQueue(MessageQueueId_t parentQueue);
|
void setParentQueue(MessageQueueId_t parentQueue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param parentQueue the Queue id of the parent object. Set to 0 if no parent present
|
* @param parentQueue The queue ID of the parent object.
|
||||||
|
* Set to 0 if no parent present
|
||||||
* @return
|
* @return
|
||||||
* -@c RETURN_OK if the Health Table was found and the object could be registered
|
* -@c RETURN_OK if the Health Table was found and the object
|
||||||
|
* could be registered
|
||||||
* -@c RETURN_FAILED else
|
* -@c RETURN_FAILED else
|
||||||
*/
|
*/
|
||||||
ReturnValue_t initialize(MessageQueueId_t parentQueue );
|
ReturnValue_t initialize(MessageQueueId_t parentQueue );
|
||||||
@ -110,11 +115,15 @@ private:
|
|||||||
HasHealthIF* owner;
|
HasHealthIF* owner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* if the #parentQueue is not NULL, a @c HEALTH_INFO message will be sent to this queue
|
* if the #parentQueue is not NULL, a @c HEALTH_INFO message
|
||||||
* @param health the health is passed as parameter so that the number of calls to the health table can be minimized
|
* will be sent to this queue
|
||||||
|
* @param health
|
||||||
|
* The health is passed as parameter so that the number of
|
||||||
|
* calls to the health table can be minimized
|
||||||
* @param oldHealth information of the previous health state.
|
* @param oldHealth information of the previous health state.
|
||||||
*/
|
*/
|
||||||
void informParent(HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth);
|
void informParent(HasHealthIF::HealthState health,
|
||||||
|
HasHealthIF::HealthState oldHealth);
|
||||||
|
|
||||||
void handleSetHealthCommand(CommandMessage *message);
|
void handleSetHealthCommand(CommandMessage *message);
|
||||||
};
|
};
|
||||||
|
@ -7,11 +7,13 @@ void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command,
|
|||||||
message->setParameter2(oldHealth);
|
message->setParameter2(oldHealth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command) {
|
void HealthMessage::setHealthMessage(CommandMessage* message,
|
||||||
|
Command_t command) {
|
||||||
message->setCommand(command);
|
message->setCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
HasHealthIF::HealthState HealthMessage::getHealth(const CommandMessage* message) {
|
HasHealthIF::HealthState HealthMessage::getHealth(
|
||||||
|
const CommandMessage* message) {
|
||||||
return (HasHealthIF::HealthState) message->getParameter();
|
return (HasHealthIF::HealthState) message->getParameter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef HEALTHMESSAGE_H_
|
#ifndef FSFW_HEALTH_HEALTHMESSAGE_H_
|
||||||
#define HEALTHMESSAGE_H_
|
#define FSFW_HEALTH_HEALTHMESSAGE_H_
|
||||||
|
|
||||||
#include "HasHealthIF.h"
|
#include "HasHealthIF.h"
|
||||||
#include "../ipc/CommandMessage.h"
|
#include "../ipc/CommandMessage.h"
|
||||||
@ -7,14 +7,20 @@
|
|||||||
class HealthMessage {
|
class HealthMessage {
|
||||||
public:
|
public:
|
||||||
static const uint8_t MESSAGE_ID = messagetypes::HEALTH_COMMAND;
|
static const uint8_t MESSAGE_ID = messagetypes::HEALTH_COMMAND;
|
||||||
static const Command_t HEALTH_SET = MAKE_COMMAND_ID(1);//REPLY_COMMAND_OK/REPLY_REJECTED
|
|
||||||
static const Command_t HEALTH_ANNOUNCE = MAKE_COMMAND_ID(3); //NO REPLY!
|
static const Command_t HEALTH_SET = MAKE_COMMAND_ID(1);
|
||||||
|
// No reply expected, health will be announced as event!
|
||||||
|
static const Command_t HEALTH_ANNOUNCE = MAKE_COMMAND_ID(2);
|
||||||
|
// Same as before, but all objects in health table will
|
||||||
|
// announce their health as events.
|
||||||
|
static const Command_t HEALTH_ANNOUNCE_ALL = MAKE_COMMAND_ID(3);
|
||||||
|
|
||||||
static const Command_t HEALTH_INFO = MAKE_COMMAND_ID(5);
|
static const Command_t HEALTH_INFO = MAKE_COMMAND_ID(5);
|
||||||
static const Command_t REPLY_HEALTH_SET = MAKE_COMMAND_ID(6);
|
static const Command_t REPLY_HEALTH_SET = MAKE_COMMAND_ID(6);
|
||||||
|
|
||||||
static void setHealthMessage(CommandMessage *message, Command_t command,
|
static void setHealthMessage(CommandMessage *message, Command_t command,
|
||||||
HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth = HasHealthIF::FAULTY);
|
HasHealthIF::HealthState health,
|
||||||
|
HasHealthIF::HealthState oldHealth = HasHealthIF::FAULTY);
|
||||||
static void setHealthMessage(CommandMessage *message, Command_t command);
|
static void setHealthMessage(CommandMessage *message, Command_t command);
|
||||||
|
|
||||||
static HasHealthIF::HealthState getHealth(const CommandMessage *message);
|
static HasHealthIF::HealthState getHealth(const CommandMessage *message);
|
||||||
@ -27,4 +33,4 @@ private:
|
|||||||
HealthMessage();
|
HealthMessage();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HEALTHMESSAGE_H_ */
|
#endif /* FSFW_HEALTH_HEALTHMESSAGE_H_ */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "HealthTable.h"
|
#include "HealthTable.h"
|
||||||
#include "../serialize/SerializeAdapter.h"
|
#include "../ipc/MutexHelper.h"
|
||||||
#include "../ipc/MutexFactory.h"
|
#include "../ipc/MutexFactory.h"
|
||||||
|
#include "../serialize/SerializeAdapter.h"
|
||||||
|
|
||||||
HealthTable::HealthTable(object_id_t objectid) :
|
HealthTable::HealthTable(object_id_t objectid) :
|
||||||
SystemObject(objectid) {
|
SystemObject(objectid) {
|
||||||
@ -9,6 +10,12 @@ HealthTable::HealthTable(object_id_t objectid) :
|
|||||||
mapIterator = healthMap.begin();
|
mapIterator = healthMap.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HealthTable::setMutexTimeout(MutexIF::TimeoutType timeoutType,
|
||||||
|
uint32_t timeoutMs) {
|
||||||
|
this->timeoutType = timeoutType;
|
||||||
|
this->mutexTimeoutMs = timeoutMs;
|
||||||
|
}
|
||||||
|
|
||||||
HealthTable::~HealthTable() {
|
HealthTable::~HealthTable() {
|
||||||
MutexFactory::instance()->deleteMutex(mutex);
|
MutexFactory::instance()->deleteMutex(mutex);
|
||||||
}
|
}
|
||||||
@ -18,74 +25,63 @@ ReturnValue_t HealthTable::registerObject(object_id_t object,
|
|||||||
if (healthMap.count(object) != 0) {
|
if (healthMap.count(object) != 0) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
healthMap.insert(
|
healthMap.emplace(object, initilialState);
|
||||||
std::pair<object_id_t, HasHealthIF::HealthState>(object,
|
|
||||||
initilialState));
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HealthTable::setHealth(object_id_t object,
|
void HealthTable::setHealth(object_id_t object,
|
||||||
HasHealthIF::HealthState newState) {
|
HasHealthIF::HealthState newState) {
|
||||||
mutex->lockMutex(MutexIF::BLOCKING);
|
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||||
HealthMap::iterator iter = healthMap.find(object);
|
HealthMap::iterator iter = healthMap.find(object);
|
||||||
if (iter != healthMap.end()) {
|
if (iter != healthMap.end()) {
|
||||||
iter->second = newState;
|
iter->second = newState;
|
||||||
}
|
}
|
||||||
mutex->unlockMutex();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HasHealthIF::HealthState HealthTable::getHealth(object_id_t object) {
|
HasHealthIF::HealthState HealthTable::getHealth(object_id_t object) {
|
||||||
HasHealthIF::HealthState state = HasHealthIF::HEALTHY;
|
HasHealthIF::HealthState state = HasHealthIF::HEALTHY;
|
||||||
mutex->lockMutex(MutexIF::BLOCKING);
|
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||||
HealthMap::iterator iter = healthMap.find(object);
|
HealthMap::iterator iter = healthMap.find(object);
|
||||||
if (iter != healthMap.end()) {
|
if (iter != healthMap.end()) {
|
||||||
state = iter->second;
|
state = iter->second;
|
||||||
}
|
}
|
||||||
mutex->unlockMutex();
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t HealthTable::getPrintSize() {
|
bool HealthTable::hasHealth(object_id_t object) {
|
||||||
mutex->lockMutex(MutexIF::BLOCKING);
|
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||||
uint32_t size = healthMap.size() * 5 + 2;
|
HealthMap::iterator iter = healthMap.find(object);
|
||||||
mutex->unlockMutex();
|
if (iter != healthMap.end()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t HealthTable::getPrintSize() {
|
||||||
|
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||||
|
uint32_t size = healthMap.size() * sizeof(object_id_t) +
|
||||||
|
sizeof(HasHealthIF::HealthState) + sizeof(uint16_t);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HealthTable::hasHealth(object_id_t object) {
|
|
||||||
bool exits = false;
|
|
||||||
mutex->lockMutex(MutexIF::BLOCKING);
|
|
||||||
HealthMap::iterator iter = healthMap.find(object);
|
|
||||||
if (iter != healthMap.end()) {
|
|
||||||
exits = true;
|
|
||||||
}
|
|
||||||
mutex->unlockMutex();
|
|
||||||
return exits;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HealthTable::printAll(uint8_t* pointer, size_t maxSize) {
|
void HealthTable::printAll(uint8_t* pointer, size_t maxSize) {
|
||||||
mutex->lockMutex(MutexIF::BLOCKING);
|
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
uint16_t count = healthMap.size();
|
uint16_t count = healthMap.size();
|
||||||
ReturnValue_t result = SerializeAdapter::serialize(&count,
|
SerializeAdapter::serialize(&count,
|
||||||
&pointer, &size, maxSize, SerializeIF::Endianness::BIG);
|
&pointer, &size, maxSize, SerializeIF::Endianness::BIG);
|
||||||
HealthMap::iterator iter;
|
for (const auto& health: healthMap) {
|
||||||
for (iter = healthMap.begin();
|
SerializeAdapter::serialize(&health.first,
|
||||||
iter != healthMap.end() && result == HasReturnvaluesIF::RETURN_OK;
|
|
||||||
++iter) {
|
|
||||||
result = SerializeAdapter::serialize(&iter->first,
|
|
||||||
&pointer, &size, maxSize, SerializeIF::Endianness::BIG);
|
&pointer, &size, maxSize, SerializeIF::Endianness::BIG);
|
||||||
uint8_t health = iter->second;
|
uint8_t healthValue = health.second;
|
||||||
result = SerializeAdapter::serialize(&health, &pointer, &size,
|
SerializeAdapter::serialize(&healthValue, &pointer, &size,
|
||||||
maxSize, SerializeIF::Endianness::BIG);
|
maxSize, SerializeIF::Endianness::BIG);
|
||||||
}
|
}
|
||||||
mutex->unlockMutex();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t HealthTable::iterate(
|
ReturnValue_t HealthTable::iterate(HealthEntry *value, bool reset) {
|
||||||
std::pair<object_id_t, HasHealthIF::HealthState> *value, bool reset) {
|
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
mutex->lockMutex(MutexIF::BLOCKING);
|
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
|
||||||
if (reset) {
|
if (reset) {
|
||||||
mapIterator = healthMap.begin();
|
mapIterator = healthMap.begin();
|
||||||
}
|
}
|
||||||
@ -94,7 +90,5 @@ ReturnValue_t HealthTable::iterate(
|
|||||||
}
|
}
|
||||||
*value = *mapIterator;
|
*value = *mapIterator;
|
||||||
mapIterator++;
|
mapIterator++;
|
||||||
mutex->unlockMutex();
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1,35 +1,47 @@
|
|||||||
#ifndef HEALTHTABLE_H_
|
#ifndef FSFW_HEALTH_HEALTHTABLE_H_
|
||||||
#define HEALTHTABLE_H_
|
#define FSFW_HEALTH_HEALTHTABLE_H_
|
||||||
|
|
||||||
#include "HealthTableIF.h"
|
#include "HealthTableIF.h"
|
||||||
#include "../objectmanager/SystemObject.h"
|
#include "../objectmanager/SystemObject.h"
|
||||||
#include "../ipc/MutexIF.h"
|
#include "../ipc/MutexIF.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
typedef std::map<object_id_t, HasHealthIF::HealthState> HealthMap;
|
|
||||||
|
|
||||||
class HealthTable: public HealthTableIF, public SystemObject {
|
class HealthTable: public HealthTableIF, public SystemObject {
|
||||||
public:
|
public:
|
||||||
HealthTable(object_id_t objectid);
|
HealthTable(object_id_t objectid);
|
||||||
virtual ~HealthTable();
|
virtual ~HealthTable();
|
||||||
|
|
||||||
|
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
|
||||||
|
|
||||||
|
/** HealthTableIF overrides */
|
||||||
virtual ReturnValue_t registerObject(object_id_t object,
|
virtual ReturnValue_t registerObject(object_id_t object,
|
||||||
HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY);
|
HasHealthIF::HealthState initilialState =
|
||||||
|
HasHealthIF::HEALTHY) override;
|
||||||
|
virtual size_t getPrintSize() override;
|
||||||
|
virtual void printAll(uint8_t *pointer, size_t maxSize) override;
|
||||||
|
|
||||||
virtual bool hasHealth(object_id_t object);
|
/** ManagesHealthIF overrides */
|
||||||
virtual void setHealth(object_id_t object, HasHealthIF::HealthState newState);
|
virtual bool hasHealth(object_id_t object) override;
|
||||||
virtual HasHealthIF::HealthState getHealth(object_id_t);
|
virtual void setHealth(object_id_t object,
|
||||||
|
HasHealthIF::HealthState newState) override;
|
||||||
virtual uint32_t getPrintSize();
|
virtual HasHealthIF::HealthState getHealth(object_id_t) override;
|
||||||
virtual void printAll(uint8_t *pointer, size_t maxSize);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
using HealthMap = std::map<object_id_t, HasHealthIF::HealthState>;
|
||||||
|
using HealthEntry = std::pair<object_id_t, HasHealthIF::HealthState>;
|
||||||
|
|
||||||
MutexIF* mutex;
|
MutexIF* mutex;
|
||||||
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||||
|
uint32_t mutexTimeoutMs = 20;
|
||||||
|
|
||||||
HealthMap healthMap;
|
HealthMap healthMap;
|
||||||
|
|
||||||
HealthMap::iterator mapIterator;
|
HealthMap::iterator mapIterator;
|
||||||
|
|
||||||
virtual ReturnValue_t iterate(std::pair<object_id_t,HasHealthIF::HealthState> *value, bool reset = false);
|
virtual ReturnValue_t iterate(
|
||||||
|
HealthEntry* value,
|
||||||
|
bool reset = false) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HEALTHTABLE_H_ */
|
#endif /* FSFW_HEALTH_HEALTHTABLE_H_ */
|
||||||
|
@ -1,26 +1,24 @@
|
|||||||
#ifndef HEALTHTABLEIF_H_
|
#ifndef FSFW_HEALTH_HEALTHTABLEIF_H_
|
||||||
#define HEALTHTABLEIF_H_
|
#define FSFW_HEALTH_HEALTHTABLEIF_H_
|
||||||
|
|
||||||
#include "ManagesHealthIF.h"
|
#include "ManagesHealthIF.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManagerIF.h"
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
#include <map>
|
|
||||||
|
|
||||||
|
|
||||||
class HealthTableIF: public ManagesHealthIF {
|
class HealthTableIF: public ManagesHealthIF {
|
||||||
friend class HealthCommandingService;
|
|
||||||
public:
|
public:
|
||||||
virtual ~HealthTableIF() {
|
virtual ~HealthTableIF() {}
|
||||||
}
|
|
||||||
|
|
||||||
virtual ReturnValue_t registerObject(object_id_t object,
|
virtual ReturnValue_t registerObject(object_id_t object,
|
||||||
HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) = 0;
|
HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) = 0;
|
||||||
|
|
||||||
virtual uint32_t getPrintSize() = 0;
|
virtual size_t getPrintSize() = 0;
|
||||||
virtual void printAll(uint8_t *pointer, size_t maxSize) = 0;
|
virtual void printAll(uint8_t *pointer, size_t maxSize) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ReturnValue_t iterate(std::pair<object_id_t,HasHealthIF::HealthState> *value, bool reset = false) = 0;
|
virtual ReturnValue_t iterate(
|
||||||
|
std::pair<object_id_t,HasHealthIF::HealthState> *value,
|
||||||
|
bool reset = false) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HEALTHTABLEIF_H_ */
|
#endif /* FRAMEWORK_HEALTH_HEALTHTABLEIF_H_ */
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#ifndef FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_
|
#ifndef FSFW_HEALTH_MANAGESHEALTHIF_H_
|
||||||
#define FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_
|
#define FSFW_HEALTH_MANAGESHEALTHIF_H_
|
||||||
|
|
||||||
#include "HasHealthIF.h"
|
#include "HasHealthIF.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManagerIF.h"
|
||||||
|
|
||||||
class ManagesHealthIF {
|
class ManagesHealthIF {
|
||||||
public:
|
public:
|
||||||
virtual ~ManagesHealthIF() {
|
virtual ~ManagesHealthIF() {
|
||||||
@ -49,4 +50,4 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_ */
|
#endif /* FSFW_HEALTH_MANAGESHEALTHIF_H_ */
|
||||||
|
@ -1,61 +1,77 @@
|
|||||||
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
|
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
|
||||||
#define FSFW_IPC_MESSAGEQUEUEIF_H_
|
#define FSFW_IPC_MESSAGEQUEUEIF_H_
|
||||||
|
|
||||||
// COULDDO: We could support blocking calls
|
|
||||||
|
|
||||||
#include "messageQueueDefinitions.h"
|
#include "messageQueueDefinitions.h"
|
||||||
#include "MessageQueueMessage.h"
|
#include "MessageQueueMessageIF.h"
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
|
// COULDDO: We could support blocking calls
|
||||||
|
// semaphores are being implemented, which makes this idea even more iteresting.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup message_queue Message Queue
|
||||||
|
* @brief Message Queue related software components
|
||||||
|
*/
|
||||||
class MessageQueueIF {
|
class MessageQueueIF {
|
||||||
public:
|
public:
|
||||||
static const MessageQueueId_t NO_QUEUE = 0;
|
static const MessageQueueId_t NO_QUEUE = 0;
|
||||||
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
|
||||||
/**
|
//! No new messages on the queue
|
||||||
* No new messages on the queue
|
|
||||||
*/
|
|
||||||
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1);
|
||||||
/**
|
//! No space left for more messages
|
||||||
* No space left for more messages
|
|
||||||
*/
|
|
||||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(2);
|
static const ReturnValue_t FULL = MAKE_RETURN_CODE(2);
|
||||||
/**
|
//! Returned if a reply method was called without partner
|
||||||
* Returned if a reply method was called without partner
|
|
||||||
*/
|
|
||||||
static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3);
|
static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3);
|
||||||
|
//! Returned if the target destination is invalid.
|
||||||
|
static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4);
|
||||||
|
|
||||||
virtual ~MessageQueueIF() {}
|
virtual ~MessageQueueIF() {}
|
||||||
/**
|
/**
|
||||||
* @brief This operation sends a message to the last communication partner.
|
* @brief This operation sends a message to the last communication partner.
|
||||||
* @details This operation simplifies answering an incoming message by using the stored
|
* @details
|
||||||
* lastParnter information as destination. If there was no message received yet
|
* This operation simplifies answering an incoming message by using the
|
||||||
* (i.e. lastPartner is zero), an error code is returned.
|
* stored lastParnter information as destination. If there was no message
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
* received yet (i.e. lastPartner is zero), an error code is returned.
|
||||||
* \return RETURN_OK if ok
|
* @param message
|
||||||
* \return NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found
|
* A pointer to a previously created message, which is sent.
|
||||||
|
* @return
|
||||||
|
* -@c RETURN_OK if ok
|
||||||
|
* -@c NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t reply( MessageQueueMessage* message ) = 0;
|
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function reads available messages from the message queue and returns the sender.
|
* @brief This function reads available messages from the message queue
|
||||||
* @details It works identically to the other receiveMessage call, but in addition returns the
|
* and returns the sender.
|
||||||
* sender's queue id.
|
* @details
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
* It works identically to the other receiveMessage call, but in addition
|
||||||
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
|
* returns the sender's queue id.
|
||||||
|
* @param message
|
||||||
|
* A pointer to a message in which the received data is stored.
|
||||||
|
* @param receivedFrom
|
||||||
|
* A pointer to a queue id in which the sender's id is stored.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t receiveMessage(MessageQueueMessage* message,
|
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t *receivedFrom) = 0;
|
MessageQueueId_t *receivedFrom) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function reads available messages from the message queue.
|
* @brief This function reads available messages from the message queue.
|
||||||
* @details If data is available it is stored in the passed message pointer. The message's
|
* @details
|
||||||
* original content is overwritten and the sendFrom information is stored in the
|
* If data is available it is stored in the passed message pointer.
|
||||||
* lastPartner attribute. Else, the lastPartner information remains untouched, the
|
* The message's original content is overwritten and the sendFrom
|
||||||
* message's content is cleared and the function returns immediately.
|
* information is stored in theblastPartner attribute. Else, the lastPartner
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
* information remains untouched, the message's content is cleared and the
|
||||||
|
* function returns immediately.
|
||||||
|
* @param message
|
||||||
|
* A pointer to a message in which the received data is stored.
|
||||||
|
* @return -@c RETURN_OK on success
|
||||||
|
* -@c MessageQueueIF::EMPTY if queue is empty
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t receiveMessage(MessageQueueMessage* message) = 0;
|
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
|
||||||
/**
|
/**
|
||||||
* Deletes all pending messages in the queue.
|
* Deletes all pending messages in the queue.
|
||||||
* @param count The number of flushed messages.
|
* @param count The number of flushed messages.
|
||||||
@ -63,57 +79,89 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t flush(uint32_t* count) = 0;
|
virtual ReturnValue_t flush(uint32_t* count) = 0;
|
||||||
/**
|
/**
|
||||||
* @brief This method returns the message queue id of the last communication partner.
|
* @brief This method returns the message queue
|
||||||
|
* id of the last communication partner.
|
||||||
*/
|
*/
|
||||||
virtual MessageQueueId_t getLastPartner() const = 0;
|
virtual MessageQueueId_t getLastPartner() const = 0;
|
||||||
/**
|
/**
|
||||||
* @brief This method returns the message queue id of this class's message queue.
|
* @brief This method returns the message queue
|
||||||
|
* id of this class's message queue.
|
||||||
*/
|
*/
|
||||||
virtual MessageQueueId_t getId() const = 0;
|
virtual MessageQueueId_t getId() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
|
* @brief With the sendMessage call, a queue message
|
||||||
* \details This method takes the message provided, adds the sentFrom information and passes
|
* is sent to a receiving queue.
|
||||||
* it on to the destination provided with an operating system call. The OS's return
|
* @details
|
||||||
* value is returned.
|
* This method takes the message provided, adds the sentFrom information
|
||||||
* \param sendTo This parameter specifies the message queue id to send the message to.
|
* and passes it on to the destination provided with an operating system
|
||||||
* \param message This is a pointer to a previously created message, which is sent.
|
* call. The OS's returnvalue is returned.
|
||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
* @param sendTo
|
||||||
* This variable is set to zero by default.
|
* This parameter specifies the message queue id to send the message to.
|
||||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full (if implemented).
|
* @param message
|
||||||
|
* This is a pointer to a previously created message, which is sent.
|
||||||
|
* @param sentFrom
|
||||||
|
* The sentFrom information can be set to inject the sender's queue id
|
||||||
|
* into the message. This variable is set to zero by default.
|
||||||
|
* @param ignoreFault
|
||||||
|
* If set to true, the internal software fault counter is not incremented
|
||||||
|
* if queue is full (if implemented).
|
||||||
|
* @return -@c RETURN_OK on success
|
||||||
|
* -@c MessageQueueIF::FULL if queue is full
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0;
|
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo,
|
||||||
/**
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||||
* @brief This operation sends a message to the given destination.
|
bool ignoreFault = false ) = 0;
|
||||||
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its
|
|
||||||
* queue id as "sentFrom" parameter.
|
|
||||||
* @param sendTo This parameter specifies the message queue id of the destination message queue.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, bool ignoreFault = false ) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief The sendToDefaultFrom method sends a queue message to the default destination.
|
* @brief This operation sends a message to the given destination.
|
||||||
* \details In all other aspects, it works identical to the sendMessage method.
|
* @details
|
||||||
* \param message This is a pointer to a previously created message, which is sent.
|
* It directly uses the sendMessage call of the MessageQueueSender parent,
|
||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
* but passes its queue id as "sentFrom" parameter.
|
||||||
* This variable is set to zero by default.
|
* @param sendTo
|
||||||
|
* This parameter specifies the message queue id of the destination
|
||||||
|
* message queue.
|
||||||
|
* @param message
|
||||||
|
* A pointer to a previously created message, which is sent.
|
||||||
|
* @param ignoreFault
|
||||||
|
* If set to true, the internal software fault counter is not incremented
|
||||||
|
* if queue is full.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0;
|
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo,
|
||||||
|
MessageQueueMessageIF* message, bool ignoreFault = false ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The sendToDefaultFrom method sends a queue message
|
||||||
|
* to the default destination.
|
||||||
|
* @details
|
||||||
|
* In all other aspects, it works identical to the sendMessage method.
|
||||||
|
* @param message
|
||||||
|
* This is a pointer to a previously created message, which is sent.
|
||||||
|
* @param sentFrom
|
||||||
|
* The sentFrom information can be set to inject the sender's queue id
|
||||||
|
* into the message. This variable is set to zero by default.
|
||||||
|
* @return -@c RETURN_OK on success
|
||||||
|
* -@c MessageQueueIF::FULL if queue is full
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
|
||||||
|
MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0;
|
||||||
/**
|
/**
|
||||||
* @brief This operation sends a message to the default destination.
|
* @brief This operation sends a message to the default destination.
|
||||||
* @details As in the sendMessage method, this function uses the sendToDefault call of the
|
* @details
|
||||||
* Implementation class and adds its queue id as "sentFrom" information.
|
* As in the sendMessage method, this function uses the sendToDefault
|
||||||
|
* call of the Implementation class and adds its queue id as
|
||||||
|
* "sentFrom" information.
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
* @param message A pointer to a previously created message, which is sent.
|
||||||
|
* @return -@c RETURN_OK on success
|
||||||
|
* -@c MessageQueueIF::FULL if queue is full
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ) = 0;
|
virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ) = 0;
|
||||||
/**
|
/**
|
||||||
* \brief This method is a simple setter for the default destination.
|
* @brief This method is a simple setter for the default destination.
|
||||||
*/
|
*/
|
||||||
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0;
|
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0;
|
||||||
/**
|
/**
|
||||||
* \brief This method is a simple getter for the default destination.
|
* @brief This method is a simple getter for the default destination.
|
||||||
*/
|
*/
|
||||||
virtual MessageQueueId_t getDefaultDestination() const = 0;
|
virtual MessageQueueId_t getDefaultDestination() const = 0;
|
||||||
|
|
||||||
@ -122,4 +170,4 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ */
|
#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_
|
#ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_
|
||||||
#define FSFW_IPC_MESSAGEQUEUESENDERIF_H_
|
#define FSFW_IPC_MESSAGEQUEUESENDERIF_H_
|
||||||
|
|
||||||
#include "../ipc/MessageQueueIF.h"
|
#include "MessageQueueIF.h"
|
||||||
#include "../ipc/MessageQueueMessageIF.h"
|
#include "MessageQueueMessageIF.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManagerIF.h"
|
||||||
|
|
||||||
class MessageQueueSenderIF {
|
class MessageQueueSenderIF {
|
||||||
@ -15,7 +15,7 @@ public:
|
|||||||
* Not sure whether this is actually a good idea.
|
* Not sure whether this is actually a good idea.
|
||||||
*/
|
*/
|
||||||
static ReturnValue_t sendMessage(MessageQueueId_t sendTo,
|
static ReturnValue_t sendMessage(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message,
|
MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE,
|
MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE,
|
||||||
bool ignoreFault = false);
|
bool ignoreFault = false);
|
||||||
private:
|
private:
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#ifndef FRAMEWORK_IPC_QUEUEFACTORY_H_
|
#ifndef FSFW_IPC_QUEUEFACTORY_H_
|
||||||
#define FRAMEWORK_IPC_QUEUEFACTORY_H_
|
#define FSFW_IPC_QUEUEFACTORY_H_
|
||||||
|
|
||||||
#include "MessageQueueIF.h"
|
#include "MessageQueueIF.h"
|
||||||
#include <stdint.h>
|
#include "MessageQueueMessage.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates message queues.
|
* Creates message queues.
|
||||||
* This class is a "singleton" interface, i.e. it provides an
|
* This class is a "singleton" interface, i.e. it provides an
|
||||||
@ -30,4 +32,4 @@ private:
|
|||||||
static QueueFactory* factoryInstance;
|
static QueueFactory* factoryInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_IPC_QUEUEFACTORY_H_ */
|
#endif /* FSFW_IPC_QUEUEFACTORY_H_ */
|
||||||
|
BIN
logo/FSFW_Logo_V3.png
Normal file
BIN
logo/FSFW_Logo_V3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
711
logo/FSFW_Logo_V3.svg
Normal file
711
logo/FSFW_Logo_V3.svg
Normal file
@ -0,0 +1,711 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="59.111mm"
|
||||||
|
height="67.383003mm"
|
||||||
|
viewBox="0 0 59.111 67.383003"
|
||||||
|
version="1.1"
|
||||||
|
id="svg22814"
|
||||||
|
inkscape:version="0.92.0 r15299"
|
||||||
|
sodipodi:docname="FSFW_Logo_V3.svg"
|
||||||
|
style="enable-background:new">
|
||||||
|
<defs
|
||||||
|
id="defs22808">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="bspline"
|
||||||
|
id="path-effect23502"
|
||||||
|
is_visible="true"
|
||||||
|
weight="33.333333"
|
||||||
|
steps="2"
|
||||||
|
helper_size="0"
|
||||||
|
apply_no_weight="true"
|
||||||
|
apply_with_weight="true"
|
||||||
|
only_selected="false" />
|
||||||
|
<filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
style="color-interpolation-filters:sRGB"
|
||||||
|
id="filter23683">
|
||||||
|
<feBlend
|
||||||
|
inkscape:collect="always"
|
||||||
|
mode="darken"
|
||||||
|
in2="BackgroundImage"
|
||||||
|
id="feBlend23685" />
|
||||||
|
</filter>
|
||||||
|
<meshgradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="meshgradient23819"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x="-9.447978"
|
||||||
|
y="-28.967659"
|
||||||
|
gradientTransform="matrix(1.6672918,0,0,1.5637161,15.752536,45.300004)">
|
||||||
|
<meshrow
|
||||||
|
id="meshrow23821">
|
||||||
|
<meshpatch
|
||||||
|
id="meshpatch23823">
|
||||||
|
<stop
|
||||||
|
path="c 11.8178,0 23.6355,0 35.4533,0"
|
||||||
|
style="stop-color:#0087ce;stop-opacity:1"
|
||||||
|
id="stop23825" />
|
||||||
|
<stop
|
||||||
|
path="c 0,3.49232 0,6.98464 0,10.477"
|
||||||
|
style="stop-color:#00beff;stop-opacity:1"
|
||||||
|
id="stop23827" />
|
||||||
|
<stop
|
||||||
|
path="c -11.8178,0 -23.6355,0 -35.4533,0"
|
||||||
|
style="stop-color:#0087ce;stop-opacity:1"
|
||||||
|
id="stop23829" />
|
||||||
|
<stop
|
||||||
|
path="c 0,-3.49232 0,-6.98464 0,-10.477"
|
||||||
|
style="stop-color:#00519e;stop-opacity:1"
|
||||||
|
id="stop23831" />
|
||||||
|
</meshpatch>
|
||||||
|
</meshrow>
|
||||||
|
</meshgradient>
|
||||||
|
<clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath24955">
|
||||||
|
<g
|
||||||
|
style="display:inline;fill:url(#meshgradient24977);fill-opacity:1;enable-background:new"
|
||||||
|
id="g24975"
|
||||||
|
transform="translate(-42.742183,-140.61702)"
|
||||||
|
clip-path="none">
|
||||||
|
<path
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98999999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98699999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 48.300305,143.44076 c -0.811661,0 -1.109125,0.75874 -1.480469,1.48047 l -4.00014,7.77454 c -0.371344,0.72173 0.668807,1.48047 1.480468,1.48047 h 9.625183 c 0.811661,0 1.109108,-0.75875 1.480469,-1.48047 l 4.00036,-7.77454 c 0.371361,-0.72172 -0.668808,-1.48047 -1.480469,-1.48047 z m 0,0.98828 h 9.625402 c 0.281935,0 0.621179,0.2415 0.492187,0.49219 l -4.00036,7.77454 c -0.128993,0.25069 -0.210251,0.49218 -0.492187,0.49218 h -9.625181 c -0.281935,0 -0.621175,-0.24149 -0.492189,-0.49218 l 4.000141,-7.77454 c 0.128986,-0.25069 0.210253,-0.49219 0.492187,-0.49219 z"
|
||||||
|
id="path24957"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ssssssssssssssssss" />
|
||||||
|
<path
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
sodipodi:nodetypes="ssssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path24959"
|
||||||
|
d="m 90.668816,143.44076 c -0.811661,0 -1.109125,0.75874 -1.480469,1.48047 l -4.00014,7.77454 c -0.371344,0.72173 0.668808,1.48047 1.480469,1.48047 h 9.625909 c 0.81166,0 1.109109,-0.75875 1.48047,-1.48047 l 4.000355,-7.77454 c 0.37136,-0.72172 -0.66881,-1.48047 -1.48046,-1.48047 z m 0,0.98828 h 9.626134 c 0.28193,0 0.62117,0.24151 0.49218,0.49219 l -4.000365,7.77454 c -0.128993,0.25069 -0.21025,0.49218 -0.49218,0.49218 h -9.625909 c -0.281935,0 -0.621174,-0.24149 -0.492188,-0.49218 l 4.00014,-7.77454 c 0.128986,-0.25069 0.210254,-0.49219 0.492188,-0.49219 z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98999999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98699999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<text
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;opacity:0.98999999;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="69.980721"
|
||||||
|
y="150.38542"
|
||||||
|
id="text24965"><tspan
|
||||||
|
dy="-2"
|
||||||
|
dx="0"
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan24961"
|
||||||
|
x="69.980721"
|
||||||
|
y="150.38542"
|
||||||
|
style="text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill-opacity:1;stroke-width:0.26458332">fs</tspan><tspan
|
||||||
|
dx="0 0 -0.27000001"
|
||||||
|
id="tspan24963"
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="69.980721"
|
||||||
|
y="157"
|
||||||
|
style="text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill-opacity:1;stroke-width:0.26458332"> fw</tspan></text>
|
||||||
|
<g
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
transform="translate(-1.937002)"
|
||||||
|
id="g24969"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.36171436px;line-height:5.85107136px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;opacity:0.98999999;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.23404284"
|
||||||
|
aria-label="{">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccssccsssccccssccccssscc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path24967"
|
||||||
|
style="font-size:18.72342873px;fill:#000000;fill-opacity:1;stroke-width:0.23404284"
|
||||||
|
d="m 67.678074,141.482 c -0.798867,0.0624 -1.915603,0.38946 -2.290072,0.80139 -0.361986,0.41191 -0.543,1.06141 -0.543,1.94766 v 1.29191 c 0,1.04851 -0.199567,1.82824 -0.599,2.34001 -0.386951,0.51177 -1.010722,0.82383 -1.872,0.93617 0.848795,0.11234 1.472567,0.41816 1.872,0.91745 0.399433,0.49929 0.599,1.22951 0.599,2.19064 v 1.38554 c 0,0.88624 0.193496,1.5478 0.543,1.98468 0.349504,0.44936 1.453759,0.79514 2.290072,0.85755 v 0.86501 c -1.260711,-0.0749 -2.215606,-0.38696 -2.864685,-0.93618 -0.636597,-0.53673 -0.954895,-1.55404 -0.954895,-3.05192 v -1.23574 c 0,-0.84879 -0.205958,-1.44794 -0.617873,-1.79745 -0.399433,-0.36199 -1.017306,-0.59291 -1.853619,-0.69277 v -0.95489 c 0.761419,-0.0624 1.360569,-0.28084 1.797449,-0.65532 0.449362,-0.38695 0.674043,-0.91745 0.674043,-1.59149 v -1.66639 c 0,-1.26071 0.293334,-2.19064 0.880001,-2.78979 0.586667,-0.59915 1.566527,-0.93617 2.939579,-1.01107 z" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
aria-label="{"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.36171436px;line-height:5.85107136px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;opacity:0.98999999;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.23404284"
|
||||||
|
id="g24973"
|
||||||
|
transform="rotate(180,73.264036,148.80851)">
|
||||||
|
<path
|
||||||
|
d="m 67.678074,141.482 c -0.798867,0.0624 -1.915603,0.38946 -2.290072,0.80139 -0.361986,0.41191 -0.543,1.06141 -0.543,1.94766 v 1.29191 c 0,1.04851 -0.199567,1.82824 -0.599,2.34001 -0.386951,0.51177 -1.010722,0.82383 -1.872,0.93617 0.848795,0.11234 1.472567,0.41816 1.872,0.91745 0.399433,0.49929 0.599,1.22951 0.599,2.19064 v 1.38554 c 0,0.88624 0.193496,1.5478 0.543,1.98468 0.349504,0.44936 1.453759,0.79514 2.290072,0.85755 v 0.86501 c -1.260711,-0.0749 -2.215606,-0.38696 -2.864685,-0.93618 -0.636597,-0.53673 -0.954895,-1.55404 -0.954895,-3.05192 v -1.23574 c 0,-0.84879 -0.205958,-1.44794 -0.617873,-1.79745 -0.399433,-0.36199 -1.017306,-0.59291 -1.853619,-0.69277 v -0.95489 c 0.761419,-0.0624 1.360569,-0.28084 1.797449,-0.65532 0.449362,-0.38695 0.674043,-0.91745 0.674043,-1.59149 v -1.66639 c 0,-1.26071 0.293334,-2.19064 0.880001,-2.78979 0.586667,-0.59915 1.566527,-0.93617 2.939579,-1.01107 z"
|
||||||
|
style="font-size:18.72342873px;fill:#000000;fill-opacity:1;stroke-width:0.23404284"
|
||||||
|
id="path24971"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccssccsssccccssccccssscc" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</clipPath>
|
||||||
|
<meshgradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="meshgradient24977"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.6672918,0,0,1.5637161,15.752536,45.300004)"
|
||||||
|
x="42.742184"
|
||||||
|
y="140.617">
|
||||||
|
<meshrow
|
||||||
|
id="meshrow24989">
|
||||||
|
<meshpatch
|
||||||
|
id="meshpatch24987">
|
||||||
|
<stop
|
||||||
|
path="c 19.7036,0 39.4071,0 59.1107,0"
|
||||||
|
style="stop-color:#00519e;stop-opacity:1"
|
||||||
|
id="stop24979" />
|
||||||
|
<stop
|
||||||
|
path="c 0,5.46099 0,10.922 0,16.383"
|
||||||
|
style="stop-color:#00beff;stop-opacity:1"
|
||||||
|
id="stop24981" />
|
||||||
|
<stop
|
||||||
|
path="c -19.7036,0 -39.4071,0 -59.1107,0"
|
||||||
|
style="stop-color:#00beff;stop-opacity:1"
|
||||||
|
id="stop24983" />
|
||||||
|
<stop
|
||||||
|
path="c 0,-5.46099 0,-10.922 0,-16.383"
|
||||||
|
style="stop-color:#00519e;stop-opacity:1"
|
||||||
|
id="stop24985" />
|
||||||
|
</meshpatch>
|
||||||
|
</meshrow>
|
||||||
|
</meshgradient>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="2"
|
||||||
|
inkscape:cx="110.06798"
|
||||||
|
inkscape:cy="138.03068"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer16"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1536"
|
||||||
|
inkscape:window-height="801"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:pagecheckerboard="true" />
|
||||||
|
<metadata
|
||||||
|
id="metadata22811">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer13"
|
||||||
|
inkscape:label="Corporate_Uni_Stuttgart"
|
||||||
|
transform="translate(0,16.383002)"
|
||||||
|
style="display:none;filter:url(#filter23683)">
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#3e444c;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23621"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-8.499999"
|
||||||
|
y="42.5" />
|
||||||
|
<rect
|
||||||
|
y="34"
|
||||||
|
x="-8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
width="8.499999"
|
||||||
|
id="rect23623"
|
||||||
|
style="opacity:1;fill:#00519e;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#00beff;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23625"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-8.499999"
|
||||||
|
y="25.5" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#009e51;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23629"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-50.999996"
|
||||||
|
y="34" />
|
||||||
|
<rect
|
||||||
|
y="25.5"
|
||||||
|
x="-50.999996"
|
||||||
|
height="8.499999"
|
||||||
|
width="8.499999"
|
||||||
|
id="rect23631"
|
||||||
|
style="opacity:1;fill:#00ffbe;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<rect
|
||||||
|
y="34"
|
||||||
|
x="-16.999998"
|
||||||
|
height="8.499999"
|
||||||
|
width="8.499999"
|
||||||
|
id="rect23635"
|
||||||
|
style="opacity:1;fill:#51009e;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#be00ff;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23637"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-16.999998"
|
||||||
|
y="25.5" />
|
||||||
|
<rect
|
||||||
|
y="42.5"
|
||||||
|
x="-50.999996"
|
||||||
|
height="8.499999"
|
||||||
|
width="8.499999"
|
||||||
|
id="rect23639"
|
||||||
|
style="opacity:1;fill:#3e4c44;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#443e4c;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23641"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-16.999998"
|
||||||
|
y="42.5" />
|
||||||
|
<rect
|
||||||
|
y="42.5"
|
||||||
|
x="-33.999996"
|
||||||
|
height="8.499999"
|
||||||
|
width="8.499999"
|
||||||
|
id="rect23655"
|
||||||
|
style="opacity:1;fill:#4c443e;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#9e5100;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23657"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-33.999996"
|
||||||
|
y="34" />
|
||||||
|
<rect
|
||||||
|
y="25.5"
|
||||||
|
x="-33.999996"
|
||||||
|
height="8.499999"
|
||||||
|
width="8.499999"
|
||||||
|
id="rect23659"
|
||||||
|
style="opacity:1;fill:#ffbe00;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#4c3e44;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23661"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-25.499998"
|
||||||
|
y="42.5" />
|
||||||
|
<rect
|
||||||
|
y="34"
|
||||||
|
x="-25.499998"
|
||||||
|
height="8.499999"
|
||||||
|
width="8.499999"
|
||||||
|
id="rect23663"
|
||||||
|
style="opacity:1;fill:#9e0051;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#ff00be;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23665"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-25.499998"
|
||||||
|
y="25.5" />
|
||||||
|
<rect
|
||||||
|
y="42.5"
|
||||||
|
x="-42.499996"
|
||||||
|
height="8.499999"
|
||||||
|
width="8.499999"
|
||||||
|
id="rect23667"
|
||||||
|
style="opacity:1;fill:#444c3e;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#519e00;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23669"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-42.499996"
|
||||||
|
y="34" />
|
||||||
|
<rect
|
||||||
|
y="25.5"
|
||||||
|
x="-42.499996"
|
||||||
|
height="8.499999"
|
||||||
|
width="8.499999"
|
||||||
|
id="rect23671"
|
||||||
|
style="opacity:1;fill:#beff00;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#006cb6;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23673"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-8.499999"
|
||||||
|
y="17" />
|
||||||
|
<rect
|
||||||
|
y="8.500001"
|
||||||
|
x="-8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
width="8.499999"
|
||||||
|
id="rect23713"
|
||||||
|
style="opacity:1;fill:#0087ce;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#00a3e7;fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="rect23715"
|
||||||
|
width="8.499999"
|
||||||
|
height="8.499999"
|
||||||
|
x="-8.499999"
|
||||||
|
y="1.9073486e-006" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer10"
|
||||||
|
inkscape:label="Logo_mono_black"
|
||||||
|
transform="translate(0,-229.617)"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
style="display:inline"
|
||||||
|
id="g23526"
|
||||||
|
transform="translate(-42.742184,139.99998)">
|
||||||
|
<path
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98999999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98699999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 48.300305,143.44076 c -0.811661,0 -1.109125,0.75874 -1.480469,1.48047 l -4.00014,7.77454 c -0.371344,0.72173 0.668807,1.48047 1.480468,1.48047 h 9.625183 c 0.811661,0 1.109108,-0.75875 1.480469,-1.48047 l 4.00036,-7.77454 c 0.371361,-0.72172 -0.668808,-1.48047 -1.480469,-1.48047 z m 0,0.98828 h 9.625402 c 0.281935,0 0.621179,0.2415 0.492187,0.49219 l -4.00036,7.77454 c -0.128993,0.25069 -0.210251,0.49218 -0.492187,0.49218 h -9.625181 c -0.281935,0 -0.621175,-0.24149 -0.492189,-0.49218 l 4.000141,-7.77454 c 0.128986,-0.25069 0.210253,-0.49219 0.492187,-0.49219 z"
|
||||||
|
id="path23506"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ssssssssssssssssss" />
|
||||||
|
<path
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
sodipodi:nodetypes="ssssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23508"
|
||||||
|
d="m 90.668816,143.44076 c -0.811661,0 -1.109125,0.75874 -1.480469,1.48047 l -4.00014,7.77454 c -0.371344,0.72173 0.668808,1.48047 1.480469,1.48047 h 9.625909 c 0.81166,0 1.109109,-0.75875 1.48047,-1.48047 l 4.000355,-7.77454 c 0.37136,-0.72172 -0.66881,-1.48047 -1.48046,-1.48047 z m 0,0.98828 h 9.626134 c 0.28193,0 0.62117,0.24151 0.49218,0.49219 l -4.000365,7.77454 c -0.128993,0.25069 -0.21025,0.49218 -0.49218,0.49218 h -9.625909 c -0.281935,0 -0.621174,-0.24149 -0.492188,-0.49218 l 4.00014,-7.77454 c 0.128986,-0.25069 0.210254,-0.49219 0.492188,-0.49219 z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98999999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98699999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<text
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;opacity:0.98999999;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="69.980721"
|
||||||
|
y="150.38542"
|
||||||
|
id="text23365-1"><tspan
|
||||||
|
dy="-2"
|
||||||
|
dx="0"
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan23363-7"
|
||||||
|
x="69.980721"
|
||||||
|
y="150.38542"
|
||||||
|
style="text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.26458332">fs</tspan><tspan
|
||||||
|
dx="0 0 -0.27000001"
|
||||||
|
id="tspan23367-0"
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="69.980721"
|
||||||
|
y="157"
|
||||||
|
style="text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.26458332"> fw</tspan></text>
|
||||||
|
<g
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
transform="translate(-1.937002)"
|
||||||
|
id="text23461"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.36171436px;line-height:5.85107136px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;opacity:0.98999999;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.23404284"
|
||||||
|
aria-label="{">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccssccsssccccssccccssscc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23467"
|
||||||
|
style="font-size:18.72342873px;fill:#000000;fill-opacity:1;stroke-width:0.23404284"
|
||||||
|
d="m 67.678074,141.482 c -0.798867,0.0624 -1.915603,0.38946 -2.290072,0.80139 -0.361986,0.41191 -0.543,1.06141 -0.543,1.94766 v 1.29191 c 0,1.04851 -0.199567,1.82824 -0.599,2.34001 -0.386951,0.51177 -1.010722,0.82383 -1.872,0.93617 0.848795,0.11234 1.472567,0.41816 1.872,0.91745 0.399433,0.49929 0.599,1.22951 0.599,2.19064 v 1.38554 c 0,0.88624 0.193496,1.5478 0.543,1.98468 0.349504,0.44936 1.453759,0.79514 2.290072,0.85755 v 0.86501 c -1.260711,-0.0749 -2.215606,-0.38696 -2.864685,-0.93618 -0.636597,-0.53673 -0.954895,-1.55404 -0.954895,-3.05192 v -1.23574 c 0,-0.84879 -0.205958,-1.44794 -0.617873,-1.79745 -0.399433,-0.36199 -1.017306,-0.59291 -1.853619,-0.69277 v -0.95489 c 0.761419,-0.0624 1.360569,-0.28084 1.797449,-0.65532 0.449362,-0.38695 0.674043,-0.91745 0.674043,-1.59149 v -1.66639 c 0,-1.26071 0.293334,-2.19064 0.880001,-2.78979 0.586667,-0.59915 1.566527,-0.93617 2.939579,-1.01107 z" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
aria-label="{"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.36171436px;line-height:5.85107136px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;opacity:0.98999999;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.23404284"
|
||||||
|
id="g23472"
|
||||||
|
transform="rotate(180,73.264036,148.80851)">
|
||||||
|
<path
|
||||||
|
d="m 67.678074,141.482 c -0.798867,0.0624 -1.915603,0.38946 -2.290072,0.80139 -0.361986,0.41191 -0.543,1.06141 -0.543,1.94766 v 1.29191 c 0,1.04851 -0.199567,1.82824 -0.599,2.34001 -0.386951,0.51177 -1.010722,0.82383 -1.872,0.93617 0.848795,0.11234 1.472567,0.41816 1.872,0.91745 0.399433,0.49929 0.599,1.22951 0.599,2.19064 v 1.38554 c 0,0.88624 0.193496,1.5478 0.543,1.98468 0.349504,0.44936 1.453759,0.79514 2.290072,0.85755 v 0.86501 c -1.260711,-0.0749 -2.215606,-0.38696 -2.864685,-0.93618 -0.636597,-0.53673 -0.954895,-1.55404 -0.954895,-3.05192 v -1.23574 c 0,-0.84879 -0.205958,-1.44794 -0.617873,-1.79745 -0.399433,-0.36199 -1.017306,-0.59291 -1.853619,-0.69277 v -0.95489 c 0.761419,-0.0624 1.360569,-0.28084 1.797449,-0.65532 0.449362,-0.38695 0.674043,-0.91745 0.674043,-1.59149 v -1.66639 c 0,-1.26071 0.293334,-2.19064 0.880001,-2.78979 0.586667,-0.59915 1.566527,-0.93617 2.939579,-1.01107 z"
|
||||||
|
style="font-size:18.72342873px;fill:#000000;fill-opacity:1;stroke-width:0.23404284"
|
||||||
|
id="path23470"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccssccsssccccssccccssscc" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer12"
|
||||||
|
inkscape:label="Logo_mono_white"
|
||||||
|
style="display:inline"
|
||||||
|
transform="translate(0,16.383002)">
|
||||||
|
<g
|
||||||
|
id="g23618">
|
||||||
|
<path
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98999999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98699999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 5.558122,20.44074 c -0.811661,0 -1.109125,0.75874 -1.480469,1.48047 l -4.00014,7.77454 c -0.371344,0.72173 0.668807,1.48047 1.480468,1.48047 h 9.625183 c 0.811661,0 1.109108,-0.75875 1.480469,-1.48047 l 4.00036,-7.77454 c 0.371361,-0.72172 -0.668808,-1.48047 -1.480469,-1.48047 z m 0,0.98828 h 9.625402 c 0.281935,0 0.621179,0.2415 0.492187,0.49219 l -4.00036,7.77454 c -0.128993,0.25069 -0.210251,0.49218 -0.492187,0.49218 H 1.557983 c -0.281935,0 -0.621175,-0.24149 -0.492189,-0.49218 l 4.000141,-7.77454 c 0.128986,-0.25069 0.210253,-0.49219 0.492187,-0.49219 z"
|
||||||
|
id="path23560"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ssssssssssssssssss" />
|
||||||
|
<path
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
sodipodi:nodetypes="ssssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23562"
|
||||||
|
d="m 47.926633,20.44074 c -0.811661,0 -1.109125,0.75874 -1.480469,1.48047 l -4.00014,7.77454 c -0.371344,0.72173 0.668808,1.48047 1.480469,1.48047 h 9.625909 c 0.81166,0 1.109109,-0.75875 1.48047,-1.48047 l 4.000355,-7.77454 c 0.37136,-0.72172 -0.66881,-1.48047 -1.48046,-1.48047 z m 0,0.98828 h 9.626134 c 0.28193,0 0.62117,0.24151 0.49218,0.49219 l -4.000365,7.77454 c -0.128993,0.25069 -0.21025,0.49218 -0.49218,0.49218 h -9.625909 c -0.281935,0 -0.621174,-0.24149 -0.492188,-0.49218 l 4.00014,-7.77454 c 0.128986,-0.25069 0.210254,-0.49219 0.492188,-0.49219 z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98999999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98699999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<text
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;opacity:0.98999999;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="27.238537"
|
||||||
|
y="27.385403"
|
||||||
|
id="text23568"><tspan
|
||||||
|
dy="-2"
|
||||||
|
dx="0"
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan23564"
|
||||||
|
x="27.238537"
|
||||||
|
y="27.385403"
|
||||||
|
style="text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ffffff;stroke-width:0.26458332">fs</tspan><tspan
|
||||||
|
dx="0 0 -0.27000001"
|
||||||
|
id="tspan23566"
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="27.238537"
|
||||||
|
y="33.999985"
|
||||||
|
style="text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#ffffff;stroke-width:0.26458332"> fw</tspan></text>
|
||||||
|
<g
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
transform="translate(-44.679185,-123.00002)"
|
||||||
|
id="g23572"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.36171436px;line-height:5.85107136px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;opacity:0.98999999;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.23404284"
|
||||||
|
aria-label="{">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccssccsssccccssccccssscc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23570"
|
||||||
|
style="font-size:18.72342873px;fill:#ffffff;fill-opacity:1;stroke-width:0.23404284"
|
||||||
|
d="m 67.678074,141.482 c -0.798867,0.0624 -1.915603,0.38946 -2.290072,0.80139 -0.361986,0.41191 -0.543,1.06141 -0.543,1.94766 v 1.29191 c 0,1.04851 -0.199567,1.82824 -0.599,2.34001 -0.386951,0.51177 -1.010722,0.82383 -1.872,0.93617 0.848795,0.11234 1.472567,0.41816 1.872,0.91745 0.399433,0.49929 0.599,1.22951 0.599,2.19064 v 1.38554 c 0,0.88624 0.193496,1.5478 0.543,1.98468 0.349504,0.44936 1.453759,0.79514 2.290072,0.85755 v 0.86501 c -1.260711,-0.0749 -2.215606,-0.38696 -2.864685,-0.93618 -0.636597,-0.53673 -0.954895,-1.55404 -0.954895,-3.05192 v -1.23574 c 0,-0.84879 -0.205958,-1.44794 -0.617873,-1.79745 -0.399433,-0.36199 -1.017306,-0.59291 -1.853619,-0.69277 v -0.95489 c 0.761419,-0.0624 1.360569,-0.28084 1.797449,-0.65532 0.449362,-0.38695 0.674043,-0.91745 0.674043,-1.59149 v -1.66639 c 0,-1.26071 0.293334,-2.19064 0.880001,-2.78979 0.586667,-0.59915 1.566527,-0.93617 2.939579,-1.01107 z" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
aria-label="{"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.36171436px;line-height:5.85107136px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;opacity:0.98999999;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.23404284"
|
||||||
|
id="g23576"
|
||||||
|
transform="rotate(180,51.892944,87.3085)">
|
||||||
|
<path
|
||||||
|
d="m 67.678074,141.482 c -0.798867,0.0624 -1.915603,0.38946 -2.290072,0.80139 -0.361986,0.41191 -0.543,1.06141 -0.543,1.94766 v 1.29191 c 0,1.04851 -0.199567,1.82824 -0.599,2.34001 -0.386951,0.51177 -1.010722,0.82383 -1.872,0.93617 0.848795,0.11234 1.472567,0.41816 1.872,0.91745 0.399433,0.49929 0.599,1.22951 0.599,2.19064 v 1.38554 c 0,0.88624 0.193496,1.5478 0.543,1.98468 0.349504,0.44936 1.453759,0.79514 2.290072,0.85755 v 0.86501 c -1.260711,-0.0749 -2.215606,-0.38696 -2.864685,-0.93618 -0.636597,-0.53673 -0.954895,-1.55404 -0.954895,-3.05192 v -1.23574 c 0,-0.84879 -0.205958,-1.44794 -0.617873,-1.79745 -0.399433,-0.36199 -1.017306,-0.59291 -1.853619,-0.69277 v -0.95489 c 0.761419,-0.0624 1.360569,-0.28084 1.797449,-0.65532 0.449362,-0.38695 0.674043,-0.91745 0.674043,-1.59149 v -1.66639 c 0,-1.26071 0.293334,-2.19064 0.880001,-2.78979 0.586667,-0.59915 1.566527,-0.93617 2.939579,-1.01107 z"
|
||||||
|
style="font-size:18.72342873px;fill:#ffffff;fill-opacity:1;stroke-width:0.23404284"
|
||||||
|
id="path23574"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccssccsssccccssccccssscc" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer14"
|
||||||
|
inkscape:label="Logo_colored"
|
||||||
|
style="display:inline"
|
||||||
|
transform="translate(0,17.000002)">
|
||||||
|
<g
|
||||||
|
id="g24826">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ssssssssssssssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23538"
|
||||||
|
d="m 5.558122,19.823743 c -0.811661,0 -1.109125,0.75874 -1.480469,1.48047 l -4.00014,7.77454 c -0.371344,0.72173 0.668807,1.48047 1.480468,1.48047 h 9.625183 c 0.811661,0 1.109108,-0.75875 1.480469,-1.48047 l 4.00036,-7.77454 c 0.371361,-0.72172 -0.668808,-1.48047 -1.480469,-1.48047 z m 0,0.98828 h 9.625402 c 0.281935,0 0.621179,0.2415 0.492187,0.49219 l -4.00036,7.77454 c -0.128993,0.25069 -0.210251,0.49218 -0.492187,0.49218 H 1.557983 c -0.281935,0 -0.621175,-0.24149 -0.492189,-0.49218 l 4.000141,-7.77454 c 0.128986,-0.25069 0.210253,-0.49219 0.492187,-0.49219 z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#00beff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98699999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
transform="translate(0,-17.000002)" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98999999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#00beff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98699999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 47.926633,19.823743 c -0.811661,0 -1.109125,0.75874 -1.480469,1.48047 l -4.00014,7.77454 c -0.371344,0.72173 0.668808,1.48047 1.480469,1.48047 h 9.625909 c 0.81166,0 1.109109,-0.75875 1.48047,-1.48047 l 4.000355,-7.77454 c 0.37136,-0.72172 -0.66881,-1.48047 -1.48046,-1.48047 z m 0,0.98828 h 9.626134 c 0.28193,0 0.62117,0.24151 0.49218,0.49219 l -4.000365,7.77454 c -0.128993,0.25069 -0.21025,0.49218 -0.49218,0.49218 h -9.625909 c -0.281935,0 -0.621174,-0.24149 -0.492188,-0.49218 l 4.00014,-7.77454 c 0.128986,-0.25069 0.210254,-0.49219 0.492188,-0.49219 z"
|
||||||
|
id="path23540"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ssssssssssssssssss"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
inkscape:export-ydpi="499.60001"
|
||||||
|
transform="translate(0,-17.000002)" />
|
||||||
|
<g
|
||||||
|
aria-label="{"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.36171436px;line-height:5.85107136px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;display:inline;opacity:0.98999999;fill:#00519e;fill-opacity:1;stroke:none;stroke-width:0.23404284;enable-background:new"
|
||||||
|
id="g23550"
|
||||||
|
transform="translate(-44.679185,-140.61702)"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
inkscape:export-ydpi="499.60001">
|
||||||
|
<path
|
||||||
|
d="m 67.678074,141.482 c -0.798867,0.0624 -1.915603,0.38946 -2.290072,0.80139 -0.361986,0.41191 -0.543,1.06141 -0.543,1.94766 v 1.29191 c 0,1.04851 -0.199567,1.82824 -0.599,2.34001 -0.386951,0.51177 -1.010722,0.82383 -1.872,0.93617 0.848795,0.11234 1.472567,0.41816 1.872,0.91745 0.399433,0.49929 0.599,1.22951 0.599,2.19064 v 1.38554 c 0,0.88624 0.193496,1.5478 0.543,1.98468 0.349504,0.44936 1.453759,0.79514 2.290072,0.85755 v 0.86501 c -1.260711,-0.0749 -2.215606,-0.38696 -2.864685,-0.93618 -0.636597,-0.53673 -0.954895,-1.55404 -0.954895,-3.05192 v -1.23574 c 0,-0.84879 -0.205958,-1.44794 -0.617873,-1.79745 -0.399433,-0.36199 -1.017306,-0.59291 -1.853619,-0.69277 v -0.95489 c 0.761419,-0.0624 1.360569,-0.28084 1.797449,-0.65532 0.449362,-0.38695 0.674043,-0.91745 0.674043,-1.59149 v -1.66639 c 0,-1.26071 0.293334,-2.19064 0.880001,-2.78979 0.586667,-0.59915 1.566527,-0.93617 2.939579,-1.01107 z"
|
||||||
|
style="font-size:18.72342873px;fill:#00519e;fill-opacity:1;stroke-width:0.23404284"
|
||||||
|
id="path23548"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccssccsssccccssccccssscc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="rotate(180,51.892943,78.500001)"
|
||||||
|
id="g23554"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.36171436px;line-height:5.85107136px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';letter-spacing:0px;word-spacing:0px;display:inline;opacity:0.98999999;fill:#00519e;fill-opacity:1;stroke:none;stroke-width:0.23404284;enable-background:new"
|
||||||
|
aria-label="{"
|
||||||
|
inkscape:export-xdpi="499.60001"
|
||||||
|
inkscape:export-ydpi="499.60001">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccssccsssccccssccccssscc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23552"
|
||||||
|
style="font-size:18.72342873px;fill:#00519e;fill-opacity:1;stroke-width:0.23404284"
|
||||||
|
d="m 67.678074,141.482 c -0.798867,0.0624 -1.915603,0.38946 -2.290072,0.80139 -0.361986,0.41191 -0.543,1.06141 -0.543,1.94766 v 1.29191 c 0,1.04851 -0.199567,1.82824 -0.599,2.34001 -0.386951,0.51177 -1.010722,0.82383 -1.872,0.93617 0.848795,0.11234 1.472567,0.41816 1.872,0.91745 0.399433,0.49929 0.599,1.22951 0.599,2.19064 v 1.38554 c 0,0.88624 0.193496,1.5478 0.543,1.98468 0.349504,0.44936 1.453759,0.79514 2.290072,0.85755 v 0.86501 c -1.260711,-0.0749 -2.215606,-0.38696 -2.864685,-0.93618 -0.636597,-0.53673 -0.954895,-1.55404 -0.954895,-3.05192 v -1.23574 c 0,-0.84879 -0.205958,-1.44794 -0.617873,-1.79745 -0.399433,-0.36199 -1.017306,-0.59291 -1.853619,-0.69277 v -0.95489 c 0.761419,-0.0624 1.360569,-0.28084 1.797449,-0.65532 0.449362,-0.38695 0.674043,-0.91745 0.674043,-1.59149 v -1.66639 c 0,-1.26071 0.293334,-2.19064 0.880001,-2.78979 0.586667,-0.59915 1.566527,-0.93617 2.939579,-1.01107 z" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23705"
|
||||||
|
d="m 24.042453,7.7684013 h 0.98425 V 6.1909995 h -0.98425 z"
|
||||||
|
style="display:inline;fill:#00519e;fill-opacity:1;stroke:none;stroke-width:0.15297562px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23707"
|
||||||
|
d="m 26.264953,3.0725683 -2.2225,3e-7 v 0.7196666 l 2.2225,-3e-7 z"
|
||||||
|
style="display:inline;fill:#0087ce;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
transform="translate(0,-0.617)" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23709"
|
||||||
|
d="m 22.994703,3.0725686 v 0.7196666 h 1.04775 V 3.0725686 Z"
|
||||||
|
style="display:inline;fill:none;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
transform="translate(0,-0.617)" />
|
||||||
|
<path
|
||||||
|
id="path23719"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#00beff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
d="m 26.41312,1.4850686 c -0.1905,-0.014111 -0.373945,-0.021167 -0.550334,-0.021167 -0.282222,0 -0.493889,0.045861 -0.635,0.1375834 -0.772583,-0.62441639 0,0 -0.772583,-0.62441639 0.282222,-0.23988888 0.663222,-0.35983332 1.143,-0.35983332 0.141111,0 0.278695,0.007056 0.41275,0.0211667 0.141111,0.0141111 0.275167,0.03175 0.402167,0.0529167 z"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="csccsccc"
|
||||||
|
transform="translate(0,-0.617)" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="csccscc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
d="m 25.227786,1.601485 c -0.134055,0.091722 -0.201083,0.2751666 -0.201083,0.5503333 v 0.92075 l -0.98425,3e-7 v -0.85725 c 0,-0.5926667 0.137583,-1.0054167 0.41275,-1.23824999 0.772583,0.62441639 0,0 0.772583,0.62441639 z"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#00a3e7;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
id="path23717"
|
||||||
|
transform="translate(0,-0.617)" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23727"
|
||||||
|
d="m 22.994703,2.4555686 v 0.7196666 h 1.04775 V 2.4555686 h -1.04775"
|
||||||
|
style="fill:#00beff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23729"
|
||||||
|
d="m 24.042453,6.1909994 h 0.98425 V 3.1752349 l -0.98425,3e-7 v 3.0157642"
|
||||||
|
style="fill:#006cb6;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23731"
|
||||||
|
d="m 24.02759,11.070149 v 0.719667 h 2.032 v -0.719667 z"
|
||||||
|
style="fill:#00beff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23733"
|
||||||
|
d="m 27.29784,11.070149 v 0.719667 h -1.23825 v -0.719667"
|
||||||
|
style="fill:#00a3e7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23735"
|
||||||
|
d="m 25.07534,13.366982 h 0.98425 v 3.016 h -0.98425 z"
|
||||||
|
style="fill:#00beff;fill-opacity:1;stroke:none;stroke-width:0.21439861px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23737"
|
||||||
|
d="m 25.07534,11.789816 h 0.98425 v 1.577166 h -0.98425 v -1.577166"
|
||||||
|
style="fill:#00a3e7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cscsccscsccc"
|
||||||
|
d="m 27.446007,10.099652 c -0.1905,-0.01411 -0.373945,-0.02117 -0.550334,-0.02117 -0.282222,0 -0.493889,0.04586 -0.635,0.137584 -0.134055,0.09172 -0.201083,0.275166 -0.201083,0.550333 v 0.92075 h -0.98425 v -0.85725 c 0,-0.592667 0.137583,-1.0054166 0.41275,-1.2382499 0.282222,-0.2398889 0.663222,-0.3598333 1.143,-0.3598333 0.141111,0 0.278695,0.00706 0.41275,0.021167 0.141111,0.014111 0.275167,0.03175 0.402167,0.052917 z"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#006cb6;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
id="path23739"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
transform="translate(0,-0.617)" />
|
||||||
|
<path
|
||||||
|
d="m 28.921204,8.5335684 c -0.677333,0 -1.199444,-0.1481667 -1.566333,-0.4445 -0.359833,-0.3033889 -0.53975,-0.7307356 -0.53975,-1.2810689 l 1.04775,4.856e-4 c 0,0.3033889 0.09878,0.53975 0.296333,0.7090833 0.204611,0.1693333 0.497417,0.254 0.878417,0.254 0,0 0,0 -0.116417,0.762 z"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#00beff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
id="path23748"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccccccc"
|
||||||
|
transform="translate(0,-0.617)" />
|
||||||
|
<path
|
||||||
|
d="m 29.799621,5.3903185 c 0.465667,0.1128889 0.811389,0.28575 1.037166,0.5185833 0.232833,0.2257778 0.34925,0.5326945 0.34925,0.92075 0,0.5221111 -0.197555,0.9383888 -0.592666,1.2488333 -0.395111,0.3033889 -0.9525,0.4550833 -1.672167,0.4550833 0.116417,-0.762 0,0 0.116417,-0.762 0.359833,0 0.631472,-0.077611 0.814917,-0.2328333 0.183444,-0.1552222 0.275166,-0.3563055 0.275166,-0.60325 0,-0.3175 -0.165805,-0.5221111 -0.497416,-0.6138333 0.169333,-0.9313333 0,0 0.169333,-0.9313333 z"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#0087ce;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
id="path23752"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccsccccscc"
|
||||||
|
transform="translate(0,-0.617)" />
|
||||||
|
<path
|
||||||
|
d="m 27.926371,4.4378185 c 0,0.3245555 0.215194,0.53975 0.645583,0.6455833 l 1.227667,0.3069167 c -0.169333,0.9313333 0,0 -0.169333,0.9313333 C 29.298677,6.222874 28.910621,6.1240962 28.466121,6.0253185 28.014566,5.9265407 27.644149,5.7677907 27.354871,5.5490685 27.065593,5.3303463 26.920954,4.9987352 26.920954,4.5542352 c 1.005417,-0.1164167 0,0 1.005417,-0.1164167 z"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#00a3e7;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
id="path23755"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cccccscc"
|
||||||
|
transform="translate(0,-0.617)" />
|
||||||
|
<path
|
||||||
|
d="m 31.048454,4.5436518 h -1.016 v -0.0635 c 0,-0.5362222 -0.342194,-0.8043333 -1.026583,-0.8043333 -0.338667,0 -0.60325,0.067028 -0.79375,0.2010834 -0.1905,0.127 -0.28575,0.3139722 -0.28575,0.5609166 -1.005417,0.1164167 0,0 -1.005417,0.1164167 0,-0.4797778 0.1905,-0.8678334 0.5715,-1.1641667 0.388056,-0.2963333 0.889001,-0.4444999 1.502834,-0.4444999 0.578555,0 1.065388,0.1199444 1.460499,0.3598333 0.395111,0.2328333 0.592667,0.5961944 0.592667,1.0900833 z"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#006cb6;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
id="path23758"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccssccccscsc"
|
||||||
|
transform="translate(0,-0.617)" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccc"
|
||||||
|
transform="translate(0,-0.617)"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23764"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#00beff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
d="m 33.742924,15.878152 1.3335,-4.191 h 1.026583 l -1.87325,5.312833 h -1.142999 c 0.656166,-1.121833 0,0 0.656166,-1.121833 z" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
d="m 32.536424,11.070152 1.2065,4.191 c -0.656166,1.121833 0,0 -0.656166,1.121833 l -1.248834,-4.370916 c 0.6985,-0.941917 0,0 0.6985,-0.941917 z"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#00a3e7;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
id="path23766"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccccc"
|
||||||
|
transform="translate(0,-0.617)"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path23768"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#0087ce;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
d="m 29.890591,15.920485 1.344083,-4.233333 h 1.30175 c -0.6985,0.941917 0,0 -0.6985,0.941917 l -1.386416,4.370916 h -1.17475 c 0.613833,-1.0795 0,0 0.613833,-1.0795 z" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
d="m 28.610008,11.687152 1.280583,4.233333 c -0.613833,1.0795 0,0 -0.613833,1.0795 l -1.756834,-5.312833 z"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:6.61458349px;font-family:'Univers for UniS 55 Roman';-inkscape-font-specification:'Univers for UniS 55 Roman, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;display:inline;opacity:0.98999999;fill:#00519e;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
id="path23770"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
transform="translate(0,-0.617)" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer16"
|
||||||
|
inkscape:label="Logo_gradient"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="display:inline;opacity:1;fill:url(#meshgradient23819);fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;enable-background:new"
|
||||||
|
id="rect23817"
|
||||||
|
width="59.111"
|
||||||
|
height="16.382999"
|
||||||
|
x="-1.110223e-016"
|
||||||
|
y="3.8147118e-006"
|
||||||
|
clip-path="url(#clipPath24955)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 58 KiB |
BIN
logo/FSFW_Logo_V3_bw.png
Normal file
BIN
logo/FSFW_Logo_V3_bw.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
@ -1,42 +1,76 @@
|
|||||||
#include "MessageQueue.h"
|
#include "MessageQueue.h"
|
||||||
|
|
||||||
#include "../../objectmanager/ObjectManagerIF.h"
|
#include "../../objectmanager/ObjectManagerIF.h"
|
||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||||
|
|
||||||
// TODO I guess we should have a way of checking if we are in an ISR and then use the "fromISR" versions of all calls
|
// TODO I guess we should have a way of checking if we are in an ISR and then
|
||||||
|
// use the "fromISR" versions of all calls
|
||||||
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) :
|
// As a first step towards this, introduces system context variable which needs
|
||||||
defaultDestination(0),lastPartner(0) {
|
// to be switched manually
|
||||||
handle = xQueueCreate(message_depth, max_message_size);
|
// Haven't found function to find system context.
|
||||||
if (handle == NULL) {
|
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize):
|
||||||
sif::error << "MessageQueue creation failed" << std::endl;
|
maxMessageSize(maxMessageSize) {
|
||||||
|
handle = xQueueCreate(messageDepth, maxMessageSize);
|
||||||
|
if (handle == nullptr) {
|
||||||
|
sif::error << "MessageQueue::MessageQueue Creation failed" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueue::~MessageQueue() {
|
MessageQueue::~MessageQueue() {
|
||||||
if (handle != NULL) {
|
if (handle != nullptr) {
|
||||||
vQueueDelete(handle);
|
vQueueDelete(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageQueue::switchSystemContext(CallContext callContext) {
|
||||||
|
this->callContext = callContext;
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, bool ignoreFault) {
|
MessageQueueMessageIF* message, bool ignoreFault) {
|
||||||
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
|
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) {
|
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
|
||||||
return sendToDefaultFrom(message, this->getId());
|
return sendToDefaultFrom(message, this->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
|
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
|
||||||
if (this->lastPartner != 0) {
|
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||||
|
return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
|
||||||
|
if (this->lastPartner != MessageQueueIF::NO_QUEUE) {
|
||||||
return sendMessageFrom(this->lastPartner, message, this->getId());
|
return sendMessageFrom(this->lastPartner, message, this->getId());
|
||||||
} else {
|
} else {
|
||||||
return NO_REPLY_PARTNER;
|
return NO_REPLY_PARTNER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message,
|
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
||||||
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||||
|
bool ignoreFault) {
|
||||||
|
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault,
|
||||||
|
callContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) {
|
||||||
|
if (result != pdPASS) {
|
||||||
|
if (not ignoreFault) {
|
||||||
|
InternalErrorReporterIF* internalErrorReporter = objectManager->
|
||||||
|
get<InternalErrorReporterIF>(
|
||||||
|
objects::INTERNAL_ERROR_REPORTER);
|
||||||
|
if (internalErrorReporter != nullptr) {
|
||||||
|
internalErrorReporter->queueMessageNotSent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MessageQueueIF::FULL;
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t* receivedFrom) {
|
MessageQueueId_t* receivedFrom) {
|
||||||
ReturnValue_t status = this->receiveMessage(message);
|
ReturnValue_t status = this->receiveMessage(message);
|
||||||
if(status == HasReturnvaluesIF::RETURN_OK) {
|
if(status == HasReturnvaluesIF::RETURN_OK) {
|
||||||
@ -45,8 +79,9 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||||
BaseType_t result = xQueueReceive(handle,reinterpret_cast<void*>(message->getBuffer()), 0);
|
BaseType_t result = xQueueReceive(handle,reinterpret_cast<void*>(
|
||||||
|
message->getBuffer()), 0);
|
||||||
if (result == pdPASS){
|
if (result == pdPASS){
|
||||||
this->lastPartner = message->getSender();
|
this->lastPartner = message->getSender();
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
@ -67,51 +102,55 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getId() const {
|
MessageQueueId_t MessageQueue::getId() const {
|
||||||
return (MessageQueueId_t) handle;
|
return reinterpret_cast<MessageQueueId_t>(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
||||||
|
defaultDestinationSet = true;
|
||||||
this->defaultDestination = defaultDestination;
|
this->defaultDestination = defaultDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
|
||||||
MessageQueueMessage* message, MessageQueueId_t sentFrom,
|
|
||||||
bool ignoreFault) {
|
|
||||||
return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
|
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
|
||||||
return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getDefaultDestination() const {
|
MessageQueueId_t MessageQueue::getDefaultDestination() const {
|
||||||
return defaultDestination;
|
return defaultDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MessageQueue::isDefaultDestinationSet() const {
|
bool MessageQueue::isDefaultDestinationSet() const {
|
||||||
return 0;
|
return defaultDestinationSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static core function to send messages.
|
||||||
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage *message, MessageQueueId_t sentFrom,
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||||
bool ignoreFault) {
|
bool ignoreFault, CallContext callContext) {
|
||||||
|
BaseType_t result = pdFALSE;
|
||||||
|
QueueHandle_t destination = nullptr;
|
||||||
|
|
||||||
|
if(sendTo == MessageQueueIF::NO_QUEUE or sendTo == 0x00) {
|
||||||
|
return MessageQueueIF::DESTINVATION_INVALID;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
destination = reinterpret_cast<QueueHandle_t>(sendTo);
|
||||||
|
}
|
||||||
|
|
||||||
message->setSender(sentFrom);
|
message->setSender(sentFrom);
|
||||||
|
|
||||||
BaseType_t result = xQueueSendToBack(reinterpret_cast<QueueHandle_t>(sendTo),
|
|
||||||
reinterpret_cast<const void*>(message->getBuffer()), 0);
|
|
||||||
if (result != pdPASS) {
|
|
||||||
if (!ignoreFault) {
|
|
||||||
InternalErrorReporterIF* internalErrorReporter =
|
|
||||||
objectManager->get<InternalErrorReporterIF>(
|
|
||||||
objects::INTERNAL_ERROR_REPORTER);
|
|
||||||
if (internalErrorReporter != NULL) {
|
|
||||||
internalErrorReporter->queueMessageNotSent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return MessageQueueIF::FULL;
|
|
||||||
}
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
|
|
||||||
|
if(callContext == CallContext::TASK) {
|
||||||
|
result = xQueueSendToBack(destination,
|
||||||
|
static_cast<const void*>(message->getBuffer()), 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* If the call context is from an interrupt,
|
||||||
|
* request a context switch if a higher priority task
|
||||||
|
* was blocked by the interrupt. */
|
||||||
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
result = xQueueSendFromISR(reinterpret_cast<QueueHandle_t>(sendTo),
|
||||||
|
static_cast<const void*>(message->getBuffer()),
|
||||||
|
&xHigherPriorityTaskWoken);
|
||||||
|
if(xHigherPriorityTaskWoken == pdTRUE) {
|
||||||
|
TaskManagement::requestContextSwitch(callContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return handleSendResult(result, ignoreFault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,159 +1,150 @@
|
|||||||
#ifndef MESSAGEQUEUE_H_
|
#ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
||||||
#define MESSAGEQUEUE_H_
|
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
||||||
|
|
||||||
#include "../../internalError/InternalErrorReporterIF.h"
|
#include "../../internalError/InternalErrorReporterIF.h"
|
||||||
#include "../../ipc/MessageQueueIF.h"
|
#include "../../ipc/MessageQueueIF.h"
|
||||||
#include "../../ipc/MessageQueueMessage.h"
|
#include "../../ipc/MessageQueueMessageIF.h"
|
||||||
|
#include "../../osal/FreeRTOS/TaskManagement.h"
|
||||||
|
|
||||||
#include <FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <queue.h>
|
#include <freertos/queue.h>
|
||||||
|
#include <fsfw/ipc/MessageQueueMessage.h>
|
||||||
|
|
||||||
//TODO this class assumes that MessageQueueId_t is the same size as void* (the FreeRTOS handle type), compiler will catch this but it might be nice to have something checking or even an always working solution
|
// TODO: this class assumes that MessageQueueId_t is the same size as void*
|
||||||
|
// (the FreeRTOS handle type), compiler will catch this but it might be nice
|
||||||
|
// to have something checking or even an always working solution
|
||||||
// https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/
|
// https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class manages sending and receiving of message queue messages.
|
* @brief This class manages sending and receiving of
|
||||||
*
|
* message queue messages.
|
||||||
* @details Message queues are used to pass asynchronous messages between processes.
|
* @details
|
||||||
|
* Message queues are used to pass asynchronous messages between processes.
|
||||||
* They work like post boxes, where all incoming messages are stored in FIFO
|
* They work like post boxes, where all incoming messages are stored in FIFO
|
||||||
* order. This class creates a new receiving queue and provides methods to fetch
|
* order. This class creates a new receiving queue and provides methods to fetch
|
||||||
* received messages. Being a child of MessageQueueSender, this class also provides
|
* received messages. Being a child of MessageQueueSender, this class also
|
||||||
* methods to send a message to a user-defined or a default destination. In addition
|
* provides methods to send a message to a user-defined or a default destination.
|
||||||
* it also provides a reply method to answer to the queue it received its last message
|
* In addition it also provides a reply method to answer to the queue it
|
||||||
* from.
|
* received its last message from.
|
||||||
* The MessageQueue should be used as "post box" for a single owning object. So all
|
*
|
||||||
* message queue communication is "n-to-one".
|
* The MessageQueue should be used as "post box" for a single owning object.
|
||||||
* For creating the queue, as well as sending and receiving messages, the class makes
|
* So all message queue communication is "n-to-one".
|
||||||
* use of the operating system calls provided.
|
* For creating the queue, as well as sending and receiving messages, the class
|
||||||
* \ingroup message_queue
|
* makes use of the operating system calls provided.
|
||||||
|
*
|
||||||
|
* Please keep in mind that FreeRTOS offers different calls for message queue
|
||||||
|
* operations if called from an ISR.
|
||||||
|
* For now, the system context needs to be switched manually.
|
||||||
|
* @ingroup osal
|
||||||
|
* @ingroup message_queue
|
||||||
*/
|
*/
|
||||||
class MessageQueue : public MessageQueueIF {
|
class MessageQueue : public MessageQueueIF {
|
||||||
friend class MessageQueueSenderIF;
|
friend class MessageQueueSenderIF;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief The constructor initializes and configures the message queue.
|
* @brief The constructor initializes and configures the message queue.
|
||||||
* @details By making use of the according operating system call, a message queue is created
|
* @details
|
||||||
* and initialized. The message depth - the maximum number of messages to be
|
* By making use of the according operating system call, a message queue
|
||||||
* buffered - may be set with the help of a parameter, whereas the message size is
|
* is created and initialized. The message depth - the maximum number of
|
||||||
* automatically set to the maximum message queue message size. The operating system
|
* messages to be buffered - may be set with the help of a parameter,
|
||||||
* sets the message queue id, or i case of failure, it is set to zero.
|
* whereas the message size is automatically set to the maximum message
|
||||||
* @param message_depth The number of messages to be buffered before passing an error to the
|
* queue message size. The operating system sets the message queue id, or
|
||||||
|
* in case of failure, it is set to zero.
|
||||||
|
* @param message_depth
|
||||||
|
* The number of messages to be buffered before passing an error to the
|
||||||
* sender. Default is three.
|
* sender. Default is three.
|
||||||
* @param max_message_size With this parameter, the maximum message size can be adjusted.
|
* @param max_message_size
|
||||||
|
* With this parameter, the maximum message size can be adjusted.
|
||||||
* This should be left default.
|
* This should be left default.
|
||||||
*/
|
*/
|
||||||
MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE );
|
MessageQueue( size_t messageDepth = 3,
|
||||||
|
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE );
|
||||||
|
|
||||||
|
/** Copying message queues forbidden */
|
||||||
|
MessageQueue(const MessageQueue&) = delete;
|
||||||
|
MessageQueue& operator=(const MessageQueue&) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The destructor deletes the formerly created message queue.
|
* @brief The destructor deletes the formerly created message queue.
|
||||||
* @details This is accomplished by using the delete call provided by the operating system.
|
* @details This is accomplished by using the delete call provided
|
||||||
|
* by the operating system.
|
||||||
*/
|
*/
|
||||||
virtual ~MessageQueue();
|
virtual ~MessageQueue();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This operation sends a message to the given destination.
|
* This function is used to switch the call context. This has to be called
|
||||||
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its
|
* if a message is sent or received from an ISR!
|
||||||
* queue id as "sentFrom" parameter.
|
* @param callContext
|
||||||
* @param sendTo This parameter specifies the message queue id of the destination message queue.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
|
||||||
*/
|
*/
|
||||||
|
void switchSystemContext(CallContext callContext);
|
||||||
|
|
||||||
|
/** MessageQueueIF implementation */
|
||||||
ReturnValue_t sendMessage(MessageQueueId_t sendTo,
|
ReturnValue_t sendMessage(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, bool ignoreFault = false );
|
MessageQueueMessageIF* message, bool ignoreFault = false) override;
|
||||||
/**
|
|
||||||
* @brief This operation sends a message to the default destination.
|
|
||||||
* @details As in the sendMessage method, this function uses the sendToDefault call of the
|
|
||||||
* MessageQueueSender parent class and adds its queue id as "sentFrom" information.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
*/
|
|
||||||
ReturnValue_t sendToDefault( MessageQueueMessage* message );
|
|
||||||
/**
|
|
||||||
* @brief This operation sends a message to the last communication partner.
|
|
||||||
* @details This operation simplifies answering an incoming message by using the stored
|
|
||||||
* lastParnter information as destination. If there was no message received yet
|
|
||||||
* (i.e. lastPartner is zero), an error code is returned.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
*/
|
|
||||||
ReturnValue_t reply( MessageQueueMessage* message );
|
|
||||||
|
|
||||||
/**
|
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
||||||
* @brief This function reads available messages from the message queue and returns the sender.
|
|
||||||
* @details It works identically to the other receiveMessage call, but in addition returns the
|
|
||||||
* sender's queue id.
|
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
|
||||||
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
|
|
||||||
*/
|
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessage* message,
|
|
||||||
MessageQueueId_t *receivedFrom);
|
|
||||||
|
|
||||||
/**
|
ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
||||||
* @brief This function reads available messages from the message queue.
|
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo,
|
||||||
* @details If data is available it is stored in the passed message pointer. The message's
|
MessageQueueMessageIF* message,
|
||||||
* original content is overwritten and the sendFrom information is stored in the
|
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||||
* lastPartner attribute. Else, the lastPartner information remains untouched, the
|
bool ignoreFault = false) override;
|
||||||
* message's content is cleared and the function returns immediately.
|
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
|
||||||
*/
|
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessage* message);
|
bool ignoreFault = false) override;
|
||||||
/**
|
|
||||||
* Deletes all pending messages in the queue.
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
||||||
* @param count The number of flushed messages.
|
MessageQueueId_t *receivedFrom) override;
|
||||||
* @return RETURN_OK on success.
|
|
||||||
*/
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
||||||
ReturnValue_t flush(uint32_t* count);
|
|
||||||
/**
|
ReturnValue_t flush(uint32_t* count) override;
|
||||||
* @brief This method returns the message queue id of the last communication partner.
|
|
||||||
*/
|
MessageQueueId_t getLastPartner() const override;
|
||||||
MessageQueueId_t getLastPartner() const;
|
|
||||||
/**
|
MessageQueueId_t getId() const override;
|
||||||
* @brief This method returns the message queue id of this class's message queue.
|
|
||||||
*/
|
void setDefaultDestination(MessageQueueId_t defaultDestination) override;
|
||||||
MessageQueueId_t getId() const;
|
|
||||||
/**
|
MessageQueueId_t getDefaultDestination() const override;
|
||||||
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
|
|
||||||
* \details This method takes the message provided, adds the sentFrom information and passes
|
bool isDefaultDestinationSet() const override;
|
||||||
* it on to the destination provided with an operating system call. The OS's return
|
|
||||||
* value is returned.
|
|
||||||
* \param sendTo This parameter specifies the message queue id to send the message to.
|
|
||||||
* \param message This is a pointer to a previously created message, which is sent.
|
|
||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
|
||||||
* This variable is set to zero by default.
|
|
||||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
|
||||||
/**
|
|
||||||
* \brief The sendToDefault method sends a queue message to the default destination.
|
|
||||||
* \details In all other aspects, it works identical to the sendMessage method.
|
|
||||||
* \param message This is a pointer to a previously created message, which is sent.
|
|
||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
|
||||||
* This variable is set to zero by default.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
|
||||||
/**
|
|
||||||
* \brief This method is a simple setter for the default destination.
|
|
||||||
*/
|
|
||||||
void setDefaultDestination(MessageQueueId_t defaultDestination);
|
|
||||||
/**
|
|
||||||
* \brief This method is a simple getter for the default destination.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getDefaultDestination() const;
|
|
||||||
|
|
||||||
bool isDefaultDestinationSet() const;
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Implementation to be called from any send Call within MessageQueue and MessageQueueSenderIF
|
* @brief Implementation to be called from any send Call within
|
||||||
* \details This method takes the message provided, adds the sentFrom information and passes
|
* MessageQueue and MessageQueueSenderIF.
|
||||||
* it on to the destination provided with an operating system call. The OS's return
|
* @details
|
||||||
* value is returned.
|
* This method takes the message provided, adds the sentFrom information and
|
||||||
* \param sendTo This parameter specifies the message queue id to send the message to.
|
* passes it on to the destination provided with an operating system call.
|
||||||
* \param message This is a pointer to a previously created message, which is sent.
|
* The OS's return value is returned.
|
||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
* @param sendTo
|
||||||
* This variable is set to zero by default.
|
* This parameter specifies the message queue id to send the message to.
|
||||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
* @param message
|
||||||
|
* This is a pointer to a previously created message, which is sent.
|
||||||
|
* @param sentFrom
|
||||||
|
* The sentFrom information can be set to inject the sender's queue id into
|
||||||
|
* the message. This variable is set to zero by default.
|
||||||
|
* @param ignoreFault
|
||||||
|
* If set to true, the internal software fault counter is not incremented
|
||||||
|
* if queue is full.
|
||||||
|
* @param context Specify whether call is made from task or from an ISR.
|
||||||
*/
|
*/
|
||||||
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,bool ignoreFault=false);
|
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||||
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE,
|
||||||
|
bool ignoreFault=false, CallContext callContext = CallContext::TASK);
|
||||||
|
|
||||||
|
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool defaultDestinationSet = false;
|
||||||
QueueHandle_t handle;
|
QueueHandle_t handle;
|
||||||
MessageQueueId_t defaultDestination;
|
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
|
||||||
MessageQueueId_t lastPartner;
|
MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
|
||||||
|
const size_t maxMessageSize;
|
||||||
|
//! Stores the current system context
|
||||||
|
CallContext callContext = CallContext::TASK;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MESSAGEQUEUE_H_ */
|
#endif /* FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ */
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
|
#include "MessageQueue.h"
|
||||||
|
|
||||||
#include "../../ipc/MessageQueueSenderIF.h"
|
#include "../../ipc/MessageQueueSenderIF.h"
|
||||||
#include "../../ipc/QueueFactory.h"
|
#include "../../ipc/QueueFactory.h"
|
||||||
|
|
||||||
#include "MessageQueue.h"
|
|
||||||
|
|
||||||
|
|
||||||
QueueFactory* QueueFactory::factoryInstance = nullptr;
|
QueueFactory* QueueFactory::factoryInstance = nullptr;
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, MessageQueueId_t sentFrom,
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||||
bool ignoreFault) {
|
bool ignoreFault) {
|
||||||
return MessageQueue::sendMessageFromMessageQueue(sendTo,message,
|
return MessageQueue::sendMessageFromMessageQueue(sendTo,message,
|
||||||
sentFrom,ignoreFault);
|
sentFrom,ignoreFault);
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
|
|
||||||
|
#include "MessageQueue.h"
|
||||||
|
|
||||||
|
#include "../../ipc/MessageQueueSenderIF.h"
|
||||||
|
#include "../../ipc/MessageQueueMessageIF.h"
|
||||||
#include "../../ipc/QueueFactory.h"
|
#include "../../ipc/QueueFactory.h"
|
||||||
#include "../../osal/host/MessageQueue.h"
|
|
||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
QueueFactory* QueueFactory::factoryInstance = nullptr;
|
QueueFactory* QueueFactory::factoryInstance = nullptr;
|
||||||
|
@ -9,9 +9,11 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize):
|
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize):
|
||||||
id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE),
|
id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE),
|
||||||
defaultDestination(MessageQueueIF::NO_QUEUE) {
|
defaultDestination(MessageQueueIF::NO_QUEUE),
|
||||||
|
maxMessageSize(maxMessageSize) {
|
||||||
//debug << "MessageQueue::MessageQueue: Creating a queue" << std::endl;
|
//debug << "MessageQueue::MessageQueue: Creating a queue" << std::endl;
|
||||||
mq_attr attributes;
|
mq_attr attributes;
|
||||||
this->id = 0;
|
this->id = 0;
|
||||||
@ -61,22 +63,27 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes,
|
|||||||
// Just an additional helpful printout :-)
|
// Just an additional helpful printout :-)
|
||||||
if(std::ifstream("/proc/sys/fs/mqueue/msg_max",std::ios::in) >>
|
if(std::ifstream("/proc/sys/fs/mqueue/msg_max",std::ios::in) >>
|
||||||
defaultMqMaxMsg and defaultMqMaxMsg < messageDepth) {
|
defaultMqMaxMsg and defaultMqMaxMsg < messageDepth) {
|
||||||
// See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html
|
/*
|
||||||
// This happens if the msg_max value is not large enough
|
See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html
|
||||||
// It is ignored if the executable is run in privileged mode.
|
This happens if the msg_max value is not large enough
|
||||||
// Run the unlockRealtime script or grant the mode manually by using:
|
It is ignored if the executable is run in privileged mode.
|
||||||
// sudo setcap 'CAP_SYS_RESOURCE=+ep' <pathToBinary>
|
Run the unlockRealtime script or grant the mode manually by using:
|
||||||
|
sudo setcap 'CAP_SYS_RESOURCE=+ep' <pathToBinary>
|
||||||
|
|
||||||
// Persistent solution for session:
|
Persistent solution for session:
|
||||||
// echo <newMsgMax> | sudo tee /proc/sys/fs/mqueue/msg_max
|
echo <newMsgMax> | sudo tee /proc/sys/fs/mqueue/msg_max
|
||||||
|
|
||||||
// Permanent solution:
|
Permanent solution:
|
||||||
// sudo nano /etc/sysctl.conf
|
sudo nano /etc/sysctl.conf
|
||||||
// Append at end: fs/mqueue/msg_max = <newMsgMaxLen>
|
Append at end: fs/mqueue/msg_max = <newMsgMaxLen>
|
||||||
// Apply changes with: sudo sysctl -p
|
Apply changes with: sudo sysctl -p
|
||||||
|
*/
|
||||||
sif::error << "MessageQueue::MessageQueue: Default MQ size "
|
sif::error << "MessageQueue::MessageQueue: Default MQ size "
|
||||||
<< defaultMqMaxMsg << " is too small for requested size "
|
<< defaultMqMaxMsg << " is too small for requested size "
|
||||||
<< messageDepth << std::endl;
|
<< messageDepth << std::endl;
|
||||||
|
sif::error << "This error can be fixed by setting the maximum "
|
||||||
|
"allowed message size higher!" << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -118,15 +125,15 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, bool ignoreFault) {
|
MessageQueueMessageIF* message, bool ignoreFault) {
|
||||||
return sendMessageFrom(sendTo, message, this->getId(), false);
|
return sendMessageFrom(sendTo, message, this->getId(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) {
|
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
|
||||||
return sendToDefaultFrom(message, this->getId());
|
return sendToDefaultFrom(message, this->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
|
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
|
||||||
if (this->lastPartner != 0) {
|
if (this->lastPartner != 0) {
|
||||||
return sendMessageFrom(this->lastPartner, message, this->getId());
|
return sendMessageFrom(this->lastPartner, message, this->getId());
|
||||||
} else {
|
} else {
|
||||||
@ -134,21 +141,34 @@ ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message,
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t* receivedFrom) {
|
MessageQueueId_t* receivedFrom) {
|
||||||
ReturnValue_t status = this->receiveMessage(message);
|
ReturnValue_t status = this->receiveMessage(message);
|
||||||
*receivedFrom = this->lastPartner;
|
*receivedFrom = this->lastPartner;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||||
|
if(message == nullptr) {
|
||||||
|
sif::error << "MessageQueue::receiveMessage: Message is "
|
||||||
|
"nullptr!" << std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(message->getMaximumMessageSize() < maxMessageSize) {
|
||||||
|
sif::error << "MessageQueue::receiveMessage: Message size "
|
||||||
|
<< message->getMaximumMessageSize()
|
||||||
|
<< " too small to receive data!" << std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int messagePriority = 0;
|
unsigned int messagePriority = 0;
|
||||||
int status = mq_receive(id,reinterpret_cast<char*>(message->getBuffer()),
|
int status = mq_receive(id,reinterpret_cast<char*>(message->getBuffer()),
|
||||||
message->MAX_MESSAGE_SIZE,&messagePriority);
|
message->getMaximumMessageSize(),&messagePriority);
|
||||||
if (status > 0) {
|
if (status > 0) {
|
||||||
this->lastPartner = message->getSender();
|
this->lastPartner = message->getSender();
|
||||||
//Check size of incoming message.
|
//Check size of incoming message.
|
||||||
if (message->messageSize < message->getMinimumMessageSize()) {
|
if (message->getMessageSize() < message->getMinimumMessageSize()) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
@ -158,7 +178,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
|
|||||||
} else {
|
} else {
|
||||||
//No message was received. Keep lastPartner anyway, I might send
|
//No message was received. Keep lastPartner anyway, I might send
|
||||||
//something later. But still, delete packet content.
|
//something later. But still, delete packet content.
|
||||||
memset(message->getData(), 0, message->MAX_DATA_SIZE);
|
memset(message->getData(), 0, message->getMaximumMessageSize());
|
||||||
switch(errno){
|
switch(errno){
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
//O_NONBLOCK or MQ_NONBLOCK was set and there are no messages
|
//O_NONBLOCK or MQ_NONBLOCK was set and there are no messages
|
||||||
@ -258,18 +278,19 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
|||||||
this->defaultDestination = defaultDestination;
|
this->defaultDestination = defaultDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
|
||||||
|
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||||
|
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, MessageQueueId_t sentFrom,
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||||
bool ignoreFault) {
|
bool ignoreFault) {
|
||||||
return sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault);
|
return sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
|
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
|
||||||
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getDefaultDestination() const {
|
MessageQueueId_t MessageQueue::getDefaultDestination() const {
|
||||||
return this->defaultDestination;
|
return this->defaultDestination;
|
||||||
}
|
}
|
||||||
@ -281,11 +302,18 @@ bool MessageQueue::isDefaultDestinationSet() const {
|
|||||||
uint16_t MessageQueue::queueCounter = 0;
|
uint16_t MessageQueue::queueCounter = 0;
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage *message, MessageQueueId_t sentFrom,
|
MessageQueueMessageIF *message, MessageQueueId_t sentFrom,
|
||||||
bool ignoreFault) {
|
bool ignoreFault) {
|
||||||
|
if(message == nullptr) {
|
||||||
|
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is "
|
||||||
|
"nullptr!" << std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
message->setSender(sentFrom);
|
message->setSender(sentFrom);
|
||||||
int result = mq_send(sendTo,
|
int result = mq_send(sendTo,
|
||||||
reinterpret_cast<const char*>(message->getBuffer()), message->messageSize,0);
|
reinterpret_cast<const char*>(message->getBuffer()),
|
||||||
|
message->getMessageSize(),0);
|
||||||
|
|
||||||
//TODO: Check if we're in ISR.
|
//TODO: Check if we're in ISR.
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
@ -303,13 +331,16 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
|||||||
//MQ_NONBLOCK flag was set in its attributes, and the
|
//MQ_NONBLOCK flag was set in its attributes, and the
|
||||||
//specified queue is full.
|
//specified queue is full.
|
||||||
return MessageQueueIF::FULL;
|
return MessageQueueIF::FULL;
|
||||||
case EBADF:
|
case EBADF: {
|
||||||
//mq_des doesn't represent a valid message queue descriptor,
|
//mq_des doesn't represent a valid message queue descriptor,
|
||||||
//or mq_des wasn't opened for writing.
|
//or mq_des wasn't opened for writing.
|
||||||
sif::error << "MessageQueue::sendMessage: Configuration error "
|
sif::error << "MessageQueue::sendMessage: Configuration error, MQ"
|
||||||
<< strerror(errno) << " in mq_send mqSendTo: " << sendTo
|
<< " destination invalid." << std::endl;
|
||||||
<< " sent from " << sentFrom << std::endl;
|
sif::error << strerror(errno) << " in "
|
||||||
/*NO BREAK*/
|
<<"mq_send to: " << sendTo << " sent from "
|
||||||
|
<< sentFrom << std::endl;
|
||||||
|
return DESTINVATION_INVALID;
|
||||||
|
}
|
||||||
case EINTR:
|
case EINTR:
|
||||||
//The call was interrupted by a signal.
|
//The call was interrupted by a signal.
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef MESSAGEQUEUE_H_
|
#ifndef FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
|
||||||
#define MESSAGEQUEUE_H_
|
#define FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
|
||||||
|
|
||||||
#include "../../internalError/InternalErrorReporterIF.h"
|
#include "../../internalError/InternalErrorReporterIF.h"
|
||||||
#include "../../ipc/MessageQueueIF.h"
|
#include "../../ipc/MessageQueueIF.h"
|
||||||
@ -56,14 +56,14 @@ public:
|
|||||||
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo,
|
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, bool ignoreFault = false );
|
MessageQueueMessageIF* message, bool ignoreFault = false );
|
||||||
/**
|
/**
|
||||||
* @brief This operation sends a message to the default destination.
|
* @brief This operation sends a message to the default destination.
|
||||||
* @details As in the sendMessage method, this function uses the sendToDefault call of the
|
* @details As in the sendMessage method, this function uses the sendToDefault call of the
|
||||||
* MessageQueueSender parent class and adds its queue id as "sentFrom" information.
|
* MessageQueueSender parent class and adds its queue id as "sentFrom" information.
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
* @param message A pointer to a previously created message, which is sent.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t sendToDefault( MessageQueueMessage* message );
|
virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message );
|
||||||
/**
|
/**
|
||||||
* @brief This operation sends a message to the last communication partner.
|
* @brief This operation sends a message to the last communication partner.
|
||||||
* @details This operation simplifies answering an incoming message by using the stored
|
* @details This operation simplifies answering an incoming message by using the stored
|
||||||
@ -71,7 +71,7 @@ public:
|
|||||||
* (i.e. lastPartner is zero), an error code is returned.
|
* (i.e. lastPartner is zero), an error code is returned.
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
* @param message A pointer to a previously created message, which is sent.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t reply( MessageQueueMessage* message );
|
ReturnValue_t reply( MessageQueueMessageIF* message );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function reads available messages from the message queue and returns the sender.
|
* @brief This function reads available messages from the message queue and returns the sender.
|
||||||
@ -80,7 +80,7 @@ public:
|
|||||||
* @param message A pointer to a message in which the received data is stored.
|
* @param message A pointer to a message in which the received data is stored.
|
||||||
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
|
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessage* message,
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t *receivedFrom);
|
MessageQueueId_t *receivedFrom);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,7 +91,7 @@ public:
|
|||||||
* message's content is cleared and the function returns immediately.
|
* message's content is cleared and the function returns immediately.
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
* @param message A pointer to a message in which the received data is stored.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessage* message);
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message);
|
||||||
/**
|
/**
|
||||||
* Deletes all pending messages in the queue.
|
* Deletes all pending messages in the queue.
|
||||||
* @param count The number of flushed messages.
|
* @param count The number of flushed messages.
|
||||||
@ -114,7 +114,9 @@ public:
|
|||||||
* This variable is set to zero by default.
|
* This variable is set to zero by default.
|
||||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false );
|
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo,
|
||||||
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||||
|
bool ignoreFault = false );
|
||||||
/**
|
/**
|
||||||
* \brief The sendToDefault method sends a queue message to the default destination.
|
* \brief The sendToDefault method sends a queue message to the default destination.
|
||||||
* \details In all other aspects, it works identical to the sendMessage method.
|
* \details In all other aspects, it works identical to the sendMessage method.
|
||||||
@ -122,7 +124,8 @@ public:
|
|||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
||||||
* This variable is set to zero by default.
|
* This variable is set to zero by default.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
|
||||||
|
MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||||
/**
|
/**
|
||||||
* \brief This method is a simple setter for the default destination.
|
* \brief This method is a simple setter for the default destination.
|
||||||
*/
|
*/
|
||||||
@ -145,7 +148,9 @@ protected:
|
|||||||
* This variable is set to zero by default.
|
* This variable is set to zero by default.
|
||||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
||||||
*/
|
*/
|
||||||
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,bool ignoreFault=false);
|
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||||
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE,
|
||||||
|
bool ignoreFault=false);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief The class stores the queue id it got assigned from the operating system in this attribute.
|
* @brief The class stores the queue id it got assigned from the operating system in this attribute.
|
||||||
@ -171,11 +176,12 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The name of the message queue, stored for unlinking
|
* The name of the message queue, stored for unlinking
|
||||||
*/
|
*/
|
||||||
char name[5];
|
char name[16];
|
||||||
|
|
||||||
static uint16_t queueCounter;
|
static uint16_t queueCounter;
|
||||||
|
const size_t maxMessageSize;
|
||||||
|
|
||||||
ReturnValue_t handleError(mq_attr* attributes, uint32_t messageDepth);
|
ReturnValue_t handleError(mq_attr* attributes, uint32_t messageDepth);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MESSAGEQUEUE_H_ */
|
#endif /* FSFW_OSAL_LINUX_MESSAGEQUEUE_H_ */
|
||||||
|
@ -15,7 +15,7 @@ QueueFactory* QueueFactory::factoryInstance = nullptr;
|
|||||||
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, MessageQueueId_t sentFrom,
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||||
bool ignoreFault) {
|
bool ignoreFault) {
|
||||||
return MessageQueue::sendMessageFromMessageQueue(sendTo,message,
|
return MessageQueue::sendMessageFromMessageQueue(sendTo,message,
|
||||||
sentFrom,ignoreFault);
|
sentFrom,ignoreFault);
|
||||||
|
@ -33,7 +33,7 @@ ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) {
|
|||||||
while(1) {
|
while(1) {
|
||||||
//! Sender Address is cached here.
|
//! Sender Address is cached here.
|
||||||
struct sockaddr_in senderAddress;
|
struct sockaddr_in senderAddress;
|
||||||
socklen_t senderSockLen = 0;
|
socklen_t senderSockLen = sizeof(senderAddress);
|
||||||
ssize_t bytesReceived = recvfrom(serverUdpSocket,
|
ssize_t bytesReceived = recvfrom(serverUdpSocket,
|
||||||
receptionBuffer.data(), frameSize, receptionFlags,
|
receptionBuffer.data(), frameSize, receptionFlags,
|
||||||
reinterpret_cast<sockaddr*>(&senderAddress), &senderSockLen);
|
reinterpret_cast<sockaddr*>(&senderAddress), &senderSockLen);
|
||||||
|
@ -65,9 +65,13 @@ TmTcUnixUdpBridge::~TmTcUnixUdpBridge() {
|
|||||||
ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
|
MutexHelper lock(mutex, MutexIF::TimeoutType::WAITING, 10);
|
||||||
|
|
||||||
|
if(ipAddrAnySet){
|
||||||
clientAddress.sin_addr.s_addr = htons(INADDR_ANY);
|
clientAddress.sin_addr.s_addr = htons(INADDR_ANY);
|
||||||
//clientAddress.sin_addr.s_addr = inet_addr("127.73.73.1");
|
//clientAddress.sin_addr.s_addr = inet_addr("127.73.73.1");
|
||||||
clientAddressLen = sizeof(serverAddress);
|
clientAddressLen = sizeof(serverAddress);
|
||||||
|
}
|
||||||
|
|
||||||
// char ipAddress [15];
|
// char ipAddress [15];
|
||||||
// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET,
|
// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET,
|
||||||
@ -85,7 +89,7 @@ ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) {
|
void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) {
|
||||||
MutexHelper lock(mutex, MutexIF::TimeoutType::WAITING, 10);
|
MutexHelper lock(mutex, MutexIF::TimeoutType::WAITING, 10);
|
||||||
|
|
||||||
// char ipAddress [15];
|
// char ipAddress [15];
|
||||||
@ -168,3 +172,7 @@ void TmTcUnixUdpBridge::handleSendError() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TmTcUnixUdpBridge::setClientAddressToAny(bool ipAddrAnySet){
|
||||||
|
this->ipAddrAnySet = ipAddrAnySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -20,8 +20,9 @@ public:
|
|||||||
uint16_t serverPort = 0xFFFF,uint16_t clientPort = 0xFFFF);
|
uint16_t serverPort = 0xFFFF,uint16_t clientPort = 0xFFFF);
|
||||||
virtual~ TmTcUnixUdpBridge();
|
virtual~ TmTcUnixUdpBridge();
|
||||||
|
|
||||||
void checkAndSetClientAddress(sockaddr_in clientAddress);
|
void checkAndSetClientAddress(sockaddr_in& clientAddress);
|
||||||
|
|
||||||
|
void setClientAddressToAny(bool ipAddrAnySet);
|
||||||
protected:
|
protected:
|
||||||
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
|
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
|
||||||
|
|
||||||
@ -36,6 +37,8 @@ private:
|
|||||||
struct sockaddr_in serverAddress;
|
struct sockaddr_in serverAddress;
|
||||||
socklen_t serverAddressLen = 0;
|
socklen_t serverAddressLen = 0;
|
||||||
|
|
||||||
|
bool ipAddrAnySet = false;
|
||||||
|
|
||||||
//! Access to the client address is mutex protected as it is set
|
//! Access to the client address is mutex protected as it is set
|
||||||
//! by another task.
|
//! by another task.
|
||||||
MutexIF* mutex;
|
MutexIF* mutex;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <rtems/score/todimpl.h>
|
#include <rtems/score/todimpl.h>
|
||||||
|
|
||||||
uint16_t Clock::leapSeconds = 0;
|
uint16_t Clock::leapSeconds = 0;
|
||||||
MutexIF* Clock::timeMutex = NULL;
|
MutexIF* Clock::timeMutex = nullptr;
|
||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void){
|
uint32_t Clock::getTicksPerSecond(void){
|
||||||
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
||||||
@ -40,7 +40,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
|
|||||||
//SHOULDDO: Not sure if we need to protect this call somehow (by thread lock or something).
|
//SHOULDDO: Not sure if we need to protect this call somehow (by thread lock or something).
|
||||||
//Uli: rtems docu says you can call this from an ISR, not sure if this means no protetion needed
|
//Uli: rtems docu says you can call this from an ISR, not sure if this means no protetion needed
|
||||||
//TODO Second parameter is ISR_lock_Context
|
//TODO Second parameter is ISR_lock_Context
|
||||||
_TOD_Set(&newTime,NULL);
|
_TOD_Set(&newTime,nullptr);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
|||||||
|
|
||||||
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
|
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
|
||||||
//SHOULDDO: works not for dates in the past (might have less leap seconds)
|
//SHOULDDO: works not for dates in the past (might have less leap seconds)
|
||||||
if (timeMutex == NULL) {
|
if (timeMutex == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,40 +157,34 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
|
|||||||
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
|
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT);
|
MutexHelper helper(timeMutex);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
leapSeconds = leapSeconds_;
|
leapSeconds = leapSeconds_;
|
||||||
|
|
||||||
result = timeMutex->unlockMutex();
|
|
||||||
return result;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
||||||
if(timeMutex==NULL){
|
if(timeMutex==nullptr){
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT);
|
MutexHelper helper(timeMutex);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
*leapSeconds_ = leapSeconds;
|
*leapSeconds_ = leapSeconds;
|
||||||
|
|
||||||
result = timeMutex->unlockMutex();
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::checkOrCreateClockMutex(){
|
ReturnValue_t Clock::checkOrCreateClockMutex(){
|
||||||
if(timeMutex==NULL){
|
if(timeMutex==nullptr){
|
||||||
MutexFactory* mutexFactory = MutexFactory::instance();
|
MutexFactory* mutexFactory = MutexFactory::instance();
|
||||||
if (mutexFactory == NULL) {
|
if (mutexFactory == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
timeMutex = mutexFactory->createMutex();
|
timeMutex = mutexFactory->createMutex();
|
||||||
if (timeMutex == NULL) {
|
if (timeMutex == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ uint32_t CpuUsage::ThreadData::getSerializedSize() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer,
|
ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer,
|
||||||
int32_t* size, Endianness streamEndianness) {
|
size_t* size, Endianness streamEndianness) {
|
||||||
ReturnValue_t result = SerializeAdapter::deSerialize(&id, buffer,
|
ReturnValue_t result = SerializeAdapter::deSerialize(&id, buffer,
|
||||||
size, streamEndianness);
|
size, streamEndianness);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
@ -12,8 +12,8 @@ ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
|
|||||||
// return INVALID_WORKSPACE_ADDRESS;
|
// return INVALID_WORKSPACE_ADDRESS;
|
||||||
case INTERNAL_ERROR_TOO_LITTLE_WORKSPACE:
|
case INTERNAL_ERROR_TOO_LITTLE_WORKSPACE:
|
||||||
return TOO_LITTLE_WORKSPACE;
|
return TOO_LITTLE_WORKSPACE;
|
||||||
case INTERNAL_ERROR_WORKSPACE_ALLOCATION:
|
// case INTERNAL_ERROR_WORKSPACE_ALLOCATION:
|
||||||
return WORKSPACE_ALLOCATION;
|
// return WORKSPACE_ALLOCATION;
|
||||||
// case INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL:
|
// case INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL:
|
||||||
// return INTERRUPT_STACK_TOO_SMALL;
|
// return INTERRUPT_STACK_TOO_SMALL;
|
||||||
case INTERNAL_ERROR_THREAD_EXITTED:
|
case INTERNAL_ERROR_THREAD_EXITTED:
|
||||||
|
@ -1,86 +0,0 @@
|
|||||||
#include "Interrupt.h"
|
|
||||||
extern "C" {
|
|
||||||
#include <bsp_flp/hw_timer/hw_timer.h>
|
|
||||||
#include <bsp_flp/hw_uart/hw_uart.h>
|
|
||||||
}
|
|
||||||
#include "RtemsBasic.h"
|
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t Interrupt::enableInterrupt(InterruptNumber_t interruptNumber) {
|
|
||||||
volatile uint32_t* irqMask = hw_irq_mask;
|
|
||||||
uint32_t expectedValue = *irqMask | (1 << interruptNumber);
|
|
||||||
*irqMask = expectedValue;
|
|
||||||
uint32_t tempValue = *irqMask;
|
|
||||||
if (tempValue == expectedValue) {
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
} else {
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t Interrupt::setInterruptServiceRoutine(IsrHandler_t handler,
|
|
||||||
InterruptNumber_t interrupt, IsrHandler_t* oldHandler) {
|
|
||||||
IsrHandler_t oldHandler_local;
|
|
||||||
if (oldHandler == NULL) {
|
|
||||||
oldHandler = &oldHandler_local;
|
|
||||||
}
|
|
||||||
//+ 0x10 comes because of trap type assignment to IRQs in UT699 processor
|
|
||||||
rtems_status_code status = rtems_interrupt_catch(handler, interrupt + 0x10,
|
|
||||||
oldHandler);
|
|
||||||
switch(status){
|
|
||||||
case RTEMS_SUCCESSFUL:
|
|
||||||
//ISR established successfully
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
case RTEMS_INVALID_NUMBER:
|
|
||||||
//illegal vector number
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
case RTEMS_INVALID_ADDRESS:
|
|
||||||
//illegal ISR entry point or invalid old_isr_handler
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
default:
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t Interrupt::disableInterrupt(InterruptNumber_t interruptNumber) {
|
|
||||||
//TODO Not implemented
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
//SHOULDDO: Make default values (edge, polarity) settable?
|
|
||||||
ReturnValue_t Interrupt::enableGpioInterrupt(InterruptNumber_t interrupt) {
|
|
||||||
volatile uint32_t* irqMask = hw_irq_mask;
|
|
||||||
uint32_t expectedValue = *irqMask | (1 << interrupt);
|
|
||||||
*irqMask = expectedValue;
|
|
||||||
uint32_t tempValue = *irqMask;
|
|
||||||
if (tempValue == expectedValue) {
|
|
||||||
volatile hw_gpio_port_t* ioPorts = hw_gpio_port;
|
|
||||||
ioPorts->direction &= ~(1 << interrupt); //Direction In
|
|
||||||
ioPorts->interrupt_edge |= 1 << interrupt; //Edge triggered
|
|
||||||
ioPorts->interrupt_polarity |= 1 << interrupt; //Trigger on rising edge
|
|
||||||
ioPorts->interrupt_mask |= 1 << interrupt; //Enable
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
} else {
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t Interrupt::disableGpioInterrupt(InterruptNumber_t interrupt) {
|
|
||||||
volatile uint32_t* irqMask = hw_irq_mask;
|
|
||||||
uint32_t expectedValue = *irqMask & ~(1 << interrupt);
|
|
||||||
*irqMask = expectedValue;
|
|
||||||
uint32_t tempValue = *irqMask;
|
|
||||||
if (tempValue == expectedValue) {
|
|
||||||
//Disable gpio IRQ
|
|
||||||
volatile hw_gpio_port_t* ioPorts = hw_gpio_port;
|
|
||||||
ioPorts->interrupt_mask &= ~(1 << interrupt);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
} else {
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Interrupt::isInterruptInProgress() {
|
|
||||||
return rtems_interrupt_is_in_progress();
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
#ifndef OS_RTEMS_INTERRUPT_H_
|
|
||||||
#define OS_RTEMS_INTERRUPT_H_
|
|
||||||
|
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
|
||||||
#include <cstring>
|
|
||||||
#include <rtems.h>
|
|
||||||
|
|
||||||
typedef rtems_isr_entry IsrHandler_t;
|
|
||||||
typedef rtems_isr IsrReturn_t;
|
|
||||||
typedef rtems_vector_number InterruptNumber_t;
|
|
||||||
|
|
||||||
class Interrupt {
|
|
||||||
public:
|
|
||||||
virtual ~Interrupt(){};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Establishes a new interrupt service routine.
|
|
||||||
* @param handler The service routine to establish
|
|
||||||
* @param interrupt The interrupt (NOT trap type) the routine shall react to.
|
|
||||||
* @return RETURN_OK on success. Otherwise, the OS failure code is returned.
|
|
||||||
*/
|
|
||||||
static ReturnValue_t setInterruptServiceRoutine(IsrHandler_t handler,
|
|
||||||
InterruptNumber_t interrupt, IsrHandler_t *oldHandler = NULL);
|
|
||||||
static ReturnValue_t enableInterrupt(InterruptNumber_t interruptNumber);
|
|
||||||
static ReturnValue_t disableInterrupt(InterruptNumber_t interruptNumber);
|
|
||||||
/**
|
|
||||||
* Enables the interrupt given.
|
|
||||||
* The function tests, if the InterruptMask register was written successfully.
|
|
||||||
* @param interrupt The interrupt to enable.
|
|
||||||
* @return RETURN_OK if the interrupt was set successfully. RETURN_FAILED else.
|
|
||||||
*/
|
|
||||||
static ReturnValue_t enableGpioInterrupt(InterruptNumber_t interrupt);
|
|
||||||
/**
|
|
||||||
* Disables the interrupt given.
|
|
||||||
* @param interrupt The interrupt to disable.
|
|
||||||
* @return RETURN_OK if the interrupt was set successfully. RETURN_FAILED else.
|
|
||||||
*/
|
|
||||||
static ReturnValue_t disableGpioInterrupt(InterruptNumber_t interrupt);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the current executing context is an ISR.
|
|
||||||
* @return true if handling an interrupt, false else.
|
|
||||||
*/
|
|
||||||
static bool isInterruptInProgress();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* OS_RTEMS_INTERRUPT_H_ */
|
|
@ -1,14 +1,15 @@
|
|||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||||
|
#include "../../objectmanager/ObjectManagerIF.h"
|
||||||
#include "MessageQueue.h"
|
#include "MessageQueue.h"
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) :
|
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) :
|
||||||
id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(NULL) {
|
id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(nullptr) {
|
||||||
rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
|
rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
|
||||||
rtems_status_code status = rtems_message_queue_create(name, message_depth,
|
rtems_status_code status = rtems_message_queue_create(name, message_depth,
|
||||||
max_message_size, 0, &(this->id));
|
max_message_size, 0, &(this->id));
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
error << "MessageQueue::MessageQueue: Creating Queue " << std::hex
|
sif::error << "MessageQueue::MessageQueue: Creating Queue " << std::hex
|
||||||
<< name << std::dec << " failed with status:"
|
<< name << std::dec << " failed with status:"
|
||||||
<< (uint32_t) status << std::endl;
|
<< (uint32_t) status << std::endl;
|
||||||
this->id = 0;
|
this->id = 0;
|
||||||
@ -20,15 +21,15 @@ MessageQueue::~MessageQueue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, bool ignoreFault) {
|
MessageQueueMessageIF* message, bool ignoreFault) {
|
||||||
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
|
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) {
|
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
|
||||||
return sendToDefaultFrom(message, this->getId());
|
return sendToDefaultFrom(message, this->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
|
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
|
||||||
if (this->lastPartner != 0) {
|
if (this->lastPartner != 0) {
|
||||||
return sendMessage(this->lastPartner, message, this->getId());
|
return sendMessage(this->lastPartner, message, this->getId());
|
||||||
} else {
|
} else {
|
||||||
@ -36,27 +37,29 @@ ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message,
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t* receivedFrom) {
|
MessageQueueId_t* receivedFrom) {
|
||||||
ReturnValue_t status = this->receiveMessage(message);
|
ReturnValue_t status = this->receiveMessage(message);
|
||||||
*receivedFrom = this->lastPartner;
|
*receivedFrom = this->lastPartner;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||||
|
size_t size = 0;
|
||||||
rtems_status_code status = rtems_message_queue_receive(id,
|
rtems_status_code status = rtems_message_queue_receive(id,
|
||||||
message->getBuffer(), &(message->messageSize),
|
message->getBuffer(),&size,
|
||||||
RTEMS_NO_WAIT, 1);
|
RTEMS_NO_WAIT, 1);
|
||||||
if (status == RTEMS_SUCCESSFUL) {
|
if (status == RTEMS_SUCCESSFUL) {
|
||||||
|
message->setMessageSize(size);
|
||||||
this->lastPartner = message->getSender();
|
this->lastPartner = message->getSender();
|
||||||
//Check size of incoming message.
|
//Check size of incoming message.
|
||||||
if (message->messageSize < message->getMinimumMessageSize()) {
|
if (message->getMessageSize() < message->getMinimumMessageSize()) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//No message was received. Keep lastPartner anyway, I might send something later.
|
//No message was received. Keep lastPartner anyway, I might send something later.
|
||||||
//But still, delete packet content.
|
//But still, delete packet content.
|
||||||
memset(message->getData(), 0, message->MAX_DATA_SIZE);
|
memset(message->getData(), 0, message->getMaximumMessageSize());
|
||||||
}
|
}
|
||||||
return convertReturnCode(status);
|
return convertReturnCode(status);
|
||||||
}
|
}
|
||||||
@ -79,20 +82,20 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, MessageQueueId_t sentFrom,
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||||
bool ignoreFault) {
|
bool ignoreFault) {
|
||||||
|
|
||||||
message->setSender(sentFrom);
|
message->setSender(sentFrom);
|
||||||
rtems_status_code result = rtems_message_queue_send(sendTo,
|
rtems_status_code result = rtems_message_queue_send(sendTo,
|
||||||
message->getBuffer(), message->messageSize);
|
message->getBuffer(), message->getMessageSize());
|
||||||
|
|
||||||
//TODO: Check if we're in ISR.
|
//TODO: Check if we're in ISR.
|
||||||
if (result != RTEMS_SUCCESSFUL && !ignoreFault) {
|
if (result != RTEMS_SUCCESSFUL && !ignoreFault) {
|
||||||
if (internalErrorReporter == NULL) {
|
if (internalErrorReporter == nullptr) {
|
||||||
internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
|
internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
|
||||||
objects::INTERNAL_ERROR_REPORTER);
|
objects::INTERNAL_ERROR_REPORTER);
|
||||||
}
|
}
|
||||||
if (internalErrorReporter != NULL) {
|
if (internalErrorReporter != nullptr) {
|
||||||
internalErrorReporter->queueMessageNotSent();
|
internalErrorReporter->queueMessageNotSent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +108,7 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
|
|||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
|
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||||
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,5 @@
|
|||||||
/**
|
#ifndef FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
|
||||||
* @file MessageQueue.h
|
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
|
||||||
*
|
|
||||||
* @date 10/02/2012
|
|
||||||
* @author Bastian Baetz
|
|
||||||
*
|
|
||||||
* @brief This file contains the definition of the MessageQueue class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MESSAGEQUEUE_H_
|
|
||||||
#define MESSAGEQUEUE_H_
|
|
||||||
|
|
||||||
#include "../../internalError/InternalErrorReporterIF.h"
|
#include "../../internalError/InternalErrorReporterIF.h"
|
||||||
#include "../../ipc/MessageQueueIF.h"
|
#include "../../ipc/MessageQueueIF.h"
|
||||||
@ -60,14 +51,14 @@ public:
|
|||||||
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t sendMessage(MessageQueueId_t sendTo,
|
ReturnValue_t sendMessage(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, bool ignoreFault = false );
|
MessageQueueMessageIF* message, bool ignoreFault = false );
|
||||||
/**
|
/**
|
||||||
* @brief This operation sends a message to the default destination.
|
* @brief This operation sends a message to the default destination.
|
||||||
* @details As in the sendMessage method, this function uses the sendToDefault call of the
|
* @details As in the sendMessage method, this function uses the sendToDefault call of the
|
||||||
* MessageQueueSender parent class and adds its queue id as "sentFrom" information.
|
* MessageQueueSender parent class and adds its queue id as "sentFrom" information.
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
* @param message A pointer to a previously created message, which is sent.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t sendToDefault( MessageQueueMessage* message );
|
ReturnValue_t sendToDefault( MessageQueueMessageIF* message );
|
||||||
/**
|
/**
|
||||||
* @brief This operation sends a message to the last communication partner.
|
* @brief This operation sends a message to the last communication partner.
|
||||||
* @details This operation simplifies answering an incoming message by using the stored
|
* @details This operation simplifies answering an incoming message by using the stored
|
||||||
@ -75,7 +66,7 @@ public:
|
|||||||
* (i.e. lastPartner is zero), an error code is returned.
|
* (i.e. lastPartner is zero), an error code is returned.
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
* @param message A pointer to a previously created message, which is sent.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t reply( MessageQueueMessage* message );
|
ReturnValue_t reply( MessageQueueMessageIF* message );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function reads available messages from the message queue and returns the sender.
|
* @brief This function reads available messages from the message queue and returns the sender.
|
||||||
@ -84,7 +75,7 @@ public:
|
|||||||
* @param message A pointer to a message in which the received data is stored.
|
* @param message A pointer to a message in which the received data is stored.
|
||||||
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
|
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessage* message,
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t *receivedFrom);
|
MessageQueueId_t *receivedFrom);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,7 +86,7 @@ public:
|
|||||||
* message's content is cleared and the function returns immediately.
|
* message's content is cleared and the function returns immediately.
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
* @param message A pointer to a message in which the received data is stored.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessage* message);
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message);
|
||||||
/**
|
/**
|
||||||
* Deletes all pending messages in the queue.
|
* Deletes all pending messages in the queue.
|
||||||
* @param count The number of flushed messages.
|
* @param count The number of flushed messages.
|
||||||
@ -121,7 +112,7 @@ public:
|
|||||||
* This variable is set to zero by default.
|
* This variable is set to zero by default.
|
||||||
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||||
/**
|
/**
|
||||||
* \brief The sendToDefault method sends a queue message to the default destination.
|
* \brief The sendToDefault method sends a queue message to the default destination.
|
||||||
* \details In all other aspects, it works identical to the sendMessage method.
|
* \details In all other aspects, it works identical to the sendMessage method.
|
||||||
@ -129,7 +120,7 @@ public:
|
|||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
|
||||||
* This variable is set to zero by default.
|
* This variable is set to zero by default.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
|
||||||
/**
|
/**
|
||||||
* \brief This method is a simple setter for the default destination.
|
* \brief This method is a simple setter for the default destination.
|
||||||
*/
|
*/
|
||||||
@ -178,4 +169,4 @@ private:
|
|||||||
static ReturnValue_t convertReturnCode(rtems_status_code inValue);
|
static ReturnValue_t convertReturnCode(rtems_status_code inValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MESSAGEQUEUE_H_ */
|
#endif /* FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_ */
|
||||||
|
@ -30,7 +30,7 @@ ReturnValue_t MultiObjectTask::startTask() {
|
|||||||
rtems_status_code status = rtems_task_start(id, MultiObjectTask::taskEntryPoint,
|
rtems_status_code status = rtems_task_start(id, MultiObjectTask::taskEntryPoint,
|
||||||
rtems_task_argument((void *) this));
|
rtems_task_argument((void *) this));
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
error << "ObjectTask::startTask for " << std::hex << this->getId()
|
sif::error << "ObjectTask::startTask for " << std::hex << this->getId()
|
||||||
<< std::dec << " failed." << std::endl;
|
<< std::dec << " failed." << std::endl;
|
||||||
}
|
}
|
||||||
switch(status){
|
switch(status){
|
||||||
@ -63,8 +63,8 @@ void MultiObjectTask::taskFunctionality() {
|
|||||||
char nameSpace[8] = { 0 };
|
char nameSpace[8] = { 0 };
|
||||||
char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace),
|
char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace),
|
||||||
nameSpace);
|
nameSpace);
|
||||||
error << "ObjectTask: " << ptr << " Deadline missed." << std::endl;
|
sif::error << "ObjectTask: " << ptr << " Deadline missed." << std::endl;
|
||||||
if (this->deadlineMissedFunc != NULL) {
|
if (this->deadlineMissedFunc != nullptr) {
|
||||||
this->deadlineMissedFunc();
|
this->deadlineMissedFunc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ void MultiObjectTask::taskFunctionality() {
|
|||||||
ReturnValue_t MultiObjectTask::addComponent(object_id_t object) {
|
ReturnValue_t MultiObjectTask::addComponent(object_id_t object) {
|
||||||
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(
|
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(
|
||||||
object);
|
object);
|
||||||
if (newObject == NULL) {
|
if (newObject == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
objectList.push_back(newObject);
|
objectList.push_back(newObject);
|
||||||
|
@ -80,7 +80,7 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* @brief The pointer to the deadline-missed function.
|
* @brief The pointer to the deadline-missed function.
|
||||||
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
||||||
* So, each may react individually on a timing failure. The pointer may be NULL,
|
* So, each may react individually on a timing failure. The pointer may be nullptr,
|
||||||
* then nothing happens on missing the deadline. The deadline is equal to the next execution
|
* then nothing happens on missing the deadline. The deadline is equal to the next execution
|
||||||
* of the periodic task.
|
* of the periodic task.
|
||||||
*/
|
*/
|
||||||
|
@ -10,7 +10,7 @@ Mutex::Mutex() :
|
|||||||
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
|
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
|
||||||
&mutexId);
|
&mutexId);
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
error << "Mutex: creation with name, id " << mutexName << ", " << mutexId
|
sif::error << "Mutex: creation with name, id " << mutexName << ", " << mutexId
|
||||||
<< " failed with " << status << std::endl;
|
<< " failed with " << status << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -18,24 +18,25 @@ Mutex::Mutex() :
|
|||||||
Mutex::~Mutex() {
|
Mutex::~Mutex() {
|
||||||
rtems_status_code status = rtems_semaphore_delete(mutexId);
|
rtems_status_code status = rtems_semaphore_delete(mutexId);
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
error << "Mutex: deletion for id " << mutexId
|
sif::error << "Mutex: deletion for id " << mutexId
|
||||||
<< " failed with " << status << std::endl;
|
<< " failed with " << status << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType =
|
ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType =
|
||||||
TimeoutType::BLOCKING, uint32_t timeoutMs) {
|
TimeoutType::BLOCKING, uint32_t timeoutMs) {
|
||||||
|
rtems_status_code status = RTEMS_INVALID_ID;
|
||||||
if(timeoutMs == MutexIF::TimeoutType::BLOCKING) {
|
if(timeoutMs == MutexIF::TimeoutType::BLOCKING) {
|
||||||
rtems_status_code status = rtems_semaphore_obtain(mutexId,
|
status = rtems_semaphore_obtain(mutexId,
|
||||||
RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||||
}
|
}
|
||||||
else if(timeoutMs == MutexIF::TimeoutType::POLLING) {
|
else if(timeoutMs == MutexIF::TimeoutType::POLLING) {
|
||||||
timeoutMs = RTEMS_NO_TIMEOUT;
|
timeoutMs = RTEMS_NO_TIMEOUT;
|
||||||
rtems_status_code status = rtems_semaphore_obtain(mutexId,
|
status = rtems_semaphore_obtain(mutexId,
|
||||||
RTEMS_NO_WAIT, 0);
|
RTEMS_NO_WAIT, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rtems_status_code status = rtems_semaphore_obtain(mutexId,
|
status = rtems_semaphore_obtain(mutexId,
|
||||||
RTEMS_WAIT, timeoutMs);
|
RTEMS_WAIT, timeoutMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef FRAMEWORK_OSAL_RTEMS_MUTEX_H_
|
#ifndef FSFW_OSAL_RTEMS_MUTEX_H_
|
||||||
#define FRAMEWORK_OSAL_RTEMS_MUTEX_H_
|
#define FSFW_OSAL_RTEMS_MUTEX_H_
|
||||||
|
|
||||||
#include "../../ipc/MutexIF.h"
|
#include "../../ipc/MutexIF.h"
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
@ -15,4 +15,4 @@ private:
|
|||||||
static uint8_t count;
|
static uint8_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* OS_RTEMS_MUTEX_H_ */
|
#endif /* FSFW_OSAL_RTEMS_MUTEX_H_ */
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include "Mutex.h"
|
#include "Mutex.h"
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
|
|
||||||
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
|
||||||
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
||||||
|
|
||||||
MutexFactory::MutexFactory() {
|
MutexFactory::MutexFactory() {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "../../devicehandlers/FixedSequenceSlot.h"
|
#include "../../tasks/FixedSequenceSlot.h"
|
||||||
#include "../../objectmanager/SystemObjectIF.h"
|
#include "../../objectmanager/SystemObjectIF.h"
|
||||||
|
#include "../../objectmanager/ObjectManagerIF.h"
|
||||||
#include "PollingTask.h"
|
#include "PollingTask.h"
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
@ -34,14 +35,14 @@ rtems_task PollingTask::taskEntryPoint(rtems_task_argument argument) {
|
|||||||
PollingTask *originalTask(reinterpret_cast<PollingTask*>(argument));
|
PollingTask *originalTask(reinterpret_cast<PollingTask*>(argument));
|
||||||
//The task's functionality is called.
|
//The task's functionality is called.
|
||||||
originalTask->taskFunctionality();
|
originalTask->taskFunctionality();
|
||||||
debug << "Polling task " << originalTask->getId()
|
sif::debug << "Polling task " << originalTask->getId()
|
||||||
<< " returned from taskFunctionality." << std::endl;
|
<< " returned from taskFunctionality." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PollingTask::missedDeadlineCounter() {
|
void PollingTask::missedDeadlineCounter() {
|
||||||
PollingTask::deadlineMissedCount++;
|
PollingTask::deadlineMissedCount++;
|
||||||
if (PollingTask::deadlineMissedCount % 10 == 0) {
|
if (PollingTask::deadlineMissedCount % 10 == 0) {
|
||||||
error << "PST missed " << PollingTask::deadlineMissedCount
|
sif::error << "PST missed " << PollingTask::deadlineMissedCount
|
||||||
<< " deadlines." << std::endl;
|
<< " deadlines." << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,7 +51,7 @@ ReturnValue_t PollingTask::startTask() {
|
|||||||
rtems_status_code status = rtems_task_start(id, PollingTask::taskEntryPoint,
|
rtems_status_code status = rtems_task_start(id, PollingTask::taskEntryPoint,
|
||||||
rtems_task_argument((void *) this));
|
rtems_task_argument((void *) this));
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
error << "PollingTask::startTask for " << std::hex << this->getId()
|
sif::error << "PollingTask::startTask for " << std::hex << this->getId()
|
||||||
<< std::dec << " failed." << std::endl;
|
<< std::dec << " failed." << std::endl;
|
||||||
}
|
}
|
||||||
switch(status){
|
switch(status){
|
||||||
@ -68,12 +69,13 @@ ReturnValue_t PollingTask::startTask() {
|
|||||||
|
|
||||||
ReturnValue_t PollingTask::addSlot(object_id_t componentId,
|
ReturnValue_t PollingTask::addSlot(object_id_t componentId,
|
||||||
uint32_t slotTimeMs, int8_t executionStep) {
|
uint32_t slotTimeMs, int8_t executionStep) {
|
||||||
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) {
|
ExecutableObjectIF* object = objectManager->get<ExecutableObjectIF>(componentId);
|
||||||
pst.addSlot(componentId, slotTimeMs, executionStep, this);
|
if (object != nullptr) {
|
||||||
|
pst.addSlot(componentId, slotTimeMs, executionStep, object, this);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error << "Component " << std::hex << componentId <<
|
sif::error << "Component " << std::hex << componentId <<
|
||||||
" not found, not adding it to pst" << std::endl;
|
" not found, not adding it to pst" << std::endl;
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
@ -90,11 +92,10 @@ ReturnValue_t PollingTask::checkSequence() const {
|
|||||||
|
|
||||||
void PollingTask::taskFunctionality() {
|
void PollingTask::taskFunctionality() {
|
||||||
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
|
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
|
||||||
std::list<FixedSequenceSlot*>::iterator it = pst.current;
|
FixedSlotSequence::SlotListIter it = pst.current;
|
||||||
|
|
||||||
//The start time for the first entry is read.
|
//The start time for the first entry is read.
|
||||||
rtems_interval interval = RtemsBasic::convertMsToTicks(
|
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
|
||||||
(*it)->pollingTimeMs);
|
|
||||||
TaskBase::setAndStartPeriod(interval,&periodId);
|
TaskBase::setAndStartPeriod(interval,&periodId);
|
||||||
//The task's "infinite" inner loop is entered.
|
//The task's "infinite" inner loop is entered.
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -107,7 +108,7 @@ void PollingTask::taskFunctionality() {
|
|||||||
//If the deadline was missed, the deadlineMissedFunc is called.
|
//If the deadline was missed, the deadlineMissedFunc is called.
|
||||||
rtems_status_code status = TaskBase::restartPeriod(interval,periodId);
|
rtems_status_code status = TaskBase::restartPeriod(interval,periodId);
|
||||||
if (status == RTEMS_TIMEOUT) {
|
if (status == RTEMS_TIMEOUT) {
|
||||||
if (this->deadlineMissedFunc != NULL) {
|
if (this->deadlineMissedFunc != nullptr) {
|
||||||
this->deadlineMissedFunc();
|
this->deadlineMissedFunc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef POLLINGTASK_H_
|
#ifndef FSFW_OSAL_RTEMS_POLLINGTASK_H_
|
||||||
#define POLLINGTASK_H_
|
#define FSFW_OSAL_RTEMS_POLLINGTASK_H_
|
||||||
|
|
||||||
#include "../../devicehandlers/FixedSlotSequence.h"
|
#include "../../tasks/FixedSlotSequence.h"
|
||||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
#include "../../tasks/FixedTimeslotTaskIF.h"
|
||||||
#include "TaskBase.h"
|
#include "TaskBase.h"
|
||||||
|
|
||||||
@ -82,4 +82,4 @@ protected:
|
|||||||
void taskFunctionality( void );
|
void taskFunctionality( void );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* POLLINGTASK_H_ */
|
#endif /* FSFW_OSAL_RTEMS_POLLINGTASK_H_ */
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
#include "../../ipc/QueueFactory.h"
|
#include "../../ipc/QueueFactory.h"
|
||||||
|
#include "../../ipc/MessageQueueSenderIF.h"
|
||||||
#include "MessageQueue.h"
|
#include "MessageQueue.h"
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
|
|
||||||
QueueFactory* QueueFactory::factoryInstance = NULL;
|
QueueFactory* QueueFactory::factoryInstance = nullptr;
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessage* message, MessageQueueId_t sentFrom,bool ignoreFault) {
|
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,bool ignoreFault) {
|
||||||
//TODO add ignoreFault functionality
|
//TODO add ignoreFault functionality
|
||||||
message->setSender(sentFrom);
|
message->setSender(sentFrom);
|
||||||
rtems_status_code result = rtems_message_queue_send(sendTo, message->getBuffer(),
|
rtems_status_code result = rtems_message_queue_send(sendTo, message->getBuffer(),
|
||||||
message->messageSize);
|
message->getMessageSize());
|
||||||
switch(result){
|
switch(result){
|
||||||
case RTEMS_SUCCESSFUL:
|
case RTEMS_SUCCESSFUL:
|
||||||
//message sent successfully
|
//message sent successfully
|
||||||
@ -37,7 +38,7 @@ ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QueueFactory* QueueFactory::instance() {
|
QueueFactory* QueueFactory::instance() {
|
||||||
if (factoryInstance == NULL) {
|
if (factoryInstance == nullptr) {
|
||||||
factoryInstance = new QueueFactory;
|
factoryInstance = new QueueFactory;
|
||||||
}
|
}
|
||||||
return factoryInstance;
|
return factoryInstance;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef OS_RTEMS_RTEMSBASIC_H_
|
#ifndef FSFW_OSAL_RTEMS_RTEMSBASIC_H_
|
||||||
#define OS_RTEMS_RTEMSBASIC_H_
|
#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_
|
||||||
|
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
@ -22,4 +22,4 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* OS_RTEMS_RTEMSBASIC_H_ */
|
#endif /* FSFW_OSAL_RTEMS_RTEMSBASIC_H_ */
|
||||||
|
@ -22,7 +22,7 @@ TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
|
|||||||
}
|
}
|
||||||
ReturnValue_t result = convertReturnCode(status);
|
ReturnValue_t result = convertReturnCode(status);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
error << "TaskBase::TaskBase: createTask with name " << std::hex
|
sif::error << "TaskBase::TaskBase: createTask with name " << std::hex
|
||||||
<< osalName << std::dec << " failed with return code "
|
<< osalName << std::dec << " failed with return code "
|
||||||
<< (uint32_t) status << std::endl;
|
<< (uint32_t) status << std::endl;
|
||||||
this->id = 0;
|
this->id = 0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef TASKBASE_H_
|
#ifndef FSFW_OSAL_RTEMS_TASKBASE_H_
|
||||||
#define TASKBASE_H_
|
#define FSFW_OSAL_RTEMS_TASKBASE_H_
|
||||||
|
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
#include "../../tasks/PeriodicTaskIF.h"
|
#include "../../tasks/PeriodicTaskIF.h"
|
||||||
@ -44,4 +44,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* TASKBASE_H_ */
|
#endif /* FSFW_OSAL_RTEMS_TASKBASE_H_ */
|
||||||
|
148
osal/windows/TcWinUdpPollingTask.cpp
Normal file
148
osal/windows/TcWinUdpPollingTask.cpp
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#include "TcWinUdpPollingTask.h"
|
||||||
|
#include "../../globalfunctions/arrayprinter.h"
|
||||||
|
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
TcWinUdpPollingTask::TcWinUdpPollingTask(object_id_t objectId,
|
||||||
|
object_id_t tmtcUnixUdpBridge, size_t frameSize,
|
||||||
|
double timeoutSeconds): SystemObject(objectId),
|
||||||
|
tmtcBridgeId(tmtcUnixUdpBridge) {
|
||||||
|
if(frameSize > 0) {
|
||||||
|
this->frameSize = frameSize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->frameSize = DEFAULT_MAX_FRAME_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up reception buffer with specified frame size.
|
||||||
|
// For now, it is assumed that only one frame is held in the buffer!
|
||||||
|
receptionBuffer.reserve(this->frameSize);
|
||||||
|
receptionBuffer.resize(this->frameSize);
|
||||||
|
|
||||||
|
if(timeoutSeconds == -1) {
|
||||||
|
receptionTimeout = DEFAULT_TIMEOUT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TcWinUdpPollingTask::~TcWinUdpPollingTask() {}
|
||||||
|
|
||||||
|
ReturnValue_t TcWinUdpPollingTask::performOperation(uint8_t opCode) {
|
||||||
|
// Poll for new UDP datagrams in permanent loop.
|
||||||
|
while(true) {
|
||||||
|
//! Sender Address is cached here.
|
||||||
|
struct sockaddr_in senderAddress;
|
||||||
|
int senderAddressSize = sizeof(senderAddress);
|
||||||
|
ssize_t bytesReceived = recvfrom(serverUdpSocket,
|
||||||
|
reinterpret_cast<char*>(receptionBuffer.data()), frameSize,
|
||||||
|
receptionFlags, reinterpret_cast<sockaddr*>(&senderAddress),
|
||||||
|
&senderAddressSize);
|
||||||
|
if(bytesReceived == SOCKET_ERROR) {
|
||||||
|
// handle error
|
||||||
|
sif::error << "TcWinUdpPollingTask::performOperation: Reception"
|
||||||
|
" error." << std::endl;
|
||||||
|
handleReadError();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//sif::debug << "TcWinUdpPollingTask::performOperation: " << bytesReceived
|
||||||
|
// << " bytes received" << std::endl;
|
||||||
|
|
||||||
|
ReturnValue_t result = handleSuccessfullTcRead(bytesReceived);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_FAILED) {
|
||||||
|
|
||||||
|
}
|
||||||
|
tmtcBridge->registerCommConnect();
|
||||||
|
tmtcBridge->checkAndSetClientAddress(senderAddress);
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t TcWinUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
|
||||||
|
store_address_t storeId;
|
||||||
|
ReturnValue_t result = tcStore->addData(&storeId,
|
||||||
|
receptionBuffer.data(), bytesRead);
|
||||||
|
// arrayprinter::print(receptionBuffer.data(), bytesRead);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
sif::error << "TcSerialPollingTask::transferPusToSoftwareBus: Data "
|
||||||
|
"storage failed" << std::endl;
|
||||||
|
sif::error << "Packet size: " << bytesRead << std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
TmTcMessage message(storeId);
|
||||||
|
|
||||||
|
result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
sif::error << "Serial Polling: Sending message to queue failed"
|
||||||
|
<< std::endl;
|
||||||
|
tcStore->deleteData(storeId);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TcWinUdpPollingTask::initialize() {
|
||||||
|
tcStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
|
||||||
|
if (tcStore == nullptr) {
|
||||||
|
sif::error << "TcSerialPollingTask::initialize: TC Store uninitialized!"
|
||||||
|
<< std::endl;
|
||||||
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmtcBridge = objectManager->get<TmTcWinUdpBridge>(tmtcBridgeId);
|
||||||
|
if(tmtcBridge == nullptr) {
|
||||||
|
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid"
|
||||||
|
" TMTC bridge object!" << std::endl;
|
||||||
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
serverUdpSocket = tmtcBridge->serverSocket;
|
||||||
|
//sif::info << "TcWinUdpPollingTask::initialize: Server UDP socket "
|
||||||
|
// << serverUdpSocket << std::endl;
|
||||||
|
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TcWinUdpPollingTask::initializeAfterTaskCreation() {
|
||||||
|
// Initialize the destination after task creation. This ensures
|
||||||
|
// that the destination has already been set in the TMTC bridge.
|
||||||
|
targetTcDestination = tmtcBridge->getRequestQueue();
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcWinUdpPollingTask::setTimeout(double timeoutSeconds) {
|
||||||
|
DWORD timeoutMs = timeoutSeconds * 1000.0;
|
||||||
|
int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO,
|
||||||
|
reinterpret_cast<const char*>(&timeoutMs), sizeof(DWORD));
|
||||||
|
if(result == -1) {
|
||||||
|
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting "
|
||||||
|
"receive timeout failed with " << strerror(errno) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcWinUdpPollingTask::handleReadError() {
|
||||||
|
int error = WSAGetLastError();
|
||||||
|
switch(error) {
|
||||||
|
case(WSANOTINITIALISED): {
|
||||||
|
sif::info << "TmTcWinUdpBridge::handleReadError: WSANOTINITIALISED: "
|
||||||
|
<< "WSAStartup(...) call " << "necessary" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(WSAEFAULT): {
|
||||||
|
sif::info << "TmTcWinUdpBridge::handleReadError: WSADEFAULT: "
|
||||||
|
<< "Bad address " << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
sif::info << "TmTcWinUdpBridge::handleReadError: Error code: "
|
||||||
|
<< error << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// to prevent spam.
|
||||||
|
Sleep(1000);
|
||||||
|
}
|
67
osal/windows/TcWinUdpPollingTask.h
Normal file
67
osal/windows/TcWinUdpPollingTask.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#ifndef FSFW_OSAL_WINDOWS_TCSOCKETPOLLINGTASK_H_
|
||||||
|
#define FSFW_OSAL_WINDOWS_TCSOCKETPOLLINGTASK_H_
|
||||||
|
|
||||||
|
#include "TmTcWinUdpBridge.h"
|
||||||
|
#include "../../objectmanager/SystemObject.h"
|
||||||
|
#include "../../tasks/ExecutableObjectIF.h"
|
||||||
|
#include "../../storagemanager/StorageManagerIF.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This class can be used to implement the polling of a Unix socket,
|
||||||
|
* using UDP for now.
|
||||||
|
* @details
|
||||||
|
* The task will be blocked while the specified number of bytes has not been
|
||||||
|
* received, so TC reception is handled inside a separate task.
|
||||||
|
* This class caches the IP address of the sender. It is assumed there
|
||||||
|
* is only one sender for now.
|
||||||
|
*/
|
||||||
|
class TcWinUdpPollingTask: public SystemObject,
|
||||||
|
public ExecutableObjectIF {
|
||||||
|
friend class TmTcWinUdpBridge;
|
||||||
|
public:
|
||||||
|
static constexpr size_t DEFAULT_MAX_FRAME_SIZE = 2048;
|
||||||
|
//! 0.5 default milliseconds timeout for now.
|
||||||
|
static constexpr timeval DEFAULT_TIMEOUT = {.tv_sec = 0, .tv_usec = 500};
|
||||||
|
|
||||||
|
TcWinUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge,
|
||||||
|
size_t frameSize = 0, double timeoutSeconds = -1);
|
||||||
|
virtual~ TcWinUdpPollingTask();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn on optional timeout for UDP polling. In the default mode,
|
||||||
|
* the receive function will block until a packet is received.
|
||||||
|
* @param timeoutSeconds
|
||||||
|
*/
|
||||||
|
void setTimeout(double timeoutSeconds);
|
||||||
|
|
||||||
|
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
|
virtual ReturnValue_t initialize() override;
|
||||||
|
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
StorageManagerIF* tcStore = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! TMTC bridge is cached.
|
||||||
|
object_id_t tmtcBridgeId = objects::NO_OBJECT;
|
||||||
|
TmTcWinUdpBridge* tmtcBridge = nullptr;
|
||||||
|
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
|
||||||
|
//! Reception flags: https://linux.die.net/man/2/recvfrom.
|
||||||
|
int receptionFlags = 0;
|
||||||
|
|
||||||
|
//! Server socket, which is member of TMTC bridge and is assigned in
|
||||||
|
//! constructor
|
||||||
|
SOCKET serverUdpSocket = 0;
|
||||||
|
|
||||||
|
std::vector<uint8_t> receptionBuffer;
|
||||||
|
|
||||||
|
size_t frameSize = 0;
|
||||||
|
timeval receptionTimeout;
|
||||||
|
|
||||||
|
ReturnValue_t handleSuccessfullTcRead(size_t bytesRead);
|
||||||
|
void handleReadError();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */
|
176
osal/windows/TmTcWinUdpBridge.cpp
Normal file
176
osal/windows/TmTcWinUdpBridge.cpp
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
#include <fsfw/ipc/MutexHelper.h>
|
||||||
|
#include "TmTcWinUdpBridge.h"
|
||||||
|
|
||||||
|
TmTcWinUdpBridge::TmTcWinUdpBridge(object_id_t objectId,
|
||||||
|
object_id_t tcDestination, object_id_t tmStoreId, object_id_t tcStoreId,
|
||||||
|
uint16_t serverPort, uint16_t clientPort):
|
||||||
|
TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
|
||||||
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
|
|
||||||
|
// Initiates Winsock DLL.
|
||||||
|
WSAData wsaData;
|
||||||
|
WORD wVersionRequested = MAKEWORD(2, 2);
|
||||||
|
int err = WSAStartup(wVersionRequested, &wsaData);
|
||||||
|
if (err != 0) {
|
||||||
|
/* Tell the user that we could not find a usable */
|
||||||
|
/* Winsock DLL. */
|
||||||
|
sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge:"
|
||||||
|
"WSAStartup failed with error: " << err << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t setServerPort = DEFAULT_UDP_SERVER_PORT;
|
||||||
|
if(serverPort != 0xFFFF) {
|
||||||
|
setServerPort = serverPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t setClientPort = DEFAULT_UDP_CLIENT_PORT;
|
||||||
|
if(clientPort != 0xFFFF) {
|
||||||
|
setClientPort = clientPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html
|
||||||
|
//clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if(serverSocket == INVALID_SOCKET) {
|
||||||
|
sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not open"
|
||||||
|
" UDP socket!" << std::endl;
|
||||||
|
handleSocketError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAddress.sin_family = AF_INET;
|
||||||
|
|
||||||
|
// Accept packets from any interface. (potentially insecure).
|
||||||
|
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
serverAddress.sin_port = htons(setServerPort);
|
||||||
|
serverAddressLen = sizeof(serverAddress);
|
||||||
|
setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
reinterpret_cast<const char*>(&serverSocketOptions),
|
||||||
|
sizeof(serverSocketOptions));
|
||||||
|
|
||||||
|
clientAddress.sin_family = AF_INET;
|
||||||
|
clientAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
clientAddress.sin_port = htons(setClientPort);
|
||||||
|
clientAddressLen = sizeof(clientAddress);
|
||||||
|
|
||||||
|
int result = bind(serverSocket,
|
||||||
|
reinterpret_cast<struct sockaddr*>(&serverAddress),
|
||||||
|
serverAddressLen);
|
||||||
|
if(result != 0) {
|
||||||
|
sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not bind "
|
||||||
|
"local port " << setServerPort << " to server socket!"
|
||||||
|
<< std::endl;
|
||||||
|
handleBindError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TmTcWinUdpBridge::~TmTcWinUdpBridge() {
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TmTcWinUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
//clientAddress.sin_addr.s_addr = htons(INADDR_ANY);
|
||||||
|
//clientAddressLen = sizeof(serverAddress);
|
||||||
|
|
||||||
|
// char ipAddress [15];
|
||||||
|
// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET,
|
||||||
|
// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
|
||||||
|
|
||||||
|
ssize_t bytesSent = sendto(serverSocket,
|
||||||
|
reinterpret_cast<const char*>(data), dataLen, flags,
|
||||||
|
reinterpret_cast<sockaddr*>(&clientAddress), clientAddressLen);
|
||||||
|
if(bytesSent == SOCKET_ERROR) {
|
||||||
|
sif::error << "TmTcWinUdpBridge::sendTm: Send operation failed."
|
||||||
|
<< std::endl;
|
||||||
|
handleSendError();
|
||||||
|
}
|
||||||
|
// sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were"
|
||||||
|
// " sent." << std::endl;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TmTcWinUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) {
|
||||||
|
MutexHelper lock(mutex, MutexIF::TimeoutType::WAITING, 10);
|
||||||
|
|
||||||
|
// char ipAddress [15];
|
||||||
|
// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET,
|
||||||
|
// &newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
|
||||||
|
// sif::debug << "IP Address Old: " << inet_ntop(AF_INET,
|
||||||
|
// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
|
||||||
|
|
||||||
|
// Set new IP address if it has changed.
|
||||||
|
if(clientAddress.sin_addr.s_addr != newAddress.sin_addr.s_addr) {
|
||||||
|
clientAddress.sin_addr.s_addr = newAddress.sin_addr.s_addr;
|
||||||
|
clientAddressLen = sizeof(clientAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TmTcWinUdpBridge::handleSocketError() {
|
||||||
|
int errCode = WSAGetLastError();
|
||||||
|
switch(errCode) {
|
||||||
|
case(WSANOTINITIALISED): {
|
||||||
|
sif::info << "TmTcWinUdpBridge::handleSocketError: WSANOTINITIALISED: "
|
||||||
|
<< "WSAStartup(...) call " << "necessary" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
/*
|
||||||
|
https://docs.microsoft.com/en-us/windows/win32/winsock/
|
||||||
|
windows-sockets-error-codes-2
|
||||||
|
*/
|
||||||
|
sif::info << "TmTcWinUdpBridge::handleSocketError: Error code: "
|
||||||
|
<< errCode << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TmTcWinUdpBridge::handleBindError() {
|
||||||
|
int errCode = WSAGetLastError();
|
||||||
|
switch(errCode) {
|
||||||
|
case(WSANOTINITIALISED): {
|
||||||
|
sif::info << "TmTcWinUdpBridge::handleBindError: WSANOTINITIALISED: "
|
||||||
|
<< "WSAStartup(...) call " << "necessary" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
/*
|
||||||
|
https://docs.microsoft.com/en-us/windows/win32/winsock/
|
||||||
|
windows-sockets-error-codes-2
|
||||||
|
*/
|
||||||
|
sif::info << "TmTcWinUdpBridge::handleBindError: Error code: "
|
||||||
|
<< errCode << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TmTcWinUdpBridge::handleSendError() {
|
||||||
|
int errCode = WSAGetLastError();
|
||||||
|
switch(errCode) {
|
||||||
|
case(WSANOTINITIALISED): {
|
||||||
|
sif::info << "TmTcWinUdpBridge::handleSendError: WSANOTINITIALISED: "
|
||||||
|
<< "WSAStartup(...) call " << "necessary" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case(WSAEADDRNOTAVAIL): {
|
||||||
|
sif::info << "TmTcWinUdpBridge::handleReadError: WSAEADDRNOTAVAIL: "
|
||||||
|
<< "Check target address. " << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
/*
|
||||||
|
https://docs.microsoft.com/en-us/windows/win32/winsock/
|
||||||
|
windows-sockets-error-codes-2
|
||||||
|
*/
|
||||||
|
sif::info << "TmTcWinUdpBridge::handleSendError: Error code: "
|
||||||
|
<< errCode << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
49
osal/windows/TmTcWinUdpBridge.h
Normal file
49
osal/windows/TmTcWinUdpBridge.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef FSFW_OSAL_WINDOWS_TMTCWINUDPBRIDGE_H_
|
||||||
|
#define FSFW_OSAL_WINDOWS_TMTCWINUDPBRIDGE_H_
|
||||||
|
|
||||||
|
#include "../../tmtcservices/TmTcBridge.h"
|
||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
class TmTcWinUdpBridge: public TmTcBridge {
|
||||||
|
friend class TcWinUdpPollingTask;
|
||||||
|
public:
|
||||||
|
// The ports chosen here should not be used by any other process.
|
||||||
|
static constexpr uint16_t DEFAULT_UDP_SERVER_PORT = 7301;
|
||||||
|
static constexpr uint16_t DEFAULT_UDP_CLIENT_PORT = 7302;
|
||||||
|
|
||||||
|
TmTcWinUdpBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
|
object_id_t tmStoreId, object_id_t tcStoreId,
|
||||||
|
uint16_t serverPort = 0xFFFF,uint16_t clientPort = 0xFFFF);
|
||||||
|
virtual~ TmTcWinUdpBridge();
|
||||||
|
|
||||||
|
void checkAndSetClientAddress(sockaddr_in clientAddress);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SOCKET serverSocket = 0;
|
||||||
|
|
||||||
|
const int serverSocketOptions = 0;
|
||||||
|
|
||||||
|
struct sockaddr_in clientAddress;
|
||||||
|
int clientAddressLen = 0;
|
||||||
|
|
||||||
|
struct sockaddr_in serverAddress;
|
||||||
|
int serverAddressLen = 0;
|
||||||
|
|
||||||
|
//! Access to the client address is mutex protected as it is set
|
||||||
|
//! by another task.
|
||||||
|
MutexIF* mutex;
|
||||||
|
|
||||||
|
void handleSocketError();
|
||||||
|
void handleBindError();
|
||||||
|
void handleSendError();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSFW_OSAL_HOST_TMTCWINUDPBRIDGE_H_ */
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef FRAMEWORK_RETURNVALUES_HASRETURNVALUESIF_H_
|
#ifndef FSFW_RETURNVALUES_HASRETURNVALUESIF_H_
|
||||||
#define FRAMEWORK_RETURNVALUES_HASRETURNVALUESIF_H_
|
#define FSFW_RETURNVALUES_HASRETURNVALUESIF_H_
|
||||||
|
|
||||||
#include "FwClassIds.h"
|
#include "FwClassIds.h"
|
||||||
#include <config/returnvalues/classIds.h>
|
#include <config/returnvalues/classIds.h>
|
||||||
@ -15,9 +15,17 @@ public:
|
|||||||
static const ReturnValue_t RETURN_FAILED = 1;
|
static const ReturnValue_t RETURN_FAILED = 1;
|
||||||
virtual ~HasReturnvaluesIF() {}
|
virtual ~HasReturnvaluesIF() {}
|
||||||
|
|
||||||
static ReturnValue_t makeReturnCode(uint8_t interfaceId, uint8_t number) {
|
/**
|
||||||
return (interfaceId << 8) + number;
|
* It is discouraged to use the input parameters 0,0 and 0,1 as this
|
||||||
|
* will generate the RETURN_OK and RETURN_FAILED returnvalues.
|
||||||
|
* @param interfaceId
|
||||||
|
* @param number
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static constexpr ReturnValue_t makeReturnCode(uint8_t interfaceId,
|
||||||
|
uint8_t number) {
|
||||||
|
return (static_cast<ReturnValue_t>(interfaceId) << 8) + number;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_RETURNVALUES_HASRETURNVALUESIF_H_ */
|
#endif /* FSFW_RETURNVALUES_HASRETURNVALUESIF_H_ */
|
||||||
|
@ -1,31 +1,39 @@
|
|||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include "CCSDSDistributor.h"
|
#include "CCSDSDistributor.h"
|
||||||
|
|
||||||
|
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||||
#include "../tmtcpacket/SpacePacketBase.h"
|
#include "../tmtcpacket/SpacePacketBase.h"
|
||||||
|
|
||||||
CCSDSDistributor::CCSDSDistributor( uint16_t setDefaultApid, object_id_t setObjectId ) :
|
CCSDSDistributor::CCSDSDistributor(uint16_t setDefaultApid,
|
||||||
TcDistributor( setObjectId ), default_apid( setDefaultApid ), tcStore(NULL) {
|
object_id_t setObjectId):
|
||||||
|
TcDistributor(setObjectId), defaultApid( setDefaultApid ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CCSDSDistributor::~CCSDSDistributor() {
|
CCSDSDistributor::~CCSDSDistributor() {}
|
||||||
|
|
||||||
}
|
TcDistributor::TcMqMapIter CCSDSDistributor::selectDestination() {
|
||||||
|
// sif::debug << "CCSDSDistributor::selectDestination received: " <<
|
||||||
iterator_t CCSDSDistributor::selectDestination() {
|
// this->currentMessage.getStorageId().pool_index << ", " <<
|
||||||
// sif::debug << "CCSDSDistributor::selectDestination received: " << this->currentMessage.getStorageId().pool_index << ", " << this->currentMessage.getStorageId().packet_index << std::endl;
|
// this->currentMessage.getStorageId().packet_index << std::endl;
|
||||||
const uint8_t* p_packet = NULL;
|
const uint8_t* packet = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
//TODO check returncode?
|
ReturnValue_t result = this->tcStore->getData(currentMessage.getStorageId(),
|
||||||
this->tcStore->getData( this->currentMessage.getStorageId(), &p_packet, &size );
|
&packet, &size );
|
||||||
SpacePacketBase current_packet( p_packet );
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
// info << "CCSDSDistributor::selectDestination has packet with APID " << std::hex << current_packet.getAPID() << std::dec << std::endl;
|
sif::error << "CCSDSDistributor::selectDestination: Getting data from"
|
||||||
iterator_t position = this->queueMap.find( current_packet.getAPID() );
|
" store failed!" << std::endl;
|
||||||
|
}
|
||||||
|
SpacePacketBase currentPacket(packet);
|
||||||
|
|
||||||
|
// sif:: info << "CCSDSDistributor::selectDestination has packet with APID "
|
||||||
|
// << std::hex << currentPacket.getAPID() << std::dec << std::endl;
|
||||||
|
TcMqMapIter position = this->queueMap.find(currentPacket.getAPID());
|
||||||
if ( position != this->queueMap.end() ) {
|
if ( position != this->queueMap.end() ) {
|
||||||
return position;
|
return position;
|
||||||
} else {
|
} else {
|
||||||
//The APID was not found. Forward packet to main SW-APID anyway to create acceptance failure report.
|
//The APID was not found. Forward packet to main SW-APID anyway to
|
||||||
return this->queueMap.find( this->default_apid );
|
// create acceptance failure report.
|
||||||
|
return this->queueMap.find( this->defaultApid );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t CCSDSDistributor::getRequestQueue() {
|
MessageQueueId_t CCSDSDistributor::getRequestQueue() {
|
||||||
@ -35,9 +43,9 @@ MessageQueueId_t CCSDSDistributor::getRequestQueue() {
|
|||||||
ReturnValue_t CCSDSDistributor::registerApplication(
|
ReturnValue_t CCSDSDistributor::registerApplication(
|
||||||
AcceptsTelecommandsIF* application) {
|
AcceptsTelecommandsIF* application) {
|
||||||
ReturnValue_t returnValue = RETURN_OK;
|
ReturnValue_t returnValue = RETURN_OK;
|
||||||
bool errorCode = true;
|
auto insertPair = this->queueMap.emplace(application->getIdentifier(),
|
||||||
errorCode = this->queueMap.insert( std::pair<uint32_t, MessageQueueId_t>( application->getIdentifier(), application->getRequestQueue() ) ).second;
|
application->getRequestQueue());
|
||||||
if( errorCode == false ) {
|
if(not insertPair.second) {
|
||||||
returnValue = RETURN_FAILED;
|
returnValue = RETURN_FAILED;
|
||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
@ -46,9 +54,8 @@ ReturnValue_t CCSDSDistributor::registerApplication(
|
|||||||
ReturnValue_t CCSDSDistributor::registerApplication(uint16_t apid,
|
ReturnValue_t CCSDSDistributor::registerApplication(uint16_t apid,
|
||||||
MessageQueueId_t id) {
|
MessageQueueId_t id) {
|
||||||
ReturnValue_t returnValue = RETURN_OK;
|
ReturnValue_t returnValue = RETURN_OK;
|
||||||
bool errorCode = true;
|
auto insertPair = this->queueMap.emplace(apid, id);
|
||||||
errorCode = this->queueMap.insert( std::pair<uint32_t, MessageQueueId_t>( apid, id ) ).second;
|
if(not insertPair.second) {
|
||||||
if( errorCode == false ) {
|
|
||||||
returnValue = RETURN_FAILED;
|
returnValue = RETURN_FAILED;
|
||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
@ -62,7 +69,11 @@ uint16_t CCSDSDistributor::getIdentifier() {
|
|||||||
ReturnValue_t CCSDSDistributor::initialize() {
|
ReturnValue_t CCSDSDistributor::initialize() {
|
||||||
ReturnValue_t status = this->TcDistributor::initialize();
|
ReturnValue_t status = this->TcDistributor::initialize();
|
||||||
this->tcStore = objectManager->get<StorageManagerIF>( objects::TC_STORE );
|
this->tcStore = objectManager->get<StorageManagerIF>( objects::TC_STORE );
|
||||||
if (this->tcStore == NULL) status = RETURN_FAILED;
|
if (this->tcStore == nullptr) {
|
||||||
|
sif::error << "CCSDSDistributor::initialize: Could not initialize"
|
||||||
|
" TC store!" << std::endl;
|
||||||
|
status = RETURN_FAILED;
|
||||||
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,58 +1,71 @@
|
|||||||
#ifndef CCSDSDISTRIBUTOR_H_
|
#ifndef FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_
|
||||||
#define CCSDSDISTRIBUTOR_H_
|
#define FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_
|
||||||
|
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManagerIF.h"
|
||||||
#include "../storagemanager/StorageManagerIF.h"
|
#include "../storagemanager/StorageManagerIF.h"
|
||||||
#include "CCSDSDistributorIF.h"
|
#include "../tcdistribution/CCSDSDistributorIF.h"
|
||||||
#include "TcDistributor.h"
|
#include "../tcdistribution/TcDistributor.h"
|
||||||
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instantiation of the CCSDSDistributorIF.
|
* @brief An instantiation of the CCSDSDistributorIF.
|
||||||
* It receives Space Packets, and selects a destination depending on the APID of the telecommands.
|
* @details
|
||||||
|
* It receives Space Packets, and selects a destination depending on the
|
||||||
|
* APID of the telecommands.
|
||||||
* The Secondary Header (with Service/Subservice) is ignored.
|
* The Secondary Header (with Service/Subservice) is ignored.
|
||||||
* \ingroup tc_distribution
|
* @ingroup tc_distribution
|
||||||
*/
|
*/
|
||||||
class CCSDSDistributor : public TcDistributor, public CCSDSDistributorIF, public AcceptsTelecommandsIF {
|
class CCSDSDistributor : public TcDistributor,
|
||||||
protected:
|
public CCSDSDistributorIF,
|
||||||
/**
|
public AcceptsTelecommandsIF {
|
||||||
* This implementation checks if an Application with fitting APID has registered and forwards the
|
|
||||||
* packet to the according message queue.
|
|
||||||
* If the packet is not found, it returns the queue to \c default_apid, where a Acceptance Failure
|
|
||||||
* message should be generated.
|
|
||||||
* @return Iterator to map entry of found APID or iterator to default APID.
|
|
||||||
*/
|
|
||||||
iterator_t selectDestination();
|
|
||||||
/**
|
|
||||||
* The default APID, where packets with unknown APID are sent to.
|
|
||||||
*/
|
|
||||||
uint16_t default_apid;
|
|
||||||
/**
|
|
||||||
* A reference to the TC storage must be maintained, as this class handles pure Space Packets and there
|
|
||||||
* exists no SpacePacketStored class.
|
|
||||||
*/
|
|
||||||
StorageManagerIF* tcStore;
|
|
||||||
/**
|
|
||||||
* The callback here handles the generation of acceptance success/failure messages.
|
|
||||||
*/
|
|
||||||
ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus );
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* The constructor sets the default APID and calls the TcDistributor ctor with a certain object id.
|
* @brief The constructor sets the default APID and calls the
|
||||||
* \c tcStore is set in the \c initialize method.
|
* TcDistributor ctor with a certain object id.
|
||||||
* @param set_default_apid The default APID, where packets with unknown destination are sent to.
|
* @details
|
||||||
|
* @c tcStore is set in the @c initialize method.
|
||||||
|
* @param setDefaultApid The default APID, where packets with unknown
|
||||||
|
* destination are sent to.
|
||||||
*/
|
*/
|
||||||
CCSDSDistributor(uint16_t setDefaultApid, object_id_t setObjectId);
|
CCSDSDistributor(uint16_t setDefaultApid, object_id_t setObjectId);
|
||||||
/**
|
/**
|
||||||
* The destructor is empty.
|
* The destructor is empty.
|
||||||
*/
|
*/
|
||||||
~CCSDSDistributor();
|
virtual ~CCSDSDistributor();
|
||||||
MessageQueueId_t getRequestQueue();
|
|
||||||
ReturnValue_t registerApplication( uint16_t apid, MessageQueueId_t id );
|
MessageQueueId_t getRequestQueue() override;
|
||||||
ReturnValue_t registerApplication( AcceptsTelecommandsIF* application );
|
ReturnValue_t registerApplication( uint16_t apid,
|
||||||
uint16_t getIdentifier();
|
MessageQueueId_t id) override;
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t registerApplication(
|
||||||
|
AcceptsTelecommandsIF* application) override;
|
||||||
|
uint16_t getIdentifier() override;
|
||||||
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* This implementation checks if an application with fitting APID has
|
||||||
|
* registered and forwards the packet to the according message queue.
|
||||||
|
* If the packet is not found, it returns the queue to @c defaultApid,
|
||||||
|
* where a Acceptance Failure message should be generated.
|
||||||
|
* @return Iterator to map entry of found APID or iterator to default APID.
|
||||||
|
*/
|
||||||
|
TcMqMapIter selectDestination() override;
|
||||||
|
/**
|
||||||
|
* The callback here handles the generation of acceptance
|
||||||
|
* success/failure messages.
|
||||||
|
*/
|
||||||
|
ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus ) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default APID, where packets with unknown APID are sent to.
|
||||||
|
*/
|
||||||
|
uint16_t defaultApid;
|
||||||
|
/**
|
||||||
|
* A reference to the TC storage must be maintained, as this class handles
|
||||||
|
* pure Space Packets and there exists no SpacePacketStored class.
|
||||||
|
*/
|
||||||
|
StorageManagerIF* tcStore = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif /* FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ */
|
||||||
|
|
||||||
#endif /* CCSDSDISTRIBUTOR_H_ */
|
|
||||||
|
@ -1,34 +1,38 @@
|
|||||||
#ifndef CCSDSDISTRIBUTORIF_H_
|
#ifndef FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_
|
||||||
#define CCSDSDISTRIBUTORIF_H_
|
#define FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_
|
||||||
|
|
||||||
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
||||||
#include "../ipc/MessageQueueSenderIF.h"
|
#include "../ipc/MessageQueueSenderIF.h"
|
||||||
/**
|
/**
|
||||||
* This is the Interface to a CCSDS Distributor.
|
* This is the Interface to a CCSDS Distributor.
|
||||||
* On a CCSDS Distributor, Applications (in terms of CCSDS) may register themselves,
|
* On a CCSDS Distributor, Applications (in terms of CCSDS) may register
|
||||||
* either by passing a pointer to themselves (and implementing the CCSDSApplicationIF,
|
* themselves, either by passing a pointer to themselves (and implementing the
|
||||||
* or by explicitly passing an APID and a MessageQueueId to route the TC's to.
|
* CCSDSApplicationIF), or by explicitly passing an APID and a MessageQueueId
|
||||||
* \ingroup tc_distribution
|
* to route the TC's to.
|
||||||
|
* @ingroup tc_distribution
|
||||||
*/
|
*/
|
||||||
class CCSDSDistributorIF {
|
class CCSDSDistributorIF {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* With this call, a class implementing the CCSDSApplicationIF can register at the
|
* With this call, a class implementing the CCSDSApplicationIF can register
|
||||||
* distributor.
|
* at the distributor.
|
||||||
* @param application A pointer to the Application to register.
|
* @param application A pointer to the Application to register.
|
||||||
* @return - \c RETURN_OK on success,
|
* @return - @c RETURN_OK on success,
|
||||||
* - \c RETURN_FAILED on failure.
|
* - @c RETURN_FAILED on failure.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t registerApplication( AcceptsTelecommandsIF* application ) = 0;
|
virtual ReturnValue_t registerApplication(
|
||||||
|
AcceptsTelecommandsIF* application) = 0;
|
||||||
/**
|
/**
|
||||||
* With this call, other Applications can register to the CCSDS distributor.
|
* With this call, other Applications can register to the CCSDS distributor.
|
||||||
* This is done by passing an APID and a MessageQueueId to the method.
|
* This is done by passing an APID and a MessageQueueId to the method.
|
||||||
* @param apid The APID to register.
|
* @param apid The APID to register.
|
||||||
* @param id The MessageQueueId of the message queue to send the TC Packets to.
|
* @param id The MessageQueueId of the message queue to send the
|
||||||
* @return - \c RETURN_OK on success,
|
* TC Packets to.
|
||||||
* - \c RETURN_FAILED on failure.
|
* @return - @c RETURN_OK on success,
|
||||||
|
* - @c RETURN_FAILED on failure.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t registerApplication( uint16_t apid, MessageQueueId_t id ) = 0;
|
virtual ReturnValue_t registerApplication( uint16_t apid,
|
||||||
|
MessageQueueId_t id) = 0;
|
||||||
/**
|
/**
|
||||||
* The empty virtual destructor.
|
* The empty virtual destructor.
|
||||||
*/
|
*/
|
||||||
@ -37,4 +41,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* CCSDSDISTRIBUTORIF_H_ */
|
#endif /* FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ */
|
||||||
|
@ -1,61 +1,74 @@
|
|||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include "CCSDSDistributorIF.h"
|
#include "CCSDSDistributorIF.h"
|
||||||
#include "PUSDistributor.h"
|
#include "PUSDistributor.h"
|
||||||
|
|
||||||
|
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||||
#include "../tmtcpacket/pus/TcPacketStored.h"
|
#include "../tmtcpacket/pus/TcPacketStored.h"
|
||||||
#include "../tmtcservices/PusVerificationReport.h"
|
#include "../tmtcservices/PusVerificationReport.h"
|
||||||
|
|
||||||
PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource) :
|
PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId,
|
||||||
TcDistributor(setObjectId), checker(setApid), verifyChannel(), currentPacket(), tcStatus(
|
object_id_t setPacketSource) :
|
||||||
RETURN_FAILED), packetSource(setPacketSource) {
|
TcDistributor(setObjectId), checker(setApid), verifyChannel(),
|
||||||
|
tcStatus(RETURN_FAILED), packetSource(setPacketSource) {}
|
||||||
|
|
||||||
|
PUSDistributor::~PUSDistributor() {}
|
||||||
|
|
||||||
|
PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() {
|
||||||
|
// sif:: debug << "PUSDistributor::handlePacket received: "
|
||||||
|
// << this->current_packet_id.store_index << ", "
|
||||||
|
// << this->current_packet_id.packet_index << std::endl;
|
||||||
|
TcMqMapIter queueMapIt = this->queueMap.end();
|
||||||
|
if(this->currentPacket == nullptr) {
|
||||||
|
return queueMapIt;
|
||||||
}
|
}
|
||||||
|
this->currentPacket->setStoreAddress(this->currentMessage.getStorageId());
|
||||||
PUSDistributor::~PUSDistributor() {
|
if (currentPacket->getWholeData() != nullptr) {
|
||||||
|
tcStatus = checker.checkPacket(currentPacket);
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(tcStatus != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
sif::debug << "PUSDistributor::handlePacket: Packet format "
|
||||||
|
<< "invalid, code "<< static_cast<int>(tcStatus)
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
iterator_t PUSDistributor::selectDestination() {
|
uint32_t queue_id = currentPacket->getService();
|
||||||
// sif::debug << "PUSDistributor::handlePacket received "<<std::endl;// << this->currentPacket.store_index << ", " << this->current_packet_id.packet_index << std::endl;
|
|
||||||
iterator_t queueMapIt = this->queueMap.end();
|
|
||||||
this->currentPacket.setStoreAddress(this->currentMessage.getStorageId());
|
|
||||||
if (currentPacket.getWholeData() != NULL) {
|
|
||||||
tcStatus = checker.checkPacket(¤tPacket);
|
|
||||||
// info << "PUSDistributor::handlePacket: packetCheck returned with " << (int)tc_status << std::endl;
|
|
||||||
uint32_t queue_id = currentPacket.getService();
|
|
||||||
queueMapIt = this->queueMap.find(queue_id);
|
queueMapIt = this->queueMap.find(queue_id);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
tcStatus = PACKET_LOST;
|
tcStatus = PACKET_LOST;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queueMapIt == this->queueMap.end()) {
|
if (queueMapIt == this->queueMap.end()) {
|
||||||
tcStatus = DESTINATION_NOT_FOUND;
|
tcStatus = DESTINATION_NOT_FOUND;
|
||||||
|
#ifdef DEBUG
|
||||||
|
sif::debug << "PUSDistributor::handlePacket: Destination not found, "
|
||||||
|
<< "code "<< static_cast<int>(tcStatus) << std::endl;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcStatus != RETURN_OK) {
|
if (tcStatus != RETURN_OK) {
|
||||||
sif::debug << "PUSDistributor::handlePacket: error with " << (int) tcStatus
|
sif::debug << "PUSDistributor::handlePacket: error with " << (int) tcStatus
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return this->queueMap.end();
|
return this->queueMap.end();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return queueMapIt;
|
return queueMapIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//uint16_t PUSDistributor::createDestination( uint8_t service_id, uint8_t subservice_id ) {
|
|
||||||
// return ( service_id << 8 ) + subservice_id;
|
|
||||||
//}
|
|
||||||
|
|
||||||
ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) {
|
ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) {
|
||||||
ReturnValue_t returnValue = RETURN_OK;
|
|
||||||
bool errorCode = true;
|
|
||||||
uint16_t serviceId = service->getIdentifier();
|
uint16_t serviceId = service->getIdentifier();
|
||||||
|
// sif::info << "Service ID: " << (int)serviceId << std::endl;
|
||||||
MessageQueueId_t queue = service->getRequestQueue();
|
MessageQueueId_t queue = service->getRequestQueue();
|
||||||
errorCode = this->queueMap.insert(
|
auto returnPair = queueMap.emplace(serviceId, queue);
|
||||||
std::pair<uint32_t, MessageQueueId_t>(serviceId, queue)).second;
|
if (not returnPair.second) {
|
||||||
if (errorCode == false) {
|
sif::error << "PUSDistributor::registerService: Service ID already"
|
||||||
//TODO Return Code
|
" exists in map." << std::endl;
|
||||||
returnValue = MessageQueueIF::NO_QUEUE;
|
return SERVICE_ID_ALREADY_EXISTS;
|
||||||
}
|
}
|
||||||
return returnValue;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t PUSDistributor::getRequestQueue() {
|
MessageQueueId_t PUSDistributor::getRequestQueue() {
|
||||||
@ -68,13 +81,14 @@ ReturnValue_t PUSDistributor::callbackAfterSending(ReturnValue_t queueStatus) {
|
|||||||
}
|
}
|
||||||
if (tcStatus != RETURN_OK) {
|
if (tcStatus != RETURN_OK) {
|
||||||
this->verifyChannel.sendFailureReport(TC_VERIFY::ACCEPTANCE_FAILURE,
|
this->verifyChannel.sendFailureReport(TC_VERIFY::ACCEPTANCE_FAILURE,
|
||||||
¤tPacket, tcStatus);
|
currentPacket, tcStatus);
|
||||||
//A failed packet is deleted immediately after reporting, otherwise it will block memory.
|
// A failed packet is deleted immediately after reporting,
|
||||||
currentPacket.deletePacket();
|
// otherwise it will block memory.
|
||||||
|
currentPacket->deletePacket();
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
} else {
|
} else {
|
||||||
this->verifyChannel.sendSuccessReport(TC_VERIFY::ACCEPTANCE_SUCCESS,
|
this->verifyChannel.sendSuccessReport(TC_VERIFY::ACCEPTANCE_SUCCESS,
|
||||||
¤tPacket);
|
currentPacket);
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,11 +98,19 @@ uint16_t PUSDistributor::getIdentifier() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PUSDistributor::initialize() {
|
ReturnValue_t PUSDistributor::initialize() {
|
||||||
|
currentPacket = new TcPacketStored();
|
||||||
|
if(currentPacket == nullptr) {
|
||||||
|
// Should not happen, memory allocation failed!
|
||||||
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
CCSDSDistributorIF* ccsdsDistributor =
|
CCSDSDistributorIF* ccsdsDistributor =
|
||||||
objectManager->get<CCSDSDistributorIF>(packetSource);
|
objectManager->get<CCSDSDistributorIF>(packetSource);
|
||||||
if (ccsdsDistributor == NULL) {
|
if (ccsdsDistributor == nullptr) {
|
||||||
|
sif::error << "PUSDistributor::initialize: Packet source invalid."
|
||||||
|
<< " Make sure it exists and implements CCSDSDistributorIF!"
|
||||||
|
<< std::endl;
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
} else {
|
}
|
||||||
return ccsdsDistributor->registerApplication(this);
|
return ccsdsDistributor->registerApplication(this);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -1,67 +1,79 @@
|
|||||||
#ifndef PUSDISTRIBUTOR_H_
|
#ifndef FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_
|
||||||
#define PUSDISTRIBUTOR_H_
|
#define FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_
|
||||||
|
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
|
||||||
#include "PUSDistributorIF.h"
|
#include "PUSDistributorIF.h"
|
||||||
#include "TcDistributor.h"
|
#include "TcDistributor.h"
|
||||||
#include "TcPacketCheck.h"
|
#include "TcPacketCheck.h"
|
||||||
|
|
||||||
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
||||||
#include "../tmtcservices/VerificationReporter.h"
|
#include "../tmtcservices/VerificationReporter.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class accepts PUS Telecommands and forwards them to Application services.
|
* This class accepts PUS Telecommands and forwards them to Application
|
||||||
* In addition, the class performs a formal packet check and sends acceptance success
|
* services. In addition, the class performs a formal packet check and
|
||||||
* or failure messages.
|
* sends acceptance success or failure messages.
|
||||||
* \ingroup tc_distribution
|
* @ingroup tc_distribution
|
||||||
*/
|
*/
|
||||||
class PUSDistributor: public TcDistributor,
|
class PUSDistributor: public TcDistributor,
|
||||||
public PUSDistributorIF,
|
public PUSDistributorIF,
|
||||||
public AcceptsTelecommandsIF {
|
public AcceptsTelecommandsIF {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* The ctor passes \c set_apid to the checker class and calls the TcDistribution ctor with a certain object id.
|
* The ctor passes @c set_apid to the checker class and calls the
|
||||||
|
* TcDistribution ctor with a certain object id.
|
||||||
* @param setApid The APID of this receiving Application.
|
* @param setApid The APID of this receiving Application.
|
||||||
* @param setObjectId Object ID of the distributor itself
|
* @param setObjectId Object ID of the distributor itself
|
||||||
* @param setPacketSource Object ID of the source of TC packets. Must implement CCSDSDistributorIF.
|
* @param setPacketSource Object ID of the source of TC packets.
|
||||||
|
* Must implement CCSDSDistributorIF.
|
||||||
*/
|
*/
|
||||||
PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource);
|
PUSDistributor(uint16_t setApid, object_id_t setObjectId,
|
||||||
|
object_id_t setPacketSource);
|
||||||
/**
|
/**
|
||||||
* The destructor is empty.
|
* The destructor is empty.
|
||||||
*/
|
*/
|
||||||
virtual ~PUSDistributor();
|
virtual ~PUSDistributor();
|
||||||
ReturnValue_t registerService(AcceptsTelecommandsIF* service);
|
ReturnValue_t registerService(AcceptsTelecommandsIF* service) override;
|
||||||
MessageQueueId_t getRequestQueue();
|
MessageQueueId_t getRequestQueue() override;
|
||||||
uint16_t getIdentifier();
|
ReturnValue_t initialize() override;
|
||||||
ReturnValue_t initialize();
|
uint16_t getIdentifier() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* This attribute contains the class, that performs a formal packet check.
|
* This attribute contains the class, that performs a formal packet check.
|
||||||
*/
|
*/
|
||||||
TcPacketCheck checker;
|
TcPacketCheck checker;
|
||||||
/**
|
/**
|
||||||
* With this class, verification messages are sent to the TC Verification service.
|
* With this class, verification messages are sent to the
|
||||||
|
* TC Verification service.
|
||||||
*/
|
*/
|
||||||
VerificationReporter verifyChannel;
|
VerificationReporter verifyChannel;
|
||||||
/**
|
/**
|
||||||
* The currently handled packet is stored here.
|
* The currently handled packet is stored here.
|
||||||
*/
|
*/
|
||||||
TcPacketStored currentPacket;
|
TcPacketStored* currentPacket = nullptr;
|
||||||
/**
|
/**
|
||||||
* With this variable, the current check status is stored to generate acceptance messages later.
|
* With this variable, the current check status is stored to generate
|
||||||
|
* acceptance messages later.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t tcStatus;
|
ReturnValue_t tcStatus;
|
||||||
|
|
||||||
const object_id_t packetSource;
|
const object_id_t packetSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads the packet service, checks if such a service is registered and forwards the packet to the destination.
|
* This method reads the packet service, checks if such a service is
|
||||||
* It also initiates the formal packet check and sending of verification messages.
|
* registered and forwards the packet to the destination.
|
||||||
* @return Iterator to map entry of found service id or iterator to \c map.end().
|
* It also initiates the formal packet check and sending of verification
|
||||||
|
* messages.
|
||||||
|
* @return Iterator to map entry of found service id
|
||||||
|
* or iterator to @c map.end().
|
||||||
*/
|
*/
|
||||||
iterator_t selectDestination();
|
TcMqMapIter selectDestination() override;
|
||||||
/**
|
/**
|
||||||
* The callback here handles the generation of acceptance success/failure messages.
|
* The callback here handles the generation of acceptance
|
||||||
|
* success/failure messages.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus);
|
ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PUSDISTRIBUTOR_H_ */
|
#endif /* FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_ */
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#ifndef PUSDISTRIBUTORIF_H_
|
#ifndef FSFW_TCDISTRIBUTION_PUSDISTRIBUTORIF_H_
|
||||||
#define PUSDISTRIBUTORIF_H_
|
#define FSFW_TCDISTRIBUTION_PUSDISTRIBUTORIF_H_
|
||||||
|
|
||||||
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
||||||
#include "../ipc/MessageQueueSenderIF.h"
|
#include "../ipc/MessageQueueSenderIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface allows PUS Services to register themselves at a PUS Distributor.
|
* This interface allows PUS Services to register themselves at a PUS Distributor.
|
||||||
* \ingroup tc_distribution
|
* @ingroup tc_distribution
|
||||||
*/
|
*/
|
||||||
class PUSDistributorIF {
|
class PUSDistributorIF {
|
||||||
public:
|
public:
|
||||||
@ -17,10 +18,10 @@ public:
|
|||||||
/**
|
/**
|
||||||
* With this method, Services can register themselves at the PUS Distributor.
|
* With this method, Services can register themselves at the PUS Distributor.
|
||||||
* @param service A pointer to the registering Service.
|
* @param service A pointer to the registering Service.
|
||||||
* @return - \c RETURN_OK on success,
|
* @return - @c RETURN_OK on success,
|
||||||
* - \c RETURN_FAILED on failure.
|
* - @c RETURN_FAILED on failure.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t registerService( AcceptsTelecommandsIF* service ) = 0;
|
virtual ReturnValue_t registerService( AcceptsTelecommandsIF* service ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PUSDISTRIBUTORIF_H_ */
|
#endif /* FSFW_TCDISTRIBUTION_PUSDISTRIBUTORIF_H_ */
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include "TcDistributor.h"
|
#include "TcDistributor.h"
|
||||||
|
|
||||||
|
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||||
#include "../tmtcservices/TmTcMessage.h"
|
#include "../tmtcservices/TmTcMessage.h"
|
||||||
#include "../ipc/QueueFactory.h"
|
#include "../ipc/QueueFactory.h"
|
||||||
|
|
||||||
TcDistributor::TcDistributor(object_id_t set_object_id) :
|
TcDistributor::TcDistributor(object_id_t objectId) :
|
||||||
SystemObject(set_object_id), tcQueue(NULL) {
|
SystemObject(objectId) {
|
||||||
tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS);
|
tcQueue = QueueFactory::instance()->
|
||||||
|
createMessageQueue(DISTRIBUTER_MAX_PACKETS);
|
||||||
}
|
}
|
||||||
|
|
||||||
TcDistributor::~TcDistributor() {
|
TcDistributor::~TcDistributor() {
|
||||||
@ -15,7 +16,6 @@ TcDistributor::~TcDistributor() {
|
|||||||
|
|
||||||
ReturnValue_t TcDistributor::performOperation(uint8_t opCode) {
|
ReturnValue_t TcDistributor::performOperation(uint8_t opCode) {
|
||||||
ReturnValue_t status = RETURN_OK;
|
ReturnValue_t status = RETURN_OK;
|
||||||
//sif::debug << "TcDistributor: performing Operation." << std::endl;
|
|
||||||
for (status = tcQueue->receiveMessage(¤tMessage); status == RETURN_OK;
|
for (status = tcQueue->receiveMessage(¤tMessage); status == RETURN_OK;
|
||||||
status = tcQueue->receiveMessage(¤tMessage)) {
|
status = tcQueue->receiveMessage(¤tMessage)) {
|
||||||
status = handlePacket();
|
status = handlePacket();
|
||||||
@ -29,7 +29,7 @@ ReturnValue_t TcDistributor::performOperation(uint8_t opCode) {
|
|||||||
|
|
||||||
ReturnValue_t TcDistributor::handlePacket() {
|
ReturnValue_t TcDistributor::handlePacket() {
|
||||||
|
|
||||||
iterator_t queueMapIt = this->selectDestination();
|
TcMqMapIter queueMapIt = this->selectDestination();
|
||||||
ReturnValue_t returnValue = RETURN_FAILED;
|
ReturnValue_t returnValue = RETURN_FAILED;
|
||||||
// sif::debug << "TcDistributor::handlePacket" << std::endl;
|
// sif::debug << "TcDistributor::handlePacket" << std::endl;
|
||||||
if (queueMapIt != this->queueMap.end()) {
|
if (queueMapIt != this->queueMap.end()) {
|
||||||
@ -40,14 +40,14 @@ ReturnValue_t TcDistributor::handlePacket() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TcDistributor::print() {
|
void TcDistributor::print() {
|
||||||
sif::debug << "Distributor content is: " << std::endl << "ID\t| message queue id"
|
sif::debug << "Distributor content is: " << std::endl
|
||||||
<< std::endl;
|
<< "ID\t| Message Queue ID" << std::endl;
|
||||||
for (iterator_t it = this->queueMap.begin(); it != this->queueMap.end();
|
sif::debug << std::setfill('0') << std::setw(8) << std::hex;
|
||||||
it++) {
|
for (const auto& queueMapIter: queueMap) {
|
||||||
sif::debug << it->first << "\t| 0x" << std::hex << it->second << std::dec
|
sif::debug << queueMapIter.first << "\t| 0x" << queueMapIter.second
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
sif::debug << std::dec;
|
sif::debug << std::setfill(' ') << std::dec;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#ifndef TCDISTRIBUTOR_H_
|
#ifndef FSFW_TMTCSERVICES_TCDISTRIBUTOR_H_
|
||||||
#define TCDISTRIBUTOR_H_
|
#define FSFW_TMTCSERVICES_TCDISTRIBUTOR_H_
|
||||||
|
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManagerIF.h"
|
||||||
#include "../objectmanager/SystemObject.h"
|
#include "../objectmanager/SystemObject.h"
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
@ -9,16 +10,12 @@
|
|||||||
#include "../ipc/MessageQueueIF.h"
|
#include "../ipc/MessageQueueIF.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \defgroup tc_distribution Telecommand Distribution
|
* @defgroup tc_distribution Telecommand Distribution
|
||||||
* All classes associated with Routing and Distribution of Telecommands belong to this group.
|
* All classes associated with Routing and Distribution of Telecommands
|
||||||
|
* belong to this group.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* This typedef simplifies writing down the \c map iterator.
|
|
||||||
*/
|
|
||||||
typedef std::map<uint32_t, MessageQueueId_t>::iterator iterator_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the base class to implement distributors for Space Packets.
|
* This is the base class to implement distributors for Space Packets.
|
||||||
@ -28,62 +25,19 @@ typedef std::map<uint32_t, MessageQueueId_t>::iterator iterator_t;
|
|||||||
* message queue ids to some identifier. The process of unpacking the
|
* message queue ids to some identifier. The process of unpacking the
|
||||||
* destination information from the packet is handled by the child class
|
* destination information from the packet is handled by the child class
|
||||||
* implementations.
|
* implementations.
|
||||||
* \ingroup tc_distribution
|
* @ingroup tc_distribution
|
||||||
*/
|
*/
|
||||||
class TcDistributor : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF {
|
class TcDistributor : public SystemObject,
|
||||||
private:
|
public ExecutableObjectIF,
|
||||||
/**
|
public HasReturnvaluesIF {
|
||||||
* This constant sets the maximum number of packets distributed per call.
|
|
||||||
*/
|
|
||||||
static const uint8_t DISTRIBUTER_MAX_PACKETS = 128;
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* This is the receiving queue for incoming Telecommands.
|
|
||||||
* The child classes must make its queue id public.
|
|
||||||
*/
|
|
||||||
MessageQueueIF* tcQueue;
|
|
||||||
/**
|
|
||||||
* The last received incoming packet information is stored in this
|
|
||||||
* member.
|
|
||||||
* As different child classes unpack the incoming packet differently
|
|
||||||
* (i.e. as a CCSDS Space Packet or as a PUS Telecommand Packet), it
|
|
||||||
* is not tried to unpack the packet information within this class.
|
|
||||||
*/
|
|
||||||
TmTcMessage currentMessage;
|
|
||||||
/**
|
|
||||||
* The map that links certain packet information to a destination.
|
|
||||||
* The packet information may be the APID of the packet or the service
|
|
||||||
* identifier. Filling of the map is under control of the different child
|
|
||||||
* classes.
|
|
||||||
*/
|
|
||||||
std::map<uint32_t, MessageQueueId_t> queueMap;
|
|
||||||
/**
|
|
||||||
* This method shall unpack the routing information from the incoming
|
|
||||||
* packet and select the map entry which represents the packet's target.
|
|
||||||
* @return An iterator to the map element to forward to or queuMap.end().
|
|
||||||
*/
|
|
||||||
virtual iterator_t selectDestination() = 0;
|
|
||||||
/**
|
|
||||||
* The handlePacket method calls the child class's selectDestination method
|
|
||||||
* and forwards the packet to its destination, if found.
|
|
||||||
* @return The message queue return value or \c RETURN_FAILED, in case no
|
|
||||||
* destination was found.
|
|
||||||
*/
|
|
||||||
ReturnValue_t handlePacket();
|
|
||||||
/**
|
|
||||||
* This method gives the child class a chance to perform some kind of operation
|
|
||||||
* after the parent tried to forward the message.
|
|
||||||
* A typically application would be sending success/failure messages.
|
|
||||||
* The default implementation just returns \c RETURN_OK.
|
|
||||||
* @param queueStatus The status of the message queue after an attempt to send the TC.
|
|
||||||
* @return - \c RETURN_OK on success
|
|
||||||
* - \c RETURN_FAILED on failure
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus );
|
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::PACKET_DISTRIBUTION;
|
using TcMessageQueueMap = std::map<uint32_t, MessageQueueId_t>;
|
||||||
static const ReturnValue_t PACKET_LOST = MAKE_RETURN_CODE( 1 );
|
using TcMqMapIter = std::map<uint32_t, MessageQueueId_t>::iterator;
|
||||||
static const ReturnValue_t DESTINATION_NOT_FOUND = MAKE_RETURN_CODE( 2 );
|
|
||||||
|
static constexpr uint8_t INTERFACE_ID = CLASS_ID::PACKET_DISTRIBUTION;
|
||||||
|
static constexpr ReturnValue_t PACKET_LOST = MAKE_RETURN_CODE( 1 );
|
||||||
|
static constexpr ReturnValue_t DESTINATION_NOT_FOUND = MAKE_RETURN_CODE( 2 );
|
||||||
|
static constexpr ReturnValue_t SERVICE_ID_ALREADY_EXISTS = MAKE_RETURN_CODE(3);
|
||||||
/**
|
/**
|
||||||
* Within the default constructor, the SystemObject id is set and the
|
* Within the default constructor, the SystemObject id is set and the
|
||||||
* message queue is initialized.
|
* message queue is initialized.
|
||||||
@ -91,7 +45,7 @@ public:
|
|||||||
* @param set_object_id This id is assigned to the distributor
|
* @param set_object_id This id is assigned to the distributor
|
||||||
* implementation.
|
* implementation.
|
||||||
*/
|
*/
|
||||||
TcDistributor( object_id_t set_object_id );
|
TcDistributor(object_id_t objectId);
|
||||||
/**
|
/**
|
||||||
* The destructor is empty, the message queues are not in the vicinity of
|
* The destructor is empty, the message queues are not in the vicinity of
|
||||||
* this class.
|
* this class.
|
||||||
@ -110,7 +64,59 @@ public:
|
|||||||
* queueMap.
|
* queueMap.
|
||||||
*/
|
*/
|
||||||
void print();
|
void print();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* This is the receiving queue for incoming Telecommands.
|
||||||
|
* The child classes must make its queue id public.
|
||||||
|
*/
|
||||||
|
MessageQueueIF* tcQueue = nullptr;
|
||||||
|
/**
|
||||||
|
* The last received incoming packet information is stored in this
|
||||||
|
* member.
|
||||||
|
* As different child classes unpack the incoming packet differently
|
||||||
|
* (i.e. as a CCSDS Space Packet or as a PUS Telecommand Packet), it
|
||||||
|
* is not tried to unpack the packet information within this class.
|
||||||
|
*/
|
||||||
|
TmTcMessage currentMessage;
|
||||||
|
/**
|
||||||
|
* The map that links certain packet information to a destination.
|
||||||
|
* The packet information may be the APID of the packet or the service
|
||||||
|
* identifier. Filling of the map is under control of the different child
|
||||||
|
* classes.
|
||||||
|
*/
|
||||||
|
TcMessageQueueMap queueMap;
|
||||||
|
/**
|
||||||
|
* This method shall unpack the routing information from the incoming
|
||||||
|
* packet and select the map entry which represents the packet's target.
|
||||||
|
* @return An iterator to the map element to forward to or queuMap.end().
|
||||||
|
*/
|
||||||
|
virtual TcMqMapIter selectDestination() = 0;
|
||||||
|
/**
|
||||||
|
* The handlePacket method calls the child class's selectDestination method
|
||||||
|
* and forwards the packet to its destination, if found.
|
||||||
|
* @return The message queue return value or @c RETURN_FAILED, in case no
|
||||||
|
* destination was found.
|
||||||
|
*/
|
||||||
|
ReturnValue_t handlePacket();
|
||||||
|
/**
|
||||||
|
* This method gives the child class a chance to perform some kind of
|
||||||
|
* operation after the parent tried to forward the message.
|
||||||
|
* A typically application would be sending success/failure messages.
|
||||||
|
* The default implementation just returns @c RETURN_OK.
|
||||||
|
* @param queueStatus The status of the message queue after an attempt
|
||||||
|
* to send the TC.
|
||||||
|
* @return - @c RETURN_OK on success
|
||||||
|
* - @c RETURN_FAILED on failure
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus );
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* This constant sets the maximum number of packets distributed per call.
|
||||||
|
*/
|
||||||
|
static constexpr uint8_t DISTRIBUTER_MAX_PACKETS = 128;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* TCDISTRIBUTOR_H_ */
|
#endif /* FSFW_TMTCSERVICES_TCDISTRIBUTOR_H_ */
|
||||||
|
@ -1,31 +1,33 @@
|
|||||||
|
#include "TcPacketCheck.h"
|
||||||
|
|
||||||
#include "../globalfunctions/CRC.h"
|
#include "../globalfunctions/CRC.h"
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||||
#include "../storagemanager/StorageManagerIF.h"
|
#include "../storagemanager/StorageManagerIF.h"
|
||||||
#include "TcPacketCheck.h"
|
|
||||||
#include "../tmtcservices/VerificationCodes.h"
|
#include "../tmtcservices/VerificationCodes.h"
|
||||||
|
|
||||||
TcPacketCheck::TcPacketCheck( uint16_t set_apid ) : apid(set_apid) {
|
TcPacketCheck::TcPacketCheck( uint16_t setApid ) : apid(setApid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TcPacketCheck::checkPacket( TcPacketStored* current_packet ) {
|
ReturnValue_t TcPacketCheck::checkPacket( TcPacketStored* currentPacket ) {
|
||||||
uint16_t calculated_crc = CRC::crc16ccitt( current_packet->getWholeData(), current_packet->getFullSize() );
|
uint16_t calculated_crc = CRC::crc16ccitt( currentPacket->getWholeData(),
|
||||||
|
currentPacket->getFullSize() );
|
||||||
if ( calculated_crc != 0 ) {
|
if ( calculated_crc != 0 ) {
|
||||||
return INCORRECT_CHECKSUM;
|
return INCORRECT_CHECKSUM;
|
||||||
}
|
}
|
||||||
bool condition = !(current_packet->hasSecondaryHeader()) ||
|
bool condition = (not currentPacket->hasSecondaryHeader()) or
|
||||||
current_packet->getPacketVersionNumber() != CCSDS_VERSION_NUMBER ||
|
(currentPacket->getPacketVersionNumber() != CCSDS_VERSION_NUMBER) or
|
||||||
!(current_packet->isTelecommand());
|
(not currentPacket->isTelecommand());
|
||||||
if ( condition ) {
|
if ( condition ) {
|
||||||
return INCORRECT_PRIMARY_HEADER;
|
return INCORRECT_PRIMARY_HEADER;
|
||||||
}
|
}
|
||||||
if ( current_packet->getAPID() != this->apid )
|
if ( currentPacket->getAPID() != this->apid )
|
||||||
return ILLEGAL_APID;
|
return ILLEGAL_APID;
|
||||||
|
|
||||||
if ( !current_packet->isSizeCorrect() ) {
|
if ( not currentPacket->isSizeCorrect() ) {
|
||||||
return INCOMPLETE_PACKET;
|
return INCOMPLETE_PACKET;
|
||||||
}
|
}
|
||||||
condition = (current_packet->getSecondaryHeaderFlag() != CCSDS_SECONDARY_HEADER_FLAG) ||
|
condition = (currentPacket->getSecondaryHeaderFlag() != CCSDS_SECONDARY_HEADER_FLAG) ||
|
||||||
(current_packet->getPusVersionNumber() != PUS_VERSION_NUMBER);
|
(currentPacket->getPusVersionNumber() != PUS_VERSION_NUMBER);
|
||||||
if ( condition ) {
|
if ( condition ) {
|
||||||
return INCORRECT_SECONDARY_HEADER;
|
return INCORRECT_SECONDARY_HEADER;
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,29 @@
|
|||||||
#ifndef TCPACKETCHECK_H_
|
#ifndef FSFW_TCDISTRIBUTION_TCPACKETCHECK_H_
|
||||||
#define TCPACKETCHECK_H_
|
#define FSFW_TCDISTRIBUTION_TCPACKETCHECK_H_
|
||||||
|
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
#include "../tmtcpacket/pus/TcPacketStored.h"
|
#include "../tmtcpacket/pus/TcPacketStored.h"
|
||||||
#include "../tmtcservices/PusVerificationReport.h"
|
#include "../tmtcservices/PusVerificationReport.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class performs a formal packet check for incoming PUS Telecommand Packets.
|
* This class performs a formal packet check for incoming PUS Telecommand Packets.
|
||||||
* Currently, it only checks if the APID and CRC are correct.
|
* Currently, it only checks if the APID and CRC are correct.
|
||||||
* \ingroup tc_distribution
|
* @ingroup tc_distribution
|
||||||
*/
|
*/
|
||||||
class TcPacketCheck : public HasReturnvaluesIF {
|
class TcPacketCheck : public HasReturnvaluesIF {
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Describes the version number a packet must have to pass.
|
* Describes the version number a packet must have to pass.
|
||||||
*/
|
*/
|
||||||
static const uint8_t CCSDS_VERSION_NUMBER = 0;
|
static constexpr uint8_t CCSDS_VERSION_NUMBER = 0;
|
||||||
/**
|
/**
|
||||||
* Describes the secondary header a packet must have to pass.
|
* Describes the secondary header a packet must have to pass.
|
||||||
*/
|
*/
|
||||||
static const uint8_t CCSDS_SECONDARY_HEADER_FLAG = 0;
|
static constexpr uint8_t CCSDS_SECONDARY_HEADER_FLAG = 0;
|
||||||
/**
|
/**
|
||||||
* Describes the TC Packet PUS Version Number a packet must have to pass.
|
* Describes the TC Packet PUS Version Number a packet must have to pass.
|
||||||
*/
|
*/
|
||||||
static const uint8_t PUS_VERSION_NUMBER = 1;
|
static constexpr uint8_t PUS_VERSION_NUMBER = 1;
|
||||||
/**
|
/**
|
||||||
* The packet id each correct packet should have.
|
* The packet id each correct packet should have.
|
||||||
* It is composed of the APID and some static fields.
|
* It is composed of the APID and some static fields.
|
||||||
@ -41,19 +42,19 @@ public:
|
|||||||
* The constructor only sets the APID attribute.
|
* The constructor only sets the APID attribute.
|
||||||
* @param set_apid The APID to set.
|
* @param set_apid The APID to set.
|
||||||
*/
|
*/
|
||||||
TcPacketCheck( uint16_t set_apid );
|
TcPacketCheck( uint16_t setApid );
|
||||||
/**
|
/**
|
||||||
* This is the actual method to formally check a certain Telecommand Packet.
|
* This is the actual method to formally check a certain Telecommand Packet.
|
||||||
* The packet's Application Data can not be checked here.
|
* The packet's Application Data can not be checked here.
|
||||||
* @param current_packet The packt to check
|
* @param current_packet The packt to check
|
||||||
* @return - \c RETURN_OK on success.
|
* @return - @c RETURN_OK on success.
|
||||||
* - \c INCORRECT_CHECKSUM if checksum is invalid.
|
* - @c INCORRECT_CHECKSUM if checksum is invalid.
|
||||||
* - \c ILLEGAL_APID if APID does not match.
|
* - @c ILLEGAL_APID if APID does not match.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t checkPacket( TcPacketStored* current_packet );
|
ReturnValue_t checkPacket( TcPacketStored* currentPacket );
|
||||||
|
|
||||||
uint16_t getApid() const;
|
uint16_t getApid() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* TCPACKETCHECK_H_ */
|
#endif /* FSFW_TCDISTRIBUTION_TCPACKETCHECK_H_ */
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "../timemanager/CCSDSTime.h"
|
#include "CCSDSTime.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <FSFWConfig.h>
|
||||||
|
|
||||||
CCSDSTime::CCSDSTime() {
|
CCSDSTime::CCSDSTime() {
|
||||||
}
|
}
|
||||||
@ -158,15 +159,16 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t*
|
|||||||
}
|
}
|
||||||
// Newlib nano can't parse uint8, see SCNu8 documentation and https://sourceware.org/newlib/README
|
// Newlib nano can't parse uint8, see SCNu8 documentation and https://sourceware.org/newlib/README
|
||||||
// Suggestion: use uint16 all the time. This should work on all systems.
|
// Suggestion: use uint16 all the time. This should work on all systems.
|
||||||
#ifdef NEWLIB_NANO_NO_C99_IO
|
#if FSFW_NO_C99_IO == 1
|
||||||
uint16_t year;
|
uint16_t year;
|
||||||
uint16_t month;
|
uint16_t month;
|
||||||
uint16_t day;
|
uint16_t day;
|
||||||
uint16_t hour;
|
uint16_t hour;
|
||||||
uint16_t minute;
|
uint16_t minute;
|
||||||
float second;
|
float second;
|
||||||
int count = sscanf((char *) from, "%4" SCNu16 "-%2" SCNu16 "-%2" SCNu16 "T%2" SCNu16 ":%2" SCNu16 ":%fZ", &year,
|
int count = sscanf((char *) from, "%4" SCNu16 "-%2" SCNu16 "-%2" SCNu16 "T%"
|
||||||
&month, &day, &hour, &minute, &second);
|
"2" SCNu16 ":%2" SCNu16 ":%fZ", &year, &month, &day, &hour,
|
||||||
|
&minute, &second);
|
||||||
if (count == 6) {
|
if (count == 6) {
|
||||||
to->year = year;
|
to->year = year;
|
||||||
to->month = month;
|
to->month = month;
|
||||||
@ -179,12 +181,13 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try Code B (yyyy-ddd)
|
// try Code B (yyyy-ddd)
|
||||||
count = sscanf((char *) from, "%4" SCNu16 "-%3" SCNu16 "T%2" SCNu16 ":%2" SCNu16 ":%fZ", &year, &day,
|
count = sscanf((char *) from, "%4" SCNu16 "-%3" SCNu16 "T%2" SCNu16 ":%"
|
||||||
&hour, &minute, &second);
|
"2" SCNu16 ":%fZ", &year, &day, &hour, &minute, &second);
|
||||||
if (count == 5) {
|
if (count == 5) {
|
||||||
uint8_t tempDay;
|
uint8_t tempDay;
|
||||||
ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year,
|
ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year,
|
||||||
reinterpret_cast<uint8_t *>(&month), reinterpret_cast<uint8_t *>(&tempDay));
|
reinterpret_cast<uint8_t *>(&month),
|
||||||
|
reinterpret_cast<uint8_t *>(&tempDay));
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define FRAMEWORK_TIMEMANAGER_CLOCK_H_
|
#define FRAMEWORK_TIMEMANAGER_CLOCK_H_
|
||||||
|
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
#include "../ipc/MutexFactory.h"
|
#include "../ipc/MutexHelper.h"
|
||||||
#include "../globalfunctions/timevalOperations.h"
|
#include "../globalfunctions/timevalOperations.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
@ -14,8 +14,12 @@ public:
|
|||||||
static const uint8_t INTERFACE_ID = CLASS_ID::TIME_STAMPER_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::TIME_STAMPER_IF;
|
||||||
static const ReturnValue_t BAD_TIMESTAMP = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t BAD_TIMESTAMP = MAKE_RETURN_CODE(1);
|
||||||
|
|
||||||
static const uint8_t MISSION_TIMESTAMP_SIZE = 8; //!< This is a mission-specific constant and determines the total size reserved for timestamps.
|
//! This is a mission-specific constant and determines the total
|
||||||
virtual ReturnValue_t addTimeStamp(uint8_t* buffer, const uint8_t maxSize) = 0;
|
//! size reserved for timestamps.
|
||||||
|
//! TODO: Default define in FSFWConfig ?
|
||||||
|
static const uint8_t MISSION_TIMESTAMP_SIZE = 8;
|
||||||
|
virtual ReturnValue_t addTimeStamp(uint8_t* buffer,
|
||||||
|
const uint8_t maxSize) = 0;
|
||||||
virtual ~TimeStamperIF() {}
|
virtual ~TimeStamperIF() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include "SpacePacketBase.h"
|
#include "SpacePacketBase.h"
|
||||||
#include <string.h>
|
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
SpacePacketBase::SpacePacketBase( const uint8_t* set_address ) {
|
SpacePacketBase::SpacePacketBase( const uint8_t* set_address ) {
|
||||||
this->data = (SpacePacketPointer*) set_address;
|
this->data = (SpacePacketPointer*) set_address;
|
||||||
@ -14,7 +14,8 @@ uint8_t SpacePacketBase::getPacketVersionNumber( void ) {
|
|||||||
return (this->data->header.packet_id_h & 0b11100000) >> 5;
|
return (this->data->header.packet_id_h & 0b11100000) >> 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpacePacketBase::initSpacePacketHeader(bool isTelecommand, bool hasSecondaryHeader, uint16_t apid, uint16_t sequenceCount) {
|
void SpacePacketBase::initSpacePacketHeader(bool isTelecommand,
|
||||||
|
bool hasSecondaryHeader, uint16_t apid, uint16_t sequenceCount) {
|
||||||
//reset header to zero:
|
//reset header to zero:
|
||||||
memset(data,0, sizeof(this->data->header) );
|
memset(data,0, sizeof(this->data->header) );
|
||||||
//Set TC/TM bit.
|
//Set TC/TM bit.
|
||||||
@ -81,7 +82,7 @@ void SpacePacketBase::setPacketDataLength( uint16_t new_length) {
|
|||||||
this->data->header.packet_length_l = ( new_length & 0x00FF );
|
this->data->header.packet_length_l = ( new_length & 0x00FF );
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SpacePacketBase::getFullSize() {
|
size_t SpacePacketBase::getFullSize() {
|
||||||
//+1 is done because size in packet data length field is: size of data field -1
|
//+1 is done because size in packet data length field is: size of data field -1
|
||||||
return this->getPacketDataLength() + sizeof(this->data->header) + 1;
|
return this->getPacketDataLength() + sizeof(this->data->header) + 1;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#ifndef SPACEPACKETBASE_H_
|
#ifndef FSFW_TMTCPACKET_SPACEPACKETBASE_H_
|
||||||
#define SPACEPACKETBASE_H_
|
#define FSFW_TMTCPACKET_SPACEPACKETBASE_H_
|
||||||
|
|
||||||
#include "ccsds_header.h"
|
#include "ccsds_header.h"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \defgroup tmtcpackets Space Packets
|
* @defgroup tmtcpackets Space Packets
|
||||||
* This is the group, where all classes associated with Telecommand and
|
* This is the group, where all classes associated with Telecommand and
|
||||||
* Telemetry packets belong to.
|
* Telemetry packets belong to.
|
||||||
* The class hierarchy resembles the dependency between the different standards
|
* The class hierarchy resembles the dependency between the different standards
|
||||||
@ -81,7 +82,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool isTelecommand( void );
|
bool isTelecommand( void );
|
||||||
|
|
||||||
void initSpacePacketHeader(bool isTelecommand, bool hasSecondaryHeader, uint16_t apid, uint16_t sequenceCount = 0);
|
void initSpacePacketHeader(bool isTelecommand, bool hasSecondaryHeader,
|
||||||
|
uint16_t apid, uint16_t sequenceCount = 0);
|
||||||
/**
|
/**
|
||||||
* The CCSDS header provides a secondary header flag (the fifth-highest bit),
|
* The CCSDS header provides a secondary header flag (the fifth-highest bit),
|
||||||
* which is checked with this method.
|
* which is checked with this method.
|
||||||
@ -167,10 +169,10 @@ public:
|
|||||||
* This method returns the full raw packet size.
|
* This method returns the full raw packet size.
|
||||||
* @return The full size of the packet in bytes.
|
* @return The full size of the packet in bytes.
|
||||||
*/
|
*/
|
||||||
uint32_t getFullSize();
|
size_t getFullSize();
|
||||||
|
|
||||||
uint32_t getApidAndSequenceCount() const;
|
uint32_t getApidAndSequenceCount() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SPACEPACKETBASE_H_ */
|
#endif /* FSFW_TMTCPACKET_SPACEPACKETBASE_H_ */
|
||||||
|
@ -7,7 +7,8 @@ class TmPacketMinimal;
|
|||||||
class PacketTimestampInterpreterIF {
|
class PacketTimestampInterpreterIF {
|
||||||
public:
|
public:
|
||||||
virtual ~PacketTimestampInterpreterIF() {}
|
virtual ~PacketTimestampInterpreterIF() {}
|
||||||
virtual ReturnValue_t getPacketTime(TmPacketMinimal* packet, timeval* timestamp) const = 0;
|
virtual ReturnValue_t getPacketTime(TmPacketMinimal* packet,
|
||||||
|
timeval* timestamp) const = 0;
|
||||||
virtual ReturnValue_t getPacketTimeRaw(TmPacketMinimal* packet, const uint8_t** timePtr, uint32_t* size) const = 0;
|
virtual ReturnValue_t getPacketTimeRaw(TmPacketMinimal* packet, const uint8_t** timePtr, uint32_t* size) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
#include "../../globalfunctions/CRC.h"
|
|
||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include "TcPacketBase.h"
|
#include "TcPacketBase.h"
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
TcPacketBase::TcPacketBase(const uint8_t* set_data) :
|
#include "../../globalfunctions/CRC.h"
|
||||||
SpacePacketBase(set_data) {
|
#include "../../globalfunctions/arrayprinter.h"
|
||||||
tcData = (TcPacketPointer*) set_data;
|
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
TcPacketBase::TcPacketBase(const uint8_t* setData) :
|
||||||
|
SpacePacketBase(setData) {
|
||||||
|
tcData = reinterpret_cast<TcPacketPointer*>(const_cast<uint8_t*>(setData));
|
||||||
}
|
}
|
||||||
|
|
||||||
TcPacketBase::~TcPacketBase() {
|
TcPacketBase::~TcPacketBase() {
|
||||||
@ -13,28 +16,28 @@ TcPacketBase::~TcPacketBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TcPacketBase::getService() {
|
uint8_t TcPacketBase::getService() {
|
||||||
return tcData->data_field.service_type;
|
return tcData->dataField.service_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TcPacketBase::getSubService() {
|
uint8_t TcPacketBase::getSubService() {
|
||||||
return tcData->data_field.service_subtype;
|
return tcData->dataField.service_subtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TcPacketBase::getAcknowledgeFlags() {
|
uint8_t TcPacketBase::getAcknowledgeFlags() {
|
||||||
return tcData->data_field.version_type_ack & 0b00001111;
|
return tcData->dataField.version_type_ack & 0b00001111;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* TcPacketBase::getApplicationData() const {
|
const uint8_t* TcPacketBase::getApplicationData() const {
|
||||||
return &tcData->data;
|
return &tcData->appData;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t TcPacketBase::getApplicationDataSize() {
|
uint16_t TcPacketBase::getApplicationDataSize() {
|
||||||
return getPacketDataLength() - sizeof(tcData->data_field) - CRC_SIZE + 1;
|
return getPacketDataLength() - sizeof(tcData->dataField) - CRC_SIZE + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t TcPacketBase::getErrorControl() {
|
uint16_t TcPacketBase::getErrorControl() {
|
||||||
uint16_t size = getApplicationDataSize() + CRC_SIZE;
|
uint16_t size = getApplicationDataSize() + CRC_SIZE;
|
||||||
uint8_t* p_to_buffer = &tcData->data;
|
uint8_t* p_to_buffer = &tcData->appData;
|
||||||
return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1];
|
return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,41 +45,42 @@ void TcPacketBase::setErrorControl() {
|
|||||||
uint32_t full_size = getFullSize();
|
uint32_t full_size = getFullSize();
|
||||||
uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE);
|
uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE);
|
||||||
uint32_t size = getApplicationDataSize();
|
uint32_t size = getApplicationDataSize();
|
||||||
(&tcData->data)[size] = (crc & 0XFF00) >> 8; // CRCH
|
(&tcData->appData)[size] = (crc & 0XFF00) >> 8; // CRCH
|
||||||
(&tcData->data)[size + 1] = (crc) & 0X00FF; // CRCL
|
(&tcData->appData)[size + 1] = (crc) & 0X00FF; // CRCL
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcPacketBase::setData(const uint8_t* p_Data) {
|
void TcPacketBase::setData(const uint8_t* pData) {
|
||||||
SpacePacketBase::setData(p_Data);
|
SpacePacketBase::setData(pData);
|
||||||
tcData = (TcPacketPointer*) p_Data;
|
tcData = (TcPacketPointer*) pData;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TcPacketBase::getSecondaryHeaderFlag() {
|
uint8_t TcPacketBase::getSecondaryHeaderFlag() {
|
||||||
return (tcData->data_field.version_type_ack & 0b10000000) >> 7;
|
return (tcData->dataField.version_type_ack & 0b10000000) >> 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TcPacketBase::getPusVersionNumber() {
|
uint8_t TcPacketBase::getPusVersionNumber() {
|
||||||
return (tcData->data_field.version_type_ack & 0b01110000) >> 4;
|
return (tcData->dataField.version_type_ack & 0b01110000) >> 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcPacketBase::print() {
|
void TcPacketBase::print() {
|
||||||
uint8_t * wholeData = getWholeData();
|
sif::debug << "TcPacketBase::print: " << std::endl;
|
||||||
sif::debug << "TcPacket contains: " << std::endl;
|
arrayprinter::print(getWholeData(), getFullSize());
|
||||||
for (uint8_t count = 0; count < getFullSize(); ++count) {
|
|
||||||
sif::debug << std::hex << (uint16_t) wholeData[count] << " ";
|
|
||||||
}
|
|
||||||
sif::debug << std::dec << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcPacketBase::initializeTcPacket(uint16_t apid, uint16_t sequenceCount,
|
void TcPacketBase::initializeTcPacket(uint16_t apid, uint16_t sequenceCount,
|
||||||
uint8_t ack, uint8_t service, uint8_t subservice) {
|
uint8_t ack, uint8_t service, uint8_t subservice) {
|
||||||
initSpacePacketHeader(true, true, apid, sequenceCount);
|
initSpacePacketHeader(true, true, apid, sequenceCount);
|
||||||
memset(&tcData->data_field, 0, sizeof(tcData->data_field));
|
std::memset(&tcData->dataField, 0, sizeof(tcData->dataField));
|
||||||
setPacketDataLength(sizeof(tcData->data_field) + CRC_SIZE);
|
setPacketDataLength(sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1);
|
||||||
//Data Field Header:
|
//Data Field Header:
|
||||||
//Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000
|
//Set CCSDS_secondary_header_flag to 0 and version number to 001
|
||||||
tcData->data_field.version_type_ack = 0b00010000;
|
tcData->dataField.version_type_ack = 0b00010000;
|
||||||
tcData->data_field.version_type_ack |= (ack & 0x0F);
|
tcData->dataField.version_type_ack |= (ack & 0x0F);
|
||||||
tcData->data_field.service_type = service;
|
tcData->dataField.service_type = service;
|
||||||
tcData->data_field.service_subtype = subservice;
|
tcData->dataField.service_subtype = subservice;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t TcPacketBase::calculateFullPacketLength(size_t appDataLen) {
|
||||||
|
return sizeof(CCSDSPrimaryHeader) + sizeof(PUSTcDataFieldHeader) +
|
||||||
|
appDataLen + TcPacketBase::CRC_SIZE;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user