Merge remote-tracking branch 'upstream/development' into fsfw_update
This commit is contained in:
commit
b673cdfb50
137
CHANGELOG.md
137
CHANGELOG.md
@ -8,13 +8,43 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v6.0.0]
|
||||
## Fixes
|
||||
|
||||
- PUS Health Service: Size check for set health command.
|
||||
- PUS Health Service: Perform operation completion for announce health command.
|
||||
|
||||
# [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
|
||||
@ -24,22 +54,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
|
||||
@ -69,18 +159,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
|
||||
|
||||
@ -100,7 +213,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)
|
||||
|
||||
@ -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(
|
||||
|
96
automation/Jenkinsfile
vendored
96
automation/Jenkinsfile
vendored
@ -1,45 +1,87 @@
|
||||
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'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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()
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ EventManager::EventManager(object_id_t setObjectId)
|
||||
}
|
||||
|
||||
EventManager::~EventManager() {
|
||||
listenerList.clear();
|
||||
QueueFactory::instance()->deleteMessageQueue(eventReportQueue);
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
}
|
||||
@ -61,9 +62,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);
|
||||
}
|
||||
|
@ -31,6 +31,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,
|
||||
|
@ -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;
|
||||
|
@ -23,7 +23,7 @@ FailureIsolationBase::~FailureIsolationBase() {
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
manager->unsubscribeFromAllEvents(eventQueue->getId(), ownerId);
|
||||
manager->unregisterListener(eventQueue->getId());
|
||||
QueueFactory::instance()->deleteMessageQueue(eventQueue);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
};
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -41,6 +41,8 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
||||
static constexpr ReturnValue_t INVALID_TIME_WINDOW = returnvalue::makeCode(CLASS_ID, 2);
|
||||
static constexpr ReturnValue_t TIMESHIFTING_NOT_POSSIBLE = returnvalue::makeCode(CLASS_ID, 3);
|
||||
static constexpr ReturnValue_t INVALID_RELATIVE_TIME = returnvalue::makeCode(CLASS_ID, 4);
|
||||
static constexpr ReturnValue_t CONTAINED_TC_TOO_SMALL = returnvalue::makeCode(CLASS_ID, 5);
|
||||
static constexpr ReturnValue_t CONTAINED_TC_CRC_MISSMATCH = returnvalue::makeCode(CLASS_ID, 6);
|
||||
|
||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_11;
|
||||
|
||||
|
@ -2,9 +2,11 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/serialize/SerializeAdapter.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h"
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
|
||||
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
|
||||
@ -171,6 +173,14 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
if (size < PusTcIF::MIN_SIZE) {
|
||||
return CONTAINED_TC_TOO_SMALL;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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(
|
||||
TMTC_RECEPTION_QUEUE_DEPTH, 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);
|
||||
|
@ -17,7 +17,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
|
||||
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;
|
||||
@ -42,7 +42,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 +91,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 +153,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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -31,4 +31,7 @@ int customSetup() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int customTeardown() { return 0; }
|
||||
int customTeardown() {
|
||||
ObjectManager::clear();
|
||||
return 0;
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user