Merge branch 'develop' into develop_update
This commit is contained in:
commit
a837a78bd4
8
.idea/cmake.xml
Normal file
8
.idea/cmake.xml
Normal 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>
|
34
CHANGELOG.md
34
CHANGELOG.md
@ -8,6 +8,40 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [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
|
# [v6.0.0] 2023-02-10
|
||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
|
@ -72,7 +72,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
|
|||||||
20
|
20
|
||||||
CACHE STRING "ETL library major version requirement")
|
CACHE STRING "ETL library major version requirement")
|
||||||
set(FSFW_ETL_LIB_VERSION
|
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")
|
CACHE STRING "ETL library exact version requirement")
|
||||||
set(FSFW_ETL_LINK_TARGET etl::etl)
|
set(FSFW_ETL_LINK_TARGET etl::etl)
|
||||||
|
|
||||||
|
@ -59,17 +59,24 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
|
|||||||
|
|
||||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||||
store_address_t dataAddress) {
|
store_address_t dataAddress) {
|
||||||
|
bool hasAdditionalData = false;
|
||||||
const uint8_t* dataPtr = nullptr;
|
const uint8_t* dataPtr = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
ReturnValue_t result;
|
||||||
if (result != returnvalue::OK) {
|
if (dataAddress != store_address_t::invalid()) {
|
||||||
CommandMessage reply;
|
hasAdditionalData = true;
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
if (result != returnvalue::OK) {
|
||||||
return;
|
CommandMessage reply;
|
||||||
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||||
ipcStore->deleteData(dataAddress);
|
if (hasAdditionalData) {
|
||||||
|
ipcStore->deleteData(dataAddress);
|
||||||
|
}
|
||||||
if (result == HasActionsIF::EXECUTION_FINISHED) {
|
if (result == HasActionsIF::EXECUTION_FINISHED) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setCompletionReply(&reply, actionId, true, result);
|
ActionMessage::setCompletionReply(&reply, actionId, true, result);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#define FSFW_CFDP_H
|
#define FSFW_CFDP_H
|
||||||
|
|
||||||
#include "cfdp/definitions.h"
|
#include "cfdp/definitions.h"
|
||||||
#include "cfdp/handler/CfdpHandler.h"
|
|
||||||
#include "cfdp/handler/DestHandler.h"
|
#include "cfdp/handler/DestHandler.h"
|
||||||
#include "cfdp/handler/FaultHandlerBase.h"
|
#include "cfdp/handler/FaultHandlerBase.h"
|
||||||
#include "cfdp/helpers.h"
|
#include "cfdp/helpers.h"
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
target_sources(
|
target_sources(${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
|
||||||
${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
|
FaultHandlerBase.cpp UserBase.cpp)
|
||||||
FaultHandlerBase.cpp UserBase.cpp CfdpHandler.cpp)
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
|
|||||||
*buffer += 1;
|
*buffer += 1;
|
||||||
**buffer = pduDataFieldLen & 0x00ff;
|
**buffer = pduDataFieldLen & 0x00ff;
|
||||||
*buffer += 1;
|
*buffer += 1;
|
||||||
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
|
**buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) |
|
||||||
pduConf.seqNum.getWidth();
|
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
|
||||||
*buffer += 1;
|
*buffer += 1;
|
||||||
*size += 4;
|
*size += 4;
|
||||||
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);
|
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);
|
||||||
|
@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() 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 {
|
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 {
|
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {
|
||||||
|
@ -58,7 +58,7 @@ void ControllerBase::handleQueue() {
|
|||||||
|
|
||||||
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
|
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
|
||||||
changeHK(this->mode, this->submode, false);
|
changeHK(this->mode, this->submode, false);
|
||||||
triggerEvent(CHANGING_MODE, mode, submode);
|
triggerEvent(CHANGING_MODE, mode_, submode_);
|
||||||
mode = mode_;
|
mode = mode_;
|
||||||
submode = submode_;
|
submode = submode_;
|
||||||
modeHelper.modeChanged(mode, submode);
|
modeHelper.modeChanged(mode, submode);
|
||||||
|
@ -166,9 +166,9 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, time
|
|||||||
timeval timeSinceEpoch = time - epoch;
|
timeval timeSinceEpoch = time - epoch;
|
||||||
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.;
|
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;
|
return TLE_TOO_OLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,9 +505,9 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
|
|||||||
float newCollIntvl = 0;
|
float newCollIntvl = 0;
|
||||||
HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl);
|
HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl);
|
||||||
if (command == HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) {
|
if (command == HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) {
|
||||||
result = changeCollectionInterval(sid, newCollIntvl, true);
|
result = changeCollectionInterval(sid, newCollIntvl);
|
||||||
} else {
|
} else {
|
||||||
result = changeCollectionInterval(sid, newCollIntvl, false);
|
result = changeCollectionInterval(sid, newCollIntvl);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -720,8 +720,8 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool ena
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float newCollectionInterval,
|
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
|
||||||
bool isDiagnostics) {
|
float newCollectionInterval) {
|
||||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||||
if (dataSet == nullptr) {
|
if (dataSet == nullptr) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
|
||||||
@ -729,11 +729,6 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float ne
|
|||||||
return DATASET_NOT_FOUND;
|
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 =
|
PeriodicHousekeepingHelper* periodicHelper =
|
||||||
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
|
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
|
||||||
|
|
||||||
|
@ -174,6 +174,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
|||||||
ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet,
|
ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet,
|
||||||
bool forDownlink,
|
bool forDownlink,
|
||||||
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
|
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
|
||||||
|
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval);
|
||||||
|
|
||||||
HasLocalDataPoolIF* getOwner();
|
HasLocalDataPoolIF* getOwner();
|
||||||
|
|
||||||
@ -337,8 +338,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
|||||||
|
|
||||||
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
|
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
|
||||||
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, bool isDiagnostics);
|
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);
|
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
|
||||||
|
|
||||||
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
|
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
|
||||||
|
@ -49,6 +49,7 @@ class DeviceCommunicationIF {
|
|||||||
// is this needed if there is no open/close call?
|
// is this needed if there is no open/close call?
|
||||||
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05);
|
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05);
|
||||||
static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06);
|
static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06);
|
||||||
|
static constexpr ReturnValue_t BUSY = MAKE_RETURN_CODE(0x07);
|
||||||
|
|
||||||
virtual ~DeviceCommunicationIF() {}
|
virtual ~DeviceCommunicationIF() {}
|
||||||
|
|
||||||
|
@ -567,7 +567,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
|||||||
continueToNormal = false;
|
continueToNormal = false;
|
||||||
// TODO: Check whether the following two lines are okay to do so.
|
// TODO: Check whether the following two lines are okay to do so.
|
||||||
transitionSourceMode = MODE_ON;
|
transitionSourceMode = MODE_ON;
|
||||||
transitionSourceSubMode = submode;
|
transitionSourceSubMode = newSubmode;
|
||||||
mode = _MODE_TO_NORMAL;
|
mode = _MODE_TO_NORMAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -257,8 +257,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
Mode_t getTransitionSourceMode() const;
|
Mode_t getTransitionSourceMode() const;
|
||||||
Submode_t getTransitionSourceSubMode() const;
|
Submode_t getTransitionSourceSubMode() const;
|
||||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||||
HealthState getHealth();
|
virtual HealthState getHealth() override;
|
||||||
ReturnValue_t setHealth(HealthState health);
|
virtual ReturnValue_t setHealth(HealthState health) override;
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
const ParameterWrapper *newValues,
|
const ParameterWrapper *newValues,
|
||||||
|
@ -10,8 +10,9 @@
|
|||||||
|
|
||||||
object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
|
object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
|
||||||
|
|
||||||
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent)
|
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent,
|
||||||
: FailureIsolationBase(owner, parent),
|
uint8_t eventQueueDepth)
|
||||||
|
: FailureIsolationBase(owner, parent, eventQueueDepth),
|
||||||
strangeReplyCount(DEFAULT_MAX_STRANGE_REPLIES, DEFAULT_STRANGE_REPLIES_TIME_MS,
|
strangeReplyCount(DEFAULT_MAX_STRANGE_REPLIES, DEFAULT_STRANGE_REPLIES_TIME_MS,
|
||||||
parameterDomainBase++),
|
parameterDomainBase++),
|
||||||
missedReplyCount(DEFAULT_MAX_MISSED_REPLY_COUNT, DEFAULT_MISSED_REPLY_TIME_MS,
|
missedReplyCount(DEFAULT_MAX_MISSED_REPLY_COUNT, DEFAULT_MISSED_REPLY_TIME_MS,
|
||||||
|
@ -13,7 +13,8 @@ class DeviceHandlerFailureIsolation : public FailureIsolationBase {
|
|||||||
friend class Heater;
|
friend class Heater;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent);
|
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent,
|
||||||
|
uint8_t eventQueueDepth = 10);
|
||||||
~DeviceHandlerFailureIsolation();
|
~DeviceHandlerFailureIsolation();
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize();
|
||||||
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);
|
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);
|
||||||
|
@ -29,11 +29,10 @@ ReturnValue_t HealthDevice::initialize() {
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (parentQueue != 0) {
|
if (parentQueue != MessageQueueIF::NO_QUEUE) {
|
||||||
return healthHelper.initialize(parentQueue);
|
return healthHelper.initialize(parentQueue);
|
||||||
} else {
|
|
||||||
return healthHelper.initialize();
|
|
||||||
}
|
}
|
||||||
|
return healthHelper.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t HealthDevice::getCommandQueue() const { return commandQueue->getId(); }
|
MessageQueueId_t HealthDevice::getCommandQueue() const { return commandQueue->getId(); }
|
||||||
|
@ -29,10 +29,8 @@ class HealthDevice : public SystemObject, public ExecutableObjectIF, public HasH
|
|||||||
protected:
|
protected:
|
||||||
HealthState lastHealth;
|
HealthState lastHealth;
|
||||||
|
|
||||||
MessageQueueId_t parentQueue;
|
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
|
||||||
MessageQueueIF* commandQueue;
|
MessageQueueIF* commandQueue;
|
||||||
|
|
||||||
public:
|
|
||||||
HealthHelper healthHelper;
|
HealthHelper healthHelper;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,8 +55,9 @@ void EventManager::notifyListeners(EventMessage* message) {
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
|
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
|
||||||
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
|
<< std::setw(8) << listener.first << " for event 0x" << std::setw(4)
|
||||||
<< result << std::setfill(' ') << std::endl;
|
<< message->getEventId() << " failed with result 0x" << std::setw(4) << result
|
||||||
|
<< std::setfill(' ') << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
|
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
|
||||||
listener.first, result);
|
listener.first, result);
|
||||||
|
@ -18,8 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
class DleParser {
|
class DleParser {
|
||||||
public:
|
public:
|
||||||
|
//! [EXPORT] : [SKIP]
|
||||||
static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(1, 1);
|
static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(1, 1);
|
||||||
|
//! [EXPORT] : [SKIP]
|
||||||
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS = returnvalue::makeCode(1, 2);
|
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS = returnvalue::makeCode(1, 2);
|
||||||
|
|
||||||
using BufPair = std::pair<uint8_t*, size_t>;
|
using BufPair = std::pair<uint8_t*, size_t>;
|
||||||
|
|
||||||
enum class ContextType { NONE, PACKET_FOUND, ERROR };
|
enum class ContextType { NONE, PACKET_FOUND, ERROR };
|
||||||
|
@ -53,8 +53,9 @@ class VectorOperations {
|
|||||||
mulScalar(vector, 1 / norm(vector, size), normalizedVector, size);
|
mulScalar(vector, 1 / norm(vector, size), normalizedVector, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static T maxAbsValue(const T *vector, uint8_t size, uint8_t *index = 0) {
|
static T maxAbsValue(const T *vector, uint8_t size, uint8_t *index = nullptr) {
|
||||||
T max = -1;
|
T max = vector[size - 1];
|
||||||
|
uint8_t foundIndex = size - 1;
|
||||||
|
|
||||||
for (; size > 0; size--) {
|
for (; size > 0; size--) {
|
||||||
T abs = vector[size - 1];
|
T abs = vector[size - 1];
|
||||||
@ -64,24 +65,35 @@ class VectorOperations {
|
|||||||
if (abs > max) {
|
if (abs > max) {
|
||||||
max = abs;
|
max = abs;
|
||||||
if (index != 0) {
|
if (index != 0) {
|
||||||
*index = size - 1;
|
foundIndex = size - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index != nullptr) {
|
||||||
|
*index = foundIndex;
|
||||||
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
static T maxValue(const T *vector, uint8_t size, uint8_t *index = 0) {
|
static T maxValue(const T *vector, uint8_t size, uint8_t *index = nullptr) {
|
||||||
T max = -1;
|
T max = vector[size - 1];
|
||||||
|
uint8_t foundIndex = size - 1;
|
||||||
|
|
||||||
for (; size > 0; size--) {
|
for (; size > 0; size--) {
|
||||||
if (vector[size - 1] > max) {
|
if (vector[size - 1] > max) {
|
||||||
max = vector[size - 1];
|
max = vector[size - 1];
|
||||||
if (index != 0) {
|
if (index != 0) {
|
||||||
*index = size - 1;
|
foundIndex = size - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index != nullptr) {
|
||||||
|
*index = foundIndex;
|
||||||
|
}
|
||||||
|
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "fsfw/datapoollocal/LocalPoolDataSetBase.h"
|
#include "fsfw/datapoollocal/LocalPoolDataSetBase.h"
|
||||||
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner)
|
PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner)
|
||||||
: owner(owner) {}
|
: owner(owner) {}
|
||||||
@ -10,51 +11,29 @@ PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* own
|
|||||||
void PeriodicHousekeepingHelper::initialize(float collectionInterval,
|
void PeriodicHousekeepingHelper::initialize(float collectionInterval,
|
||||||
dur_millis_t minimumPeriodicInterval) {
|
dur_millis_t minimumPeriodicInterval) {
|
||||||
this->minimumPeriodicInterval = minimumPeriodicInterval;
|
this->minimumPeriodicInterval = minimumPeriodicInterval;
|
||||||
collectionIntervalTicks = intervalSecondsToIntervalTicks(collectionInterval);
|
changeCollectionInterval(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() const {
|
float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() const {
|
||||||
return intervalTicksToSeconds(collectionIntervalTicks);
|
return collectionInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeriodicHousekeepingHelper::checkOpNecessary() {
|
bool PeriodicHousekeepingHelper::checkOpNecessary() {
|
||||||
if (internalTickCounter >= collectionIntervalTicks) {
|
if (hkGenerationCd.hasTimedOut()) {
|
||||||
internalTickCounter = 1;
|
hkGenerationCd.resetTimer();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
internalTickCounter++;
|
|
||||||
return false;
|
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) {
|
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();
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "fsfw/timemanager/Clock.h"
|
#include "fsfw/timemanager/Clock.h"
|
||||||
|
#include "fsfw/timemanager/Countdown.h"
|
||||||
|
|
||||||
class LocalPoolDataSetBase;
|
class LocalPoolDataSetBase;
|
||||||
|
|
||||||
@ -19,13 +20,10 @@ class PeriodicHousekeepingHelper {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
LocalPoolDataSetBase* owner = nullptr;
|
LocalPoolDataSetBase* owner = nullptr;
|
||||||
|
Countdown hkGenerationCd;
|
||||||
uint32_t intervalSecondsToIntervalTicks(float collectionIntervalSeconds);
|
float collectionInterval = 0.0;
|
||||||
float intervalTicksToSeconds(uint32_t collectionInterval) const;
|
|
||||||
|
|
||||||
dur_millis_t minimumPeriodicInterval = 0;
|
dur_millis_t minimumPeriodicInterval = 0;
|
||||||
uint32_t internalTickCounter = 1;
|
|
||||||
uint32_t collectionIntervalTicks = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ */
|
#endif /* FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ */
|
||||||
|
@ -5,9 +5,12 @@
|
|||||||
#include "fsfw/ipc/QueueFactory.h"
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.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),
|
: SystemObject(setObjectId),
|
||||||
poolManager(this, commandQueue),
|
poolManager(this, commandQueue),
|
||||||
|
enableSetByDefault(enableSetByDefault),
|
||||||
|
generationFrequency(generationFrequency),
|
||||||
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
||||||
internalErrorDataset(this) {
|
internalErrorDataset(this) {
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
|
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
|
||||||
@ -134,9 +137,8 @@ ReturnValue_t InternalErrorReporter::initializeLocalDataPool(localpool::DataPool
|
|||||||
localDataPoolMap.emplace(errorPoolIds::TM_HITS, &tmHitsEntry);
|
localDataPoolMap.emplace(errorPoolIds::TM_HITS, &tmHitsEntry);
|
||||||
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, &queueHitsEntry);
|
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, &queueHitsEntry);
|
||||||
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, &storeHitsEntry);
|
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, &storeHitsEntry);
|
||||||
poolManager.subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams(
|
poolManager.subscribeForRegularPeriodicPacket(
|
||||||
internalErrorSid, false,
|
subdp::RegularHkPeriodicParams(internalErrorSid, enableSetByDefault, generationFrequency));
|
||||||
static_cast<float>(getPeriodicOperationFrequency()) / static_cast<float>(1000.0)));
|
|
||||||
internalErrorDataset.setValidity(true, true);
|
internalErrorDataset.setValidity(true, true);
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,8 @@ class InternalErrorReporter : public SystemObject,
|
|||||||
public InternalErrorReporterIF,
|
public InternalErrorReporterIF,
|
||||||
public HasLocalDataPoolIF {
|
public HasLocalDataPoolIF {
|
||||||
public:
|
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
|
* Enable diagnostic printout. Please note that this feature will
|
||||||
@ -63,6 +64,8 @@ class InternalErrorReporter : public SystemObject,
|
|||||||
MutexIF* mutex = nullptr;
|
MutexIF* mutex = nullptr;
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||||
uint32_t timeoutMs = 20;
|
uint32_t timeoutMs = 20;
|
||||||
|
bool enableSetByDefault;
|
||||||
|
float generationFrequency;
|
||||||
|
|
||||||
sid_t internalErrorSid;
|
sid_t internalErrorSid;
|
||||||
InternalErrorDataset internalErrorDataset;
|
InternalErrorDataset internalErrorDataset;
|
||||||
|
@ -20,16 +20,18 @@ TaskFactory::~TaskFactory() = default;
|
|||||||
|
|
||||||
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
||||||
|
|
||||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(
|
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
|
||||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
TaskStackSize stackSize_,
|
||||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
TaskPeriod periodInSeconds_,
|
||||||
|
TaskDeadlineMissedFunction deadLineMissedFunction_,
|
||||||
|
void* args) {
|
||||||
return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
||||||
deadLineMissedFunction_);
|
deadLineMissedFunction_);
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
|
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
|
||||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
||||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_, void* args) {
|
||||||
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
||||||
deadLineMissedFunction_);
|
deadLineMissedFunction_);
|
||||||
}
|
}
|
||||||
|
@ -89,8 +89,6 @@ timeval Clock::getUptime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getUptime(timeval* uptime) {
|
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;
|
double uptimeSeconds;
|
||||||
std::ifstream ifile("/proc/uptime");
|
std::ifstream ifile("/proc/uptime");
|
||||||
if (ifile.bad()) {
|
if (ifile.bad()) {
|
||||||
|
@ -7,10 +7,15 @@
|
|||||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
|
||||||
|
|
||||||
FixedTimeslotTask::FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
|
FixedTimeslotTask::FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
|
||||||
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_)
|
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_,
|
||||||
|
PosixThreadArgs* args)
|
||||||
: FixedTimeslotTaskBase(periodSeconds_, dlmFunc_),
|
: FixedTimeslotTaskBase(periodSeconds_, dlmFunc_),
|
||||||
posixThread(name_, priority_, stackSize_),
|
posixThread(name_, SchedulingPolicy::REGULAR, priority_, stackSize_),
|
||||||
started(false) {}
|
started(false) {
|
||||||
|
if (args != nullptr) {
|
||||||
|
posixThread.setSchedPolicy(args->policy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
||||||
// The argument is re-interpreted as PollingTask.
|
// The argument is re-interpreted as PollingTask.
|
||||||
|
@ -23,7 +23,8 @@ class FixedTimeslotTask : public FixedTimeslotTaskBase {
|
|||||||
* @param deadlineMissedFunc_
|
* @param deadlineMissedFunc_
|
||||||
*/
|
*/
|
||||||
FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
|
FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
|
||||||
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_);
|
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_,
|
||||||
|
PosixThreadArgs* args);
|
||||||
~FixedTimeslotTask() override = default;
|
~FixedTimeslotTask() override = default;
|
||||||
|
|
||||||
ReturnValue_t startTask() override;
|
ReturnValue_t startTask() override;
|
||||||
|
@ -4,10 +4,15 @@
|
|||||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||||
|
|
||||||
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_,
|
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_,
|
||||||
TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_)
|
TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_,
|
||||||
|
PosixThreadArgs* args)
|
||||||
: PeriodicTaskBase(period_, dlmFunc_),
|
: PeriodicTaskBase(period_, dlmFunc_),
|
||||||
posixThread(name_, priority_, stackSize_),
|
posixThread(name_, SchedulingPolicy::REGULAR, priority_, stackSize_),
|
||||||
started(false) {}
|
started(false) {
|
||||||
|
if (args != nullptr) {
|
||||||
|
posixThread.setSchedPolicy(args->policy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
||||||
// The argument is re-interpreted as PollingTask.
|
// The argument is re-interpreted as PollingTask.
|
||||||
|
@ -24,7 +24,7 @@ class PeriodicPosixTask : public PeriodicTaskBase {
|
|||||||
* @param deadlineMissedFunc_
|
* @param deadlineMissedFunc_
|
||||||
*/
|
*/
|
||||||
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_,
|
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_,
|
||||||
TaskDeadlineMissedFunction dlmFunc_);
|
TaskDeadlineMissedFunction dlmFunc_, PosixThreadArgs* args);
|
||||||
~PeriodicPosixTask() override = default;
|
~PeriodicPosixTask() override = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,8 +7,9 @@
|
|||||||
#include "fsfw/osal/linux/unixUtility.h"
|
#include "fsfw/osal/linux/unixUtility.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_)
|
PosixThread::PosixThread(const char* name_, SchedulingPolicy schedPolciy, int priority_,
|
||||||
: thread(0), priority(priority_), stackSize(stackSize_) {
|
size_t stackSize_)
|
||||||
|
: thread(0), schedPolicy(schedPolciy), priority(priority_), stackSize(stackSize_) {
|
||||||
name[0] = '\0';
|
name[0] = '\0';
|
||||||
std::strncat(name, name_, PTHREAD_MAX_NAMELEN - 1);
|
std::strncat(name, name_, PTHREAD_MAX_NAMELEN - 1);
|
||||||
}
|
}
|
||||||
@ -178,20 +179,30 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
|
|||||||
#ifndef FSFW_USE_REALTIME_FOR_LINUX
|
#ifndef FSFW_USE_REALTIME_FOR_LINUX
|
||||||
#error "Please define FSFW_USE_REALTIME_FOR_LINUX with either 0 or 1"
|
#error "Please define FSFW_USE_REALTIME_FOR_LINUX with either 0 or 1"
|
||||||
#endif
|
#endif
|
||||||
|
if (schedPolicy == SchedulingPolicy::RR) {
|
||||||
|
// RR -> This needs root privileges for the process
|
||||||
#if FSFW_USE_REALTIME_FOR_LINUX == 1
|
#if FSFW_USE_REALTIME_FOR_LINUX == 1
|
||||||
// FIFO -> This needs root privileges for the process
|
status = pthread_attr_setschedpolicy(&attributes, SCHED_RR);
|
||||||
status = pthread_attr_setschedpolicy(&attributes, SCHED_FIFO);
|
if (status != 0) {
|
||||||
if (status != 0) {
|
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedpolicy");
|
||||||
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedpolicy");
|
}
|
||||||
|
sched_param scheduleParams;
|
||||||
|
scheduleParams.sched_priority = priority;
|
||||||
|
status = pthread_attr_setschedparam(&attributes, &scheduleParams);
|
||||||
|
if (status != 0) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "PosixThread: Setting priority failed" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning
|
||||||
|
<< "Real time priorities are only allowed if FSFW_USE_REALTIME_FOR_LINUX is set to 1"
|
||||||
|
<< std::endl;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
sched_param scheduleParams;
|
|
||||||
scheduleParams.__sched_priority = priority;
|
|
||||||
status = pthread_attr_setschedparam(&attributes, &scheduleParams);
|
|
||||||
if (status != 0) {
|
|
||||||
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedparam");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Set Signal Mask for suspend until startTask is called
|
// Set Signal Mask for suspend until startTask is called
|
||||||
sigset_t waitSignal;
|
sigset_t waitSignal;
|
||||||
sigemptyset(&waitSignal);
|
sigemptyset(&waitSignal);
|
||||||
@ -243,3 +254,5 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
|
|||||||
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_destroy");
|
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_destroy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PosixThread::setSchedPolicy(SchedulingPolicy policy) { this->schedPolicy = policy; }
|
||||||
|
@ -9,10 +9,15 @@
|
|||||||
|
|
||||||
#include "../../returnvalues/returnvalue.h"
|
#include "../../returnvalues/returnvalue.h"
|
||||||
|
|
||||||
|
enum SchedulingPolicy { REGULAR, RR };
|
||||||
|
struct PosixThreadArgs {
|
||||||
|
SchedulingPolicy policy = SchedulingPolicy::REGULAR;
|
||||||
|
};
|
||||||
|
|
||||||
class PosixThread {
|
class PosixThread {
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t PTHREAD_MAX_NAMELEN = 16;
|
static constexpr uint8_t PTHREAD_MAX_NAMELEN = 16;
|
||||||
PosixThread(const char* name_, int priority_, size_t stackSize_);
|
PosixThread(const char* name_, SchedulingPolicy schedPolicy, int priority_, size_t stackSize_);
|
||||||
virtual ~PosixThread();
|
virtual ~PosixThread();
|
||||||
/**
|
/**
|
||||||
* Set the Thread to sleep state
|
* Set the Thread to sleep state
|
||||||
@ -20,6 +25,9 @@ class PosixThread {
|
|||||||
* @return Returns Failed if sleep fails
|
* @return Returns Failed if sleep fails
|
||||||
*/
|
*/
|
||||||
static ReturnValue_t sleep(uint64_t ns);
|
static ReturnValue_t sleep(uint64_t ns);
|
||||||
|
|
||||||
|
void setSchedPolicy(SchedulingPolicy policy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Function to suspend the task until SIGUSR1 was received
|
* @brief Function to suspend the task until SIGUSR1 was received
|
||||||
*
|
*
|
||||||
@ -72,6 +80,7 @@ class PosixThread {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
char name[PTHREAD_MAX_NAMELEN];
|
char name[PTHREAD_MAX_NAMELEN];
|
||||||
|
SchedulingPolicy schedPolicy;
|
||||||
int priority;
|
int priority;
|
||||||
size_t stackSize = 0;
|
size_t stackSize = 0;
|
||||||
|
|
||||||
|
@ -12,18 +12,20 @@ TaskFactory::~TaskFactory() = default;
|
|||||||
|
|
||||||
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
||||||
|
|
||||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(
|
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
|
||||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
TaskStackSize stackSize_,
|
||||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
TaskPeriod periodInSeconds_,
|
||||||
|
TaskDeadlineMissedFunction deadLineMissedFunction_,
|
||||||
|
void* args) {
|
||||||
return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
||||||
deadLineMissedFunction_);
|
deadLineMissedFunction_, reinterpret_cast<PosixThreadArgs*>(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
|
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
|
||||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
||||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_, void* args) {
|
||||||
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
||||||
deadLineMissedFunction_);
|
deadLineMissedFunction_, reinterpret_cast<PosixThreadArgs*>(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
||||||
|
@ -6,7 +6,11 @@ DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwit
|
|||||||
: SystemObject(objectId, registerGlobally),
|
: SystemObject(objectId, registerGlobally),
|
||||||
switcherList(numberOfSwitches),
|
switcherList(numberOfSwitches),
|
||||||
fuseList(numberOfFuses),
|
fuseList(numberOfFuses),
|
||||||
switchDelayMs(switchDelayMs) {}
|
switchDelayMs(switchDelayMs) {
|
||||||
|
for (auto &switchState : switcherList) {
|
||||||
|
switchState = PowerSwitchIF::SWITCH_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
|
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
|
||||||
this->switcherList = switcherList;
|
this->switcherList = switcherList;
|
||||||
|
@ -42,7 +42,7 @@ class PowerSwitcherComponent : public SystemObject,
|
|||||||
private:
|
private:
|
||||||
MessageQueueIF *queue = nullptr;
|
MessageQueueIF *queue = nullptr;
|
||||||
|
|
||||||
Mode_t mode = MODE_OFF;
|
Mode_t mode = MODE_UNDEFINED;
|
||||||
Submode_t submode = 0;
|
Submode_t submode = 0;
|
||||||
|
|
||||||
ModeHelper modeHelper;
|
ModeHelper modeHelper;
|
||||||
|
@ -4,9 +4,10 @@
|
|||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/pus/servicepackets/Service3Packets.h"
|
#include "fsfw/pus/servicepackets/Service3Packets.h"
|
||||||
|
|
||||||
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId)
|
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
||||||
: CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, NUM_OF_PARALLEL_COMMANDS,
|
uint32_t queueDepth, uint8_t numParallelCommands)
|
||||||
COMMAND_TIMEOUT_SECONDS) {}
|
: CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, numParallelCommands,
|
||||||
|
COMMAND_TIMEOUT_SECONDS, queueDepth) {}
|
||||||
|
|
||||||
Service3Housekeeping::~Service3Housekeeping() {}
|
Service3Housekeeping::~Service3Housekeeping() {}
|
||||||
|
|
||||||
|
@ -28,7 +28,8 @@ class Service3Housekeeping : public CommandingServiceBase, public AcceptsHkPacke
|
|||||||
static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4;
|
static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4;
|
||||||
static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60;
|
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();
|
virtual ~Service3Housekeeping();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
Service8FunctionManagement::Service8FunctionManagement(object_id_t objectId, uint16_t apid,
|
Service8FunctionManagement::Service8FunctionManagement(object_id_t objectId, uint16_t apid,
|
||||||
uint8_t serviceId,
|
uint8_t serviceId, size_t queueDepth,
|
||||||
uint8_t numParallelCommands,
|
uint8_t numParallelCommands,
|
||||||
uint16_t commandTimeoutSeconds)
|
uint16_t commandTimeoutSeconds)
|
||||||
: CommandingServiceBase(objectId, apid, "PUS 8 Functional Commanding", serviceId,
|
: CommandingServiceBase(objectId, apid, "PUS 8 Functional Commanding", serviceId,
|
||||||
numParallelCommands, commandTimeoutSeconds) {}
|
numParallelCommands, commandTimeoutSeconds, queueDepth) {}
|
||||||
|
|
||||||
Service8FunctionManagement::~Service8FunctionManagement() {}
|
Service8FunctionManagement::~Service8FunctionManagement() {}
|
||||||
|
|
||||||
|
@ -31,7 +31,8 @@
|
|||||||
class Service8FunctionManagement : public CommandingServiceBase {
|
class Service8FunctionManagement : public CommandingServiceBase {
|
||||||
public:
|
public:
|
||||||
Service8FunctionManagement(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
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;
|
~Service8FunctionManagement() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -315,20 +315,7 @@ object_id_t SubsystemBase::getObjectId() const { return SystemObject::getObjectI
|
|||||||
void SubsystemBase::modeChanged() {}
|
void SubsystemBase::modeChanged() {}
|
||||||
|
|
||||||
ReturnValue_t SubsystemBase::registerChild(const ModeTreeChildIF& child) {
|
ReturnValue_t SubsystemBase::registerChild(const ModeTreeChildIF& child) {
|
||||||
ChildInfo info;
|
return registerChild(child.getObjectId(), child.getModeIF().getCommandQueue());
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; }
|
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; }
|
const HasModesIF& SubsystemBase::getModeIF() const { return *this; }
|
||||||
|
|
||||||
ModeTreeChildIF& SubsystemBase::getModeTreeChildIF() { 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;
|
||||||
|
}
|
||||||
|
@ -61,6 +61,8 @@ class SubsystemBase : public SystemObject,
|
|||||||
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
|
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
|
||||||
*/
|
*/
|
||||||
ReturnValue_t registerChild(const ModeTreeChildIF &child) override;
|
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;
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
|
@ -47,7 +47,8 @@ class TaskFactory {
|
|||||||
*/
|
*/
|
||||||
PeriodicTaskIF* createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
|
PeriodicTaskIF* createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
|
||||||
TaskStackSize stackSize_, TaskPeriod periodInSeconds_,
|
TaskStackSize stackSize_, TaskPeriod periodInSeconds_,
|
||||||
TaskDeadlineMissedFunction deadLineMissedFunction_);
|
TaskDeadlineMissedFunction deadLineMissedFunction_,
|
||||||
|
void* args = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The meaning for the variables for fixed timeslot tasks is the same as for periodic tasks.
|
* The meaning for the variables for fixed timeslot tasks is the same as for periodic tasks.
|
||||||
@ -62,7 +63,8 @@ class TaskFactory {
|
|||||||
FixedTimeslotTaskIF* createFixedTimeslotTask(TaskName name_, TaskPriority taskPriority_,
|
FixedTimeslotTaskIF* createFixedTimeslotTask(TaskName name_, TaskPriority taskPriority_,
|
||||||
TaskStackSize stackSize_,
|
TaskStackSize stackSize_,
|
||||||
TaskPeriod periodInSeconds_,
|
TaskPeriod periodInSeconds_,
|
||||||
TaskDeadlineMissedFunction deadLineMissedFunction_);
|
TaskDeadlineMissedFunction deadLineMissedFunction_,
|
||||||
|
void* args = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to be called to delete a task
|
* Function to be called to delete a task
|
||||||
|
@ -40,7 +40,7 @@ struct PusTmParams {
|
|||||||
size_t dataLen)
|
size_t dataLen)
|
||||||
: secHeader(service, subservice, timeStamper), adapter(data, dataLen), sourceData(&adapter) {}
|
: secHeader(service, subservice, timeStamper), adapter(data, dataLen), sourceData(&adapter) {}
|
||||||
PusTmSecHeader secHeader;
|
PusTmSecHeader secHeader;
|
||||||
SerialBufferAdapter<uint8_t> adapter;
|
SerialBufferAdapter<size_t> adapter;
|
||||||
const SerializeIF* sourceData = nullptr;
|
const SerializeIF* sourceData = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,3 +24,9 @@ void PusTmZeroCopyWriter::updateErrorControl() {
|
|||||||
crcStart[0] = (crc16 >> 8) & 0xff;
|
crcStart[0] = (crc16 >> 8) & 0xff;
|
||||||
crcStart[1] = crc16 & 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);
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@ class PusTmZeroCopyWriter : public PusTmReader {
|
|||||||
PusTmZeroCopyWriter(TimeReaderIF& timeReader, uint8_t* data, size_t size);
|
PusTmZeroCopyWriter(TimeReaderIF& timeReader, uint8_t* data, size_t size);
|
||||||
|
|
||||||
void setSequenceCount(uint16_t seqCount);
|
void setSequenceCount(uint16_t seqCount);
|
||||||
|
void setMessageCount(uint16_t msgCount);
|
||||||
void updateErrorControl();
|
void updateErrorControl();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -5,8 +5,18 @@
|
|||||||
|
|
||||||
namespace spi {
|
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 };
|
enum SpiModes : uint8_t { MODE_0, MODE_1, MODE_2, MODE_3 };
|
||||||
|
|
||||||
}
|
} // namespace spi
|
||||||
|
|
||||||
#endif /* FSFW_HAL_COMMON_SPI_SPICOMMON_H_ */
|
#endif /* FSFW_HAL_COMMON_SPI_SPICOMMON_H_ */
|
||||||
|
@ -73,8 +73,10 @@ static constexpr uint8_t CTRL_REG_4_VAL = SET_BLE;
|
|||||||
/* Register 5 */
|
/* Register 5 */
|
||||||
static constexpr uint8_t SET_REBOOT_MEM = 1 << 7;
|
static constexpr uint8_t SET_REBOOT_MEM = 1 << 7;
|
||||||
static constexpr uint8_t SET_FIFO_ENB = 1 << 6;
|
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). */
|
/* Possible range values in degrees per second (DPS). */
|
||||||
static constexpr uint16_t RANGE_DPS_00 = 245;
|
static constexpr uint16_t RANGE_DPS_00 = 245;
|
||||||
|
@ -165,7 +165,8 @@ ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) {
|
|||||||
if (not filesystem::exists(path, e)) {
|
if (not filesystem::exists(path, e)) {
|
||||||
return FILE_DOES_NOT_EXIST;
|
return FILE_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
ofstream of(path);
|
// Specify truncation flug explicitely.
|
||||||
|
ofstream of(path, std::ios::out | std::ios::trunc);
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,11 +88,11 @@ int SerialComIF::configureUartPort(SerialCookie* uartCookie) {
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
uart::setParity(options, uartCookie->getParity());
|
serial::setParity(options, uartCookie->getParity());
|
||||||
setStopBitOptions(&options, uartCookie);
|
setStopBitOptions(&options, uartCookie);
|
||||||
setDatasizeOptions(&options, uartCookie);
|
setDatasizeOptions(&options, uartCookie);
|
||||||
setFixedOptions(&options);
|
setFixedOptions(&options);
|
||||||
uart::setMode(options, uartCookie->getUartMode());
|
serial::setMode(options, uartCookie->getUartMode());
|
||||||
if (uartCookie->getInputShouldBeFlushed()) {
|
if (uartCookie->getInputShouldBeFlushed()) {
|
||||||
tcflush(fd, TCIFLUSH);
|
tcflush(fd, TCIFLUSH);
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ int SerialComIF::configureUartPort(SerialCookie* uartCookie) {
|
|||||||
options.c_cc[VTIME] = 0;
|
options.c_cc[VTIME] = 0;
|
||||||
options.c_cc[VMIN] = 0;
|
options.c_cc[VMIN] = 0;
|
||||||
|
|
||||||
uart::setBaudrate(options, uartCookie->getBaudrate());
|
serial::setBaudrate(options, uartCookie->getBaudrate());
|
||||||
|
|
||||||
/* Save option settings */
|
/* Save option settings */
|
||||||
if (tcsetattr(fd, TCSANOW, &options) != 0) {
|
if (tcsetattr(fd, TCSANOW, &options) != 0) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "fsfw/serviceinterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
void uart::setMode(struct termios& options, UartModes mode) {
|
void serial::setMode(struct termios& options, UartModes mode) {
|
||||||
if (mode == UartModes::NON_CANONICAL) {
|
if (mode == UartModes::NON_CANONICAL) {
|
||||||
/* Disable canonical mode */
|
/* Disable canonical mode */
|
||||||
options.c_lflag &= ~ICANON;
|
options.c_lflag &= ~ICANON;
|
||||||
@ -12,7 +12,7 @@ void uart::setMode(struct termios& options, UartModes mode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart::setBaudrate(struct termios& options, UartBaudRate baud) {
|
void serial::setBaudrate(struct termios& options, UartBaudRate baud) {
|
||||||
switch (baud) {
|
switch (baud) {
|
||||||
case UartBaudRate::RATE_50:
|
case UartBaudRate::RATE_50:
|
||||||
cfsetspeed(&options, B50);
|
cfsetspeed(&options, B50);
|
||||||
@ -114,7 +114,7 @@ void uart::setBaudrate(struct termios& options, UartBaudRate baud) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart::setBitsPerWord(struct termios& options, BitsPerWord bits) {
|
void serial::setBitsPerWord(struct termios& options, BitsPerWord bits) {
|
||||||
options.c_cflag &= ~CSIZE; // Clear all the size bits
|
options.c_cflag &= ~CSIZE; // Clear all the size bits
|
||||||
if (bits == BitsPerWord::BITS_5) {
|
if (bits == BitsPerWord::BITS_5) {
|
||||||
options.c_cflag |= CS5;
|
options.c_cflag |= CS5;
|
||||||
@ -127,11 +127,11 @@ void uart::setBitsPerWord(struct termios& options, BitsPerWord bits) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart::enableRead(struct termios& options) { options.c_cflag |= CREAD; }
|
void serial::enableRead(struct termios& options) { options.c_cflag |= CREAD; }
|
||||||
|
|
||||||
void uart::ignoreCtrlLines(struct termios& options) { options.c_cflag |= CLOCAL; }
|
void serial::ignoreCtrlLines(struct termios& options) { options.c_cflag |= CLOCAL; }
|
||||||
|
|
||||||
void uart::setParity(struct termios& options, Parity parity) {
|
void serial::setParity(struct termios& options, Parity parity) {
|
||||||
/* Clear parity bit */
|
/* Clear parity bit */
|
||||||
options.c_cflag &= ~PARENB;
|
options.c_cflag &= ~PARENB;
|
||||||
switch (parity) {
|
switch (parity) {
|
||||||
@ -148,11 +148,11 @@ void uart::setParity(struct termios& options, Parity parity) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int uart::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) {
|
int serial::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) {
|
||||||
return ioctl(serialPort, TIOCGICOUNT, &icounter);
|
return ioctl(serialPort, TIOCGICOUNT, &icounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart::setStopbits(struct termios& options, StopBits bits) {
|
void serial::setStopbits(struct termios& options, StopBits bits) {
|
||||||
if (bits == StopBits::TWO_STOP_BITS) {
|
if (bits == StopBits::TWO_STOP_BITS) {
|
||||||
// Use two stop bits
|
// Use two stop bits
|
||||||
options.c_cflag |= CSTOPB;
|
options.c_cflag |= CSTOPB;
|
||||||
@ -161,3 +161,7 @@ void uart::setStopbits(struct termios& options, StopBits bits) {
|
|||||||
options.c_cflag &= ~CSTOPB;
|
options.c_cflag &= ~CSTOPB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serial::flushRxBuf(int fd) { tcflush(fd, TCIFLUSH); }
|
||||||
|
|
||||||
|
void serial::flushTxRxBuf(int fd) { tcflush(fd, TCIOFLUSH); }
|
||||||
|
@ -45,7 +45,7 @@ enum class UartBaudRate {
|
|||||||
RATE_4000000
|
RATE_4000000
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace uart {
|
namespace serial {
|
||||||
|
|
||||||
void setMode(struct termios& options, UartModes mode);
|
void setMode(struct termios& options, UartModes mode);
|
||||||
/**
|
/**
|
||||||
@ -64,8 +64,11 @@ void setParity(struct termios& options, Parity parity);
|
|||||||
|
|
||||||
void ignoreCtrlLines(struct termios& options);
|
void ignoreCtrlLines(struct termios& options);
|
||||||
|
|
||||||
|
void flushRxBuf(int fd);
|
||||||
|
void flushTxRxBuf(int fd);
|
||||||
|
|
||||||
int readCountersAndErrors(int serialPort, serial_icounter_struct& icounter);
|
int readCountersAndErrors(int serialPort, serial_icounter_struct& icounter);
|
||||||
|
|
||||||
} // namespace uart
|
} // namespace serial
|
||||||
|
|
||||||
#endif /* FSFW_HAL_LINUX_UART_HELPER_H_ */
|
#endif /* FSFW_HAL_LINUX_UART_HELPER_H_ */
|
||||||
|
@ -173,7 +173,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
int fileDescriptor = 0;
|
int fileDescriptor = 0;
|
||||||
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
|
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
|
||||||
if (fileHelper.getOpenResult() != returnvalue::OK) {
|
if (fileHelper.getOpenResult() != returnvalue::OK) {
|
||||||
return OPENING_FILE_FAILED;
|
return spi::OPENING_FILE_FAILED;
|
||||||
}
|
}
|
||||||
spi::SpiModes spiMode = spi::SpiModes::MODE_0;
|
spi::SpiModes spiMode = spi::SpiModes::MODE_0;
|
||||||
uint32_t spiSpeed = 0;
|
uint32_t spiSpeed = 0;
|
||||||
@ -234,7 +234,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
spiCookie->setTransferSize(0);
|
spiCookie->setTransferSize(0);
|
||||||
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
|
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
|
||||||
result = FULL_DUPLEX_TRANSFER_FAILED;
|
result = spi::FULL_DUPLEX_TRANSFER_FAILED;
|
||||||
}
|
}
|
||||||
#if FSFW_HAL_SPI_WIRETAPPING == 1
|
#if FSFW_HAL_SPI_WIRETAPPING == 1
|
||||||
performSpiWiretapping(spiCookie);
|
performSpiWiretapping(spiCookie);
|
||||||
@ -250,7 +250,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
sif::printWarning("SpiComIF::sendMessage: Half-Duplex write operation failed!\n");
|
sif::printWarning("SpiComIF::sendMessage: Half-Duplex write operation failed!\n");
|
||||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 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;
|
int fileDescriptor = 0;
|
||||||
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
|
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
|
||||||
if (fileHelper.getOpenResult() != returnvalue::OK) {
|
if (fileHelper.getOpenResult() != returnvalue::OK) {
|
||||||
return OPENING_FILE_FAILED;
|
return spi::OPENING_FILE_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* rxBuf = nullptr;
|
uint8_t* rxBuf = nullptr;
|
||||||
@ -327,7 +327,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
|
|||||||
sif::printWarning("SpiComIF::sendMessage: Half-Duplex read operation failed!\n");
|
sif::printWarning("SpiComIF::sendMessage: Half-Duplex read operation failed!\n");
|
||||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 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) {
|
if (gpioId != gpio::NO_GPIO and not csLockManual) {
|
||||||
|
@ -22,15 +22,6 @@ class SpiCookie;
|
|||||||
*/
|
*/
|
||||||
class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
||||||
public:
|
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);
|
SpiComIF(object_id_t objectId, std::string devname, GpioIF& gpioComIF);
|
||||||
|
|
||||||
ReturnValue_t initializeInterface(CookieIF* cookie) override;
|
ReturnValue_t initializeInterface(CookieIF* cookie) override;
|
||||||
|
@ -36,7 +36,7 @@ UioMapper::~UioMapper() {}
|
|||||||
|
|
||||||
ReturnValue_t UioMapper::getMappedAdress(uint32_t** address, Permissions permissions) {
|
ReturnValue_t UioMapper::getMappedAdress(uint32_t** address, Permissions permissions) {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
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 (fd < 1) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "UioMapper::getMappedAdress: Invalid UIO device file " << uioFile << std::endl;
|
sif::error << "UioMapper::getMappedAdress: Invalid UIO device file " << uioFile << std::endl;
|
||||||
|
@ -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);
|
sif::printWarning("SpiComIF::handle%sSendOperation: HAL error %d occured\n", modeString, status);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case (HAL_BUSY): {
|
case (HAL_BUSY): {
|
||||||
return spi::HAL_BUSY_RETVAL;
|
return spi::BUSY;
|
||||||
}
|
}
|
||||||
case (HAL_ERROR): {
|
case (HAL_ERROR): {
|
||||||
return spi::HAL_ERROR_RETVAL;
|
return spi::GENERIC_ERROR;
|
||||||
}
|
}
|
||||||
case (HAL_TIMEOUT): {
|
case (HAL_TIMEOUT): {
|
||||||
return spi::HAL_TIMEOUT_RETVAL;
|
return spi::TIMEOUT;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
|
@ -30,9 +30,9 @@
|
|||||||
*/
|
*/
|
||||||
void Factory::produceFrameworkObjects(void* args) {
|
void Factory::produceFrameworkObjects(void* args) {
|
||||||
setStaticFrameworkObjectIds();
|
setStaticFrameworkObjectIds();
|
||||||
new EventManager(objects::EVENT_MANAGER);
|
new EventManager(objects::EVENT_MANAGER, 120);
|
||||||
new HealthTable(objects::HEALTH_TABLE);
|
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}};
|
PoolManager::LocalPoolConfig poolCfg = {{100, 16}, {50, 32}, {25, 64}, {15, 128}, {5, 1024}};
|
||||||
|
@ -27,12 +27,7 @@ TEST_CASE("Action Helper", "[action]") {
|
|||||||
CHECK(not testDhMock.executeActionCalled);
|
CHECK(not testDhMock.executeActionCalled);
|
||||||
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
|
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
|
||||||
CHECK(testDhMock.executeActionCalled);
|
CHECK(testDhMock.executeActionCalled);
|
||||||
// No message is sent if everything is alright.
|
|
||||||
CHECK(not testMqMock.wasMessageSent());
|
CHECK(not testMqMock.wasMessageSent());
|
||||||
store_address_t invalidAddress;
|
|
||||||
ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
|
|
||||||
actionHelper.handleActionMessage(&actionMessage);
|
|
||||||
CHECK(testMqMock.wasMessageSent());
|
|
||||||
const uint8_t* ptr = nullptr;
|
const uint8_t* ptr = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
REQUIRE(ipcStore->getData(paramAddress, &ptr, &size) ==
|
REQUIRE(ipcStore->getData(paramAddress, &ptr, &size) ==
|
||||||
@ -44,6 +39,10 @@ TEST_CASE("Action Helper", "[action]") {
|
|||||||
for (uint8_t i = 0; i < 3; i++) {
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
REQUIRE(ptr[i] == (i + 1));
|
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();
|
testDhMock.clearBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,17 +94,5 @@ TEST_CASE("Action Helper", "[action]") {
|
|||||||
REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId);
|
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") {}
|
SECTION("Data Reply") {}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
|
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
|
||||||
SerializeIF::Endianness::BIG) == returnvalue::OK);
|
SerializeIF::Endianness::BIG) == returnvalue::OK);
|
||||||
CHECK(serBuf[0] == 0x3f);
|
CHECK(serBuf[0] == 0x3f);
|
||||||
CHECK(serBuf[3] == 0x99);
|
CHECK(serBuf[3] == 0x88);
|
||||||
REQUIRE(creator.getCrcFlag() == true);
|
REQUIRE(creator.getCrcFlag() == true);
|
||||||
REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER);
|
REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER);
|
||||||
REQUIRE(creator.getLargeFileFlag() == true);
|
REQUIRE(creator.getLargeFileFlag() == true);
|
||||||
@ -127,7 +127,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
|
REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
|
||||||
REQUIRE(creator.getSegmentationControl() == true);
|
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)
|
// 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;
|
uint32_t entityId = 0;
|
||||||
size_t deSerSize = 0;
|
size_t deSerSize = 0;
|
||||||
SerializeAdapter::deSerialize(&entityId, serBuf.data() + 4, &deSerSize,
|
SerializeAdapter::deSerialize(&entityId, serBuf.data() + 4, &deSerSize,
|
||||||
@ -175,7 +175,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
REQUIRE(serBuf[1] == 0);
|
REQUIRE(serBuf[1] == 0);
|
||||||
REQUIRE(serBuf[2] == 0);
|
REQUIRE(serBuf[2] == 0);
|
||||||
// Entity and Transaction Sequence number are 1 byte large
|
// Entity and Transaction Sequence number are 1 byte large
|
||||||
REQUIRE(serBuf[3] == 0b00010001);
|
REQUIRE(serBuf[3] == 0b00000000);
|
||||||
// Source ID
|
// Source ID
|
||||||
REQUIRE(serBuf[4] == 0);
|
REQUIRE(serBuf[4] == 0);
|
||||||
// Transaction Seq Number
|
// Transaction Seq Number
|
||||||
@ -220,7 +220,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
REQUIRE(serBuf[1] == 0);
|
REQUIRE(serBuf[1] == 0);
|
||||||
REQUIRE(serBuf[2] == 0);
|
REQUIRE(serBuf[2] == 0);
|
||||||
// Entity and Transaction Sequence number are 1 byte large
|
// Entity and Transaction Sequence number are 1 byte large
|
||||||
REQUIRE(serBuf[3] == 0b00010001);
|
REQUIRE(serBuf[3] == 0b00000000);
|
||||||
REQUIRE(serSize == 7);
|
REQUIRE(serSize == 7);
|
||||||
// Deser call not strictly necessary
|
// Deser call not strictly necessary
|
||||||
auto reader = PduHeaderReader(serBuf.data(), serBuf.size());
|
auto reader = PduHeaderReader(serBuf.data(), serBuf.size());
|
||||||
@ -270,7 +270,7 @@ TEST_CASE("CFDP Header", "[cfdp]") {
|
|||||||
REQUIRE(reader.parseData() == returnvalue::OK);
|
REQUIRE(reader.parseData() == returnvalue::OK);
|
||||||
// Everything except version bit flipped to one now
|
// Everything except version bit flipped to one now
|
||||||
REQUIRE(serBuf[0] == 0x3f);
|
REQUIRE(serBuf[0] == 0x3f);
|
||||||
REQUIRE(serBuf[3] == 0b11001010);
|
REQUIRE(serBuf[3] == 0b10111001);
|
||||||
REQUIRE(reader.getWholePduSize() == 14);
|
REQUIRE(reader.getWholePduSize() == 14);
|
||||||
|
|
||||||
REQUIRE(reader.getCrcFlag() == true);
|
REQUIRE(reader.getCrcFlag() == true);
|
||||||
|
@ -68,7 +68,7 @@ TEST_CASE("File Data PDU", "[cfdp][pdu]") {
|
|||||||
// Bits 1 to 3 length of enitity IDs is 2
|
// Bits 1 to 3 length of enitity IDs is 2
|
||||||
// Bit 4: Segment metadata flag is set
|
// Bit 4: Segment metadata flag is set
|
||||||
// Bit 5 to seven: length of transaction seq num is 2
|
// Bit 5 to seven: length of transaction seq num is 2
|
||||||
REQUIRE(fileDataBuffer[3] == 0b10101010);
|
REQUIRE(fileDataBuffer[3] == 0b10011001);
|
||||||
REQUIRE((fileDataBuffer[10] >> 6) &
|
REQUIRE((fileDataBuffer[10] >> 6) &
|
||||||
0b11 == cfdp::RecordContinuationState::CONTAINS_START_AND_END);
|
0b11 == cfdp::RecordContinuationState::CONTAINS_START_AND_END);
|
||||||
// Segment metadata length
|
// Segment metadata length
|
||||||
|
@ -30,7 +30,7 @@ TEST_CASE("CFDP File Directive", "[cfdp][pdu]") {
|
|||||||
REQUIRE(serBuf[1] == 0);
|
REQUIRE(serBuf[1] == 0);
|
||||||
REQUIRE(serBuf[2] == 5);
|
REQUIRE(serBuf[2] == 5);
|
||||||
// Entity and Transaction Sequence number are 1 byte large
|
// Entity and Transaction Sequence number are 1 byte large
|
||||||
REQUIRE(serBuf[3] == 0b00010001);
|
REQUIRE(serBuf[3] == 0b00000000);
|
||||||
// Source ID
|
// Source ID
|
||||||
REQUIRE(serBuf[4] == 0);
|
REQUIRE(serBuf[4] == 0);
|
||||||
// Transaction Seq Number
|
// Transaction Seq Number
|
||||||
@ -82,4 +82,4 @@ TEST_CASE("CFDP File Directive", "[cfdp][pdu]") {
|
|||||||
// Invalid file directive
|
// Invalid file directive
|
||||||
REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELD);
|
REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,8 @@ TEST_CASE("CFDP Base", "[cfdp]") {
|
|||||||
// PDU data field length is 5 (4 + Directive code octet)
|
// PDU data field length is 5 (4 + Directive code octet)
|
||||||
REQUIRE(serBuf[1] == 0);
|
REQUIRE(serBuf[1] == 0);
|
||||||
REQUIRE(serBuf[2] == 5);
|
REQUIRE(serBuf[2] == 5);
|
||||||
// Entity and Transaction Sequence number are 1 byte large
|
// Entity and Transaction Sequence number are 1 byte large, value minus one is stored
|
||||||
REQUIRE(serBuf[3] == 0b00010001);
|
REQUIRE(serBuf[3] == 0b00000000);
|
||||||
// Source ID
|
// Source ID
|
||||||
REQUIRE(serBuf[4] == 0);
|
REQUIRE(serBuf[4] == 0);
|
||||||
// Transaction Seq Number
|
// Transaction Seq Number
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <catch2/catch_approx.hpp>
|
#include <catch2/catch_approx.hpp>
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "CatchDefinitions.h"
|
#include "CatchDefinitions.h"
|
||||||
@ -309,9 +310,7 @@ TEST_CASE("Local Pool Manager Tests", "[LocManTest]") {
|
|||||||
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
|
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
|
||||||
false);
|
false);
|
||||||
CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK);
|
CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK);
|
||||||
/* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the
|
CHECK_THAT(poolOwner.dataset.getCollectionInterval(), Catch::Matchers::WithinAbs(0.4, 0.01));
|
||||||
resulting collection interval should be 1.0 second */
|
|
||||||
CHECK(poolOwner.dataset.getCollectionInterval() == 1.0);
|
|
||||||
REQUIRE(poolOwnerMock.wasMessageSent());
|
REQUIRE(poolOwnerMock.wasMessageSent());
|
||||||
REQUIRE(poolOwnerMock.numberOfSentMessages() == 1);
|
REQUIRE(poolOwnerMock.numberOfSentMessages() == 1);
|
||||||
CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK);
|
CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK);
|
||||||
@ -348,14 +347,6 @@ TEST_CASE("Local Pool Manager Tests", "[LocManTest]") {
|
|||||||
REQUIRE(poolOwnerMock.numberOfSentMessages() == 1);
|
REQUIRE(poolOwnerMock.numberOfSentMessages() == 1);
|
||||||
CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK);
|
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);
|
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false);
|
||||||
CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) ==
|
CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) ==
|
||||||
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
|
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
|
||||||
|
Loading…
Reference in New Issue
Block a user