Compare commits

...

88 Commits

Author SHA1 Message Date
a837a78bd4 Merge branch 'develop' into develop_update 2023-09-01 12:14:08 +02:00
d246ce34d0 Merge pull request 'Change TLE validity duration' (#159) from spg4-tle-too-old into develop
Reviewed-on: #159
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2023-08-14 10:09:00 +02:00
796c7a9e37 tle is too old after 30 days now 2023-08-09 11:42:11 +02:00
d575da8540 Merge pull request 'Small tweak to allow immediate HK generation' (#158) from small-hk-tweak into develop
Reviewed-on: #158
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-17 10:37:39 +02:00
62ace649a7 fix unittest 2023-07-17 10:35:35 +02:00
aac74fae38 shared cmake file 2023-07-17 10:34:19 +02:00
a26b0c38ac small tweak to allow immediate HK generation 2023-07-17 10:31:02 +02:00
42e74d22cc Merge pull request 'countdown based HK generation' (#156) from hk-generation-countdown-based into develop
Reviewed-on: #156
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-11 17:35:10 +02:00
36caa58043 Merge branch 'develop' into hk-generation-countdown-based 2023-07-11 17:34:24 +02:00
988e07f0be countdown 2023-07-11 15:40:43 +02:00
88e8665280 important bugfix for PUS TM creator 2023-07-10 17:45:02 +02:00
9c8b1c697b added back missing function 2023-07-10 14:20:02 +02:00
110cb903a6 countdown based HK generation 2023-07-10 14:14:31 +02:00
8da89eba80 Merge pull request 'add API to set msg counter' (#155) from pus-msg-counter-mutable into develop
Reviewed-on: #155
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-28 13:19:28 +02:00
7e8845f2c2 Merge remote-tracking branch 'origin/develop' into pus-msg-counter-mutable 2023-06-26 18:12:36 +02:00
6aff3250c2 Merge pull request 'Internal Error Reporter Configurability' (#154) from internal-error-reporter-set into develop
Reviewed-on: #154
2023-06-26 18:10:06 +02:00
c3572e31a8 add API to set msg counter 2023-06-25 12:35:50 +02:00
2293e7f2bb typo 2023-06-22 16:12:41 +02:00
a85a38c882 some thnings are configurable now 2023-06-22 16:08:29 +02:00
0f76cdb3ba typo 2023-06-20 20:36:03 +02:00
268c2e87c9 Merge pull request 'max value calc fix' (#153) from max-value-fix-v2 into develop
Reviewed-on: #153
2023-06-20 18:20:00 +02:00
87f94a252f Merge branch 'develop' into max-value-fix-v2 2023-06-20 18:19:19 +02:00
c7037d417a nullptr check for optional argument 2023-06-20 11:54:15 +02:00
f80c5980ea max value calc fix 2023-06-19 17:04:45 +02:00
ad01642fee Merge pull request 'specify truncate flag explicitely' (#151) from specify-truncate-flag-explicitely into develop
Reviewed-on: #151
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-19 09:32:19 +02:00
f2947bc78e specify truncate flag explicitely 2023-06-18 19:04:36 +02:00
0a977ea688 Merge pull request 'make number of parallel cmds configurable' (#149) from make-srv3-num-parallel-cmds-configurable into develop
Reviewed-on: #149
2023-06-14 03:37:02 +02:00
74b164b1da make number of parallel cmds configurable 2023-06-13 08:09:04 +02:00
5322de0599 Merge pull request 'Pull CFPD bugfix in dev branch' (#147) from pull-cfdp-fix-into-dev-branch into obsw-v3.0.0-dev
Reviewed-on: #147
2023-06-09 13:41:29 +02:00
9a4bf51006 Merge branch 'develop' into obsw-v3.0.0-dev 2023-06-09 13:11:30 +02:00
3a70229510 Merge pull request 'configurable queue depth' (#146) from service-8-configurable-queue-depth into obsw-v3.0.0-dev
Reviewed-on: #146
2023-06-09 13:03:17 +02:00
b3beedad9f Merge branch 'obsw-v3.0.0-dev' into service-8-configurable-queue-depth 2023-06-09 13:03:08 +02:00
efe217a197 Merge pull request 'Rework L3GD20H Config' (#143) from gyr-config-rework into obsw-v3.0.0-dev
Reviewed-on: #143
2023-06-09 13:01:23 +02:00
b442ca09b9 configurable queue depth 2023-06-07 13:46:46 +02:00
9372b2a575 Merge remote-tracking branch 'upstream/development' into develop 2023-05-25 15:03:54 +02:00
aafa53148e Merge pull request 'CFDP Bugfix' (#144) from cfdp-bugfix-unittest-fixes into develop
Reviewed-on: #144
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-05-22 10:40:44 +02:00
e0adb3325f werks 2023-05-22 10:37:26 +02:00
4391823f01 changelog 2023-05-15 16:14:36 +02:00
1a77e6bb09 proper floating point comparison 2023-05-15 16:13:05 +02:00
cae131edcf CFDP and unittest bugfixes 2023-05-15 16:02:55 +02:00
4518fec65c CHANGELOG 2023-05-08 15:25:47 +02:00
dac1aacab2 Merge pull request 'Update Power Switch IF' (#743) from eive/fsfw:update_power_switch_if into development
Reviewed-on: fsfw/fsfw#743
2023-05-08 15:00:47 +02:00
0042f92fdf Merge pull request 'bump ETL version' (#748) from KSat/fsfw:bump_etl_dep into development
Reviewed-on: fsfw/fsfw#748
2023-05-08 14:53:02 +02:00
656faf8169 Merge remote-tracking branch 'upstream/development' into update_power_switch_if 2023-05-08 14:44:27 +02:00
f84431e965 Merge pull request 'bugfix and changelog for Linux getUptime' (#745) from eive/fsfw:important_bugfix_linux_get_uptime into development
Reviewed-on: fsfw/fsfw#745
2023-05-08 14:29:55 +02:00
0cec9ebb73 Merge pull request 'small tweak for version getter' (#744) from eive/fsfw:small_version_getter_tweak into development
Reviewed-on: fsfw/fsfw#744
2023-05-08 14:13:06 +02:00
a440b7c394 Merge pull request 'add CFDP subsystem ID' (#742) from eive/fsfw:add_cfdp_subsystem_id into development
Reviewed-on: fsfw/fsfw#742
2023-05-08 14:09:04 +02:00
bbfc1b2b34 Merge pull request 'FixedArrayList compile time assert' (#740) from eive/fsfw:container_additional_assert into development
Reviewed-on: fsfw/fsfw#740
2023-05-08 14:04:56 +02:00
025b379e8b bump ETL version 2023-05-04 14:04:55 +02:00
258f0d3313 use both LPFs 2023-04-19 15:25:14 +02:00
5eb9ee8bc1 DHB fdir: event queue depth confgurable 2023-04-14 21:22:24 +02:00
7f61d17cee even better event manager printout 2023-04-14 21:08:44 +02:00
ffa2fa477f Merge pull request 'move CFDP handler' (#142) from move_cfdp_handler into develop
Reviewed-on: #142
2023-04-11 16:50:46 +02:00
894d1e3b87 move CFDP handler 2023-04-11 16:36:54 +02:00
285d327b97 clean up spi retval defs 2023-04-07 17:42:44 +02:00
e97fa5ac84 add skip directive for retvals 2023-04-07 11:03:46 +02:00
5a9304765f accepts action commands without ipc data 2023-04-06 22:34:57 +02:00
6650c293da change collection interval is public now 2023-04-04 15:59:26 +02:00
9fca7581dd Merge branch 'develop' of https://egit.irs.uni-stuttgart.de/eive/fsfw into develop 2023-04-04 01:52:29 +02:00
4af90f99f3 changelog 2023-04-04 01:52:26 +02:00
94cdf67a80 make health functions virtual 2023-04-04 01:51:58 +02:00
7966ede11b add O_SYNC flag for UioMapper 2023-04-03 21:57:18 +02:00
7a392dc33a new register function 2023-04-03 18:54:35 +02:00
1e3c89b672 i dont think ths needs to be public 2023-04-03 17:59:14 +02:00
e2e87b149d initialize switch state list 2023-04-03 14:31:45 +02:00
4f632e2c68 ctrl base bugfix 2023-03-28 19:37:47 +02:00
314f0fa2cd start power switch component in undefined mode 2023-03-28 15:27:48 +02:00
b31e1037fb HK service configurable queue depth 2023-03-26 20:05:10 +02:00
0f81d5e458 Merge remote-tracking branch 'upstream/development' into container_additional_assert 2023-03-15 12:34:36 +01:00
b50f092939 Merge remote-tracking branch 'upstream/development' into update_power_switch_if 2023-03-15 12:33:08 +01:00
2f90e12179 Merge remote-tracking branch 'upstream/development' into important_bugfix_linux_get_uptime 2023-03-15 12:32:25 +01:00
8b77fac099 Merge pull request 'health service fixes and changelog' (#746) from eive/fsfw:health_service_fixes into development
Reviewed-on: fsfw/fsfw#746
2023-03-15 12:29:31 +01:00
47503824d7 health service fixes and changelog 2023-03-15 12:27:39 +01:00
5e3f5c4121 fuse update 2023-03-15 12:25:39 +01:00
1f36c082ef bugfix and changelog for Linux getUptime 2023-03-15 12:21:50 +01:00
aa84e93603 small tweak for version getter 2023-03-15 12:17:36 +01:00
8f63a0e747 changelog 2023-03-15 12:15:21 +01:00
6fc8f756a7 update power switch IF 2023-03-15 12:13:55 +01:00
d98ed40e3d add CFDP subsystem ID 2023-03-15 12:09:30 +01:00
b057250bfb changelog 2023-03-15 11:53:12 +01:00
066dd0d397 changelog 2023-03-15 11:52:20 +01:00
f735c2e9d4 assert size larger than 0 2023-03-15 11:51:51 +01:00
54ef9ec3f6 Merge branch 'develop' into develop_update 2023-03-15 11:50:12 +01:00
4dc49c57d5 Merge branch 'develop' into develop_update 2023-02-07 12:31:41 +01:00
e9d629b9b3 Merge branch 'develop' into develop_update 2023-02-07 12:24:27 +01:00
48403c002d Merge remote-tracking branch 'upstream/development' into develop_update 2022-12-19 15:02:07 +01:00
e86d8c64db Merge branch 'develop' into develop_update 2022-11-28 08:36:13 +01:00
1de1b045cd Merge remote-tracking branch 'upstream/development' into develop_update 2022-11-28 08:28:56 +01:00
52 changed files with 218 additions and 386 deletions

8
.idea/cmake.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSharedSettings">
<configurations>
<configuration PROFILE_NAME="Debug Test" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DFSFW_BUILD_TESTS=ON -DFSFW_OSAL=host" />
</configurations>
</component>
</project>

View File

@ -8,6 +8,40 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
## Fixes
- The `PusTmCreator` API only accepted 255 bytes of source data. It can now accept source
data with a size limited only by the size of `size_t`.
- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence
number fields stored the actual length of the field instead of the length minus 1 like specified
in the CFDP standard.
- PUS Health Service: Size check for set health command.
Perform operation completion for announce health command.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745
- Small tweak for version getter
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744
## Added
- add CFDP subsystem ID
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
- `PusTmZcWriter` now exposes API to set message counter field.
## Changed
- HK generation is now countdown based.
- Bump ETL version to 20.35.14
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748
- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Assert that `FixedArrayList` is larger than 0 at compile time.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740
- Health functions are virtual now.
# [v6.0.0] 2023-02-10
## Fixes

View File

@ -72,7 +72,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
20
CACHE STRING "ETL library major version requirement")
set(FSFW_ETL_LIB_VERSION
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
${FSFW_ETL_LIB_MAJOR_VERSION}.35.14
CACHE STRING "ETL library exact version requirement")
set(FSFW_ETL_LINK_TARGET etl::etl)

View File

@ -59,17 +59,24 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) {
bool hasAdditionalData = false;
const uint8_t* dataPtr = nullptr;
size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
return;
ReturnValue_t result;
if (dataAddress != store_address_t::invalid()) {
hasAdditionalData = true;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
return;
}
}
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
ipcStore->deleteData(dataAddress);
if (hasAdditionalData) {
ipcStore->deleteData(dataAddress);
}
if (result == HasActionsIF::EXECUTION_FINISHED) {
CommandMessage reply;
ActionMessage::setCompletionReply(&reply, actionId, true, result);

View File

@ -2,7 +2,6 @@
#define FSFW_CFDP_H
#include "cfdp/definitions.h"
#include "cfdp/handler/CfdpHandler.h"
#include "cfdp/handler/DestHandler.h"
#include "cfdp/handler/FaultHandlerBase.h"
#include "cfdp/helpers.h"

View File

@ -1,3 +1,2 @@
target_sources(
${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
FaultHandlerBase.cpp UserBase.cpp CfdpHandler.cpp)
target_sources(${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
FaultHandlerBase.cpp UserBase.cpp)

View File

@ -1,134 +0,0 @@
#include "CfdpHandler.h"
#include "fsfw/cfdp/pdu/AckPduReader.h"
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
#include "fsfw/globalfunctions/arrayprinter.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
using namespace returnvalue;
using namespace cfdp;
CfdpHandler::CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg)
: SystemObject(fsfwParams.objectId),
msgQueue(fsfwParams.msgQueue),
destHandler(
DestHandlerParams(LocalEntityCfg(cfdpCfg.id, cfdpCfg.indicCfg, cfdpCfg.faultHandler),
cfdpCfg.userHandler, cfdpCfg.remoteCfgProvider, cfdpCfg.packetInfoList,
cfdpCfg.lostSegmentsList),
FsfwParams(fsfwParams.packetDest, nullptr, this, fsfwParams.tcStore,
fsfwParams.tmStore)) {
destHandler.setMsgQueue(msgQueue);
}
[[nodiscard]] const char* CfdpHandler::getName() const { return "CFDP Handler"; }
[[nodiscard]] uint32_t CfdpHandler::getIdentifier() const {
return destHandler.getDestHandlerParams().cfg.localId.getValue();
}
[[nodiscard]] MessageQueueId_t CfdpHandler::getRequestQueue() const { return msgQueue.getId(); }
ReturnValue_t CfdpHandler::initialize() {
ReturnValue_t result = destHandler.initialize();
if (result != OK) {
return result;
}
tcStore = destHandler.getTcStore();
tmStore = destHandler.getTmStore();
return SystemObject::initialize();
}
ReturnValue_t CfdpHandler::performOperation(uint8_t operationCode) {
// TODO: Receive TC packets and route them to source and dest handler, depending on which is
// correct or more appropriate
ReturnValue_t status;
ReturnValue_t result = OK;
TmTcMessage tmtcMsg;
for (status = msgQueue.receiveMessage(&tmtcMsg); status == returnvalue::OK;
status = msgQueue.receiveMessage(&tmtcMsg)) {
result = handleCfdpPacket(tmtcMsg);
if (result != OK) {
status = result;
}
}
auto& fsmRes = destHandler.performStateMachine();
// TODO: Error handling?
while (fsmRes.callStatus == CallStatus::CALL_AGAIN) {
destHandler.performStateMachine();
// TODO: Error handling?
}
return status;
}
ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) {
auto accessorPair = tcStore->getData(msg.getStorageId());
if (accessorPair.first != OK) {
return accessorPair.first;
}
PduHeaderReader reader(accessorPair.second.data(), accessorPair.second.size());
ReturnValue_t result = reader.parseData();
if (result != returnvalue::OK) {
return INVALID_PDU_FORMAT;
}
// The CFDP distributor should have taken care of ensuring the destination ID is correct
PduType type = reader.getPduType();
// Only the destination handler can process these PDUs
if (type == PduType::FILE_DATA) {
// Disable auto-deletion of packet
accessorPair.second.release();
PacketInfo info(type, msg.getStorageId());
result = destHandler.passPacket(info);
} else {
// Route depending on PDU type and directive type if applicable. It retrieves directive type
// from the raw stream for better performance (with sanity and directive code check).
// The routing is based on section 4.5 of the CFDP standard which specifies the PDU forwarding
// procedure.
// PDU header only. Invalid supplied data. A directive packet should have a valid data field
// with at least one byte being the directive code
const uint8_t* pduDataField = reader.getPduDataField();
if (pduDataField == nullptr) {
return INVALID_PDU_FORMAT;
}
if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) {
return INVALID_DIRECTIVE_FIELD;
}
auto directive = static_cast<FileDirective>(pduDataField[0]);
auto passToDestHandler = [&]() {
accessorPair.second.release();
PacketInfo info(type, msg.getStorageId(), directive);
result = destHandler.passPacket(info);
};
auto passToSourceHandler = [&]() {
};
if (directive == FileDirective::METADATA or directive == FileDirective::EOF_DIRECTIVE or
directive == FileDirective::PROMPT) {
// Section b) of 4.5.3: These PDUs should always be targeted towards the file receiver a.k.a.
// the destination handler
passToDestHandler();
} else if (directive == FileDirective::FINISH or directive == FileDirective::NAK or
directive == FileDirective::KEEP_ALIVE) {
// Section c) of 4.5.3: These PDUs should always be targeted towards the file sender a.k.a.
// the source handler
passToSourceHandler();
} else if (directive == FileDirective::ACK) {
// Section a): Recipient depends of the type of PDU that is being acknowledged. We can simply
// extract the PDU type from the raw stream. If it is an EOF PDU, this packet is passed to
// the source handler, for a Finished PDU, it is passed to the destination handler.
FileDirective ackedDirective;
if (not AckPduReader::checkAckedDirectiveField(pduDataField[1], ackedDirective)) {
return INVALID_ACK_DIRECTIVE_FIELDS;
}
if (ackedDirective == FileDirective::EOF_DIRECTIVE) {
passToSourceHandler();
} else if (ackedDirective == FileDirective::FINISH) {
passToDestHandler();
}
}
}
return result;
}

View File

@ -1,71 +0,0 @@
#ifndef FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
#define FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
#include <utility>
#include "fsfw/cfdp/handler/DestHandler.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
struct FsfwHandlerParams {
FsfwHandlerParams(object_id_t objectId, HasFileSystemIF& vfs, AcceptsTelemetryIF& packetDest,
StorageManagerIF& tcStore, StorageManagerIF& tmStore, MessageQueueIF& msgQueue)
: objectId(objectId),
vfs(vfs),
packetDest(packetDest),
tcStore(tcStore),
tmStore(tmStore),
msgQueue(msgQueue) {}
object_id_t objectId{};
HasFileSystemIF& vfs;
AcceptsTelemetryIF& packetDest;
StorageManagerIF& tcStore;
StorageManagerIF& tmStore;
MessageQueueIF& msgQueue;
};
struct CfdpHandlerCfg {
CfdpHandlerCfg(cfdp::EntityId localId, cfdp::IndicationCfg indicationCfg,
cfdp::UserBase& userHandler, cfdp::FaultHandlerBase& userFaultHandler,
cfdp::PacketInfoListBase& packetInfo, cfdp::LostSegmentsListBase& lostSegmentsList,
cfdp::RemoteConfigTableIF& remoteCfgProvider)
: id(std::move(localId)),
indicCfg(indicationCfg),
packetInfoList(packetInfo),
lostSegmentsList(lostSegmentsList),
remoteCfgProvider(remoteCfgProvider),
userHandler(userHandler),
faultHandler(userFaultHandler) {}
cfdp::EntityId id;
cfdp::IndicationCfg indicCfg;
cfdp::PacketInfoListBase& packetInfoList;
cfdp::LostSegmentsListBase& lostSegmentsList;
cfdp::RemoteConfigTableIF& remoteCfgProvider;
cfdp::UserBase& userHandler;
cfdp::FaultHandlerBase& faultHandler;
};
class CfdpHandler : public SystemObject, public ExecutableObjectIF, public AcceptsTelecommandsIF {
public:
explicit CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg);
[[nodiscard]] const char* getName() const override;
[[nodiscard]] uint32_t getIdentifier() const override;
[[nodiscard]] MessageQueueId_t getRequestQueue() const override;
ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t operationCode) override;
private:
MessageQueueIF& msgQueue;
cfdp::DestHandler destHandler;
StorageManagerIF* tcStore = nullptr;
StorageManagerIF* tmStore = nullptr;
ReturnValue_t handleCfdpPacket(TmTcMessage& msg);
};
#endif // FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H

View File

@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
*buffer += 1;
**buffer = pduDataFieldLen & 0x00ff;
*buffer += 1;
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
pduConf.seqNum.getWidth();
**buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) |
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
*buffer += 1;
*size += 4;
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);

View File

@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
}
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
return static_cast<cfdp::WidthInBytes>(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1);
}
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1);
}
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {

View File

@ -58,7 +58,7 @@ void ControllerBase::handleQueue() {
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
changeHK(this->mode, this->submode, false);
triggerEvent(CHANGING_MODE, mode, submode);
triggerEvent(CHANGING_MODE, mode_, submode_);
mode = mode_;
submode = submode_;
modeHelper.modeChanged(mode, submode);

View File

@ -166,9 +166,9 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, time
timeval timeSinceEpoch = time - epoch;
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.;
double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365;
double monthsSinceEpoch = minutesSinceEpoch / 60 / 24 / 30;
if ((yearsSinceEpoch > 1) || (yearsSinceEpoch < -1)) {
if ((monthsSinceEpoch > 1) || (monthsSinceEpoch < -1)) {
return TLE_TOO_OLD;
}

View File

@ -505,9 +505,9 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
float newCollIntvl = 0;
HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl);
if (command == HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) {
result = changeCollectionInterval(sid, newCollIntvl, true);
result = changeCollectionInterval(sid, newCollIntvl);
} else {
result = changeCollectionInterval(sid, newCollIntvl, false);
result = changeCollectionInterval(sid, newCollIntvl);
}
break;
}
@ -720,8 +720,8 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool ena
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float newCollectionInterval,
bool isDiagnostics) {
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
float newCollectionInterval) {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
@ -729,11 +729,6 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float ne
return DATASET_NOT_FOUND;
}
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
if ((targetIsDiagnostics and not isDiagnostics) or (not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE;
}
PeriodicHousekeepingHelper* periodicHelper =
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);

View File

@ -174,6 +174,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet,
bool forDownlink,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval);
HasLocalDataPoolIF* getOwner();
@ -337,8 +338,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, bool isDiagnostics);
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval,
bool isDiagnostics);
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);

View File

@ -257,8 +257,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const;
virtual void getMode(Mode_t *mode, Submode_t *submode);
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual HealthState getHealth() override;
virtual ReturnValue_t setHealth(HealthState health) override;
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues,

View File

@ -10,8 +10,9 @@
object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent)
: FailureIsolationBase(owner, parent),
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent,
uint8_t eventQueueDepth)
: FailureIsolationBase(owner, parent, eventQueueDepth),
strangeReplyCount(DEFAULT_MAX_STRANGE_REPLIES, DEFAULT_STRANGE_REPLIES_TIME_MS,
parameterDomainBase++),
missedReplyCount(DEFAULT_MAX_MISSED_REPLY_COUNT, DEFAULT_MISSED_REPLY_TIME_MS,

View File

@ -13,7 +13,8 @@ class DeviceHandlerFailureIsolation : public FailureIsolationBase {
friend class Heater;
public:
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent);
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent,
uint8_t eventQueueDepth = 10);
~DeviceHandlerFailureIsolation();
ReturnValue_t initialize();
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);

View File

@ -29,11 +29,10 @@ ReturnValue_t HealthDevice::initialize() {
if (result != returnvalue::OK) {
return result;
}
if (parentQueue != 0) {
if (parentQueue != MessageQueueIF::NO_QUEUE) {
return healthHelper.initialize(parentQueue);
} else {
return healthHelper.initialize();
}
return healthHelper.initialize();
}
MessageQueueId_t HealthDevice::getCommandQueue() const { return commandQueue->getId(); }

View File

@ -29,10 +29,8 @@ class HealthDevice : public SystemObject, public ExecutableObjectIF, public HasH
protected:
HealthState lastHealth;
MessageQueueId_t parentQueue;
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
MessageQueueIF* commandQueue;
public:
HealthHelper healthHelper;
};

View File

@ -55,8 +55,9 @@ void EventManager::notifyListeners(EventMessage* message) {
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
<< result << std::setfill(' ') << std::endl;
<< std::setw(8) << listener.first << " for event 0x" << std::setw(4)
<< message->getEventId() << " failed with result 0x" << std::setw(4) << result
<< std::setfill(' ') << std::endl;
#else
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
listener.first, result);

View File

@ -18,8 +18,11 @@
*/
class DleParser {
public:
//! [EXPORT] : [SKIP]
static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(1, 1);
//! [EXPORT] : [SKIP]
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS = returnvalue::makeCode(1, 2);
using BufPair = std::pair<uint8_t*, size_t>;
enum class ContextType { NONE, PACKET_FOUND, ERROR };

View File

@ -53,8 +53,9 @@ class VectorOperations {
mulScalar(vector, 1 / norm(vector, size), normalizedVector, size);
}
static T maxAbsValue(const T *vector, uint8_t size, uint8_t *index = 0) {
T max = -1;
static T maxAbsValue(const T *vector, uint8_t size, uint8_t *index = nullptr) {
T max = vector[size - 1];
uint8_t foundIndex = size - 1;
for (; size > 0; size--) {
T abs = vector[size - 1];
@ -64,24 +65,35 @@ class VectorOperations {
if (abs > max) {
max = abs;
if (index != 0) {
*index = size - 1;
foundIndex = size - 1;
}
}
}
if (index != nullptr) {
*index = foundIndex;
}
return max;
}
static T maxValue(const T *vector, uint8_t size, uint8_t *index = 0) {
T max = -1;
static T maxValue(const T *vector, uint8_t size, uint8_t *index = nullptr) {
T max = vector[size - 1];
uint8_t foundIndex = size - 1;
for (; size > 0; size--) {
if (vector[size - 1] > max) {
max = vector[size - 1];
if (index != 0) {
*index = size - 1;
foundIndex = size - 1;
}
}
}
if (index != nullptr) {
*index = foundIndex;
}
return max;
}

View File

@ -3,6 +3,7 @@
#include <cmath>
#include "fsfw/datapoollocal/LocalPoolDataSetBase.h"
#include "fsfw/serviceinterface.h"
PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner)
: owner(owner) {}
@ -10,51 +11,29 @@ PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* own
void PeriodicHousekeepingHelper::initialize(float collectionInterval,
dur_millis_t minimumPeriodicInterval) {
this->minimumPeriodicInterval = minimumPeriodicInterval;
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. */
internalTickCounter = collectionIntervalTicks;
changeCollectionInterval(collectionInterval);
}
float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() const {
return intervalTicksToSeconds(collectionIntervalTicks);
return collectionInterval;
}
bool PeriodicHousekeepingHelper::checkOpNecessary() {
if (internalTickCounter >= collectionIntervalTicks) {
internalTickCounter = 1;
if (hkGenerationCd.hasTimedOut()) {
hkGenerationCd.resetTimer();
return true;
}
internalTickCounter++;
return false;
}
uint32_t PeriodicHousekeepingHelper::intervalSecondsToIntervalTicks(
float collectionIntervalSeconds) {
if (owner == nullptr) {
return 0;
}
/* Avoid division by zero */
if (minimumPeriodicInterval == 0) {
/* Perform operation each cycle */
return 1;
} else {
dur_millis_t intervalInMs = collectionIntervalSeconds * 1000;
uint32_t divisor = minimumPeriodicInterval;
uint32_t ticks = std::ceil(static_cast<float>(intervalInMs) / divisor);
return ticks;
}
}
float PeriodicHousekeepingHelper::intervalTicksToSeconds(uint32_t collectionInterval) const {
/* Number of ticks times the minimum interval is in milliseconds, so we divide by 1000 to get
the value in seconds */
return static_cast<float>(collectionInterval * minimumPeriodicInterval / 1000.0);
}
void PeriodicHousekeepingHelper::changeCollectionInterval(float newIntervalSeconds) {
collectionIntervalTicks = intervalSecondsToIntervalTicks(newIntervalSeconds);
uint32_t intervalMs = newIntervalSeconds * 1000;
if (newIntervalSeconds <= 0) {
intervalMs = minimumPeriodicInterval;
newIntervalSeconds = static_cast<float>(minimumPeriodicInterval) / 1000.0;
}
collectionInterval = newIntervalSeconds;
hkGenerationCd.setTimeout(intervalMs);
// We want an immediate HK packet at the start, so time out the generation CD immediately.
hkGenerationCd.timeOut();
}

View File

@ -4,6 +4,7 @@
#include <cstdint>
#include "fsfw/timemanager/Clock.h"
#include "fsfw/timemanager/Countdown.h"
class LocalPoolDataSetBase;
@ -19,13 +20,10 @@ class PeriodicHousekeepingHelper {
private:
LocalPoolDataSetBase* owner = nullptr;
uint32_t intervalSecondsToIntervalTicks(float collectionIntervalSeconds);
float intervalTicksToSeconds(uint32_t collectionInterval) const;
Countdown hkGenerationCd;
float collectionInterval = 0.0;
dur_millis_t minimumPeriodicInterval = 0;
uint32_t internalTickCounter = 1;
uint32_t collectionIntervalTicks = 0;
};
#endif /* FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ */

View File

@ -5,9 +5,12 @@
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth,
bool enableSetByDefault, float generationFrequency)
: SystemObject(setObjectId),
poolManager(this, commandQueue),
enableSetByDefault(enableSetByDefault),
generationFrequency(generationFrequency),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
@ -134,9 +137,8 @@ ReturnValue_t InternalErrorReporter::initializeLocalDataPool(localpool::DataPool
localDataPoolMap.emplace(errorPoolIds::TM_HITS, &tmHitsEntry);
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, &queueHitsEntry);
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, &storeHitsEntry);
poolManager.subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams(
internalErrorSid, false,
static_cast<float>(getPeriodicOperationFrequency()) / static_cast<float>(1000.0)));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(internalErrorSid, enableSetByDefault, generationFrequency));
internalErrorDataset.setValidity(true, true);
return returnvalue::OK;
}

View File

@ -21,7 +21,8 @@ class InternalErrorReporter : public SystemObject,
public InternalErrorReporterIF,
public HasLocalDataPoolIF {
public:
InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth = 5);
InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth,
bool enableSetByDefault, float generationFrequency);
/**
* Enable diagnostic printout. Please note that this feature will
@ -63,6 +64,8 @@ class InternalErrorReporter : public SystemObject,
MutexIF* mutex = nullptr;
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 20;
bool enableSetByDefault;
float generationFrequency;
sid_t internalErrorSid;
InternalErrorDataset internalErrorDataset;

View File

@ -89,8 +89,6 @@ timeval Clock::getUptime() {
}
ReturnValue_t Clock::getUptime(timeval* uptime) {
// TODO This is not posix compatible and delivers only seconds precision
// Linux specific file read but more precise.
double uptimeSeconds;
std::ifstream ifile("/proc/uptime");
if (ifile.bad()) {

View File

@ -6,7 +6,11 @@ DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwit
: SystemObject(objectId, registerGlobally),
switcherList(numberOfSwitches),
fuseList(numberOfFuses),
switchDelayMs(switchDelayMs) {}
switchDelayMs(switchDelayMs) {
for (auto &switchState : switcherList) {
switchState = PowerSwitchIF::SWITCH_UNKNOWN;
}
}
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
this->switcherList = switcherList;

View File

@ -42,7 +42,7 @@ class PowerSwitcherComponent : public SystemObject,
private:
MessageQueueIF *queue = nullptr;
Mode_t mode = MODE_OFF;
Mode_t mode = MODE_UNDEFINED;
Submode_t submode = 0;
ModeHelper modeHelper;

View File

@ -4,9 +4,10 @@
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/pus/servicepackets/Service3Packets.h"
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId)
: CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, NUM_OF_PARALLEL_COMMANDS,
COMMAND_TIMEOUT_SECONDS) {}
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint32_t queueDepth, uint8_t numParallelCommands)
: CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, numParallelCommands,
COMMAND_TIMEOUT_SECONDS, queueDepth) {}
Service3Housekeeping::~Service3Housekeeping() {}

View File

@ -28,7 +28,8 @@ class Service3Housekeeping : public CommandingServiceBase, public AcceptsHkPacke
static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4;
static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60;
Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId);
Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId, uint32_t queueDepth,
uint8_t numParallelCommands);
virtual ~Service3Housekeeping();
protected:

View File

@ -9,11 +9,11 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
Service8FunctionManagement::Service8FunctionManagement(object_id_t objectId, uint16_t apid,
uint8_t serviceId,
uint8_t serviceId, size_t queueDepth,
uint8_t numParallelCommands,
uint16_t commandTimeoutSeconds)
: CommandingServiceBase(objectId, apid, "PUS 8 Functional Commanding", serviceId,
numParallelCommands, commandTimeoutSeconds) {}
numParallelCommands, commandTimeoutSeconds, queueDepth) {}
Service8FunctionManagement::~Service8FunctionManagement() {}

View File

@ -31,7 +31,8 @@
class Service8FunctionManagement : public CommandingServiceBase {
public:
Service8FunctionManagement(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
size_t queueDepth, uint8_t numParallelCommands = 4,
uint16_t commandTimeoutSeconds = 60);
~Service8FunctionManagement() override;
protected:

View File

@ -315,20 +315,7 @@ object_id_t SubsystemBase::getObjectId() const { return SystemObject::getObjectI
void SubsystemBase::modeChanged() {}
ReturnValue_t SubsystemBase::registerChild(const ModeTreeChildIF& child) {
ChildInfo info;
const HasModesIF& modeChild = child.getModeIF();
// intentional to force an initial command during system startup
info.commandQueue = modeChild.getCommandQueue();
info.mode = HasModesIF::MODE_UNDEFINED;
info.submode = SUBMODE_NONE;
info.healthChanged = false;
auto resultPair = childrenMap.emplace(child.getObjectId(), info);
if (not resultPair.second) {
return COULD_NOT_INSERT_CHILD;
}
return returnvalue::OK;
return registerChild(child.getObjectId(), child.getModeIF().getCommandQueue());
}
const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; }
@ -336,3 +323,19 @@ const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; }
const HasModesIF& SubsystemBase::getModeIF() const { return *this; }
ModeTreeChildIF& SubsystemBase::getModeTreeChildIF() { return *this; }
ReturnValue_t SubsystemBase::registerChild(object_id_t childObjectId, MessageQueueId_t childQueue) {
ChildInfo info;
// intentional to force an initial command during system startup
info.commandQueue = childQueue;
info.mode = HasModesIF::MODE_UNDEFINED;
info.submode = SUBMODE_NONE;
info.healthChanged = false;
auto resultPair = childrenMap.emplace(childObjectId, info);
if (not resultPair.second) {
return COULD_NOT_INSERT_CHILD;
}
return returnvalue::OK;
}

View File

@ -61,6 +61,8 @@ class SubsystemBase : public SystemObject,
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
*/
ReturnValue_t registerChild(const ModeTreeChildIF &child) override;
// TODO: Add this to HasModeTreeChildrenIF.
ReturnValue_t registerChild(object_id_t childObjectId, MessageQueueId_t childQueue);
ReturnValue_t initialize() override;

View File

@ -40,7 +40,7 @@ struct PusTmParams {
size_t dataLen)
: secHeader(service, subservice, timeStamper), adapter(data, dataLen), sourceData(&adapter) {}
PusTmSecHeader secHeader;
SerialBufferAdapter<uint8_t> adapter;
SerialBufferAdapter<size_t> adapter;
const SerializeIF* sourceData = nullptr;
};

View File

@ -24,3 +24,9 @@ void PusTmZeroCopyWriter::updateErrorControl() {
crcStart[0] = (crc16 >> 8) & 0xff;
crcStart[1] = crc16 & 0xff;
}
void PusTmZeroCopyWriter::setMessageCount(uint16_t msgCount) {
size_t serSize = 0;
SerializeAdapter::serialize(&msgCount, const_cast<uint8_t*>(pointers.secHeaderStart + 3),
&serSize, 2, SerializeIF::Endianness::NETWORK);
}

View File

@ -14,6 +14,7 @@ class PusTmZeroCopyWriter : public PusTmReader {
PusTmZeroCopyWriter(TimeReaderIF& timeReader, uint8_t* data, size_t size);
void setSequenceCount(uint16_t seqCount);
void setMessageCount(uint16_t msgCount);
void updateErrorControl();
private:

View File

@ -5,8 +5,18 @@
namespace spi {
static constexpr uint8_t CLASS_ID = CLASS_ID::HAL_SPI;
static constexpr ReturnValue_t OPENING_FILE_FAILED = returnvalue::makeCode(CLASS_ID, 0);
/* Full duplex (ioctl) transfer failure */
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED = returnvalue::makeCode(CLASS_ID, 1);
/* Half duplex (read/write) transfer failure */
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED = returnvalue::makeCode(CLASS_ID, 2);
static constexpr ReturnValue_t TIMEOUT = returnvalue::makeCode(CLASS_ID, 3);
static constexpr ReturnValue_t BUSY = returnvalue::makeCode(CLASS_ID, 4);
static constexpr ReturnValue_t GENERIC_ERROR = returnvalue::makeCode(CLASS_ID, 5);
enum SpiModes : uint8_t { MODE_0, MODE_1, MODE_2, MODE_3 };
}
} // namespace spi
#endif /* FSFW_HAL_COMMON_SPI_SPICOMMON_H_ */

View File

@ -73,8 +73,10 @@ static constexpr uint8_t CTRL_REG_4_VAL = SET_BLE;
/* Register 5 */
static constexpr uint8_t SET_REBOOT_MEM = 1 << 7;
static constexpr uint8_t SET_FIFO_ENB = 1 << 6;
static constexpr uint8_t SET_OUT_SEL_1 = 1 << 1;
static constexpr uint8_t SET_OUT_SEL_0 = 1 << 0;
static constexpr uint8_t CTRL_REG_5_VAL = 0b00000000;
static constexpr uint8_t CTRL_REG_5_VAL = SET_OUT_SEL_1 | SET_OUT_SEL_0;
/* Possible range values in degrees per second (DPS). */
static constexpr uint16_t RANGE_DPS_00 = 245;

View File

@ -165,7 +165,8 @@ ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) {
if (not filesystem::exists(path, e)) {
return FILE_DOES_NOT_EXIST;
}
ofstream of(path);
// Specify truncation flug explicitely.
ofstream of(path, std::ios::out | std::ios::trunc);
return returnvalue::OK;
}

View File

@ -173,7 +173,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
int fileDescriptor = 0;
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return OPENING_FILE_FAILED;
return spi::OPENING_FILE_FAILED;
}
spi::SpiModes spiMode = spi::SpiModes::MODE_0;
uint32_t spiSpeed = 0;
@ -234,7 +234,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
if (retval < 0) {
spiCookie->setTransferSize(0);
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
result = FULL_DUPLEX_TRANSFER_FAILED;
result = spi::FULL_DUPLEX_TRANSFER_FAILED;
}
#if FSFW_HAL_SPI_WIRETAPPING == 1
performSpiWiretapping(spiCookie);
@ -250,7 +250,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
sif::printWarning("SpiComIF::sendMessage: Half-Duplex write operation failed!\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
result = HALF_DUPLEX_TRANSFER_FAILED;
result = spi::HALF_DUPLEX_TRANSFER_FAILED;
}
}
@ -287,7 +287,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
int fileDescriptor = 0;
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return OPENING_FILE_FAILED;
return spi::OPENING_FILE_FAILED;
}
uint8_t* rxBuf = nullptr;
@ -327,7 +327,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
sif::printWarning("SpiComIF::sendMessage: Half-Duplex read operation failed!\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
result = HALF_DUPLEX_TRANSFER_FAILED;
result = spi::HALF_DUPLEX_TRANSFER_FAILED;
}
if (gpioId != gpio::NO_GPIO and not csLockManual) {

View File

@ -22,15 +22,6 @@ class SpiCookie;
*/
class SpiComIF : public DeviceCommunicationIF, public SystemObject {
public:
static constexpr uint8_t spiRetvalId = CLASS_ID::HAL_SPI;
static constexpr ReturnValue_t OPENING_FILE_FAILED = returnvalue::makeCode(spiRetvalId, 0);
/* Full duplex (ioctl) transfer failure */
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED =
returnvalue::makeCode(spiRetvalId, 1);
/* Half duplex (read/write) transfer failure */
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
returnvalue::makeCode(spiRetvalId, 2);
SpiComIF(object_id_t objectId, std::string devname, GpioIF& gpioComIF);
ReturnValue_t initializeInterface(CookieIF* cookie) override;

View File

@ -36,7 +36,7 @@ UioMapper::~UioMapper() {}
ReturnValue_t UioMapper::getMappedAdress(uint32_t** address, Permissions permissions) {
ReturnValue_t result = returnvalue::OK;
int fd = open(uioFile.c_str(), O_RDWR);
int fd = open(uioFile.c_str(), O_RDWR | O_SYNC);
if (fd < 1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "UioMapper::getMappedAdress: Invalid UIO device file " << uioFile << std::endl;

View File

@ -357,13 +357,13 @@ ReturnValue_t SpiComIF::halErrorHandler(HAL_StatusTypeDef status, spi::TransferM
sif::printWarning("SpiComIF::handle%sSendOperation: HAL error %d occured\n", modeString, status);
switch (status) {
case (HAL_BUSY): {
return spi::HAL_BUSY_RETVAL;
return spi::BUSY;
}
case (HAL_ERROR): {
return spi::HAL_ERROR_RETVAL;
return spi::GENERIC_ERROR;
}
case (HAL_TIMEOUT): {
return spi::HAL_TIMEOUT_RETVAL;
return spi::TIMEOUT;
}
default: {
return returnvalue::FAILED;

View File

@ -30,9 +30,9 @@
*/
void Factory::produceFrameworkObjects(void* args) {
setStaticFrameworkObjectIds();
new EventManager(objects::EVENT_MANAGER);
new EventManager(objects::EVENT_MANAGER, 120);
new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 20, false, 1.0);
{
PoolManager::LocalPoolConfig poolCfg = {{100, 16}, {50, 32}, {25, 64}, {15, 128}, {5, 1024}};

View File

@ -27,12 +27,7 @@ TEST_CASE("Action Helper", "[action]") {
CHECK(not testDhMock.executeActionCalled);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
CHECK(testDhMock.executeActionCalled);
// No message is sent if everything is alright.
CHECK(not testMqMock.wasMessageSent());
store_address_t invalidAddress;
ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
actionHelper.handleActionMessage(&actionMessage);
CHECK(testMqMock.wasMessageSent());
const uint8_t* ptr = nullptr;
size_t size = 0;
REQUIRE(ipcStore->getData(paramAddress, &ptr, &size) ==
@ -44,6 +39,10 @@ TEST_CASE("Action Helper", "[action]") {
for (uint8_t i = 0; i < 3; i++) {
REQUIRE(ptr[i] == (i + 1));
}
// Action message without application data is also valid
store_address_t invalidAddress;
ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
actionHelper.handleActionMessage(&actionMessage);
testDhMock.clearBuffer();
}
@ -95,17 +94,5 @@ TEST_CASE("Action Helper", "[action]") {
REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId);
}
SECTION("Missing IPC Data") {
ActionMessage::setCommand(&actionMessage, testActionId, store_address_t::invalid());
CHECK(not testDhMock.executeActionCalled);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
CommandMessage testMessage;
REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK);
REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::STEP_FAILED));
REQUIRE(ActionMessage::getReturnCode(&testMessage) ==
static_cast<uint32_t>(StorageManagerIF::ILLEGAL_STORAGE_ID));
REQUIRE(ActionMessage::getStep(&testMessage) == 0);
}
SECTION("Data Reply") {}
}

View File

@ -97,7 +97,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
SerializeIF::Endianness::BIG) == returnvalue::OK);
CHECK(serBuf[0] == 0x3f);
CHECK(serBuf[3] == 0x99);
CHECK(serBuf[3] == 0x88);
REQUIRE(creator.getCrcFlag() == true);
REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER);
REQUIRE(creator.getLargeFileFlag() == true);
@ -127,7 +127,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
REQUIRE(creator.getSegmentationControl() == true);
// Last three bits are 2 now (length of seq number) and bit 1 to bit 3 is 4 (len entity IDs)
REQUIRE(serBuf[3] == 0b11001010);
REQUIRE(serBuf[3] == 0b10111001);
uint32_t entityId = 0;
size_t deSerSize = 0;
SerializeAdapter::deSerialize(&entityId, serBuf.data() + 4, &deSerSize,
@ -175,7 +175,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
REQUIRE(serBuf[1] == 0);
REQUIRE(serBuf[2] == 0);
// Entity and Transaction Sequence number are 1 byte large
REQUIRE(serBuf[3] == 0b00010001);
REQUIRE(serBuf[3] == 0b00000000);
// Source ID
REQUIRE(serBuf[4] == 0);
// Transaction Seq Number
@ -220,7 +220,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
REQUIRE(serBuf[1] == 0);
REQUIRE(serBuf[2] == 0);
// Entity and Transaction Sequence number are 1 byte large
REQUIRE(serBuf[3] == 0b00010001);
REQUIRE(serBuf[3] == 0b00000000);
REQUIRE(serSize == 7);
// Deser call not strictly necessary
auto reader = PduHeaderReader(serBuf.data(), serBuf.size());
@ -270,7 +270,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
REQUIRE(reader.parseData() == returnvalue::OK);
// Everything except version bit flipped to one now
REQUIRE(serBuf[0] == 0x3f);
REQUIRE(serBuf[3] == 0b11001010);
REQUIRE(serBuf[3] == 0b10111001);
REQUIRE(reader.getWholePduSize() == 14);
REQUIRE(reader.getCrcFlag() == true);

View File

@ -68,7 +68,7 @@ TEST_CASE("File Data PDU", "[cfdp][pdu]") {
// Bits 1 to 3 length of enitity IDs is 2
// Bit 4: Segment metadata flag is set
// Bit 5 to seven: length of transaction seq num is 2
REQUIRE(fileDataBuffer[3] == 0b10101010);
REQUIRE(fileDataBuffer[3] == 0b10011001);
REQUIRE((fileDataBuffer[10] >> 6) &
0b11 == cfdp::RecordContinuationState::CONTAINS_START_AND_END);
// Segment metadata length

View File

@ -30,7 +30,7 @@ TEST_CASE("CFDP File Directive", "[cfdp][pdu]") {
REQUIRE(serBuf[1] == 0);
REQUIRE(serBuf[2] == 5);
// Entity and Transaction Sequence number are 1 byte large
REQUIRE(serBuf[3] == 0b00010001);
REQUIRE(serBuf[3] == 0b00000000);
// Source ID
REQUIRE(serBuf[4] == 0);
// Transaction Seq Number
@ -82,4 +82,4 @@ TEST_CASE("CFDP File Directive", "[cfdp][pdu]") {
// Invalid file directive
REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELD);
}
}
}

View File

@ -33,8 +33,8 @@ TEST_CASE("CFDP Base", "[cfdp]") {
// PDU data field length is 5 (4 + Directive code octet)
REQUIRE(serBuf[1] == 0);
REQUIRE(serBuf[2] == 5);
// Entity and Transaction Sequence number are 1 byte large
REQUIRE(serBuf[3] == 0b00010001);
// Entity and Transaction Sequence number are 1 byte large, value minus one is stored
REQUIRE(serBuf[3] == 0b00000000);
// Source ID
REQUIRE(serBuf[4] == 0);
// Transaction Seq Number

View File

@ -9,6 +9,7 @@
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>
#include <iostream>
#include "CatchDefinitions.h"
@ -309,9 +310,7 @@ TEST_CASE("Local Pool Manager Tests", "[LocManTest]") {
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
false);
CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK);
/* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the
resulting collection interval should be 1.0 second */
CHECK(poolOwner.dataset.getCollectionInterval() == 1.0);
CHECK_THAT(poolOwner.dataset.getCollectionInterval(), Catch::Matchers::WithinAbs(0.4, 0.01));
REQUIRE(poolOwnerMock.wasMessageSent());
REQUIRE(poolOwnerMock.numberOfSentMessages() == 1);
CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK);
@ -348,14 +347,6 @@ TEST_CASE("Local Pool Manager Tests", "[LocManTest]") {
REQUIRE(poolOwnerMock.numberOfSentMessages() == 1);
CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
false);
CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(poolOwnerMock.wasMessageSent());
REQUIRE(poolOwnerMock.numberOfSentMessages() == 1);
CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));