diff --git a/CHANGELOG.md b/CHANGELOG.md index 265e3129c..d3e03c4fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,24 +8,38 @@ and this project adheres to [Semantic Versioning](http://semver.org/). # [unreleased] -# [v6.0.0] +# [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 @@ -35,11 +49,43 @@ 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 - `CServiceHealthCommanding`: Add announce all health info implementation PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122 +- 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 @@ -51,17 +97,36 @@ and this project adheres to [Semantic Versioning](http://semver.org/). PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709 - Add new `UnsignedByteField` class PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660 +- publish documentation for development and master branch + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/681 +- Add Linux HAL options + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/663 +- Expand SerializeIF + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/656 +- PUS Service 11: Additional Safety Check + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/666 +- improvements for auto-formatter script + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/665 +- provide a weak print char impl + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/674 + +## Removed + +- now that doc server is up, remove markdown files + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/688 +- remove bsp specific code + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/679 ## Changes - `CService201HealthCommanding` renamed to `CServiceHealthCommanding`, service ID customizable now. `CServiceHealthCommanding` expects configuration struct `HealthServiceCfg` now - PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122 + PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725 - `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712 - Moved some container returnvalues to dedicated header and namespace - to they can be used without template specification. + so they can be used without template specification. PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707 - Remove default secondary header argument for `uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and @@ -91,18 +156,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 @@ -122,7 +210,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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9025537a9..5eddde7ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) @@ -196,13 +196,13 @@ message( ) # Check whether the user has already installed ETL first -find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET) +find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET) # Not installed, so use FetchContent to download and provide etl 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( diff --git a/scripts/check_release.py b/scripts/check_release.py new file mode 100755 index 000000000..eb5c89f90 --- /dev/null +++ b/scripts/check_release.py @@ -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() diff --git a/src/fsfw/cfdp/handler/DestHandler.cpp b/src/fsfw/cfdp/handler/DestHandler.cpp index b4d4af098..4ffa797ff 100644 --- a/src/fsfw/cfdp/handler/DestHandler.cpp +++ b/src/fsfw/cfdp/handler/DestHandler.cpp @@ -178,16 +178,25 @@ ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info) dp.user.fileSegmentRecvdIndication(segParams); } result = dp.user.vfs.writeToFile(fileOpParams, fileData); - if (offset.value() + fileSegmentLen > tp.progress) { - tp.progress = offset.value() + fileSegmentLen; - } if (result != returnvalue::OK) { // TODO: Proper Error handling #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "File write error" << std::endl; + sif::error << "cfdp::DestHandler: VFS file write error with code 0x" << std::hex << std::setw(2) + << result << std::endl; #endif + tp.vfsErrorCount++; + if (tp.vfsErrorCount < 3) { + // TODO: Provide execution step as parameter + fp.eventReporter->forwardEvent(events::FILESTORE_ERROR, static_cast(fsmRes.step), + result); + } + return result; } else { tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE; + tp.vfsErrorCount = 0; + } + if (offset.value() + fileSegmentLen > tp.progress) { + tp.progress = offset.value() + fileSegmentLen; } return result; } @@ -271,35 +280,55 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met return OK; } ReturnValue_t result = OK; - fsmRes.step = TransactionStep::TRANSACTION_START; - if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) { - fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED; - } else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) { - fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED; - } - tp.checksumType = info.getChecksumType(); - tp.closureRequested = info.isClosureRequested(); size_t sourceNameSize = 0; + const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize); - if (sourceNameSize > tp.sourceName.size()) { - // TODO: Warning, event etc. + if (sourceNameSize + 1 > tp.sourceName.size()) { + fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large"); return FAILED; } std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize); tp.sourceName[sourceNameSize] = '\0'; size_t destNameSize = 0; const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize); - if (destNameSize > tp.destName.size()) { - // TODO: Warning, event etc. + if (destNameSize + 1 > tp.destName.size()) { + fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large"); return FAILED; } std::memcpy(tp.destName.data(), destNamePtr, destNameSize); tp.destName[destNameSize] = '\0'; - reader.fillConfig(tp.pduConf); - tp.pduConf.direction = Direction::TOWARDS_SENDER; - tp.transactionId.entityId = tp.pduConf.sourceId; - tp.transactionId.seqNum = tp.pduConf.seqNum; - if (not dp.remoteCfgTable.getRemoteCfg(tp.pduConf.sourceId, &tp.remoteCfg)) { + + // If both dest name size and source name size are 0, we are dealing with a metadata only PDU, + // so there is no need to create a file or truncate an existing file + if (destNameSize > 0 and sourceNameSize > 0) { + FilesystemParams fparams(tp.destName.data()); + // handling to allow only specifying target directory. Example: + // Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt + if (dp.user.vfs.isDirectory(tp.destName.data())) { + result = tryBuildingAbsoluteDestName(destNameSize); + if (result != OK) { + return result; + } + } + if (dp.user.vfs.fileExists(fparams)) { + result = dp.user.vfs.truncateFile(fparams); + if (result != returnvalue::OK) { + fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error"); + return FAILED; + // TODO: Relevant for filestore rejection error? + } + } else { + result = dp.user.vfs.createFile(fparams); + if (result != OK) { + fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error"); + return FAILED; + // TODO: Relevant for filestore rejection error? + } + } + } + EntityId sourceId; + reader.getSourceId(sourceId); + if (not dp.remoteCfgTable.getRemoteCfg(sourceId, &tp.remoteCfg)) { // TODO: Warning, event etc. #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "cfdp::DestHandler" << __func__ @@ -308,22 +337,18 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met #endif return FAILED; } - // If both dest name size and source name size are 0, we are dealing with a metadata only PDU, - // so there is no need to create a file or truncate an existing file - if (destNameSize > 0 and sourceNameSize > 0) { - FilesystemParams fparams(tp.destName.data()); - // TODO: Filesystem errors? - if (dp.user.vfs.fileExists(fparams)) { - dp.user.vfs.truncateFile(fparams); - } else { - result = dp.user.vfs.createFile(fparams); - if (result != OK) { - // TODO: Handle FS error. This is probably a case for the filestore rejection mechanism of - // CFDP. - // In any case, it does not really make sense to continue here - } - } + fsmRes.step = TransactionStep::TRANSACTION_START; + if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) { + fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED; + } else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) { + fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED; } + tp.checksumType = info.getChecksumType(); + tp.closureRequested = info.isClosureRequested(); + reader.fillConfig(tp.pduConf); + tp.pduConf.direction = Direction::TOWARDS_SENDER; + tp.transactionId.entityId = tp.pduConf.sourceId; + tp.transactionId.seqNum = tp.pduConf.seqNum; fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS; MetadataRecvdParams params(tp.transactionId, tp.pduConf.sourceId); params.fileSize = tp.fileSize.getSize(); @@ -362,6 +387,37 @@ ReturnValue_t cfdp::DestHandler::handleTransferCompletion() { return OK; } +ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) { + char baseNameBuf[tp.destName.size()]{}; + FilesystemParams fparamsSrc(tp.sourceName.data()); + size_t baseNameLen = 0; + ReturnValue_t result = + dp.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf, sizeof(baseNameBuf), baseNameLen); + if (result != returnvalue::OK or baseNameLen == 0) { + fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name"); + return FAILED; + } + // Destination name + slash + base name + null termination + if (destNameSize + 1 + baseNameLen + 1 > tp.destName.size()) { + fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, + "dest filename too large after adding source base name"); + return FAILED; + } + tp.destName[destNameSize++] = '/'; + std::memcpy(tp.destName.data() + destNameSize, baseNameBuf, baseNameLen); + destNameSize += baseNameLen; + tp.destName[destNameSize++] = '\0'; + return OK; +} + +void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result, const char* info) { + fp.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR, + static_cast(fsmRes.step), result); +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "cfdp::DestHandler: " << info << std::endl; +#endif +} + void cfdp::DestHandler::finish() { tp.reset(); dp.packetListRef.clear(); diff --git a/src/fsfw/cfdp/handler/DestHandler.h b/src/fsfw/cfdp/handler/DestHandler.h index 5cef88d46..9057b3f56 100644 --- a/src/fsfw/cfdp/handler/DestHandler.h +++ b/src/fsfw/cfdp/handler/DestHandler.h @@ -84,7 +84,7 @@ enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN }; class DestHandler { public: - enum class TransactionStep { + enum class TransactionStep : uint8_t { IDLE = 0, TRANSACTION_START = 1, RECEIVING_FILE_DATA_PDUS = 2, @@ -157,11 +157,13 @@ class DestHandler { progress = 0; remoteCfg = nullptr; closureRequested = false; + vfsErrorCount = 0; checksumType = ChecksumType::NULL_CHECKSUM; } ChecksumType checksumType = ChecksumType::NULL_CHECKSUM; bool closureRequested = false; + uint16_t vfsErrorCount = 0; std::vector sourceName; std::vector destName; cfdp::FileSize fileSize; @@ -189,9 +191,11 @@ class DestHandler { ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData, size_t maxSize); ReturnValue_t handleTransferCompletion(); + ReturnValue_t tryBuildingAbsoluteDestName(size_t destNameSize); ReturnValue_t sendFinishedPdu(); ReturnValue_t noticeOfCompletion(); ReturnValue_t checksumVerification(); + void fileErrorHandler(Event event, ReturnValue_t result, const char* info); const FsmResult& updateFsmRes(uint8_t errors); void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx); void finish(); diff --git a/src/fsfw/cfdp/handler/defs.h b/src/fsfw/cfdp/handler/defs.h index 190fb67d1..5f17ca2dd 100644 --- a/src/fsfw/cfdp/handler/defs.h +++ b/src/fsfw/cfdp/handler/defs.h @@ -12,6 +12,9 @@ namespace events { static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW); static constexpr Event MSG_QUEUE_ERROR = event::makeEvent(SSID, 1, severity::LOW); static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity::LOW); +static constexpr Event FILESTORE_ERROR = event::makeEvent(SSID, 3, severity::LOW); +//! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name +static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, severity::LOW); } // namespace events diff --git a/src/fsfw/datapoollocal/LocalDataPoolManager.cpp b/src/fsfw/datapoollocal/LocalDataPoolManager.cpp index 67c2b4b87..f66a328c7 100644 --- a/src/fsfw/datapoollocal/LocalDataPoolManager.cpp +++ b/src/fsfw/datapoollocal/LocalDataPoolManager.cpp @@ -70,8 +70,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { return returnvalue::OK; } -ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(uint8_t nonDiagInvlFactor) { - setNonDiagnosticIntervalFactor(nonDiagInvlFactor); +ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation() { return initializeHousekeepingPoolEntriesOnce(); } @@ -661,10 +660,6 @@ ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(HousekeepingPacke return hkPacket.serialize(&dataPtr, serializedSize, maxSize, SerializeIF::Endianness::MACHINE); } -void LocalDataPoolManager::setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor) { - this->nonDiagnosticIntervalFactor = nonDiagInvlFactor; -} - void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) { sid_t sid = receiver.dataId.sid; LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); @@ -718,7 +713,7 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool ena if ((LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and enable) or (not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and not enable)) { - return REPORTING_STATUS_UNCHANGED; + return returnvalue::OK; } LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable); diff --git a/src/fsfw/datapoollocal/LocalDataPoolManager.h b/src/fsfw/datapoollocal/LocalDataPoolManager.h index 8f369ea06..65d58d590 100644 --- a/src/fsfw/datapoollocal/LocalDataPoolManager.h +++ b/src/fsfw/datapoollocal/LocalDataPoolManager.h @@ -102,7 +102,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces * @param nonDiagInvlFactor * @return */ - ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5); + ReturnValue_t initializeAfterTaskCreation(); /** * @brief This should be called in the periodic handler of the owner. @@ -152,17 +152,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces MessageQueueId_t targetQueueId, bool generateSnapshot) override; - /** - * Non-Diagnostics packets usually have a lower minimum sampling frequency - * than diagnostic packets. - * A factor can be specified to determine the minimum sampling frequency - * for non-diagnostic packets. The minimum sampling frequency of the - * diagnostics packets,which is usually jusst the period of the - * performOperation calls, is multiplied with that factor. - * @param factor - */ - void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor); - /** * @brief The manager is also able to handle housekeeping messages. * @details diff --git a/src/fsfw/datapoollocal/LocalPoolDataSetBase.cpp b/src/fsfw/datapoollocal/LocalPoolDataSetBase.cpp index 38aad828b..289954462 100644 --- a/src/fsfw/datapoollocal/LocalPoolDataSetBase.cpp +++ b/src/fsfw/datapoollocal/LocalPoolDataSetBase.cpp @@ -250,9 +250,8 @@ void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) { bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; } void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval, - dur_millis_t minimumPeriodicInterval, - uint8_t nonDiagIntervalFactor) { - periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, nonDiagIntervalFactor); + dur_millis_t minimumPeriodicInterval) { + periodicHelper->initialize(collectionInterval, minimumPeriodicInterval); } void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; } diff --git a/src/fsfw/datapoollocal/LocalPoolDataSetBase.h b/src/fsfw/datapoollocal/LocalPoolDataSetBase.h index 9166cf34f..7aec77eaa 100644 --- a/src/fsfw/datapoollocal/LocalPoolDataSetBase.h +++ b/src/fsfw/datapoollocal/LocalPoolDataSetBase.h @@ -191,8 +191,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF { */ bool reportingEnabled = false; - void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval, - uint8_t nonDiagIntervalFactor = 5); + void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval); /** * If the valid state of a dataset is always relevant to the whole diff --git a/src/fsfw/datapoollocal/internal/LocalPoolDataSetAttorney.h b/src/fsfw/datapoollocal/internal/LocalPoolDataSetAttorney.h index e7dbd0c70..6f9a3b27b 100644 --- a/src/fsfw/datapoollocal/internal/LocalPoolDataSetAttorney.h +++ b/src/fsfw/datapoollocal/internal/LocalPoolDataSetAttorney.h @@ -12,10 +12,8 @@ class LocalPoolDataSetAttorney { static bool isDiagnostics(LocalPoolDataSetBase& set) { return set.isDiagnostics(); } static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval, - uint32_t minimumPeriodicIntervalMs, - uint8_t nonDiagIntervalFactor = 5) { - set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs, - nonDiagIntervalFactor); + uint32_t minimumPeriodicIntervalMs) { + set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs); } static void setReportingEnabled(LocalPoolDataSetBase& set, bool enabled) { diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp index b2505344e..99b7496c6 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp @@ -58,12 +58,7 @@ void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) { this->hkDestination = hkDestination; } -void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId, - lp_id_t heaterRequestPoolId, - uint32_t thermalSetId) { - thermalSet = - new DeviceHandlerThermalSet(this, thermalSetId, thermalStatePoolId, heaterRequestPoolId); -} +void DeviceHandlerBase::enableThermalModule(ThermalStateCfg cfg) { this->thermalStateCfg = cfg; } DeviceHandlerBase::~DeviceHandlerBase() { if (comCookie != nullptr) { @@ -227,12 +222,11 @@ ReturnValue_t DeviceHandlerBase::initialize() { fillCommandAndReplyMap(); if (thermalSet != nullptr) { + PoolReadGuard pg(thermalSet); // Set temperature target state to NON_OP. - result = thermalSet->read(); - if (result == returnvalue::OK) { + if (pg.getReadResult() == returnvalue::OK) { thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; thermalSet->heaterRequest.setValid(true); - thermalSet->commit(); } } @@ -382,7 +376,7 @@ void DeviceHandlerBase::doStateMachine() { } ReturnValue_t switchState = getStateOfSwitches(); if ((switchState == PowerSwitchIF::SWITCH_OFF) || (switchState == NO_SWITCH)) { - setMode(_MODE_SWITCH_IS_OFF); + setMode(MODE_OFF, SUBMODE_NONE); } } break; case MODE_OFF: @@ -395,9 +389,6 @@ void DeviceHandlerBase::doStateMachine() { case MODE_NORMAL: case MODE_ERROR_ON: break; - case _MODE_SWITCH_IS_OFF: - setMode(MODE_OFF, SUBMODE_NONE); - break; default: triggerEvent(OBJECT_IN_INVALID_MODE, mode, submode); setMode(_MODE_POWER_DOWN, 0); @@ -574,6 +565,9 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { */ if (newMode == MODE_ON and continueToNormal) { continueToNormal = false; + // TODO: Check whether the following two lines are okay to do so. + transitionSourceMode = MODE_ON; + transitionSourceSubMode = submode; mode = _MODE_TO_NORMAL; return; } @@ -594,12 +588,12 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { Clock::getUptime(&timeoutStart); if (mode == MODE_OFF and thermalSet != nullptr) { - ReturnValue_t result = thermalSet->read(); - if (result == returnvalue::OK) { + PoolReadGuard pg(thermalSet); + if (pg.getReadResult() == returnvalue::OK) { if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) { thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; } - thermalSet->heaterRequest.commit(PoolVariableIF::VALID); + thermalSet->heaterRequest.setValid(true); } } /* TODO: This will probably be done by the LocalDataPoolManager now */ @@ -1088,8 +1082,8 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_ // Do not check thermal state for MODE_RAW if ((mode == MODE_OFF) and ((commandedMode == MODE_ON) or (commandedMode == MODE_NORMAL)) and (thermalSet != nullptr)) { - ReturnValue_t result = thermalSet->read(); - if (result == returnvalue::OK) { + PoolReadGuard pg(thermalSet); + if (pg.getReadResult() == returnvalue::OK) { if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and (not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) { triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value); @@ -1150,11 +1144,10 @@ void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode, Submode_t childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON); triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode); if (thermalSet != nullptr) { - ReturnValue_t result = thermalSet->read(); - if (result == returnvalue::OK) { + PoolReadGuard pg(thermalSet); + if (pg.getReadResult() == returnvalue::OK) { if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL; - thermalSet->commit(); } } } @@ -1477,11 +1470,11 @@ void DeviceHandlerBase::performOperationHook() {} ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { - if (thermalSet != nullptr) { - localDataPoolMap.emplace(thermalSet->thermalStatePoolId, - new PoolEntry); - localDataPoolMap.emplace(thermalSet->heaterRequestPoolId, - new PoolEntry); + if (thermalStateCfg.has_value()) { + localDataPoolMap.emplace(thermalStateCfg.value().thermalStatePoolId, + new PoolEntry()); + localDataPoolMap.emplace(thermalStateCfg.value().thermalRequestPoolId, + new PoolEntry()); } return returnvalue::OK; } @@ -1494,6 +1487,10 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() { } this->poolManager.initializeAfterTaskCreation(); + if (thermalStateCfg.has_value()) { + ThermalStateCfg& cfg = thermalStateCfg.value(); + thermalSet = new DeviceHandlerThermalSet(this, cfg); + } if (setStartupImmediately) { startTransition(MODE_ON, getInitialSubmode()); } diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.h b/src/fsfw/devicehandlers/DeviceHandlerBase.h index b06815d17..57e9d9820 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.h +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.h @@ -2,6 +2,7 @@ #define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ #include +#include #include "DeviceCommunicationIF.h" #include "DeviceHandlerFailureIsolation.h" @@ -149,11 +150,6 @@ class DeviceHandlerBase : public DeviceHandlerIF, //! has been commanded on and the handler waits for it to be on. //! When the switch is on, the mode changes to @c _MODE_TO_ON. static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; - //! This is a transitional state which can not be commanded. The switch has - //! been commanded off and is off now. This state is only to do an RMAP - //! cycle once more where the doSendRead() function will set the mode to - //! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board. - static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; void setHkDestination(object_id_t hkDestination); @@ -163,13 +159,8 @@ class DeviceHandlerBase : public DeviceHandlerIF, * The device handler will then take care of creating local pool entries * for the device thermal state and device heating request. * Custom local pool IDs can be assigned as well. - * @param thermalStatePoolId - * @param thermalRequestPoolId */ - void setThermalStateRequestPoolIds( - lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID, - lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID, - uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID); + void enableThermalModule(ThermalStateCfg cfg); ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override; ModeTreeChildIF &getModeTreeChildIF() override; @@ -931,6 +922,8 @@ class DeviceHandlerBase : public DeviceHandlerIF, //! Object which may be the root cause of an identified fault. static object_id_t defaultFdirParentId; + std::optional thermalStateCfg; + /** * @brief Send a reply to a received device handler command. * diff --git a/src/fsfw/devicehandlers/DeviceHandlerIF.h b/src/fsfw/devicehandlers/DeviceHandlerIF.h index 474c3a750..5e1fdd2f7 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerIF.h +++ b/src/fsfw/devicehandlers/DeviceHandlerIF.h @@ -136,4 +136,10 @@ class DeviceHandlerIF { virtual MessageQueueId_t getCommandQueue() const = 0; }; +struct ThermalStateCfg { + lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID; + lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID; + uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID; +}; + #endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */ diff --git a/src/fsfw/devicehandlers/DeviceHandlerThermalSet.h b/src/fsfw/devicehandlers/DeviceHandlerThermalSet.h index 944d7c0f8..49ebd5f46 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerThermalSet.h +++ b/src/fsfw/devicehandlers/DeviceHandlerThermalSet.h @@ -7,27 +7,21 @@ class DeviceHandlerThermalSet : public StaticLocalDataSet<2> { public: - DeviceHandlerThermalSet( - HasLocalDataPoolIF* hkOwner, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID, - lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID, - lp_id_t heaterRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID) - : DeviceHandlerThermalSet(hkOwner->getObjectId(), setId, thermalStateId, heaterRequestId) {} + DeviceHandlerThermalSet(HasLocalDataPoolIF* hkOwner, ThermalStateCfg cfg) + : DeviceHandlerThermalSet(hkOwner->getObjectId(), cfg) {} - DeviceHandlerThermalSet( - object_id_t deviceHandler, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID, - lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID, - lp_id_t thermalStateRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID) - : StaticLocalDataSet(sid_t(deviceHandler, setId)), - thermalStatePoolId(thermalStateId), - heaterRequestPoolId(thermalStateRequestId) {} + DeviceHandlerThermalSet(object_id_t deviceHandler, ThermalStateCfg cfg) + : StaticLocalDataSet(sid_t(deviceHandler, cfg.thermalSetId)), + thermalStatePoolId(cfg.thermalStatePoolId), + heaterRequestPoolId(cfg.thermalRequestPoolId) {} const lp_id_t thermalStatePoolId; const lp_id_t heaterRequestPoolId; lp_var_t thermalState = - lp_var_t(thermalStatePoolId, sid.objectId, this); + lp_var_t(sid.objectId, thermalStatePoolId, this); lp_var_t heaterRequest = - lp_var_t(heaterRequestPoolId, sid.objectId, this); + lp_var_t(sid.objectId, heaterRequestPoolId, this); }; #endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_ */ diff --git a/src/fsfw/events/EventManager.cpp b/src/fsfw/events/EventManager.cpp index ab9991585..f2a099ed8 100644 --- a/src/fsfw/events/EventManager.cpp +++ b/src/fsfw/events/EventManager.cpp @@ -15,12 +15,12 @@ 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(); auto mqArgs = MqArgs(setObjectId, static_cast(this)); eventReportQueue = QueueFactory::instance()->createMessageQueue( - MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs); + eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs); } EventManager::~EventManager() { diff --git a/src/fsfw/events/EventManager.h b/src/fsfw/events/EventManager.h index 555afa0ed..9064adda2 100644 --- a/src/fsfw/events/EventManager.h +++ b/src/fsfw/events/EventManager.h @@ -21,9 +21,9 @@ extern const char* translateEvents(Event event); class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject { public: - static const uint16_t MAX_EVENTS_PER_CYCLE = 80; + static const uint16_t DEFAULT_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); diff --git a/src/fsfw/events/fwSubsystemIdRanges.h b/src/fsfw/events/fwSubsystemIdRanges.h index 574ea0702..e395c2f96 100644 --- a/src/fsfw/events/fwSubsystemIdRanges.h +++ b/src/fsfw/events/fwSubsystemIdRanges.h @@ -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, diff --git a/src/fsfw/fdir/FaultCounter.cpp b/src/fsfw/fdir/FaultCounter.cpp index eea088173..9ef359aa8 100644 --- a/src/fsfw/fdir/FaultCounter.cpp +++ b/src/fsfw/fdir/FaultCounter.cpp @@ -68,7 +68,7 @@ ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId, parameterWrapper->set(faultCount); break; case ParameterIds::TIMEOUT: - parameterWrapper->set(timer.timeout); + parameterWrapper->set(timer.getTimeoutMs()); break; default: return INVALID_IDENTIFIER_ID; diff --git a/src/fsfw/filesystem/HasFileSystemIF.h b/src/fsfw/filesystem/HasFileSystemIF.h index 24400b1c0..a507938e3 100644 --- a/src/fsfw/filesystem/HasFileSystemIF.h +++ b/src/fsfw/filesystem/HasFileSystemIF.h @@ -74,6 +74,12 @@ class HasFileSystemIF { return MessageQueueIF::NO_QUEUE; } + // Get the base filename without the full directory path + virtual ReturnValue_t getBaseFilename(FilesystemParams params, char* nameBuf, size_t maxLen, + size_t& baseNameLen) = 0; + + virtual bool isDirectory(const char* path) = 0; + virtual bool fileExists(FilesystemParams params) = 0; /** diff --git a/src/fsfw/housekeeping/PeriodicHousekeepingHelper.cpp b/src/fsfw/housekeeping/PeriodicHousekeepingHelper.cpp index 0c2bef96d..b39e45c36 100644 --- a/src/fsfw/housekeeping/PeriodicHousekeepingHelper.cpp +++ b/src/fsfw/housekeeping/PeriodicHousekeepingHelper.cpp @@ -8,10 +8,8 @@ PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* own : owner(owner) {} void PeriodicHousekeepingHelper::initialize(float collectionInterval, - dur_millis_t minimumPeriodicInterval, - uint8_t nonDiagIntervalFactor) { + dur_millis_t minimumPeriodicInterval) { this->minimumPeriodicInterval = minimumPeriodicInterval; - this->nonDiagIntervalFactor = nonDiagIntervalFactor; collectionIntervalTicks = intervalSecondsToIntervalTicks(collectionInterval); /* This will cause a checkOpNecessary call to be true immediately. I think it's okay if a HK packet is generated immediately instead of waiting one generation cycle. */ @@ -36,42 +34,17 @@ uint32_t PeriodicHousekeepingHelper::intervalSecondsToIntervalTicks( if (owner == nullptr) { return 0; } - bool isDiagnostics = owner->isDiagnostics(); /* Avoid division by zero */ if (minimumPeriodicInterval == 0) { - if (isDiagnostics) { - /* Perform operation each cycle */ - return 1; - } else { - return nonDiagIntervalFactor; - } + /* Perform operation each cycle */ + return 1; + } else { dur_millis_t intervalInMs = collectionIntervalSeconds * 1000; uint32_t divisor = minimumPeriodicInterval; - if (not isDiagnostics) { - /* We need to multiply the divisor because non-diagnostics only - allow a multiple of the minimum periodic interval */ - divisor *= nonDiagIntervalFactor; - } uint32_t ticks = std::ceil(static_cast(intervalInMs) / divisor); - if (not isDiagnostics) { - /* Now we need to multiply the calculated ticks with the factor as as well - because the minimum tick count to generate a non-diagnostic is the factor itself. - Example calculation for non-diagnostic with - 0.4 second interval and 0.2 second task interval. - Resultant tick count of 5 is equal to operation each second. - - Examle calculation for non-diagnostic with 2.0 second interval and 0.2 second - task interval. - Resultant tick count of 10 is equal to operatin every 2 seconds. - - Example calculation for diagnostic with 0.4 second interval and 0.3 - second task interval. Resulting tick count of 2 is equal to operation - every 0.6 seconds. */ - ticks *= nonDiagIntervalFactor; - } return ticks; } } diff --git a/src/fsfw/housekeeping/PeriodicHousekeepingHelper.h b/src/fsfw/housekeeping/PeriodicHousekeepingHelper.h index 8b6245ba6..1ec0febfa 100644 --- a/src/fsfw/housekeeping/PeriodicHousekeepingHelper.h +++ b/src/fsfw/housekeeping/PeriodicHousekeepingHelper.h @@ -11,8 +11,7 @@ class PeriodicHousekeepingHelper { public: PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner); - void initialize(float collectionInterval, dur_millis_t minimumPeriodicInterval, - uint8_t nonDiagIntervalFactor); + void initialize(float collectionInterval, dur_millis_t minimumPeriodicInterval); void changeCollectionInterval(float newInterval); float getCollectionIntervalInSeconds() const; @@ -20,7 +19,6 @@ class PeriodicHousekeepingHelper { private: LocalPoolDataSetBase* owner = nullptr; - uint8_t nonDiagIntervalFactor = 0; uint32_t intervalSecondsToIntervalTicks(float collectionIntervalSeconds); float intervalTicksToSeconds(uint32_t collectionInterval) const; diff --git a/src/fsfw/ipc/MutexGuard.h b/src/fsfw/ipc/MutexGuard.h index f6d2f25f3..9887f3965 100644 --- a/src/fsfw/ipc/MutexGuard.h +++ b/src/fsfw/ipc/MutexGuard.h @@ -7,14 +7,17 @@ class MutexGuard { public: MutexGuard(MutexIF* mutex, MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::BLOCKING, - uint32_t timeoutMs = 0) + uint32_t timeoutMs = 0, const char* context = nullptr) : internalMutex(mutex) { + if (context == nullptr) { + context = "unknown"; + } if (mutex == nullptr) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "MutexGuard: Passed mutex is invalid!" << std::endl; + sif::error << "MutexGuard::" << context << ": Passed mutex is invalid!" << std::endl; #else - sif::printError("MutexGuard: Passed mutex is invalid!\n"); + sif::printError("MutexGuard::%s: Passed mutex is invalid!\n", context); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ return; @@ -23,11 +26,11 @@ class MutexGuard { #if FSFW_VERBOSE_LEVEL >= 1 if (result == MutexIF::MUTEX_TIMEOUT) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "MutexGuard: Lock of mutex failed with timeout of " << timeoutMs - << " milliseconds!" << std::endl; + sif::error << "MutexGuard::" << context << ": Lock of mutex failed with timeout of " + << timeoutMs << " milliseconds!" << std::endl; #else - sif::printError("MutexGuard: Lock of mutex failed with timeout of %lu milliseconds\n", - timeoutMs); + sif::printError("MutexGuard::%s: Lock of mutex failed with timeout of %lu milliseconds\n", + context, timeoutMs); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ } else if (result != returnvalue::OK) { diff --git a/src/fsfw/modes/ModeMessage.cpp b/src/fsfw/modes/ModeMessage.cpp index 0d7eaeea3..fbfb71aae 100644 --- a/src/fsfw/modes/ModeMessage.cpp +++ b/src/fsfw/modes/ModeMessage.cpp @@ -35,6 +35,8 @@ void ModeMessage::setModeAnnounceMessage(CommandMessage& message, bool recursive message.setCommand(cmd); } -void ModeMessage::setCmdModeModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode) { +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); } diff --git a/src/fsfw/modes/ModeMessage.h b/src/fsfw/modes/ModeMessage.h index 89203f6ec..9a3c2cc01 100644 --- a/src/fsfw/modes/ModeMessage.h +++ b/src/fsfw/modes/ModeMessage.h @@ -38,14 +38,15 @@ class ModeMessage { ModeMessage() = delete; - static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode, - Submode_t submode); static Mode_t getMode(const CommandMessage* message); static Submode_t getSubmode(const CommandMessage* message); static ReturnValue_t getCantReachModeReason(const CommandMessage* message); - static void setCmdModeModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode); + 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); }; diff --git a/src/fsfw/objectmanager/frameworkObjects.h b/src/fsfw/objectmanager/frameworkObjects.h index 9487147d9..bf153cae9 100644 --- a/src/fsfw/objectmanager/frameworkObjects.h +++ b/src/fsfw/objectmanager/frameworkObjects.h @@ -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, diff --git a/src/fsfw/osal/common/TcpIpBase.cpp b/src/fsfw/osal/common/TcpIpBase.cpp index 486a5171f..3e760f0e2 100644 --- a/src/fsfw/osal/common/TcpIpBase.cpp +++ b/src/fsfw/osal/common/TcpIpBase.cpp @@ -41,6 +41,7 @@ int TcpIpBase::closeSocket(socket_t socket) { #elif defined(PLATFORM_UNIX) return close(socket); #endif + return -1; } int TcpIpBase::getLastSocketError() { @@ -49,4 +50,5 @@ int TcpIpBase::getLastSocketError() { #elif defined(PLATFORM_UNIX) return errno; #endif + return 0; } diff --git a/src/fsfw/osal/common/TcpTmTcBridge.cpp b/src/fsfw/osal/common/TcpTmTcBridge.cpp index f99a8bc19..0bf3ab28d 100644 --- a/src/fsfw/osal/common/TcpTmTcBridge.cpp +++ b/src/fsfw/osal/common/TcpTmTcBridge.cpp @@ -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(); diff --git a/src/fsfw/osal/common/TcpTmTcBridge.h b/src/fsfw/osal/common/TcpTmTcBridge.h index 504592cc3..b330ba2ae 100644 --- a/src/fsfw/osal/common/TcpTmTcBridge.h +++ b/src/fsfw/osal/common/TcpTmTcBridge.h @@ -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(); diff --git a/src/fsfw/osal/common/UdpTmTcBridge.cpp b/src/fsfw/osal/common/UdpTmTcBridge.cpp index c0848ceba..d6014ec78 100644 --- a/src/fsfw/osal/common/UdpTmTcBridge.cpp +++ b/src/fsfw/osal/common/UdpTmTcBridge.cpp @@ -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; } diff --git a/src/fsfw/osal/common/UdpTmTcBridge.h b/src/fsfw/osal/common/UdpTmTcBridge.h index 92829c468..ce8adb4c8 100644 --- a/src/fsfw/osal/common/UdpTmTcBridge.h +++ b/src/fsfw/osal/common/UdpTmTcBridge.h @@ -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; diff --git a/src/fsfw/osal/host/Clock.cpp b/src/fsfw/osal/host/Clock.cpp index dbf6529c9..2a3c94bc8 100644 --- a/src/fsfw/osal/host/Clock.cpp +++ b/src/fsfw/osal/host/Clock.cpp @@ -47,7 +47,32 @@ ReturnValue_t Clock::setClock(const timeval* time) { return returnvalue::OK; } -ReturnValue_t Clock::getClock_timeval(timeval* time) { +ReturnValue_t Clock::getClockMonotonic(timeval* time) { +#if defined(PLATFORM_WIN) + // TODO: Implement with std::chrono::steady_clock.. or in some other way. I am not even sure + // whether this is possible with steady_clock. The conversion we have to do here just to be + // generic is kind of awkward.. + return returnvalue::FAILED; +#elif defined(PLATFORM_UNIX) + timespec timeMonotonic; + int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic); + if (status != 0) { + return returnvalue::FAILED; + } + time->tv_sec = timeMonotonic.tv_sec; + time->tv_usec = timeMonotonic.tv_nsec / 1000.0; + return returnvalue::OK; +#else +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl; +#else + sif::printWarning("Clock::getUptime: Not implemented for found OS!\n"); +#endif + return returnvalue::FAILED; +#endif +} + +ReturnValue_t Clock::getClock(timeval* time) { #if defined(PLATFORM_WIN) auto now = std::chrono::system_clock::now(); auto secondsChrono = std::chrono::time_point_cast(now); @@ -75,6 +100,8 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) { #endif } +ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); } + ReturnValue_t Clock::getClock_usecs(uint64_t* time) { if (time == nullptr) { return returnvalue::FAILED; diff --git a/src/fsfw/osal/linux/Clock.cpp b/src/fsfw/osal/linux/Clock.cpp index bfdcf4e20..fd861da23 100644 --- a/src/fsfw/osal/linux/Clock.cpp +++ b/src/fsfw/osal/linux/Clock.cpp @@ -42,7 +42,7 @@ ReturnValue_t Clock::setClock(const timeval* time) { return returnvalue::OK; } -ReturnValue_t Clock::getClock_timeval(timeval* time) { +ReturnValue_t Clock::getClock(timeval* time) { timespec timeUnix{}; int status = clock_gettime(CLOCK_REALTIME, &timeUnix); if (status != 0) { @@ -53,6 +53,8 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) { return returnvalue::OK; } +ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); } + ReturnValue_t Clock::getClock_usecs(uint64_t* time) { timeval timeVal{}; ReturnValue_t result = getClock_timeval(&timeVal); @@ -64,6 +66,17 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) { return returnvalue::OK; } +ReturnValue_t Clock::getClockMonotonic(timeval* time) { + timespec timeMonotonic{}; + int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic); + if (status != 0) { + return returnvalue::FAILED; + } + time->tv_sec = timeMonotonic.tv_sec; + time->tv_usec = timeMonotonic.tv_nsec / 1000.0; + return returnvalue::OK; +} + timeval Clock::getUptime() { timeval uptime{}; auto result = getUptime(&uptime); @@ -79,11 +92,16 @@ 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. diff --git a/src/fsfw/osal/rtems/SemaphoreFactory.cpp b/src/fsfw/osal/rtems/SemaphoreFactory.cpp index 35099ddce..1e470f40c 100644 --- a/src/fsfw/osal/rtems/SemaphoreFactory.cpp +++ b/src/fsfw/osal/rtems/SemaphoreFactory.cpp @@ -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" diff --git a/src/fsfw/power/Fuse.h b/src/fsfw/power/Fuse.h index e8b86cfde..c1b35899c 100644 --- a/src/fsfw/power/Fuse.h +++ b/src/fsfw/power/Fuse.h @@ -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. diff --git a/src/fsfw/power/PowerSwitchIF.h b/src/fsfw/power/PowerSwitchIF.h index 437462189..0b331e118 100644 --- a/src/fsfw/power/PowerSwitchIF.h +++ b/src/fsfw/power/PowerSwitchIF.h @@ -28,7 +28,9 @@ class PowerSwitchIF { static const ReturnValue_t SWITCH_TIMEOUT = MAKE_RETURN_CODE(2); static const ReturnValue_t FUSE_ON = MAKE_RETURN_CODE(3); static const ReturnValue_t FUSE_OFF = MAKE_RETURN_CODE(4); - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_2; + static const ReturnValue_t SWITCH_UNKNOWN = MAKE_RETURN_CODE(5); + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF; //!< Someone detected that a switch went off which shouldn't. Severity: //!< Low, Parameter1: switchId1, Parameter2: switchId2 static const Event SWITCH_WENT_OFF = MAKE_EVENT(0, severity::LOW); @@ -50,6 +52,7 @@ class PowerSwitchIF { * @return * - @c SWITCH_ON if the specified switch is on. * - @c SWITCH_OFF if the specified switch is off. + * - @c SWITCH_UNKNOWN if the state of the specified switch is unknown. * - @c returnvalue::FAILED if an error occured */ virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const = 0; diff --git a/src/fsfw/power/PowerSwitcherComponent.cpp b/src/fsfw/power/PowerSwitcherComponent.cpp index b07a7296b..39a8a2d0f 100644 --- a/src/fsfw/power/PowerSwitcherComponent.cpp +++ b/src/fsfw/power/PowerSwitcherComponent.cpp @@ -2,6 +2,7 @@ #include #include +#include PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher, power::Switch_t pwrSwitch) @@ -28,6 +29,9 @@ ReturnValue_t PowerSwitcherComponent::performOperation(uint8_t opCode) { continue; } } + if (getHealth() == FAULTY) { + performFaultyOperation(); + } if (switcher.active()) { switcher.doStateMachine(); auto currState = switcher.getState(); @@ -111,9 +115,11 @@ const HasHealthIF* PowerSwitcherComponent::getOptHealthIF() const { return this; const HasModesIF& PowerSwitcherComponent::getModeIF() const { return *this; } ReturnValue_t PowerSwitcherComponent::connectModeTreeParent(HasModeTreeChildrenIF& parent) { - return parent.registerChild(*this); + return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper); } object_id_t PowerSwitcherComponent::getObjectId() const { return SystemObject::getObjectId(); } ModeTreeChildIF& PowerSwitcherComponent::getModeTreeChildIF() { return *this; } + +void PowerSwitcherComponent::performFaultyOperation() {} diff --git a/src/fsfw/power/PowerSwitcherComponent.h b/src/fsfw/power/PowerSwitcherComponent.h index 38dddc376..d6fc06cd7 100644 --- a/src/fsfw/power/PowerSwitcherComponent.h +++ b/src/fsfw/power/PowerSwitcherComponent.h @@ -1,5 +1,4 @@ -#ifndef _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ -#define _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ +#pragma once #include #include @@ -37,9 +36,11 @@ class PowerSwitcherComponent : public SystemObject, ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override; ModeTreeChildIF &getModeTreeChildIF() override; + protected: + PowerSwitcher switcher; + private: MessageQueueIF *queue = nullptr; - PowerSwitcher switcher; Mode_t mode = MODE_OFF; Submode_t submode = 0; @@ -49,24 +50,23 @@ class PowerSwitcherComponent : public SystemObject, void setMode(Mode_t newMode, Submode_t newSubmode); - virtual ReturnValue_t performOperation(uint8_t opCode) override; + ReturnValue_t performOperation(uint8_t opCode) override; ReturnValue_t initialize() override; - MessageQueueId_t getCommandQueue() const override; + [[nodiscard]] MessageQueueId_t getCommandQueue() const override; void getMode(Mode_t *mode, Submode_t *submode) override; ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode) override; void startTransition(Mode_t mode, Submode_t submode) override; + virtual void performFaultyOperation(); void setToExternalControl() override; void announceMode(bool recursive) override; ReturnValue_t setHealth(HealthState health) override; HasHealthIF::HealthState getHealth() override; - object_id_t getObjectId() const override; - const HasHealthIF *getOptHealthIF() const override; - const HasModesIF &getModeIF() const override; + [[nodiscard]] object_id_t getObjectId() const override; + [[nodiscard]] const HasHealthIF *getOptHealthIF() const override; + [[nodiscard]] const HasModesIF &getModeIF() const override; }; - -#endif /* _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ */ diff --git a/src/fsfw/pus/CService200ModeCommanding.cpp b/src/fsfw/pus/CService200ModeCommanding.cpp index f5928be79..0dbdedfe0 100644 --- a/src/fsfw/pus/CService200ModeCommanding.cpp +++ b/src/fsfw/pus/CService200ModeCommanding.cpp @@ -19,7 +19,7 @@ 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: @@ -54,27 +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) { - ReturnValue_t result = returnvalue::OK; - if (subservice == Subservice::COMMAND_MODE_ANNCOUNCE or - subservice == Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY) { - bool recursive = true; - if (subservice == Subservice::COMMAND_MODE_ANNCOUNCE) { - recursive = false; - } - ModeMessage::setModeAnnounceMessage(*message, recursive); - } else { - 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()); + 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; } - - return result; } ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply, @@ -85,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); diff --git a/src/fsfw/pus/CService200ModeCommanding.h b/src/fsfw/pus/CService200ModeCommanding.h index 830e5950e..cf2baf7ea 100644 --- a/src/fsfw/pus/CService200ModeCommanding.h +++ b/src/fsfw/pus/CService200ModeCommanding.h @@ -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, diff --git a/src/fsfw/pus/CServiceHealthCommanding.cpp b/src/fsfw/pus/CServiceHealthCommanding.cpp index 57b704fdf..3ced4ffb9 100644 --- a/src/fsfw/pus/CServiceHealthCommanding.cpp +++ b/src/fsfw/pus/CServiceHealthCommanding.cpp @@ -10,9 +10,23 @@ CServiceHealthCommanding::CServiceHealthCommanding(HealthServiceCfg args) : CommandingServiceBase(args.objectId, args.apid, "PUS 201 Health MGMT", args.service, args.numParallelCommands, args.commandTimeoutSeconds), - healthTable(args.table), + healthTableId(args.table), maxNumHealthInfoPerCycle(args.maxNumHealthInfoPerCycle) {} +ReturnValue_t CServiceHealthCommanding::initialize() { + ReturnValue_t result = CommandingServiceBase::initialize(); + if (result != returnvalue::OK) { + return result; + } + + healthTable = ObjectManager::instance()->get(healthTableId); + if (healthTable == nullptr) { + return returnvalue::FAILED; + } + + return returnvalue::OK; +} + ReturnValue_t CServiceHealthCommanding::isValidSubservice(uint8_t subservice) { switch (subservice) { case (Subservice::COMMAND_SET_HEALTH): @@ -68,6 +82,9 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message, 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) { @@ -79,7 +96,7 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message, } case (Subservice::COMMAND_ANNOUNCE_HEALTH): { HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE); - break; + return CommandingServiceBase::EXECUTION_COMPLETE; } case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): { ReturnValue_t result = iterateHealthTable(true); @@ -88,14 +105,6 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message, return EXECUTION_COMPLETE; } return result; - while (true) { - ReturnValue_t result = iterateHealthTable(false); - if (result != returnvalue::OK) { - break; - } - } - - return returnvalue::OK; } default: { // Should never happen, subservice was already checked @@ -142,7 +151,7 @@ void CServiceHealthCommanding::doPeriodicOperation() { ReturnValue_t CServiceHealthCommanding::iterateHealthTable(bool reset) { std::pair pair; - ReturnValue_t result = healthTable.iterate(&pair, reset); + ReturnValue_t result = healthTable->iterate(&pair, reset); if (result != returnvalue::OK) { return result; } else { diff --git a/src/fsfw/pus/CServiceHealthCommanding.h b/src/fsfw/pus/CServiceHealthCommanding.h index 18f6c140f..2cc16589f 100644 --- a/src/fsfw/pus/CServiceHealthCommanding.h +++ b/src/fsfw/pus/CServiceHealthCommanding.h @@ -6,7 +6,7 @@ #include "fsfw/tmtcservices/CommandingServiceBase.h" struct HealthServiceCfg { - HealthServiceCfg(object_id_t objectId, uint16_t apid, HealthTable &healthTable, + HealthServiceCfg(object_id_t objectId, uint16_t apid, object_id_t healthTable, uint16_t maxNumHealthInfoPerCycle) : objectId(objectId), apid(apid), @@ -14,7 +14,7 @@ struct HealthServiceCfg { maxNumHealthInfoPerCycle(maxNumHealthInfoPerCycle) {} object_id_t objectId; uint16_t apid; - HealthTable &table; + object_id_t table; uint16_t maxNumHealthInfoPerCycle; uint8_t service = 201; uint8_t numParallelCommands = 4; @@ -40,6 +40,8 @@ class CServiceHealthCommanding : public CommandingServiceBase { CServiceHealthCommanding(HealthServiceCfg args); ~CServiceHealthCommanding() override = default; + ReturnValue_t initialize() override; + protected: /* CSB abstract function implementations */ ReturnValue_t isValidSubservice(uint8_t subservice) override; @@ -57,7 +59,8 @@ class CServiceHealthCommanding : public CommandingServiceBase { void doPeriodicOperation() override; private: - HealthTable &healthTable; + const object_id_t healthTableId; + HealthTable *healthTable; uint16_t maxNumHealthInfoPerCycle = 0; bool reportAllHealth = false; ReturnValue_t iterateHealthTable(bool reset); diff --git a/src/fsfw/pus/Service11TelecommandScheduling.tpp b/src/fsfw/pus/Service11TelecommandScheduling.tpp index 2ad112772..8352f85db 100644 --- a/src/fsfw/pus/Service11TelecommandScheduling.tpp +++ b/src/fsfw/pus/Service11TelecommandScheduling.tpp @@ -160,7 +160,7 @@ inline ReturnValue_t Service11TelecommandScheduling::doInsertActivi // (See requirement for Time margin) timeval tNow = {}; Clock::getClock_timeval(&tNow); - if (timestamp - tNow.tv_sec <= RELEASE_TIME_MARGIN_SECONDS) { + if (timestamp < static_cast(tNow.tv_sec + RELEASE_TIME_MARGIN_SECONDS)) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "Service11TelecommandScheduling::doInsertActivity: Release time too close to " "current time" diff --git a/src/fsfw/rmap/rmapStructs.h b/src/fsfw/rmap/rmapStructs.h index 55e32606f..1e86734b1 100644 --- a/src/fsfw/rmap/rmapStructs.h +++ b/src/fsfw/rmap/rmapStructs.h @@ -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<createMutex(); } PoolManager::~PoolManager() { MutexFactory::instance()->deleteMutex(mutex); } ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address) { - MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs); + MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX); ReturnValue_t status = LocalPool::reserveSpace(size, address); return status; } @@ -22,12 +22,12 @@ ReturnValue_t PoolManager::deleteData(store_address_t storeId) { << storeId.poolIndex << ". id is " << storeId.packetIndex << std::endl; #endif #endif - MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs); + MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX); return LocalPool::deleteData(storeId); } ReturnValue_t PoolManager::deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) { - MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20); + MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX); ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId); return status; } diff --git a/src/fsfw/storagemanager/PoolManager.h b/src/fsfw/storagemanager/PoolManager.h index aa8c93ddc..d4bb9f0d1 100644 --- a/src/fsfw/storagemanager/PoolManager.h +++ b/src/fsfw/storagemanager/PoolManager.h @@ -56,6 +56,7 @@ class PoolManager : public LocalPool { protected: //! Default mutex timeout value to prevent permanent blocking. uint32_t mutexTimeoutMs = 20; + static constexpr char LOCK_CTX[] = "PoolManager"; ReturnValue_t reserveSpace(size_t size, store_address_t* address) override; diff --git a/src/fsfw/subsystem/SubsystemBase.cpp b/src/fsfw/subsystem/SubsystemBase.cpp index 5cfe59a37..eccd447ca 100644 --- a/src/fsfw/subsystem/SubsystemBase.cpp +++ b/src/fsfw/subsystem/SubsystemBase.cpp @@ -21,6 +21,7 @@ SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(c ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator tableIter, Submode_t targetSubmode) { + using namespace mode; std::map::iterator childIter; for (; tableIter.value != NULL; ++tableIter) { @@ -34,13 +35,21 @@ ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIteratorgetSubmode(); + // Check submodes here. + uint8_t mask; + bool submodesAllowedMask = tableIter.value->submodesAllowed(&mask); + uint8_t submodeToCheckAgainst = tableIter.value->getSubmode(); if (tableIter.value->inheritSubmode()) { submodeToCheckAgainst = targetSubmode; } - - if (childIter->second.submode != submodeToCheckAgainst) { - return returnvalue::FAILED; + if (submodesAllowedMask) { + if ((childIter->second.submode | mask) != mask) { + return returnvalue::FAILED; + } + } else { + if (childIter->second.submode != submodeToCheckAgainst) { + return returnvalue::FAILED; + } } } return returnvalue::OK; @@ -117,6 +126,20 @@ ReturnValue_t SubsystemBase::updateChildMode(MessageQueueId_t queue, Mode_t mode return CHILD_NOT_FOUND; } +ReturnValue_t SubsystemBase::updateChildModeByObjId(object_id_t objectId, Mode_t mode, + Submode_t submode) { + std::map::iterator iter; + + for (iter = childrenMap.begin(); iter != childrenMap.end(); iter++) { + if (iter->first == objectId) { + iter->second.mode = mode; + iter->second.submode = submode; + return returnvalue::OK; + } + } + return CHILD_NOT_FOUND; +} + ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue, bool changedHealth) { for (auto iter = childrenMap.begin(); iter != childrenMap.end(); iter++) { if (iter->second.commandQueue == queue) { diff --git a/src/fsfw/subsystem/SubsystemBase.h b/src/fsfw/subsystem/SubsystemBase.h index 0fbf9f4a7..c3886d616 100644 --- a/src/fsfw/subsystem/SubsystemBase.h +++ b/src/fsfw/subsystem/SubsystemBase.h @@ -115,6 +115,7 @@ class SubsystemBase : public SystemObject, Submode_t targetSubmode = SUBMODE_NONE); ReturnValue_t updateChildMode(MessageQueueId_t queue, Mode_t mode, Submode_t submode); + ReturnValue_t updateChildModeByObjId(object_id_t objectId, Mode_t mode, Submode_t submode); ReturnValue_t updateChildChangedHealth(MessageQueueId_t queue, bool changedHealth = true); diff --git a/src/fsfw/subsystem/modes/ModeDefinitions.h b/src/fsfw/subsystem/modes/ModeDefinitions.h index d22bcd954..70a66fa6c 100644 --- a/src/fsfw/subsystem/modes/ModeDefinitions.h +++ b/src/fsfw/subsystem/modes/ModeDefinitions.h @@ -1,111 +1,126 @@ #ifndef FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_ #define FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_ -#include "../../modes/HasModesIF.h" -#include "../../objectmanager/SystemObjectIF.h" -#include "../../serialize/SerialLinkedListAdapter.h" -#include "../../serialize/SerializeIF.h" +#include "fsfw/modes/HasModesIF.h" +#include "fsfw/objectmanager/SystemObjectIF.h" +#include "fsfw/serialize/SerialLinkedListAdapter.h" +#include "fsfw/serialize/SerializeIF.h" -class ModeListEntry : public SerializeIF, public LinkedElement { +namespace mode { +enum SpecialSubmodeFlags : uint8_t { INHERIT = 1 << 0, ALLOWED_MASK = 1 << 1 }; +} + +class ModeListEntry : public SerialLinkedListAdapter, + public LinkedElement { public: - ModeListEntry() : LinkedElement(this) {} + static constexpr uint8_t ALL_SUBMODES_ALLOWED_MASK = 0xff; - uint32_t value1 = 0; - uint32_t value2 = 0; - uint8_t value3 = 0; - uint8_t value4 = 0; + ModeListEntry() : SerialLinkedListAdapter(), LinkedElement(this) { setLinks(); } - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const { - ReturnValue_t result; + SerializeElement value1 = 0; + SerializeElement value2 = 0; + SerializeElement value3 = 0; + SerializeElement value4 = 0; + SerializeElement value5 = 0; - result = SerializeAdapter::serialize(&value1, buffer, size, maxSize, streamEndianness); - - if (result != returnvalue::OK) { - return result; - } - result = SerializeAdapter::serialize(&value2, buffer, size, maxSize, streamEndianness); - - if (result != returnvalue::OK) { - return result; - } - result = SerializeAdapter::serialize(&value3, buffer, size, maxSize, streamEndianness); - - if (result != returnvalue::OK) { - return result; - } - - result = SerializeAdapter::serialize(&value4, buffer, size, maxSize, streamEndianness); - - return result; + ModeListEntry(const ModeListEntry& other) + : SerialLinkedListAdapter(), LinkedElement(this) { + value1.entry = other.value1.entry; + value2.entry = other.value2.entry; + value3.entry = other.value3.entry; + value4.entry = other.value4.entry; + value5.entry = other.value5.entry; + setLinks(); } - virtual size_t getSerializedSize() const { - return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4); + ModeListEntry& operator=(const ModeListEntry& other) { + this->value1.entry = other.value1.entry; + this->value2.entry = other.value2.entry; + this->value3.entry = other.value3.entry; + this->value4.entry = other.value4.entry; + this->value5.entry = other.value5.entry; + return *this; } - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) { - ReturnValue_t result; - - result = SerializeAdapter::deSerialize(&value1, buffer, size, streamEndianness); - - if (result != returnvalue::OK) { - return result; - } - result = SerializeAdapter::deSerialize(&value2, buffer, size, streamEndianness); - - if (result != returnvalue::OK) { - return result; - } - result = SerializeAdapter::deSerialize(&value3, buffer, size, streamEndianness); - - if (result != returnvalue::OK) { - return result; - } - result = SerializeAdapter::deSerialize(&value4, buffer, size, streamEndianness); - - return result; + void setLinks() { + setStart(&value1); + value1.setNext(&value2); + value2.setNext(&value3); + value3.setNext(&value4); + value4.setNext(&value5); } // for Sequences - Mode_t getTableId() const { return value1; } + Mode_t getTableId() const { return value1.entry; } - void setTableId(Mode_t tableId) { this->value1 = tableId; } + void setTableId(Mode_t tableId) { this->value1.entry = tableId; } - uint8_t getWaitSeconds() const { return value2; } + uint8_t getWaitSeconds() const { return value2.entry; } - void setWaitSeconds(uint8_t waitSeconds) { this->value2 = waitSeconds; } + void setWaitSeconds(uint8_t waitSeconds) { this->value2.entry = waitSeconds; } - bool checkSuccess() const { return value3 == 1; } + bool checkSuccess() const { return value3.entry == 1; } - void setCheckSuccess(bool checkSuccess) { this->value3 = checkSuccess; } + void setCheckSuccess(bool checkSuccess) { this->value3.entry = checkSuccess; } // for Tables - object_id_t getObject() const { return value1; } + object_id_t getObject() const { return value1.entry; } - void setObject(object_id_t object) { this->value1 = object; } + void setObject(object_id_t object) { this->value1.entry = object; } - Mode_t getMode() const { return value2; } + Mode_t getMode() const { return value2.entry; } - void setMode(Mode_t mode) { this->value2 = mode; } + void setMode(Mode_t mode) { this->value2.entry = mode; } - Submode_t getSubmode() const { return value3; } + Submode_t getSubmode() const { return value3.entry; } - void setSubmode(Submode_t submode) { this->value3 = submode; } + void setSubmode(Submode_t submode) { this->value3.entry = submode; } - bool inheritSubmode() const { return value4 == 1; } - - void setInheritSubmode(bool inherit) { - if (inherit) { - value4 = 1; - } else { - value4 = 0; + bool inheritSubmode() const { + return (value4.entry & mode::SpecialSubmodeFlags::INHERIT) == + mode::SpecialSubmodeFlags::INHERIT; + } + bool submodesAllowed(uint8_t* mask) const { + bool submodesAllowed = (value4.entry & mode::SpecialSubmodeFlags::ALLOWED_MASK) == + mode::SpecialSubmodeFlags::ALLOWED_MASK; + if (submodesAllowed and mask != nullptr) { + *mask = value5.entry; } + return submodesAllowed; } - bool operator==(ModeListEntry other) { - return ((value1 == other.value1) && (value2 == other.value2) && (value3 == other.value3)); + /** + * Enable the inheritance of submodes. This is relevant for both the execution + * of mode tables and for mode checking. + */ + void enableInheritSubmode() { value4.entry |= mode::SpecialSubmodeFlags::INHERIT; } + /** + * Disable the inheritance of submodes. This is relevant for both the execution + * of mode tables and for mode checking. + */ + void disableInheritSubmode() { value4.entry &= ~mode::SpecialSubmodeFlags::INHERIT; } + + /** + * Specialization of @enableSubmodeAllowed which allows all submodes. + */ + void allowAllSubmodes() { enableSubmodeAllowed(ALL_SUBMODES_ALLOWED_MASK); } + + /** + * Enable an allowed submode mask for mode checks. Any submode which contains bits + * outside of the mask will be declined. + * + * For example, for a mask of 0b11, only the modes 0b00, 0b01 and 0b11 will be accepted. + */ + void enableSubmodeAllowed(uint8_t mask) { + value4.entry |= mode::SpecialSubmodeFlags::ALLOWED_MASK; + value5.entry = mask; + } + /** + * Enforce the equality of submodes for mode checks. This is the default. + */ + void disableSubmodeAllowed() { + value4.entry &= ~mode::SpecialSubmodeFlags::ALLOWED_MASK; + value5.entry = 0; } }; diff --git a/src/fsfw/tasks/FixedTimeslotTaskBase.cpp b/src/fsfw/tasks/FixedTimeslotTaskBase.cpp index 3327deaed..0e1e3c5d0 100644 --- a/src/fsfw/tasks/FixedTimeslotTaskBase.cpp +++ b/src/fsfw/tasks/FixedTimeslotTaskBase.cpp @@ -15,10 +15,10 @@ ReturnValue_t FixedTimeslotTaskBase::addSlot(object_id_t execId, ExecutableObjec uint32_t slotTimeMs, int8_t executionStep) { if (execObj == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << execObj + sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << execId << std::setfill(' ') << " not found, not adding it to PST" << std::dec << std::endl; #else - sif::printError("Component 0x%08x not found, not adding it to PST\n"); + sif::printError("Component 0x%08x not found, not adding it to PST\n", execId); #endif return returnvalue::FAILED; } diff --git a/src/fsfw/thermal/Heater.cpp b/src/fsfw/thermal/Heater.cpp index 04abadc7b..da78a74a3 100644 --- a/src/fsfw/thermal/Heater.cpp +++ b/src/fsfw/thermal/Heater.cpp @@ -283,7 +283,7 @@ ReturnValue_t Heater::getParameter(uint8_t domainId, uint8_t uniqueId, } switch (uniqueId) { case 0: - parameterWrapper->set(heaterOnCountdown.timeout); + parameterWrapper->set(heaterOnCountdown.getTimeoutMs()); break; default: return INVALID_IDENTIFIER_ID; diff --git a/src/fsfw/timemanager/CCSDSTime.cpp b/src/fsfw/timemanager/CCSDSTime.cpp index cb0d57587..7ca1f7f19 100644 --- a/src/fsfw/timemanager/CCSDSTime.cpp +++ b/src/fsfw/timemanager/CCSDSTime.cpp @@ -246,6 +246,20 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* return UNSUPPORTED_TIME_FORMAT; } +ReturnValue_t CCSDSTime::convertToAsciiWithSecs(int8_t* to, const Clock::TimeOfDay_t* from, + uint8_t length) { + if (from == nullptr or to == nullptr) { + return returnvalue::FAILED; + } + int count = snprintf(reinterpret_cast(to), length, + "%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32, + from->year, from->month, from->day, from->hour, from->minute, from->second); + if (count >= length) { + return returnvalue::FAILED; + } + return returnvalue::OK; +} + ReturnValue_t CCSDSTime::checkCcs(const uint8_t* time, uint8_t length) { const Ccs_mseconds* time_struct = reinterpret_cast(time); diff --git a/src/fsfw/timemanager/CCSDSTime.h b/src/fsfw/timemanager/CCSDSTime.h index 77801cecc..03a8ea8f8 100644 --- a/src/fsfw/timemanager/CCSDSTime.h +++ b/src/fsfw/timemanager/CCSDSTime.h @@ -207,7 +207,8 @@ class CCSDSTime { static ReturnValue_t convertFromASCII(Clock::TimeOfDay_t *to, uint8_t const *from, uint8_t length); - + static ReturnValue_t convertToAsciiWithSecs(int8_t *to, const Clock::TimeOfDay_t *from, + uint8_t length); static uint32_t subsecondsToMicroseconds(uint16_t subseconds); private: diff --git a/src/fsfw/timemanager/CdsShortTimeStamper.cpp b/src/fsfw/timemanager/CdsShortTimeStamper.cpp index 8fb33f12f..aa2590293 100644 --- a/src/fsfw/timemanager/CdsShortTimeStamper.cpp +++ b/src/fsfw/timemanager/CdsShortTimeStamper.cpp @@ -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, diff --git a/src/fsfw/timemanager/CdsShortTimeStamper.h b/src/fsfw/timemanager/CdsShortTimeStamper.h index 244d54b66..a16a07b6f 100644 --- a/src/fsfw/timemanager/CdsShortTimeStamper.h +++ b/src/fsfw/timemanager/CdsShortTimeStamper.h @@ -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. diff --git a/src/fsfw/timemanager/Clock.h b/src/fsfw/timemanager/Clock.h index 83bc3d9f8..6fe6486c8 100644 --- a/src/fsfw/timemanager/Clock.h +++ b/src/fsfw/timemanager/Clock.h @@ -49,6 +49,13 @@ class Clock { * @return -@c returnvalue::OK on success. Otherwise, the OS failure code is returned. */ static ReturnValue_t setClock(const timeval *time); + + /** + * @deprecated Use getClock instead, which does the same. + * @param time + * @return + */ + static ReturnValue_t getClock_timeval(timeval *time); /** * This system call returns the current system clock in timeval format. * The timval format has the fields @c tv_sec with seconds and @c tv_usec with @@ -56,7 +63,18 @@ class Clock { * @param time A pointer to a timeval struct where the current time is stored. * @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned. */ - static ReturnValue_t getClock_timeval(timeval *time); + static ReturnValue_t getClock(timeval *time); + + /** + * Retrieve a monotonic clock. This clock this is also more suited for measuring elapsed times + * between two time points, but less suited when the absolute time is required. + * + * Implementation example: A generic UNIX implementation can use CLOCK_MONOTONIC_RAW with + * `clock_gettime`. + * @param time + * @return + */ + static ReturnValue_t getClockMonotonic(timeval *time); /** * Get the time since boot in a timeval struct diff --git a/src/fsfw/timemanager/Countdown.cpp b/src/fsfw/timemanager/Countdown.cpp index 334883ae1..5e743efe7 100644 --- a/src/fsfw/timemanager/Countdown.cpp +++ b/src/fsfw/timemanager/Countdown.cpp @@ -1,49 +1,62 @@ #include "fsfw/timemanager/Countdown.h" -Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) : timeout(initialTimeout) { +#include "fsfw/globalfunctions/timevalOperations.h" + +Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) { if (startImmediately) { setTimeout(initialTimeout); } else { - timeout = initialTimeout; + timeout.tv_sec = initialTimeout / 1000; + timeout.tv_usec = (initialTimeout % 1000) * 1000; } } -Countdown::~Countdown() {} +Countdown::~Countdown() = default; ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) { - ReturnValue_t returnValue = Clock::getUptime(&startTime); - timeout = milliseconds; - return returnValue; + timeout.tv_sec = milliseconds / 1000; + timeout.tv_usec = (milliseconds % 1000) * 1000; + return Clock::getClockMonotonic(&startTime); } bool Countdown::hasTimedOut() const { - if (uint32_t(this->getCurrentTime() - startTime) >= timeout) { + // Account for system clock going back in time. + if (getCurrentTime() < startTime) { return true; - } else { - return false; } + if (getCurrentTime() - startTime >= timeout) { + return true; + } + return false; } bool Countdown::isBusy() const { return !hasTimedOut(); } -ReturnValue_t Countdown::resetTimer() { return setTimeout(timeout); } +ReturnValue_t Countdown::resetTimer() { return setTimeoutTv(timeout); } void Countdown::timeOut() { startTime = this->getCurrentTime() - timeout; } uint32_t Countdown::getRemainingMillis() const { - // We fetch the time before the if-statement - // to be sure that the return is in - // range 0 <= number <= timeout - uint32_t currentTime = this->getCurrentTime(); if (this->hasTimedOut()) { return 0; - } else { - return (startTime + timeout) - currentTime; } + timeval remainingMillisTv = (startTime + timeout) - this->getCurrentTime(); + return remainingMillisTv.tv_sec * 1000 + remainingMillisTv.tv_usec / 1000; } -uint32_t Countdown::getCurrentTime() const { - uint32_t currentTime; - Clock::getUptime(¤tTime); +uint32_t Countdown::timevalToMs(timeval &tv) { return tv.tv_sec * 1000 + tv.tv_usec / 1000; } + +ReturnValue_t Countdown::setTimeoutTv(timeval tv) { + timeout = tv; + return Clock::getClockMonotonic(&startTime); +} + +uint32_t Countdown::getTimeoutMs() const { return timeout.tv_sec * 1000 + timeout.tv_usec / 1000; } + +timeval Countdown::getTimeout() const { return timeout; } + +timeval Countdown::getCurrentTime() const { + timeval currentTime{}; + Clock::getClockMonotonic(¤tTime); return currentTime; } diff --git a/src/fsfw/timemanager/Countdown.h b/src/fsfw/timemanager/Countdown.h index 265347899..44a1d4ad3 100644 --- a/src/fsfw/timemanager/Countdown.h +++ b/src/fsfw/timemanager/Countdown.h @@ -6,6 +6,10 @@ /** * * Countdown keeps track of a timespan. + * This class uses the system clock internally to achieve + * a high resolution. This means that the API is only partially + * resistant against time jumps. The user must take care to account + * for time jumps in some from if this relevant. * * Countdown::resetTimer restarts the timer. * Countdown::setTimeout sets a new countdown duration and resets. @@ -39,6 +43,8 @@ class Countdown { * @return Returnvalue from Clock::getUptime */ ReturnValue_t setTimeout(uint32_t milliseconds); + ReturnValue_t setTimeoutTv(timeval tv); + /** * Returns true if the countdown duration has passed. * @@ -61,22 +67,31 @@ class Countdown { * Returns the remaining milliseconds (0 if timeout) */ uint32_t getRemainingMillis() const; + + uint32_t getTimeoutMs() const; + + timeval getTimeout() const; + /** * Makes hasTimedOut() return true */ void timeOut(); - /** - * Internal countdown duration in milliseconds - */ - uint32_t timeout; + + static inline uint32_t timevalToMs(timeval& tv); private: /** - * Last time the timer was started (uptime) + * Start time of the countdown. */ - uint32_t startTime = 0; + timeval startTime{}; - uint32_t getCurrentTime() const; + /** + * Timeout as timeval type. The countdown has timed out when the + * current time exceeds the start time plus the timeout. + */ + timeval timeout{}; + + timeval getCurrentTime() const; }; #endif /* FSFW_TIMEMANAGER_COUNTDOWN_H_ */ diff --git a/src/fsfw/timemanager/Stopwatch.cpp b/src/fsfw/timemanager/Stopwatch.cpp index 05d5c0e8b..ad39f1b39 100644 --- a/src/fsfw/timemanager/Stopwatch.cpp +++ b/src/fsfw/timemanager/Stopwatch.cpp @@ -9,10 +9,10 @@ Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode) : displayOnDestruction(displayOnDestruction), displayMode(displayMode) { // Measures start time on initialization. - Clock::getUptime(&startTime); + Clock::getClockMonotonic(&startTime); } -void Stopwatch::start() { Clock::getUptime(&startTime); } +void Stopwatch::start() { Clock::getClockMonotonic(&startTime); } dur_millis_t Stopwatch::stop(bool display) { stopInternal(); @@ -63,6 +63,6 @@ StopwatchDisplayMode Stopwatch::getDisplayMode() const { return displayMode; } void Stopwatch::stopInternal() { timeval endTime; - Clock::getUptime(&endTime); + Clock::getClockMonotonic(&endTime); elapsedTime = endTime - startTime; } diff --git a/src/fsfw/tmstorage/TmStoreFrontendIF.h b/src/fsfw/tmstorage/TmStoreFrontendIF.h index 56bcd7fab..1e3dd5791 100644 --- a/src/fsfw/tmstorage/TmStoreFrontendIF.h +++ b/src/fsfw/tmstorage/TmStoreFrontendIF.h @@ -6,47 +6,12 @@ #include "fsfw/returnvalues/returnvalue.h" #include "tmStorageConf.h" -class TmPacketMinimal; -class SpacePacketBase; +class PusTmReader; +class SpacePacketReader; class TmStoreBackendIF; class TmStoreFrontendIF { public: - virtual TmStoreBackendIF* getBackend() const = 0; - - /** - * What do I need to implement here? - * This is propably used by PUS Service 15 so we should propably check for messages.. - * Provide base implementation? - * @param opCode - * @return - */ - virtual ReturnValue_t performOperation(uint8_t opCode) = 0; - /** - * Callback from the back-end to indicate a certain packet was received. - * front-end takes care of discarding/downloading the packet. - * @param packet Pointer to the newly received Space Packet. - * @param address Start address of the packet found - * @param isLastPacket Indicates if no more packets can be fetched. - * @return If more packets shall be fetched, returnvalue::OK must be returned. - * Any other code stops fetching packets. - */ - virtual ReturnValue_t packetRetrieved(TmPacketMinimal* packet, uint32_t address) = 0; - virtual void noMorePacketsInStore() = 0; - virtual void handleRetrievalFailed(ReturnValue_t errorCode, uint32_t parameter1 = 0, - uint32_t parameter2 = 0) = 0; - /** - * To get the queue where commands shall be sent. - * @return Id of command queue. - */ - virtual MessageQueueId_t getCommandQueue() const = 0; - virtual ReturnValue_t fetchPackets(ApidSsc start, ApidSsc end) = 0; - virtual ReturnValue_t deletePackets(ApidSsc upTo) = 0; - virtual ReturnValue_t checkPacket(SpacePacketBase* tmPacket) = 0; - virtual bool isEnabled() const = 0; - virtual void setEnabled(bool enabled) = 0; - virtual void resetDownlinkedPacketCount() = 0; - virtual ReturnValue_t setDumpTarget(object_id_t dumpTarget) = 0; static const uint8_t INTERFACE_ID = CLASS_ID::TM_STORE_FRONTEND_IF; static const ReturnValue_t BUSY = MAKE_RETURN_CODE(1); static const ReturnValue_t LAST_PACKET_FOUND = MAKE_RETURN_CODE(2); @@ -57,7 +22,38 @@ class TmStoreFrontendIF { static const ReturnValue_t ALL_DELETED = MAKE_RETURN_CODE(7); static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(8); static const ReturnValue_t NOT_READY = MAKE_RETURN_CODE(9); - virtual ~TmStoreFrontendIF() {} + + virtual ~TmStoreFrontendIF() = default; + + /** + * To get the queue where commands shall be sent. + * @return Id of command queue. + */ + virtual MessageQueueId_t getCommandQueue() const = 0; + + virtual TmStoreBackendIF* getBackend() const = 0; + + /** + * Callback from the back-end to indicate a certain packet was received. + * front-end takes care of discarding/downloading the packet. + * @param packet Pointer to the newly received Space Packet. + * @param address Start address of the packet found + * @param isLastPacket Indicates if no more packets can be fetched. + * @return If more packets shall be fetched, returnvalue::OK must be returned. + * Any other code stops fetching packets. + */ + virtual ReturnValue_t packetRetrieved(PusTmReader* packet, uint32_t address) = 0; + virtual void noMorePacketsInStore() = 0; + virtual void handleRetrievalFailed(ReturnValue_t errorCode, uint32_t parameter1 = 0, + uint32_t parameter2 = 0) = 0; + + virtual ReturnValue_t fetchPackets(ApidSsc start, ApidSsc end) = 0; + virtual ReturnValue_t deletePackets(ApidSsc upTo) = 0; + virtual ReturnValue_t checkPacket(SpacePacketReader* tmPacket) = 0; + virtual bool isEnabled() const = 0; + virtual void setEnabled(bool enabled) = 0; + virtual void resetDownlinkedPacketCount() = 0; + virtual ReturnValue_t setDumpTarget(object_id_t dumpTarget) = 0; }; #endif /* FSFW_TMTCSERVICES_TMSTOREFRONTENDIF_H_ */ diff --git a/src/fsfw/tmstorage/TmStoreFrontendSimpleIF.h b/src/fsfw/tmstorage/TmStoreFrontendSimpleIF.h new file mode 100644 index 000000000..5089f37de --- /dev/null +++ b/src/fsfw/tmstorage/TmStoreFrontendSimpleIF.h @@ -0,0 +1,15 @@ +#ifndef FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_ +#define FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_ + +#include + +class TmStoreFrontendSimpleIF { + public: + virtual ~TmStoreFrontendSimpleIF() = default; + + virtual MessageQueueId_t getCommandQueue() const = 0; + + private: +}; + +#endif /* FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_ */ diff --git a/src/fsfw/tmstorage/TmStorePackets.h b/src/fsfw/tmstorage/TmStorePackets.h index e519b3b77..22ed3c216 100644 --- a/src/fsfw/tmstorage/TmStorePackets.h +++ b/src/fsfw/tmstorage/TmStorePackets.h @@ -1,6 +1,10 @@ #ifndef FSFW_TMSTORAGE_TMSTOREPACKETS_H_ #define FSFW_TMSTORAGE_TMSTOREPACKETS_H_ +#include + +#include + #include "fsfw/globalfunctions/timevalOperations.h" #include "fsfw/serialize/SerialBufferAdapter.h" #include "fsfw/serialize/SerialFixedArrayListAdapter.h" @@ -24,7 +28,7 @@ class ServiceSubservice : public SerialLinkedListAdapter { class ApidSsc : public SerializeIF { public: - ApidSsc() : apid(SpacePacketBase::LIMIT_APID), ssc(0) {} + ApidSsc() : apid(ccsds::LIMIT_APID), ssc(0) {} ApidSsc(uint16_t apid, uint16_t ssc) : apid(apid), ssc(ssc) {} uint16_t apid; uint16_t ssc; @@ -62,51 +66,59 @@ class ChangeSelectionDefinition : public SerialLinkedListAdapter { class TmPacketInformation : public SerializeIF { public: - TmPacketInformation(TmPacketMinimal* packet) { setContent(packet); } - TmPacketInformation() - : apid(SpacePacketBase::LIMIT_APID), + TmPacketInformation(PusTmReader* packet, size_t timestampLen) : rawTimestamp(timestampLen) { + setContent(packet); + } + TmPacketInformation(size_t timestampLen) + : apid(ccsds::LIMIT_APID), sourceSequenceCount(0), serviceType(0), serviceSubtype(0), - subCounter(0) {} + subCounter(0), + rawTimestamp(timestampLen) {} void reset() { - apid = SpacePacketBase::LIMIT_APID; + apid = ccsds::LIMIT_APID; sourceSequenceCount = 0; serviceType = 0; serviceSubtype = 0; subCounter = 0; - memset(rawTimestamp, 0, sizeof(rawTimestamp)); + memset(rawTimestamp.data(), 0, rawTimestamp.size()); } - void setContent(TmPacketMinimal* packet) { - apid = packet->getAPID(); - sourceSequenceCount = packet->getPacketSequenceCount(); + void setContent(PusTmReader* packet) { + apid = packet->getApid(); + sourceSequenceCount = packet->getSequenceCount(); serviceType = packet->getService(); serviceSubtype = packet->getSubService(); - subCounter = packet->getPacketSubcounter(); - memset(rawTimestamp, 0, sizeof(rawTimestamp)); - const uint8_t* pField = NULL; - uint32_t size = 0; - ReturnValue_t result = packet->getPacketTimeRaw(&pField, &size); - if (result != returnvalue::OK) { - return; - } - if (*pField == CCSDSTime::P_FIELD_CDS_SHORT && size <= TimeStamperIF::MISSION_TIMESTAMP_SIZE) { - // Shortcut to avoid converting CDS back and forth. - memcpy(rawTimestamp, pField, size); - return; - } - timeval time = {0, 0}; - result = packet->getPacketTime(&time); - if (result != returnvalue::OK) { - return; - } - - CCSDSTime::CDS_short cdsFormat; - result = CCSDSTime::convertToCcsds(&cdsFormat, &time); - if (result != returnvalue::OK) { - return; - } - memcpy(rawTimestamp, &cdsFormat, sizeof(cdsFormat)); + subCounter = packet->getMessageTypeCounter(); + memset(rawTimestamp.data(), 0, rawTimestamp.size()); + // TODO: Fix all of this + // const uint8_t* pField = NULL; + // uint32_t size = 0; + // auto* timeReader = packet->getTimeReader(); + // ReturnValue_t result = packet->getPacketTimeRaw(&pField, &size); + // if (result != returnvalue::OK) { + // return; + //} + // if (*pField == CCSDSTime::P_FIELD_CDS_SHORT && size <= TimeStamperIF::MISSION_TIMESTAMP_SIZE) + // { + // Shortcut to avoid converting CDS back and forth. + // TODO: Fix + // memcpy(rawTimestamp, pField, size); + // return; + // } + // timeval time = {0, 0}; + // result = packet->getPacketTime(&time); + // if (result != returnvalue::OK) { + // return; + // } + // + // CCSDSTime::CDS_short cdsFormat; + // result = CCSDSTime::convertToCcsds(&cdsFormat, &time); + // if (result != returnvalue::OK) { + // return; + // } + // TODO: Fix + // memcpy(rawTimestamp, &cdsFormat, sizeof(cdsFormat)); } void setContent(TmPacketInformation* content) { apid = content->apid; @@ -114,9 +126,10 @@ class TmPacketInformation : public SerializeIF { serviceType = content->serviceType; serviceSubtype = content->serviceSubtype; subCounter = content->subCounter; - memcpy(rawTimestamp, content->rawTimestamp, sizeof(rawTimestamp)); + // TODO: Fix + // memcpy(rawTimestamp, content->rawTimestamp, sizeof(rawTimestamp)); } - bool isValid() const { return (apid < SpacePacketBase::LIMIT_APID) ? true : false; } + bool isValid() const { return (apid < ccsds::LIMIT_APID) ? true : false; } static void reset(TmPacketInformation* packet) { packet->reset(); } static bool isOlderThan(const TmPacketInformation* packet, const timeval* cmpTime) { @@ -216,7 +229,7 @@ class TmPacketInformation : public SerializeIF { if (result != returnvalue::OK) { return result; } - SerialBufferAdapter adapter(rawTimestamp, sizeof(rawTimestamp)); + SerialBufferAdapter adapter(rawTimestamp.data(), rawTimestamp.size()); return adapter.serialize(buffer, size, maxSize, streamEndianness); } @@ -227,7 +240,7 @@ class TmPacketInformation : public SerializeIF { size += SerializeAdapter::getSerializedSize(&serviceType); size += SerializeAdapter::getSerializedSize(&serviceSubtype); size += SerializeAdapter::getSerializedSize(&subCounter); - SerialBufferAdapter adapter(rawTimestamp, sizeof(rawTimestamp)); + SerialBufferAdapter adapter(rawTimestamp.data(), rawTimestamp.size()); size += adapter.getSerializedSize(); return size; }; @@ -253,7 +266,7 @@ class TmPacketInformation : public SerializeIF { if (result != returnvalue::OK) { return result; } - SerialBufferAdapter adapter(rawTimestamp, sizeof(rawTimestamp)); + SerialBufferAdapter adapter(rawTimestamp.data(), rawTimestamp.size()); return adapter.deSerialize(buffer, size, streamEndianness); } @@ -263,6 +276,6 @@ class TmPacketInformation : public SerializeIF { uint8_t serviceType; uint8_t serviceSubtype; uint8_t subCounter; - uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE]; + std::vector rawTimestamp; }; #endif /* FSFW_TMSTORAGE_TMSTOREPACKETS_H_ */ diff --git a/src/fsfw/tmtcservices/TmTcBridge.cpp b/src/fsfw/tmtcservices/TmTcBridge.cpp index 9ff587660..f098103ee 100644 --- a/src/fsfw/tmtcservices/TmTcBridge.cpp +++ b/src/fsfw/tmtcservices/TmTcBridge.cpp @@ -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), @@ -18,7 +18,7 @@ TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDes { auto mqArgs = MqArgs(objectId, static_cast(this)); tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue( - TMTC_RECEPTION_QUEUE_DEPTH, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); + msgQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); } TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); } @@ -145,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; } @@ -159,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; } diff --git a/src/fsfw/tmtcservices/TmTcBridge.h b/src/fsfw/tmtcservices/TmTcBridge.h index f2637abd0..858793cc1 100644 --- a/src/fsfw/tmtcservices/TmTcBridge.h +++ b/src/fsfw/tmtcservices/TmTcBridge.h @@ -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 unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 1000; + 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; /** diff --git a/src/fsfw/version.cpp b/src/fsfw/version.cpp index 050187a9a..27d44c03a 100644 --- a/src/fsfw/version.cpp +++ b/src/fsfw/version.cpp @@ -1,6 +1,7 @@ #include "version.h" #include +#include #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; diff --git a/src/fsfw_hal/devicehandlers/CMakeLists.txt b/src/fsfw_hal/devicehandlers/CMakeLists.txt index 17139416c..e5999ad53 100644 --- a/src/fsfw_hal/devicehandlers/CMakeLists.txt +++ b/src/fsfw_hal/devicehandlers/CMakeLists.txt @@ -1,3 +1,5 @@ target_sources( ${LIB_FSFW_NAME} PRIVATE GyroL3GD20Handler.cpp MgmRM3100Handler.cpp MgmLIS3MDLHandler.cpp) + +add_subdirectory(devicedefinitions) diff --git a/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.cpp b/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.cpp index 46ca17b96..c71f34ce8 100644 --- a/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.cpp +++ b/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.cpp @@ -46,17 +46,17 @@ ReturnValue_t GyroHandlerL3GD20H::buildTransitionDeviceCommand(DeviceCommandId_t return NOTHING_TO_SEND; } case (InternalState::CONFIGURE): { - *id = L3GD20H::CONFIGURE_CTRL_REGS; + *id = l3gd20h::CONFIGURE_CTRL_REGS; uint8_t command[5]; - command[0] = L3GD20H::CTRL_REG_1_VAL; - command[1] = L3GD20H::CTRL_REG_2_VAL; - command[2] = L3GD20H::CTRL_REG_3_VAL; - command[3] = L3GD20H::CTRL_REG_4_VAL; - command[4] = L3GD20H::CTRL_REG_5_VAL; + command[0] = l3gd20h::CTRL_REG_1_VAL; + command[1] = l3gd20h::CTRL_REG_2_VAL; + command[2] = l3gd20h::CTRL_REG_3_VAL; + command[3] = l3gd20h::CTRL_REG_4_VAL; + command[4] = l3gd20h::CTRL_REG_5_VAL; return buildCommandFromCommand(*id, command, 5); } case (InternalState::CHECK_REGS): { - *id = L3GD20H::READ_REGS; + *id = l3gd20h::READ_REGS; return buildCommandFromCommand(*id, nullptr, 0); } default: @@ -76,7 +76,7 @@ ReturnValue_t GyroHandlerL3GD20H::buildTransitionDeviceCommand(DeviceCommandId_t } ReturnValue_t GyroHandlerL3GD20H::buildNormalDeviceCommand(DeviceCommandId_t *id) { - *id = L3GD20H::READ_REGS; + *id = l3gd20h::READ_REGS; return buildCommandFromCommand(*id, nullptr, 0); } @@ -84,15 +84,15 @@ ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand(DeviceCommandId_t devi const uint8_t *commandData, size_t commandDataLen) { switch (deviceCommand) { - case (L3GD20H::READ_REGS): { - commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | L3GD20H::READ_MASK; - std::memset(commandBuffer + 1, 0, L3GD20H::READ_LEN); + case (l3gd20h::READ_REGS): { + commandBuffer[0] = l3gd20h::READ_START | l3gd20h::AUTO_INCREMENT_MASK | l3gd20h::READ_MASK; + std::memset(commandBuffer + 1, 0, l3gd20h::READ_LEN); rawPacket = commandBuffer; - rawPacketLen = L3GD20H::READ_LEN + 1; + rawPacketLen = l3gd20h::READ_LEN + 1; break; } - case (L3GD20H::CONFIGURE_CTRL_REGS): { - commandBuffer[0] = L3GD20H::CTRL_REG_1 | L3GD20H::AUTO_INCREMENT_MASK; + case (l3gd20h::CONFIGURE_CTRL_REGS): { + commandBuffer[0] = l3gd20h::CTRL_REG_1 | l3gd20h::AUTO_INCREMENT_MASK; if (commandData == nullptr or commandDataLen != 5) { return DeviceHandlerIF::INVALID_COMMAND_PARAMETER; } @@ -103,15 +103,15 @@ ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand(DeviceCommandId_t devi ctrlReg4Value = commandData[3]; ctrlReg5Value = commandData[4]; - bool fsH = ctrlReg4Value & L3GD20H::SET_FS_1; - bool fsL = ctrlReg4Value & L3GD20H::SET_FS_0; + bool fsH = ctrlReg4Value & l3gd20h::SET_FS_1; + bool fsL = ctrlReg4Value & l3gd20h::SET_FS_0; if (not fsH and not fsL) { - sensitivity = L3GD20H::SENSITIVITY_00; + sensitivity = l3gd20h::SENSITIVITY_00; } else if (not fsH and fsL) { - sensitivity = L3GD20H::SENSITIVITY_01; + sensitivity = l3gd20h::SENSITIVITY_01; } else { - sensitivity = L3GD20H::SENSITIVITY_11; + sensitivity = l3gd20h::SENSITIVITY_11; } commandBuffer[1] = ctrlReg1Value; @@ -124,8 +124,8 @@ ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand(DeviceCommandId_t devi rawPacketLen = 6; break; } - case (L3GD20H::READ_CTRL_REGS): { - commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | L3GD20H::READ_MASK; + case (l3gd20h::READ_CTRL_REGS): { + commandBuffer[0] = l3gd20h::READ_START | l3gd20h::AUTO_INCREMENT_MASK | l3gd20h::READ_MASK; std::memset(commandBuffer + 1, 0, 5); rawPacket = commandBuffer; @@ -151,11 +151,11 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { ReturnValue_t result = returnvalue::OK; switch (id) { - case (L3GD20H::CONFIGURE_CTRL_REGS): { + case (l3gd20h::CONFIGURE_CTRL_REGS): { commandExecuted = true; break; } - case (L3GD20H::READ_CTRL_REGS): { + case (l3gd20h::READ_CTRL_REGS): { if (packet[1] == ctrlReg1Value and packet[2] == ctrlReg2Value and packet[3] == ctrlReg3Value and packet[4] == ctrlReg4Value and packet[5] == ctrlReg5Value) { @@ -167,7 +167,7 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, } break; } - case (L3GD20H::READ_REGS): { + case (l3gd20h::READ_REGS): { if (packet[1] != ctrlReg1Value and packet[2] != ctrlReg2Value and packet[3] != ctrlReg3Value and packet[4] != ctrlReg4Value and packet[5] != ctrlReg5Value) { @@ -178,16 +178,16 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id, } } - statusReg = packet[L3GD20H::STATUS_IDX]; + statusReg = packet[l3gd20h::STATUS_IDX]; - int16_t angVelocXRaw = packet[L3GD20H::OUT_X_H] << 8 | packet[L3GD20H::OUT_X_L]; - int16_t angVelocYRaw = packet[L3GD20H::OUT_Y_H] << 8 | packet[L3GD20H::OUT_Y_L]; - int16_t angVelocZRaw = packet[L3GD20H::OUT_Z_H] << 8 | packet[L3GD20H::OUT_Z_L]; + int16_t angVelocXRaw = packet[l3gd20h::OUT_X_H] << 8 | packet[l3gd20h::OUT_X_L]; + int16_t angVelocYRaw = packet[l3gd20h::OUT_Y_H] << 8 | packet[l3gd20h::OUT_Y_L]; + int16_t angVelocZRaw = packet[l3gd20h::OUT_Z_H] << 8 | packet[l3gd20h::OUT_Z_L]; float angVelocX = angVelocXRaw * sensitivity; float angVelocY = angVelocYRaw * sensitivity; float angVelocZ = angVelocZRaw * sensitivity; - int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX]; + int8_t temperaturOffset = (-1) * packet[l3gd20h::TEMPERATURE_IDX]; float temperature = 25.0 + temperaturOffset; if (periodicPrintout) { if (debugDivider.checkAndIncrement()) { @@ -248,19 +248,19 @@ void GyroHandlerL3GD20H::setToGoToNormalMode(bool enable) { this->goNormalModeIm ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X, new PoolEntry({0.0})); - localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, new PoolEntry({0.0})); - localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Z, new PoolEntry({0.0})); - localDataPoolMap.emplace(L3GD20H::TEMPERATURE, new PoolEntry({0.0})); + localDataPoolMap.emplace(l3gd20h::ANG_VELOC_X, new PoolEntry({0.0})); + localDataPoolMap.emplace(l3gd20h::ANG_VELOC_Y, new PoolEntry({0.0})); + localDataPoolMap.emplace(l3gd20h::ANG_VELOC_Z, new PoolEntry({0.0})); + localDataPoolMap.emplace(l3gd20h::TEMPERATURE, new PoolEntry({0.0})); poolManager.subscribeForRegularPeriodicPacket( subdp::RegularHkPeriodicParams(dataset.getSid(), false, 10.0)); return returnvalue::OK; } void GyroHandlerL3GD20H::fillCommandAndReplyMap() { - insertInCommandAndReplyMap(L3GD20H::READ_REGS, 1, &dataset); - insertInCommandAndReplyMap(L3GD20H::CONFIGURE_CTRL_REGS, 1); - insertInCommandAndReplyMap(L3GD20H::READ_CTRL_REGS, 1); + insertInCommandAndReplyMap(l3gd20h::READ_REGS, 1, &dataset); + insertInCommandAndReplyMap(l3gd20h::CONFIGURE_CTRL_REGS, 1); + insertInCommandAndReplyMap(l3gd20h::READ_CTRL_REGS, 1); } void GyroHandlerL3GD20H::modeChanged() { internalState = InternalState::NONE; } diff --git a/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.h b/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.h index 7c1ebdac1..9897dc002 100644 --- a/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.h +++ b/src/fsfw_hal/devicehandlers/GyroL3GD20Handler.h @@ -3,8 +3,7 @@ #include #include - -#include "devicedefinitions/GyroL3GD20Definitions.h" +#include /** * @brief Device Handler for the L3GD20H gyroscope sensor @@ -59,9 +58,9 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase { uint32_t transitionDelayMs = 0; GyroPrimaryDataset dataset; - float absLimitX = L3GD20H::RANGE_DPS_00; - float absLimitY = L3GD20H::RANGE_DPS_00; - float absLimitZ = L3GD20H::RANGE_DPS_00; + float absLimitX = l3gd20h::RANGE_DPS_00; + float absLimitY = l3gd20h::RANGE_DPS_00; + float absLimitZ = l3gd20h::RANGE_DPS_00; enum class InternalState { NONE, CONFIGURE, CHECK_REGS, NORMAL }; InternalState internalState = InternalState::NONE; @@ -70,16 +69,16 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase { uint8_t statusReg = 0; bool goNormalModeImmediately = false; - uint8_t ctrlReg1Value = L3GD20H::CTRL_REG_1_VAL; - uint8_t ctrlReg2Value = L3GD20H::CTRL_REG_2_VAL; - uint8_t ctrlReg3Value = L3GD20H::CTRL_REG_3_VAL; - uint8_t ctrlReg4Value = L3GD20H::CTRL_REG_4_VAL; - uint8_t ctrlReg5Value = L3GD20H::CTRL_REG_5_VAL; + uint8_t ctrlReg1Value = l3gd20h::CTRL_REG_1_VAL; + uint8_t ctrlReg2Value = l3gd20h::CTRL_REG_2_VAL; + uint8_t ctrlReg3Value = l3gd20h::CTRL_REG_3_VAL; + uint8_t ctrlReg4Value = l3gd20h::CTRL_REG_4_VAL; + uint8_t ctrlReg5Value = l3gd20h::CTRL_REG_5_VAL; - uint8_t commandBuffer[L3GD20H::READ_LEN + 1]; + uint8_t commandBuffer[l3gd20h::READ_LEN + 1]; // Set default value - float sensitivity = L3GD20H::SENSITIVITY_00; + float sensitivity = l3gd20h::SENSITIVITY_00; bool periodicPrintout = false; PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3); diff --git a/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp b/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp index 82027bfdb..a66745e1b 100644 --- a/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp +++ b/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp @@ -10,11 +10,11 @@ MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCom dataset(this), transitionDelay(transitionDelay) { // Set to default values right away - registers[0] = MGMLIS3MDL::CTRL_REG1_DEFAULT; - registers[1] = MGMLIS3MDL::CTRL_REG2_DEFAULT; - registers[2] = MGMLIS3MDL::CTRL_REG3_DEFAULT; - registers[3] = MGMLIS3MDL::CTRL_REG4_DEFAULT; - registers[4] = MGMLIS3MDL::CTRL_REG5_DEFAULT; + registers[0] = mgmLis3::CTRL_REG1_DEFAULT; + registers[1] = mgmLis3::CTRL_REG2_DEFAULT; + registers[2] = mgmLis3::CTRL_REG3_DEFAULT; + registers[3] = mgmLis3::CTRL_REG4_DEFAULT; + registers[4] = mgmLis3::CTRL_REG5_DEFAULT; } MgmLIS3MDLHandler::~MgmLIS3MDLHandler() {} @@ -63,15 +63,15 @@ ReturnValue_t MgmLIS3MDLHandler::buildTransitionDeviceCommand(DeviceCommandId_t return DeviceHandlerBase::NOTHING_TO_SEND; } case (InternalState::STATE_FIRST_CONTACT): { - *id = MGMLIS3MDL::IDENTIFY_DEVICE; + *id = mgmLis3::IDENTIFY_DEVICE; break; } case (InternalState::STATE_SETUP): { - *id = MGMLIS3MDL::SETUP_MGM; + *id = mgmLis3::SETUP_MGM; break; } case (InternalState::STATE_CHECK_REGISTERS): { - *id = MGMLIS3MDL::READ_CONFIG_AND_DATA; + *id = mgmLis3::READ_CONFIG_AND_DATA; break; } default: { @@ -88,28 +88,12 @@ ReturnValue_t MgmLIS3MDLHandler::buildTransitionDeviceCommand(DeviceCommandId_t return buildCommandFromCommand(*id, NULL, 0); } -uint8_t MgmLIS3MDLHandler::readCommand(uint8_t command, bool continuousCom) { - command |= (1 << MGMLIS3MDL::RW_BIT); - if (continuousCom == true) { - command |= (1 << MGMLIS3MDL::MS_BIT); - } - return command; -} - -uint8_t MgmLIS3MDLHandler::writeCommand(uint8_t command, bool continuousCom) { - command &= ~(1 << MGMLIS3MDL::RW_BIT); - if (continuousCom == true) { - command |= (1 << MGMLIS3MDL::MS_BIT); - } - return command; -} - void MgmLIS3MDLHandler::setupMgm() { - registers[0] = MGMLIS3MDL::CTRL_REG1_DEFAULT; - registers[1] = MGMLIS3MDL::CTRL_REG2_DEFAULT; - registers[2] = MGMLIS3MDL::CTRL_REG3_DEFAULT; - registers[3] = MGMLIS3MDL::CTRL_REG4_DEFAULT; - registers[4] = MGMLIS3MDL::CTRL_REG5_DEFAULT; + registers[0] = mgmLis3::CTRL_REG1_DEFAULT; + registers[1] = mgmLis3::CTRL_REG2_DEFAULT; + registers[2] = mgmLis3::CTRL_REG3_DEFAULT; + registers[3] = mgmLis3::CTRL_REG4_DEFAULT; + registers[4] = mgmLis3::CTRL_REG5_DEFAULT; prepareCtrlRegisterWrite(); } @@ -117,11 +101,11 @@ void MgmLIS3MDLHandler::setupMgm() { ReturnValue_t MgmLIS3MDLHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) { // Data/config register will be read in an alternating manner. if (communicationStep == CommunicationStep::DATA) { - *id = MGMLIS3MDL::READ_CONFIG_AND_DATA; + *id = mgmLis3::READ_CONFIG_AND_DATA; communicationStep = CommunicationStep::TEMPERATURE; return buildCommandFromCommand(*id, NULL, 0); } else { - *id = MGMLIS3MDL::READ_TEMPERATURE; + *id = mgmLis3::READ_TEMPERATURE; communicationStep = CommunicationStep::DATA; return buildCommandFromCommand(*id, NULL, 0); } @@ -131,33 +115,33 @@ ReturnValue_t MgmLIS3MDLHandler::buildCommandFromCommand(DeviceCommandId_t devic const uint8_t *commandData, size_t commandDataLen) { switch (deviceCommand) { - case (MGMLIS3MDL::READ_CONFIG_AND_DATA): { + case (mgmLis3::READ_CONFIG_AND_DATA): { std::memset(commandBuffer, 0, sizeof(commandBuffer)); - commandBuffer[0] = readCommand(MGMLIS3MDL::CTRL_REG1, true); + commandBuffer[0] = mgmLis3::readCommand(mgmLis3::CTRL_REG1, true); rawPacket = commandBuffer; - rawPacketLen = MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1; + rawPacketLen = mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS + 1; return returnvalue::OK; } - case (MGMLIS3MDL::READ_TEMPERATURE): { + case (mgmLis3::READ_TEMPERATURE): { std::memset(commandBuffer, 0, 3); - commandBuffer[0] = readCommand(MGMLIS3MDL::TEMP_LOWBYTE, true); + commandBuffer[0] = mgmLis3::readCommand(mgmLis3::TEMP_LOWBYTE, true); rawPacket = commandBuffer; rawPacketLen = 3; return returnvalue::OK; } - case (MGMLIS3MDL::IDENTIFY_DEVICE): { + case (mgmLis3::IDENTIFY_DEVICE): { return identifyDevice(); } - case (MGMLIS3MDL::TEMP_SENSOR_ENABLE): { + case (mgmLis3::TEMP_SENSOR_ENABLE): { return enableTemperatureSensor(commandData, commandDataLen); } - case (MGMLIS3MDL::SETUP_MGM): { + case (mgmLis3::SETUP_MGM): { setupMgm(); return returnvalue::OK; } - case (MGMLIS3MDL::ACCURACY_OP_MODE_SET): { + case (mgmLis3::ACCURACY_OP_MODE_SET): { return setOperatingMode(commandData, commandDataLen); } default: @@ -168,7 +152,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildCommandFromCommand(DeviceCommandId_t devic ReturnValue_t MgmLIS3MDLHandler::identifyDevice() { uint32_t size = 2; - commandBuffer[0] = readCommand(MGMLIS3MDL::IDENTIFY_DEVICE_REG_ADDR); + commandBuffer[0] = mgmLis3::readCommand(mgmLis3::IDENTIFY_DEVICE_REG_ADDR); commandBuffer[1] = 0x00; rawPacket = commandBuffer; @@ -180,9 +164,9 @@ ReturnValue_t MgmLIS3MDLHandler::identifyDevice() { ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len, DeviceCommandId_t *foundId, size_t *foundLen) { *foundLen = len; - if (len == MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1) { + if (len == mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS + 1) { *foundLen = len; - *foundId = MGMLIS3MDL::READ_CONFIG_AND_DATA; + *foundId = mgmLis3::READ_CONFIG_AND_DATA; // Check validity by checking config registers if (start[1] != registers[0] or start[2] != registers[1] or start[3] != registers[2] or start[4] != registers[3] or start[5] != registers[4]) { @@ -199,17 +183,17 @@ ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len, commandExecuted = true; } - } else if (len == MGMLIS3MDL::TEMPERATURE_REPLY_LEN) { + } else if (len == mgmLis3::TEMPERATURE_REPLY_LEN) { *foundLen = len; - *foundId = MGMLIS3MDL::READ_TEMPERATURE; - } else if (len == MGMLIS3MDL::SETUP_REPLY_LEN) { + *foundId = mgmLis3::READ_TEMPERATURE; + } else if (len == mgmLis3::SETUP_REPLY_LEN) { *foundLen = len; - *foundId = MGMLIS3MDL::SETUP_MGM; + *foundId = mgmLis3::SETUP_MGM; } else if (len == SINGLE_COMMAND_ANSWER_LEN) { *foundLen = len; *foundId = getPendingCommand(); - if (*foundId == MGMLIS3MDL::IDENTIFY_DEVICE) { - if (start[1] != MGMLIS3MDL::DEVICE_ID) { + if (*foundId == mgmLis3::IDENTIFY_DEVICE) { + if (start[1] != mgmLis3::DEVICE_ID) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "MGMHandlerLIS3MDL::scanForReply: " @@ -241,30 +225,31 @@ ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len, } ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { switch (id) { - case MGMLIS3MDL::IDENTIFY_DEVICE: { + case mgmLis3::IDENTIFY_DEVICE: { break; } - case MGMLIS3MDL::SETUP_MGM: { + case mgmLis3::SETUP_MGM: { break; } - case MGMLIS3MDL::READ_CONFIG_AND_DATA: { + case mgmLis3::READ_CONFIG_AND_DATA: { + using namespace mgmLis3; // TODO: Store configuration in new local datasets. float sensitivityFactor = getSensitivityFactor(getSensitivity(registers[2])); int16_t mgmMeasurementRawX = - packet[MGMLIS3MDL::X_HIGHBYTE_IDX] << 8 | packet[MGMLIS3MDL::X_LOWBYTE_IDX]; + packet[mgmLis3::X_HIGHBYTE_IDX] << 8 | packet[mgmLis3::X_LOWBYTE_IDX]; int16_t mgmMeasurementRawY = - packet[MGMLIS3MDL::Y_HIGHBYTE_IDX] << 8 | packet[MGMLIS3MDL::Y_LOWBYTE_IDX]; + packet[mgmLis3::Y_HIGHBYTE_IDX] << 8 | packet[mgmLis3::Y_LOWBYTE_IDX]; int16_t mgmMeasurementRawZ = - packet[MGMLIS3MDL::Z_HIGHBYTE_IDX] << 8 | packet[MGMLIS3MDL::Z_LOWBYTE_IDX]; + packet[mgmLis3::Z_HIGHBYTE_IDX] << 8 | packet[mgmLis3::Z_LOWBYTE_IDX]; // Target value in microtesla float mgmX = static_cast(mgmMeasurementRawX) * sensitivityFactor * - MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR; + mgmLis3::GAUSS_TO_MICROTESLA_FACTOR; float mgmY = static_cast(mgmMeasurementRawY) * sensitivityFactor * - MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR; + mgmLis3::GAUSS_TO_MICROTESLA_FACTOR; float mgmZ = static_cast(mgmMeasurementRawZ) * sensitivityFactor * - MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR; + mgmLis3::GAUSS_TO_MICROTESLA_FACTOR; if (periodicPrintout) { if (debugDivider.checkAndIncrement()) { @@ -306,7 +291,7 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons break; } - case MGMLIS3MDL::READ_TEMPERATURE: { + case mgmLis3::READ_TEMPERATURE: { int16_t tempValueRaw = packet[2] << 8 | packet[1]; float tempValue = 25.0 + ((static_cast(tempValueRaw)) / 8.0); if (periodicPrintout) { @@ -334,41 +319,6 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons return returnvalue::OK; } -MGMLIS3MDL::Sensitivies MgmLIS3MDLHandler::getSensitivity(uint8_t ctrlRegister2) { - bool fs0Set = ctrlRegister2 & (1 << MGMLIS3MDL::FSO); // Checks if FS0 bit is set - bool fs1Set = ctrlRegister2 & (1 << MGMLIS3MDL::FS1); // Checks if FS1 bit is set - - if (fs0Set && fs1Set) - return MGMLIS3MDL::Sensitivies::GAUSS_16; - else if (!fs0Set && fs1Set) - return MGMLIS3MDL::Sensitivies::GAUSS_12; - else if (fs0Set && !fs1Set) - return MGMLIS3MDL::Sensitivies::GAUSS_8; - else - return MGMLIS3MDL::Sensitivies::GAUSS_4; -} - -float MgmLIS3MDLHandler::getSensitivityFactor(MGMLIS3MDL::Sensitivies sens) { - switch (sens) { - case (MGMLIS3MDL::GAUSS_4): { - return MGMLIS3MDL::FIELD_LSB_PER_GAUSS_4_SENS; - } - case (MGMLIS3MDL::GAUSS_8): { - return MGMLIS3MDL::FIELD_LSB_PER_GAUSS_8_SENS; - } - case (MGMLIS3MDL::GAUSS_12): { - return MGMLIS3MDL::FIELD_LSB_PER_GAUSS_12_SENS; - } - case (MGMLIS3MDL::GAUSS_16): { - return MGMLIS3MDL::FIELD_LSB_PER_GAUSS_16_SENS; - } - default: { - // Should never happen - return MGMLIS3MDL::FIELD_LSB_PER_GAUSS_4_SENS; - } - } -} - ReturnValue_t MgmLIS3MDLHandler::enableTemperatureSensor(const uint8_t *commandData, size_t commandDataLen) { if (commandData == nullptr) { @@ -376,16 +326,16 @@ ReturnValue_t MgmLIS3MDLHandler::enableTemperatureSensor(const uint8_t *commandD } triggerEvent(CHANGE_OF_SETUP_PARAMETER); uint32_t size = 2; - commandBuffer[0] = writeCommand(MGMLIS3MDL::CTRL_REG1); + commandBuffer[0] = mgmLis3::writeCommand(mgmLis3::CTRL_REG1); if (commandDataLen > 1) { return INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS; } switch (commandData[0]) { - case (MGMLIS3MDL::ON): { + case (mgmLis3::ON): { commandBuffer[1] = registers[0] | (1 << 7); break; } - case (MGMLIS3MDL::OFF): { + case (mgmLis3::OFF): { commandBuffer[1] = registers[0] & ~(1 << 7); break; } @@ -408,23 +358,23 @@ ReturnValue_t MgmLIS3MDLHandler::setOperatingMode(const uint8_t *commandData, } switch (commandData[0]) { - case MGMLIS3MDL::LOW: - registers[0] = (registers[0] & (~(1 << MGMLIS3MDL::OM1))) & (~(1 << MGMLIS3MDL::OM0)); - registers[3] = (registers[3] & (~(1 << MGMLIS3MDL::OMZ1))) & (~(1 << MGMLIS3MDL::OMZ0)); + case mgmLis3::LOW: + registers[0] = (registers[0] & (~(1 << mgmLis3::OM1))) & (~(1 << mgmLis3::OM0)); + registers[3] = (registers[3] & (~(1 << mgmLis3::OMZ1))) & (~(1 << mgmLis3::OMZ0)); break; - case MGMLIS3MDL::MEDIUM: - registers[0] = (registers[0] & (~(1 << MGMLIS3MDL::OM1))) | (1 << MGMLIS3MDL::OM0); - registers[3] = (registers[3] & (~(1 << MGMLIS3MDL::OMZ1))) | (1 << MGMLIS3MDL::OMZ0); + case mgmLis3::MEDIUM: + registers[0] = (registers[0] & (~(1 << mgmLis3::OM1))) | (1 << mgmLis3::OM0); + registers[3] = (registers[3] & (~(1 << mgmLis3::OMZ1))) | (1 << mgmLis3::OMZ0); break; - case MGMLIS3MDL::HIGH: - registers[0] = (registers[0] | (1 << MGMLIS3MDL::OM1)) & (~(1 << MGMLIS3MDL::OM0)); - registers[3] = (registers[3] | (1 << MGMLIS3MDL::OMZ1)) & (~(1 << MGMLIS3MDL::OMZ0)); + case mgmLis3::HIGH: + registers[0] = (registers[0] | (1 << mgmLis3::OM1)) & (~(1 << mgmLis3::OM0)); + registers[3] = (registers[3] | (1 << mgmLis3::OMZ1)) & (~(1 << mgmLis3::OMZ0)); break; - case MGMLIS3MDL::ULTRA: - registers[0] = (registers[0] | (1 << MGMLIS3MDL::OM1)) | (1 << MGMLIS3MDL::OM0); - registers[3] = (registers[3] | (1 << MGMLIS3MDL::OMZ1)) | (1 << MGMLIS3MDL::OMZ0); + case mgmLis3::ULTRA: + registers[0] = (registers[0] | (1 << mgmLis3::OM1)) | (1 << mgmLis3::OM0); + registers[3] = (registers[3] | (1 << mgmLis3::OMZ1)) | (1 << mgmLis3::OMZ0); break; default: break; @@ -434,24 +384,24 @@ ReturnValue_t MgmLIS3MDLHandler::setOperatingMode(const uint8_t *commandData, } void MgmLIS3MDLHandler::fillCommandAndReplyMap() { - insertInCommandAndReplyMap(MGMLIS3MDL::READ_CONFIG_AND_DATA, 1, &dataset); - insertInCommandAndReplyMap(MGMLIS3MDL::READ_TEMPERATURE, 1); - insertInCommandAndReplyMap(MGMLIS3MDL::SETUP_MGM, 1); - insertInCommandAndReplyMap(MGMLIS3MDL::IDENTIFY_DEVICE, 1); - insertInCommandAndReplyMap(MGMLIS3MDL::TEMP_SENSOR_ENABLE, 1); - insertInCommandAndReplyMap(MGMLIS3MDL::ACCURACY_OP_MODE_SET, 1); + insertInCommandAndReplyMap(mgmLis3::READ_CONFIG_AND_DATA, 1, &dataset); + insertInCommandAndReplyMap(mgmLis3::READ_TEMPERATURE, 1); + insertInCommandAndReplyMap(mgmLis3::SETUP_MGM, 1); + insertInCommandAndReplyMap(mgmLis3::IDENTIFY_DEVICE, 1); + insertInCommandAndReplyMap(mgmLis3::TEMP_SENSOR_ENABLE, 1); + insertInCommandAndReplyMap(mgmLis3::ACCURACY_OP_MODE_SET, 1); } void MgmLIS3MDLHandler::setToGoToNormalMode(bool enable) { this->goToNormalMode = enable; } ReturnValue_t MgmLIS3MDLHandler::prepareCtrlRegisterWrite() { - commandBuffer[0] = writeCommand(MGMLIS3MDL::CTRL_REG1, true); + commandBuffer[0] = mgmLis3::writeCommand(mgmLis3::CTRL_REG1, true); - for (size_t i = 0; i < MGMLIS3MDL::NR_OF_CTRL_REGISTERS; i++) { + for (size_t i = 0; i < mgmLis3::NR_OF_CTRL_REGISTERS; i++) { commandBuffer[i + 1] = registers[i]; } rawPacket = commandBuffer; - rawPacketLen = MGMLIS3MDL::NR_OF_CTRL_REGISTERS + 1; + rawPacketLen = mgmLis3::NR_OF_CTRL_REGISTERS + 1; // We dont have to check if this is working because we just did i return returnvalue::OK; @@ -467,8 +417,8 @@ void MgmLIS3MDLHandler::modeChanged(void) { internalState = InternalState::STATE ReturnValue_t MgmLIS3MDLHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTHS, &mgmXYZ); - localDataPoolMap.emplace(MGMLIS3MDL::TEMPERATURE_CELCIUS, &temperature); + localDataPoolMap.emplace(mgmLis3::FIELD_STRENGTHS, &mgmXYZ); + localDataPoolMap.emplace(mgmLis3::TEMPERATURE_CELCIUS, &temperature); poolManager.subscribeForRegularPeriodicPacket({dataset.getSid(), false, 10.0}); return returnvalue::OK; } diff --git a/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h b/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h index 3626a2b08..78b3b38c9 100644 --- a/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h +++ b/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.h @@ -1,7 +1,8 @@ #ifndef MISSION_DEVICES_MGMLIS3MDLHANDLER_H_ #define MISSION_DEVICES_MGMLIS3MDLHANDLER_H_ -#include "devicedefinitions/MgmLIS3HandlerDefs.h" +#include + #include "fsfw/devicehandlers/DeviceHandlerBase.h" #include "fsfw/globalfunctions/PeriodicOperationDivider.h" @@ -66,7 +67,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase { LocalDataPoolManager &poolManager) override; private: - MGMLIS3MDL::MgmPrimaryDataset dataset; + mgmLis3::MgmPrimaryDataset dataset; // Length a single command SPI answer static const uint8_t SINGLE_COMMAND_ANSWER_LEN = 2; @@ -74,7 +75,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase { // Single SPI command has 2 bytes, first for adress, second for content size_t singleComandSize = 2; // Has the size for all adresses of the lis3mdl + the continous write bit - uint8_t commandBuffer[MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1]; + uint8_t commandBuffer[mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS + 1]; float absLimitX = 100; float absLimitY = 100; @@ -85,7 +86,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase { * registers when we want to change something. * --> everytime we change set a register we have to save it */ - uint8_t registers[MGMLIS3MDL::NR_OF_CTRL_REGISTERS]; + uint8_t registers[mgmLis3::NR_OF_CTRL_REGISTERS]; uint8_t statusRegister = 0; bool goToNormalMode = false; @@ -107,35 +108,6 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase { /*------------------------------------------------------------------------*/ /* Device specific commands and variables */ /*------------------------------------------------------------------------*/ - /** - * Sets the read bit for the command - * @param single command to set the read-bit at - * @param boolean to select a continuous read bit, default = false - */ - uint8_t readCommand(uint8_t command, bool continuousCom = false); - - /** - * Sets the write bit for the command - * @param single command to set the write-bit at - * @param boolean to select a continuous write bit, default = false - */ - uint8_t writeCommand(uint8_t command, bool continuousCom = false); - - /** - * This Method gets the full scale for the measurement range - * e.g.: +- 4 gauss. See p.25 datasheet. - * @return The ReturnValue does not contain the sign of the value - */ - MGMLIS3MDL::Sensitivies getSensitivity(uint8_t ctrlReg2); - - /** - * The 16 bit value needs to be multiplied with a sensitivity factor - * which depends on the sensitivity configuration - * - * @param sens Configured sensitivity of the LIS3 device - * @return Multiplication factor to get the sensor value from raw data. - */ - float getSensitivityFactor(MGMLIS3MDL::Sensitivies sens); /** * This Command detects the device ID diff --git a/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp b/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp index 4becd4209..c17e3abce 100644 --- a/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp +++ b/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp @@ -63,21 +63,21 @@ ReturnValue_t MgmRM3100Handler::buildTransitionDeviceCommand(DeviceCommandId_t * return NOTHING_TO_SEND; } case (InternalState::CONFIGURE_CMM): { - *id = RM3100::CONFIGURE_CMM; + *id = mgmRm3100::CONFIGURE_CMM; break; } case (InternalState::READ_CMM): { - *id = RM3100::READ_CMM; + *id = mgmRm3100::READ_CMM; break; } case (InternalState::STATE_CONFIGURE_TMRC): { - commandBuffer[0] = RM3100::TMRC_DEFAULT_VALUE; + commandBuffer[0] = mgmRm3100::TMRC_DEFAULT_VALUE; commandLen = 1; - *id = RM3100::CONFIGURE_TMRC; + *id = mgmRm3100::CONFIGURE_TMRC; break; } case (InternalState::STATE_READ_TMRC): { - *id = RM3100::READ_TMRC; + *id = mgmRm3100::READ_TMRC; break; } default: @@ -103,42 +103,42 @@ ReturnValue_t MgmRM3100Handler::buildCommandFromCommand(DeviceCommandId_t device const uint8_t *commandData, size_t commandDataLen) { switch (deviceCommand) { - case (RM3100::CONFIGURE_CMM): { - commandBuffer[0] = RM3100::CMM_REGISTER; - commandBuffer[1] = RM3100::CMM_VALUE; + case (mgmRm3100::CONFIGURE_CMM): { + commandBuffer[0] = mgmRm3100::CMM_REGISTER; + commandBuffer[1] = mgmRm3100::CMM_VALUE; rawPacket = commandBuffer; rawPacketLen = 2; break; } - case (RM3100::READ_CMM): { - commandBuffer[0] = RM3100::CMM_REGISTER | RM3100::READ_MASK; + case (mgmRm3100::READ_CMM): { + commandBuffer[0] = mgmRm3100::CMM_REGISTER | mgmRm3100::READ_MASK; commandBuffer[1] = 0; rawPacket = commandBuffer; rawPacketLen = 2; break; } - case (RM3100::CONFIGURE_TMRC): { + case (mgmRm3100::CONFIGURE_TMRC): { return handleTmrcConfigCommand(deviceCommand, commandData, commandDataLen); } - case (RM3100::READ_TMRC): { - commandBuffer[0] = RM3100::TMRC_REGISTER | RM3100::READ_MASK; + case (mgmRm3100::READ_TMRC): { + commandBuffer[0] = mgmRm3100::TMRC_REGISTER | mgmRm3100::READ_MASK; commandBuffer[1] = 0; rawPacket = commandBuffer; rawPacketLen = 2; break; } - case (RM3100::CONFIGURE_CYCLE_COUNT): { + case (mgmRm3100::CONFIGURE_CYCLE_COUNT): { return handleCycleCountConfigCommand(deviceCommand, commandData, commandDataLen); } - case (RM3100::READ_CYCLE_COUNT): { - commandBuffer[0] = RM3100::CYCLE_COUNT_START_REGISTER | RM3100::READ_MASK; + case (mgmRm3100::READ_CYCLE_COUNT): { + commandBuffer[0] = mgmRm3100::CYCLE_COUNT_START_REGISTER | mgmRm3100::READ_MASK; std::memset(commandBuffer + 1, 0, 6); rawPacket = commandBuffer; rawPacketLen = 7; break; } - case (RM3100::READ_DATA): { - commandBuffer[0] = RM3100::MEASUREMENT_REG_START | RM3100::READ_MASK; + case (mgmRm3100::READ_DATA): { + commandBuffer[0] = mgmRm3100::MEASUREMENT_REG_START | mgmRm3100::READ_MASK; std::memset(commandBuffer + 1, 0, 9); rawPacketLen = 10; break; @@ -150,7 +150,7 @@ ReturnValue_t MgmRM3100Handler::buildCommandFromCommand(DeviceCommandId_t device } ReturnValue_t MgmRM3100Handler::buildNormalDeviceCommand(DeviceCommandId_t *id) { - *id = RM3100::READ_DATA; + *id = mgmRm3100::READ_DATA; return buildCommandFromCommand(*id, nullptr, 0); } @@ -165,16 +165,16 @@ ReturnValue_t MgmRM3100Handler::scanForReply(const uint8_t *start, size_t len, ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { ReturnValue_t result = returnvalue::OK; switch (id) { - case (RM3100::CONFIGURE_CMM): - case (RM3100::CONFIGURE_CYCLE_COUNT): - case (RM3100::CONFIGURE_TMRC): { + case (mgmRm3100::CONFIGURE_CMM): + case (mgmRm3100::CONFIGURE_CYCLE_COUNT): + case (mgmRm3100::CONFIGURE_TMRC): { // We can only check whether write was successful with read operation if (getMode() == _MODE_START_UP) { commandExecuted = true; } break; } - case (RM3100::READ_CMM): { + case (mgmRm3100::READ_CMM): { uint8_t cmmValue = packet[1]; // We clear the seventh bit in any case // because this one is zero sometimes for some reason @@ -188,7 +188,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const } break; } - case (RM3100::READ_TMRC): { + case (mgmRm3100::READ_TMRC): { if (packet[1] == tmrcRegValue) { commandExecuted = true; // Reading TMRC was commanded. Trigger event to inform ground @@ -202,7 +202,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const } break; } - case (RM3100::READ_CYCLE_COUNT): { + case (mgmRm3100::READ_CYCLE_COUNT): { uint16_t cycleCountX = packet[1] << 8 | packet[2]; uint16_t cycleCountY = packet[3] << 8 | packet[4]; uint16_t cycleCountZ = packet[5] << 8 | packet[6]; @@ -217,7 +217,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const } break; } - case (RM3100::READ_DATA): { + case (mgmRm3100::READ_DATA): { result = handleDataReadout(packet); break; } @@ -244,7 +244,7 @@ ReturnValue_t MgmRM3100Handler::handleCycleCountConfigCommand(DeviceCommandId_t return DeviceHandlerIF::INVALID_COMMAND_PARAMETER; } - commandBuffer[0] = RM3100::CYCLE_COUNT_VALUE; + commandBuffer[0] = mgmRm3100::CYCLE_COUNT_VALUE; std::memcpy(commandBuffer + 1, &cycleCountRegValueX, 2); std::memcpy(commandBuffer + 3, &cycleCountRegValueY, 2); std::memcpy(commandBuffer + 5, &cycleCountRegValueZ, 2); @@ -255,7 +255,7 @@ ReturnValue_t MgmRM3100Handler::handleCycleCountConfigCommand(DeviceCommandId_t ReturnValue_t MgmRM3100Handler::handleCycleCommand(bool oneCycleValue, const uint8_t *commandData, size_t commandDataLen) { - RM3100::CycleCountCommand command(oneCycleValue); + mgmRm3100::CycleCountCommand command(oneCycleValue); ReturnValue_t result = command.deSerialize(&commandData, &commandDataLen, SerializeIF::Endianness::BIG); if (result != returnvalue::OK) { @@ -284,7 +284,7 @@ ReturnValue_t MgmRM3100Handler::handleTmrcConfigCommand(DeviceCommandId_t device return DeviceHandlerIF::INVALID_COMMAND_PARAMETER; } - commandBuffer[0] = RM3100::TMRC_REGISTER; + commandBuffer[0] = mgmRm3100::TMRC_REGISTER; commandBuffer[1] = commandData[0]; tmrcRegValue = commandData[0]; rawPacketLen = 2; @@ -293,23 +293,23 @@ ReturnValue_t MgmRM3100Handler::handleTmrcConfigCommand(DeviceCommandId_t device } void MgmRM3100Handler::fillCommandAndReplyMap() { - insertInCommandAndReplyMap(RM3100::CONFIGURE_CMM, 3); - insertInCommandAndReplyMap(RM3100::READ_CMM, 3); + insertInCommandAndReplyMap(mgmRm3100::CONFIGURE_CMM, 3); + insertInCommandAndReplyMap(mgmRm3100::READ_CMM, 3); - insertInCommandAndReplyMap(RM3100::CONFIGURE_TMRC, 3); - insertInCommandAndReplyMap(RM3100::READ_TMRC, 3); + insertInCommandAndReplyMap(mgmRm3100::CONFIGURE_TMRC, 3); + insertInCommandAndReplyMap(mgmRm3100::READ_TMRC, 3); - insertInCommandAndReplyMap(RM3100::CONFIGURE_CYCLE_COUNT, 3); - insertInCommandAndReplyMap(RM3100::READ_CYCLE_COUNT, 3); + insertInCommandAndReplyMap(mgmRm3100::CONFIGURE_CYCLE_COUNT, 3); + insertInCommandAndReplyMap(mgmRm3100::READ_CYCLE_COUNT, 3); - insertInCommandAndReplyMap(RM3100::READ_DATA, 3, &primaryDataset); + insertInCommandAndReplyMap(mgmRm3100::READ_DATA, 3, &primaryDataset); } void MgmRM3100Handler::modeChanged() { internalState = InternalState::NONE; } ReturnValue_t MgmRM3100Handler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(RM3100::FIELD_STRENGTHS, &mgmXYZ); + localDataPoolMap.emplace(mgmRm3100::FIELD_STRENGTHS, &mgmXYZ); poolManager.subscribeForRegularPeriodicPacket({primaryDataset.getSid(), false, 10.0}); return returnvalue::OK; } diff --git a/src/fsfw_hal/devicehandlers/MgmRM3100Handler.h b/src/fsfw_hal/devicehandlers/MgmRM3100Handler.h index d45b24041..1e56bc9d3 100644 --- a/src/fsfw_hal/devicehandlers/MgmRM3100Handler.h +++ b/src/fsfw_hal/devicehandlers/MgmRM3100Handler.h @@ -1,7 +1,8 @@ #ifndef MISSION_DEVICES_MGMRM3100HANDLER_H_ #define MISSION_DEVICES_MGMRM3100HANDLER_H_ -#include "devicedefinitions/MgmRM3100HandlerDefs.h" +#include + #include "fsfw/devicehandlers/DeviceHandlerBase.h" #include "fsfw/globalfunctions/PeriodicOperationDivider.h" @@ -69,19 +70,19 @@ class MgmRM3100Handler : public DeviceHandlerBase { }; InternalState internalState = InternalState::NONE; bool commandExecuted = false; - RM3100::Rm3100PrimaryDataset primaryDataset; + mgmRm3100::Rm3100PrimaryDataset primaryDataset; uint8_t commandBuffer[10]; uint8_t commandBufferLen = 0; - uint8_t cmmRegValue = RM3100::CMM_VALUE; - uint8_t tmrcRegValue = RM3100::TMRC_DEFAULT_VALUE; - uint16_t cycleCountRegValueX = RM3100::CYCLE_COUNT_VALUE; - uint16_t cycleCountRegValueY = RM3100::CYCLE_COUNT_VALUE; - uint16_t cycleCountRegValueZ = RM3100::CYCLE_COUNT_VALUE; - float scaleFactorX = 1.0 / RM3100::DEFAULT_GAIN; - float scaleFactorY = 1.0 / RM3100::DEFAULT_GAIN; - float scaleFactorZ = 1.0 / RM3100::DEFAULT_GAIN; + uint8_t cmmRegValue = mgmRm3100::CMM_VALUE; + uint8_t tmrcRegValue = mgmRm3100::TMRC_DEFAULT_VALUE; + uint16_t cycleCountRegValueX = mgmRm3100::CYCLE_COUNT_VALUE; + uint16_t cycleCountRegValueY = mgmRm3100::CYCLE_COUNT_VALUE; + uint16_t cycleCountRegValueZ = mgmRm3100::CYCLE_COUNT_VALUE; + float scaleFactorX = 1.0 / mgmRm3100::DEFAULT_GAIN; + float scaleFactorY = 1.0 / mgmRm3100::DEFAULT_GAIN; + float scaleFactorZ = 1.0 / mgmRm3100::DEFAULT_GAIN; bool goToNormalModeAtStartup = false; uint32_t transitionDelay; diff --git a/src/fsfw_hal/devicehandlers/devicedefinitions/CMakeLists.txt b/src/fsfw_hal/devicehandlers/devicedefinitions/CMakeLists.txt new file mode 100644 index 000000000..2d874fb56 --- /dev/null +++ b/src/fsfw_hal/devicehandlers/devicedefinitions/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${LIB_FSFW_NAME} PRIVATE gyroL3gHelpers.cpp mgmLis3Helpers.cpp) diff --git a/src/fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.cpp b/src/fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.cpp new file mode 100644 index 000000000..13f00b102 --- /dev/null +++ b/src/fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.cpp @@ -0,0 +1,14 @@ +#include + +float l3gd20h::ctrlReg4ToSensitivity(uint8_t reg) { + bool fsH = reg & l3gd20h::SET_FS_1; + bool fsL = reg & l3gd20h::SET_FS_0; + + if (not fsH and not fsL) { + return l3gd20h::SENSITIVITY_00; + } else if (not fsH and fsL) { + return l3gd20h::SENSITIVITY_01; + } else { + return l3gd20h::SENSITIVITY_11; + } +} diff --git a/src/fsfw_hal/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h b/src/fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h similarity index 87% rename from src/fsfw_hal/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h rename to src/fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h index 2a85ff3e7..4aef68119 100644 --- a/src/fsfw_hal/devicehandlers/devicedefinitions/GyroL3GD20Definitions.h +++ b/src/fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h @@ -6,7 +6,9 @@ #include -namespace L3GD20H { +namespace l3gd20h { + +float ctrlReg4ToSensitivity(uint8_t reg); /* Actual size is 15 but we round up a bit */ static constexpr size_t MAX_BUFFER_SIZE = 16; @@ -103,31 +105,33 @@ static constexpr DeviceCommandId_t READ_REGS = 0; static constexpr DeviceCommandId_t CONFIGURE_CTRL_REGS = 1; static constexpr DeviceCommandId_t READ_CTRL_REGS = 2; +static constexpr DeviceCommandId_t REQUEST = 0x70; +static constexpr DeviceCommandId_t REPLY = 0x77; + static constexpr uint32_t GYRO_DATASET_ID = READ_REGS; enum GyroPoolIds : lp_id_t { ANG_VELOC_X, ANG_VELOC_Y, ANG_VELOC_Z, TEMPERATURE }; -} // namespace L3GD20H +} // namespace l3gd20h class GyroPrimaryDataset : public StaticLocalDataSet<5> { public: /** Constructor for data users like controllers */ GyroPrimaryDataset(object_id_t mgmId) - : StaticLocalDataSet(sid_t(mgmId, L3GD20H::GYRO_DATASET_ID)) { + : StaticLocalDataSet(sid_t(mgmId, l3gd20h::GYRO_DATASET_ID)) { setAllVariablesReadOnly(); } - - /* Angular velocities in degrees per second (DPS) */ - lp_var_t angVelocX = lp_var_t(sid.objectId, L3GD20H::ANG_VELOC_X, this); - lp_var_t angVelocY = lp_var_t(sid.objectId, L3GD20H::ANG_VELOC_Y, this); - lp_var_t angVelocZ = lp_var_t(sid.objectId, L3GD20H::ANG_VELOC_Z, this); - lp_var_t temperature = lp_var_t(sid.objectId, L3GD20H::TEMPERATURE, this); - - private: - friend class GyroHandlerL3GD20H; /** Constructor for the data creator */ GyroPrimaryDataset(HasLocalDataPoolIF* hkOwner) - : StaticLocalDataSet(hkOwner, L3GD20H::GYRO_DATASET_ID) {} + : StaticLocalDataSet(hkOwner, l3gd20h::GYRO_DATASET_ID) {} + + /* Angular velocities in degrees per second (DPS) */ + lp_var_t angVelocX = lp_var_t(sid.objectId, l3gd20h::ANG_VELOC_X, this); + lp_var_t angVelocY = lp_var_t(sid.objectId, l3gd20h::ANG_VELOC_Y, this); + lp_var_t angVelocZ = lp_var_t(sid.objectId, l3gd20h::ANG_VELOC_Z, this); + lp_var_t temperature = lp_var_t(sid.objectId, l3gd20h::TEMPERATURE, this); + + private: }; #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_GYROL3GD20DEFINITIONS_H_ */ diff --git a/src/fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.cpp b/src/fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.cpp new file mode 100644 index 000000000..3609ea013 --- /dev/null +++ b/src/fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.cpp @@ -0,0 +1,52 @@ +#include "mgmLis3Helpers.h" + +uint8_t mgmLis3::readCommand(uint8_t command, bool continuousCom) { + command |= (1 << mgmLis3::RW_BIT); + if (continuousCom == true) { + command |= (1 << mgmLis3::MS_BIT); + } + return command; +} + +uint8_t mgmLis3::writeCommand(uint8_t command, bool continuousCom) { + command &= ~(1 << mgmLis3::RW_BIT); + if (continuousCom == true) { + command |= (1 << mgmLis3::MS_BIT); + } + return command; +} + +mgmLis3::Sensitivies mgmLis3::getSensitivity(uint8_t ctrlRegister2) { + bool fs0Set = ctrlRegister2 & (1 << mgmLis3::FSO); // Checks if FS0 bit is set + bool fs1Set = ctrlRegister2 & (1 << mgmLis3::FS1); // Checks if FS1 bit is set + + if (fs0Set && fs1Set) + return mgmLis3::Sensitivies::GAUSS_16; + else if (!fs0Set && fs1Set) + return mgmLis3::Sensitivies::GAUSS_12; + else if (fs0Set && !fs1Set) + return mgmLis3::Sensitivies::GAUSS_8; + else + return mgmLis3::Sensitivies::GAUSS_4; +} + +float mgmLis3::getSensitivityFactor(mgmLis3::Sensitivies sens) { + switch (sens) { + case (mgmLis3::GAUSS_4): { + return mgmLis3::FIELD_LSB_PER_GAUSS_4_SENS; + } + case (mgmLis3::GAUSS_8): { + return mgmLis3::FIELD_LSB_PER_GAUSS_8_SENS; + } + case (mgmLis3::GAUSS_12): { + return mgmLis3::FIELD_LSB_PER_GAUSS_12_SENS; + } + case (mgmLis3::GAUSS_16): { + return mgmLis3::FIELD_LSB_PER_GAUSS_16_SENS; + } + default: { + // Should never happen + return mgmLis3::FIELD_LSB_PER_GAUSS_4_SENS; + } + } +} diff --git a/src/fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h b/src/fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h similarity index 86% rename from src/fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h rename to src/fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h index 34237637e..8d47a2008 100644 --- a/src/fsfw_hal/devicehandlers/devicedefinitions/MgmLIS3HandlerDefs.h +++ b/src/fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h @@ -7,13 +7,43 @@ #include -namespace MGMLIS3MDL { +namespace mgmLis3 { enum Set { ON, OFF }; enum OpMode { LOW, MEDIUM, HIGH, ULTRA }; enum Sensitivies : uint8_t { GAUSS_4 = 4, GAUSS_8 = 8, GAUSS_12 = 12, GAUSS_16 = 16 }; +/** + * Sets the read bit for the command + * @param single command to set the read-bit at + * @param boolean to select a continuous read bit, default = false + */ +uint8_t readCommand(uint8_t command, bool continuousCom = false); + +/** + * Sets the write bit for the command + * @param single command to set the write-bit at + * @param boolean to select a continuous write bit, default = false + */ +uint8_t writeCommand(uint8_t command, bool continuousCom = false); + +/** + * This Method gets the full scale for the measurement range + * e.g.: +- 4 gauss. See p.25 datasheet. + * @return The ReturnValue does not contain the sign of the value + */ +mgmLis3::Sensitivies getSensitivity(uint8_t ctrlReg2); + +/** + * The 16 bit value needs to be multiplied with a sensitivity factor + * which depends on the sensitivity configuration + * + * @param sens Configured sensitivity of the LIS3 device + * @return Multiplication factor to get the sensor value from raw data. + */ +float getSensitivityFactor(mgmLis3::Sensitivies sens); + /* Actually 15, we just round up a bit */ static constexpr size_t MAX_BUFFER_SIZE = 16; @@ -154,6 +184,6 @@ class MgmPrimaryDataset : public StaticLocalDataSet<4> { lp_var_t temperature = lp_var_t(sid.objectId, TEMPERATURE_CELCIUS, this); }; -} // namespace MGMLIS3MDL +} // namespace mgmLis3 #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_MGMLIS3HANDLERDEFS_H_ */ diff --git a/src/fsfw_hal/devicehandlers/devicedefinitions/MgmRM3100HandlerDefs.h b/src/fsfw_hal/devicehandlers/devicedefinitions/mgmRm3100Helpers.h similarity index 98% rename from src/fsfw_hal/devicehandlers/devicedefinitions/MgmRM3100HandlerDefs.h rename to src/fsfw_hal/devicehandlers/devicedefinitions/mgmRm3100Helpers.h index a2aa8ab00..680bd13dd 100644 --- a/src/fsfw_hal/devicehandlers/devicedefinitions/MgmRM3100HandlerDefs.h +++ b/src/fsfw_hal/devicehandlers/devicedefinitions/mgmRm3100Helpers.h @@ -8,7 +8,7 @@ #include -namespace RM3100 { +namespace mgmRm3100 { /* Actually 10, we round up a little bit */ static constexpr size_t MAX_BUFFER_SIZE = 12; @@ -115,6 +115,6 @@ class Rm3100PrimaryDataset : public StaticLocalDataSet<3> { lp_vec_t fieldStrengths = lp_vec_t(sid.objectId, FIELD_STRENGTHS, this); }; -} // namespace RM3100 +} // namespace mgmRm3100 #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_MGMHANDLERRM3100DEFINITIONS_H_ */ diff --git a/src/fsfw_hal/host/HostFilesystem.cpp b/src/fsfw_hal/host/HostFilesystem.cpp index fe593f278..315ba4224 100644 --- a/src/fsfw_hal/host/HostFilesystem.cpp +++ b/src/fsfw_hal/host/HostFilesystem.cpp @@ -15,7 +15,8 @@ ReturnValue_t HostFilesystem::writeToFile(FileOpParams params, const uint8_t *da return returnvalue::FAILED; } path path(params.path()); - if (not exists(path)) { + std::error_code e; + if (not exists(path, e)) { return HasFileSystemIF::FILE_DOES_NOT_EXIST; } // This is equivalent to "r+" mode, which is what we need here. Only using ::out would truncate @@ -35,7 +36,8 @@ ReturnValue_t HostFilesystem::readFromFile(FileOpParams params, uint8_t **buffer return returnvalue::FAILED; } path path(params.path()); - if (not exists(path)) { + std::error_code e; + if (not exists(path, e)) { return HasFileSystemIF::FILE_DOES_NOT_EXIST; } ifstream file(path); @@ -59,7 +61,8 @@ ReturnValue_t HostFilesystem::createFile(FilesystemParams params, const uint8_t return returnvalue::FAILED; } path path(params.path); - if (exists(path)) { + std::error_code e; + if (exists(path, e)) { return HasFileSystemIF::FILE_ALREADY_EXISTS; } ofstream file(path); @@ -74,7 +77,8 @@ ReturnValue_t HostFilesystem::removeFile(const char *path_, FileSystemArgsIF *ar return returnvalue::FAILED; } path path(path_); - if (not exists(path)) { + std::error_code e; + if (not exists(path, e)) { return HasFileSystemIF::FILE_DOES_NOT_EXIST; } if (remove(path, errorCode)) { @@ -89,7 +93,8 @@ ReturnValue_t HostFilesystem::createDirectory(FilesystemParams params, bool crea } path dirPath(params.path); - if (exists(dirPath)) { + std::error_code e; + if (exists(dirPath, e)) { return HasFileSystemIF::DIRECTORY_ALREADY_EXISTS; } @@ -110,7 +115,8 @@ ReturnValue_t HostFilesystem::removeDirectory(FilesystemParams params, bool dele return returnvalue::FAILED; } path dirPath(params.path); - if (not exists(dirPath)) { + std::error_code e; + if (not exists(dirPath, e)) { return HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST; } if (is_regular_file(dirPath)) { @@ -149,14 +155,31 @@ ReturnValue_t HostFilesystem::rename(const char *oldPath_, const char *newPath_, bool HostFilesystem::fileExists(FilesystemParams params) { path path(params.path); - return filesystem::exists(path); + std::error_code e; + return filesystem::exists(path, e); } ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) { path path(params.path); - if (not filesystem::exists(path)) { + std::error_code e; + if (not filesystem::exists(path, e)) { return FILE_DOES_NOT_EXIST; } ofstream of(path); return returnvalue::OK; } + +bool HostFilesystem::isDirectory(const char *path) { return filesystem::is_directory(path); } + +ReturnValue_t HostFilesystem::getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen, + size_t &baseNameLen) { + std::string path(params.path); + std::string baseName = path.substr(path.find_last_of("/\\") + 1); + if (baseName.size() + 1 > maxLen) { + return returnvalue::FAILED; + } + std::memcpy(nameBuf, baseName.c_str(), baseName.size()); + nameBuf[baseName.size()] = '\0'; + baseNameLen = baseName.size(); + return returnvalue::OK; +} diff --git a/src/fsfw_hal/host/HostFilesystem.h b/src/fsfw_hal/host/HostFilesystem.h index 7b865e2de..da217aecd 100644 --- a/src/fsfw_hal/host/HostFilesystem.h +++ b/src/fsfw_hal/host/HostFilesystem.h @@ -9,6 +9,9 @@ class HostFilesystem : public HasFileSystemIF { public: HostFilesystem(); + ReturnValue_t getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen, + size_t &baseNameLen) override; + bool isDirectory(const char *path) override; bool fileExists(FilesystemParams params) override; ReturnValue_t truncateFile(FilesystemParams params) override; ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override; diff --git a/src/fsfw_hal/linux/CommandExecutor.cpp b/src/fsfw_hal/linux/CommandExecutor.cpp index 27cf8aca8..e8f64432b 100644 --- a/src/fsfw_hal/linux/CommandExecutor.cpp +++ b/src/fsfw_hal/linux/CommandExecutor.cpp @@ -17,7 +17,7 @@ ReturnValue_t CommandExecutor::load(std::string command, bool blocking, bool pri return COMMAND_PENDING; } - currentCmd = command; + currentCmd = std::move(command); this->blocking = blocking; this->printOutput = printOutput; if (state == States::IDLE) { diff --git a/src/fsfw_hal/linux/UnixFileGuard.cpp b/src/fsfw_hal/linux/UnixFileGuard.cpp index 3e916ba29..3178f39d2 100644 --- a/src/fsfw_hal/linux/UnixFileGuard.cpp +++ b/src/fsfw_hal/linux/UnixFileGuard.cpp @@ -6,14 +6,11 @@ #include "fsfw/FSFW.h" #include "fsfw/serviceinterface.h" -UnixFileGuard::UnixFileGuard(const std::string& device, int* fileDescriptor, int flags, +UnixFileGuard::UnixFileGuard(const std::string& device, int& fileDescriptor, int flags, std::string diagnosticPrefix) - : fileDescriptor(fileDescriptor) { - if (fileDescriptor == nullptr) { - return; - } - *fileDescriptor = open(device.c_str(), flags); - if (*fileDescriptor < 0) { + : fdRef(fileDescriptor) { + fileDescriptor = open(device.c_str(), flags); + if (fileDescriptor < 0) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << diagnosticPrefix << ": Opening device failed with error code " << errno << ": " @@ -27,10 +24,6 @@ UnixFileGuard::UnixFileGuard(const std::string& device, int* fileDescriptor, int } } -UnixFileGuard::~UnixFileGuard() { - if (fileDescriptor != nullptr) { - close(*fileDescriptor); - } -} +UnixFileGuard::~UnixFileGuard() { close(fdRef); } ReturnValue_t UnixFileGuard::getOpenResult() const { return openStatus; } diff --git a/src/fsfw_hal/linux/UnixFileGuard.h b/src/fsfw_hal/linux/UnixFileGuard.h index eec852336..884e551cc 100644 --- a/src/fsfw_hal/linux/UnixFileGuard.h +++ b/src/fsfw_hal/linux/UnixFileGuard.h @@ -15,7 +15,15 @@ class UnixFileGuard { static constexpr ReturnValue_t OPEN_FILE_FAILED = 1; - UnixFileGuard(const std::string& device, int* fileDescriptor, int flags, + /** + * Open a device and assign the given file descriptor variable + * @param device [in] Device name. + * @param fileDescriptor [in/out] Will be assigned by file guard and re-used to + * close the guard. + * @param flags + * @param diagnosticPrefix + */ + UnixFileGuard(const std::string& device, int& fileDescriptor, int flags, std::string diagnosticPrefix = ""); virtual ~UnixFileGuard(); @@ -23,7 +31,7 @@ class UnixFileGuard { ReturnValue_t getOpenResult() const; private: - int* fileDescriptor = nullptr; + int& fdRef; ReturnValue_t openStatus = returnvalue::OK; }; diff --git a/src/fsfw_hal/linux/i2c/I2cComIF.cpp b/src/fsfw_hal/linux/i2c/I2cComIF.cpp index 66c2bb511..1a85d4d34 100644 --- a/src/fsfw_hal/linux/i2c/I2cComIF.cpp +++ b/src/fsfw_hal/linux/i2c/I2cComIF.cpp @@ -66,8 +66,7 @@ ReturnValue_t I2cComIF::initializeInterface(CookieIF* cookie) { ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) { ReturnValue_t result; - int fd; - std::string deviceFile; + int fd = 0; if (sendData == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 @@ -98,12 +97,12 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s return returnvalue::FAILED; } - deviceFile = i2cCookie->getDeviceFile(); - UnixFileGuard fileHelper(deviceFile, &fd, O_RDWR, "I2cComIF::sendMessage"); + const auto& deviceFile = i2cCookie->getDeviceFile(); + UnixFileGuard fileHelper(deviceFile, fd, O_RDWR, "I2cComIF::sendMessage"); if (fileHelper.getOpenResult() != returnvalue::OK) { return fileHelper.getOpenResult(); } - result = openDevice(deviceFile, i2cAddress, &fd); + result = openI2cSlave(deviceFile, i2cAddress, fd); if (result != returnvalue::OK) { return result; } @@ -113,8 +112,9 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s if (i2cCookie->errorCounter < 3) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "I2cComIF::sendMessage: Failed to send data to I2C " - "device with error code " - << errno << ". Error description: " << strerror(errno) << std::endl; + "device from " + << deviceFile << " with error code " << errno + << ". Error description: " << strerror(errno) << std::endl; #endif } return returnvalue::FAILED; @@ -131,8 +131,7 @@ ReturnValue_t I2cComIF::getSendSuccess(CookieIF* cookie) { return returnvalue::O ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) { ReturnValue_t result; - int fd; - std::string deviceFile; + int fd = 0; if (requestLen == 0) { return returnvalue::OK; @@ -157,12 +156,12 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe } i2cDeviceMapIter->second.replyLen = 0; - deviceFile = i2cCookie->getDeviceFile(); - UnixFileGuard fileHelper(deviceFile, &fd, O_RDWR, "I2cComIF::requestReceiveMessage"); + auto& deviceFile = i2cCookie->getDeviceFile(); + UnixFileGuard fileHelper(deviceFile, fd, O_RDWR, "I2cComIF::requestReceiveMessage"); if (fileHelper.getOpenResult() != returnvalue::OK) { return fileHelper.getOpenResult(); } - result = openDevice(deviceFile, i2cAddress, &fd); + result = openI2cSlave(deviceFile, i2cAddress, fd); if (result != returnvalue::OK) { return result; } @@ -220,9 +219,9 @@ ReturnValue_t I2cComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, return returnvalue::OK; } -ReturnValue_t I2cComIF::openDevice(std::string deviceFile, address_t i2cAddress, - int* fileDescriptor) { - if (ioctl(*fileDescriptor, I2C_SLAVE, i2cAddress) < 0) { +ReturnValue_t I2cComIF::openI2cSlave(const std::string& deviceFile, address_t i2cAddress, + int& fileDescriptor) { + if (ioctl(fileDescriptor, I2C_SLAVE, i2cAddress) < 0) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "I2cComIF: Specifying target device failed with error code " << errno << "." diff --git a/src/fsfw_hal/linux/i2c/I2cComIF.h b/src/fsfw_hal/linux/i2c/I2cComIF.h index 8c44cee01..983ce734b 100644 --- a/src/fsfw_hal/linux/i2c/I2cComIF.h +++ b/src/fsfw_hal/linux/i2c/I2cComIF.h @@ -49,7 +49,8 @@ class I2cComIF : public DeviceCommunicationIF, public SystemObject { * @param fileDescriptor Pointer to device descriptor. * @return returnvalue::OK if successful, otherwise returnvalue::FAILED. */ - ReturnValue_t openDevice(std::string deviceFile, address_t i2cAddress, int *fileDescriptor); + ReturnValue_t openI2cSlave(const std::string &deviceFile, address_t i2cAddress, + int &fileDescriptor); }; #endif /* LINUX_I2C_I2COMIF_H_ */ diff --git a/src/fsfw_hal/linux/i2c/I2cCookie.cpp b/src/fsfw_hal/linux/i2c/I2cCookie.cpp index 0186be604..f41527a30 100644 --- a/src/fsfw_hal/linux/i2c/I2cCookie.cpp +++ b/src/fsfw_hal/linux/i2c/I2cCookie.cpp @@ -1,12 +1,12 @@ #include "fsfw_hal/linux/i2c/I2cCookie.h" I2cCookie::I2cCookie(address_t i2cAddress_, size_t maxReplyLen_, std::string deviceFile_) - : i2cAddress(i2cAddress_), maxReplyLen(maxReplyLen_), deviceFile(deviceFile_) {} + : i2cAddress(i2cAddress_), maxReplyLen(maxReplyLen_), deviceFile(std::move(deviceFile_)) {} address_t I2cCookie::getAddress() const { return i2cAddress; } size_t I2cCookie::getMaxReplyLen() const { return maxReplyLen; } -std::string I2cCookie::getDeviceFile() const { return deviceFile; } +const std::string& I2cCookie::getDeviceFile() const { return deviceFile; } I2cCookie::~I2cCookie() {} diff --git a/src/fsfw_hal/linux/i2c/I2cCookie.h b/src/fsfw_hal/linux/i2c/I2cCookie.h index 8be712051..e54bcd55c 100644 --- a/src/fsfw_hal/linux/i2c/I2cCookie.h +++ b/src/fsfw_hal/linux/i2c/I2cCookie.h @@ -25,7 +25,7 @@ class I2cCookie : public CookieIF { address_t getAddress() const; size_t getMaxReplyLen() const; - std::string getDeviceFile() const; + const std::string& getDeviceFile() const; uint8_t errorCounter = 0; diff --git a/src/fsfw_hal/linux/serial/SerialComIF.cpp b/src/fsfw_hal/linux/serial/SerialComIF.cpp index ae117c06a..177d74e45 100644 --- a/src/fsfw_hal/linux/serial/SerialComIF.cpp +++ b/src/fsfw_hal/linux/serial/SerialComIF.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include diff --git a/src/fsfw_hal/linux/spi/ManualCsLockGuard.h b/src/fsfw_hal/linux/spi/ManualCsLockGuard.h index feb6dd83e..8456f9f13 100644 --- a/src/fsfw_hal/linux/spi/ManualCsLockGuard.h +++ b/src/fsfw_hal/linux/spi/ManualCsLockGuard.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "fsfw/ipc/MutexIF.h" #include "fsfw/returnvalues/returnvalue.h" #include "fsfw_hal/common/gpio/GpioIF.h" diff --git a/src/fsfw_hal/linux/spi/SpiComIF.cpp b/src/fsfw_hal/linux/spi/SpiComIF.cpp index 11db7cfe6..d285b1204 100644 --- a/src/fsfw_hal/linux/spi/SpiComIF.cpp +++ b/src/fsfw_hal/linux/spi/SpiComIF.cpp @@ -75,7 +75,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) { spiCookie->getSpiParameters(spiMode, spiSpeed, ¶ms); int fileDescriptor = 0; - UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::initializeInterface"); + UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::initializeInterface"); if (fileHelper.getOpenResult() != returnvalue::OK) { return fileHelper.getOpenResult(); } @@ -171,7 +171,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const int retval = 0; /* Prepare transfer */ int fileDescriptor = 0; - UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage"); + UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::sendMessage"); if (fileHelper.getOpenResult() != returnvalue::OK) { return OPENING_FILE_FAILED; } @@ -179,12 +179,11 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const uint32_t spiSpeed = 0; spiCookie->getSpiParameters(spiMode, spiSpeed, nullptr); setSpiSpeedAndMode(fileDescriptor, spiMode, spiSpeed); - spiCookie->assignWriteBuffer(sendData); - spiCookie->setTransferSize(sendLen); bool fullDuplex = spiCookie->isFullDuplex(); gpioId_t gpioId = spiCookie->getChipSelectPin(); bool csLockManual = spiCookie->getCsLockManual(); + spiCookie->setTransferSize(0); MutexIF::TimeoutType csType; dur_millis_t csTimeout = 0; @@ -195,9 +194,13 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const if (result != returnvalue::OK) { #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code " - << "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec - << std::endl; + if (result == MutexIF::MUTEX_TIMEOUT) { + sif::error << "SpiComIF::sendMessage: Lock timeout" << std::endl; + } else { + sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code " + << "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec + << std::endl; + } #else sif::printError("SpiComIF::sendMessage: Failed to lock mutex with code %d\n", result); #endif @@ -214,17 +217,22 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const sif::printWarning("SpiComIF::sendMessage: Pulling low CS pin failed"); #endif #endif + csMutex->unlockMutex(); return result; } } else { updateLinePolarity(fileDescriptor); } + spiCookie->assignWriteBuffer(sendData); + spiCookie->setTransferSize(sendLen); + /* Execute transfer */ if (fullDuplex) { /* Initiate a full duplex SPI transfer. */ retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), spiCookie->getTransferStructHandle()); if (retval < 0) { + spiCookie->setTransferSize(0); utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); result = FULL_DUPLEX_TRANSFER_FAILED; } @@ -234,6 +242,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const } else { /* We write with a blocking half-duplex transfer here */ if (write(fileDescriptor, sendData, sendLen) != static_cast(sendLen)) { + spiCookie->setTransferSize(0); #if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "SpiComIF::sendMessage: Half-Duplex write operation failed!" << std::endl; @@ -276,7 +285,7 @@ ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) { ReturnValue_t result = returnvalue::OK; int fileDescriptor = 0; - UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage"); + UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage"); if (fileHelper.getOpenResult() != returnvalue::OK) { return OPENING_FILE_FAILED; } diff --git a/src/fsfw_hal/linux/spi/SpiComIF.h b/src/fsfw_hal/linux/spi/SpiComIF.h index 7033ea372..14a3355a7 100644 --- a/src/fsfw_hal/linux/spi/SpiComIF.h +++ b/src/fsfw_hal/linux/spi/SpiComIF.h @@ -90,8 +90,6 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject { * pulled high */ MutexIF* csMutex = nullptr; - // MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; - // uint32_t timeoutMs = DEFAULT_MUTEX_TIMEOUT; spi_ioc_transfer clockUpdateTransfer = {}; using SpiDeviceMap = std::unordered_map; diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index ad26e3923..950b96b89 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(util) add_subdirectory(container) add_subdirectory(osal) add_subdirectory(pus) +add_subdirectory(subsystem) add_subdirectory(serialize) add_subdirectory(datapoollocal) add_subdirectory(storagemanager) diff --git a/unittests/mocks/FilesystemMock.cpp b/unittests/mocks/FilesystemMock.cpp index bf0c3bf67..248502279 100644 --- a/unittests/mocks/FilesystemMock.cpp +++ b/unittests/mocks/FilesystemMock.cpp @@ -138,3 +138,10 @@ ReturnValue_t FilesystemMock::truncateFile(FilesystemParams params) { truncateCalledOnFile = params.path; return returnvalue::OK; } + +ReturnValue_t FilesystemMock::getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen, + size_t &baseNameLen) { + return returnvalue::OK; +} + +bool FilesystemMock::isDirectory(const char *path) { return false; } diff --git a/unittests/mocks/FilesystemMock.h b/unittests/mocks/FilesystemMock.h index 74221d708..2ddbefc36 100644 --- a/unittests/mocks/FilesystemMock.h +++ b/unittests/mocks/FilesystemMock.h @@ -56,6 +56,10 @@ class FilesystemMock : public HasFileSystemIF { std::string truncateCalledOnFile; ReturnValue_t feedFile(const std::string &filename, std::ifstream &file); + ReturnValue_t getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen, + size_t &baseNameLen) override; + + bool isDirectory(const char *path) override; bool fileExists(FilesystemParams params) override; ReturnValue_t truncateFile(FilesystemParams params) override; diff --git a/unittests/subsystem/CMakeLists.txt b/unittests/subsystem/CMakeLists.txt new file mode 100644 index 000000000..724ebc056 --- /dev/null +++ b/unittests/subsystem/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE testModeDef.cpp) diff --git a/unittests/subsystem/testModeDef.cpp b/unittests/subsystem/testModeDef.cpp new file mode 100644 index 000000000..758b33016 --- /dev/null +++ b/unittests/subsystem/testModeDef.cpp @@ -0,0 +1,49 @@ + +#include +#include + +#include "fsfw/subsystem/modes/ModeDefinitions.h" + +TEST_CASE("Mode Definitions", "[mode]") { + ModeListEntry entry; + + SECTION("Basic") { + entry.setMode(HasModesIF::MODE_OFF); + entry.setSubmode(2); + CHECK(entry.getMode() == HasModesIF::MODE_OFF); + CHECK(entry.getSubmode() == 2); + uint8_t mask; + CHECK(entry.submodesAllowed(&mask) == false); + } + + SECTION("Allowed submode mask") { + entry.allowAllSubmodes(); + uint8_t mask; + CHECK(entry.submodesAllowed(&mask) == true); + CHECK(mask == 0xff); + } + + SECTION("Serialization") { + std::array buf{}; + entry.setObject(0x1f2f3f4f); + entry.setMode(HasModesIF::MODE_ON); + entry.setSubmode(2); + entry.enableInheritSubmode(); + entry.enableSubmodeAllowed(0x1f); + uint8_t* serPtr = buf.data(); + size_t serLen = 0; + REQUIRE(entry.serialize(&serPtr, &serLen, buf.size(), SerializeIF::Endianness::NETWORK) == + returnvalue::OK); + CHECK(buf[0] == 0x1f); + CHECK(buf[1] == 0x2f); + CHECK(buf[2] == 0x3f); + CHECK(buf[3] == 0x4f); + CHECK(buf[4] == 0); + CHECK(buf[5] == 0); + CHECK(buf[6] == 0); + CHECK(buf[7] == HasModesIF::MODE_ON); + CHECK(buf[8] == 2); + CHECK(buf[9] == (mode::SpecialSubmodeFlags::ALLOWED_MASK | mode::SpecialSubmodeFlags::INHERIT)); + CHECK(buf[10] == 0x1f); + } +} diff --git a/unittests/timemanager/TestCountdown.cpp b/unittests/timemanager/TestCountdown.cpp index 67f4ddb22..61d372e7a 100644 --- a/unittests/timemanager/TestCountdown.cpp +++ b/unittests/timemanager/TestCountdown.cpp @@ -1,15 +1,18 @@ #include #include +#include +#include #include "CatchDefinitions.h" +static constexpr bool TEST_LONGER_CD = false; TEST_CASE("Countdown Tests", "[TestCountdown]") { INFO("Countdown Tests"); Countdown count(20); - REQUIRE(count.timeout == 20); + REQUIRE(count.getTimeoutMs() == 20); REQUIRE(count.setTimeout(100) == static_cast(returnvalue::OK)); - REQUIRE(count.timeout == 100); + REQUIRE(count.getTimeoutMs() == 100); REQUIRE(count.setTimeout(150) == static_cast(returnvalue::OK)); REQUIRE(count.isBusy()); REQUIRE(not count.hasTimedOut()); @@ -25,4 +28,19 @@ TEST_CASE("Countdown Tests", "[TestCountdown]") { count.resetTimer(); REQUIRE(not count.hasTimedOut()); REQUIRE(count.isBusy()); + count.setTimeout(100); + REQUIRE(not count.hasTimedOut()); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + REQUIRE(not count.hasTimedOut()); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + REQUIRE(count.hasTimedOut()); + + // Takes longer, disabled by default + if (TEST_LONGER_CD) { + count.setTimeout(2500); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + REQUIRE(not count.hasTimedOut()); + std::this_thread::sleep_for(std::chrono::milliseconds(1500)); + REQUIRE(count.hasTimedOut()); + } }