Compare commits
105 Commits
mueller/re
...
docker_d3
Author | SHA1 | Date | |
---|---|---|---|
7de56f189b | |||
541f563683 | |||
28ea71a077 | |||
a044d7d724 | |||
687700cee8 | |||
732b615cb3 | |||
394ce2ec3e | |||
dde96ae220 | |||
c3aaab4b93 | |||
edf1d5ae8d | |||
690991b4b5 | |||
1a294e6a13 | |||
8c4e34153b | |||
b60e4bcb90 | |||
b18410aa63 | |||
7f57a8784a | |||
4b33aa8262 | |||
d47a908117 | |||
fce95e04a8 | |||
fc742e4270 | |||
b5183a19fc | |||
ca453a8f16 | |||
b7c0c07141 | |||
0158102f11 | |||
69859fdbc9 | |||
90bccc744e | |||
ab89108c55 | |||
a682bbe400 | |||
e67fc2ab0d | |||
71ce966531 | |||
6b0f4a159f | |||
4a06b558c1 | |||
6d921f03fd | |||
65bc8213fe | |||
a0ee86ace8 | |||
a07a368272 | |||
cb8a4bbbec | |||
17f54006b8 | |||
395cf9cfa7 | |||
a3c0b441ec | |||
b4132800ae | |||
ad53b48fcb | |||
dee40f9079 | |||
92ec24352f | |||
3f9e459f48 | |||
e0c7f8d51d | |||
eb79386c92 | |||
4542f31c40 | |||
689fb378d8 | |||
98b711a872 | |||
800aa131fa | |||
6983980304 | |||
7c0ba59993 | |||
28873fc87b | |||
24e849ed9c | |||
d8985c141e | |||
7602b15256 | |||
d1a82bceed | |||
7292b02907 | |||
347714d53a | |||
f230fa1617 | |||
93615b100c | |||
e18d3d559e | |||
08ff061d07 | |||
cc351c1066 | |||
664a548c53 | |||
e9895559a3 | |||
eda5b8f593 | |||
e03f55604a | |||
51d7df2dba | |||
12046a2db6 | |||
c697d0f8ab | |||
c7cf8e710d | |||
7dddcdfd55 | |||
261eea381e | |||
e59f1f26bf | |||
f7cde80088 | |||
e60a665de4 | |||
34658ef7db | |||
940fd6f465 | |||
f288d5120d | |||
5a425a1c58 | |||
5e62258aa6 | |||
0b53b4873f | |||
8e2597f609 | |||
dac700b80a | |||
d0fc360697 | |||
576414438c | |||
13cda86d23 | |||
e1dd27b9dd | |||
8e9d4b451c | |||
816550b69c | |||
7fee852dbd | |||
1e7032f89c | |||
8a12a5097e | |||
87e4a57ef7 | |||
0375ee1881 | |||
c8e034d975 | |||
2708b71d77 | |||
6366283ce2 | |||
8dc640c162 | |||
2e4b9bcd7c | |||
aacaf52fd9 | |||
89f83f4e3d | |||
39b7976056 |
.gitignore
.idea/codeStyles
.run
CHANGELOG.mdCMakeLists.txtREADME.mdautomation
hal/src/fsfw_hal
scripts
src
CMakeLists.txt
fsfw
CMakeLists.txt
action
cfdp
container
controller
coordinates
datalinklayer
datapool
datapoollocal
devicehandlers
events
fdir
globalfunctions
health
housekeeping
internalerror
ipc
memory
modes
monitoring
objectmanager
osal
CMakeLists.txt
common
freertos
CMakeLists.txtFixedTimeslotTask.cppFixedTimeslotTask.hFreeRTOSTaskIF.hPeriodicTask.cppPeriodicTask.h
host
CMakeLists.txtFixedTimeslotTask.cppFixedTimeslotTask.hPeriodicTask.cppPeriodicTask.hTaskFactory.cpptaskHelpers.cpptaskHelpers.h
linux
CMakeLists.txtFixedTimeslotTask.cppFixedTimeslotTask.hPeriodicPosixTask.cppPeriodicPosixTask.hPosixThread.hTaskFactory.cpp
rtems
CMakeLists.txtFixedTimeslotTask.cppFixedTimeslotTask.hMessageQueue.cppMessageQueue.hPeriodicTask.cppPeriodicTask.hQueueFactory.cppRTEMSTaskBase.cppRTEMSTaskBase.hTaskFactory.cpp
windows
parameters
power
pus
CMakeLists.txtService11TelecommandScheduling.hService11TelecommandScheduling.tppService5EventReporting.cpp
rmap
serialize
serviceinterface
storagemanager
subsystem
tasks
CMakeLists.txtFixedSlotSequence.cppFixedSlotSequence.hFixedTimeslotTaskBase.cppFixedTimeslotTaskBase.hFixedTimeslotTaskIF.hPeriodicTaskBase.cppPeriodicTaskBase.hPeriodicTaskIF.hTaskFactory.hTypedef.hdefinitions.h
tcdistribution
thermal
timemanager
tmstorage
tmtcpacket
tmtcservices
tests/src/fsfw_tests
integration
unit
hal
internalerror
mocks
storagemanager
testcfg
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,6 +1,14 @@
|
||||
# PyCharm and CLion
|
||||
/.idea/*
|
||||
!/.idea/runConfigurations
|
||||
!/.idea/cmake.xml
|
||||
!/.idea/codeStyles
|
||||
|
||||
# Eclipse
|
||||
.cproject
|
||||
.project
|
||||
.settings
|
||||
.metadata
|
||||
|
||||
/build*
|
||||
/cmake-build*
|
||||
|
14
.idea/codeStyles/Project.xml
generated
Normal file
14
.idea/codeStyles/Project.xml
generated
Normal file
@ -0,0 +1,14 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<clangFormatSettings>
|
||||
<option name="ENABLED" value="true" />
|
||||
</clangFormatSettings>
|
||||
<codeStyleSettings language="CMake">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="0" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
7
.run/fsfw-tests_coverage.run.xml
Normal file
7
.run/fsfw-tests_coverage.run.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="fsfw-tests_coverage" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="fsfw-tests" TARGET_NAME="fsfw-tests_coverage" CONFIG_NAME="Debug Unittest" RUN_TARGET_PROJECT_NAME="fsfw-tests" RUN_TARGET_NAME="fsfw-tests">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
7
.run/fsfw.run.xml
Normal file
7
.run/fsfw.run.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="fsfw" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="fsfw-tests" TARGET_NAME="fsfw" CONFIG_NAME="Debug Unittest" RUN_TARGET_PROJECT_NAME="fsfw-tests" RUN_TARGET_NAME="fsfw-tests">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
41
CHANGELOG.md
41
CHANGELOG.md
@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## Changes
|
||||
|
||||
- Renamed auto-formatting script to `auto-formatter.sh` and made it more robust.
|
||||
If `cmake-format` is installed, it will also auto-format the `CMakeLists.txt` files now.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/625
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/626
|
||||
- Bump C++ required version to C++17. Every project which uses the FSFW and every modern
|
||||
compiler supports it
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622
|
||||
@ -43,6 +47,38 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
|
||||
|
||||
### Task Module Refactoring
|
||||
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/636
|
||||
|
||||
**Refactoring general task code**
|
||||
|
||||
- There was a lot of duplicate/boilerplate code inside the individual task IF OSAL implementations.
|
||||
Remove it by introducing base classes `PeriodicTaskBase` and `FixedTimeslotTaskBase`.
|
||||
|
||||
**Refactor PeriodicTaskIF**
|
||||
|
||||
- Convert `virtual ReturnValue_t addComponent(object_id_t object)` to
|
||||
`virtual ReturnValue_t addComponent(object_id_t object, uint8_t opCode = 0)`, allowing to pass
|
||||
the operation code passed to `performOperation`. Updated API taking
|
||||
an `ExecutableObjectIF` accordingly
|
||||
|
||||
**Refactor FixedTimeslotTaskIF**
|
||||
|
||||
- Add additional `addSlot` function which takes an `ExecutableObjectIF` pointer and its Object ID
|
||||
|
||||
**Refactor FixedSequenceSlot**
|
||||
|
||||
- Introduce typedef `CustomCheckFunc` for `ReturnValue_t (*customCheckFunction)(const SlotList&)`.
|
||||
- Convert `ReturnValue_t (*customCheckFunction)(const SlotList&)` to
|
||||
`ReturnValue_t (*customCheckFunction)(const SlotList&, void*)`, allowing arbitrary user arguments
|
||||
for the custom checker
|
||||
|
||||
**Linux Task Module**
|
||||
|
||||
- Use composition instead of inheritance for the `PeriodicPosixTask` and make the `PosixTask` a
|
||||
member of the class
|
||||
|
||||
### HAL
|
||||
|
||||
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||
@ -84,6 +120,11 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
||||
|
||||
## Additions
|
||||
|
||||
- Added options for CI/CD builds: `FSFW_CICD_BUILD`. This allows the source code to know
|
||||
whether it is running in CI/CD
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/623
|
||||
- Basic `clion` support: Update `.gitignore` and add some basic run configurations
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/625
|
||||
- LTO support: Allow using LTO/IPO by setting `FSFW_ENABLE_LTO=1`. CMake is able to detect whether
|
||||
the user compiler supports IPO/LPO. LTO is on by default now. Most modern compilers support it,
|
||||
can make good use of it and it usually makes the code faster and/or smaller.
|
||||
|
@ -71,7 +71,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
|
||||
20
|
||||
CACHE STRING "ETL library major version requirement")
|
||||
set(FSFW_ETL_LIB_VERSION
|
||||
${FSFW_ETL_LIB_MAJOR_VERSION}.27.3
|
||||
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
|
||||
CACHE STRING "ETL library exact version requirement")
|
||||
set(FSFW_ETL_LINK_TARGET etl::etl)
|
||||
|
||||
@ -105,6 +105,7 @@ endif()
|
||||
|
||||
option(FSFW_BUILD_UNITTESTS
|
||||
"Build unittest binary in addition to static library" OFF)
|
||||
option(FSFW_CICD_BUILD "Build for CI/CD. This can disable problematic test" OFF)
|
||||
option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF)
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON)
|
||||
|
@ -99,7 +99,7 @@ add and link against the FSFW library in general.
|
||||
|
||||
4. Link against the FSFW library
|
||||
|
||||
```cmake
|
||||
```sh
|
||||
target_link_libraries(${YourProjectName} PRIVATE fsfw)
|
||||
```
|
||||
|
||||
@ -131,7 +131,7 @@ default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF
|
||||
You can use the following commands inside the `fsfw` folder to set up the build system
|
||||
|
||||
```sh
|
||||
mkdir build-Unittest && cd build-Unittest
|
||||
mkdir build-tests && cd build-tests
|
||||
cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host -DCMAKE_BUILD_TYPE=Debug ..
|
||||
```
|
||||
|
||||
|
@ -12,3 +12,9 @@ RUN git clone https://github.com/catchorg/Catch2.git && \
|
||||
git checkout v3.0.0-preview5 && \
|
||||
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
||||
cmake --build build/ --target install
|
||||
|
||||
RUN git clone https://github.com/ETLCPP/etl.git && \
|
||||
cd etl && \
|
||||
git checkout 20.28.0 && \
|
||||
cmake -B build . && \
|
||||
cmake --install build/
|
||||
|
2
automation/Jenkinsfile
vendored
2
automation/Jenkinsfile
vendored
@ -14,7 +14,7 @@ pipeline {
|
||||
stage('Configure') {
|
||||
steps {
|
||||
dir(BUILDDIR) {
|
||||
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..'
|
||||
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
ReturnValue_t result = gpioComIF->pullLow(gpioId);
|
||||
result = gpioComIF->pullLow(gpioId);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
|
@ -10,6 +10,10 @@
|
||||
#include "stm32h7xx_hal.h"
|
||||
#include "stm32h7xx_hal_spi.h"
|
||||
|
||||
#ifndef STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION
|
||||
#define STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION 1
|
||||
#endif
|
||||
|
||||
enum class TransferStates { IDLE, WAIT, SUCCESS, FAILURE };
|
||||
|
||||
class GyroL3GD20H {
|
||||
|
@ -4,9 +4,10 @@ if [[ ! -f README.md ]]; then
|
||||
fi
|
||||
|
||||
cmake_fmt="cmake-format"
|
||||
file_selectors="-iname CMakeLists.txt"
|
||||
if command -v ${cmake_fmt} &> /dev/null; then
|
||||
cmake_fmt_cmd="${cmake_fmt} -i CMakeLists.txt"
|
||||
eval ${cmake_fmt_cmd}
|
||||
${cmake_fmt} -i CMakeLists.txt
|
||||
find ./src ${file_selectors} | xargs ${cmake_fmt} -i
|
||||
else
|
||||
echo "No ${cmake_fmt} tool found, not formatting CMake files"
|
||||
fi
|
||||
@ -14,9 +15,9 @@ fi
|
||||
cpp_format="clang-format"
|
||||
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
|
||||
if command -v ${cpp_format} &> /dev/null; then
|
||||
find ./src ${file_selectors} | xargs clang-format --style=file -i
|
||||
find ./hal ${file_selectors} | xargs clang-format --style=file -i
|
||||
find ./tests ${file_selectors} | xargs clang-format --style=file -i
|
||||
find ./src ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||
find ./hal ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||
find ./tests ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||
else
|
||||
echo "No ${cpp_format} tool found, not formatting C++/C files"
|
||||
fi
|
||||
|
@ -1,9 +1,6 @@
|
||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
target_include_directories(${LIB_FSFW_NAME}
|
||||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_subdirectory(fsfw)
|
||||
|
@ -1,6 +1,4 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
version.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE version.cpp)
|
||||
|
||||
# Core
|
||||
|
||||
@ -37,22 +35,22 @@ add_subdirectory(tmtcservices)
|
||||
# Optional
|
||||
|
||||
if(FSFW_ADD_MONITORING)
|
||||
add_subdirectory(monitoring)
|
||||
add_subdirectory(monitoring)
|
||||
endif()
|
||||
if(FSFW_ADD_PUS)
|
||||
add_subdirectory(pus)
|
||||
add_subdirectory(pus)
|
||||
endif()
|
||||
if(FSFW_ADD_TMSTORAGE)
|
||||
add_subdirectory(tmstorage)
|
||||
add_subdirectory(tmstorage)
|
||||
endif()
|
||||
if(FSFW_ADD_COORDINATES)
|
||||
add_subdirectory(coordinates)
|
||||
add_subdirectory(coordinates)
|
||||
endif()
|
||||
if(FSFW_ADD_RMAP)
|
||||
add_subdirectory(rmap)
|
||||
add_subdirectory(rmap)
|
||||
endif()
|
||||
if(FSFW_ADD_DATALINKLAYER)
|
||||
add_subdirectory(datalinklayer)
|
||||
add_subdirectory(datalinklayer)
|
||||
endif()
|
||||
|
||||
# OSAL
|
||||
|
@ -1,7 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ActionHelper.cpp
|
||||
ActionMessage.cpp
|
||||
CommandActionHelper.cpp
|
||||
SimpleActionHelper.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE ActionHelper.cpp ActionMessage.cpp
|
||||
CommandActionHelper.cpp SimpleActionHelper.cpp)
|
||||
|
@ -1,7 +1,4 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
CFDPHandler.cpp
|
||||
CFDPMessage.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE CFDPHandler.cpp CFDPMessage.cpp)
|
||||
|
||||
add_subdirectory(pdu)
|
||||
add_subdirectory(tlv)
|
||||
|
@ -1,32 +1,30 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
PduConfig.cpp
|
||||
VarLenField.cpp
|
||||
HeaderSerializer.cpp
|
||||
HeaderDeserializer.cpp
|
||||
FileDirectiveDeserializer.cpp
|
||||
FileDirectiveSerializer.cpp
|
||||
|
||||
AckInfo.cpp
|
||||
AckPduSerializer.cpp
|
||||
AckPduDeserializer.cpp
|
||||
EofInfo.cpp
|
||||
EofPduSerializer.cpp
|
||||
EofPduDeserializer.cpp
|
||||
NakInfo.cpp
|
||||
NakPduSerializer.cpp
|
||||
NakPduDeserializer.cpp
|
||||
FinishedInfo.cpp
|
||||
FinishedPduSerializer.cpp
|
||||
FinishedPduDeserializer.cpp
|
||||
MetadataInfo.cpp
|
||||
MetadataPduSerializer.cpp
|
||||
MetadataPduDeserializer.cpp
|
||||
KeepAlivePduSerializer.cpp
|
||||
KeepAlivePduDeserializer.cpp
|
||||
PromptPduSerializer.cpp
|
||||
PromptPduDeserializer.cpp
|
||||
|
||||
FileDataSerializer.cpp
|
||||
FileDataDeserializer.cpp
|
||||
FileDataInfo.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE PduConfig.cpp
|
||||
VarLenField.cpp
|
||||
HeaderSerializer.cpp
|
||||
HeaderDeserializer.cpp
|
||||
FileDirectiveDeserializer.cpp
|
||||
FileDirectiveSerializer.cpp
|
||||
AckInfo.cpp
|
||||
AckPduSerializer.cpp
|
||||
AckPduDeserializer.cpp
|
||||
EofInfo.cpp
|
||||
EofPduSerializer.cpp
|
||||
EofPduDeserializer.cpp
|
||||
NakInfo.cpp
|
||||
NakPduSerializer.cpp
|
||||
NakPduDeserializer.cpp
|
||||
FinishedInfo.cpp
|
||||
FinishedPduSerializer.cpp
|
||||
FinishedPduDeserializer.cpp
|
||||
MetadataInfo.cpp
|
||||
MetadataPduSerializer.cpp
|
||||
MetadataPduDeserializer.cpp
|
||||
KeepAlivePduSerializer.cpp
|
||||
KeepAlivePduDeserializer.cpp
|
||||
PromptPduSerializer.cpp
|
||||
PromptPduDeserializer.cpp
|
||||
FileDataSerializer.cpp
|
||||
FileDataDeserializer.cpp
|
||||
FileDataInfo.cpp)
|
||||
|
@ -1,10 +1,10 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
EntityIdTlv.cpp
|
||||
FilestoreRequestTlv.cpp
|
||||
FilestoreResponseTlv.cpp
|
||||
Lv.cpp
|
||||
Tlv.cpp
|
||||
FlowLabelTlv.cpp
|
||||
MessageToUserTlv.cpp
|
||||
FaultHandlerOverrideTlv.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE EntityIdTlv.cpp
|
||||
FilestoreRequestTlv.cpp
|
||||
FilestoreResponseTlv.cpp
|
||||
Lv.cpp
|
||||
Tlv.cpp
|
||||
FlowLabelTlv.cpp
|
||||
MessageToUserTlv.cpp
|
||||
FaultHandlerOverrideTlv.cpp)
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
SharedRingBuffer.cpp
|
||||
SimpleRingBuffer.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE SharedRingBuffer.cpp
|
||||
SimpleRingBuffer.cpp)
|
||||
|
@ -1,4 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
ControllerBase.cpp
|
||||
ExtendedControllerBase.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE ControllerBase.cpp
|
||||
ExtendedControllerBase.cpp)
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
CoordinateTransformations.cpp
|
||||
Sgp4Propagator.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE CoordinateTransformations.cpp
|
||||
Sgp4Propagator.cpp)
|
||||
|
@ -1,12 +1,11 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
Clcw.cpp
|
||||
DataLinkLayer.cpp
|
||||
Farm1StateLockout.cpp
|
||||
Farm1StateOpen.cpp
|
||||
Farm1StateWait.cpp
|
||||
MapPacketExtraction.cpp
|
||||
TcTransferFrame.cpp
|
||||
TcTransferFrameLocal.cpp
|
||||
VirtualChannelReception.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE Clcw.cpp
|
||||
DataLinkLayer.cpp
|
||||
Farm1StateLockout.cpp
|
||||
Farm1StateOpen.cpp
|
||||
Farm1StateWait.cpp
|
||||
MapPacketExtraction.cpp
|
||||
TcTransferFrame.cpp
|
||||
TcTransferFrameLocal.cpp
|
||||
VirtualChannelReception.cpp)
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
PoolDataSetBase.cpp
|
||||
PoolEntry.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE PoolDataSetBase.cpp PoolEntry.cpp)
|
||||
|
@ -1,10 +1,6 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
LocalDataPoolManager.cpp
|
||||
LocalDataSet.cpp
|
||||
LocalPoolDataSetBase.cpp
|
||||
LocalPoolObjectBase.cpp
|
||||
SharedLocalDataSet.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE LocalDataPoolManager.cpp LocalDataSet.cpp LocalPoolDataSetBase.cpp
|
||||
LocalPoolObjectBase.cpp SharedLocalDataSet.cpp)
|
||||
|
||||
add_subdirectory(internal)
|
@ -696,9 +696,9 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
/* Configuration error */
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalDataPoolManager::performHkOperation: HK generation failed." << std::endl;
|
||||
sif::warning << "LocalDataPoolManager::performPeriodicHkOperation: HK generation failed." << std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalDataPoolManager::performHkOperation: HK generation failed.\n");
|
||||
sif::printWarning("LocalDataPoolManager::performPeriodicHkOperation: HK generation failed.\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
HasLocalDpIFUserAttorney.cpp
|
||||
HasLocalDpIFManagerAttorney.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE HasLocalDpIFUserAttorney.cpp
|
||||
HasLocalDpIFManagerAttorney.cpp)
|
||||
|
@ -1,11 +1,10 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
AssemblyBase.cpp
|
||||
ChildHandlerBase.cpp
|
||||
ChildHandlerFDIR.cpp
|
||||
DeviceHandlerBase.cpp
|
||||
DeviceHandlerFailureIsolation.cpp
|
||||
DeviceHandlerMessage.cpp
|
||||
DeviceTmReportingWrapper.cpp
|
||||
HealthDevice.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE AssemblyBase.cpp
|
||||
ChildHandlerBase.cpp
|
||||
ChildHandlerFDIR.cpp
|
||||
DeviceHandlerBase.cpp
|
||||
DeviceHandlerFailureIsolation.cpp
|
||||
DeviceHandlerMessage.cpp
|
||||
DeviceTmReportingWrapper.cpp
|
||||
HealthDevice.cpp)
|
||||
|
@ -1,6 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
EventManager.cpp
|
||||
EventMessage.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE EventManager.cpp EventMessage.cpp)
|
||||
|
||||
add_subdirectory(eventmatching)
|
||||
|
@ -1,7 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
EventIdRangeMatcher.cpp
|
||||
EventMatchTree.cpp
|
||||
ReporterRangeMatcher.cpp
|
||||
SeverityRangeMatcher.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE EventIdRangeMatcher.cpp EventMatchTree.cpp
|
||||
ReporterRangeMatcher.cpp SeverityRangeMatcher.cpp)
|
||||
|
@ -27,6 +27,7 @@ enum : uint8_t {
|
||||
PUS_SERVICE_6 = 86,
|
||||
PUS_SERVICE_8 = 88,
|
||||
PUS_SERVICE_9 = 89,
|
||||
PUS_SERVICE_11 = 91,
|
||||
PUS_SERVICE_17 = 97,
|
||||
PUS_SERVICE_23 = 103,
|
||||
MGM_LIS3MDL = 106,
|
||||
|
@ -1,6 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
EventCorrelation.cpp
|
||||
FailureIsolationBase.cpp
|
||||
FaultCounter.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE EventCorrelation.cpp FailureIsolationBase.cpp
|
||||
FaultCounter.cpp)
|
||||
|
@ -1,13 +1,12 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
arrayprinter.cpp
|
||||
AsciiConverter.cpp
|
||||
CRC.cpp
|
||||
DleEncoder.cpp
|
||||
PeriodicOperationDivider.cpp
|
||||
timevalOperations.cpp
|
||||
Type.cpp
|
||||
bitutility.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE arrayprinter.cpp
|
||||
AsciiConverter.cpp
|
||||
CRC.cpp
|
||||
DleEncoder.cpp
|
||||
PeriodicOperationDivider.cpp
|
||||
timevalOperations.cpp
|
||||
Type.cpp
|
||||
bitutility.cpp)
|
||||
|
||||
add_subdirectory(math)
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
QuaternionOperations.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE QuaternionOperations.cpp)
|
||||
|
@ -1,6 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
HealthHelper.cpp
|
||||
HealthMessage.cpp
|
||||
HealthTable.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE HealthHelper.cpp HealthMessage.cpp
|
||||
HealthTable.cpp)
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
HousekeepingMessage.cpp
|
||||
PeriodicHousekeepingHelper.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE HousekeepingMessage.cpp
|
||||
PeriodicHousekeepingHelper.cpp)
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
InternalErrorReporter.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE InternalErrorReporter.cpp)
|
||||
|
@ -1,6 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
CommandMessage.cpp
|
||||
CommandMessageCleaner.cpp
|
||||
MessageQueueMessage.cpp
|
||||
MessageQueueBase.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE CommandMessage.cpp CommandMessageCleaner.cpp
|
||||
MessageQueueMessage.cpp MessageQueueBase.cpp)
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
MemoryHelper.cpp
|
||||
MemoryMessage.cpp
|
||||
GenericFileSystemMessage.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE MemoryHelper.cpp MemoryMessage.cpp
|
||||
GenericFileSystemMessage.cpp)
|
||||
|
@ -1,5 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ModeHelper.cpp
|
||||
ModeMessage.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE ModeHelper.cpp ModeMessage.cpp)
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
LimitViolationReporter.cpp
|
||||
MonitoringMessage.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE LimitViolationReporter.cpp
|
||||
MonitoringMessage.cpp)
|
||||
|
@ -1,5 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ObjectManager.cpp
|
||||
SystemObject.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE ObjectManager.cpp SystemObject.cpp)
|
||||
|
@ -14,6 +14,7 @@ enum framework_objects : object_id_t {
|
||||
PUS_SERVICE_5_EVENT_REPORTING = 0x53000005,
|
||||
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
||||
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
||||
PUS_SERVICE_11_TC_SCHEDULER = 0x53000011,
|
||||
PUS_SERVICE_17_TEST = 0x53000017,
|
||||
PUS_SERVICE_20_PARAMETERS = 0x53000020,
|
||||
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
|
||||
|
@ -1,34 +1,32 @@
|
||||
# Check the OS_FSFW variable
|
||||
if(FSFW_OSAL MATCHES "freertos")
|
||||
add_subdirectory(freertos)
|
||||
add_subdirectory(freertos)
|
||||
elseif(FSFW_OSAL MATCHES "rtems")
|
||||
add_subdirectory(rtems)
|
||||
add_subdirectory(rtems)
|
||||
elseif(FSFW_OSAL MATCHES "linux")
|
||||
add_subdirectory(linux)
|
||||
add_subdirectory(linux)
|
||||
elseif(FSFW_OSAL MATCHES "host")
|
||||
add_subdirectory(host)
|
||||
if (WIN32)
|
||||
add_subdirectory(windows)
|
||||
elseif(UNIX)
|
||||
# We still need to pull in some Linux specific sources
|
||||
target_sources(${LIB_FSFW_NAME} PUBLIC
|
||||
linux/tcpipHelpers.cpp
|
||||
)
|
||||
endif ()
|
||||
add_subdirectory(host)
|
||||
if(WIN32)
|
||||
add_subdirectory(windows)
|
||||
elseif(UNIX)
|
||||
# We still need to pull in some Linux specific sources
|
||||
target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp)
|
||||
endif()
|
||||
|
||||
else()
|
||||
|
||||
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
|
||||
# Not set. Assumuing this is a host build, try to determine host OS
|
||||
if (WIN32)
|
||||
add_subdirectory(host)
|
||||
add_subdirectory(windows)
|
||||
elseif (UNIX)
|
||||
add_subdirectory(linux)
|
||||
else ()
|
||||
# MacOS or other OSes have not been tested yet / are not supported.
|
||||
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
|
||||
endif()
|
||||
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
|
||||
# Not set. Assumuing this is a host build, try to determine host OS
|
||||
if(WIN32)
|
||||
add_subdirectory(host)
|
||||
add_subdirectory(windows)
|
||||
elseif(UNIX)
|
||||
add_subdirectory(linux)
|
||||
else()
|
||||
# MacOS or other OSes have not been tested yet / are not supported.
|
||||
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
|
@ -1,17 +1,10 @@
|
||||
if(DEFINED WIN32 OR DEFINED UNIX)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
tcpipCommon.cpp
|
||||
TcpIpBase.cpp
|
||||
UdpTcPollingTask.cpp
|
||||
UdpTmTcBridge.cpp
|
||||
TcpTmTcServer.cpp
|
||||
TcpTmTcBridge.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE tcpipCommon.cpp TcpIpBase.cpp UdpTcPollingTask.cpp
|
||||
UdpTmTcBridge.cpp TcpTmTcServer.cpp TcpTmTcBridge.cpp)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
wsock32
|
||||
ws2_32
|
||||
)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE wsock32 ws2_32)
|
||||
endif()
|
@ -109,8 +109,8 @@ TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
||||
using namespace tcpip;
|
||||
// If a connection is accepted, the corresponding socket will be assigned to the new socket
|
||||
socket_t connSocket = 0;
|
||||
// sockaddr clientSockAddr = {};
|
||||
// socklen_t connectorSockAddrLen = 0;
|
||||
sockaddr clientSockAddr = {};
|
||||
socklen_t connectorSockAddrLen = 0;
|
||||
int retval = 0;
|
||||
|
||||
// Listen for connection requests permanently for lifetime of program
|
||||
@ -121,8 +121,7 @@ TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
||||
continue;
|
||||
}
|
||||
|
||||
// connSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen);
|
||||
connSocket = accept(listenerTcpSocket, nullptr, nullptr);
|
||||
connSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen);
|
||||
|
||||
if (connSocket == INVALID_SOCKET) {
|
||||
handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500);
|
||||
@ -137,6 +136,7 @@ TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
||||
if (retval != 0) {
|
||||
handleError(Protocol::TCP, ErrorSources::SHUTDOWN_CALL);
|
||||
}
|
||||
|
||||
closeSocket(connSocket);
|
||||
connSocket = 0;
|
||||
}
|
||||
|
@ -1,32 +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
|
||||
QueueMapManager.cpp
|
||||
)
|
||||
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
|
||||
QueueMapManager.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(STATUS
|
||||
"LIB_OS_NAME is empty. Make sure to include the FreeRTOS header path properly."
|
||||
)
|
||||
message(
|
||||
STATUS
|
||||
"LIB_OS_NAME is empty. Make sure to include the FreeRTOS header path properly."
|
||||
)
|
||||
else()
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${LIB_OS_NAME}
|
||||
)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_OS_NAME})
|
||||
endif()
|
||||
|
@ -1,27 +1,23 @@
|
||||
#include "fsfw/osal/freertos/FixedTimeslotTask.h"
|
||||
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
|
||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
|
||||
|
||||
FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority,
|
||||
TaskStackSize setStack, TaskPeriod overallPeriod,
|
||||
void (*setDeadlineMissedFunc)())
|
||||
: started(false), handle(nullptr), pst(overallPeriod * 1000) {
|
||||
TaskStackSize setStack, TaskPeriod period,
|
||||
TaskDeadlineMissedFunction dlmFunc_)
|
||||
: FixedTimeslotTaskBase(period, dlmFunc_), started(false), handle(nullptr) {
|
||||
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
|
||||
xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
|
||||
// All additional attributes are applied to the object.
|
||||
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
||||
}
|
||||
|
||||
FixedTimeslotTask::~FixedTimeslotTask() {}
|
||||
FixedTimeslotTask::~FixedTimeslotTask() = default;
|
||||
|
||||
void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
||||
// The argument is re-interpreted as FixedTimeslotTask. The Task object is
|
||||
// global, so it is found from any place.
|
||||
FixedTimeslotTask* originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
||||
auto* originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
||||
/* Task should not start until explicitly requested,
|
||||
* but in FreeRTOS, tasks start as soon as they are created if the scheduler
|
||||
* is running but not if the scheduler is not running.
|
||||
@ -32,26 +28,18 @@ void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
||||
* can continue */
|
||||
|
||||
if (not originalTask->started) {
|
||||
vTaskSuspend(NULL);
|
||||
vTaskSuspend(nullptr);
|
||||
}
|
||||
|
||||
originalTask->taskFunctionality();
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "Polling task " << originalTask->handle << " returned from taskFunctionality."
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printDebug("Polling task returned from taskFunctionality\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::missedDeadlineCounter() {
|
||||
FixedTimeslotTask::deadlineMissedCount++;
|
||||
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines."
|
||||
<< std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||
started = true;
|
||||
|
||||
@ -63,31 +51,12 @@ ReturnValue_t FixedTimeslotTask::startTask() {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
int8_t executionStep) {
|
||||
ExecutableObjectIF* handler = ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
|
||||
if (handler != nullptr) {
|
||||
pst.addSlot(componentId, slotTimeMs, executionStep, handler, this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst"
|
||||
<< std::endl;
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); }
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::checkSequence() const { return pst.checkSequence(); }
|
||||
|
||||
void FixedTimeslotTask::taskFunctionality() {
|
||||
[[noreturn]] void FixedTimeslotTask::taskFunctionality() {
|
||||
// A local iterator for the Polling Sequence Table is created to find the
|
||||
// start time for the first entry.
|
||||
auto slotListIter = pst.current;
|
||||
auto slotListIter = pollingSeqTable.current;
|
||||
|
||||
pst.intializeSequenceAfterTaskCreation();
|
||||
pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||
|
||||
// The start time for the first entry is read.
|
||||
uint32_t intervalMs = slotListIter->pollingTimeMs;
|
||||
@ -108,10 +77,10 @@ void FixedTimeslotTask::taskFunctionality() {
|
||||
/* Enter the loop that defines the task behavior. */
|
||||
for (;;) {
|
||||
// The component for this slot is executed and the next one is chosen.
|
||||
this->pst.executeAndAdvance();
|
||||
if (not pst.slotFollowsImmediately()) {
|
||||
this->pollingSeqTable.executeAndAdvance();
|
||||
if (not pollingSeqTable.slotFollowsImmediately()) {
|
||||
// Get the interval till execution of the next slot.
|
||||
intervalMs = this->pst.getIntervalToPreviousSlotMs();
|
||||
intervalMs = this->pollingSeqTable.getIntervalToPreviousSlotMs();
|
||||
interval = pdMS_TO_TICKS(intervalMs);
|
||||
|
||||
#if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10
|
||||
@ -132,8 +101,8 @@ void FixedTimeslotTask::taskFunctionality() {
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::handleMissedDeadline() {
|
||||
if (deadlineMissedFunc != nullptr) {
|
||||
this->deadlineMissedFunc();
|
||||
if (dlmFunc != nullptr) {
|
||||
dlmFunc();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,11 +4,11 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "FreeRTOSTaskIF.h"
|
||||
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||
#include "fsfw/tasks/FixedTimeslotTaskIF.h"
|
||||
#include "fsfw/tasks/Typedef.h"
|
||||
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||
#include "fsfw/tasks/definitions.h"
|
||||
#include "task.h"
|
||||
|
||||
class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
||||
class FixedTimeslotTask : public FixedTimeslotTaskBase, public FreeRTOSTaskIF {
|
||||
public:
|
||||
/**
|
||||
* Keep in mind that you need to call before vTaskStartScheduler()!
|
||||
@ -23,7 +23,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
||||
* @return Pointer to the newly created task.
|
||||
*/
|
||||
FixedTimeslotTask(TaskName name, TaskPriority setPriority, TaskStackSize setStack,
|
||||
TaskPeriod overallPeriod, void (*setDeadlineMissedFunc)());
|
||||
TaskPeriod overallPeriod, TaskDeadlineMissedFunction dlmFunc);
|
||||
|
||||
/**
|
||||
* @brief The destructor of the class.
|
||||
@ -32,26 +32,9 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
||||
* initialization for the PST and the device handlers. This is done by
|
||||
* calling the PST's destructor.
|
||||
*/
|
||||
virtual ~FixedTimeslotTask(void);
|
||||
~FixedTimeslotTask() override;
|
||||
|
||||
ReturnValue_t startTask(void);
|
||||
/**
|
||||
* This static function can be used as #deadlineMissedFunc.
|
||||
* It counts missedDeadlines and prints the number of missed deadlines
|
||||
* every 10th time.
|
||||
*/
|
||||
static void missedDeadlineCounter();
|
||||
/**
|
||||
* A helper variable to count missed deadlines.
|
||||
*/
|
||||
static uint32_t deadlineMissedCount;
|
||||
|
||||
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
int8_t executionStep) override;
|
||||
|
||||
uint32_t getPeriodMs() const override;
|
||||
|
||||
ReturnValue_t checkSequence() const override;
|
||||
ReturnValue_t startTask() override;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
@ -61,17 +44,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
||||
bool started;
|
||||
TaskHandle_t handle;
|
||||
|
||||
FixedSlotSequence pst;
|
||||
|
||||
/**
|
||||
* @brief This attribute holds a function pointer that is executed when
|
||||
* a deadline was missed.
|
||||
* @details
|
||||
* Another function may be announced to determine the actions to perform
|
||||
* when a deadline was missed. Currently, only one function for missing
|
||||
* any deadline is allowed. If not used, it shall be declared NULL.
|
||||
*/
|
||||
void (*deadlineMissedFunc)(void);
|
||||
/**
|
||||
* @brief This is the entry point for a new task.
|
||||
* @details
|
||||
@ -88,7 +60,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
||||
* It links the functionalities provided by FixedSlotSequence with the
|
||||
* OS's System Calls to keep the timing of the periods.
|
||||
*/
|
||||
void taskFunctionality(void);
|
||||
[[noreturn]] void taskFunctionality();
|
||||
|
||||
void handleMissedDeadline();
|
||||
};
|
||||
|
@ -6,11 +6,11 @@
|
||||
|
||||
class FreeRTOSTaskIF {
|
||||
public:
|
||||
virtual ~FreeRTOSTaskIF() {}
|
||||
virtual ~FreeRTOSTaskIF() = default;
|
||||
virtual TaskHandle_t getTaskHandle() = 0;
|
||||
|
||||
protected:
|
||||
bool checkMissedDeadline(const TickType_t xLastWakeTime, const TickType_t interval) {
|
||||
static 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. */
|
||||
|
@ -5,27 +5,28 @@
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
|
||||
PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
|
||||
TaskPeriod setPeriod, TaskDeadlineMissedFunction deadlineMissedFunc)
|
||||
: started(false), handle(NULL), period(setPeriod), deadlineMissedFunc(deadlineMissedFunc) {
|
||||
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_)
|
||||
: PeriodicTaskBase(setPeriod, dlmFunc_), started(false), handle(nullptr) {
|
||||
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
|
||||
BaseType_t status = xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
|
||||
if (status != pdPASS) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "PeriodicTask Insufficient heap memory remaining. "
|
||||
"Status: "
|
||||
sif::debug << "PeriodicTask::PeriodicTask Insufficient heap memory remaining. Status: "
|
||||
<< status << std::endl;
|
||||
#else
|
||||
sif::printDebug("PeriodicTask::PeriodicTask: Insufficient heap memory remaining. Status: %d\n",
|
||||
status);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
PeriodicTask::~PeriodicTask(void) {
|
||||
// Do not delete objects, we were responsible for ptrs only.
|
||||
}
|
||||
// Do not delete objects, we were responsible for ptrs only.
|
||||
PeriodicTask::~PeriodicTask() = default;
|
||||
|
||||
void PeriodicTask::taskEntryPoint(void* argument) {
|
||||
// The argument is re-interpreted as PeriodicTask. The Task object is
|
||||
// global, so it is found from any place.
|
||||
PeriodicTask* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||
auto* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||
/* Task should not start until explicitly requested,
|
||||
* but in FreeRTOS, tasks start as soon as they are created if the scheduler
|
||||
* is running but not if the scheduler is not running.
|
||||
@ -36,7 +37,7 @@ void PeriodicTask::taskEntryPoint(void* argument) {
|
||||
* can continue */
|
||||
|
||||
if (not originalTask->started) {
|
||||
vTaskSuspend(NULL);
|
||||
vTaskSuspend(nullptr);
|
||||
}
|
||||
|
||||
originalTask->taskFunctionality();
|
||||
@ -62,13 +63,11 @@ ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void PeriodicTask::taskFunctionality() {
|
||||
[[noreturn]] void PeriodicTask::taskFunctionality() {
|
||||
TickType_t xLastWakeTime;
|
||||
const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.);
|
||||
|
||||
for (auto const& object : objectList) {
|
||||
object->initializeAfterTaskCreation();
|
||||
}
|
||||
initObjsAfterTaskCreation();
|
||||
|
||||
/* The xLastWakeTime variable needs to be initialized with the current tick
|
||||
count. Note that this is the only time the variable is written to
|
||||
@ -77,8 +76,8 @@ void PeriodicTask::taskFunctionality() {
|
||||
xLastWakeTime = xTaskGetTickCount();
|
||||
/* Enter the loop that defines the task behavior. */
|
||||
for (;;) {
|
||||
for (auto const& object : objectList) {
|
||||
object->performOperation();
|
||||
for (auto const& objectPair : objectList) {
|
||||
objectPair.first->performOperation(objectPair.second);
|
||||
}
|
||||
|
||||
#if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10
|
||||
@ -95,32 +94,10 @@ void PeriodicTask::taskFunctionality() {
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
||||
return addComponent(newObject);
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
|
||||
if (object == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
||||
"it implement ExecutableObjectIF"
|
||||
<< std::endl;
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
objectList.push_back(object);
|
||||
object->setTaskIF(this);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
uint32_t PeriodicTask::getPeriodMs() const { return period * 1000; }
|
||||
|
||||
TaskHandle_t PeriodicTask::getTaskHandle() { return handle; }
|
||||
|
||||
void PeriodicTask::handleMissedDeadline() {
|
||||
if (deadlineMissedFunc != nullptr) {
|
||||
this->deadlineMissedFunc();
|
||||
if (dlmFunc != nullptr) {
|
||||
dlmFunc();
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "FreeRTOSTaskIF.h"
|
||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||
#include "fsfw/tasks/Typedef.h"
|
||||
#include "fsfw/tasks/PeriodicTaskBase.h"
|
||||
#include "fsfw/tasks/definitions.h"
|
||||
#include "task.h"
|
||||
|
||||
class ExecutableObjectIF;
|
||||
@ -17,7 +17,7 @@ class ExecutableObjectIF;
|
||||
* periodic activities of multiple objects.
|
||||
* @ingroup task_handling
|
||||
*/
|
||||
class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
||||
class PeriodicTask : public PeriodicTaskBase, public FreeRTOSTaskIF {
|
||||
public:
|
||||
/**
|
||||
* Keep in Mind that you need to call before this vTaskStartScheduler()!
|
||||
@ -43,7 +43,7 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
||||
* @brief Currently, the executed object's lifetime is not coupled with
|
||||
* the task object's lifetime, so the destructor is empty.
|
||||
*/
|
||||
virtual ~PeriodicTask(void);
|
||||
~PeriodicTask() override;
|
||||
|
||||
/**
|
||||
* @brief The method to start the task.
|
||||
@ -53,27 +53,6 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
||||
* to the system call.
|
||||
*/
|
||||
ReturnValue_t startTask() override;
|
||||
/**
|
||||
* Adds an object to the list of objects to be executed.
|
||||
* The objects are executed in the order added.
|
||||
* @param object Id of the object to add.
|
||||
* @return
|
||||
* -@c RETURN_OK on success
|
||||
* -@c RETURN_FAILED if the object could not be added.
|
||||
*/
|
||||
ReturnValue_t addComponent(object_id_t object) override;
|
||||
|
||||
/**
|
||||
* Adds an object to the list of objects to be executed.
|
||||
* The objects are executed in the order added.
|
||||
* @param object Id of the object to add.
|
||||
* @return
|
||||
* -@c RETURN_OK on success
|
||||
* -@c RETURN_FAILED if the object could not be added.
|
||||
*/
|
||||
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
|
||||
|
||||
uint32_t getPeriodMs() const override;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
@ -83,28 +62,6 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
||||
bool started;
|
||||
TaskHandle_t handle;
|
||||
|
||||
//! Typedef for the List of objects.
|
||||
typedef std::vector<ExecutableObjectIF*> ObjectList;
|
||||
/**
|
||||
* @brief This attribute holds a list of objects to be executed.
|
||||
*/
|
||||
ObjectList objectList;
|
||||
/**
|
||||
* @brief The period of the task.
|
||||
* @details
|
||||
* The period determines the frequency of the task's execution.
|
||||
* It is expressed in clock ticks.
|
||||
*/
|
||||
TaskPeriod period;
|
||||
/**
|
||||
* @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, then nothing happens on missing the deadline.
|
||||
* The deadline is equal to the next execution of the periodic task.
|
||||
*/
|
||||
void (*deadlineMissedFunc)(void);
|
||||
/**
|
||||
* @brief This is the function executed in the new task's context.
|
||||
* @details
|
||||
@ -125,7 +82,7 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
||||
* the next period.
|
||||
* On missing the deadline, the deadlineMissedFunction is executed.
|
||||
*/
|
||||
void taskFunctionality(void);
|
||||
[[noreturn]] void taskFunctionality();
|
||||
|
||||
void handleMissedDeadline();
|
||||
};
|
||||
|
@ -1,27 +1,23 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
Clock.cpp
|
||||
FixedTimeslotTask.cpp
|
||||
MessageQueue.cpp
|
||||
Mutex.cpp
|
||||
MutexFactory.cpp
|
||||
PeriodicTask.cpp
|
||||
QueueFactory.cpp
|
||||
QueueMapManager.cpp
|
||||
SemaphoreFactory.cpp
|
||||
TaskFactory.cpp
|
||||
taskHelpers.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE Clock.cpp
|
||||
FixedTimeslotTask.cpp
|
||||
MessageQueue.cpp
|
||||
Mutex.cpp
|
||||
MutexFactory.cpp
|
||||
PeriodicTask.cpp
|
||||
QueueFactory.cpp
|
||||
QueueMapManager.cpp
|
||||
SemaphoreFactory.cpp
|
||||
TaskFactory.cpp
|
||||
taskHelpers.cpp)
|
||||
|
||||
if(UNIX)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${CMAKE_THREAD_LIBS_INIT})
|
||||
if(NOT APPLE)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
rt
|
||||
)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE rt)
|
||||
endif()
|
||||
|
||||
endif()
|
@ -3,9 +3,7 @@
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include "fsfw/ipc/MutexFactory.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/osal/host/FixedTimeslotTask.h"
|
||||
#include "fsfw/osal/host/Mutex.h"
|
||||
#include "fsfw/osal/host/taskHelpers.h"
|
||||
#include "fsfw/platform.h"
|
||||
@ -22,12 +20,8 @@
|
||||
|
||||
FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority,
|
||||
TaskStackSize setStack, TaskPeriod setPeriod,
|
||||
void (*setDeadlineMissedFunc)())
|
||||
: started(false),
|
||||
pollingSeqTable(setPeriod * 1000),
|
||||
taskName(name),
|
||||
period(setPeriod),
|
||||
deadlineMissedFunc(setDeadlineMissedFunc) {
|
||||
TaskDeadlineMissedFunction dlmFunc_)
|
||||
: FixedTimeslotTaskBase(setPeriod, dlmFunc_), started(false), taskName(name) {
|
||||
// It is propably possible to set task priorities by using the native
|
||||
// task handles for Windows / Linux
|
||||
mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this);
|
||||
@ -39,7 +33,7 @@ FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority,
|
||||
tasks::insertTaskName(mainThread.get_id(), taskName);
|
||||
}
|
||||
|
||||
FixedTimeslotTask::~FixedTimeslotTask(void) {
|
||||
FixedTimeslotTask::~FixedTimeslotTask() {
|
||||
// Do not delete objects, we were responsible for ptrs only.
|
||||
terminateThread = true;
|
||||
if (mainThread.joinable()) {
|
||||
@ -48,7 +42,7 @@ FixedTimeslotTask::~FixedTimeslotTask(void) {
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
||||
FixedTimeslotTask* originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
||||
auto* originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
||||
|
||||
if (not originalTask->started) {
|
||||
// we have to suspend/block here until the task is started.
|
||||
@ -81,7 +75,9 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::taskFunctionality() {
|
||||
pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||
ReturnValue_t result = pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||
// Ignore returnvalue for now
|
||||
static_cast<void>(result);
|
||||
|
||||
// A local iterator for the Polling Sequence Table is created to
|
||||
// find the start time for the first entry.
|
||||
@ -106,37 +102,15 @@ void FixedTimeslotTask::taskFunctionality() {
|
||||
// we need to wait before executing the current slot
|
||||
// this gives us the time to wait:
|
||||
interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs());
|
||||
delayForInterval(¤tStartTime, interval);
|
||||
// TODO deadline missed check
|
||||
if (not delayForInterval(¤tStartTime, interval)) {
|
||||
if (dlmFunc != nullptr) {
|
||||
dlmFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
int8_t executionStep) {
|
||||
ExecutableObjectIF* executableObject =
|
||||
ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
|
||||
if (executableObject != nullptr) {
|
||||
pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, executableObject, this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Component " << std::hex << "0x" << componentId
|
||||
<< "not found, "
|
||||
"not adding it to PST.."
|
||||
<< std::dec << std::endl;
|
||||
#else
|
||||
sif::printError("Component 0x%08x not found, not adding it to PST..\n",
|
||||
static_cast<unsigned int>(componentId));
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::checkSequence() const { return pollingSeqTable.checkSequence(); }
|
||||
|
||||
uint32_t FixedTimeslotTask::getPeriodMs() const { return period * 1000; }
|
||||
|
||||
bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) {
|
||||
bool shouldDelay = false;
|
||||
// Get current wakeup time
|
||||
|
@ -6,10 +6,10 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../tasks/FixedSlotSequence.h"
|
||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
||||
#include "../../tasks/Typedef.h"
|
||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||
#include "fsfw/tasks/definitions.h"
|
||||
|
||||
class ExecutableObjectIF;
|
||||
|
||||
@ -19,7 +19,7 @@ class ExecutableObjectIF;
|
||||
* @details
|
||||
* @ingroup task_handling
|
||||
*/
|
||||
class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
||||
class FixedTimeslotTask : public FixedTimeslotTaskBase {
|
||||
public:
|
||||
/**
|
||||
* @brief Standard constructor of the class.
|
||||
@ -39,7 +39,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
||||
* @brief Currently, the executed object's lifetime is not coupled with
|
||||
* the task object's lifetime, so the destructor is empty.
|
||||
*/
|
||||
virtual ~FixedTimeslotTask(void);
|
||||
~FixedTimeslotTask() override;
|
||||
|
||||
/**
|
||||
* @brief The method to start the task.
|
||||
@ -48,56 +48,22 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
||||
* The address of the task object is passed as an argument
|
||||
* to the system call.
|
||||
*/
|
||||
ReturnValue_t startTask(void);
|
||||
ReturnValue_t startTask() override;
|
||||
|
||||
/**
|
||||
* Add timeslot to the polling sequence table.
|
||||
* @param componentId
|
||||
* @param slotTimeMs
|
||||
* @param executionStep
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
|
||||
|
||||
ReturnValue_t checkSequence() const override;
|
||||
|
||||
uint32_t getPeriodMs() const;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms);
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
protected:
|
||||
using chron_ms = std::chrono::milliseconds;
|
||||
|
||||
bool started;
|
||||
//!< Typedef for the List of objects.
|
||||
typedef std::vector<ExecutableObjectIF*> ObjectList;
|
||||
|
||||
std::thread mainThread;
|
||||
std::atomic<bool> terminateThread{false};
|
||||
|
||||
//! Polling sequence table which contains the object to execute
|
||||
//! and information like the timeslots and the passed execution step.
|
||||
FixedSlotSequence pollingSeqTable;
|
||||
|
||||
std::condition_variable initCondition;
|
||||
std::mutex initMutex;
|
||||
std::string taskName;
|
||||
/**
|
||||
* @brief The period of the task.
|
||||
* @details
|
||||
* The period determines the frequency of the task's execution.
|
||||
* It is expressed in clock ticks.
|
||||
*/
|
||||
TaskPeriod period;
|
||||
|
||||
/**
|
||||
* @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, then nothing happens on missing the deadline.
|
||||
* The deadline is equal to the next execution of the periodic task.
|
||||
*/
|
||||
void (*deadlineMissedFunc)(void);
|
||||
/**
|
||||
* @brief This is the function executed in the new task's context.
|
||||
* @details
|
||||
@ -117,9 +83,9 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
||||
* the checkAndRestartPeriod system call blocks the task until the next
|
||||
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
||||
*/
|
||||
void taskFunctionality(void);
|
||||
void taskFunctionality();
|
||||
|
||||
bool delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval);
|
||||
static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval);
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */
|
||||
|
@ -3,13 +3,10 @@
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include "fsfw/ipc/MutexFactory.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/osal/host/Mutex.h"
|
||||
#include "fsfw/osal/host/taskHelpers.h"
|
||||
#include "fsfw/platform.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
|
||||
#if defined(PLATFORM_WIN)
|
||||
#include <processthreadsapi.h>
|
||||
@ -20,8 +17,8 @@
|
||||
#endif
|
||||
|
||||
PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
|
||||
TaskPeriod setPeriod, void (*setDeadlineMissedFunc)())
|
||||
: started(false), taskName(name), period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) {
|
||||
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_)
|
||||
: PeriodicTaskBase(setPeriod, dlmFunc_), started(false), taskName(name) {
|
||||
// It is probably possible to set task priorities by using the native
|
||||
// task handles for Windows / Linux
|
||||
mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this);
|
||||
@ -33,7 +30,7 @@ PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStack
|
||||
tasks::insertTaskName(mainThread.get_id(), taskName);
|
||||
}
|
||||
|
||||
PeriodicTask::~PeriodicTask(void) {
|
||||
PeriodicTask::~PeriodicTask() {
|
||||
// Do not delete objects, we were responsible for ptrs only.
|
||||
terminateThread = true;
|
||||
if (mainThread.joinable()) {
|
||||
@ -42,7 +39,7 @@ PeriodicTask::~PeriodicTask(void) {
|
||||
}
|
||||
|
||||
void PeriodicTask::taskEntryPoint(void* argument) {
|
||||
PeriodicTask* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||
auto* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||
|
||||
if (not originalTask->started) {
|
||||
// we have to suspend/block here until the task is started.
|
||||
@ -75,47 +72,27 @@ ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) {
|
||||
}
|
||||
|
||||
void PeriodicTask::taskFunctionality() {
|
||||
for (const auto& object : objectList) {
|
||||
object->initializeAfterTaskCreation();
|
||||
}
|
||||
initObjsAfterTaskCreation();
|
||||
|
||||
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};
|
||||
|
||||
/* Enter the loop that defines the task behavior. */
|
||||
for (;;) {
|
||||
if (terminateThread.load()) {
|
||||
break;
|
||||
}
|
||||
for (const auto& object : objectList) {
|
||||
object->performOperation();
|
||||
for (const auto& objectPair : objectList) {
|
||||
objectPair.first->performOperation(objectPair.second);
|
||||
}
|
||||
if (not delayForInterval(¤tStartTime, periodChrono)) {
|
||||
if (deadlineMissedFunc != nullptr) {
|
||||
this->deadlineMissedFunc();
|
||||
if (dlmFunc != nullptr) {
|
||||
this->dlmFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
||||
return addComponent(newObject);
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
|
||||
if (object == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
object->setTaskIF(this);
|
||||
objectList.push_back(object);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
uint32_t PeriodicTask::getPeriodMs() const { return period * 1000; }
|
||||
|
||||
bool PeriodicTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) {
|
||||
bool shouldDelay = false;
|
||||
// Get current wakeup time
|
||||
|
@ -6,9 +6,9 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../tasks/PeriodicTaskIF.h"
|
||||
#include "../../tasks/Typedef.h"
|
||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||
#include "fsfw/tasks/PeriodicTaskBase.h"
|
||||
#include "fsfw/tasks/definitions.h"
|
||||
|
||||
class ExecutableObjectIF;
|
||||
|
||||
@ -19,7 +19,7 @@ class ExecutableObjectIF;
|
||||
*
|
||||
* @ingroup task_handling
|
||||
*/
|
||||
class PeriodicTask : public PeriodicTaskIF {
|
||||
class PeriodicTask : public PeriodicTaskBase {
|
||||
public:
|
||||
/**
|
||||
* @brief Standard constructor of the class.
|
||||
@ -34,12 +34,12 @@ class PeriodicTask : public PeriodicTaskIF {
|
||||
* assigned.
|
||||
*/
|
||||
PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
|
||||
TaskPeriod setPeriod, void (*setDeadlineMissedFunc)());
|
||||
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc);
|
||||
/**
|
||||
* @brief Currently, the executed object's lifetime is not coupled with
|
||||
* the task object's lifetime, so the destructor is empty.
|
||||
*/
|
||||
virtual ~PeriodicTask(void);
|
||||
~PeriodicTask() override;
|
||||
|
||||
/**
|
||||
* @brief The method to start the task.
|
||||
@ -48,63 +48,20 @@ class PeriodicTask : public PeriodicTaskIF {
|
||||
* The address of the task object is passed as an argument
|
||||
* to the system call.
|
||||
*/
|
||||
ReturnValue_t startTask(void);
|
||||
/**
|
||||
* Adds an object to the list of objects to be executed.
|
||||
* The objects are executed in the order added.
|
||||
* @param object Id of the object to add.
|
||||
* @return
|
||||
* -@c RETURN_OK on success
|
||||
* -@c RETURN_FAILED if the object could not be added.
|
||||
*/
|
||||
ReturnValue_t addComponent(object_id_t object);
|
||||
ReturnValue_t startTask() override;
|
||||
|
||||
/**
|
||||
* Adds an object to the list of objects to be executed.
|
||||
* The objects are executed in the order added.
|
||||
* @param object pointer to the object to add.
|
||||
* @return
|
||||
* -@c RETURN_OK on success
|
||||
* -@c RETURN_FAILED if the object could not be added.
|
||||
*/
|
||||
ReturnValue_t addComponent(ExecutableObjectIF* object);
|
||||
|
||||
uint32_t getPeriodMs() const;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms);
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
protected:
|
||||
using chron_ms = std::chrono::milliseconds;
|
||||
bool started;
|
||||
//!< Typedef for the List of objects.
|
||||
typedef std::vector<ExecutableObjectIF*> ObjectList;
|
||||
std::thread mainThread;
|
||||
std::atomic<bool> terminateThread{false};
|
||||
|
||||
/**
|
||||
* @brief This attribute holds a list of objects to be executed.
|
||||
*/
|
||||
ObjectList objectList;
|
||||
|
||||
std::condition_variable initCondition;
|
||||
std::mutex initMutex;
|
||||
std::string taskName;
|
||||
/**
|
||||
* @brief The period of the task.
|
||||
* @details
|
||||
* The period determines the frequency of the task's execution.
|
||||
* It is expressed in clock ticks.
|
||||
*/
|
||||
TaskPeriod period;
|
||||
/**
|
||||
* @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, then nothing happens on missing the deadline.
|
||||
* The deadline is equal to the next execution of the periodic task.
|
||||
*/
|
||||
void (*deadlineMissedFunc)(void);
|
||||
|
||||
/**
|
||||
* @brief This is the function executed in the new task's context.
|
||||
* @details
|
||||
@ -124,9 +81,9 @@ class PeriodicTask : public PeriodicTaskIF {
|
||||
* the checkAndRestartPeriod system call blocks the task until the next
|
||||
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
||||
*/
|
||||
void taskFunctionality(void);
|
||||
void taskFunctionality();
|
||||
|
||||
bool delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval);
|
||||
static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval);
|
||||
};
|
||||
|
||||
#endif /* PERIODICTASK_H_ */
|
||||
#endif /* FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ */
|
||||
|
@ -14,9 +14,9 @@ TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
||||
// Not used for the host implementation for now because C++ thread abstraction is used
|
||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0;
|
||||
|
||||
TaskFactory::TaskFactory() {}
|
||||
TaskFactory::TaskFactory() = default;
|
||||
|
||||
TaskFactory::~TaskFactory() {}
|
||||
TaskFactory::~TaskFactory() = default;
|
||||
|
||||
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
std::mutex nameMapLock;
|
||||
std::map<std::thread::id, std::string> taskNameMap;
|
||||
|
||||
ReturnValue_t tasks::insertTaskName(std::thread::id threadId, std::string taskName) {
|
||||
ReturnValue_t tasks::insertTaskName(std::thread::id threadId, const std::string& taskName) {
|
||||
std::lock_guard<std::mutex> lg(nameMapLock);
|
||||
auto returnPair = taskNameMap.emplace(threadId, taskName);
|
||||
if (not returnPair.second) {
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
namespace tasks {
|
||||
|
||||
ReturnValue_t insertTaskName(std::thread::id threadId, std::string taskName);
|
||||
ReturnValue_t insertTaskName(std::thread::id threadId, const std::string& taskName);
|
||||
std::string getTaskName(std::thread::id threadId);
|
||||
|
||||
} // namespace tasks
|
||||
|
@ -1,29 +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
|
||||
tcpipHelpers.cpp
|
||||
unixUtility.cpp
|
||||
)
|
||||
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
|
||||
tcpipHelpers.cpp
|
||||
unixUtility.cpp)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
target_link_libraries(${LIB_FSFW_NAME} PUBLIC
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PUBLIC ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
if(NOT APPLE)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PUBLIC
|
||||
rt
|
||||
)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PUBLIC rt)
|
||||
endif()
|
||||
|
@ -1,22 +1,20 @@
|
||||
#include "fsfw/osal/linux/FixedTimeslotTask.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <climits>
|
||||
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
|
||||
|
||||
FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_,
|
||||
uint32_t periodMs_)
|
||||
: PosixThread(name_, priority_, stackSize_), pst(periodMs_), started(false) {}
|
||||
|
||||
FixedTimeslotTask::~FixedTimeslotTask() {}
|
||||
FixedTimeslotTask::FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
|
||||
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_)
|
||||
: FixedTimeslotTaskBase(periodSeconds_, dlmFunc_),
|
||||
posixThread(name_, priority_, stackSize_),
|
||||
started(false) {}
|
||||
|
||||
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
||||
// The argument is re-interpreted as PollingTask.
|
||||
FixedTimeslotTask* originalTask(reinterpret_cast<FixedTimeslotTask*>(arg));
|
||||
auto* originalTask(reinterpret_cast<FixedTimeslotTask*>(arg));
|
||||
// The task's functionality is called.
|
||||
originalTask->taskFunctionality();
|
||||
return nullptr;
|
||||
@ -24,7 +22,7 @@ void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||
started = true;
|
||||
createTask(&taskEntryPoint, this);
|
||||
posixThread.createTask(&taskEntryPoint, this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
@ -32,63 +30,36 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
||||
return PosixThread::sleep((uint64_t)ms * 1000000);
|
||||
}
|
||||
|
||||
uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); }
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
int8_t executionStep) {
|
||||
ExecutableObjectIF* executableObject =
|
||||
ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
|
||||
if (executableObject != nullptr) {
|
||||
pst.addSlot(componentId, slotTimeMs, executionStep, executableObject, this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst"
|
||||
<< std::dec << std::endl;
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::checkSequence() const { return pst.checkSequence(); }
|
||||
|
||||
void FixedTimeslotTask::taskFunctionality() {
|
||||
[[noreturn]] void FixedTimeslotTask::taskFunctionality() {
|
||||
// Like FreeRTOS pthreads are running as soon as they are created
|
||||
if (!started) {
|
||||
suspend();
|
||||
posixThread.suspend();
|
||||
}
|
||||
|
||||
pst.intializeSequenceAfterTaskCreation();
|
||||
// Returnvalue ignored for now
|
||||
static_cast<void>(pollingSeqTable.intializeSequenceAfterTaskCreation());
|
||||
|
||||
// The start time for the first entry is read.
|
||||
uint64_t lastWakeTime = getCurrentMonotonicTimeMs();
|
||||
uint64_t interval = pst.getIntervalToNextSlotMs();
|
||||
uint64_t lastWakeTime = PosixThread::getCurrentMonotonicTimeMs();
|
||||
uint32_t interval = 0;
|
||||
|
||||
// The task's "infinite" inner loop is entered.
|
||||
while (1) {
|
||||
if (pst.slotFollowsImmediately()) {
|
||||
while (true) {
|
||||
if (pollingSeqTable.slotFollowsImmediately()) {
|
||||
// Do nothing
|
||||
} else {
|
||||
// The interval for the next polling slot is selected.
|
||||
interval = this->pst.getIntervalToPreviousSlotMs();
|
||||
interval = pollingSeqTable.getIntervalToPreviousSlotMs();
|
||||
// The period is checked and restarted with the new interval.
|
||||
// If the deadline was missed, the deadlineMissedFunc is called.
|
||||
if (!PosixThread::delayUntil(&lastWakeTime, interval)) {
|
||||
// No time left on timer -> we missed the deadline
|
||||
missedDeadlineCounter();
|
||||
if(dlmFunc != nullptr){
|
||||
dlmFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
// The device handler for this slot is executed and the next one is chosen.
|
||||
this->pst.executeAndAdvance();
|
||||
}
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::missedDeadlineCounter() {
|
||||
FixedTimeslotTask::deadlineMissedCount++;
|
||||
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines."
|
||||
<< std::endl;
|
||||
#endif
|
||||
pollingSeqTable.executeAndAdvance();
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,12 @@
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../../tasks/FixedSlotSequence.h"
|
||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
||||
#include "PosixThread.h"
|
||||
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||
#include "fsfw/tasks/definitions.h"
|
||||
|
||||
class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread {
|
||||
class FixedTimeslotTask : public FixedTimeslotTaskBase {
|
||||
public:
|
||||
/**
|
||||
* Create a generic periodic task.
|
||||
@ -21,29 +22,13 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread {
|
||||
* @param period_
|
||||
* @param deadlineMissedFunc_
|
||||
*/
|
||||
FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, uint32_t periodMs_);
|
||||
virtual ~FixedTimeslotTask();
|
||||
FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
|
||||
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_);
|
||||
~FixedTimeslotTask() override = default;
|
||||
|
||||
virtual ReturnValue_t startTask();
|
||||
ReturnValue_t startTask() override;
|
||||
|
||||
virtual ReturnValue_t sleepFor(uint32_t ms);
|
||||
|
||||
virtual uint32_t getPeriodMs() const;
|
||||
|
||||
virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
|
||||
|
||||
virtual ReturnValue_t checkSequence() const;
|
||||
|
||||
/**
|
||||
* This static function can be used as #deadlineMissedFunc.
|
||||
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
|
||||
*/
|
||||
static void missedDeadlineCounter();
|
||||
|
||||
/**
|
||||
* A helper variable to count missed deadlines.
|
||||
*/
|
||||
static uint32_t deadlineMissedCount;
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
@ -53,9 +38,12 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread {
|
||||
* It links the functionalities provided by FixedSlotSequence with the
|
||||
* OS's System Calls to keep the timing of the periods.
|
||||
*/
|
||||
virtual void taskFunctionality();
|
||||
[[noreturn]] virtual void taskFunctionality();
|
||||
|
||||
private:
|
||||
PosixThread posixThread;
|
||||
bool started;
|
||||
|
||||
/**
|
||||
* @brief This is the entry point in a new thread.
|
||||
*
|
||||
@ -68,9 +56,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread {
|
||||
* arbitrary data.
|
||||
*/
|
||||
static void* taskEntryPoint(void* arg);
|
||||
FixedSlotSequence pst;
|
||||
|
||||
bool started;
|
||||
};
|
||||
|
||||
#endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */
|
||||
|
@ -1,86 +1,54 @@
|
||||
#include "fsfw/osal/linux/PeriodicPosixTask.h"
|
||||
#include "PeriodicPosixTask.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
|
||||
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_,
|
||||
uint32_t period_, void(deadlineMissedFunc_)())
|
||||
: PosixThread(name_, priority_, stackSize_),
|
||||
objectList(),
|
||||
started(false),
|
||||
periodMs(period_),
|
||||
deadlineMissedFunc(deadlineMissedFunc_) {}
|
||||
|
||||
PeriodicPosixTask::~PeriodicPosixTask() {
|
||||
// Not Implemented
|
||||
}
|
||||
TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_)
|
||||
: PeriodicTaskBase(period_, dlmFunc_),
|
||||
posixThread(name_, priority_, stackSize_),
|
||||
started(false) {}
|
||||
|
||||
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
||||
// The argument is re-interpreted as PollingTask.
|
||||
PeriodicPosixTask* originalTask(reinterpret_cast<PeriodicPosixTask*>(arg));
|
||||
auto* originalTask(reinterpret_cast<PeriodicPosixTask*>(arg));
|
||||
// The task's functionality is called.
|
||||
originalTask->taskFunctionality();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) {
|
||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
||||
return addComponent(newObject);
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object) {
|
||||
if (object == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
||||
<< " it implements ExecutableObjectIF!" << std::endl;
|
||||
#else
|
||||
sif::printError(
|
||||
"PeriodicTask::addComponent: Invalid object. Make sure it "
|
||||
"implements ExecutableObjectIF!\n");
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
objectList.push_back(object);
|
||||
object->setTaskIF(this);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) {
|
||||
return PosixThread::sleep((uint64_t)ms * 1000000);
|
||||
return PosixThread::sleep(static_cast<uint64_t>(ms) * 1000000);
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicPosixTask::startTask(void) {
|
||||
ReturnValue_t PeriodicPosixTask::startTask() {
|
||||
if (isEmpty()) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
started = true;
|
||||
PosixThread::createTask(&taskEntryPoint, this);
|
||||
posixThread.createTask(&taskEntryPoint, this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void PeriodicPosixTask::taskFunctionality(void) {
|
||||
[[noreturn]] void PeriodicPosixTask::taskFunctionality() {
|
||||
if (not started) {
|
||||
suspend();
|
||||
posixThread.suspend();
|
||||
}
|
||||
|
||||
for (auto const& object : objectList) {
|
||||
object->initializeAfterTaskCreation();
|
||||
}
|
||||
initObjsAfterTaskCreation();
|
||||
|
||||
uint64_t lastWakeTime = getCurrentMonotonicTimeMs();
|
||||
uint64_t lastWakeTime = PosixThread::getCurrentMonotonicTimeMs();
|
||||
uint64_t periodMs = getPeriodMs();
|
||||
// The task's "infinite" inner loop is entered.
|
||||
while (1) {
|
||||
for (auto const& object : objectList) {
|
||||
object->performOperation();
|
||||
while (true) {
|
||||
for (auto const& objOpCodePair : objectList) {
|
||||
objOpCodePair.first->performOperation(objOpCodePair.second);
|
||||
}
|
||||
|
||||
if (not PosixThread::delayUntil(&lastWakeTime, periodMs)) {
|
||||
if (this->deadlineMissedFunc != nullptr) {
|
||||
this->deadlineMissedFunc();
|
||||
if (dlmFunc != nullptr) {
|
||||
dlmFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t PeriodicPosixTask::getPeriodMs() const { return periodMs; }
|
||||
|
@ -3,12 +3,13 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../tasks/ExecutableObjectIF.h"
|
||||
#include "../../tasks/PeriodicTaskIF.h"
|
||||
#include "PosixThread.h"
|
||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tasks/PeriodicTaskBase.h"
|
||||
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||
|
||||
class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
||||
class PeriodicPosixTask : public PeriodicTaskBase {
|
||||
public:
|
||||
/**
|
||||
* Create a generic periodic task.
|
||||
@ -22,9 +23,9 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
||||
* @param period_
|
||||
* @param deadlineMissedFunc_
|
||||
*/
|
||||
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, uint32_t period_,
|
||||
void (*deadlineMissedFunc_)());
|
||||
virtual ~PeriodicPosixTask();
|
||||
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_,
|
||||
TaskDeadlineMissedFunction dlmFunc_);
|
||||
~PeriodicPosixTask() override = default;
|
||||
|
||||
/**
|
||||
* @brief The method to start the task.
|
||||
@ -34,42 +35,17 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
||||
* to the system call.
|
||||
*/
|
||||
ReturnValue_t startTask() override;
|
||||
/**
|
||||
* Adds an object to the list of objects to be executed.
|
||||
* The objects are executed in the order added.
|
||||
* @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) override;
|
||||
|
||||
/**
|
||||
* Adds an object to the list of objects to be executed.
|
||||
* The objects are executed in the order added.
|
||||
* @param object pointer to the object to add.
|
||||
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
||||
*/
|
||||
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
|
||||
|
||||
uint32_t getPeriodMs() const override;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
private:
|
||||
typedef std::vector<ExecutableObjectIF*> ObjectList; //!< Typedef for the List of objects.
|
||||
/**
|
||||
* @brief This attribute holds a list of objects to be executed.
|
||||
*/
|
||||
ObjectList objectList;
|
||||
PosixThread posixThread;
|
||||
|
||||
/**
|
||||
* @brief Flag to indicate that the task was started and is allowed to run
|
||||
*/
|
||||
bool started;
|
||||
|
||||
/**
|
||||
* @brief Period of the task in milliseconds
|
||||
*/
|
||||
uint32_t periodMs;
|
||||
/**
|
||||
* @brief The function containing the actual functionality of the task.
|
||||
* @details The method sets and starts
|
||||
@ -78,7 +54,7 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
||||
* will be blocked until the next period. On missing the deadline, the deadlineMissedFunction is
|
||||
* executed.
|
||||
*/
|
||||
virtual void taskFunctionality(void);
|
||||
[[noreturn]] virtual void taskFunctionality();
|
||||
/**
|
||||
* @brief This is the entry point in a new thread.
|
||||
*
|
||||
@ -86,14 +62,6 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
||||
* of the child class. Needs a valid pointer to the derived class.
|
||||
*/
|
||||
static void* taskEntryPoint(void* arg);
|
||||
/**
|
||||
* @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, then nothing happens on missing the deadline. The deadline is equal to the next execution
|
||||
* of the periodic task.
|
||||
*/
|
||||
void (*deadlineMissedFunc)();
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ */
|
||||
|
@ -35,6 +35,21 @@ class PosixThread {
|
||||
*/
|
||||
void resume();
|
||||
|
||||
/**
|
||||
* @brief Function that has to be called by derived class because the
|
||||
* derived class pointer has to be valid as argument.
|
||||
* @details
|
||||
* This function creates a pthread with the given parameters. As the
|
||||
* function requires a pointer to the derived object it has to be called
|
||||
* after the this pointer of the derived object is valid.
|
||||
* Sets the taskEntryPoint as function to be called by new a thread.
|
||||
* @param fnc_ Function which will be executed by the thread.
|
||||
* @param arg_
|
||||
* argument of the taskEntryPoint function, needs to be this pointer
|
||||
* of derived class
|
||||
*/
|
||||
void createTask(void* (*fnc_)(void*), void* arg_);
|
||||
|
||||
/**
|
||||
* Delay function similar to FreeRtos delayUntil function
|
||||
*
|
||||
@ -55,21 +70,6 @@ class PosixThread {
|
||||
protected:
|
||||
pthread_t thread;
|
||||
|
||||
/**
|
||||
* @brief Function that has to be called by derived class because the
|
||||
* derived class pointer has to be valid as argument.
|
||||
* @details
|
||||
* This function creates a pthread with the given parameters. As the
|
||||
* function requires a pointer to the derived object it has to be called
|
||||
* after the this pointer of the derived object is valid.
|
||||
* Sets the taskEntryPoint as function to be called by new a thread.
|
||||
* @param fnc_ Function which will be executed by the thread.
|
||||
* @param arg_
|
||||
* argument of the taskEntryPoint function, needs to be this pointer
|
||||
* of derived class
|
||||
*/
|
||||
void createTask(void* (*fnc_)(void*), void* arg_);
|
||||
|
||||
private:
|
||||
char name[PTHREAD_MAX_NAMELEN];
|
||||
int priority;
|
||||
|
@ -8,21 +8,22 @@
|
||||
// TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
||||
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
||||
|
||||
TaskFactory::~TaskFactory() {}
|
||||
TaskFactory::~TaskFactory() = default;
|
||||
|
||||
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
||||
|
||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(
|
||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||
return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_ * 1000,
|
||||
return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
||||
deadLineMissedFunction_);
|
||||
}
|
||||
|
||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
|
||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_ * 1000);
|
||||
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
||||
deadLineMissedFunction_);
|
||||
}
|
||||
|
||||
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
||||
|
@ -1,20 +1,17 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
Clock.cpp
|
||||
CpuUsage.cpp
|
||||
InitTask.cpp
|
||||
InternalErrorCodes.cpp
|
||||
MessageQueue.cpp
|
||||
PeriodicTask.cpp
|
||||
Mutex.cpp
|
||||
MutexFactory.cpp
|
||||
FixedTimeslotTask.cpp
|
||||
QueueFactory.cpp
|
||||
RtemsBasic.cpp
|
||||
RTEMSTaskBase.cpp
|
||||
TaskFactory.cpp
|
||||
BinarySemaphore.cpp
|
||||
SemaphoreFactory.cpp
|
||||
)
|
||||
|
||||
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE Clock.cpp
|
||||
CpuUsage.cpp
|
||||
InitTask.cpp
|
||||
InternalErrorCodes.cpp
|
||||
MessageQueue.cpp
|
||||
PeriodicTask.cpp
|
||||
Mutex.cpp
|
||||
MutexFactory.cpp
|
||||
FixedTimeslotTask.cpp
|
||||
QueueFactory.cpp
|
||||
RtemsBasic.cpp
|
||||
RTEMSTaskBase.cpp
|
||||
TaskFactory.cpp
|
||||
BinarySemaphore.cpp
|
||||
SemaphoreFactory.cpp)
|
||||
|
@ -1,42 +1,32 @@
|
||||
#include "fsfw/osal/rtems/FixedTimeslotTask.h"
|
||||
|
||||
#include <rtems/bspIo.h>
|
||||
#include <rtems/io.h>
|
||||
#include <rtems/rtems/ratemon.h>
|
||||
#include <rtems/rtems/status.h>
|
||||
#include <rtems/rtems/tasks.h>
|
||||
#include <rtems/rtems/types.h>
|
||||
#include <sys/_stdint.h>
|
||||
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/objectmanager/SystemObjectIF.h"
|
||||
#include "fsfw/osal/rtems/RtemsBasic.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/tasks/FixedSequenceSlot.h"
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <list>
|
||||
|
||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
||||
|
||||
FixedTimeslotTask::FixedTimeslotTask(const char *name, rtems_task_priority setPriority,
|
||||
size_t setStack, uint32_t setOverallPeriod,
|
||||
void (*setDeadlineMissedFunc)(void))
|
||||
: RTEMSTaskBase(setPriority, setStack, name), periodId(0), pst(setOverallPeriod) {
|
||||
// All additional attributes are applied to the object.
|
||||
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
||||
}
|
||||
size_t setStack, TaskPeriod setOverallPeriod,
|
||||
TaskDeadlineMissedFunction dlmFunc_)
|
||||
: FixedTimeslotTaskBase(setOverallPeriod, dlmFunc_),
|
||||
RTEMSTaskBase(setPriority, setStack, name),
|
||||
periodId(0) {}
|
||||
|
||||
FixedTimeslotTask::~FixedTimeslotTask() {}
|
||||
FixedTimeslotTask::~FixedTimeslotTask() = default;
|
||||
|
||||
rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) {
|
||||
/* The argument is re-interpreted as a FixedTimeslotTask */
|
||||
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask *>(argument));
|
||||
auto *originalTask(reinterpret_cast<FixedTimeslotTask *>(argument));
|
||||
/* The task's functionality is called. */
|
||||
return originalTask->taskFunctionality();
|
||||
/* Should never be reached */
|
||||
@ -46,16 +36,6 @@ rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::missedDeadlineCounter() {
|
||||
FixedTimeslotTask::deadlineMissedCount++;
|
||||
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines."
|
||||
<< std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||
rtems_status_code status =
|
||||
rtems_task_start(id, FixedTimeslotTask::taskEntryPoint, rtems_task_argument((void *)this));
|
||||
@ -79,54 +59,35 @@ ReturnValue_t FixedTimeslotTask::startTask() {
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
int8_t executionStep) {
|
||||
ExecutableObjectIF *object = ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
|
||||
if (object != nullptr) {
|
||||
pst.addSlot(componentId, slotTimeMs, executionStep, object, this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst"
|
||||
<< std::endl;
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); }
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::checkSequence() const { return pst.checkSequence(); }
|
||||
|
||||
void FixedTimeslotTask::taskFunctionality() {
|
||||
[[noreturn]] void FixedTimeslotTask::taskFunctionality() {
|
||||
/* A local iterator for the Polling Sequence Table is created to find the start time for
|
||||
the first entry. */
|
||||
FixedSlotSequence::SlotListIter it = pst.current;
|
||||
auto it = pollingSeqTable.current;
|
||||
|
||||
/* Initialize the PST with the correct calling task */
|
||||
pst.intializeSequenceAfterTaskCreation();
|
||||
pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||
|
||||
/* The start time for the first entry is read. */
|
||||
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
|
||||
RTEMSTaskBase::setAndStartPeriod(interval, &periodId);
|
||||
// The task's "infinite" inner loop is entered.
|
||||
while (1) {
|
||||
if (pst.slotFollowsImmediately()) {
|
||||
while (true) {
|
||||
if (pollingSeqTable.slotFollowsImmediately()) {
|
||||
/* Do nothing */
|
||||
} else {
|
||||
/* The interval for the next polling slot is selected. */
|
||||
interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs());
|
||||
interval = RtemsBasic::convertMsToTicks(pollingSeqTable.getIntervalToNextSlotMs());
|
||||
/* The period is checked and restarted with the new interval.
|
||||
If the deadline was missed, the deadlineMissedFunc is called. */
|
||||
rtems_status_code status = RTEMSTaskBase::restartPeriod(interval, periodId);
|
||||
if (status == RTEMS_TIMEOUT) {
|
||||
if (this->deadlineMissedFunc != nullptr) {
|
||||
this->deadlineMissedFunc();
|
||||
if (dlmFunc != nullptr) {
|
||||
dlmFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* The device handler for this slot is executed and the next one is chosen. */
|
||||
this->pst.executeAndAdvance();
|
||||
this->pollingSeqTable.executeAndAdvance();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
#ifndef FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
|
||||
#define FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
|
||||
|
||||
#include "../../tasks/FixedSlotSequence.h"
|
||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
||||
#include "RTEMSTaskBase.h"
|
||||
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||
|
||||
class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF {
|
||||
class FixedTimeslotTask : public FixedTimeslotTaskBase, public RTEMSTaskBase {
|
||||
public:
|
||||
/**
|
||||
* @brief The standard constructor of the class.
|
||||
@ -17,7 +17,7 @@ class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF {
|
||||
* @param getPst The object id of the completely initialized polling sequence.
|
||||
*/
|
||||
FixedTimeslotTask(const char *name, rtems_task_priority setPriority, size_t setStackSize,
|
||||
uint32_t overallPeriod, void (*setDeadlineMissedFunc)());
|
||||
TaskPeriod overallPeriod, TaskDeadlineMissedFunction dlmFunc);
|
||||
|
||||
/**
|
||||
* @brief The destructor of the class.
|
||||
@ -25,44 +25,17 @@ class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF {
|
||||
* The destructor frees all heap memory that was allocated on thread initialization
|
||||
* for the PST andthe device handlers. This is done by calling the PST's destructor.
|
||||
*/
|
||||
virtual ~FixedTimeslotTask(void);
|
||||
~FixedTimeslotTask() override;
|
||||
|
||||
ReturnValue_t startTask(void);
|
||||
/**
|
||||
* This static function can be used as #deadlineMissedFunc.
|
||||
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
|
||||
*/
|
||||
static void missedDeadlineCounter();
|
||||
/**
|
||||
* A helper variable to count missed deadlines.
|
||||
*/
|
||||
static uint32_t deadlineMissedCount;
|
||||
|
||||
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
|
||||
|
||||
uint32_t getPeriodMs() const;
|
||||
|
||||
ReturnValue_t checkSequence() const;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms);
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief id of the associated OS period
|
||||
*/
|
||||
rtems_id periodId;
|
||||
|
||||
FixedSlotSequence pst;
|
||||
|
||||
/**
|
||||
* @brief This attribute holds a function pointer that is executed when a deadline was missed.
|
||||
*
|
||||
* @details
|
||||
* Another function may be announced to determine the actions to perform when a deadline
|
||||
* was missed. Currently, only one function for missing any deadline is allowed.
|
||||
* If not used, it shall be declared NULL.
|
||||
*/
|
||||
void (*deadlineMissedFunc)(void) = nullptr;
|
||||
/**
|
||||
* @brief This is the entry point in a new polling thread.
|
||||
* @details This method is the entry point in the new thread
|
||||
@ -76,7 +49,7 @@ class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF {
|
||||
* It links the functionalities provided by FixedSlotSequence with the OS's system calls to
|
||||
* keep the timing of the periods.
|
||||
*/
|
||||
void taskFunctionality(void);
|
||||
[[noreturn]] void taskFunctionality();
|
||||
};
|
||||
|
||||
#endif /* FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ */
|
||||
|
@ -65,7 +65,7 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueu
|
||||
}
|
||||
|
||||
ReturnValue_t returnCode = convertReturnCode(result);
|
||||
if (result == MessageQueueIF::EMPTY) {
|
||||
if (returnCode == MessageQueueIF::EMPTY) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
|
@ -36,9 +36,9 @@ class MessageQueue : public MessageQueueBase {
|
||||
* @param max_message_size With this parameter, the maximum message size can be adjusted.
|
||||
* This should be left default.
|
||||
*/
|
||||
MessageQueue(size_t message_depth = 3,
|
||||
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||
MqArgs* args = nullptr);
|
||||
explicit MessageQueue(size_t message_depth = 3,
|
||||
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||
MqArgs* args = nullptr);
|
||||
|
||||
/** Copying message queues forbidden */
|
||||
MessageQueue(const MessageQueue&) = delete;
|
||||
@ -48,18 +48,19 @@ class MessageQueue : public MessageQueueBase {
|
||||
* @brief The destructor deletes the formerly created message queue.
|
||||
* @details This is accomplished by using the delete call provided by the operating system.
|
||||
*/
|
||||
virtual ~MessageQueue();
|
||||
~MessageQueue() override;
|
||||
|
||||
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||
ReturnValue_t flush(uint32_t* count) override;
|
||||
|
||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
||||
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||
bool ignoreFault = false) override;
|
||||
MessageQueueId_t sentFrom, bool ignoreFault) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief This attribute stores a reference to the internal error reporter for reporting full
|
||||
* queues. \details In the event of a full destination queue, the reporter will be notified. The
|
||||
* @brief This attribute stores a reference to the internal error reporter for reporting full
|
||||
* queues. @details In the event of a full destination queue, the reporter will be notified. The
|
||||
* reference is set by lazy loading
|
||||
*/
|
||||
InternalErrorReporterIF* internalErrorReporter;
|
||||
|
@ -5,12 +5,12 @@
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
|
||||
PeriodicTask::PeriodicTask(const char* name, rtems_task_priority setPriority, size_t setStack,
|
||||
rtems_interval setPeriod, void (*setDeadlineMissedFunc)())
|
||||
: RTEMSTaskBase(setPriority, setStack, name),
|
||||
periodTicks(RtemsBasic::convertMsToTicks(setPeriod)),
|
||||
deadlineMissedFunc(setDeadlineMissedFunc) {}
|
||||
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_)
|
||||
: PeriodicTaskBase(setPeriod, dlmFunc_),
|
||||
RTEMSTaskBase(setPriority, setStack, name),
|
||||
periodTicks(RtemsBasic::convertMsToTicks(static_cast<uint32_t>(setPeriod * 1000.0))) {}
|
||||
|
||||
PeriodicTask::~PeriodicTask(void) {
|
||||
PeriodicTask::~PeriodicTask() {
|
||||
/* Do not delete objects, we were responsible for pointers only. */
|
||||
rtems_rate_monotonic_delete(periodId);
|
||||
}
|
||||
@ -18,7 +18,7 @@ PeriodicTask::~PeriodicTask(void) {
|
||||
rtems_task PeriodicTask::taskEntryPoint(rtems_task_argument argument) {
|
||||
/* The argument is re-interpreted as MultiObjectTask. The Task object is global,
|
||||
so it is found from any place. */
|
||||
PeriodicTask* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||
auto* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||
return originalTask->taskFunctionality();
|
||||
;
|
||||
}
|
||||
@ -28,8 +28,10 @@ ReturnValue_t PeriodicTask::startTask() {
|
||||
rtems_task_start(id, PeriodicTask::taskEntryPoint, rtems_task_argument((void*)this));
|
||||
if (status != RTEMS_SUCCESSFUL) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "ObjectTask::startTask for " << std::hex << this->getId() << std::dec
|
||||
<< " failed." << std::endl;
|
||||
sif::error << "PeriodicTask::startTask for " << std::hex << this->getId() << std::dec
|
||||
<< " failed" << std::endl;
|
||||
#else
|
||||
sif::printError("PeriodicTask::startTask for 0x%08x failed\n", getId());
|
||||
#endif
|
||||
}
|
||||
switch (status) {
|
||||
@ -47,38 +49,20 @@ ReturnValue_t PeriodicTask::startTask() {
|
||||
|
||||
ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { return RTEMSTaskBase::sleepFor(ms); }
|
||||
|
||||
void PeriodicTask::taskFunctionality() {
|
||||
[[noreturn]] void PeriodicTask::taskFunctionality() {
|
||||
RTEMSTaskBase::setAndStartPeriod(periodTicks, &periodId);
|
||||
for (const auto& object : objectList) {
|
||||
object->initializeAfterTaskCreation();
|
||||
}
|
||||
initObjsAfterTaskCreation();
|
||||
|
||||
/* The task's "infinite" inner loop is entered. */
|
||||
while (1) {
|
||||
for (const auto& object : objectList) {
|
||||
object->performOperation();
|
||||
while (true) {
|
||||
for (const auto& objectPair : objectList) {
|
||||
objectPair.first->performOperation(objectPair.second);
|
||||
}
|
||||
rtems_status_code status = RTEMSTaskBase::restartPeriod(periodTicks, periodId);
|
||||
if (status == RTEMS_TIMEOUT) {
|
||||
if (this->deadlineMissedFunc != nullptr) {
|
||||
this->deadlineMissedFunc();
|
||||
if (dlmFunc != nullptr) {
|
||||
dlmFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
||||
return addComponent(newObject);
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
|
||||
if (object == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
objectList.push_back(object);
|
||||
object->setTaskIF(this);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
uint32_t PeriodicTask::getPeriodMs() const { return RtemsBasic::convertTicksToMs(periodTicks); }
|
||||
|
@ -3,9 +3,10 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../../objectmanager/ObjectManagerIF.h"
|
||||
#include "../../tasks/PeriodicTaskIF.h"
|
||||
#include "RTEMSTaskBase.h"
|
||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||
#include "fsfw/tasks/PeriodicTaskBase.h"
|
||||
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||
|
||||
class ExecutableObjectIF;
|
||||
|
||||
@ -18,7 +19,7 @@ class ExecutableObjectIF;
|
||||
* @author baetz
|
||||
* @ingroup task_handling
|
||||
*/
|
||||
class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
||||
class PeriodicTask : public PeriodicTaskBase, public RTEMSTaskBase {
|
||||
public:
|
||||
/**
|
||||
* @brief Standard constructor of the class.
|
||||
@ -36,12 +37,12 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
||||
* that shall be assigned.
|
||||
*/
|
||||
PeriodicTask(const char *name, rtems_task_priority setPriority, size_t setStack,
|
||||
rtems_interval setPeriod, void (*setDeadlineMissedFunc)());
|
||||
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc);
|
||||
/**
|
||||
* @brief Currently, the executed object's lifetime is not coupled with the task object's
|
||||
* lifetime, so the destructor is empty.
|
||||
*/
|
||||
virtual ~PeriodicTask(void);
|
||||
~PeriodicTask() override;
|
||||
|
||||
/**
|
||||
* @brief The method to start the task.
|
||||
@ -50,33 +51,11 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
||||
* The address of the task object is passed as an argument
|
||||
* to the system call.
|
||||
*/
|
||||
ReturnValue_t startTask(void);
|
||||
/**
|
||||
* Adds an object to the list of objects to be executed.
|
||||
* The objects are executed in the order added.
|
||||
* @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) override;
|
||||
|
||||
/**
|
||||
* Adds an object to the list of objects to be executed.
|
||||
* The objects are executed in the order added.
|
||||
* @param object pointer to the object to add.
|
||||
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
||||
*/
|
||||
ReturnValue_t addComponent(ExecutableObjectIF *object) override;
|
||||
|
||||
uint32_t getPeriodMs() const override;
|
||||
ReturnValue_t startTask() override;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
protected:
|
||||
typedef std::vector<ExecutableObjectIF *> ObjectList; //!< Typedef for the List of objects.
|
||||
/**
|
||||
* @brief This attribute holds a list of objects to be executed.
|
||||
*/
|
||||
ObjectList objectList;
|
||||
/**
|
||||
* @brief The period of the task.
|
||||
* @details The period determines the frequency of the task's execution. It is expressed in
|
||||
@ -87,14 +66,7 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
||||
* @brief id of the associated OS period
|
||||
*/
|
||||
rtems_id periodId = 0;
|
||||
/**
|
||||
* @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
|
||||
* nullptr, then nothing happens on missing the deadline. The deadline is equal to the next
|
||||
* execution of the periodic task.
|
||||
*/
|
||||
void (*deadlineMissedFunc)(void);
|
||||
|
||||
/**
|
||||
* @brief This is the function executed in the new task's context.
|
||||
* @details It converts the argument back to the thread object type and copies the class
|
||||
@ -110,7 +82,7 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
||||
* are called. Afterwards the checkAndRestartPeriod system call blocks the task until the next
|
||||
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
||||
*/
|
||||
void taskFunctionality(void);
|
||||
[[noreturn]] void taskFunctionality();
|
||||
};
|
||||
|
||||
#endif /* FSFW_OSAL_RTEMS_PERIODICTASK_H_ */
|
||||
|
@ -45,9 +45,9 @@ QueueFactory* QueueFactory::instance() {
|
||||
return factoryInstance;
|
||||
}
|
||||
|
||||
QueueFactory::QueueFactory() {}
|
||||
QueueFactory::QueueFactory() = default;
|
||||
|
||||
QueueFactory::~QueueFactory() {}
|
||||
QueueFactory::~QueueFactory() = default;
|
||||
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
|
||||
MqArgs* args) {
|
||||
|
@ -32,7 +32,7 @@ RTEMSTaskBase::RTEMSTaskBase(rtems_task_priority set_priority, size_t stack_size
|
||||
|
||||
RTEMSTaskBase::~RTEMSTaskBase() { rtems_task_delete(id); }
|
||||
|
||||
rtems_id RTEMSTaskBase::getId() { return this->id; }
|
||||
rtems_id RTEMSTaskBase::getId() const { return this->id; }
|
||||
|
||||
ReturnValue_t RTEMSTaskBase::sleepFor(uint32_t ms) {
|
||||
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
|
||||
|
@ -36,9 +36,9 @@ class RTEMSTaskBase {
|
||||
/**
|
||||
* @brief This method returns the task id of this class.
|
||||
*/
|
||||
rtems_id getId();
|
||||
rtems_id getId() const;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms);
|
||||
static ReturnValue_t sleepFor(uint32_t ms);
|
||||
static ReturnValue_t setAndStartPeriod(rtems_interval period, rtems_id *periodId);
|
||||
static rtems_status_code restartPeriod(rtems_interval period, rtems_id periodId);
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "fsfw/tasks/TaskFactory.h"
|
||||
|
||||
#include "fsfw/osal/rtems/FixedTimeslotTask.h"
|
||||
#include "fsfw/osal/rtems/InitTask.h"
|
||||
#include "fsfw/osal/rtems/PeriodicTask.h"
|
||||
#include "fsfw/osal/rtems/RtemsBasic.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
@ -9,29 +8,29 @@
|
||||
// TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
||||
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
||||
|
||||
TaskFactory::~TaskFactory() {}
|
||||
TaskFactory::TaskFactory() = default;
|
||||
|
||||
TaskFactory::~TaskFactory() = default;
|
||||
|
||||
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
||||
|
||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(
|
||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
||||
|
||||
return static_cast<PeriodicTaskIF*>(
|
||||
new PeriodicTask(name_, taskPriority_, stackSize_, taskPeriod, deadLineMissedFunction_));
|
||||
return static_cast<PeriodicTaskIF*>(new PeriodicTask(name_, taskPriority_, stackSize_,
|
||||
periodInSeconds_, deadLineMissedFunction_));
|
||||
}
|
||||
|
||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
|
||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
||||
return static_cast<FixedTimeslotTaskIF*>(
|
||||
new FixedTimeslotTask(name_, taskPriority_, stackSize_, taskPeriod, deadLineMissedFunction_));
|
||||
return static_cast<FixedTimeslotTaskIF*>(new FixedTimeslotTask(
|
||||
name_, taskPriority_, stackSize_, periodInSeconds_, deadLineMissedFunction_));
|
||||
}
|
||||
|
||||
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
||||
// TODO not implemented
|
||||
// This should call the OS specific destructor
|
||||
delete (dynamic_cast<PeriodicTask*>(task));
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
@ -45,5 +44,3 @@ void TaskFactory::printMissedDeadline() {
|
||||
/* TODO: Implement */
|
||||
return;
|
||||
}
|
||||
|
||||
TaskFactory::TaskFactory() {}
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
tcpipHelpers.cpp
|
||||
winTaskHelpers.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE tcpipHelpers.cpp winTaskHelpers.cpp)
|
||||
|
@ -1,6 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ParameterHelper.cpp
|
||||
ParameterMessage.cpp
|
||||
ParameterWrapper.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE ParameterHelper.cpp ParameterMessage.cpp
|
||||
ParameterWrapper.cpp)
|
||||
|
@ -1,8 +1,4 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
Fuse.cpp
|
||||
PowerComponent.cpp
|
||||
PowerSensor.cpp
|
||||
PowerSwitcher.cpp
|
||||
DummyPowerSwitcher.cpp
|
||||
PowerSwitcherComponent.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE Fuse.cpp PowerComponent.cpp PowerSensor.cpp PowerSwitcher.cpp
|
||||
DummyPowerSwitcher.cpp PowerSwitcherComponent.cpp)
|
||||
|
@ -3,9 +3,12 @@
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/power/PowerSwitchIF.h>
|
||||
|
||||
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t pwrSwitch)
|
||||
: SystemObject(objectId), switcher(pwrSwitcher, pwrSwitch), modeHelper(this),
|
||||
healthHelper(this, objectId) {
|
||||
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
|
||||
power::Switch_t pwrSwitch)
|
||||
: SystemObject(objectId),
|
||||
switcher(pwrSwitcher, pwrSwitch),
|
||||
modeHelper(this),
|
||||
healthHelper(this, objectId) {
|
||||
queue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
@ -25,12 +28,12 @@ ReturnValue_t PowerSwitcherComponent::performOperation(uint8_t opCode) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(switcher.active()) {
|
||||
if (switcher.active()) {
|
||||
switcher.doStateMachine();
|
||||
auto currState = switcher.getState();
|
||||
if (currState == PowerSwitcher::SWITCH_IS_OFF) {
|
||||
setMode(MODE_OFF, 0);
|
||||
} else if(currState == PowerSwitcher::SWITCH_IS_ON) {
|
||||
} else if (currState == PowerSwitcher::SWITCH_IS_ON) {
|
||||
setMode(MODE_ON, 0);
|
||||
}
|
||||
}
|
||||
@ -39,19 +42,17 @@ ReturnValue_t PowerSwitcherComponent::performOperation(uint8_t opCode) {
|
||||
|
||||
ReturnValue_t PowerSwitcherComponent::initialize() {
|
||||
ReturnValue_t result = modeHelper.initialize();
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = healthHelper.initialize();
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return SystemObject::initialize();
|
||||
}
|
||||
|
||||
MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const {
|
||||
return queue->getId();
|
||||
}
|
||||
MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const { return queue->getId(); }
|
||||
|
||||
void PowerSwitcherComponent::getMode(Mode_t *mode, Submode_t *submode) {
|
||||
*mode = this->mode;
|
||||
@ -64,25 +65,25 @@ ReturnValue_t PowerSwitcherComponent::setHealth(HealthState health) {
|
||||
}
|
||||
|
||||
ReturnValue_t PowerSwitcherComponent::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) {
|
||||
uint32_t *msToReachTheMode) {
|
||||
*msToReachTheMode = 5000;
|
||||
if(mode != MODE_ON and mode != MODE_OFF) {
|
||||
if (mode != MODE_ON and mode != MODE_OFF) {
|
||||
return TRANS_NOT_ALLOWED;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void PowerSwitcherComponent::startTransition(Mode_t mode, Submode_t submode) {
|
||||
if(mode == MODE_OFF) {
|
||||
if (mode == MODE_OFF) {
|
||||
switcher.turnOff(true);
|
||||
switcher.doStateMachine();
|
||||
if(switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
|
||||
if (switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
|
||||
setMode(MODE_OFF, 0);
|
||||
}
|
||||
} else if (mode == MODE_ON) {
|
||||
switcher.turnOn(true);
|
||||
switcher.doStateMachine();
|
||||
if(switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
|
||||
if (switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
|
||||
setMode(MODE_ON, 0);
|
||||
}
|
||||
}
|
||||
@ -103,6 +104,4 @@ void PowerSwitcherComponent::setMode(Mode_t newMode, Submode_t newSubmode) {
|
||||
announceMode(false);
|
||||
}
|
||||
|
||||
HasHealthIF::HealthState PowerSwitcherComponent::getHealth() {
|
||||
return healthHelper.getHealth();
|
||||
}
|
||||
HasHealthIF::HealthState PowerSwitcherComponent::getHealth() { return healthHelper.getHealth(); }
|
||||
|
@ -6,8 +6,8 @@
|
||||
#include <fsfw/modes/HasModesIF.h>
|
||||
#include <fsfw/modes/ModeHelper.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/power/definitions.h>
|
||||
#include <fsfw/power/PowerSwitcher.h>
|
||||
#include <fsfw/power/definitions.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
|
||||
class PowerSwitchIF;
|
||||
@ -22,19 +22,17 @@ class PowerSwitchIF;
|
||||
* Commanding this component to MODE_OFF will cause the switcher to turn the switch off while
|
||||
* commanding in to MODE_ON will cause the switcher to turn the switch on.
|
||||
*/
|
||||
class PowerSwitcherComponent:
|
||||
public SystemObject,
|
||||
public HasReturnvaluesIF,
|
||||
public ExecutableObjectIF,
|
||||
public HasModesIF,
|
||||
public HasHealthIF {
|
||||
public:
|
||||
PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
|
||||
power::Switch_t pwrSwitch);
|
||||
class PowerSwitcherComponent : public SystemObject,
|
||||
public HasReturnvaluesIF,
|
||||
public ExecutableObjectIF,
|
||||
public HasModesIF,
|
||||
public HasHealthIF {
|
||||
public:
|
||||
PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
|
||||
power::Switch_t pwrSwitch);
|
||||
|
||||
private:
|
||||
|
||||
MessageQueueIF* queue = nullptr;
|
||||
private:
|
||||
MessageQueueIF *queue = nullptr;
|
||||
PowerSwitcher switcher;
|
||||
|
||||
Mode_t mode = MODE_OFF;
|
||||
@ -52,7 +50,7 @@ private:
|
||||
MessageQueueId_t getCommandQueue() const override;
|
||||
void getMode(Mode_t *mode, Submode_t *submode) override;
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) override;
|
||||
uint32_t *msToReachTheMode) override;
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
void setToExternalControl() override;
|
||||
void announceMode(bool recursive) override;
|
||||
|
@ -1,12 +1,12 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
Service1TelecommandVerification.cpp
|
||||
Service2DeviceAccess.cpp
|
||||
Service3Housekeeping.cpp
|
||||
Service5EventReporting.cpp
|
||||
Service8FunctionManagement.cpp
|
||||
Service9TimeManagement.cpp
|
||||
Service17Test.cpp
|
||||
Service20ParameterManagement.cpp
|
||||
CService200ModeCommanding.cpp
|
||||
CService201HealthCommanding.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE Service1TelecommandVerification.cpp
|
||||
Service2DeviceAccess.cpp
|
||||
Service3Housekeeping.cpp
|
||||
Service5EventReporting.cpp
|
||||
Service8FunctionManagement.cpp
|
||||
Service9TimeManagement.cpp
|
||||
Service17Test.cpp
|
||||
Service20ParameterManagement.cpp
|
||||
CService200ModeCommanding.cpp
|
||||
CService201HealthCommanding.cpp)
|
||||
|
@ -44,6 +44,12 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
||||
static constexpr ReturnValue_t INVALID_RELATIVE_TIME =
|
||||
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 3);
|
||||
|
||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_11;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Deletion of a TC from the map failed.
|
||||
//! P1: First 32 bit of request ID, P2. Last 32 bit of Request ID
|
||||
static constexpr Event TC_DELETION_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM);
|
||||
|
||||
// The types of PUS-11 subservices
|
||||
enum Subservice : uint8_t {
|
||||
ENABLE_SCHEDULING = 1,
|
||||
@ -73,7 +79,10 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
||||
uint16_t releaseTimeMarginSeconds = DEFAULT_RELEASE_TIME_MARGIN,
|
||||
bool debugMode = false);
|
||||
|
||||
~Service11TelecommandScheduling();
|
||||
~Service11TelecommandScheduling() override;
|
||||
|
||||
void enableExpiredTcDeletion();
|
||||
void disableExpiredTcDeletion();
|
||||
|
||||
/** PusServiceBase overrides */
|
||||
ReturnValue_t handleRequest(uint8_t subservice) override;
|
||||
@ -82,8 +91,8 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
||||
|
||||
private:
|
||||
struct TelecommandStruct {
|
||||
uint64_t requestId;
|
||||
uint32_t seconds;
|
||||
uint64_t requestId{};
|
||||
uint32_t seconds{};
|
||||
store_address_t storeAddr; // uint16
|
||||
};
|
||||
|
||||
@ -92,9 +101,11 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
||||
// minimum release time offset to insert into schedule
|
||||
const uint16_t RELEASE_TIME_MARGIN_SECONDS = 5;
|
||||
|
||||
// the maximum amount of stored TCs is defined here
|
||||
static constexpr uint16_t MAX_STORED_TELECOMMANDS = 500;
|
||||
|
||||
/**
|
||||
* By default, the scheduling will be disabled. This is a standard requirement
|
||||
*/
|
||||
bool schedulingEnabled = false;
|
||||
bool deleteExpiredTcWhenDisabled = true;
|
||||
bool debugMode = false;
|
||||
StorageManagerIF* tcStore = nullptr;
|
||||
AcceptsTelecommandsIF* tcRecipient = nullptr;
|
||||
@ -109,6 +120,7 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
||||
|
||||
TelecommandMap telecommandMap;
|
||||
|
||||
ReturnValue_t handleResetCommand();
|
||||
/**
|
||||
* @brief Logic to be performed on an incoming TC[11,4].
|
||||
* @return RETURN_OK if successful
|
||||
@ -139,17 +151,6 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
||||
*/
|
||||
ReturnValue_t doFilterTimeshiftActivity(const uint8_t* data, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Deserializes a generic type from a payload buffer by using the FSFW
|
||||
* SerializeAdapter Interface.
|
||||
* @param output Output to be deserialized
|
||||
* @param buf Payload buffer (application data)
|
||||
* @param bufsize Remaining size of payload buffer (application data size)
|
||||
* @return RETURN_OK if successful
|
||||
*/
|
||||
template <typename T>
|
||||
ReturnValue_t deserializeViaFsfwInterface(T& output, const uint8_t* buf, size_t bufsize);
|
||||
|
||||
/**
|
||||
* @brief Extracts the Request ID from the Application Data of a TC by utilizing a ctor of the
|
||||
* class TcPacketPus.
|
||||
@ -177,7 +178,7 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
||||
* @param ssc Source Sequence Count
|
||||
* @return Request ID
|
||||
*/
|
||||
uint64_t buildRequestId(uint32_t sourceId, uint16_t apid, uint16_t ssc) const;
|
||||
[[nodiscard]] uint64_t buildRequestId(uint32_t sourceId, uint16_t apid, uint16_t ssc) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the filter range for filter TCs from a data packet
|
||||
@ -194,7 +195,7 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
||||
/**
|
||||
* @brief Prints content of multimap. Use for simple debugging only.
|
||||
*/
|
||||
void debugPrintMultimapContent(void) const;
|
||||
void debugPrintMultimapContent() const;
|
||||
};
|
||||
|
||||
#include "Service11TelecommandScheduling.tpp"
|
||||
|
@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
#include <fsfw/serialize/SerializeAdapter.h>
|
||||
#include <fsfw/tmtcservices/AcceptsTelecommandsIF.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/serialize/SerializeAdapter.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
|
||||
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
@ -18,7 +19,7 @@ inline Service11TelecommandScheduling<MAX_NUM_TCS>::Service11TelecommandScheduli
|
||||
tcRecipient(tcRecipient) {}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline Service11TelecommandScheduling<MAX_NUM_TCS>::~Service11TelecommandScheduling() {}
|
||||
inline Service11TelecommandScheduling<MAX_NUM_TCS>::~Service11TelecommandScheduling() = default;
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::handleRequest(
|
||||
@ -37,6 +38,17 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::handleRequest(
|
||||
return handleInvalidData("handleRequest");
|
||||
}
|
||||
switch (subservice) {
|
||||
case Subservice::ENABLE_SCHEDULING: {
|
||||
schedulingEnabled = true;
|
||||
break;
|
||||
}
|
||||
case Subservice::DISABLE_SCHEDULING: {
|
||||
schedulingEnabled = false;
|
||||
break;
|
||||
}
|
||||
case Subservice::RESET_SCHEDULING: {
|
||||
return handleResetCommand();
|
||||
}
|
||||
case Subservice::INSERT_ACTIVITY:
|
||||
return doInsertActivity(data, size);
|
||||
case Subservice::DELETE_ACTIVITY:
|
||||
@ -48,41 +60,43 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::handleRequest(
|
||||
case Subservice::FILTER_TIMESHIFT_ACTIVITY:
|
||||
return doFilterTimeshiftActivity(data, size);
|
||||
default:
|
||||
break;
|
||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::performService() {
|
||||
// DEBUG
|
||||
// DebugPrintMultimapContent();
|
||||
|
||||
if (not schedulingEnabled) {
|
||||
return RETURN_OK;
|
||||
}
|
||||
// get current time as UNIX timestamp
|
||||
timeval tNow = {};
|
||||
Clock::getClock_timeval(&tNow);
|
||||
|
||||
// TODO: Optionally limit the max number of released TCs per cycle?
|
||||
// NOTE: The iterator is increased in the loop here. Increasing the iterator as for-loop arg
|
||||
// does not work in this case as we are deleting the current element here.
|
||||
for (auto it = telecommandMap.begin(); it != telecommandMap.end();) {
|
||||
if (it->first <= tNow.tv_sec) {
|
||||
// release tc
|
||||
TmTcMessage releaseMsg(it->second.storeAddr);
|
||||
auto sendRet = this->requestQueue->sendMessage(recipientMsgQueueId, &releaseMsg, false);
|
||||
if (schedulingEnabled) {
|
||||
// release tc
|
||||
TmTcMessage releaseMsg(it->second.storeAddr);
|
||||
auto sendRet = this->requestQueue->sendMessage(recipientMsgQueueId, &releaseMsg, false);
|
||||
|
||||
if (sendRet != HasReturnvaluesIF::RETURN_OK) {
|
||||
return sendRet;
|
||||
}
|
||||
|
||||
telecommandMap.erase(it++);
|
||||
|
||||
if (debugMode) {
|
||||
if (sendRet != HasReturnvaluesIF::RETURN_OK) {
|
||||
return sendRet;
|
||||
}
|
||||
if (debugMode) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "Released TC & erased it from TC map" << std::endl;
|
||||
sif::info << "Released TC & erased it from TC map" << std::endl;
|
||||
#else
|
||||
sif::printInfo("Released TC & erased it from TC map\n");
|
||||
sif::printInfo("Released TC & erased it from TC map\n");
|
||||
#endif
|
||||
}
|
||||
telecommandMap.erase(it++);
|
||||
} else if (deleteExpiredTcWhenDisabled) {
|
||||
telecommandMap.erase(it++);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -112,12 +126,30 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::initialize() {
|
||||
return res;
|
||||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::handleResetCommand() {
|
||||
for (auto it = telecommandMap.begin(); it != telecommandMap.end(); it++) {
|
||||
ReturnValue_t result = tcStore->deleteData(it->second.storeAddr);
|
||||
if (result != RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
// This should not happen
|
||||
sif::warning << "Service11TelecommandScheduling::handleRequestDeleting: Deletion failed"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning("Service11TelecommandScheduling::handleRequestDeleting: Deletion failed\n");
|
||||
#endif
|
||||
triggerEvent(TC_DELETION_FAILED, (it->second.requestId >> 32) & 0xffffffff,
|
||||
it->second.requestId & 0xffffffff);
|
||||
}
|
||||
}
|
||||
telecommandMap.clear();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivity(
|
||||
const uint8_t *data, size_t size) {
|
||||
uint32_t timestamp = 0;
|
||||
const uint8_t *initData = data;
|
||||
size_t initSz = size;
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(×tamp, &data, &size, DEF_END);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
@ -142,7 +174,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
|
||||
|
||||
// store currentPacket and receive the store address
|
||||
store_address_t addr{};
|
||||
if (tcStore->addData(&addr, initData, initSz) != RETURN_OK ||
|
||||
if (tcStore->addData(&addr, data, size) != RETURN_OK ||
|
||||
addr.raw == storeId::INVALID_STORE_ADDRESS) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Service11TelecommandScheduling::doInsertActivity: Adding data to TC Store failed"
|
||||
@ -404,7 +436,6 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doFilterTimesh
|
||||
// and then insert it again as new entry
|
||||
telecommandMap.insert(std::make_pair(tempKey, tempTc));
|
||||
shiftedItemsCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (debugMode) {
|
||||
@ -463,9 +494,9 @@ template <size_t MAX_NUM_TCS>
|
||||
inline uint64_t Service11TelecommandScheduling<MAX_NUM_TCS>::buildRequestId(uint32_t sourceId,
|
||||
uint16_t apid,
|
||||
uint16_t ssc) const {
|
||||
uint64_t sourceId64 = static_cast<uint64_t>(sourceId);
|
||||
uint64_t apid64 = static_cast<uint64_t>(apid);
|
||||
uint64_t ssc64 = static_cast<uint64_t>(ssc);
|
||||
auto sourceId64 = static_cast<uint64_t>(sourceId);
|
||||
auto apid64 = static_cast<uint64_t>(apid);
|
||||
auto ssc64 = static_cast<uint64_t>(ssc);
|
||||
|
||||
return (sourceId64 << 32) | (apid64 << 16) | ssc64;
|
||||
}
|
||||
@ -483,7 +514,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::getMapFilterFr
|
||||
if (typeRaw > 3) {
|
||||
return INVALID_TYPE_TIME_WINDOW;
|
||||
}
|
||||
TypeOfTimeWindow type = static_cast<TypeOfTimeWindow>(typeRaw);
|
||||
auto type = static_cast<TypeOfTimeWindow>(typeRaw);
|
||||
|
||||
// we now have the type of delete activity - so now we set the range to delete,
|
||||
// according to the type of time window.
|
||||
@ -558,7 +589,10 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::getMapFilterFr
|
||||
|
||||
// additional security check, this should never be true
|
||||
if (itBegin->first > itEnd->first) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
#else
|
||||
sif::printError("11::GetMapFilterFromData: itBegin > itEnd\n");
|
||||
#endif
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
@ -580,19 +614,32 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::handleInvalidD
|
||||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline void Service11TelecommandScheduling<MAX_NUM_TCS>::debugPrintMultimapContent(void) const {
|
||||
inline void Service11TelecommandScheduling<MAX_NUM_TCS>::debugPrintMultimapContent() const {
|
||||
#if FSFW_DISABLE_PRINTOUT == 0
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "Service11TelecommandScheduling::debugPrintMultimapContent: Multimap Content"
|
||||
<< std::endl;
|
||||
sif::debug << "[" << dit->first << "]: Request ID: " << dit->second.requestId << " | "
|
||||
<< "Store Address: " << dit->second.storeAddr << std::endl;
|
||||
#else
|
||||
sif::printDebug("Service11TelecommandScheduling::debugPrintMultimapContent: Multimap Content\n");
|
||||
for (auto dit = telecommandMap.begin(); dit != telecommandMap.end(); ++dit) {
|
||||
sif::printDebug("[%d]: Request ID: %d | Store Address: %d\n", dit->first,
|
||||
dit->second.requestId, dit->second.storeAddr);
|
||||
#endif
|
||||
for (const auto &dit : telecommandMap) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "[" << dit.first << "]: Request ID: " << dit.second.requestId << " | "
|
||||
<< "Store Address: " << dit.second.storeAddr.raw << std::endl;
|
||||
#else
|
||||
sif::printDebug("[%d]: Request ID: %d | Store Address: %d\n", dit.first, dit.second.requestId,
|
||||
dit.second.storeAddr);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline void Service11TelecommandScheduling<MAX_NUM_TCS>::enableExpiredTcDeletion() {
|
||||
deleteExpiredTcWhenDisabled = true;
|
||||
}
|
||||
|
||||
template <size_t MAX_NUM_TCS>
|
||||
inline void Service11TelecommandScheduling<MAX_NUM_TCS>::disableExpiredTcDeletion() {
|
||||
deleteExpiredTcWhenDisabled = false;
|
||||
}
|
||||
|
@ -86,8 +86,8 @@ ReturnValue_t Service5EventReporting::handleRequest(uint8_t subservice) {
|
||||
// In addition to the default PUSServiceBase initialization, this service needs
|
||||
// to be registered to the event manager to listen for events.
|
||||
ReturnValue_t Service5EventReporting::initialize() {
|
||||
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
||||
if (manager == NULL) {
|
||||
auto* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
||||
if (manager == nullptr) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
// register Service 5 as listener for events
|
||||
|
@ -1,7 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
RMAP.cpp
|
||||
RMAPCookie.cpp
|
||||
RmapDeviceCommunicationIF.cpp
|
||||
)
|
||||
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE RMAP.cpp RMAPCookie.cpp
|
||||
RmapDeviceCommunicationIF.cpp)
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
SerialBufferAdapter.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE SerialBufferAdapter.cpp)
|
||||
|
@ -1,5 +1,4 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
ServiceInterfaceStream.cpp
|
||||
ServiceInterfaceBuffer.cpp
|
||||
ServiceInterfacePrinter.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE ServiceInterfaceStream.cpp ServiceInterfaceBuffer.cpp
|
||||
ServiceInterfacePrinter.cpp)
|
||||
|
@ -1,7 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ConstStorageAccessor.cpp
|
||||
StorageAccessor.cpp
|
||||
LocalPool.cpp
|
||||
PoolManager.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE ConstStorageAccessor.cpp StorageAccessor.cpp
|
||||
LocalPool.cpp PoolManager.cpp)
|
||||
|
@ -13,7 +13,7 @@ StorageAccessor::StorageAccessor(store_address_t storeId, StorageManagerIF* stor
|
||||
StorageAccessor& StorageAccessor::operator=(StorageAccessor&& other) {
|
||||
// Call the parent move assignment and also assign own member.
|
||||
dataPointer = other.dataPointer;
|
||||
StorageAccessor::operator=(std::move(other));
|
||||
ConstStorageAccessor::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
Subsystem.cpp
|
||||
SubsystemBase.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE Subsystem.cpp SubsystemBase.cpp)
|
||||
|
||||
add_subdirectory(modes)
|
@ -1,5 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ModeSequenceMessage.cpp
|
||||
ModeStore.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE ModeSequenceMessage.cpp ModeStore.cpp)
|
||||
|
@ -1,5 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
FixedSequenceSlot.cpp
|
||||
FixedSlotSequence.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE FixedSequenceSlot.cpp FixedSlotSequence.cpp
|
||||
PeriodicTaskBase.cpp FixedTimeslotTaskBase.cpp)
|
||||
|
@ -29,7 +29,7 @@ void FixedSlotSequence::executeAndAdvance() {
|
||||
|
||||
uint32_t FixedSlotSequence::getIntervalToNextSlotMs() {
|
||||
uint32_t oldTime;
|
||||
SlotListIter slotListIter = current;
|
||||
auto slotListIter = current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
oldTime = slotListIter->pollingTimeMs;
|
||||
// Advance to the next object.
|
||||
@ -51,7 +51,7 @@ uint32_t FixedSlotSequence::getIntervalToNextSlotMs() {
|
||||
|
||||
uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() {
|
||||
uint32_t currentTime;
|
||||
SlotListIter slotListIter = current;
|
||||
auto slotListIter = current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
currentTime = slotListIter->pollingTimeMs;
|
||||
|
||||
@ -67,7 +67,7 @@ uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() {
|
||||
|
||||
bool FixedSlotSequence::slotFollowsImmediately() {
|
||||
uint32_t currentTime = current->pollingTimeMs;
|
||||
SlotListIter fixedSequenceIter = this->current;
|
||||
auto fixedSequenceIter = this->current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
if (fixedSequenceIter == slotList.begin()) return false;
|
||||
fixedSequenceIter--;
|
||||
@ -96,8 +96,8 @@ ReturnValue_t FixedSlotSequence::checkSequence() const {
|
||||
return FixedTimeslotTaskIF::SLOT_LIST_EMPTY;
|
||||
}
|
||||
|
||||
if (customCheckFunction != nullptr) {
|
||||
ReturnValue_t result = customCheckFunction(slotList);
|
||||
if (customChecker != nullptr) {
|
||||
ReturnValue_t result = customChecker(slotList, customCheckArgs);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// Continue for now but print error output.
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
@ -161,6 +161,9 @@ ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void FixedSlotSequence::addCustomCheck(ReturnValue_t (*customCheckFunction)(const SlotList&)) {
|
||||
this->customCheckFunction = customCheckFunction;
|
||||
void FixedSlotSequence::addCustomCheck(CustomCheckFunc customChecker_, void* checkerArgs_) {
|
||||
customChecker = customChecker_;
|
||||
customCheckArgs = checkerArgs_;
|
||||
}
|
||||
|
||||
bool FixedSlotSequence::isEmpty() const { return slotList.empty(); }
|
||||
|
@ -30,12 +30,12 @@ class FixedSlotSequence {
|
||||
public:
|
||||
using SlotList = std::multiset<FixedSequenceSlot>;
|
||||
using SlotListIter = std::multiset<FixedSequenceSlot>::iterator;
|
||||
|
||||
using CustomCheckFunc = ReturnValue_t (*)(const SlotList&, void* args);
|
||||
/**
|
||||
* @brief The constructor of the FixedSlotSequence object.
|
||||
* @param setLength The period length, expressed in ms.
|
||||
*/
|
||||
FixedSlotSequence(uint32_t setLengthMs);
|
||||
explicit FixedSlotSequence(uint32_t setLengthMs);
|
||||
|
||||
/**
|
||||
* @brief The destructor of the FixedSlotSequence object.
|
||||
@ -106,7 +106,7 @@ class FixedSlotSequence {
|
||||
/**
|
||||
* @brief This method returns the length of this FixedSlotSequence instance.
|
||||
*/
|
||||
uint32_t getLengthMs() const;
|
||||
[[nodiscard]] uint32_t getLengthMs() const;
|
||||
|
||||
/**
|
||||
* @brief The method to execute the device handler entered in the current
|
||||
@ -137,7 +137,7 @@ class FixedSlotSequence {
|
||||
* @return
|
||||
* - SLOT_LIST_EMPTY if the slot list is empty
|
||||
*/
|
||||
ReturnValue_t checkSequence() const;
|
||||
[[nodiscard]] ReturnValue_t checkSequence() const;
|
||||
|
||||
/**
|
||||
* @brief A custom check can be injected for the respective slot list.
|
||||
@ -149,7 +149,7 @@ class FixedSlotSequence {
|
||||
* @param customCheckFunction
|
||||
*
|
||||
*/
|
||||
void addCustomCheck(ReturnValue_t (*customCheckFunction)(const SlotList&));
|
||||
void addCustomCheck(CustomCheckFunc func, void* userArgs);
|
||||
|
||||
/**
|
||||
* @brief Perform any initialization steps required after the executing
|
||||
@ -157,7 +157,9 @@ class FixedSlotSequence {
|
||||
* executing task!
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t intializeSequenceAfterTaskCreation() const;
|
||||
[[nodiscard]] ReturnValue_t intializeSequenceAfterTaskCreation() const;
|
||||
|
||||
[[nodiscard]] bool isEmpty() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
@ -173,7 +175,8 @@ class FixedSlotSequence {
|
||||
*/
|
||||
SlotList slotList;
|
||||
|
||||
ReturnValue_t (*customCheckFunction)(const SlotList&) = nullptr;
|
||||
CustomCheckFunc customChecker = nullptr;
|
||||
void* customCheckArgs = nullptr;
|
||||
|
||||
uint32_t lengthMs;
|
||||
};
|
||||
|
27
src/fsfw/tasks/FixedTimeslotTaskBase.cpp
Normal file
27
src/fsfw/tasks/FixedTimeslotTaskBase.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "FixedTimeslotTaskBase.h"
|
||||
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
|
||||
FixedTimeslotTaskBase::FixedTimeslotTaskBase(TaskPeriod period_,
|
||||
TaskDeadlineMissedFunction dlmFunc_)
|
||||
: period(period_), pollingSeqTable(getPeriodMs()), dlmFunc(dlmFunc_) {}
|
||||
uint32_t FixedTimeslotTaskBase::getPeriodMs() const { return static_cast<uint32_t>(period * 1000); }
|
||||
|
||||
bool FixedTimeslotTaskBase::isEmpty() const { return pollingSeqTable.isEmpty(); }
|
||||
|
||||
ReturnValue_t FixedTimeslotTaskBase::checkSequence() { return pollingSeqTable.checkSequence(); }
|
||||
|
||||
ReturnValue_t FixedTimeslotTaskBase::addSlot(object_id_t execId, ExecutableObjectIF* execObj,
|
||||
uint32_t slotTimeMs, int8_t executionStep) {
|
||||
if (execObj == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << execObj
|
||||
<< std::setfill(' ') << " not found, not adding it to PST" << std::dec << std::endl;
|
||||
#else
|
||||
sif::printError("Component 0x%08x not found, not adding it to PST\n");
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
pollingSeqTable.addSlot(execId, slotTimeMs, executionStep, execObj, this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
44
src/fsfw/tasks/FixedTimeslotTaskBase.h
Normal file
44
src/fsfw/tasks/FixedTimeslotTaskBase.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H
|
||||
#define FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H
|
||||
|
||||
#include "FixedSlotSequence.h"
|
||||
#include "FixedTimeslotTaskIF.h"
|
||||
#include "definitions.h"
|
||||
|
||||
class FixedTimeslotTaskBase : public FixedTimeslotTaskIF {
|
||||
public:
|
||||
explicit FixedTimeslotTaskBase(TaskPeriod period, TaskDeadlineMissedFunction dlmFunc = nullptr);
|
||||
~FixedTimeslotTaskBase() override = default;
|
||||
;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Period of task in floating point seconds
|
||||
*/
|
||||
TaskPeriod period;
|
||||
|
||||
//! Polling sequence table which contains the object to execute
|
||||
//! and information like the timeslots and the passed execution step.
|
||||
FixedSlotSequence pollingSeqTable;
|
||||
|
||||
/**
|
||||
* @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, then nothing happens on missing the deadline.
|
||||
* The deadline is equal to the next execution of the periodic task.
|
||||
*/
|
||||
TaskDeadlineMissedFunction dlmFunc = nullptr;
|
||||
|
||||
ReturnValue_t checkSequence() override;
|
||||
|
||||
[[nodiscard]] uint32_t getPeriodMs() const override;
|
||||
|
||||
[[nodiscard]] bool isEmpty() const override;
|
||||
|
||||
ReturnValue_t addSlot(object_id_t execId, ExecutableObjectIF* componentId, uint32_t slotTimeMs,
|
||||
int8_t executionStep) override;
|
||||
};
|
||||
|
||||
#endif // FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H
|
@ -2,6 +2,7 @@
|
||||
#define FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_
|
||||
|
||||
#include "PeriodicTaskIF.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||
#include "fsfw/returnvalues/FwClassIds.h"
|
||||
|
||||
@ -11,10 +12,23 @@
|
||||
*/
|
||||
class FixedTimeslotTaskIF : public PeriodicTaskIF {
|
||||
public:
|
||||
virtual ~FixedTimeslotTaskIF() {}
|
||||
~FixedTimeslotTaskIF() override = default;
|
||||
|
||||
static constexpr ReturnValue_t SLOT_LIST_EMPTY =
|
||||
HasReturnvaluesIF::makeReturnCode(CLASS_ID::FIXED_SLOT_TASK_IF, 0);
|
||||
|
||||
/**
|
||||
* Add an object with a slot time and the execution step to the task.
|
||||
* The execution step will be passed to the object (e.g. as an operation
|
||||
* code in #performOperation)
|
||||
* @param componentId
|
||||
* @param slotTimeMs
|
||||
* @param executionStep
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t addSlot(object_id_t execId, ExecutableObjectIF* obj, uint32_t slotTimeMs,
|
||||
int8_t executionStep) = 0;
|
||||
|
||||
/**
|
||||
* Add an object with a slot time and the execution step to the task.
|
||||
* The execution step will be passed to the object (e.g. as an operation
|
||||
@ -25,12 +39,24 @@ class FixedTimeslotTaskIF : public PeriodicTaskIF {
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
int8_t executionStep) = 0;
|
||||
int8_t executionStep) {
|
||||
auto* execObj = ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
|
||||
return addSlot(componentId, execObj, slotTimeMs, executionStep);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the sequence is valid and perform all other required
|
||||
* initialization steps which are needed after task creation
|
||||
*/
|
||||
virtual ReturnValue_t checkSequence() const = 0;
|
||||
virtual ReturnValue_t checkSequence() = 0;
|
||||
|
||||
ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user