Compare commits

..

315 Commits

Author SHA1 Message Date
e949368b06 Merge pull request 'uart cookie API change' (#62) from mueller/uart-com-if-tweaks into eive/develop
Reviewed-on: eive/fsfw#62
2022-04-13 15:04:03 +02:00
4d49cb6a3c Merge pull request 'added DLE parser' (#61) from mueller/dle-parser into eive/develop
Reviewed-on: eive/fsfw#61
2022-04-13 15:03:27 +02:00
935a8e13a5 uart cookie API change 2022-04-13 14:57:43 +02:00
5ff88129b8 added DLE parser 2022-04-13 14:45:36 +02:00
ce17be63f4 Merge pull request 'Pool Entry Update V2' (#60) from mueller/pool-entry-update-v2 into eive/develop
Reviewed-on: eive/fsfw#60
2022-04-12 19:28:01 +02:00
2734d9d758 Merge pull request 'fix compiler warnings' (#59) from mueller/compiler-warning-fixes-upstream into eive/develop
Reviewed-on: eive/fsfw#59
2022-04-12 19:27:37 +02:00
c45328b34d Merge branch 'eive/develop' into mueller/compiler-warning-fixes-upstream 2022-04-11 16:03:52 +02:00
478b305fbe fix compiler warnings 2022-04-11 16:02:20 +02:00
28e93696df Merge pull request 'IPC Pass Arbitrary Args to MQ IF' (#58) from mueller/ipc-pass-arbitrary-args-to-mq-eive into eive/develop
Reviewed-on: eive/fsfw#58
2022-04-11 14:55:54 +02:00
942d1e5e4b Merge remote-tracking branch 'origin/eive/develop' into mueller/ipc-pass-arbitrary-args-to-mq-eive 2022-04-11 14:40:43 +02:00
95f018a0b0 update IF method
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-04-11 14:07:02 +02:00
8c2105ae0a correct init value for object ID
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-04-11 14:00:37 +02:00
ed2c2af4a0 take upstream impl of local data pool manager
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-04-11 13:59:38 +02:00
82df132e7d tests running again
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-04-11 13:54:43 +02:00
a02619e5a2 strongly simplified and streamlined IPC MQ Impl
- Generic code was duplicated across all OSALs.
  Is contained in generic base class now
- Remove duplicate documentation
2022-04-11 11:19:38 +02:00
6ce09e968d Merge pull request 'Update from FSFW upstream' (#56) from mueller/update-from-upstream into eive/develop
Reviewed-on: eive/fsfw#56
2022-04-11 09:03:08 +02:00
290db6ccad Merge remote-tracking branch 'upstream/development' into mueller/update-from-upstream 2022-04-11 08:51:55 +02:00
94ed582297 Merge branch 'eive/develop' of https://egit.irs.uni-stuttgart.de/eive/fsfw into eive/develop 2022-04-07 19:47:49 +02:00
47ced1efac pool entry takes const T* now 2022-04-07 19:47:37 +02:00
85a6e4b129 Merge pull request 'improve clock error handler' (#55) from mueller/clock-update into eive/develop
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
Reviewed-on: eive/fsfw#55
2022-04-07 19:29:49 +02:00
f94bc02b6c Merge branch 'eive/develop' into mueller/clock-update 2022-04-07 17:36:04 +02:00
5bda877d97 improve clock error handler 2022-04-07 17:23:06 +02:00
51e7f1c2f2 Merge pull request 'FSFW Update' (#54) from mueller/clock-update into eive/develop
Reviewed-on: eive/fsfw#54
2022-04-07 11:33:06 +02:00
a11d7455df Merge branch 'eive/develop' into mueller/master
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-04-07 11:04:47 +02:00
4dc903fe20 Merge pull request 'Pool Entry Update' (#53) from mueller/pool-entry-update into eive/develop
Reviewed-on: eive/fsfw#53
2022-04-07 11:04:29 +02:00
3325cc18fc Merge branch 'eive/develop' into mueller/pool-entry-update 2022-04-07 11:03:56 +02:00
43917d98c0 Merge branch 'mueller/master' of https://egit.irs.uni-stuttgart.de/eive/fsfw into mueller/master
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-04-07 11:01:49 +02:00
e3ffcae3e0 emit warning in linux clock 2022-04-07 11:01:39 +02:00
0677de39aa make reporting setter public
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-04-07 00:15:42 +02:00
aded4fae1e printout improvement
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-04-04 20:34:31 +02:00
a011e70665 Merge branch 'development' into mueller/ipc-pass-arbitrary-args-to-mq
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-04-04 17:21:11 +02:00
7df51f7202 Merge pull request 'add power switcher component' (#52) from mueller/power-switcher-component into eive/develop
Reviewed-on: eive/fsfw#52
2022-04-04 15:51:18 +02:00
7530c44849 Merge branch 'eive/develop' into mueller/pool-entry-update 2022-04-04 15:46:10 +02:00
e4c6a69f77 this should also zero-init the pool entries
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-04-04 15:44:03 +02:00
761a0c9bac new pool ctor which only takes len
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-04-04 15:39:02 +02:00
7e61ce1ed2 Merge pull request 'cmake lists update to suppress large warning' (#588) from eive/fsfw:mueller/catch2-find-package-quiet into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #588
2022-04-04 14:07:38 +02:00
518666f822 add power switcher component 2022-04-01 17:01:56 +02:00
318cd8e244 Merge pull request 'Update FSFW' (#51) from mueller/master into eive/develop
Reviewed-on: eive/fsfw#51
2022-04-01 14:51:31 +02:00
1bc7a91869 apply auto-formatter
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-04-01 14:08:29 +02:00
8e26e287c3 Merge remote-tracking branch 'origin/eive/develop' into mueller/master
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-04-01 14:07:26 +02:00
ce2f7c4fdf Merge pull request 'DHB and CommandActionHelper changes' (#50) from meier/develop into eive/develop
Reviewed-on: eive/fsfw#50
2022-04-01 14:07:05 +02:00
b3d2d440d7 Merge remote-tracking branch 'origin/eive/develop' into mueller/master
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-31 16:13:47 +02:00
Jakob Meier
fbf9626fde Merge branch 'eive/develop' into meier/dhbAlternativeReply 2022-03-31 15:04:55 +02:00
fcb6437388 Merge branch 'development' into mueller/ipc-pass-arbitrary-args-to-mq
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-31 14:42:15 +02:00
29cf8c9009 fix in getReplyLength 2022-03-31 11:42:39 +02:00
61d0815de8 Merge pull request 'Refactor Power Module' (#49) from mueller/refactor-power-switch-if-etc-eive into eive/develop
Reviewed-on: eive/fsfw#49
2022-03-31 09:01:24 +02:00
127fbeb980 Merge branch 'mueller/refactor-power-switch-if-etc' into mueller/refactor-power-switch-if-etc-eive 2022-03-30 17:41:55 +02:00
b42987059a make dummy power switcher a system object
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-30 17:41:38 +02:00
c2581ff4f5 Merge remote-tracking branch 'origin/eive/develop' into mueller/master
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-30 13:12:11 +02:00
7b6f68c509 Merge remote-tracking branch 'origin/eive/develop' into mueller/refactor-power-switch-if-etc-eive 2022-03-30 12:14:57 +02:00
Jakob Meier
532607bf8f extended command info 2022-03-30 09:21:03 +02:00
Jakob Meier
a230dc4313 command action default arguments 2022-03-30 09:20:46 +02:00
4be45adae6 Merge branch 'development' into mueller/catch2-find-package-quiet
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-28 16:44:23 +02:00
0d7d2203d2 Merge pull request 'Added function to add component to a periodic task by pointer' (#591) from mohr/task into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #591
2022-03-28 15:23:26 +02:00
cde184f428 Merge branch 'development' into mohr/task
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-28 15:18:23 +02:00
df3794dfd8 Merge pull request 'delete code which is not required anymore' (#587) from eive/fsfw:mueller/small-mgmlis3-tweak into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #587
2022-03-28 15:08:22 +02:00
d02d5c351d Merge branch 'development' into mueller/small-mgmlis3-tweak
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-28 15:05:24 +02:00
febecd4b30 Merge pull request 'small tweaks for local datapool code' (#582) from eive/fsfw:mueller/localpool-tweaks into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #582
2022-03-28 14:49:42 +02:00
964e311d8b Merge branch 'development' into mueller/localpool-tweaks
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build queued...
2022-03-28 14:48:34 +02:00
d43caa8296 Merge pull request 'Using enums to configure baudrate and bits per word in Linux HAL UART' (#585) from mohr/hal_uart into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #585
2022-03-28 14:47:04 +02:00
916ed3f56a added function to add component to a periodic task by pointer
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-28 13:50:42 +02:00
3ea9f999b7 apply auto-formatter
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-28 12:59:51 +02:00
79f3c7324a tweaks for dummy power switcher
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-28 12:59:32 +02:00
23af170229 small tweaks
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-28 12:59:03 +02:00
b32d1da421 this should compile
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-28 12:57:11 +02:00
6f0362b956 refactor power module
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-28 12:48:15 +02:00
60972228ef reworked power switch interface
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-28 12:47:09 +02:00
6ea1eabb2d small order change in DHB
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-28 12:21:25 +02:00
283a37dccc Merge pull request 'meier/gpioClass' (#47) from meier/gpioClass into eive/develop
Reviewed-on: eive/fsfw#47
2022-03-28 10:22:32 +02:00
acf0cdfba3 Merge branch 'eive/develop' into meier/gpioClass 2022-03-28 10:22:11 +02:00
a01002aa5d Merge pull request 'meier/seqCount' (#46) from meier/seqCount into eive/develop
Reviewed-on: eive/fsfw#46
2022-03-28 10:21:48 +02:00
Jakob Meier
b52f19254b class to abstract gpio handling 2022-03-28 09:12:29 +02:00
79615e47e4 Merge branch 'eive/develop' into meier/seqCount 2022-03-25 15:48:42 +01:00
e6130263ef Merge pull request 'Update FSFW' (#45) from mueller/master into eive/develop
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
Reviewed-on: eive/fsfw#45
2022-03-25 14:56:19 +01:00
6895dbcc81 Merge remote-tracking branch 'origin/eive/develop' into mueller/master
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-25 14:39:22 +01:00
d9d9a28ef8 delete code which is not required anymore
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-24 21:04:46 +01:00
Cleanroom Laptop L590
d95582b81b cmake lists update to suppress large warning
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-24 16:54:41 +01:00
c60aa68d00 changed hal linux uart baudrate and bits per word to enums
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
fsfw/fsfw/pipeline/pr-master This commit looks good
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-24 15:44:32 +01:00
4b5e3e70f7 add option to directly check switch state
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-22 20:35:04 +01:00
a0dfdfab2c Allow passing a MqArgs struct to the MQ creation
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
The struct contains context information (which can be extended)
and an arbitrary user argument in form of a void pointer.
This makes the API a lot more flexible
2022-03-22 17:49:22 +01:00
3e17011087 small tweaks for local datapool code
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build started...
2022-03-22 17:42:56 +01:00
f441505476 update changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-22 17:41:49 +01:00
7c64797f03 Add more baud rates
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-22 17:38:47 +01:00
bbe21e7e89 doc additions
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-22 16:14:23 +01:00
2823420c46 more docs 2022-03-22 16:10:20 +01:00
6dd6f28db0 added active function 2022-03-22 15:55:18 +01:00
d791fc87b7 some improvements for PowerSwitcher 2022-03-22 15:49:04 +01:00
16f2fa9327 Merge remote-tracking branch 'upstream/development' into mueller/master 2022-03-21 10:12:06 +01:00
927041209b added override specifiers 2022-03-21 09:12:56 +01:00
Jakob Meier
bac8b40880 Merge branch 'eive/develop' into meier/seqCount 2022-03-17 20:02:29 +01:00
Jakob Meier
caf78835b2 added -- operator 2022-03-17 20:00:17 +01:00
b6ed45a85c small form fix 2022-03-17 19:59:16 +01:00
ddc1cdb1f5 additional docs 2022-03-17 19:22:24 +01:00
543daaa95a various tweaks and improvements 2022-03-17 19:19:02 +01:00
38c87fdeb2 Merge remote-tracking branch 'upstream/development' into eive/develop 2022-03-17 09:47:20 +01:00
5ca5fe4040 Merge remote-tracking branch 'upstream/development' into eive/develop 2022-03-14 17:50:27 +01:00
Jakob Meier
1b7e0371c3 fixed merge conflict 2022-03-14 15:25:17 +01:00
e08bdd3e35 Merge pull request 'Always define FSFW_DISABLE_PRINTOUT' (#576) from eive/fsfw:mueller/define-fsfw-disabled-printout-upstream into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #576
2022-03-14 15:20:40 +01:00
d2dd16aef3 Merge branch 'development' into mueller/define-fsfw-disabled-printout-upstream
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-14 15:12:37 +01:00
b7a617dab3 Merge pull request 'minor event changes' (#578) from eive/fsfw:mueller/event-update into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #578
2022-03-14 15:12:21 +01:00
bc95e7c886 Merge branch 'mueller/event-update' of https://egit.irs.uni-stuttgart.de/eive/fsfw into mueller/event-update
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-14 15:08:54 +01:00
fca43b3d34 run auto-formatter 2022-03-14 15:08:45 +01:00
48c5c3fbd5 Merge branch 'development' into mueller/event-update
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-14 15:07:25 +01:00
b694aea100 Merge pull request 'call setTimeout in Countdown ctor' (#577) from eive/fsfw:mueller/countdown-improvement-upstream into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #577
2022-03-14 15:04:57 +01:00
6998626ad4 Merge branch 'development' into mueller/define-fsfw-disabled-printout-upstream
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-14 15:02:07 +01:00
Jakob Meier
d4ade5e885 sequence count operator overloading 2022-03-14 15:01:17 +01:00
24ad858b64 Merge branch 'development' into mueller/countdown-improvement-upstream
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-14 14:46:54 +01:00
288d453978 Merge pull request 'Version Getter Function' (#575) from eive/fsfw:mueller/version-getter-upstream into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #575
2022-03-14 14:44:37 +01:00
522cbc7f3d Merge remote-tracking branch 'upstream/development' into mueller/version-getter-upstream
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-14 14:38:27 +01:00
ce5bcc5897 bugfix
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-14 14:37:41 +01:00
97c93afeff Merge remote-tracking branch 'upstream/development' into mueller/version-getter-upstream
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-14 14:24:43 +01:00
8704b9ab06 Merge pull request 'Fixed test issue with overflow of times' (#574) from gaisser/fsfw:gaisser_ccsds_time_tests into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #574
2022-03-14 14:23:35 +01:00
5a1585bd00 Merge pull request 'SPI HAL improvement' (#573) from eive/fsfw:mueller/spi-initialize-line-state into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #573
2022-03-14 14:18:03 +01:00
5d6de90859 Merge remote-tracking branch 'upstream/development' into mueller/spi-initialize-line-state
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build queued...
2022-03-14 14:15:13 +01:00
378c6c8006 Merge pull request 'HAL: Update for GPIO code' (#572) from eive/fsfw:mueller/gpio-update into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #572
2022-03-14 14:13:33 +01:00
f4922a8686 Merge pull request 'small test device handler fixes' (#571) from eive/fsfw:mueller/small-dh-test-foxes into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #571
2022-03-14 14:11:44 +01:00
0bdcb40609 minor event changes
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-11 14:25:34 +01:00
fec5f83f4f minor event changes 2022-03-11 14:25:01 +01:00
17262a1da9 Merge branch 'mueller/version-getter-upstream' into mueller/master 2022-03-10 09:59:18 +01:00
e684680d60 avoid namespace pollution
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-10 09:58:37 +01:00
aa5d1042f0 undef major and minor 2022-03-10 09:57:37 +01:00
b5d6b9745f undef major and minor 2022-03-10 09:56:23 +01:00
60639f56dc Merge branch 'mueller/version-getter' into mueller/master 2022-03-10 09:47:32 +01:00
3aa0bbde68 Merge branch 'mueller/version-getter-upstream' into mueller/version-getter 2022-03-10 09:47:10 +01:00
14ac852b7e this tests even a bit more
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-10 09:44:06 +01:00
6b1a81ee92 minor tweaks
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-10 09:40:34 +01:00
3779b44813 added some more minor tests
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-10 09:37:57 +01:00
949549178a update changelog
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-10 09:36:36 +01:00
7daa9812ff added tests
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-03-10 09:35:10 +01:00
97bc71a3ff added tests 2022-03-10 09:34:29 +01:00
06577ed78a Merge branch 'mueller/version-getter' into mueller/master 2022-03-09 19:11:57 +01:00
ca508bfe61 getter not required anymore
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-09 19:10:33 +01:00
b27f3b84aa getter not required anymore 2022-03-09 19:10:05 +01:00
345a799031 improved version.h
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-09 19:08:17 +01:00
9509847b84 Merge branch 'mueller/version-getter' into mueller/master 2022-03-09 19:05:30 +01:00
45b51f9ac8 improved version.h 2022-03-09 19:05:07 +01:00
445d5dd6f0 Added Checks for CDSShort in unittests
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-09 18:56:08 +01:00
d5ff6da40b Merge pull request 'function to get fsfw version' (#43) from mueller/version-getter into eive/develop
Reviewed-on: eive/fsfw#43
2022-03-08 12:04:13 +01:00
e498136273 Merge pull request 'call setTimeout' (#44) from mueller/countdown-improvement into eive/develop
Reviewed-on: eive/fsfw#44
2022-03-08 12:03:13 +01:00
238baa8597 call setTimeout
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-08 11:54:20 +01:00
47d158156b call setTimeout 2022-03-08 11:52:33 +01:00
d63c01b96f set timeout in countdown ctor 2022-03-08 11:50:47 +01:00
3b497dbb8d Merge branch 'mueller/version-getter' into mueller/master 2022-03-08 10:16:56 +01:00
bf733162eb Merge remote-tracking branch 'origin/eive/develop' into mueller/master 2022-03-08 10:15:54 +01:00
7932afc315 small form change
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-08 10:13:11 +01:00
d1e3dc4d49 define FSFW_DISABLE_PRINTOUT in any case 2022-03-08 10:12:02 +01:00
73f0b9c0dc Merge pull request 'define FSFW_DISABLE_PRINTOUT in any case' (#42) from mueller/define-fsfw-disabled-printout into eive/develop
Reviewed-on: eive/fsfw#42
2022-03-08 10:11:45 +01:00
b5e55f64b0 Merge pull request 'Another HasModesIF improvement' (#41) from mueller/master into eive/develop
Reviewed-on: eive/fsfw#41
2022-03-08 10:11:05 +01:00
77e5fba7fd update changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-08 10:08:53 +01:00
ca70c8c614 function to get fsfw version 2022-03-08 10:07:07 +01:00
7ca6d1a695 function to get fsfw version 2022-03-08 10:05:18 +01:00
cc3210f366 Merge branch 'eive/develop' into mueller/define-fsfw-disabled-printout 2022-03-08 09:57:43 +01:00
155d66e534 define FSFW_DISABLE_PRINTOUT in any case 2022-03-08 09:57:11 +01:00
d4c76a7e46 Merge branch 'mueller/master' of https://egit.irs.uni-stuttgart.de/eive/fsfw into mueller/master 2022-03-08 09:56:39 +01:00
dba3c27b99 define FSFW_DISABLE_PRINTOUT in any case 2022-03-08 09:56:24 +01:00
202cfc6dbb Merge branch 'eive/develop' into mueller/master 2022-03-08 09:47:37 +01:00
84f95e8d76 this is better 2022-03-08 09:45:58 +01:00
6de4798805 Merge pull request 'better name of invalid mode retval' (#40) from mueller/master into eive/develop
Reviewed-on: eive/fsfw#40
2022-03-08 09:37:58 +01:00
82a645deba Merge branch 'eive/develop' into mueller/master 2022-03-08 09:36:25 +01:00
8b1c277c58 better name of invalid mode retval 2022-03-08 09:34:22 +01:00
14620fdd72 minor correction
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build started...
2022-03-08 09:02:40 +01:00
89c1878622 add link to PR
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-08 09:01:23 +01:00
d6856fc54a another minor changelog update
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-08 09:00:14 +01:00
e5a9cab34e fix changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-08 08:57:18 +01:00
5f23f709cc Merge pull request 'Update for Assembly Base' (#38) from mueller/master into eive/develop
Reviewed-on: eive/fsfw#38
2022-03-08 07:53:04 +01:00
a4f97a7ba7 Fixed another issue of time checks
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-07 18:33:24 +01:00
8b1af232c3 Added Tests for CCSDS Time, fixed LPM Test
Changed behaviour of Host and Linux Clock
2022-03-07 18:22:10 +01:00
983fa346b3 update CHANGELOG
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-07 16:17:33 +01:00
32f420c4f0 SPI HAL improvement
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
- Initialize line state
2022-03-07 16:13:04 +01:00
41a82e923c update changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-07 16:09:18 +01:00
5ddac36314 GPIO update 2022-03-07 16:07:01 +01:00
d06eecf9b0 small test device handler fixes
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-07 15:56:45 +01:00
a7cb2d4354 small test device handler fixes 2022-03-07 15:54:56 +01:00
7571987a1d Merge branch 'eive/develop' into mueller/master 2022-03-07 15:43:52 +01:00
d6c1041133 Merge remote-tracking branch 'upstream/development' into eive/develop 2022-03-07 15:34:11 +01:00
5912ddd2a2 Merge pull request 'Activates new gcc compiler flags' (#568) from gaisser/fsfw:gaisser_compiler_flags into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #568
2022-03-07 14:44:09 +01:00
7db11588b4 Merge branch 'development' into gaisser_compiler_flags 2022-03-07 14:39:01 +01:00
c88b931ef1 Merge pull request 'HAL Devicehandlers: Periodic printouts are runtime configurable now' (#561) from eive/fsfw:mueller/dev-printout-runtime-configurable into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #561
2022-03-07 14:36:25 +01:00
10ffa2f44a Merge branch 'development' into mueller/dev-printout-runtime-configurable
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-07 14:20:56 +01:00
dbe31dd339 Merge pull request 'some forgotten size_t' (#570) from eive/fsfw:mohr/sizes into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #570
2022-03-07 14:19:59 +01:00
14b44f8bb2 Merge branch 'development' into gaisser_compiler_flags
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-07 13:09:21 +01:00
117747970d some forgotten size_t
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-05 22:03:25 +01:00
3c53e2c259 renamed some ModeIF definitions 2022-03-05 03:01:43 +01:00
45f0d7fd45 docs 2022-03-04 18:06:57 +01:00
c6540650e2 Merge pull request 'Changing build to -j4 from -j to lessen load on build server' (#569) from mohr/slowbuild into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #569
2022-03-04 15:16:25 +01:00
aebab4c73c Merge remote-tracking branch 'upstream/development' into mueller/master 2022-03-04 15:08:45 +01:00
c3c2e1c0dd Merge remote-tracking branch 'upstream/development' into eive/develop 2022-03-04 15:08:07 +01:00
4e6c1cb72a docs 2022-03-04 00:55:41 +01:00
f659f13759 Changing build to -j4 from -j to lessen load on build server
Some checks are pending
fsfw/fsfw/pipeline/head Build started...
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-03-03 16:03:06 +01:00
e2eb6a46b6 Merge branch 'eive/develop' into mueller/master 2022-03-03 13:43:15 +01:00
75c56280ad Merge pull request 'GPIO HAL Updates' (#36) from mueller/gpio-hal-updates into eive/develop
Reviewed-on: eive/fsfw#36
2022-03-03 09:44:42 +01:00
0ccaf27fcb better printout for parameter code 2022-03-01 19:43:21 +01:00
95078e1103 Merge remote-tracking branch 'upstream/development' into mueller/dev-printout-runtime-configurable
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 15:52:54 +01:00
e05e203c83 fix merge conflict
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-28 15:50:27 +01:00
8920255565 Merge pull request 'one shot flag not static anymore' (#560) from eive/fsfw:mueller/test-task-one-shot-flag-not-static into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #560
2022-02-28 15:50:06 +01:00
ac036b2a70 Merge remote-tracking branch 'origin/eive/develop' into mueller/gpio-hal-updates
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 15:49:11 +01:00
2d12618c96 Merge branch 'development' into mueller/test-task-one-shot-flag-not-static
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 15:42:08 +01:00
2d9216ba19 Merge branch 'mueller/gpio-hal-updates' into mueller/master 2022-02-28 15:37:03 +01:00
2fed161eff Merge branch 'eive/develop' into mueller/gpio-hal-updates
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 15:34:48 +01:00
68ca6fd122 Merge branch 'development' into gaisser_compiler_flags
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 15:29:57 +01:00
33e9592659 Merge pull request 'Unit test for Internal Error Reporter' (#563) from gaisser/fsfw:gaisser_unit_test_internal_error into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #563
2022-02-28 15:26:00 +01:00
19d217e3b9 Merge remote-tracking branch 'upstream/development' into mueller/dev-printout-runtime-configurable
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-28 15:23:54 +01:00
af286d3bc6 Merge remote-tracking branch 'upstream/development' into mueller/test-task-one-shot-flag-not-static
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 15:23:21 +01:00
4cf2a384f3 Merge remote-tracking branch 'upstream/development' into mueller/gpio-hal-updates
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 15:22:32 +01:00
27267b7cb0 Merge remote-tracking branch 'upstream/development' into mueller/gpio-hal-updates
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-28 15:21:39 +01:00
20928732ec Merge branch 'development' into gaisser_unit_test_internal_error
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 15:19:44 +01:00
505e00c067 Merge remote-tracking branch 'origin/eive/develop' into mueller/master 2022-02-28 15:17:29 +01:00
68225586d2 some fixes
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-28 15:16:43 +01:00
6d825a1aa6 some fixes 2022-02-28 15:16:24 +01:00
a8426750f2 Merge pull request 'display run commands in helper script' (#564) from eive/fsfw:mueller/update-helper-script into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #564
2022-02-28 15:13:39 +01:00
2635f39344 Merge branch 'development' into mueller/update-helper-script
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 15:05:02 +01:00
89327463e3 Merge pull request 'HkSwitchHelper should not be needed anymore' (#557) from eive/fsfw:mueller/delete-obsolete-module into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #557
2022-02-28 15:03:09 +01:00
fa73ad6731 Merge branch 'mueller/gpio-hal-updates' into mueller/master 2022-02-28 15:01:41 +01:00
cf45eca100 Merge remote-tracking branch 'upstream/development' into mueller/dev-printout-runtime-configurable
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-28 15:00:38 +01:00
c0fa365f8f Merge remote-tracking branch 'upstream/development' into mueller/delete-obsolete-module
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 14:58:28 +01:00
9d9f19781d Merge remote-tracking branch 'upstream/development' into mueller/test-task-one-shot-flag-not-static
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-28 14:57:38 +01:00
f4520ea346 Merge remote-tracking branch 'upstream/development' into mueller/test-task-one-shot-flag-not-static
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-28 14:56:51 +01:00
331aa9442d some updates
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-28 14:56:37 +01:00
bbacdc5cac Merge pull request 'Linux HAL: Add I2C wiretapping option' (#559) from eive/fsfw:mueller/hal-i2c-wiretapping into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #559
2022-02-28 14:55:21 +01:00
28b28b5684 Merge branch 'mueller/gpio-hal-updates' into mueller/master 2022-02-28 14:48:27 +01:00
afd3a942e2 use enum class
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-28 14:46:12 +01:00
729bcc4aaf Merge remote-tracking branch 'upstream/development' into mueller/gpio-hal-updates
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-28 14:39:35 +01:00
a6c0f3fef5 Merge remote-tracking branch 'upstream/development' into mueller/delete-obsolete-module
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-28 14:17:09 +01:00
6e0b90696d Merge pull request 'initial submode' (#35) from meier/dhbInitialSubmode into eive/develop
Reviewed-on: eive/fsfw#35
2022-02-28 13:23:26 +01:00
Jakob Meier
eacb4ac407 initial submode 2022-02-25 14:41:43 +01:00
09c1918c1f Merge pull request 'Update FSFW' (#34) from mueller/master into eive/develop
Reviewed-on: eive/fsfw#34
2022-02-25 11:38:11 +01:00
123f2ff360 removed unnecessary warning 2022-02-25 11:10:48 +01:00
0e8328fca3 Fixed include based on Feedback
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-24 11:22:51 +01:00
1ef3dae72e Fixed an missing include
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-23 22:36:29 +01:00
32381a7872 Fixed an issue with wrong buffer size 2022-02-23 21:20:22 +01:00
09815f5cce Clang format 2022-02-23 18:24:07 +01:00
f6357b4531 WIP compiler Flags and new unit tests for fixes 2022-02-23 18:23:22 +01:00
a10e5c6ed4 Merge branch 'development' into mueller/update-helper-script
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-23 15:38:25 +01:00
d6d13eec95 Merge branch 'development' into gaisser_unit_test_internal_error
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-23 12:37:55 +01:00
457bc6609e Merge pull request 'apply clang format' (#558) from eive/fsfw:mueller/apply-clang-format into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #558
2022-02-23 12:36:24 +01:00
e75155c329 Merge branch 'development' into mueller/apply-clang-format
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-23 12:30:40 +01:00
d4e48006f2 Merge branch 'development' into mueller/update-helper-script
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-23 12:28:12 +01:00
d6508e23b6 Added more coverage and Documentation
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-23 12:12:49 +01:00
2cb254a556 Removed unused code 2022-02-23 11:53:48 +01:00
f99f5ed730 Merge branch 'development' into mueller/dev-printout-runtime-configurable
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-23 11:03:48 +01:00
7ce2c1b624 Merge branch 'development' into mueller/gpio-hal-updates
Some checks reported errors
fsfw/fsfw/pipeline/pr-development Something is wrong with the build of this commit
2022-02-23 11:02:02 +01:00
5f7e384442 Merge branch 'development' into mueller/hal-i2c-wiretapping
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-23 11:01:53 +01:00
56d0c8c616 Merge branch 'development' into mueller/test-task-one-shot-flag-not-static
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-23 11:01:34 +01:00
5ff0f8ea10 Merge pull request 'README tweak' (#562) from eive/fsfw:mueller/readme-tweak into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
Reviewed-on: #562
2022-02-23 10:08:49 +01:00
4747e54c5d no default values for srv5 params 2022-02-22 20:08:19 +01:00
2e230daa14 additional comment 2022-02-22 18:59:50 +01:00
e909c6b6f7 Merge branch 'mueller/spi-update-clock-polarity' into mueller/master 2022-02-22 18:59:06 +01:00
d88d7c938f update spi clock polarity
- Perform an empty SPI transfer after setting speed and mode
2022-02-22 18:58:20 +01:00
fdc8a3d4f7 display run commands in helper script
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 14:02:03 +01:00
389641f8fd display run commands 2022-02-22 14:00:34 +01:00
e5e85bcff9 still clang
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 13:43:25 +01:00
4862edfdb5 Clang format 2022-02-22 13:42:56 +01:00
a50b52df51 Fixed an issue in host OSAL and added more coverage to IER
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
2022-02-22 13:37:28 +01:00
eac7e6db07 try readme tweak
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:40:31 +01:00
0c4835bfb5 update changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:37:38 +01:00
aebd4817b8 periodic printouts are runtime configurable now
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:33:41 +01:00
9c2ceb4a9f one shot flag not static anymore
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-22 11:29:23 +01:00
b440c30223 update changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:26:11 +01:00
68ace0b74a update changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:23:29 +01:00
d119479c0a update changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:22:20 +01:00
6739890d53 add i2c wiretapping option
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:19:49 +01:00
90b8ad1e6d apply clang format
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:16:33 +01:00
025f79fcb4 apply clang format
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:16:14 +01:00
3966b656e9 apply .clang format
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:15:01 +01:00
6fb64f9ada removed source from cmakelists.txt
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:11:54 +01:00
3a5881a0cb more time
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-22 11:10:02 +01:00
2f1b923009 this module should not be needed anymore
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-22 11:06:00 +01:00
1e982ec00b updated for windows compatibility
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-22 11:00:39 +01:00
701135e2a6 applied clang format 2022-02-22 10:17:56 +01:00
19f8e41c7f Merge pull request 'Update FSFW' (#33) from mueller/master into eive/develop
Reviewed-on: eive/fsfw#33
2022-02-21 11:00:17 +01:00
c4a055986c Merge remote-tracking branch 'origin/eive/develop' into mueller/master 2022-02-21 10:37:53 +01:00
d74a373f1d make periodic printout run time configurable 2022-02-19 16:41:30 +01:00
cf69af4e7e passing mqArgs to all mq ctor calls 2022-02-19 16:14:02 +01:00
45ea09291a Still test for InternalError Reporter 2022-02-18 19:57:36 +01:00
b7f3eff742 WIP unit tests 2022-02-18 19:08:06 +01:00
508979d32d cache mq args 2022-02-18 14:52:25 +01:00
0d66569687 this is a bit cleaner 2022-02-18 14:07:41 +01:00
a5871ed0b1 added void* args to queue factory and mq ctor 2022-02-18 14:00:06 +01:00
a12e98d948 update event mngr printout 2022-02-18 13:39:42 +01:00
bd05afbddd printout improvements 2022-02-18 13:09:18 +01:00
b3482eba24 error check in event manager 2022-02-17 20:41:47 +01:00
9e92afbf07 bugfix in test task 2022-02-16 18:54:55 +01:00
0d6d44f72f Merge remote-tracking branch 'upstream/development' into mueller/master 2022-02-15 17:08:29 +01:00
81f5b0c3bf Merge branch 'mueller/dhb-docs' into mueller/master 2022-02-10 14:03:28 +01:00
062e93fd88 started DHB docs 2022-02-10 13:53:01 +01:00
c20bf31d5d Merge pull request 'meier/halAdjustments' (#32) from meier/halAdjustments into eive/develop
Reviewed-on: eive/fsfw#32
2022-02-07 11:03:09 +01:00
Jakob Meier
3c06d2dbbb run clang format script 2022-02-05 18:11:23 +01:00
Jakob Meier
018d814f29 adapt to develop 2022-02-05 17:12:42 +01:00
Jakob Meier
c0648a789b merged develop 2022-02-05 17:07:06 +01:00
Jakob Meier
9579e94a71 option to exclude libgpiod from build 2022-02-05 16:09:23 +01:00
Jakob Meier
235fd79dfb added missing baudrates 2022-02-05 16:08:28 +01:00
83635d3667 Merge pull request 'Fix for event definitions' (#31) from mueller/fix-events into eive/develop
Reviewed-on: eive/fsfw#31
2022-02-03 18:20:48 +01:00
581ae4c990 another include removed 2022-02-03 17:37:29 +01:00
32a9e0c704 another include removed 2022-02-03 17:37:11 +01:00
940c53eba6 removed HK switch helper from cmake file 2022-02-03 17:34:15 +01:00
0d4bd856bd removed HK switch helper from cmake file 2022-02-03 17:33:46 +01:00
b7f6a6961b delete switch helper, some other fixes 2022-02-03 17:14:11 +01:00
a910a05541 parser is not perfect.. 2022-02-03 17:09:58 +01:00
973996e102 more fixes 2022-02-03 17:08:30 +01:00
b3aee76d91 fixes for event definitoons for parser 2022-02-03 17:06:18 +01:00
b3151a0ba0 added i2c wiretapping 2022-02-03 13:37:28 +01:00
fca48257b7 zero initialize array 2022-02-03 12:02:08 +01:00
8f95b03e6a fixes warning for good 2022-02-03 11:13:26 +01:00
527dba9a9d Merge branch 'mueller/comp-branch' into mueller/master 2022-02-02 20:15:20 +01:00
22cd38fffd this should work for c++11
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-02 20:05:46 +01:00
1a518109d0 Merge branch 'mueller/comp-branch' into mueller/master 2022-02-02 19:49:03 +01:00
8030d9ac1b this fixes the warning
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-02 19:47:58 +01:00
992c05df56 added cpp printout preprocessor guards
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-02 17:52:09 +01:00
6698d283b6 device wants hard reboot event added 2022-02-02 16:04:36 +01:00
33386550cf add uio subdir
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2022-02-02 12:17:42 +01:00
3a65c0db91 use C++ casts 2022-02-02 12:13:42 +01:00
41614303d7 renamed variable 2022-02-02 12:11:39 +01:00
783176848a include fixes 2022-02-02 12:10:39 +01:00
07cb980e06 apply clang script
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2022-02-02 12:05:03 +01:00
d8c5bd125e All EIVE changes 2022-02-02 12:02:58 +01:00
158 changed files with 2567 additions and 1540 deletions

View File

@@ -8,6 +8,36 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
# [v5.0.0]
## Changes
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
and mode
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
- GPIO HAL: `Direction`, `GpioOperation` and `Levels` are enum classes now, which prevents
name clashes with Windows defines.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
- New CMake option `FSFW_HAL_LINUX_ADD_LIBGPIOD` to specifically exclude `gpiod` code.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
- HAL Devicehandlers: Periodic printout is run-time configurable now
- `oneShotAction` flag in the `TestTask` class is not static anymore
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
## Removed
- Removed the `HkSwitchHelper`. This module should not be needed anymore, now that the local
datapools have been implemented.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/557
## Additions
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
inside `fsfw/version.h`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
# [v4.0.0]
## Additions

View File

@@ -48,9 +48,10 @@ add_library(${LIB_FSFW_NAME})
if(FSFW_BUILD_UNITTESTS)
message(STATUS "Building the FSFW unittests in addition to the static library")
# Check whether the user has already installed Catch2 first
find_package(Catch2 3)
find_package(Catch2 3 QUIET)
# Not installed, so use FetchContent to download and provide Catch2
if(NOT Catch2_FOUND)
message(STATUS "Catch2 installation not found. Downloading Catch2 library with FetchContent")
include(FetchContent)
FetchContent_Declare(
@@ -281,6 +282,24 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-Wimplicit-fallthrough=1
-Wno-unused-parameter
-Wno-psabi
-Wduplicated-cond # check for duplicate conditions
-Wduplicated-branches # check for duplicate branches
-Wlogical-op # Search for bitwise operations instead of logical
-Wnull-dereference # Search for NULL dereference
-Wundef # Warn if undefind marcos are used
-Wformat=2 # Format string problem detection
-Wformat-overflow=2 # Formatting issues in printf
-Wformat-truncation=2 # Formatting issues in printf
-Wformat-security # Search for dangerous printf operations
-Wstrict-overflow=3 # Warn if integer overflows might happen
-Warray-bounds=2 # Some array bounds violations will be found
-Wshift-overflow=2 # Search for bit left shift overflows (<c++14)
-Wcast-qual # Warn if the constness is cast away
-Wstringop-overflow=4
# -Wstack-protector # Emits a few false positives for low level access
# -Wconversion # Creates many false positives
# -Warith-conversion # Use with Wconversion to find more implicit conversions
# -fanalyzer # Should be used to look through problems
)
endif()

View File

@@ -71,9 +71,9 @@ add and link against the FSFW library in general.
4. Link against the FSFW library
```cmake
target_link_libraries(<YourProjectName> PRIVATE fsfw)
```
```cmake
target_link_libraries(${YourProjectName} PRIVATE fsfw)
```
5. It should now be possible use the FSFW as a static library from the user code.

View File

@@ -21,14 +21,14 @@ pipeline {
stage('Build') {
steps {
dir(BUILDDIR) {
sh 'cmake --build . -j'
sh 'cmake --build . -j4'
}
}
}
stage('Unittests') {
steps {
dir(BUILDDIR) {
sh 'cmake --build . -- fsfw-tests_coverage -j'
sh 'cmake --build . -- fsfw-tests_coverage -j4'
}
}
}

View File

@@ -9,6 +9,7 @@ option(FSFW_HAL_ADD_LINUX "Add the Linux HAL to the sources. Requires gpiod libr
# Linux. The only exception from this is the gpiod library which requires a dedicated installation,
# but CMake is able to determine whether this library is installed with find_library.
option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add peripheral drivers for embedded Linux" ON)
option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Target implements libgpiod" ON)
option(FSFW_HAL_ADD_RASPBERRY_PI "Add Raspberry Pi specific code to the sources" OFF)
option(FSFW_HAL_ADD_STM32H7 "Add the STM32H7 HAL to the sources" OFF)

View File

@@ -9,11 +9,11 @@ using gpioId_t = uint16_t;
namespace gpio {
enum Levels : uint8_t { LOW = 0, HIGH = 1, NONE = 99 };
enum class Levels : int { LOW = 0, HIGH = 1, NONE = 99 };
enum Direction : uint8_t { IN = 0, OUT = 1 };
enum class Direction : int { IN = 0, OUT = 1 };
enum GpioOperation { READ, WRITE };
enum class GpioOperation { READ, WRITE };
enum class GpioTypes {
NONE,
@@ -80,7 +80,7 @@ class GpiodRegularByChip : public GpiodRegularBase {
public:
GpiodRegularByChip()
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, std::string(), gpio::Direction::IN,
gpio::LOW, 0) {}
gpio::Levels::LOW, 0) {}
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_,
gpio::Direction direction_, gpio::Levels initValue_)
@@ -90,7 +90,7 @@ class GpiodRegularByChip : public GpiodRegularBase {
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_)
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, consumer_, gpio::Direction::IN,
gpio::LOW, lineNum_),
gpio::Levels::LOW, lineNum_),
chipname(chipname_) {}
std::string chipname;
@@ -106,7 +106,7 @@ class GpiodRegularByLabel : public GpiodRegularBase {
GpiodRegularByLabel(std::string label_, int lineNum_, std::string consumer_)
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL, consumer_, gpio::Direction::IN,
gpio::LOW, lineNum_),
gpio::Levels::LOW, lineNum_),
label(label_) {}
std::string label;
@@ -127,7 +127,7 @@ class GpiodRegularByLineName : public GpiodRegularBase {
GpiodRegularByLineName(std::string lineName_, std::string consumer_)
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME, consumer_, gpio::Direction::IN,
gpio::LOW),
gpio::Levels::LOW),
lineName(lineName_) {}
std::string lineName;

View File

@@ -8,11 +8,7 @@ GyroHandlerL3GD20H::GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceC
CookieIF *comCookie, uint32_t transitionDelayMs)
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
transitionDelayMs(transitionDelayMs),
dataset(this) {
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
debugDivider = new PeriodicOperationDivider(3);
#endif
}
dataset(this) {}
GyroHandlerL3GD20H::~GyroHandlerL3GD20H() {}
@@ -193,22 +189,22 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id,
int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX];
float temperature = 25.0 + temperaturOffset;
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
if (debugDivider->checkAndIncrement()) {
/* Set terminal to utf-8 if there is an issue with micro printout. */
if (periodicPrintout) {
if (debugDivider.checkAndIncrement()) {
/* Set terminal to utf-8 if there is an issue with micro printout. */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "GyroHandlerL3GD20H: Angular velocities (deg/s):" << std::endl;
sif::info << "X: " << angVelocX << std::endl;
sif::info << "Y: " << angVelocY << std::endl;
sif::info << "Z: " << angVelocZ << std::endl;
sif::info << "GyroHandlerL3GD20H: Angular velocities (deg/s):" << std::endl;
sif::info << "X: " << angVelocX << std::endl;
sif::info << "Y: " << angVelocY << std::endl;
sif::info << "Z: " << angVelocZ << std::endl;
#else
sif::printInfo("GyroHandlerL3GD20H: Angular velocities (deg/s):\n");
sif::printInfo("X: %f\n", angVelocX);
sif::printInfo("Y: %f\n", angVelocY);
sif::printInfo("Z: %f\n", angVelocZ);
sif::printInfo("GyroHandlerL3GD20H: Angular velocities (deg/s):\n");
sif::printInfo("X: %f\n", angVelocX);
sif::printInfo("Y: %f\n", angVelocY);
sif::printInfo("Z: %f\n", angVelocZ);
#endif
}
}
#endif
PoolReadGuard readSet(&dataset);
if (readSet.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
@@ -272,3 +268,8 @@ void GyroHandlerL3GD20H::setAbsoluteLimits(float limitX, float limitY, float lim
this->absLimitY = limitY;
this->absLimitZ = limitZ;
}
void GyroHandlerL3GD20H::enablePeriodicPrintouts(bool enable, uint8_t divider) {
periodicPrintout = enable;
debugDivider.setDivider(divider);
}

View File

@@ -5,7 +5,6 @@
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include "devicedefinitions/GyroL3GD20Definitions.h"
#include "fsfw/FSFW.h"
/**
* @brief Device Handler for the L3GD20H gyroscope sensor
@@ -22,6 +21,8 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase {
uint32_t transitionDelayMs);
virtual ~GyroHandlerL3GD20H();
void enablePeriodicPrintouts(bool enable, uint8_t divider);
/**
* Set the absolute limit for the values on the axis in degrees per second.
* The dataset values will be marked as invalid if that limit is exceeded
@@ -80,9 +81,8 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase {
// Set default value
float sensitivity = L3GD20H::SENSITIVITY_00;
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
PeriodicOperationDivider *debugDivider = nullptr;
#endif
bool periodicPrintout = false;
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
};
#endif /* MISSION_DEVICES_GYROL3GD20HANDLER_H_ */

View File

@@ -1,9 +1,6 @@
#include "MgmLIS3MDLHandler.h"
#include "fsfw/datapool/PoolReadGuard.h"
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
#endif
#include <cmath>
@@ -12,9 +9,6 @@ MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCom
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
dataset(this),
transitionDelay(transitionDelay) {
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
debugDivider = new PeriodicOperationDivider(3);
#endif
// Set to default values right away
registers[0] = MGMLIS3MDL::CTRL_REG1_DEFAULT;
registers[1] = MGMLIS3MDL::CTRL_REG2_DEFAULT;
@@ -264,7 +258,7 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
int16_t mgmMeasurementRawZ =
packet[MGMLIS3MDL::Z_HIGHBYTE_IDX] << 8 | packet[MGMLIS3MDL::Z_LOWBYTE_IDX];
/* Target value in microtesla */
// Target value in microtesla
float mgmX = static_cast<float>(mgmMeasurementRawX) * sensitivityFactor *
MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR;
float mgmY = static_cast<float>(mgmMeasurementRawY) * sensitivityFactor *
@@ -272,23 +266,24 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
float mgmZ = static_cast<float>(mgmMeasurementRawZ) * sensitivityFactor *
MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR;
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
if (debugDivider->checkAndIncrement()) {
if (periodicPrintout) {
if (debugDivider.checkAndIncrement()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "MGMHandlerLIS3: Magnetic field strength in"
" microtesla:"
<< std::endl;
sif::info << "X: " << mgmX << " uT" << std::endl;
sif::info << "Y: " << mgmY << " uT" << std::endl;
sif::info << "Z: " << mgmZ << " uT" << std::endl;
sif::info << "MGMHandlerLIS3: Magnetic field strength in"
" microtesla:"
<< std::endl;
sif::info << "X: " << mgmX << " uT" << std::endl;
sif::info << "Y: " << mgmY << " uT" << std::endl;
sif::info << "Z: " << mgmZ << " uT" << std::endl;
#else
sif::printInfo("MGMHandlerLIS3: Magnetic field strength in microtesla:\n");
sif::printInfo("X: %f uT\n", mgmX);
sif::printInfo("Y: %f uT\n", mgmY);
sif::printInfo("Z: %f uT\n", mgmZ);
sif::printInfo("MGMHandlerLIS3: Magnetic field strength in microtesla:\n");
sif::printInfo("X: %f uT\n", mgmX);
sif::printInfo("Y: %f uT\n", mgmY);
sif::printInfo("Z: %f uT\n", mgmZ);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 0 */
}
}
#endif /* OBSW_VERBOSE_LEVEL >= 1 */
PoolReadGuard readHelper(&dataset);
if (readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
if (std::abs(mgmX) < absLimitX) {
@@ -318,15 +313,16 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
case MGMLIS3MDL::READ_TEMPERATURE: {
int16_t tempValueRaw = packet[2] << 8 | packet[1];
float tempValue = 25.0 + ((static_cast<float>(tempValueRaw)) / 8.0);
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
if (debugDivider->check()) {
if (periodicPrintout) {
if (debugDivider.check()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "MGMHandlerLIS3: Temperature: " << tempValue << " C" << std::endl;
sif::info << "MGMHandlerLIS3: Temperature: " << tempValue << " C" << std::endl;
#else
sif::printInfo("MGMHandlerLIS3: Temperature: %f C\n");
sif::printInfo("MGMHandlerLIS3: Temperature: %f C\n");
#endif
}
}
#endif
ReturnValue_t result = dataset.read();
if (result == HasReturnvaluesIF::RETURN_OK) {
dataset.temperature = tempValue;
@@ -462,7 +458,9 @@ ReturnValue_t MgmLIS3MDLHandler::prepareCtrlRegisterWrite() {
return RETURN_OK;
}
void MgmLIS3MDLHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {}
void MgmLIS3MDLHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
DeviceHandlerBase::doTransition(modeFrom, subModeFrom);
}
uint32_t MgmLIS3MDLHandler::getTransitionDelayMs(Mode_t from, Mode_t to) { return transitionDelay; }
@@ -482,3 +480,8 @@ void MgmLIS3MDLHandler::setAbsoluteLimits(float xLimit, float yLimit, float zLim
this->absLimitY = yLimit;
this->absLimitZ = zLimit;
}
void MgmLIS3MDLHandler::enablePeriodicPrintouts(bool enable, uint8_t divider) {
periodicPrintout = enable;
debugDivider.setDivider(divider);
}

View File

@@ -3,8 +3,8 @@
#include "devicedefinitions/MgmLIS3HandlerDefs.h"
#include "events/subsystemIdRanges.h"
#include "fsfw/FSFW.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
class PeriodicOperationDivider;
@@ -30,6 +30,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
uint32_t transitionDelay);
virtual ~MgmLIS3MDLHandler();
void enablePeriodicPrintouts(bool enable, uint8_t divider);
/**
* Set the absolute limit for the values on the axis in microtesla. The dataset values will
* be marked as invalid if that limit is exceeded
@@ -167,9 +168,8 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
*/
ReturnValue_t prepareCtrlRegisterWrite();
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
PeriodicOperationDivider *debugDivider;
#endif
bool periodicPrintout = false;
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
};
#endif /* MISSION_DEVICES_MGMLIS3MDLHANDLER_H_ */

View File

@@ -10,11 +10,7 @@ MgmRM3100Handler::MgmRM3100Handler(object_id_t objectId, object_id_t deviceCommu
CookieIF *comCookie, uint32_t transitionDelay)
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
primaryDataset(this),
transitionDelay(transitionDelay) {
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
debugDivider = new PeriodicOperationDivider(3);
#endif
}
transitionDelay(transitionDelay) {}
MgmRM3100Handler::~MgmRM3100Handler() {}
@@ -337,23 +333,23 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
float fieldStrengthY = fieldStrengthRawY * scaleFactorX;
float fieldStrengthZ = fieldStrengthRawZ * scaleFactorX;
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
if (debugDivider->checkAndIncrement()) {
if (periodicPrintout) {
if (debugDivider.checkAndIncrement()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "MgmRM3100Handler: Magnetic field strength in"
" microtesla:"
<< std::endl;
sif::info << "X: " << fieldStrengthX << " uT" << std::endl;
sif::info << "Y: " << fieldStrengthY << " uT" << std::endl;
sif::info << "Z: " << fieldStrengthZ << " uT" << std::endl;
sif::info << "MgmRM3100Handler: Magnetic field strength in"
" microtesla:"
<< std::endl;
sif::info << "X: " << fieldStrengthX << " uT" << std::endl;
sif::info << "Y: " << fieldStrengthY << " uT" << std::endl;
sif::info << "Z: " << fieldStrengthZ << " uT" << std::endl;
#else
sif::printInfo("MgmRM3100Handler: Magnetic field strength in microtesla:\n");
sif::printInfo("X: %f uT\n", fieldStrengthX);
sif::printInfo("Y: %f uT\n", fieldStrengthY);
sif::printInfo("Z: %f uT\n", fieldStrengthZ);
sif::printInfo("MgmRM3100Handler: Magnetic field strength in microtesla:\n");
sif::printInfo("X: %f uT\n", fieldStrengthX);
sif::printInfo("Y: %f uT\n", fieldStrengthY);
sif::printInfo("Z: %f uT\n", fieldStrengthZ);
#endif
}
}
#endif
// TODO: Sanity check on values?
PoolReadGuard readGuard(&primaryDataset);
@@ -365,3 +361,8 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
}
return RETURN_OK;
}
void MgmRM3100Handler::enablePeriodicPrintouts(bool enable, uint8_t divider) {
periodicPrintout = enable;
debugDivider.setDivider(divider);
}

View File

@@ -2,12 +2,8 @@
#define MISSION_DEVICES_MGMRM3100HANDLER_H_
#include "devicedefinitions/MgmRM3100HandlerDefs.h"
#include "fsfw/FSFW.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
#endif
/**
* @brief Device Handler for the RM3100 geomagnetic magnetometer sensor
@@ -33,6 +29,7 @@ class MgmRM3100Handler : public DeviceHandlerBase {
uint32_t transitionDelay);
virtual ~MgmRM3100Handler();
void enablePeriodicPrintouts(bool enable, uint8_t divider);
/**
* Configure device handler to go to normal mode after startup immediately
* @param enable
@@ -98,9 +95,9 @@ class MgmRM3100Handler : public DeviceHandlerBase {
size_t commandDataLen);
ReturnValue_t handleDataReadout(const uint8_t *packet);
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
PeriodicOperationDivider *debugDivider;
#endif
bool periodicPrintout = false;
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
};
#endif /* MISSION_DEVICEHANDLING_MGMRM3100HANDLER_H_ */

View File

@@ -9,7 +9,9 @@ target_sources(${LIB_FSFW_NAME} PRIVATE
)
if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
add_subdirectory(gpio)
endif()
add_subdirectory(spi)
add_subdirectory(i2c)
add_subdirectory(uart)

View File

@@ -0,0 +1,27 @@
#ifndef FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_
#define FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_
#include "fsfw_hal/common/gpio/GpioIF.h"
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
/**
* @brief Additional abstraction layer for handling GPIOs.
*
* @author J. Meier
*/
class Gpio {
public:
Gpio(gpioId_t gpioId, GpioIF* gpioIF) : gpioId(gpioId), gpioIF(gpioIF) {
if (gpioIF == nullptr) {
sif::error << "Gpio::Gpio: Invalid GpioIF" << std::endl;
}
}
ReturnValue_t pullHigh() { return gpioIF->pullHigh(gpioId); }
ReturnValue_t pullLow() { return gpioIF->pullLow(gpioId); }
private:
gpioId_t gpioId = gpio::NO_GPIO;
GpioIF* gpioIF = nullptr;
};
#endif /* FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_ */

View File

@@ -161,11 +161,12 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
consumer = regularGpio.consumer;
/* Configure direction and add a description to the GPIO */
switch (direction) {
case (gpio::OUT): {
result = gpiod_line_request_output(lineHandle, consumer.c_str(), regularGpio.initValue);
case (gpio::Direction::OUT): {
result = gpiod_line_request_output(lineHandle, consumer.c_str(),
static_cast<int>(regularGpio.initValue));
break;
}
case (gpio::IN): {
case (gpio::Direction::IN): {
result = gpiod_line_request_input(lineHandle, consumer.c_str());
break;
}
@@ -211,7 +212,7 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
if (regularGpio == nullptr) {
return GPIO_TYPE_FAILURE;
}
return driveGpio(gpioId, *regularGpio, gpio::HIGH);
return driveGpio(gpioId, *regularGpio, gpio::Levels::HIGH);
} else {
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
if (gpioCallback->callback == nullptr) {
@@ -243,7 +244,7 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
if (regularGpio == nullptr) {
return GPIO_TYPE_FAILURE;
}
return driveGpio(gpioId, *regularGpio, gpio::LOW);
return driveGpio(gpioId, *regularGpio, gpio::Levels::LOW);
} else {
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
if (gpioCallback->callback == nullptr) {
@@ -258,11 +259,11 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegularBase& regularGpio,
gpio::Levels logicLevel) {
int result = gpiod_line_set_value(regularGpio.lineHandle, logicLevel);
int result = gpiod_line_set_value(regularGpio.lineHandle, static_cast<int>(logicLevel));
if (result < 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID " << gpioId
<< " to logic level " << logicLevel << std::endl;
<< " to logic level " << static_cast<int>(logicLevel) << std::endl;
#else
sif::printWarning(
"LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID %d to "

View File

@@ -1,4 +1,13 @@
#include "fsfw_hal/linux/i2c/I2cComIF.h"
#include "I2cComIF.h"
#include "fsfw/FSFW.h"
#include "fsfw/serviceinterface.h"
#include "fsfw_hal/linux/UnixFileGuard.h"
#include "fsfw_hal/linux/utility.h"
#if FSFW_HAL_I2C_WIRETAPPING == 1
#include "fsfw/globalfunctions/arrayprinter.h"
#endif
#include <errno.h>
#include <fcntl.h>
@@ -8,11 +17,6 @@
#include <cstring>
#include "fsfw/FSFW.h"
#include "fsfw/serviceinterface.h"
#include "fsfw_hal/linux/UnixFileGuard.h"
#include "fsfw_hal/linux/utility.h"
I2cComIF::I2cComIF(object_id_t objectId) : SystemObject(objectId) {}
I2cComIF::~I2cComIF() {}
@@ -112,6 +116,11 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
#if FSFW_HAL_I2C_WIRETAPPING == 1
sif::info << "Sent I2C data to bus " << deviceFile << ":" << std::endl;
arrayprinter::print(sendData, sendLen);
#endif
return HasReturnvaluesIF::RETURN_OK;
}
@@ -176,6 +185,11 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
return HasReturnvaluesIF::RETURN_FAILED;
}
#if FSFW_HAL_I2C_WIRETAPPING == 1
sif::info << "I2C read bytes from bus " << deviceFile << ":" << std::endl;
arrayprinter::print(replyBuffer, requestLen);
#endif
i2cDeviceMapIter->second.replyLen = requestLen;
return HasReturnvaluesIF::RETURN_OK;
}

View File

@@ -7,7 +7,7 @@
ReturnValue_t gpio::createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int bcmPin,
std::string consumer, gpio::Direction direction,
int initValue) {
gpio::Levels initValue) {
if (cookie == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}

View File

@@ -21,7 +21,8 @@ namespace gpio {
* @return
*/
ReturnValue_t createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int bcmPin,
std::string consumer, gpio::Direction direction, int initValue);
std::string consumer, gpio::Direction direction,
gpio::Levels initValue);
} // namespace gpio
#endif /* BSP_RPI_GPIO_GPIORPI_H_ */

View File

@@ -401,4 +401,12 @@ void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed)
if (retval != 0) {
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed");
}
// This updates the SPI clock default polarity. Only setting the mode does not update
// the line state, which can be an issue on mode switches because the clock line will
// switch the state after the chip select is pulled low
clockUpdateTransfer.len = 0;
retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer);
if (retval != 0) {
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed");
}
}

View File

@@ -74,6 +74,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
MutexIF* spiMutex = nullptr;
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 20;
spi_ioc_transfer clockUpdateTransfer = {};
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;
using SpiDeviceMapIter = SpiDeviceMap::iterator;

View File

@@ -148,16 +148,16 @@ void UartComIF::setDatasizeOptions(struct termios* options, UartCookie* uartCook
/* Clear size bits */
options->c_cflag &= ~CSIZE;
switch (uartCookie->getBitsPerWord()) {
case 5:
case BitsPerWord::BITS_5:
options->c_cflag |= CS5;
break;
case 6:
case BitsPerWord::BITS_6:
options->c_cflag |= CS6;
break;
case 7:
case BitsPerWord::BITS_7:
options->c_cflag |= CS7;
break;
case 8:
case BitsPerWord::BITS_8:
options->c_cflag |= CS8;
break;
default:
@@ -193,82 +193,126 @@ void UartComIF::setFixedOptions(struct termios* options) {
void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCookie) {
switch (uartCookie->getBaudrate()) {
case 50:
case UartBaudRate::RATE_50:
cfsetispeed(options, B50);
cfsetospeed(options, B50);
break;
case 75:
case UartBaudRate::RATE_75:
cfsetispeed(options, B75);
cfsetospeed(options, B75);
break;
case 110:
case UartBaudRate::RATE_110:
cfsetispeed(options, B110);
cfsetospeed(options, B110);
break;
case 134:
case UartBaudRate::RATE_134:
cfsetispeed(options, B134);
cfsetospeed(options, B134);
break;
case 150:
case UartBaudRate::RATE_150:
cfsetispeed(options, B150);
cfsetospeed(options, B150);
break;
case 200:
case UartBaudRate::RATE_200:
cfsetispeed(options, B200);
cfsetospeed(options, B200);
break;
case 300:
case UartBaudRate::RATE_300:
cfsetispeed(options, B300);
cfsetospeed(options, B300);
break;
case 600:
case UartBaudRate::RATE_600:
cfsetispeed(options, B600);
cfsetospeed(options, B600);
break;
case 1200:
case UartBaudRate::RATE_1200:
cfsetispeed(options, B1200);
cfsetospeed(options, B1200);
break;
case 1800:
case UartBaudRate::RATE_1800:
cfsetispeed(options, B1800);
cfsetospeed(options, B1800);
break;
case 2400:
case UartBaudRate::RATE_2400:
cfsetispeed(options, B2400);
cfsetospeed(options, B2400);
break;
case 4800:
case UartBaudRate::RATE_4800:
cfsetispeed(options, B4800);
cfsetospeed(options, B4800);
break;
case 9600:
case UartBaudRate::RATE_9600:
cfsetispeed(options, B9600);
cfsetospeed(options, B9600);
break;
case 19200:
case UartBaudRate::RATE_19200:
cfsetispeed(options, B19200);
cfsetospeed(options, B19200);
break;
case 38400:
case UartBaudRate::RATE_38400:
cfsetispeed(options, B38400);
cfsetospeed(options, B38400);
break;
case 57600:
case UartBaudRate::RATE_57600:
cfsetispeed(options, B57600);
cfsetospeed(options, B57600);
break;
case 115200:
case UartBaudRate::RATE_115200:
cfsetispeed(options, B115200);
cfsetospeed(options, B115200);
break;
case 230400:
case UartBaudRate::RATE_230400:
cfsetispeed(options, B230400);
cfsetospeed(options, B230400);
break;
case 460800:
case UartBaudRate::RATE_460800:
cfsetispeed(options, B460800);
cfsetospeed(options, B460800);
break;
case UartBaudRate::RATE_500000:
cfsetispeed(options, B500000);
cfsetospeed(options, B500000);
break;
case UartBaudRate::RATE_576000:
cfsetispeed(options, B576000);
cfsetospeed(options, B576000);
break;
case UartBaudRate::RATE_921600:
cfsetispeed(options, B921600);
cfsetospeed(options, B921600);
break;
case UartBaudRate::RATE_1000000:
cfsetispeed(options, B1000000);
cfsetospeed(options, B1000000);
break;
case UartBaudRate::RATE_1152000:
cfsetispeed(options, B1152000);
cfsetospeed(options, B1152000);
break;
case UartBaudRate::RATE_1500000:
cfsetispeed(options, B1500000);
cfsetospeed(options, B1500000);
break;
case UartBaudRate::RATE_2000000:
cfsetispeed(options, B2000000);
cfsetospeed(options, B2000000);
break;
case UartBaudRate::RATE_2500000:
cfsetispeed(options, B2500000);
cfsetospeed(options, B2500000);
break;
case UartBaudRate::RATE_3000000:
cfsetispeed(options, B3000000);
cfsetospeed(options, B3000000);
break;
case UartBaudRate::RATE_3500000:
cfsetispeed(options, B3500000);
cfsetospeed(options, B3500000);
break;
case UartBaudRate::RATE_4000000:
cfsetispeed(options, B4000000);
cfsetospeed(options, B4000000);
break;
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
@@ -427,7 +471,7 @@ ReturnValue_t UartComIF::handleNoncanonicalRead(UartCookie& uartCookie, UartDevi
auto bufferPtr = iter->second.replyBuffer.data();
// Size check to prevent buffer overflow
if (requestLen > uartCookie.getMaxReplyLen()) {
#if OBSW_VERBOSE_LEVEL >= 1
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::requestReceiveMessage: Next read would cause overflow!"
<< std::endl;

View File

@@ -1,9 +1,9 @@
#include "fsfw_hal/linux/uart/UartCookie.h"
#include "UartCookie.h"
#include <fsfw/serviceinterface.h>
UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode,
uint32_t baudrate, size_t maxReplyLen)
UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
size_t maxReplyLen, UartModes uartMode)
: handlerId(handlerId),
deviceFile(deviceFile),
uartMode(uartMode),
@@ -12,7 +12,7 @@ UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes
UartCookie::~UartCookie() {}
uint32_t UartCookie::getBaudrate() const { return baudrate; }
UartBaudRate UartCookie::getBaudrate() const { return baudrate; }
size_t UartCookie::getMaxReplyLen() const { return maxReplyLen; }
@@ -24,23 +24,9 @@ void UartCookie::setParityEven() { parity = Parity::EVEN; }
Parity UartCookie::getParity() const { return parity; }
void UartCookie::setBitsPerWord(uint8_t bitsPerWord_) {
switch (bitsPerWord_) {
case 5:
case 6:
case 7:
case 8:
break;
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "UartCookie::setBitsPerWord: Invalid bits per word specified" << std::endl;
#endif
return;
}
bitsPerWord = bitsPerWord_;
}
void UartCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; }
uint8_t UartCookie::getBitsPerWord() const { return bitsPerWord; }
BitsPerWord UartCookie::getBitsPerWord() const { return bitsPerWord; }
StopBits UartCookie::getStopBits() const { return stopBits; }

View File

@@ -12,6 +12,41 @@ enum class StopBits { ONE_STOP_BIT, TWO_STOP_BITS };
enum class UartModes { CANONICAL, NON_CANONICAL };
enum class BitsPerWord { BITS_5, BITS_6, BITS_7, BITS_8 };
enum class UartBaudRate {
RATE_50,
RATE_75,
RATE_110,
RATE_134,
RATE_150,
RATE_200,
RATE_300,
RATE_600,
RATE_1200,
RATE_1800,
RATE_2400,
RATE_4800,
RATE_9600,
RATE_19200,
RATE_38400,
RATE_57600,
RATE_115200,
RATE_230400,
RATE_460800,
RATE_500000,
RATE_576000,
RATE_921600,
RATE_1000000,
RATE_1152000,
RATE_1500000,
RATE_2000000,
RATE_2500000,
RATE_3000000,
RATE_3500000,
RATE_4000000
};
/**
* @brief Cookie for the UartComIF. There are many options available to configure the UART driver.
* The constructor only requests for common options like the baudrate. Other options can
@@ -27,25 +62,23 @@ class UartCookie : public CookieIF {
* @param uartMode Specify the UART mode. The canonical mode should be used if the
* messages are separated by a delimited character like '\n'. See the
* termios documentation for more information
* @param baudrate The baudrate to use for input and output. Possible Baudrates are: 50,
* 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, B19200,
* 38400, 57600, 115200, 230400, 460800
* @param baudrate The baudrate to use for input and output.
* @param maxReplyLen The maximum size an object using this cookie expects
* @details
* Default configuration: No parity
* 8 databits (number of bits transfered with one uart frame)
* One stop bit
*/
UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode, uint32_t baudrate,
size_t maxReplyLen);
UartCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
size_t maxReplyLen, UartModes uartMode = UartModes::NON_CANONICAL);
virtual ~UartCookie();
uint32_t getBaudrate() const;
UartBaudRate getBaudrate() const;
size_t getMaxReplyLen() const;
std::string getDeviceFile() const;
Parity getParity() const;
uint8_t getBitsPerWord() const;
BitsPerWord getBitsPerWord() const;
StopBits getStopBits() const;
UartModes getUartMode() const;
object_id_t getHandlerId() const;
@@ -76,7 +109,7 @@ class UartCookie : public CookieIF {
/**
* Function two set number of bits per UART frame.
*/
void setBitsPerWord(uint8_t bitsPerWord_);
void setBitsPerWord(BitsPerWord bitsPerWord_);
/**
* Function to specify the number of stopbits.
@@ -97,10 +130,10 @@ class UartCookie : public CookieIF {
std::string deviceFile;
const UartModes uartMode;
bool flushInput = false;
uint32_t baudrate;
UartBaudRate baudrate;
size_t maxReplyLen = 0;
Parity parity = Parity::NONE;
uint8_t bitsPerWord = 8;
BitsPerWord bitsPerWord = BitsPerWord::BITS_8;
uint8_t readCycles = 1;
StopBits stopBits = StopBits::ONE_STOP_BIT;
bool replySizeFixed = true;

View File

@@ -97,11 +97,11 @@ def handle_docs_type(args, build_dir_list: list):
build_directory = determine_build_dir(build_dir_list)
os.chdir(build_directory)
if args.build:
os.system("cmake --build . -j")
cmd_runner("cmake --build . -j")
if args.open:
if not os.path.isfile("docs/sphinx/index.html"):
# try again..
os.system("cmake --build . -j")
cmd_runner("cmake --build . -j")
if not os.path.isfile("docs/sphinx/index.html"):
print(
"No Sphinx documentation file detected. "
@@ -143,25 +143,21 @@ def handle_tests_type(args, build_dir_list: list):
if which("valgrind") is None:
print("Please install valgrind first")
sys.exit(1)
if os.path.split(os.getcwd())[1] != UNITTEST_FOLDER_NAME:
# If we are in a different directory we try to switch into it but
# this might fail
os.chdir(UNITTEST_FOLDER_NAME)
os.system("valgrind --leak-check=full ./fsfw-tests")
cmd_runner("valgrind --leak-check=full ./fsfw-tests")
os.chdir("..")
def create_tests_build_cfg():
os.mkdir(UNITTEST_FOLDER_NAME)
os.chdir(UNITTEST_FOLDER_NAME)
os.system("cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..")
cmd_runner("cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..")
os.chdir("..")
def create_docs_build_cfg():
os.mkdir(DOCS_FOLDER_NAME)
os.chdir(DOCS_FOLDER_NAME)
os.system("cmake -DFSFW_OSAL=host -DFSFW_BUILD_DOCS=ON ..")
cmd_runner("cmake -DFSFW_OSAL=host -DFSFW_BUILD_DOCS=ON ..")
os.chdir("..")
@@ -184,7 +180,7 @@ def check_for_cmake_build_dir(build_dir_list: list) -> list:
def perform_lcov_operation(directory: str, chdir: bool):
if chdir:
os.chdir(directory)
os.system("cmake --build . -- fsfw-tests_coverage -j")
cmd_runner("cmake --build . -- fsfw-tests_coverage -j")
def determine_build_dir(build_dir_list: List[str]):
@@ -206,5 +202,10 @@ def determine_build_dir(build_dir_list: List[str]):
return build_directory
def cmd_runner(cmd: str):
print(f"Executing command: {cmd}")
os.system(cmd)
if __name__ == "__main__":
main()

View File

@@ -1,3 +1,7 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
version.cpp
)
# Core
add_subdirectory(action)

View File

@@ -30,6 +30,10 @@
#define FSFW_VERBOSE_LEVEL 1
#endif /* FSFW_VERBOSE_LEVEL */
#ifndef FSFW_DISABLE_PRINTOUT
#define FSFW_DISABLE_PRINTOUT 0
#endif
#ifndef FSFW_USE_REALTIME_FOR_LINUX
#define FSFW_USE_REALTIME_FOR_LINUX 0
#endif /* FSFW_USE_REALTIME_FOR_LINUX */
@@ -57,16 +61,9 @@
#define FSFW_HAL_SPI_WIRETAPPING 0
#endif
#ifndef FSFW_HAL_L3GD20_GYRO_DEBUG
#define FSFW_HAL_L3GD20_GYRO_DEBUG 0
#endif /* FSFW_HAL_L3GD20_GYRO_DEBUG */
#ifndef FSFW_HAL_RM3100_MGM_DEBUG
#define FSFW_HAL_RM3100_MGM_DEBUG 0
#endif /* FSFW_HAL_RM3100_MGM_DEBUG */
#ifndef FSFW_HAL_LIS3MDL_MGM_DEBUG
#define FSFW_HAL_LIS3MDL_MGM_DEBUG 0
#endif /* FSFW_HAL_LIS3MDL_MGM_DEBUG */
// Can be used for low-level debugging of the I2C bus
#ifndef FSFW_HAL_I2C_WIRETAPPING
#define FSFW_HAL_I2C_WIRETAPPING 0
#endif
#endif /* FSFW_FSFW_H_ */

View File

@@ -2,8 +2,8 @@
#define FSFW_VERSION_H_
// Versioning is kept in project CMakeLists.txt file
#define FSFW_VERSION @FSFW_VERSION@
#define FSFW_SUBVERSION @FSFW_SUBVERSION@
#define FSFW_REVISION @FSFW_REVISION@
#define FSFW_VERSION_MAJOR @FSFW_VERSION@
#define FSFW_VERSION_MINOR @FSFW_SUBVERSION@
#define FSFW_VERSION_REVISION @FSFW_REVISION@
#endif /* FSFW_VERSION_H_ */

View File

@@ -16,8 +16,8 @@ class CommandActionHelper {
public:
CommandActionHelper(CommandsActionsIF* owner);
virtual ~CommandActionHelper();
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data,
uint32_t size);
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
const uint8_t* data = nullptr, uint32_t size = 0);
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
ReturnValue_t initialize();
ReturnValue_t handleReply(CommandMessage* reply);

View File

@@ -12,7 +12,9 @@ object_id_t CFDPHandler::packetDestination = 0;
CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist)
: SystemObject(setObjectId) {
requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION);
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
requestQueue = QueueFactory::instance()->createMessageQueue(
CFDP_HANDLER_MAX_RECEPTION, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
distributor = dist;
}

View File

@@ -6,10 +6,13 @@
#include <fsfw/cfdp/tlv/Tlv.h>
#include <fsfw/cfdp/tlv/TlvIF.h>
#include <fsfw/serialize/SerializeIF.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <cstddef>
#include <cstdint>
#include "fsfw/FSFW.h"
namespace cfdp {
enum FilestoreActionCode {

View File

@@ -10,16 +10,24 @@ class HybridIterator : public LinkedElement<T>::Iterator, public ArrayList<T, co
HybridIterator() {}
HybridIterator(typename LinkedElement<T>::Iterator *iter)
: LinkedElement<T>::Iterator(*iter), value(iter->value), linked(true) {}
: LinkedElement<T>::Iterator(*iter), value(iter->value), linked(true) {
if(iter != nullptr) {
value = iter->value;
}
}
HybridIterator(LinkedElement<T> *start)
: LinkedElement<T>::Iterator(start), value(start->value), linked(true) {}
: LinkedElement<T>::Iterator(start), linked(true) {
if(start != nullptr) {
value = start->value;
}
}
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
typename ArrayList<T, count_t>::Iterator end)
: ArrayList<T, count_t>::Iterator(start), value(start.value), linked(false), end(end.value) {
if (value == this->end) {
value = NULL;
value = nullptr;
}
}

View File

@@ -13,7 +13,9 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
submode(SUBMODE_NONE),
modeHelper(this),
healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

@@ -1,7 +1,6 @@
#ifndef FSFW_CONTROLLER_CONTROLLERBASE_H_
#define FSFW_CONTROLLER_CONTROLLERBASE_H_
#include "fsfw/datapool/HkSwitchHelper.h"
#include "fsfw/health/HasHealthIF.h"
#include "fsfw/health/HealthHelper.h"
#include "fsfw/modes/HasModesIF.h"

View File

@@ -1,6 +1,4 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
HkSwitchHelper.cpp
PoolDataSetBase.cpp
PoolEntry.cpp
target_sources(${LIB_FSFW_NAME} PRIVATE
PoolDataSetBase.cpp
PoolEntry.cpp
)

View File

@@ -1,67 +0,0 @@
#include "fsfw/datapool/HkSwitchHelper.h"
#include "fsfw/ipc/QueueFactory.h"
HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy)
: commandActionHelper(this), eventProxy(eventProxy) {
actionQueue = QueueFactory::instance()->createMessageQueue();
}
HkSwitchHelper::~HkSwitchHelper() { QueueFactory::instance()->deleteMessageQueue(actionQueue); }
ReturnValue_t HkSwitchHelper::initialize() {
ReturnValue_t result = commandActionHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return result;
}
ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) {
CommandMessage command;
while (actionQueue->receiveMessage(&command) == HasReturnvaluesIF::RETURN_OK) {
ReturnValue_t result = commandActionHelper.handleReply(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
command.setToUnknownCommand();
actionQueue->reply(&command);
}
return HasReturnvaluesIF::RETURN_OK;
}
void HkSwitchHelper::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {}
void HkSwitchHelper::stepFailedReceived(ActionId_t actionId, uint8_t step,
ReturnValue_t returnCode) {
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
}
void HkSwitchHelper::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) {}
void HkSwitchHelper::completionSuccessfulReceived(ActionId_t actionId) {}
void HkSwitchHelper::completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) {
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
}
ReturnValue_t HkSwitchHelper::switchHK(SerializeIF* sids, bool enable) {
// ActionId_t action = HKService::DISABLE_HK;
// if (enable) {
// action = HKService::ENABLE_HK;
// }
//
// ReturnValue_t result = commandActionHelper.commandAction(
// objects::PUS_HK_SERVICE, action, sids);
//
// if (result != HasReturnvaluesIF::RETURN_OK) {
// eventProxy->forwardEvent(SWITCHING_TM_FAILED, result);
// }
// return result;
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueIF* HkSwitchHelper::getCommandQueuePtr() { return actionQueue; }

View File

@@ -1,44 +0,0 @@
#ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
#define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
#include "fsfw/action/CommandsActionsIF.h"
#include "fsfw/events/EventReportingProxyIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
// TODO this class violations separation between mission and framework
// but it is only a transitional solution until the Datapool is
// implemented decentrally
class HkSwitchHelper : public ExecutableObjectIF, public CommandsActionsIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HK;
static const Event SWITCHING_TM_FAILED =
MAKE_EVENT(1, severity::LOW); //!< Commanding the HK Service failed, p1: error code, p2
//!< action: 0 disable / 1 enable
HkSwitchHelper(EventReportingProxyIF* eventProxy);
virtual ~HkSwitchHelper();
ReturnValue_t initialize();
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
ReturnValue_t switchHK(SerializeIF* sids, bool enable);
virtual void setTaskIF(PeriodicTaskIF* task_){};
protected:
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step);
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode);
virtual void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size);
virtual void completionSuccessfulReceived(ActionId_t actionId);
virtual void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode);
virtual MessageQueueIF* getCommandQueuePtr();
private:
CommandActionHelper commandActionHelper;
MessageQueueIF* actionQueue;
EventReportingProxyIF* eventProxy;
};
#endif /* FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ */

View File

@@ -7,24 +7,26 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
template <typename T>
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, bool setValid)
: length(static_cast<uint8_t>(initValue.size())), valid(setValid) {
this->address = new T[this->length];
if (initValue.size() == 0) {
std::memset(this->address, 0, this->getByteSize());
} else {
std::copy(initValue.begin(), initValue.end(), this->address);
PoolEntry<T>::PoolEntry(uint8_t len, bool setValid): length(len), valid(setValid) {
this->address = new T[this->length]();
std::memset(this->address, 0, this->getByteSize());
}
template <typename T>
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValues, bool setValid)
: length(static_cast<uint8_t>(initValues.size())), valid(setValid) {
this->address = new T[this->length]();
if (initValues.size() > 0) {
std::copy(initValues.begin(), initValues.end(), this->address);
}
}
template <typename T>
PoolEntry<T>::PoolEntry(T* initValue, uint8_t setLength, bool setValid)
PoolEntry<T>::PoolEntry(const T* initValue, uint8_t setLength, bool setValid)
: length(setLength), valid(setValid) {
this->address = new T[this->length];
this->address = new T[this->length]();
if (initValue != nullptr) {
std::memcpy(this->address, initValue, this->getByteSize());
} else {
std::memset(this->address, 0, this->getByteSize());
}
}

View File

@@ -33,6 +33,9 @@ class PoolEntry : public PoolEntryIF {
"instead! The ECSS standard defines a boolean as a one bit "
"field. Therefore it is preferred to store a boolean as an "
"uint8_t");
PoolEntry(uint8_t len = 1, bool setValid = false);
/**
* @brief In the classe's constructor, space is allocated on the heap and
* potential initialization values are copied to that space.
@@ -49,7 +52,7 @@ class PoolEntry : public PoolEntryIF {
* @param setValid
* Sets the initialization flag. It is invalid by default.
*/
PoolEntry(std::initializer_list<T> initValue = {0}, bool setValid = false);
PoolEntry(std::initializer_list<T> initValue, bool setValid = false);
/**
* @brief In the classe's constructor, space is allocated on the heap and
@@ -62,7 +65,7 @@ class PoolEntry : public PoolEntryIF {
* @param setValid
* Sets the initialization flag. It is invalid by default.
*/
PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false);
PoolEntry(const T* initValue, uint8_t setLength = 1, bool setValid = false);
//! Explicitely deleted copy ctor, copying is not allowed.
PoolEntry(const PoolEntry&) = delete;

View File

@@ -84,8 +84,8 @@ ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() {
return result;
}
printWarningOrError(sif::OutputTypes::OUT_WARNING, "initialize", HasReturnvaluesIF::RETURN_FAILED,
"The map should only be initialized once");
printWarningOrError(sif::OutputTypes::OUT_WARNING, "initializeHousekeepingPoolEntriesOnce",
HasReturnvaluesIF::RETURN_FAILED, "The map should only be initialized once");
return HasReturnvaluesIF::RETURN_OK;
}

View File

@@ -162,6 +162,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
object_id_t getCreatorObjectId();
bool getReportingEnabled() const;
void setReportingEnabled(bool enabled);
/**
* Returns the current periodic HK generation interval this set
@@ -189,7 +190,6 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* Used for periodic generation.
*/
bool reportingEnabled = false;
void setReportingEnabled(bool enabled);
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor = 5);

View File

@@ -47,13 +47,14 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
HasLocalDataPoolIF* hkOwner = ObjectManager::instance()->get<HasLocalDataPoolIF>(poolOwner);
if (hkOwner == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPoolVariable: The supplied pool owner did not implement the correct "
"interface HasLocalDataPoolIF!"
<< std::endl;
sif::error << "LocalPoolVariable: The supplied pool owner 0x" << std::hex << poolOwner
<< std::dec << " did not implement the correct interface "
<< "HasLocalDataPoolIF" << std::endl;
#else
sif::printError(
"LocalPoolVariable: The supplied pool owner did not implement the correct "
"interface HasLocalDataPoolIF!\n");
"LocalPoolVariable: The supplied pool owner 0x%08x did not implement the correct "
"interface HasLocalDataPoolIF\n",
poolOwner);
#endif
return;
}

View File

@@ -46,7 +46,7 @@ class StaticLocalDataSet : public LocalPoolDataSetBase {
}
private:
std::array<PoolVariableIF*, NUM_VARIABLES> poolVarList;
std::array<PoolVariableIF*, NUM_VARIABLES> poolVarList = {};
};
#endif /* FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_ */

View File

@@ -26,11 +26,7 @@ void AssemblyBase::performChildOperation() {
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
doStartTransition(mode, submode);
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
triggerModeHelperEvents(mode, submode);
}
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
@@ -77,9 +73,10 @@ bool AssemblyBase::handleChildrenChangedHealth() {
}
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
triggerEvent(TRYING_RECOVERY);
triggerEvent(TRYING_RECOVERY, iter->first, 0);
recoveryState = RECOVERY_STARTED;
recoveringDevice = iter;
// The user needs to take care of commanding the children off in commandChildren
doStartTransition(targetMode, targetSubmode);
} else {
triggerEvent(CHILD_CHANGED_HEALTH);
@@ -228,6 +225,9 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
bool AssemblyBase::checkAndHandleRecovery() {
switch (recoveryState) {
case RECOVERY_STARTED:
// The recovery was already start in #handleChildrenChangedHealth and we just need
// to wait for an off time period.
// TODO: make time period configurable
recoveryState = RECOVERY_WAIT;
recoveryOffTimer.resetTimer();
return true;
@@ -266,3 +266,11 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal
modeHelper.setForced(true);
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
}
void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) {
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
}

View File

@@ -12,7 +12,8 @@
* Documentation: Dissertation Baetz p.156, 157.
*
* This class reduces the complexity of controller components which would
* otherwise be needed for the handling of redundant devices.
* otherwise be needed for the handling of redundant devices. However, it can also be used to
* manage the mode keeping and recovery of non-redundant devices
*
* The template class monitors mode and health state of its children
* and checks availability of devices on every detected change.
@@ -26,11 +27,9 @@
*
* Important:
*
* The implementation must call registerChild(object_id_t child)
* for all commanded children during initialization.
* The implementation must call #registerChild for all commanded children during initialization.
* The implementation must call the initialization function of the base class.
* (This will call the function in SubsystemBase)
*
*/
class AssemblyBase : public SubsystemBase {
public:
@@ -47,13 +46,14 @@ class AssemblyBase : public SubsystemBase {
protected:
/**
* Command children to reach [mode,submode] combination
* Can be done by setting #commandsOutstanding correctly,
* or using executeTable()
* Command children to reach [mode,submode] combination. Can be done by setting
* #commandsOutstanding correctly, or using #executeTable. In case of an FDIR recovery,
* the user needs to ensure that the target devices are healthy. If a device is not healthy,
* a recovery might be on-going and the device needs to be commanded to off first.
* @param mode
* @param submode
* @return
* - @c RETURN_OK if ok
* - @c RETURN_OK if OK
* - @c NEED_SECOND_STEP if children need to be commanded again
*/
virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0;
@@ -120,8 +120,19 @@ class AssemblyBase : public SubsystemBase {
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
virtual void performChildOperation();
/**
* @brief Default periodic handler
* @details
* This is the default periodic handler which will be called by the SubsystemBase
* performOperation. It performs the child transitions or reacts to changed health/mode states
* of children objects
*/
virtual void performChildOperation() override;
/**
* This function handles changed mode or health states of children
* @return
*/
bool handleChildrenChanged();
/**
@@ -134,12 +145,37 @@ class AssemblyBase : public SubsystemBase {
bool handleChildrenChangedHealth();
/**
* Core transition handler. The default implementation will only do something if
* #commandsOutstanding is smaller or equal to zero, which means that all mode commands
* from the #doPerformTransition call were executed successfully.
*
* Unless a second step was requested, the function will then use #checkChildrenState to
* determine whether the target mode was reached.
*
* There is some special handling for certain (internal) modes:
* - A second step is necessary. #commandChildren will be performed again
* - The device health was overwritten. #commandChildren will be called
* - A recovery is ongoing. #checkAndHandleRecovery will be called.
*/
virtual void handleChildrenTransition();
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
/**
* Calls #doStartTransition and triggers an informative event as well that the mode will
* change
* @param mode
* @param submode
*/
virtual void startTransition(Mode_t mode, Submode_t submode);
/**
* This function starts the transition by setting the internal #targetSubmode and #targetMode
* variables and then calling the #commandChildren function.
* @param mode
* @param submode
*/
virtual void doStartTransition(Mode_t mode, Submode_t submode);
virtual bool isInTransition();
@@ -160,7 +196,7 @@ class AssemblyBase : public SubsystemBase {
* Manages recovery of a device
* @return true if recovery is still ongoing, false else.
*/
bool checkAndHandleRecovery();
virtual bool checkAndHandleRecovery();
/**
* Helper method to overwrite health state of one of the children.
@@ -168,6 +204,8 @@ class AssemblyBase : public SubsystemBase {
* @param objectId Must be a registered child.
*/
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
void triggerModeHelperEvents(Mode_t mode, Submode_t submode);
};
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */

View File

@@ -39,8 +39,9 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
childTransitionDelay(5000),
transitionSourceMode(_MODE_POWER_DOWN),
transitionSourceSubMode(SUBMODE_NONE) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE);
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
insertInCommandMap(RAW_COMMAND_ID);
cookieInfo.state = COOKIE_UNUSED;
cookieInfo.pendingCommand = deviceCommandMap.end();
@@ -48,9 +49,6 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase",
HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie");
}
if (this->fdirInstance == nullptr) {
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFdirParentId);
}
}
void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
@@ -126,6 +124,18 @@ ReturnValue_t DeviceHandlerBase::initialize() {
if (result != RETURN_OK) {
return result;
}
if (this->fdirInstance == nullptr) {
this->fdirInstance =
new DeviceHandlerFailureIsolation(this->getObjectId(), defaultFdirParentId);
}
if (this->parent != objects::NO_OBJECT) {
HasModesIF* modeIF = ObjectManager::instance()->get<HasModesIF>(this->parent);
HasHealthIF* healthIF = ObjectManager::instance()->get<HasHealthIF>(this->parent);
if (modeIF != nullptr and healthIF != nullptr) {
setParentQueue(modeIF->getCommandQueue());
}
}
communicationInterface =
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
@@ -352,14 +362,12 @@ void DeviceHandlerBase::doStateMachine() {
}
} break;
case _MODE_WAIT_OFF: {
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (powerSwitcher == nullptr) {
setMode(MODE_OFF);
break;
}
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
setMode(MODE_ERROR_ON);
@@ -410,7 +418,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) {
// No need to check, as we may try to insert multiple times.
insertInCommandMap(deviceCommand);
insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
if (hasDifferentReplyId) {
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic);
} else {
@@ -437,11 +445,15 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
}
}
ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) {
ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand,
bool useAlternativeReply,
DeviceCommandId_t alternativeReplyId) {
DeviceCommandInfo info;
info.expectedReplies = 0;
info.isExecuting = false;
info.sendReplyTo = NO_COMMANDER;
info.useAlternativeReplyId = alternativeReplyId;
info.alternativeReplyId = alternativeReplyId;
auto resultPair = deviceCommandMap.emplace(deviceCommand, info);
if (resultPair.second) {
return RETURN_OK;
@@ -451,12 +463,20 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm
}
size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
DeviceReplyIter iter = deviceReplyMap.find(commandId);
if (iter != deviceReplyMap.end()) {
return iter->second.replyLen;
DeviceCommandId_t replyId = NO_COMMAND_ID;
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
if (command->second.useAlternativeReplyId) {
replyId = command->second.alternativeReplyId;
} else {
return 0;
replyId = commandId;
}
DeviceReplyIter iter = deviceReplyMap.find(replyId);
if (iter != deviceReplyMap.end()) {
if (iter->second.delayCycles != 0) {
return iter->second.replyLen;
}
}
return 0;
}
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
@@ -651,7 +671,9 @@ void DeviceHandlerBase::doGetWrite() {
// We need to distinguish here, because a raw command never expects a reply.
//(Could be done in eRIRM, but then child implementations need to be careful.
result = enableReplyInReplyMap(cookieInfo.pendingCommand);
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
result = enableReplyInReplyMap(command, 1, command->second.useAlternativeReplyId,
command->second.alternativeReplyId);
} else {
// always generate a failure event, so that FDIR knows what's up
triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first);
@@ -824,7 +846,7 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
}
ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t** data,
uint32_t* len) {
size_t* len) {
size_t lenTmp;
if (IPCStore == nullptr) {
@@ -1385,6 +1407,8 @@ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task) { executingTask = task;
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId,
uint32_t parameter) {}
Submode_t DeviceHandlerBase::getInitialSubmode() { return SUBMODE_NONE; }
void DeviceHandlerBase::performOperationHook() {}
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
@@ -1407,7 +1431,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
this->poolManager.initializeAfterTaskCreation();
if (setStartupImmediately) {
startTransition(MODE_ON, SUBMODE_NONE);
startTransition(MODE_ON, getInitialSubmode());
}
return HasReturnvaluesIF::RETURN_OK;
}
@@ -1491,3 +1515,11 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
}
return commandIter->second.sendReplyTo;
}
void DeviceHandlerBase::setCustomFdir(FailureIsolationBase* fdir) { this->fdirInstance = fdir; }
void DeviceHandlerBase::setParent(object_id_t parent) { this->parent = parent; }
void DeviceHandlerBase::setPowerSwitcher(PowerSwitchIF* switcher) {
this->powerSwitcher = switcher;
}

View File

@@ -103,6 +103,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie,
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
void setCustomFdir(FailureIsolationBase *fdir);
void setParent(object_id_t parent);
void setPowerSwitcher(PowerSwitchIF *switcher);
void setHkDestination(object_id_t hkDestination);
/**
@@ -478,7 +481,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @return - @c RETURN_OK when the command was successfully inserted,
* - @c RETURN_FAILED else.
*/
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand);
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand,
bool useAlternativeReply = false,
DeviceCommandId_t alternativeReplyId = 0);
/**
* Enables a periodic reply for a given command. It sets to delay cycles to the specified
@@ -647,6 +652,12 @@ class DeviceHandlerBase : public DeviceHandlerIF,
virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0,
uint32_t parameter = 0);
/**
* @brief Can be overwritten by a child to specify the initial submode when device has been set
* to startup immediately.
*/
virtual Submode_t getInitialSubmode();
protected:
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
@@ -673,7 +684,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! Pointer to the raw packet that will be sent.
uint8_t *rawPacket = nullptr;
//! Size of the #rawPacket.
uint32_t rawPacketLen = 0;
size_t rawPacketLen = 0;
/**
* The mode the device handler is currently in.
@@ -751,6 +762,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! if this is != NO_COMMANDER, DHB was commanded externally and shall
//! report everything to commander.
MessageQueueId_t sendReplyTo;
bool useAlternativeReplyId;
DeviceCommandId_t alternativeReplyId;
};
using DeviceCommandMap = std::map<DeviceCommandId_t, DeviceCommandInfo>;
/**
@@ -818,6 +831,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
/** Pointer to the used FDIR instance. If not provided by child,
* default class is instantiated. */
FailureIsolationBase *fdirInstance;
object_id_t parent = objects::NO_OBJECT;
//! To correctly delete the default instance.
bool defaultFDIRUsed;
@@ -1250,7 +1264,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* - @c RETURN_FAILED IPCStore is nullptr
* - the return value from the IPCStore if it was not @c RETURN_OK
*/
ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, uint32_t *len);
ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, size_t *len);
/**
* @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW, nothing else!

View File

@@ -29,6 +29,7 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
switch (event->getEvent()) {
case HasModesIF::MODE_TRANSITION_FAILED:
case HasModesIF::OBJECT_IN_INVALID_MODE:
case DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT:
// We'll try a recovery as long as defined in MAX_REBOOT.
// Might cause some AssemblyBase cycles, so keep number low.
handleRecovery(event->getEvent());

View File

@@ -109,6 +109,7 @@ class DeviceHandlerIF {
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW);
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
static const Event DEVICE_WANTS_HARD_REBOOT = MAKE_EVENT(11, severity::HIGH);
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;

View File

@@ -8,7 +8,9 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue
parentQueue(parentQueue),
commandQueue(),
healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(3);
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

@@ -7,8 +7,14 @@
// could be moved to more suitable location
#include <events/subsystemIdRanges.h>
typedef uint16_t EventId_t;
typedef uint8_t EventSeverity_t;
using EventId_t = uint16_t;
using EventSeverity_t = uint8_t;
using UniqueEventId_t = uint8_t;
namespace severity {
enum Severity : EventSeverity_t { INFO = 1, LOW = 2, MEDIUM = 3, HIGH = 4 };
} // namespace severity
#define MAKE_EVENT(id, severity) (((severity) << 16) + (SUBSYSTEM_ID * 100) + (id))
@@ -20,18 +26,11 @@ constexpr EventId_t getEventId(Event event) { return (event & 0xFFFF); }
constexpr EventSeverity_t getSeverity(Event event) { return ((event >> 16) & 0xFF); }
constexpr Event makeEvent(uint8_t subsystemId, uint8_t uniqueEventId,
constexpr Event makeEvent(uint8_t subsystemId, UniqueEventId_t uniqueEventId,
EventSeverity_t eventSeverity) {
return (eventSeverity << 16) + (subsystemId * 100) + uniqueEventId;
}
} // namespace event
namespace severity {
static constexpr EventSeverity_t INFO = 1;
static constexpr EventSeverity_t LOW = 2;
static constexpr EventSeverity_t MEDIUM = 3;
static constexpr EventSeverity_t HIGH = 4;
} // namespace severity
#endif /* EVENTOBJECT_EVENT_H_ */

View File

@@ -18,8 +18,9 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
EventManager::EventManager(object_id_t setObjectId)
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
mutex = MutexFactory::instance()->createMutex();
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
EventMessage::EVENT_MESSAGE_SIZE);
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
eventReportQueue = QueueFactory::instance()->createMessageQueue(
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
}
EventManager::~EventManager() {
@@ -46,9 +47,20 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
void EventManager::notifyListeners(EventMessage* message) {
lockMutex();
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
if (iter->second.match(message)) {
MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender());
for (auto& listener : listenerList) {
if (listener.second.match(message)) {
ReturnValue_t result =
MessageQueueSenderIF::sendMessage(listener.first, message, message->getSender());
if (result != HasReturnvaluesIF::RETURN_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;
#else
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
listener.first, result);
#endif
}
}
}
unlockMutex();
@@ -189,4 +201,19 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
}
}
void EventManager::printListeners() {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Event manager listener MQ IDs:" << std::setfill('0') << std::hex << std::endl;
for (auto& listener : listenerList) {
sif::info << "0x" << std::setw(8) << listener.first << std::endl;
}
sif::info << std::dec << std::setfill(' ');
#else
sif::printInfo("Event manager listener MQ IDs:\n");
for (auto& listener : listenerList) {
sif::printInfo("0x%08x\n", listener.first);
}
#endif
}
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */

View File

@@ -42,6 +42,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
bool reporterInverted = false);
ReturnValue_t performOperation(uint8_t opCode);
void printListeners();
protected:
MessageQueueIF* eventReportQueue = nullptr;

View File

@@ -9,8 +9,9 @@
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
uint8_t messageDepth, uint8_t parameterDomainBase)
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
eventQueue =
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE);
auto mqArgs = MqArgs(owner, static_cast<void*>(this));
eventQueue = QueueFactory::instance()->createMessageQueue(
messageDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
}
FailureIsolationBase::~FailureIsolationBase() {
@@ -51,11 +52,12 @@ ReturnValue_t FailureIsolationBase::initialize() {
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
if (parentIF == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FailureIsolationBase::intialize: Parent object"
<< "invalid." << std::endl;
#endif
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Make sure it implements ConfirmsFailuresIF." << std::endl;
sif::error << "FailureIsolationBase::intialize: Parent object "
<< "invalid" << std::endl;
sif::error << "Make sure it implements ConfirmsFailuresIF" << std::endl;
#else
sif::printError("FailureIsolationBase::intialize: Parent object invalid\n");
sif::printError("Make sure it implements ConfirmsFailuresIF\n");
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
return RETURN_FAILED;

View File

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

View File

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

View File

@@ -28,7 +28,7 @@ const uint16_t CRC::crc16ccitt_table[256] = {
// CRC implementation
uint16_t CRC::crc16ccitt(uint8_t const input[], uint32_t length, uint16_t startingCrc) {
uint8_t *data = (uint8_t *)input;
const uint8_t *data = static_cast<const uint8_t *>(input);
unsigned int tbl_idx;
while (length--) {
@@ -39,88 +39,4 @@ uint16_t CRC::crc16ccitt(uint8_t const input[], uint32_t length, uint16_t starti
}
return startingCrc & 0xffff;
// The part below is not used!
// bool temr[16];
// bool xor_out[16];
// bool r[16];
// bool d[8];
// uint16_t crc_value = 0;
//
//
// for (int i=0; i<16 ;i++) {
// temr[i] = false;
// xor_out[i] = false;
// }
//
//
// for (int i=0; i<16 ;i++)
// r[i] = true; // initialize with 0xFFFF
//
//
//
// for (int j=0; j<length ;j++)
// {
//
// for (int i=0; i<8 ;i++)
// if ((input[j] & 1<<i) == 1<<i)
// d[7-i]=true; // reverse input data
// else
// d[7-i]=false; // reverse input data
//
//
//
// temr[0] = d[4] ^ d[0];
// temr[1] = d[5] ^ d[1];
// temr[2] = d[6] ^ d[2];
// temr[3] = d[7] ^ d[3];
// temr[4] = r[12] ^ r[8];
// temr[5] = r[13] ^ r[9];
// temr[6] = r[14] ^ r[10];
// temr[7] = r[15] ^ r[11];
// temr[8] = d[4] ^ r[12];
// temr[9] = d[5] ^ r[13];
// temr[10] = d[6] ^ r[14];
// temr[11] = d[7] ^ r[15];
// temr[12] = temr[0] ^ temr[4];
// temr[13] = temr[1] ^ temr[5];
// temr[14] = temr[2] ^ temr[6];
// temr[15] = temr[3] ^ temr[7];
//
//
// xor_out[0] = temr[12];
// xor_out[1] = temr[13];
// xor_out[2] = temr[14];
// xor_out[3] = temr[15];
// xor_out[4] = temr[8];
// xor_out[5] = temr[9] ^ temr[12];
// xor_out[6] = temr[10] ^ temr[13];
// xor_out[7] = temr[11] ^ temr[14];
// xor_out[8] = temr[15] ^ r[0];
// xor_out[9] = temr[8] ^ r[1];
// xor_out[10] = temr[9] ^ r[2];
// xor_out[11] = temr[10] ^ r[3];
// xor_out[12] = temr[11] ^ temr[12] ^ r[4];
// xor_out[13] = temr[13] ^ r[5];
// xor_out[14] = temr[14] ^ r[6];
// xor_out[15] = temr[15] ^ r[7];
//
// for (int i=0; i<16 ;i++)
// {
// r[i]= xor_out[i] ;
// }
//
// }
//
//
//
// for (int i=0; i<16 ;i++)
// {
// if (xor_out[i] == true)
// crc_value = crc_value + pow(2,(15 -i)); // reverse CrC result before
//Final XOR
// }
//
// crc_value = 0;// for debug mode
// return (crc_value);
} /* Calculate_CRC() */

View File

@@ -0,0 +1,231 @@
#include "DleParser.h"
#include <fsfw/globalfunctions/DleEncoder.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <cstdio>
DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
BufPair decodedBuf, UserHandler handler, void* args)
: decodeRingBuf(decodeRingBuf),
decoder(decoder),
encodedBuf(encodedBuf),
decodedBuf(decodedBuf),
handler(handler),
ctx(args) {
if (handler == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DleParser::DleParser: Invalid user handler" << std::endl;
#else
sif::printError("DleParser::DleParser: Invalid user handler\n");
#endif
}
}
ReturnValue_t DleParser::passData(uint8_t* data, size_t len) {
if (data == nullptr or len == 0 or handler == nullptr) {
return RETURN_FAILED;
}
size_t copyIntoRingBufFromHere = 0;
size_t copyAmount = len;
size_t startIdx = 0;
ReturnValue_t result = RETURN_OK;
bool startFoundInThisPacket = false;
for (size_t idx = 0; idx < len; idx++) {
if (data[idx] == DleEncoder::STX_CHAR) {
if (not startFound and not startFoundInThisPacket) {
startIdx = idx;
copyIntoRingBufFromHere = idx;
copyAmount = len - idx;
} else {
// Maybe print warning, should not happen
decodeRingBuf.clear();
ErrorInfo info;
info.len = idx;
prepareErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info);
handler(ctx);
copyIntoRingBufFromHere = idx;
copyAmount = len - idx;
}
startFound = true;
startFoundInThisPacket = true;
} else if (data[idx] == DleEncoder::ETX_CHAR) {
if (startFoundInThisPacket) {
size_t readLen = 0;
size_t decodedLen = 0;
result = decoder.decode(data + startIdx, idx + 1 - startIdx, &readLen, decodedBuf.first,
decodedBuf.second, &decodedLen);
if (result == HasReturnvaluesIF::RETURN_OK) {
ctx.setType(ContextType::PACKET_FOUND);
ctx.decodedPacket.first = decodedBuf.first;
ctx.decodedPacket.second = decodedLen;
this->handler(ctx);
} else if (result == DleEncoder::STREAM_TOO_SHORT) {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
handler(ctx);
} else {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
handler(ctx);
}
decodeRingBuf.clear();
if ((idx + 1) < len) {
copyIntoRingBufFromHere = idx + 1;
copyAmount = len - idx - 1;
} else {
copyAmount = 0;
}
} else if (startFound) {
// ETX found but STX was found in another mini packet. Reconstruct the full packet
// to decode it
result = decodeRingBuf.writeData(data, idx + 1);
if (result != HasReturnvaluesIF::RETURN_OK) {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
handler(ctx);
}
size_t fullEncodedLen = decodeRingBuf.getAvailableReadData();
if (fullEncodedLen > encodedBuf.second) {
ErrorInfo info;
info.len = fullEncodedLen;
prepareErrorContext(ErrorTypes::ENCODED_BUF_TOO_SMALL, info);
handler(ctx);
decodeRingBuf.clear();
} else {
size_t decodedLen = 0;
size_t readLen = 0;
decodeRingBuf.readData(encodedBuf.first, fullEncodedLen, true);
result = decoder.decode(encodedBuf.first, fullEncodedLen, &readLen, decodedBuf.first,
decodedBuf.second, &decodedLen);
if (result == HasReturnvaluesIF::RETURN_OK) {
if (this->handler != nullptr) {
ctx.setType(ContextType::PACKET_FOUND);
ctx.decodedPacket.first = decodedBuf.first;
ctx.decodedPacket.second = decodedLen;
this->handler(ctx);
}
} else if (result == DleEncoder::STREAM_TOO_SHORT) {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
handler(ctx);
} else {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::DECODE_ERROR, info);
handler(ctx);
}
decodeRingBuf.clear();
startFound = false;
startFoundInThisPacket = false;
if ((idx + 1) < len) {
copyIntoRingBufFromHere = idx + 1;
copyAmount = len - idx - 1;
} else {
copyAmount = 0;
}
}
} else {
// End data without preceeding STX
ErrorInfo info;
info.len = idx + 1;
prepareErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info);
handler(ctx);
decodeRingBuf.clear();
if ((idx + 1) < len) {
copyIntoRingBufFromHere = idx + 1;
copyAmount = len - idx - 1;
} else {
copyAmount = 0;
}
}
startFoundInThisPacket = false;
startFound = false;
}
}
if (copyAmount > 0) {
result = decodeRingBuf.writeData(data + copyIntoRingBufFromHere, copyAmount);
if (result != HasReturnvaluesIF::RETURN_OK) {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
handler(ctx);
}
}
return RETURN_OK;
}
void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "DleParserBase::handleFoundPacket: Detected DLE packet with " << len << " bytes"
<< std::endl;
#else
sif::printInfo("DleParserBase::handleFoundPacket: Detected DLE packet with %d bytes\n", len);
#endif
#endif
}
void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) {
switch (err) {
case (ErrorTypes::NONE): {
errorPrinter("No error");
break;
}
case (ErrorTypes::DECODE_ERROR): {
errorPrinter("Decode Error");
break;
}
case (ErrorTypes::RING_BUF_ERROR): {
errorPrinter("Ring Buffer Error");
break;
}
case (ErrorTypes::ENCODED_BUF_TOO_SMALL):
case (ErrorTypes::DECODING_BUF_TOO_SMALL): {
char opt[64];
snprintf(opt, sizeof(opt), ": Too small for packet with length %d", ctx.len);
if (err == ErrorTypes::ENCODED_BUF_TOO_SMALL) {
errorPrinter("Encoded buf too small", opt);
} else {
errorPrinter("Decoding buf too small", opt);
}
break;
}
case (ErrorTypes::CONSECUTIVE_STX_CHARS): {
errorPrinter("Consecutive STX chars detected");
break;
}
case (ErrorTypes::CONSECUTIVE_ETX_CHARS): {
errorPrinter("Consecutive ETX chars detected");
break;
}
}
}
void DleParser::errorPrinter(const char* str, const char* opt) {
if (opt == nullptr) {
opt = "";
}
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "DleParserBase::handleParseError: " << str << opt << std::endl;
#else
sif::printInfo("DleParserBase::handleParseError: %s%s\n", str, opt);
#endif
#endif
}
void DleParser::prepareErrorContext(ErrorTypes err, ErrorInfo info) {
ctx.setType(ContextType::ERROR);
ctx.error.first = err;
ctx.error.second = info;
}
void DleParser::reset() {
startFound = false;
decodeRingBuf.clear();
}

View File

@@ -0,0 +1,127 @@
#ifndef MISSION_DEVICES_DLEPARSER_H_
#define MISSION_DEVICES_DLEPARSER_H_
#include <fsfw/container/SimpleRingBuffer.h>
#include <fsfw/globalfunctions/DleEncoder.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <cstddef>
#include <utility>
/**
* @brief This base helper class can be used to extract DLE encoded packets from a data stream
* @details
* The core API of the parser takes received packets which can contains DLE packets. The parser
* can deal with DLE packets split across multiple packets. It does so by using a dedicated
* decoding ring buffer. The user can process received packets and detect errors by
* overriding two provided virtual methods. This also allows detecting multiple DLE packets
* inside one passed packet.
*/
class DleParser : public HasReturnvaluesIF {
public:
using BufPair = std::pair<uint8_t*, size_t>;
enum class ContextType { PACKET_FOUND, ERROR };
enum class ErrorTypes {
NONE,
ENCODED_BUF_TOO_SMALL,
DECODING_BUF_TOO_SMALL,
DECODE_ERROR,
RING_BUF_ERROR,
CONSECUTIVE_STX_CHARS,
CONSECUTIVE_ETX_CHARS
};
union ErrorInfo {
size_t len;
ReturnValue_t res;
};
using ErrorPair = std::pair<ErrorTypes, ErrorInfo>;
struct Context {
public:
Context(void* args) : userArgs(args) { setType(ContextType::PACKET_FOUND); }
void setType(ContextType type) {
if (type == ContextType::PACKET_FOUND) {
error.first = ErrorTypes::NONE;
error.second.len = 0;
} else {
decodedPacket.first = nullptr;
decodedPacket.second = 0;
}
}
ContextType getType() const { return type; }
BufPair decodedPacket = {};
ErrorPair error;
void* userArgs;
private:
ContextType type;
};
using UserHandler = void (*)(const Context& ctx);
/**
* Base class constructor
* @param decodeRingBuf Ring buffer used to store multiple packets to allow detecting DLE packets
* split across multiple packets
* @param decoder Decoder instance
* @param encodedBuf Buffer used to store encoded packets. It has to be large enough to hold
* the largest expected encoded DLE packet size
* @param decodedBuf Buffer used to store decoded packets. It has to be large enough to hold the
* largest expected decoded DLE packet size
* @param handler Function which will be called on a found packet
* @param args Arbitrary user argument
*/
DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
BufPair decodedBuf, UserHandler handler, void* args);
/**
* This function allows to pass new data into the parser. It then scans for DLE packets
* automatically and inserts (part of) the packet into a ring buffer if necessary.
* @param data
* @param len
* @return
*/
ReturnValue_t passData(uint8_t* data, size_t len);
/**
* Example found packet handler
* function call
* @param packet Decoded packet
* @param len Length of detected packet
*/
void defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args);
/**
* Will be called if an error occured in the #passData call
* @param err
* @param ctx Context information depending on the error type
* - For buffer length errors, will be set to the detected packet length which is too large
* - For decode or ring buffer errors, will be set to the result returned from the failed call
*/
static void defaultErrorHandler(ErrorTypes err, ErrorInfo ctx);
static void errorPrinter(const char* str, const char* opt = nullptr);
void prepareErrorContext(ErrorTypes err, ErrorInfo ctx);
/**
* Resets the parser by resetting the internal states and clearing the decoding ring buffer
*/
void reset();
private:
SimpleRingBuffer& decodeRingBuf;
DleEncoder& decoder;
BufPair encodedBuf;
BufPair decodedBuf;
UserHandler handler = nullptr;
Context ctx;
bool startFound = false;
};
#endif /* MISSION_DEVICES_DLEPARSER_H_ */

View File

@@ -1,6 +1,7 @@
#include "fsfw/globalfunctions/arrayprinter.h"
#include <bitset>
#include <cmath>
#include "fsfw/serviceinterface/ServiceInterface.h"
@@ -68,7 +69,7 @@ void arrayprinter::printHex(const uint8_t *data, size_t size, size_t maxCharPerL
currentPos += snprintf(printBuffer + currentPos, 6, "%02x", data[i]);
if (i < size - 1) {
currentPos += sprintf(printBuffer + currentPos, ",");
if (i > 0 and (i + 1) % maxCharPerLine == 0) {
if ((i + 1) % maxCharPerLine == 0) {
currentPos += sprintf(printBuffer + currentPos, "\n");
}
}
@@ -97,20 +98,21 @@ void arrayprinter::printDec(const uint8_t *data, size_t size, size_t maxCharPerL
}
std::cout << "]" << std::endl;
#else
// General format: 32, 243, -12 so it is number of chars times 5
// General format: 32,243,-12 so it is number of chars times 4
// plus line break plus small safety margin.
char printBuffer[(size + 1) * 5 + 1] = {};
uint16_t expectedLines = ceil((double)size / maxCharPerLine);
char printBuffer[size * 4 + 1 + expectedLines] = {};
size_t currentPos = 0;
for (size_t i = 0; i < size; i++) {
// To avoid buffer overflows.
if (sizeof(printBuffer) - currentPos <= 5) {
if (sizeof(printBuffer) - currentPos <= 4) {
break;
}
currentPos += snprintf(printBuffer + currentPos, 3, "%d", data[i]);
currentPos += snprintf(printBuffer + currentPos, 4, "%d", data[i]);
if (i < size - 1) {
currentPos += sprintf(printBuffer + currentPos, ",");
if (i > 0 and (i + 1) % maxCharPerLine == 0) {
if ((i + 1) % maxCharPerLine == 0) {
currentPos += sprintf(printBuffer + currentPos, "\n");
}
}

View File

@@ -179,6 +179,9 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
virtual ReturnValue_t cleanUpElement(iterator position) { return HasReturnvaluesIF::RETURN_OK; }
bool matchSubtree(iterator iter, T number) {
if(iter == nullptr) {
return false;
}
bool isMatch = iter->match(number);
if (isMatch) {
if (iter.left() == this->end()) {

View File

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

View File

@@ -7,11 +7,13 @@
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
: SystemObject(setObjectId),
commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
@@ -36,15 +38,14 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "InternalErrorReporter::performOperation: Errors "
<< "occured!" << std::endl;
sif::debug << "Queue errors: " << newQueueHits << std::endl;
sif::debug << "TM errors: " << newTmHits << std::endl;
sif::debug << "Store errors: " << newStoreHits << std::endl;
<< "occured: Queue | TM | Store : " << newQueueHits << " | " << newTmHits << " | "
<< newStoreHits << std::endl;
#else
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n");
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits));
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits));
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits));
sif::printDebug(
"InternalErrorReporter::performOperation: Errors occured: Queue | TM | Store: %lu | %lu "
"| %lu\n",
static_cast<unsigned int>(newQueueHits), static_cast<unsigned int>(newTmHits),
static_cast<unsigned int>(newStoreHits));
#endif
}
}
@@ -57,6 +58,9 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
internalErrorDataset.storeHits.value += newStoreHits;
internalErrorDataset.tmHits.value += newTmHits;
internalErrorDataset.setValidity(true, true);
if ((newQueueHits != 0) or (newStoreHits != 0) or (newTmHits != 0)) {
internalErrorDataset.setChanged(true);
}
}
}
@@ -77,14 +81,6 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() {
return value;
}
uint32_t InternalErrorReporter::getQueueHits() {
uint32_t value;
mutex->lockMutex(timeoutType, timeoutMs);
value = queueHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementQueueHits() {
mutex->lockMutex(timeoutType, timeoutMs);
queueHits++;
@@ -100,14 +96,6 @@ uint32_t InternalErrorReporter::getAndResetTmHits() {
return value;
}
uint32_t InternalErrorReporter::getTmHits() {
uint32_t value;
mutex->lockMutex(timeoutType, timeoutMs);
value = tmHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementTmHits() {
mutex->lockMutex(timeoutType, timeoutMs);
tmHits++;
@@ -125,14 +113,6 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() {
return value;
}
uint32_t InternalErrorReporter::getStoreHits() {
uint32_t value;
mutex->lockMutex(timeoutType, timeoutMs);
value = storeHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementStoreHits() {
mutex->lockMutex(timeoutType, timeoutMs);
storeHits++;

View File

@@ -46,11 +46,11 @@ class InternalErrorReporter : public SystemObject,
virtual ReturnValue_t initializeAfterTaskCreation() override;
virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual void queueMessageNotSent();
virtual void queueMessageNotSent() override;
virtual void lostTm();
virtual void lostTm() override;
virtual void storeFull();
virtual void storeFull() override;
virtual void setTaskIF(PeriodicTaskIF* task) override;
@@ -74,15 +74,12 @@ class InternalErrorReporter : public SystemObject,
uint32_t storeHits = 0;
uint32_t getAndResetQueueHits();
uint32_t getQueueHits();
void incrementQueueHits();
uint32_t getAndResetTmHits();
uint32_t getTmHits();
void incrementTmHits();
uint32_t getAndResetStoreHits();
uint32_t getStoreHits();
void incrementStoreHits();
};

View File

@@ -1,22 +1,34 @@
#ifndef INTERNALERRORREPORTERIF_H_
#define INTERNALERRORREPORTERIF_H_
/**
* @brief Interface which is used to report internal errors like full message queues or stores.
* @details
* This interface smust be used for the InteralErrorReporter object.
* It should be used to indicate that there was a Problem with Queues or Stores.
*
* It can be used to report missing Telemetry which could not be sent due to a internal problem.
*
*/
class InternalErrorReporterIF {
public:
virtual ~InternalErrorReporterIF() {}
/**
* Thread safe
* @brief Function to be called if a message queue could not be sent.
* @details OSAL Implementations should call this function to indicate that
* a message was lost.
*
* Implementations are required to be Thread safe
*/
virtual void queueMessageNotSent() = 0;
/**
* Thread safe
* @brief Function to be called if Telemetry could not be sent
* @details Implementations must be Thread safe
*/
virtual void lostTm() = 0;
/**
* Thread safe
* @brief Function to be called if a onboard storage is full
* @details Implementations must be Thread safe
*/
virtual void storeFull() = 0;
};

View File

@@ -1,6 +1,6 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
CommandMessage.cpp
CommandMessageCleaner.cpp
MessageQueueMessage.cpp
target_sources(${LIB_FSFW_NAME} PRIVATE
CommandMessage.cpp
CommandMessageCleaner.cpp
MessageQueueMessage.cpp
MessageQueueBase.cpp
)

View File

@@ -0,0 +1,64 @@
#include "MessageQueueBase.h"
MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest,
MqArgs* args): id(id) {
this->defaultDest = defaultDest;
if(args != nullptr) {
this->args = *args;
}
}
MessageQueueBase::~MessageQueueBase() {}
ReturnValue_t MessageQueueBase::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId(), false);
}
ReturnValue_t MessageQueueBase::reply(MessageQueueMessageIF* message) {
if (this->last != MessageQueueIF::NO_QUEUE) {
return sendMessageFrom(this->last, message, this->getId());
} else {
return NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueueBase::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->last;
return status;
}
MessageQueueId_t MessageQueueBase::getLastPartner() const {
return last;
}
MessageQueueId_t MessageQueueBase::getId() const {
return id;
}
MqArgs& MessageQueueBase::getMqArgs() {
return args;
}
void MessageQueueBase::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDest = defaultDestination;
}
MessageQueueId_t MessageQueueBase::getDefaultDestination() const {
return defaultDest;
}
bool MessageQueueBase::isDefaultDestinationSet() const {
return (defaultDest != NO_QUEUE);
}
ReturnValue_t MessageQueueBase::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), false);
}
ReturnValue_t MessageQueueBase::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDest, message, sentFrom, ignoreFault);
}

View File

@@ -0,0 +1,41 @@
#ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
#define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
#include <fsfw/ipc/definitions.h>
#include <fsfw/ipc/MessageQueueIF.h>
class MessageQueueBase: public MessageQueueIF {
public:
MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs);
virtual ~MessageQueueBase();
// Default implementations for MessageQueueIF where possible
virtual MessageQueueId_t getLastPartner() const override;
virtual MessageQueueId_t getId() const override;
virtual MqArgs& getMqArgs() override;
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) override;
virtual MessageQueueId_t getDefaultDestination() const override;
virtual bool isDefaultDestinationSet() const override;
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) override;
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) override;
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) override;
// OSAL specific, forward the abstract function
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
protected:
MessageQueueId_t id = MessageQueueIF::NO_QUEUE;
MessageQueueId_t last = MessageQueueIF::NO_QUEUE;
MessageQueueId_t defaultDest = MessageQueueIF::NO_QUEUE;
MqArgs args = {};
};
#endif /* FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ */

View File

@@ -1,6 +1,7 @@
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
#define FSFW_IPC_MESSAGEQUEUEIF_H_
#include <fsfw/ipc/definitions.h>
#include <cstdint>
#include "../returnvalues/HasReturnvaluesIF.h"
@@ -44,8 +45,7 @@ class MessageQueueIF {
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
/**
* @brief This function reads available messages from the message queue
* and returns the sender.
* @brief This function reads available messages from the message queue and returns the sender.
* @details
* It works identically to the other receiveMessage call, but in addition
* returns the sender's queue id.
@@ -78,19 +78,16 @@ class MessageQueueIF {
*/
virtual ReturnValue_t flush(uint32_t* count) = 0;
/**
* @brief This method returns the message queue
* id of the last communication partner.
* @brief This method returns the message queue ID of the last communication partner.
*/
virtual MessageQueueId_t getLastPartner() const = 0;
/**
* @brief This method returns the message queue
* id of this class's message queue.
* @brief This method returns the message queue ID of this class's message queue.
*/
virtual MessageQueueId_t getId() const = 0;
/**
* @brief With the sendMessage call, a queue message
* is sent to a receiving queue.
* @brief With the sendMessage call, a queue message is sent to a receiving queue.
* @details
* This method takes the message provided, adds the sentFrom information
* and passes it on to the destination provided with an operating system
@@ -129,8 +126,7 @@ class MessageQueueIF {
bool ignoreFault = false) = 0;
/**
* @brief The sendToDefaultFrom method sends a queue message
* to the default destination.
* @brief The sendToDefaultFrom method sends a queue message to the default destination.
* @details
* In all other aspects, it works identical to the sendMessage method.
* @param message
@@ -164,6 +160,8 @@ class MessageQueueIF {
virtual MessageQueueId_t getDefaultDestination() const = 0;
virtual bool isDefaultDestinationSet() const = 0;
virtual MqArgs& getMqArgs() = 0;
};
#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */

View File

@@ -5,6 +5,7 @@
#include "MessageQueueIF.h"
#include "MessageQueueMessage.h"
#include "definitions.h"
/**
* Creates message queues.
@@ -22,7 +23,8 @@ class QueueFactory {
static QueueFactory* instance();
MessageQueueIF* createMessageQueue(uint32_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
void deleteMessageQueue(MessageQueueIF* queue);

View File

@@ -0,0 +1,14 @@
#ifndef FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
#define FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
#include <fsfw/objectmanager/SystemObjectIF.h>
#include <fsfw/objectmanager/frameworkObjects.h>
struct MqArgs {
MqArgs(){};
MqArgs(object_id_t objectId, void* args = nullptr) : objectId(objectId), args(args) {}
object_id_t objectId = objects::NO_OBJECT;
void* args = nullptr;
};
#endif /* FSFW_SRC_FSFW_IPC_DEFINITIONS_H_ */

View File

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

View File

@@ -95,13 +95,16 @@ void ObjectManager::initialize() {
for (auto const& it : objectList) {
result = it.second->initialize();
if (result != RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
object_id_t var = it.first;
sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8)
<< std::setfill('0') << var
<< " failed to "
"initialize with code 0x"
<< result << std::dec << std::setfill(' ') << std::endl;
<< std::setfill('0') << it.first << " failed to initialize with code 0x" << result
<< std::dec << std::setfill(' ') << std::endl;
#else
sif::printError(
"ObjectManager::initialize: Object 0x%08x failed to initialize with code 0x%04x\n", var,
it.first);
#endif
#endif
errorCount++;
}

View File

@@ -4,8 +4,9 @@
#include "fsfw/osal/freertos/QueueMapManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
: maxMessageSize(maxMessageSize) {
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
maxMessageSize(maxMessageSize) {
handle = xQueueCreate(messageDepth, maxMessageSize);
if (handle == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -15,10 +16,10 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
#else
sif::printError("MessageQueue::MessageQueue: Creation failed\n");
sif::printError("Specified Message Depth: %d\n", messageDepth);
sif::printError("Specified MAximum Message Size: %d\n", maxMessageSize);
sif::printError("Specified Maximum Message Size: %d\n", maxMessageSize);
#endif
}
QueueMapManager::instance()->addMessageQueue(handle, &queueId);
QueueMapManager::instance()->addMessageQueue(handle, &id);
}
MessageQueue::~MessageQueue() {
@@ -29,28 +30,6 @@ MessageQueue::~MessageQueue() {
void MessageQueue::switchSystemContext(CallContext callContext) { this->callContext = callContext; }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId());
}
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
}
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != MessageQueueIF::NO_QUEUE) {
return sendMessageFrom(this->lastPartner, message, this->getId());
} else {
return NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault, callContext);
@@ -72,27 +51,16 @@ ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
if (status == HasReturnvaluesIF::RETURN_OK) {
*receivedFrom = this->lastPartner;
}
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
BaseType_t result = xQueueReceive(handle, reinterpret_cast<void*>(message->getBuffer()), 0);
if (result == pdPASS) {
this->lastPartner = message->getSender();
this->last = message->getSender();
return HasReturnvaluesIF::RETURN_OK;
} else {
return MessageQueueIF::EMPTY;
}
}
MessageQueueId_t MessageQueue::getLastPartner() const { return lastPartner; }
ReturnValue_t MessageQueue::flush(uint32_t* count) {
// TODO FreeRTOS does not support flushing partially
// Is always successful
@@ -100,17 +68,6 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getId() const { return queueId; }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
defaultDestinationSet = true;
this->defaultDestination = defaultDestination;
}
MessageQueueId_t MessageQueue::getDefaultDestination() const { return defaultDestination; }
bool MessageQueue::isDefaultDestinationSet() const { return defaultDestinationSet; }
// static core function to send messages.
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message,

View File

@@ -1,12 +1,14 @@
#ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
#include <fsfw/ipc/MessageQueueBase.h>
#include "FreeRTOS.h"
#include "TaskManagement.h"
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/MessageQueueMessageIF.h"
#include "fsfw/ipc/definitions.h"
#include "queue.h"
/**
@@ -32,7 +34,7 @@
* @ingroup osal
* @ingroup message_queue
*/
class MessageQueue : public MessageQueueIF {
class MessageQueue : public MessageQueueBase {
friend class MessageQueueSenderIF;
public:
@@ -53,7 +55,8 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(size_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete;
@@ -73,40 +76,15 @@ class MessageQueue : public MessageQueueIF {
*/
void switchSystemContext(CallContext callContext);
/** MessageQueueIF implementation */
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault = false) override;
QueueHandle_t getNativeQueueHandle();
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
ReturnValue_t reply(MessageQueueMessageIF* message) override;
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false) override;
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false) override;
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) override;
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
ReturnValue_t flush(uint32_t* count) override;
MessageQueueId_t getLastPartner() const override;
MessageQueueId_t getId() const override;
void setDefaultDestination(MessageQueueId_t defaultDestination) override;
MessageQueueId_t getDefaultDestination() const override;
bool isDefaultDestinationSet() const override;
QueueHandle_t getNativeQueueHandle();
protected:
/**
* @brief Implementation to be called from any send Call within
@@ -136,12 +114,8 @@ class MessageQueue : public MessageQueueIF {
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
private:
bool defaultDestinationSet = false;
QueueHandle_t handle;
MessageQueueId_t queueId = MessageQueueIF::NO_QUEUE;
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
const size_t maxMessageSize;
//! Stores the current system context
CallContext callContext = CallContext::TASK;

View File

@@ -97,7 +97,11 @@ void PeriodicTask::taskFunctionality() {
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
if (newObject == nullptr) {
return addComponent(newObject);
}
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
if (object == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
"it implement ExecutableObjectIF"
@@ -105,8 +109,8 @@ ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
objectList.push_back(newObject);
newObject->setTaskIF(this);
objectList.push_back(object);
object->setTaskIF(this);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@@ -63,6 +63,16 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
*/
ReturnValue_t addComponent(object_id_t object) override;
/**
* Adds an object to the list of objects to be executed.
* The objects are executed in the order added.
* @param object Id of the object to add.
* @return
* -@c RETURN_OK on success
* -@c RETURN_FAILED if the object could not be added.
*/
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
uint32_t getPeriodMs() const override;
ReturnValue_t sleepFor(uint32_t ms) override;

View File

@@ -22,8 +22,9 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
return new MessageQueue(messageDepth, maxMessageSize);
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@@ -150,17 +150,14 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval*
time_tm.tm_hour = from->hour;
time_tm.tm_min = from->minute;
time_tm.tm_sec = from->second;
time_tm.tm_isdst = 0;
time_t seconds = mktime(&time_tm);
time_t seconds = timegm(&time_tm);
to->tv_sec = seconds;
to->tv_usec = from->usecond;
// Fails in 2038..
return HasReturnvaluesIF::RETURN_OK;
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl;
#endif
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {

View File

@@ -8,10 +8,12 @@
#include "fsfw/osal/host/QueueMapManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
: messageSize(maxMessageSize), messageDepth(messageDepth) {
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
messageSize(maxMessageSize),
messageDepth(messageDepth) {
queueLock = MutexFactory::instance()->createMutex();
auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId);
auto result = QueueMapManager::instance()->addMessageQueue(this, &id);
if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::MessageQueue: Could not be created" << std::endl;
@@ -23,42 +25,11 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
MessageQueue::~MessageQueue() { MutexFactory::instance()->deleteMutex(queueLock); }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId());
}
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
}
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != MessageQueueIF::NO_QUEUE) {
return sendMessageFrom(this->lastPartner, message, this->getId());
} else {
return MessageQueueIF::NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault);
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
if (status == HasReturnvaluesIF::RETURN_OK) {
*receivedFrom = this->lastPartner;
}
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
if (messageQueue.empty()) {
return MessageQueueIF::EMPTY;
@@ -68,12 +39,10 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
message->getBuffer());
messageQueue.pop();
// The last partner is the first uint32_t field in the message
this->lastPartner = message->getSender();
this->last = message->getSender();
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getLastPartner() const { return lastPartner; }
ReturnValue_t MessageQueue::flush(uint32_t* count) {
*count = messageQueue.size();
// Clears the queue.
@@ -81,17 +50,6 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getId() const { return mqId; }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
defaultDestinationSet = true;
this->defaultDestination = defaultDestination;
}
MessageQueueId_t MessageQueue::getDefaultDestination() const { return defaultDestination; }
bool MessageQueue::isDefaultDestinationSet() const { return defaultDestinationSet; }
// static core function to send messages.
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message,
@@ -125,6 +83,13 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
memcpy(targetQueue->messageQueue.back().data(), message->getBuffer(),
message->getMaximumMessageSize());
} else {
if (not ignoreFault) {
InternalErrorReporterIF* internalErrorReporter =
ObjectManager::instance()->get<InternalErrorReporterIF>(objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != nullptr) {
internalErrorReporter->queueMessageNotSent();
}
}
return MessageQueueIF::FULL;
}
return HasReturnvaluesIF::RETURN_OK;

View File

@@ -1,15 +1,17 @@
#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
#include <memory>
#include <queue>
#include "fsfw/ipc/MessageQueueBase.h"
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/ipc/definitions.h"
#include "fsfw/timemanager/Clock.h"
#include <memory>
#include <queue>
/**
* @brief This class manages sending and receiving of
* message queue messages.
@@ -33,7 +35,7 @@
* @ingroup osal
* @ingroup message_queue
*/
class MessageQueue : public MessageQueueIF {
class MessageQueue : public MessageQueueBase {
friend class MessageQueueSenderIF;
public:
@@ -54,7 +56,8 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(size_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete;
@@ -67,121 +70,12 @@ class MessageQueue : public MessageQueueIF {
*/
virtual ~MessageQueue();
/**
* @brief This operation sends a message to the given destination.
* @details It directly uses the sendMessage call of the MessageQueueSender
* parent, but passes its queue id as "sentFrom" parameter.
* @param sendTo This parameter specifies the message queue id of the
* destination message queue.
* @param message A pointer to a previously created message, which is sent.
* @param ignoreFault If set to true, the internal software fault counter
* is not incremented if queue is full.
*/
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault = false) override;
/**
* @brief This operation sends a message to the default destination.
* @details As in the sendMessage method, this function uses the
* sendToDefault call of the MessageQueueSender parent class and adds its
* queue id as "sentFrom" information.
* @param message A pointer to a previously created message, which is sent.
*/
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
/**
* @brief This operation sends a message to the last communication partner.
* @details This operation simplifies answering an incoming message by using
* the stored lastPartner information as destination. If there was no
* message received yet (i.e. lastPartner is zero), an error code is returned.
* @param message A pointer to a previously created message, which is sent.
*/
ReturnValue_t reply(MessageQueueMessageIF* message) override;
/**
* @brief With the sendMessage call, a queue message is sent to a
* receiving queue.
* @details
* This method takes the message provided, adds the sentFrom information and
* passes it on to the destination provided with an operating system call.
* The OS's return value is returned.
* @param sendTo This parameter specifies the message queue id to send
* the message to.
* @param message This is a pointer to a previously created message,
* which is sent.
* @param sentFrom The sentFrom information can be set to inject the
* sender's queue id into the message. This variable is set to zero by
* default.
* @param ignoreFault If set to true, the internal software fault counter
* is not incremented if queue is full.
*/
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false) override;
/**
* @brief The sendToDefault method sends a queue message to the default
* destination.
* @details
* In all other aspects, it works identical to the sendMessage method.
* @param message This is a pointer to a previously created message,
* which is sent.
* @param sentFrom The sentFrom information can be set to inject the
* sender's queue id into the message. This variable is set to zero by
* default.
*/
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false) override;
/**
* @brief This function reads available messages from the message queue
* and returns the sender.
* @details
* It works identically to the other receiveMessage call, but in addition
* returns the sender's queue id.
* @param message A pointer to a message in which the received data is stored.
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
*/
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) override;
/**
* @brief This function reads available messages from the message queue.
* @details
* If data is available it is stored in the passed message pointer.
* The message's original content is overwritten and the sendFrom
* information is stored in the lastPartner attribute. Else, the lastPartner
* information remains untouched, the message's content is cleared and the
* function returns immediately.
* @param message A pointer to a message in which the received data is stored.
*/
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
/**
* Deletes all pending messages in the queue.
* @param count The number of flushed messages.
* @return RETURN_OK on success.
*/
ReturnValue_t flush(uint32_t* count) override;
/**
* @brief This method returns the message queue id of the last
* communication partner.
*/
MessageQueueId_t getLastPartner() const override;
/**
* @brief This method returns the message queue id of this class's
* message queue.
*/
MessageQueueId_t getId() const override;
/**
* @brief This method is a simple setter for the default destination.
*/
void setDefaultDestination(MessageQueueId_t defaultDestination) override;
/**
* @brief This method is a simple getter for the default destination.
*/
MessageQueueId_t getDefaultDestination() const override;
bool isDefaultDestinationSet() const override;
ReturnValue_t lockQueue(MutexIF::TimeoutType timeoutType, dur_millis_t lockTimeout);
ReturnValue_t unlockQueue();
@@ -211,23 +105,14 @@ class MessageQueue : public MessageQueueIF {
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false);
// static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
private:
std::queue<std::vector<uint8_t>> messageQueue;
/**
* @brief The class stores the queue id it got assigned.
* If initialization fails, the queue id is set to zero.
*/
MessageQueueId_t mqId = MessageQueueIF::NO_QUEUE;
size_t messageSize = 0;
size_t messageDepth = 0;
MutexIF* queueLock;
bool defaultDestinationSet = false;
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
};
#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */

View File

@@ -102,11 +102,15 @@ void PeriodicTask::taskFunctionality() {
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
if (newObject == nullptr) {
return addComponent(newObject);
}
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
if (object == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
newObject->setTaskIF(this);
objectList.push_back(newObject);
object->setTaskIF(this);
objectList.push_back(object);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@@ -59,6 +59,16 @@ class PeriodicTask : public PeriodicTaskIF {
*/
ReturnValue_t addComponent(object_id_t object);
/**
* Adds an object to the list of objects to be executed.
* The objects are executed in the order added.
* @param object pointer to the object to add.
* @return
* -@c RETURN_OK on success
* -@c RETURN_FAILED if the object could not be added.
*/
ReturnValue_t addComponent(ExecutableObjectIF* object);
uint32_t getPeriodMs() const;
ReturnValue_t sleepFor(uint32_t ms);

View File

@@ -27,12 +27,13 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
// A thread-safe queue can be implemented by using a combination
// of std::queue and std::mutex. This uses dynamic memory allocation
// which could be alleviated by using a custom allocator, external library
// (etl::queue) or simply using std::queue, we're on a host machine anyway.
return new MessageQueue(messageDepth, maxMessageSize);
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@@ -1,6 +1,7 @@
#include "fsfw/osal/linux/BinarySemaphore.h"
#include <errno.h>
#include <stdio.h>
#include <time.h>
#include <cstring>

View File

@@ -1,29 +1,29 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
Clock.cpp
BinarySemaphore.cpp
CountingSemaphore.cpp
FixedTimeslotTask.cpp
InternalErrorCodes.cpp
MessageQueue.cpp
Mutex.cpp
MutexFactory.cpp
PeriodicPosixTask.cpp
PosixThread.cpp
QueueFactory.cpp
SemaphoreFactory.cpp
TaskFactory.cpp
tcpipHelpers.cpp
unixUtility.cpp
BinarySemaphore.cpp
CountingSemaphore.cpp
FixedTimeslotTask.cpp
InternalErrorCodes.cpp
MessageQueue.cpp
Mutex.cpp
MutexFactory.cpp
PeriodicPosixTask.cpp
PosixThread.cpp
QueueFactory.cpp
SemaphoreFactory.cpp
TaskFactory.cpp
tcpipHelpers.cpp
unixUtility.cpp
)
find_package(Threads REQUIRED)
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
${CMAKE_THREAD_LIBS_INIT}
rt
${CMAKE_THREAD_LIBS_INIT}
rt
)
target_link_libraries(${LIB_FSFW_NAME} INTERFACE
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_THREAD_LIBS_INIT}
)

View File

@@ -1,4 +1,5 @@
#include "fsfw/timemanager/Clock.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include <linux/sysinfo.h>
#include <sys/sysinfo.h>
@@ -7,12 +8,13 @@
#include <unistd.h>
#include <fstream>
#include "fsfw/serviceinterface/ServiceInterface.h"
#include <cstring>
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
void handleClockError(const char* func);
uint32_t Clock::getTicksPerSecond(void) {
uint32_t ticks = sysconf(_SC_CLK_TCK);
return ticks;
@@ -27,7 +29,7 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
// TODO errno
handleClockError("setClock");
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
@@ -39,7 +41,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
timeUnix.tv_nsec = (__syscall_slong_t)time->tv_usec * 1000;
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
// TODO errno
handleClockError("setClock");
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
@@ -49,6 +51,7 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
timespec timeUnix;
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
handleClockError("getClock_timeval");
return HasReturnvaluesIF::RETURN_FAILED;
}
time->tv_sec = timeUnix.tv_sec;
@@ -140,8 +143,9 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval*
fromTm.tm_hour = from->hour;
fromTm.tm_min = from->minute;
fromTm.tm_sec = from->second;
fromTm.tm_isdst = 0;
to->tv_sec = mktime(&fromTm);
to->tv_sec = timegm(&fromTm);
to->tv_usec = from->usecond;
return HasReturnvaluesIF::RETURN_OK;
}
@@ -150,3 +154,15 @@ ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return HasReturnvaluesIF::RETURN_OK;
}
void handleClockError(const char* func) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::" << func << ": Failed with code " << errno << ": " << strerror(errno)
<< std::endl;
#else
sif::printWarning("Clock::%s: Failed with code %d: %s\n", func, errno, strerror(errno));
#endif
#endif
}

View File

@@ -11,13 +11,10 @@
#include "fsfw/osal/linux/unixUtility.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize)
: id(MessageQueueIF::NO_QUEUE),
lastPartner(MessageQueueIF::NO_QUEUE),
defaultDestination(MessageQueueIF::NO_QUEUE),
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs* args)
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
maxMessageSize(maxMessageSize) {
mq_attr attributes;
this->id = 0;
// Set attributes
attributes.mq_curmsgs = 0;
attributes.mq_maxmsg = messageDepth;
@@ -50,30 +47,6 @@ MessageQueue::~MessageQueue() {
}
}
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), false);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId());
}
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != 0) {
return sendMessageFrom(this->lastPartner, message, this->getId());
} else {
return NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->lastPartner;
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
if (message == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -96,7 +69,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
int status = mq_receive(id, reinterpret_cast<char*>(message->getBuffer()),
message->getMaximumMessageSize(), &messagePriority);
if (status > 0) {
this->lastPartner = message->getSender();
this->last = message->getSender();
// Check size of incoming message.
if (message->getMessageSize() < message->getMinimumMessageSize()) {
return HasReturnvaluesIF::RETURN_FAILED;
@@ -164,8 +137,6 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
}
}
MessageQueueId_t MessageQueue::getLastPartner() const { return this->lastPartner; }
ReturnValue_t MessageQueue::flush(uint32_t* count) {
mq_attr attrib;
int status = mq_getattr(id, &attrib);
@@ -212,26 +183,11 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getId() const { return this->id; }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDestination = defaultDestination;
}
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
}
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault);
}
MessageQueueId_t MessageQueue::getDefaultDestination() const { return this->defaultDestination; }
bool MessageQueue::isDefaultDestinationSet() const { return (defaultDestination != NO_QUEUE); }
uint16_t MessageQueue::queueCounter = 0;
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
@@ -240,9 +196,9 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
bool ignoreFault) {
if (message == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is nullptr!" << std::endl;
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is nullptr" << std::endl;
#else
sif::printError("MessageQueue::sendMessageFromMessageQueue: Message is nullptr!\n");
sif::printError("MessageQueue::sendMessageFromMessageQueue: Message is nullptr\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
@@ -256,7 +212,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
if (!ignoreFault) {
InternalErrorReporterIF* internalErrorReporter =
ObjectManager::instance()->get<InternalErrorReporterIF>(objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != NULL) {
if (internalErrorReporter != nullptr) {
internalErrorReporter->queueMessageNotSent();
}
}

View File

@@ -1,11 +1,13 @@
#ifndef FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
#define FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
#include <fsfw/ipc/MessageQueueBase.h>
#include <mqueue.h>
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/definitions.h"
/**
* @brief This class manages sending and receiving of message queue messages.
*
@@ -25,7 +27,7 @@
* makes use of the operating system calls provided.
* @ingroup message_queue
*/
class MessageQueue : public MessageQueueIF {
class MessageQueue : public MessageQueueBase {
friend class MessageQueueSenderIF;
public:
@@ -42,104 +44,25 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(uint32_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete;
MessageQueue& operator=(const MessageQueue&) = delete;
/**
* @brief The destructor deletes the formerly created message queue.
* @details This is accomplished by using the delete call provided by the operating system.
*/
virtual ~MessageQueue();
/**
* @brief This operation sends a message to the given destination.
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes
* its queue id as "sentFrom" parameter.
* @param sendTo This parameter specifies the message queue id of the destination message
* queue.
* @param message A pointer to a previously created message, which is sent.
* @param ignoreFault If set to true, the internal software fault counter is not incremented if
* queue is full.
*/
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault = false);
/**
* @brief This operation sends a message to the default destination.
* @details As in the sendMessage method, this function uses the sendToDefault call of the
* MessageQueueSender parent class and adds its queue id as "sentFrom"
* information.
* @param message A pointer to a previously created message, which is sent.
*/
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message);
/**
* @brief This operation sends a message to the last communication partner.
* @details This operation simplifies answering an incoming message by using the stored
* lastParnter information as destination. If there was no message received yet
* (i.e. lastPartner is zero), an error code is returned.
* @param message A pointer to a previously created message, which is sent.
*/
ReturnValue_t reply(MessageQueueMessageIF* message);
/**
* @brief This function reads available messages from the message queue and returns the
* sender.
* @details It works identically to the other receiveMessage call, but in addition returns the
* sender's queue id.
* @param message A pointer to a message in which the received data is stored.
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
*/
ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom);
/**
* @brief This function reads available messages from the message queue.
* @details If data is available it is stored in the passed message pointer. The message's
* original content is overwritten and the sendFrom information is stored in
* the lastPartner attribute. Else, the lastPartner information remains untouched, the message's
* content is cleared and the function returns immediately.
* @param message A pointer to a message in which the received data is stored.
*/
ReturnValue_t receiveMessage(MessageQueueMessageIF* message);
/**
* Deletes all pending messages in the queue.
* @param count The number of flushed messages.
* @return RETURN_OK on success.
*/
ReturnValue_t flush(uint32_t* count);
/**
* @brief This method returns the message queue id of the last communication partner.
*/
MessageQueueId_t getLastPartner() const;
/**
* @brief This method returns the message queue id of this class's message queue.
*/
MessageQueueId_t getId() const;
/**
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
* \param sendTo This parameter specifies the message queue id to send the message to.
* \param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the
* message. This variable is set to zero by default. \param ignoreFault If set to true, the
* internal software fault counter is not incremented if queue is full.
*/
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false);
/**
* \brief The sendToDefault method sends a queue message to the default destination.
* \details In all other aspects, it works identical to the sendMessage method.
* \param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the
* message. This variable is set to zero by default.
*/
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false);
/**
* \brief This method is a simple setter for the default destination.
*/
void setDefaultDestination(MessageQueueId_t defaultDestination);
/**
* \brief This method is a simple getter for the default destination.
*/
MessageQueueId_t getDefaultDestination() const;
bool isDefaultDestinationSet() const;
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
ReturnValue_t flush(uint32_t* count) override;
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom,
bool ignoreFault = false) override;
protected:
/**
@@ -158,31 +81,10 @@ class MessageQueue : public MessageQueueIF {
bool ignoreFault = false);
private:
/**
* @brief The class stores the queue id it got assigned from the operating system in this
* attribute. If initialization fails, the queue id is set to zero.
*/
MessageQueueId_t id;
/**
* @brief In this attribute, the queue id of the last communication partner is stored
* to allow for replying.
*/
MessageQueueId_t lastPartner;
/**
* @brief The message queue's name -a user specific information for the operating system- is
* generated automatically with the help of this static counter.
*/
/**
* \brief This attribute stores a default destination to send messages to.
* \details It is stored to simplify sending to always-the-same receiver. The attribute may
* be set in the constructor or by a setter call to setDefaultDestination.
*/
MessageQueueId_t defaultDestination;
/**
* The name of the message queue, stored for unlinking
*/
char name[16];
char name[16] = {};
static uint16_t queueCounter;
const size_t maxMessageSize;

View File

@@ -28,7 +28,11 @@ void* PeriodicPosixTask::taskEntryPoint(void* arg) {
ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) {
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
if (newObject == nullptr) {
return addComponent(newObject);
}
ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object) {
if (object == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
<< " it implements ExecutableObjectIF!" << std::endl;
@@ -39,8 +43,8 @@ ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) {
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
objectList.push_back(newObject);
newObject->setTaskIF(this);
objectList.push_back(object);
object->setTaskIF(this);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@@ -42,6 +42,14 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
*/
ReturnValue_t addComponent(object_id_t object) override;
/**
* Adds an object to the list of objects to be executed.
* The objects are executed in the order added.
* @param object pointer to the object to add.
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
*/
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
uint32_t getPeriodMs() const override;
ReturnValue_t sleepFor(uint32_t ms) override;
@@ -65,9 +73,10 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
/**
* @brief The function containing the actual functionality of the task.
* @details The method sets and starts
* the task's period, then enters a loop that is repeated indefinitely. Within the
* loop, all performOperation methods of the added objects are called. Afterwards the task will be
* blocked until the next period. On missing the deadline, the deadlineMissedFunction is executed.
* the task's period, then enters a loop that is repeated indefinitely. Within
* the loop, all performOperation methods of the added objects are called. Afterwards the task
* will be blocked until the next period. On missing the deadline, the deadlineMissedFunction is
* executed.
*/
virtual void taskFunctionality(void);
/**

View File

@@ -28,8 +28,9 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
return new MessageQueue(messageDepth, maxMessageSize);
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@@ -6,8 +6,9 @@
#include "fsfw/osal/rtems/RtemsBasic.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size)
: id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(nullptr) {
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size, MqArgs* args)
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
internalErrorReporter(nullptr) {
rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
rtems_status_code status =
rtems_message_queue_create(name, message_depth, max_message_size, 0, &(this->id));
@@ -16,43 +17,19 @@ MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size)
sif::error << "MessageQueue::MessageQueue: Creating Queue " << std::hex << name << std::dec
<< " failed with status:" << (uint32_t)status << std::endl;
#endif
this->id = 0;
this->id = MessageQueueIF::NO_QUEUE;
}
}
MessageQueue::~MessageQueue() { rtems_message_queue_delete(id); }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId());
}
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != 0) {
return sendMessage(this->lastPartner, message, this->getId());
} else {
return NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->lastPartner;
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
size_t size = 0;
rtems_status_code status =
rtems_message_queue_receive(id, message->getBuffer(), &size, RTEMS_NO_WAIT, 1);
if (status == RTEMS_SUCCESSFUL) {
message->setMessageSize(size);
this->lastPartner = message->getSender();
this->last = message->getSender();
// Check size of incoming message.
if (message->getMessageSize() < message->getMinimumMessageSize()) {
return HasReturnvaluesIF::RETURN_FAILED;
@@ -65,19 +42,11 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
return convertReturnCode(status);
}
MessageQueueId_t MessageQueue::getLastPartner() const { return this->lastPartner; }
ReturnValue_t MessageQueue::flush(uint32_t* count) {
rtems_status_code status = rtems_message_queue_flush(id, count);
return convertReturnCode(status);
}
MessageQueueId_t MessageQueue::getId() const { return this->id; }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDestination = defaultDestination;
}
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
message->setSender(sentFrom);
@@ -103,15 +72,6 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueu
return returnCode;
}
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
}
MessageQueueId_t MessageQueue::getDefaultDestination() const { return this->defaultDestination; }
bool MessageQueue::isDefaultDestinationSet() const { return (defaultDestination != NO_QUEUE); }
ReturnValue_t MessageQueue::convertReturnCode(rtems_status_code inValue) {
switch (inValue) {
case RTEMS_SUCCESSFUL:

View File

@@ -1,10 +1,12 @@
#ifndef FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
#include <fsfw/ipc/MessageQueueBase.h>
#include "RtemsBasic.h"
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/definitions.h"
/**
* @brief This class manages sending and receiving of message queue messages.
@@ -19,7 +21,7 @@
*as well as sending and receiving messages, the class makes use of the operating system calls
*provided. \ingroup message_queue
*/
class MessageQueue : public MessageQueueIF {
class MessageQueue : public MessageQueueBase {
public:
/**
* @brief The constructor initializes and configures the message queue.
@@ -34,131 +36,26 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(size_t message_depth = 3,
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete;
MessageQueue& operator=(const MessageQueue&) = delete;
/**
* @brief The destructor deletes the formerly created message queue.
* @details This is accomplished by using the delete call provided by the operating system.
*/
virtual ~MessageQueue();
/**
* @brief This operation sends a message to the given destination.
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes
* its queue id as "sentFrom" parameter.
* @param sendTo This parameter specifies the message queue id of the destination message
* queue.
* @param message A pointer to a previously created message, which is sent.
* @param ignoreFault If set to true, the internal software fault counter is not incremented if
* queue is full.
*/
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault = false);
/**
* @brief This operation sends a message to the default destination.
* @details As in the sendMessage method, this function uses the sendToDefault call of the
* MessageQueueSender parent class and adds its queue id as "sentFrom"
* information.
* @param message A pointer to a previously created message, which is sent.
*/
ReturnValue_t sendToDefault(MessageQueueMessageIF* message);
/**
* @brief This operation sends a message to the last communication partner.
* @details This operation simplifies answering an incoming message by using the stored
* lastParnter information as destination. If there was no message received yet
* (i.e. lastPartner is zero), an error code is returned.
* @param message A pointer to a previously created message, which is sent.
*/
ReturnValue_t reply(MessageQueueMessageIF* message);
/**
* @brief This function reads available messages from the message queue and returns the
* sender.
* @details It works identically to the other receiveMessage call, but in addition returns the
* sender's queue id.
* @param message A pointer to a message in which the received data is stored.
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
*/
ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom);
/**
* @brief This function reads available messages from the message queue.
* @details If data is available it is stored in the passed message pointer. The message's
* original content is overwritten and the sendFrom information is stored in
* the lastPartner attribute. Else, the lastPartner information remains untouched, the message's
* content is cleared and the function returns immediately.
* @param message A pointer to a message in which the received data is stored.
*/
ReturnValue_t receiveMessage(MessageQueueMessageIF* message);
/**
* Deletes all pending messages in the queue.
* @param count The number of flushed messages.
* @return RETURN_OK on success.
*/
ReturnValue_t flush(uint32_t* count);
/**
* @brief This method returns the message queue id of the last communication partner.
*/
MessageQueueId_t getLastPartner() const;
/**
* @brief This method returns the message queue id of this class's message queue.
*/
MessageQueueId_t getId() const;
/**
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
* \details This method takes the message provided, adds the sentFrom information and passes
* it on to the destination provided with an operating system call. The OS's
* return value is returned.
* \param sendTo This parameter specifies the message queue id to send the message to.
* \param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the
* message. This variable is set to zero by default. \param ignoreFault If set to true, the
* internal software fault counter is not incremented if queue is full.
*/
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
ReturnValue_t flush(uint32_t* count) override;
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false);
/**
* \brief The sendToDefault method sends a queue message to the default destination.
* \details In all other aspects, it works identical to the sendMessage method.
* \param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the
* message. This variable is set to zero by default.
*/
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false);
/**
* \brief This method is a simple setter for the default destination.
*/
void setDefaultDestination(MessageQueueId_t defaultDestination);
/**
* \brief This method is a simple getter for the default destination.
*/
MessageQueueId_t getDefaultDestination() const;
bool isDefaultDestinationSet() const;
bool ignoreFault = false) override;
private:
/**
* @brief The class stores the queue id it got assigned from the operating system in this
* attribute. If initialization fails, the queue id is set to zero.
*/
MessageQueueId_t id;
/**
* @brief In this attribute, the queue id of the last communication partner is stored
* to allow for replying.
*/
MessageQueueId_t lastPartner;
/**
* @brief The message queue's name -a user specific information for the operating system- is
* generated automatically with the help of this static counter.
*/
/**
* \brief This attribute stores a default destination to send messages to.
* \details It is stored to simplify sending to always-the-same receiver. The attribute may
* be set in the constructor or by a setter call to setDefaultDestination.
*/
MessageQueueId_t defaultDestination;
/**
* \brief This attribute stores a reference to the internal error reporter for reporting full
* queues. \details In the event of a full destination queue, the reporter will be notified. The

View File

@@ -68,11 +68,15 @@ void PeriodicTask::taskFunctionality() {
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
if (newObject == nullptr) {
return addComponent(newObject);
}
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
if (object == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
objectList.push_back(newObject);
newObject->setTaskIF(this);
objectList.push_back(object);
object->setTaskIF(this);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@@ -13,8 +13,8 @@ class ExecutableObjectIF;
* @brief This class represents a specialized task for periodic activities of multiple objects.
*
* @details MultiObjectTask is an extension to ObjectTask in the way that it is able to execute
* multiple objects that implement the ExecutableObjectIF interface. The objects
* must be added prior to starting the task.
* multiple objects that implement the ExecutableObjectIF interface. The
* objects must be added prior to starting the task.
* @author baetz
* @ingroup task_handling
*/
@@ -59,6 +59,15 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
*/
ReturnValue_t addComponent(object_id_t object) override;
/**
* Adds an object to the list of objects to be executed.
* The objects are executed in the order added.
* @param object pointer to the object to add.
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
*/
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
uint32_t getPeriodMs() const override;
ReturnValue_t sleepFor(uint32_t ms) override;

View File

@@ -49,8 +49,9 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
return new MessageQueue(messageDepth, maxMessageSize);
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@@ -66,7 +66,7 @@ class HasParametersIF {
* @param newValues
* @param startAtIndex Linear index, runs left to right, top to bottom for
* matrix indexes.
* @return
* @return RETURN_OK if parameter is valid and a set function of the parameter wrapper was called.
*/
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
ParameterWrapper *parameterWrapper,

View File

@@ -211,9 +211,13 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (data == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable!" << std::endl;
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable or "
"data pointer not set"
<< std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Called on read-only variable!\n");
sif::printWarning(
"ParameterWrapper::copyFrom: Called on read-only variable "
"or data pointer not set\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return READONLY;
@@ -222,9 +226,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (from->readonlyData == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Source not set!" << std::endl;
sif::warning << "ParameterWrapper::copyFrom: Source not set" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Source not set!\n");
sif::printWarning("ParameterWrapper::copyFrom: Source not set\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return SOURCE_NOT_SET;
@@ -233,9 +237,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (type != from->type) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch!" << std::endl;
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch!\n");
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return DATATYPE_MISSMATCH;
@@ -245,9 +249,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (rows == 0 or columns == 0) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero!" << std::endl;
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero!\n");
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return COLUMN_OR_ROWS_ZERO;

View File

@@ -1,7 +1,8 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
Fuse.cpp
PowerComponent.cpp
PowerSensor.cpp
PowerSwitcher.cpp
target_sources(${LIB_FSFW_NAME} PRIVATE
Fuse.cpp
PowerComponent.cpp
PowerSensor.cpp
PowerSwitcher.cpp
DummyPowerSwitcher.cpp
PowerSwitcherComponent.cpp
)

View File

@@ -0,0 +1,46 @@
#include "DummyPowerSwitcher.h"
DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches,
size_t numberOfFuses, uint32_t switchDelayMs)
: SystemObject(objectId),
switcherList(numberOfSwitches),
fuseList(numberOfFuses),
switchDelayMs(switchDelayMs) {}
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
this->switcherList = switcherList;
}
void DummyPowerSwitcher::setInitialFusesList(std::vector<ReturnValue_t> fuseList) {
this->fuseList = fuseList;
}
ReturnValue_t DummyPowerSwitcher::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) {
if (switchNr < switcherList.capacity()) {
switcherList[switchNr] = onOff;
}
return RETURN_FAILED;
}
ReturnValue_t DummyPowerSwitcher::sendFuseOnCommand(uint8_t fuseNr) {
if (fuseNr < fuseList.capacity()) {
fuseList[fuseNr] = FUSE_ON;
}
return RETURN_FAILED;
}
ReturnValue_t DummyPowerSwitcher::getSwitchState(power::Switch_t switchNr) const {
if (switchNr < switcherList.capacity()) {
return switcherList[switchNr];
}
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t DummyPowerSwitcher::getFuseState(uint8_t fuseNr) const {
if (fuseNr < fuseList.capacity()) {
return fuseList[fuseNr];
}
return HasReturnvaluesIF::RETURN_FAILED;
}
uint32_t DummyPowerSwitcher::getSwitchDelayMs(void) const { return switchDelayMs; }

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