Merge branch 'mueller/master' of https://egit.irs.uni-stuttgart.de/KSat/fsfw into mueller/master

This commit is contained in:
Robin Müller 2020-12-15 14:41:07 +01:00
commit 3e41b202a1
179 changed files with 1344 additions and 1240 deletions

View File

@ -1,5 +1,8 @@
## Changes from ASTP 0.0.1 to 1.0.0
### Host OSAL
- Bugfix in MessageQueue, which caused the sender not to be set properly
### FreeRTOS OSAL
@ -11,3 +14,49 @@ a C file without issues
- It is now possible to change the message queue depth for the telecommand verification service (PUS1)
- The same is possible for the event reporting service (PUS5)
- PUS Health Service added, which allows to command and retrieve health via PUS packets
### EnhancedControllerBase
- New base class for a controller which also implements HasActionsIF and HasLocalDataPoolIF
### Local Pool
- Interface of LocalPools has changed. LocalPool is not a template anymore. Instead the size and bucket number of the pools per page and the number of pages are passed to the ctor instead of two ctor arguments and a template parameter
### Parameter Service
- The API of the parameter service has been changed to prevent inconsistencies
between documentation and actual code and to clarify usage.
- The parameter ID now consists of:
1. Domain ID (1 byte)
2. Unique Identifier (1 byte)
3. Linear Index (2 bytes)
The linear index can be used for arrays as well as matrices.
The parameter load command now explicitely expects the ECSS PTC and PFC
information as well as the rows and column number. Rows and column will
default to one, which is equivalent to one scalar parameter (the most
important use-case)
### File System Interface
- A new interfaces specifies the functions for a software object which exposes the file system of a given hardware to use message based file handling (e.g. PUS commanding)
### Internal Error Reporter
- The new internal error reporter uses the local data pools. The pool IDs for
the exisiting three error values and the new error set will be hardcoded for
now, the the constructor for the internal error reporter just takes an object
ID for now.
### Device Handler Base
- There is an additional `PERFORM_OPERATION` step for the device handler base. It is important
that DHB users adapt their polling sequence tables to perform this step. This steps allows for aclear distinction between operation and communication steps
### Events
- makeEvent function: Now takes three input parameters instead of two and
allows setting a unique ID. Event.cpp source file removed, functions now
defined in header directly. Namespaces renamed. Functions declared `constexpr`
now

85
CMakeLists.txt Normal file
View File

@ -0,0 +1,85 @@
cmake_minimum_required(VERSION 3.13)
set(LIB_FSFW_NAME fsfw)
add_library(${LIB_FSFW_NAME})
# Set options for FSFW OSAL selection.
if(UNIX)
set(OS_FSFW "linux" CACHE STRING "OS abstraction layer used in the FSFW")
elseif(WIN32)
set(OS_FSFW "host" CACHE STRING "OS abstraction layer used in the FSFW")
endif()
set_property(CACHE OS_FSFW PROPERTY STRINGS host linux rtems freertos)
if(${OS_FSFW} STREQUAL host)
set(OS_FSFW_NAME "Host")
elseif(${OS_FSFW} STREQUAL linux)
set(OS_FSFW_NAME "Linux")
elseif(${OS_FSFW} STREQUAL freertos)
set(OS_FSFW_NAME "FreeRTOS")
elseif(${OS_FSFW} STREQUAL rtems)
set(OS_FSFW_NAME "RTEMS")
else()
message(WARNING "Invalid operating system for FSFW specified! Setting to host..")
set(OS_FSFW_NAME "Host")
set(OS_FSFW "host")
endif()
message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system")
# Options to exclude parts of the FSFW from compilation.
option(FSFW_USE_RMAP "Compile with RMAP" ON)
option(FSFW_USE_DATALINKLAYER "Compile with Data Link Layer" ON)
add_subdirectory(action)
add_subdirectory(container)
add_subdirectory(controller)
add_subdirectory(coordinates)
add_subdirectory(datalinklayer)
add_subdirectory(datapool)
add_subdirectory(devicehandlers)
add_subdirectory(events)
add_subdirectory(fdir)
add_subdirectory(globalfunctions)
add_subdirectory(health)
add_subdirectory(internalError)
add_subdirectory(ipc)
add_subdirectory(memory)
add_subdirectory(modes)
add_subdirectory(monitoring)
add_subdirectory(objectmanager)
add_subdirectory(osal)
add_subdirectory(parameters)
add_subdirectory(power)
add_subdirectory(pus)
if(FSFW_USE_RMAP)
add_subdirectory(rmap)
endif()
add_subdirectory(serialize)
add_subdirectory(serviceinterface)
add_subdirectory(storagemanager)
add_subdirectory(subsystem)
add_subdirectory(tasks)
add_subdirectory(tcdistribution)
add_subdirectory(thermal)
add_subdirectory(timemanager)
add_subdirectory(tmstorage)
add_subdirectory(tmtcpacket)
add_subdirectory(tmtcservices)
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it.
# If this is not given, we include the default configuration and emit a warning.
if(NOT FSFW_CONFIG_PATH)
message(WARNING "Flight Software Framework configuration path not set!")
message(WARNING "Setting default configuration!")
add_subdirectory(defaultcfg/fsfwconfig)
endif()
# Required include paths to compile the FSFW
target_include_directories(${LIB_FSFW_NAME}
INTERFACE
${FSFW_CONFIG_PATH}
)

View File

@ -1,10 +1,11 @@
#ifndef FSFW_DEFAULTCFG_VERSION_H_
#define FSFW_DEFAULTCFG_VERSION_H_
const char* const FSFW_VERSION_NAME = "fsfw";
const char* const FSFW_VERSION_NAME = "ASTP";
#define FSFW_VERSION 0
#define FSFW_SUBVERSION 0
#define FSFW_REVISION 1

2
NOTICE
View File

@ -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
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.
No copyright assignment is required to contribute to the Flight Software Framework.

View File

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

View File

@ -8,7 +8,7 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth) :
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
submode(SUBMODE_NONE), modeHelper(this),
healthHelper(this, setObjectId), hkSwitcher(this) {
healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth);
}
@ -44,10 +44,6 @@ ReturnValue_t ControllerBase::initialize() {
return result;
}
result = hkSwitcher.initialize();
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
@ -107,7 +103,6 @@ void ControllerBase::announceMode(bool recursive) {
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
handleQueue();
hkSwitcher.performOperation();
performControlOperation();
return RETURN_OK;
}

View File

@ -72,9 +72,6 @@ protected:
HealthHelper healthHelper;
// Is this still needed?
HkSwitchHelper hkSwitcher;
/**
* Pointer to the task which executes this component,
* is invalid before setTaskIF was called.

View File

@ -97,7 +97,6 @@ ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
handleQueue();
hkSwitcher.performOperation();
localPoolManager.performHkOperation();
performControlOperation();
return RETURN_OK;

View File

@ -19,12 +19,12 @@ class VirtualChannelReception;
class DataLinkLayer : public CCSDSReturnValuesIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_1;
static const Event RF_AVAILABLE = MAKE_EVENT(0, SEVERITY::INFO); //!< A RF available signal was detected. P1: raw RFA state, P2: 0
static const Event RF_LOST = MAKE_EVENT(1, SEVERITY::INFO); //!< A previously found RF available signal was lost. P1: raw RFA state, P2: 0
static const Event BIT_LOCK = MAKE_EVENT(2, SEVERITY::INFO); //!< A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0
static const Event BIT_LOCK_LOST = MAKE_EVENT(3, SEVERITY::INFO); //!< A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0
// static const Event RF_CHAIN_LOST = MAKE_EVENT(4, SEVERITY::INFO); //!< The CCSDS Board detected that either bit lock or RF available or both are lost. No parameters.
static const Event FRAME_PROCESSING_FAILED = MAKE_EVENT(5, SEVERITY::LOW); //!< The CCSDS Board could not interpret a TC
static const Event RF_AVAILABLE = MAKE_EVENT(0, severity::INFO); //!< A RF available signal was detected. P1: raw RFA state, P2: 0
static const Event RF_LOST = MAKE_EVENT(1, severity::INFO); //!< A previously found RF available signal was lost. P1: raw RFA state, P2: 0
static const Event BIT_LOCK = MAKE_EVENT(2, severity::INFO); //!< A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0
static const Event BIT_LOCK_LOST = MAKE_EVENT(3, severity::INFO); //!< A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0
// static const Event RF_CHAIN_LOST = MAKE_EVENT(4, severity::INFO); //!< The CCSDS Board detected that either bit lock or RF available or both are lost. No parameters.
static const Event FRAME_PROCESSING_FAILED = MAKE_EVENT(5, severity::LOW); //!< The CCSDS Board could not interpret a TC
/**
* The Constructor sets the passed parameters and nothing else.
* @param set_frame_buffer The buffer in which incoming frame candidates are stored.

View File

@ -9,9 +9,9 @@
MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
object_id_t setPacketDestination) :
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0),
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId),
bufferPosition(packetBuffer), packetDestination(setPacketDestination),
packetStore(NULL), tcQueueId(MessageQueueIF::NO_QUEUE) {
tcQueueId(MessageQueueIF::NO_QUEUE) {
std::memset(packetBuffer, 0, sizeof(packetBuffer));
}

View File

@ -1,5 +1,5 @@
#ifndef MAPPACKETEXTRACTION_H_
#define MAPPACKETEXTRACTION_H_
#ifndef FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_
#define FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_
#include "MapPacketExtractionIF.h"
#include "../objectmanager/ObjectManagerIF.h"
@ -20,11 +20,12 @@ private:
static const uint32_t MAX_PACKET_SIZE = 4096;
uint8_t lastSegmentationFlag; //!< The segmentation flag of the last received frame.
uint8_t mapId; //!< MAP ID of this MAP Channel.
uint32_t packetLength; //!< Complete length of the current Space Packet.
uint32_t packetLength = 0; //!< Complete length of the current Space Packet.
uint8_t* bufferPosition; //!< Position to write to in the internal Packet buffer.
uint8_t packetBuffer[MAX_PACKET_SIZE]; //!< The internal Space Packet Buffer.
object_id_t packetDestination;
StorageManagerIF* packetStore; //!< Pointer to the store where full TC packets are stored.
//!< Pointer to the store where full TC packets are stored.
StorageManagerIF* packetStore = nullptr;
MessageQueueId_t tcQueueId; //!< QueueId to send found packets to the distributor.
/**
* Debug method to print the packet Buffer's content.
@ -69,4 +70,4 @@ public:
uint8_t getMapId() const;
};
#endif /* MAPPACKETEXTRACTION_H_ */
#endif /* FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_ */

View File

@ -13,7 +13,7 @@ class HkSwitchHelper: public ExecutableObjectIF, public CommandsActionsIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HK;
static const Event SWITCHING_TM_FAILED = MAKE_EVENT(1, SEVERITY::LOW); //!< Commanding the HK Service failed, p1: error code, p2 action: 0 disable / 1 enable
static const Event SWITCHING_TM_FAILED = MAKE_EVENT(1, severity::LOW); //!< Commanding the HK Service failed, p1: error code, p2 action: 0 disable / 1 enable
HkSwitchHelper(EventReportingProxyIF *eventProxy);
virtual ~HkSwitchHelper();

View File

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

View File

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

View File

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

View File

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

View File

@ -113,7 +113,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
doGetRead();
// This will be performed after datasets have been updated by the
// custom device implementation.
hkManager.performHkOperation();
hkManager.performHkOperation();
break;
default:
break;
@ -693,7 +693,7 @@ void DeviceHandlerBase::doGetRead() {
void DeviceHandlerBase::parseReply(const uint8_t* receivedData,
size_t receivedDataLen) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
DeviceCommandId_t foundId = 0xffffffff;
DeviceCommandId_t foundId = DeviceHandlerIF::NO_COMMAND;
size_t foundLen = 0;
// The loop may not execute more often than the number of received bytes
// (worst case). This approach avoids infinite loops due to buggy
@ -1453,3 +1453,9 @@ dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const {
return pstIntervalMs;
}
DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
if(cookieInfo.pendingCommand != deviceCommandMap.end()) {
return cookieInfo.pendingCommand->first;
}
return DeviceHandlerIF::NO_COMMAND;
}

View File

@ -234,7 +234,7 @@ protected:
* - If the device does not change the mode, the mode will be changed to
* _MODE_POWER_DOWN, when the timeout (from getTransitionDelay())
* has passed.
* 0xffffffff
*
* #transitionFailure can be set to a failure code indicating the reason
* for a failed transition
*/
@ -734,15 +734,27 @@ protected:
//! before setTaskIF was called.
PeriodicTaskIF* executingTask = nullptr;
static object_id_t powerSwitcherId; //!< Object which switches power on and off.
//!< Object which switches power on and off.
static object_id_t powerSwitcherId;
static object_id_t rawDataReceiverId; //!< Object which receives RAW data by default.
//!< Object which receives RAW data by default.
static object_id_t rawDataReceiverId;
//!< Object which may be the root cause of an identified fault.
static object_id_t defaultFdirParentId;
/**
* Helper function to get pending command. This is useful for devices
* like SPI sensors to identify the last sent command.
* @return
*/
DeviceCommandId_t getPendingCommand() const;
static object_id_t defaultFdirParentId; //!< Object which may be the root cause of an identified fault.
/**
* Helper function to report a missed reply
*
* Can be overwritten by children to act on missed replies or to fake reporting Id.
* Can be overwritten by children to act on missed replies or to fake
* reporting Id.
*
* @param id of the missed reply
*/
@ -849,15 +861,18 @@ protected:
/**
* Build the device command to send for raw mode.
*
* This is only called in @c MODE_RAW. It is for the rare case that in raw mode packets
* are to be sent by the handler itself. It is NOT needed for the raw commanding service.
* Its only current use is in the STR handler which gets its raw packets from a different
* source.
* Also it can be used for transitional commands, to get the device ready for @c MODE_RAW
* This is only called in @c MODE_RAW. It is for the rare case that in
* raw mode packets are to be sent by the handler itself. It is NOT needed
* for the raw commanding service. Its only current use is in the STR
* handler which gets its raw packets from a different source.
* Also it can be used for transitional commands, to get the device ready
* for @c MODE_RAW
*
* As it is almost never used, there is a default implementation returning @c NOTHING_TO_SEND.
* As it is almost never used, there is a default implementation
* returning @c NOTHING_TO_SEND.
*
* #rawPacket and #rawPacketLen must be set by this method to the packet to be sent.
* #rawPacket and #rawPacketLen must be set by this method to the packet
* to be sent.
*
* @param[out] id the device command id built
* @return
@ -870,7 +885,9 @@ protected:
* Returns the delay cycle count of a reply.
* A count != 0 indicates that the command is already executed.
* @param deviceCommand The command to look for
* @return The current delay count. If the command does not exist (should never happen) it returns 0.
* @return
* The current delay count. If the command does not exist (should never
* happen) it returns 0.
*/
uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand);
@ -880,20 +897,22 @@ protected:
* It gets space in the #IPCStore, copies data there, then sends a raw reply
* containing the store address.
*
* This method is virtual, as the STR has a different channel to send raw replies
* and overwrites it accordingly.
* This method is virtual, as the STR has a different channel to send
* raw replies and overwrites it accordingly.
*
* @param data data to send
* @param len length of @c data
* @param sendTo the messageQueueId of the one to send to
* @param isCommand marks the raw data as a command, the message then will be of type raw_command
* @param isCommand marks the raw data as a command, the message then
* will be of type raw_command
*/
virtual void replyRawData(const uint8_t *data, size_t len,
MessageQueueId_t sendTo, bool isCommand = false);
/**
* Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping is active and if so,
* does not send the Data as the wiretapping will have sent it already
* Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping
* is active and if so, does not send the data as the wiretapping will have
* sent it already
*/
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
@ -905,17 +924,19 @@ protected:
/**
* Enable the reply checking for a command
*
* Is only called, if the command was sent (ie the getWriteReply was successful).
* Must ensure that all replies are activated and correctly linked to the command that initiated it.
* The default implementation looks for a reply with the same id as the command id in the replyMap or
* uses the alternativeReplyId if flagged so.
* When found, copies maxDelayCycles to delayCycles in the reply information and sets the command to
* expect one reply.
* Is only called, if the command was sent (i.e. the getWriteReply was
* successful). Must ensure that all replies are activated and correctly
* linked to the command that initiated it.
* The default implementation looks for a reply with the same id as the
* command id in the replyMap or uses the alternativeReplyId if flagged so.
* When found, copies maxDelayCycles to delayCycles in the reply information
* and sets the command to expect one reply.
*
* Can be overwritten by the child, if a command activates multiple replies
* or replyId differs from commandId.
* Notes for child implementations:
* - If the command was not found in the reply map, NO_REPLY_EXPECTED MUST be returned.
* - If the command was not found in the reply map,
* NO_REPLY_EXPECTED MUST be returned.
* - A failure code may be returned if something went fundamentally wrong.
*
* @param deviceCommand
@ -931,17 +952,20 @@ protected:
* get the state of the PCDU switches in the datapool
*
* @return
* - @c PowerSwitchIF::SWITCH_ON if all switches specified by #switches are on
* - @c PowerSwitchIF::SWITCH_OFF one of the switches specified by #switches are off
* - @c PowerSwitchIF::RETURN_FAILED if an error occured
* - @c PowerSwitchIF::SWITCH_ON if all switches specified
* by #switches are on
* - @c PowerSwitchIF::SWITCH_OFF one of the switches specified by
* #switches are off
* - @c PowerSwitchIF::RETURN_FAILED if an error occured
*/
ReturnValue_t getStateOfSwitches(void);
/**
* set all datapool variables that are update periodically in normal mode invalid
*
* Child classes should provide an implementation which sets all those variables invalid
* which are set periodically during any normal mode.
* @brief Set all datapool variables that are update periodically in
* normal mode invalid
* @details TODO: Use local pools
* Child classes should provide an implementation which sets all those
* variables invalid which are set periodically during any normal mode.
*/
virtual void setNormalDatapoolEntriesInvalid() = 0;
@ -951,11 +975,12 @@ protected:
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
/**
* Children can overwrite this function to suppress checking of the command Queue
* Children can overwrite this function to suppress checking of the
* command Queue
*
* This can be used when the child does not want to receive a command in a certain
* situation. Care must be taken that checking is not permanentely disabled as this
* would render the handler unusable.
* This can be used when the child does not want to receive a command in
* a certain situation. Care must be taken that checking is not
* permanentely disabled as this would render the handler unusable.
*
* @return whether checking the queue should NOT be done
*/
@ -994,17 +1019,20 @@ protected:
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) const;
/**
* Checks state of switches in conjunction with mode and triggers an event if they don't fit.
* Checks state of switches in conjunction with mode and triggers an event
* if they don't fit.
*/
virtual void checkSwitchState();
/**
* Reserved for the rare case where a device needs to perform additional operation cyclically in OFF mode.
* Reserved for the rare case where a device needs to perform additional
* operation cyclically in OFF mode.
*/
virtual void doOffActivity();
/**
* Reserved for the rare case where a device needs to perform additional operation cyclically in ON mode.
* Reserved for the rare case where a device needs to perform additional
* operation cyclically in ON mode.
*/
virtual void doOnActivity();
@ -1045,9 +1073,10 @@ private:
/**
* Information about a cookie.
*
* This is stored in a map for each cookie, to not only track the state, but also information
* about the sent command. Tracking this information is needed as
* the state of a commandId (waiting for reply) is done when a RMAP write reply is received.
* This is stored in a map for each cookie, to not only track the state,
* but also information about the sent command. Tracking this information
* is needed as the state of a commandId (waiting for reply) is done when a
* write reply is received.
*/
struct CookieInfo {
CookieState_t state;
@ -1104,10 +1133,14 @@ private:
/**
* Handle the device handler mode.
*
* - checks whether commands are valid for the current mode, rejects them accordingly
* - checks whether commanded mode transitions are required and calls handleCommandedModeTransition()
* - does the necessary action for the current mode or calls doChildStateMachine in modes @c MODE_TO_ON and @c MODE_TO_OFF
* - actions that happen in transitions (eg setting a timeout) are handled in setMode()
* - checks whether commands are valid for the current mode, rejects
* them accordingly
* - checks whether commanded mode transitions are required and calls
* handleCommandedModeTransition()
* - does the necessary action for the current mode or calls
* doChildStateMachine in modes @c MODE_TO_ON and @c MODE_TO_OFF
* - actions that happen in transitions (e.g. setting a timeout) are
* handled in setMode()
*/
void doStateMachine(void);
@ -1117,16 +1150,17 @@ private:
/**
* Decrement the counter for the timout of replies.
*
* This is called at the beginning of each cycle. It checks whether a reply has timed out (that means a reply was expected
* but not received).
* This is called at the beginning of each cycle. It checks whether a
* reply has timed out (that means a reply was expected but not received).
*/
void decrementDeviceReplyMap(void);
/**
* Convenience function to handle a reply.
*
* Called after scanForReply() has found a packet. Checks if the found id is in the #deviceCommandMap, if so,
* calls interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) for further action.
* Called after scanForReply() has found a packet. Checks if the found ID
* is in the #deviceCommandMap, if so, calls
* #interpretDeviceReply for further action.
*
* It also resets the timeout counter for the command id.
*
@ -1186,7 +1220,7 @@ private:
* @param[out] len
* @return
* - @c RETURN_OK @c data is valid
* - @c RETURN_FAILED IPCStore is NULL
* - @c RETURN_FAILED IPCStore is nullptr
* - the return value from the IPCStore if it was not @c RETURN_OK
*/
ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data,

View File

@ -191,7 +191,7 @@ void DeviceHandlerFailureIsolation::triggerEvent(Event event, uint32_t parameter
uint32_t parameter2) {
//Do not throw error events if fdirState != none.
//This will still forward MODE and HEALTH INFO events in any case.
if (fdirState == NONE || EVENT::getSeverity(event) == SEVERITY::INFO) {
if (fdirState == NONE || event::getSeverity(event) == severity::INFO) {
FailureIsolationBase::triggerEvent(event, parameter1, parameter2);
}
}
@ -201,7 +201,7 @@ bool DeviceHandlerFailureIsolation::isFdirActionInProgress() {
}
void DeviceHandlerFailureIsolation::startRecovery(Event reason) {
throwFdirEvent(FDIR_STARTS_RECOVERY, EVENT::getEventId(reason));
throwFdirEvent(FDIR_STARTS_RECOVERY, event::getEventId(reason));
setOwnerHealth(HasHealthIF::NEEDS_RECOVERY);
setFdirState(RECOVERY_ONGOING);
}
@ -228,7 +228,7 @@ ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
}
void DeviceHandlerFailureIsolation::setFaulty(Event reason) {
throwFdirEvent(FDIR_TURNS_OFF_DEVICE, EVENT::getEventId(reason));
throwFdirEvent(FDIR_TURNS_OFF_DEVICE, event::getEventId(reason));
setOwnerHealth(HasHealthIF::FAULTY);
setFdirState(AWAIT_SHUTDOWN);
}

View File

@ -95,17 +95,17 @@ public:
static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH;
static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, SEVERITY::LOW);
static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, SEVERITY::LOW);
static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, SEVERITY::LOW);
static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, SEVERITY::LOW);
static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, SEVERITY::LOW);
static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, SEVERITY::LOW);
static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, SEVERITY::LOW);
static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, SEVERITY::LOW);
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, SEVERITY::LOW); //!< Indicates a SW bug in child class.
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, SEVERITY::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH);
static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, severity::LOW);
static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, severity::LOW);
static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, severity::LOW);
static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, severity::LOW);
static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, severity::LOW);
static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, severity::LOW);
static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, severity::LOW);
static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, severity::LOW);
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW); //!< Indicates a SW bug in child class.
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;

8
events/CMakeLists.txt Normal file
View File

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

View File

@ -1,16 +0,0 @@
#include "Event.h"
namespace EVENT {
EventId_t getEventId(Event event) {
return (event & 0xFFFF);
}
EventSeverity_t getSeverity(Event event) {
return ((event >> 16) & 0xFF);
}
Event makeEvent(uint8_t subsystemId, uint8_t uniqueEventId,
EventSeverity_t eventSeverity) {
return (eventSeverity << 16) + (subsystemId * 100) + uniqueEventId;
}
}

View File

@ -3,7 +3,7 @@
#include <stdint.h>
#include "fwSubsystemIdRanges.h"
//could be move to more suitable location
// could be moved to more suitable location
#include <events/subsystemIdRanges.h>
typedef uint16_t EventId_t;
@ -13,33 +13,28 @@ typedef uint8_t EventSeverity_t;
typedef uint32_t Event;
namespace EVENT {
EventId_t getEventId(Event event);
namespace event {
EventSeverity_t getSeverity(Event event);
Event makeEvent(uint8_t subsystemId, uint8_t uniqueEventId,
EventSeverity_t eventSeverity);
constexpr EventId_t getEventId(Event event) {
return (event & 0xFFFF);
}
namespace SEVERITY {
static const EventSeverity_t INFO = 1;
static const EventSeverity_t LOW = 2;
static const EventSeverity_t MEDIUM = 3;
static const EventSeverity_t HIGH = 4;
constexpr EventSeverity_t getSeverity(Event event) {
return ((event >> 16) & 0xFF);
}
//Unfortunately, this does not work nicely because of the inability to define static classes in headers.
//struct Event {
// Event(uint8_t domain, uint8_t counter, EventSeverity_t severity) :
// id(domain*100+counter), severity(severity) {
// }
// EventId_t id;
// EventSeverity_t severity;
// static const EventSeverity_t INFO = 1;
// static const EventSeverity_t LOW = 2;
// static const EventSeverity_t MEDIUM = 3;
// static const EventSeverity_t HIGH = 4;
//};
constexpr Event makeEvent(uint8_t subsystemId, uint8_t uniqueEventId,
EventSeverity_t eventSeverity) {
return (eventSeverity << 16) + (subsystemId * 100) + uniqueEventId;
}
}
namespace severity {
static constexpr EventSeverity_t INFO = 1;
static constexpr EventSeverity_t LOW = 2;
static constexpr EventSeverity_t MEDIUM = 3;
static constexpr EventSeverity_t HIGH = 4;
}
#endif /* EVENTOBJECT_EVENT_H_ */

View File

@ -1,4 +1,6 @@
#include "EventManager.h"
#include "EventMessage.h"
#include <FSFWConfig.h>
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../ipc/QueueFactory.h"
@ -9,7 +11,6 @@
// objects registering for certain events.
// Each listener requires 1 or 2 EventIdMatcher and 1 or 2 ReportRangeMatcher.
// So a good guess is 75 to a max of 100 pools required for each, which fits well.
// This should be configurable..
const LocalPool::LocalPoolConfig EventManager::poolConfig = {
{fsfwconfig::FSFW_EVENTMGMR_MATCHTREE_NODES,
sizeof(EventMatchTree::Node)},
@ -113,12 +114,12 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener,
return result;
}
#if FSFW_DEBUG_OUTPUT == 1
#if FSFW_OBJ_EVENT_TRANSLATION == 1
void EventManager::printEvent(EventMessage* message) {
const char *string = 0;
switch (message->getSeverity()) {
case SEVERITY::INFO:
case severity::INFO:
#if DEBUG_INFO_EVENT == 1
string = translateObject(message->getReporter());
sif::info << "EVENT: ";

View File

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

View File

@ -48,7 +48,7 @@ void EventMessage::setMessageId(uint8_t id) {
EventSeverity_t EventMessage::getSeverity() {
Event event;
memcpy(&event, getData(), sizeof(Event));
return EVENT::getSeverity(event);
return event::getSeverity(event);
}
void EventMessage::setSeverity(EventSeverity_t severity) {
@ -61,7 +61,7 @@ void EventMessage::setSeverity(EventSeverity_t severity) {
EventId_t EventMessage::getEventId() {
Event event;
memcpy(&event, getData(), sizeof(Event));
return EVENT::getEventId(event);
return event::getEventId(event);
}
void EventMessage::setEventId(EventId_t eventId) {

View File

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

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_
#define FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_
#ifndef FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_
#define FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_
namespace SUBSYSTEM_ID {
enum {
@ -27,4 +27,4 @@ enum {
#endif /* FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ */
#endif /* FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_ */

View File

@ -139,7 +139,7 @@ void FailureIsolationBase::triggerEvent(Event event, uint32_t parameter1,
uint32_t parameter2) {
//With this mechanism, all events are disabled for a certain device.
//That's not so good for visibility.
if (isFdirDisabledForSeverity(EVENT::getSeverity(event))) {
if (isFdirDisabledForSeverity(event::getSeverity(event))) {
return;
}
EventMessage message(event, ownerId, parameter1, parameter2);
@ -148,7 +148,7 @@ void FailureIsolationBase::triggerEvent(Event event, uint32_t parameter1,
}
bool FailureIsolationBase::isFdirDisabledForSeverity(EventSeverity_t severity) {
if ((owner != NULL) && (severity != SEVERITY::INFO)) {
if ((owner != NULL) && (severity != severity::INFO)) {
if (owner->getHealth() == HasHealthIF::EXTERNAL_CONTROL) {
//External control disables handling of fault messages.
return true;

View File

@ -14,9 +14,9 @@ class FailureIsolationBase: public HasReturnvaluesIF,
public HasParametersIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, SEVERITY::INFO); //!< FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, SEVERITY::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery.
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, SEVERITY::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery.
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, severity::INFO); //!< FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, severity::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery.
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, severity::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery.
FailureIsolationBase(object_id_t owner,
object_id_t parent = objects::NO_OBJECT,

View File

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

View File

@ -1,4 +1,4 @@
#include "../globalfunctions/Type.h"
#include "Type.h"
#include "../serialize/SerializeAdapter.h"
Type::Type() :

View File

@ -1,5 +1,5 @@
#ifndef TYPE_H_
#define TYPE_H_
#ifndef FSFW_GLOBALFUNCTIONS_TYPE_H_
#define FSFW_GLOBALFUNCTIONS_TYPE_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeIF.h"
@ -97,4 +97,4 @@ struct PodTypeConversion<double> {
static const Type::ActualType_t type = Type::DOUBLE;
};
#endif /* TYPE_H_ */
#endif /* FSFW_GLOBALFUNCTIONS_TYPE_H_ */

View File

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

View File

@ -21,13 +21,13 @@ public:
static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1;
static const Event HEALTH_INFO = MAKE_EVENT(6, SEVERITY::INFO);
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, SEVERITY::INFO);
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, SEVERITY::LOW);
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, SEVERITY::LOW); //!< Assembly overwrites health information of children to keep satellite alive.
static const Event TRYING_RECOVERY = MAKE_EVENT(10, SEVERITY::MEDIUM); //!< Someone starts a recovery of a component (typically power-cycle). No parameters.
static const Event RECOVERY_STEP = MAKE_EVENT(11, SEVERITY::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1: 0 for the first, 1 for the second event. P2: 0
static const Event RECOVERY_DONE = MAKE_EVENT(12, SEVERITY::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW); //!< Assembly overwrites health information of children to keep satellite alive.
static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM); //!< Someone starts a recovery of a component (typically power-cycle). No parameters.
static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1: 0 for the first, 1 for the second event. P2: 0
static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
virtual ~HasHealthIF() {
}

View File

@ -2,6 +2,7 @@
#define FSFW_IPC_COMMANDMESSAGE_H_
#include "CommandMessageIF.h"
#include "MessageQueueMessage.h"
#include "FwMessageTypes.h"

View File

@ -1,8 +1,8 @@
#ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#define FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#include "../ipc/MessageQueueIF.h"
#include "../ipc/MessageQueueMessageIF.h"
#include "MessageQueueIF.h"
#include "MessageQueueMessageIF.h"
#include "../objectmanager/ObjectManagerIF.h"
class MessageQueueSenderIF {

View File

@ -1,7 +1,7 @@
#ifndef FRAMEWORK_IPC_MUTEXFACTORY_H_
#define FRAMEWORK_IPC_MUTEXFACTORY_H_
#ifndef FSFW_IPC_MUTEXFACTORY_H_
#define FSFW_IPC_MUTEXFACTORY_H_
#include "../ipc/MutexIF.h"
#include "MutexIF.h"
/**
* Creates Mutex.
* This class is a "singleton" interface, i.e. it provides an
@ -31,4 +31,4 @@ private:
#endif /* FRAMEWORK_IPC_MUTEXFACTORY_H_ */
#endif /* FSFW_IPC_MUTEXFACTORY_H_ */

View File

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

View File

@ -1,22 +0,0 @@
#ifndef FRAMEWORK_MEMORY_MEMORYPROXYIF_H_
#define FRAMEWORK_MEMORY_MEMORYPROXYIF_H_
#include "../memory/AcceptsMemoryMessagesIF.h"
/**
* This was a nice idea to transparently forward incoming messages to another object.
* But it doesn't work like that.
*/
class MemoryProxyIF : public AcceptsMemoryMessagesIF {
public:
virtual MessageQueueId_t getProxyQueue() const = 0;
MessageQueueId_t getCommandQueue() const {
return getProxyQueue();
}
virtual ~MemoryProxyIF() {}
};
#endif /* FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ */

View File

@ -18,14 +18,14 @@ public:
static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER;
static const Event CHANGING_MODE = MAKE_EVENT(0, SEVERITY::INFO); //!< An object announces changing the mode. p1: target mode. p2: target submode
static const Event MODE_INFO = MAKE_EVENT(1, SEVERITY::INFO); //!< An Object announces its mode; parameter1 is mode, parameter2 is submode
static const Event FALLBACK_FAILED = MAKE_EVENT(2, SEVERITY::HIGH);
static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, SEVERITY::LOW);
static const Event CANT_KEEP_MODE = MAKE_EVENT(4, SEVERITY::HIGH);
static const Event OBJECT_IN_INVALID_MODE = MAKE_EVENT(5, SEVERITY::LOW); //!< Indicates a bug or configuration failure: Object is in a mode it should never be in.
static const Event FORCING_MODE = MAKE_EVENT(6, SEVERITY::MEDIUM); //!< The mode is changed, but for some reason, the change is forced, i.e. EXTERNAL_CONTROL ignored. p1: target mode. p2: target submode
static const Event MODE_CMD_REJECTED = MAKE_EVENT(7, SEVERITY::LOW); //!< A mode command was rejected by the called object. Par1: called object id, Par2: return code.
static const Event CHANGING_MODE = MAKE_EVENT(0, severity::INFO); //!< An object announces changing the mode. p1: target mode. p2: target submode
static const Event MODE_INFO = MAKE_EVENT(1, severity::INFO); //!< An Object announces its mode; parameter1 is mode, parameter2 is submode
static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH);
static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, severity::LOW);
static const Event CANT_KEEP_MODE = MAKE_EVENT(4, severity::HIGH);
static const Event OBJECT_IN_INVALID_MODE = MAKE_EVENT(5, severity::LOW); //!< Indicates a bug or configuration failure: Object is in a mode it should never be in.
static const Event FORCING_MODE = MAKE_EVENT(6, severity::MEDIUM); //!< The mode is changed, but for some reason, the change is forced, i.e. EXTERNAL_CONTROL ignored. p1: target mode. p2: target submode
static const Event MODE_CMD_REJECTED = MAKE_EVENT(7, severity::LOW); //!< A mode command was rejected by the called object. Par1: called object id, Par2: return code.
static const Mode_t MODE_ON = 1; //!< The device is powered and ready to perform operations. In this mode, no commands are sent by the device handler itself, but direct commands van be commanded and will be interpreted
static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in this mode is a mode change to on.

View File

@ -72,7 +72,7 @@ protected:
return HasReturnvaluesIF::RETURN_OK;
}
LocalPoolVar<T> poolVariable;
LocalPoolVariable<T> poolVariable;
};
#endif /* FSFW_MONITORING_MONITORBASE_H_ */

View File

@ -15,10 +15,10 @@ public:
static const uint8_t LIMIT_TYPE_OBJECT = 128;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_2;
static const Event MONITOR_CHANGED_STATE = MAKE_EVENT(1, SEVERITY::LOW);
static const Event VALUE_BELOW_LOW_LIMIT = MAKE_EVENT(2, SEVERITY::LOW);
static const Event VALUE_ABOVE_HIGH_LIMIT = MAKE_EVENT(3, SEVERITY::LOW);
static const Event VALUE_OUT_OF_RANGE = MAKE_EVENT(4, SEVERITY::LOW);
static const Event MONITOR_CHANGED_STATE = MAKE_EVENT(1, severity::LOW);
static const Event VALUE_BELOW_LOW_LIMIT = MAKE_EVENT(2, severity::LOW);
static const Event VALUE_ABOVE_HIGH_LIMIT = MAKE_EVENT(3, severity::LOW);
static const Event VALUE_OUT_OF_RANGE = MAKE_EVENT(4, severity::LOW);
static const uint8_t INTERFACE_ID = CLASS_ID::LIMITS_IF;
static const ReturnValue_t UNCHECKED = MAKE_RETURN_CODE(1);

View File

@ -2,6 +2,9 @@
#include "TaskManagement.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#if (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8
BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() {
handle = TaskManagement::getCurrentTaskHandle();
if(handle == nullptr) {
@ -97,3 +100,6 @@ uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR(
higherPriorityTaskWoken);
return notificationValue;
}
#endif /* (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8 */

View File

@ -7,8 +7,8 @@
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
// todo: does not work for older FreeRTOS version, so we should
// actually check whether tskKERNEL_VERSION_MAJOR is larger than.. 7 or 8 ?
#if (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8
/**
* @brief Binary Semaphore implementation using the task notification value.
@ -90,4 +90,7 @@ protected:
TaskHandle_t handle;
};
#endif /* (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8 */
#endif /* FSFW_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */

View File

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

View File

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

View File

@ -1,6 +1,7 @@
#include "Timekeeper.h"
#include "../../timemanager/Clock.h"
#include "../../globalfunctions/timevalOperations.h"
#include "../../osal/FreeRTOS/Timekeeper.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

View File

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

View File

@ -1,13 +1,14 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#ifndef FSFW_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#define FSFW_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h"
#include "CountingSemaphUsingTask.h"
#include "../../tasks/SemaphoreIF.h"
extern "C" {
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
}
#if (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8
/**
* @brief Couting Semaphore implementation which uses the notification value
@ -102,4 +103,7 @@ private:
const uint8_t maxCount;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */
#endif /* (tskKERNEL_VERSION_MAJOR == 8 && tskKERNEL_VERSION_MINOR > 2) || \
tskKERNEL_VERSION_MAJOR > 8 */
#endif /* FSFW_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
#include "../../osal/FreeRTOS/Mutex.h"
#include "Mutex.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"

View File

@ -1,5 +1,7 @@
#include "Mutex.h"
#include "../../ipc/MutexFactory.h"
#include "../../osal/FreeRTOS/Mutex.h"
//TODO: Different variant than the lazy loading in QueueFactory.
//What's better and why? -> one is on heap the other on bss/data

View File

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

View File

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

View File

@ -1,8 +1,8 @@
#include "MessageQueue.h"
#include "../../ipc/MessageQueueSenderIF.h"
#include "../../ipc/QueueFactory.h"
#include "../../osal/FreeRTOS/MessageQueue.h"
QueueFactory* QueueFactory::factoryInstance = nullptr;

View File

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

View File

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

View File

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

View File

@ -106,11 +106,6 @@ ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t Clock::getUptimeSeconds() {
timeval uptime = getUptime();
return uptime.tv_sec;
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
// do some magic with chrono (C++20!)

View File

@ -1,7 +1,9 @@
#include "FixedTimeslotTask.h"
#include "Mutex.h"
#include "../../osal/host/FixedTimeslotTask.h"
#include "../../ipc/MutexFactory.h"
#include "../../osal/host/Mutex.h"
#include "../../osal/host/FixedTimeslotTask.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../tasks/ExecutableObjectIF.h"
@ -33,18 +35,18 @@ FixedTimeslotTask::FixedTimeslotTask(const char *name, TaskPriority setPriority,
reinterpret_cast<HANDLE>(mainThread.native_handle()),
ABOVE_NORMAL_PRIORITY_CLASS);
if(result != 0) {
sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with "
<< "code " << GetLastError() << std::endl;
sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
}
result = SetThreadPriority(
reinterpret_cast<HANDLE>(mainThread.native_handle()),
THREAD_PRIORITY_NORMAL);
if(result != 0) {
sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with "
"code " << GetLastError() << std::endl;
sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
}
#elif defined(LINUX)
// we can just copy and paste the code from linux here.
// TODO: we can just copy and paste the code from the linux OSAL here.
#endif
}
@ -58,8 +60,7 @@ FixedTimeslotTask::~FixedTimeslotTask(void) {
}
void FixedTimeslotTask::taskEntryPoint(void* argument) {
FixedTimeslotTask *originalTask(
reinterpret_cast<FixedTimeslotTask*>(argument));
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
if (not originalTask->started) {
// we have to suspend/block here until the task is started.
@ -114,8 +115,9 @@ void FixedTimeslotTask::taskFunctionality() {
this->pollingSeqTable.executeAndAdvance();
if (not pollingSeqTable.slotFollowsImmediately()) {
// we need to wait before executing the current slot
//this gives us the time to wait:
interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs());
// this gives us the time to wait:
interval = chron_ms(
this->pollingSeqTable.getIntervalToPreviousSlotMs());
delayForInterval(&currentStartTime, interval);
//TODO deadline missed check
}

View File

@ -74,7 +74,7 @@ protected:
//!< Typedef for the List of objects.
typedef std::vector<ExecutableObjectIF*> ObjectList;
std::thread mainThread;
std::atomic<bool> terminateThread = false;
std::atomic<bool> terminateThread { false };
//! Polling sequence table which contains the object to execute
//! and information like the timeslots and the passed execution step.

View File

@ -34,7 +34,7 @@ ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
}
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != 0) {
if (this->lastPartner != MessageQueueIF::NO_QUEUE) {
return sendMessageFrom(this->lastPartner, message, this->getId());
} else {
return MessageQueueIF::NO_REPLY_PARTNER;
@ -106,6 +106,7 @@ bool MessageQueue::isDefaultDestinationSet() const {
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
message->setSender(sentFrom);
if(message->getMessageSize() > message->getMaximumMessageSize()) {
// Actually, this should never happen or an error will be emitted
// in MessageQueueMessage.
@ -126,7 +127,6 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
// TODO: Better returnvalue
return HasReturnvaluesIF::RETURN_FAILED;
}
if(targetQueue->messageQueue.size() < targetQueue->messageDepth) {
MutexHelper mutexLock(targetQueue->queueLock,
MutexIF::TimeoutType::WAITING, 20);
@ -145,7 +145,6 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
else {
return MessageQueueIF::FULL;
}
message->setSender(sentFrom);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -4,21 +4,18 @@
Mutex::Mutex() {}
ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) {
if(timeoutMs == MutexIF::BLOCKING) {
if(timeoutType == MutexIF::BLOCKING) {
mutex.lock();
locked = true;
return HasReturnvaluesIF::RETURN_OK;
}
else if(timeoutMs == MutexIF::POLLING) {
else if(timeoutType == MutexIF::POLLING) {
if(mutex.try_lock()) {
locked = true;
return HasReturnvaluesIF::RETURN_OK;
}
}
else if(timeoutMs > MutexIF::POLLING){
auto chronoMs = std::chrono::milliseconds(timeoutMs);
if(mutex.try_lock_for(chronoMs)) {
locked = true;
return HasReturnvaluesIF::RETURN_OK;
}
}
@ -26,11 +23,7 @@ ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) {
}
ReturnValue_t Mutex::unlockMutex() {
if(not locked) {
return MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX;
}
mutex.unlock();
locked = false;
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,5 +1,5 @@
#ifndef FSFW_OSAL_HOST_MUTEX_H_
#define FSFW_OSAL_HOST_MUTEX_H_
#ifndef FSFW_OSAL_HOSTED_MUTEX_H_
#define FSFW_OSAL_HOSTED_MUTEX_H_
#include "../../ipc/MutexIF.h"
@ -22,8 +22,8 @@ public:
std::timed_mutex* getMutexHandle();
private:
bool locked = false;
//bool locked = false;
std::timed_mutex mutex;
};
#endif /* FSFW_OSAL_HOST_MUTEX_H_ */
#endif /* FSFW_OSAL_HOSTED_MUTEX_H_ */

View File

@ -89,16 +89,16 @@ ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) {
}
void PeriodicTask::taskFunctionality() {
for (const auto& object: objectList) {
object->initializeAfterTaskCreation();
}
std::chrono::milliseconds periodChrono(static_cast<uint32_t>(period*1000));
auto currentStartTime {
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
};
auto nextStartTime{ currentStartTime };
for (const auto& object: objectList) {
object->initializeAfterTaskCreation();
}
auto nextStartTime { currentStartTime };
/* Enter the loop that defines the task behavior. */
for (;;) {
@ -109,10 +109,6 @@ void PeriodicTask::taskFunctionality() {
object->performOperation();
}
if(not delayForInterval(&currentStartTime, periodChrono)) {
#ifdef DEBUG
sif::warning << "PeriodicTask: " << taskName <<
" missed deadline!\n" << std::flush;
#endif
if(deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();
}

View File

@ -69,7 +69,7 @@ protected:
//!< Typedef for the List of objects.
typedef std::vector<ExecutableObjectIF*> ObjectList;
std::thread mainThread;
std::atomic<bool> terminateThread = false;
std::atomic<bool> terminateThread { false };
/**
* @brief This attribute holds a list of objects to be executed.

View File

@ -1,7 +1,11 @@
#include "MessageQueue.h"
#include "../../ipc/QueueFactory.h"
#include "../../ipc/MessageQueueSenderIF.h"
#include "../../ipc/MessageQueueMessageIF.h"
#include "../../ipc/QueueFactory.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include <cstring>
QueueFactory* QueueFactory::factoryInstance = nullptr;

View File

@ -44,17 +44,9 @@ MessageQueueIF* QueueMapManager::getMessageQueue(
return queueIter->second;
}
else {
if(messageQueueId == MessageQueueIF::NO_QUEUE) {
sif::error << "QueueMapManager::getQueueHandle: Configuration"
<< " error, NO_QUEUE was passed to this function!"
<< std::endl;
}
else {
sif::warning << "QueueMapManager::getQueueHandle: The ID "
<< messageQueueId << " does not exists in the map."
<< std::endl;
}
return nullptr;
sif::warning << "QueueMapManager::getQueueHandle: The ID " <<
messageQueueId << " does not exists in the map" << std::endl;
return nullptr;
}
}

View File

@ -1,4 +1,4 @@
#include "../../osal/linux/BinarySemaphore.h"
#include "BinarySemaphore.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
extern "C" {

25
osal/linux/CMakeLists.txt Normal file
View File

@ -0,0 +1,25 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
Clock.cpp
BinarySemaphore.cpp
CountingSemaphore.cpp
FixedTimeslotTask.cpp
InternalErrorCodes.cpp
MessageQueue.cpp
Mutex.cpp
MutexFactory.cpp
PeriodicPosixTask.cpp
PosixThread.cpp
QueueFactory.cpp
SemaphoreFactory.cpp
TaskFactory.cpp
TcUnixUdpPollingTask.cpp
TmTcUnixUdpBridge.cpp
Timer.cpp
)
target_link_libraries(${LIB_FSFW_NAME}
PRIVATE
rt
pthread
)

View File

@ -1,4 +1,3 @@
#include <fsfw/timemanager/Stopwatch.h>
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../timemanager/Clock.h"
@ -86,15 +85,16 @@ ReturnValue_t Clock::getUptime(timeval* uptime) {
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t Clock::getUptimeSeconds() {
//TODO This is not posix compatible and delivers only seconds precision
struct sysinfo sysInfo;
int result = sysinfo(&sysInfo);
if(result != 0){
return HasReturnvaluesIF::RETURN_FAILED;
}
return sysInfo.uptime;
}
// Wait for new FSFW Clock function delivering seconds uptime.
//uint32_t Clock::getUptimeSeconds() {
// //TODO This is not posix compatible and delivers only seconds precision
// struct sysinfo sysInfo;
// int result = sysinfo(&sysInfo);
// if(result != 0){
// return HasReturnvaluesIF::RETURN_FAILED;
// }
// return sysInfo.uptime;
//}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
timeval uptime;

View File

@ -1,4 +1,4 @@
#include "../../osal/linux/Mutex.h"
#include "Mutex.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../timemanager/Clock.h"

View File

@ -1,12 +1,8 @@
#ifndef OS_LINUX_MUTEX_H_
#define OS_LINUX_MUTEX_H_
#ifndef FSFW_OSAL_LINUX_MUTEX_H_
#define FSFW_OSAL_LINUX_MUTEX_H_
#include "../../ipc/MutexIF.h"
extern "C" {
#include <pthread.h>
}
class Mutex : public MutexIF {
public:

View File

@ -1,5 +1,6 @@
#include "Mutex.h"
#include "../../ipc/MutexFactory.h"
#include "../../osal/linux/Mutex.h"
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();

View File

@ -1,5 +1,7 @@
#include "PosixThread.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../osal/linux/PosixThread.h"
#include <cstring>
#include <errno.h>

View File

@ -1,6 +1,7 @@
#include "../../tasks/SemaphoreFactory.h"
#include "BinarySemaphore.h"
#include "CountingSemaphore.h"
#include "../../tasks/SemaphoreFactory.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr;

View File

@ -1,5 +1,6 @@
#include "../../osal/linux/FixedTimeslotTask.h"
#include "../../osal/linux/PeriodicPosixTask.h"
#include "FixedTimeslotTask.h"
#include "PeriodicPosixTask.h"
#include "../../tasks/TaskFactory.h"
#include "../../returnvalues/HasReturnvaluesIF.h"

View File

@ -1,6 +1,7 @@
#include "Timer.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include <errno.h>
#include "../../osal/linux/Timer.h"
Timer::Timer() {
sigevent sigEvent;

View File

@ -3,7 +3,7 @@
#include <rtems/score/todimpl.h>
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
MutexIF* Clock::timeMutex = nullptr;
uint32_t Clock::getTicksPerSecond(void){
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).
//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
_TOD_Set(&newTime,NULL);
_TOD_Set(&newTime,nullptr);
return HasReturnvaluesIF::RETURN_OK;
}
@ -131,7 +131,7 @@ ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
//SHOULDDO: works not for dates in the past (might have less leap seconds)
if (timeMutex == NULL) {
if (timeMutex == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
@ -157,40 +157,34 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
MutexHelper helper(timeMutex);
leapSeconds = leapSeconds_;
result = timeMutex->unlockMutex();
return result;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if(timeMutex==NULL){
if(timeMutex==nullptr){
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
MutexHelper helper(timeMutex);
*leapSeconds_ = leapSeconds;
result = timeMutex->unlockMutex();
return result;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::checkOrCreateClockMutex(){
if(timeMutex==NULL){
if(timeMutex==nullptr){
MutexFactory* mutexFactory = MutexFactory::instance();
if (mutexFactory == NULL) {
if (mutexFactory == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
timeMutex = mutexFactory->createMutex();
if (timeMutex == NULL) {
if (timeMutex == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
}

View File

@ -158,7 +158,7 @@ uint32_t CpuUsage::ThreadData::getSerializedSize() const {
}
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,
size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {

View File

@ -12,8 +12,8 @@ ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
// return INVALID_WORKSPACE_ADDRESS;
case INTERNAL_ERROR_TOO_LITTLE_WORKSPACE:
return TOO_LITTLE_WORKSPACE;
case INTERNAL_ERROR_WORKSPACE_ALLOCATION:
return WORKSPACE_ALLOCATION;
// case INTERNAL_ERROR_WORKSPACE_ALLOCATION:
// return WORKSPACE_ALLOCATION;
// case INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL:
// return INTERRUPT_STACK_TOO_SMALL;
case INTERNAL_ERROR_THREAD_EXITTED:

View File

@ -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();
}

View File

@ -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_ */

View File

@ -1,14 +1,15 @@
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../objectmanager/ObjectManagerIF.h"
#include "MessageQueue.h"
#include "RtemsBasic.h"
#include <cstring>
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_status_code status = rtems_message_queue_create(name, message_depth,
max_message_size, 0, &(this->id));
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:"
<< (uint32_t) status << std::endl;
this->id = 0;
@ -20,15 +21,15 @@ MessageQueue::~MessageQueue() {
}
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, bool ignoreFault) {
MessageQueueMessageIF* message, bool 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());
}
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != 0) {
return sendMessage(this->lastPartner, message, this->getId());
} 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) {
ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->lastPartner;
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,
message->getBuffer(), &(message->messageSize),
message->getBuffer(),&size,
RTEMS_NO_WAIT, 1);
if (status == RTEMS_SUCCESSFUL) {
message->setMessageSize(size);
this->lastPartner = message->getSender();
//Check size of incoming message.
if (message->messageSize < message->getMinimumMessageSize()) {
if (message->getMessageSize() < message->getMinimumMessageSize()) {
return HasReturnvaluesIF::RETURN_FAILED;
}
} else {
//No message was received. Keep lastPartner anyway, I might send something later.
//But still, delete packet content.
memset(message->getData(), 0, message->MAX_DATA_SIZE);
memset(message->getData(), 0, message->getMaximumMessageSize());
}
return convertReturnCode(status);
}
@ -79,20 +82,20 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
}
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
message->setSender(sentFrom);
rtems_status_code result = rtems_message_queue_send(sendTo,
message->getBuffer(), message->messageSize);
message->getBuffer(), message->getMessageSize());
//TODO: Check if we're in ISR.
if (result != RTEMS_SUCCESSFUL && !ignoreFault) {
if (internalErrorReporter == NULL) {
if (internalErrorReporter == nullptr) {
internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
}
if (internalErrorReporter != NULL) {
if (internalErrorReporter != nullptr) {
internalErrorReporter->queueMessageNotSent();
}
}
@ -105,7 +108,7 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
return returnCode;
}
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
}

View File

@ -1,14 +1,5 @@
/**
* @file 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_
#ifndef FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
#include "../../internalError/InternalErrorReporterIF.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.
*/
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.
* @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 );
ReturnValue_t sendToDefault( MessageQueueMessageIF* message );
/**
* @brief This operation sends a message to the last communication partner.
* @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.
* @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.
@ -84,7 +75,7 @@ public:
* @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,
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t *receivedFrom);
/**
@ -95,7 +86,7 @@ public:
* message's content is cleared and the function returns immediately.
* @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.
* @param count The number of flushed messages.
@ -121,7 +112,7 @@ public:
* 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 );
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.
* \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.
* 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.
*/
@ -178,4 +169,4 @@ private:
static ReturnValue_t convertReturnCode(rtems_status_code inValue);
};
#endif /* MESSAGEQUEUE_H_ */
#endif /* FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_ */

View File

@ -30,7 +30,7 @@ ReturnValue_t MultiObjectTask::startTask() {
rtems_status_code status = rtems_task_start(id, MultiObjectTask::taskEntryPoint,
rtems_task_argument((void *) this));
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;
}
switch(status){
@ -63,8 +63,8 @@ void MultiObjectTask::taskFunctionality() {
char nameSpace[8] = { 0 };
char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace),
nameSpace);
error << "ObjectTask: " << ptr << " Deadline missed." << std::endl;
if (this->deadlineMissedFunc != NULL) {
sif::error << "ObjectTask: " << ptr << " Deadline missed." << std::endl;
if (this->deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();
}
}
@ -74,12 +74,13 @@ void MultiObjectTask::taskFunctionality() {
ReturnValue_t MultiObjectTask::addComponent(object_id_t object) {
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(
object);
if (newObject == NULL) {
if (newObject == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
objectList.push_back(newObject);
ReturnValue_t result = newObject->initializeAfterTaskCreation();
return result;
newObject->setTaskIF(this);
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t MultiObjectTask::getPeriodMs() const {

View File

@ -1,11 +1,5 @@
/**
* @file MultiObjectTask.h
* @brief This file defines the MultiObjectTask class.
* @date 30.01.2014
* @author baetz
*/
#ifndef MULTIOBJECTTASK_H_
#define MULTIOBJECTTASK_H_
#ifndef FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_
#define FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_
#include "../../objectmanager/ObjectManagerIF.h"
#include "../../tasks/PeriodicTaskIF.h"
@ -21,7 +15,7 @@ class ExecutableObjectIF;
* @details MultiObjectTask is an extension to ObjectTask in the way that it is able to execute
* multiple objects that implement the ExecutableObjectIF interface. The objects must be
* added prior to starting the task.
*
* @author baetz
* @ingroup task_handling
*/
class MultiObjectTask: public TaskBase, public PeriodicTaskIF {
@ -63,11 +57,11 @@ public:
* @param object Id of the object to add.
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
*/
ReturnValue_t addComponent(object_id_t object);
ReturnValue_t addComponent(object_id_t object) override;
uint32_t getPeriodMs() const;
uint32_t getPeriodMs() const override;
ReturnValue_t sleepFor(uint32_t ms);
ReturnValue_t sleepFor(uint32_t ms) override;
protected:
typedef std::vector<ExecutableObjectIF*> ObjectList; //!< Typedef for the List of objects.
/**
@ -86,7 +80,7 @@ protected:
/**
* @brief The pointer to the deadline-missed function.
* @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
* of the periodic task.
*/
@ -110,4 +104,4 @@ protected:
void taskFunctionality(void);
};
#endif /* MULTIOBJECTTASK_H_ */
#endif /* FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ */

View File

@ -1,7 +1,6 @@
#include "Mutex.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
const uint32_t MutexIF::NO_TIMEOUT = RTEMS_NO_TIMEOUT;
uint8_t Mutex::count = 0;
Mutex::Mutex() :
@ -11,7 +10,7 @@ Mutex::Mutex() :
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
&mutexId);
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;
}
}
@ -19,13 +18,28 @@ Mutex::Mutex() :
Mutex::~Mutex() {
rtems_status_code status = rtems_semaphore_delete(mutexId);
if (status != RTEMS_SUCCESSFUL) {
error << "Mutex: deletion for id " << mutexId
sif::error << "Mutex: deletion for id " << mutexId
<< " failed with " << status << std::endl;
}
}
ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) {
rtems_status_code status = rtems_semaphore_obtain(mutexId, RTEMS_WAIT, timeoutMs);
ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType =
TimeoutType::BLOCKING, uint32_t timeoutMs) {
rtems_status_code status = RTEMS_INVALID_ID;
if(timeoutMs == MutexIF::TimeoutType::BLOCKING) {
status = rtems_semaphore_obtain(mutexId,
RTEMS_WAIT, RTEMS_NO_TIMEOUT);
}
else if(timeoutMs == MutexIF::TimeoutType::POLLING) {
timeoutMs = RTEMS_NO_TIMEOUT;
status = rtems_semaphore_obtain(mutexId,
RTEMS_NO_WAIT, 0);
}
else {
status = rtems_semaphore_obtain(mutexId,
RTEMS_WAIT, timeoutMs);
}
switch(status){
case RTEMS_SUCCESSFUL:
//semaphore obtained successfully

View File

@ -1,5 +1,5 @@
#ifndef OS_RTEMS_MUTEX_H_
#define OS_RTEMS_MUTEX_H_
#ifndef FSFW_OSAL_RTEMS_MUTEX_H_
#define FSFW_OSAL_RTEMS_MUTEX_H_
#include "../../ipc/MutexIF.h"
#include "RtemsBasic.h"
@ -8,11 +8,11 @@ class Mutex : public MutexIF {
public:
Mutex();
~Mutex();
ReturnValue_t lockMutex(uint32_t timeoutMs);
ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0);
ReturnValue_t unlockMutex();
private:
rtems_id mutexId;
static uint8_t count;
};
#endif /* OS_RTEMS_MUTEX_H_ */
#endif /* FSFW_OSAL_RTEMS_MUTEX_H_ */

View File

@ -2,7 +2,6 @@
#include "Mutex.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() {

View File

@ -1,7 +1,8 @@
#include "../../tasks/FixedSequenceSlot.h"
#include "../../objectmanager/SystemObjectIF.h"
#include "../../osal/rtems/PollingTask.h"
#include "../../osal/rtems/RtemsBasic.h"
#include "../../objectmanager/ObjectManagerIF.h"
#include "PollingTask.h"
#include "RtemsBasic.h"
#include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include <rtems/bspIo.h>
@ -34,14 +35,14 @@ rtems_task PollingTask::taskEntryPoint(rtems_task_argument argument) {
PollingTask *originalTask(reinterpret_cast<PollingTask*>(argument));
//The task's functionality is called.
originalTask->taskFunctionality();
debug << "Polling task " << originalTask->getId()
sif::debug << "Polling task " << originalTask->getId()
<< " returned from taskFunctionality." << std::endl;
}
void PollingTask::missedDeadlineCounter() {
PollingTask::deadlineMissedCount++;
if (PollingTask::deadlineMissedCount % 10 == 0) {
error << "PST missed " << PollingTask::deadlineMissedCount
sif::error << "PST missed " << PollingTask::deadlineMissedCount
<< " deadlines." << std::endl;
}
}
@ -50,7 +51,7 @@ ReturnValue_t PollingTask::startTask() {
rtems_status_code status = rtems_task_start(id, PollingTask::taskEntryPoint,
rtems_task_argument((void *) this));
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;
}
switch(status){
@ -68,8 +69,9 @@ ReturnValue_t PollingTask::startTask() {
ReturnValue_t PollingTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) {
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep, this);
ExecutableObjectIF* object = objectManager->get<ExecutableObjectIF>(componentId);
if (object != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep, object, this);
return HasReturnvaluesIF::RETURN_OK;
}
@ -82,7 +84,7 @@ uint32_t PollingTask::getPeriodMs() const {
return pst.getLengthMs();
}
ReturnValue_t PollingTask::checkAndInitializeSequence() const {
ReturnValue_t PollingTask::checkSequence() const {
return pst.checkSequence();
}
@ -90,11 +92,10 @@ ReturnValue_t PollingTask::checkAndInitializeSequence() const {
void PollingTask::taskFunctionality() {
// 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.
rtems_interval interval = RtemsBasic::convertMsToTicks(
(*it)->pollingTimeMs);
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
TaskBase::setAndStartPeriod(interval,&periodId);
//The task's "infinite" inner loop is entered.
while (1) {
@ -107,7 +108,7 @@ void PollingTask::taskFunctionality() {
//If the deadline was missed, the deadlineMissedFunc is called.
rtems_status_code status = TaskBase::restartPeriod(interval,periodId);
if (status == RTEMS_TIMEOUT) {
if (this->deadlineMissedFunc != NULL) {
if (this->deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();
}
}

View File

@ -1,5 +1,5 @@
#ifndef POLLINGTASK_H_
#define POLLINGTASK_H_
#ifndef FSFW_OSAL_RTEMS_POLLINGTASK_H_
#define FSFW_OSAL_RTEMS_POLLINGTASK_H_
#include "../../tasks/FixedSlotSequence.h"
#include "../../tasks/FixedTimeslotTaskIF.h"
@ -42,7 +42,7 @@ class PollingTask: public TaskBase, public FixedTimeslotTaskIF {
uint32_t getPeriodMs() const;
ReturnValue_t checkAndInitializeSequence() const;
ReturnValue_t checkSequence() const;
ReturnValue_t sleepFor(uint32_t ms);
protected:
@ -82,4 +82,4 @@ protected:
void taskFunctionality( void );
};
#endif /* POLLINGTASK_H_ */
#endif /* FSFW_OSAL_RTEMS_POLLINGTASK_H_ */

View File

@ -1,16 +1,17 @@
#include "../../ipc/QueueFactory.h"
#include "../../ipc/MessageQueueSenderIF.h"
#include "MessageQueue.h"
#include "RtemsBasic.h"
QueueFactory* QueueFactory::factoryInstance = NULL;
QueueFactory* QueueFactory::factoryInstance = nullptr;
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
message->setSender(sentFrom);
rtems_status_code result = rtems_message_queue_send(sendTo, message->getBuffer(),
message->messageSize);
message->getMessageSize());
switch(result){
case RTEMS_SUCCESSFUL:
//message sent successfully
@ -37,7 +38,7 @@ ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
}
QueueFactory* QueueFactory::instance() {
if (factoryInstance == NULL) {
if (factoryInstance == nullptr) {
factoryInstance = new QueueFactory;
}
return factoryInstance;

View File

@ -1,5 +1,5 @@
#ifndef OS_RTEMS_RTEMSBASIC_H_
#define OS_RTEMS_RTEMSBASIC_H_
#ifndef FSFW_OSAL_RTEMS_RTEMSBASIC_H_
#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_
#include "../../returnvalues/HasReturnvaluesIF.h"
#include <rtems.h>
@ -22,4 +22,4 @@ public:
}
};
#endif /* OS_RTEMS_RTEMSBASIC_H_ */
#endif /* FSFW_OSAL_RTEMS_RTEMSBASIC_H_ */

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