Compare commits
700 Commits
50733e223a
...
ASTP_1.1.0
Author | SHA1 | Date | |
---|---|---|---|
b00bfe4bda | |||
2b2899e100 | |||
b52644dd2a | |||
1015cdbe88 | |||
cae69d5400 | |||
47af5260a2 | |||
1e380fe562 | |||
bd7c13ff7e
|
|||
2684e82c7f | |||
66d1d14ae3 | |||
5f9a6bb155 | |||
8a5a3c0243 | |||
2ccc0dbb00
|
|||
cfbdb10a55 | |||
ee89a2f00d
|
|||
dbfcf8b271 | |||
717971f69c
|
|||
b0a69d4c9d | |||
ecb03b8a6d
|
|||
b1f6252e30 | |||
05edb7a00c | |||
0cde65f5a1
|
|||
fbbc640f4d | |||
03e1a3e945 | |||
cc5c8ca698 | |||
996fbf134e | |||
1c7c532ef6 | |||
41e3a6b54b | |||
aa1bfcbb96 | |||
0f484abcaa | |||
c371cf4851 | |||
ad191409f4 | |||
398250c959 | |||
4b248740f3 | |||
21d213f35f | |||
105a498b93 | |||
0a0c5592f3 | |||
aa33ff2f48 | |||
3076c423c0 | |||
5f27fe6392 | |||
af99303eac | |||
1d2dabb4b4 | |||
eead2a8a49
|
|||
a7068acca7 | |||
99b007f37e | |||
7cf4aa0d5a | |||
b1e3a1b2b5 | |||
56d2af9d25 | |||
dadba69272 | |||
40a8c9a495 | |||
8dc66784a8 | |||
d0f37b851b | |||
1b6759020a | |||
537a30a4de | |||
a993872884 | |||
d700fb551c | |||
73bae057bd | |||
589e64fc46 | |||
1630682548 | |||
4b095eea89 | |||
fb7b059137 | |||
bc151983b5 | |||
40b2979ce8 | |||
7030d3e108 | |||
41cb8cb8ae | |||
75adf52d28 | |||
0157681471 | |||
b6b144bcdb | |||
145dd33fb1 | |||
50fac22f54 | |||
8b83541264 | |||
57699cccb7 | |||
33e7c635c5 | |||
070c3f3bbf | |||
3891014340 | |||
c3be4cdee6 | |||
6b9747ee0b | |||
ad820fbe99 | |||
722a7b3240 | |||
442b9370ae | |||
54e60f4ddc | |||
e961f3f038 | |||
c9836abf03 | |||
404c3821e6 | |||
567699954c | |||
43d4953e4a | |||
e6059812b5 | |||
f0a7b1cad2 | |||
e46615e830 | |||
e7ac2c7009 | |||
95c6a24437 | |||
237ba8112b | |||
aab3fd828b | |||
46cfe7452a | |||
e6868464bf | |||
e15f03fb0a | |||
59e7f0caae | |||
a2deac3441 | |||
5eadcaf10d | |||
2bf5a972e1 | |||
5d2c62e75d | |||
5ac68f731e | |||
7fa0443725 | |||
f4cb63c53c | |||
0cde6f317d | |||
2737bc390c | |||
07ba05b209 | |||
f3d9fb645e | |||
e9adaf672f | |||
fc4e65b2fc | |||
36030ef87c | |||
b7060a9c78 | |||
e147d5a4f5 | |||
a8c0d96c39 | |||
ed27d388d5 | |||
e2ae9756f3 | |||
c07672f9b4 | |||
6db2efc20d | |||
94062c67d3 | |||
9e0146f579 | |||
d3423b30b0 | |||
58a532fc4d | |||
ac027e3ff2 | |||
ff6b4134a5 | |||
5847081a24 | |||
0bc124fd21 | |||
1e9c789287 | |||
b06113993c | |||
4fa56a2f1d | |||
a320e3e1ef | |||
4095be449a | |||
d20f0c5da1 | |||
9496ed42e2 | |||
14027e449c | |||
1626b266d7 | |||
d27f49c968 | |||
a6dd2d5dcb | |||
8293e6b0c7 | |||
d81c6f40fb | |||
5b23b928cf | |||
cd016c8281 | |||
e1c91f82b7 | |||
9d0155d9ae
|
|||
d807998f4d | |||
8b17c40aa6 | |||
d7d24bd9aa | |||
c1d30aad13 | |||
126def219b | |||
08b9e92d25 | |||
86431c854b | |||
f3530d3c7e | |||
0a76c5b0b5 | |||
6ede3f9ba2 | |||
097244bf8b | |||
5c9b1769c1 | |||
2f511523cb | |||
9f83739771 | |||
054de9781b | |||
20e7fe6cb1 | |||
f8cd8e1e7d | |||
818634755d | |||
413ff0d1b9 | |||
87fee9bd0e | |||
5273ffa721 | |||
e7c00b5633 | |||
f2ab07c782 | |||
ff33a1274d | |||
e7cfd324ae | |||
52b549b97c | |||
cac9a0eecd | |||
56d43f5b49 | |||
10e7e42388 | |||
fc34e7fd75 | |||
18a9729c75 | |||
763347f203 | |||
1ff52e43a0 | |||
6a40b8244d | |||
7f1cbaef23 | |||
3356ccc9d4 | |||
4fd443f70b | |||
06631d06a5
|
|||
9244a96e7b | |||
03ef63302b
|
|||
3f91803422 | |||
5759c2cbe6 | |||
c50796b785 | |||
a0caa92a8a | |||
a91139be76 | |||
fee2ac0eb9 | |||
2878f21c93 | |||
4caf906d96 | |||
b38e9ede0c | |||
17b3672330 | |||
629814bc9b
|
|||
4fb792447e
|
|||
40dae8c961 | |||
9e1f3ee585 | |||
e851d8a46c | |||
0038c1dc53 | |||
1a3bb5bada | |||
e45b8bc739 | |||
dcd72d421e | |||
cc8c3aef3d | |||
0055d34d9a | |||
a2ba3181b9 | |||
864621ee37 | |||
54ff8f9341 | |||
e4efc01e34 | |||
c455fc1417 | |||
d792679d49 | |||
9352e15405 | |||
38a5e7e618 | |||
1cceda8e63 | |||
0c342ad7fc | |||
524e50a6dd | |||
8c4381eca6 | |||
29a05eb113 | |||
17adb2cc3e | |||
534b4850df | |||
7b29583f8f | |||
a66fc53396 | |||
5471030c32 | |||
1af7870b15 | |||
1cbeb54b8d | |||
0ec83afa13 | |||
153c44601b
|
|||
e6a8371d4a | |||
64efb8ec7f | |||
c8b2b3a038 | |||
6873d2b847 | |||
91c3692f6d | |||
69788e1279 | |||
ec69076652 | |||
a62bda97a0 | |||
32f0131973 | |||
9784d5123b | |||
ea8d887a6b | |||
29cebab790 | |||
03095776f1
|
|||
bad9f67c39 | |||
98add88d14 | |||
e1b595d620 | |||
770356f8b6 | |||
62e409a9f2 | |||
39940823d1 | |||
4479a2628d | |||
b09119cd8d | |||
10bc568560 | |||
6e09e29ec2 | |||
43fb05ac5d | |||
e832487081 | |||
01acbaa270 | |||
cf8a9996a7 | |||
a8b5fec725 | |||
fc7e401ddc | |||
ed186b04df | |||
f906605097 | |||
9a2fbefc9f | |||
07f1216316 | |||
4faa5b0685 | |||
ae1dab1fce | |||
9a5f717169 | |||
d7d52439d7 | |||
321de4e46b | |||
2635ec3d56 | |||
3f7915fe49 | |||
f87a10891a | |||
f4ac5c3844 | |||
922f145ffa | |||
9731127eaf | |||
5124f314f4 | |||
4bb078c451 | |||
547538fbc5 | |||
06d34efa74 | |||
b786b53c35 | |||
e50d0738ab | |||
01d0bd6c64 | |||
5676969fe3 | |||
5d93cf12f7 | |||
438049bb80 | |||
6e6fb62b3c | |||
7b8928ef47 | |||
924ea420a9 | |||
fbe860c6a5 | |||
8b266aa542 | |||
5144cbd789 | |||
720ce59680 | |||
f1ffa88e07 | |||
d4b26825af | |||
7e249db15e | |||
83e7dbb1f0 | |||
2e417c787d | |||
316310e993 | |||
6db0725aa4 | |||
e0d39b1feb | |||
d9a0a4f2ea | |||
b8c7a65709 | |||
d3c3a9147a | |||
40cc3c383b | |||
d92a20a669 | |||
c1f4ae08fb | |||
2b84ab018c | |||
9e881b6a16 | |||
905d525aa2 | |||
e6a1a7cc2d | |||
dd367bf083 | |||
8f4ab6d7ed | |||
b30a3aaa38 | |||
efb7c8760a | |||
bddd8720b2 | |||
00d9a4f3ed | |||
f988271be4 | |||
38d929c2a8 | |||
b4594e6f43 | |||
6e12f08965 | |||
2dd2d8f133 | |||
10c3483fe5 | |||
e799e45198 | |||
23e3f2f34f | |||
9ee1bd15c4 | |||
cbeb78f089 | |||
6983ddc3e0 | |||
80aab5f461 | |||
43ddb44573 | |||
9f8a345e35 | |||
3ff5484415 | |||
7322a7d0f5 | |||
0e76333d33 | |||
c234da6f07 | |||
8930be9f32 | |||
32996338a0 | |||
2736ebbd19 | |||
dea2205908 | |||
d1a256cbf6 | |||
509945c323 | |||
435c6e6410 | |||
3429918f5e | |||
f2da31239c | |||
3a75be2683 | |||
aa9d7b2226 | |||
eea482b438 | |||
3a90578780 | |||
42720e6f7d | |||
1d818294e4 | |||
581832e4f4 | |||
9e559658a7 | |||
b1c532078e | |||
37ac579f51 | |||
aaceac81af | |||
d781c6fcec | |||
bdd9889718 | |||
a5f44b8580 | |||
d1265a55b4 | |||
b542ed5c03 | |||
8b42132cbe | |||
b1670decf7 | |||
1d3d2be853 | |||
d4ab2c6cdb | |||
1c021651d7 | |||
3175883346 | |||
4d403b40c9 | |||
f6afa36b1c | |||
0c77ce4dcf | |||
4c11b2f660 | |||
614d1ccb7c | |||
e3c44fd27f | |||
078116c7be | |||
b5a14bb9df | |||
86577f4b80 | |||
d625642abc | |||
83d0db8242 | |||
533d164cac | |||
951eb40e96 | |||
538dec7062 | |||
8f17d6623a | |||
0585ef9051 | |||
0da95b75a2 | |||
e44f8bfea3 | |||
fe2b3a01cf | |||
0e92fa4046 | |||
32b289cbec | |||
fa108f0a3b | |||
aa849894c6 | |||
a4ca61d834 | |||
b41eb518e7 | |||
1b8878a81f | |||
95096d83de | |||
2331188536 | |||
b2937ae510 | |||
3f8fae24dd | |||
12f47fdd0d | |||
b757c5523c | |||
5271375063 | |||
4955015f3f | |||
898e06591b | |||
d62dea442d | |||
66a09b94ac | |||
125dffcf28 | |||
8dec4c9311 | |||
26ce8d7185 | |||
1996f5949f | |||
ca4a0b1bb8 | |||
588f9471d8 | |||
703dfe9854 | |||
7bc04014e8 | |||
5eb6b277ba | |||
2684b0c68e | |||
76c571b969 | |||
c08e2f0bf7 | |||
bceca86da6 | |||
8ab2044c30 | |||
7173d2ecfc | |||
cf120e2d86 | |||
e92d3901f7 | |||
b071c850af | |||
df7434dae5 | |||
6e5b032dbb | |||
67b05fee2e | |||
286a3649cf | |||
9eefd5b95d | |||
36e524abe3 | |||
c527391b10 | |||
9602a3ed6a | |||
33823b445c | |||
e55f74a00e | |||
8b83de6ca9 | |||
3bacc8ec53 | |||
6f78c13dcf | |||
824f272432 | |||
78b6a83285 | |||
620b2ae79e | |||
8d28bc4b6a | |||
dcde177fe3 | |||
4f89fc62ab | |||
c59fa578c7 | |||
6c0972b2d5 | |||
7ad8763b14 | |||
03936fc5c1 | |||
3789663db7 | |||
b2e4438811 | |||
6501c16fd7 | |||
943495117b | |||
30910034f0 | |||
596d3bc68a | |||
1e73302ba2 | |||
9ba7fabdea | |||
676c9ffcf3 | |||
5095fd206f | |||
bb5b7bed40 | |||
e5b3b6d75e | |||
61affafecd | |||
7525c88392 | |||
3e9c19ee11 | |||
a7bf9a6734 | |||
82d7b7ed6f | |||
7598eb6b56 | |||
7b3616c41f | |||
9737d4cf2a | |||
c815905b5a | |||
59028ccc3f | |||
372e8c66a8 | |||
f5ac4368d8 | |||
6d0bc26624 | |||
baafeadcf4 | |||
dbda6fee82 | |||
cad302730e | |||
da2f594a00 | |||
d5a065eaa8 | |||
b695242420 | |||
494dd0db32 | |||
8be4f45969 | |||
4e5e6e145e | |||
e67ff6a937 | |||
bdd66072d1 | |||
1966b33613 | |||
331bbd14e7 | |||
9efc5dbd61 | |||
f82cc1bca4 | |||
e7cd7c8dc3 | |||
778ef4ef23 | |||
17b8d3fed0 | |||
d57955ade7 | |||
18e40d6248 | |||
caa3cf538b | |||
b3ca7b8667 | |||
2d069896a5 | |||
cb514e7493 | |||
bc7d956899 | |||
41e30dcb6c | |||
227074fd4d | |||
a56cf43897 | |||
e501390d7b | |||
e0d7363eed | |||
69b428222a | |||
6df1abf570 | |||
d84003d62a | |||
a7878aaf04 | |||
23873f6bc6 | |||
8de33f1301 | |||
35825a6561 | |||
043d47e5e4 | |||
bd903b8447 | |||
4250c7e022 | |||
d66e486f16 | |||
21a7fd621d | |||
dae4a5fa74 | |||
d8d18c9333 | |||
041461a066 | |||
bff8d103ba | |||
6580aa73bf | |||
9a3cd1d7fc | |||
e64de87af7 | |||
7ea4fedcea | |||
1caa45118b | |||
6e43a70af5 | |||
559c8d0637 | |||
ef5c0d50f3 | |||
3f47db9c18 | |||
91db9c362e | |||
1d3438bb7d | |||
cc84d542c8 | |||
9e9113912b | |||
9f09c190bb | |||
2b6ccbc17f | |||
458d783211 | |||
5cf2197c06 | |||
940bbf47e4 | |||
714f11f117 | |||
ffce336801 | |||
50ba377380 | |||
304773f7a7 | |||
16566a5690 | |||
68415853b5 | |||
fb5a1b93fc | |||
828115a566 | |||
d79f0e1172 | |||
35d8453b48 | |||
36039266ee | |||
a65211be51 | |||
fcff06c83f | |||
ea6ee7e79c | |||
110159eea1 | |||
788dbe4eca | |||
f45d19a961 | |||
c5ee2260d1 | |||
92f249dc62 | |||
f3cc664d4f | |||
91f69aa34f | |||
8b561d073c | |||
242a146f61 | |||
c55cf8f279 | |||
8eb25c02aa | |||
94f9d1ee16 | |||
6cded300ae | |||
1bec19bdd7 | |||
2fba1a6cfe | |||
c5b2c47af4 | |||
ce770a67b2 | |||
f0178a8f73 | |||
e1b57424f8 | |||
06eadb55ab | |||
8d7d4c639a | |||
58e219981f | |||
671bab012e | |||
a3d245f5a0 | |||
1ccfb74709 | |||
1443758274 | |||
e013ae954f | |||
c28398257b | |||
4154c06825 | |||
8a1f043b39 | |||
2a1aea7c73 | |||
8d748a4bbf | |||
dc88424910 | |||
03b2e1be3e | |||
10390de63b | |||
0416aaf3fe | |||
ee67e46a9f | |||
eb37a0ad2f | |||
b9cb0495a9 | |||
ac5d0cf58f | |||
48375a5221 | |||
46e4816faf | |||
85b92af777 | |||
5136d90659 | |||
cb2c66e256 | |||
72ce47358e | |||
36d1a36a74 | |||
ae5d880406 | |||
bcd51c0725 | |||
5209a9bb89 | |||
712ba5124c | |||
16763202c1 | |||
9998de086f | |||
d4d3da60a9 | |||
9b2772c126 | |||
939fa16d1a | |||
d736e9c874 | |||
257e79f8fc | |||
3bd7ba961e | |||
6be6d593a3 | |||
1829d9cf0a | |||
255d4a90a9 | |||
f7c1aae464 | |||
cdb012fe5a | |||
2bca40c527 | |||
1446ce94bf | |||
8c5e261a0d | |||
5f197be2ff | |||
6e5252b69e | |||
093eb05269 | |||
c1cb93baa9 | |||
c0b490df65 | |||
e27d4fd060 | |||
a404bc881e | |||
5ac3762dc5 | |||
4522668066 | |||
8b90360b45 | |||
f067695353 | |||
503de9ba89 | |||
cf945d4d34 | |||
7f0db5b47c | |||
e65990feff | |||
484f9b6b37 | |||
bc722b5583 | |||
6b4bed8ca9 | |||
7f47a10cbd | |||
9266c874c1 | |||
ac6e34fc65 | |||
6127bb5ea4 | |||
98f89302c4 | |||
76d81b5b49 | |||
17a1ae9d0e | |||
dcb569a7c8 | |||
5b0758638b | |||
f85ab2b300 | |||
3b7bebeb6f | |||
2fce82db10 | |||
73dcb78a65 | |||
a0e7b45d94 | |||
8b5abd1fd5 | |||
8a0431c578 | |||
942ecc89bd | |||
3036793814 | |||
f40cdcf472 | |||
686ae101ee | |||
4136420685 | |||
de45e9b8a9 | |||
47698418fc | |||
d1cd180534 | |||
a93984869c | |||
a0dea39670 | |||
35d75bae56 | |||
578664ad06 | |||
86d0d5c4ee | |||
7e0cc471c9 | |||
194a9eef64 | |||
18fddf2755 | |||
31517604c9 | |||
38c7e050ab | |||
7310d2b5fe | |||
d39c729a16 | |||
f11e7407d6 | |||
52c177479f | |||
0bb19c5ee5 | |||
4dbd5a58e3 | |||
df9f534d12 | |||
ef93c70665 | |||
47402055f9 | |||
0495f390ef | |||
d1c83159e5 | |||
5289c274f3 | |||
094d237814 | |||
e245f56a4f | |||
a85c94ea80 | |||
8850b770ee | |||
bdd1bdb080 | |||
7b82a7c1a7 | |||
cc2e26443d | |||
583d354fb5 | |||
d4ca1ddb20 | |||
ca22ff5d8e | |||
b6888a8185 | |||
f4a60a0323 | |||
f7b70984c1 | |||
74def820c6 | |||
6e6e1304bb | |||
2c21400aed | |||
aa7ea35b80 | |||
0514ab4d05 | |||
a9135696a5 | |||
38dd230887 | |||
eae3175976 | |||
79cf009049 | |||
73b9d058e5 | |||
baba8fa5d7 | |||
05508418a7 | |||
f69d6d49c7 | |||
eb5548333e | |||
fd11cae7be |
37
CHANGELOG
37
CHANGELOG
@@ -1,3 +1,16 @@
|
|||||||
|
## Changes from ASTP 1.0.0 to 1.1.0
|
||||||
|
|
||||||
|
### PUS
|
||||||
|
|
||||||
|
- Added PUS C support
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
- Additional configuration option fsfwconfig::FSFW_MAX_TM_PACKET_SIZE which
|
||||||
|
need to be specified in FSFWConfig.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Changes from ASTP 0.0.1 to 1.0.0
|
## Changes from ASTP 0.0.1 to 1.0.0
|
||||||
|
|
||||||
### Host OSAL
|
### Host OSAL
|
||||||
@@ -22,7 +35,9 @@ a C file without issues
|
|||||||
|
|
||||||
### Local Pool
|
### Local Pool
|
||||||
|
|
||||||
- Interface of LocalPools has changed. LocalPool is not a template anymore. Instead the size and bucket number of the pools per page and the number of pages are passed to the ctor instead of two ctor arguments and a template parameter
|
- Interface of LocalPools has changed. LocalPool is not a template anymore. Instead the size and
|
||||||
|
bucket number of the pools per page and the number of pages are passed to the ctor instead of
|
||||||
|
two ctor arguments and a template parameter
|
||||||
|
|
||||||
### Parameter Service
|
### Parameter Service
|
||||||
|
|
||||||
@@ -40,7 +55,8 @@ important use-case)
|
|||||||
|
|
||||||
### File System Interface
|
### File System Interface
|
||||||
|
|
||||||
- A new interfaces specifies the functions for a software object which exposes the file system of a given hardware to use message based file handling (e.g. PUS commanding)
|
- A new interfaces specifies the functions for a software object which exposes the file system of
|
||||||
|
a given hardware to use message based file handling (e.g. PUS commanding)
|
||||||
|
|
||||||
### Internal Error Reporter
|
### Internal Error Reporter
|
||||||
|
|
||||||
@@ -52,7 +68,8 @@ ID for now.
|
|||||||
### Device Handler Base
|
### Device Handler Base
|
||||||
|
|
||||||
- There is an additional `PERFORM_OPERATION` step for the device handler base. It is important
|
- There is an additional `PERFORM_OPERATION` step for the device handler base. It is important
|
||||||
that DHB users adapt their polling sequence tables to perform this step. This steps allows for aclear distinction between operation and communication steps
|
that DHB users adapt their polling sequence tables to perform this step. This steps allows for
|
||||||
|
a clear distinction between operation and communication steps
|
||||||
- setNormalDatapoolEntriesInvalid is not an abstract method and a default implementation was provided
|
- setNormalDatapoolEntriesInvalid is not an abstract method and a default implementation was provided
|
||||||
- getTransitionDelayMs is now an abstract method
|
- getTransitionDelayMs is now an abstract method
|
||||||
|
|
||||||
@@ -69,7 +86,8 @@ now
|
|||||||
|
|
||||||
### Commanding Service Base
|
### Commanding Service Base
|
||||||
|
|
||||||
- CSB uses the new fsfwconfig::FSFW_CSB_FIFO_DEPTH variable to determine the FIFO depth for each CSB instance. This variable has to be set in the FSFWConfig.h file
|
- CSB uses the new fsfwconfig::FSFW_CSB_FIFO_DEPTH variable to determine the FIFO depth for each
|
||||||
|
CSB instance. This variable has to be set in the FSFWConfig.h file
|
||||||
|
|
||||||
### Service Interface
|
### Service Interface
|
||||||
|
|
||||||
@@ -81,4 +99,13 @@ now
|
|||||||
For the fsfw, this can be done by checking the processor define FSFW_CPP_OSTREAM_ENABLED from FSFWConfig.h.
|
For the fsfw, this can be done by checking the processor define FSFW_CPP_OSTREAM_ENABLED from FSFWConfig.h.
|
||||||
For mission code, developers need to replace sif:: calls by the printf counterparts, but only if the CPP stream are excluded.
|
For mission code, developers need to replace sif:: calls by the printf counterparts, but only if the CPP stream are excluded.
|
||||||
If this is not the case, everything should work as usual.
|
If this is not the case, everything should work as usual.
|
||||||
-
|
|
||||||
|
### ActionHelper and ActionMessage
|
||||||
|
|
||||||
|
- ActionHelper finish function and ActionMessage::setCompletionReply now expects explicit
|
||||||
|
information whether to report a success or failure message instead of deriving it implicitely
|
||||||
|
from returnvalue
|
||||||
|
|
||||||
|
### PUS Parameter Service 20
|
||||||
|
|
||||||
|
Added PUS parameter service 20 (only custom subservices available).
|
||||||
|
@@ -1,5 +1,13 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
option(FSFW_GENERATE_SECTIONS
|
||||||
|
"Generate function and data sections. Required to remove unused code" ON
|
||||||
|
)
|
||||||
|
|
||||||
|
if(FSFW_GENERATE_SECTIONS)
|
||||||
|
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
||||||
# Options to exclude parts of the FSFW from compilation.
|
# Options to exclude parts of the FSFW from compilation.
|
||||||
option(FSFW_USE_RMAP "Compile with RMAP" ON)
|
option(FSFW_USE_RMAP "Compile with RMAP" ON)
|
||||||
@@ -10,6 +18,13 @@ add_library(${LIB_FSFW_NAME})
|
|||||||
|
|
||||||
set_property(CACHE OS_FSFW PROPERTY STRINGS host linux rtems freertos)
|
set_property(CACHE OS_FSFW PROPERTY STRINGS host linux rtems freertos)
|
||||||
|
|
||||||
|
if(NOT CMAKE_CXX_STANDARD)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
elseif(${CMAKE_CXX_STANDARD} LESS 11)
|
||||||
|
message(FATAL_ERROR "Compiling the FSFW requires a minimum of C++11 support")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT OS_FSFW)
|
if(NOT OS_FSFW)
|
||||||
message(STATUS "No OS for FSFW via OS_FSFW set. Assuming host OS")
|
message(STATUS "No OS for FSFW via OS_FSFW set. Assuming host OS")
|
||||||
# Assume host OS and autodetermine from OS_FSFW
|
# Assume host OS and autodetermine from OS_FSFW
|
||||||
@@ -26,15 +41,22 @@ if(NOT OS_FSFW)
|
|||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(FSFW_OSAL_DEFINITION FSFW_HOST)
|
||||||
|
|
||||||
if(${OS_FSFW} STREQUAL host)
|
if(${OS_FSFW} STREQUAL host)
|
||||||
set(OS_FSFW_NAME "Host")
|
set(OS_FSFW_NAME "Host")
|
||||||
elseif(${OS_FSFW} STREQUAL linux)
|
elseif(${OS_FSFW} STREQUAL linux)
|
||||||
set(OS_FSFW_NAME "Linux")
|
set(OS_FSFW_NAME "Linux")
|
||||||
|
set(FSFW_OSAL_DEFINITION FSFW_LINUX)
|
||||||
elseif(${OS_FSFW} STREQUAL freertos)
|
elseif(${OS_FSFW} STREQUAL freertos)
|
||||||
set(OS_FSFW_NAME "FreeRTOS")
|
set(OS_FSFW_NAME "FreeRTOS")
|
||||||
target_link_libraries(${LIB_FSFW_NAME} ${LIB_OS_NAME})
|
set(FSFW_OSAL_DEFINITION FSFW_FREERTOS)
|
||||||
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
${LIB_OS_NAME}
|
||||||
|
)
|
||||||
elseif(${OS_FSFW} STREQUAL rtems)
|
elseif(${OS_FSFW} STREQUAL rtems)
|
||||||
set(OS_FSFW_NAME "RTEMS")
|
set(OS_FSFW_NAME "RTEMS")
|
||||||
|
set(FSFW_OSAL_DEFINITION FSFW_RTEMS)
|
||||||
else()
|
else()
|
||||||
message(WARNING
|
message(WARNING
|
||||||
"Invalid operating system for FSFW specified! Setting to host.."
|
"Invalid operating system for FSFW specified! Setting to host.."
|
||||||
@@ -43,6 +65,14 @@ else()
|
|||||||
set(OS_FSFW "host")
|
set(OS_FSFW "host")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
${FSFW_OSAL_DEFINITION}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(${LIB_FSFW_NAME} INTERFACE
|
||||||
|
${FSFW_OSAL_DEFINITION}
|
||||||
|
)
|
||||||
|
|
||||||
message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system.")
|
message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system.")
|
||||||
|
|
||||||
add_subdirectory(action)
|
add_subdirectory(action)
|
||||||
@@ -88,6 +118,7 @@ add_subdirectory(timemanager)
|
|||||||
add_subdirectory(tmstorage)
|
add_subdirectory(tmstorage)
|
||||||
add_subdirectory(tmtcpacket)
|
add_subdirectory(tmtcpacket)
|
||||||
add_subdirectory(tmtcservices)
|
add_subdirectory(tmtcservices)
|
||||||
|
add_subdirectory(unittest)
|
||||||
|
|
||||||
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it.
|
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it.
|
||||||
# If this is not given, we include the default configuration and emit a warning.
|
# If this is not given, we include the default configuration and emit a warning.
|
||||||
@@ -107,6 +138,21 @@ else()
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATHS})
|
||||||
|
if(IS_ABSOLUTE ${INCLUDE_PATH})
|
||||||
|
set(CURR_ABS_INC_PATH "${INCLUDE_PATH}")
|
||||||
|
else()
|
||||||
|
get_filename_component(CURR_ABS_INC_PATH
|
||||||
|
${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_VERBOSE)
|
||||||
|
message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
if(NOT DEFINED FSFW_WARNING_FLAGS)
|
if(NOT DEFINED FSFW_WARNING_FLAGS)
|
||||||
set(FSFW_WARNING_FLAGS
|
set(FSFW_WARNING_FLAGS
|
||||||
@@ -117,7 +163,20 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|||||||
-Wno-psabi
|
-Wno-psabi
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(FSFW_GENERATE_SECTIONS)
|
||||||
|
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
"-ffunction-sections"
|
||||||
|
"-fdata-sections"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(FSFW_REMOVE_UNUSED_CODE)
|
||||||
|
target_link_options(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
"Wl,--gc-sections"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(FSFW_WARNING_SHADOW_LOCAL_GCC)
|
if(FSFW_WARNING_SHADOW_LOCAL_GCC)
|
||||||
list(APPEND WARNING_FLAGS "-Wshadow=local")
|
list(APPEND WARNING_FLAGS "-Wshadow=local")
|
||||||
endif()
|
endif()
|
||||||
@@ -132,6 +191,7 @@ endif()
|
|||||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
||||||
${CMAKE_SOURCE_DIR}
|
${CMAKE_SOURCE_DIR}
|
||||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||||
|
${FSFW_ADD_INC_PATHS_ABS}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Includes path required to compile FSFW itself as well
|
# Includes path required to compile FSFW itself as well
|
||||||
@@ -140,9 +200,14 @@ target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
|||||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
||||||
${CMAKE_SOURCE_DIR}
|
${CMAKE_SOURCE_DIR}
|
||||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||||
|
${FSFW_ADD_INC_PATHS_ABS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||||
${FSFW_WARNING_FLAGS}
|
${FSFW_WARNING_FLAGS}
|
||||||
${COMPILER_FLAGS}
|
${COMPILER_FLAGS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
${FSFW_ADDITIONAL_LINK_LIBS}
|
||||||
|
)
|
7
FSFW.h
Normal file
7
FSFW.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef FSFW_FSFW_H_
|
||||||
|
#define FSFW_FSFW_H_
|
||||||
|
|
||||||
|
#include "FSFWConfig.h"
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSFW_FSFW_H_ */
|
@@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
const char* const FSFW_VERSION_NAME = "ASTP";
|
const char* const FSFW_VERSION_NAME = "ASTP";
|
||||||
|
|
||||||
#define FSFW_VERSION 0
|
#define FSFW_VERSION 1
|
||||||
#define FSFW_SUBVERSION 0
|
#define FSFW_SUBVERSION 0
|
||||||
#define FSFW_REVISION 1
|
#define FSFW_REVISION 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
11
README.md
11
README.md
@@ -38,11 +38,12 @@ a starting point. The [configuration section](doc/README-config.md#top) provides
|
|||||||
|
|
||||||
[1. High-level overview](doc/README-highlevel.md#top) <br>
|
[1. High-level overview](doc/README-highlevel.md#top) <br>
|
||||||
[2. Core components](doc/README-core.md#top) <br>
|
[2. Core components](doc/README-core.md#top) <br>
|
||||||
[3. OSAL overview](doc/README-osal.md#top) <br>
|
[3. Configuration](doc/README-config.md#top) <br>
|
||||||
[4. PUS services](doc/README-pus.md#top) <br>
|
[4. OSAL overview](doc/README-osal.md#top) <br>
|
||||||
[5. Device Handler overview](doc/README-devicehandlers.md#top) <br>
|
[5. PUS services](doc/README-pus.md#top) <br>
|
||||||
[6. Controller overview](doc/README-controllers.md#top) <br>
|
[6. Device Handler overview](doc/README-devicehandlers.md#top) <br>
|
||||||
[7. Local Data Pools](doc/README-localpools.md#top) <br>
|
[7. Controller overview](doc/README-controllers.md#top) <br>
|
||||||
|
[8. Local Data Pools](doc/README-localpools.md#top) <br>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2,152 +2,120 @@
|
|||||||
#include "HasActionsIF.h"
|
#include "HasActionsIF.h"
|
||||||
|
|
||||||
#include "../ipc/MessageQueueSenderIF.h"
|
#include "../ipc/MessageQueueSenderIF.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManager.h"
|
||||||
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
ActionHelper::ActionHelper(HasActionsIF* setOwner,
|
ActionHelper::ActionHelper(HasActionsIF* setOwner,
|
||||||
MessageQueueIF* useThisQueue) :
|
MessageQueueIF* useThisQueue) :
|
||||||
owner(setOwner), queueToUse(useThisQueue) {
|
owner(setOwner), queueToUse(useThisQueue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionHelper::~ActionHelper() {
|
ActionHelper::~ActionHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
||||||
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
||||||
ActionId_t currentAction = ActionMessage::getActionId(command);
|
ActionId_t currentAction = ActionMessage::getActionId(command);
|
||||||
prepareExecution(command->getSender(), currentAction,
|
prepareExecution(command->getSender(), currentAction,
|
||||||
ActionMessage::getStoreId(command));
|
ActionMessage::getStoreId(command));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return CommandMessage::UNKNOWN_COMMAND;
|
return CommandMessage::UNKNOWN_COMMAND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
||||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||||
if (ipcStore == nullptr) {
|
if (ipcStore == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
if(queueToUse_ != nullptr) {
|
if(queueToUse_ != nullptr) {
|
||||||
setQueueToUse(queueToUse_);
|
setQueueToUse(queueToUse_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo,
|
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo,
|
||||||
ActionId_t commandId, ReturnValue_t result) {
|
ActionId_t commandId, ReturnValue_t result) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
||||||
queueToUse->sendMessage(reportTo, &reply);
|
queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
void ActionHelper::finish(bool success, MessageQueueId_t reportTo, ActionId_t commandId,
|
||||||
ReturnValue_t result) {
|
ReturnValue_t result) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setCompletionReply(&reply, commandId, result);
|
ActionMessage::setCompletionReply(&reply, commandId, success, result);
|
||||||
queueToUse->sendMessage(reportTo, &reply);
|
queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
|
void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
|
||||||
queueToUse = queue;
|
queueToUse = queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
||||||
ActionId_t actionId, store_address_t dataAddress) {
|
ActionId_t actionId, store_address_t dataAddress) {
|
||||||
const uint8_t* dataPtr = NULL;
|
const uint8_t* dataPtr = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||||
ipcStore->deleteData(dataAddress);
|
ipcStore->deleteData(dataAddress);
|
||||||
if(result == HasActionsIF::EXECUTION_FINISHED) {
|
if(result == HasActionsIF::EXECUTION_FINISHED) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setCompletionReply(&reply, actionId, result);
|
ActionMessage::setCompletionReply(&reply, actionId, true, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
}
|
}
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||||
ActionId_t replyId, SerializeIF* data, bool hideSender) {
|
ActionId_t replyId, SerializeIF* data, bool hideSender) {
|
||||||
CommandMessage reply;
|
|
||||||
store_address_t storeAddress;
|
|
||||||
uint8_t *dataPtr;
|
|
||||||
size_t maxSize = data->getSerializedSize();
|
|
||||||
if (maxSize == 0) {
|
|
||||||
//No error, there's simply nothing to report.
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
size_t size = 0;
|
|
||||||
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
|
|
||||||
&dataPtr);
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = data->serialize(&dataPtr, &size, maxSize,
|
|
||||||
SerializeIF::Endianness::BIG);
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
ipcStore->deleteData(storeAddress);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
// We don't need to report the objectId, as we receive REQUESTED data
|
|
||||||
// before the completion success message.
|
|
||||||
// True aperiodic replies need to be reported with
|
|
||||||
// another dedicated message.
|
|
||||||
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
|
||||||
|
|
||||||
// If the sender needs to be hidden, for example to handle packet
|
|
||||||
// as unrequested reply, this will be done here.
|
|
||||||
if (hideSender) {
|
|
||||||
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = queueToUse->sendMessage(reportTo, &reply);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
|
||||||
ipcStore->deleteData(storeAddress);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ActionHelper::resetHelper() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
|
||||||
ActionId_t replyId, const uint8_t *data, size_t dataSize,
|
|
||||||
bool hideSender) {
|
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
store_address_t storeAddress;
|
store_address_t storeAddress;
|
||||||
ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize);
|
uint8_t *dataPtr;
|
||||||
|
size_t maxSize = data->getSerializedSize();
|
||||||
|
if (maxSize == 0) {
|
||||||
|
/* No error, there's simply nothing to report. */
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
size_t size = 0;
|
||||||
|
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
|
||||||
|
&dataPtr);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ActionHelper::reportData: Getting free element from IPC store failed!" <<
|
||||||
|
std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ActionHelper::reportData: Getting free element from IPC "
|
||||||
|
"store failed!\n");
|
||||||
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
result = data->serialize(&dataPtr, &size, maxSize,
|
||||||
|
SerializeIF::Endianness::BIG);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeAddress);
|
ipcStore->deleteData(storeAddress);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't need to report the objectId, as we receive REQUESTED data
|
/* We don't need to report the objectId, as we receive REQUESTED data before the completion
|
||||||
// before the completion success message.
|
success message. True aperiodic replies need to be reported with another dedicated message. */
|
||||||
// True aperiodic replies need to be reported with
|
|
||||||
// another dedicated message.
|
|
||||||
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
||||||
|
|
||||||
// If the sender needs to be hidden, for example to handle packet
|
/* If the sender needs to be hidden, for example to handle packet
|
||||||
// as unrequested reply, this will be done here.
|
as unrequested reply, this will be done here. */
|
||||||
if (hideSender) {
|
if (hideSender) {
|
||||||
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
@@ -160,3 +128,40 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ActionHelper::resetHelper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||||
|
ActionId_t replyId, const uint8_t *data, size_t dataSize,
|
||||||
|
bool hideSender) {
|
||||||
|
CommandMessage reply;
|
||||||
|
store_address_t storeAddress;
|
||||||
|
ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ActionHelper::reportData: Adding data to IPC store failed!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ActionHelper::reportData: Adding data to IPC store failed!\n");
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We don't need to report the objectId, as we receive REQUESTED data before the completion
|
||||||
|
success message. True aperiodic replies need to be reported with another dedicated message. */
|
||||||
|
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
||||||
|
|
||||||
|
/* If the sender needs to be hidden, for example to handle packet
|
||||||
|
as unrequested reply, this will be done here. */
|
||||||
|
if (hideSender) {
|
||||||
|
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = queueToUse->sendMessage(reportTo, &reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
ipcStore->deleteData(storeAddress);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@@ -18,68 +18,68 @@ class HasActionsIF;
|
|||||||
|
|
||||||
class ActionHelper {
|
class ActionHelper {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor of the action helper
|
* Constructor of the action helper
|
||||||
* @param setOwner Pointer to the owner of the interface
|
* @param setOwner Pointer to the owner of the interface
|
||||||
* @param useThisQueue messageQueue to be used, can be set during
|
* @param useThisQueue messageQueue to be used, can be set during
|
||||||
* initialize function as well.
|
* initialize function as well.
|
||||||
*/
|
*/
|
||||||
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||||
|
|
||||||
virtual ~ActionHelper();
|
virtual ~ActionHelper();
|
||||||
/**
|
/**
|
||||||
* Function to be called from the owner with a new command message
|
* Function to be called from the owner with a new command message
|
||||||
*
|
*
|
||||||
* If the message is a valid action message the helper will use the
|
* If the message is a valid action message the helper will use the
|
||||||
* executeAction function from HasActionsIF.
|
* executeAction function from HasActionsIF.
|
||||||
* If the message is invalid or the callback fails a message reply will be
|
* If the message is invalid or the callback fails a message reply will be
|
||||||
* send to the sender of the message automatically.
|
* send to the sender of the message automatically.
|
||||||
*
|
*
|
||||||
* @param command Pointer to a command message received by the owner
|
* @param command Pointer to a command message received by the owner
|
||||||
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message,
|
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message,
|
||||||
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
||||||
*/
|
*/
|
||||||
ReturnValue_t handleActionMessage(CommandMessage* command);
|
ReturnValue_t handleActionMessage(CommandMessage* command);
|
||||||
/**
|
/**
|
||||||
* Helper initialize function. Must be called before use of any other
|
* Helper initialize function. Must be called before use of any other
|
||||||
* helper function
|
* helper function
|
||||||
* @param queueToUse_ Pointer to the messageQueue to be used, optional
|
* @param queueToUse_ Pointer to the messageQueue to be used, optional
|
||||||
* if queue was set in constructor
|
* if queue was set in constructor
|
||||||
* @return Returns RETURN_OK if successful
|
* @return Returns RETURN_OK if successful
|
||||||
*/
|
*/
|
||||||
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
||||||
/**
|
/**
|
||||||
* Function to be called from the owner to send a step message.
|
* Function to be called from the owner to send a step message.
|
||||||
* Success or failure will be determined by the result value.
|
* Success or failure will be determined by the result value.
|
||||||
*
|
*
|
||||||
* @param step Number of steps already done
|
* @param step Number of steps already done
|
||||||
* @param reportTo The messageQueueId to report the step message to
|
* @param reportTo The messageQueueId to report the step message to
|
||||||
* @param commandId ID of the executed command
|
* @param commandId ID of the executed command
|
||||||
* @param result Result of the execution
|
* @param result Result of the execution
|
||||||
*/
|
*/
|
||||||
void step(uint8_t step, MessageQueueId_t reportTo,
|
void step(uint8_t step, MessageQueueId_t reportTo,
|
||||||
ActionId_t commandId,
|
ActionId_t commandId,
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
/**
|
/**
|
||||||
* Function to be called by the owner to send a action completion message
|
* Function to be called by the owner to send a action completion message
|
||||||
*
|
* @param success Specify whether action was completed successfully or not.
|
||||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
* @param reportTo MessageQueueId_t to report the action completion message to
|
||||||
* @param commandId ID of the executed command
|
* @param commandId ID of the executed command
|
||||||
* @param result Result of the execution
|
* @param result Result of the execution
|
||||||
*/
|
*/
|
||||||
void finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
void finish(bool success, MessageQueueId_t reportTo, ActionId_t commandId,
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
/**
|
/**
|
||||||
* Function to be called by the owner if an action does report data.
|
* Function to be called by the owner if an action does report data.
|
||||||
* Takes a SerializeIF* pointer and serializes it into the IPC store.
|
* Takes a SerializeIF* pointer and serializes it into the IPC store.
|
||||||
* @param reportTo MessageQueueId_t to report the action completion
|
* @param reportTo MessageQueueId_t to report the action completion
|
||||||
* message to
|
* message to
|
||||||
* @param replyId ID of the executed command
|
* @param replyId ID of the executed command
|
||||||
* @param data Pointer to the data
|
* @param data Pointer to the data
|
||||||
* @return Returns RETURN_OK if successful, otherwise failure code
|
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||||
*/
|
*/
|
||||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
||||||
SerializeIF* data, bool hideSender = false);
|
SerializeIF* data, bool hideSender = false);
|
||||||
/**
|
/**
|
||||||
* Function to be called by the owner if an action does report data.
|
* Function to be called by the owner if an action does report data.
|
||||||
* Takes the raw data and writes it into the IPC store.
|
* Takes the raw data and writes it into the IPC store.
|
||||||
@@ -91,35 +91,36 @@ public:
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
||||||
const uint8_t* data, size_t dataSize, bool hideSender = false);
|
const uint8_t* data, size_t dataSize, bool hideSender = false);
|
||||||
/**
|
/**
|
||||||
* Function to setup the MessageQueueIF* of the helper. Can be used to
|
* Function to setup the MessageQueueIF* of the helper. Can be used to
|
||||||
* set the MessageQueueIF* if message queue is unavailable at construction
|
* set the MessageQueueIF* if message queue is unavailable at construction
|
||||||
* and initialize but must be setup before first call of other functions.
|
* and initialize but must be setup before first call of other functions.
|
||||||
* @param queue Queue to be used by the helper
|
* @param queue Queue to be used by the helper
|
||||||
*/
|
*/
|
||||||
void setQueueToUse(MessageQueueIF *queue);
|
void setQueueToUse(MessageQueueIF *queue);
|
||||||
protected:
|
protected:
|
||||||
//!< Increase of value of this per step
|
//! Increase of value of this per step
|
||||||
static const uint8_t STEP_OFFSET = 1;
|
static const uint8_t STEP_OFFSET = 1;
|
||||||
HasActionsIF* owner;//!< Pointer to the owner
|
//! Pointer to the owner
|
||||||
//! Queue to be used as response sender, has to be set in ctor or with
|
HasActionsIF* owner;
|
||||||
//! setQueueToUse
|
//! Queue to be used as response sender, has to be set in ctor or with
|
||||||
MessageQueueIF* queueToUse;
|
//! setQueueToUse
|
||||||
//! Pointer to an IPC Store, initialized during construction or
|
MessageQueueIF* queueToUse;
|
||||||
StorageManagerIF* ipcStore = nullptr;
|
//! Pointer to an IPC Store, initialized during construction or
|
||||||
|
StorageManagerIF* ipcStore = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal function called by handleActionMessage
|
* Internal function called by handleActionMessage
|
||||||
* @param commandedBy MessageQueueID of Commander
|
* @param commandedBy MessageQueueID of Commander
|
||||||
* @param actionId ID of action to be done
|
* @param actionId ID of action to be done
|
||||||
* @param dataAddress Address of additional data in IPC Store
|
* @param dataAddress Address of additional data in IPC Store
|
||||||
*/
|
*/
|
||||||
virtual void prepareExecution(MessageQueueId_t commandedBy,
|
virtual void prepareExecution(MessageQueueId_t commandedBy,
|
||||||
ActionId_t actionId, store_address_t dataAddress);
|
ActionId_t actionId, store_address_t dataAddress);
|
||||||
/**
|
/**
|
||||||
* @brief Default implementation is empty.
|
* @brief Default implementation is empty.
|
||||||
*/
|
*/
|
||||||
virtual void resetHelper();
|
virtual void resetHelper();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_ACTION_ACTIONHELPER_H_ */
|
#endif /* FSFW_ACTION_ACTIONHELPER_H_ */
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#include "ActionMessage.h"
|
#include "ActionMessage.h"
|
||||||
#include "HasActionsIF.h"
|
#include "HasActionsIF.h"
|
||||||
|
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManager.h"
|
||||||
#include "../storagemanager/StorageManagerIF.h"
|
#include "../storagemanager/StorageManagerIF.h"
|
||||||
|
|
||||||
ActionMessage::ActionMessage() {
|
ActionMessage::ActionMessage() {
|
||||||
@@ -11,71 +11,72 @@ ActionMessage::~ActionMessage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
|
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
|
||||||
store_address_t parameters) {
|
store_address_t parameters) {
|
||||||
message->setCommand(EXECUTE_ACTION);
|
message->setCommand(EXECUTE_ACTION);
|
||||||
message->setParameter(fid);
|
message->setParameter(fid);
|
||||||
message->setParameter2(parameters.raw);
|
message->setParameter2(parameters.raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionId_t ActionMessage::getActionId(const CommandMessage* message) {
|
ActionId_t ActionMessage::getActionId(const CommandMessage* message) {
|
||||||
return ActionId_t(message->getParameter());
|
return ActionId_t(message->getParameter());
|
||||||
}
|
}
|
||||||
|
|
||||||
store_address_t ActionMessage::getStoreId(const CommandMessage* message) {
|
store_address_t ActionMessage::getStoreId(const CommandMessage* message) {
|
||||||
store_address_t temp;
|
store_address_t temp;
|
||||||
temp.raw = message->getParameter2();
|
temp.raw = message->getParameter2();
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
||||||
ReturnValue_t result) {
|
ReturnValue_t result) {
|
||||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||||
message->setCommand(STEP_SUCCESS);
|
message->setCommand(STEP_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
message->setCommand(STEP_FAILED);
|
message->setCommand(STEP_FAILED);
|
||||||
}
|
}
|
||||||
message->setParameter(fid);
|
message->setParameter(fid);
|
||||||
message->setParameter2((step << 16) + result);
|
message->setParameter2((step << 16) + result);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ActionMessage::getStep(const CommandMessage* message) {
|
uint8_t ActionMessage::getStep(const CommandMessage* message) {
|
||||||
return uint8_t((message->getParameter2() >> 16) & 0xFF);
|
return uint8_t((message->getParameter2() >> 16) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ActionMessage::getReturnCode(const CommandMessage* message) {
|
ReturnValue_t ActionMessage::getReturnCode(const CommandMessage* message) {
|
||||||
return message->getParameter2() & 0xFFFF;
|
return message->getParameter2() & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionMessage::setDataReply(CommandMessage* message, ActionId_t actionId,
|
void ActionMessage::setDataReply(CommandMessage* message, ActionId_t actionId,
|
||||||
store_address_t data) {
|
store_address_t data) {
|
||||||
message->setCommand(DATA_REPLY);
|
message->setCommand(DATA_REPLY);
|
||||||
message->setParameter(actionId);
|
message->setParameter(actionId);
|
||||||
message->setParameter2(data.raw);
|
message->setParameter2(data.raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionMessage::setCompletionReply(CommandMessage* message,
|
void ActionMessage::setCompletionReply(CommandMessage* message,
|
||||||
ActionId_t fid, ReturnValue_t result) {
|
ActionId_t fid, bool success, ReturnValue_t result) {
|
||||||
if (result == HasReturnvaluesIF::RETURN_OK or result == HasActionsIF::EXECUTION_FINISHED) {
|
if (success) {
|
||||||
message->setCommand(COMPLETION_SUCCESS);
|
message->setCommand(COMPLETION_SUCCESS);
|
||||||
} else {
|
}
|
||||||
message->setCommand(COMPLETION_FAILED);
|
else {
|
||||||
}
|
message->setCommand(COMPLETION_FAILED);
|
||||||
message->setParameter(fid);
|
}
|
||||||
message->setParameter2(result);
|
message->setParameter(fid);
|
||||||
|
message->setParameter2(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionMessage::clear(CommandMessage* message) {
|
void ActionMessage::clear(CommandMessage* message) {
|
||||||
switch(message->getCommand()) {
|
switch(message->getCommand()) {
|
||||||
case EXECUTE_ACTION:
|
case EXECUTE_ACTION:
|
||||||
case DATA_REPLY: {
|
case DATA_REPLY: {
|
||||||
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
|
StorageManagerIF *ipcStore = ObjectManager::instance()->get<StorageManagerIF>(
|
||||||
objects::IPC_STORE);
|
objects::IPC_STORE);
|
||||||
if (ipcStore != NULL) {
|
if (ipcStore != NULL) {
|
||||||
ipcStore->deleteData(getStoreId(message));
|
ipcStore->deleteData(getStoreId(message));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,29 +15,33 @@ using ActionId_t = uint32_t;
|
|||||||
*/
|
*/
|
||||||
class ActionMessage {
|
class ActionMessage {
|
||||||
private:
|
private:
|
||||||
ActionMessage();
|
ActionMessage();
|
||||||
public:
|
public:
|
||||||
static const uint8_t MESSAGE_ID = messagetypes::ACTION;
|
static const uint8_t MESSAGE_ID = messagetypes::ACTION;
|
||||||
static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1);
|
static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1);
|
||||||
static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2);
|
static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2);
|
||||||
static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3);
|
static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3);
|
||||||
static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4);
|
static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4);
|
||||||
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
|
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
|
||||||
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
||||||
virtual ~ActionMessage();
|
|
||||||
static void setCommand(CommandMessage* message, ActionId_t fid,
|
virtual ~ActionMessage();
|
||||||
store_address_t parameters);
|
static void setCommand(CommandMessage* message, ActionId_t fid,
|
||||||
static ActionId_t getActionId(const CommandMessage* message );
|
store_address_t parameters);
|
||||||
static store_address_t getStoreId(const CommandMessage* message );
|
|
||||||
static void setStepReply(CommandMessage* message, ActionId_t fid,
|
static ActionId_t getActionId(const CommandMessage* message );
|
||||||
uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
static store_address_t getStoreId(const CommandMessage* message);
|
||||||
static uint8_t getStep(const CommandMessage* message );
|
|
||||||
static ReturnValue_t getReturnCode(const CommandMessage* message );
|
static void setStepReply(CommandMessage* message, ActionId_t fid,
|
||||||
static void setDataReply(CommandMessage* message, ActionId_t actionId,
|
uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
store_address_t data);
|
static uint8_t getStep(const CommandMessage* message );
|
||||||
static void setCompletionReply(CommandMessage* message, ActionId_t fid,
|
static ReturnValue_t getReturnCode(const CommandMessage* message );
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
static void setDataReply(CommandMessage* message, ActionId_t actionId,
|
||||||
static void clear(CommandMessage* message);
|
store_address_t data);
|
||||||
|
static void setCompletionReply(CommandMessage* message, ActionId_t fid,
|
||||||
|
bool success, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
|
|
||||||
|
static void clear(CommandMessage* message);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_ACTION_ACTIONMESSAGE_H_ */
|
#endif /* FSFW_ACTION_ACTIONMESSAGE_H_ */
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
ActionHelper.cpp
|
ActionHelper.cpp
|
||||||
ActionMessage.cpp
|
ActionMessage.cpp
|
||||||
CommandActionHelper.cpp
|
CommandActionHelper.cpp
|
||||||
SimpleActionHelper.cpp
|
SimpleActionHelper.cpp
|
||||||
)
|
)
|
@@ -2,126 +2,127 @@
|
|||||||
#include "CommandActionHelper.h"
|
#include "CommandActionHelper.h"
|
||||||
#include "CommandsActionsIF.h"
|
#include "CommandsActionsIF.h"
|
||||||
#include "HasActionsIF.h"
|
#include "HasActionsIF.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
|
||||||
|
#include "../objectmanager/ObjectManager.h"
|
||||||
|
|
||||||
CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) :
|
CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) :
|
||||||
owner(setOwner), queueToUse(NULL), ipcStore(
|
owner(setOwner), queueToUse(NULL), ipcStore(
|
||||||
NULL), commandCount(0), lastTarget(0) {
|
NULL), commandCount(0), lastTarget(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandActionHelper::~CommandActionHelper() {
|
CommandActionHelper::~CommandActionHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
||||||
ActionId_t actionId, SerializeIF *data) {
|
ActionId_t actionId, SerializeIF *data) {
|
||||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
HasActionsIF *receiver = ObjectManager::instance()->get<HasActionsIF>(commandTo);
|
||||||
if (receiver == NULL) {
|
if (receiver == NULL) {
|
||||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||||
}
|
}
|
||||||
store_address_t storeId;
|
store_address_t storeId;
|
||||||
uint8_t *storePointer;
|
uint8_t *storePointer;
|
||||||
size_t maxSize = data->getSerializedSize();
|
size_t maxSize = data->getSerializedSize();
|
||||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize,
|
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize,
|
||||||
&storePointer);
|
&storePointer);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
result = data->serialize(&storePointer, &size, maxSize,
|
result = data->serialize(&storePointer, &size, maxSize,
|
||||||
SerializeIF::Endianness::BIG);
|
SerializeIF::Endianness::BIG);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
||||||
ActionId_t actionId, const uint8_t *data, uint32_t size) {
|
ActionId_t actionId, const uint8_t *data, uint32_t size) {
|
||||||
// if (commandCount != 0) {
|
// if (commandCount != 0) {
|
||||||
// return CommandsFunctionsIF::ALREADY_COMMANDING;
|
// return CommandsFunctionsIF::ALREADY_COMMANDING;
|
||||||
// }
|
// }
|
||||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
HasActionsIF *receiver = ObjectManager::instance()->get<HasActionsIF>(commandTo);
|
||||||
if (receiver == NULL) {
|
if (receiver == NULL) {
|
||||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||||
}
|
}
|
||||||
store_address_t storeId;
|
store_address_t storeId;
|
||||||
ReturnValue_t result = ipcStore->addData(&storeId, data, size);
|
ReturnValue_t result = ipcStore->addData(&storeId, data, size);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId,
|
ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId,
|
||||||
ActionId_t actionId, store_address_t storeId) {
|
ActionId_t actionId, store_address_t storeId) {
|
||||||
CommandMessage command;
|
CommandMessage command;
|
||||||
ActionMessage::setCommand(&command, actionId, storeId);
|
ActionMessage::setCommand(&command, actionId, storeId);
|
||||||
ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
|
ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeId);
|
ipcStore->deleteData(storeId);
|
||||||
}
|
}
|
||||||
lastTarget = queueId;
|
lastTarget = queueId;
|
||||||
commandCount++;
|
commandCount++;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::initialize() {
|
ReturnValue_t CommandActionHelper::initialize() {
|
||||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||||
if (ipcStore == NULL) {
|
if (ipcStore == NULL) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
queueToUse = owner->getCommandQueuePtr();
|
queueToUse = owner->getCommandQueuePtr();
|
||||||
if (queueToUse == NULL) {
|
if (queueToUse == NULL) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
||||||
if (reply->getSender() != lastTarget) {
|
if (reply->getSender() != lastTarget) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
switch (reply->getCommand()) {
|
switch (reply->getCommand()) {
|
||||||
case ActionMessage::COMPLETION_SUCCESS:
|
case ActionMessage::COMPLETION_SUCCESS:
|
||||||
commandCount--;
|
commandCount--;
|
||||||
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::COMPLETION_FAILED:
|
case ActionMessage::COMPLETION_FAILED:
|
||||||
commandCount--;
|
commandCount--;
|
||||||
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
||||||
ActionMessage::getReturnCode(reply));
|
ActionMessage::getReturnCode(reply));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::STEP_SUCCESS:
|
case ActionMessage::STEP_SUCCESS:
|
||||||
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
||||||
ActionMessage::getStep(reply));
|
ActionMessage::getStep(reply));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::STEP_FAILED:
|
case ActionMessage::STEP_FAILED:
|
||||||
commandCount--;
|
commandCount--;
|
||||||
owner->stepFailedReceived(ActionMessage::getActionId(reply),
|
owner->stepFailedReceived(ActionMessage::getActionId(reply),
|
||||||
ActionMessage::getStep(reply),
|
ActionMessage::getStep(reply),
|
||||||
ActionMessage::getReturnCode(reply));
|
ActionMessage::getReturnCode(reply));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::DATA_REPLY:
|
case ActionMessage::DATA_REPLY:
|
||||||
extractDataForOwner(ActionMessage::getActionId(reply),
|
extractDataForOwner(ActionMessage::getActionId(reply),
|
||||||
ActionMessage::getStoreId(reply));
|
ActionMessage::getStoreId(reply));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
default:
|
default:
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CommandActionHelper::getCommandCount() const {
|
uint8_t CommandActionHelper::getCommandCount() const {
|
||||||
return commandCount;
|
return commandCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) {
|
void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) {
|
||||||
const uint8_t * data = NULL;
|
const uint8_t * data = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
owner->dataReceived(actionId, data, size);
|
owner->dataReceived(actionId, data, size);
|
||||||
ipcStore->deleteData(storeId);
|
ipcStore->deleteData(storeId);
|
||||||
}
|
}
|
||||||
|
@@ -11,26 +11,26 @@
|
|||||||
class CommandsActionsIF;
|
class CommandsActionsIF;
|
||||||
|
|
||||||
class CommandActionHelper {
|
class CommandActionHelper {
|
||||||
friend class CommandsActionsIF;
|
friend class CommandsActionsIF;
|
||||||
public:
|
public:
|
||||||
CommandActionHelper(CommandsActionsIF* owner);
|
CommandActionHelper(CommandsActionsIF* owner);
|
||||||
virtual ~CommandActionHelper();
|
virtual ~CommandActionHelper();
|
||||||
ReturnValue_t commandAction(object_id_t commandTo,
|
ReturnValue_t commandAction(object_id_t commandTo,
|
||||||
ActionId_t actionId, const uint8_t* data, uint32_t size);
|
ActionId_t actionId, const uint8_t* data, uint32_t size);
|
||||||
ReturnValue_t commandAction(object_id_t commandTo,
|
ReturnValue_t commandAction(object_id_t commandTo,
|
||||||
ActionId_t actionId, SerializeIF* data);
|
ActionId_t actionId, SerializeIF* data);
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize();
|
||||||
ReturnValue_t handleReply(CommandMessage* reply);
|
ReturnValue_t handleReply(CommandMessage* reply);
|
||||||
uint8_t getCommandCount() const;
|
uint8_t getCommandCount() const;
|
||||||
private:
|
private:
|
||||||
CommandsActionsIF* owner;
|
CommandsActionsIF* owner;
|
||||||
MessageQueueIF* queueToUse;
|
MessageQueueIF* queueToUse;
|
||||||
StorageManagerIF* ipcStore;
|
StorageManagerIF* ipcStore;
|
||||||
uint8_t commandCount;
|
uint8_t commandCount;
|
||||||
MessageQueueId_t lastTarget;
|
MessageQueueId_t lastTarget;
|
||||||
void extractDataForOwner(ActionId_t actionId, store_address_t storeId);
|
void extractDataForOwner(ActionId_t actionId, store_address_t storeId);
|
||||||
ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId,
|
ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId,
|
||||||
store_address_t storeId);
|
store_address_t storeId);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* COMMANDACTIONHELPER_H_ */
|
#endif /* COMMANDACTIONHELPER_H_ */
|
||||||
|
@@ -15,22 +15,22 @@
|
|||||||
* - replyReceived(id, step, cause) (if cause == OK, it's a success).
|
* - replyReceived(id, step, cause) (if cause == OK, it's a success).
|
||||||
*/
|
*/
|
||||||
class CommandsActionsIF {
|
class CommandsActionsIF {
|
||||||
friend class CommandActionHelper;
|
friend class CommandActionHelper;
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF;
|
||||||
static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1);
|
||||||
static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2);
|
static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2);
|
||||||
virtual ~CommandsActionsIF() {}
|
virtual ~CommandsActionsIF() {}
|
||||||
virtual MessageQueueIF* getCommandQueuePtr() = 0;
|
virtual MessageQueueIF* getCommandQueuePtr() = 0;
|
||||||
protected:
|
protected:
|
||||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
|
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
|
||||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||||
ReturnValue_t returnCode) = 0;
|
ReturnValue_t returnCode) = 0;
|
||||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
|
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||||
uint32_t size) = 0;
|
uint32_t size) = 0;
|
||||||
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
|
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
|
||||||
virtual void completionFailedReceived(ActionId_t actionId,
|
virtual void completionFailedReceived(ActionId_t actionId,
|
||||||
ReturnValue_t returnCode) = 0;
|
ReturnValue_t returnCode) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -35,28 +35,28 @@
|
|||||||
*/
|
*/
|
||||||
class HasActionsIF {
|
class HasActionsIF {
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF;
|
||||||
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);
|
||||||
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
|
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
|
||||||
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
|
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
|
||||||
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
||||||
virtual ~HasActionsIF() { }
|
virtual ~HasActionsIF() { }
|
||||||
/**
|
/**
|
||||||
* Function to get the MessageQueueId_t of the implementing object
|
* Function to get the MessageQueueId_t of the implementing object
|
||||||
* @return MessageQueueId_t of the object
|
* @return MessageQueueId_t of the object
|
||||||
*/
|
*/
|
||||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
/**
|
/**
|
||||||
* Execute or initialize the execution of a certain function.
|
* Execute or initialize the execution of a certain function.
|
||||||
* The ActionHelpers will execute this function and behave differently
|
* The ActionHelpers will execute this function and behave differently
|
||||||
* depending on the returnvalue.
|
* depending on the returnvalue.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* -@c EXECUTION_FINISHED Finish reply will be generated
|
* -@c EXECUTION_FINISHED Finish reply will be generated
|
||||||
* -@c Not RETURN_OK Step failure reply will be generated
|
* -@c Not RETURN_OK Step failure reply will be generated
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
||||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
|
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2,74 +2,74 @@
|
|||||||
#include "SimpleActionHelper.h"
|
#include "SimpleActionHelper.h"
|
||||||
|
|
||||||
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
|
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
|
||||||
MessageQueueIF* useThisQueue) :
|
MessageQueueIF* useThisQueue) :
|
||||||
ActionHelper(setOwner, useThisQueue), isExecuting(false) {
|
ActionHelper(setOwner, useThisQueue), isExecuting(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleActionHelper::~SimpleActionHelper() {
|
SimpleActionHelper::~SimpleActionHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleActionHelper::step(ReturnValue_t result) {
|
void SimpleActionHelper::step(ReturnValue_t result) {
|
||||||
// STEP_OFFESET is subtracted to compensate for adding offset in base
|
// STEP_OFFESET is subtracted to compensate for adding offset in base
|
||||||
// method, which is not necessary here.
|
// method, which is not necessary here.
|
||||||
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
|
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
|
||||||
result);
|
result);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
resetHelper();
|
resetHelper();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleActionHelper::finish(ReturnValue_t result) {
|
void SimpleActionHelper::finish(ReturnValue_t result) {
|
||||||
ActionHelper::finish(lastCommander, lastAction, result);
|
ActionHelper::finish(lastCommander, lastAction, result);
|
||||||
resetHelper();
|
resetHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) {
|
ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) {
|
||||||
return ActionHelper::reportData(lastCommander, lastAction, data);
|
return ActionHelper::reportData(lastCommander, lastAction, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleActionHelper::resetHelper() {
|
void SimpleActionHelper::resetHelper() {
|
||||||
stepCount = 0;
|
stepCount = 0;
|
||||||
isExecuting = false;
|
isExecuting = false;
|
||||||
lastAction = 0;
|
lastAction = 0;
|
||||||
lastCommander = 0;
|
lastCommander = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
||||||
ActionId_t actionId, store_address_t dataAddress) {
|
ActionId_t actionId, store_address_t dataAddress) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
if (isExecuting) {
|
if (isExecuting) {
|
||||||
ipcStore->deleteData(dataAddress);
|
ipcStore->deleteData(dataAddress);
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0,
|
ActionMessage::setStepReply(&reply, actionId, 0,
|
||||||
HasActionsIF::IS_BUSY);
|
HasActionsIF::IS_BUSY);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
}
|
}
|
||||||
const uint8_t* dataPtr = NULL;
|
const uint8_t* dataPtr = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastCommander = commandedBy;
|
lastCommander = commandedBy;
|
||||||
lastAction = actionId;
|
lastAction = actionId;
|
||||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||||
ipcStore->deleteData(dataAddress);
|
ipcStore->deleteData(dataAddress);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case HasReturnvaluesIF::RETURN_OK:
|
case HasReturnvaluesIF::RETURN_OK:
|
||||||
isExecuting = true;
|
isExecuting = true;
|
||||||
stepCount++;
|
stepCount++;
|
||||||
break;
|
break;
|
||||||
case HasActionsIF::EXECUTION_FINISHED:
|
case HasActionsIF::EXECUTION_FINISHED:
|
||||||
ActionMessage::setCompletionReply(&reply, actionId,
|
ActionMessage::setCompletionReply(&reply, actionId,
|
||||||
HasReturnvaluesIF::RETURN_OK);
|
true, HasReturnvaluesIF::RETURN_OK);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -4,27 +4,27 @@
|
|||||||
#include "ActionHelper.h"
|
#include "ActionHelper.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is an action helper which is only able to service one action
|
* @brief This is an action helper which is only able to service one action
|
||||||
* at a time but remembers last commander and last action which
|
* at a time but remembers last commander and last action which
|
||||||
* simplifies usage
|
* simplifies usage
|
||||||
*/
|
*/
|
||||||
class SimpleActionHelper: public ActionHelper {
|
class SimpleActionHelper: public ActionHelper {
|
||||||
public:
|
public:
|
||||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||||
virtual ~SimpleActionHelper();
|
virtual ~SimpleActionHelper();
|
||||||
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
ReturnValue_t reportData(SerializeIF* data);
|
ReturnValue_t reportData(SerializeIF* data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||||
store_address_t dataAddress);
|
store_address_t dataAddress);
|
||||||
virtual void resetHelper();
|
virtual void resetHelper();
|
||||||
private:
|
private:
|
||||||
bool isExecuting;
|
bool isExecuting;
|
||||||
MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE;
|
||||||
ActionId_t lastAction = 0;
|
ActionId_t lastAction = 0;
|
||||||
uint8_t stepCount = 0;
|
uint8_t stepCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SIMPLEACTIONHELPER_H_ */
|
#endif /* SIMPLEACTIONHELPER_H_ */
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
#include "../serialize/SerializeIF.h"
|
#include "../serialize/SerializeIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A List that stores its values in an array.
|
* @brief A List that stores its values in an array.
|
||||||
* @details
|
* @details
|
||||||
* The underlying storage is an array that can be allocated by the class
|
* The underlying storage is an array that can be allocated by the class
|
||||||
* itself or supplied via ctor.
|
* itself or supplied via ctor.
|
||||||
@@ -15,237 +15,237 @@
|
|||||||
*/
|
*/
|
||||||
template<typename T, typename count_t = uint8_t>
|
template<typename T, typename count_t = uint8_t>
|
||||||
class ArrayList {
|
class ArrayList {
|
||||||
template<typename U, typename count> friend class SerialArrayListAdapter;
|
template<typename U, typename count> friend class SerialArrayListAdapter;
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
|
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
|
||||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
|
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the allocating constructor.
|
* This is the allocating constructor.
|
||||||
* It allocates an array of the specified size.
|
* It allocates an array of the specified size.
|
||||||
* @param maxSize
|
* @param maxSize
|
||||||
*/
|
*/
|
||||||
ArrayList(count_t maxSize) :
|
ArrayList(count_t maxSize) :
|
||||||
size(0), maxSize_(maxSize), allocated(true) {
|
size(0), maxSize_(maxSize), allocated(true) {
|
||||||
entries = new T[maxSize];
|
entries = new T[maxSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the non-allocating constructor
|
* This is the non-allocating constructor
|
||||||
*
|
*
|
||||||
* It expects a pointer to an array of a certain size and initializes
|
* It expects a pointer to an array of a certain size and initializes
|
||||||
* itself to it.
|
* itself to it.
|
||||||
*
|
*
|
||||||
* @param storage the array to use as backend
|
* @param storage the array to use as backend
|
||||||
* @param maxSize size of storage
|
* @param maxSize size of storage
|
||||||
* @param size size of data already present in storage
|
* @param size size of data already present in storage
|
||||||
*/
|
*/
|
||||||
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
|
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
|
||||||
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
|
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copying is forbiden by declaring copy ctor and copy assignment deleted
|
* Copying is forbiden by declaring copy ctor and copy assignment deleted
|
||||||
* It is too ambigous in this case.
|
* It is too ambigous in this case.
|
||||||
* (Allocate a new backend? Use the same? What to do in an modifying call?)
|
* (Allocate a new backend? Use the same? What to do in an modifying call?)
|
||||||
*/
|
*/
|
||||||
ArrayList(const ArrayList& other) = delete;
|
ArrayList(const ArrayList& other) = delete;
|
||||||
const ArrayList& operator=(const ArrayList& other) = delete;
|
const ArrayList& operator=(const ArrayList& other) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of Elements stored in this List
|
* Number of Elements stored in this List
|
||||||
*/
|
*/
|
||||||
count_t size;
|
count_t size;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor, if the allocating constructor was used, it deletes the array.
|
* Destructor, if the allocating constructor was used, it deletes the array.
|
||||||
*/
|
*/
|
||||||
virtual ~ArrayList() {
|
virtual ~ArrayList() {
|
||||||
if (allocated) {
|
if (allocated) {
|
||||||
delete[] entries;
|
delete[] entries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Iterator to go trough an ArrayList
|
* An Iterator to go trough an ArrayList
|
||||||
*
|
*
|
||||||
* It stores a pointer to an element and increments the
|
* It stores a pointer to an element and increments the
|
||||||
* pointer when incremented itself.
|
* pointer when incremented itself.
|
||||||
*/
|
*/
|
||||||
class Iterator {
|
class Iterator {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Empty ctor, points to NULL
|
* Empty ctor, points to NULL
|
||||||
*/
|
*/
|
||||||
Iterator(): value(0) {}
|
Iterator(): value(0) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the Iterator to point to an element
|
* Initializes the Iterator to point to an element
|
||||||
*
|
*
|
||||||
* @param initialize
|
* @param initialize
|
||||||
*/
|
*/
|
||||||
Iterator(T *initialize) {
|
Iterator(T *initialize) {
|
||||||
value = initialize;
|
value = initialize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current element the iterator points to
|
* The current element the iterator points to
|
||||||
*/
|
*/
|
||||||
T *value;
|
T *value;
|
||||||
|
|
||||||
Iterator& operator++() {
|
Iterator& operator++() {
|
||||||
value++;
|
value++;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator operator++(int) {
|
Iterator operator++(int) {
|
||||||
Iterator tmp(*this);
|
Iterator tmp(*this);
|
||||||
operator++();
|
operator++();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator& operator--() {
|
Iterator& operator--() {
|
||||||
value--;
|
value--;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator operator--(int) {
|
Iterator operator--(int) {
|
||||||
Iterator tmp(*this);
|
Iterator tmp(*this);
|
||||||
operator--();
|
operator--();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator*() {
|
T& operator*() {
|
||||||
return *value;
|
return *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator*() const {
|
const T& operator*() const {
|
||||||
return *value;
|
return *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *operator->() {
|
T *operator->() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T *operator->() const {
|
const T *operator->() const {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
friend bool operator==(const ArrayList::Iterator& lhs,
|
friend bool operator==(const ArrayList::Iterator& lhs,
|
||||||
const ArrayList::Iterator& rhs) {
|
const ArrayList::Iterator& rhs) {
|
||||||
return (lhs.value == rhs.value);
|
return (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const ArrayList::Iterator& lhs,
|
friend bool operator!=(const ArrayList::Iterator& lhs,
|
||||||
const ArrayList::Iterator& rhs) {
|
const ArrayList::Iterator& rhs) {
|
||||||
return not (lhs.value == rhs.value);
|
return not (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterator pointing to the first stored elmement
|
* Iterator pointing to the first stored elmement
|
||||||
*
|
*
|
||||||
* @return Iterator to the first element
|
* @return Iterator to the first element
|
||||||
*/
|
*/
|
||||||
Iterator begin() const {
|
Iterator begin() const {
|
||||||
return Iterator(&entries[0]);
|
return Iterator(&entries[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns an Iterator pointing to the element after the last stored entry
|
* returns an Iterator pointing to the element after the last stored entry
|
||||||
*
|
*
|
||||||
* @return Iterator to the element after the last entry
|
* @return Iterator to the element after the last entry
|
||||||
*/
|
*/
|
||||||
Iterator end() const {
|
Iterator end() const {
|
||||||
return Iterator(&entries[size]);
|
return Iterator(&entries[size]);
|
||||||
}
|
}
|
||||||
|
|
||||||
T & operator[](count_t i) const {
|
T & operator[](count_t i) const {
|
||||||
return entries[i];
|
return entries[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The first element
|
* The first element
|
||||||
*
|
*
|
||||||
* @return pointer to the first stored element
|
* @return pointer to the first stored element
|
||||||
*/
|
*/
|
||||||
T *front() {
|
T *front() {
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last element
|
* The last element
|
||||||
*
|
*
|
||||||
* does not return a valid pointer if called on an empty list.
|
* does not return a valid pointer if called on an empty list.
|
||||||
*
|
*
|
||||||
* @return pointer to the last stored element
|
* @return pointer to the last stored element
|
||||||
*/
|
*/
|
||||||
T *back() {
|
T *back() {
|
||||||
return &entries[size - 1];
|
return &entries[size - 1];
|
||||||
//Alternative solution
|
//Alternative solution
|
||||||
//return const_cast<T*>(static_cast<const T*>(*this).back());
|
//return const_cast<T*>(static_cast<const T*>(*this).back());
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* back() const{
|
const T* back() const{
|
||||||
return &entries[size-1];
|
return &entries[size-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of elements this List can contain
|
* The maximum number of elements this List can contain
|
||||||
*
|
*
|
||||||
* @return maximum number of elements
|
* @return maximum number of elements
|
||||||
*/
|
*/
|
||||||
size_t maxSize() const {
|
size_t maxSize() const {
|
||||||
return this->maxSize_;
|
return this->maxSize_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert a new element into the list.
|
* Insert a new element into the list.
|
||||||
*
|
*
|
||||||
* The new element is inserted after the last stored element.
|
* The new element is inserted after the last stored element.
|
||||||
*
|
*
|
||||||
* @param entry
|
* @param entry
|
||||||
* @return
|
* @return
|
||||||
* -@c FULL if the List is full
|
* -@c FULL if the List is full
|
||||||
* -@c RETURN_OK else
|
* -@c RETURN_OK else
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insert(T entry) {
|
ReturnValue_t insert(T entry) {
|
||||||
if (size >= maxSize_) {
|
if (size >= maxSize_) {
|
||||||
return FULL;
|
return FULL;
|
||||||
}
|
}
|
||||||
entries[size] = entry;
|
entries[size] = entry;
|
||||||
++size;
|
++size;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clear the List
|
* clear the List
|
||||||
*
|
*
|
||||||
* This does not actually clear all entries, it only sets the size to 0.
|
* This does not actually clear all entries, it only sets the size to 0.
|
||||||
*/
|
*/
|
||||||
void clear() {
|
void clear() {
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
count_t remaining() {
|
count_t remaining() {
|
||||||
return (maxSize_ - size);
|
return (maxSize_ - size);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* pointer to the array in which the entries are stored
|
* pointer to the array in which the entries are stored
|
||||||
*/
|
*/
|
||||||
T *entries;
|
T *entries;
|
||||||
/**
|
/**
|
||||||
* remembering the maximum size
|
* remembering the maximum size
|
||||||
*/
|
*/
|
||||||
size_t maxSize_;
|
size_t maxSize_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* true if the array was allocated and needs to be deleted in the destructor.
|
* true if the array was allocated and needs to be deleted in the destructor.
|
||||||
*/
|
*/
|
||||||
bool allocated;
|
bool allocated;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -7,65 +7,65 @@
|
|||||||
template<typename Tp>
|
template<typename Tp>
|
||||||
class BinaryNode {
|
class BinaryNode {
|
||||||
public:
|
public:
|
||||||
BinaryNode(Tp* setValue) :
|
BinaryNode(Tp* setValue) :
|
||||||
value(setValue), left(NULL), right(NULL), parent(NULL) {
|
value(setValue), left(NULL), right(NULL), parent(NULL) {
|
||||||
}
|
}
|
||||||
Tp *value;
|
Tp *value;
|
||||||
BinaryNode* left;
|
BinaryNode* left;
|
||||||
BinaryNode* right;
|
BinaryNode* right;
|
||||||
BinaryNode* parent;
|
BinaryNode* parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Tp>
|
template<typename Tp>
|
||||||
class ExplicitNodeIterator {
|
class ExplicitNodeIterator {
|
||||||
public:
|
public:
|
||||||
typedef ExplicitNodeIterator<Tp> _Self;
|
typedef ExplicitNodeIterator<Tp> _Self;
|
||||||
typedef BinaryNode<Tp> _Node;
|
typedef BinaryNode<Tp> _Node;
|
||||||
typedef Tp value_type;
|
typedef Tp value_type;
|
||||||
typedef Tp* pointer;
|
typedef Tp* pointer;
|
||||||
typedef Tp& reference;
|
typedef Tp& reference;
|
||||||
ExplicitNodeIterator() :
|
ExplicitNodeIterator() :
|
||||||
element(NULL) {
|
element(NULL) {
|
||||||
}
|
}
|
||||||
ExplicitNodeIterator(_Node* node) :
|
ExplicitNodeIterator(_Node* node) :
|
||||||
element(node) {
|
element(node) {
|
||||||
}
|
}
|
||||||
BinaryNode<Tp>* element;
|
BinaryNode<Tp>* element;
|
||||||
_Self up() {
|
_Self up() {
|
||||||
return _Self(element->parent);
|
return _Self(element->parent);
|
||||||
}
|
}
|
||||||
_Self left() {
|
_Self left() {
|
||||||
if (element != NULL) {
|
if (element != NULL) {
|
||||||
return _Self(element->left);
|
return _Self(element->left);
|
||||||
} else {
|
} else {
|
||||||
return _Self(NULL);
|
return _Self(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
_Self right() {
|
_Self right() {
|
||||||
if (element != NULL) {
|
if (element != NULL) {
|
||||||
return _Self(element->right);
|
return _Self(element->right);
|
||||||
} else {
|
} else {
|
||||||
return _Self(NULL);
|
return _Self(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
bool operator==(const _Self& __x) const {
|
bool operator==(const _Self& __x) const {
|
||||||
return element == __x.element;
|
return element == __x.element;
|
||||||
}
|
}
|
||||||
bool operator!=(const _Self& __x) const {
|
bool operator!=(const _Self& __x) const {
|
||||||
return element != __x.element;
|
return element != __x.element;
|
||||||
}
|
}
|
||||||
pointer
|
pointer
|
||||||
operator->() const {
|
operator->() const {
|
||||||
if (element != NULL) {
|
if (element != NULL) {
|
||||||
return element->value;
|
return element->value;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pointer operator*() const {
|
pointer operator*() const {
|
||||||
return this->operator->();
|
return this->operator->();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,77 +75,77 @@ public:
|
|||||||
template<typename Tp>
|
template<typename Tp>
|
||||||
class BinaryTree {
|
class BinaryTree {
|
||||||
public:
|
public:
|
||||||
typedef ExplicitNodeIterator<Tp> iterator;
|
typedef ExplicitNodeIterator<Tp> iterator;
|
||||||
typedef BinaryNode<Tp> Node;
|
typedef BinaryNode<Tp> Node;
|
||||||
typedef std::pair<iterator, iterator> children;
|
typedef std::pair<iterator, iterator> children;
|
||||||
BinaryTree() :
|
BinaryTree() :
|
||||||
rootNode(NULL) {
|
rootNode(NULL) {
|
||||||
}
|
}
|
||||||
BinaryTree(Node* rootNode) :
|
BinaryTree(Node* rootNode) :
|
||||||
rootNode(rootNode) {
|
rootNode(rootNode) {
|
||||||
}
|
}
|
||||||
iterator begin() const {
|
iterator begin() const {
|
||||||
return iterator(rootNode);
|
return iterator(rootNode);
|
||||||
}
|
}
|
||||||
static iterator end() {
|
static iterator end() {
|
||||||
return iterator(NULL);
|
return iterator(NULL);
|
||||||
}
|
}
|
||||||
iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) {
|
iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) {
|
||||||
newNode->parent = parentNode.element;
|
newNode->parent = parentNode.element;
|
||||||
if (parentNode.element != NULL) {
|
if (parentNode.element != NULL) {
|
||||||
if (insertLeft) {
|
if (insertLeft) {
|
||||||
parentNode.element->left = newNode;
|
parentNode.element->left = newNode;
|
||||||
} else {
|
} else {
|
||||||
parentNode.element->right = newNode;
|
parentNode.element->right = newNode;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Insert first element.
|
//Insert first element.
|
||||||
rootNode = newNode;
|
rootNode = newNode;
|
||||||
}
|
}
|
||||||
return iterator(newNode);
|
return iterator(newNode);
|
||||||
}
|
}
|
||||||
//No recursion to children. Needs to be done externally.
|
//No recursion to children. Needs to be done externally.
|
||||||
children erase(iterator node) {
|
children erase(iterator node) {
|
||||||
if (node.element == rootNode) {
|
if (node.element == rootNode) {
|
||||||
//We're root node
|
//We're root node
|
||||||
rootNode = NULL;
|
rootNode = NULL;
|
||||||
} else {
|
} else {
|
||||||
//Delete parent's reference
|
//Delete parent's reference
|
||||||
if (node.up().left() == node) {
|
if (node.up().left() == node) {
|
||||||
node.up().element->left = NULL;
|
node.up().element->left = NULL;
|
||||||
} else {
|
} else {
|
||||||
node.up().element->right = NULL;
|
node.up().element->right = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return children(node.element->left, node.element->right);
|
return children(node.element->left, node.element->right);
|
||||||
}
|
}
|
||||||
static uint32_t countLeft(iterator start) {
|
static uint32_t countLeft(iterator start) {
|
||||||
if (start == end()) {
|
if (start == end()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//We also count the start node itself.
|
//We also count the start node itself.
|
||||||
uint32_t count = 1;
|
uint32_t count = 1;
|
||||||
while (start.left() != end()) {
|
while (start.left() != end()) {
|
||||||
count++;
|
count++;
|
||||||
start = start.left();
|
start = start.left();
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
static uint32_t countRight(iterator start) {
|
static uint32_t countRight(iterator start) {
|
||||||
if (start == end()) {
|
if (start == end()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//We also count the start node itself.
|
//We also count the start node itself.
|
||||||
uint32_t count = 1;
|
uint32_t count = 1;
|
||||||
while (start.right() != end()) {
|
while (start.right() != end()) {
|
||||||
count++;
|
count++;
|
||||||
start = start.right();
|
start = start.right();
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Node* rootNode;
|
Node* rootNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
SharedRingBuffer.cpp
|
SharedRingBuffer.cpp
|
||||||
SimpleRingBuffer.cpp
|
SimpleRingBuffer.cpp
|
||||||
)
|
)
|
@@ -5,8 +5,8 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Simple First-In-First-Out data structure. The maximum size
|
* @brief Simple First-In-First-Out data structure. The maximum size
|
||||||
* can be set in the constructor.
|
* can be set in the constructor.
|
||||||
* @details
|
* @details
|
||||||
* The maximum capacity can be determined at run-time, so this container
|
* The maximum capacity can be determined at run-time, so this container
|
||||||
* performs dynamic memory allocation!
|
* performs dynamic memory allocation!
|
||||||
@@ -17,39 +17,39 @@
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
class DynamicFIFO: public FIFOBase<T> {
|
class DynamicFIFO: public FIFOBase<T> {
|
||||||
public:
|
public:
|
||||||
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
|
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
|
||||||
fifoVector(maxCapacity) {
|
fifoVector(maxCapacity) {
|
||||||
// trying to pass the pointer of the uninitialized vector
|
// trying to pass the pointer of the uninitialized vector
|
||||||
// to the FIFOBase constructor directly lead to a super evil bug.
|
// to the FIFOBase constructor directly lead to a super evil bug.
|
||||||
// So we do it like this now.
|
// So we do it like this now.
|
||||||
this->setContainer(fifoVector.data());
|
this->setContainer(fifoVector.data());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom copy constructor which prevents setting the
|
* @brief Custom copy constructor which prevents setting the
|
||||||
* underlying pointer wrong. This function allocates memory!
|
* underlying pointer wrong. This function allocates memory!
|
||||||
* @details This is a very heavy operation so try to avoid this!
|
* @details This is a very heavy operation so try to avoid this!
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
|
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
|
||||||
fifoVector(other.maxCapacity) {
|
fifoVector(other.maxCapacity) {
|
||||||
this->fifoVector = other.fifoVector;
|
this->fifoVector = other.fifoVector;
|
||||||
this->setContainer(fifoVector.data());
|
this->setContainer(fifoVector.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom assignment operator
|
* @brief Custom assignment operator
|
||||||
* @details This is a very heavy operation so try to avoid this!
|
* @details This is a very heavy operation so try to avoid this!
|
||||||
* @param other DyamicFIFO to copy from
|
* @param other DyamicFIFO to copy from
|
||||||
*/
|
*/
|
||||||
DynamicFIFO& operator=(const DynamicFIFO& other){
|
DynamicFIFO& operator=(const DynamicFIFO& other){
|
||||||
FIFOBase<T>::operator=(other);
|
FIFOBase<T>::operator=(other);
|
||||||
this->fifoVector = other.fifoVector;
|
this->fifoVector = other.fifoVector;
|
||||||
this->setContainer(fifoVector.data());
|
this->setContainer(fifoVector.data());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::vector<T> fifoVector;
|
std::vector<T> fifoVector;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTAINER_DYNAMICFIFO_H_ */
|
#endif /* FSFW_CONTAINER_DYNAMICFIFO_H_ */
|
||||||
|
@@ -5,8 +5,8 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Simple First-In-First-Out data structure with size fixed at
|
* @brief Simple First-In-First-Out data structure with size fixed at
|
||||||
* compile time
|
* compile time
|
||||||
* @details
|
* @details
|
||||||
* Performs no dynamic memory allocation.
|
* Performs no dynamic memory allocation.
|
||||||
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
||||||
@@ -16,32 +16,32 @@
|
|||||||
template<typename T, size_t capacity>
|
template<typename T, size_t capacity>
|
||||||
class FIFO: public FIFOBase<T> {
|
class FIFO: public FIFOBase<T> {
|
||||||
public:
|
public:
|
||||||
FIFO(): FIFOBase<T>(nullptr, capacity) {
|
FIFO(): FIFOBase<T>(nullptr, capacity) {
|
||||||
this->setContainer(fifoArray.data());
|
this->setContainer(fifoArray.data());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom copy constructor to set pointer correctly.
|
* @brief Custom copy constructor to set pointer correctly.
|
||||||
* @param other
|
* @param other
|
||||||
*/
|
*/
|
||||||
FIFO(const FIFO& other): FIFOBase<T>(other) {
|
FIFO(const FIFO& other): FIFOBase<T>(other) {
|
||||||
this->fifoArray = other.fifoArray;
|
this->fifoArray = other.fifoArray;
|
||||||
this->setContainer(fifoArray.data());
|
this->setContainer(fifoArray.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom assignment operator
|
* @brief Custom assignment operator
|
||||||
* @param other
|
* @param other
|
||||||
*/
|
*/
|
||||||
FIFO& operator=(const FIFO& other){
|
FIFO& operator=(const FIFO& other){
|
||||||
FIFOBase<T>::operator=(other);
|
FIFOBase<T>::operator=(other);
|
||||||
this->fifoArray = other.fifoArray;
|
this->fifoArray = other.fifoArray;
|
||||||
this->setContainer(fifoArray.data());
|
this->setContainer(fifoArray.data());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<T, capacity> fifoArray;
|
std::array<T, capacity> fifoArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTAINER_FIFO_H_ */
|
#endif /* FSFW_CONTAINER_FIFO_H_ */
|
||||||
|
@@ -8,70 +8,70 @@
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class FIFOBase {
|
class FIFOBase {
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
|
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
|
||||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
|
||||||
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
|
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
|
||||||
|
|
||||||
/** Default ctor, takes pointer to first entry of underlying container
|
/** Default ctor, takes pointer to first entry of underlying container
|
||||||
* and maximum capacity */
|
* and maximum capacity */
|
||||||
FIFOBase(T* values, const size_t maxCapacity);
|
FIFOBase(T* values, const size_t maxCapacity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert value into FIFO
|
* Insert value into FIFO
|
||||||
* @param value
|
* @param value
|
||||||
* @return RETURN_OK on success, FULL if full
|
* @return RETURN_OK on success, FULL if full
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insert(T value);
|
ReturnValue_t insert(T value);
|
||||||
/**
|
/**
|
||||||
* Retrieve item from FIFO. This removes the item from the FIFO.
|
* Retrieve item from FIFO. This removes the item from the FIFO.
|
||||||
* @param value Must point to a valid T
|
* @param value Must point to a valid T
|
||||||
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
||||||
*/
|
*/
|
||||||
ReturnValue_t retrieve(T *value);
|
ReturnValue_t retrieve(T *value);
|
||||||
/**
|
/**
|
||||||
* Retrieve item from FIFO without removing it from FIFO.
|
* Retrieve item from FIFO without removing it from FIFO.
|
||||||
* @param value Must point to a valid T
|
* @param value Must point to a valid T
|
||||||
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
||||||
*/
|
*/
|
||||||
ReturnValue_t peek(T * value);
|
ReturnValue_t peek(T * value);
|
||||||
/**
|
/**
|
||||||
* Remove item from FIFO.
|
* Remove item from FIFO.
|
||||||
* @return RETURN_OK on success, EMPTY if empty
|
* @return RETURN_OK on success, EMPTY if empty
|
||||||
*/
|
*/
|
||||||
ReturnValue_t pop();
|
ReturnValue_t pop();
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Check if FIFO is empty
|
* Check if FIFO is empty
|
||||||
* @return True if empty, False if not
|
* @return True if empty, False if not
|
||||||
*/
|
*/
|
||||||
bool empty();
|
bool empty();
|
||||||
/***
|
/***
|
||||||
* Check if FIFO is Full
|
* Check if FIFO is Full
|
||||||
* @return True if full, False if not
|
* @return True if full, False if not
|
||||||
*/
|
*/
|
||||||
bool full();
|
bool full();
|
||||||
/***
|
/***
|
||||||
* Current used size (elements) used
|
* Current used size (elements) used
|
||||||
* @return size_t in elements
|
* @return size_t in elements
|
||||||
*/
|
*/
|
||||||
size_t size();
|
size_t size();
|
||||||
/***
|
/***
|
||||||
* Get maximal capacity of fifo
|
* Get maximal capacity of fifo
|
||||||
* @return size_t with max capacity of this fifo
|
* @return size_t with max capacity of this fifo
|
||||||
*/
|
*/
|
||||||
size_t getMaxCapacity() const;
|
size_t getMaxCapacity() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setContainer(T* data);
|
void setContainer(T* data);
|
||||||
size_t maxCapacity = 0;
|
size_t maxCapacity = 0;
|
||||||
|
|
||||||
T* values;
|
T* values;
|
||||||
|
|
||||||
size_t readIndex = 0;
|
size_t readIndex = 0;
|
||||||
size_t writeIndex = 0;
|
size_t writeIndex = 0;
|
||||||
size_t currentSize = 0;
|
size_t currentSize = 0;
|
||||||
|
|
||||||
size_t next(size_t current);
|
size_t next(size_t current);
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "FIFOBase.tpp"
|
#include "FIFOBase.tpp"
|
||||||
|
@@ -7,87 +7,87 @@
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity):
|
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity):
|
||||||
maxCapacity(maxCapacity), values(values){};
|
maxCapacity(maxCapacity), values(values){};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::insert(T value) {
|
inline ReturnValue_t FIFOBase<T>::insert(T value) {
|
||||||
if (full()) {
|
if (full()) {
|
||||||
return FULL;
|
return FULL;
|
||||||
} else {
|
} else {
|
||||||
values[writeIndex] = value;
|
values[writeIndex] = value;
|
||||||
writeIndex = next(writeIndex);
|
writeIndex = next(writeIndex);
|
||||||
++currentSize;
|
++currentSize;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
|
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
} else {
|
} else {
|
||||||
if (value == nullptr){
|
if (value == nullptr){
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
*value = values[readIndex];
|
*value = values[readIndex];
|
||||||
readIndex = next(readIndex);
|
readIndex = next(readIndex);
|
||||||
--currentSize;
|
--currentSize;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::peek(T* value) {
|
inline ReturnValue_t FIFOBase<T>::peek(T* value) {
|
||||||
if(empty()) {
|
if(empty()) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
} else {
|
} else {
|
||||||
if (value == nullptr){
|
if (value == nullptr){
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
*value = values[readIndex];
|
*value = values[readIndex];
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::pop() {
|
inline ReturnValue_t FIFOBase<T>::pop() {
|
||||||
T value;
|
T value;
|
||||||
return this->retrieve(&value);
|
return this->retrieve(&value);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool FIFOBase<T>::empty() {
|
inline bool FIFOBase<T>::empty() {
|
||||||
return (currentSize == 0);
|
return (currentSize == 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool FIFOBase<T>::full() {
|
inline bool FIFOBase<T>::full() {
|
||||||
return (currentSize == maxCapacity);
|
return (currentSize == maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline size_t FIFOBase<T>::size() {
|
inline size_t FIFOBase<T>::size() {
|
||||||
return currentSize;
|
return currentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline size_t FIFOBase<T>::next(size_t current) {
|
inline size_t FIFOBase<T>::next(size_t current) {
|
||||||
++current;
|
++current;
|
||||||
if (current == maxCapacity) {
|
if (current == maxCapacity) {
|
||||||
current = 0;
|
current = 0;
|
||||||
}
|
}
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline size_t FIFOBase<T>::getMaxCapacity() const {
|
inline size_t FIFOBase<T>::getMaxCapacity() const {
|
||||||
return maxCapacity;
|
return maxCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void FIFOBase<T>::setContainer(T *data) {
|
inline void FIFOBase<T>::setContainer(T *data) {
|
||||||
this->values = data;
|
this->values = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -8,30 +8,32 @@
|
|||||||
*/
|
*/
|
||||||
template<typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
template<typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
||||||
class FixedArrayList: public ArrayList<T, count_t> {
|
class FixedArrayList: public ArrayList<T, count_t> {
|
||||||
static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE");
|
#if !defined(_MSC_VER)
|
||||||
|
static_assert(MAX_SIZE <= (std::pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE");
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
T data[MAX_SIZE];
|
T data[MAX_SIZE];
|
||||||
public:
|
public:
|
||||||
FixedArrayList() :
|
FixedArrayList() :
|
||||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedArrayList(const FixedArrayList& other) :
|
FixedArrayList(const FixedArrayList& other) :
|
||||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||||
memcpy(this->data, other.data, sizeof(this->data));
|
memcpy(this->data, other.data, sizeof(this->data));
|
||||||
this->entries = data;
|
this->entries = data;
|
||||||
this->size = other.size;
|
this->size = other.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedArrayList& operator=(FixedArrayList other) {
|
FixedArrayList& operator=(FixedArrayList other) {
|
||||||
memcpy(this->data, other.data, sizeof(this->data));
|
memcpy(this->data, other.data, sizeof(this->data));
|
||||||
this->entries = data;
|
this->entries = data;
|
||||||
this->size = other.size;
|
this->size = other.size;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~FixedArrayList() {
|
virtual ~FixedArrayList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -18,212 +18,212 @@
|
|||||||
*/
|
*/
|
||||||
template<typename key_t, typename T>
|
template<typename key_t, typename T>
|
||||||
class FixedMap: public SerializeIF {
|
class FixedMap: public SerializeIF {
|
||||||
static_assert (std::is_trivially_copyable<T>::value or
|
static_assert (std::is_trivially_copyable<T>::value or
|
||||||
std::is_base_of<SerializeIF, T>::value,
|
std::is_base_of<SerializeIF, T>::value,
|
||||||
"Types used in FixedMap must either be trivial copy-able or a "
|
"Types used in FixedMap must either be trivial copy-able or a "
|
||||||
"derived class from SerializeIF to be serialize-able");
|
"derived class from SerializeIF to be serialize-able");
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
|
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
|
||||||
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
|
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
|
||||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
|
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
|
||||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
|
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const key_t EMPTY_SLOT = -1;
|
static const key_t EMPTY_SLOT = -1;
|
||||||
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
|
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
|
||||||
uint32_t _size;
|
uint32_t _size;
|
||||||
|
|
||||||
uint32_t findIndex(key_t key) const {
|
uint32_t findIndex(key_t key) const {
|
||||||
if (_size == 0) {
|
if (_size == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
for (i = 0; i < _size; ++i) {
|
for (i = 0; i < _size; ++i) {
|
||||||
if (theMap[i].first == key) {
|
if (theMap[i].first == key) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
FixedMap(uint32_t maxSize) :
|
FixedMap(uint32_t maxSize) :
|
||||||
theMap(maxSize), _size(0) {
|
theMap(maxSize), _size(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
|
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
|
||||||
public:
|
public:
|
||||||
Iterator() :
|
Iterator() :
|
||||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
|
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator(std::pair<key_t, T> *pair) :
|
Iterator(std::pair<key_t, T> *pair) :
|
||||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) {
|
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
friend bool operator==(const typename FixedMap::Iterator& lhs,
|
friend bool operator==(const typename FixedMap::Iterator& lhs,
|
||||||
const typename FixedMap::Iterator& rhs) {
|
const typename FixedMap::Iterator& rhs) {
|
||||||
return (lhs.value == rhs.value);
|
return (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const typename FixedMap::Iterator& lhs,
|
friend bool operator!=(const typename FixedMap::Iterator& lhs,
|
||||||
const typename FixedMap::Iterator& rhs) {
|
const typename FixedMap::Iterator& rhs) {
|
||||||
return not (lhs.value == rhs.value);
|
return not (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator begin() const {
|
Iterator begin() const {
|
||||||
return Iterator(&theMap[0]);
|
return Iterator(&theMap[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator end() const {
|
Iterator end() const {
|
||||||
return Iterator(&theMap[_size]);
|
return Iterator(&theMap[_size]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t size() const {
|
uint32_t size() const {
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) {
|
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) {
|
||||||
if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
|
if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
|
||||||
return KEY_ALREADY_EXISTS;
|
return KEY_ALREADY_EXISTS;
|
||||||
}
|
}
|
||||||
if (_size == theMap.maxSize()) {
|
if (_size == theMap.maxSize()) {
|
||||||
return MAP_FULL;
|
return MAP_FULL;
|
||||||
}
|
}
|
||||||
theMap[_size].first = key;
|
theMap[_size].first = key;
|
||||||
theMap[_size].second = value;
|
theMap[_size].second = value;
|
||||||
if (storedValue != nullptr) {
|
if (storedValue != nullptr) {
|
||||||
*storedValue = Iterator(&theMap[_size]);
|
*storedValue = Iterator(&theMap[_size]);
|
||||||
}
|
}
|
||||||
++_size;
|
++_size;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t insert(std::pair<key_t, T> pair) {
|
ReturnValue_t insert(std::pair<key_t, T> pair) {
|
||||||
return insert(pair.first, pair.second);
|
return insert(pair.first, pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t exists(key_t key) const {
|
ReturnValue_t exists(key_t key) const {
|
||||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||||
if (findIndex(key) < _size) {
|
if (findIndex(key) < _size) {
|
||||||
result = HasReturnvaluesIF::RETURN_OK;
|
result = HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t erase(Iterator *iter) {
|
ReturnValue_t erase(Iterator *iter) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
if ((i = findIndex((*iter).value->first)) >= _size) {
|
if ((i = findIndex((*iter).value->first)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
theMap[i] = theMap[_size - 1];
|
theMap[i] = theMap[_size - 1];
|
||||||
--_size;
|
--_size;
|
||||||
--((*iter).value);
|
--((*iter).value);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t erase(key_t key) {
|
ReturnValue_t erase(key_t key) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
if ((i = findIndex(key)) >= _size) {
|
if ((i = findIndex(key)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
theMap[i] = theMap[_size - 1];
|
theMap[i] = theMap[_size - 1];
|
||||||
--_size;
|
--_size;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *findValue(key_t key) const {
|
T *findValue(key_t key) const {
|
||||||
return &theMap[findIndex(key)].second;
|
return &theMap[findIndex(key)].second;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator find(key_t key) const {
|
Iterator find(key_t key) const {
|
||||||
ReturnValue_t result = exists(key);
|
ReturnValue_t result = exists(key);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
return Iterator(&theMap[findIndex(key)]);
|
return Iterator(&theMap[findIndex(key)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t find(key_t key, T **value) const {
|
ReturnValue_t find(key_t key, T **value) const {
|
||||||
ReturnValue_t result = exists(key);
|
ReturnValue_t result = exists(key);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
*value = &theMap[findIndex(key)].second;
|
*value = &theMap[findIndex(key)].second;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() {
|
bool empty() {
|
||||||
if(_size == 0) {
|
if(_size == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool full() {
|
bool full() {
|
||||||
if(_size >= theMap.maxSize()) {
|
if(_size >= theMap.maxSize()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t maxSize() const {
|
uint32_t maxSize() const {
|
||||||
return theMap.maxSize();
|
return theMap.maxSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||||
size_t maxSize, Endianness streamEndianness) const {
|
size_t maxSize, Endianness streamEndianness) const {
|
||||||
ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
|
ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
|
||||||
buffer, size, maxSize, streamEndianness);
|
buffer, size, maxSize, streamEndianness);
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||||
result = SerializeAdapter::serialize(&theMap[i].first, buffer,
|
result = SerializeAdapter::serialize(&theMap[i].first, buffer,
|
||||||
size, maxSize, streamEndianness);
|
size, maxSize, streamEndianness);
|
||||||
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
|
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
|
||||||
maxSize, streamEndianness);
|
maxSize, streamEndianness);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual size_t getSerializedSize() const {
|
virtual size_t getSerializedSize() const {
|
||||||
uint32_t printSize = sizeof(_size);
|
uint32_t printSize = sizeof(_size);
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
for (i = 0; i < _size; ++i) {
|
for (i = 0; i < _size; ++i) {
|
||||||
printSize += SerializeAdapter::getSerializedSize(
|
printSize += SerializeAdapter::getSerializedSize(
|
||||||
&theMap[i].first);
|
&theMap[i].first);
|
||||||
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
|
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
|
||||||
}
|
}
|
||||||
|
|
||||||
return printSize;
|
return printSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
Endianness streamEndianness) {
|
Endianness streamEndianness) {
|
||||||
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
|
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
|
||||||
buffer, size, streamEndianness);
|
buffer, size, streamEndianness);
|
||||||
if (this->_size > theMap.maxSize()) {
|
if (this->_size > theMap.maxSize()) {
|
||||||
return SerializeIF::TOO_MANY_ELEMENTS;
|
return SerializeIF::TOO_MANY_ELEMENTS;
|
||||||
}
|
}
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||||
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
|
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
|
||||||
size, streamEndianness);
|
size, streamEndianness);
|
||||||
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
|
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
|
||||||
streamEndianness);
|
streamEndianness);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -34,172 +34,172 @@
|
|||||||
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
|
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
|
||||||
class FixedOrderedMultimap {
|
class FixedOrderedMultimap {
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
|
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
|
||||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01);
|
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01);
|
||||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
|
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Constructor which needs a size_t for the maximum allowed size
|
* Constructor which needs a size_t for the maximum allowed size
|
||||||
*
|
*
|
||||||
* Can not be resized during runtime
|
* Can not be resized during runtime
|
||||||
*
|
*
|
||||||
* Allocates memory at construction
|
* Allocates memory at construction
|
||||||
* @param maxSize size_t of Maximum allowed size
|
* @param maxSize size_t of Maximum allowed size
|
||||||
*/
|
*/
|
||||||
FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){
|
FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Virtual destructor frees Memory by deleting its member
|
* Virtual destructor frees Memory by deleting its member
|
||||||
*/
|
*/
|
||||||
virtual ~FixedOrderedMultimap() {
|
virtual ~FixedOrderedMultimap() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Special iterator for FixedOrderedMultimap
|
* Special iterator for FixedOrderedMultimap
|
||||||
*/
|
*/
|
||||||
class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator {
|
class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator {
|
||||||
public:
|
public:
|
||||||
Iterator() :
|
Iterator() :
|
||||||
ArrayList<std::pair<key_t, T>, size_t>::Iterator() {
|
ArrayList<std::pair<key_t, T>, size_t>::Iterator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator(std::pair<key_t, T> *pair) :
|
Iterator(std::pair<key_t, T> *pair) :
|
||||||
ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) {
|
ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Returns an iterator pointing to the first element
|
* Returns an iterator pointing to the first element
|
||||||
* @return Iterator pointing to first element
|
* @return Iterator pointing to first element
|
||||||
*/
|
*/
|
||||||
Iterator begin() const {
|
Iterator begin() const {
|
||||||
return Iterator(&theMap[0]);
|
return Iterator(&theMap[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an iterator pointing to one element past the end
|
* Returns an iterator pointing to one element past the end
|
||||||
* @return Iterator pointing to one element past the end
|
* @return Iterator pointing to one element past the end
|
||||||
*/
|
*/
|
||||||
Iterator end() const {
|
Iterator end() const {
|
||||||
return Iterator(&theMap[_size]);
|
return Iterator(&theMap[_size]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Returns the current size of the map (not maximum size!)
|
* Returns the current size of the map (not maximum size!)
|
||||||
* @return Current size
|
* @return Current size
|
||||||
*/
|
*/
|
||||||
size_t size() const{
|
size_t size() const{
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the map, does not deallocate any memory
|
* Clears the map, does not deallocate any memory
|
||||||
*/
|
*/
|
||||||
void clear(){
|
void clear(){
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the maximum size of the map
|
* Returns the maximum size of the map
|
||||||
* @return Maximum size of the map
|
* @return Maximum size of the map
|
||||||
*/
|
*/
|
||||||
size_t maxSize() const{
|
size_t maxSize() const{
|
||||||
return theMap.maxSize();
|
return theMap.maxSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Used to insert a key and value separately.
|
* Used to insert a key and value separately.
|
||||||
*
|
*
|
||||||
* @param[in] key Key of the new element
|
* @param[in] key Key of the new element
|
||||||
* @param[in] value Value of the new element
|
* @param[in] value Value of the new element
|
||||||
* @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr
|
* @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr
|
||||||
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr);
|
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Used to insert new pair instead of single values
|
* Used to insert new pair instead of single values
|
||||||
*
|
*
|
||||||
* @param pair Pair to be inserted
|
* @param pair Pair to be inserted
|
||||||
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insert(std::pair<key_t, T> pair);
|
ReturnValue_t insert(std::pair<key_t, T> pair);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Can be used to check if a certain key is in the map
|
* Can be used to check if a certain key is in the map
|
||||||
* @param key Key to be checked
|
* @param key Key to be checked
|
||||||
* @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
|
* @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
|
||||||
*/
|
*/
|
||||||
ReturnValue_t exists(key_t key) const;
|
ReturnValue_t exists(key_t key) const;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Used to delete the element in the iterator
|
* Used to delete the element in the iterator
|
||||||
*
|
*
|
||||||
* The iterator will point to the element before or begin(),
|
* The iterator will point to the element before or begin(),
|
||||||
* but never to one element in front of the map.
|
* but never to one element in front of the map.
|
||||||
*
|
*
|
||||||
* @warning The iterator needs to be valid and dereferenceable
|
* @warning The iterator needs to be valid and dereferenceable
|
||||||
* @param[in/out] iter Pointer to iterator to the element that needs to be ereased
|
* @param[in/out] iter Pointer to iterator to the element that needs to be ereased
|
||||||
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
||||||
*/
|
*/
|
||||||
ReturnValue_t erase(Iterator *iter);
|
ReturnValue_t erase(Iterator *iter);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Used to erase by key
|
* Used to erase by key
|
||||||
* @param key Key to be erased
|
* @param key Key to be erased
|
||||||
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
||||||
*/
|
*/
|
||||||
ReturnValue_t erase(key_t key);
|
ReturnValue_t erase(key_t key);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Find returns the first appearance of the key
|
* Find returns the first appearance of the key
|
||||||
*
|
*
|
||||||
* If the key does not exist, it points to end()
|
* If the key does not exist, it points to end()
|
||||||
*
|
*
|
||||||
* @param key Key to search for
|
* @param key Key to search for
|
||||||
* @return Iterator pointing to the first entry of key
|
* @return Iterator pointing to the first entry of key
|
||||||
*/
|
*/
|
||||||
Iterator find(key_t key) const{
|
Iterator find(key_t key) const{
|
||||||
ReturnValue_t result = exists(key);
|
ReturnValue_t result = exists(key);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
return Iterator(&theMap[findFirstIndex(key)]);
|
return Iterator(&theMap[findFirstIndex(key)]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Finds first entry of the given key and returns a
|
* Finds first entry of the given key and returns a
|
||||||
* pointer to the value
|
* pointer to the value
|
||||||
*
|
*
|
||||||
* @param key Key to search for
|
* @param key Key to search for
|
||||||
* @param value Found value
|
* @param value Found value
|
||||||
* @return RETURN_OK if it points to the value,
|
* @return RETURN_OK if it points to the value,
|
||||||
* KEY_DOES_NOT_EXIST if the key is not in the map
|
* KEY_DOES_NOT_EXIST if the key is not in the map
|
||||||
*/
|
*/
|
||||||
ReturnValue_t find(key_t key, T **value) const;
|
ReturnValue_t find(key_t key, T **value) const;
|
||||||
|
|
||||||
friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs,
|
friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs,
|
||||||
const typename FixedOrderedMultimap::Iterator& rhs) {
|
const typename FixedOrderedMultimap::Iterator& rhs) {
|
||||||
return (lhs.value == rhs.value);
|
return (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
|
friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
|
||||||
const typename FixedOrderedMultimap::Iterator& rhs) {
|
const typename FixedOrderedMultimap::Iterator& rhs) {
|
||||||
return not (lhs.value == rhs.value);
|
return not (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef KEY_COMPARE compare;
|
typedef KEY_COMPARE compare;
|
||||||
compare myComp;
|
compare myComp;
|
||||||
ArrayList<std::pair<key_t, T>, size_t> theMap;
|
ArrayList<std::pair<key_t, T>, size_t> theMap;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
|
|
||||||
size_t findFirstIndex(key_t key, size_t startAt = 0) const;
|
size_t findFirstIndex(key_t key, size_t startAt = 0) const;
|
||||||
|
|
||||||
size_t findNicePlace(key_t key) const;
|
size_t findNicePlace(key_t key) const;
|
||||||
|
|
||||||
void removeFromPosition(size_t position);
|
void removeFromPosition(size_t position);
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "FixedOrderedMultimap.tpp"
|
#include "FixedOrderedMultimap.tpp"
|
||||||
|
@@ -4,105 +4,105 @@
|
|||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
|
||||||
if (_size == theMap.maxSize()) {
|
if (_size == theMap.maxSize()) {
|
||||||
return MAP_FULL;
|
return MAP_FULL;
|
||||||
}
|
}
|
||||||
size_t position = findNicePlace(key);
|
size_t position = findNicePlace(key);
|
||||||
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
|
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
|
||||||
(_size - position) * sizeof(std::pair<key_t,T>));
|
(_size - position) * sizeof(std::pair<key_t,T>));
|
||||||
theMap[position].first = key;
|
theMap[position].first = key;
|
||||||
theMap[position].second = value;
|
theMap[position].second = value;
|
||||||
++_size;
|
++_size;
|
||||||
if (storedValue != nullptr) {
|
if (storedValue != nullptr) {
|
||||||
*storedValue = Iterator(&theMap[position]);
|
*storedValue = Iterator(&theMap[position]);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
|
||||||
return insert(pair.first, pair.second);
|
return insert(pair.first, pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
|
||||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||||
if (findFirstIndex(key) < _size) {
|
if (findFirstIndex(key) < _size) {
|
||||||
result = HasReturnvaluesIF::RETURN_OK;
|
result = HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
|
||||||
size_t i;
|
size_t i;
|
||||||
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
removeFromPosition(i);
|
removeFromPosition(i);
|
||||||
if (*iter != begin()) {
|
if (*iter != begin()) {
|
||||||
(*iter)--;
|
(*iter)--;
|
||||||
} else {
|
} else {
|
||||||
*iter = begin();
|
*iter = begin();
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
|
||||||
size_t i;
|
size_t i;
|
||||||
if ((i = findFirstIndex(key)) >= _size) {
|
if ((i = findFirstIndex(key)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
removeFromPosition(i);
|
removeFromPosition(i);
|
||||||
i = findFirstIndex(key, i);
|
i = findFirstIndex(key, i);
|
||||||
} while (i < _size);
|
} while (i < _size);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
|
||||||
ReturnValue_t result = exists(key);
|
ReturnValue_t result = exists(key);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
*value = &theMap[findFirstIndex(key)].second;
|
*value = &theMap[findFirstIndex(key)].second;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const {
|
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const {
|
||||||
if (startAt >= _size) {
|
if (startAt >= _size) {
|
||||||
return startAt + 1;
|
return startAt + 1;
|
||||||
}
|
}
|
||||||
size_t i = startAt;
|
size_t i = startAt;
|
||||||
for (i = startAt; i < _size; ++i) {
|
for (i = startAt; i < _size; ++i) {
|
||||||
if (theMap[i].first == key) {
|
if (theMap[i].first == key) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
|
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (i = 0; i < _size; ++i) {
|
for (i = 0; i < _size; ++i) {
|
||||||
if (myComp(key, theMap[i].first)) {
|
if (myComp(key, theMap[i].first)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
|
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
|
||||||
if (_size <= position) {
|
if (_size <= position) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
|
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
|
||||||
(_size - position - 1) * sizeof(std::pair<key_t,T>));
|
(_size - position - 1) * sizeof(std::pair<key_t,T>));
|
||||||
--_size;
|
--_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -6,85 +6,85 @@
|
|||||||
|
|
||||||
template<typename T, typename count_t = uint8_t>
|
template<typename T, typename count_t = uint8_t>
|
||||||
class HybridIterator: public LinkedElement<T>::Iterator,
|
class HybridIterator: public LinkedElement<T>::Iterator,
|
||||||
public ArrayList<T, count_t>::Iterator {
|
public ArrayList<T, count_t>::Iterator {
|
||||||
public:
|
public:
|
||||||
HybridIterator() {}
|
HybridIterator() {}
|
||||||
|
|
||||||
HybridIterator(typename LinkedElement<T>::Iterator *iter) :
|
HybridIterator(typename LinkedElement<T>::Iterator *iter) :
|
||||||
LinkedElement<T>::Iterator(*iter), value(iter->value),
|
LinkedElement<T>::Iterator(*iter), value(iter->value),
|
||||||
linked(true) {
|
linked(true) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridIterator(LinkedElement<T> *start) :
|
HybridIterator(LinkedElement<T> *start) :
|
||||||
LinkedElement<T>::Iterator(start), value(start->value),
|
LinkedElement<T>::Iterator(start), value(start->value),
|
||||||
linked(true) {
|
linked(true) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
||||||
typename ArrayList<T, count_t>::Iterator end) :
|
typename ArrayList<T, count_t>::Iterator end) :
|
||||||
ArrayList<T, count_t>::Iterator(start), value(start.value),
|
ArrayList<T, count_t>::Iterator(start), value(start.value),
|
||||||
linked(false), end(end.value) {
|
linked(false), end(end.value) {
|
||||||
if (value == this->end) {
|
if (value == this->end) {
|
||||||
value = NULL;
|
value = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridIterator(T *firstElement, T *lastElement) :
|
HybridIterator(T *firstElement, T *lastElement) :
|
||||||
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
|
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
|
||||||
linked(false), end(++lastElement) {
|
linked(false), end(++lastElement) {
|
||||||
if (value == end) {
|
if (value == end) {
|
||||||
value = NULL;
|
value = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridIterator& operator++() {
|
HybridIterator& operator++() {
|
||||||
if (linked) {
|
if (linked) {
|
||||||
LinkedElement<T>::Iterator::operator++();
|
LinkedElement<T>::Iterator::operator++();
|
||||||
if (LinkedElement<T>::Iterator::value != nullptr) {
|
if (LinkedElement<T>::Iterator::value != nullptr) {
|
||||||
value = LinkedElement<T>::Iterator::value->value;
|
value = LinkedElement<T>::Iterator::value->value;
|
||||||
} else {
|
} else {
|
||||||
value = nullptr;
|
value = nullptr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ArrayList<T, count_t>::Iterator::operator++();
|
ArrayList<T, count_t>::Iterator::operator++();
|
||||||
value = ArrayList<T, count_t>::Iterator::value;
|
value = ArrayList<T, count_t>::Iterator::value;
|
||||||
|
|
||||||
if (value == end) {
|
if (value == end) {
|
||||||
value = nullptr;
|
value = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridIterator operator++(int) {
|
HybridIterator operator++(int) {
|
||||||
HybridIterator tmp(*this);
|
HybridIterator tmp(*this);
|
||||||
operator++();
|
operator++();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const HybridIterator& other) const {
|
bool operator==(const HybridIterator& other) const {
|
||||||
return value == other.value;
|
return value == other.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const HybridIterator& other) const {
|
bool operator!=(const HybridIterator& other) const {
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
T operator*() {
|
T operator*() {
|
||||||
return *value;
|
return *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *operator->() {
|
T *operator->() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T* value = nullptr;
|
T* value = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool linked = false;
|
bool linked = false;
|
||||||
T *end = nullptr;
|
T *end = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */
|
#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -22,50 +22,50 @@
|
|||||||
*/
|
*/
|
||||||
class PlacementFactory {
|
class PlacementFactory {
|
||||||
public:
|
public:
|
||||||
PlacementFactory(StorageManagerIF* backend) :
|
PlacementFactory(StorageManagerIF* backend) :
|
||||||
dataBackend(backend) {
|
dataBackend(backend) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Generates an object of type T in the backend storage.
|
* Generates an object of type T in the backend storage.
|
||||||
*
|
*
|
||||||
* @warning Do not use with any Type that allocates memory internally!
|
* @warning Do not use with any Type that allocates memory internally!
|
||||||
*
|
*
|
||||||
* @tparam T Type of Object
|
* @tparam T Type of Object
|
||||||
* @param args Constructor Arguments to be passed
|
* @param args Constructor Arguments to be passed
|
||||||
* @return A pointer to the new object or a nullptr in case of failure
|
* @return A pointer to the new object or a nullptr in case of failure
|
||||||
*/
|
*/
|
||||||
template<typename T, typename ... Args>
|
template<typename T, typename ... Args>
|
||||||
T* generate(Args&&... args) {
|
T* generate(Args&&... args) {
|
||||||
store_address_t tempId;
|
store_address_t tempId;
|
||||||
uint8_t* pData = nullptr;
|
uint8_t* pData = nullptr;
|
||||||
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
|
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
|
||||||
&pData);
|
&pData);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
T* temp = new (pData) T(std::forward<Args>(args)...);
|
T* temp = new (pData) T(std::forward<Args>(args)...);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
/***
|
/***
|
||||||
* Function to destroy the object allocated with generate and free space in backend.
|
* Function to destroy the object allocated with generate and free space in backend.
|
||||||
* This must be called by the user.
|
* This must be called by the user.
|
||||||
*
|
*
|
||||||
* @param thisElement Element to be destroyed
|
* @param thisElement Element to be destroyed
|
||||||
* @return RETURN_OK if the element was destroyed, different errors on failure
|
* @return RETURN_OK if the element was destroyed, different errors on failure
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ReturnValue_t destroy(T* thisElement) {
|
ReturnValue_t destroy(T* thisElement) {
|
||||||
if (thisElement == nullptr){
|
if (thisElement == nullptr){
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
|
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
|
||||||
thisElement->~T();
|
thisElement->~T();
|
||||||
uint8_t* pointer = (uint8_t*) (thisElement);
|
uint8_t* pointer = (uint8_t*) (thisElement);
|
||||||
return dataBackend->deleteData(pointer, sizeof(T));
|
return dataBackend->deleteData(pointer, sizeof(T));
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
StorageManagerIF* dataBackend;
|
StorageManagerIF* dataBackend;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */
|
#endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */
|
||||||
|
@@ -7,107 +7,107 @@
|
|||||||
template<uint8_t N_READ_PTRS = 1>
|
template<uint8_t N_READ_PTRS = 1>
|
||||||
class RingBufferBase {
|
class RingBufferBase {
|
||||||
public:
|
public:
|
||||||
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
|
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
|
||||||
start(startAddress), write(startAddress), size(size),
|
start(startAddress), write(startAddress), size(size),
|
||||||
overwriteOld(overwriteOld) {
|
overwriteOld(overwriteOld) {
|
||||||
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
||||||
read[count] = startAddress;
|
read[count] = startAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~RingBufferBase() {}
|
virtual ~RingBufferBase() {}
|
||||||
|
|
||||||
bool isFull(uint8_t n = 0) {
|
bool isFull(uint8_t n = 0) {
|
||||||
return (availableWriteSpace(n) == 0);
|
return (availableWriteSpace(n) == 0);
|
||||||
}
|
}
|
||||||
bool isEmpty(uint8_t n = 0) {
|
bool isEmpty(uint8_t n = 0) {
|
||||||
return (getAvailableReadData(n) == 0);
|
return (getAvailableReadData(n) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getAvailableReadData(uint8_t n = 0) const {
|
size_t getAvailableReadData(uint8_t n = 0) const {
|
||||||
return ((write + size) - read[n]) % size;
|
return ((write + size) - read[n]) % size;
|
||||||
}
|
}
|
||||||
size_t availableWriteSpace(uint8_t n = 0) const {
|
size_t availableWriteSpace(uint8_t n = 0) const {
|
||||||
//One less to avoid ambiguous full/empty problem.
|
//One less to avoid ambiguous full/empty problem.
|
||||||
return (((read[n] + size) - write - 1) % size);
|
return (((read[n] + size) - write - 1) % size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overwritesOld() const {
|
bool overwritesOld() const {
|
||||||
return overwriteOld;
|
return overwriteOld;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getMaxSize() const {
|
size_t getMaxSize() const {
|
||||||
return size - 1;
|
return size - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
write = start;
|
write = start;
|
||||||
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
||||||
read[count] = start;
|
read[count] = start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t writeTillWrap() {
|
size_t writeTillWrap() {
|
||||||
return (start + size) - write;
|
return (start + size) - write;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readTillWrap(uint8_t n = 0) {
|
size_t readTillWrap(uint8_t n = 0) {
|
||||||
return (start + size) - read[n];
|
return (start + size) - read[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getStart() const {
|
size_t getStart() const {
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const size_t start;
|
const size_t start;
|
||||||
size_t write;
|
size_t write;
|
||||||
size_t read[N_READ_PTRS];
|
size_t read[N_READ_PTRS];
|
||||||
const size_t size;
|
const size_t size;
|
||||||
const bool overwriteOld;
|
const bool overwriteOld;
|
||||||
|
|
||||||
void incrementWrite(uint32_t amount) {
|
void incrementWrite(uint32_t amount) {
|
||||||
write = ((write + amount - start) % size) + start;
|
write = ((write + amount - start) % size) + start;
|
||||||
}
|
}
|
||||||
void incrementRead(uint32_t amount, uint8_t n = 0) {
|
void incrementRead(uint32_t amount, uint8_t n = 0) {
|
||||||
read[n] = ((read[n] + amount - start) % size) + start;
|
read[n] = ((read[n] + amount - start) % size) + start;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
|
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
|
||||||
if (getAvailableReadData(n) >= amount) {
|
if (getAvailableReadData(n) >= amount) {
|
||||||
incrementRead(amount, n);
|
incrementRead(amount, n);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t writeData(uint32_t amount) {
|
ReturnValue_t writeData(uint32_t amount) {
|
||||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||||
incrementWrite(amount);
|
incrementWrite(amount);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getRead(uint8_t n = 0) const {
|
size_t getRead(uint8_t n = 0) const {
|
||||||
return read[n];
|
return read[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRead(uint32_t read, uint8_t n = 0) {
|
void setRead(uint32_t read, uint8_t n = 0) {
|
||||||
if (read >= start && read < (start+size)) {
|
if (read >= start && read < (start+size)) {
|
||||||
this->read[n] = read;
|
this->read[n] = read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getWrite() const {
|
uint32_t getWrite() const {
|
||||||
return write;
|
return write;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setWrite(uint32_t write) {
|
void setWrite(uint32_t write) {
|
||||||
this->write = write;
|
this->write = write;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */
|
#endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */
|
||||||
|
@@ -1,25 +1,28 @@
|
|||||||
#include "SharedRingBuffer.h"
|
#include "SharedRingBuffer.h"
|
||||||
#include "../ipc/MutexFactory.h"
|
#include "../ipc/MutexFactory.h"
|
||||||
#include "../ipc/MutexHelper.h"
|
#include "../ipc/MutexGuard.h"
|
||||||
|
|
||||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
|
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||||
bool overwriteOld, size_t maxExcessBytes):
|
bool overwriteOld, size_t maxExcessBytes):
|
||||||
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
|
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
|
||||||
maxExcessBytes) {
|
maxExcessBytes) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
|
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
|
||||||
const size_t size, bool overwriteOld, size_t maxExcessBytes):
|
const size_t size, bool overwriteOld, size_t maxExcessBytes):
|
||||||
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
|
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
|
||||||
maxExcessBytes) {
|
maxExcessBytes) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedRingBuffer::~SharedRingBuffer() {
|
||||||
|
MutexFactory::instance()->deleteMutex(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) {
|
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) {
|
||||||
this->fifoDepth = fifoDepth;
|
this->fifoDepth = fifoDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
|
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
|
||||||
@@ -38,20 +41,20 @@ MutexIF* SharedRingBuffer::getMutexHandle() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SharedRingBuffer::initialize() {
|
ReturnValue_t SharedRingBuffer::initialize() {
|
||||||
if(fifoDepth > 0) {
|
if(fifoDepth > 0) {
|
||||||
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
|
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
|
||||||
}
|
}
|
||||||
return SystemObject::initialize();
|
return SystemObject::initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
|
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
|
||||||
if(receiveSizesFIFO == nullptr) {
|
if(receiveSizesFIFO == nullptr) {
|
||||||
// Configuration error.
|
// Configuration error.
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
|
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
|
||||||
<< " was not configured to have sizes FIFO, returning nullptr!"
|
<< " was not configured to have sizes FIFO, returning nullptr!"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return receiveSizesFIFO;
|
return receiveSizesFIFO;
|
||||||
}
|
}
|
||||||
|
@@ -15,76 +15,79 @@
|
|||||||
* and unlock operations.
|
* and unlock operations.
|
||||||
*/
|
*/
|
||||||
class SharedRingBuffer: public SystemObject,
|
class SharedRingBuffer: public SystemObject,
|
||||||
public SimpleRingBuffer {
|
public SimpleRingBuffer {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* This constructor allocates a new internal buffer with the supplied size.
|
* This constructor allocates a new internal buffer with the supplied size.
|
||||||
* @param size
|
* @param size
|
||||||
* @param overwriteOld
|
* @param overwriteOld
|
||||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||||
* will be overwritten.
|
* will be overwritten.
|
||||||
*/
|
*/
|
||||||
SharedRingBuffer(object_id_t objectId, const size_t size,
|
SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||||
bool overwriteOld, size_t maxExcessBytes);
|
bool overwriteOld, size_t maxExcessBytes);
|
||||||
|
/**
|
||||||
|
* This constructor takes an external buffer with the specified size.
|
||||||
|
* @param buffer
|
||||||
|
* @param size
|
||||||
|
* @param overwriteOld
|
||||||
|
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||||
|
* will be overwritten.
|
||||||
|
*/
|
||||||
|
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
|
||||||
|
bool overwriteOld, size_t maxExcessBytes);
|
||||||
|
|
||||||
/**
|
virtual~ SharedRingBuffer();
|
||||||
* @brief This function can be used to add an optional FIFO to the class
|
|
||||||
* @details
|
|
||||||
* This FIFO will be allocated in the initialize function (and will
|
|
||||||
* have a fixed maximum size after that). It can be used to store
|
|
||||||
* values like packet sizes, for example for a shared ring buffer
|
|
||||||
* used by producer/consumer tasks.
|
|
||||||
*/
|
|
||||||
void setToUseReceiveSizeFIFO(size_t fifoDepth);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor takes an external buffer with the specified size.
|
* @brief This function can be used to add an optional FIFO to the class
|
||||||
* @param buffer
|
* @details
|
||||||
* @param size
|
* This FIFO will be allocated in the initialize function (and will
|
||||||
* @param overwriteOld
|
* have a fixed maximum size after that). It can be used to store
|
||||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
* values like packet sizes, for example for a shared ring buffer
|
||||||
* will be overwritten.
|
* used by producer/consumer tasks.
|
||||||
*/
|
*/
|
||||||
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
|
void setToUseReceiveSizeFIFO(size_t fifoDepth);
|
||||||
bool overwriteOld, size_t maxExcessBytes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unless a read-only constant value is read, all operations on the
|
|
||||||
* shared ring buffer should be protected by calling this function.
|
|
||||||
* @param timeoutType
|
|
||||||
* @param timeout
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
|
|
||||||
dur_millis_t timeout);
|
|
||||||
/**
|
|
||||||
* Any locked mutex also has to be unlocked, otherwise, access to the
|
|
||||||
* shared ring buffer will be blocked.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t unlockRingBufferMutex();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The mutex handle can be accessed directly, for example to perform
|
|
||||||
* the lock with the #MutexHelper for a RAII compliant lock operation.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
MutexIF* getMutexHandle() const;
|
|
||||||
|
|
||||||
ReturnValue_t initialize() override;
|
/**
|
||||||
|
* Unless a read-only constant value is read, all operations on the
|
||||||
|
* shared ring buffer should be protected by calling this function.
|
||||||
|
* @param timeoutType
|
||||||
|
* @param timeout
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
|
||||||
|
dur_millis_t timeout);
|
||||||
|
/**
|
||||||
|
* Any locked mutex also has to be unlocked, otherwise, access to the
|
||||||
|
* shared ring buffer will be blocked.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t unlockRingBufferMutex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the shared ring buffer was configured to have a sizes FIFO, a handle
|
* The mutex handle can be accessed directly, for example to perform
|
||||||
* to that FIFO can be retrieved with this function.
|
* the lock with the #MutexGuard for a RAII compliant lock operation.
|
||||||
* Do not forget to protect access with a lock if required!
|
* @return
|
||||||
* @return
|
*/
|
||||||
*/
|
MutexIF* getMutexHandle() const;
|
||||||
DynamicFIFO<size_t>* getReceiveSizesFIFO();
|
|
||||||
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the shared ring buffer was configured to have a sizes FIFO, a handle
|
||||||
|
* to that FIFO can be retrieved with this function.
|
||||||
|
* Do not forget to protect access with a lock if required!
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
DynamicFIFO<size_t>* getReceiveSizesFIFO();
|
||||||
private:
|
private:
|
||||||
MutexIF* mutex = nullptr;
|
MutexIF* mutex = nullptr;
|
||||||
|
|
||||||
size_t fifoDepth = 0;
|
size_t fifoDepth = 0;
|
||||||
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
|
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2,31 +2,31 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
|
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||||
size_t maxExcessBytes) :
|
size_t maxExcessBytes) :
|
||||||
RingBufferBase<>(0, size, overwriteOld),
|
RingBufferBase<>(0, size, overwriteOld),
|
||||||
maxExcessBytes(maxExcessBytes) {
|
maxExcessBytes(maxExcessBytes) {
|
||||||
if(maxExcessBytes > size) {
|
if(maxExcessBytes > size) {
|
||||||
this->maxExcessBytes = size;
|
this->maxExcessBytes = size;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this->maxExcessBytes = maxExcessBytes;
|
this->maxExcessBytes = maxExcessBytes;
|
||||||
}
|
}
|
||||||
buffer = new uint8_t[size + maxExcessBytes];
|
buffer = new uint8_t[size + maxExcessBytes];
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
|
SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
|
||||||
bool overwriteOld, size_t maxExcessBytes):
|
bool overwriteOld, size_t maxExcessBytes):
|
||||||
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
|
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
|
||||||
if(maxExcessBytes > size) {
|
if(maxExcessBytes > size) {
|
||||||
this->maxExcessBytes = size;
|
this->maxExcessBytes = size;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this->maxExcessBytes = maxExcessBytes;
|
this->maxExcessBytes = maxExcessBytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleRingBuffer::~SimpleRingBuffer() {
|
SimpleRingBuffer::~SimpleRingBuffer() {
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
|
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
|
||||||
@@ -48,58 +48,58 @@ ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
|
void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
|
||||||
if(getExcessBytes() > 0) {
|
if(getExcessBytes() > 0) {
|
||||||
moveExcessBytesToStart();
|
moveExcessBytesToStart();
|
||||||
}
|
}
|
||||||
incrementWrite(amount);
|
incrementWrite(amount);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
|
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
|
||||||
size_t amount) {
|
size_t amount) {
|
||||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||||
size_t amountTillWrap = writeTillWrap();
|
size_t amountTillWrap = writeTillWrap();
|
||||||
if (amountTillWrap >= amount) {
|
if (amountTillWrap >= amount) {
|
||||||
// remaining size in buffer is sufficient to fit full amount.
|
// remaining size in buffer is sufficient to fit full amount.
|
||||||
memcpy(&buffer[write], data, amount);
|
memcpy(&buffer[write], data, amount);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memcpy(&buffer[write], data, amountTillWrap);
|
memcpy(&buffer[write], data, amountTillWrap);
|
||||||
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
|
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
|
||||||
}
|
}
|
||||||
incrementWrite(amount);
|
incrementWrite(amount);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
|
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
|
||||||
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
|
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
|
||||||
size_t availableData = getAvailableReadData(READ_PTR);
|
size_t availableData = getAvailableReadData(READ_PTR);
|
||||||
size_t amountTillWrap = readTillWrap(READ_PTR);
|
size_t amountTillWrap = readTillWrap(READ_PTR);
|
||||||
if (availableData < amount) {
|
if (availableData < amount) {
|
||||||
if (readRemaining) {
|
if (readRemaining) {
|
||||||
// more data available than amount specified.
|
// more data available than amount specified.
|
||||||
amount = availableData;
|
amount = availableData;
|
||||||
} else {
|
} else {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trueAmount != nullptr) {
|
if (trueAmount != nullptr) {
|
||||||
*trueAmount = amount;
|
*trueAmount = amount;
|
||||||
}
|
}
|
||||||
if (amountTillWrap >= amount) {
|
if (amountTillWrap >= amount) {
|
||||||
memcpy(data, &buffer[read[READ_PTR]], amount);
|
memcpy(data, &buffer[read[READ_PTR]], amount);
|
||||||
} else {
|
} else {
|
||||||
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
|
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
|
||||||
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
|
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(incrementReadPtr) {
|
if(incrementReadPtr) {
|
||||||
deleteData(amount, readRemaining);
|
deleteData(amount, readRemaining);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SimpleRingBuffer::getExcessBytes() const {
|
size_t SimpleRingBuffer::getExcessBytes() const {
|
||||||
@@ -114,18 +114,18 @@ void SimpleRingBuffer::moveExcessBytesToStart() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
|
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
|
||||||
bool deleteRemaining, size_t* trueAmount) {
|
bool deleteRemaining, size_t* trueAmount) {
|
||||||
size_t availableData = getAvailableReadData(READ_PTR);
|
size_t availableData = getAvailableReadData(READ_PTR);
|
||||||
if (availableData < amount) {
|
if (availableData < amount) {
|
||||||
if (deleteRemaining) {
|
if (deleteRemaining) {
|
||||||
amount = availableData;
|
amount = availableData;
|
||||||
} else {
|
} else {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trueAmount != nullptr) {
|
if (trueAmount != nullptr) {
|
||||||
*trueAmount = amount;
|
*trueAmount = amount;
|
||||||
}
|
}
|
||||||
incrementRead(amount, READ_PTR);
|
incrementRead(amount, READ_PTR);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Circular buffer implementation, useful for buffering
|
* @brief Circular buffer implementation, useful for buffering
|
||||||
* into data streams.
|
* into data streams.
|
||||||
* @details
|
* @details
|
||||||
* Note that the deleteData() has to be called to increment the read pointer.
|
* Note that the deleteData() has to be called to increment the read pointer.
|
||||||
@@ -25,104 +25,104 @@ public:
|
|||||||
* with getFreeElement.
|
* with getFreeElement.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
SimpleRingBuffer(const size_t size, bool overwriteOld,
|
SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||||
size_t maxExcessBytes = 0);
|
size_t maxExcessBytes = 0);
|
||||||
/**
|
/**
|
||||||
* This constructor takes an external buffer with the specified size.
|
* This constructor takes an external buffer with the specified size.
|
||||||
* @param buffer
|
* @param buffer
|
||||||
* @param size
|
* @param size
|
||||||
* @param overwriteOld
|
* @param overwriteOld
|
||||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||||
* will be overwritten.
|
* will be overwritten.
|
||||||
* @param maxExcessBytes
|
* @param maxExcessBytes
|
||||||
* If the buffer can accomodate additional bytes for contigous write
|
* If the buffer can accomodate additional bytes for contigous write
|
||||||
* operations with getFreeElement, this is the maximum allowed additional
|
* operations with getFreeElement, this is the maximum allowed additional
|
||||||
* size
|
* size
|
||||||
*/
|
*/
|
||||||
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
|
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
|
||||||
size_t maxExcessBytes = 0);
|
size_t maxExcessBytes = 0);
|
||||||
|
|
||||||
virtual ~SimpleRingBuffer();
|
virtual ~SimpleRingBuffer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write to circular buffer and increment write pointer by amount.
|
* Write to circular buffer and increment write pointer by amount.
|
||||||
* @param data
|
* @param data
|
||||||
* @param amount
|
* @param amount
|
||||||
* @return -@c RETURN_OK if write operation was successfull
|
* @return -@c RETURN_OK if write operation was successfull
|
||||||
* -@c RETURN_FAILED if
|
* -@c RETURN_FAILED if
|
||||||
*/
|
*/
|
||||||
ReturnValue_t writeData(const uint8_t* data, size_t amount);
|
ReturnValue_t writeData(const uint8_t* data, size_t amount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a pointer to a free element. If the remaining buffer is
|
* Returns a pointer to a free element. If the remaining buffer is
|
||||||
* not large enough, the data will be written past the actual size
|
* not large enough, the data will be written past the actual size
|
||||||
* and the amount of excess bytes will be cached. This function
|
* and the amount of excess bytes will be cached. This function
|
||||||
* does not increment the write pointer!
|
* does not increment the write pointer!
|
||||||
* @param writePointer Pointer to a pointer which can be used to write
|
* @param writePointer Pointer to a pointer which can be used to write
|
||||||
* contiguous blocks into the ring buffer
|
* contiguous blocks into the ring buffer
|
||||||
* @param amount
|
* @param amount
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
|
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This increments the write pointer and also copies the excess bytes
|
* This increments the write pointer and also copies the excess bytes
|
||||||
* to the beginning. It should be called if the write operation
|
* to the beginning. It should be called if the write operation
|
||||||
* conducted after calling getFreeElement() was performed.
|
* conducted after calling getFreeElement() was performed.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
void confirmBytesWritten(size_t amount);
|
void confirmBytesWritten(size_t amount);
|
||||||
|
|
||||||
virtual size_t getExcessBytes() const;
|
virtual size_t getExcessBytes() const;
|
||||||
/**
|
/**
|
||||||
* Helper functions which moves any excess bytes to the start
|
* Helper functions which moves any excess bytes to the start
|
||||||
* of the ring buffer.
|
* of the ring buffer.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual void moveExcessBytesToStart();
|
virtual void moveExcessBytesToStart();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read from circular buffer at read pointer.
|
* Read from circular buffer at read pointer.
|
||||||
* @param data
|
* @param data
|
||||||
* @param amount
|
* @param amount
|
||||||
* @param incrementReadPtr
|
* @param incrementReadPtr
|
||||||
* If this is set to true, the read pointer will be incremented.
|
* If this is set to true, the read pointer will be incremented.
|
||||||
* If readRemaining is set to true, the read pointer will be incremented
|
* If readRemaining is set to true, the read pointer will be incremented
|
||||||
* accordingly.
|
* accordingly.
|
||||||
* @param readRemaining
|
* @param readRemaining
|
||||||
* If this is set to true, the data will be read even if the amount
|
* If this is set to true, the data will be read even if the amount
|
||||||
* specified exceeds the read data available.
|
* specified exceeds the read data available.
|
||||||
* @param trueAmount [out]
|
* @param trueAmount [out]
|
||||||
* If readRemaining was set to true, the true amount read will be assigned
|
* If readRemaining was set to true, the true amount read will be assigned
|
||||||
* to the passed value.
|
* to the passed value.
|
||||||
* @return
|
* @return
|
||||||
* - @c RETURN_OK if data was read successfully
|
* - @c RETURN_OK if data was read successfully
|
||||||
* - @c RETURN_FAILED if not enough data was available and readRemaining
|
* - @c RETURN_FAILED if not enough data was available and readRemaining
|
||||||
* was set to false.
|
* was set to false.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t readData(uint8_t* data, size_t amount,
|
ReturnValue_t readData(uint8_t* data, size_t amount,
|
||||||
bool incrementReadPtr = false, bool readRemaining = false,
|
bool incrementReadPtr = false, bool readRemaining = false,
|
||||||
size_t* trueAmount = nullptr);
|
size_t* trueAmount = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete data by incrementing read pointer.
|
* Delete data by incrementing read pointer.
|
||||||
* @param amount
|
* @param amount
|
||||||
* @param deleteRemaining
|
* @param deleteRemaining
|
||||||
* If the amount specified is larger than the remaing size to read and this
|
* If the amount specified is larger than the remaing size to read and this
|
||||||
* is set to true, the remaining amount will be deleted as well
|
* is set to true, the remaining amount will be deleted as well
|
||||||
* @param trueAmount [out]
|
* @param trueAmount [out]
|
||||||
* If deleteRemaining was set to true, the amount deleted will be assigned
|
* If deleteRemaining was set to true, the amount deleted will be assigned
|
||||||
* to the passed value.
|
* to the passed value.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
|
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
|
||||||
size_t* trueAmount = nullptr);
|
size_t* trueAmount = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const uint8_t READ_PTR = 0;
|
static const uint8_t READ_PTR = 0;
|
||||||
uint8_t* buffer = nullptr;
|
uint8_t* buffer = nullptr;
|
||||||
size_t maxExcessBytes;
|
size_t maxExcessBytes;
|
||||||
size_t excessBytes = 0;
|
size_t excessBytes = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */
|
#endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */
|
||||||
|
@@ -5,71 +5,71 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Linked list data structure,
|
* @brief Linked list data structure,
|
||||||
* each entry has a pointer to the next entry (singly)
|
* each entry has a pointer to the next entry (singly)
|
||||||
* @ingroup container
|
* @ingroup container
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class LinkedElement {
|
class LinkedElement {
|
||||||
public:
|
public:
|
||||||
T *value;
|
T *value;
|
||||||
class Iterator {
|
class Iterator {
|
||||||
public:
|
public:
|
||||||
LinkedElement<T> *value = nullptr;
|
LinkedElement<T> *value = nullptr;
|
||||||
Iterator() {}
|
Iterator() {}
|
||||||
|
|
||||||
Iterator(LinkedElement<T> *element) :
|
Iterator(LinkedElement<T> *element) :
|
||||||
value(element) {
|
value(element) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator& operator++() {
|
Iterator& operator++() {
|
||||||
value = value->getNext();
|
value = value->getNext();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator operator++(int) {
|
Iterator operator++(int) {
|
||||||
Iterator tmp(*this);
|
Iterator tmp(*this);
|
||||||
operator++();
|
operator++();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(Iterator other) {
|
bool operator==(Iterator other) {
|
||||||
return value == other.value;
|
return value == other.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(Iterator other) {
|
bool operator!=(Iterator other) {
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
T *operator->() {
|
T *operator->() {
|
||||||
return value->value;
|
return value->value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
LinkedElement(T* setElement, LinkedElement<T>* setNext = nullptr):
|
LinkedElement(T* setElement, LinkedElement<T>* setNext = nullptr):
|
||||||
value(setElement), next(setNext) {}
|
value(setElement), next(setNext) {}
|
||||||
|
|
||||||
virtual ~LinkedElement(){}
|
virtual ~LinkedElement(){}
|
||||||
|
|
||||||
virtual LinkedElement* getNext() const {
|
virtual LinkedElement* getNext() const {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setNext(LinkedElement* next) {
|
virtual void setNext(LinkedElement* next) {
|
||||||
this->next = next;
|
this->next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setEnd() {
|
virtual void setEnd() {
|
||||||
this->next = nullptr;
|
this->next = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkedElement* begin() {
|
LinkedElement* begin() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
LinkedElement* end() {
|
LinkedElement* end() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
LinkedElement *next;
|
LinkedElement *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -77,52 +77,52 @@ class SinglyLinkedList {
|
|||||||
public:
|
public:
|
||||||
using ElementIterator = typename LinkedElement<T>::Iterator;
|
using ElementIterator = typename LinkedElement<T>::Iterator;
|
||||||
|
|
||||||
SinglyLinkedList() {}
|
SinglyLinkedList() {}
|
||||||
|
|
||||||
SinglyLinkedList(ElementIterator start) :
|
SinglyLinkedList(ElementIterator start) :
|
||||||
start(start.value) {}
|
start(start.value) {}
|
||||||
|
|
||||||
SinglyLinkedList(LinkedElement<T>* startElement) :
|
SinglyLinkedList(LinkedElement<T>* startElement) :
|
||||||
start(startElement) {}
|
start(startElement) {}
|
||||||
|
|
||||||
ElementIterator begin() const {
|
ElementIterator begin() const {
|
||||||
return ElementIterator::Iterator(start);
|
return ElementIterator::Iterator(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns iterator to nulltr */
|
/** Returns iterator to nulltr */
|
||||||
ElementIterator end() const {
|
ElementIterator end() const {
|
||||||
return ElementIterator::Iterator();
|
return ElementIterator::Iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns last element in singly linked list.
|
* Returns last element in singly linked list.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ElementIterator back() const {
|
ElementIterator back() const {
|
||||||
LinkedElement<T> *element = start;
|
LinkedElement<T> *element = start;
|
||||||
while (element->getNext() != nullptr) {
|
while (element->getNext() != nullptr) {
|
||||||
element = element->getNext();
|
element = element->getNext();
|
||||||
}
|
}
|
||||||
return ElementIterator::Iterator(element);
|
return ElementIterator::Iterator(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getSize() const {
|
size_t getSize() const {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
LinkedElement<T> *element = start;
|
LinkedElement<T> *element = start;
|
||||||
while (element != nullptr) {
|
while (element != nullptr) {
|
||||||
size++;
|
size++;
|
||||||
element = element->getNext();
|
element = element->getNext();
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
void setStart(LinkedElement<T>* firstElement) {
|
void setStart(LinkedElement<T>* firstElement) {
|
||||||
start = firstElement;
|
start = firstElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNext(LinkedElement<T>* currentElement,
|
void setNext(LinkedElement<T>* currentElement,
|
||||||
LinkedElement<T>* nextElement) {
|
LinkedElement<T>* nextElement) {
|
||||||
currentElement->setNext(nextElement);
|
currentElement->setNext(nextElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLast(LinkedElement<T>* lastElement) {
|
void setLast(LinkedElement<T>* lastElement) {
|
||||||
lastElement->setEnd();
|
lastElement->setEnd();
|
||||||
@@ -148,7 +148,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LinkedElement<T> *start = nullptr;
|
LinkedElement<T> *start = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SINGLYLINKEDLIST_H_ */
|
#endif /* SINGLYLINKEDLIST_H_ */
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
PRIVATE
|
ControllerBase.cpp
|
||||||
ControllerBase.cpp
|
ExtendedControllerBase.cpp
|
||||||
)
|
)
|
@@ -3,130 +3,131 @@
|
|||||||
#include "../subsystem/SubsystemBase.h"
|
#include "../subsystem/SubsystemBase.h"
|
||||||
#include "../ipc/QueueFactory.h"
|
#include "../ipc/QueueFactory.h"
|
||||||
#include "../action/HasActionsIF.h"
|
#include "../action/HasActionsIF.h"
|
||||||
|
#include "../objectmanager/ObjectManager.h"
|
||||||
|
|
||||||
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||||
size_t commandQueueDepth) :
|
size_t commandQueueDepth) :
|
||||||
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
|
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
|
||||||
submode(SUBMODE_NONE), modeHelper(this),
|
submode(SUBMODE_NONE), modeHelper(this),
|
||||||
healthHelper(this, setObjectId) {
|
healthHelper(this, setObjectId) {
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||||
commandQueueDepth);
|
commandQueueDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerBase::~ControllerBase() {
|
ControllerBase::~ControllerBase() {
|
||||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::initialize() {
|
ReturnValue_t ControllerBase::initialize() {
|
||||||
ReturnValue_t result = SystemObject::initialize();
|
ReturnValue_t result = SystemObject::initialize();
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t parentQueue = 0;
|
MessageQueueId_t parentQueue = 0;
|
||||||
if (parentId != objects::NO_OBJECT) {
|
if (parentId != objects::NO_OBJECT) {
|
||||||
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
SubsystemBase *parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
|
||||||
if (parent == nullptr) {
|
if (parent == nullptr) {
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
parentQueue = parent->getCommandQueue();
|
parentQueue = parent->getCommandQueue();
|
||||||
|
|
||||||
parent->registerChild(getObjectId());
|
parent->registerChild(getObjectId());
|
||||||
}
|
}
|
||||||
|
|
||||||
result = healthHelper.initialize(parentQueue);
|
result = healthHelper.initialize(parentQueue);
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = modeHelper.initialize(parentQueue);
|
result = modeHelper.initialize(parentQueue);
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t ControllerBase::getCommandQueue() const {
|
MessageQueueId_t ControllerBase::getCommandQueue() const {
|
||||||
return commandQueue->getId();
|
return commandQueue->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::handleQueue() {
|
void ControllerBase::handleQueue() {
|
||||||
CommandMessage command;
|
CommandMessage command;
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
for (result = commandQueue->receiveMessage(&command);
|
for (result = commandQueue->receiveMessage(&command);
|
||||||
result == RETURN_OK;
|
result == RETURN_OK;
|
||||||
result = commandQueue->receiveMessage(&command)) {
|
result = commandQueue->receiveMessage(&command)) {
|
||||||
|
|
||||||
result = modeHelper.handleModeCommand(&command);
|
result = modeHelper.handleModeCommand(&command);
|
||||||
if (result == RETURN_OK) {
|
if (result == RETURN_OK) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = healthHelper.handleHealthCommand(&command);
|
result = healthHelper.handleHealthCommand(&command);
|
||||||
if (result == RETURN_OK) {
|
if (result == RETURN_OK) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result = handleCommandMessage(&command);
|
result = handleCommandMessage(&command);
|
||||||
if (result == RETURN_OK) {
|
if (result == RETURN_OK) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
command.setToUnknownCommand();
|
command.setToUnknownCommand();
|
||||||
commandQueue->reply(&command);
|
commandQueue->reply(&command);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
|
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||||
changeHK(this->mode, this->submode, false);
|
changeHK(this->mode, this->submode, false);
|
||||||
triggerEvent(CHANGING_MODE, mode, submode);
|
triggerEvent(CHANGING_MODE, mode, submode);
|
||||||
this->mode = mode;
|
this->mode = mode;
|
||||||
this->submode = submode;
|
this->submode = submode;
|
||||||
modeHelper.modeChanged(mode, submode);
|
modeHelper.modeChanged(mode, submode);
|
||||||
modeChanged(mode, submode);
|
modeChanged(mode, submode);
|
||||||
announceMode(false);
|
announceMode(false);
|
||||||
changeHK(this->mode, this->submode, true);
|
changeHK(this->mode, this->submode, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
|
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
|
||||||
*mode = this->mode;
|
*mode = this->mode;
|
||||||
*submode = this->submode;
|
*submode = this->submode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::setToExternalControl() {
|
void ControllerBase::setToExternalControl() {
|
||||||
healthHelper.setHealth(EXTERNAL_CONTROL);
|
healthHelper.setHealth(EXTERNAL_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::announceMode(bool recursive) {
|
void ControllerBase::announceMode(bool recursive) {
|
||||||
triggerEvent(MODE_INFO, mode, submode);
|
triggerEvent(MODE_INFO, mode, submode);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
||||||
handleQueue();
|
handleQueue();
|
||||||
performControlOperation();
|
performControlOperation();
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) {
|
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||||
switch (health) {
|
switch (health) {
|
||||||
case HEALTHY:
|
case HEALTHY:
|
||||||
case EXTERNAL_CONTROL:
|
case EXTERNAL_CONTROL:
|
||||||
healthHelper.setHealth(health);
|
healthHelper.setHealth(health);
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
default:
|
default:
|
||||||
return INVALID_HEALTH_STATE;
|
return INVALID_HEALTH_STATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HasHealthIF::HealthState ControllerBase::getHealth() {
|
HasHealthIF::HealthState ControllerBase::getHealth() {
|
||||||
return healthHelper.getHealth();
|
return healthHelper.getHealth();
|
||||||
}
|
}
|
||||||
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
|
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
|
||||||
executingTask = task_;
|
executingTask = task_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||||
|
@@ -17,39 +17,39 @@
|
|||||||
* a mode and a health state. This avoids boilerplate code.
|
* a mode and a health state. This avoids boilerplate code.
|
||||||
*/
|
*/
|
||||||
class ControllerBase: public HasModesIF,
|
class ControllerBase: public HasModesIF,
|
||||||
public HasHealthIF,
|
public HasHealthIF,
|
||||||
public ExecutableObjectIF,
|
public ExecutableObjectIF,
|
||||||
public SystemObject,
|
public SystemObject,
|
||||||
public HasReturnvaluesIF {
|
public HasReturnvaluesIF {
|
||||||
public:
|
public:
|
||||||
static const Mode_t MODE_NORMAL = 2;
|
static const Mode_t MODE_NORMAL = 2;
|
||||||
|
|
||||||
ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||||
size_t commandQueueDepth = 3);
|
size_t commandQueueDepth = 3);
|
||||||
virtual ~ControllerBase();
|
virtual ~ControllerBase();
|
||||||
|
|
||||||
/** SystemObject override */
|
/** SystemObject override */
|
||||||
virtual ReturnValue_t initialize() override;
|
virtual ReturnValue_t initialize() override;
|
||||||
|
|
||||||
virtual MessageQueueId_t getCommandQueue() const override;
|
virtual MessageQueueId_t getCommandQueue() const override;
|
||||||
|
|
||||||
/** HasHealthIF overrides */
|
/** HasHealthIF overrides */
|
||||||
virtual ReturnValue_t setHealth(HealthState health) override;
|
virtual ReturnValue_t setHealth(HealthState health) override;
|
||||||
virtual HasHealthIF::HealthState getHealth() override;
|
virtual HasHealthIF::HealthState getHealth() override;
|
||||||
|
|
||||||
/** ExecutableObjectIF overrides */
|
/** ExecutableObjectIF overrides */
|
||||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
virtual void setTaskIF(PeriodicTaskIF* task) override;
|
virtual void setTaskIF(PeriodicTaskIF* task) override;
|
||||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implemented by child class. Handle command messages which are not
|
* Implemented by child class. Handle command messages which are not
|
||||||
* mode or health messages.
|
* mode or health messages.
|
||||||
* @param message
|
* @param message
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,35 +60,35 @@ protected:
|
|||||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode) = 0;
|
uint32_t *msToReachTheMode) = 0;
|
||||||
|
|
||||||
const object_id_t parentId;
|
const object_id_t parentId;
|
||||||
|
|
||||||
Mode_t mode;
|
Mode_t mode;
|
||||||
|
|
||||||
Submode_t submode;
|
Submode_t submode;
|
||||||
|
|
||||||
MessageQueueIF* commandQueue = nullptr;
|
MessageQueueIF* commandQueue = nullptr;
|
||||||
|
|
||||||
ModeHelper modeHelper;
|
ModeHelper modeHelper;
|
||||||
|
|
||||||
HealthHelper healthHelper;
|
HealthHelper healthHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to the task which executes this component,
|
* Pointer to the task which executes this component,
|
||||||
* is invalid before setTaskIF was called.
|
* is invalid before setTaskIF was called.
|
||||||
*/
|
*/
|
||||||
PeriodicTaskIF* executingTask = nullptr;
|
PeriodicTaskIF* executingTask = nullptr;
|
||||||
|
|
||||||
/** Handle mode and health messages */
|
/** Handle mode and health messages */
|
||||||
virtual void handleQueue();
|
virtual void handleQueue();
|
||||||
|
|
||||||
/** Mode helpers */
|
/** Mode helpers */
|
||||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||||
virtual void setToExternalControl();
|
virtual void setToExternalControl();
|
||||||
virtual void announceMode(bool recursive);
|
virtual void announceMode(bool recursive);
|
||||||
/** HK helpers */
|
/** HK helpers */
|
||||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */
|
#endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */
|
||||||
|
@@ -8,17 +8,12 @@ ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId,
|
|||||||
actionHelper(this, commandQueue) {
|
actionHelper(this, commandQueue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
|
ExtendedControllerBase::~ExtendedControllerBase() {
|
||||||
MessageQueueId_t commandedBy, const uint8_t *data, size_t size) {
|
|
||||||
// needs to be overriden and implemented by child class.
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
|
||||||
|
MessageQueueId_t commandedBy, const uint8_t *data, size_t size) {
|
||||||
ReturnValue_t ExtendedControllerBase::initializeLocalDataPool(
|
/* Needs to be overriden and implemented by child class. */
|
||||||
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
|
||||||
// needs to be overriden and implemented by child class.
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,8 +88,10 @@ ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
|
|||||||
|
|
||||||
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
|
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
|
||||||
handleQueue();
|
handleQueue();
|
||||||
poolManager.performHkOperation();
|
|
||||||
performControlOperation();
|
performControlOperation();
|
||||||
|
/* We do this after performing control operation because variables will be set changed
|
||||||
|
in this function. */
|
||||||
|
poolManager.performHkOperation();
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,14 +99,6 @@ MessageQueueId_t ExtendedControllerBase::getCommandQueue() const {
|
|||||||
return commandQueue->getId();
|
return commandQueue->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalPoolDataSetBase* ExtendedControllerBase::getDataSetHandle(sid_t sid) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "ExtendedControllerBase::getDataSetHandle: No child "
|
|
||||||
<< " implementation provided, returning nullptr!" << std::endl;
|
|
||||||
#endif
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalDataPoolManager* ExtendedControllerBase::getHkManagerHandle() {
|
LocalDataPoolManager* ExtendedControllerBase::getHkManagerHandle() {
|
||||||
return &poolManager;
|
return &poolManager;
|
||||||
}
|
}
|
||||||
|
@@ -22,13 +22,14 @@ class ExtendedControllerBase: public ControllerBase,
|
|||||||
public:
|
public:
|
||||||
ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
|
ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
|
||||||
size_t commandQueueDepth = 3);
|
size_t commandQueueDepth = 3);
|
||||||
|
virtual ~ExtendedControllerBase();
|
||||||
|
|
||||||
/** SystemObjectIF overrides */
|
/* SystemObjectIF overrides */
|
||||||
virtual ReturnValue_t initialize() override;
|
virtual ReturnValue_t initialize() override;
|
||||||
|
|
||||||
virtual MessageQueueId_t getCommandQueue() const override;
|
virtual MessageQueueId_t getCommandQueue() const override;
|
||||||
|
|
||||||
/** ExecutableObjectIF overrides */
|
/* ExecutableObjectIF overrides */
|
||||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
@@ -49,22 +50,26 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual void performControlOperation() = 0;
|
virtual void performControlOperation() = 0;
|
||||||
|
|
||||||
/** Handle the four messages mentioned above */
|
/* Handle the four messages mentioned above */
|
||||||
void handleQueue() override;
|
void handleQueue() override;
|
||||||
|
|
||||||
/** HasActionsIF overrides */
|
/* HasActionsIF overrides */
|
||||||
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
||||||
MessageQueueId_t commandedBy, const uint8_t* data,
|
MessageQueueId_t commandedBy, const uint8_t* data,
|
||||||
size_t size) override;
|
size_t size) override;
|
||||||
|
|
||||||
/** HasLocalDatapoolIF overrides */
|
/* HasLocalDatapoolIF overrides */
|
||||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||||
virtual object_id_t getObjectId() const override;
|
virtual object_id_t getObjectId() const override;
|
||||||
virtual ReturnValue_t initializeLocalDataPool(
|
|
||||||
localpool::DataPool& localDataPoolMap,
|
|
||||||
LocalDataPoolManager& poolManager) override;
|
|
||||||
virtual uint32_t getPeriodicOperationFrequency() const override;
|
virtual uint32_t getPeriodicOperationFrequency() const override;
|
||||||
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
|
||||||
|
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||||
|
LocalDataPoolManager& poolManager) override = 0;
|
||||||
|
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0;
|
||||||
|
|
||||||
|
// Mode abstract functions
|
||||||
|
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
|
uint32_t *msToReachTheMode) override = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -19,7 +19,8 @@ class VirtualChannelReception;
|
|||||||
class DataLinkLayer : public CCSDSReturnValuesIF {
|
class DataLinkLayer : public CCSDSReturnValuesIF {
|
||||||
public:
|
public:
|
||||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_1;
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_1;
|
||||||
static const Event RF_AVAILABLE = MAKE_EVENT(0, severity::INFO); //!< A RF available signal was detected. P1: raw RFA state, P2: 0
|
//! [EXPORT] : [COMMENT] A RF available signal was detected. P1: raw RFA state, P2: 0
|
||||||
|
static const Event RF_AVAILABLE = MAKE_EVENT(0, severity::INFO);
|
||||||
static const Event RF_LOST = MAKE_EVENT(1, severity::INFO); //!< A previously found RF available signal was lost. P1: raw RFA state, P2: 0
|
static const Event RF_LOST = MAKE_EVENT(1, severity::INFO); //!< A previously found RF available signal was lost. P1: raw RFA state, P2: 0
|
||||||
static const Event BIT_LOCK = MAKE_EVENT(2, severity::INFO); //!< A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0
|
static const Event BIT_LOCK = MAKE_EVENT(2, severity::INFO); //!< A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0
|
||||||
static const Event BIT_LOCK_LOST = MAKE_EVENT(3, severity::INFO); //!< A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0
|
static const Event BIT_LOCK_LOST = MAKE_EVENT(3, severity::INFO); //!< A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
#include "MapPacketExtraction.h"
|
#include "MapPacketExtraction.h"
|
||||||
|
|
||||||
#include "../ipc/QueueFactory.h"
|
#include "../ipc/QueueFactory.h"
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||||
#include "../storagemanager/StorageManagerIF.h"
|
#include "../storagemanager/StorageManagerIF.h"
|
||||||
#include "../tmtcpacket/SpacePacketBase.h"
|
#include "../tmtcpacket/SpacePacketBase.h"
|
||||||
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
||||||
#include "../tmtcservices/TmTcMessage.h"
|
#include "../tmtcservices/TmTcMessage.h"
|
||||||
|
#include "../objectmanager/ObjectManager.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
|
MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
|
||||||
@@ -131,9 +134,9 @@ void MapPacketExtraction::clearBuffers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MapPacketExtraction::initialize() {
|
ReturnValue_t MapPacketExtraction::initialize() {
|
||||||
packetStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
|
packetStore = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
|
||||||
AcceptsTelecommandsIF* distributor = objectManager->get<
|
AcceptsTelecommandsIF* distributor = ObjectManager::instance()->
|
||||||
AcceptsTelecommandsIF>(packetDestination);
|
get<AcceptsTelecommandsIF>(packetDestination);
|
||||||
if ((packetStore != NULL) && (distributor != NULL)) {
|
if ((packetStore != NULL) && (distributor != NULL)) {
|
||||||
tcQueueId = distributor->getRequestQueue();
|
tcQueueId = distributor->getRequestQueue();
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
|
@@ -18,15 +18,13 @@ class PoolVariableIF;
|
|||||||
class DataSetIF {
|
class DataSetIF {
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS;
|
static constexpr uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS;
|
||||||
static constexpr ReturnValue_t INVALID_PARAMETER_DEFINITION =
|
static constexpr ReturnValue_t INVALID_PARAMETER_DEFINITION = MAKE_RETURN_CODE(1);
|
||||||
MAKE_RETURN_CODE( 0x01 );
|
static constexpr ReturnValue_t SET_WAS_ALREADY_READ = MAKE_RETURN_CODE(2);
|
||||||
static constexpr ReturnValue_t SET_WAS_ALREADY_READ = MAKE_RETURN_CODE( 0x02 );
|
static constexpr ReturnValue_t COMMITING_WITHOUT_READING = MAKE_RETURN_CODE(3);
|
||||||
static constexpr ReturnValue_t COMMITING_WITHOUT_READING =
|
|
||||||
MAKE_RETURN_CODE(0x03);
|
|
||||||
|
|
||||||
static constexpr ReturnValue_t DATA_SET_UNINITIALISED = MAKE_RETURN_CODE( 0x04 );
|
static constexpr ReturnValue_t DATA_SET_UNINITIALISED = MAKE_RETURN_CODE(4);
|
||||||
static constexpr ReturnValue_t DATA_SET_FULL = MAKE_RETURN_CODE( 0x05 );
|
static constexpr ReturnValue_t DATA_SET_FULL = MAKE_RETURN_CODE(5);
|
||||||
static constexpr ReturnValue_t POOL_VAR_NULL = MAKE_RETURN_CODE( 0x06 );
|
static constexpr ReturnValue_t POOL_VAR_NULL = MAKE_RETURN_CODE(6);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is an empty virtual destructor,
|
* @brief This is an empty virtual destructor,
|
||||||
|
@@ -7,7 +7,7 @@ HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
HkSwitchHelper::~HkSwitchHelper() {
|
HkSwitchHelper::~HkSwitchHelper() {
|
||||||
// TODO Auto-generated destructor stub
|
QueueFactory::instance()->deleteMessageQueue(actionQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t HkSwitchHelper::initialize() {
|
ReturnValue_t HkSwitchHelper::initialize() {
|
||||||
|
@@ -1,71 +1,82 @@
|
|||||||
#include "PoolDataSetBase.h"
|
#include "PoolDataSetBase.h"
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
#include "ReadCommitIFAttorney.h"
|
||||||
|
|
||||||
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
||||||
const size_t maxFillCount):
|
const size_t maxFillCount):
|
||||||
registeredVariables(registeredVariablesArray),
|
registeredVariables(registeredVariablesArray),
|
||||||
maxFillCount(maxFillCount) {
|
maxFillCount(maxFillCount) {}
|
||||||
}
|
|
||||||
|
|
||||||
PoolDataSetBase::~PoolDataSetBase() {}
|
PoolDataSetBase::~PoolDataSetBase() {}
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t PoolDataSetBase::registerVariable(
|
ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF *variable) {
|
||||||
PoolVariableIF *variable) {
|
if(registeredVariables == nullptr) {
|
||||||
if (state != States::STATE_SET_UNINITIALISED) {
|
/* Underlying container invalid */
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
if (state != States::STATE_SET_UNINITIALISED) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "DataSet::registerVariable: "
|
sif::error << "DataSet::registerVariable: Call made in wrong position." << std::endl;
|
||||||
"Call made in wrong position." << std::endl;
|
#else
|
||||||
|
sif::printError("DataSet::registerVariable: Call made in wrong position.");
|
||||||
#endif
|
#endif
|
||||||
return DataSetIF::DATA_SET_UNINITIALISED;
|
return DataSetIF::DATA_SET_UNINITIALISED;
|
||||||
}
|
}
|
||||||
if (variable == nullptr) {
|
if (variable == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "DataSet::registerVariable: "
|
sif::error << "DataSet::registerVariable: Pool variable is nullptr." << std::endl;
|
||||||
"Pool variable is nullptr." << std::endl;
|
#else
|
||||||
|
sif::printError("DataSet::registerVariable: Pool variable is nullptr.\n");
|
||||||
#endif
|
#endif
|
||||||
return DataSetIF::POOL_VAR_NULL;
|
return DataSetIF::POOL_VAR_NULL;
|
||||||
}
|
}
|
||||||
if (fillCount >= maxFillCount) {
|
if (fillCount >= maxFillCount) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "DataSet::registerVariable: "
|
sif::error << "DataSet::registerVariable: DataSet is full." << std::endl;
|
||||||
"DataSet is full." << std::endl;
|
#else
|
||||||
|
sif::printError("DataSet::registerVariable: DataSet is full.\n");
|
||||||
#endif
|
#endif
|
||||||
return DataSetIF::DATA_SET_FULL;
|
return DataSetIF::DATA_SET_FULL;
|
||||||
}
|
}
|
||||||
registeredVariables[fillCount] = variable;
|
registeredVariables[fillCount] = variable;
|
||||||
fillCount++;
|
fillCount++;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType,
|
ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType,
|
||||||
uint32_t lockTimeout) {
|
uint32_t lockTimeout) {
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
ReturnValue_t error = result;
|
ReturnValue_t error = result;
|
||||||
if (state == States::STATE_SET_UNINITIALISED) {
|
if (state == States::STATE_SET_UNINITIALISED) {
|
||||||
lockDataPool(timeoutType, lockTimeout);
|
lockDataPool(timeoutType, lockTimeout);
|
||||||
for (uint16_t count = 0; count < fillCount; count++) {
|
for (uint16_t count = 0; count < fillCount; count++) {
|
||||||
result = readVariable(count);
|
result = readVariable(count);
|
||||||
if(result != RETURN_OK) {
|
if(result != RETURN_OK) {
|
||||||
error = result;
|
error = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state = States::STATE_SET_WAS_READ;
|
state = States::STATE_SET_WAS_READ;
|
||||||
unlockDataPool();
|
unlockDataPool();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "DataSet::read(): "
|
sif::warning << "PoolDataSetBase::read: Call made in wrong position. Don't forget to "
|
||||||
"Call made in wrong position. Don't forget to commit"
|
"commit member datasets!" << std::endl;
|
||||||
" member datasets!" << std::endl;
|
#else
|
||||||
#endif
|
sif::printWarning("PoolDataSetBase::read: Call made in wrong position. Don't forget to "
|
||||||
result = SET_WAS_ALREADY_READ;
|
"commit member datasets!\n");
|
||||||
}
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
|
result = SET_WAS_ALREADY_READ;
|
||||||
|
}
|
||||||
|
|
||||||
if(error != HasReturnvaluesIF::RETURN_OK) {
|
if(error != HasReturnvaluesIF::RETURN_OK) {
|
||||||
result = error;
|
result = error;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t PoolDataSetBase::getFillCount() const {
|
uint16_t PoolDataSetBase::getFillCount() const {
|
||||||
@@ -73,144 +84,136 @@ uint16_t PoolDataSetBase::getFillCount() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
|
ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
if(registeredVariables[count] == nullptr) {
|
if(registeredVariables[count] == nullptr) {
|
||||||
// configuration error.
|
/* Configuration error. */
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These checks are often performed by the respective
|
/* These checks are often performed by the respective variable implementation too, but I guess
|
||||||
// variable implementation too, but I guess a double check does not hurt.
|
a double check does not hurt. */
|
||||||
if (registeredVariables[count]->getReadWriteMode() !=
|
if (registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_WRITE and
|
||||||
PoolVariableIF::VAR_WRITE and
|
registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) {
|
||||||
registeredVariables[count]->getDataPoolId()
|
if(protectEveryReadCommitCall) {
|
||||||
!= PoolVariableIF::NO_PARAMETER)
|
result = registeredVariables[count]->read(timeoutTypeForSingleVars,
|
||||||
{
|
mutexTimeoutForSingleVars);
|
||||||
if(protectEveryReadCommitCall) {
|
}
|
||||||
result = registeredVariables[count]->read(
|
else {
|
||||||
timeoutTypeForSingleVars,
|
/* The readWithoutLock function is protected, so we use the attorney here */
|
||||||
mutexTimeoutForSingleVars);
|
result = ReadCommitIFAttorney::readWithoutLock(registeredVariables[count]);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
result = registeredVariables[count]->readWithoutLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
result = INVALID_PARAMETER_DEFINITION;
|
result = INVALID_PARAMETER_DEFINITION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType,
|
ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType,
|
||||||
uint32_t lockTimeout) {
|
uint32_t lockTimeout) {
|
||||||
if (state == States::STATE_SET_WAS_READ) {
|
if (state == States::STATE_SET_WAS_READ) {
|
||||||
handleAlreadyReadDatasetCommit(timeoutType, lockTimeout);
|
handleAlreadyReadDatasetCommit(timeoutType, lockTimeout);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return handleUnreadDatasetCommit(timeoutType, lockTimeout);
|
return handleUnreadDatasetCommit(timeoutType, lockTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoolDataSetBase::handleAlreadyReadDatasetCommit(
|
void PoolDataSetBase::handleAlreadyReadDatasetCommit(
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
||||||
lockDataPool(timeoutType, lockTimeout);
|
lockDataPool(timeoutType, lockTimeout);
|
||||||
for (uint16_t count = 0; count < fillCount; count++) {
|
for (uint16_t count = 0; count < fillCount; count++) {
|
||||||
if (registeredVariables[count]->getReadWriteMode()
|
if ((registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_READ) and
|
||||||
!= PoolVariableIF::VAR_READ
|
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
|
||||||
&& registeredVariables[count]->getDataPoolId()
|
if(protectEveryReadCommitCall) {
|
||||||
!= PoolVariableIF::NO_PARAMETER) {
|
registeredVariables[count]->commit(timeoutTypeForSingleVars,
|
||||||
if(protectEveryReadCommitCall) {
|
mutexTimeoutForSingleVars);
|
||||||
registeredVariables[count]->commit(
|
}
|
||||||
timeoutTypeForSingleVars,
|
else {
|
||||||
mutexTimeoutForSingleVars);
|
/* The commitWithoutLock function is protected, so we use the attorney here */
|
||||||
}
|
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
|
||||||
else {
|
}
|
||||||
registeredVariables[count]->commitWithoutLock();
|
}
|
||||||
}
|
}
|
||||||
}
|
state = States::STATE_SET_UNINITIALISED;
|
||||||
}
|
unlockDataPool();
|
||||||
state = States::STATE_SET_UNINITIALISED;
|
|
||||||
unlockDataPool();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(
|
ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
lockDataPool(timeoutType, lockTimeout);
|
lockDataPool(timeoutType, lockTimeout);
|
||||||
for (uint16_t count = 0; count < fillCount; count++) {
|
for (uint16_t count = 0; count < fillCount; count++) {
|
||||||
if (registeredVariables[count]->getReadWriteMode()
|
if ((registeredVariables[count]->getReadWriteMode() == PoolVariableIF::VAR_WRITE) and
|
||||||
== PoolVariableIF::VAR_WRITE
|
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
|
||||||
&& registeredVariables[count]->getDataPoolId()
|
if(protectEveryReadCommitCall) {
|
||||||
!= PoolVariableIF::NO_PARAMETER) {
|
result = registeredVariables[count]->commit(timeoutTypeForSingleVars,
|
||||||
if(protectEveryReadCommitCall) {
|
mutexTimeoutForSingleVars);
|
||||||
result = registeredVariables[count]->commit(
|
}
|
||||||
timeoutTypeForSingleVars,
|
else {
|
||||||
mutexTimeoutForSingleVars);
|
/* The commitWithoutLock function is protected, so we use the attorney here */
|
||||||
}
|
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
|
||||||
else {
|
}
|
||||||
result = registeredVariables[count]->commitWithoutLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (registeredVariables[count]->getDataPoolId()
|
} else if (registeredVariables[count]->getDataPoolId()
|
||||||
!= PoolVariableIF::NO_PARAMETER) {
|
!= PoolVariableIF::NO_PARAMETER) {
|
||||||
if (result != COMMITING_WITHOUT_READING) {
|
if (result != COMMITING_WITHOUT_READING) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "DataSet::commit(): commit-without-read call made "
|
sif::error << "DataSet::commit(): commit-without-read call made "
|
||||||
"with non write-only variable." << std::endl;
|
"with non write-only variable." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
result = COMMITING_WITHOUT_READING;
|
result = COMMITING_WITHOUT_READING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state = States::STATE_SET_UNINITIALISED;
|
state = States::STATE_SET_UNINITIALISED;
|
||||||
unlockDataPool();
|
unlockDataPool();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType,
|
ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType,
|
||||||
uint32_t lockTimeout) {
|
uint32_t lockTimeout) {
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PoolDataSetBase::unlockDataPool() {
|
ReturnValue_t PoolDataSetBase::unlockDataPool() {
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size,
|
ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size,
|
||||||
const size_t maxSize, SerializeIF::Endianness streamEndianness) const {
|
const size_t maxSize, SerializeIF::Endianness streamEndianness) const {
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||||
for (uint16_t count = 0; count < fillCount; count++) {
|
for (uint16_t count = 0; count < fillCount; count++) {
|
||||||
result = registeredVariables[count]->serialize(buffer, size, maxSize,
|
result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness);
|
||||||
streamEndianness);
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
return result;
|
||||||
return result;
|
}
|
||||||
}
|
}
|
||||||
}
|
return result;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PoolDataSetBase::deSerialize(const uint8_t** buffer, size_t* size,
|
ReturnValue_t PoolDataSetBase::deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
SerializeIF::Endianness streamEndianness) {
|
SerializeIF::Endianness streamEndianness) {
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||||
for (uint16_t count = 0; count < fillCount; count++) {
|
for (uint16_t count = 0; count < fillCount; count++) {
|
||||||
result = registeredVariables[count]->deSerialize(buffer, size,
|
result = registeredVariables[count]->deSerialize(buffer, size,
|
||||||
streamEndianness);
|
streamEndianness);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t PoolDataSetBase::getSerializedSize() const {
|
size_t PoolDataSetBase::getSerializedSize() const {
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
for (uint16_t count = 0; count < fillCount; count++) {
|
for (uint16_t count = 0; count < fillCount; count++) {
|
||||||
size += registeredVariables[count]->getSerializedSize();
|
size += registeredVariables[count]->getSerializedSize();
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) {
|
void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) {
|
||||||
@@ -218,13 +221,13 @@ void PoolDataSetBase::setContainer(PoolVariableIF **variablesContainer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PoolVariableIF** PoolDataSetBase::getContainer() const {
|
PoolVariableIF** PoolDataSetBase::getContainer() const {
|
||||||
return registeredVariables;
|
return registeredVariables;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoolDataSetBase::setReadCommitProtectionBehaviour(
|
void PoolDataSetBase::setReadCommitProtectionBehaviour(
|
||||||
bool protectEveryReadCommit, MutexIF::TimeoutType timeoutType,
|
bool protectEveryReadCommit, MutexIF::TimeoutType timeoutType,
|
||||||
uint32_t mutexTimeout) {
|
uint32_t mutexTimeout) {
|
||||||
this->protectEveryReadCommitCall = protectEveryReadCommit;
|
this->protectEveryReadCommitCall = protectEveryReadCommit;
|
||||||
this->timeoutTypeForSingleVars = timeoutType;
|
this->timeoutTypeForSingleVars = timeoutType;
|
||||||
this->mutexTimeoutForSingleVars = mutexTimeout;
|
this->mutexTimeoutForSingleVars = mutexTimeout;
|
||||||
}
|
}
|
||||||
|
@@ -29,96 +29,99 @@
|
|||||||
* @author Bastian Baetz
|
* @author Bastian Baetz
|
||||||
* @ingroup data_pool
|
* @ingroup data_pool
|
||||||
*/
|
*/
|
||||||
class PoolDataSetBase: public PoolDataSetIF,
|
class PoolDataSetBase:
|
||||||
public SerializeIF,
|
public PoolDataSetIF,
|
||||||
public HasReturnvaluesIF {
|
public SerializeIF,
|
||||||
|
public HasReturnvaluesIF {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates an empty dataset. Use registerVariable or
|
* @brief Creates an empty dataset. Use registerVariable or
|
||||||
* supply a pointer to this dataset to PoolVariable
|
* supply a pointer to this dataset to PoolVariable
|
||||||
* initializations to register pool variables.
|
* initializations to register pool variables.
|
||||||
*/
|
*/
|
||||||
PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
PoolDataSetBase(PoolVariableIF** registeredVariablesArray, const size_t maxFillCount);
|
||||||
const size_t maxFillCount);
|
|
||||||
virtual~ PoolDataSetBase();
|
|
||||||
|
|
||||||
/**
|
/* Forbidden for now */
|
||||||
* @brief The read call initializes reading out all registered variables.
|
PoolDataSetBase(const PoolDataSetBase& otherSet) = delete;
|
||||||
* It is mandatory to call commit after every read call!
|
const PoolDataSetBase& operator=(const PoolDataSetBase& otherSet) = delete;
|
||||||
* @details
|
|
||||||
* It iterates through the list of registered variables and calls all read()
|
|
||||||
* functions of the registered pool variables (which read out their values
|
|
||||||
* from the data pool) which are not write-only.
|
|
||||||
* In case of an error (e.g. a wrong data type, or an invalid data pool id),
|
|
||||||
* the operation is aborted and @c INVALID_PARAMETER_DEFINITION returned.
|
|
||||||
*
|
|
||||||
* The data pool is locked during the whole read operation and
|
|
||||||
* freed afterwards. It is mandatory to call commit after a read call,
|
|
||||||
* even if the read operation is not successful!
|
|
||||||
* @return
|
|
||||||
* - @c RETURN_OK if all variables were read successfully.
|
|
||||||
* - @c INVALID_PARAMETER_DEFINITION if a pool entry does not exist or there
|
|
||||||
* is a type conflict.
|
|
||||||
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
|
|
||||||
* commit() in between
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t read(
|
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
|
||||||
uint32_t lockTimeout = 20) override;
|
|
||||||
/**
|
|
||||||
* @brief The commit call initializes writing back the registered variables.
|
|
||||||
* @details
|
|
||||||
* It iterates through the list of registered variables and calls the
|
|
||||||
* commit() method of the remaining registered variables (which write back
|
|
||||||
* their values to the pool).
|
|
||||||
*
|
|
||||||
* The data pool is locked during the whole commit operation and
|
|
||||||
* freed afterwards. The state changes to "was committed" after this operation.
|
|
||||||
*
|
|
||||||
* If the set does contain at least one variable which is not write-only
|
|
||||||
* commit() can only be called after read(). If the set only contains
|
|
||||||
* variables which are write only, commit() can be called without a
|
|
||||||
* preceding read() call. Every read call must be followed by a commit call!
|
|
||||||
* @return - @c RETURN_OK if all variables were read successfully.
|
|
||||||
* - @c COMMITING_WITHOUT_READING if set was not read yet and
|
|
||||||
* contains non write-only variables
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t commit(
|
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
|
||||||
uint32_t lockTimeout = 20) override;
|
|
||||||
|
|
||||||
/**
|
virtual~ PoolDataSetBase();
|
||||||
* Register the passed pool variable instance into the data set.
|
|
||||||
* @param variable
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t registerVariable( PoolVariableIF* variable) override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the means to lock the underlying data structure to ensure
|
* @brief The read call initializes reading out all registered variables.
|
||||||
* thread-safety. Default implementation is empty
|
* It is mandatory to call commit after every read call!
|
||||||
* @return Always returns -@c RETURN_OK
|
* @details
|
||||||
*/
|
* It iterates through the list of registered variables and calls all read()
|
||||||
virtual ReturnValue_t lockDataPool(
|
* functions of the registered pool variables (which read out their values
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
* from the data pool) which are not write-only.
|
||||||
uint32_t timeoutMs = 20) override;
|
* In case of an error (e.g. a wrong data type, or an invalid data pool id),
|
||||||
/**
|
* the operation is aborted and @c INVALID_PARAMETER_DEFINITION returned.
|
||||||
* Provides the means to unlock the underlying data structure to ensure
|
*
|
||||||
* thread-safety. Default implementation is empty
|
* The data pool is locked during the whole read operation and
|
||||||
* @return Always returns -@c RETURN_OK
|
* freed afterwards. It is mandatory to call commit after a read call,
|
||||||
*/
|
* even if the read operation is not successful!
|
||||||
virtual ReturnValue_t unlockDataPool() override;
|
* @return
|
||||||
|
* - @c RETURN_OK if all variables were read successfully.
|
||||||
|
* - @c INVALID_PARAMETER_DEFINITION if a pool entry does not exist or there
|
||||||
|
* is a type conflict.
|
||||||
|
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
|
||||||
|
* commit() in between
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||||
|
uint32_t lockTimeout = 20) override;
|
||||||
|
/**
|
||||||
|
* @brief The commit call initializes writing back the registered variables.
|
||||||
|
* @details
|
||||||
|
* It iterates through the list of registered variables and calls the
|
||||||
|
* commit() method of the remaining registered variables (which write back
|
||||||
|
* their values to the pool).
|
||||||
|
*
|
||||||
|
* The data pool is locked during the whole commit operation and
|
||||||
|
* freed afterwards. The state changes to "was committed" after this operation.
|
||||||
|
*
|
||||||
|
* If the set does contain at least one variable which is not write-only
|
||||||
|
* commit() can only be called after read(). If the set only contains
|
||||||
|
* variables which are write only, commit() can be called without a
|
||||||
|
* preceding read() call. Every read call must be followed by a commit call!
|
||||||
|
* @return - @c RETURN_OK if all variables were read successfully.
|
||||||
|
* - @c COMMITING_WITHOUT_READING if set was not read yet and
|
||||||
|
* contains non write-only variables
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||||
|
uint32_t lockTimeout = 20) override;
|
||||||
|
|
||||||
virtual uint16_t getFillCount() const;
|
/**
|
||||||
|
* Register the passed pool variable instance into the data set.
|
||||||
|
* @param variable
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t registerVariable( PoolVariableIF* variable) override;
|
||||||
|
|
||||||
/* SerializeIF implementations */
|
/**
|
||||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
* Provides the means to lock the underlying data structure to ensure
|
||||||
const size_t maxSize,
|
* thread-safety. Default implementation is empty
|
||||||
SerializeIF::Endianness streamEndianness) const override;
|
* @return Always returns -@c RETURN_OK
|
||||||
virtual size_t getSerializedSize() const override;
|
*/
|
||||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
virtual ReturnValue_t lockDataPool(
|
||||||
SerializeIF::Endianness streamEndianness) override;
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||||
|
uint32_t timeoutMs = 20) override;
|
||||||
|
/**
|
||||||
|
* Provides the means to unlock the underlying data structure to ensure
|
||||||
|
* thread-safety. Default implementation is empty
|
||||||
|
* @return Always returns -@c RETURN_OK
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t unlockDataPool() override;
|
||||||
|
|
||||||
|
virtual uint16_t getFillCount() const;
|
||||||
|
|
||||||
|
/* SerializeIF implementations */
|
||||||
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||||
|
const size_t maxSize,
|
||||||
|
SerializeIF::Endianness streamEndianness) const override;
|
||||||
|
virtual size_t getSerializedSize() const override;
|
||||||
|
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
|
SerializeIF::Endianness streamEndianness) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can be used to individually protect every read and commit call.
|
* Can be used to individually protect every read and commit call.
|
||||||
@@ -130,48 +133,48 @@ public:
|
|||||||
uint32_t mutexTimeout = 20);
|
uint32_t mutexTimeout = 20);
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The fill_count attribute ensures that the variables
|
* @brief The fill_count attribute ensures that the variables
|
||||||
* register in the correct array position and that the maximum
|
* register in the correct array position and that the maximum
|
||||||
* number of variables is not exceeded.
|
* number of variables is not exceeded.
|
||||||
*/
|
*/
|
||||||
uint16_t fillCount = 0;
|
uint16_t fillCount = 0;
|
||||||
/**
|
/**
|
||||||
* States of the seet.
|
* States of the seet.
|
||||||
*/
|
*/
|
||||||
enum class States {
|
enum class States {
|
||||||
STATE_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED
|
STATE_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED
|
||||||
STATE_SET_WAS_READ //!< DATA_SET_WAS_READ
|
STATE_SET_WAS_READ //!< DATA_SET_WAS_READ
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @brief state manages the internal state of the data set,
|
* @brief state manages the internal state of the data set,
|
||||||
* which is important e.g. for the behavior on destruction.
|
* which is important e.g. for the behavior on destruction.
|
||||||
*/
|
*/
|
||||||
States state = States::STATE_SET_UNINITIALISED;
|
States state = States::STATE_SET_UNINITIALISED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This array represents all pool variables registered in this set.
|
* @brief This array represents all pool variables registered in this set.
|
||||||
* Child classes can use a static or dynamic container to create
|
* Child classes can use a static or dynamic container to create
|
||||||
* an array of registered variables and assign the first entry here.
|
* an array of registered variables and assign the first entry here.
|
||||||
*/
|
*/
|
||||||
PoolVariableIF** registeredVariables = nullptr;
|
PoolVariableIF** registeredVariables = nullptr;
|
||||||
const size_t maxFillCount = 0;
|
const size_t maxFillCount = 0;
|
||||||
|
|
||||||
void setContainer(PoolVariableIF** variablesContainer);
|
void setContainer(PoolVariableIF** variablesContainer);
|
||||||
PoolVariableIF** getContainer() const;
|
PoolVariableIF** getContainer() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool protectEveryReadCommitCall = false;
|
bool protectEveryReadCommitCall = false;
|
||||||
MutexIF::TimeoutType timeoutTypeForSingleVars = MutexIF::TimeoutType::WAITING;
|
MutexIF::TimeoutType timeoutTypeForSingleVars = MutexIF::TimeoutType::WAITING;
|
||||||
uint32_t mutexTimeoutForSingleVars = 20;
|
uint32_t mutexTimeoutForSingleVars = 20;
|
||||||
|
|
||||||
ReturnValue_t readVariable(uint16_t count);
|
ReturnValue_t readVariable(uint16_t count);
|
||||||
void handleAlreadyReadDatasetCommit(
|
void handleAlreadyReadDatasetCommit(
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||||
uint32_t timeoutMs = 20);
|
uint32_t timeoutMs = 20);
|
||||||
ReturnValue_t handleUnreadDatasetCommit(
|
ReturnValue_t handleUnreadDatasetCommit(
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||||
uint32_t timeoutMs = 20);
|
uint32_t timeoutMs = 20);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */
|
#endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */
|
||||||
|
@@ -8,7 +8,9 @@
|
|||||||
* @brief Extendes the DataSetIF by adding abstract functions to lock
|
* @brief Extendes the DataSetIF by adding abstract functions to lock
|
||||||
* and unlock a data pool and read/commit semantics.
|
* and unlock a data pool and read/commit semantics.
|
||||||
*/
|
*/
|
||||||
class PoolDataSetIF: public DataSetIF, public ReadCommitIF {
|
class PoolDataSetIF:
|
||||||
|
virtual public DataSetIF,
|
||||||
|
virtual public ReadCommitIF {
|
||||||
public:
|
public:
|
||||||
virtual~ PoolDataSetIF() {};
|
virtual~ PoolDataSetIF() {};
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, bool setValid ):
|
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, bool setValid ):
|
||||||
length(initValue.size()), valid(setValid) {
|
length(static_cast<uint8_t>(initValue.size())), valid(setValid) {
|
||||||
this->address = new T[this->length];
|
this->address = new T[this->length];
|
||||||
if(initValue.size() == 0) {
|
if(initValue.size() == 0) {
|
||||||
std::memset(this->address, 0, this->getByteSize());
|
std::memset(this->address, 0, this->getByteSize());
|
||||||
|
@@ -8,9 +8,9 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Helper class to read data sets or pool variables
|
* @brief Helper class to read data sets or pool variables
|
||||||
*/
|
*/
|
||||||
class PoolReadHelper {
|
class PoolReadGuard {
|
||||||
public:
|
public:
|
||||||
PoolReadHelper(ReadCommitIF* readObject,
|
PoolReadGuard(ReadCommitIF* readObject,
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||||
uint32_t mutexTimeout = 20):
|
uint32_t mutexTimeout = 20):
|
||||||
readObject(readObject), mutexTimeout(mutexTimeout) {
|
readObject(readObject), mutexTimeout(mutexTimeout) {
|
||||||
@@ -32,8 +32,18 @@ public:
|
|||||||
return readResult;
|
return readResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
~PoolReadHelper() {
|
/**
|
||||||
if(readObject != nullptr) {
|
* @brief Can be used to suppress commit on destruction.
|
||||||
|
*/
|
||||||
|
void setNoCommitMode(bool commit) {
|
||||||
|
this->noCommit = commit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default destructor which will take care of commiting changed values.
|
||||||
|
*/
|
||||||
|
~PoolReadGuard() {
|
||||||
|
if(readObject != nullptr and not noCommit) {
|
||||||
readObject->commit(timeoutType, mutexTimeout);
|
readObject->commit(timeoutType, mutexTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +52,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
ReadCommitIF* readObject = nullptr;
|
ReadCommitIF* readObject = nullptr;
|
||||||
ReturnValue_t readResult = HasReturnvaluesIF::RETURN_OK;
|
ReturnValue_t readResult = HasReturnvaluesIF::RETURN_OK;
|
||||||
|
bool noCommit = false;
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||||
uint32_t mutexTimeout = 20;
|
uint32_t mutexTimeout = 20;
|
||||||
};
|
};
|
@@ -1,9 +1,10 @@
|
|||||||
#ifndef FSFW_DATAPOOL_POOLVARIABLEIF_H_
|
#ifndef FSFW_DATAPOOL_POOLVARIABLEIF_H_
|
||||||
#define FSFW_DATAPOOL_POOLVARIABLEIF_H_
|
#define FSFW_DATAPOOL_POOLVARIABLEIF_H_
|
||||||
|
|
||||||
|
#include "ReadCommitIF.h"
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
#include "../serialize/SerializeIF.h"
|
#include "../serialize/SerializeIF.h"
|
||||||
#include "ReadCommitIF.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This interface is used to control data pool
|
* @brief This interface is used to control data pool
|
||||||
@@ -18,47 +19,48 @@
|
|||||||
* @author Bastian Baetz
|
* @author Bastian Baetz
|
||||||
* @ingroup data_pool
|
* @ingroup data_pool
|
||||||
*/
|
*/
|
||||||
class PoolVariableIF : public SerializeIF,
|
class PoolVariableIF :
|
||||||
public ReadCommitIF {
|
public SerializeIF,
|
||||||
friend class PoolDataSetBase;
|
public ReadCommitIF {
|
||||||
friend class LocalPoolDataSetBase;
|
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF;
|
static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF;
|
||||||
static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0);
|
static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0);
|
||||||
static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1);
|
static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1);
|
||||||
|
|
||||||
static constexpr bool VALID = 1;
|
static constexpr bool VALID = 1;
|
||||||
static constexpr bool INVALID = 0;
|
static constexpr bool INVALID = 0;
|
||||||
static constexpr uint32_t NO_PARAMETER = 0xffffffff;
|
static constexpr uint32_t NO_PARAMETER = 0xffffffff;
|
||||||
|
|
||||||
enum ReadWriteMode_t {
|
enum ReadWriteMode_t {
|
||||||
VAR_READ, VAR_WRITE, VAR_READ_WRITE
|
VAR_READ, VAR_WRITE, VAR_READ_WRITE
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is an empty virtual destructor,
|
* @brief This is an empty virtual destructor,
|
||||||
* as it is proposed for C++ interfaces.
|
* as it is proposed for C++ interfaces.
|
||||||
*/
|
*/
|
||||||
virtual ~PoolVariableIF() {}
|
virtual ~PoolVariableIF() {}
|
||||||
/**
|
/**
|
||||||
* @brief This method returns if the variable is write-only,
|
* @brief This method returns if the variable is write-only,
|
||||||
* read-write or read-only.
|
* read-write or read-only.
|
||||||
*/
|
*/
|
||||||
virtual ReadWriteMode_t getReadWriteMode() const = 0;
|
virtual ReadWriteMode_t getReadWriteMode() const = 0;
|
||||||
/**
|
virtual void setReadWriteMode(ReadWriteMode_t newMode) = 0;
|
||||||
* @brief This operation shall return the data pool id of the variable.
|
|
||||||
*/
|
|
||||||
virtual uint32_t getDataPoolId() const = 0;
|
|
||||||
/**
|
|
||||||
* @brief With this call, the valid information of the
|
|
||||||
* variable is returned.
|
|
||||||
*/
|
|
||||||
virtual bool isValid() const = 0;
|
|
||||||
/**
|
|
||||||
* @brief With this call, the valid information of the variable is set.
|
|
||||||
*/
|
|
||||||
virtual void setValid(bool validity) = 0;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This operation shall return the data pool id of the variable.
|
||||||
|
*/
|
||||||
|
virtual uint32_t getDataPoolId() const = 0;
|
||||||
|
/**
|
||||||
|
* @brief With this call, the valid information of the
|
||||||
|
* variable is returned.
|
||||||
|
*/
|
||||||
|
virtual bool isValid() const = 0;
|
||||||
|
/**
|
||||||
|
* @brief With this call, the valid information of the variable is set.
|
||||||
|
*/
|
||||||
|
virtual void setValid(bool validity) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using pool_rwm_t = PoolVariableIF::ReadWriteMode_t;
|
using pool_rwm_t = PoolVariableIF::ReadWriteMode_t;
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
* semantics.
|
* semantics.
|
||||||
*/
|
*/
|
||||||
class ReadCommitIF {
|
class ReadCommitIF {
|
||||||
|
friend class ReadCommitIFAttorney;
|
||||||
public:
|
public:
|
||||||
virtual ~ReadCommitIF() {}
|
virtual ~ReadCommitIF() {}
|
||||||
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType,
|
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType,
|
||||||
@@ -18,9 +19,8 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
//! Optional and protected because this is interesting for classes grouping
|
/* Optional and protected because this is interesting for classes grouping members with commit
|
||||||
//! members with commit and read semantics where the lock is only necessary
|
and read semantics where the lock is only necessary once. */
|
||||||
//! once.
|
|
||||||
virtual ReturnValue_t readWithoutLock() {
|
virtual ReturnValue_t readWithoutLock() {
|
||||||
return read(MutexIF::TimeoutType::WAITING, 20);
|
return read(MutexIF::TimeoutType::WAITING, 20);
|
||||||
}
|
}
|
||||||
|
32
datapool/ReadCommitIFAttorney.h
Normal file
32
datapool/ReadCommitIFAttorney.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_
|
||||||
|
#define FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_
|
||||||
|
|
||||||
|
#include <fsfw/datapool/ReadCommitIF.h>
|
||||||
|
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This class determines which members are allowed to access protected members
|
||||||
|
* of the ReadCommitIF.
|
||||||
|
*/
|
||||||
|
class ReadCommitIFAttorney {
|
||||||
|
private:
|
||||||
|
static ReturnValue_t readWithoutLock(ReadCommitIF* readCommitIF) {
|
||||||
|
if(readCommitIF == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
return readCommitIF->readWithoutLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ReturnValue_t commitWithoutLock(ReadCommitIF* readCommitIF) {
|
||||||
|
if(readCommitIF == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
return readCommitIF->commitWithoutLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class PoolDataSetBase;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_ */
|
@@ -1,13 +1,15 @@
|
|||||||
#ifndef FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
|
#ifndef FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
|
||||||
#define FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
|
#define FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
|
||||||
|
|
||||||
#include "PoolDataSetIF.h"
|
#include "PoolDataSetIF.h"
|
||||||
|
|
||||||
class SharedDataSetIF: public PoolDataSetIF {
|
class SharedDataSetIF {
|
||||||
public:
|
public:
|
||||||
virtual ~SharedDataSetIF() {};
|
virtual ~SharedDataSetIF() {};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ReturnValue_t lockDataset(dur_millis_t mutexTimeout) = 0;
|
virtual ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType,
|
||||||
|
dur_millis_t mutexTimeout) = 0;
|
||||||
virtual ReturnValue_t unlockDataset() = 0;
|
virtual ReturnValue_t unlockDataset() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -18,7 +18,7 @@ public:
|
|||||||
* This function is protected because it should only be used by the
|
* This function is protected because it should only be used by the
|
||||||
* class imlementing the interface.
|
* class imlementing the interface.
|
||||||
*/
|
*/
|
||||||
virtual LocalDataPoolManager* getHkManagerHandle() = 0;
|
virtual LocalDataPoolManager* getPoolManagerHandle() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@@ -23,11 +23,22 @@ class LocalPoolObjectBase;
|
|||||||
* @details
|
* @details
|
||||||
* Any class implementing this interface shall also have a LocalDataPoolManager member class which
|
* Any class implementing this interface shall also have a LocalDataPoolManager member class which
|
||||||
* contains the actual pool data structure and exposes the public interface for it.
|
* contains the actual pool data structure and exposes the public interface for it.
|
||||||
|
*
|
||||||
* The local data pool can be accessed using helper classes by using the
|
* The local data pool can be accessed using helper classes by using the
|
||||||
* LocalPoolVariable, LocalPoolVector or LocalDataSet classes. Every local pool variable can
|
* LocalPoolVariable, LocalPoolVector or LocalDataSet classes. Every local pool variable can
|
||||||
* be uniquely identified by a global pool ID (gp_id_t) and every dataset tied
|
* be uniquely identified by a global pool ID (gp_id_t) and every dataset tied
|
||||||
* to a pool manager can be uniqely identified by a global structure ID (sid_t).
|
* to a pool manager can be uniqely identified by a global structure ID (sid_t).
|
||||||
*
|
*
|
||||||
|
* All software objects which want to use the local pool of another object shall also use this
|
||||||
|
* interface, for example to get a handle to the subscription interface. The interface
|
||||||
|
* can be retrieved using the object manager, provided the target object is a SystemObject.
|
||||||
|
* For example, the following line of code can be used to retrieve the interface
|
||||||
|
*
|
||||||
|
* HasLocalDataPoolIF* poolIF = ObjectManager::instance()->
|
||||||
|
* get<HasLocalDataPoolIF>(objects::SOME_OBJECT);
|
||||||
|
* if(poolIF != nullptr) {
|
||||||
|
* doSomething()
|
||||||
|
* }
|
||||||
*/
|
*/
|
||||||
class HasLocalDataPoolIF {
|
class HasLocalDataPoolIF {
|
||||||
friend class HasLocalDpIFManagerAttorney;
|
friend class HasLocalDpIFManagerAttorney;
|
||||||
@@ -55,34 +66,45 @@ public:
|
|||||||
* usually be the period the pool owner performs its periodic operation.
|
* usually be the period the pool owner performs its periodic operation.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual uint32_t getPeriodicOperationFrequency() const = 0;
|
virtual dur_millis_t getPeriodicOperationFrequency() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function will be called by the manager if an update
|
* @brief This function will be called by the manager if an update
|
||||||
* notification is received.
|
* notification is received.
|
||||||
* @details HasLocalDataPoolIF
|
* @details HasLocalDataPoolIF
|
||||||
* Can be overriden by the child class to handle changed datasets.
|
* Can be overriden by the child class to handle changed datasets.
|
||||||
* @param sid
|
* @param sid SID of the updated set
|
||||||
* @param storeId If a snapshot was requested, data will be located inside
|
* @param storeId If a snapshot was requested, data will be located inside
|
||||||
* the IPC store with this store ID.
|
* the IPC store with this store ID.
|
||||||
|
* @param clearMessage If this is set to true, the pool manager will take care of
|
||||||
|
* clearing the store automatically
|
||||||
*/
|
*/
|
||||||
virtual void handleChangedDataset(sid_t sid,
|
virtual void handleChangedDataset(sid_t sid,
|
||||||
store_address_t storeId = storeId::INVALID_STORE_ADDRESS) {
|
store_address_t storeId = storeId::INVALID_STORE_ADDRESS,
|
||||||
return;
|
bool* clearMessage = nullptr) {
|
||||||
|
if(clearMessage != nullptr) {
|
||||||
|
*clearMessage = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function will be called by the manager if an update
|
* @brief This function will be called by the manager if an update
|
||||||
* notification is received.
|
* notification is received.
|
||||||
* @details
|
* @details
|
||||||
* Can be overriden by the child class to handle changed pool IDs.
|
* Can be overriden by the child class to handle changed pool variables.
|
||||||
* @param sid
|
* @param gpid GPID of the updated variable.
|
||||||
* @param storeId If a snapshot was requested, data will be located inside
|
* @param storeId If a snapshot was requested, data will be located inside
|
||||||
* the IPC store with this store ID.
|
* the IPC store with this store ID.
|
||||||
|
* @param clearMessage Relevant for snapshots. If the boolean this points to is set to true,
|
||||||
|
* the pool manager will take care of clearing the store automatically
|
||||||
|
* after the callback.
|
||||||
*/
|
*/
|
||||||
virtual void handleChangedPoolVariable(lp_id_t poolId,
|
virtual void handleChangedPoolVariable(gp_id_t gpid,
|
||||||
store_address_t storeId = storeId::INVALID_STORE_ADDRESS) {
|
store_address_t storeId = storeId::INVALID_STORE_ADDRESS,
|
||||||
return;
|
bool* clearMessage = nullptr) {
|
||||||
|
if(clearMessage != nullptr) {
|
||||||
|
*clearMessage = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,8 +174,8 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) {
|
virtual LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "HasLocalDataPoolIF::getPoolObjectHandle: Not overriden"
|
sif::warning << "HasLocalDataPoolIF::getPoolObjectHandle: Not overriden. "
|
||||||
<< ". Returning nullptr!" << std::endl;
|
"Returning nullptr!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("HasLocalDataPoolIF::getPoolObjectHandle: "
|
sif::printWarning("HasLocalDataPoolIF::getPoolObjectHandle: "
|
||||||
"Not overriden. Returning nullptr!\n");
|
"Not overriden. Returning nullptr!\n");
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@
|
|||||||
#include "../ipc/MutexIF.h"
|
#include "../ipc/MutexIF.h"
|
||||||
#include "../ipc/CommandMessage.h"
|
#include "../ipc/CommandMessage.h"
|
||||||
#include "../ipc/MessageQueueIF.h"
|
#include "../ipc/MessageQueueIF.h"
|
||||||
#include "../ipc/MutexHelper.h"
|
#include "../ipc/MutexGuard.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -24,7 +24,7 @@ void setStaticFrameworkObjectIds();
|
|||||||
}
|
}
|
||||||
|
|
||||||
class LocalPoolDataSetBase;
|
class LocalPoolDataSetBase;
|
||||||
class HousekeepingPacketUpdate;
|
class HousekeepingSnapshot;
|
||||||
class HasLocalDataPoolIF;
|
class HasLocalDataPoolIF;
|
||||||
class LocalDataPool;
|
class LocalDataPool;
|
||||||
|
|
||||||
@@ -52,17 +52,17 @@ class LocalDataPool;
|
|||||||
* Each pool entry has a valid state too.
|
* Each pool entry has a valid state too.
|
||||||
* @author R. Mueller
|
* @author R. Mueller
|
||||||
*/
|
*/
|
||||||
class LocalDataPoolManager: public ProvidesDataPoolSubscriptionIF,
|
class LocalDataPoolManager:
|
||||||
public AccessPoolManagerIF {
|
public ProvidesDataPoolSubscriptionIF,
|
||||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
public AccessPoolManagerIF {
|
||||||
//! Some classes using the pool manager directly need to access class internals of the
|
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||||
//! manager. The attorney provides granular control of access to these internals.
|
//! Some classes using the pool manager directly need to access class internals of the
|
||||||
friend class LocalDpManagerAttorney;
|
//! manager. The attorney provides granular control of access to these internals.
|
||||||
|
friend class LocalDpManagerAttorney;
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
|
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
|
||||||
|
|
||||||
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0);
|
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0);
|
||||||
|
|
||||||
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1);
|
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1);
|
||||||
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
|
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
|
||||||
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
|
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
|
||||||
@@ -81,29 +81,29 @@ public:
|
|||||||
* @param appendValidityBuffer Specify whether a buffer containing the
|
* @param appendValidityBuffer Specify whether a buffer containing the
|
||||||
* validity state is generated when serializing or deserializing packets.
|
* validity state is generated when serializing or deserializing packets.
|
||||||
*/
|
*/
|
||||||
LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
|
LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
|
||||||
bool appendValidityBuffer = true);
|
bool appendValidityBuffer = true);
|
||||||
virtual~ LocalDataPoolManager();
|
virtual~ LocalDataPoolManager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns the queue to use. Make sure to call this in the #initialize
|
* Assigns the queue to use. Make sure to call this in the #initialize
|
||||||
* function of the owner.
|
* function of the owner.
|
||||||
* @param queueToUse
|
* @param queueToUse
|
||||||
* @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc
|
* @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t initialize(MessageQueueIF* queueToUse);
|
ReturnValue_t initialize(MessageQueueIF* queueToUse);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the map by calling the map initialization function and
|
* Initializes the map by calling the map initialization function and
|
||||||
* setting the periodic factor for non-diagnostic packets.
|
* setting the periodic factor for non-diagnostic packets.
|
||||||
* Don't forget to call this in the #initializeAfterTaskCreation call of
|
* Don't forget to call this in the #initializeAfterTaskCreation call of
|
||||||
* the owner, otherwise the map will be invalid!
|
* the owner, otherwise the map will be invalid!
|
||||||
* @param nonDiagInvlFactor
|
* @param nonDiagInvlFactor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t initializeAfterTaskCreation(
|
ReturnValue_t initializeAfterTaskCreation(
|
||||||
uint8_t nonDiagInvlFactor = 5);
|
uint8_t nonDiagInvlFactor = 5);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This should be called in the periodic handler of the owner.
|
* @brief This should be called in the periodic handler of the owner.
|
||||||
@@ -116,49 +116,49 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t performHkOperation();
|
virtual ReturnValue_t performHkOperation();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for the generation of periodic packets.
|
* @brief Subscribe for the generation of periodic packets.
|
||||||
* @details
|
* @details
|
||||||
* This subscription mechanism will generally be used by the data creator
|
* This subscription mechanism will generally be used by the data creator
|
||||||
* to generate housekeeping packets which are downlinked directly.
|
* to generate housekeeping packets which are downlinked directly.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
|
ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
|
||||||
float collectionInterval, bool isDiagnostics,
|
float collectionInterval, bool isDiagnostics,
|
||||||
object_id_t packetDestination = defaultHkDestination) override;
|
object_id_t packetDestination = defaultHkDestination) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for the generation of packets if the dataset
|
* @brief Subscribe for the generation of packets if the dataset
|
||||||
* is marked as changed.
|
* is marked as changed.
|
||||||
* @details
|
* @details
|
||||||
* This subscription mechanism will generally be used by the data creator.
|
* This subscription mechanism will generally be used by the data creator.
|
||||||
* @param sid
|
* @param sid
|
||||||
* @param isDiagnostics
|
* @param isDiagnostics
|
||||||
* @param packetDestination
|
* @param packetDestination
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t subscribeForUpdatePackets(sid_t sid, bool reportingEnabled,
|
ReturnValue_t subscribeForUpdatePacket(sid_t sid, bool reportingEnabled,
|
||||||
bool isDiagnostics,
|
bool isDiagnostics,
|
||||||
object_id_t packetDestination = defaultHkDestination) override;
|
object_id_t packetDestination = defaultHkDestination) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for a notification message which will be sent
|
* @brief Subscribe for a notification message which will be sent
|
||||||
* if a dataset has changed.
|
* if a dataset has changed.
|
||||||
* @details
|
* @details
|
||||||
* This subscription mechanism will generally be used internally by
|
* This subscription mechanism will generally be used internally by
|
||||||
* other software components.
|
* other software components.
|
||||||
* @param setId Set ID of the set to receive update messages from.
|
* @param setId Set ID of the set to receive update messages from.
|
||||||
* @param destinationObject
|
* @param destinationObject
|
||||||
* @param targetQueueId
|
* @param targetQueueId
|
||||||
* @param generateSnapshot If this is set to true, a copy of the current
|
* @param generateSnapshot If this is set to true, a copy of the current
|
||||||
* data with a timestamp will be generated and sent via message.
|
* data with a timestamp will be generated and sent via message.
|
||||||
* Otherwise, only an notification message is sent.
|
* Otherwise, only an notification message is sent.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId,
|
ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId,
|
||||||
object_id_t destinationObject,
|
object_id_t destinationObject,
|
||||||
MessageQueueId_t targetQueueId,
|
MessageQueueId_t targetQueueId,
|
||||||
bool generateSnapshot) override;
|
bool generateSnapshot) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for an notification message which will be sent if a
|
* @brief Subscribe for an notification message which will be sent if a
|
||||||
@@ -174,23 +174,21 @@ public:
|
|||||||
* Otherwise, only an notification message is sent.
|
* Otherwise, only an notification message is sent.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t subscribeForVariableUpdateMessages(const lp_id_t localPoolId,
|
ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId,
|
||||||
object_id_t destinationObject,
|
object_id_t destinationObject,
|
||||||
MessageQueueId_t targetQueueId,
|
MessageQueueId_t targetQueueId,
|
||||||
bool generateSnapshot) override;
|
bool generateSnapshot) override;
|
||||||
|
|
||||||
MutexIF* getLocalPoolMutex() override;
|
/**
|
||||||
|
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
||||||
/**
|
* than diagnostic packets.
|
||||||
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
* A factor can be specified to determine the minimum sampling frequency
|
||||||
* than diagnostic packets.
|
* for non-diagnostic packets. The minimum sampling frequency of the
|
||||||
* A factor can be specified to determine the minimum sampling frequency
|
* diagnostics packets,which is usually jusst the period of the
|
||||||
* for non-diagnostic packets. The minimum sampling frequency of the
|
* performOperation calls, is multiplied with that factor.
|
||||||
* diagnostics packets,which is usually jusst the period of the
|
* @param factor
|
||||||
* performOperation calls, is multiplied with that factor.
|
*/
|
||||||
* @param factor
|
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
|
||||||
*/
|
|
||||||
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The manager is also able to handle housekeeping messages.
|
* @brief The manager is also able to handle housekeeping messages.
|
||||||
@@ -206,18 +204,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t handleHousekeepingMessage(CommandMessage* message);
|
virtual ReturnValue_t handleHousekeepingMessage(CommandMessage* message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a housekeeping packet with a given SID.
|
* Generate a housekeeping packet with a given SID.
|
||||||
* @param sid
|
* @param sid
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t generateHousekeepingPacket(sid_t sid,
|
ReturnValue_t generateHousekeepingPacket(sid_t sid,
|
||||||
LocalPoolDataSetBase* dataSet, bool forDownlink,
|
LocalPoolDataSetBase* dataSet, bool forDownlink,
|
||||||
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
|
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
|
||||||
|
|
||||||
HasLocalDataPoolIF* getOwner();
|
HasLocalDataPoolIF* getOwner();
|
||||||
|
|
||||||
ReturnValue_t printPoolEntry(lp_id_t localPoolId);
|
ReturnValue_t printPoolEntry(lp_id_t localPoolId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Different types of housekeeping reporting are possible.
|
* Different types of housekeeping reporting are possible.
|
||||||
@@ -236,22 +234,19 @@ public:
|
|||||||
PERIODIC,
|
PERIODIC,
|
||||||
//! Housekeeping packet will be generated if values have changed.
|
//! Housekeeping packet will be generated if values have changed.
|
||||||
UPDATE_HK,
|
UPDATE_HK,
|
||||||
//! Update notification will be sent out as message.
|
//! Update notification will be sent out as message.
|
||||||
UPDATE_NOTIFICATION,
|
UPDATE_NOTIFICATION,
|
||||||
//! Notification will be sent out as message and a snapshot of the
|
//! Notification will be sent out as message and a snapshot of the
|
||||||
//! current data will be generated.
|
//! current data will be generated.
|
||||||
UPDATE_SNAPSHOT,
|
UPDATE_SNAPSHOT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/** Different data types are possible in the HK receiver map. For example, updates can be
|
||||||
* Different data types are possible in the HK receiver map.
|
requested for full datasets or for single pool variables. Periodic reporting is only possible
|
||||||
* For example, updates can be requested for full datasets or
|
for data sets. */
|
||||||
* for single pool variables. Periodic reporting is only possible for
|
|
||||||
* data sets.
|
|
||||||
*/
|
|
||||||
enum class DataType: uint8_t {
|
enum class DataType: uint8_t {
|
||||||
LOCAL_POOL_VARIABLE,
|
LOCAL_POOL_VARIABLE,
|
||||||
DATA_SET
|
DATA_SET
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Copying forbidden */
|
/* Copying forbidden */
|
||||||
@@ -267,11 +262,22 @@ public:
|
|||||||
|
|
||||||
object_id_t getCreatorObjectId() const;
|
object_id_t getCreatorObjectId() const;
|
||||||
|
|
||||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
/**
|
||||||
private:
|
* Get the pointer to the mutex. Can be used to lock the data pool
|
||||||
|
* externally. Use with care and don't forget to unlock locked mutexes!
|
||||||
|
* For now, only friend classes can accss this function.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
MutexIF* getMutexHandle();
|
||||||
|
|
||||||
|
virtual LocalDataPoolManager* getPoolManagerHandle() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** Core data structure for the actual pool data */
|
||||||
localpool::DataPool localPoolMap;
|
localpool::DataPool localPoolMap;
|
||||||
//! Every housekeeping data manager has a mutex to protect access
|
/** Every housekeeping data manager has a mutex to protect access
|
||||||
//! to it's data pool.
|
to it's data pool. */
|
||||||
MutexIF* mutex = nullptr;
|
MutexIF* mutex = nullptr;
|
||||||
|
|
||||||
/** The class which actually owns the manager (and its datapool). */
|
/** The class which actually owns the manager (and its datapool). */
|
||||||
@@ -279,9 +285,9 @@ private:
|
|||||||
|
|
||||||
uint8_t nonDiagnosticIntervalFactor = 0;
|
uint8_t nonDiagnosticIntervalFactor = 0;
|
||||||
|
|
||||||
/** Default receiver for periodic HK packets */
|
/** Default receiver for periodic HK packets */
|
||||||
static object_id_t defaultHkDestination;
|
static object_id_t defaultHkDestination;
|
||||||
MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE;
|
||||||
|
|
||||||
union DataId {
|
union DataId {
|
||||||
DataId(): sid() {};
|
DataId(): sid() {};
|
||||||
@@ -291,10 +297,10 @@ private:
|
|||||||
|
|
||||||
/** The data pool manager will keep an internal map of HK receivers. */
|
/** The data pool manager will keep an internal map of HK receivers. */
|
||||||
struct HkReceiver {
|
struct HkReceiver {
|
||||||
/** Object ID of receiver */
|
/** Object ID of receiver */
|
||||||
object_id_t objectId = objects::NO_OBJECT;
|
object_id_t objectId = objects::NO_OBJECT;
|
||||||
|
|
||||||
DataType dataType = DataType::DATA_SET;
|
DataType dataType = DataType::DATA_SET;
|
||||||
DataId dataId;
|
DataId dataId;
|
||||||
|
|
||||||
ReportingType reportingType = ReportingType::PERIODIC;
|
ReportingType reportingType = ReportingType::PERIODIC;
|
||||||
@@ -304,7 +310,7 @@ private:
|
|||||||
/** This vector will contain the list of HK receivers. */
|
/** This vector will contain the list of HK receivers. */
|
||||||
using HkReceivers = std::vector<struct HkReceiver>;
|
using HkReceivers = std::vector<struct HkReceiver>;
|
||||||
|
|
||||||
HkReceivers hkReceiversMap;
|
HkReceivers hkReceivers;
|
||||||
|
|
||||||
struct HkUpdateResetHelper {
|
struct HkUpdateResetHelper {
|
||||||
DataType dataType = DataType::DATA_SET;
|
DataType dataType = DataType::DATA_SET;
|
||||||
@@ -314,7 +320,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
using HkUpdateResetList = std::vector<struct HkUpdateResetHelper>;
|
using HkUpdateResetList = std::vector<struct HkUpdateResetHelper>;
|
||||||
// Will only be created when needed.
|
/** This list is used to manage creating multiple update packets and only resetting
|
||||||
|
the update flag if all of them were created. Will only be created when needed. */
|
||||||
HkUpdateResetList* hkUpdateResetList = nullptr;
|
HkUpdateResetList* hkUpdateResetList = nullptr;
|
||||||
|
|
||||||
/** This is the map holding the actual data. Should only be initialized
|
/** This is the map holding the actual data. Should only be initialized
|
||||||
@@ -324,37 +331,28 @@ private:
|
|||||||
* of generated housekeeping packets. */
|
* of generated housekeeping packets. */
|
||||||
bool appendValidityBuffer = true;
|
bool appendValidityBuffer = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Queue used for communication, for example commands.
|
* @brief Queue used for communication, for example commands.
|
||||||
* Is also used to send messages. Can be set either in the constructor
|
* Is also used to send messages. Can be set either in the constructor
|
||||||
* or in the initialize() function.
|
* or in the initialize() function.
|
||||||
*/
|
*/
|
||||||
MessageQueueIF* hkQueue = nullptr;
|
MessageQueueIF* hkQueue = nullptr;
|
||||||
|
|
||||||
/** Global IPC store is used to store all packets. */
|
/** Global IPC store is used to store all packets. */
|
||||||
StorageManagerIF* ipcStore = nullptr;
|
StorageManagerIF* ipcStore = nullptr;
|
||||||
/**
|
|
||||||
* Get the pointer to the mutex. Can be used to lock the data pool
|
|
||||||
* externally. Use with care and don't forget to unlock locked mutexes!
|
|
||||||
* For now, only friend classes can accss this function.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
MutexIF* getMutexHandle();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a variable by supplying its local pool ID and assign the pool
|
* Read a variable by supplying its local pool ID and assign the pool
|
||||||
* entry to the supplied PoolEntry pointer. The type of the pool entry
|
* entry to the supplied PoolEntry pointer. The type of the pool entry
|
||||||
* is deduced automatically. This call is not thread-safe!
|
* is deduced automatically. This call is not thread-safe!
|
||||||
* For now, only friend classes like LocalPoolVar may access this
|
* For now, only classes designated by the LocalDpManagerAttorney may use this function.
|
||||||
* function.
|
* @tparam T Type of the pool entry
|
||||||
* @tparam T Type of the pool entry
|
* @param localPoolId Pool ID of the variable to read
|
||||||
* @param localPoolId Pool ID of the variable to read
|
* @param poolVar [out] Corresponding pool entry will be assigned to the
|
||||||
* @param poolVar [out] Corresponding pool entry will be assigned to the
|
* supplied pointer.
|
||||||
* supplied pointer.
|
* @return
|
||||||
* @return
|
*/
|
||||||
*/
|
template <class T> ReturnValue_t fetchPoolEntry(lp_id_t localPoolId, PoolEntry<T> **poolEntry);
|
||||||
template <class T> ReturnValue_t fetchPoolEntry(lp_id_t localPoolId,
|
|
||||||
PoolEntry<T> **poolEntry);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is used to fill the local data pool map with pool
|
* This function is used to fill the local data pool map with pool
|
||||||
@@ -364,55 +362,53 @@ private:
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t initializeHousekeepingPoolEntriesOnce();
|
ReturnValue_t initializeHousekeepingPoolEntriesOnce();
|
||||||
|
|
||||||
ReturnValue_t serializeHkPacketIntoStore(
|
MutexIF* getLocalPoolMutex() override;
|
||||||
HousekeepingPacketDownlink& hkPacket,
|
|
||||||
store_address_t& storeId, bool forDownlink, size_t* serializedSize);
|
|
||||||
|
|
||||||
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
|
ReturnValue_t serializeHkPacketIntoStore(HousekeepingPacketDownlink& hkPacket,
|
||||||
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable,
|
store_address_t& storeId, bool forDownlink, size_t* serializedSize);
|
||||||
bool isDiagnostics);
|
|
||||||
ReturnValue_t changeCollectionInterval(sid_t sid,
|
|
||||||
float newCollectionInterval, bool isDiagnostics);
|
|
||||||
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
|
|
||||||
|
|
||||||
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
|
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
|
||||||
void handleChangeResetLogic(DataType type,
|
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, bool isDiagnostics);
|
||||||
DataId dataId, MarkChangedIF* toReset);
|
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval,
|
||||||
void resetHkUpdateResetHelper();
|
bool isDiagnostics);
|
||||||
|
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
|
||||||
|
|
||||||
ReturnValue_t handleHkUpdate(HkReceiver& hkReceiver,
|
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
|
||||||
ReturnValue_t& status);
|
void handleChangeResetLogic(DataType type,
|
||||||
ReturnValue_t handleNotificationUpdate(HkReceiver& hkReceiver,
|
DataId dataId, MarkChangedIF* toReset);
|
||||||
ReturnValue_t& status);
|
void resetHkUpdateResetHelper();
|
||||||
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver,
|
|
||||||
ReturnValue_t& status);
|
|
||||||
ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket,
|
|
||||||
store_address_t& storeId);
|
|
||||||
|
|
||||||
void printWarningOrError(sif::OutputTypes outputType,
|
ReturnValue_t handleHkUpdate(HkReceiver& hkReceiver, ReturnValue_t& status);
|
||||||
const char* functionName,
|
ReturnValue_t handleNotificationUpdate(HkReceiver& hkReceiver, ReturnValue_t& status);
|
||||||
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver, ReturnValue_t& status);
|
||||||
const char* errorPrint = nullptr);
|
ReturnValue_t addUpdateToStore(HousekeepingSnapshot& updatePacket, store_address_t& storeId);
|
||||||
|
|
||||||
|
void printWarningOrError(sif::OutputTypes outputType, const char* functionName,
|
||||||
|
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
||||||
|
const char* errorPrint = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<class T> inline
|
template<class T> inline
|
||||||
ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
|
ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, PoolEntry<T> **poolEntry) {
|
||||||
PoolEntry<T> **poolEntry) {
|
if(poolEntry == nullptr) {
|
||||||
auto poolIter = localPoolMap.find(localPoolId);
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
if (poolIter == localPoolMap.end()) {
|
}
|
||||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
|
||||||
localpool::POOL_ENTRY_NOT_FOUND);
|
|
||||||
return localpool::POOL_ENTRY_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
|
auto poolIter = localPoolMap.find(localPoolId);
|
||||||
if(*poolEntry == nullptr) {
|
if (poolIter == localPoolMap.end()) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
|
||||||
localpool::POOL_ENTRY_TYPE_CONFLICT);
|
localpool::POOL_ENTRY_NOT_FOUND);
|
||||||
return localpool::POOL_ENTRY_TYPE_CONFLICT;
|
return localpool::POOL_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
|
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
|
||||||
|
if(*poolEntry == nullptr) {
|
||||||
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
|
||||||
|
localpool::POOL_ENTRY_TYPE_CONFLICT);
|
||||||
|
return localpool::POOL_ENTRY_TYPE_CONFLICT;
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -4,11 +4,26 @@
|
|||||||
#include "LocalPoolDataSetBase.h"
|
#include "LocalPoolDataSetBase.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This dataset type can be used to group related pool variables if the number of
|
||||||
|
* variables should not be fixed.
|
||||||
|
* @details
|
||||||
|
* This will is the primary data structure to organize pool variables into
|
||||||
|
* sets which can be accessed via the housekeeping service interface or
|
||||||
|
* which can be sent to other software objects.
|
||||||
|
*
|
||||||
|
* It is recommended to read the documentation of the LocalPoolDataSetBase
|
||||||
|
* class for more information on how this class works and how to use it.
|
||||||
|
* @tparam capacity Capacity of the static dataset, which is usually known
|
||||||
|
* beforehand.
|
||||||
|
*/
|
||||||
class LocalDataSet: public LocalPoolDataSetBase {
|
class LocalDataSet: public LocalPoolDataSetBase {
|
||||||
public:
|
public:
|
||||||
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
|
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
|
||||||
const size_t maxSize);
|
const size_t maxSize);
|
||||||
|
|
||||||
LocalDataSet(sid_t sid, const size_t maxSize);
|
LocalDataSet(sid_t sid, const size_t maxSize);
|
||||||
|
|
||||||
virtual~ LocalDataSet();
|
virtual~ LocalDataSet();
|
||||||
|
|
||||||
//! Copying forbidden for now.
|
//! Copying forbidden for now.
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
#include "internal/HasLocalDpIFUserAttorney.h"
|
#include "internal/HasLocalDpIFUserAttorney.h"
|
||||||
|
|
||||||
#include "../serviceinterface/ServiceInterface.h"
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
|
#include "../objectmanager/ObjectManager.h"
|
||||||
|
#include "../globalfunctions/bitutility.h"
|
||||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||||
#include "../housekeeping/PeriodicHousekeepingHelper.h"
|
#include "../housekeeping/PeriodicHousekeepingHelper.h"
|
||||||
#include "../serialize/SerializeAdapter.h"
|
#include "../serialize/SerializeAdapter.h"
|
||||||
@@ -28,37 +30,36 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
|
|||||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||||
|
|
||||||
if(accessor != nullptr) {
|
if(accessor != nullptr) {
|
||||||
poolManager = accessor->getHkManagerHandle();
|
poolManager = accessor->getPoolManagerHandle();
|
||||||
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->sid.objectId = hkOwner->getObjectId();
|
this->sid.objectId = hkOwner->getObjectId();
|
||||||
this->sid.ownerSetId = setId;
|
this->sid.ownerSetId = setId;
|
||||||
|
|
||||||
// Data creators get a periodic helper for periodic HK data generation.
|
/* Data creators get a periodic helper for periodic HK data generation. */
|
||||||
if(periodicHandling) {
|
if(periodicHandling) {
|
||||||
periodicHelper = new PeriodicHousekeepingHelper(this);
|
periodicHelper = new PeriodicHousekeepingHelper(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
|
LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray,
|
||||||
PoolVariableIF** registeredVariablesArray,
|
|
||||||
const size_t maxNumberOfVariables):
|
const size_t maxNumberOfVariables):
|
||||||
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
||||||
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(
|
HasLocalDataPoolIF* hkOwner = ObjectManager::instance()->get<HasLocalDataPoolIF>(
|
||||||
sid.objectId);
|
sid.objectId);
|
||||||
if(hkOwner != nullptr) {
|
if(hkOwner != nullptr) {
|
||||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||||
if(accessor != nullptr) {
|
if(accessor != nullptr) {
|
||||||
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
||||||
|
poolManager = accessor->getPoolManagerHandle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->sid = sid;
|
this->sid = sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalPoolDataSetBase::LocalPoolDataSetBase(
|
LocalPoolDataSetBase::LocalPoolDataSetBase(PoolVariableIF **registeredVariablesArray,
|
||||||
PoolVariableIF **registeredVariablesArray,
|
|
||||||
const size_t maxNumberOfVariables, bool protectEveryReadCommitCall):
|
const size_t maxNumberOfVariables, bool protectEveryReadCommitCall):
|
||||||
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
|
||||||
this->setReadCommitProtectionBehaviour(protectEveryReadCommitCall);
|
this->setReadCommitProtectionBehaviour(protectEveryReadCommitCall);
|
||||||
@@ -66,9 +67,19 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(
|
|||||||
|
|
||||||
|
|
||||||
LocalPoolDataSetBase::~LocalPoolDataSetBase() {
|
LocalPoolDataSetBase::~LocalPoolDataSetBase() {
|
||||||
|
/* We only delete objects which were created in the class constructor */
|
||||||
if(periodicHelper != nullptr) {
|
if(periodicHelper != nullptr) {
|
||||||
delete periodicHelper;
|
delete periodicHelper;
|
||||||
}
|
}
|
||||||
|
/* In case set was read but not comitted, we commit all variables with an invalid state */
|
||||||
|
if(state == States::STATE_SET_WAS_READ) {
|
||||||
|
for (uint16_t count = 0; count < fillCount; count++) {
|
||||||
|
if(registeredVariables[count] != nullptr) {
|
||||||
|
registeredVariables[count]->setValid(false);
|
||||||
|
registeredVariables[count]->commit(MutexIF::TimeoutType::WAITING, 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalPoolDataSetBase::lockDataPool(
|
ReturnValue_t LocalPoolDataSetBase::lockDataPool(
|
||||||
@@ -83,24 +94,33 @@ ReturnValue_t LocalPoolDataSetBase::lockDataPool(
|
|||||||
ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer,
|
ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer,
|
||||||
size_t *size, size_t maxSize,
|
size_t *size, size_t maxSize,
|
||||||
SerializeIF::Endianness streamEndianness) const {
|
SerializeIF::Endianness streamEndianness) const {
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount)/8.0);
|
const uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount)/8.0);
|
||||||
uint8_t validityMask[validityMaskSize];
|
uint8_t* validityPtr = nullptr;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* Use a std::vector here because MSVC will (rightly) not create a fixed size array
|
||||||
|
with a non constant size specifier */
|
||||||
|
std::vector<uint8_t> validityMask(validityMaskSize);
|
||||||
|
validityPtr = validityMask.data();
|
||||||
|
#else
|
||||||
|
uint8_t validityMask[validityMaskSize] = {0};
|
||||||
|
validityPtr = validityMask;
|
||||||
|
#endif
|
||||||
uint8_t validBufferIndex = 0;
|
uint8_t validBufferIndex = 0;
|
||||||
uint8_t validBufferIndexBit = 0;
|
uint8_t validBufferIndexBit = 0;
|
||||||
for (uint16_t count = 0; count < fillCount; count++) {
|
for (uint16_t count = 0; count < fillCount; count++) {
|
||||||
if(registeredVariables[count]->isValid()) {
|
if(registeredVariables[count]->isValid()) {
|
||||||
// set validity buffer here.
|
/* Set bit at correct position */
|
||||||
this->bitSetter(validityMask + validBufferIndex,
|
bitutil::bitSet(validityPtr + validBufferIndex, validBufferIndexBit);
|
||||||
validBufferIndexBit);
|
|
||||||
if(validBufferIndexBit == 7) {
|
|
||||||
validBufferIndex ++;
|
|
||||||
validBufferIndexBit = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
validBufferIndexBit ++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if(validBufferIndexBit == 7) {
|
||||||
|
validBufferIndex ++;
|
||||||
|
validBufferIndexBit = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
validBufferIndexBit ++;
|
||||||
|
}
|
||||||
|
|
||||||
result = registeredVariables[count]->serialize(buffer, size, maxSize,
|
result = registeredVariables[count]->serialize(buffer, size, maxSize,
|
||||||
streamEndianness);
|
streamEndianness);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
@@ -112,7 +132,7 @@ ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer
|
|||||||
return SerializeIF::BUFFER_TOO_SHORT;
|
return SerializeIF::BUFFER_TOO_SHORT;
|
||||||
}
|
}
|
||||||
// copy validity buffer to end
|
// copy validity buffer to end
|
||||||
std::memcpy(*buffer, validityMask, validityMaskSize);
|
std::memcpy(*buffer, validityPtr, validityMaskSize);
|
||||||
*size += validityMaskSize;
|
*size += validityMaskSize;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -137,7 +157,7 @@ ReturnValue_t LocalPoolDataSetBase::deSerializeWithValidityBuffer(
|
|||||||
uint8_t validBufferIndexBit = 0;
|
uint8_t validBufferIndexBit = 0;
|
||||||
for (uint16_t count = 0; count < fillCount; count++) {
|
for (uint16_t count = 0; count < fillCount; count++) {
|
||||||
// set validity buffer here.
|
// set validity buffer here.
|
||||||
bool nextVarValid = this->bitGetter(*buffer +
|
bool nextVarValid = bitutil::bitGet(*buffer +
|
||||||
validBufferIndex, validBufferIndexBit);
|
validBufferIndex, validBufferIndexBit);
|
||||||
registeredVariables[count]->setValid(nextVarValid);
|
registeredVariables[count]->setValid(nextVarValid);
|
||||||
|
|
||||||
@@ -162,7 +182,7 @@ ReturnValue_t LocalPoolDataSetBase::unlockDataPool() {
|
|||||||
ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer,
|
ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer,
|
||||||
size_t* size, size_t maxSize,SerializeIF::Endianness streamEndianness,
|
size_t* size, size_t maxSize,SerializeIF::Endianness streamEndianness,
|
||||||
bool serializeFillCount) const {
|
bool serializeFillCount) const {
|
||||||
// Serialize as uint8_t
|
/* Serialize fill count as uint8_t */
|
||||||
uint8_t fillCount = this->fillCount;
|
uint8_t fillCount = this->fillCount;
|
||||||
if(serializeFillCount) {
|
if(serializeFillCount) {
|
||||||
SerializeAdapter::serialize(&fillCount, buffer, size, maxSize,
|
SerializeAdapter::serialize(&fillCount, buffer, size, maxSize,
|
||||||
@@ -235,21 +255,6 @@ ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const {
|
|
||||||
if(position > 7) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "LocalPoolDataSetBase::bitSetter: Invalid position!"
|
|
||||||
<< std::endl;
|
|
||||||
#else
|
|
||||||
sif::printWarning("LocalPoolDataSetBase::bitSetter: "
|
|
||||||
"Invalid position!\n\r");
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint8_t shiftNumber = position + (7 - 2 * position);
|
|
||||||
*byte |= 1 << shiftNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LocalPoolDataSetBase::setDiagnostic(bool isDiagnostics) {
|
void LocalPoolDataSetBase::setDiagnostic(bool isDiagnostics) {
|
||||||
this->diagnostic = isDiagnostics;
|
this->diagnostic = isDiagnostics;
|
||||||
}
|
}
|
||||||
@@ -266,11 +271,9 @@ bool LocalPoolDataSetBase::getReportingEnabled() const {
|
|||||||
return reportingEnabled;
|
return reportingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPoolDataSetBase::initializePeriodicHelper(
|
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
|
||||||
float collectionInterval, dur_millis_t minimumPeriodicInterval,
|
dur_millis_t minimumPeriodicInterval, uint8_t nonDiagIntervalFactor) {
|
||||||
bool isDiagnostics, uint8_t nonDiagIntervalFactor) {
|
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, nonDiagIntervalFactor);
|
||||||
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval,
|
|
||||||
isDiagnostics, nonDiagIntervalFactor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPoolDataSetBase::setChanged(bool changed) {
|
void LocalPoolDataSetBase::setChanged(bool changed) {
|
||||||
@@ -285,19 +288,6 @@ sid_t LocalPoolDataSetBase::getSid() const {
|
|||||||
return sid;
|
return sid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte,
|
|
||||||
uint8_t position) const {
|
|
||||||
if(position > 7) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::debug << "Pool Raw Access: Bit setting invalid position"
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint8_t shiftNumber = position + (7 - 2 * position);
|
|
||||||
return *byte & (1 << shiftNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LocalPoolDataSetBase::isValid() const {
|
bool LocalPoolDataSetBase::isValid() const {
|
||||||
return this->valid;
|
return this->valid;
|
||||||
}
|
}
|
||||||
@@ -305,7 +295,7 @@ bool LocalPoolDataSetBase::isValid() const {
|
|||||||
void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) {
|
void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) {
|
||||||
if(setEntriesRecursively) {
|
if(setEntriesRecursively) {
|
||||||
for(size_t idx = 0; idx < this->getFillCount(); idx++) {
|
for(size_t idx = 0; idx < this->getFillCount(); idx++) {
|
||||||
registeredVariables[idx] -> setValid(valid);
|
registeredVariables[idx]->setValid(valid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->valid = valid;
|
this->valid = valid;
|
||||||
@@ -317,3 +307,18 @@ object_id_t LocalPoolDataSetBase::getCreatorObjectId() {
|
|||||||
}
|
}
|
||||||
return objects::NO_OBJECT;
|
return objects::NO_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalPoolDataSetBase::setAllVariablesReadOnly() {
|
||||||
|
for(size_t idx = 0; idx < this->getFillCount(); idx++) {
|
||||||
|
registeredVariables[idx]->setReadWriteMode(pool_rwm_t::VAR_READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float LocalPoolDataSetBase::getCollectionInterval() const {
|
||||||
|
if(periodicHelper != nullptr) {
|
||||||
|
return periodicHelper->getCollectionIntervalInSeconds();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -59,7 +59,7 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructor for users of the local pool data, which need
|
* @brief Constructor for users of the local pool data, which need
|
||||||
* to access data created by one (!) HK manager.
|
* to access data created by one HK manager.
|
||||||
* @details
|
* @details
|
||||||
* Unlike the first constructor, no component for periodic handling
|
* Unlike the first constructor, no component for periodic handling
|
||||||
* will be initiated.
|
* will be initiated.
|
||||||
@@ -97,12 +97,24 @@ public:
|
|||||||
* @brief The destructor automatically manages writing the valid
|
* @brief The destructor automatically manages writing the valid
|
||||||
* information of variables.
|
* information of variables.
|
||||||
* @details
|
* @details
|
||||||
* In case the data set was read out, but not committed(indicated by state),
|
* In case the data set was read out, but not committed (indicated by state),
|
||||||
* the destructor parses all variables that are still registered to the set.
|
* the destructor parses all variables that are still registered to the set.
|
||||||
* For each, the valid flag in the data pool is set to "invalid".
|
* For each, the valid flag in the data pool is set to "invalid".
|
||||||
*/
|
*/
|
||||||
~LocalPoolDataSetBase();
|
~LocalPoolDataSetBase();
|
||||||
|
|
||||||
|
/* The copy constructor and assingment constructor are forbidden for now.
|
||||||
|
The use-cases are limited and the first step would be to implement them properly for the
|
||||||
|
base class */
|
||||||
|
LocalPoolDataSetBase(const LocalPoolDataSetBase& otherSet) = delete;
|
||||||
|
const LocalPoolDataSetBase& operator=(const LocalPoolDataSetBase& otherSet) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper functions used to set all currently contained variables to read-only.
|
||||||
|
* It is recommended to call this in set constructors intended to be used
|
||||||
|
* by data consumers to prevent accidentally changing pool data.
|
||||||
|
*/
|
||||||
|
void setAllVariablesReadOnly();
|
||||||
void setValidityBufferGeneration(bool withValidityBuffer);
|
void setValidityBufferGeneration(bool withValidityBuffer);
|
||||||
|
|
||||||
sid_t getSid() const;
|
sid_t getSid() const;
|
||||||
@@ -153,6 +165,17 @@ public:
|
|||||||
bool hasChanged() const override;
|
bool hasChanged() const override;
|
||||||
|
|
||||||
object_id_t getCreatorObjectId();
|
object_id_t getCreatorObjectId();
|
||||||
|
|
||||||
|
bool getReportingEnabled() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current periodic HK generation interval this set
|
||||||
|
* belongs to a HK manager and the interval is not 0. Otherwise,
|
||||||
|
* returns 0.0
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
float getCollectionInterval() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
sid_t sid;
|
sid_t sid;
|
||||||
//! This mutex is used if the data is created by one object only.
|
//! This mutex is used if the data is created by one object only.
|
||||||
@@ -167,11 +190,9 @@ protected:
|
|||||||
*/
|
*/
|
||||||
bool reportingEnabled = false;
|
bool reportingEnabled = false;
|
||||||
void setReportingEnabled(bool enabled);
|
void setReportingEnabled(bool enabled);
|
||||||
bool getReportingEnabled() const;
|
|
||||||
|
|
||||||
void initializePeriodicHelper(float collectionInterval,
|
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
|
||||||
dur_millis_t minimumPeriodicInterval,
|
uint8_t nonDiagIntervalFactor = 5);
|
||||||
bool isDiagnostics, uint8_t nonDiagIntervalFactor = 5);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the valid state of a dataset is always relevant to the whole
|
* If the valid state of a dataset is always relevant to the whole
|
||||||
@@ -211,13 +232,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t unlockDataPool() override;
|
ReturnValue_t unlockDataPool() override;
|
||||||
|
|
||||||
/**
|
|
||||||
* Set n-th bit of a byte, with n being the position from 0
|
|
||||||
* (most significant bit) to 7 (least significant bit)
|
|
||||||
*/
|
|
||||||
void bitSetter(uint8_t* byte, uint8_t position) const;
|
|
||||||
bool bitGetter(const uint8_t* byte, uint8_t position) const;
|
|
||||||
|
|
||||||
PeriodicHousekeepingHelper* periodicHelper = nullptr;
|
PeriodicHousekeepingHelper* periodicHelper = nullptr;
|
||||||
LocalDataPoolManager* poolManager = nullptr;
|
LocalDataPoolManager* poolManager = nullptr;
|
||||||
|
|
||||||
|
@@ -1,9 +1,11 @@
|
|||||||
#include "LocalPoolObjectBase.h"
|
#include "LocalPoolObjectBase.h"
|
||||||
#include "LocalDataPoolManager.h"
|
#include "LocalDataPoolManager.h"
|
||||||
#include "internal/HasLocalDpIFUserAttorney.h"
|
#include "AccessLocalPoolF.h"
|
||||||
#include "HasLocalDataPoolIF.h"
|
#include "HasLocalDataPoolIF.h"
|
||||||
|
#include "internal/HasLocalDpIFUserAttorney.h"
|
||||||
|
|
||||||
|
#include "../objectmanager/ObjectManager.h"
|
||||||
|
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
|
||||||
|
|
||||||
LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
|
LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
|
||||||
DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
|
DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
|
||||||
@@ -22,7 +24,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkO
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||||
hkManager = poolManAccessor->getHkManagerHandle();
|
hkManager = poolManAccessor->getPoolManagerHandle();
|
||||||
|
|
||||||
if (dataSet != nullptr) {
|
if (dataSet != nullptr) {
|
||||||
dataSet->registerVariable(this);
|
dataSet->registerVariable(this);
|
||||||
@@ -35,22 +37,27 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
|
|||||||
if(poolId == PoolVariableIF::NO_PARAMETER) {
|
if(poolId == PoolVariableIF::NO_PARAMETER) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
|
sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
|
||||||
<< "which is the NO_PARAMETER value!" << std::endl;
|
"which is the NO_PARAMETER value!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
|
||||||
|
"which is the NO_PARAMETER value!\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(poolOwner);
|
HasLocalDataPoolIF* hkOwner = ObjectManager::instance()->get<HasLocalDataPoolIF>(poolOwner);
|
||||||
if(hkOwner == nullptr) {
|
if(hkOwner == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "LocalPoolVariable: The supplied pool owner did not "
|
sif::error << "LocalPoolVariable: The supplied pool owner did not implement the correct "
|
||||||
<< "implement the correct interface"
|
"interface HasLocalDataPoolIF!" << std::endl;
|
||||||
<< " HasLocalDataPoolIF!" << std::endl;
|
#else
|
||||||
|
sif::printError( "LocalPoolVariable: The supplied pool owner did not implement the correct "
|
||||||
|
"interface HasLocalDataPoolIF!\n");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||||
if(accessor != nullptr) {
|
if(accessor != nullptr) {
|
||||||
hkManager = accessor->getHkManagerHandle();
|
hkManager = accessor->getPoolManagerHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dataSet != nullptr) {
|
if(dataSet != nullptr) {
|
||||||
@@ -93,6 +100,10 @@ void LocalPoolObjectBase::setReadWriteMode(pool_rwm_t newReadWriteMode) {
|
|||||||
void LocalPoolObjectBase::reportReadCommitError(const char* variableType,
|
void LocalPoolObjectBase::reportReadCommitError(const char* variableType,
|
||||||
ReturnValue_t error, bool read, object_id_t objectId, lp_id_t lpId) {
|
ReturnValue_t error, bool read, object_id_t objectId, lp_id_t lpId) {
|
||||||
#if FSFW_DISABLE_PRINTOUT == 0
|
#if FSFW_DISABLE_PRINTOUT == 0
|
||||||
|
const char* variablePrintout = variableType;
|
||||||
|
if(variablePrintout == nullptr) {
|
||||||
|
variablePrintout = "Unknown Type";
|
||||||
|
}
|
||||||
const char* type = nullptr;
|
const char* type = nullptr;
|
||||||
if(read) {
|
if(read) {
|
||||||
type = "read";
|
type = "read";
|
||||||
@@ -119,12 +130,12 @@ void LocalPoolObjectBase::reportReadCommitError(const char* variableType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << variableType << ": " << type << " call | " << errMsg << " | Owner: 0x"
|
sif::warning << variablePrintout << ": " << type << " call | " << errMsg << " | Owner: 0x"
|
||||||
<< std::hex << std::setw(8) << std::setfill('0') << objectId << std::dec
|
<< std::hex << std::setw(8) << std::setfill('0') << objectId << std::dec
|
||||||
<< " LPID: " << lpId << std::endl;
|
<< " LPID: " << lpId << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("%s: %s call | %s | Owner: 0x%08x LPID: %lu\n",
|
sif::printWarning("%s: %s call | %s | Owner: 0x%08x LPID: %lu\n",
|
||||||
variableType, type, errMsg, objectId, lpId);
|
variablePrintout, type, errMsg, objectId, lpId);
|
||||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
|
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
|
||||||
}
|
}
|
||||||
|
@@ -20,12 +20,10 @@ class LocalPoolObjectBase: public PoolVariableIF,
|
|||||||
public HasReturnvaluesIF,
|
public HasReturnvaluesIF,
|
||||||
public MarkChangedIF {
|
public MarkChangedIF {
|
||||||
public:
|
public:
|
||||||
LocalPoolObjectBase(lp_id_t poolId,
|
LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
|
||||||
HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
|
|
||||||
pool_rwm_t setReadWriteMode);
|
pool_rwm_t setReadWriteMode);
|
||||||
|
|
||||||
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
|
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
|
||||||
DataSetIF* dataSet = nullptr,
|
|
||||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||||
|
|
||||||
void setReadWriteMode(pool_rwm_t newReadWriteMode);
|
void setReadWriteMode(pool_rwm_t newReadWriteMode);
|
||||||
|
@@ -26,8 +26,17 @@ inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId,
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::read(
|
inline ReturnValue_t LocalPoolVariable<T>::read(
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
if(hkManager == nullptr) {
|
||||||
return readWithoutLock();
|
return readWithoutLock();
|
||||||
|
}
|
||||||
|
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
||||||
|
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = readWithoutLock();
|
||||||
|
mutex->unlockMutex();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -43,7 +52,6 @@ inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
|
|||||||
PoolEntry<T>* poolEntry = nullptr;
|
PoolEntry<T>* poolEntry = nullptr;
|
||||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||||
&poolEntry);
|
&poolEntry);
|
||||||
//ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
|
|
||||||
if(result != RETURN_OK) {
|
if(result != RETURN_OK) {
|
||||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVariable", result,
|
reportReadCommitError("LocalPoolVariable", result,
|
||||||
@@ -51,15 +59,6 @@ inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually this should never happen..
|
|
||||||
// if(poolEntry->address == nullptr) {
|
|
||||||
// result = PoolVariableIF::INVALID_POOL_ENTRY;
|
|
||||||
// object_id_t ownerObjectId = hkManager->getOwner()->getObjectId();
|
|
||||||
// reportReadCommitError("LocalPoolVariable", result,
|
|
||||||
// false, ownerObjectId, localPoolId);
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
this->value = *(poolEntry->getDataPtr());
|
this->value = *(poolEntry->getDataPtr());
|
||||||
this->valid = poolEntry->getValid();
|
this->valid = poolEntry->getValid();
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
@@ -75,8 +74,17 @@ inline ReturnValue_t LocalPoolVariable<T>::commit(bool setValid,
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::commit(
|
inline ReturnValue_t LocalPoolVariable<T>::commit(
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
if(hkManager == nullptr) {
|
||||||
return commitWithoutLock();
|
return commitWithoutLock();
|
||||||
|
}
|
||||||
|
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
||||||
|
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = commitWithoutLock();
|
||||||
|
mutex->unlockMutex();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -90,7 +98,6 @@ inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PoolEntry<T>* poolEntry = nullptr;
|
PoolEntry<T>* poolEntry = nullptr;
|
||||||
//ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry);
|
|
||||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||||
&poolEntry);
|
&poolEntry);
|
||||||
if(result != RETURN_OK) {
|
if(result != RETURN_OK) {
|
||||||
|
@@ -77,8 +77,7 @@ public:
|
|||||||
* @param dataSet
|
* @param dataSet
|
||||||
* @param setReadWriteMode
|
* @param setReadWriteMode
|
||||||
*/
|
*/
|
||||||
LocalPoolVector(gp_id_t globalPoolId,
|
LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
|
||||||
DataSetIF* dataSet = nullptr,
|
|
||||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,7 +86,7 @@ public:
|
|||||||
* The user can work on this attribute just like he would on a local
|
* The user can work on this attribute just like he would on a local
|
||||||
* array of this type.
|
* array of this type.
|
||||||
*/
|
*/
|
||||||
T value[vectorSize];
|
T value[vectorSize]= {};
|
||||||
/**
|
/**
|
||||||
* @brief The classes destructor is empty.
|
* @brief The classes destructor is empty.
|
||||||
* @details If commit() was not called, the local value is
|
* @details If commit() was not called, the local value is
|
||||||
|
@@ -16,7 +16,6 @@ inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner,
|
|||||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template<typename T, uint16_t vectorSize>
|
||||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
||||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||||
@@ -26,7 +25,7 @@ inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
|||||||
template<typename T, uint16_t vectorSize>
|
template<typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||||
return readWithoutLock();
|
return readWithoutLock();
|
||||||
}
|
}
|
||||||
template<typename T, uint16_t vectorSize>
|
template<typename T, uint16_t vectorSize>
|
||||||
@@ -65,7 +64,7 @@ inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(bool valid,
|
|||||||
template<typename T, uint16_t vectorSize>
|
template<typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||||
MutexHelper(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||||
return commitWithoutLock();
|
return commitWithoutLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,12 +17,8 @@ public:
|
|||||||
* to generate housekeeping packets which are downlinked directly.
|
* to generate housekeeping packets which are downlinked directly.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t subscribeForPeriodicPacket(sid_t sid,
|
virtual ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
|
||||||
bool enableReporting,
|
float collectionInterval, bool isDiagnostics, object_id_t packetDestination) = 0;
|
||||||
float collectionInterval, bool isDiagnostics,
|
|
||||||
object_id_t packetDestination) = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for the generation of packets if the dataset
|
* @brief Subscribe for the generation of packets if the dataset
|
||||||
* is marked as changed.
|
* is marked as changed.
|
||||||
@@ -33,51 +29,42 @@ public:
|
|||||||
* @param packetDestination
|
* @param packetDestination
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t subscribeForUpdatePackets(sid_t sid,
|
virtual ReturnValue_t subscribeForUpdatePacket(sid_t sid, bool reportingEnabled,
|
||||||
bool reportingEnabled,
|
bool isDiagnostics, object_id_t packetDestination) = 0;
|
||||||
bool isDiagnostics,
|
|
||||||
object_id_t packetDestination) = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for a notification message which will be sent
|
* @brief Subscribe for a notification message which will be sent
|
||||||
* if a dataset has changed.
|
* if a dataset has changed.
|
||||||
* @details
|
* @details
|
||||||
* This subscription mechanism will generally be used internally by
|
* This subscription mechanism will generally be used internally by
|
||||||
* other software components.
|
* other software components.
|
||||||
* @param setId Set ID of the set to receive update messages from.
|
* @param setId Set ID of the set to receive update messages from.
|
||||||
* @param destinationObject
|
* @param destinationObject Object ID of the receiver.
|
||||||
* @param targetQueueId
|
* @param targetQueueId Receiver queue ID
|
||||||
* @param generateSnapshot If this is set to true, a copy of the current
|
* @param generateSnapshot If this is set to true, a copy of the current data with a
|
||||||
* data with a timestamp will be generated and sent via message.
|
* timestamp will be generated and sent via message.
|
||||||
* Otherwise, only an notification message is sent.
|
* Otherwise, only an notification message is sent.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId,
|
virtual ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId,
|
||||||
object_id_t destinationObject,
|
object_id_t destinationObject, MessageQueueId_t targetQueueId,
|
||||||
MessageQueueId_t targetQueueId,
|
|
||||||
bool generateSnapshot) = 0;
|
bool generateSnapshot) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for an notification message which will be sent if a
|
* @brief Subscribe for an notification message which will be sent if a
|
||||||
* pool variable has changed.
|
* pool variable has changed.
|
||||||
* @details
|
* @details
|
||||||
* This subscription mechanism will generally be used internally by
|
* This subscription mechanism will generally be used internally by
|
||||||
* other software components.
|
* other software components.
|
||||||
* @param localPoolId Pool ID of the pool variable
|
* @param localPoolId Pool ID of the pool variable
|
||||||
* @param destinationObject
|
* @param destinationObject Object ID of the receiver
|
||||||
* @param targetQueueId
|
* @param targetQueueId Receiver queue ID
|
||||||
* @param generateSnapshot If this is set to true, a copy of the current
|
* @param generateSnapshot If this is set to true, a copy of the current data with a
|
||||||
* data with a timestamp will be generated and sent via message.
|
* timestamp will be generated and sent via message. Otherwise,
|
||||||
* Otherwise, only an notification message is sent.
|
* only an notification message is sent.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t subscribeForVariableUpdateMessages(
|
virtual ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId,
|
||||||
const lp_id_t localPoolId,
|
object_id_t destinationObject, MessageQueueId_t targetQueueId,
|
||||||
object_id_t destinationObject,
|
|
||||||
MessageQueueId_t targetQueueId,
|
|
||||||
bool generateSnapshot) = 0;
|
bool generateSnapshot) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_ */
|
#endif /* FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_ */
|
||||||
|
@@ -1,16 +1,37 @@
|
|||||||
#include "SharedLocalDataSet.h"
|
#include "SharedLocalDataSet.h"
|
||||||
|
|
||||||
|
|
||||||
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, sid_t sid,
|
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, sid_t sid,
|
||||||
const size_t maxSize): SystemObject(objectId),
|
const size_t maxSize): SystemObject(objectId),
|
||||||
LocalPoolDataSetBase(sid, nullptr, maxSize) {
|
LocalPoolDataSetBase(sid, nullptr, maxSize), poolVarVector(maxSize) {
|
||||||
this->setContainer(poolVarVector.data());
|
this->setContainer(poolVarVector.data());
|
||||||
datasetLock = MutexFactory::instance()->createMutex();
|
datasetLock = MutexFactory::instance()->createMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SharedLocalDataSet::lockDataset(dur_millis_t mutexTimeout) {
|
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId,
|
||||||
return datasetLock->lockMutex(MutexIF::TimeoutType::WAITING, mutexTimeout);
|
HasLocalDataPoolIF *owner, uint32_t setId,
|
||||||
|
const size_t maxSize): SystemObject(objectId),
|
||||||
|
LocalPoolDataSetBase(owner, setId, nullptr, maxSize), poolVarVector(maxSize) {
|
||||||
|
this->setContainer(poolVarVector.data());
|
||||||
|
datasetLock = MutexFactory::instance()->createMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t SharedLocalDataSet::lockDataset(MutexIF::TimeoutType timeoutType,
|
||||||
|
dur_millis_t mutexTimeout) {
|
||||||
|
if(datasetLock != nullptr) {
|
||||||
|
return datasetLock->lockMutex(timeoutType, mutexTimeout);
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SharedLocalDataSet::~SharedLocalDataSet() {
|
||||||
|
MutexFactory::instance()->deleteMutex(datasetLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SharedLocalDataSet::unlockDataset() {
|
ReturnValue_t SharedLocalDataSet::unlockDataset() {
|
||||||
return datasetLock->unlockMutex();
|
if(datasetLock != nullptr) {
|
||||||
|
return datasetLock->unlockMutex();
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
@@ -11,16 +11,22 @@
|
|||||||
* multiple threads. It provides a lock in addition to all other functionalities provided
|
* multiple threads. It provides a lock in addition to all other functionalities provided
|
||||||
* by the LocalPoolDataSetBase class.
|
* by the LocalPoolDataSetBase class.
|
||||||
*
|
*
|
||||||
* TODO: override and protect read, commit and some other calls used by pool manager.
|
* The user is completely responsible for lockingand unlocking the dataset when using the
|
||||||
|
* shared dataset.
|
||||||
*/
|
*/
|
||||||
class SharedLocalDataSet:
|
class SharedLocalDataSet:
|
||||||
public SystemObject,
|
public SystemObject,
|
||||||
public LocalPoolDataSetBase,
|
public LocalPoolDataSetBase,
|
||||||
public SharedDataSetIF {
|
public SharedDataSetIF {
|
||||||
public:
|
public:
|
||||||
SharedLocalDataSet(object_id_t objectId, sid_t sid,
|
SharedLocalDataSet(object_id_t objectId, HasLocalDataPoolIF* owner, uint32_t setId,
|
||||||
const size_t maxSize);
|
const size_t maxSize);
|
||||||
ReturnValue_t lockDataset(dur_millis_t mutexTimeout) override;
|
SharedLocalDataSet(object_id_t objectId, sid_t sid, const size_t maxSize);
|
||||||
|
|
||||||
|
virtual~ SharedLocalDataSet();
|
||||||
|
|
||||||
|
ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||||
|
dur_millis_t mutexTimeout = 20) override;
|
||||||
ReturnValue_t unlockDataset() override;
|
ReturnValue_t unlockDataset() override;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@@ -2,11 +2,15 @@
|
|||||||
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
|
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
|
||||||
|
|
||||||
#include "LocalPoolDataSetBase.h"
|
#include "LocalPoolDataSetBase.h"
|
||||||
|
#include "LocalPoolVariable.h"
|
||||||
|
#include "LocalPoolVector.h"
|
||||||
|
|
||||||
#include "../objectmanager/SystemObjectIF.h"
|
#include "../objectmanager/SystemObjectIF.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This local dataset type is created on the stack.
|
* @brief This dataset type can be used to group related pool variables if the number of
|
||||||
|
* variables is fixed.
|
||||||
* @details
|
* @details
|
||||||
* This will is the primary data structure to organize pool variables into
|
* This will is the primary data structure to organize pool variables into
|
||||||
* sets which can be accessed via the housekeeping service interface or
|
* sets which can be accessed via the housekeeping service interface or
|
||||||
|
12
datapoollocal/datapoollocal.h
Normal file
12
datapoollocal/datapoollocal.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_
|
||||||
|
#define FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_
|
||||||
|
|
||||||
|
/* Collected related headers */
|
||||||
|
#include "LocalPoolVariable.h"
|
||||||
|
#include "LocalPoolVector.h"
|
||||||
|
#include "StaticLocalDataSet.h"
|
||||||
|
#include "LocalDataSet.h"
|
||||||
|
#include "SharedLocalDataSet.h"
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_ */
|
@@ -24,7 +24,6 @@ private:
|
|||||||
return manager.getMutexHandle();
|
return manager.getMutexHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T> friend class LocalPoolVariable;
|
template<typename T> friend class LocalPoolVariable;
|
||||||
template<typename T, uint16_t vecSize> friend class LocalPoolVector;
|
template<typename T, uint16_t vecSize> friend class LocalPoolVector;
|
||||||
};
|
};
|
||||||
|
@@ -14,9 +14,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
|
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
|
||||||
uint32_t minimumPeriodicIntervalMs,
|
uint32_t minimumPeriodicIntervalMs, uint8_t nonDiagIntervalFactor = 5) {
|
||||||
bool isDiagnostics, uint8_t nonDiagIntervalFactor = 5) {
|
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs,
|
||||||
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs, isDiagnostics,
|
|
||||||
nonDiagIntervalFactor);
|
nonDiagIntervalFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,8 +21,8 @@ static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF;
|
|||||||
static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x00);
|
static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x00);
|
||||||
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x01);
|
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x01);
|
||||||
|
|
||||||
//! This is the core data structure of the local data pools. Users should insert all desired
|
/** This is the core data structure of the local data pools. Users should insert all desired
|
||||||
//! pool variables, using the std::map interface.
|
pool variables, using the std::map interface. */
|
||||||
using DataPool = std::map<lp_id_t, PoolEntryIF*>;
|
using DataPool = std::map<lp_id_t, PoolEntryIF*>;
|
||||||
using DataPoolMapIter = DataPool::iterator;
|
using DataPoolMapIter = DataPool::iterator;
|
||||||
|
|
||||||
@@ -96,11 +96,11 @@ union gp_id_t {
|
|||||||
return raw == INVALID_GPID;
|
return raw == INVALID_GPID;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const sid_t& other) const {
|
bool operator==(const gp_id_t& other) const {
|
||||||
return raw == other.raw;
|
return raw == other.raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const sid_t& other) const {
|
bool operator!=(const gp_id_t& other) const {
|
||||||
return not (raw == other.raw);
|
return not (raw == other.raw);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -1,15 +1,23 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
|
||||||
ipc/missionMessageTypes.cpp
|
|
||||||
objects/FsfwFactory.cpp
|
|
||||||
pollingsequence/PollingSequenceFactory.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Should be added to include path
|
|
||||||
target_include_directories(${TARGET_NAME} PRIVATE
|
target_include_directories(${TARGET_NAME} PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT FSFW_CONFIG_PATH)
|
target_sources(${TARGET_NAME} PRIVATE
|
||||||
set(FSFW_CONFIG_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
ipc/missionMessageTypes.cpp
|
||||||
|
pollingsequence/PollingSequenceFactory.cpp
|
||||||
|
objects/FsfwFactory.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# If a special translation file for object IDs exists, compile it.
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp")
|
||||||
|
target_sources(${TARGET_NAME} PRIVATE
|
||||||
|
objects/translateObjects.cpp
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# If a special translation file for events exists, compile it.
|
||||||
|
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp")
|
||||||
|
target_sources(${TARGET_NAME} PRIVATE
|
||||||
|
events/translateEvents.cpp
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
@@ -7,27 +7,30 @@
|
|||||||
//! Used to determine whether C++ ostreams are used which can increase
|
//! Used to determine whether C++ ostreams are used which can increase
|
||||||
//! the binary size significantly. If this is disabled,
|
//! the binary size significantly. If this is disabled,
|
||||||
//! the C stdio functions can be used alternatively
|
//! the C stdio functions can be used alternatively
|
||||||
#define FSFW_CPP_OSTREAM_ENABLED 1
|
#define FSFW_CPP_OSTREAM_ENABLED 1
|
||||||
|
|
||||||
//! More FSFW related printouts depending on level. Useful for development.
|
//! More FSFW related printouts depending on level. Useful for development.
|
||||||
#define FSFW_VERBOSE_LEVEL 1
|
#define FSFW_VERBOSE_LEVEL 1
|
||||||
|
|
||||||
//! Can be used to completely disable printouts, even the C stdio ones.
|
//! Can be used to completely disable printouts, even the C stdio ones.
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0
|
#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0
|
||||||
#define FSFW_DISABLE_PRINTOUT 0
|
#define FSFW_DISABLE_PRINTOUT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define FSFW_USE_PUS_C_TELEMETRY 1
|
||||||
|
#define FSFW_USE_PUS_C_TELECOMMANDS 1
|
||||||
|
|
||||||
//! Can be used to disable the ANSI color sequences for C stdio.
|
//! Can be used to disable the ANSI color sequences for C stdio.
|
||||||
#define FSFW_COLORED_OUTPUT 1
|
#define FSFW_COLORED_OUTPUT 1
|
||||||
|
|
||||||
//! If FSFW_OBJ_EVENT_TRANSLATION is set to one,
|
//! If FSFW_OBJ_EVENT_TRANSLATION is set to one,
|
||||||
//! additional output which requires the translation files translateObjects
|
//! additional output which requires the translation files translateObjects
|
||||||
//! and translateEvents (and their compiled source files)
|
//! and translateEvents (and their compiled source files)
|
||||||
#define FSFW_OBJ_EVENT_TRANSLATION 0
|
#define FSFW_OBJ_EVENT_TRANSLATION 0
|
||||||
|
|
||||||
#if FSFW_OBJ_EVENT_TRANSLATION == 1
|
#if FSFW_OBJ_EVENT_TRANSLATION == 1
|
||||||
//! Specify whether info events are printed too.
|
//! Specify whether info events are printed too.
|
||||||
#define FSFW_DEBUG_INFO 1
|
#define FSFW_DEBUG_INFO 1
|
||||||
#include "objects/translateObjects.h"
|
#include "objects/translateObjects.h"
|
||||||
#include "events/translateEvents.h"
|
#include "events/translateEvents.h"
|
||||||
#else
|
#else
|
||||||
@@ -35,15 +38,22 @@
|
|||||||
|
|
||||||
//! When using the newlib nano library, C99 support for stdio facilities
|
//! When using the newlib nano library, C99 support for stdio facilities
|
||||||
//! will not be provided. This define should be set to 1 if this is the case.
|
//! will not be provided. This define should be set to 1 if this is the case.
|
||||||
#define FSFW_NO_C99_IO 1
|
#define FSFW_NO_C99_IO 1
|
||||||
|
|
||||||
//! Specify whether a special mode store is used for Subsystem components.
|
//! Specify whether a special mode store is used for Subsystem components.
|
||||||
#define FSFW_USE_MODESTORE 0
|
#define FSFW_USE_MODESTORE 0
|
||||||
|
|
||||||
|
//! Defines if the real time scheduler for linux should be used.
|
||||||
|
//! If set to 0, this will also disable priority settings for linux
|
||||||
|
//! as most systems will not allow to set nice values without privileges
|
||||||
|
//! For embedded linux system set this to 1.
|
||||||
|
//! If set to 1 the binary needs "cap_sys_nice=eip" privileges to run
|
||||||
|
#define FSFW_USE_REALTIME_FOR_LINUX 1
|
||||||
|
|
||||||
namespace fsfwconfig {
|
namespace fsfwconfig {
|
||||||
//! Default timestamp size. The default timestamp will be an eight byte CDC
|
|
||||||
//! short timestamp.
|
//! Default timestamp size. The default timestamp will be an seven byte CDC short timestamp.
|
||||||
static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8;
|
static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 7;
|
||||||
|
|
||||||
//! Configure the allocated pool sizes for the event manager.
|
//! Configure the allocated pool sizes for the event manager.
|
||||||
static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
|
static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
|
||||||
@@ -52,11 +62,14 @@ static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
|
|||||||
|
|
||||||
//! Defines the FIFO depth of each commanding service base which
|
//! Defines the FIFO depth of each commanding service base which
|
||||||
//! also determines how many commands a CSB service can handle in one cycle
|
//! also determines how many commands a CSB service can handle in one cycle
|
||||||
//! simulataneously. This will increase the required RAM for
|
//! simultaneously. This will increase the required RAM for
|
||||||
//! each CSB service !
|
//! each CSB service !
|
||||||
static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6;
|
static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6;
|
||||||
|
|
||||||
static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124;
|
static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124;
|
||||||
|
|
||||||
|
static constexpr size_t FSFW_MAX_TM_PACKET_SIZE = 2048;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_FSFWCONFIG_H_ */
|
#endif /* CONFIG_FSFWCONFIG_H_ */
|
||||||
|
@@ -24,6 +24,13 @@
|
|||||||
* 1. check logic when active-> checkChildrenStateOn
|
* 1. check logic when active-> checkChildrenStateOn
|
||||||
* 2. transition logic to change the mode -> commandChildren
|
* 2. transition logic to change the mode -> commandChildren
|
||||||
*
|
*
|
||||||
|
* Important:
|
||||||
|
*
|
||||||
|
* The implementation must call registerChild(object_id_t child)
|
||||||
|
* 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 {
|
class AssemblyBase: public SubsystemBase {
|
||||||
public:
|
public:
|
||||||
@@ -41,9 +48,6 @@ public:
|
|||||||
virtual ~AssemblyBase();
|
virtual ~AssemblyBase();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// SHOULDDO: Change that OVERWRITE_HEALTH may be returned
|
|
||||||
// (or return internalState directly?)
|
|
||||||
/**
|
/**
|
||||||
* Command children to reach [mode,submode] combination
|
* Command children to reach [mode,submode] combination
|
||||||
* Can be done by setting #commandsOutstanding correctly,
|
* Can be done by setting #commandsOutstanding correctly,
|
||||||
@@ -68,6 +72,18 @@ protected:
|
|||||||
virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode,
|
virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode,
|
||||||
Submode_t wantedSubmode) = 0;
|
Submode_t wantedSubmode) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether a combination of mode and submode is valid.
|
||||||
|
*
|
||||||
|
* Ground Controller like precise return values from HasModesIF.
|
||||||
|
* So, please return any of them.
|
||||||
|
*
|
||||||
|
* @param mode The targeted mode
|
||||||
|
* @param submode The targeted submmode
|
||||||
|
* @return Any information why this combination is invalid from HasModesIF
|
||||||
|
* like HasModesIF::INVALID_SUBMODE.
|
||||||
|
* On success return HasReturnvaluesIF::RETURN_OK
|
||||||
|
*/
|
||||||
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
|
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
|
||||||
Submode_t submode) = 0;
|
Submode_t submode) = 0;
|
||||||
|
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
#include "ChildHandlerBase.h"
|
#include "ChildHandlerBase.h"
|
||||||
#include "../subsystem/SubsystemBase.h"
|
#include "../subsystem/SubsystemBase.h"
|
||||||
#include "../subsystem/SubsystemBase.h"
|
|
||||||
|
|
||||||
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId,
|
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId,
|
||||||
object_id_t deviceCommunication, CookieIF * cookie,
|
object_id_t deviceCommunication, CookieIF * cookie,
|
||||||
@@ -30,7 +29,7 @@ ReturnValue_t ChildHandlerBase::initialize() {
|
|||||||
MessageQueueId_t parentQueue = 0;
|
MessageQueueId_t parentQueue = 0;
|
||||||
|
|
||||||
if (parentId != objects::NO_OBJECT) {
|
if (parentId != objects::NO_OBJECT) {
|
||||||
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
SubsystemBase *parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
|
||||||
if (parent == NULL) {
|
if (parent == NULL) {
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
|||||||
#include "DeviceHandlerFailureIsolation.h"
|
#include "DeviceHandlerFailureIsolation.h"
|
||||||
|
|
||||||
#include "../devicehandlers/DeviceHandlerIF.h"
|
#include "../devicehandlers/DeviceHandlerIF.h"
|
||||||
|
#include "../objectmanager/ObjectManager.h"
|
||||||
#include "../modes/HasModesIF.h"
|
#include "../modes/HasModesIF.h"
|
||||||
#include "../health/HealthTableIF.h"
|
#include "../health/HealthTableIF.h"
|
||||||
#include "../power/Fuse.h"
|
#include "../power/Fuse.h"
|
||||||
@@ -175,7 +176,7 @@ ReturnValue_t DeviceHandlerFailureIsolation::initialize() {
|
|||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
ConfirmsFailuresIF* power = objectManager->get<ConfirmsFailuresIF>(
|
ConfirmsFailuresIF* power = ObjectManager::instance()->get<ConfirmsFailuresIF>(
|
||||||
powerConfirmationId);
|
powerConfirmationId);
|
||||||
if (power != nullptr) {
|
if (power != nullptr) {
|
||||||
powerConfirmation = power->getEventReceptionQueue();
|
powerConfirmation = power->getEventReceptionQueue();
|
||||||
@@ -209,20 +210,20 @@ void DeviceHandlerFailureIsolation::startRecovery(Event reason) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
|
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
|
||||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = strangeReplyCount.getParameter(domainId, parameterId,
|
ReturnValue_t result = strangeReplyCount.getParameter(domainId, uniqueId,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
parameterWrapper, newValues, startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = missedReplyCount.getParameter(domainId, parameterId,
|
result = missedReplyCount.getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = recoveryCounter.getParameter(domainId, parameterId,
|
result = recoveryCounter.getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -17,9 +17,9 @@ public:
|
|||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize();
|
||||||
void triggerEvent(Event event, uint32_t parameter1 = 0,
|
void triggerEvent(Event event, uint32_t parameter1 = 0,
|
||||||
uint32_t parameter2 = 0);bool isFdirActionInProgress();
|
uint32_t parameter2 = 0);bool isFdirActionInProgress();
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
uint16_t startAtIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FaultCounter strangeReplyCount;
|
FaultCounter strangeReplyCount;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#include "DeviceHandlerMessage.h"
|
#include "DeviceHandlerMessage.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManager.h"
|
||||||
|
|
||||||
store_address_t DeviceHandlerMessage::getStoreAddress(
|
store_address_t DeviceHandlerMessage::getStoreAddress(
|
||||||
const CommandMessage* message) {
|
const CommandMessage* message) {
|
||||||
@@ -70,7 +70,7 @@ void DeviceHandlerMessage::clear(CommandMessage* message) {
|
|||||||
case REPLY_RAW_COMMAND:
|
case REPLY_RAW_COMMAND:
|
||||||
case REPLY_RAW_REPLY:
|
case REPLY_RAW_REPLY:
|
||||||
case REPLY_DIRECT_COMMAND_DATA: {
|
case REPLY_DIRECT_COMMAND_DATA: {
|
||||||
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
|
StorageManagerIF *ipcStore = ObjectManager::instance()->get<StorageManagerIF>(
|
||||||
objects::IPC_STORE);
|
objects::IPC_STORE);
|
||||||
if (ipcStore != nullptr) {
|
if (ipcStore != nullptr) {
|
||||||
ipcStore->deleteData(getStoreAddress(message));
|
ipcStore->deleteData(getStoreAddress(message));
|
||||||
|
@@ -16,9 +16,9 @@ ReturnValue_t HealthDevice::performOperation(uint8_t opCode) {
|
|||||||
CommandMessage command;
|
CommandMessage command;
|
||||||
ReturnValue_t result = commandQueue->receiveMessage(&command);
|
ReturnValue_t result = commandQueue->receiveMessage(&command);
|
||||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||||
healthHelper.handleHealthCommand(&command);
|
result = healthHelper.handleHealthCommand(&command);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t HealthDevice::initialize() {
|
ReturnValue_t HealthDevice::initialize() {
|
||||||
|
@@ -1,12 +1,30 @@
|
|||||||
|
Configuring the FSFW
|
||||||
## Configuring the FSFW
|
======
|
||||||
|
|
||||||
The FSFW can be configured via the `fsfwconfig` folder. A template folder has
|
The FSFW can be configured via the `fsfwconfig` folder. A template folder has
|
||||||
been provided to have a starting point for this. The folder should be added
|
been provided to have a starting point for this. The folder should be added
|
||||||
to the include path.
|
to the include path. The primary configuration file is the `FSFWConfig.h` folder. Some
|
||||||
|
of the available options will be explained in more detail here.
|
||||||
|
|
||||||
|
# Auto-Translation of Events
|
||||||
|
|
||||||
### Configuring the Event Manager
|
The FSFW allows the automatic translation of events, which allows developers to track triggered
|
||||||
|
events directly via console output. Using this feature requires:
|
||||||
|
|
||||||
|
1. `FSFW_OBJ_EVENT_TRANSLATION` set to 1 in the configuration file.
|
||||||
|
2. Special auto-generated translation files which translate event IDs and object IDs into
|
||||||
|
human readable strings. These files can be generated using the
|
||||||
|
[modgen Python scripts](https://git.ksat-stuttgart.de/source/modgen.git).
|
||||||
|
3. The generated translation files for the object IDs should be named `translatesObjects.cpp`
|
||||||
|
and `translateObjects.h` and should be copied to the `fsfwconfig/objects` folder
|
||||||
|
4. The generated translation files for the event IDs should be named `translateEvents.cpp` and
|
||||||
|
`translateEvents.h` and should be copied to the `fsfwconfig/events` folder
|
||||||
|
|
||||||
|
An example implementations of these translation file generators can be found as part
|
||||||
|
of the [SOURCE project here](https://git.ksat-stuttgart.de/source/sourceobsw/-/tree/development/generators)
|
||||||
|
or the [FSFW example](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_example_public/src/branch/master/generators)
|
||||||
|
|
||||||
|
## Configuring the Event Manager
|
||||||
|
|
||||||
The number of allowed subscriptions can be modified with the following
|
The number of allowed subscriptions can be modified with the following
|
||||||
parameters:
|
parameters:
|
||||||
@@ -18,4 +36,5 @@ static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240;
|
|||||||
static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120;
|
static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120;
|
||||||
static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
|
static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -19,8 +19,9 @@ A nullptr check of the returning Pointer must be done. This function is based on
|
|||||||
```cpp
|
```cpp
|
||||||
template <typename T> T* ObjectManagerIF::get( object_id_t id )
|
template <typename T> T* ObjectManagerIF::get( object_id_t id )
|
||||||
```
|
```
|
||||||
* A typical way to create all objects on startup is a handing a static produce function to the ObjectManager on creation.
|
* A typical way to create all objects on startup is a handing a static produce function to the
|
||||||
By calling objectManager->initialize() the produce function will be called and all SystemObjects will be initialized afterwards.
|
ObjectManager on creation. By calling objectManager->initialize() the produce function will be
|
||||||
|
called and all SystemObjects will be initialized afterwards.
|
||||||
|
|
||||||
### Event Manager
|
### Event Manager
|
||||||
|
|
||||||
@@ -36,14 +37,19 @@ By calling objectManager->initialize() the produce function will be called and a
|
|||||||
|
|
||||||
### Stores
|
### Stores
|
||||||
|
|
||||||
* The message based communication can only exchange a few bytes of information inside the message itself. Therefore, additional information can
|
* The message based communication can only exchange a few bytes of information inside the message
|
||||||
be exchanged with Stores. With this, only the store address must be exchanged in the message.
|
itself. Therefore, additional information can be exchanged with Stores. With this, only the
|
||||||
* Internally, the FSFW uses an IPC Store to exchange data between processes. For incoming TCs a TC Store is used. For outgoing TM a TM store is used.
|
store address must be exchanged in the message.
|
||||||
|
* Internally, the FSFW uses an IPC Store to exchange data between processes. For incoming TCs a TC
|
||||||
|
Store is used. For outgoing TM a TM store is used.
|
||||||
* All of them should use the Thread Safe Class storagemanager/PoolManager
|
* All of them should use the Thread Safe Class storagemanager/PoolManager
|
||||||
|
|
||||||
### Tasks
|
### Tasks
|
||||||
|
|
||||||
There are two different types of tasks:
|
There are two different types of tasks:
|
||||||
* The PeriodicTask just executes objects that are of type ExecutableObjectIF in the order of the insertion to the Tasks.
|
* The PeriodicTask just executes objects that are of type ExecutableObjectIF in the order of the
|
||||||
* FixedTimeslotTask executes a list of calls in the order of the given list. This is intended for DeviceHandlers, where polling should be in a defined order. An example can be found in defaultcfg/fsfwconfig/pollingSequence
|
insertion to the Tasks.
|
||||||
|
* FixedTimeslotTask executes a list of calls in the order of the given list. This is intended for
|
||||||
|
DeviceHandlers, where polling should be in a defined order. An example can be found in
|
||||||
|
`defaultcfg/fsfwconfig/pollingSequence` folder
|
||||||
|
|
||||||
|
@@ -1,99 +1,135 @@
|
|||||||
# High-level overview
|
High-level overview
|
||||||
|
======
|
||||||
|
|
||||||
## Structure
|
# Structure
|
||||||
|
|
||||||
The general structure is driven by the usage of interfaces provided by objects.
|
The general structure is driven by the usage of interfaces provided by objects.
|
||||||
The FSFW uses C++11 as baseline. The intention behind this is that this C++ Standard should be widely available, even with older compilers.
|
The FSFW uses C++11 as baseline. The intention behind this is that this C++ Standard should be
|
||||||
|
widely available, even with older compilers.
|
||||||
The FSFW uses dynamic allocation during the initialization but provides static containers during runtime.
|
The FSFW uses dynamic allocation during the initialization but provides static containers during runtime.
|
||||||
This simplifies the instantiation of objects and allows the usage of some standard containers.
|
This simplifies the instantiation of objects and allows the usage of some standard containers.
|
||||||
Dynamic Allocation after initialization is discouraged and different solutions are provided in the FSFW to achieve that.
|
Dynamic Allocation after initialization is discouraged and different solutions are provided in the
|
||||||
The fsfw uses run-time type information but exceptions are not allowed.
|
FSFW to achieve that. The fsfw uses run-time type information but exceptions are not allowed.
|
||||||
|
|
||||||
### Failure Handling
|
# Failure Handling
|
||||||
|
|
||||||
Functions should return a defined ReturnValue_t to signal to the caller that something has gone wrong.
|
Functions should return a defined `ReturnValue_t` to signal to the caller that something has
|
||||||
Returnvalues must be unique. For this the function HasReturnvaluesIF::makeReturnCode or the Macro MAKE_RETURN can be used.
|
gone wrong. Returnvalues must be unique. For this the function `HasReturnvaluesIF::makeReturnCode`
|
||||||
The CLASS_ID is a unique id for that type of object. See returnvalues/FwClassIds.
|
or the macro `MAKE_RETURN` can be used. The `CLASS_ID` is a unique id for that type of object.
|
||||||
|
See `returnvalues/FwClassIds` folder. The user can add custom `CLASS_ID`s via the
|
||||||
|
`fsfwconfig` folder.
|
||||||
|
|
||||||
### OSAL
|
# OSAL
|
||||||
|
|
||||||
The FSFW provides operation system abstraction layers for Linux, FreeRTOS and RTEMS.
|
The FSFW provides operation system abstraction layers for Linux, FreeRTOS and RTEMS.
|
||||||
The OSAL provides periodic tasks, message queues, clocks and semaphores as well as mutexes.
|
The OSAL provides periodic tasks, message queues, clocks and semaphores as well as mutexes.
|
||||||
The [OSAL README](doc/README-osal.md#top) provides more detailed information on provided components and how to use them.
|
The [OSAL README](doc/README-osal.md#top) provides more detailed information on provided components
|
||||||
|
and how to use them.
|
||||||
|
|
||||||
### Core Components
|
# Core Components
|
||||||
|
|
||||||
The FSFW has following core components. More detailed informations can be found in the
|
The FSFW has following core components. More detailed informations can be found in the
|
||||||
[core component section](doc/README-core.md#top):
|
[core component section](doc/README-core.md#top):
|
||||||
|
|
||||||
1. Tasks: Abstraction for different (periodic) task types like periodic tasks or tasks with fixed timeslots
|
1. Tasks: Abstraction for different (periodic) task types like periodic tasks or tasks
|
||||||
2. ObjectManager: This module stores all `SystemObjects` by mapping a provided unique object ID to the object handles.
|
with fixed timeslots
|
||||||
3. Static Stores: Different stores are provided to store data of variable size (like telecommands or small telemetry) in a pool structure without
|
2. ObjectManager: This module stores all `SystemObjects` by mapping a provided unique object ID
|
||||||
using dynamic memory allocation. These pools are allocated up front.
|
to the object handles.
|
||||||
|
3. Static Stores: Different stores are provided to store data of variable size (like telecommands
|
||||||
|
or small telemetry) in a pool structure without using dynamic memory allocation.
|
||||||
|
These pools are allocated up front.
|
||||||
3. Clock: This module provided common time related functions
|
3. Clock: This module provided common time related functions
|
||||||
4. EventManager: This module allows routing of events generated by `SystemObjects`
|
4. EventManager: This module allows routing of events generated by `SystemObjects`
|
||||||
5. HealthTable: A component which stores the health states of objects
|
5. HealthTable: A component which stores the health states of objects
|
||||||
|
|
||||||
### Static IDs in the framework
|
# Static IDs in the framework
|
||||||
|
|
||||||
Some parts of the framework use a static routing address for communication.
|
Some parts of the framework use a static routing address for communication.
|
||||||
An example setup of ids can be found in the example config in "defaultcft/fsfwconfig/objects/Factory::setStaticFrameworkObjectIds()".
|
An example setup of ids can be found in the example config in `defaultcft/fsfwconfig/objects`
|
||||||
|
inside the function `Factory::setStaticFrameworkObjectIds()`.
|
||||||
|
|
||||||
### Events
|
# Events
|
||||||
|
|
||||||
Events are tied to objects. EventIds can be generated by calling the Macro MAKE_EVENT. This works analog to the returnvalues.
|
Events are tied to objects. EventIds can be generated by calling the Macro MAKE_EVENT.
|
||||||
Every object that needs own EventIds has to get a unique SUBSYSTEM_ID.
|
This works analog to the returnvalues. Every object that needs own EventIds has to get a
|
||||||
Every SystemObject can call triggerEvent from the parent class.
|
unique SUBSYSTEM_ID. Every SystemObject can call triggerEvent from the parent class.
|
||||||
Therefore, event messages contain the specific EventId and the objectId of the object that has triggered.
|
Therefore, event messages contain the specific EventId and the objectId of the object that
|
||||||
|
has triggered.
|
||||||
|
|
||||||
### Internal Communication
|
# Internal Communication
|
||||||
|
|
||||||
Components communicate mostly over Message through Queues.
|
Components communicate mostly via Messages through Queues.
|
||||||
Those queues are created by calling the singleton QueueFactory::instance()->create().
|
Those queues are created by calling the singleton `QueueFactory::instance()->create()` which
|
||||||
|
will create `MessageQueue` instances for the used OSAL.
|
||||||
|
|
||||||
### External Communication
|
# External Communication
|
||||||
|
|
||||||
The external communication with the mission control system is mostly up to the user implementation.
|
The external communication with the mission control system is mostly up to the user implementation.
|
||||||
The FSFW provides PUS Services which can be used to but don't need to be used.
|
The FSFW provides PUS Services which can be used to but don't need to be used.
|
||||||
The services can be seen as a conversion from a TC to a message based communication and back.
|
The services can be seen as a conversion from a TC to a message based communication and back.
|
||||||
|
|
||||||
#### CCSDS Frames, CCSDS Space Packets and PUS
|
## TMTC Communication
|
||||||
|
|
||||||
If the communication is based on CCSDS Frames and Space Packets, several classes can be used to distributed the packets to the corresponding services. Those can be found in tcdistribution.
|
The FSFW provides some components to facilitate TMTC handling via the PUS commands.
|
||||||
If Space Packets are used, a timestamper must be created.
|
For example, a UDP or TCP PUS server socket can be opened on a specific port using the
|
||||||
An example can be found in the timemanager folder, this uses CCSDSTime::CDS_short.
|
files located in `osal/common`. The FSFW example uses this functionality to allow sending telecommands
|
||||||
|
and receiving telemetry using the [TMTC commander application](https://github.com/spacefisch/tmtccmd).
|
||||||
|
Simple commands like the PUS Service 17 ping service can be tested by simply running the
|
||||||
|
`tmtc_client_cli.py` or `tmtc_client_gui.py` utility in
|
||||||
|
the [example tmtc folder](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_example_public/src/branch/master/tmtc)
|
||||||
|
while the `fsfw_example` application is running.
|
||||||
|
|
||||||
#### Device Handlers
|
More generally, any class responsible for handling incoming telecommands and sending telemetry
|
||||||
|
can implement the generic `TmTcBridge` class located in `tmtcservices`. Many applications
|
||||||
|
also use a dedicated polling task for reading telecommands which passes telecommands
|
||||||
|
to the `TmTcBridge` implementation.
|
||||||
|
|
||||||
|
## CCSDS Frames, CCSDS Space Packets and PUS
|
||||||
|
|
||||||
|
If the communication is based on CCSDS Frames and Space Packets, several classes can be used to
|
||||||
|
distributed the packets to the corresponding services. Those can be found in `tcdistribution`.
|
||||||
|
If Space Packets are used, a timestamper has to be provided by the user.
|
||||||
|
An example can be found in the `timemanager` folder, which uses `CCSDSTime::CDS_short`.
|
||||||
|
|
||||||
|
# Device Handlers
|
||||||
|
|
||||||
DeviceHandlers are another important component of the FSFW.
|
DeviceHandlers are another important component of the FSFW.
|
||||||
The idea is, to have a software counterpart of every physical device to provide a simple mode, health and commanding interface.
|
The idea is, to have a software counterpart of every physical device to provide a simple mode,
|
||||||
By separating the underlying Communication Interface with DeviceCommunicationIF, a device handler (DH) can be tested on different hardware.
|
health and commanding interface. By separating the underlying Communication Interface with
|
||||||
The DH has mechanisms to monitor the communication with the physical device which allow for FDIR reaction.
|
`DeviceCommunicationIF`, a device handler (DH) can be tested on different hardware.
|
||||||
Device Handlers can be created by overriding `DeviceHandlerBase`.
|
The DH has mechanisms to monitor the communication with the physical device which allow
|
||||||
A standard FDIR component for the DH will be created automatically but can be overwritten by the user.
|
for FDIR reaction. Device Handlers can be created by implementing `DeviceHandlerBase`.
|
||||||
More information on DeviceHandlers can be found in the related [documentation section](doc/README-devicehandlers.md#top).
|
A standard FDIR component for the DH will be created automatically but can
|
||||||
|
be overwritten by the user. More information on DeviceHandlers can be found in the
|
||||||
|
related [documentation section](doc/README-devicehandlers.md#top).
|
||||||
|
|
||||||
#### Modes, Health
|
# Modes and Health
|
||||||
|
|
||||||
The two interfaces HasModesIF and HasHealthIF provide access for commanding and monitoring of components.
|
The two interfaces `HasModesIF` and `HasHealthIF` provide access for commanding and monitoring
|
||||||
On-board Mode Management is implement in hierarchy system.
|
of components. On-board Mode Management is implement in hierarchy system.
|
||||||
DeviceHandlers and Controllers are the lowest part of the hierarchy.
|
DeviceHandlers and Controllers are the lowest part of the hierarchy.
|
||||||
The next layer are Assemblies. Those assemblies act as a component which handle redundancies of handlers.
|
The next layer are Assemblies. Those assemblies act as a component which handle
|
||||||
Assemblies share a common core with the next level which are the Subsystems.
|
redundancies of handlers. Assemblies share a common core with the next level which
|
||||||
|
are the Subsystems.
|
||||||
|
|
||||||
Those Assemblies are intended to act as auto-generated components from a database which describes the subsystem modes.
|
Those Assemblies are intended to act as auto-generated components from a database which describes
|
||||||
The definitions contain transition and target tables which contain the DH, Assembly and Controller Modes to be commanded.
|
the subsystem modes. The definitions contain transition and target tables which contain the DH,
|
||||||
Transition tables contain as many steps as needed to reach the mode from any other mode, e.g. a switch into any higher AOCS mode might first turn on the sensors, than the actuators and the controller as last component.
|
Assembly and Controller Modes to be commanded.
|
||||||
|
Transition tables contain as many steps as needed to reach the mode from any other mode, e.g. a
|
||||||
|
switch into any higher AOCS mode might first turn on the sensors, than the actuators and the
|
||||||
|
controller as last component.
|
||||||
The target table is used to describe the state that is checked continuously by the subsystem.
|
The target table is used to describe the state that is checked continuously by the subsystem.
|
||||||
All of this allows System Modes to be generated as Subsystem object as well from the same database.
|
All of this allows System Modes to be generated as Subsystem object as well from the same database.
|
||||||
This System contains list of subsystem modes in the transition and target tables.
|
This System contains list of subsystem modes in the transition and target tables.
|
||||||
Therefore, it allows a modular system to create system modes and easy commanding of those, because only the highest components must be commanded.
|
Therefore, it allows a modular system to create system modes and easy commanding of those, because
|
||||||
|
only the highest components must be commanded.
|
||||||
|
|
||||||
The health state represents if the component is able to perform its tasks.
|
The health state represents if the component is able to perform its tasks.
|
||||||
This can be used to signal the system to avoid using this component instead of a redundant one.
|
This can be used to signal the system to avoid using this component instead of a redundant one.
|
||||||
The on-board FDIR uses the health state for isolation and recovery.
|
The on-board FDIR uses the health state for isolation and recovery.
|
||||||
|
|
||||||
## Unit Tests
|
# Unit Tests
|
||||||
|
|
||||||
Unit Tests are provided in the unittest folder. Those use the catch2 framework but do not include catch2 itself. More information on how to run these tests can be found in the separate
|
Unit Tests are provided in the unittest folder. Those use the catch2 framework but do not include
|
||||||
|
catch2 itself. More information on how to run these tests can be found in the separate
|
||||||
[`fsfw_tests` reposoitory](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_tests)
|
[`fsfw_tests` reposoitory](https://egit.irs.uni-stuttgart.de/fsfw/fsfw_tests)
|
||||||
|
@@ -1,3 +1,172 @@
|
|||||||
## Local Data Pools
|
## Local Data Pools Developer Information
|
||||||
|
|
||||||
|
The following text is targeted towards mission software developers which would like
|
||||||
|
to use the local data pools provided by the FSFW to store data like sensor values so they can be
|
||||||
|
used by other software objects like controllers as well. If a custom class should have a local
|
||||||
|
pool which can be used by other software objects as well, following steps have to be performed:
|
||||||
|
|
||||||
|
1. Create a `LocalDataPoolManager` member object in the custom class
|
||||||
|
2. Implement the `HasLocalDataPoolIF` with specifies the interface between the local pool manager
|
||||||
|
and the class owning the local pool.
|
||||||
|
|
||||||
|
The local data pool manager is also able to process housekeeping service requests in form
|
||||||
|
of messages, generate periodic housekeeping packet, generate notification and snapshots of changed
|
||||||
|
variables and datasets and process notifications and snapshots coming from other objects.
|
||||||
|
The two former tasks are related to the external interface using telemetry and telecommands (TMTC)
|
||||||
|
while the later two are related to data consumers like controllers only acting on data change
|
||||||
|
detected by the data creator instead of checking the data manually each cycle. Two important
|
||||||
|
framework classes `DeviceHandlerBase` and `ExtendedControllerBase` already perform the two steps
|
||||||
|
shown above so the steps required are altered slightly.
|
||||||
|
|
||||||
|
### Storing and Accessing pool data
|
||||||
|
|
||||||
|
The pool manager is responsible for thread-safe access of the pool data, but the actual
|
||||||
|
access to the pool data from the point of view of a mission software developer happens via proxy
|
||||||
|
classes like pool variable classes. These classes store a copy
|
||||||
|
of the pool variable with the matching datatype and copy the actual data from the local pool
|
||||||
|
on a `read` call. Changed variables can then be written to the local pool with a `commit` call.
|
||||||
|
The `read` and `commit` calls are thread-safe and can be called concurrently from data creators
|
||||||
|
and data consumers. Generally, a user will create a dataset class which in turn groups all
|
||||||
|
cohesive pool variables. These sets simply iterator over the list of variables and call the
|
||||||
|
`read` and `commit` functions of each variable. The following diagram shows the
|
||||||
|
high-level architecture of the local data pools.
|
||||||
|
|
||||||
|
<img align="center" src="./images/PoolArchitecture.png" width="50%"> <br>
|
||||||
|
|
||||||
|
An example is shown for using the local data pools with a Gyroscope.
|
||||||
|
For example, the following code shows an implementation to access data from a Gyroscope taken
|
||||||
|
from the SOURCE CubeSat project:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class GyroPrimaryDataset: public StaticLocalDataSet<3 * sizeof(float)> {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor for data users
|
||||||
|
* @param gyroId
|
||||||
|
*/
|
||||||
|
GyroPrimaryDataset(object_id_t gyroId):
|
||||||
|
StaticLocalDataSet(sid_t(gyroId, gyrodefs::GYRO_DATA_SET_ID)) {
|
||||||
|
setAllVariablesReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
lp_var_t<float> angVelocityX = lp_var_t<float>(sid.objectId,
|
||||||
|
gyrodefs::ANGULAR_VELOCITY_X, this);
|
||||||
|
lp_var_t<float> angVelocityY = lp_var_t<float>(sid.objectId,
|
||||||
|
gyrodefs::ANGULAR_VELOCITY_Y, this);
|
||||||
|
lp_var_t<float> angVelocityZ = lp_var_t<float>(sid.objectId,
|
||||||
|
gyrodefs::ANGULAR_VELOCITY_Z, this);
|
||||||
|
private:
|
||||||
|
|
||||||
|
friend class GyroHandler;
|
||||||
|
/**
|
||||||
|
* Constructor for data creator
|
||||||
|
* @param hkOwner
|
||||||
|
*/
|
||||||
|
GyroPrimaryDataset(HasLocalDataPoolIF* hkOwner):
|
||||||
|
StaticLocalDataSet(hkOwner, gyrodefs::GYRO_DATA_SET_ID) {}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
There is a public constructor for users which sets all variables to read-only and there is a
|
||||||
|
constructor for the GyroHandler data creator by marking it private and declaring the `GyroHandler`
|
||||||
|
as a friend class. Both the atittude controller and the `GyroHandler` can now
|
||||||
|
use the same class definition to access the pool variables with `read` and `commit` semantics
|
||||||
|
in a thread-safe way. Generally, each class requiring access will have the set class as a member
|
||||||
|
class. The data creator will also be generally a `DeviceHandlerBase` subclass and some additional
|
||||||
|
steps are necessary to expose the set for housekeeping purposes.
|
||||||
|
|
||||||
|
### Using the local data pools in a `DeviceHandlerBase` subclass
|
||||||
|
|
||||||
|
It is very common to store data generated by devices like a sensor into a pool which can
|
||||||
|
then be used by other objects. Therefore, the `DeviceHandlerBase` already has a
|
||||||
|
local pool. Using the aforementioned example, our `GyroHandler` will now have the set class
|
||||||
|
as a member:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class GyroHandler: ... {
|
||||||
|
|
||||||
|
public:
|
||||||
|
...
|
||||||
|
private:
|
||||||
|
...
|
||||||
|
GyroPrimaryDataset gyroData;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The constructor used for the creators expects the owner class as a parameter, so we initialize
|
||||||
|
the object in the `GyroHandler` constructor like this:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
GyroHandler::GyroHandler(object_id_t objectId, object_id_t comIF,
|
||||||
|
CookieIF *comCookie, uint8_t switchId):
|
||||||
|
DeviceHandlerBase(objectId, comIF, comCookie), switchId(switchId),
|
||||||
|
gyroData(this) {}
|
||||||
|
```
|
||||||
|
|
||||||
|
We need to assign the set to a reply ID used in the `DeviceHandlerBase`.
|
||||||
|
The combination of the `GyroHandler` object ID and the reply ID will be the 64-bit structure ID
|
||||||
|
`sid_t` and is used to globally identify the set, for example when requesting housekeeping data or
|
||||||
|
generating update messages. We need to assign our custom set class in some way so that the local
|
||||||
|
pool manager can access the custom data sets as well.
|
||||||
|
By default, the `getDataSetHandle` will take care of this tasks. The default implementation for a
|
||||||
|
`DeviceHandlerBase` subclass will use the internal command map to retrieve
|
||||||
|
a handle to a dataset from a given reply ID. Therefore,
|
||||||
|
we assign the set in the `fillCommandAndReplyMap` function:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void GyroHandler::fillCommandAndReplyMap() {
|
||||||
|
...
|
||||||
|
this->insertInCommandAndReplyMap(gyrodefs::GYRO_DATA, 3, &gyroData);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, we need to create the actual pool entries as well, using the `initializeLocalDataPool`
|
||||||
|
function. Here, we also immediately subscribe for periodic housekeeping packets
|
||||||
|
with an interval of 4 seconds. They are still disabled in this example and can be enabled
|
||||||
|
with a housekeeping service command.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
ReturnValue_t GyroHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||||
|
LocalDataPoolManager &poolManager) {
|
||||||
|
localDataPoolMap.emplace(gyrodefs::ANGULAR_VELOCITY_X,
|
||||||
|
new PoolEntry<float>({0.0}));
|
||||||
|
localDataPoolMap.emplace(gyrodefs::ANGULAR_VELOCITY_Y,
|
||||||
|
new PoolEntry<float>({0.0}));
|
||||||
|
localDataPoolMap.emplace(gyrodefs::ANGULAR_VELOCITY_Z,
|
||||||
|
new PoolEntry<float>({0.0}));
|
||||||
|
localDataPoolMap.emplace(gyrodefs::GENERAL_CONFIG_REG42,
|
||||||
|
new PoolEntry<uint8_t>({0}));
|
||||||
|
localDataPoolMap.emplace(gyrodefs::RANGE_CONFIG_REG43,
|
||||||
|
new PoolEntry<uint8_t>({0}));
|
||||||
|
|
||||||
|
poolManager.subscribeForPeriodicPacket(gyroData.getSid(), false, 4.0, false);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, if we receive some sensor data and converted them into the right format,
|
||||||
|
we can write it into the pool like this, using a guard class to ensure the set is commited back
|
||||||
|
in any case:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
PoolReadGuard readHelper(&gyroData);
|
||||||
|
if(readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
if(not gyroData.isValid()) {
|
||||||
|
gyroData.setValidity(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
gyroData.angVelocityX = angularVelocityX;
|
||||||
|
gyroData.angVelocityY = angularVelocityY;
|
||||||
|
gyroData.angVelocityZ = angularVelocityZ;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The guard class will commit the changed data on destruction automatically.
|
||||||
|
|
||||||
|
### Using the local data pools in a `ExtendedControllerBase` subclass
|
||||||
|
|
||||||
|
Coming soon
|
||||||
|
|
||||||
|
|
||||||
|
3
doc/doxy/.gitignore
vendored
Normal file
3
doc/doxy/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
html
|
||||||
|
latex
|
||||||
|
rtf
|
2609
doc/doxy/OPUS.doxyfile
Normal file
2609
doc/doxy/OPUS.doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/images/PoolArchitecture.png
Normal file
BIN
doc/images/PoolArchitecture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
@@ -1,11 +1,10 @@
|
|||||||
#include "EventManager.h"
|
#include "EventManager.h"
|
||||||
#include "EventMessage.h"
|
#include "EventMessage.h"
|
||||||
|
|
||||||
#include <FSFWConfig.h>
|
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include "../ipc/QueueFactory.h"
|
#include "../ipc/QueueFactory.h"
|
||||||
#include "../ipc/MutexFactory.h"
|
#include "../ipc/MutexFactory.h"
|
||||||
|
|
||||||
|
MessageQueueId_t EventManagerIF::eventmanagerQueue = MessageQueueIF::NO_QUEUE;
|
||||||
|
|
||||||
// If one checks registerListener calls, there are around 40 (to max 50)
|
// If one checks registerListener calls, there are around 40 (to max 50)
|
||||||
// objects registering for certain events.
|
// objects registering for certain events.
|
||||||
@@ -114,53 +113,6 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FSFW_OBJ_EVENT_TRANSLATION == 1
|
|
||||||
|
|
||||||
void EventManager::printEvent(EventMessage* message) {
|
|
||||||
const char *string = 0;
|
|
||||||
switch (message->getSeverity()) {
|
|
||||||
case severity::INFO:
|
|
||||||
#if DEBUG_INFO_EVENT == 1
|
|
||||||
string = translateObject(message->getReporter());
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::info << "EVENT: ";
|
|
||||||
if (string != 0) {
|
|
||||||
sif::info << string;
|
|
||||||
} else {
|
|
||||||
sif::info << "0x" << std::hex << message->getReporter() << std::dec;
|
|
||||||
}
|
|
||||||
sif::info << " reported " << translateEvents(message->getEvent()) << " ("
|
|
||||||
<< std::dec << message->getEventId() << std::hex << ") P1: 0x"
|
|
||||||
<< message->getParameter1() << " P2: 0x"
|
|
||||||
<< message->getParameter2() << std::dec << std::endl;
|
|
||||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
|
||||||
#endif /* DEBUG_INFO_EVENT == 1 */
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
string = translateObject(message->getReporter());
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::debug << "EventManager: ";
|
|
||||||
if (string != 0) {
|
|
||||||
sif::debug << string;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sif::debug << "0x" << std::hex << message->getReporter() << std::dec;
|
|
||||||
}
|
|
||||||
sif::debug << " reported " << translateEvents(message->getEvent())
|
|
||||||
<< " (" << std::dec << message->getEventId() << ") "
|
|
||||||
<< std::endl;
|
|
||||||
sif::debug << std::hex << "P1 Hex: 0x" << message->getParameter1()
|
|
||||||
<< ", P1 Dec: " << std::dec << message->getParameter1()
|
|
||||||
<< std::endl;
|
|
||||||
sif::debug << std::hex << "P2 Hex: 0x" << message->getParameter2()
|
|
||||||
<< ", P2 Dec: " << std::dec << message->getParameter2()
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void EventManager::lockMutex() {
|
void EventManager::lockMutex() {
|
||||||
mutex->lockMutex(timeoutType, timeoutMs);
|
mutex->lockMutex(timeoutType, timeoutMs);
|
||||||
}
|
}
|
||||||
@@ -174,3 +126,85 @@ void EventManager::setMutexTimeout(MutexIF::TimeoutType timeoutType,
|
|||||||
this->timeoutType = timeoutType;
|
this->timeoutType = timeoutType;
|
||||||
this->timeoutMs = timeoutMs;
|
this->timeoutMs = timeoutMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FSFW_OBJ_EVENT_TRANSLATION == 1
|
||||||
|
|
||||||
|
void EventManager::printEvent(EventMessage* message) {
|
||||||
|
switch (message->getSeverity()) {
|
||||||
|
case severity::INFO: {
|
||||||
|
#if FSFW_DEBUG_INFO == 1
|
||||||
|
printUtility(sif::OutputTypes::OUT_INFO, message);
|
||||||
|
#endif /* DEBUG_INFO_EVENT == 1 */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
printUtility(sif::OutputTypes::OUT_DEBUG, message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventManager::printUtility(sif::OutputTypes printType, EventMessage *message) {
|
||||||
|
const char *string = 0;
|
||||||
|
if(printType == sif::OutputTypes::OUT_INFO) {
|
||||||
|
string = translateObject(message->getReporter());
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::info << "EventManager: ";
|
||||||
|
if (string != 0) {
|
||||||
|
sif::info << string;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sif::info << "0x" << std::hex << std::setw(8) << std::setfill('0') <<
|
||||||
|
message->getReporter() << std::setfill(' ') << std::dec;
|
||||||
|
}
|
||||||
|
sif::info << " reported event with ID " << message->getEventId() << std::endl;
|
||||||
|
sif::debug << translateEvents(message->getEvent()) << " | " <<std::hex << "P1 Hex: 0x" <<
|
||||||
|
message->getParameter1() << " | P1 Dec: " << std::dec << message->getParameter1() <<
|
||||||
|
std::hex << " | P2 Hex: 0x" << message->getParameter2() << " | P2 Dec: " <<
|
||||||
|
std::dec << message->getParameter2() << std::endl;
|
||||||
|
#else
|
||||||
|
if (string != 0) {
|
||||||
|
sif::printInfo("Event Manager: %s reported event with ID %d\n", string,
|
||||||
|
message->getEventId());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sif::printInfo("Event Manager: Reporter ID 0x%08x reported event with ID %d\n",
|
||||||
|
message->getReporter(), message->getEventId());
|
||||||
|
}
|
||||||
|
sif::printInfo("P1 Hex: 0x%x | P1 Dec: %d | P2 Hex: 0x%x | P2 Dec: %d\n",
|
||||||
|
message->getParameter1(), message->getParameter1(),
|
||||||
|
message->getParameter2(), message->getParameter2());
|
||||||
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 0 */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
string = translateObject(message->getReporter());
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::debug << "EventManager: ";
|
||||||
|
if (string != 0) {
|
||||||
|
sif::debug << string;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sif::debug << "0x" << std::hex << std::setw(8) << std::setfill('0') <<
|
||||||
|
message->getReporter() << std::setfill(' ') << std::dec;
|
||||||
|
}
|
||||||
|
sif::debug << " reported event with ID " << message->getEventId() << std::endl;
|
||||||
|
sif::debug << translateEvents(message->getEvent()) << " | " <<std::hex << "P1 Hex: 0x" <<
|
||||||
|
message->getParameter1() << " | P1 Dec: " << std::dec << message->getParameter1() <<
|
||||||
|
std::hex << " | P2 Hex: 0x" << message->getParameter2() << " | P2 Dec: " <<
|
||||||
|
std::dec << message->getParameter2() << std::endl;
|
||||||
|
#else
|
||||||
|
if (string != 0) {
|
||||||
|
sif::printDebug("Event Manager: %s reported event with ID %d\n", string,
|
||||||
|
message->getEventId());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sif::printDebug("Event Manager: Reporter ID 0x%08x reported event with ID %d\n",
|
||||||
|
message->getReporter(), message->getEventId());
|
||||||
|
}
|
||||||
|
sif::printDebug("P1 Hex: 0x%x | P1 Dec: %d | P2 Hex: 0x%x | P2 Dec: %d\n",
|
||||||
|
message->getParameter1(), message->getParameter1(),
|
||||||
|
message->getParameter2(), message->getParameter2());
|
||||||
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 0 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */
|
||||||
|
@@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
#include "EventManagerIF.h"
|
#include "EventManagerIF.h"
|
||||||
#include "eventmatching/EventMatchTree.h"
|
#include "eventmatching/EventMatchTree.h"
|
||||||
|
#include "FSFWConfig.h"
|
||||||
|
|
||||||
#include <FSFWConfig.h>
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
#include "../objectmanager/SystemObject.h"
|
#include "../objectmanager/SystemObject.h"
|
||||||
#include "../storagemanager/LocalPool.h"
|
#include "../storagemanager/LocalPool.h"
|
||||||
#include "../tasks/ExecutableObjectIF.h"
|
#include "../tasks/ExecutableObjectIF.h"
|
||||||
@@ -67,6 +67,7 @@ protected:
|
|||||||
|
|
||||||
#if FSFW_OBJ_EVENT_TRANSLATION == 1
|
#if FSFW_OBJ_EVENT_TRANSLATION == 1
|
||||||
void printEvent(EventMessage *message);
|
void printEvent(EventMessage *message);
|
||||||
|
void printUtility(sif::OutputTypes printType, EventMessage* message);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void lockMutex();
|
void lockMutex();
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
#ifndef EVENTMANAGERIF_H_
|
#ifndef FSFW_EVENTS_EVENTMANAGERIF_H_
|
||||||
#define EVENTMANAGERIF_H_
|
#define FSFW_EVENTS_EVENTMANAGERIF_H_
|
||||||
|
|
||||||
#include "EventMessage.h"
|
#include "EventMessage.h"
|
||||||
#include "eventmatching/eventmatching.h"
|
#include "eventmatching/eventmatching.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManager.h"
|
||||||
#include "../ipc/MessageQueueSenderIF.h"
|
#include "../ipc/MessageQueueSenderIF.h"
|
||||||
#include "../ipc/MessageQueueIF.h"
|
#include "../ipc/MessageQueueIF.h"
|
||||||
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
class EventManagerIF {
|
class EventManagerIF {
|
||||||
public:
|
public:
|
||||||
@@ -41,11 +42,19 @@ public:
|
|||||||
|
|
||||||
static void triggerEvent(EventMessage* message,
|
static void triggerEvent(EventMessage* message,
|
||||||
MessageQueueId_t sentFrom = 0) {
|
MessageQueueId_t sentFrom = 0) {
|
||||||
static MessageQueueId_t eventmanagerQueue = MessageQueueIF::NO_QUEUE;
|
|
||||||
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
|
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
|
||||||
EventManagerIF *eventmanager = objectManager->get<EventManagerIF>(
|
EventManagerIF *eventmanager = ObjectManager::instance()->get<EventManagerIF>(
|
||||||
objects::EVENT_MANAGER);
|
objects::EVENT_MANAGER);
|
||||||
if (eventmanager == nullptr) {
|
if (eventmanager == nullptr) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "EventManagerIF::triggerEvent: EventManager invalid or not found!"
|
||||||
|
<< std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("EventManagerIF::triggerEvent: "
|
||||||
|
"EventManager invalid or not found!");
|
||||||
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eventmanagerQueue = eventmanager->getEventReportQueue();
|
eventmanagerQueue = eventmanager->getEventReportQueue();
|
||||||
@@ -53,6 +62,10 @@ public:
|
|||||||
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
|
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Initialized by EventManager (C++11 does not allow header-only static member initialization).
|
||||||
|
static MessageQueueId_t eventmanagerQueue;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EVENTMANAGERIF_H_ */
|
#endif /* FSFW_EVENTS_EVENTMANAGERIF_H_ */
|
||||||
|
@@ -109,6 +109,6 @@ bool EventMessage::isClearedEventMessage() {
|
|||||||
return getEvent() == INVALID_EVENT;
|
return getEvent() == INVALID_EVENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t EventMessage::getMinimumMessageSize() {
|
size_t EventMessage::getMinimumMessageSize() const {
|
||||||
return EVENT_MESSAGE_SIZE;
|
return EVENT_MESSAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
@@ -45,7 +45,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const Event INVALID_EVENT = 0;
|
static const Event INVALID_EVENT = 0;
|
||||||
virtual size_t getMinimumMessageSize();
|
virtual size_t getMinimumMessageSize() const override;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,30 +1,37 @@
|
|||||||
#ifndef FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_
|
#ifndef FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_
|
||||||
#define FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_
|
#define FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace SUBSYSTEM_ID {
|
namespace SUBSYSTEM_ID {
|
||||||
enum {
|
enum: uint8_t {
|
||||||
MEMORY = 22,
|
MEMORY = 22,
|
||||||
OBSW = 26,
|
OBSW = 26,
|
||||||
CDH = 28,
|
CDH = 28,
|
||||||
TCS_1 = 59,
|
TCS_1 = 59,
|
||||||
PCDU_1 = 42,
|
PCDU_1 = 42,
|
||||||
PCDU_2 = 43,
|
PCDU_2 = 43,
|
||||||
HEATER = 50,
|
HEATER = 50,
|
||||||
T_SENSORS = 52,
|
T_SENSORS = 52,
|
||||||
FDIR = 70,
|
FDIR = 70,
|
||||||
FDIR_1 = 71,
|
FDIR_1 = 71,
|
||||||
FDIR_2 = 72,
|
FDIR_2 = 72,
|
||||||
HK = 73,
|
HK = 73,
|
||||||
SYSTEM_MANAGER = 74,
|
SYSTEM_MANAGER = 74,
|
||||||
SYSTEM_MANAGER_1 = 75,
|
SYSTEM_MANAGER_1 = 75,
|
||||||
SYSTEM_1 = 79,
|
SYSTEM_1 = 79,
|
||||||
PUS_SERVICE_1 = 80,
|
PUS_SERVICE_1 = 80,
|
||||||
PUS_SERVICE_9 = 89,
|
PUS_SERVICE_2 = 82,
|
||||||
PUS_SERVICE_17 = 97,
|
PUS_SERVICE_3 = 83,
|
||||||
FW_SUBSYSTEM_ID_RANGE
|
PUS_SERVICE_5 = 85,
|
||||||
|
PUS_SERVICE_6 = 86,
|
||||||
|
PUS_SERVICE_8 = 88,
|
||||||
|
PUS_SERVICE_9 = 89,
|
||||||
|
PUS_SERVICE_17 = 97,
|
||||||
|
PUS_SERVICE_23 = 103,
|
||||||
|
|
||||||
|
FW_SUBSYSTEM_ID_RANGE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_ */
|
#endif /* FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_ */
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
#include "../health/HasHealthIF.h"
|
#include "../health/HasHealthIF.h"
|
||||||
#include "../health/HealthMessage.h"
|
#include "../health/HealthMessage.h"
|
||||||
#include "../ipc/QueueFactory.h"
|
#include "../ipc/QueueFactory.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManager.h"
|
||||||
|
|
||||||
FailureIsolationBase::FailureIsolationBase(object_id_t owner,
|
FailureIsolationBase::FailureIsolationBase(object_id_t owner,
|
||||||
object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) :
|
object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) :
|
||||||
@@ -18,7 +18,7 @@ FailureIsolationBase::~FailureIsolationBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t FailureIsolationBase::initialize() {
|
ReturnValue_t FailureIsolationBase::initialize() {
|
||||||
EventManagerIF* manager = objectManager->get<EventManagerIF>(
|
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(
|
||||||
objects::EVENT_MANAGER);
|
objects::EVENT_MANAGER);
|
||||||
if (manager == nullptr) {
|
if (manager == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
@@ -36,7 +36,7 @@ ReturnValue_t FailureIsolationBase::initialize() {
|
|||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
owner = objectManager->get<HasHealthIF>(ownerId);
|
owner = ObjectManager::instance()->get<HasHealthIF>(ownerId);
|
||||||
if (owner == nullptr) {
|
if (owner == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "FailureIsolationBase::intialize: Owner object "
|
sif::error << "FailureIsolationBase::intialize: Owner object "
|
||||||
@@ -46,7 +46,7 @@ ReturnValue_t FailureIsolationBase::initialize() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (faultTreeParent != objects::NO_OBJECT) {
|
if (faultTreeParent != objects::NO_OBJECT) {
|
||||||
ConfirmsFailuresIF* parentIF = objectManager->get<ConfirmsFailuresIF>(
|
ConfirmsFailuresIF* parentIF = ObjectManager::instance()->get<ConfirmsFailuresIF>(
|
||||||
faultTreeParent);
|
faultTreeParent);
|
||||||
if (parentIF == nullptr) {
|
if (parentIF == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
@@ -58,14 +58,14 @@ FaultCounter::FaultCounter() :
|
|||||||
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
|
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
if (domainId != parameterDomain) {
|
if (domainId != parameterDomain) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set(failureThreshold);
|
parameterWrapper->set(failureThreshold);
|
||||||
break;
|
break;
|
||||||
|
@@ -23,7 +23,7 @@ public:
|
|||||||
void setFailureThreshold(uint32_t failureThreshold);
|
void setFailureThreshold(uint32_t failureThreshold);
|
||||||
void setFaultDecrementTimeMs(uint32_t timeMs);
|
void setFaultDecrementTimeMs(uint32_t timeMs);
|
||||||
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user