Compare commits
	
		
			138 Commits
		
	
	
		
			docker_d7
			...
			docker_d11
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8c20417af9 | |||
| ac817f296b | |||
| 
						
						
							
						
						622ad9ff18
	
				 | 
					
					
						|||
| 
						
						
							
						
						f0e4eacac5
	
				 | 
					
					
						|||
| acc737feb2 | |||
| 
						
						
							
						
						c9281a3760
	
				 | 
					
					
						|||
| 
						
						
							
						
						cc97c7f82d
	
				 | 
					
					
						|||
| 
						
						
							
						
						a3b102c0d0
	
				 | 
					
					
						|||
| 5dd4f15b39 | |||
| b5a3c0226e | |||
| 
						
						
							
						
						e925b8595c
	
				 | 
					
					
						|||
| c5bf5389b8 | |||
| 
						
						
							
						
						7285dd6bac
	
				 | 
					
					
						|||
| b53bf2ea12 | |||
| 610c196f6d | |||
| ece47b4f2f | |||
| 3f777c54fe | |||
| 
						
						
							
						
						3d54895251
	
				 | 
					
					
						|||
| d91e1ecc0a | |||
| 
						
						
							
						
						e5910c77e9
	
				 | 
					
					
						|||
| 
						
						
							
						
						1569416a8f
	
				 | 
					
					
						|||
| 
						
						
							
						
						278c8f1186
	
				 | 
					
					
						|||
| 
						
						
							
						
						60f6ef5f1f
	
				 | 
					
					
						|||
| 4ecd9eb62e | |||
| fb89d7a3b6 | |||
| 146c3471d0 | |||
| 1816c3f623 | |||
| d03d5aa74c | |||
| 26e97ddf89 | |||
| be3a57a795 | |||
| 13b97abf0d | |||
| f95c373076 | |||
| e03731bcf8 | |||
| 9fe8579377 | |||
| 2714e588d7 | |||
| e905288adc | |||
| 3805ea50a7 | |||
| 699bd694cd | |||
| 4518fec65c | |||
| dac1aacab2 | |||
| 0042f92fdf | |||
| 656faf8169 | |||
| f84431e965 | |||
| 0cec9ebb73 | |||
| a440b7c394 | |||
| bbfc1b2b34 | |||
| 
						
						
							
						
						025b379e8b
	
				 | 
					
					
						|||
| c35a0a8541 | |||
| 0f81d5e458 | |||
| e0a072859b | |||
| b50f092939 | |||
| 2f90e12179 | |||
| 8b77fac099 | |||
| 47503824d7 | |||
| 5e3f5c4121 | |||
| 1f36c082ef | |||
| aa84e93603 | |||
| 8f63a0e747 | |||
| 6fc8f756a7 | |||
| 067cb7d0f8 | |||
| d98ed40e3d | |||
| 2c17af4ef8 | |||
| 110fb43b9c | |||
| b057250bfb | |||
| 066dd0d397 | |||
| f735c2e9d4 | |||
| dc7afc5415 | |||
| 9bf3ff95b7 | |||
| 61562b18ab | |||
| d76d97a36b | |||
| 76b377c4c0 | |||
| 3562bf11b9 | |||
| fffb2b61e5 | |||
| 94e5f62331 | |||
| 0a9c563bbc | |||
| fa7675897d | |||
| 3a2393885f | |||
| c752b6d143 | |||
| b676040c7c | |||
| 010509efb4 | |||
| dfb1633f00 | |||
| 5f7172e130 | |||
| 0c6465cd95 | |||
| f94987c46d | |||
| 1809ce359b | |||
| 8c712441ab | |||
| f1b0ca7cff | |||
| 000df85556 | |||
| 1fffcc2229 | |||
| a419806a05 | |||
| 6445debfa1 | |||
| 8014e4adf9 | |||
| 134d908f26 | |||
| 40a9e12416 | |||
| f39054edd4 | |||
| 5adf89b911 | |||
| c2e6a22dec | |||
| c8e065a713 | |||
| 3ed49dbae3 | |||
| 4cf52d5dfe | |||
| 539d7aac9e | |||
| 0a23f2c85a | |||
| 46230e6c6d | |||
| b22d439300 | |||
| 7e7b3bbbc9 | |||
| 5b92247fbd | |||
| e2b66df72e | |||
| d9da55fdab | |||
| 7b828f233a | |||
| c3d1000cd5 | |||
| 8e0e57714d | |||
| 066f7a6f9b | |||
| cc9e54ea6b | |||
| 31465a4e0f | |||
| c0e5d1eb99 | |||
| 3bc5d4a2e0 | |||
| b1e9dd9e4a | |||
| ab86599db3 | |||
| 034eb34c2e | |||
| 4374c7c4f4 | |||
| 5343844be5 | |||
| e300490b93 | |||
| 0f811777a7 | |||
| e93137939e | |||
| c1f42618db | |||
| 1f88c006d9 | |||
| 7e94baceef | |||
| 61df451dd8 | |||
| 29ea89044e | |||
| e487f5be87 | |||
| 9b05e8f274 | |||
| eb223dae88 | |||
| 3656662d88 | |||
| fe71978467 | |||
| b646717a76 | |||
| 99d8c845f2 | |||
| ba62c28b64 | |||
| 7adb47aecb | 
							
								
								
									
										167
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -8,14 +8,74 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 | 
			
		||||
 | 
			
		||||
# [unreleased]
 | 
			
		||||
 | 
			
		||||
# [v6.0.0]
 | 
			
		||||
## Fixes
 | 
			
		||||
 | 
			
		||||
- The `PusTmCreator` API only accepted 255 bytes of source data. It can now accept source
 | 
			
		||||
  data with a size limited only by the size of `size_t`.
 | 
			
		||||
- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence
 | 
			
		||||
  number fields stored the actual length of the field instead of the length minus 1 like specified
 | 
			
		||||
  in the CFDP standard.
 | 
			
		||||
- PUS Health Service: Size check for set health command.
 | 
			
		||||
  Perform operation completion for announce health command.
 | 
			
		||||
  https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746
 | 
			
		||||
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
 | 
			
		||||
  https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745
 | 
			
		||||
- Small tweak for version getter
 | 
			
		||||
  https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744
 | 
			
		||||
- Important bugfix for `LocalPool::delete` function, where an overflow could possibly lead to UB.
 | 
			
		||||
 | 
			
		||||
## Added
 | 
			
		||||
 | 
			
		||||
- add CFDP subsystem ID
 | 
			
		||||
  https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
 | 
			
		||||
- New object ID for persistent TM store PUS 15
 | 
			
		||||
- `EventManager`: Add function to print all listeners.
 | 
			
		||||
 | 
			
		||||
## Changed
 | 
			
		||||
 | 
			
		||||
- Bump ETL version to 20.35.14
 | 
			
		||||
  https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748
 | 
			
		||||
- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`.
 | 
			
		||||
  https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
 | 
			
		||||
- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue.
 | 
			
		||||
  https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
 | 
			
		||||
- Assert that `FixedArrayList` is larger than 0 at compile time.
 | 
			
		||||
  https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740
 | 
			
		||||
- `EventManager`: Queue depth is configurable now
 | 
			
		||||
- `ActionHelper`: Allow execution of actions without additional data
 | 
			
		||||
 | 
			
		||||
# [v6.0.0] 2023-02-10
 | 
			
		||||
 | 
			
		||||
## Fixes
 | 
			
		||||
 | 
			
		||||
- Mode Service: Add allowed subservice
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/739
 | 
			
		||||
- `CService200ModeManagement`: Various bugfixes which lead to now execution complete being generated
 | 
			
		||||
  on mode announcements, duplicate mode reply generated on announce commands, and the mode read
 | 
			
		||||
  subservice not working properly.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/736
 | 
			
		||||
- Memory leak fixes for the TCP/IP TMTC bridge.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/737
 | 
			
		||||
- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
 | 
			
		||||
  seconds instead of uptime.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
 | 
			
		||||
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
 | 
			
		||||
  only the X scaling factor was used.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724
 | 
			
		||||
- HAL MGM3100 Handler: Z value was previously calculated with bytes of the X value.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/733
 | 
			
		||||
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
 | 
			
		||||
  to false correctly because the `read` and `write` calls were missing.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/728
 | 
			
		||||
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
 | 
			
		||||
  of the correct unsegmented flags (0b11) as specified in the standard.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/727
 | 
			
		||||
- TC Scheduler Service 11: Add size and CRC check for contained TC.
 | 
			
		||||
  Bug: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/issues/719
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/720
 | 
			
		||||
- Only delete health table entry in `HealthHelper` destructor if
 | 
			
		||||
  health table was set.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710
 | 
			
		||||
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
 | 
			
		||||
  Also properly reset the reply size for successfull transfers and erroneous transfers.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
 | 
			
		||||
@@ -25,22 +85,82 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 | 
			
		||||
- `TcpTmTcServer.cpp`: The server was actually not able to handle
 | 
			
		||||
  CCSDS packets which were clumped together. This has been fixed now.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
 | 
			
		||||
- `CServiceHealthCommanding`: Add announce all health info implementation
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
 | 
			
		||||
- various fixes related to linux Unittests and memory leaks
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/715
 | 
			
		||||
- small fix to allow teardown handling
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/713
 | 
			
		||||
- fix compiler warning for fixed array list copy ctor
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/704
 | 
			
		||||
- missing include
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/703
 | 
			
		||||
- defaultconfig did not build anymore
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/702
 | 
			
		||||
- hotfix
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/699
 | 
			
		||||
- small fix for helper
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/698
 | 
			
		||||
- missing retval conv
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/697
 | 
			
		||||
- DHB Countdown Bug
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/693
 | 
			
		||||
- doc corrections
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/687
 | 
			
		||||
- better error printout
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/686
 | 
			
		||||
- include correction
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/683
 | 
			
		||||
- better warning for missing include paths
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/676
 | 
			
		||||
- Service 11 regression
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/670
 | 
			
		||||
 | 
			
		||||
## Added
 | 
			
		||||
 | 
			
		||||
- Empty constructor for `CdsShortTimeStamper` which does not do an object manager registration.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/730
 | 
			
		||||
- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.
 | 
			
		||||
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
 | 
			
		||||
  option on the TCP server. CTOR prototype has changed and expects an explicit
 | 
			
		||||
  TCP configuration struct to be passed.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/722
 | 
			
		||||
- `DleParser` helper class to parse DLE encoded packets from a byte stream.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/711
 | 
			
		||||
- `UioMapper` is able to resolve symlinks now.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
 | 
			
		||||
- Add new `UnsignedByteField` class
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
 | 
			
		||||
- publish documentation for development and master branch
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/681
 | 
			
		||||
- Add Linux HAL options
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/663
 | 
			
		||||
- Expand SerializeIF
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/656
 | 
			
		||||
- PUS Service 11: Additional Safety Check
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/666
 | 
			
		||||
- improvements for auto-formatter script
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/665
 | 
			
		||||
- provide a weak print char impl
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/674
 | 
			
		||||
 | 
			
		||||
## Removed
 | 
			
		||||
 | 
			
		||||
- now that doc server is up, remove markdown files
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/688
 | 
			
		||||
- remove bsp specific code
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/679
 | 
			
		||||
 | 
			
		||||
## Changes
 | 
			
		||||
 | 
			
		||||
- `CService201HealthCommanding` renamed to `CServiceHealthCommanding`,
 | 
			
		||||
  service ID customizable now. `CServiceHealthCommanding` expects configuration struct
 | 
			
		||||
  `HealthServiceCfg` now
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
 | 
			
		||||
- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
 | 
			
		||||
- Moved some container returnvalues to dedicated header and namespace
 | 
			
		||||
  to they can be used without template specification.
 | 
			
		||||
  so they can be used without template specification.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707
 | 
			
		||||
- Remove default secondary header argument for
 | 
			
		||||
  `uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
 | 
			
		||||
@@ -70,18 +190,41 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 | 
			
		||||
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
 | 
			
		||||
  a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
 | 
			
		||||
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
 | 
			
		||||
  interface itself so it can be re-used more easily. Also add new
 | 
			
		||||
  abstract function `bool hasDataAtId(store_address_t storeId) const`.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
 | 
			
		||||
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
 | 
			
		||||
  - Make functions `const` where it makes sense
 | 
			
		||||
  - Add `const char* getName const` abstract function
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
 | 
			
		||||
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
 | 
			
		||||
  interface itself so it can be re-used more easily. Also add new
 | 
			
		||||
  abstract function `bool hasDataAtId(store_address_t storeId) const`.
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
 | 
			
		||||
- Generic TMTC Bridge Update
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/734
 | 
			
		||||
- comment tweak to event parser can read everything
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/732
 | 
			
		||||
- CMakeLists file updates
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/731
 | 
			
		||||
- improve srv20 error messages
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/723
 | 
			
		||||
- I2C Linux: remove duplicate printout
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/718
 | 
			
		||||
- printout handling improvements
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/717
 | 
			
		||||
- vec getter, reset for content
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/716
 | 
			
		||||
- updates for source sequence counter
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/714
 | 
			
		||||
- SP reader getPacketData is const now
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/708
 | 
			
		||||
- refactoring of serial drivers for linux
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/705
 | 
			
		||||
- Local Pool Update Remove Add Data Ignore Fault Argument
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/701
 | 
			
		||||
- Switch to new documentation server
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/694
 | 
			
		||||
- Windows Tweaks
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/691
 | 
			
		||||
- Refactor Local Pool API
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/667
 | 
			
		||||
- group MGM data in local pool vectors
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/664
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## CFDP
 | 
			
		||||
 | 
			
		||||
@@ -101,7 +244,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 | 
			
		||||
     implementation without an extra component
 | 
			
		||||
  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
 | 
			
		||||
 | 
			
		||||
# [v5.0.0] 25.07.2022
 | 
			
		||||
# [v5.0.0] 2022-07-25
 | 
			
		||||
 | 
			
		||||
## Changes
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
 | 
			
		||||
# Version file handling  #
 | 
			
		||||
# ##############################################################################
 | 
			
		||||
 | 
			
		||||
set(FSFW_VERSION_IF_GIT_FAILS 5)
 | 
			
		||||
set(FSFW_VERSION_IF_GIT_FAILS 6)
 | 
			
		||||
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
 | 
			
		||||
set(FSFW_REVISION_IF_GIT_FAILS 0)
 | 
			
		||||
 | 
			
		||||
@@ -72,7 +72,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
 | 
			
		||||
    20
 | 
			
		||||
    CACHE STRING "ETL library major version requirement")
 | 
			
		||||
set(FSFW_ETL_LIB_VERSION
 | 
			
		||||
    ${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
 | 
			
		||||
    ${FSFW_ETL_LIB_MAJOR_VERSION}.36.0
 | 
			
		||||
    CACHE STRING "ETL library exact version requirement")
 | 
			
		||||
set(FSFW_ETL_LINK_TARGET etl::etl)
 | 
			
		||||
 | 
			
		||||
@@ -80,7 +80,7 @@ set(FSFW_CATCH2_LIB_MAJOR_VERSION
 | 
			
		||||
    3
 | 
			
		||||
    CACHE STRING "Catch2 library major version requirement")
 | 
			
		||||
set(FSFW_CATCH2_LIB_VERSION
 | 
			
		||||
    v${FSFW_CATCH2_LIB_MAJOR_VERSION}.1.0
 | 
			
		||||
    v${FSFW_CATCH2_LIB_MAJOR_VERSION}.3.2
 | 
			
		||||
    CACHE STRING "Catch2 library exact version requirement")
 | 
			
		||||
 | 
			
		||||
# Keep this off by default for now. See PR:
 | 
			
		||||
@@ -153,12 +153,12 @@ if(FSFW_BUILD_TESTS)
 | 
			
		||||
      "${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
 | 
			
		||||
  )
 | 
			
		||||
  # Check whether the user has already installed Catch2 first
 | 
			
		||||
  find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
 | 
			
		||||
  find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION} QUIET)
 | 
			
		||||
  # Not installed, so use FetchContent to download and provide Catch2
 | 
			
		||||
  if(NOT Catch2_FOUND)
 | 
			
		||||
    message(
 | 
			
		||||
      STATUS
 | 
			
		||||
        "${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent"
 | 
			
		||||
        "${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent."
 | 
			
		||||
    )
 | 
			
		||||
    include(FetchContent)
 | 
			
		||||
 | 
			
		||||
@@ -201,8 +201,8 @@ find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
 | 
			
		||||
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
 | 
			
		||||
  message(
 | 
			
		||||
    STATUS
 | 
			
		||||
      "${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing "
 | 
			
		||||
      "etl with FindPackage")
 | 
			
		||||
      "${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent."
 | 
			
		||||
  )
 | 
			
		||||
  include(FetchContent)
 | 
			
		||||
 | 
			
		||||
  FetchContent_Declare(
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,10 @@ RUN apt-get --yes upgrade
 | 
			
		||||
ARG DEBIAN_FRONTEND=noninteractive
 | 
			
		||||
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping python3 pip doxygen graphviz rsync
 | 
			
		||||
 | 
			
		||||
RUN python3 -m pip install sphinx breathe
 | 
			
		||||
# This should also install Sphinx
 | 
			
		||||
COPY docs/requirements.txt .
 | 
			
		||||
RUN python3 -m pip install -r requirements.txt
 | 
			
		||||
RUN python3 -m pip install breathe
 | 
			
		||||
 | 
			
		||||
RUN git clone https://github.com/catchorg/Catch2.git && \
 | 
			
		||||
        cd Catch2 && \
 | 
			
		||||
@@ -26,4 +29,4 @@ RUN adduser --uid 114 jenkins
 | 
			
		||||
 | 
			
		||||
#add documentation server to known hosts
 | 
			
		||||
RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts
 | 
			
		||||
RUN echo "|1|CcBvBc3EG03G+XM5rqRHs6gK/Gg=|oGeJQ+1I8NGI2THIkJsW92DpTzs= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts
 | 
			
		||||
RUN echo "|1|CcBvBc3EG03G+XM5rqRHs6gK/Gg=|oGeJQ+1I8NGI2THIkJsW92DpTzs= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										118
									
								
								automation/Jenkinsfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										118
									
								
								automation/Jenkinsfile
									
									
									
									
										vendored
									
									
								
							@@ -1,82 +1,130 @@
 | 
			
		||||
pipeline {
 | 
			
		||||
    environment {
 | 
			
		||||
        BUILDDIR = 'cmake-build-tests'
 | 
			
		||||
        BUILDDIR_HOST = 'cmake-build-tests-host'
 | 
			
		||||
        BUILDDIR_LINUX = 'cmake-build-tests-linux'
 | 
			
		||||
        DOCDDIR = 'cmake-build-documentation'
 | 
			
		||||
    }
 | 
			
		||||
    agent {
 | 
			
		||||
        docker { 
 | 
			
		||||
            image 'fsfw-ci:d6'
 | 
			
		||||
            args '--network host'
 | 
			
		||||
            args '--network host --sysctl fs.mqueue.msg_max=100'
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    stages {
 | 
			
		||||
        stage('Clean') {
 | 
			
		||||
            steps {
 | 
			
		||||
                sh 'rm -rf $BUILDDIR'
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        stage('Configure') {
 | 
			
		||||
            steps {
 | 
			
		||||
                dir(BUILDDIR) {
 | 
			
		||||
                    sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
 | 
			
		||||
        stage('Host') {
 | 
			
		||||
            stages{
 | 
			
		||||
                stage('Clean') {
 | 
			
		||||
                    steps {
 | 
			
		||||
                        sh 'rm -rf $BUILDDIR_HOST'
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                stage('Configure') {
 | 
			
		||||
                    steps {
 | 
			
		||||
                        dir(BUILDDIR_HOST) {
 | 
			
		||||
                            sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                stage('Build') {
 | 
			
		||||
                    steps {
 | 
			
		||||
                        dir(BUILDDIR_HOST) {
 | 
			
		||||
                            sh 'cmake --build . -j4'
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                stage('Unittests') {
 | 
			
		||||
                    steps {
 | 
			
		||||
                        dir(BUILDDIR_HOST) {
 | 
			
		||||
                            sh 'cmake --build . -- fsfw-tests_coverage -j4'
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                stage('Valgrind') {
 | 
			
		||||
                    steps {
 | 
			
		||||
                        dir(BUILDDIR_HOST) {
 | 
			
		||||
                            sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        stage('Build') {
 | 
			
		||||
            steps {
 | 
			
		||||
                dir(BUILDDIR) {
 | 
			
		||||
                    sh 'cmake --build . -j4'
 | 
			
		||||
        stage('Linux') {
 | 
			
		||||
            stages{
 | 
			
		||||
                stage('Clean') {
 | 
			
		||||
                    steps {
 | 
			
		||||
                        sh 'rm -rf $BUILDDIR_LINUX'
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        stage('Unittests') {
 | 
			
		||||
            steps {
 | 
			
		||||
                dir(BUILDDIR) {
 | 
			
		||||
                    sh 'cmake --build . -- fsfw-tests_coverage -j4'
 | 
			
		||||
                stage('Configure') {
 | 
			
		||||
                    steps {
 | 
			
		||||
                        dir(BUILDDIR_LINUX) {
 | 
			
		||||
                            sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        stage('Valgrind') {
 | 
			
		||||
            steps {
 | 
			
		||||
                dir(BUILDDIR) {
 | 
			
		||||
                    sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
 | 
			
		||||
                stage('Build') {
 | 
			
		||||
                    steps {
 | 
			
		||||
                        dir(BUILDDIR_LINUX) {
 | 
			
		||||
                            sh 'cmake --build . -j4'
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                stage('Unittests') {
 | 
			
		||||
                    steps {
 | 
			
		||||
                        dir(BUILDDIR_LINUX) {
 | 
			
		||||
                            sh 'cmake --build . -- fsfw-tests_coverage -j4'
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                stage('Valgrind') {
 | 
			
		||||
                    steps {
 | 
			
		||||
                        dir(BUILDDIR_LINUX) {
 | 
			
		||||
                            sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        stage('Documentation') {
 | 
			
		||||
            when {
 | 
			
		||||
                branch 'development'
 | 
			
		||||
              anyOf {
 | 
			
		||||
                branch 'development';
 | 
			
		||||
                branch pattern: 'development-doc-deployment*'
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            steps {
 | 
			
		||||
                dir(DOCDDIR) {
 | 
			
		||||
                    sh 'cmake -DFSFW_BUILD_DOCS=ON -DFSFW_OSAL=host ..'
 | 
			
		||||
                    sh 'make Sphinx'
 | 
			
		||||
                    sshagent(credentials: ['documentation-buildfix']) {
 | 
			
		||||
                        sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/development'
 | 
			
		||||
                        sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/projects/fsfw/development'
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                dir(BUILDDIR) {
 | 
			
		||||
                dir(BUILDDIR_LINUX) {
 | 
			
		||||
                    sshagent(credentials: ['documentation-buildfix']) {
 | 
			
		||||
                        sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/coverage/development'
 | 
			
		||||
                        sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/projects/fsfw/coverage/development'
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        stage('Master Documentation') {
 | 
			
		||||
            when {
 | 
			
		||||
                branch 'master'
 | 
			
		||||
              anyOf {
 | 
			
		||||
                branch 'master';
 | 
			
		||||
                branch pattern: 'master-doc-deployment*'
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            steps {
 | 
			
		||||
                dir(DOCDDIR) {
 | 
			
		||||
                    sh 'cmake -DFSFW_BUILD_DOCS=ON -DFSFW_OSAL=host ..'
 | 
			
		||||
                    sh 'make Sphinx'
 | 
			
		||||
                    sshagent(credentials: ['documentation-buildfix']) {
 | 
			
		||||
                        sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/master'
 | 
			
		||||
                        sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/projects/fsfw/master'
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                dir(BUILDDIR) {
 | 
			
		||||
                dir(BUILDDIR_LINUX) {
 | 
			
		||||
                    sshagent(credentials: ['documentation-buildfix']) {
 | 
			
		||||
                        sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/coverage/master'
 | 
			
		||||
                        sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/projects/fsfw/coverage/master'
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@ project = "Flight Software Framework"
 | 
			
		||||
copyright = "2021, Institute of Space Systems (IRS)"
 | 
			
		||||
author = "Institute of Space Systems (IRS)"
 | 
			
		||||
 | 
			
		||||
# TODO: Should try to read this from CMakeLists.txt automatically..
 | 
			
		||||
# The full version, including alpha/beta/rc tags
 | 
			
		||||
release = "5.0.0"
 | 
			
		||||
 | 
			
		||||
@@ -48,7 +49,7 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
 | 
			
		||||
# The theme to use for HTML and HTML Help pages.  See the documentation for
 | 
			
		||||
# a list of builtin themes.
 | 
			
		||||
#
 | 
			
		||||
html_theme = "alabaster"
 | 
			
		||||
html_theme = "sphinx_rtd_theme"
 | 
			
		||||
 | 
			
		||||
html_theme_options = {
 | 
			
		||||
    "extra_nav_links": {"Impressum" : "https://www.uni-stuttgart.de/impressum", "Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html"}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								docs/requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								docs/requirements.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
sphinx-rtd-theme==1.3.0
 | 
			
		||||
							
								
								
									
										110
									
								
								scripts/check_release.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										110
									
								
								scripts/check_release.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
#! /bin/python
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
import json
 | 
			
		||||
import urllib.request
 | 
			
		||||
import re
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
def main() -> None:
 | 
			
		||||
    parser = argparse.ArgumentParser(
 | 
			
		||||
        description="List undocumented PRs"
 | 
			
		||||
    )
 | 
			
		||||
    parser.add_argument("-v", "--version", type=str, required=True)
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
    
 | 
			
		||||
    match = re.search("([0-9]+\.[0-9]+\.[0-9]+)", args.version)
 | 
			
		||||
    
 | 
			
		||||
    if not match:
 | 
			
		||||
        print("invalid version")
 | 
			
		||||
        exit(1)
 | 
			
		||||
    
 | 
			
		||||
    version = "v" + match.group(1)
 | 
			
		||||
    
 | 
			
		||||
    print("looking for milestone for " + version + " ...")
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/milestones?name=" + version) as milestone_json:
 | 
			
		||||
        milestones = json.load(milestone_json)
 | 
			
		||||
        if (len(milestones) == 0):
 | 
			
		||||
            print("did not find any milestone")
 | 
			
		||||
            exit(1)
 | 
			
		||||
        if (len(milestones) > 1):
 | 
			
		||||
            print("found multiple milestons")
 | 
			
		||||
        milestone_title = milestones[0]['title']
 | 
			
		||||
        milestone = str(milestones[0]['id'])
 | 
			
		||||
        print("Using Milestone \""+ milestone_title + "\" with id " + milestone)
 | 
			
		||||
    
 | 
			
		||||
    milestone_prs = []
 | 
			
		||||
    
 | 
			
		||||
    page = 1
 | 
			
		||||
    last_count = 1;
 | 
			
		||||
    while last_count != 0:
 | 
			
		||||
        with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/pulls?state=closed&milestone=" + str(milestone) + "&limit=100&page=" + str(page)) as pull_requests_json:
 | 
			
		||||
            pull_requests = json.load(pull_requests_json)
 | 
			
		||||
            for pr in pull_requests:
 | 
			
		||||
                milestone_prs.append({'number': str(pr['number']), 'title' : pr['title']})
 | 
			
		||||
            page += 1
 | 
			
		||||
            last_count = len(pull_requests)
 | 
			
		||||
    
 | 
			
		||||
    print("Found " + str(len(milestone_prs)) + " closed PRs in Milestone")
 | 
			
		||||
    
 | 
			
		||||
    print("looking for CHANGELOG.md ...")
 | 
			
		||||
    
 | 
			
		||||
    path = Path(".")
 | 
			
		||||
    
 | 
			
		||||
    files = list(path.glob("CHANGELOG.md"))
 | 
			
		||||
    
 | 
			
		||||
    if (len(files) != 1):
 | 
			
		||||
        files = list(path.glob("../CHANGELOG.md"))
 | 
			
		||||
        
 | 
			
		||||
    if (len(files) != 1):
 | 
			
		||||
        print("did not find CHANGELOG.md. Run script in either root directory or scripts subfolder.")
 | 
			
		||||
        exit(1)
 | 
			
		||||
        
 | 
			
		||||
    print("Scanning CHANGELOG.md ...")
 | 
			
		||||
    
 | 
			
		||||
    changelog_prs = []
 | 
			
		||||
    
 | 
			
		||||
    with open(files[0]) as changelog:
 | 
			
		||||
        line = changelog.readline()
 | 
			
		||||
        while (line):
 | 
			
		||||
            #print("line: " + line)
 | 
			
		||||
            match = re.search("\#.+(v[0-9]+\.[0-9]+\.[0-9]+)", line)
 | 
			
		||||
            if (match):
 | 
			
		||||
                if match.group(1) == version:
 | 
			
		||||
                    #print("found version")
 | 
			
		||||
                    line = changelog.readline()
 | 
			
		||||
                    continue
 | 
			
		||||
                else:
 | 
			
		||||
                    #print("done with " + match.group(1))
 | 
			
		||||
                    break
 | 
			
		||||
            
 | 
			
		||||
            match = re.search("PR: https://egit\.irs\.uni-stuttgart\.de/fsfw/fsfw/pulls/([0-9]+)", line)
 | 
			
		||||
            if match:
 | 
			
		||||
                changelog_prs.append(match.group(1))
 | 
			
		||||
                
 | 
			
		||||
            line = changelog.readline()
 | 
			
		||||
    
 | 
			
		||||
    print("Found " + str(len(changelog_prs)) + " PRs in CHANGELOG.md")
 | 
			
		||||
    
 | 
			
		||||
    print("")
 | 
			
		||||
    
 | 
			
		||||
    copy_array = changelog_prs.copy()
 | 
			
		||||
    print("PRs in CHANGELOG.md that are not in Milestone:")
 | 
			
		||||
    for pr in milestone_prs:
 | 
			
		||||
        if pr['number'] in copy_array:
 | 
			
		||||
            copy_array.remove(pr['number'])
 | 
			
		||||
    for pr in copy_array:
 | 
			
		||||
        print("https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr)
 | 
			
		||||
 | 
			
		||||
    print("")
 | 
			
		||||
 | 
			
		||||
    print("PRs in milestone that are not in CHANGELOG.md:")
 | 
			
		||||
    
 | 
			
		||||
    for pr in milestone_prs:
 | 
			
		||||
        if pr['number'] not in changelog_prs:
 | 
			
		||||
            print("- " + pr['title'] + "\n  PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr['number'])
 | 
			
		||||
 | 
			
		||||
main()
 | 
			
		||||
@@ -59,17 +59,24 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
 | 
			
		||||
 | 
			
		||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
 | 
			
		||||
                                    store_address_t dataAddress) {
 | 
			
		||||
  bool hasAdditionalData = false;
 | 
			
		||||
  const uint8_t* dataPtr = nullptr;
 | 
			
		||||
  size_t size = 0;
 | 
			
		||||
  ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
 | 
			
		||||
  if (result != returnvalue::OK) {
 | 
			
		||||
    CommandMessage reply;
 | 
			
		||||
    ActionMessage::setStepReply(&reply, actionId, 0, result);
 | 
			
		||||
    queueToUse->sendMessage(commandedBy, &reply);
 | 
			
		||||
    return;
 | 
			
		||||
  ReturnValue_t result;
 | 
			
		||||
  if (dataAddress != store_address_t::invalid()) {
 | 
			
		||||
    hasAdditionalData = true;
 | 
			
		||||
    ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
 | 
			
		||||
    if (result != returnvalue::OK) {
 | 
			
		||||
      CommandMessage reply;
 | 
			
		||||
      ActionMessage::setStepReply(&reply, actionId, 0, result);
 | 
			
		||||
      queueToUse->sendMessage(commandedBy, &reply);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  result = owner->executeAction(actionId, commandedBy, dataPtr, size);
 | 
			
		||||
  ipcStore->deleteData(dataAddress);
 | 
			
		||||
  if (hasAdditionalData) {
 | 
			
		||||
    ipcStore->deleteData(dataAddress);
 | 
			
		||||
  }
 | 
			
		||||
  if (result == HasActionsIF::EXECUTION_FINISHED) {
 | 
			
		||||
    CommandMessage reply;
 | 
			
		||||
    ActionMessage::setCompletionReply(&reply, actionId, true, result);
 | 
			
		||||
 
 | 
			
		||||
@@ -16,8 +16,8 @@ class CommandActionHelper {
 | 
			
		||||
 public:
 | 
			
		||||
  explicit CommandActionHelper(CommandsActionsIF* owner);
 | 
			
		||||
  virtual ~CommandActionHelper();
 | 
			
		||||
  ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data,
 | 
			
		||||
                              uint32_t size);
 | 
			
		||||
  ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
 | 
			
		||||
                              const uint8_t* data = nullptr, uint32_t size = 0);
 | 
			
		||||
  ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
 | 
			
		||||
  ReturnValue_t initialize();
 | 
			
		||||
  ReturnValue_t handleReply(CommandMessage* reply);
 | 
			
		||||
 
 | 
			
		||||
@@ -51,8 +51,9 @@ class VarLenField : public SerializeIF {
 | 
			
		||||
    return os;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  using SerializeIF::deSerialize;  // we overloaded above, so this is needed to uncofuse the
 | 
			
		||||
                                   // compiler
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
 | 
			
		||||
                            Endianness streamEndianness) override;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
 | 
			
		||||
  *buffer += 1;
 | 
			
		||||
  **buffer = pduDataFieldLen & 0x00ff;
 | 
			
		||||
  *buffer += 1;
 | 
			
		||||
  **buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
 | 
			
		||||
             pduConf.seqNum.getWidth();
 | 
			
		||||
  **buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) |
 | 
			
		||||
             segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
 | 
			
		||||
  *buffer += 1;
 | 
			
		||||
  *size += 4;
 | 
			
		||||
  ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);
 | 
			
		||||
 
 | 
			
		||||
@@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
 | 
			
		||||
  return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
 | 
			
		||||
  return static_cast<cfdp::WidthInBytes>(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
 | 
			
		||||
  return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
 | 
			
		||||
  return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,8 @@ class EntityIdTlv : public TlvIF {
 | 
			
		||||
   */
 | 
			
		||||
  ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
 | 
			
		||||
 | 
			
		||||
  using SerializeIF::deSerialize;  // we overloaded this function, so this is needed to unconfuse
 | 
			
		||||
                                   // the compiler
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                            Endianness streamEndianness) override;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,8 @@ class FilestoreResponseTlv : public cfdp::FilestoreTlvBase {
 | 
			
		||||
   */
 | 
			
		||||
  ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness);
 | 
			
		||||
 | 
			
		||||
  using SerializeIF::deSerialize;  // we overloaded this function, so this is needed to unconfuse
 | 
			
		||||
                                   // the compiler
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                            Endianness streamEndianness) override;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
 | 
			
		||||
class FixedArrayList : public ArrayList<T, count_t> {
 | 
			
		||||
  static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
 | 
			
		||||
                "count_t is not large enough to hold MAX_SIZE");
 | 
			
		||||
  static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  T data[MAX_SIZE];
 | 
			
		||||
 
 | 
			
		||||
@@ -155,8 +155,8 @@ class FixedMap : public SerializeIF {
 | 
			
		||||
 | 
			
		||||
  uint32_t maxSize() const { return theMap.maxSize(); }
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                                  Endianness streamEndianness) const {
 | 
			
		||||
  ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                          Endianness streamEndianness) const override {
 | 
			
		||||
    ReturnValue_t result =
 | 
			
		||||
        SerializeAdapter::serialize(&this->_size, buffer, size, maxSize, streamEndianness);
 | 
			
		||||
    uint32_t i = 0;
 | 
			
		||||
@@ -170,7 +170,7 @@ class FixedMap : public SerializeIF {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual size_t getSerializedSize() const {
 | 
			
		||||
  size_t getSerializedSize() const override {
 | 
			
		||||
    uint32_t printSize = sizeof(_size);
 | 
			
		||||
    uint32_t i = 0;
 | 
			
		||||
 | 
			
		||||
@@ -182,8 +182,8 @@ class FixedMap : public SerializeIF {
 | 
			
		||||
    return printSize;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                                    Endianness streamEndianness) {
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                            Endianness streamEndianness) override {
 | 
			
		||||
    ReturnValue_t result =
 | 
			
		||||
        SerializeAdapter::deSerialize(&this->_size, buffer, size, streamEndianness);
 | 
			
		||||
    if (this->_size > theMap.maxSize()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -64,8 +64,8 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
 | 
			
		||||
   * - @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;
 | 
			
		||||
  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
 | 
			
		||||
@@ -84,15 +84,15 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
 | 
			
		||||
   * 			- @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;
 | 
			
		||||
  ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
 | 
			
		||||
                       uint32_t lockTimeout = 20) override;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Register the passed pool variable instance into the data set.
 | 
			
		||||
   * @param variable
 | 
			
		||||
   * @return
 | 
			
		||||
   */
 | 
			
		||||
  virtual ReturnValue_t registerVariable(PoolVariableIF* variable) override;
 | 
			
		||||
  ReturnValue_t registerVariable(PoolVariableIF* variable) override;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Provides the means to lock the underlying data structure to ensure
 | 
			
		||||
 
 | 
			
		||||
@@ -87,9 +87,9 @@ class LocalPoolVariable : public LocalPoolObjectBase {
 | 
			
		||||
 | 
			
		||||
  ReturnValue_t serialize(uint8_t** buffer, size_t* size, 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;
 | 
			
		||||
  size_t getSerializedSize() const override;
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                            SerializeIF::Endianness streamEndianness) override;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief	This is a call to read the array's values
 | 
			
		||||
 
 | 
			
		||||
@@ -98,11 +98,11 @@ class LocalPoolVector : public LocalPoolObjectBase {
 | 
			
		||||
  T& operator[](size_t i);
 | 
			
		||||
  const T& operator[](size_t i) const;
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
 | 
			
		||||
                                  SerializeIF::Endianness streamEndiannes) const override;
 | 
			
		||||
  virtual size_t getSerializedSize() const override;
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                                    SerializeIF::Endianness streamEndianness) override;
 | 
			
		||||
  ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
 | 
			
		||||
                          SerializeIF::Endianness streamEndiannes) const override;
 | 
			
		||||
  size_t getSerializedSize() const override;
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                            SerializeIF::Endianness streamEndianness) override;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief	This is a call to read the array's values
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
 | 
			
		||||
 | 
			
		||||
#include "fsfw/datapool/PoolReadGuard.h"
 | 
			
		||||
#include "fsfw/datapoollocal/LocalPoolVariable.h"
 | 
			
		||||
#include "fsfw/devicehandlers/AcceptsDeviceResponsesIF.h"
 | 
			
		||||
#include "fsfw/devicehandlers/DeviceTmReportingWrapper.h"
 | 
			
		||||
@@ -1508,7 +1509,10 @@ DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
 | 
			
		||||
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
 | 
			
		||||
  for (const auto& reply : deviceReplyMap) {
 | 
			
		||||
    if (reply.second.dataSet != nullptr) {
 | 
			
		||||
      reply.second.dataSet->setValidity(false, true);
 | 
			
		||||
      PoolReadGuard pg(reply.second.dataSet);
 | 
			
		||||
      if (pg.getReadResult() == returnvalue::OK) {
 | 
			
		||||
        reply.second.dataSet->setValidity(false, true);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,14 +15,16 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
 | 
			
		||||
    {fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)},
 | 
			
		||||
    {fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}};
 | 
			
		||||
 | 
			
		||||
EventManager::EventManager(object_id_t setObjectId)
 | 
			
		||||
EventManager::EventManager(object_id_t setObjectId, uint32_t eventQueueDepth)
 | 
			
		||||
    : SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
 | 
			
		||||
  mutex = MutexFactory::instance()->createMutex();
 | 
			
		||||
  eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
 | 
			
		||||
                                                                  EventMessage::EVENT_MESSAGE_SIZE);
 | 
			
		||||
  auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
 | 
			
		||||
  eventReportQueue = QueueFactory::instance()->createMessageQueue(
 | 
			
		||||
      eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EventManager::~EventManager() {
 | 
			
		||||
  listenerList.clear();
 | 
			
		||||
  QueueFactory::instance()->deleteMessageQueue(eventReportQueue);
 | 
			
		||||
  MutexFactory::instance()->deleteMutex(mutex);
 | 
			
		||||
}
 | 
			
		||||
@@ -46,9 +48,20 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
 | 
			
		||||
 | 
			
		||||
void EventManager::notifyListeners(EventMessage* message) {
 | 
			
		||||
  lockMutex();
 | 
			
		||||
  for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
 | 
			
		||||
    if (iter->second.match(message)) {
 | 
			
		||||
      MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender());
 | 
			
		||||
  for (auto& listener : listenerList) {
 | 
			
		||||
    if (listener.second.match(message)) {
 | 
			
		||||
      ReturnValue_t result =
 | 
			
		||||
          MessageQueueSenderIF::sendMessage(listener.first, message, message->getSender());
 | 
			
		||||
      if (result != returnvalue::OK) {
 | 
			
		||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
 | 
			
		||||
        sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
 | 
			
		||||
                   << std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
 | 
			
		||||
                   << result << std::setfill(' ') << std::endl;
 | 
			
		||||
#else
 | 
			
		||||
        sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
 | 
			
		||||
                        listener.first, result);
 | 
			
		||||
#endif
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  unlockMutex();
 | 
			
		||||
@@ -61,9 +74,14 @@ ReturnValue_t EventManager::registerListener(MessageQueueId_t listener,
 | 
			
		||||
  if (!result.second) {
 | 
			
		||||
    return returnvalue::FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return returnvalue::OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t EventManager::unregisterListener(MessageQueueId_t listener) {
 | 
			
		||||
  return listenerList.erase(listener) == 1 ? returnvalue::OK : returnvalue::FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t EventManager::subscribeToEvent(MessageQueueId_t listener, EventId_t event) {
 | 
			
		||||
  return subscribeToEventRange(listener, event);
 | 
			
		||||
}
 | 
			
		||||
@@ -194,4 +212,19 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EventManager::printListeners() {
 | 
			
		||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
 | 
			
		||||
  sif::info << "Event manager listener MQ IDs:" << std::setfill('0') << std::hex << std::endl;
 | 
			
		||||
  for (auto& listener : listenerList) {
 | 
			
		||||
    sif::info << "0x" << std::setw(8) << listener.first << std::endl;
 | 
			
		||||
  }
 | 
			
		||||
  sif::info << std::dec << std::setfill(' ');
 | 
			
		||||
#else
 | 
			
		||||
  sif::printInfo("Event manager listener MQ IDs:\n");
 | 
			
		||||
  for (auto& listener : listenerList) {
 | 
			
		||||
    sif::printInfo("0x%08x\n", listener.first);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */
 | 
			
		||||
 
 | 
			
		||||
@@ -21,9 +21,7 @@ extern const char* translateEvents(Event event);
 | 
			
		||||
 | 
			
		||||
class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject {
 | 
			
		||||
 public:
 | 
			
		||||
  static const uint16_t MAX_EVENTS_PER_CYCLE = 80;
 | 
			
		||||
 | 
			
		||||
  EventManager(object_id_t setObjectId);
 | 
			
		||||
  EventManager(object_id_t setObjectId, uint32_t eventQueueDepth);
 | 
			
		||||
  virtual ~EventManager();
 | 
			
		||||
 | 
			
		||||
  void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
 | 
			
		||||
@@ -31,6 +29,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
 | 
			
		||||
  MessageQueueId_t getEventReportQueue();
 | 
			
		||||
 | 
			
		||||
  ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false);
 | 
			
		||||
  ReturnValue_t unregisterListener(MessageQueueId_t listener) override;
 | 
			
		||||
  ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event);
 | 
			
		||||
  ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object);
 | 
			
		||||
  ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,
 | 
			
		||||
@@ -43,6 +42,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
 | 
			
		||||
                                          object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
 | 
			
		||||
                                          bool reporterInverted = false);
 | 
			
		||||
  ReturnValue_t performOperation(uint8_t opCode);
 | 
			
		||||
  void printListeners();
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  MessageQueueIF* eventReportQueue = nullptr;
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ class EventManagerIF {
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t registerListener(MessageQueueId_t listener,
 | 
			
		||||
                                         bool forwardAllButSelected = false) = 0;
 | 
			
		||||
  virtual ReturnValue_t unregisterListener(MessageQueueId_t listener) = 0;
 | 
			
		||||
  virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event) = 0;
 | 
			
		||||
  virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) = 0;
 | 
			
		||||
  virtual ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ enum : uint8_t {
 | 
			
		||||
  CDH = 28,
 | 
			
		||||
  TCS_1 = 59,
 | 
			
		||||
  PCDU_1 = 42,
 | 
			
		||||
  PCDU_2 = 43,
 | 
			
		||||
  POWER_SWITCH_IF = 43,
 | 
			
		||||
  HEATER = 50,
 | 
			
		||||
  T_SENSORS = 52,
 | 
			
		||||
  FDIR = 70,
 | 
			
		||||
@@ -33,6 +33,7 @@ enum : uint8_t {
 | 
			
		||||
  PUS_SERVICE_23 = 103,
 | 
			
		||||
  MGM_LIS3MDL = 106,
 | 
			
		||||
  MGM_RM3100 = 107,
 | 
			
		||||
  CFDP = 108,
 | 
			
		||||
 | 
			
		||||
  FW_SUBSYSTEM_ID_RANGE
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ FailureIsolationBase::~FailureIsolationBase() {
 | 
			
		||||
#endif
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  manager->unsubscribeFromAllEvents(eventQueue->getId(), ownerId);
 | 
			
		||||
  manager->unregisterListener(eventQueue->getId());
 | 
			
		||||
  QueueFactory::instance()->deleteMessageQueue(eventQueue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -44,13 +44,13 @@ class Type : public SerializeIF {
 | 
			
		||||
 | 
			
		||||
  static ActualType_t getActualType(uint8_t ptc, uint8_t pfc);
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
 | 
			
		||||
                                  Endianness streamEndianness) const override;
 | 
			
		||||
  ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
 | 
			
		||||
                          Endianness streamEndianness) const override;
 | 
			
		||||
 | 
			
		||||
  virtual size_t getSerializedSize() const override;
 | 
			
		||||
  size_t getSerializedSize() const override;
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
 | 
			
		||||
                                    Endianness streamEndianness) override;
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
 | 
			
		||||
                            Endianness streamEndianness) override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  ActualType_t actualType;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
 | 
			
		||||
  MatchTree(iterator root, uint8_t maxDepth = -1)
 | 
			
		||||
      : BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
 | 
			
		||||
  MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
 | 
			
		||||
  virtual ~MatchTree() {}
 | 
			
		||||
  virtual ~MatchTree() { clear(); }
 | 
			
		||||
  virtual bool match(T number) override { return matchesTree(number); }
 | 
			
		||||
  bool matchesTree(T number) {
 | 
			
		||||
    iterator iter = this->begin();
 | 
			
		||||
@@ -176,6 +176,45 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
 | 
			
		||||
    return cleanUpElement(position);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void clear() {
 | 
			
		||||
    Node* localRoot = BinaryTree<SerializeableMatcherIF<T>>::rootNode;
 | 
			
		||||
 | 
			
		||||
    if (localRoot == nullptr) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Node* node = localRoot->left;
 | 
			
		||||
 | 
			
		||||
    while (true) {
 | 
			
		||||
      if (node->left != nullptr) {
 | 
			
		||||
        node = node->left;
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      if (node->right != nullptr) {
 | 
			
		||||
        node = node->right;
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      if (node->parent == nullptr) {
 | 
			
		||||
        // this is the root node with no children
 | 
			
		||||
        if (node->value != nullptr) {
 | 
			
		||||
          cleanUpElement(iterator(node));
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      // leaf
 | 
			
		||||
      {
 | 
			
		||||
        Node* parent = node->parent;
 | 
			
		||||
        if (parent->left == node) {
 | 
			
		||||
          parent->left = nullptr;
 | 
			
		||||
        } else {
 | 
			
		||||
          parent->right = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        cleanUpElement(iterator(node));
 | 
			
		||||
        node = parent;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t cleanUpElement(iterator position) { return returnvalue::OK; }
 | 
			
		||||
 | 
			
		||||
  bool matchSubtree(iterator iter, T number) {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,26 +16,24 @@ class HasHealthIF {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
 | 
			
		||||
  static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
 | 
			
		||||
  static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2);
 | 
			
		||||
  static constexpr ReturnValue_t OBJECT_NOT_HEALTHY = returnvalue::makeCode(INTERFACE_ID, 1);
 | 
			
		||||
  static constexpr ReturnValue_t INVALID_HEALTH_STATE = returnvalue::makeCode(INTERFACE_ID, 2);
 | 
			
		||||
  static constexpr ReturnValue_t IS_EXTERNALLY_CONTROLLED = returnvalue::makeCode(INTERFACE_ID, 3);
 | 
			
		||||
 | 
			
		||||
  static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1;
 | 
			
		||||
  //! P1: New Health, P2: Old Health
 | 
			
		||||
  static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
 | 
			
		||||
  static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
 | 
			
		||||
  static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
 | 
			
		||||
  static const Event OVERWRITING_HEALTH =
 | 
			
		||||
      MAKE_EVENT(9, severity::LOW);  //!< Assembly overwrites health information of children to keep
 | 
			
		||||
                                     //!< satellite alive.
 | 
			
		||||
  static const Event TRYING_RECOVERY =
 | 
			
		||||
      MAKE_EVENT(10, severity::MEDIUM);  //!< Someone starts a recovery of a component (typically
 | 
			
		||||
                                         //!< power-cycle). No parameters.
 | 
			
		||||
  static const Event RECOVERY_STEP =
 | 
			
		||||
      MAKE_EVENT(11, severity::MEDIUM);  //!< Recovery is ongoing. Comes twice during recovery. P1:
 | 
			
		||||
                                         //!< 0 for the first, 1 for the second event. P2: 0
 | 
			
		||||
  static const Event RECOVERY_DONE = MAKE_EVENT(
 | 
			
		||||
      12,
 | 
			
		||||
      severity::MEDIUM);  //!< Recovery was completed. Not necessarily successful. No parameters.
 | 
			
		||||
 | 
			
		||||
  //! Assembly overwrites health information of children to keep satellite alive.
 | 
			
		||||
  static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW);
 | 
			
		||||
  //! Someone starts a recovery of a component (typically power-cycle). No parameters.
 | 
			
		||||
  static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM);
 | 
			
		||||
  //! Recovery is ongoing. Comes twice during recovery.
 | 
			
		||||
  //! P1: 0 for the first, 1 for the second event. P2: 0
 | 
			
		||||
  static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM);
 | 
			
		||||
  //! Recovery was completed. Not necessarily successful. No parameters.
 | 
			
		||||
  static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM);
 | 
			
		||||
  virtual ~HasHealthIF() {}
 | 
			
		||||
 | 
			
		||||
  virtual MessageQueueId_t getCommandQueue() const = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,6 @@
 | 
			
		||||
 | 
			
		||||
HealthTable::HealthTable(object_id_t objectid) : SystemObject(objectid) {
 | 
			
		||||
  mutex = MutexFactory::instance()->createMutex();
 | 
			
		||||
  ;
 | 
			
		||||
 | 
			
		||||
  mapIterator = healthMap.begin();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,8 @@
 | 
			
		||||
#include "HealthTableIF.h"
 | 
			
		||||
 | 
			
		||||
class HealthTable : public HealthTableIF, public SystemObject {
 | 
			
		||||
  friend class CServiceHealthCommanding;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  explicit HealthTable(object_id_t objectid);
 | 
			
		||||
  ~HealthTable() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -54,8 +54,8 @@ class HousekeepingSnapshot : public SerializeIF {
 | 
			
		||||
  HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize, LocalPoolObjectBase* dataSetPtr)
 | 
			
		||||
      : timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr){};
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                                  Endianness streamEndianness) const {
 | 
			
		||||
  ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                          Endianness streamEndianness) const {
 | 
			
		||||
    if (timeStamp != nullptr) {
 | 
			
		||||
      /* Endianness will always be MACHINE, so we can simply use memcpy
 | 
			
		||||
      here. */
 | 
			
		||||
@@ -70,15 +70,15 @@ class HousekeepingSnapshot : public SerializeIF {
 | 
			
		||||
    return updateData->serialize(buffer, size, maxSize, streamEndianness);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual size_t getSerializedSize() const {
 | 
			
		||||
  size_t getSerializedSize() const {
 | 
			
		||||
    if (updateData == nullptr) {
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
    return timeStampSize + updateData->getSerializedSize();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                                    SerializeIF::Endianness streamEndianness) override {
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                            SerializeIF::Endianness streamEndianness) override {
 | 
			
		||||
    if (*size < timeStampSize) {
 | 
			
		||||
      return SerializeIF::STREAM_TOO_SHORT;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -7,14 +7,17 @@
 | 
			
		||||
 | 
			
		||||
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
 | 
			
		||||
    : SystemObject(setObjectId),
 | 
			
		||||
      commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
 | 
			
		||||
      poolManager(this, commandQueue),
 | 
			
		||||
      internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
 | 
			
		||||
      internalErrorDataset(this) {
 | 
			
		||||
  commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
 | 
			
		||||
  mutex = MutexFactory::instance()->createMutex();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
 | 
			
		||||
InternalErrorReporter::~InternalErrorReporter() {
 | 
			
		||||
  MutexFactory::instance()->deleteMutex(mutex);
 | 
			
		||||
  QueueFactory::instance()->deleteMessageQueue(commandQueue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
 | 
			
		||||
  this->diagnosticPrintout = enable;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,3 +24,19 @@ void ModeMessage::setCantReachMode(CommandMessage* message, ReturnValue_t reason
 | 
			
		||||
  message->setParameter(reason);
 | 
			
		||||
  message->setParameter2(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModeMessage::setModeAnnounceMessage(CommandMessage& message, bool recursive) {
 | 
			
		||||
  Command_t cmd;
 | 
			
		||||
  if (recursive) {
 | 
			
		||||
    cmd = CMD_MODE_ANNOUNCE_RECURSIVELY;
 | 
			
		||||
  } else {
 | 
			
		||||
    cmd = CMD_MODE_ANNOUNCE;
 | 
			
		||||
  }
 | 
			
		||||
  message.setCommand(cmd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModeMessage::setCmdModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode) {
 | 
			
		||||
  setModeMessage(&message, CMD_MODE_COMMAND, mode, submode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModeMessage::setModeReadMessage(CommandMessage& message) { message.setCommand(CMD_MODE_READ); }
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,9 @@ class ModeMessage {
 | 
			
		||||
 | 
			
		||||
  static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
 | 
			
		||||
                             Submode_t submode);
 | 
			
		||||
  static void setCmdModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode);
 | 
			
		||||
  static void setModeAnnounceMessage(CommandMessage& message, bool recursive);
 | 
			
		||||
  static void setModeReadMessage(CommandMessage& message);
 | 
			
		||||
  static void setCantReachMode(CommandMessage* message, ReturnValue_t reason);
 | 
			
		||||
  static void clear(CommandMessage* message);
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -32,9 +32,9 @@ class AbsLimitMonitor : public MonitorBase<T> {
 | 
			
		||||
    return returnvalue::OK;  // We're not out of range.
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
 | 
			
		||||
                                     ParameterWrapper *parameterWrapper,
 | 
			
		||||
                                     const ParameterWrapper *newValues, uint16_t startAtIndex) {
 | 
			
		||||
  ReturnValue_t getParameter(uint8_t domainId, uint8_t parameterId,
 | 
			
		||||
                             ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
 | 
			
		||||
                             uint16_t startAtIndex) override {
 | 
			
		||||
    ReturnValue_t result = this->MonitorBase<T>::getParameter(
 | 
			
		||||
        domainId, parameterId, parameterWrapper, newValues, startAtIndex);
 | 
			
		||||
    // We'll reuse the DOMAIN_ID of MonitorReporter,
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ class MonitoringMessage : public CommandMessage {
 | 
			
		||||
  static const Command_t LIMIT_VIOLATION_REPORT = MAKE_COMMAND_ID(10);
 | 
			
		||||
  virtual ~MonitoringMessage();
 | 
			
		||||
  static void setLimitViolationReport(CommandMessage* message, store_address_t storeId);
 | 
			
		||||
  using CommandMessage::clear;
 | 
			
		||||
  static void clear(CommandMessage* message);
 | 
			
		||||
  static store_address_t getStoreId(const CommandMessage* message);
 | 
			
		||||
  static void setTypicalMessage(CommandMessage* message, Command_t type, store_address_t storeId);
 | 
			
		||||
 
 | 
			
		||||
@@ -23,9 +23,17 @@ void ObjectManager::setObjectFactoryFunction(produce_function_t objFactoryFunc,
 | 
			
		||||
 | 
			
		||||
ObjectManager::ObjectManager() = default;
 | 
			
		||||
 | 
			
		||||
void ObjectManager::clear() {
 | 
			
		||||
  if (objManagerInstance != nullptr) {
 | 
			
		||||
    delete objManagerInstance;
 | 
			
		||||
    objManagerInstance = nullptr;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ObjectManager::~ObjectManager() {
 | 
			
		||||
  for (auto const& iter : objectList) {
 | 
			
		||||
    delete iter.second;
 | 
			
		||||
  teardown = true;
 | 
			
		||||
  for (auto iter = objectList.begin(); iter != objectList.end(); iter = objectList.erase(iter)) {
 | 
			
		||||
    delete iter->second;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -53,6 +61,12 @@ ReturnValue_t ObjectManager::insert(object_id_t id, SystemObjectIF* object) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t ObjectManager::remove(object_id_t id) {
 | 
			
		||||
  // this function is called during destruction of System Objects
 | 
			
		||||
  // disabeld for teardown to avoid iterator invalidation and
 | 
			
		||||
  // double free
 | 
			
		||||
  if (teardown) {
 | 
			
		||||
    return returnvalue::OK;
 | 
			
		||||
  }
 | 
			
		||||
  if (this->getSystemObject(id) != nullptr) {
 | 
			
		||||
    this->objectList.erase(id);
 | 
			
		||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
 | 
			
		||||
 
 | 
			
		||||
@@ -24,12 +24,17 @@ class ObjectManager : public ObjectManagerIF {
 | 
			
		||||
  using produce_function_t = void (*)(void* args);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns the single instance of TaskFactory.
 | 
			
		||||
   * Returns the single instance of ObjectManager.
 | 
			
		||||
   * The implementation of #instance is found in its subclasses.
 | 
			
		||||
   * Thus, we choose link-time variability of the  instance.
 | 
			
		||||
   */
 | 
			
		||||
  static ObjectManager* instance();
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Deletes the single instance of ObjectManager
 | 
			
		||||
   */
 | 
			
		||||
  static void clear();
 | 
			
		||||
 | 
			
		||||
  void setObjectFactoryFunction(produce_function_t prodFunc, void* args);
 | 
			
		||||
 | 
			
		||||
  template <typename T>
 | 
			
		||||
@@ -66,6 +71,9 @@ class ObjectManager : public ObjectManagerIF {
 | 
			
		||||
   */
 | 
			
		||||
  std::map<object_id_t, SystemObjectIF*> objectList;
 | 
			
		||||
  static ObjectManager* objManagerInstance;
 | 
			
		||||
  // used when the OM itself is deleted to modify behaviour of remove()
 | 
			
		||||
  // to avoid iterator invalidation and double free
 | 
			
		||||
  bool teardown = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Documentation can be found in the class method declaration above
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ enum framework_objects : object_id_t {
 | 
			
		||||
  PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
 | 
			
		||||
  PUS_SERVICE_9_TIME_MGMT = 0x53000009,
 | 
			
		||||
  PUS_SERVICE_11_TC_SCHEDULER = 0x53000011,
 | 
			
		||||
  PUS_SERVICE_15_TM_STORAGE = 0x53000015,
 | 
			
		||||
  PUS_SERVICE_17_TEST = 0x53000017,
 | 
			
		||||
  PUS_SERVICE_20_PARAMETERS = 0x53000020,
 | 
			
		||||
  PUS_SERVICE_200_MODE_MGMT = 0x53000200,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,13 @@
 | 
			
		||||
# Check the OS_FSFW variable
 | 
			
		||||
if(FSFW_OSAL MATCHES "freertos")
 | 
			
		||||
  add_subdirectory(freertos)
 | 
			
		||||
  set(FSFW_OSAL_FREERTOS 1)
 | 
			
		||||
elseif(FSFW_OSAL MATCHES "rtems")
 | 
			
		||||
  add_subdirectory(rtems)
 | 
			
		||||
  set(FSFW_OSAL_RTEMS 1)
 | 
			
		||||
elseif(FSFW_OSAL MATCHES "linux")
 | 
			
		||||
  add_subdirectory(linux)
 | 
			
		||||
  set(FSFW_OSAL_LINUX 1)
 | 
			
		||||
elseif(FSFW_OSAL MATCHES "host")
 | 
			
		||||
  add_subdirectory(host)
 | 
			
		||||
  if(WIN32)
 | 
			
		||||
@@ -13,16 +16,20 @@ elseif(FSFW_OSAL MATCHES "host")
 | 
			
		||||
    # We still need to pull in some Linux specific sources
 | 
			
		||||
    target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp)
 | 
			
		||||
  endif()
 | 
			
		||||
 | 
			
		||||
  set(FSFW_OSAL_HOST 1)
 | 
			
		||||
else()
 | 
			
		||||
  message(
 | 
			
		||||
    WARNING
 | 
			
		||||
      "${MSG_PREFIX} The FSFW_OSAL variable was not set. Assuming host OS..")
 | 
			
		||||
 | 
			
		||||
  message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
 | 
			
		||||
  # Not set. Assumuing this is a host build, try to determine host OS
 | 
			
		||||
  if(WIN32)
 | 
			
		||||
    add_subdirectory(host)
 | 
			
		||||
    add_subdirectory(windows)
 | 
			
		||||
    set(FSFW_OSAL_HOST 1)
 | 
			
		||||
  elseif(UNIX)
 | 
			
		||||
    add_subdirectory(linux)
 | 
			
		||||
    set(FSFW_OSAL_LINUX 1)
 | 
			
		||||
  else()
 | 
			
		||||
    # MacOS or other OSes have not been tested yet / are not supported.
 | 
			
		||||
    message(FATAL_ERROR "The host OS could not be determined! Aborting.")
 | 
			
		||||
@@ -31,3 +38,5 @@ else()
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
add_subdirectory(common)
 | 
			
		||||
 | 
			
		||||
configure_file(osal.h.in ${CMAKE_BINARY_DIR}/fsfw/osal/osal.h)
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,8 @@ int TcpIpBase::closeSocket(socket_t socket) {
 | 
			
		||||
  return closesocket(socket);
 | 
			
		||||
#elif defined(PLATFORM_UNIX)
 | 
			
		||||
  return close(socket);
 | 
			
		||||
#else
 | 
			
		||||
  return -1;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -48,5 +50,7 @@ int TcpIpBase::getLastSocketError() {
 | 
			
		||||
  return WSAGetLastError();
 | 
			
		||||
#elif defined(PLATFORM_UNIX)
 | 
			
		||||
  return errno;
 | 
			
		||||
#else
 | 
			
		||||
  return 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,9 +16,9 @@
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId,
 | 
			
		||||
                             object_id_t tcStoreId)
 | 
			
		||||
    : TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, tmStoreId, tcStoreId) {
 | 
			
		||||
TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
 | 
			
		||||
                             uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId)
 | 
			
		||||
    : TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
 | 
			
		||||
  mutex = MutexFactory::instance()->createMutex();
 | 
			
		||||
  // Connection is always up, TM is requested by connecting to server and receiving packets
 | 
			
		||||
  registerCommConnect();
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ class TcpTmTcBridge : public TmTcBridge {
 | 
			
		||||
   * @param tmStoreId TM store object ID. It is recommended to the default object ID
 | 
			
		||||
   * @param tcStoreId TC store object ID. It is recommended to the default object ID
 | 
			
		||||
   */
 | 
			
		||||
  TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
 | 
			
		||||
  TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, uint32_t msgQueueDepth,
 | 
			
		||||
                object_id_t tmStoreId = objects::TM_STORE,
 | 
			
		||||
                object_id_t tcStoreId = objects::TC_STORE);
 | 
			
		||||
  virtual ~TcpTmTcBridge();
 | 
			
		||||
 
 | 
			
		||||
@@ -26,12 +26,12 @@
 | 
			
		||||
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
 | 
			
		||||
 | 
			
		||||
TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
 | 
			
		||||
                             size_t receptionBufferSize, size_t ringBufferSize,
 | 
			
		||||
                             std::string customTcpServerPort, ReceptionModes receptionMode)
 | 
			
		||||
                             TcpTmTcServer::TcpConfig cfg, size_t receptionBufferSize,
 | 
			
		||||
                             size_t ringBufferSize, ReceptionModes receptionMode)
 | 
			
		||||
    : SystemObject(objectId),
 | 
			
		||||
      tmtcBridgeId(tmtcTcpBridge),
 | 
			
		||||
      receptionMode(receptionMode),
 | 
			
		||||
      tcpConfig(std::move(customTcpServerPort)),
 | 
			
		||||
      tcpConfig(cfg),
 | 
			
		||||
      receptionBuffer(receptionBufferSize),
 | 
			
		||||
      ringBuffer(ringBufferSize, true) {}
 | 
			
		||||
 | 
			
		||||
@@ -91,6 +91,15 @@ ReturnValue_t TcpTmTcServer::initialize() {
 | 
			
		||||
    return returnvalue::FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (tcpConfig.reuseAddr) {
 | 
			
		||||
    unsigned int enable = 1;
 | 
			
		||||
    setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
 | 
			
		||||
  }
 | 
			
		||||
  if (tcpConfig.reusePort) {
 | 
			
		||||
    unsigned int enable = 1;
 | 
			
		||||
    setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Bind to the address found by getaddrinfo
 | 
			
		||||
  retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
 | 
			
		||||
  if (retval == SOCKET_ERROR) {
 | 
			
		||||
 
 | 
			
		||||
@@ -41,11 +41,11 @@ class SpacePacketParser;
 | 
			
		||||
 */
 | 
			
		||||
class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableObjectIF {
 | 
			
		||||
 public:
 | 
			
		||||
  enum class ReceptionModes { SPACE_PACKETS };
 | 
			
		||||
 | 
			
		||||
  struct TcpConfig {
 | 
			
		||||
   public:
 | 
			
		||||
    explicit TcpConfig(std::string tcpPort) : tcpPort(std::move(tcpPort)) {}
 | 
			
		||||
    TcpConfig(bool reuseAddr, bool reusePort) : reuseAddr(reuseAddr), reusePort(reusePort) {}
 | 
			
		||||
    TcpConfig(std::string tcpPort, bool reuseAddr, bool reusePort)
 | 
			
		||||
        : tcpPort(std::move(tcpPort)), reuseAddr(reuseAddr), reusePort(reusePort) {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Passed to the recv call
 | 
			
		||||
@@ -63,8 +63,23 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
 | 
			
		||||
     */
 | 
			
		||||
    int tcpTmFlags = 0;
 | 
			
		||||
 | 
			
		||||
    const std::string tcpPort;
 | 
			
		||||
    std::string tcpPort = DEFAULT_SERVER_PORT;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the SO_REUSEADDR option on the socket. See
 | 
			
		||||
     * https://man7.org/linux/man-pages/man7/socket.7.html for more details. This option is
 | 
			
		||||
     * especially useful in a debugging and development environment where an OBSW image might be
 | 
			
		||||
     * re-flashed oftentimes and where all incoming telecommands are received on a dedicated TCP
 | 
			
		||||
     * port.
 | 
			
		||||
     */
 | 
			
		||||
    bool reuseAddr = false;
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the SO_REUSEPORT option on the socket. See
 | 
			
		||||
     * https://man7.org/linux/man-pages/man7/socket.7.html for more details.
 | 
			
		||||
     */
 | 
			
		||||
    bool reusePort = false;
 | 
			
		||||
  };
 | 
			
		||||
  enum class ReceptionModes { SPACE_PACKETS };
 | 
			
		||||
 | 
			
		||||
  static const std::string DEFAULT_SERVER_PORT;
 | 
			
		||||
 | 
			
		||||
@@ -80,10 +95,9 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
 | 
			
		||||
   *                              size will be the Ethernet MTU size
 | 
			
		||||
   * @param customTcpServerPort   The user can specify another port than the default (7301) here.
 | 
			
		||||
   */
 | 
			
		||||
  TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
 | 
			
		||||
  TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, TcpTmTcServer::TcpConfig cfg,
 | 
			
		||||
                size_t receptionBufferSize = RING_BUFFER_SIZE,
 | 
			
		||||
                size_t ringBufferSize = RING_BUFFER_SIZE,
 | 
			
		||||
                std::string customTcpServerPort = DEFAULT_SERVER_PORT,
 | 
			
		||||
                ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
 | 
			
		||||
  ~TcpTmTcServer() override;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,9 +20,9 @@
 | 
			
		||||
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
 | 
			
		||||
 | 
			
		||||
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
 | 
			
		||||
                             const std::string &udpServerPort_, object_id_t tmStoreId,
 | 
			
		||||
                             object_id_t tcStoreId)
 | 
			
		||||
    : TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, tmStoreId, tcStoreId) {
 | 
			
		||||
                             uint32_t msgQueueDepth, const std::string &udpServerPort_,
 | 
			
		||||
                             object_id_t tmStoreId, object_id_t tcStoreId)
 | 
			
		||||
    : TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
 | 
			
		||||
  if (udpServerPort_.empty()) {
 | 
			
		||||
    udpServerPort = DEFAULT_SERVER_PORT;
 | 
			
		||||
  } else {
 | 
			
		||||
@@ -126,10 +126,7 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
 | 
			
		||||
    tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL);
 | 
			
		||||
  }
 | 
			
		||||
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
 | 
			
		||||
  sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent
 | 
			
		||||
             << " bytes were"
 | 
			
		||||
                " sent."
 | 
			
		||||
             << std::endl;
 | 
			
		||||
  sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent << " bytes were sent" << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
  return returnvalue::OK;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
 | 
			
		||||
  /* The ports chosen here should not be used by any other process. */
 | 
			
		||||
  static const std::string DEFAULT_SERVER_PORT;
 | 
			
		||||
 | 
			
		||||
  UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
 | 
			
		||||
  UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, uint32_t msgQueueDepth,
 | 
			
		||||
                const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE,
 | 
			
		||||
                object_id_t tcStoreId = objects::TC_STORE);
 | 
			
		||||
  ~UdpTmTcBridge() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
#include <condition_variable>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
 | 
			
		||||
#include "fsfw/tasks/FixedSlotSequence.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
#include <condition_variable>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
 | 
			
		||||
#include "fsfw/tasks/PeriodicTaskBase.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
#include <fsfw/returnvalues/returnvalue.h>
 | 
			
		||||
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace tasks {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -76,14 +76,17 @@ timeval Clock::getUptime() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t Clock::getUptime(timeval* uptime) {
 | 
			
		||||
  // TODO This is not posix compatible and delivers only seconds precision
 | 
			
		||||
  //  Linux specific file read but more precise.
 | 
			
		||||
  double uptimeSeconds;
 | 
			
		||||
  if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) {
 | 
			
		||||
  std::ifstream ifile("/proc/uptime");
 | 
			
		||||
  if (ifile.bad()) {
 | 
			
		||||
    return returnvalue::FAILED;
 | 
			
		||||
  }
 | 
			
		||||
  if (ifile >> uptimeSeconds) {
 | 
			
		||||
    uptime->tv_sec = uptimeSeconds;
 | 
			
		||||
    uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
 | 
			
		||||
    return returnvalue::OK;
 | 
			
		||||
  }
 | 
			
		||||
  return returnvalue::OK;
 | 
			
		||||
  return returnvalue::FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Wait for new FSFW Clock function delivering seconds uptime.
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs*
 | 
			
		||||
  attributes.mq_msgsize = maxMessageSize;
 | 
			
		||||
  attributes.mq_flags = 0;  // Flags are ignored on Linux during mq_open
 | 
			
		||||
  // Set the name of the queue. The slash is mandatory!
 | 
			
		||||
  sprintf(name, "/FSFW_MQ%u\n", queueCounter++);
 | 
			
		||||
  sprintf(name, "/FSFW_MQ%u", queueCounter++);
 | 
			
		||||
 | 
			
		||||
  // Create a nonblocking queue if the name is available (the queue is read
 | 
			
		||||
  // and writable for the owner as well as the group)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								src/fsfw/osal/osal.h.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/fsfw/osal/osal.h.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
namespace osal {
 | 
			
		||||
    enum osalTarget{
 | 
			
		||||
        HOST,
 | 
			
		||||
        LINUX,
 | 
			
		||||
        WINDOWS,
 | 
			
		||||
        FREERTOS,
 | 
			
		||||
        RTEMS,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
#cmakedefine FSFW_OSAL_HOST
 | 
			
		||||
#cmakedefine FSFW_OSAL_LINUX
 | 
			
		||||
#cmakedefine FSFW_OSAL_WINDOWS
 | 
			
		||||
#cmakedefine FSFW_OSAL_FREERTOS
 | 
			
		||||
#cmakedefine FSFW_OSAL_RTEMS
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    constexpr osalTarget getTarget() {
 | 
			
		||||
#ifdef FSFW_OSAL_HOST
 | 
			
		||||
  return HOST;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef FSFW_OSAL_LINUX
 | 
			
		||||
  return LINUX;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef FSFW_OSAL_WINDOWS
 | 
			
		||||
  return WINDOWS;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef FSFW_OSAL_FREERTOS
 | 
			
		||||
  return FREERTOS;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef FSFW_OSAL_RTEMS
 | 
			
		||||
  return RTEMS;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -19,13 +19,13 @@ class CpuUsage : public SerializeIF {
 | 
			
		||||
    float timeRunning;
 | 
			
		||||
    float percentUsage;
 | 
			
		||||
 | 
			
		||||
    virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                                    Endianness streamEndianness) const override;
 | 
			
		||||
    ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                            Endianness streamEndianness) const override;
 | 
			
		||||
 | 
			
		||||
    virtual size_t getSerializedSize() const override;
 | 
			
		||||
    size_t getSerializedSize() const override;
 | 
			
		||||
 | 
			
		||||
    virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                                      Endianness streamEndianness) override;
 | 
			
		||||
    ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                              Endianness streamEndianness) override;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  CpuUsage();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
#include "fsfw/osal/rtems/BinarySemaphore.h"
 | 
			
		||||
//#include "fsfw/osal/rtems/CountingSemaphore.h"
 | 
			
		||||
// #include "fsfw/osal/rtems/CountingSemaphore.h"
 | 
			
		||||
 | 
			
		||||
#include "fsfw/serviceinterface/ServiceInterface.h"
 | 
			
		||||
#include "fsfw/tasks/SemaphoreFactory.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -40,13 +40,15 @@ class ParameterWrapper : public SerializeIF {
 | 
			
		||||
  ParameterWrapper(Type type, uint8_t rows, uint8_t columns, const void *data);
 | 
			
		||||
  virtual ~ParameterWrapper();
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
 | 
			
		||||
                                  Endianness streamEndianness) const override;
 | 
			
		||||
  ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
 | 
			
		||||
                          Endianness streamEndianness) const override;
 | 
			
		||||
 | 
			
		||||
  virtual size_t getSerializedSize() const override;
 | 
			
		||||
  size_t getSerializedSize() const override;
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
 | 
			
		||||
                                    Endianness streamEndianness) override;
 | 
			
		||||
  using SerializeIF::deSerialize;  // we overloaded this function, so this is needed to unconfuse
 | 
			
		||||
                                   // the compiler
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
 | 
			
		||||
                            Endianness streamEndianness) override;
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
 | 
			
		||||
                                    Endianness streamEndianness, uint16_t startWritingAtIndex = 0);
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ class Fuse : public SystemObject,
 | 
			
		||||
    gp_id_t poolIdPower;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1;
 | 
			
		||||
  static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF;
 | 
			
		||||
  //! PSS detected that current on a fuse is totally out of bounds.
 | 
			
		||||
  static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(1, severity::LOW);
 | 
			
		||||
  //! PSS detected a fuse that went off.
 | 
			
		||||
 
 | 
			
		||||
@@ -28,10 +28,12 @@ class PowerSwitchIF {
 | 
			
		||||
  static const ReturnValue_t SWITCH_TIMEOUT = MAKE_RETURN_CODE(2);
 | 
			
		||||
  static const ReturnValue_t FUSE_ON = MAKE_RETURN_CODE(3);
 | 
			
		||||
  static const ReturnValue_t FUSE_OFF = MAKE_RETURN_CODE(4);
 | 
			
		||||
  static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_2;
 | 
			
		||||
  static const Event SWITCH_WENT_OFF = MAKE_EVENT(
 | 
			
		||||
      0, severity::LOW);  //!< Someone detected that a switch went off which shouldn't. Severity:
 | 
			
		||||
                          //!< Low, Parameter1: switchId1, Parameter2: switchId2
 | 
			
		||||
  static const ReturnValue_t SWITCH_UNKNOWN = MAKE_RETURN_CODE(5);
 | 
			
		||||
 | 
			
		||||
  static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF;
 | 
			
		||||
  //!< Someone detected that a switch went off which shouldn't. Severity:
 | 
			
		||||
  //!< Low, Parameter1: switchId1, Parameter2: switchId2
 | 
			
		||||
  static const Event SWITCH_WENT_OFF = MAKE_EVENT(0, severity::LOW);
 | 
			
		||||
  /**
 | 
			
		||||
   * send a direct command to the Power Unit to enable/disable the specified switch.
 | 
			
		||||
   *
 | 
			
		||||
@@ -50,6 +52,7 @@ class PowerSwitchIF {
 | 
			
		||||
   * @return
 | 
			
		||||
   *     - @c SWITCH_ON if the specified switch is on.
 | 
			
		||||
   *     - @c SWITCH_OFF if the specified switch is off.
 | 
			
		||||
   *     - @c SWITCH_UNKNOWN if the state of the specified switch is unknown.
 | 
			
		||||
   *     - @c returnvalue::FAILED if an error occured
 | 
			
		||||
   */
 | 
			
		||||
  virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,4 +9,4 @@ target_sources(
 | 
			
		||||
          Service17Test.cpp
 | 
			
		||||
          Service20ParameterManagement.cpp
 | 
			
		||||
          CService200ModeCommanding.cpp
 | 
			
		||||
          CService201HealthCommanding.cpp)
 | 
			
		||||
          CServiceHealthCommanding.cpp)
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,8 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
 | 
			
		||||
  switch (subservice) {
 | 
			
		||||
    case (Subservice::COMMAND_MODE_COMMAND):
 | 
			
		||||
    case (Subservice::COMMAND_MODE_READ):
 | 
			
		||||
    case (Subservice::COMMAND_MODE_ANNCOUNCE):
 | 
			
		||||
    case (Subservice::COMMAND_MODE_ANNOUNCE):
 | 
			
		||||
    case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
 | 
			
		||||
      return returnvalue::OK;
 | 
			
		||||
    default:
 | 
			
		||||
      return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
 | 
			
		||||
@@ -53,16 +54,32 @@ ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue(
 | 
			
		||||
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
 | 
			
		||||
                                                        const uint8_t *tcData, size_t tcDataLen,
 | 
			
		||||
                                                        uint32_t *state, object_id_t objectId) {
 | 
			
		||||
  ModePacket modeCommandPacket;
 | 
			
		||||
  ReturnValue_t result =
 | 
			
		||||
      modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
 | 
			
		||||
  if (result != returnvalue::OK) {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
  bool recursive = false;
 | 
			
		||||
  switch (subservice) {
 | 
			
		||||
    case (Subservice::COMMAND_MODE_COMMAND): {
 | 
			
		||||
      ModePacket modeCommandPacket;
 | 
			
		||||
      ReturnValue_t result =
 | 
			
		||||
          modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
 | 
			
		||||
      if (result != returnvalue::OK) {
 | 
			
		||||
        return result;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(),
 | 
			
		||||
                              modeCommandPacket.getSubmode());
 | 
			
		||||
  return result;
 | 
			
		||||
      ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND,
 | 
			
		||||
                                  modeCommandPacket.getMode(), modeCommandPacket.getSubmode());
 | 
			
		||||
      return returnvalue::OK;
 | 
			
		||||
    }
 | 
			
		||||
    case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
 | 
			
		||||
      recursive = true;
 | 
			
		||||
      [[fallthrough]];
 | 
			
		||||
    case (Subservice::COMMAND_MODE_ANNOUNCE):
 | 
			
		||||
      ModeMessage::setModeAnnounceMessage(*message, recursive);
 | 
			
		||||
      return EXECUTION_COMPLETE;
 | 
			
		||||
    case (Subservice::COMMAND_MODE_READ):
 | 
			
		||||
      ModeMessage::setModeReadMessage(*message);
 | 
			
		||||
      return returnvalue::OK;
 | 
			
		||||
    default:
 | 
			
		||||
      return CommandingServiceBase::INVALID_SUBSERVICE;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply,
 | 
			
		||||
@@ -73,8 +90,10 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply
 | 
			
		||||
  ReturnValue_t result = returnvalue::FAILED;
 | 
			
		||||
  switch (replyId) {
 | 
			
		||||
    case (ModeMessage::REPLY_MODE_REPLY): {
 | 
			
		||||
      result = prepareModeReply(reply, objectId);
 | 
			
		||||
      break;
 | 
			
		||||
      if (previousCommand != ModeMessage::CMD_MODE_COMMAND) {
 | 
			
		||||
        return prepareModeReply(reply, objectId);
 | 
			
		||||
      }
 | 
			
		||||
      return returnvalue::OK;
 | 
			
		||||
    }
 | 
			
		||||
    case (ModeMessage::REPLY_WRONG_MODE_REPLY): {
 | 
			
		||||
      result = prepareWrongModeReply(reply, objectId);
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ class CService200ModeCommanding : public CommandingServiceBase {
 | 
			
		||||
    COMMAND_MODE_READ = 3,
 | 
			
		||||
    //!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event.
 | 
			
		||||
    //! This command does NOT have a reply
 | 
			
		||||
    COMMAND_MODE_ANNCOUNCE = 4,
 | 
			
		||||
    COMMAND_MODE_ANNOUNCE = 4,
 | 
			
		||||
    //!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this
 | 
			
		||||
    //! command to every child. This command does NOT have a reply.
 | 
			
		||||
    COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,106 +0,0 @@
 | 
			
		||||
#include "fsfw/pus/CService201HealthCommanding.h"
 | 
			
		||||
 | 
			
		||||
#include "fsfw/health/HasHealthIF.h"
 | 
			
		||||
#include "fsfw/health/HealthMessage.h"
 | 
			
		||||
#include "fsfw/objectmanager/ObjectManager.h"
 | 
			
		||||
#include "fsfw/pus/servicepackets/Service201Packets.h"
 | 
			
		||||
#include "fsfw/serviceinterface/ServiceInterface.h"
 | 
			
		||||
 | 
			
		||||
CService201HealthCommanding::CService201HealthCommanding(object_id_t objectId, uint16_t apid,
 | 
			
		||||
                                                         uint8_t serviceId,
 | 
			
		||||
                                                         uint8_t numParallelCommands,
 | 
			
		||||
                                                         uint16_t commandTimeoutSeconds)
 | 
			
		||||
    : CommandingServiceBase(objectId, apid, "PUS 201 Health MGMT", serviceId, numParallelCommands,
 | 
			
		||||
                            commandTimeoutSeconds) {}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
 | 
			
		||||
  switch (subservice) {
 | 
			
		||||
    case (Subservice::COMMAND_SET_HEALTH):
 | 
			
		||||
    case (Subservice::COMMAND_ANNOUNCE_HEALTH):
 | 
			
		||||
    case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL):
 | 
			
		||||
      return returnvalue::OK;
 | 
			
		||||
    default:
 | 
			
		||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
 | 
			
		||||
      sif::error << "Invalid Subservice" << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
      return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CService201HealthCommanding::getMessageQueueAndObject(uint8_t subservice,
 | 
			
		||||
                                                                    const uint8_t *tcData,
 | 
			
		||||
                                                                    size_t tcDataLen,
 | 
			
		||||
                                                                    MessageQueueId_t *id,
 | 
			
		||||
                                                                    object_id_t *objectId) {
 | 
			
		||||
  if (tcDataLen < sizeof(object_id_t)) {
 | 
			
		||||
    return CommandingServiceBase::INVALID_TC;
 | 
			
		||||
  }
 | 
			
		||||
  SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG);
 | 
			
		||||
 | 
			
		||||
  return checkInterfaceAndAcquireMessageQueue(id, objectId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
 | 
			
		||||
    MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
 | 
			
		||||
  auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
 | 
			
		||||
  if (destination == nullptr) {
 | 
			
		||||
    return CommandingServiceBase::INVALID_OBJECT;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  *messageQueueToSet = destination->getCommandQueue();
 | 
			
		||||
  return returnvalue::OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CService201HealthCommanding::prepareCommand(CommandMessage *message,
 | 
			
		||||
                                                          uint8_t subservice, const uint8_t *tcData,
 | 
			
		||||
                                                          size_t tcDataLen, uint32_t *state,
 | 
			
		||||
                                                          object_id_t objectId) {
 | 
			
		||||
  ReturnValue_t result = returnvalue::OK;
 | 
			
		||||
  switch (subservice) {
 | 
			
		||||
    case (Subservice::COMMAND_SET_HEALTH): {
 | 
			
		||||
      HealthSetCommand healthCommand;
 | 
			
		||||
      result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
 | 
			
		||||
      if (result != returnvalue::OK) {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET,
 | 
			
		||||
                                      healthCommand.getHealth());
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
 | 
			
		||||
      HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
 | 
			
		||||
      HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    default: {
 | 
			
		||||
      // Should never happen, subservice was already checked
 | 
			
		||||
      result = returnvalue::FAILED;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *reply,
 | 
			
		||||
                                                       Command_t previousCommand, uint32_t *state,
 | 
			
		||||
                                                       CommandMessage *optionalNextCommand,
 | 
			
		||||
                                                       object_id_t objectId, bool *isStep) {
 | 
			
		||||
  Command_t replyId = reply->getCommand();
 | 
			
		||||
  if (replyId == HealthMessage::REPLY_HEALTH_SET) {
 | 
			
		||||
    return EXECUTION_COMPLETE;
 | 
			
		||||
  } else if (replyId == CommandMessageIF::REPLY_REJECTED) {
 | 
			
		||||
    return reply->getReplyRejectedReason();
 | 
			
		||||
  }
 | 
			
		||||
  return CommandingServiceBase::INVALID_REPLY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Not used for now, health state already reported by event
 | 
			
		||||
[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(
 | 
			
		||||
    const CommandMessage *reply) {
 | 
			
		||||
  auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
 | 
			
		||||
  auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
 | 
			
		||||
  HealthSetReply healthSetReply(health, oldHealth);
 | 
			
		||||
  return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										161
									
								
								src/fsfw/pus/CServiceHealthCommanding.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/fsfw/pus/CServiceHealthCommanding.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
#include <fsfw/events/EventManagerIF.h>
 | 
			
		||||
#include <fsfw/pus/CServiceHealthCommanding.h>
 | 
			
		||||
 | 
			
		||||
#include "fsfw/health/HasHealthIF.h"
 | 
			
		||||
#include "fsfw/health/HealthMessage.h"
 | 
			
		||||
#include "fsfw/objectmanager/ObjectManager.h"
 | 
			
		||||
#include "fsfw/pus/servicepackets/Service201Packets.h"
 | 
			
		||||
#include "fsfw/serviceinterface/ServiceInterface.h"
 | 
			
		||||
 | 
			
		||||
CServiceHealthCommanding::CServiceHealthCommanding(HealthServiceCfg args)
 | 
			
		||||
    : CommandingServiceBase(args.objectId, args.apid, "PUS 201 Health MGMT", args.service,
 | 
			
		||||
                            args.numParallelCommands, args.commandTimeoutSeconds),
 | 
			
		||||
      healthTableId(args.table),
 | 
			
		||||
      maxNumHealthInfoPerCycle(args.maxNumHealthInfoPerCycle) {}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CServiceHealthCommanding::initialize() {
 | 
			
		||||
  ReturnValue_t result = CommandingServiceBase::initialize();
 | 
			
		||||
  if (result != returnvalue::OK) {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  healthTable = ObjectManager::instance()->get<HealthTable>(healthTableId);
 | 
			
		||||
  if (healthTable == nullptr) {
 | 
			
		||||
    return returnvalue::FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return returnvalue::OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CServiceHealthCommanding::isValidSubservice(uint8_t subservice) {
 | 
			
		||||
  switch (subservice) {
 | 
			
		||||
    case (Subservice::COMMAND_SET_HEALTH):
 | 
			
		||||
    case (Subservice::COMMAND_ANNOUNCE_HEALTH):
 | 
			
		||||
    case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL):
 | 
			
		||||
      return returnvalue::OK;
 | 
			
		||||
    default:
 | 
			
		||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
 | 
			
		||||
      sif::error << "Invalid Subservice" << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
      return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CServiceHealthCommanding::getMessageQueueAndObject(uint8_t subservice,
 | 
			
		||||
                                                                 const uint8_t *tcData,
 | 
			
		||||
                                                                 size_t tcDataLen,
 | 
			
		||||
                                                                 MessageQueueId_t *id,
 | 
			
		||||
                                                                 object_id_t *objectId) {
 | 
			
		||||
  switch (subservice) {
 | 
			
		||||
    case (Subservice::COMMAND_SET_HEALTH):
 | 
			
		||||
    case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
 | 
			
		||||
      if (tcDataLen < sizeof(object_id_t)) {
 | 
			
		||||
        return CommandingServiceBase::INVALID_TC;
 | 
			
		||||
      }
 | 
			
		||||
      SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG);
 | 
			
		||||
 | 
			
		||||
      return checkInterfaceAndAcquireMessageQueue(id, objectId);
 | 
			
		||||
    }
 | 
			
		||||
    case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
 | 
			
		||||
      return returnvalue::OK;
 | 
			
		||||
    }
 | 
			
		||||
    default: {
 | 
			
		||||
      return returnvalue::FAILED;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CServiceHealthCommanding::checkInterfaceAndAcquireMessageQueue(
 | 
			
		||||
    MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
 | 
			
		||||
  auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
 | 
			
		||||
  if (destination == nullptr) {
 | 
			
		||||
    return CommandingServiceBase::INVALID_OBJECT;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  *messageQueueToSet = destination->getCommandQueue();
 | 
			
		||||
  return returnvalue::OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
 | 
			
		||||
                                                       const uint8_t *tcData, size_t tcDataLen,
 | 
			
		||||
                                                       uint32_t *state, object_id_t objectId) {
 | 
			
		||||
  ReturnValue_t result = returnvalue::OK;
 | 
			
		||||
  switch (subservice) {
 | 
			
		||||
    case (Subservice::COMMAND_SET_HEALTH): {
 | 
			
		||||
      if (tcDataLen != sizeof(object_id_t) + sizeof(HasHealthIF::HealthState)) {
 | 
			
		||||
        return CommandingServiceBase::INVALID_TC;
 | 
			
		||||
      }
 | 
			
		||||
      HealthSetCommand healthCommand;
 | 
			
		||||
      result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
 | 
			
		||||
      if (result != returnvalue::OK) {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET,
 | 
			
		||||
                                      healthCommand.getHealth());
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
 | 
			
		||||
      HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
 | 
			
		||||
      return CommandingServiceBase::EXECUTION_COMPLETE;
 | 
			
		||||
    }
 | 
			
		||||
    case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
 | 
			
		||||
      ReturnValue_t result = iterateHealthTable(true);
 | 
			
		||||
      if (result == returnvalue::OK) {
 | 
			
		||||
        reportAllHealth = true;
 | 
			
		||||
        return EXECUTION_COMPLETE;
 | 
			
		||||
      }
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
    default: {
 | 
			
		||||
      // Should never happen, subservice was already checked
 | 
			
		||||
      result = returnvalue::FAILED;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CServiceHealthCommanding::handleReply(const CommandMessage *reply,
 | 
			
		||||
                                                    Command_t previousCommand, uint32_t *state,
 | 
			
		||||
                                                    CommandMessage *optionalNextCommand,
 | 
			
		||||
                                                    object_id_t objectId, bool *isStep) {
 | 
			
		||||
  Command_t replyId = reply->getCommand();
 | 
			
		||||
  if (replyId == HealthMessage::REPLY_HEALTH_SET) {
 | 
			
		||||
    return EXECUTION_COMPLETE;
 | 
			
		||||
  } else if (replyId == CommandMessageIF::REPLY_REJECTED) {
 | 
			
		||||
    return reply->getReplyRejectedReason();
 | 
			
		||||
  }
 | 
			
		||||
  return CommandingServiceBase::INVALID_REPLY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CServiceHealthCommanding::doPeriodicOperation() {
 | 
			
		||||
  if (reportAllHealth) {
 | 
			
		||||
    for (uint8_t i = 0; i < maxNumHealthInfoPerCycle; i++) {
 | 
			
		||||
      ReturnValue_t result = iterateHealthTable(false);
 | 
			
		||||
      if (result != returnvalue::OK) {
 | 
			
		||||
        reportAllHealth = false;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Not used for now, health state already reported by event
 | 
			
		||||
[[maybe_unused]] ReturnValue_t CServiceHealthCommanding::prepareHealthSetReply(
 | 
			
		||||
    const CommandMessage *reply) {
 | 
			
		||||
  auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
 | 
			
		||||
  auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
 | 
			
		||||
  HealthSetReply healthSetReply(health, oldHealth);
 | 
			
		||||
  return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CServiceHealthCommanding::iterateHealthTable(bool reset) {
 | 
			
		||||
  std::pair<object_id_t, HasHealthIF::HealthState> pair;
 | 
			
		||||
 | 
			
		||||
  ReturnValue_t result = healthTable->iterate(&pair, reset);
 | 
			
		||||
  if (result != returnvalue::OK) {
 | 
			
		||||
    return result;
 | 
			
		||||
  } else {
 | 
			
		||||
    EventManagerIF::triggerEvent(pair.first, HasHealthIF::HEALTH_INFO, pair.second, pair.second);
 | 
			
		||||
    return returnvalue::OK;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,26 @@
 | 
			
		||||
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
 | 
			
		||||
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
 | 
			
		||||
 | 
			
		||||
#include <fsfw/health/HealthTable.h>
 | 
			
		||||
 | 
			
		||||
#include "fsfw/tmtcservices/CommandingServiceBase.h"
 | 
			
		||||
 | 
			
		||||
struct HealthServiceCfg {
 | 
			
		||||
  HealthServiceCfg(object_id_t objectId, uint16_t apid, object_id_t healthTable,
 | 
			
		||||
                   uint16_t maxNumHealthInfoPerCycle)
 | 
			
		||||
      : objectId(objectId),
 | 
			
		||||
        apid(apid),
 | 
			
		||||
        table(healthTable),
 | 
			
		||||
        maxNumHealthInfoPerCycle(maxNumHealthInfoPerCycle) {}
 | 
			
		||||
  object_id_t objectId;
 | 
			
		||||
  uint16_t apid;
 | 
			
		||||
  object_id_t table;
 | 
			
		||||
  uint16_t maxNumHealthInfoPerCycle;
 | 
			
		||||
  uint8_t service = 201;
 | 
			
		||||
  uint8_t numParallelCommands = 4;
 | 
			
		||||
  uint16_t commandTimeoutSeconds = 60;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief   Custom PUS service to set health of all objects
 | 
			
		||||
 *          implementing hasHealthIF.
 | 
			
		||||
@@ -17,11 +35,12 @@
 | 
			
		||||
 * child class like this service
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class CService201HealthCommanding : public CommandingServiceBase {
 | 
			
		||||
class CServiceHealthCommanding : public CommandingServiceBase {
 | 
			
		||||
 public:
 | 
			
		||||
  CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
 | 
			
		||||
                              uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
 | 
			
		||||
  ~CService201HealthCommanding() override = default;
 | 
			
		||||
  CServiceHealthCommanding(HealthServiceCfg args);
 | 
			
		||||
  ~CServiceHealthCommanding() override = default;
 | 
			
		||||
 | 
			
		||||
  ReturnValue_t initialize() override;
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  /* CSB abstract function implementations */
 | 
			
		||||
@@ -37,7 +56,14 @@ class CService201HealthCommanding : public CommandingServiceBase {
 | 
			
		||||
                            CommandMessage *optionalNextCommand, object_id_t objectId,
 | 
			
		||||
                            bool *isStep) override;
 | 
			
		||||
 | 
			
		||||
  void doPeriodicOperation() override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  const object_id_t healthTableId;
 | 
			
		||||
  HealthTable *healthTable;
 | 
			
		||||
  uint16_t maxNumHealthInfoPerCycle = 0;
 | 
			
		||||
  bool reportAllHealth = false;
 | 
			
		||||
  ReturnValue_t iterateHealthTable(bool reset);
 | 
			
		||||
  static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
 | 
			
		||||
                                                            const object_id_t *objectId);
 | 
			
		||||
 | 
			
		||||
@@ -2,12 +2,12 @@
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
 | 
			
		||||
#include "fsfw/globalfunctions/CRC.h"
 | 
			
		||||
#include "fsfw/objectmanager/ObjectManager.h"
 | 
			
		||||
#include "fsfw/serialize/SerializeAdapter.h"
 | 
			
		||||
#include "fsfw/serviceinterface.h"
 | 
			
		||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
 | 
			
		||||
#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h"
 | 
			
		||||
#include "fsfw/globalfunctions/CRC.h"
 | 
			
		||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
 | 
			
		||||
 | 
			
		||||
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
 | 
			
		||||
 | 
			
		||||
@@ -180,7 +180,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
 | 
			
		||||
  if (CRC::crc16ccitt(data, size) != 0) {
 | 
			
		||||
    return CONTAINED_TC_CRC_MISSMATCH;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  // store currentPacket and receive the store address
 | 
			
		||||
  store_address_t addr{};
 | 
			
		||||
  if (tcStore->addData(&addr, data, size) != returnvalue::OK ||
 | 
			
		||||
 
 | 
			
		||||
@@ -69,14 +69,14 @@ ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue
 | 
			
		||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
 | 
			
		||||
    sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire"
 | 
			
		||||
               << "MessageQueue: Can't access object" << std::endl;
 | 
			
		||||
    sif::error << "Object ID: " << std::hex << objectId << std::dec << std::endl;
 | 
			
		||||
    sif::error << "Make sure it implements ReceivesParameterMessagesIF!" << std::endl;
 | 
			
		||||
    sif::error << "Object ID: 0x" << std::hex << *objectId << std::dec << std::endl;
 | 
			
		||||
    sif::error << "Make sure it implements ReceivesParameterMessagesIF" << std::endl;
 | 
			
		||||
#else
 | 
			
		||||
    sif::printError(
 | 
			
		||||
        "Service20ParameterManagement::checkInterfaceAndAcquire"
 | 
			
		||||
        "MessageQueue: Can't access object\n");
 | 
			
		||||
    sif::printError("Object ID: 0x%08x\n", *objectId);
 | 
			
		||||
    sif::printError("Make sure it implements ReceivesParameterMessagesIF!\n");
 | 
			
		||||
    sif::printError("Make sure it implements ReceivesParameterMessagesIF\n");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return CommandingServiceBase::INVALID_OBJECT;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
#include "fsfw/pus/Service9TimeManagement.h"
 | 
			
		||||
 | 
			
		||||
#include <cmath>
 | 
			
		||||
 | 
			
		||||
#include "fsfw/events/EventManagerIF.h"
 | 
			
		||||
#include "fsfw/pus/servicepackets/Service9Packets.h"
 | 
			
		||||
#include "fsfw/serviceinterface/ServiceInterface.h"
 | 
			
		||||
@@ -15,9 +17,17 @@ ReturnValue_t Service9TimeManagement::performService() { return returnvalue::OK;
 | 
			
		||||
 | 
			
		||||
ReturnValue_t Service9TimeManagement::handleRequest(uint8_t subservice) {
 | 
			
		||||
  switch (subservice) {
 | 
			
		||||
    case SUBSERVICE::SET_TIME: {
 | 
			
		||||
    case Subservice::SET_TIME: {
 | 
			
		||||
      return setTime();
 | 
			
		||||
    }
 | 
			
		||||
    case Subservice::DUMP_TIME: {
 | 
			
		||||
      timeval newTime;
 | 
			
		||||
      Clock::getClock_timeval(&newTime);
 | 
			
		||||
      uint32_t subsecondMs =
 | 
			
		||||
          static_cast<uint32_t>(std::floor(static_cast<double>(newTime.tv_usec) / 1000.0));
 | 
			
		||||
      triggerEvent(CLOCK_DUMP, newTime.tv_sec, subsecondMs);
 | 
			
		||||
      return returnvalue::OK;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
      return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
 | 
			
		||||
  }
 | 
			
		||||
@@ -33,14 +43,14 @@ ReturnValue_t Service9TimeManagement::setTime() {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint32_t formerUptime;
 | 
			
		||||
  Clock::getUptime(&formerUptime);
 | 
			
		||||
  timeval time;
 | 
			
		||||
  Clock::getClock_timeval(&time);
 | 
			
		||||
  result = Clock::setClock(&timeToSet);
 | 
			
		||||
 | 
			
		||||
  if (result == returnvalue::OK) {
 | 
			
		||||
    uint32_t newUptime;
 | 
			
		||||
    Clock::getUptime(&newUptime);
 | 
			
		||||
    triggerEvent(CLOCK_SET, newUptime, formerUptime);
 | 
			
		||||
    timeval newTime;
 | 
			
		||||
    Clock::getClock_timeval(&newTime);
 | 
			
		||||
    triggerEvent(CLOCK_SET, time.tv_sec, newTime.tv_sec);
 | 
			
		||||
    return returnvalue::OK;
 | 
			
		||||
  } else {
 | 
			
		||||
    triggerEvent(CLOCK_SET_FAILURE, result, 0);
 | 
			
		||||
 
 | 
			
		||||
@@ -6,10 +6,13 @@
 | 
			
		||||
class Service9TimeManagement : public PusServiceBase {
 | 
			
		||||
 public:
 | 
			
		||||
  static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
 | 
			
		||||
  static constexpr Event CLOCK_SET =
 | 
			
		||||
      MAKE_EVENT(0, severity::INFO);  //!< Clock has been set. P1: New Uptime. P2: Old Uptime
 | 
			
		||||
  static constexpr Event CLOCK_SET_FAILURE =
 | 
			
		||||
      MAKE_EVENT(1, severity::LOW);  //!< Clock could not be set. P1: Returncode.
 | 
			
		||||
 | 
			
		||||
  //!< Clock has been set. P1: old timeval seconds. P2: new timeval seconds.
 | 
			
		||||
  static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO);
 | 
			
		||||
  //!< Clock dump event. P1: timeval seconds P2: timeval milliseconds.
 | 
			
		||||
  static constexpr Event CLOCK_DUMP = MAKE_EVENT(1, severity::INFO);
 | 
			
		||||
  //!< Clock could not be set. P1: Returncode.
 | 
			
		||||
  static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(2, severity::LOW);
 | 
			
		||||
 | 
			
		||||
  static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
 | 
			
		||||
 | 
			
		||||
@@ -30,8 +33,9 @@ class Service9TimeManagement : public PusServiceBase {
 | 
			
		||||
  virtual ReturnValue_t setTime();
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  enum SUBSERVICE {
 | 
			
		||||
    SET_TIME = 128  //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
 | 
			
		||||
  enum Subservice {
 | 
			
		||||
    SET_TIME = 128,  //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
 | 
			
		||||
    DUMP_TIME = 129,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,8 @@ class EventReport : public SerializeIF {  //!< [EXPORT] : [SUBSERVICE] 1, 2, 3,
 | 
			
		||||
        parameter1(parameter1_),
 | 
			
		||||
        parameter2(parameter2_) {}
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                                  SerializeIF::Endianness streamEndianness) const override {
 | 
			
		||||
  ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                          SerializeIF::Endianness streamEndianness) const override {
 | 
			
		||||
    ReturnValue_t result =
 | 
			
		||||
        SerializeAdapter::serialize(&reportId, buffer, size, maxSize, streamEndianness);
 | 
			
		||||
    if (result != returnvalue::OK) {
 | 
			
		||||
@@ -46,7 +46,7 @@ class EventReport : public SerializeIF {  //!< [EXPORT] : [SUBSERVICE] 1, 2, 3,
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual size_t getSerializedSize() const override {
 | 
			
		||||
  size_t getSerializedSize() const override {
 | 
			
		||||
    uint32_t size = 0;
 | 
			
		||||
    size += SerializeAdapter::getSerializedSize(&reportId);
 | 
			
		||||
    size += SerializeAdapter::getSerializedSize(&objectId);
 | 
			
		||||
@@ -55,8 +55,8 @@ class EventReport : public SerializeIF {  //!< [EXPORT] : [SUBSERVICE] 1, 2, 3,
 | 
			
		||||
    return size;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                                    SerializeIF::Endianness streamEndianness) override {
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                            SerializeIF::Endianness streamEndianness) override {
 | 
			
		||||
    return returnvalue::FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,11 +10,11 @@
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RMAP command bits
 | 
			
		||||
//#define RMAP_COMMAND_BIT_INCREMENT	2
 | 
			
		||||
//#define RMAP_COMMAND_BIT_REPLY		3
 | 
			
		||||
//#define RMAP_COMMAND_BIT_WRITE		5
 | 
			
		||||
//#define RMAP_COMMAND_BIT_VERIFY		4
 | 
			
		||||
//#define RMAP_COMMAND_BIT			6
 | 
			
		||||
// #define RMAP_COMMAND_BIT_INCREMENT	2
 | 
			
		||||
// #define RMAP_COMMAND_BIT_REPLY		3
 | 
			
		||||
// #define RMAP_COMMAND_BIT_WRITE		5
 | 
			
		||||
// #define RMAP_COMMAND_BIT_VERIFY		4
 | 
			
		||||
// #define RMAP_COMMAND_BIT			6
 | 
			
		||||
 | 
			
		||||
namespace RMAPIds {
 | 
			
		||||
 | 
			
		||||
@@ -32,14 +32,14 @@ static const uint8_t RMAP_COMMAND_READ = ((1 << RMAP_COMMAND_BIT) | (1 << RMAP_C
 | 
			
		||||
static const uint8_t RMAP_REPLY_WRITE =
 | 
			
		||||
    ((1 << RMAP_COMMAND_BIT_WRITE) | (1 << RMAP_COMMAND_BIT_REPLY));
 | 
			
		||||
static const uint8_t RMAP_REPLY_READ = ((1 << RMAP_COMMAND_BIT_REPLY));
 | 
			
		||||
//#define RMAP_COMMAND_WRITE			((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE)
 | 
			
		||||
// #define RMAP_COMMAND_WRITE			((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE)
 | 
			
		||||
//| (1<<RMAP_COMMAND_BIT_REPLY)) #define RMAP_COMMAND_WRITE_VERIFY	((1<<RMAP_COMMAND_BIT) |
 | 
			
		||||
//(1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define
 | 
			
		||||
// RMAP_COMMAND_READ			((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY))
 | 
			
		||||
//  RMAP_COMMAND_READ			((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY))
 | 
			
		||||
 | 
			
		||||
//#define RMAP_REPLY_WRITE			((1<<RMAP_COMMAND_BIT_WRITE) |
 | 
			
		||||
// #define RMAP_REPLY_WRITE			((1<<RMAP_COMMAND_BIT_WRITE) |
 | 
			
		||||
//(1<<RMAP_COMMAND_BIT_REPLY))
 | 
			
		||||
//#define RMAP_REPLY_WRITE_VERIFY		((1<<RMAP_COMMAND_BIT_WRITE) |
 | 
			
		||||
// #define RMAP_REPLY_WRITE_VERIFY		((1<<RMAP_COMMAND_BIT_WRITE) |
 | 
			
		||||
//(1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define RMAP_REPLY_READ
 | 
			
		||||
//((1<<RMAP_COMMAND_BIT_REPLY))
 | 
			
		||||
 | 
			
		||||
@@ -49,9 +49,9 @@ static const uint8_t RMAP_COMMAND_HEADER_LEN = 16;
 | 
			
		||||
static const uint8_t RMAP_WRITE_REPLY_HEADER_LEN = 8;
 | 
			
		||||
static const uint8_t RMAP_READ_REPLY_HEADER_LEN = 12;
 | 
			
		||||
static const uint8_t RMAP_DATA_FOOTER_SIZE = 1;  // SIZE OF CRC
 | 
			
		||||
//#define RMAP_COMMAND_HEADER_LEN		16
 | 
			
		||||
//#define RMAP_WRITE_REPLY_HEADER_LEN	8
 | 
			
		||||
//#define RMAP_READ_REPLY_HEADER_LEN	12
 | 
			
		||||
// #define RMAP_COMMAND_HEADER_LEN		16
 | 
			
		||||
// #define RMAP_WRITE_REPLY_HEADER_LEN	8
 | 
			
		||||
// #define RMAP_READ_REPLY_HEADER_LEN	12
 | 
			
		||||
 | 
			
		||||
}  // namespace RMAPIds
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,8 +16,10 @@ class SerialArrayListAdapter : public SerializeIF {
 | 
			
		||||
 public:
 | 
			
		||||
  SerialArrayListAdapter(ArrayList<T, count_t>* adaptee) : adaptee(adaptee) {}
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                                  Endianness streamEndianness) const {
 | 
			
		||||
  using SerializeIF::serialize;  // we overload this function as well, so this is needed to uncofuse
 | 
			
		||||
                                 // the compiler
 | 
			
		||||
  ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                          Endianness streamEndianness) const override {
 | 
			
		||||
    return serialize(adaptee, buffer, size, maxSize, streamEndianness);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -34,7 +36,7 @@ class SerialArrayListAdapter : public SerializeIF {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual size_t getSerializedSize() const { return getSerializedSize(adaptee); }
 | 
			
		||||
  size_t getSerializedSize() const override { return getSerializedSize(adaptee); }
 | 
			
		||||
 | 
			
		||||
  static uint32_t getSerializedSize(const ArrayList<T, count_t>* list) {
 | 
			
		||||
    uint32_t printSize = sizeof(count_t);
 | 
			
		||||
@@ -47,8 +49,10 @@ class SerialArrayListAdapter : public SerializeIF {
 | 
			
		||||
    return printSize;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                                    Endianness streamEndianness) {
 | 
			
		||||
  using SerializeIF::deSerialize;  // we overload this function as well, so this is needed to
 | 
			
		||||
                                   // uncofuse the compiler
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                            Endianness streamEndianness) override {
 | 
			
		||||
    return deSerialize(adaptee, buffer, size, streamEndianness);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -45,8 +45,10 @@ class SerialLinkedListAdapter : public SinglyLinkedList<T>, public SerializeIF {
 | 
			
		||||
  SerialLinkedListAdapter(bool printCount = false)
 | 
			
		||||
      : SinglyLinkedList<T>(), printCount(printCount) {}
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                                  Endianness streamEndianness) const override {
 | 
			
		||||
  using SerializeIF::serialize;  // we overloaded this function, so this is needed to unconfuse the
 | 
			
		||||
                                 // compiler
 | 
			
		||||
  ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                          Endianness streamEndianness) const override {
 | 
			
		||||
    if (printCount) {
 | 
			
		||||
      count_t mySize = SinglyLinkedList<T>::getSize();
 | 
			
		||||
      ReturnValue_t result =
 | 
			
		||||
@@ -68,7 +70,7 @@ class SerialLinkedListAdapter : public SinglyLinkedList<T>, public SerializeIF {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual size_t getSerializedSize() const override {
 | 
			
		||||
  size_t getSerializedSize() const override {
 | 
			
		||||
    if (printCount) {
 | 
			
		||||
      return SerialLinkedListAdapter<T>::getSerializedSize() + sizeof(count_t);
 | 
			
		||||
    } else {
 | 
			
		||||
@@ -76,6 +78,8 @@ class SerialLinkedListAdapter : public SinglyLinkedList<T>, public SerializeIF {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  using SerializeIF::deSerialize;  // we overloaded this function, so this is needed to unconfuse
 | 
			
		||||
                                   // the compiler
 | 
			
		||||
  static size_t getSerializedSize(const LinkedElement<T>* element) {
 | 
			
		||||
    size_t size = 0;
 | 
			
		||||
    while (element != nullptr) {
 | 
			
		||||
@@ -85,8 +89,8 @@ class SerialLinkedListAdapter : public SinglyLinkedList<T>, public SerializeIF {
 | 
			
		||||
    return size;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                                    Endianness streamEndianness) override {
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                            Endianness streamEndianness) override {
 | 
			
		||||
    return deSerialize(SinglyLinkedList<T>::start, buffer, size, streamEndianness);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,8 +32,8 @@ class SerializeElement : public SerializeIF, public LinkedElement<SerializeIF> {
 | 
			
		||||
 | 
			
		||||
  size_t getSerializedSize() const override { return SerializeAdapter::getSerializedSize(&entry); }
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
 | 
			
		||||
                                    Endianness streamEndianness) override {
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
 | 
			
		||||
                            Endianness streamEndianness) override {
 | 
			
		||||
    return SerializeAdapter::deSerialize(&entry, buffer, size, streamEndianness);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -89,7 +89,7 @@ ReturnValue_t LocalPool::deleteData(store_address_t storeId) {
 | 
			
		||||
  ReturnValue_t status = returnvalue::OK;
 | 
			
		||||
  size_type pageSize = getSubpoolElementSize(storeId.poolIndex);
 | 
			
		||||
  if ((pageSize != 0) and (storeId.packetIndex < numberOfElements[storeId.poolIndex])) {
 | 
			
		||||
    uint16_t packetPosition = getRawPosition(storeId);
 | 
			
		||||
    size_type packetPosition = getRawPosition(storeId);
 | 
			
		||||
    uint8_t* ptr = &store[storeId.poolIndex][packetPosition];
 | 
			
		||||
    std::memset(ptr, 0, pageSize);
 | 
			
		||||
    // Set free list
 | 
			
		||||
 
 | 
			
		||||
@@ -15,8 +15,8 @@ class ModeListEntry : public SerializeIF, public LinkedElement<ModeListEntry> {
 | 
			
		||||
  uint8_t value3 = 0;
 | 
			
		||||
  uint8_t value4 = 0;
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                                  Endianness streamEndianness) const {
 | 
			
		||||
  ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
 | 
			
		||||
                          Endianness streamEndianness) const override {
 | 
			
		||||
    ReturnValue_t result;
 | 
			
		||||
 | 
			
		||||
    result = SerializeAdapter::serialize(&value1, buffer, size, maxSize, streamEndianness);
 | 
			
		||||
@@ -40,12 +40,12 @@ class ModeListEntry : public SerializeIF, public LinkedElement<ModeListEntry> {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual size_t getSerializedSize() const {
 | 
			
		||||
  size_t getSerializedSize() const override {
 | 
			
		||||
    return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                                    Endianness streamEndianness) {
 | 
			
		||||
  ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
 | 
			
		||||
                            Endianness streamEndianness) override {
 | 
			
		||||
    ReturnValue_t result;
 | 
			
		||||
 | 
			
		||||
    result = SerializeAdapter::deSerialize(&value1, buffer, size, streamEndianness);
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@
 | 
			
		||||
 | 
			
		||||
#include "fsfw/timemanager/Clock.h"
 | 
			
		||||
 | 
			
		||||
CdsShortTimeStamper::CdsShortTimeStamper() : SystemObject(0, false) {}
 | 
			
		||||
 | 
			
		||||
CdsShortTimeStamper::CdsShortTimeStamper(object_id_t objectId) : SystemObject(objectId) {}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t CdsShortTimeStamper::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
class CdsShortTimeStamper : public TimeWriterIF, public TimeReaderIF, public SystemObject {
 | 
			
		||||
 public:
 | 
			
		||||
  static constexpr size_t TIMESTAMP_LEN = 7;
 | 
			
		||||
  CdsShortTimeStamper();
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief   Default constructor which also registers the time stamper as a
 | 
			
		||||
   *          system object so it can be found with the #objectManager.
 | 
			
		||||
 
 | 
			
		||||
@@ -100,5 +100,6 @@ ReturnValue_t PusTcCreator::setSerializableUserData(const SerializeIF &serializa
 | 
			
		||||
void PusTcCreator::setup() {
 | 
			
		||||
  spCreator.setPacketType(ccsds::PacketType::TC);
 | 
			
		||||
  spCreator.setSecHeaderFlag();
 | 
			
		||||
  spCreator.setSeqFlags(ccsds::SequenceFlags::UNSEGMENTED);
 | 
			
		||||
  updateSpLengthField();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -119,6 +119,7 @@ void PusTmCreator::setup() {
 | 
			
		||||
  updateSpLengthField();
 | 
			
		||||
  spCreator.setPacketType(ccsds::PacketType::TM);
 | 
			
		||||
  spCreator.setSecHeaderFlag();
 | 
			
		||||
  spCreator.setSeqFlags(ccsds::SequenceFlags::UNSEGMENTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PusTmCreator::setMessageTypeCounter(uint16_t messageTypeCounter) {
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@ struct PusTmParams {
 | 
			
		||||
              size_t dataLen)
 | 
			
		||||
      : secHeader(service, subservice, timeStamper), adapter(data, dataLen), sourceData(&adapter) {}
 | 
			
		||||
  PusTmSecHeader secHeader;
 | 
			
		||||
  SerialBufferAdapter<uint8_t> adapter;
 | 
			
		||||
  SerialBufferAdapter<size_t> adapter;
 | 
			
		||||
  const SerializeIF* sourceData = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
#define TMTCBRIDGE_WIRETAPPING 0
 | 
			
		||||
 | 
			
		||||
TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination,
 | 
			
		||||
                       object_id_t tmStoreId, object_id_t tcStoreId)
 | 
			
		||||
                       uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId)
 | 
			
		||||
    : SystemObject(objectId),
 | 
			
		||||
      name(name),
 | 
			
		||||
      tmStoreId(tmStoreId),
 | 
			
		||||
@@ -16,7 +16,9 @@ TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDes
 | 
			
		||||
      tcDestination(tcDestination)
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
  tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH);
 | 
			
		||||
  auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
 | 
			
		||||
  tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(
 | 
			
		||||
      msgQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
 | 
			
		||||
@@ -35,7 +37,7 @@ ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerC
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored) {
 | 
			
		||||
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored) {
 | 
			
		||||
  if (maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) {
 | 
			
		||||
    this->maxNumberOfPacketsStored = maxNumberOfPacketsStored;
 | 
			
		||||
    return returnvalue::OK;
 | 
			
		||||
@@ -143,13 +145,17 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
 | 
			
		||||
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
 | 
			
		||||
 | 
			
		||||
    if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) {
 | 
			
		||||
      storeDownlinkData(&message);
 | 
			
		||||
      ReturnValue_t result = storeDownlinkData(&message);
 | 
			
		||||
      if (result != returnvalue::OK) {
 | 
			
		||||
        tmStore->deleteData(message.getStorageId());
 | 
			
		||||
      }
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    result = tmStore->getData(message.getStorageId(), &data, &size);
 | 
			
		||||
    if (result != returnvalue::OK) {
 | 
			
		||||
      status = result;
 | 
			
		||||
      tmStore->deleteData(message.getStorageId());
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -157,9 +163,9 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
 | 
			
		||||
    if (result != returnvalue::OK) {
 | 
			
		||||
      status = result;
 | 
			
		||||
    } else {
 | 
			
		||||
      tmStore->deleteData(message.getStorageId());
 | 
			
		||||
      packetSentCounter++;
 | 
			
		||||
    }
 | 
			
		||||
    tmStore->deleteData(message.getStorageId());
 | 
			
		||||
  }
 | 
			
		||||
  return status;
 | 
			
		||||
}
 | 
			
		||||
@@ -171,15 +177,18 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (tmFifo->full()) {
 | 
			
		||||
    if (warningSwitch) {
 | 
			
		||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
 | 
			
		||||
    sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
 | 
			
		||||
                    "of stored packet IDs reached!"
 | 
			
		||||
                 << std::endl;
 | 
			
		||||
      sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
 | 
			
		||||
                      "of stored packet IDs reached!"
 | 
			
		||||
                   << std::endl;
 | 
			
		||||
#else
 | 
			
		||||
    sif::printWarning(
 | 
			
		||||
        "TmTcBridge::storeDownlinkData: TM downlink max. number "
 | 
			
		||||
        "of stored packet IDs reached!\n");
 | 
			
		||||
      sif::printWarning(
 | 
			
		||||
          "TmTcBridge::storeDownlinkData: TM downlink max. number "
 | 
			
		||||
          "of stored packet IDs reached!\n");
 | 
			
		||||
#endif
 | 
			
		||||
      warningSwitch = false;
 | 
			
		||||
    }
 | 
			
		||||
    if (overwriteOld) {
 | 
			
		||||
      tmFifo->retrieve(&storeId);
 | 
			
		||||
      tmStore->deleteData(storeId);
 | 
			
		||||
@@ -221,6 +230,7 @@ ReturnValue_t TmTcBridge::handleStoredTm() {
 | 
			
		||||
    packetSentCounter++;
 | 
			
		||||
 | 
			
		||||
    if (tmFifo->empty()) {
 | 
			
		||||
      warningSwitch = true;
 | 
			
		||||
      tmStored = false;
 | 
			
		||||
    }
 | 
			
		||||
    tmStore->deleteData(storeId);
 | 
			
		||||
 
 | 
			
		||||
@@ -15,15 +15,14 @@ class TmTcBridge : public AcceptsTelemetryIF,
 | 
			
		||||
                   public ExecutableObjectIF,
 | 
			
		||||
                   public SystemObject {
 | 
			
		||||
 public:
 | 
			
		||||
  static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
 | 
			
		||||
  static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
 | 
			
		||||
  static constexpr uint8_t LIMIT_DOWNLINK_PACKETS_STORED = 200;
 | 
			
		||||
  static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500;
 | 
			
		||||
 | 
			
		||||
  static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
 | 
			
		||||
  static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
 | 
			
		||||
 | 
			
		||||
  TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination,
 | 
			
		||||
             object_id_t tmStoreId, object_id_t tcStoreId);
 | 
			
		||||
             uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId);
 | 
			
		||||
  ~TmTcBridge() override;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
@@ -42,7 +41,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
 | 
			
		||||
   * @return -@c returnvalue::OK if value was set successfully
 | 
			
		||||
   *         -@c returnvalue::FAILED otherwise, stored value stays the same
 | 
			
		||||
   */
 | 
			
		||||
  ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored);
 | 
			
		||||
  ReturnValue_t setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * This will set up the bridge to overwrite old data in the FIFO.
 | 
			
		||||
@@ -91,6 +90,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
 | 
			
		||||
  //! by default, so telemetry will be handled immediately.
 | 
			
		||||
  bool communicationLinkUp = true;
 | 
			
		||||
  bool tmStored = false;
 | 
			
		||||
  bool warningSwitch = true;
 | 
			
		||||
  bool overwriteOld = true;
 | 
			
		||||
  uint8_t packetSentCounter = 0;
 | 
			
		||||
 | 
			
		||||
@@ -152,7 +152,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
 | 
			
		||||
   */
 | 
			
		||||
  DynamicFIFO<store_address_t>* tmFifo = nullptr;
 | 
			
		||||
  uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
 | 
			
		||||
  uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
 | 
			
		||||
  unsigned int maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
#include "version.h"
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
#include "fsfw/FSFWVersion.h"
 | 
			
		||||
 | 
			
		||||
@@ -20,7 +21,7 @@ fsfw::Version::Version(int major, int minor, int revision, const char* addInfo)
 | 
			
		||||
 | 
			
		||||
void fsfw::Version::getVersion(char* str, size_t maxLen) const {
 | 
			
		||||
  size_t len = snprintf(str, maxLen, "%d.%d.%d", major, minor, revision);
 | 
			
		||||
  if (addInfo != nullptr) {
 | 
			
		||||
  if (addInfo != nullptr and std::strcmp(addInfo, "") != 0) {
 | 
			
		||||
    snprintf(str + len, maxLen - len, "-%s", addInfo);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -30,7 +31,7 @@ namespace fsfw {
 | 
			
		||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
 | 
			
		||||
std::ostream& operator<<(std::ostream& os, const Version& v) {
 | 
			
		||||
  os << v.major << "." << v.minor << "." << v.revision;
 | 
			
		||||
  if (v.addInfo != nullptr) {
 | 
			
		||||
  if (v.addInfo != nullptr and std::strcmp(v.addInfo, "") != 0) {
 | 
			
		||||
    os << "-" << v.addInfo;
 | 
			
		||||
  }
 | 
			
		||||
  return os;
 | 
			
		||||
 
 | 
			
		||||
@@ -325,12 +325,12 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
 | 
			
		||||
  // trickery here to calculate the raw values first
 | 
			
		||||
  int32_t fieldStrengthRawX = ((packet[1] << 24) | (packet[2] << 16) | (packet[3] << 8)) >> 8;
 | 
			
		||||
  int32_t fieldStrengthRawY = ((packet[4] << 24) | (packet[5] << 16) | (packet[6] << 8)) >> 8;
 | 
			
		||||
  int32_t fieldStrengthRawZ = ((packet[7] << 24) | (packet[8] << 16) | (packet[3] << 8)) >> 8;
 | 
			
		||||
  int32_t fieldStrengthRawZ = ((packet[7] << 24) | (packet[8] << 16) | (packet[9] << 8)) >> 8;
 | 
			
		||||
 | 
			
		||||
  // Now scale to physical value in microtesla
 | 
			
		||||
  float fieldStrengthX = fieldStrengthRawX * scaleFactorX;
 | 
			
		||||
  float fieldStrengthY = fieldStrengthRawY * scaleFactorX;
 | 
			
		||||
  float fieldStrengthZ = fieldStrengthRawZ * scaleFactorX;
 | 
			
		||||
  float fieldStrengthY = fieldStrengthRawY * scaleFactorY;
 | 
			
		||||
  float fieldStrengthZ = fieldStrengthRawZ * scaleFactorZ;
 | 
			
		||||
 | 
			
		||||
  if (periodicPrintout) {
 | 
			
		||||
    if (debugDivider.checkAndIncrement()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -180,10 +180,6 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
 | 
			
		||||
    sif::debug << "I2cComIF::requestReceiveMessage: Read " << readLen << " of " << requestLen
 | 
			
		||||
               << " bytes" << std::endl;
 | 
			
		||||
#endif
 | 
			
		||||
    return returnvalue::FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@
 | 
			
		||||
 */
 | 
			
		||||
void Factory::produceFrameworkObjects(void* args) {
 | 
			
		||||
  setStaticFrameworkObjectIds();
 | 
			
		||||
  new EventManager(objects::EVENT_MANAGER);
 | 
			
		||||
  new EventManager(objects::EVENT_MANAGER, 80);
 | 
			
		||||
  new HealthTable(objects::HEALTH_TABLE);
 | 
			
		||||
  new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -31,4 +31,7 @@ int customSetup() {
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int customTeardown() { return 0; }
 | 
			
		||||
int customTeardown() {
 | 
			
		||||
  ObjectManager::clear();
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,12 +27,7 @@ TEST_CASE("Action Helper", "[action]") {
 | 
			
		||||
    CHECK(not testDhMock.executeActionCalled);
 | 
			
		||||
    REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
 | 
			
		||||
    CHECK(testDhMock.executeActionCalled);
 | 
			
		||||
    // No message is sent if everything is alright.
 | 
			
		||||
    CHECK(not testMqMock.wasMessageSent());
 | 
			
		||||
    store_address_t invalidAddress;
 | 
			
		||||
    ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
 | 
			
		||||
    actionHelper.handleActionMessage(&actionMessage);
 | 
			
		||||
    CHECK(testMqMock.wasMessageSent());
 | 
			
		||||
    const uint8_t* ptr = nullptr;
 | 
			
		||||
    size_t size = 0;
 | 
			
		||||
    REQUIRE(ipcStore->getData(paramAddress, &ptr, &size) ==
 | 
			
		||||
@@ -44,6 +39,10 @@ TEST_CASE("Action Helper", "[action]") {
 | 
			
		||||
    for (uint8_t i = 0; i < 3; i++) {
 | 
			
		||||
      REQUIRE(ptr[i] == (i + 1));
 | 
			
		||||
    }
 | 
			
		||||
    // Action message without application data is also valid
 | 
			
		||||
    store_address_t invalidAddress;
 | 
			
		||||
    ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
 | 
			
		||||
    actionHelper.handleActionMessage(&actionMessage);
 | 
			
		||||
    testDhMock.clearBuffer();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -95,17 +94,5 @@ TEST_CASE("Action Helper", "[action]") {
 | 
			
		||||
    REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  SECTION("Missing IPC Data") {
 | 
			
		||||
    ActionMessage::setCommand(&actionMessage, testActionId, store_address_t::invalid());
 | 
			
		||||
    CHECK(not testDhMock.executeActionCalled);
 | 
			
		||||
    REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
 | 
			
		||||
    CommandMessage testMessage;
 | 
			
		||||
    REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK);
 | 
			
		||||
    REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::STEP_FAILED));
 | 
			
		||||
    REQUIRE(ActionMessage::getReturnCode(&testMessage) ==
 | 
			
		||||
            static_cast<uint32_t>(StorageManagerIF::ILLEGAL_STORAGE_ID));
 | 
			
		||||
    REQUIRE(ActionMessage::getStep(&testMessage) == 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  SECTION("Data Reply") {}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -97,7 +97,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
 | 
			
		||||
      REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
 | 
			
		||||
                                SerializeIF::Endianness::BIG) == returnvalue::OK);
 | 
			
		||||
      CHECK(serBuf[0] == 0x3f);
 | 
			
		||||
      CHECK(serBuf[3] == 0x99);
 | 
			
		||||
      CHECK(serBuf[3] == 0x88);
 | 
			
		||||
      REQUIRE(creator.getCrcFlag() == true);
 | 
			
		||||
      REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER);
 | 
			
		||||
      REQUIRE(creator.getLargeFileFlag() == true);
 | 
			
		||||
@@ -127,7 +127,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
 | 
			
		||||
      REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
 | 
			
		||||
      REQUIRE(creator.getSegmentationControl() == true);
 | 
			
		||||
      // Last three bits are 2 now (length of seq number) and bit 1 to bit 3 is 4 (len entity IDs)
 | 
			
		||||
      REQUIRE(serBuf[3] == 0b11001010);
 | 
			
		||||
      REQUIRE(serBuf[3] == 0b10111001);
 | 
			
		||||
      uint32_t entityId = 0;
 | 
			
		||||
      size_t deSerSize = 0;
 | 
			
		||||
      SerializeAdapter::deSerialize(&entityId, serBuf.data() + 4, &deSerSize,
 | 
			
		||||
@@ -175,7 +175,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
 | 
			
		||||
    REQUIRE(serBuf[1] == 0);
 | 
			
		||||
    REQUIRE(serBuf[2] == 0);
 | 
			
		||||
    // Entity and Transaction Sequence number are 1 byte large
 | 
			
		||||
    REQUIRE(serBuf[3] == 0b00010001);
 | 
			
		||||
    REQUIRE(serBuf[3] == 0b00000000);
 | 
			
		||||
    // Source ID
 | 
			
		||||
    REQUIRE(serBuf[4] == 0);
 | 
			
		||||
    // Transaction Seq Number
 | 
			
		||||
@@ -220,7 +220,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
 | 
			
		||||
    REQUIRE(serBuf[1] == 0);
 | 
			
		||||
    REQUIRE(serBuf[2] == 0);
 | 
			
		||||
    // Entity and Transaction Sequence number are 1 byte large
 | 
			
		||||
    REQUIRE(serBuf[3] == 0b00010001);
 | 
			
		||||
    REQUIRE(serBuf[3] == 0b00000000);
 | 
			
		||||
    REQUIRE(serSize == 7);
 | 
			
		||||
    // Deser call not strictly necessary
 | 
			
		||||
    auto reader = PduHeaderReader(serBuf.data(), serBuf.size());
 | 
			
		||||
@@ -270,7 +270,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
 | 
			
		||||
    REQUIRE(reader.parseData() == returnvalue::OK);
 | 
			
		||||
    // Everything except version bit flipped to one now
 | 
			
		||||
    REQUIRE(serBuf[0] == 0x3f);
 | 
			
		||||
    REQUIRE(serBuf[3] == 0b11001010);
 | 
			
		||||
    REQUIRE(serBuf[3] == 0b10111001);
 | 
			
		||||
    REQUIRE(reader.getWholePduSize() == 14);
 | 
			
		||||
 | 
			
		||||
    REQUIRE(reader.getCrcFlag() == true);
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@ TEST_CASE("File Data PDU", "[cfdp][pdu]") {
 | 
			
		||||
    // Bits 1 to 3 length of enitity IDs is 2
 | 
			
		||||
    // Bit 4: Segment metadata flag is set
 | 
			
		||||
    // Bit 5 to seven: length of transaction seq num is 2
 | 
			
		||||
    REQUIRE(fileDataBuffer[3] == 0b10101010);
 | 
			
		||||
    REQUIRE(fileDataBuffer[3] == 0b10011001);
 | 
			
		||||
    REQUIRE((fileDataBuffer[10] >> 6) &
 | 
			
		||||
            0b11 == cfdp::RecordContinuationState::CONTAINS_START_AND_END);
 | 
			
		||||
    // Segment metadata length
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ TEST_CASE("CFDP File Directive", "[cfdp][pdu]") {
 | 
			
		||||
    REQUIRE(serBuf[1] == 0);
 | 
			
		||||
    REQUIRE(serBuf[2] == 5);
 | 
			
		||||
    // Entity and Transaction Sequence number are 1 byte large
 | 
			
		||||
    REQUIRE(serBuf[3] == 0b00010001);
 | 
			
		||||
    REQUIRE(serBuf[3] == 0b00000000);
 | 
			
		||||
    // Source ID
 | 
			
		||||
    REQUIRE(serBuf[4] == 0);
 | 
			
		||||
    // Transaction Seq Number
 | 
			
		||||
@@ -82,4 +82,4 @@ TEST_CASE("CFDP File Directive", "[cfdp][pdu]") {
 | 
			
		||||
    // Invalid file directive
 | 
			
		||||
    REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELD);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,8 @@ TEST_CASE("CFDP Base", "[cfdp]") {
 | 
			
		||||
    // PDU data field length is 5 (4 + Directive code octet)
 | 
			
		||||
    REQUIRE(serBuf[1] == 0);
 | 
			
		||||
    REQUIRE(serBuf[2] == 5);
 | 
			
		||||
    // Entity and Transaction Sequence number are 1 byte large
 | 
			
		||||
    REQUIRE(serBuf[3] == 0b00010001);
 | 
			
		||||
    // Entity and Transaction Sequence number are 1 byte large, value minus one is stored
 | 
			
		||||
    REQUIRE(serBuf[3] == 0b00000000);
 | 
			
		||||
    // Source ID
 | 
			
		||||
    REQUIRE(serBuf[4] == 0);
 | 
			
		||||
    // Transaction Seq Number
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,9 @@ DeviceHandlerCommander::DeviceHandlerCommander(object_id_t objectId)
 | 
			
		||||
      QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DeviceHandlerCommander::~DeviceHandlerCommander() {}
 | 
			
		||||
DeviceHandlerCommander::~DeviceHandlerCommander() {
 | 
			
		||||
  QueueFactory::instance()->deleteMessageQueue(commandQueue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ReturnValue_t DeviceHandlerCommander::performOperation(uint8_t operationCode) {
 | 
			
		||||
  readCommandQueue();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,46 +1,38 @@
 | 
			
		||||
 | 
			
		||||
#ifdef LINUX
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#include <fsfw/osal/osal.h>
 | 
			
		||||
#include <fsfw/tasks/SemaphoreFactory.h>
 | 
			
		||||
#include <fsfw/timemanager/Stopwatch.h>
 | 
			
		||||
 | 
			
		||||
#include "catch.hpp"
 | 
			
		||||
#include "core/CatchDefinitions.h"
 | 
			
		||||
#include <catch2/catch_test_macros.hpp>
 | 
			
		||||
 | 
			
		||||
TEST_CASE("Binary Semaphore Test" , "[BinSemaphore]") {
 | 
			
		||||
        //perform set-up here
 | 
			
		||||
        SemaphoreIF* binSemaph = SemaphoreFactory::instance()->
 | 
			
		||||
                        createBinarySemaphore();
 | 
			
		||||
        REQUIRE(binSemaph != nullptr);
 | 
			
		||||
        SECTION("Simple Test") {
 | 
			
		||||
                // set-up is run for each section
 | 
			
		||||
                REQUIRE(binSemaph->getSemaphoreCounter() == 1);
 | 
			
		||||
                REQUIRE(binSemaph->release() ==
 | 
			
		||||
                                static_cast<int>(SemaphoreIF::SEMAPHORE_NOT_OWNED));
 | 
			
		||||
                REQUIRE(binSemaph->acquire(SemaphoreIF::POLLING) ==
 | 
			
		||||
                                result::OK);
 | 
			
		||||
                {
 | 
			
		||||
                        // not precise enough on linux.. should use clock instead..
 | 
			
		||||
                        //Stopwatch stopwatch(false);
 | 
			
		||||
                        //REQUIRE(binSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 5) ==
 | 
			
		||||
                        //		SemaphoreIF::SEMAPHORE_TIMEOUT);
 | 
			
		||||
                        //dur_millis_t time = stopwatch.stop();
 | 
			
		||||
                        //CHECK(time == 5);
 | 
			
		||||
                }
 | 
			
		||||
                REQUIRE(binSemaph->getSemaphoreCounter() == 0);
 | 
			
		||||
                REQUIRE(binSemaph->release() == result::OK);
 | 
			
		||||
        }
 | 
			
		||||
        SemaphoreFactory::instance()->deleteSemaphore(binSemaph);
 | 
			
		||||
        // perform tear-down here
 | 
			
		||||
// binary semaphores currently only supported on linux
 | 
			
		||||
#ifdef FSFW_OSAL_LINUX
 | 
			
		||||
 | 
			
		||||
TEST_CASE("Binary Semaphore Test", "[BinSemaphore]") {
 | 
			
		||||
  // perform set-up here
 | 
			
		||||
  SemaphoreIF* binSemaph = SemaphoreFactory::instance()->createBinarySemaphore();
 | 
			
		||||
  REQUIRE(binSemaph != nullptr);
 | 
			
		||||
  SECTION("Simple Test") {
 | 
			
		||||
    // set-up is run for each section
 | 
			
		||||
    REQUIRE(binSemaph->getSemaphoreCounter() == 1);
 | 
			
		||||
    REQUIRE(binSemaph->release() == static_cast<int>(SemaphoreIF::SEMAPHORE_NOT_OWNED));
 | 
			
		||||
    REQUIRE(binSemaph->acquire(SemaphoreIF::POLLING) == returnvalue::OK);
 | 
			
		||||
    {
 | 
			
		||||
      // not precise enough on linux.. should use clock instead..
 | 
			
		||||
      // Stopwatch stopwatch(false);
 | 
			
		||||
      // REQUIRE(binSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 5) ==
 | 
			
		||||
      //		SemaphoreIF::SEMAPHORE_TIMEOUT);
 | 
			
		||||
      // dur_millis_t time = stopwatch.stop();
 | 
			
		||||
      // CHECK(time == 5);
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE(binSemaph->getSemaphoreCounter() == 0);
 | 
			
		||||
    REQUIRE(binSemaph->release() == returnvalue::OK);
 | 
			
		||||
  }
 | 
			
		||||
  SemaphoreFactory::instance()->deleteSemaphore(binSemaph);
 | 
			
		||||
  // perform tear-down here
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_CASE("Counting Semaphore Test" , "[CountingSemaph]") {
 | 
			
		||||
        SECTION("Simple Test") {
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
TEST_CASE("Counting Semaphore Test", "[CountingSemaph]") {
 | 
			
		||||
  SECTION("Simple Test") {}
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
namespace addresses {
 | 
			
		||||
/* Logical addresses have uint32_t datatype */
 | 
			
		||||
enum logicalAddresses : address_t {};
 | 
			
		||||
enum LogicAddress : address_t {};
 | 
			
		||||
}  // namespace addresses
 | 
			
		||||
 | 
			
		||||
#endif /* CONFIG_DEVICES_LOGICALADDRESSES_H_ */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user