Merge branch 'development' into mueller/tmtcservices-update
This commit is contained in:
commit
329cd8862a
@ -53,6 +53,12 @@ ID for now.
|
|||||||
|
|
||||||
- There is an additional `PERFORM_OPERATION` step for the device handler base. It is important
|
- 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
|
that DHB users adapt their polling sequence tables to perform this step. This steps allows for aclear distinction between operation and communication steps
|
||||||
|
- setNormalDatapoolEntriesInvalid is not an abstract method and a default implementation was provided
|
||||||
|
- getTransitionDelayMs is now an abstract method
|
||||||
|
|
||||||
|
### DeviceHandlerIF
|
||||||
|
|
||||||
|
- Typo for UNKNOWN_DEVICE_REPLY
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
|
@ -3,14 +3,23 @@ cmake_minimum_required(VERSION 3.13)
|
|||||||
set(LIB_FSFW_NAME fsfw)
|
set(LIB_FSFW_NAME fsfw)
|
||||||
add_library(${LIB_FSFW_NAME})
|
add_library(${LIB_FSFW_NAME})
|
||||||
|
|
||||||
# Set options for FSFW OSAL selection.
|
set_property(CACHE OS_FSFW PROPERTY STRINGS host linux rtems freertos)
|
||||||
|
|
||||||
|
if(NOT OS_FSFW)
|
||||||
|
message(STATUS "No OS for FSFW via OS_FSFW set. Assuming host OS")
|
||||||
|
# Assume host OS and autodetermine from OS_FSFW
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
set(OS_FSFW "linux" CACHE STRING "OS abstraction layer used in the FSFW")
|
set(OS_FSFW "linux"
|
||||||
|
CACHE STRING
|
||||||
|
"OS abstraction layer used in the FSFW"
|
||||||
|
)
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
set(OS_FSFW "host" CACHE STRING "OS abstraction layer used in the FSFW")
|
set(OS_FSFW "host"
|
||||||
|
CACHE STRING "OS abstraction layer used in the FSFW"
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_property(CACHE OS_FSFW PROPERTY STRINGS host linux rtems freertos)
|
endif()
|
||||||
|
|
||||||
if(${OS_FSFW} STREQUAL host)
|
if(${OS_FSFW} STREQUAL host)
|
||||||
set(OS_FSFW_NAME "Host")
|
set(OS_FSFW_NAME "Host")
|
||||||
@ -18,15 +27,18 @@ elseif(${OS_FSFW} STREQUAL linux)
|
|||||||
set(OS_FSFW_NAME "Linux")
|
set(OS_FSFW_NAME "Linux")
|
||||||
elseif(${OS_FSFW} STREQUAL freertos)
|
elseif(${OS_FSFW} STREQUAL freertos)
|
||||||
set(OS_FSFW_NAME "FreeRTOS")
|
set(OS_FSFW_NAME "FreeRTOS")
|
||||||
|
target_link_libraries(${LIB_FSFW_NAME} ${LIB_OS_NAME})
|
||||||
elseif(${OS_FSFW} STREQUAL rtems)
|
elseif(${OS_FSFW} STREQUAL rtems)
|
||||||
set(OS_FSFW_NAME "RTEMS")
|
set(OS_FSFW_NAME "RTEMS")
|
||||||
else()
|
else()
|
||||||
message(WARNING "Invalid operating system for FSFW specified! Setting to host..")
|
message(WARNING
|
||||||
|
"Invalid operating system for FSFW specified! Setting to host.."
|
||||||
|
)
|
||||||
set(OS_FSFW_NAME "Host")
|
set(OS_FSFW_NAME "Host")
|
||||||
set(OS_FSFW "host")
|
set(OS_FSFW "host")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system")
|
message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system.")
|
||||||
|
|
||||||
# Options to exclude parts of the FSFW from compilation.
|
# Options to exclude parts of the FSFW from compilation.
|
||||||
option(FSFW_USE_RMAP "Compile with RMAP" ON)
|
option(FSFW_USE_RMAP "Compile with RMAP" ON)
|
||||||
@ -36,8 +48,14 @@ add_subdirectory(action)
|
|||||||
add_subdirectory(container)
|
add_subdirectory(container)
|
||||||
add_subdirectory(controller)
|
add_subdirectory(controller)
|
||||||
add_subdirectory(coordinates)
|
add_subdirectory(coordinates)
|
||||||
|
|
||||||
|
if(FSFW_USE_DATALINKLAYER)
|
||||||
add_subdirectory(datalinklayer)
|
add_subdirectory(datalinklayer)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_subdirectory(datapool)
|
add_subdirectory(datapool)
|
||||||
|
add_subdirectory(datapoollocal)
|
||||||
|
add_subdirectory(housekeeping)
|
||||||
add_subdirectory(devicehandlers)
|
add_subdirectory(devicehandlers)
|
||||||
add_subdirectory(events)
|
add_subdirectory(events)
|
||||||
add_subdirectory(fdir)
|
add_subdirectory(fdir)
|
||||||
@ -78,8 +96,48 @@ message(WARNING "Setting default configuration!")
|
|||||||
add_subdirectory(defaultcfg/fsfwconfig)
|
add_subdirectory(defaultcfg/fsfwconfig)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Required include paths to compile the FSFW
|
# FSFW might be part of a possibly complicated folder structure, so we
|
||||||
target_include_directories(${LIB_FSFW_NAME}
|
# extract the absolute path of the fsfwconfig folder.
|
||||||
INTERFACE
|
if(IS_ABSOLUTE ${FSFW_CONFIG_PATH})
|
||||||
${FSFW_CONFIG_PATH}
|
set(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH})
|
||||||
|
else()
|
||||||
|
get_filename_component(FSFW_CONFIG_PATH_ABSOLUTE
|
||||||
|
${FSFW_CONFIG_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
set(WARNING_FLAGS
|
||||||
|
-Wall
|
||||||
|
-Wextra
|
||||||
|
-Wshadow=local
|
||||||
|
-Wimplicit-fallthrough=1
|
||||||
|
-Wno-unused-parameter
|
||||||
|
-Wno-psabi
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
set(COMPILER_FLAGS "/permissive-")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Required include paths to compile the FSFW
|
||||||
|
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
||||||
|
${CMAKE_SOURCE_DIR}
|
||||||
|
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Includes path required to compile FSFW itself as well
|
||||||
|
# We assume that the fsfwconfig folder uses include relative to the project
|
||||||
|
# root here!
|
||||||
|
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
${CMAKE_SOURCE_DIR}
|
||||||
|
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Machine specific options can be set with the ABI_FLAGS variable.
|
||||||
|
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
${WARNING_FLAGS}
|
||||||
|
${COMPILER_FLAGS}
|
||||||
|
${ABI_FLAGS}
|
||||||
)
|
)
|
||||||
|
100
README.md
100
README.md
@ -1,4 +1,5 @@
|
|||||||
![FSFW Logo](logo/FSFW_Logo_V3_bw.png)
|
![FSFW Logo](logo/FSFW_Logo_V3_bw.png)
|
||||||
|
|
||||||
# Flight Software Framework (FSFW)
|
# Flight Software Framework (FSFW)
|
||||||
|
|
||||||
The Flight Software Framework is a C++ Object Oriented Framework for unmanned,
|
The Flight Software Framework is a C++ Object Oriented Framework for unmanned,
|
||||||
@ -14,83 +15,54 @@ The framework is designed for systems, which communicate with external devices,
|
|||||||
Therefore, a mode and health system provides control over the states of the software and the controlled devices.
|
Therefore, a mode and health system provides control over the states of the software and the controlled devices.
|
||||||
In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well.
|
In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well.
|
||||||
|
|
||||||
The recommended hardware is a microprocessor with more than 2 MB of RAM and 1 MB of non-volatile Memory.
|
The recommended hardware is a microprocessor with more than 1 MB of RAM and 1 MB of non-volatile Memory.
|
||||||
For reference, current Applications use a Cobham Gaisler UT699 (LEON3FT), a ISISPACE IOBC or a Zynq-7020 SoC.
|
For reference, current Applications use a Cobham Gaisler UT699 (LEON3FT), a ISISPACE IOBC or a Zynq-7020 SoC.
|
||||||
|
The `fsfw` was also tested on the STM32H743ZI-Nucleo board.
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
The [FSFW example](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_example) provides a good starting point and a demo
|
||||||
|
to see the FSFW capabilities and build it with the Make or the CMake build system.
|
||||||
|
Generally, the FSFW is included in a project by compiling the FSFW sources and providing
|
||||||
|
a configuration folder and adding it to the include path.
|
||||||
|
A template configuration folder was provided and can be copied into the project root to have
|
||||||
|
a starting point. The [configuration section](doc/README-config.md#top) provides more specific information about
|
||||||
|
the possible options.
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
|
|
||||||
The general structure is driven by the usage of interfaces provided by objects. The FSFW uses C++11 as baseline. The intention behind this is that this C++ Standard should be widely available, even with older compilers.
|
The general structure is driven by the usage of interfaces provided by objects.
|
||||||
|
The FSFW uses C++11 as baseline. The intention behind this is that this C++ Standard should be widely available, even with older compilers.
|
||||||
The FSFW uses dynamic allocation during the initialization but provides static containers during runtime.
|
The FSFW uses dynamic allocation during the initialization but provides static containers during runtime.
|
||||||
This simplifies the instantiation of objects and allows the usage of some standard containers.
|
This simplifies the instantiation of objects and allows the usage of some standard containers.
|
||||||
Dynamic Allocation after initialization is discouraged and different solutions are provided in the FSFW to achieve that.
|
Dynamic Allocation after initialization is discouraged and different solutions are provided in the FSFW to achieve that.
|
||||||
The fsfw uses Run-time type information.
|
The fsfw uses run-time type information but exceptions are not allowed.
|
||||||
Exceptions are not allowed.
|
|
||||||
|
|
||||||
### Failure Handling
|
### Failure Handling
|
||||||
|
|
||||||
Functions should return a defined ReturnValue_t to signal to the caller that something is gone wrong.
|
Functions should return a defined ReturnValue_t to signal to the caller that something has gone wrong.
|
||||||
Returnvalues must be unique. For this the function HasReturnvaluesIF::makeReturnCode or the Macro MAKE_RETURN can be used.
|
Returnvalues must be unique. For this the function HasReturnvaluesIF::makeReturnCode or the Macro MAKE_RETURN can be used.
|
||||||
The CLASS_ID is a unique id for that type of object. See returnvalues/FwClassIds.
|
The CLASS_ID is a unique id for that type of object. See returnvalues/FwClassIds.
|
||||||
|
|
||||||
### OSAL
|
### OSAL
|
||||||
The FSFW provides operation system abstraction layers for Linux, FreeRTOS and RTEMS. A independent OSAL called "host" is currently not finished. This aims to be running on windows as well.
|
|
||||||
The OSAL provides periodic tasks, message queues, clocks and Semaphores as well as Mutexes.
|
The FSFW provides operation system abstraction layers for Linux, FreeRTOS and RTEMS.
|
||||||
|
A independent Host OSAL is in development which will provide abstraction for common type of
|
||||||
|
host OSes (tested for Linux and Windows, not for MacOS yet).
|
||||||
|
The OSAL provides periodic tasks, message queues, clocks and semaphores as well as mutexes.
|
||||||
|
|
||||||
### Core Components
|
### Core Components
|
||||||
|
|
||||||
Clock:
|
The FSFW has following core components. More detailed informations can be found in the
|
||||||
* This is a class of static functions that can be used at anytime
|
[core component section](doc/README-core.md#top):
|
||||||
* Leap Seconds must be set if any time conversions from UTC to other times is used
|
|
||||||
|
|
||||||
ObjectManager (must be created):
|
|
||||||
|
|
||||||
* The component which handles all references. All SystemObjects register at this component.
|
|
||||||
* Any SystemObject needs to have a unique ObjectId. Those can be managed like objects::framework_objects.
|
|
||||||
* A reference to an object can be get by calling the following function. T must be the specific Interface you want to call.
|
|
||||||
A nullptr check of the returning Pointer must be done. This function is based on Run-time type information.
|
|
||||||
|
|
||||||
``` c++
|
|
||||||
template <typename T> T* ObjectManagerIF::get( object_id_t id )
|
|
||||||
|
|
||||||
```
|
|
||||||
* A typical way to create all objects on startup is a handing a static produce function to the ObjectManager on creation.
|
|
||||||
By calling objectManager->initialize() the produce function will be called and all SystemObjects will be initialized afterwards.
|
|
||||||
|
|
||||||
Event Manager:
|
|
||||||
|
|
||||||
* Component which allows routing of events
|
|
||||||
* Other objects can subscribe to specific events, ranges of events or all events of an object.
|
|
||||||
* Subscriptions can be done during runtime but should be done during initialization
|
|
||||||
* Amounts of allowed subscriptions must be configured by setting this parameters:
|
|
||||||
|
|
||||||
``` c++
|
|
||||||
namespace fsfwconfig {
|
|
||||||
//! Configure the allocated pool sizes for the event manager.
|
|
||||||
static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
|
|
||||||
static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120;
|
|
||||||
static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Health Table:
|
|
||||||
|
|
||||||
* A component which holds every health state
|
|
||||||
* Provides a thread safe way to access all health states without the need of message exchanges
|
|
||||||
|
|
||||||
Stores
|
|
||||||
|
|
||||||
* The message based communication can only exchange a few bytes of information inside the message itself. Therefore, additional information can be exchanged with Stores. With this, only the store address must be exchanged in the message.
|
|
||||||
* Internally, the FSFW uses an IPC Store to exchange data between processes. For incoming TCs a TC Store is used. For outgoing TM a TM store is used.
|
|
||||||
* All of them should use the Thread Safe Class storagemanager/PoolManager
|
|
||||||
|
|
||||||
Tasks
|
|
||||||
|
|
||||||
There are two different types of tasks:
|
|
||||||
* The PeriodicTask just executes objects that are of type ExecutableObjectIF in the order of the insertion to the Tasks.
|
|
||||||
* FixedTimeslotTask executes a list of calls in the order of the given list. This is intended for DeviceHandlers, where polling should be in a defined order. An example can be found in defaultcfg/fsfwconfig/pollingSequence
|
|
||||||
|
|
||||||
|
1. Tasks: Abstraction for different (periodic) task types like periodic tasks or tasks with fixed timeslots
|
||||||
|
2. ObjectManager: This module stores all `SystemObjects` by mapping a provided unique object ID to the object handles.
|
||||||
|
3. Static Stores: Different stores are provided to store data of variable size (like telecommands or small telemetry) in a pool structure without
|
||||||
|
using dynamic memory allocation. These pools are allocated up front.
|
||||||
|
3. Clock: This module provided common time related functions
|
||||||
|
4. EventManager: This module allows routing of events generated by `SystemObjects`
|
||||||
|
5. HealthTable: A component which stores the health states of objects
|
||||||
|
|
||||||
### Static Ids in the framework
|
### Static Ids in the framework
|
||||||
|
|
||||||
@ -121,13 +93,15 @@ If the communication is based on CCSDS Frames and Space Packets, several classes
|
|||||||
If Space Packets are used, a timestamper must be created.
|
If Space Packets are used, a timestamper must be created.
|
||||||
An example can be found in the timemanager folder, this uses CCSDSTime::CDS_short.
|
An example can be found in the timemanager folder, this uses CCSDSTime::CDS_short.
|
||||||
|
|
||||||
#### DeviceHandling
|
#### Device Handlers
|
||||||
|
|
||||||
DeviceHandlers are a core component of the FSFW.
|
DeviceHandlers are another important component of the FSFW.
|
||||||
The idea is, to have a software counterpart of every physical device to provide a simple mode, health and commanding interface.
|
The idea is, to have a software counterpart of every physical device to provide a simple mode, health and commanding interface.
|
||||||
By separating the underlying Communication Interface with DeviceCommunicationIF, a DH can be tested on different hardware.
|
By separating the underlying Communication Interface with DeviceCommunicationIF, a device handler (DH) can be tested on different hardware.
|
||||||
The DH has mechanisms to monitor the communication with the physical device which allow for FDIR reaction.
|
The DH has mechanisms to monitor the communication with the physical device which allow for FDIR reaction.
|
||||||
|
Device Handlers can be created by overriding `DeviceHandlerBase`.
|
||||||
A standard FDIR component for the DH will be created automatically but can be overwritten by the user.
|
A standard FDIR component for the DH will be created automatically but can be overwritten by the user.
|
||||||
|
More information on DeviceHandlers can be found in the related [documentation section](doc/README-devicehandlers.md#top).
|
||||||
|
|
||||||
#### Modes, Health
|
#### Modes, Health
|
||||||
|
|
||||||
@ -149,10 +123,6 @@ The health state represents if the component is able to perform its tasks.
|
|||||||
This can be used to signal the system to avoid using this component instead of a redundant one.
|
This can be used to signal the system to avoid using this component instead of a redundant one.
|
||||||
The on-board FDIR uses the health state for isolation and recovery.
|
The on-board FDIR uses the health state for isolation and recovery.
|
||||||
|
|
||||||
## Example config
|
|
||||||
|
|
||||||
A example config can be found in defaultcfg/fsfwconfig.
|
|
||||||
|
|
||||||
## Unit Tests
|
## Unit Tests
|
||||||
|
|
||||||
Unit Tests are provided in the unittest folder. Those use the catch2 framework but do not include catch2 itself.
|
Unit Tests are provided in the unittest folder. Those use the catch2 framework but do not include catch2 itself.
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#ifndef SGP4PROPAGATOR_H_
|
#ifndef SGP4PROPAGATOR_H_
|
||||||
#define SGP4PROPAGATOR_H_
|
#define SGP4PROPAGATOR_H_
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
#include "../contrib/sgp4/sgp4unit.h"
|
#include "../contrib/sgp4/sgp4unit.h"
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
ControllerSet.cpp
|
|
||||||
DataPool.cpp
|
|
||||||
DataPoolAdmin.cpp
|
|
||||||
DataPoolParameterWrapper.cpp
|
|
||||||
DataSet.cpp
|
|
||||||
HkSwitchHelper.cpp
|
HkSwitchHelper.cpp
|
||||||
|
PoolDataSetBase.cpp
|
||||||
PoolEntry.cpp
|
PoolEntry.cpp
|
||||||
PoolRawAccess.cpp
|
|
||||||
)
|
)
|
8
datapoollocal/CMakeLists.txt
Normal file
8
datapoollocal/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
target_sources(${LIB_FSFW_NAME}
|
||||||
|
PRIVATE
|
||||||
|
LocalDataPoolManager.cpp
|
||||||
|
LocalDataSet.cpp
|
||||||
|
LocalPoolDataSetBase.cpp
|
||||||
|
LocalPoolObjectBase.cpp
|
||||||
|
SharedLocalDataSet.cpp
|
||||||
|
)
|
@ -926,11 +926,6 @@ void DeviceHandlerBase::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
|||||||
setMode(getBaseMode(mode));
|
setMode(getBaseMode(mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DeviceHandlerBase::getTransitionDelayMs(Mode_t modeFrom,
|
|
||||||
Mode_t modeTo) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) {
|
ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) {
|
||||||
if(powerSwitcher == nullptr) {
|
if(powerSwitcher == nullptr) {
|
||||||
return NO_SWITCH;
|
return NO_SWITCH;
|
||||||
@ -1459,3 +1454,11 @@ DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
|
|||||||
}
|
}
|
||||||
return DeviceHandlerIF::NO_COMMAND;
|
return DeviceHandlerIF::NO_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
|
||||||
|
for(const auto& reply: deviceReplyMap) {
|
||||||
|
if(reply.second.dataSet != nullptr) {
|
||||||
|
reply.second.dataSet->setValidity(false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -254,7 +254,8 @@ protected:
|
|||||||
*
|
*
|
||||||
* @param[out] id the device command id that has been built
|
* @param[out] id the device command id that has been built
|
||||||
* @return
|
* @return
|
||||||
* - @c RETURN_OK to send command after setting #rawPacket and #rawPacketLen.
|
* - @c RETURN_OK to send command after setting #rawPacket and
|
||||||
|
* #rawPacketLen.
|
||||||
* - @c NOTHING_TO_SEND when no command is to be sent.
|
* - @c NOTHING_TO_SEND when no command is to be sent.
|
||||||
* - Anything else triggers an even with the returnvalue as a parameter.
|
* - Anything else triggers an even with the returnvalue as a parameter.
|
||||||
*/
|
*/
|
||||||
@ -273,7 +274,8 @@ protected:
|
|||||||
* and filling them in doStartUp(), doShutDown() and doTransition() so no
|
* and filling them in doStartUp(), doShutDown() and doTransition() so no
|
||||||
* modes have to be checked here.
|
* modes have to be checked here.
|
||||||
*
|
*
|
||||||
* #rawPacket and #rawPacketLen must be set by this method to the packet to be sent.
|
* #rawPacket and #rawPacketLen must be set by this method to the
|
||||||
|
* packet to be sent.
|
||||||
*
|
*
|
||||||
* @param[out] id the device command id built
|
* @param[out] id the device command id built
|
||||||
* @return
|
* @return
|
||||||
@ -284,19 +286,23 @@ protected:
|
|||||||
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0;
|
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Build a device command packet from data supplied by a direct command.
|
* @brief Build a device command packet from data supplied by a
|
||||||
|
* direct command.
|
||||||
*
|
*
|
||||||
* @details
|
* @details
|
||||||
* #rawPacket and #rawPacketLen should be set by this method to the packet to be sent.
|
* #rawPacket and #rawPacketLen should be set by this method to the packet
|
||||||
* The existence of the command in the command map and the command size check
|
* to be sent. The existence of the command in the command map and the
|
||||||
* against 0 are done by the base class.
|
* command size check against 0 are done by the base class.
|
||||||
*
|
*
|
||||||
* @param deviceCommand the command to build, already checked against deviceCommandMap
|
* @param deviceCommand the command to build, already checked against
|
||||||
|
* deviceCommandMap
|
||||||
* @param commandData pointer to the data from the direct command
|
* @param commandData pointer to the data from the direct command
|
||||||
* @param commandDataLen length of commandData
|
* @param commandDataLen length of commandData
|
||||||
* @return
|
* @return
|
||||||
* - @c RETURN_OK to send command after #rawPacket and #rawPacketLen have been set.
|
* - @c RETURN_OK to send command after #rawPacket and #rawPacketLen
|
||||||
* - Anything else triggers an event with the returnvalue as a parameter
|
* have been set.
|
||||||
|
* - Anything else triggers an event with the
|
||||||
|
* returnvalue as a parameter
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||||
const uint8_t * commandData, size_t commandDataLen) = 0;
|
const uint8_t * commandData, size_t commandDataLen) = 0;
|
||||||
@ -484,7 +490,7 @@ protected:
|
|||||||
* @param modeTo
|
* @param modeTo
|
||||||
* @return time in ms
|
* @return time in ms
|
||||||
*/
|
*/
|
||||||
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo);
|
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the switches connected to the device.
|
* Return the switches connected to the device.
|
||||||
@ -681,7 +687,7 @@ protected:
|
|||||||
//! The dataset used to access housekeeping data related to the
|
//! The dataset used to access housekeeping data related to the
|
||||||
//! respective device reply. Will point to a dataset held by
|
//! respective device reply. Will point to a dataset held by
|
||||||
//! the child handler (if one is specified)
|
//! the child handler (if one is specified)
|
||||||
LocalPoolDataSetBase* dataSet;
|
LocalPoolDataSetBase* dataSet = nullptr;
|
||||||
//! The command that expects this reply.
|
//! The command that expects this reply.
|
||||||
DeviceCommandMap::iterator command;
|
DeviceCommandMap::iterator command;
|
||||||
};
|
};
|
||||||
@ -743,6 +749,17 @@ protected:
|
|||||||
//!< Object which may be the root cause of an identified fault.
|
//!< Object which may be the root cause of an identified fault.
|
||||||
static object_id_t defaultFdirParentId;
|
static object_id_t defaultFdirParentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set all datapool variables that are update periodically in
|
||||||
|
* normal mode invalid
|
||||||
|
* @details
|
||||||
|
* The default implementation will set all datasets which have been added
|
||||||
|
* in #fillCommandAndReplyMap to invalid. It will also set all pool
|
||||||
|
* variables inside the dataset to invalid. The user can override this
|
||||||
|
* method optionally.
|
||||||
|
*/
|
||||||
|
virtual void setNormalDatapoolEntriesInvalid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to get pending command. This is useful for devices
|
* Helper function to get pending command. This is useful for devices
|
||||||
* like SPI sensors to identify the last sent command.
|
* like SPI sensors to identify the last sent command.
|
||||||
@ -785,7 +802,6 @@ protected:
|
|||||||
*
|
*
|
||||||
* The submode is left unchanged.
|
* The submode is left unchanged.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @param newMode
|
* @param newMode
|
||||||
*/
|
*/
|
||||||
void setMode(Mode_t newMode);
|
void setMode(Mode_t newMode);
|
||||||
@ -838,8 +854,6 @@ protected:
|
|||||||
virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom);
|
virtual void doTransition(Mode_t modeFrom, Submode_t subModeFrom);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the combination of mode and submode valid?
|
|
||||||
*
|
|
||||||
* @param mode
|
* @param mode
|
||||||
* @param submode
|
* @param submode
|
||||||
* @return
|
* @return
|
||||||
@ -850,13 +864,10 @@ protected:
|
|||||||
Submode_t submode);
|
Submode_t submode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Rmap action for the current step.
|
* Get the communication action for the current step.
|
||||||
*
|
|
||||||
* The step number can be read from #pstStep.
|
* The step number can be read from #pstStep.
|
||||||
*
|
* @return The communication action to execute in this step
|
||||||
* @return The Rmap action to execute in this step
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual CommunicationAction getComAction();
|
virtual CommunicationAction getComAction();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -898,8 +909,8 @@ protected:
|
|||||||
* It gets space in the #IPCStore, copies data there, then sends a raw reply
|
* It gets space in the #IPCStore, copies data there, then sends a raw reply
|
||||||
* containing the store address.
|
* containing the store address.
|
||||||
*
|
*
|
||||||
* This method is virtual, as the STR has a different channel to send
|
* This method is virtual, as devices can have different channels to send
|
||||||
* raw replies and overwrites it accordingly.
|
* raw replies
|
||||||
*
|
*
|
||||||
* @param data data to send
|
* @param data data to send
|
||||||
* @param len length of @c data
|
* @param len length of @c data
|
||||||
@ -918,7 +929,7 @@ protected:
|
|||||||
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
|
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* notify child about mode change
|
* @brief Notify child about mode change.
|
||||||
*/
|
*/
|
||||||
virtual void modeChanged(void);
|
virtual void modeChanged(void);
|
||||||
|
|
||||||
@ -950,8 +961,7 @@ protected:
|
|||||||
DeviceCommandId_t alternateReplyID = 0);
|
DeviceCommandId_t alternateReplyID = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the state of the PCDU switches in the datapool
|
* Get the state of the PCDU switches in the local datapool
|
||||||
*
|
|
||||||
* @return
|
* @return
|
||||||
* - @c PowerSwitchIF::SWITCH_ON if all switches specified
|
* - @c PowerSwitchIF::SWITCH_ON if all switches specified
|
||||||
* by #switches are on
|
* by #switches are on
|
||||||
@ -961,15 +971,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t getStateOfSwitches(void);
|
ReturnValue_t getStateOfSwitches(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* build a list of sids and pass it to the #hkSwitcher
|
* build a list of sids and pass it to the #hkSwitcher
|
||||||
*/
|
*/
|
||||||
|
@ -131,7 +131,7 @@ public:
|
|||||||
// Standard codes used in interpretDeviceReply
|
// Standard codes used in interpretDeviceReply
|
||||||
static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC0); //the device reported, that it did not execute the command
|
static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC0); //the device reported, that it did not execute the command
|
||||||
static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC1);
|
static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC1);
|
||||||
static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC2); //the deviceCommandId reported by scanforReply is unknown
|
static const ReturnValue_t UNKNOWN_DEVICE_REPLY = MAKE_RETURN_CODE(0xC2); //the deviceCommandId reported by scanforReply is unknown
|
||||||
static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC3); //syntax etc is correct but still not ok, eg parameters where none are expected
|
static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC3); //syntax etc is correct but still not ok, eg parameters where none are expected
|
||||||
|
|
||||||
// Standard codes used in buildCommandFromCommand
|
// Standard codes used in buildCommandFromCommand
|
||||||
|
21
doc/README-config.md
Normal file
21
doc/README-config.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
## Configuring the FSFW
|
||||||
|
|
||||||
|
The FSFW can be configured via the `fsfwconfig` folder. A template folder has
|
||||||
|
been provided to have a starting point for this. The folder should be added
|
||||||
|
to the include path.
|
||||||
|
|
||||||
|
|
||||||
|
### Configuring the Event Manager
|
||||||
|
|
||||||
|
The number of allowed subscriptions can be modified with the following
|
||||||
|
parameters:
|
||||||
|
|
||||||
|
``` c++
|
||||||
|
namespace fsfwconfig {
|
||||||
|
//! Configure the allocated pool sizes for the event manager.
|
||||||
|
static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
|
||||||
|
static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120;
|
||||||
|
static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
|
||||||
|
}
|
||||||
|
```
|
50
doc/README-core.md
Normal file
50
doc/README-core.md
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
## FSFW Core Modules
|
||||||
|
|
||||||
|
These core modules provide the most important functionalities of the
|
||||||
|
Flight Software Framework
|
||||||
|
|
||||||
|
### Clock
|
||||||
|
|
||||||
|
* This is a class of static functions that can be used at anytime
|
||||||
|
* Leap Seconds must be set if any time conversions from UTC to other times is used
|
||||||
|
|
||||||
|
### ObjectManager
|
||||||
|
|
||||||
|
* Must be created during program startup
|
||||||
|
* The component which handles all references. All SystemObjects register at this component.
|
||||||
|
* Any SystemObject needs to have a unique ObjectId. Those can be managed like objects::framework_objects.
|
||||||
|
* A reference to an object can be get by calling the following function. T must be the specific Interface you want to call.
|
||||||
|
A nullptr check of the returning Pointer must be done. This function is based on Run-time type information.
|
||||||
|
|
||||||
|
``` c++
|
||||||
|
template <typename T> T* ObjectManagerIF::get( object_id_t id )
|
||||||
|
|
||||||
|
```
|
||||||
|
* A typical way to create all objects on startup is a handing a static produce function to the ObjectManager on creation.
|
||||||
|
By calling objectManager->initialize() the produce function will be called and all SystemObjects will be initialized afterwards.
|
||||||
|
|
||||||
|
### Event Manager
|
||||||
|
|
||||||
|
* Component which allows routing of events
|
||||||
|
* Other objects can subscribe to specific events, ranges of events or all events of an object.
|
||||||
|
* Subscriptions can be done during runtime but should be done during initialization
|
||||||
|
* Amounts of allowed subscriptions can be configured in `FSFWConfig.h`
|
||||||
|
|
||||||
|
### Health Table
|
||||||
|
|
||||||
|
* A component which holds every health state
|
||||||
|
* Provides a thread safe way to access all health states without the need of message exchanges
|
||||||
|
|
||||||
|
### Stores
|
||||||
|
|
||||||
|
* The message based communication can only exchange a few bytes of information inside the message itself. Therefore, additional information can
|
||||||
|
be exchanged with Stores. With this, only the store address must be exchanged in the message.
|
||||||
|
* Internally, the FSFW uses an IPC Store to exchange data between processes. For incoming TCs a TC Store is used. For outgoing TM a TM store is used.
|
||||||
|
* All of them should use the Thread Safe Class storagemanager/PoolManager
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
There are two different types of tasks:
|
||||||
|
* The PeriodicTask just executes objects that are of type ExecutableObjectIF in the order of the insertion to the Tasks.
|
||||||
|
* FixedTimeslotTask executes a list of calls in the order of the given list. This is intended for DeviceHandlers, where polling should be in a defined order. An example can be found in defaultcfg/fsfwconfig/pollingSequence
|
||||||
|
|
1
doc/README-devicehandlers.md
Normal file
1
doc/README-devicehandlers.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
## FSFW DeviceHandlers
|
@ -1,6 +1,5 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
Event.cpp
|
|
||||||
EventManager.cpp
|
EventManager.cpp
|
||||||
EventMessage.cpp
|
EventMessage.cpp
|
||||||
)
|
)
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
#define TIMEVALOPERATIONS_H_
|
#define TIMEVALOPERATIONS_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
timeval& operator+=(timeval& lhs, const timeval& rhs);
|
timeval& operator+=(timeval& lhs, const timeval& rhs);
|
||||||
|
|
||||||
|
5
housekeeping/CMakeLists.txt
Normal file
5
housekeeping/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
target_sources(${LIB_FSFW_NAME}
|
||||||
|
PRIVATE
|
||||||
|
HousekeepingMessage.cpp
|
||||||
|
PeriodicHousekeepingHelper.cpp
|
||||||
|
)
|
@ -22,9 +22,23 @@
|
|||||||
#else
|
#else
|
||||||
#error "Can't decide which end is which!"
|
#error "Can't decide which end is which!"
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
|
||||||
|
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
|
||||||
|
#else
|
||||||
|
#define BYTE_ORDER_SYSTEM BIG_ENDIAN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error __BYTE_ORDER__ not defined
|
#error __BYTE_ORDER__ not defined
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
30
osal/FreeRTOS/CMakeLists.txt
Normal file
30
osal/FreeRTOS/CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
target_sources(${LIB_FSFW_NAME}
|
||||||
|
PRIVATE
|
||||||
|
Clock.cpp
|
||||||
|
FixedTimeslotTask.cpp
|
||||||
|
BinarySemaphore.cpp
|
||||||
|
BinSemaphUsingTask.cpp
|
||||||
|
CountingSemaphore.cpp
|
||||||
|
CountingSemaphUsingTask.cpp
|
||||||
|
MessageQueue.cpp
|
||||||
|
Mutex.cpp
|
||||||
|
MutexFactory.cpp
|
||||||
|
PeriodicTask.cpp
|
||||||
|
QueueFactory.cpp
|
||||||
|
SemaphoreFactory.cpp
|
||||||
|
TaskFactory.cpp
|
||||||
|
Timekeeper.cpp
|
||||||
|
TaskManagement.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# FreeRTOS is required to link the FSFW now. It is recommended to compile
|
||||||
|
# FreeRTOS as a static library and set LIB_OS_NAME to the target name of the
|
||||||
|
# library.
|
||||||
|
if(NOT LIB_OS_NAME)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"FreeRTOS needs to be linked as a target and "
|
||||||
|
"LIB_OS_NAME needs to be set to the target"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(${LIB_FSWFW_NAME} ${LIB_OS_NAME})
|
@ -13,9 +13,9 @@ target_sources(${LIB_FSFW_NAME}
|
|||||||
)
|
)
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
add_definitions(-pthread)
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME}
|
target_link_libraries(${LIB_FSFW_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
rt
|
rt
|
||||||
|
pthread
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
@ -119,7 +119,7 @@ void TcWinUdpPollingTask::setTimeout(double timeoutSeconds) {
|
|||||||
int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO,
|
int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO,
|
||||||
reinterpret_cast<const char*>(&timeoutMs), sizeof(DWORD));
|
reinterpret_cast<const char*>(&timeoutMs), sizeof(DWORD));
|
||||||
if(result == -1) {
|
if(result == -1) {
|
||||||
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting "
|
sif::error << "TcWinUdpPollingTask::TcSocketPollingTask: Setting "
|
||||||
"receive timeout failed with " << strerror(errno) << std::endl;
|
"receive timeout failed with " << strerror(errno) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,17 +128,22 @@ void TcWinUdpPollingTask::handleReadError() {
|
|||||||
int error = WSAGetLastError();
|
int error = WSAGetLastError();
|
||||||
switch(error) {
|
switch(error) {
|
||||||
case(WSANOTINITIALISED): {
|
case(WSANOTINITIALISED): {
|
||||||
sif::info << "TmTcWinUdpBridge::handleReadError: WSANOTINITIALISED: "
|
sif::info << "TcWinUdpPollingTask::handleReadError: WSANOTINITIALISED: "
|
||||||
<< "WSAStartup(...) call " << "necessary" << std::endl;
|
<< "WSAStartup(...) call " << "necessary" << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case(WSAEFAULT): {
|
case(WSAEFAULT): {
|
||||||
sif::info << "TmTcWinUdpBridge::handleReadError: WSADEFAULT: "
|
sif::info << "TcWinUdpPollingTask::handleReadError: WSADEFAULT: "
|
||||||
<< "Bad address " << std::endl;
|
<< "Bad address " << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case(WSAEINVAL): {
|
||||||
|
sif::info << "TcWinUdpPollingTask::handleReadError: WSAEINVAL: "
|
||||||
|
<< "Invalid input parameters. " << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
sif::info << "TmTcWinUdpBridge::handleReadError: Error code: "
|
sif::info << "TcWinUdpPollingTask::handleReadError: Error code: "
|
||||||
<< error << std::endl;
|
<< error << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2,4 +2,6 @@ target_sources(${LIB_FSFW_NAME}
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
ConstStorageAccessor.cpp
|
ConstStorageAccessor.cpp
|
||||||
StorageAccessor.cpp
|
StorageAccessor.cpp
|
||||||
|
LocalPool.cpp
|
||||||
|
PoolManager.cpp
|
||||||
)
|
)
|
@ -1,10 +1,10 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
AbstractTemperatureSensor.cpp
|
AbstractTemperatureSensor.cpp
|
||||||
CoreComponent.cpp
|
|
||||||
Heater.cpp
|
Heater.cpp
|
||||||
RedundantHeater.cpp
|
RedundantHeater.cpp
|
||||||
|
ThermalComponentCore.cpp
|
||||||
ThermalComponent.cpp
|
ThermalComponent.cpp
|
||||||
ThermalModule.cpp
|
ThermalModule.cpp
|
||||||
ThermalMonitor.cpp
|
ThermalMonitorReporter.cpp
|
||||||
)
|
)
|
||||||
|
@ -6,7 +6,12 @@
|
|||||||
#include "../globalfunctions/timevalOperations.h"
|
#include "../globalfunctions/timevalOperations.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
//! Don't use these for time points, type is not large enough for UNIX epoch.
|
//! Don't use these for time points, type is not large enough for UNIX epoch.
|
||||||
using dur_millis_t = uint32_t;
|
using dur_millis_t = uint32_t;
|
||||||
|
Loading…
Reference in New Issue
Block a user