Compare commits

...

140 Commits

Author SHA1 Message Date
a837a78bd4 Merge branch 'develop' into develop_update 2023-09-01 12:14:08 +02:00
d246ce34d0 Merge pull request 'Change TLE validity duration' (#159) from spg4-tle-too-old into develop
Reviewed-on: #159
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2023-08-14 10:09:00 +02:00
796c7a9e37 tle is too old after 30 days now 2023-08-09 11:42:11 +02:00
d575da8540 Merge pull request 'Small tweak to allow immediate HK generation' (#158) from small-hk-tweak into develop
Reviewed-on: #158
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-17 10:37:39 +02:00
62ace649a7 fix unittest 2023-07-17 10:35:35 +02:00
aac74fae38 shared cmake file 2023-07-17 10:34:19 +02:00
a26b0c38ac small tweak to allow immediate HK generation 2023-07-17 10:31:02 +02:00
42e74d22cc Merge pull request 'countdown based HK generation' (#156) from hk-generation-countdown-based into develop
Reviewed-on: #156
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-11 17:35:10 +02:00
36caa58043 Merge branch 'develop' into hk-generation-countdown-based 2023-07-11 17:34:24 +02:00
988e07f0be countdown 2023-07-11 15:40:43 +02:00
88e8665280 important bugfix for PUS TM creator 2023-07-10 17:45:02 +02:00
9c8b1c697b added back missing function 2023-07-10 14:20:02 +02:00
110cb903a6 countdown based HK generation 2023-07-10 14:14:31 +02:00
8da89eba80 Merge pull request 'add API to set msg counter' (#155) from pus-msg-counter-mutable into develop
Reviewed-on: #155
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-28 13:19:28 +02:00
7e8845f2c2 Merge remote-tracking branch 'origin/develop' into pus-msg-counter-mutable 2023-06-26 18:12:36 +02:00
6aff3250c2 Merge pull request 'Internal Error Reporter Configurability' (#154) from internal-error-reporter-set into develop
Reviewed-on: #154
2023-06-26 18:10:06 +02:00
c3572e31a8 add API to set msg counter 2023-06-25 12:35:50 +02:00
2293e7f2bb typo 2023-06-22 16:12:41 +02:00
a85a38c882 some thnings are configurable now 2023-06-22 16:08:29 +02:00
0f76cdb3ba typo 2023-06-20 20:36:03 +02:00
268c2e87c9 Merge pull request 'max value calc fix' (#153) from max-value-fix-v2 into develop
Reviewed-on: #153
2023-06-20 18:20:00 +02:00
87f94a252f Merge branch 'develop' into max-value-fix-v2 2023-06-20 18:19:19 +02:00
c7037d417a nullptr check for optional argument 2023-06-20 11:54:15 +02:00
f80c5980ea max value calc fix 2023-06-19 17:04:45 +02:00
ad01642fee Merge pull request 'specify truncate flag explicitely' (#151) from specify-truncate-flag-explicitely into develop
Reviewed-on: #151
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-19 09:32:19 +02:00
f2947bc78e specify truncate flag explicitely 2023-06-18 19:04:36 +02:00
0a977ea688 Merge pull request 'make number of parallel cmds configurable' (#149) from make-srv3-num-parallel-cmds-configurable into develop
Reviewed-on: #149
2023-06-14 03:37:02 +02:00
74b164b1da make number of parallel cmds configurable 2023-06-13 08:09:04 +02:00
5322de0599 Merge pull request 'Pull CFPD bugfix in dev branch' (#147) from pull-cfdp-fix-into-dev-branch into obsw-v3.0.0-dev
Reviewed-on: #147
2023-06-09 13:41:29 +02:00
9a4bf51006 Merge branch 'develop' into obsw-v3.0.0-dev 2023-06-09 13:11:30 +02:00
3a70229510 Merge pull request 'configurable queue depth' (#146) from service-8-configurable-queue-depth into obsw-v3.0.0-dev
Reviewed-on: #146
2023-06-09 13:03:17 +02:00
b3beedad9f Merge branch 'obsw-v3.0.0-dev' into service-8-configurable-queue-depth 2023-06-09 13:03:08 +02:00
efe217a197 Merge pull request 'Rework L3GD20H Config' (#143) from gyr-config-rework into obsw-v3.0.0-dev
Reviewed-on: #143
2023-06-09 13:01:23 +02:00
b442ca09b9 configurable queue depth 2023-06-07 13:46:46 +02:00
9372b2a575 Merge remote-tracking branch 'upstream/development' into develop 2023-05-25 15:03:54 +02:00
aafa53148e Merge pull request 'CFDP Bugfix' (#144) from cfdp-bugfix-unittest-fixes into develop
Reviewed-on: #144
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-05-22 10:40:44 +02:00
e0adb3325f werks 2023-05-22 10:37:26 +02:00
4391823f01 changelog 2023-05-15 16:14:36 +02:00
1a77e6bb09 proper floating point comparison 2023-05-15 16:13:05 +02:00
cae131edcf CFDP and unittest bugfixes 2023-05-15 16:02:55 +02:00
4518fec65c CHANGELOG 2023-05-08 15:25:47 +02:00
dac1aacab2 Merge pull request 'Update Power Switch IF' (#743) from eive/fsfw:update_power_switch_if into development
Reviewed-on: fsfw/fsfw#743
2023-05-08 15:00:47 +02:00
0042f92fdf Merge pull request 'bump ETL version' (#748) from KSat/fsfw:bump_etl_dep into development
Reviewed-on: fsfw/fsfw#748
2023-05-08 14:53:02 +02:00
656faf8169 Merge remote-tracking branch 'upstream/development' into update_power_switch_if 2023-05-08 14:44:27 +02:00
f84431e965 Merge pull request 'bugfix and changelog for Linux getUptime' (#745) from eive/fsfw:important_bugfix_linux_get_uptime into development
Reviewed-on: fsfw/fsfw#745
2023-05-08 14:29:55 +02:00
0cec9ebb73 Merge pull request 'small tweak for version getter' (#744) from eive/fsfw:small_version_getter_tweak into development
Reviewed-on: fsfw/fsfw#744
2023-05-08 14:13:06 +02:00
a440b7c394 Merge pull request 'add CFDP subsystem ID' (#742) from eive/fsfw:add_cfdp_subsystem_id into development
Reviewed-on: fsfw/fsfw#742
2023-05-08 14:09:04 +02:00
bbfc1b2b34 Merge pull request 'FixedArrayList compile time assert' (#740) from eive/fsfw:container_additional_assert into development
Reviewed-on: fsfw/fsfw#740
2023-05-08 14:04:56 +02:00
025b379e8b bump ETL version 2023-05-04 14:04:55 +02:00
258f0d3313 use both LPFs 2023-04-19 15:25:14 +02:00
5eb9ee8bc1 DHB fdir: event queue depth confgurable 2023-04-14 21:22:24 +02:00
7f61d17cee even better event manager printout 2023-04-14 21:08:44 +02:00
ffa2fa477f Merge pull request 'move CFDP handler' (#142) from move_cfdp_handler into develop
Reviewed-on: #142
2023-04-11 16:50:46 +02:00
894d1e3b87 move CFDP handler 2023-04-11 16:36:54 +02:00
285d327b97 clean up spi retval defs 2023-04-07 17:42:44 +02:00
e97fa5ac84 add skip directive for retvals 2023-04-07 11:03:46 +02:00
5a9304765f accepts action commands without ipc data 2023-04-06 22:34:57 +02:00
6650c293da change collection interval is public now 2023-04-04 15:59:26 +02:00
9fca7581dd Merge branch 'develop' of https://egit.irs.uni-stuttgart.de/eive/fsfw into develop 2023-04-04 01:52:29 +02:00
4af90f99f3 changelog 2023-04-04 01:52:26 +02:00
94cdf67a80 make health functions virtual 2023-04-04 01:51:58 +02:00
7966ede11b add O_SYNC flag for UioMapper 2023-04-03 21:57:18 +02:00
7a392dc33a new register function 2023-04-03 18:54:35 +02:00
1e3c89b672 i dont think ths needs to be public 2023-04-03 17:59:14 +02:00
e2e87b149d initialize switch state list 2023-04-03 14:31:45 +02:00
4f632e2c68 ctrl base bugfix 2023-03-28 19:37:47 +02:00
314f0fa2cd start power switch component in undefined mode 2023-03-28 15:27:48 +02:00
b31e1037fb HK service configurable queue depth 2023-03-26 20:05:10 +02:00
b814e7198f Merge pull request 'Allow creating regular threads' (#140) from allow_creating_regular_threads into develop
Reviewed-on: #140
2023-03-24 14:15:53 +01:00
6328b70d7b Merge branch 'develop' into allow_creating_regular_threads 2023-03-24 14:15:39 +01:00
a937b457f9 this is so confusing 2023-03-24 14:10:47 +01:00
4415dc24e1 fix host OSAL 2023-03-24 13:25:34 +01:00
e704295cce default value 2023-03-24 11:58:23 +01:00
d16b3c7e67 try to do this cleanly 2023-03-24 11:53:41 +01:00
3b86545725 Merge pull request 'add BUSY retval' (#141) from busy_retval_dhb_com into develop
Reviewed-on: #141
2023-03-24 11:35:09 +01:00
cf6150cc18 add BUSY retval 2023-03-24 00:57:44 +01:00
bfb5c2ff03 Merge branch 'develop' into allow_creating_regular_threads 2023-03-23 18:45:49 +01:00
bf02061d47 Merge pull request 'use RR sched instead of FIFO for Linux RT' (#139) from use_rr_sched into develop
Reviewed-on: #139
2023-03-23 18:45:09 +01:00
2c4e110254 Merge branch 'develop' into use_rr_sched 2023-03-23 18:44:59 +01:00
7ed75ea87b Merge remote-tracking branch 'origin/develop' into allow_creating_regular_threads 2023-03-23 18:44:06 +01:00
db4587bb59 allow creating regular threads 2023-03-23 18:29:17 +01:00
33ac395072 use RR sched instead of FIFO for Linux RT 2023-03-23 15:42:14 +01:00
f8a7c1d4ed rename namespace 2023-03-22 01:03:49 +01:00
341437df13 add flush functions for serial helpers 2023-03-21 20:20:13 +01:00
227524a21d transition source submode is tricky 2023-03-20 15:49:09 +01:00
0f81d5e458 Merge remote-tracking branch 'upstream/development' into container_additional_assert 2023-03-15 12:34:36 +01:00
b50f092939 Merge remote-tracking branch 'upstream/development' into update_power_switch_if 2023-03-15 12:33:08 +01:00
2f90e12179 Merge remote-tracking branch 'upstream/development' into important_bugfix_linux_get_uptime 2023-03-15 12:32:25 +01:00
8b77fac099 Merge pull request 'health service fixes and changelog' (#746) from eive/fsfw:health_service_fixes into development
Reviewed-on: fsfw/fsfw#746
2023-03-15 12:29:31 +01:00
47503824d7 health service fixes and changelog 2023-03-15 12:27:39 +01:00
5e3f5c4121 fuse update 2023-03-15 12:25:39 +01:00
1f36c082ef bugfix and changelog for Linux getUptime 2023-03-15 12:21:50 +01:00
aa84e93603 small tweak for version getter 2023-03-15 12:17:36 +01:00
8f63a0e747 changelog 2023-03-15 12:15:21 +01:00
6fc8f756a7 update power switch IF 2023-03-15 12:13:55 +01:00
d98ed40e3d add CFDP subsystem ID 2023-03-15 12:09:30 +01:00
b057250bfb changelog 2023-03-15 11:53:12 +01:00
066dd0d397 changelog 2023-03-15 11:52:20 +01:00
f735c2e9d4 assert size larger than 0 2023-03-15 11:51:51 +01:00
54ef9ec3f6 Merge branch 'develop' into develop_update 2023-03-15 11:50:12 +01:00
43fd0b2f59 resolve some more merge conflicts 2023-03-15 11:48:50 +01:00
d0607824ad Merge remote-tracking branch 'upstream/development' into develop 2023-03-15 11:40:48 +01:00
cf27954a86 changelog 2023-03-14 19:55:01 +01:00
f84e3284ab just hardcode spill option to true 2023-03-14 19:54:21 +01:00
5250423d1d Merge pull request 'Periodic HK helper simplification' (#136) from periodic_hk_helper_simplification into develop
Reviewed-on: #136
2023-03-14 18:27:14 +01:00
522bd41d6e changelog 2023-03-14 18:26:44 +01:00
c61c85280b remove more code 2023-03-14 18:26:04 +01:00
afbe5e1f65 Merge remote-tracking branch 'origin/develop' into periodic_hk_helper_simplification 2023-03-14 18:23:57 +01:00
4c88ab80c8 Merge pull request 'Pool Manager spill to higher pools option' (#135) from pool_manager_spilling_opt into develop
Reviewed-on: #135
2023-03-14 18:22:31 +01:00
5ba69b169f changelog 2023-03-14 18:22:00 +01:00
40405fe6c7 add spill option 2023-03-14 18:21:16 +01:00
aac32e763c some compile fixes 2023-03-14 18:20:17 +01:00
bf980d74c0 HK helper simplification 2023-03-14 17:40:39 +01:00
b6b9d1d790 make dataset enable idempotent 2023-03-14 16:49:46 +01:00
0973ba6bf2 Merge pull request 'basic faulty cb for power switcher component' (#134) from feature_power_switch_faulty_cb into develop
Reviewed-on: #134
2023-03-14 14:15:11 +01:00
1cfebb5d47 Merge branch 'develop' into feature_power_switch_faulty_cb 2023-03-14 14:14:50 +01:00
0b0a0299bc power switch IF improvements 2023-03-14 13:45:03 +01:00
8382d61b92 possible fix for power switch component 2023-03-14 11:44:13 +01:00
7208343b6d basic faulty cb for power switcher component 2023-03-13 16:01:13 +01:00
dc7afc5415 Version bump, CHANGELOG update, format 2023-02-23 13:38:24 +01:00
9bf3ff95b7 Merge pull request 'Add Health Service Announce All Health Info' (#725) from eive/fsfw:add_health_service_announce_all into development
Reviewed-on: fsfw/fsfw#725
2023-02-23 13:13:56 +01:00
61562b18ab Merge branch 'development' into add_health_service_announce_all 2023-02-23 12:56:12 +01:00
d76d97a36b changed health table parameter to objectId 2023-02-23 12:44:42 +01:00
76b377c4c0 Merge pull request 'Mode Service: Add allowed subservice' (#739) from eive/fsfw:small_mode_service_fix into development
Reviewed-on: fsfw/fsfw#739
2023-02-20 13:40:53 +01:00
3562bf11b9 CHANGELOG update 2023-02-10 11:06:46 +01:00
fffb2b61e5 release check helper 2023-02-10 11:06:30 +01:00
94e5f62331 add allowed subservice 2023-02-09 18:30:08 +01:00
0a9c563bbc format 2023-02-09 15:58:48 +01:00
4dc49c57d5 Merge branch 'develop' into develop_update 2023-02-07 12:31:41 +01:00
e9d629b9b3 Merge branch 'develop' into develop_update 2023-02-07 12:24:27 +01:00
5b92247fbd Merge branch 'development' into add_health_service_announce_all 2023-02-06 16:31:05 +01:00
d9da55fdab Merge branch 'development' into add_health_service_announce_all 2023-02-06 15:03:52 +01:00
066f7a6f9b remove unreachable code 2023-02-06 14:41:14 +01:00
c1f42618db small but important bugfix for health service 2023-02-01 19:59:32 +01:00
61df451dd8 update changelog 2023-02-01 17:41:47 +01:00
29ea89044e beatufil 2023-02-01 17:35:49 +01:00
e487f5be87 proper announce all impl 2023-02-01 17:35:32 +01:00
48403c002d Merge remote-tracking branch 'upstream/development' into develop_update 2022-12-19 15:02:07 +01:00
e86d8c64db Merge branch 'develop' into develop_update 2022-11-28 08:36:13 +01:00
1de1b045cd Merge remote-tracking branch 'upstream/development' into develop_update 2022-11-28 08:28:56 +01:00
80 changed files with 591 additions and 567 deletions

8
.idea/cmake.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSharedSettings">
<configurations>
<configuration PROFILE_NAME="Debug Test" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DFSFW_BUILD_TESTS=ON -DFSFW_OSAL=host" />
</configurations>
</component>
</project>

View File

@ -8,17 +8,50 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
# [v6.0.0]
## Fixes
- The `PusTmCreator` API only accepted 255 bytes of source data. It can now accept source
data with a size limited only by the size of `size_t`.
- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence
number fields stored the actual length of the field instead of the length minus 1 like specified
in the CFDP standard.
- PUS Health Service: Size check for set health command.
Perform operation completion for announce health command.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745
- Small tweak for version getter
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744
## Added
- add CFDP subsystem ID
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
- `PusTmZcWriter` now exposes API to set message counter field.
## Changed
- HK generation is now countdown based.
- Bump ETL version to 20.35.14
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748
- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Assert that `FixedArrayList` is larger than 0 at compile time.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740
- Health functions are virtual now.
# [v6.0.0] 2023-02-10
## Fixes
- Add monotonic watchdog Clock API and use it in `Countdown` and `Stopwatch` class.
- Bugfix in `Service11TelecommandScheduling` which allowed commands
time tagged in the past to be inserted.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/738
- Mode Service: Add allowed subservice
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/739
- `CService200ModeManagement`: Various bugfixes which lead to now execution complete being generated
on mode announcements, duplicate mode reply generated on announce commands, and the mode read
subservice not working properly.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/736
- Memory leak fixes for the TCP/IP TMTC bridge.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/737
- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
@ -27,16 +60,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
only the X scaling factor was used.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724
- Bugfix for RM3100 MGM sensors. Z value was previously calculated
with bytes of the X value.
- HAL MGM3100 Handler: Z value was previously calculated with bytes of the X value.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/733
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
to false correctly because the `read` and `write` calls were missing.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/728
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
of the correct unsegmented flags (0b11) as specified in the standard.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/727
- TC Scheduler Service 11: Add size and CRC check for contained TC.
Bug: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/issues/719
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/720
- Only delete health table entry in `HealthHelper` destructor if
health table was set.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
Also properly reset the reply size for successfull transfers and erroneous transfers.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
@ -46,6 +83,36 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `TcpTmTcServer.cpp`: The server was actually not able to handle
CCSDS packets which were clumped together. This has been fixed now.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
- `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
- various fixes related to linux Unittests and memory leaks
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/715
- small fix to allow teardown handling
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/713
- fix compiler warning for fixed array list copy ctor
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/704
- missing include
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/703
- defaultconfig did not build anymore
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/702
- hotfix
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/699
- small fix for helper
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/698
- missing retval conv
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/697
- DHB Countdown Bug
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/693
- doc corrections
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/687
- better error printout
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/686
- include correction
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/683
- better warning for missing include paths
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/676
- Service 11 regression
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/670
## Added
@ -64,17 +131,36 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
- Add new `UnsignedByteField` class
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
- publish documentation for development and master branch
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/681
- Add Linux HAL options
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/663
- Expand SerializeIF
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/656
- PUS Service 11: Additional Safety Check
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/666
- improvements for auto-formatter script
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/665
- provide a weak print char impl
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/674
## Removed
- now that doc server is up, remove markdown files
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/688
- remove bsp specific code
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/679
## Changes
- `CService201HealthCommanding` renamed to `CServiceHealthCommanding`,
service ID customizable now. `CServiceHealthCommanding` expects configuration struct
`HealthServiceCfg` now
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
- Moved some container returnvalues to dedicated header and namespace
to they can be used without template specification.
so they can be used without template specification.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707
- Remove default secondary header argument for
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
@ -104,18 +190,41 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
interface itself so it can be re-used more easily. Also add new
abstract function `bool hasDataAtId(store_address_t storeId) const`.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
- Make functions `const` where it makes sense
- Add `const char* getName const` abstract function
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
interface itself so it can be re-used more easily. Also add new
abstract function `bool hasDataAtId(store_address_t storeId) const`.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
- Generic TMTC Bridge Update
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/734
- comment tweak to event parser can read everything
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/732
- CMakeLists file updates
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/731
- improve srv20 error messages
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/723
- I2C Linux: remove duplicate printout
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/718
- printout handling improvements
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/717
- vec getter, reset for content
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/716
- updates for source sequence counter
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/714
- SP reader getPacketData is const now
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/708
- refactoring of serial drivers for linux
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/705
- Local Pool Update Remove Add Data Ignore Fault Argument
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/701
- Switch to new documentation server
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/694
- Windows Tweaks
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/691
- Refactor Local Pool API
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/667
- group MGM data in local pool vectors
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/664
## CFDP
@ -135,17 +244,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
implementation without an extra component
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
## HAL
- SPI: Cache the SPI device in the communication interface. Architecturally, this makes a
lot more sense because each ComIF should be responsible for one SPI bus.
- SPI: Move the empty transfer to update the line polarity to separate function. This means
it is not automatically called when calling the setter function for SPI speed and mode.
The user should call this function after locking the CS mutex if multiple SPI devices with
differing speeds and modes are attached to one bus.
- SPI: Getter functions for SPI speed and mode.
# [v5.0.0] 25.07.2022
# [v5.0.0] 2022-07-25
## Changes

View File

@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
# Version file handling #
# ##############################################################################
set(FSFW_VERSION_IF_GIT_FAILS 5)
set(FSFW_VERSION_IF_GIT_FAILS 6)
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
set(FSFW_REVISION_IF_GIT_FAILS 0)
@ -72,7 +72,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}.28.0
${FSFW_ETL_LIB_MAJOR_VERSION}.35.14
CACHE STRING "ETL library exact version requirement")
set(FSFW_ETL_LINK_TARGET etl::etl)

110
scripts/check_release.py Executable file
View File

@ -0,0 +1,110 @@
#! /bin/python
import argparse
import json
import urllib.request
import re
from pathlib import Path
def main() -> None:
parser = argparse.ArgumentParser(
description="List undocumented PRs"
)
parser.add_argument("-v", "--version", type=str, required=True)
args = parser.parse_args()
match = re.search("([0-9]+\.[0-9]+\.[0-9]+)", args.version)
if not match:
print("invalid version")
exit(1)
version = "v" + match.group(1)
print("looking for milestone for " + version + " ...")
with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/milestones?name=" + version) as milestone_json:
milestones = json.load(milestone_json)
if (len(milestones) == 0):
print("did not find any milestone")
exit(1)
if (len(milestones) > 1):
print("found multiple milestons")
milestone_title = milestones[0]['title']
milestone = str(milestones[0]['id'])
print("Using Milestone \""+ milestone_title + "\" with id " + milestone)
milestone_prs = []
page = 1
last_count = 1;
while last_count != 0:
with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/pulls?state=closed&milestone=" + str(milestone) + "&limit=100&page=" + str(page)) as pull_requests_json:
pull_requests = json.load(pull_requests_json)
for pr in pull_requests:
milestone_prs.append({'number': str(pr['number']), 'title' : pr['title']})
page += 1
last_count = len(pull_requests)
print("Found " + str(len(milestone_prs)) + " closed PRs in Milestone")
print("looking for CHANGELOG.md ...")
path = Path(".")
files = list(path.glob("CHANGELOG.md"))
if (len(files) != 1):
files = list(path.glob("../CHANGELOG.md"))
if (len(files) != 1):
print("did not find CHANGELOG.md. Run script in either root directory or scripts subfolder.")
exit(1)
print("Scanning CHANGELOG.md ...")
changelog_prs = []
with open(files[0]) as changelog:
line = changelog.readline()
while (line):
#print("line: " + line)
match = re.search("\#.+(v[0-9]+\.[0-9]+\.[0-9]+)", line)
if (match):
if match.group(1) == version:
#print("found version")
line = changelog.readline()
continue
else:
#print("done with " + match.group(1))
break
match = re.search("PR: https://egit\.irs\.uni-stuttgart\.de/fsfw/fsfw/pulls/([0-9]+)", line)
if match:
changelog_prs.append(match.group(1))
line = changelog.readline()
print("Found " + str(len(changelog_prs)) + " PRs in CHANGELOG.md")
print("")
copy_array = changelog_prs.copy()
print("PRs in CHANGELOG.md that are not in Milestone:")
for pr in milestone_prs:
if pr['number'] in copy_array:
copy_array.remove(pr['number'])
for pr in copy_array:
print("https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr)
print("")
print("PRs in milestone that are not in CHANGELOG.md:")
for pr in milestone_prs:
if pr['number'] not in changelog_prs:
print("- " + pr['title'] + "\n PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr['number'])
main()

View File

@ -59,17 +59,24 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) {
bool hasAdditionalData = false;
const uint8_t* dataPtr = nullptr;
size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
return;
ReturnValue_t result;
if (dataAddress != store_address_t::invalid()) {
hasAdditionalData = true;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
return;
}
}
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
ipcStore->deleteData(dataAddress);
if (hasAdditionalData) {
ipcStore->deleteData(dataAddress);
}
if (result == HasActionsIF::EXECUTION_FINISHED) {
CommandMessage reply;
ActionMessage::setCompletionReply(&reply, actionId, true, result);

View File

@ -2,7 +2,6 @@
#define FSFW_CFDP_H
#include "cfdp/definitions.h"
#include "cfdp/handler/CfdpHandler.h"
#include "cfdp/handler/DestHandler.h"
#include "cfdp/handler/FaultHandlerBase.h"
#include "cfdp/helpers.h"

View File

@ -1,3 +1,2 @@
target_sources(
${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
FaultHandlerBase.cpp UserBase.cpp CfdpHandler.cpp)
target_sources(${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
FaultHandlerBase.cpp UserBase.cpp)

View File

@ -1,134 +0,0 @@
#include "CfdpHandler.h"
#include "fsfw/cfdp/pdu/AckPduReader.h"
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
#include "fsfw/globalfunctions/arrayprinter.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
using namespace returnvalue;
using namespace cfdp;
CfdpHandler::CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg)
: SystemObject(fsfwParams.objectId),
msgQueue(fsfwParams.msgQueue),
destHandler(
DestHandlerParams(LocalEntityCfg(cfdpCfg.id, cfdpCfg.indicCfg, cfdpCfg.faultHandler),
cfdpCfg.userHandler, cfdpCfg.remoteCfgProvider, cfdpCfg.packetInfoList,
cfdpCfg.lostSegmentsList),
FsfwParams(fsfwParams.packetDest, nullptr, this, fsfwParams.tcStore,
fsfwParams.tmStore)) {
destHandler.setMsgQueue(msgQueue);
}
[[nodiscard]] const char* CfdpHandler::getName() const { return "CFDP Handler"; }
[[nodiscard]] uint32_t CfdpHandler::getIdentifier() const {
return destHandler.getDestHandlerParams().cfg.localId.getValue();
}
[[nodiscard]] MessageQueueId_t CfdpHandler::getRequestQueue() const { return msgQueue.getId(); }
ReturnValue_t CfdpHandler::initialize() {
ReturnValue_t result = destHandler.initialize();
if (result != OK) {
return result;
}
tcStore = destHandler.getTcStore();
tmStore = destHandler.getTmStore();
return SystemObject::initialize();
}
ReturnValue_t CfdpHandler::performOperation(uint8_t operationCode) {
// TODO: Receive TC packets and route them to source and dest handler, depending on which is
// correct or more appropriate
ReturnValue_t status;
ReturnValue_t result = OK;
TmTcMessage tmtcMsg;
for (status = msgQueue.receiveMessage(&tmtcMsg); status == returnvalue::OK;
status = msgQueue.receiveMessage(&tmtcMsg)) {
result = handleCfdpPacket(tmtcMsg);
if (result != OK) {
status = result;
}
}
auto& fsmRes = destHandler.performStateMachine();
// TODO: Error handling?
while (fsmRes.callStatus == CallStatus::CALL_AGAIN) {
destHandler.performStateMachine();
// TODO: Error handling?
}
return status;
}
ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) {
auto accessorPair = tcStore->getData(msg.getStorageId());
if (accessorPair.first != OK) {
return accessorPair.first;
}
PduHeaderReader reader(accessorPair.second.data(), accessorPair.second.size());
ReturnValue_t result = reader.parseData();
if (result != returnvalue::OK) {
return INVALID_PDU_FORMAT;
}
// The CFDP distributor should have taken care of ensuring the destination ID is correct
PduType type = reader.getPduType();
// Only the destination handler can process these PDUs
if (type == PduType::FILE_DATA) {
// Disable auto-deletion of packet
accessorPair.second.release();
PacketInfo info(type, msg.getStorageId());
result = destHandler.passPacket(info);
} else {
// Route depending on PDU type and directive type if applicable. It retrieves directive type
// from the raw stream for better performance (with sanity and directive code check).
// The routing is based on section 4.5 of the CFDP standard which specifies the PDU forwarding
// procedure.
// PDU header only. Invalid supplied data. A directive packet should have a valid data field
// with at least one byte being the directive code
const uint8_t* pduDataField = reader.getPduDataField();
if (pduDataField == nullptr) {
return INVALID_PDU_FORMAT;
}
if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) {
return INVALID_DIRECTIVE_FIELD;
}
auto directive = static_cast<FileDirective>(pduDataField[0]);
auto passToDestHandler = [&]() {
accessorPair.second.release();
PacketInfo info(type, msg.getStorageId(), directive);
result = destHandler.passPacket(info);
};
auto passToSourceHandler = [&]() {
};
if (directive == FileDirective::METADATA or directive == FileDirective::EOF_DIRECTIVE or
directive == FileDirective::PROMPT) {
// Section b) of 4.5.3: These PDUs should always be targeted towards the file receiver a.k.a.
// the destination handler
passToDestHandler();
} else if (directive == FileDirective::FINISH or directive == FileDirective::NAK or
directive == FileDirective::KEEP_ALIVE) {
// Section c) of 4.5.3: These PDUs should always be targeted towards the file sender a.k.a.
// the source handler
passToSourceHandler();
} else if (directive == FileDirective::ACK) {
// Section a): Recipient depends of the type of PDU that is being acknowledged. We can simply
// extract the PDU type from the raw stream. If it is an EOF PDU, this packet is passed to
// the source handler, for a Finished PDU, it is passed to the destination handler.
FileDirective ackedDirective;
if (not AckPduReader::checkAckedDirectiveField(pduDataField[1], ackedDirective)) {
return INVALID_ACK_DIRECTIVE_FIELDS;
}
if (ackedDirective == FileDirective::EOF_DIRECTIVE) {
passToSourceHandler();
} else if (ackedDirective == FileDirective::FINISH) {
passToDestHandler();
}
}
}
return result;
}

View File

@ -1,71 +0,0 @@
#ifndef FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
#define FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
#include <utility>
#include "fsfw/cfdp/handler/DestHandler.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
struct FsfwHandlerParams {
FsfwHandlerParams(object_id_t objectId, HasFileSystemIF& vfs, AcceptsTelemetryIF& packetDest,
StorageManagerIF& tcStore, StorageManagerIF& tmStore, MessageQueueIF& msgQueue)
: objectId(objectId),
vfs(vfs),
packetDest(packetDest),
tcStore(tcStore),
tmStore(tmStore),
msgQueue(msgQueue) {}
object_id_t objectId{};
HasFileSystemIF& vfs;
AcceptsTelemetryIF& packetDest;
StorageManagerIF& tcStore;
StorageManagerIF& tmStore;
MessageQueueIF& msgQueue;
};
struct CfdpHandlerCfg {
CfdpHandlerCfg(cfdp::EntityId localId, cfdp::IndicationCfg indicationCfg,
cfdp::UserBase& userHandler, cfdp::FaultHandlerBase& userFaultHandler,
cfdp::PacketInfoListBase& packetInfo, cfdp::LostSegmentsListBase& lostSegmentsList,
cfdp::RemoteConfigTableIF& remoteCfgProvider)
: id(std::move(localId)),
indicCfg(indicationCfg),
packetInfoList(packetInfo),
lostSegmentsList(lostSegmentsList),
remoteCfgProvider(remoteCfgProvider),
userHandler(userHandler),
faultHandler(userFaultHandler) {}
cfdp::EntityId id;
cfdp::IndicationCfg indicCfg;
cfdp::PacketInfoListBase& packetInfoList;
cfdp::LostSegmentsListBase& lostSegmentsList;
cfdp::RemoteConfigTableIF& remoteCfgProvider;
cfdp::UserBase& userHandler;
cfdp::FaultHandlerBase& faultHandler;
};
class CfdpHandler : public SystemObject, public ExecutableObjectIF, public AcceptsTelecommandsIF {
public:
explicit CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg);
[[nodiscard]] const char* getName() const override;
[[nodiscard]] uint32_t getIdentifier() const override;
[[nodiscard]] MessageQueueId_t getRequestQueue() const override;
ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t operationCode) override;
private:
MessageQueueIF& msgQueue;
cfdp::DestHandler destHandler;
StorageManagerIF* tcStore = nullptr;
StorageManagerIF* tmStore = nullptr;
ReturnValue_t handleCfdpPacket(TmTcMessage& msg);
};
#endif // FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H

View File

@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
*buffer += 1;
**buffer = pduDataFieldLen & 0x00ff;
*buffer += 1;
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
pduConf.seqNum.getWidth();
**buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) |
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
*buffer += 1;
*size += 4;
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);

View File

@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
}
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
return static_cast<cfdp::WidthInBytes>(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1);
}
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1);
}
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {

View File

@ -58,7 +58,7 @@ void ControllerBase::handleQueue() {
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
changeHK(this->mode, this->submode, false);
triggerEvent(CHANGING_MODE, mode, submode);
triggerEvent(CHANGING_MODE, mode_, submode_);
mode = mode_;
submode = submode_;
modeHelper.modeChanged(mode, submode);

View File

@ -166,9 +166,9 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, time
timeval timeSinceEpoch = time - epoch;
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.;
double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365;
double monthsSinceEpoch = minutesSinceEpoch / 60 / 24 / 30;
if ((yearsSinceEpoch > 1) || (yearsSinceEpoch < -1)) {
if ((monthsSinceEpoch > 1) || (monthsSinceEpoch < -1)) {
return TLE_TOO_OLD;
}

View File

@ -70,8 +70,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(uint8_t nonDiagInvlFactor) {
setNonDiagnosticIntervalFactor(nonDiagInvlFactor);
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation() {
return initializeHousekeepingPoolEntriesOnce();
}
@ -506,9 +505,9 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
float newCollIntvl = 0;
HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl);
if (command == HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) {
result = changeCollectionInterval(sid, newCollIntvl, true);
result = changeCollectionInterval(sid, newCollIntvl);
} else {
result = changeCollectionInterval(sid, newCollIntvl, false);
result = changeCollectionInterval(sid, newCollIntvl);
}
break;
}
@ -661,10 +660,6 @@ ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(HousekeepingPacke
return hkPacket.serialize(&dataPtr, serializedSize, maxSize, SerializeIF::Endianness::MACHINE);
}
void LocalDataPoolManager::setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor) {
this->nonDiagnosticIntervalFactor = nonDiagInvlFactor;
}
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
sid_t sid = receiver.dataId.sid;
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
@ -718,15 +713,15 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool ena
if ((LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and enable) or
(not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and not enable)) {
return REPORTING_STATUS_UNCHANGED;
return returnvalue::OK;
}
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable);
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float newCollectionInterval,
bool isDiagnostics) {
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
float newCollectionInterval) {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
@ -734,11 +729,6 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float ne
return DATASET_NOT_FOUND;
}
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
if ((targetIsDiagnostics and not isDiagnostics) or (not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE;
}
PeriodicHousekeepingHelper* periodicHelper =
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);

View File

@ -102,7 +102,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
* @param nonDiagInvlFactor
* @return
*/
ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5);
ReturnValue_t initializeAfterTaskCreation();
/**
* @brief This should be called in the periodic handler of the owner.
@ -152,17 +152,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
MessageQueueId_t targetQueueId,
bool generateSnapshot) override;
/**
* Non-Diagnostics packets usually have a lower minimum sampling frequency
* than diagnostic packets.
* A factor can be specified to determine the minimum sampling frequency
* for non-diagnostic packets. The minimum sampling frequency of the
* diagnostics packets,which is usually jusst the period of the
* performOperation calls, is multiplied with that factor.
* @param factor
*/
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
/**
* @brief The manager is also able to handle housekeeping messages.
* @details
@ -185,6 +174,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet,
bool forDownlink,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval);
HasLocalDataPoolIF* getOwner();
@ -348,8 +338,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, bool isDiagnostics);
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval,
bool isDiagnostics);
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);

View File

@ -250,9 +250,8 @@ void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; }
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, nonDiagIntervalFactor);
dur_millis_t minimumPeriodicInterval) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval);
}
void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; }

View File

@ -191,8 +191,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
*/
bool reportingEnabled = false;
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor = 5);
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval);
/**
* If the valid state of a dataset is always relevant to the whole

View File

@ -12,10 +12,8 @@ class LocalPoolDataSetAttorney {
static bool isDiagnostics(LocalPoolDataSetBase& set) { return set.isDiagnostics(); }
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
uint32_t minimumPeriodicIntervalMs,
uint8_t nonDiagIntervalFactor = 5) {
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs,
nonDiagIntervalFactor);
uint32_t minimumPeriodicIntervalMs) {
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs);
}
static void setReportingEnabled(LocalPoolDataSetBase& set, bool enabled) {

View File

@ -49,6 +49,7 @@ class DeviceCommunicationIF {
// is this needed if there is no open/close call?
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06);
static constexpr ReturnValue_t BUSY = MAKE_RETURN_CODE(0x07);
virtual ~DeviceCommunicationIF() {}

View File

@ -567,7 +567,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
continueToNormal = false;
// TODO: Check whether the following two lines are okay to do so.
transitionSourceMode = MODE_ON;
transitionSourceSubMode = submode;
transitionSourceSubMode = newSubmode;
mode = _MODE_TO_NORMAL;
return;
}

View File

@ -257,8 +257,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const;
virtual void getMode(Mode_t *mode, Submode_t *submode);
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual HealthState getHealth() override;
virtual ReturnValue_t setHealth(HealthState health) override;
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues,

View File

@ -10,8 +10,9 @@
object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent)
: FailureIsolationBase(owner, parent),
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent,
uint8_t eventQueueDepth)
: FailureIsolationBase(owner, parent, eventQueueDepth),
strangeReplyCount(DEFAULT_MAX_STRANGE_REPLIES, DEFAULT_STRANGE_REPLIES_TIME_MS,
parameterDomainBase++),
missedReplyCount(DEFAULT_MAX_MISSED_REPLY_COUNT, DEFAULT_MISSED_REPLY_TIME_MS,

View File

@ -13,7 +13,8 @@ class DeviceHandlerFailureIsolation : public FailureIsolationBase {
friend class Heater;
public:
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent);
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent,
uint8_t eventQueueDepth = 10);
~DeviceHandlerFailureIsolation();
ReturnValue_t initialize();
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);

View File

@ -29,11 +29,10 @@ ReturnValue_t HealthDevice::initialize() {
if (result != returnvalue::OK) {
return result;
}
if (parentQueue != 0) {
if (parentQueue != MessageQueueIF::NO_QUEUE) {
return healthHelper.initialize(parentQueue);
} else {
return healthHelper.initialize();
}
return healthHelper.initialize();
}
MessageQueueId_t HealthDevice::getCommandQueue() const { return commandQueue->getId(); }

View File

@ -29,10 +29,8 @@ class HealthDevice : public SystemObject, public ExecutableObjectIF, public HasH
protected:
HealthState lastHealth;
MessageQueueId_t parentQueue;
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
MessageQueueIF* commandQueue;
public:
HealthHelper healthHelper;
};

View File

@ -55,8 +55,9 @@ void EventManager::notifyListeners(EventMessage* message) {
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
<< result << std::setfill(' ') << std::endl;
<< std::setw(8) << listener.first << " for event 0x" << std::setw(4)
<< message->getEventId() << " failed with result 0x" << std::setw(4) << result
<< std::setfill(' ') << std::endl;
#else
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
listener.first, result);

View File

@ -10,7 +10,7 @@ enum : uint8_t {
CDH = 28,
TCS_1 = 59,
PCDU_1 = 42,
PCDU_2 = 43,
POWER_SWITCH_IF = 43,
HEATER = 50,
T_SENSORS = 52,
FDIR = 70,

View File

@ -18,8 +18,11 @@
*/
class DleParser {
public:
//! [EXPORT] : [SKIP]
static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(1, 1);
//! [EXPORT] : [SKIP]
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS = returnvalue::makeCode(1, 2);
using BufPair = std::pair<uint8_t*, size_t>;
enum class ContextType { NONE, PACKET_FOUND, ERROR };

View File

@ -53,8 +53,9 @@ class VectorOperations {
mulScalar(vector, 1 / norm(vector, size), normalizedVector, size);
}
static T maxAbsValue(const T *vector, uint8_t size, uint8_t *index = 0) {
T max = -1;
static T maxAbsValue(const T *vector, uint8_t size, uint8_t *index = nullptr) {
T max = vector[size - 1];
uint8_t foundIndex = size - 1;
for (; size > 0; size--) {
T abs = vector[size - 1];
@ -64,24 +65,35 @@ class VectorOperations {
if (abs > max) {
max = abs;
if (index != 0) {
*index = size - 1;
foundIndex = size - 1;
}
}
}
if (index != nullptr) {
*index = foundIndex;
}
return max;
}
static T maxValue(const T *vector, uint8_t size, uint8_t *index = 0) {
T max = -1;
static T maxValue(const T *vector, uint8_t size, uint8_t *index = nullptr) {
T max = vector[size - 1];
uint8_t foundIndex = size - 1;
for (; size > 0; size--) {
if (vector[size - 1] > max) {
max = vector[size - 1];
if (index != 0) {
*index = size - 1;
foundIndex = size - 1;
}
}
}
if (index != nullptr) {
*index = foundIndex;
}
return max;
}

View File

@ -3,85 +3,37 @@
#include <cmath>
#include "fsfw/datapoollocal/LocalPoolDataSetBase.h"
#include "fsfw/serviceinterface.h"
PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner)
: owner(owner) {}
void PeriodicHousekeepingHelper::initialize(float collectionInterval,
dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor) {
dur_millis_t minimumPeriodicInterval) {
this->minimumPeriodicInterval = minimumPeriodicInterval;
this->nonDiagIntervalFactor = nonDiagIntervalFactor;
collectionIntervalTicks = intervalSecondsToIntervalTicks(collectionInterval);
/* This will cause a checkOpNecessary call to be true immediately. I think it's okay
if a HK packet is generated immediately instead of waiting one generation cycle. */
internalTickCounter = collectionIntervalTicks;
changeCollectionInterval(collectionInterval);
}
float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() const {
return intervalTicksToSeconds(collectionIntervalTicks);
return collectionInterval;
}
bool PeriodicHousekeepingHelper::checkOpNecessary() {
if (internalTickCounter >= collectionIntervalTicks) {
internalTickCounter = 1;
if (hkGenerationCd.hasTimedOut()) {
hkGenerationCd.resetTimer();
return true;
}
internalTickCounter++;
return false;
}
uint32_t PeriodicHousekeepingHelper::intervalSecondsToIntervalTicks(
float collectionIntervalSeconds) {
if (owner == nullptr) {
return 0;
}
bool isDiagnostics = owner->isDiagnostics();
/* Avoid division by zero */
if (minimumPeriodicInterval == 0) {
if (isDiagnostics) {
/* Perform operation each cycle */
return 1;
} else {
return nonDiagIntervalFactor;
}
} else {
dur_millis_t intervalInMs = collectionIntervalSeconds * 1000;
uint32_t divisor = minimumPeriodicInterval;
if (not isDiagnostics) {
/* We need to multiply the divisor because non-diagnostics only
allow a multiple of the minimum periodic interval */
divisor *= nonDiagIntervalFactor;
}
uint32_t ticks = std::ceil(static_cast<float>(intervalInMs) / divisor);
if (not isDiagnostics) {
/* Now we need to multiply the calculated ticks with the factor as as well
because the minimum tick count to generate a non-diagnostic is the factor itself.
Example calculation for non-diagnostic with
0.4 second interval and 0.2 second task interval.
Resultant tick count of 5 is equal to operation each second.
Examle calculation for non-diagnostic with 2.0 second interval and 0.2 second
task interval.
Resultant tick count of 10 is equal to operatin every 2 seconds.
Example calculation for diagnostic with 0.4 second interval and 0.3
second task interval. Resulting tick count of 2 is equal to operation
every 0.6 seconds. */
ticks *= nonDiagIntervalFactor;
}
return ticks;
}
}
float PeriodicHousekeepingHelper::intervalTicksToSeconds(uint32_t collectionInterval) const {
/* Number of ticks times the minimum interval is in milliseconds, so we divide by 1000 to get
the value in seconds */
return static_cast<float>(collectionInterval * minimumPeriodicInterval / 1000.0);
}
void PeriodicHousekeepingHelper::changeCollectionInterval(float newIntervalSeconds) {
collectionIntervalTicks = intervalSecondsToIntervalTicks(newIntervalSeconds);
uint32_t intervalMs = newIntervalSeconds * 1000;
if (newIntervalSeconds <= 0) {
intervalMs = minimumPeriodicInterval;
newIntervalSeconds = static_cast<float>(minimumPeriodicInterval) / 1000.0;
}
collectionInterval = newIntervalSeconds;
hkGenerationCd.setTimeout(intervalMs);
// We want an immediate HK packet at the start, so time out the generation CD immediately.
hkGenerationCd.timeOut();
}

View File

@ -4,6 +4,7 @@
#include <cstdint>
#include "fsfw/timemanager/Clock.h"
#include "fsfw/timemanager/Countdown.h"
class LocalPoolDataSetBase;
@ -11,8 +12,7 @@ class PeriodicHousekeepingHelper {
public:
PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner);
void initialize(float collectionInterval, dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor);
void initialize(float collectionInterval, dur_millis_t minimumPeriodicInterval);
void changeCollectionInterval(float newInterval);
float getCollectionIntervalInSeconds() const;
@ -20,14 +20,10 @@ class PeriodicHousekeepingHelper {
private:
LocalPoolDataSetBase* owner = nullptr;
uint8_t nonDiagIntervalFactor = 0;
uint32_t intervalSecondsToIntervalTicks(float collectionIntervalSeconds);
float intervalTicksToSeconds(uint32_t collectionInterval) const;
Countdown hkGenerationCd;
float collectionInterval = 0.0;
dur_millis_t minimumPeriodicInterval = 0;
uint32_t internalTickCounter = 1;
uint32_t collectionIntervalTicks = 0;
};
#endif /* FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ */

View File

@ -5,9 +5,12 @@
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth,
bool enableSetByDefault, float generationFrequency)
: SystemObject(setObjectId),
poolManager(this, commandQueue),
enableSetByDefault(enableSetByDefault),
generationFrequency(generationFrequency),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
@ -134,9 +137,8 @@ ReturnValue_t InternalErrorReporter::initializeLocalDataPool(localpool::DataPool
localDataPoolMap.emplace(errorPoolIds::TM_HITS, &tmHitsEntry);
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, &queueHitsEntry);
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, &storeHitsEntry);
poolManager.subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams(
internalErrorSid, false,
static_cast<float>(getPeriodicOperationFrequency()) / static_cast<float>(1000.0)));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(internalErrorSid, enableSetByDefault, generationFrequency));
internalErrorDataset.setValidity(true, true);
return returnvalue::OK;
}

View File

@ -21,7 +21,8 @@ class InternalErrorReporter : public SystemObject,
public InternalErrorReporterIF,
public HasLocalDataPoolIF {
public:
InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth = 5);
InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth,
bool enableSetByDefault, float generationFrequency);
/**
* Enable diagnostic printout. Please note that this feature will
@ -63,6 +64,8 @@ class InternalErrorReporter : public SystemObject,
MutexIF* mutex = nullptr;
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 20;
bool enableSetByDefault;
float generationFrequency;
sid_t internalErrorSid;
InternalErrorDataset internalErrorDataset;

View File

@ -20,16 +20,18 @@ TaskFactory::~TaskFactory() = default;
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
PeriodicTaskIF* TaskFactory::createPeriodicTask(
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
TaskStackSize stackSize_,
TaskPeriod periodInSeconds_,
TaskDeadlineMissedFunction deadLineMissedFunction_,
void* args) {
return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_,
deadLineMissedFunction_);
}
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_, void* args) {
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_,
deadLineMissedFunction_);
}

View File

@ -89,8 +89,6 @@ timeval Clock::getUptime() {
}
ReturnValue_t Clock::getUptime(timeval* uptime) {
// TODO This is not posix compatible and delivers only seconds precision
// Linux specific file read but more precise.
double uptimeSeconds;
std::ifstream ifile("/proc/uptime");
if (ifile.bad()) {

View File

@ -7,10 +7,15 @@
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
FixedTimeslotTask::FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_)
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_,
PosixThreadArgs* args)
: FixedTimeslotTaskBase(periodSeconds_, dlmFunc_),
posixThread(name_, priority_, stackSize_),
started(false) {}
posixThread(name_, SchedulingPolicy::REGULAR, priority_, stackSize_),
started(false) {
if (args != nullptr) {
posixThread.setSchedPolicy(args->policy);
}
}
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
// The argument is re-interpreted as PollingTask.

View File

@ -23,7 +23,8 @@ class FixedTimeslotTask : public FixedTimeslotTaskBase {
* @param deadlineMissedFunc_
*/
FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_);
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_,
PosixThreadArgs* args);
~FixedTimeslotTask() override = default;
ReturnValue_t startTask() override;

View File

@ -4,10 +4,15 @@
#include "fsfw/tasks/ExecutableObjectIF.h"
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_,
TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_)
TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_,
PosixThreadArgs* args)
: PeriodicTaskBase(period_, dlmFunc_),
posixThread(name_, priority_, stackSize_),
started(false) {}
posixThread(name_, SchedulingPolicy::REGULAR, priority_, stackSize_),
started(false) {
if (args != nullptr) {
posixThread.setSchedPolicy(args->policy);
}
}
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
// The argument is re-interpreted as PollingTask.

View File

@ -24,7 +24,7 @@ class PeriodicPosixTask : public PeriodicTaskBase {
* @param deadlineMissedFunc_
*/
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_,
TaskDeadlineMissedFunction dlmFunc_);
TaskDeadlineMissedFunction dlmFunc_, PosixThreadArgs* args);
~PeriodicPosixTask() override = default;
/**

View File

@ -7,8 +7,9 @@
#include "fsfw/osal/linux/unixUtility.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_)
: thread(0), priority(priority_), stackSize(stackSize_) {
PosixThread::PosixThread(const char* name_, SchedulingPolicy schedPolciy, int priority_,
size_t stackSize_)
: thread(0), schedPolicy(schedPolciy), priority(priority_), stackSize(stackSize_) {
name[0] = '\0';
std::strncat(name, name_, PTHREAD_MAX_NAMELEN - 1);
}
@ -178,20 +179,30 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
#ifndef FSFW_USE_REALTIME_FOR_LINUX
#error "Please define FSFW_USE_REALTIME_FOR_LINUX with either 0 or 1"
#endif
if (schedPolicy == SchedulingPolicy::RR) {
// RR -> This needs root privileges for the process
#if FSFW_USE_REALTIME_FOR_LINUX == 1
// FIFO -> This needs root privileges for the process
status = pthread_attr_setschedpolicy(&attributes, SCHED_FIFO);
if (status != 0) {
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedpolicy");
status = pthread_attr_setschedpolicy(&attributes, SCHED_RR);
if (status != 0) {
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedpolicy");
}
sched_param scheduleParams;
scheduleParams.sched_priority = priority;
status = pthread_attr_setschedparam(&attributes, &scheduleParams);
if (status != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "PosixThread: Setting priority failed" << std::endl;
#endif
}
#else
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning
<< "Real time priorities are only allowed if FSFW_USE_REALTIME_FOR_LINUX is set to 1"
<< std::endl;
#endif
#endif
}
sched_param scheduleParams;
scheduleParams.__sched_priority = priority;
status = pthread_attr_setschedparam(&attributes, &scheduleParams);
if (status != 0) {
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedparam");
}
#endif
// Set Signal Mask for suspend until startTask is called
sigset_t waitSignal;
sigemptyset(&waitSignal);
@ -243,3 +254,5 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_destroy");
}
}
void PosixThread::setSchedPolicy(SchedulingPolicy policy) { this->schedPolicy = policy; }

View File

@ -9,10 +9,15 @@
#include "../../returnvalues/returnvalue.h"
enum SchedulingPolicy { REGULAR, RR };
struct PosixThreadArgs {
SchedulingPolicy policy = SchedulingPolicy::REGULAR;
};
class PosixThread {
public:
static constexpr uint8_t PTHREAD_MAX_NAMELEN = 16;
PosixThread(const char* name_, int priority_, size_t stackSize_);
PosixThread(const char* name_, SchedulingPolicy schedPolicy, int priority_, size_t stackSize_);
virtual ~PosixThread();
/**
* Set the Thread to sleep state
@ -20,6 +25,9 @@ class PosixThread {
* @return Returns Failed if sleep fails
*/
static ReturnValue_t sleep(uint64_t ns);
void setSchedPolicy(SchedulingPolicy policy);
/**
* @brief Function to suspend the task until SIGUSR1 was received
*
@ -72,6 +80,7 @@ class PosixThread {
private:
char name[PTHREAD_MAX_NAMELEN];
SchedulingPolicy schedPolicy;
int priority;
size_t stackSize = 0;

View File

@ -12,18 +12,20 @@ TaskFactory::~TaskFactory() = default;
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
PeriodicTaskIF* TaskFactory::createPeriodicTask(
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
TaskStackSize stackSize_,
TaskPeriod periodInSeconds_,
TaskDeadlineMissedFunction deadLineMissedFunction_,
void* args) {
return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_,
deadLineMissedFunction_);
deadLineMissedFunction_, reinterpret_cast<PosixThreadArgs*>(args));
}
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_, void* args) {
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_,
deadLineMissedFunction_);
deadLineMissedFunction_, reinterpret_cast<PosixThreadArgs*>(args));
}
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {

View File

@ -1,5 +1,5 @@
#include "fsfw/osal/rtems/BinarySemaphore.h"
//#include "fsfw/osal/rtems/CountingSemaphore.h"
// #include "fsfw/osal/rtems/CountingSemaphore.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/tasks/SemaphoreFactory.h"

View File

@ -6,7 +6,11 @@ DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwit
: SystemObject(objectId, registerGlobally),
switcherList(numberOfSwitches),
fuseList(numberOfFuses),
switchDelayMs(switchDelayMs) {}
switchDelayMs(switchDelayMs) {
for (auto &switchState : switcherList) {
switchState = PowerSwitchIF::SWITCH_UNKNOWN;
}
}
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
this->switcherList = switcherList;

View File

@ -32,7 +32,7 @@ class Fuse : public SystemObject,
gp_id_t poolIdPower;
};
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF;
//! PSS detected that current on a fuse is totally out of bounds.
static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(1, severity::LOW);
//! PSS detected a fuse that went off.

View File

@ -28,7 +28,9 @@ class PowerSwitchIF {
static const ReturnValue_t SWITCH_TIMEOUT = MAKE_RETURN_CODE(2);
static const ReturnValue_t FUSE_ON = MAKE_RETURN_CODE(3);
static const ReturnValue_t FUSE_OFF = MAKE_RETURN_CODE(4);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_2;
static const ReturnValue_t SWITCH_UNKNOWN = MAKE_RETURN_CODE(5);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF;
//!< Someone detected that a switch went off which shouldn't. Severity:
//!< Low, Parameter1: switchId1, Parameter2: switchId2
static const Event SWITCH_WENT_OFF = MAKE_EVENT(0, severity::LOW);
@ -50,6 +52,7 @@ class PowerSwitchIF {
* @return
* - @c SWITCH_ON if the specified switch is on.
* - @c SWITCH_OFF if the specified switch is off.
* - @c SWITCH_UNKNOWN if the state of the specified switch is unknown.
* - @c returnvalue::FAILED if an error occured
*/
virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const = 0;

View File

@ -2,6 +2,7 @@
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/power/PowerSwitchIF.h>
#include <fsfw/subsystem/helper.h>
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
power::Switch_t pwrSwitch)
@ -28,6 +29,9 @@ ReturnValue_t PowerSwitcherComponent::performOperation(uint8_t opCode) {
continue;
}
}
if (getHealth() == FAULTY) {
performFaultyOperation();
}
if (switcher.active()) {
switcher.doStateMachine();
auto currState = switcher.getState();
@ -111,9 +115,11 @@ const HasHealthIF* PowerSwitcherComponent::getOptHealthIF() const { return this;
const HasModesIF& PowerSwitcherComponent::getModeIF() const { return *this; }
ReturnValue_t PowerSwitcherComponent::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return parent.registerChild(*this);
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
}
object_id_t PowerSwitcherComponent::getObjectId() const { return SystemObject::getObjectId(); }
ModeTreeChildIF& PowerSwitcherComponent::getModeTreeChildIF() { return *this; }
void PowerSwitcherComponent::performFaultyOperation() {}

View File

@ -1,5 +1,4 @@
#ifndef _FSFW_POWER_POWERSWITCHERCOMPONENT_H_
#define _FSFW_POWER_POWERSWITCHERCOMPONENT_H_
#pragma once
#include <fsfw/health/HasHealthIF.h>
#include <fsfw/health/HealthHelper.h>
@ -37,11 +36,13 @@ class PowerSwitcherComponent : public SystemObject,
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
private:
MessageQueueIF *queue = nullptr;
protected:
PowerSwitcher switcher;
Mode_t mode = MODE_OFF;
private:
MessageQueueIF *queue = nullptr;
Mode_t mode = MODE_UNDEFINED;
Submode_t submode = 0;
ModeHelper modeHelper;
@ -49,24 +50,23 @@ class PowerSwitcherComponent : public SystemObject,
void setMode(Mode_t newMode, Submode_t newSubmode);
virtual ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initialize() override;
MessageQueueId_t getCommandQueue() const override;
[[nodiscard]] 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;
void startTransition(Mode_t mode, Submode_t submode) override;
virtual void performFaultyOperation();
void setToExternalControl() override;
void announceMode(bool recursive) override;
ReturnValue_t setHealth(HealthState health) override;
HasHealthIF::HealthState getHealth() override;
object_id_t getObjectId() const override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
[[nodiscard]] object_id_t getObjectId() const override;
[[nodiscard]] const HasHealthIF *getOptHealthIF() const override;
[[nodiscard]] const HasModesIF &getModeIF() const override;
};
#endif /* _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ */

View File

@ -10,9 +10,23 @@
CServiceHealthCommanding::CServiceHealthCommanding(HealthServiceCfg args)
: CommandingServiceBase(args.objectId, args.apid, "PUS 201 Health MGMT", args.service,
args.numParallelCommands, args.commandTimeoutSeconds),
healthTable(args.table),
healthTableId(args.table),
maxNumHealthInfoPerCycle(args.maxNumHealthInfoPerCycle) {}
ReturnValue_t CServiceHealthCommanding::initialize() {
ReturnValue_t result = CommandingServiceBase::initialize();
if (result != returnvalue::OK) {
return result;
}
healthTable = ObjectManager::instance()->get<HealthTable>(healthTableId);
if (healthTable == nullptr) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t CServiceHealthCommanding::isValidSubservice(uint8_t subservice) {
switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH):
@ -91,14 +105,6 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message,
return EXECUTION_COMPLETE;
}
return result;
while (true) {
ReturnValue_t result = iterateHealthTable(false);
if (result != returnvalue::OK) {
break;
}
}
return returnvalue::OK;
}
default: {
// Should never happen, subservice was already checked
@ -145,7 +151,7 @@ void CServiceHealthCommanding::doPeriodicOperation() {
ReturnValue_t CServiceHealthCommanding::iterateHealthTable(bool reset) {
std::pair<object_id_t, HasHealthIF::HealthState> pair;
ReturnValue_t result = healthTable.iterate(&pair, reset);
ReturnValue_t result = healthTable->iterate(&pair, reset);
if (result != returnvalue::OK) {
return result;
} else {

View File

@ -6,7 +6,7 @@
#include "fsfw/tmtcservices/CommandingServiceBase.h"
struct HealthServiceCfg {
HealthServiceCfg(object_id_t objectId, uint16_t apid, HealthTable &healthTable,
HealthServiceCfg(object_id_t objectId, uint16_t apid, object_id_t healthTable,
uint16_t maxNumHealthInfoPerCycle)
: objectId(objectId),
apid(apid),
@ -14,7 +14,7 @@ struct HealthServiceCfg {
maxNumHealthInfoPerCycle(maxNumHealthInfoPerCycle) {}
object_id_t objectId;
uint16_t apid;
HealthTable &table;
object_id_t table;
uint16_t maxNumHealthInfoPerCycle;
uint8_t service = 201;
uint8_t numParallelCommands = 4;
@ -40,6 +40,8 @@ class CServiceHealthCommanding : public CommandingServiceBase {
CServiceHealthCommanding(HealthServiceCfg args);
~CServiceHealthCommanding() override = default;
ReturnValue_t initialize() override;
protected:
/* CSB abstract function implementations */
ReturnValue_t isValidSubservice(uint8_t subservice) override;
@ -57,7 +59,8 @@ class CServiceHealthCommanding : public CommandingServiceBase {
void doPeriodicOperation() override;
private:
HealthTable &healthTable;
const object_id_t healthTableId;
HealthTable *healthTable;
uint16_t maxNumHealthInfoPerCycle = 0;
bool reportAllHealth = false;
ReturnValue_t iterateHealthTable(bool reset);

View File

@ -4,9 +4,10 @@
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/pus/servicepackets/Service3Packets.h"
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId)
: CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, NUM_OF_PARALLEL_COMMANDS,
COMMAND_TIMEOUT_SECONDS) {}
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint32_t queueDepth, uint8_t numParallelCommands)
: CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, numParallelCommands,
COMMAND_TIMEOUT_SECONDS, queueDepth) {}
Service3Housekeeping::~Service3Housekeeping() {}

View File

@ -28,7 +28,8 @@ class Service3Housekeeping : public CommandingServiceBase, public AcceptsHkPacke
static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4;
static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60;
Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId);
Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId, uint32_t queueDepth,
uint8_t numParallelCommands);
virtual ~Service3Housekeeping();
protected:

View File

@ -9,11 +9,11 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
Service8FunctionManagement::Service8FunctionManagement(object_id_t objectId, uint16_t apid,
uint8_t serviceId,
uint8_t serviceId, size_t queueDepth,
uint8_t numParallelCommands,
uint16_t commandTimeoutSeconds)
: CommandingServiceBase(objectId, apid, "PUS 8 Functional Commanding", serviceId,
numParallelCommands, commandTimeoutSeconds) {}
numParallelCommands, commandTimeoutSeconds, queueDepth) {}
Service8FunctionManagement::~Service8FunctionManagement() {}

View File

@ -31,7 +31,8 @@
class Service8FunctionManagement : public CommandingServiceBase {
public:
Service8FunctionManagement(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
size_t queueDepth, uint8_t numParallelCommands = 4,
uint16_t commandTimeoutSeconds = 60);
~Service8FunctionManagement() override;
protected:

View File

@ -10,11 +10,11 @@
//////////////////////////////////////////////////////////////////////////////////
// RMAP command bits
//#define RMAP_COMMAND_BIT_INCREMENT 2
//#define RMAP_COMMAND_BIT_REPLY 3
//#define RMAP_COMMAND_BIT_WRITE 5
//#define RMAP_COMMAND_BIT_VERIFY 4
//#define RMAP_COMMAND_BIT 6
// #define RMAP_COMMAND_BIT_INCREMENT 2
// #define RMAP_COMMAND_BIT_REPLY 3
// #define RMAP_COMMAND_BIT_WRITE 5
// #define RMAP_COMMAND_BIT_VERIFY 4
// #define RMAP_COMMAND_BIT 6
namespace RMAPIds {
@ -32,14 +32,14 @@ static const uint8_t RMAP_COMMAND_READ = ((1 << RMAP_COMMAND_BIT) | (1 << RMAP_C
static const uint8_t RMAP_REPLY_WRITE =
((1 << RMAP_COMMAND_BIT_WRITE) | (1 << RMAP_COMMAND_BIT_REPLY));
static const uint8_t RMAP_REPLY_READ = ((1 << RMAP_COMMAND_BIT_REPLY));
//#define RMAP_COMMAND_WRITE ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE)
// #define RMAP_COMMAND_WRITE ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE)
//| (1<<RMAP_COMMAND_BIT_REPLY)) #define RMAP_COMMAND_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT) |
//(1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define
// RMAP_COMMAND_READ ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY))
// RMAP_COMMAND_READ ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_REPLY_WRITE ((1<<RMAP_COMMAND_BIT_WRITE) |
// #define RMAP_REPLY_WRITE ((1<<RMAP_COMMAND_BIT_WRITE) |
//(1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_REPLY_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT_WRITE) |
// #define RMAP_REPLY_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT_WRITE) |
//(1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define RMAP_REPLY_READ
//((1<<RMAP_COMMAND_BIT_REPLY))
@ -49,9 +49,9 @@ static const uint8_t RMAP_COMMAND_HEADER_LEN = 16;
static const uint8_t RMAP_WRITE_REPLY_HEADER_LEN = 8;
static const uint8_t RMAP_READ_REPLY_HEADER_LEN = 12;
static const uint8_t RMAP_DATA_FOOTER_SIZE = 1; // SIZE OF CRC
//#define RMAP_COMMAND_HEADER_LEN 16
//#define RMAP_WRITE_REPLY_HEADER_LEN 8
//#define RMAP_READ_REPLY_HEADER_LEN 12
// #define RMAP_COMMAND_HEADER_LEN 16
// #define RMAP_WRITE_REPLY_HEADER_LEN 8
// #define RMAP_READ_REPLY_HEADER_LEN 12
} // namespace RMAPIds

View File

@ -3,7 +3,7 @@
#include "fsfw/FSFW.h"
PoolManager::PoolManager(object_id_t setObjectId, const LocalPoolConfig& localPoolConfig)
: LocalPool(setObjectId, localPoolConfig, true) {
: LocalPool(setObjectId, localPoolConfig, true, true) {
mutex = MutexFactory::instance()->createMutex();
}

View File

@ -315,20 +315,7 @@ object_id_t SubsystemBase::getObjectId() const { return SystemObject::getObjectI
void SubsystemBase::modeChanged() {}
ReturnValue_t SubsystemBase::registerChild(const ModeTreeChildIF& child) {
ChildInfo info;
const HasModesIF& modeChild = child.getModeIF();
// intentional to force an initial command during system startup
info.commandQueue = modeChild.getCommandQueue();
info.mode = HasModesIF::MODE_UNDEFINED;
info.submode = SUBMODE_NONE;
info.healthChanged = false;
auto resultPair = childrenMap.emplace(child.getObjectId(), info);
if (not resultPair.second) {
return COULD_NOT_INSERT_CHILD;
}
return returnvalue::OK;
return registerChild(child.getObjectId(), child.getModeIF().getCommandQueue());
}
const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; }
@ -336,3 +323,19 @@ const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; }
const HasModesIF& SubsystemBase::getModeIF() const { return *this; }
ModeTreeChildIF& SubsystemBase::getModeTreeChildIF() { return *this; }
ReturnValue_t SubsystemBase::registerChild(object_id_t childObjectId, MessageQueueId_t childQueue) {
ChildInfo info;
// intentional to force an initial command during system startup
info.commandQueue = childQueue;
info.mode = HasModesIF::MODE_UNDEFINED;
info.submode = SUBMODE_NONE;
info.healthChanged = false;
auto resultPair = childrenMap.emplace(childObjectId, info);
if (not resultPair.second) {
return COULD_NOT_INSERT_CHILD;
}
return returnvalue::OK;
}

View File

@ -61,6 +61,8 @@ class SubsystemBase : public SystemObject,
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
*/
ReturnValue_t registerChild(const ModeTreeChildIF &child) override;
// TODO: Add this to HasModeTreeChildrenIF.
ReturnValue_t registerChild(object_id_t childObjectId, MessageQueueId_t childQueue);
ReturnValue_t initialize() override;

View File

@ -47,7 +47,8 @@ class TaskFactory {
*/
PeriodicTaskIF* createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
TaskStackSize stackSize_, TaskPeriod periodInSeconds_,
TaskDeadlineMissedFunction deadLineMissedFunction_);
TaskDeadlineMissedFunction deadLineMissedFunction_,
void* args = nullptr);
/**
* The meaning for the variables for fixed timeslot tasks is the same as for periodic tasks.
@ -62,7 +63,8 @@ class TaskFactory {
FixedTimeslotTaskIF* createFixedTimeslotTask(TaskName name_, TaskPriority taskPriority_,
TaskStackSize stackSize_,
TaskPeriod periodInSeconds_,
TaskDeadlineMissedFunction deadLineMissedFunction_);
TaskDeadlineMissedFunction deadLineMissedFunction_,
void* args = nullptr);
/**
* Function to be called to delete a task

View File

@ -40,7 +40,7 @@ struct PusTmParams {
size_t dataLen)
: secHeader(service, subservice, timeStamper), adapter(data, dataLen), sourceData(&adapter) {}
PusTmSecHeader secHeader;
SerialBufferAdapter<uint8_t> adapter;
SerialBufferAdapter<size_t> adapter;
const SerializeIF* sourceData = nullptr;
};

View File

@ -24,3 +24,9 @@ void PusTmZeroCopyWriter::updateErrorControl() {
crcStart[0] = (crc16 >> 8) & 0xff;
crcStart[1] = crc16 & 0xff;
}
void PusTmZeroCopyWriter::setMessageCount(uint16_t msgCount) {
size_t serSize = 0;
SerializeAdapter::serialize(&msgCount, const_cast<uint8_t*>(pointers.secHeaderStart + 3),
&serSize, 2, SerializeIF::Endianness::NETWORK);
}

View File

@ -14,6 +14,7 @@ class PusTmZeroCopyWriter : public PusTmReader {
PusTmZeroCopyWriter(TimeReaderIF& timeReader, uint8_t* data, size_t size);
void setSequenceCount(uint16_t seqCount);
void setMessageCount(uint16_t msgCount);
void updateErrorControl();
private:

View File

@ -5,8 +5,18 @@
namespace spi {
static constexpr uint8_t CLASS_ID = CLASS_ID::HAL_SPI;
static constexpr ReturnValue_t OPENING_FILE_FAILED = returnvalue::makeCode(CLASS_ID, 0);
/* Full duplex (ioctl) transfer failure */
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED = returnvalue::makeCode(CLASS_ID, 1);
/* Half duplex (read/write) transfer failure */
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED = returnvalue::makeCode(CLASS_ID, 2);
static constexpr ReturnValue_t TIMEOUT = returnvalue::makeCode(CLASS_ID, 3);
static constexpr ReturnValue_t BUSY = returnvalue::makeCode(CLASS_ID, 4);
static constexpr ReturnValue_t GENERIC_ERROR = returnvalue::makeCode(CLASS_ID, 5);
enum SpiModes : uint8_t { MODE_0, MODE_1, MODE_2, MODE_3 };
}
} // namespace spi
#endif /* FSFW_HAL_COMMON_SPI_SPICOMMON_H_ */

View File

@ -73,8 +73,10 @@ static constexpr uint8_t CTRL_REG_4_VAL = SET_BLE;
/* Register 5 */
static constexpr uint8_t SET_REBOOT_MEM = 1 << 7;
static constexpr uint8_t SET_FIFO_ENB = 1 << 6;
static constexpr uint8_t SET_OUT_SEL_1 = 1 << 1;
static constexpr uint8_t SET_OUT_SEL_0 = 1 << 0;
static constexpr uint8_t CTRL_REG_5_VAL = 0b00000000;
static constexpr uint8_t CTRL_REG_5_VAL = SET_OUT_SEL_1 | SET_OUT_SEL_0;
/* Possible range values in degrees per second (DPS). */
static constexpr uint16_t RANGE_DPS_00 = 245;

View File

@ -165,7 +165,8 @@ ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) {
if (not filesystem::exists(path, e)) {
return FILE_DOES_NOT_EXIST;
}
ofstream of(path);
// Specify truncation flug explicitely.
ofstream of(path, std::ios::out | std::ios::trunc);
return returnvalue::OK;
}

View File

@ -112,8 +112,9 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s
if (i2cCookie->errorCounter < 3) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "I2cComIF::sendMessage: Failed to send data to I2C "
"device from " << deviceFile << " with error code "
<< errno << ". Error description: " << strerror(errno) << std::endl;
"device from "
<< deviceFile << " with error code " << errno
<< ". Error description: " << strerror(errno) << std::endl;
#endif
}
return returnvalue::FAILED;

View File

@ -88,11 +88,11 @@ int SerialComIF::configureUartPort(SerialCookie* uartCookie) {
return fd;
}
uart::setParity(options, uartCookie->getParity());
serial::setParity(options, uartCookie->getParity());
setStopBitOptions(&options, uartCookie);
setDatasizeOptions(&options, uartCookie);
setFixedOptions(&options);
uart::setMode(options, uartCookie->getUartMode());
serial::setMode(options, uartCookie->getUartMode());
if (uartCookie->getInputShouldBeFlushed()) {
tcflush(fd, TCIFLUSH);
}
@ -101,7 +101,7 @@ int SerialComIF::configureUartPort(SerialCookie* uartCookie) {
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 0;
uart::setBaudrate(options, uartCookie->getBaudrate());
serial::setBaudrate(options, uartCookie->getBaudrate());
/* Save option settings */
if (tcsetattr(fd, TCSANOW, &options) != 0) {

View File

@ -3,7 +3,7 @@
#include "fsfw/serviceinterface.h"
void uart::setMode(struct termios& options, UartModes mode) {
void serial::setMode(struct termios& options, UartModes mode) {
if (mode == UartModes::NON_CANONICAL) {
/* Disable canonical mode */
options.c_lflag &= ~ICANON;
@ -12,7 +12,7 @@ void uart::setMode(struct termios& options, UartModes mode) {
}
}
void uart::setBaudrate(struct termios& options, UartBaudRate baud) {
void serial::setBaudrate(struct termios& options, UartBaudRate baud) {
switch (baud) {
case UartBaudRate::RATE_50:
cfsetspeed(&options, B50);
@ -114,7 +114,7 @@ void uart::setBaudrate(struct termios& options, UartBaudRate baud) {
}
}
void uart::setBitsPerWord(struct termios& options, BitsPerWord bits) {
void serial::setBitsPerWord(struct termios& options, BitsPerWord bits) {
options.c_cflag &= ~CSIZE; // Clear all the size bits
if (bits == BitsPerWord::BITS_5) {
options.c_cflag |= CS5;
@ -127,11 +127,11 @@ void uart::setBitsPerWord(struct termios& options, BitsPerWord bits) {
}
}
void uart::enableRead(struct termios& options) { options.c_cflag |= CREAD; }
void serial::enableRead(struct termios& options) { options.c_cflag |= CREAD; }
void uart::ignoreCtrlLines(struct termios& options) { options.c_cflag |= CLOCAL; }
void serial::ignoreCtrlLines(struct termios& options) { options.c_cflag |= CLOCAL; }
void uart::setParity(struct termios& options, Parity parity) {
void serial::setParity(struct termios& options, Parity parity) {
/* Clear parity bit */
options.c_cflag &= ~PARENB;
switch (parity) {
@ -148,11 +148,11 @@ void uart::setParity(struct termios& options, Parity parity) {
}
}
int uart::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) {
int serial::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) {
return ioctl(serialPort, TIOCGICOUNT, &icounter);
}
void uart::setStopbits(struct termios& options, StopBits bits) {
void serial::setStopbits(struct termios& options, StopBits bits) {
if (bits == StopBits::TWO_STOP_BITS) {
// Use two stop bits
options.c_cflag |= CSTOPB;
@ -161,3 +161,7 @@ void uart::setStopbits(struct termios& options, StopBits bits) {
options.c_cflag &= ~CSTOPB;
}
}
void serial::flushRxBuf(int fd) { tcflush(fd, TCIFLUSH); }
void serial::flushTxRxBuf(int fd) { tcflush(fd, TCIOFLUSH); }

View File

@ -45,7 +45,7 @@ enum class UartBaudRate {
RATE_4000000
};
namespace uart {
namespace serial {
void setMode(struct termios& options, UartModes mode);
/**
@ -64,8 +64,11 @@ void setParity(struct termios& options, Parity parity);
void ignoreCtrlLines(struct termios& options);
void flushRxBuf(int fd);
void flushTxRxBuf(int fd);
int readCountersAndErrors(int serialPort, serial_icounter_struct& icounter);
} // namespace uart
} // namespace serial
#endif /* FSFW_HAL_LINUX_UART_HELPER_H_ */

View File

@ -173,7 +173,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
int fileDescriptor = 0;
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return OPENING_FILE_FAILED;
return spi::OPENING_FILE_FAILED;
}
spi::SpiModes spiMode = spi::SpiModes::MODE_0;
uint32_t spiSpeed = 0;
@ -234,7 +234,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
if (retval < 0) {
spiCookie->setTransferSize(0);
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
result = FULL_DUPLEX_TRANSFER_FAILED;
result = spi::FULL_DUPLEX_TRANSFER_FAILED;
}
#if FSFW_HAL_SPI_WIRETAPPING == 1
performSpiWiretapping(spiCookie);
@ -250,7 +250,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
sif::printWarning("SpiComIF::sendMessage: Half-Duplex write operation failed!\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
result = HALF_DUPLEX_TRANSFER_FAILED;
result = spi::HALF_DUPLEX_TRANSFER_FAILED;
}
}
@ -287,7 +287,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
int fileDescriptor = 0;
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return OPENING_FILE_FAILED;
return spi::OPENING_FILE_FAILED;
}
uint8_t* rxBuf = nullptr;
@ -327,7 +327,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
sif::printWarning("SpiComIF::sendMessage: Half-Duplex read operation failed!\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
result = HALF_DUPLEX_TRANSFER_FAILED;
result = spi::HALF_DUPLEX_TRANSFER_FAILED;
}
if (gpioId != gpio::NO_GPIO and not csLockManual) {

View File

@ -22,15 +22,6 @@ class SpiCookie;
*/
class SpiComIF : public DeviceCommunicationIF, public SystemObject {
public:
static constexpr uint8_t spiRetvalId = CLASS_ID::HAL_SPI;
static constexpr ReturnValue_t OPENING_FILE_FAILED = returnvalue::makeCode(spiRetvalId, 0);
/* Full duplex (ioctl) transfer failure */
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED =
returnvalue::makeCode(spiRetvalId, 1);
/* Half duplex (read/write) transfer failure */
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
returnvalue::makeCode(spiRetvalId, 2);
SpiComIF(object_id_t objectId, std::string devname, GpioIF& gpioComIF);
ReturnValue_t initializeInterface(CookieIF* cookie) override;

View File

@ -36,7 +36,7 @@ UioMapper::~UioMapper() {}
ReturnValue_t UioMapper::getMappedAdress(uint32_t** address, Permissions permissions) {
ReturnValue_t result = returnvalue::OK;
int fd = open(uioFile.c_str(), O_RDWR);
int fd = open(uioFile.c_str(), O_RDWR | O_SYNC);
if (fd < 1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "UioMapper::getMappedAdress: Invalid UIO device file " << uioFile << std::endl;

View File

@ -357,13 +357,13 @@ ReturnValue_t SpiComIF::halErrorHandler(HAL_StatusTypeDef status, spi::TransferM
sif::printWarning("SpiComIF::handle%sSendOperation: HAL error %d occured\n", modeString, status);
switch (status) {
case (HAL_BUSY): {
return spi::HAL_BUSY_RETVAL;
return spi::BUSY;
}
case (HAL_ERROR): {
return spi::HAL_ERROR_RETVAL;
return spi::GENERIC_ERROR;
}
case (HAL_TIMEOUT): {
return spi::HAL_TIMEOUT_RETVAL;
return spi::TIMEOUT;
}
default: {
return returnvalue::FAILED;

View File

@ -30,9 +30,9 @@
*/
void Factory::produceFrameworkObjects(void* args) {
setStaticFrameworkObjectIds();
new EventManager(objects::EVENT_MANAGER);
new EventManager(objects::EVENT_MANAGER, 120);
new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 20, false, 1.0);
{
PoolManager::LocalPoolConfig poolCfg = {{100, 16}, {50, 32}, {25, 64}, {15, 128}, {5, 1024}};

View File

@ -27,12 +27,7 @@ TEST_CASE("Action Helper", "[action]") {
CHECK(not testDhMock.executeActionCalled);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
CHECK(testDhMock.executeActionCalled);
// No message is sent if everything is alright.
CHECK(not testMqMock.wasMessageSent());
store_address_t invalidAddress;
ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
actionHelper.handleActionMessage(&actionMessage);
CHECK(testMqMock.wasMessageSent());
const uint8_t* ptr = nullptr;
size_t size = 0;
REQUIRE(ipcStore->getData(paramAddress, &ptr, &size) ==
@ -44,6 +39,10 @@ TEST_CASE("Action Helper", "[action]") {
for (uint8_t i = 0; i < 3; i++) {
REQUIRE(ptr[i] == (i + 1));
}
// Action message without application data is also valid
store_address_t invalidAddress;
ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
actionHelper.handleActionMessage(&actionMessage);
testDhMock.clearBuffer();
}
@ -95,17 +94,5 @@ TEST_CASE("Action Helper", "[action]") {
REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId);
}
SECTION("Missing IPC Data") {
ActionMessage::setCommand(&actionMessage, testActionId, store_address_t::invalid());
CHECK(not testDhMock.executeActionCalled);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
CommandMessage testMessage;
REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK);
REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::STEP_FAILED));
REQUIRE(ActionMessage::getReturnCode(&testMessage) ==
static_cast<uint32_t>(StorageManagerIF::ILLEGAL_STORAGE_ID));
REQUIRE(ActionMessage::getStep(&testMessage) == 0);
}
SECTION("Data Reply") {}
}

View File

@ -97,7 +97,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
SerializeIF::Endianness::BIG) == returnvalue::OK);
CHECK(serBuf[0] == 0x3f);
CHECK(serBuf[3] == 0x99);
CHECK(serBuf[3] == 0x88);
REQUIRE(creator.getCrcFlag() == true);
REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER);
REQUIRE(creator.getLargeFileFlag() == true);
@ -127,7 +127,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
REQUIRE(creator.getSegmentationControl() == true);
// Last three bits are 2 now (length of seq number) and bit 1 to bit 3 is 4 (len entity IDs)
REQUIRE(serBuf[3] == 0b11001010);
REQUIRE(serBuf[3] == 0b10111001);
uint32_t entityId = 0;
size_t deSerSize = 0;
SerializeAdapter::deSerialize(&entityId, serBuf.data() + 4, &deSerSize,
@ -175,7 +175,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
REQUIRE(serBuf[1] == 0);
REQUIRE(serBuf[2] == 0);
// Entity and Transaction Sequence number are 1 byte large
REQUIRE(serBuf[3] == 0b00010001);
REQUIRE(serBuf[3] == 0b00000000);
// Source ID
REQUIRE(serBuf[4] == 0);
// Transaction Seq Number
@ -220,7 +220,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
REQUIRE(serBuf[1] == 0);
REQUIRE(serBuf[2] == 0);
// Entity and Transaction Sequence number are 1 byte large
REQUIRE(serBuf[3] == 0b00010001);
REQUIRE(serBuf[3] == 0b00000000);
REQUIRE(serSize == 7);
// Deser call not strictly necessary
auto reader = PduHeaderReader(serBuf.data(), serBuf.size());
@ -270,7 +270,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
REQUIRE(reader.parseData() == returnvalue::OK);
// Everything except version bit flipped to one now
REQUIRE(serBuf[0] == 0x3f);
REQUIRE(serBuf[3] == 0b11001010);
REQUIRE(serBuf[3] == 0b10111001);
REQUIRE(reader.getWholePduSize() == 14);
REQUIRE(reader.getCrcFlag() == true);

View File

@ -68,7 +68,7 @@ TEST_CASE("File Data PDU", "[cfdp][pdu]") {
// Bits 1 to 3 length of enitity IDs is 2
// Bit 4: Segment metadata flag is set
// Bit 5 to seven: length of transaction seq num is 2
REQUIRE(fileDataBuffer[3] == 0b10101010);
REQUIRE(fileDataBuffer[3] == 0b10011001);
REQUIRE((fileDataBuffer[10] >> 6) &
0b11 == cfdp::RecordContinuationState::CONTAINS_START_AND_END);
// Segment metadata length

View File

@ -30,7 +30,7 @@ TEST_CASE("CFDP File Directive", "[cfdp][pdu]") {
REQUIRE(serBuf[1] == 0);
REQUIRE(serBuf[2] == 5);
// Entity and Transaction Sequence number are 1 byte large
REQUIRE(serBuf[3] == 0b00010001);
REQUIRE(serBuf[3] == 0b00000000);
// Source ID
REQUIRE(serBuf[4] == 0);
// Transaction Seq Number
@ -82,4 +82,4 @@ TEST_CASE("CFDP File Directive", "[cfdp][pdu]") {
// Invalid file directive
REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELD);
}
}
}

View File

@ -33,8 +33,8 @@ TEST_CASE("CFDP Base", "[cfdp]") {
// PDU data field length is 5 (4 + Directive code octet)
REQUIRE(serBuf[1] == 0);
REQUIRE(serBuf[2] == 5);
// Entity and Transaction Sequence number are 1 byte large
REQUIRE(serBuf[3] == 0b00010001);
// Entity and Transaction Sequence number are 1 byte large, value minus one is stored
REQUIRE(serBuf[3] == 0b00000000);
// Source ID
REQUIRE(serBuf[4] == 0);
// Transaction Seq Number

View File

@ -9,6 +9,7 @@
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>
#include <iostream>
#include "CatchDefinitions.h"
@ -309,9 +310,7 @@ TEST_CASE("Local Pool Manager Tests", "[LocManTest]") {
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
false);
CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK);
/* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the
resulting collection interval should be 1.0 second */
CHECK(poolOwner.dataset.getCollectionInterval() == 1.0);
CHECK_THAT(poolOwner.dataset.getCollectionInterval(), Catch::Matchers::WithinAbs(0.4, 0.01));
REQUIRE(poolOwnerMock.wasMessageSent());
REQUIRE(poolOwnerMock.numberOfSentMessages() == 1);
CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK);
@ -348,14 +347,6 @@ TEST_CASE("Local Pool Manager Tests", "[LocManTest]") {
REQUIRE(poolOwnerMock.numberOfSentMessages() == 1);
CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
false);
CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(poolOwnerMock.wasMessageSent());
REQUIRE(poolOwnerMock.numberOfSentMessages() == 1);
CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));