CFDP source handler #776

Merged
muellerr merged 96 commits from cfdp-source-handler into main 2023-10-19 11:11:31 +02:00
20 changed files with 141 additions and 94 deletions
Showing only changes of commit ffe1281eb9 - Show all commits

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 313 translations.
* @details
* Generated on: 2023-10-11 10:54:39
* Generated on: 2023-10-13 09:17:41
*/
#include "translateEvents.h"

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 174 translations.
* Generated on: 2023-10-11 10:54:39
* Generated on: 2023-10-13 09:17:41
*/
#include "translateObjects.h"

View File

@ -41,6 +41,7 @@ enum commonClassIds : uint8_t {
LOCAL_PARAM_HANDLER, // LPH
PERSISTENT_TM_STORE, // PTM
TM_SINK, // TMS
VIRTUAL_CHANNEL, // VCS
COMMON_CLASS_ID_END // [EXPORT] : [END]
};
}

View File

@ -513,3 +513,5 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
0x6d00;PTM_DumpDone;No description;0;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
0x6d01;PTM_BusyDumping;No description;1;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
0x6e00;TMS_IsBusy;No description;0;TM_SINK;mission/tmtc/DirectTmSinkIF.h
0x6e01;TMS_PartiallyWritten;No description;1;TM_SINK;mission/tmtc/DirectTmSinkIF.h
0x6f00;VCS_ChannelDoesNotExist;No description;0;VIRTUAL_CHANNEL;mission/com/VirtualChannel.h

1 Full ID (hex) Name Description Unique ID Subsytem Name File Path
513 0x6d00 PTM_DumpDone No description 0 PERSISTENT_TM_STORE mission/tmtc/PersistentTmStore.h
514 0x6d01 PTM_BusyDumping No description 1 PERSISTENT_TM_STORE mission/tmtc/PersistentTmStore.h
515 0x6e00 TMS_IsBusy No description 0 TM_SINK mission/tmtc/DirectTmSinkIF.h
516 0x6e01 TMS_PartiallyWritten No description 1 TM_SINK mission/tmtc/DirectTmSinkIF.h
517 0x6f00 VCS_ChannelDoesNotExist No description 0 VIRTUAL_CHANNEL mission/com/VirtualChannel.h

View File

@ -608,4 +608,6 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
0x6d00;PTM_DumpDone;No description;0;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
0x6d01;PTM_BusyDumping;No description;1;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
0x6e00;TMS_IsBusy;No description;0;TM_SINK;mission/tmtc/DirectTmSinkIF.h
0x7000;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h
0x6e01;TMS_PartiallyWritten;No description;1;TM_SINK;mission/tmtc/DirectTmSinkIF.h
0x6f00;VCS_ChannelDoesNotExist;No description;0;VIRTUAL_CHANNEL;mission/com/VirtualChannel.h
0x7100;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h

1 Full ID (hex) Name Description Unique ID Subsytem Name File Path
608 0x6d00 PTM_DumpDone No description 0 PERSISTENT_TM_STORE mission/tmtc/PersistentTmStore.h
609 0x6d01 PTM_BusyDumping No description 1 PERSISTENT_TM_STORE mission/tmtc/PersistentTmStore.h
610 0x6e00 TMS_IsBusy No description 0 TM_SINK mission/tmtc/DirectTmSinkIF.h
611 0x7000 0x6e01 SCBU_KeyNotFound TMS_PartiallyWritten No description 0 1 SCRATCH_BUFFER TM_SINK bsp_q7s/memory/scratchApi.h mission/tmtc/DirectTmSinkIF.h
612 0x6f00 VCS_ChannelDoesNotExist No description 0 VIRTUAL_CHANNEL mission/com/VirtualChannel.h
613 0x7100 SCBU_KeyNotFound No description 0 SCRATCH_BUFFER bsp_q7s/memory/scratchApi.h

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 313 translations.
* @details
* Generated on: 2023-10-11 10:54:39
* Generated on: 2023-10-13 09:17:41
*/
#include "translateEvents.h"

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 178 translations.
* Generated on: 2023-10-11 10:54:39
* Generated on: 2023-10-13 09:17:41
*/
#include "translateObjects.h"

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 313 translations.
* @details
* Generated on: 2023-10-11 10:54:39
* Generated on: 2023-10-13 09:17:41
*/
#include "translateEvents.h"

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 178 translations.
* Generated on: 2023-10-11 10:54:39
* Generated on: 2023-10-13 09:17:41
*/
#include "translateObjects.h"

View File

@ -23,7 +23,7 @@ ReturnValue_t PapbVcInterface::initialize() {
return returnvalue::OK;
}
ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size, size_t& writtenSize) {
// There are no packets smaller than 4, this is considered a configuration error.
if (size < 4) {
return returnvalue::FAILED;
@ -37,19 +37,7 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
abortPacketTransfer();
return returnvalue::FAILED;
}
for (size_t idx = 0; idx < size; idx++) {
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
}
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
completePacketTransfer();
return returnvalue::OK;
return finishWritePartialOpt(data, size, true);
}
void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) {
@ -65,6 +53,26 @@ bool PapbVcInterface::pollReadyForPacket() const {
return (reg >> 6) & 0b1;
}
ReturnValue_t PapbVcInterface::finishWritePartialOpt(const uint8_t* data, size_t remainingSize,
bool handlePartial) {
for (size_t idx = 0; idx < remainingSize; idx++) {
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
if (not pollReadyForPacket()) {
return PARTIALLY_WRITTEN;
}
abortPacketTransfer();
return returnvalue::FAILED;
}
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
}
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
completePacketTransfer();
return returnvalue::OK;
}
bool PapbVcInterface::isVcInterfaceBufferEmpty() {
ReturnValue_t result = returnvalue::OK;
gpio::Levels papbEmptyState = gpio::Levels::HIGH;
@ -101,21 +109,8 @@ inline bool PapbVcInterface::pollReadyForOctet(uint32_t maxCycles) const {
return false;
}
ReturnValue_t PapbVcInterface::sendTestFrame() {
/** Size of one complete transfer frame data field amounts to 1105 bytes */
uint8_t testPacket[1105];
/** Fill one test packet */
for (int idx = 0; idx < 1105; idx++) {
testPacket[idx] = static_cast<uint8_t>(idx & 0xFF);
}
ReturnValue_t result = write(testPacket, 1105);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
ReturnValue_t PapbVcInterface::finishWrite(const uint8_t* data, size_t remainingSize) {
return finishWritePartialOpt(data, remainingSize, false);
}
void PapbVcInterface::abortPacketTransfer() { *vcBaseReg = CONFIG_ABORT; }

View File

@ -40,7 +40,11 @@ class PapbVcInterface : public VirtualChannelIF {
* @param size
* @return returnvalue::OK on successfull write, PAPB_BUSY if PAPB is busy.
*/
ReturnValue_t write(const uint8_t* data, size_t size) override;
ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) override;
ReturnValue_t finishWrite(const uint8_t* data, size_t remainingSize) override;
ReturnValue_t finishWritePartialOpt(const uint8_t* data, size_t remainingSize,
bool handlePartial);
void cancelTransfer() override;
@ -126,12 +130,6 @@ class PapbVcInterface : public VirtualChannelIF {
* the packet buffer of the virtual channel or not.
*/
bool isVcInterfaceBufferEmpty();
/**
* @brief This function sends a complete telemetry transfer frame data field (1105 bytes)
* to the papb interface of the PTME IP Core. Can be used to test the implementation.
*/
ReturnValue_t sendTestFrame();
};
#endif /* LINUX_OBC_PAPBVCINTERFACE_H_ */

View File

@ -19,15 +19,12 @@ ReturnValue_t Ptme::initialize() {
return returnvalue::OK;
}
ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) {
VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId);
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual "
"channel with id "
<< static_cast<unsigned int>(vcId) << std::endl;
return UNKNOWN_VC_ID;
bool Ptme::containsVc(uint8_t vcId) const {
auto channelIter = vcInterfaceMap.find(vcId);
if (channelIter == vcInterfaceMap.end()) {
return false;
}
return vcInterfaceMapIter->second->write(data, size);
return true;
}
void Ptme::addVcInterface(VcId_t vcId, VirtualChannelIF* vc) {
@ -50,21 +47,10 @@ void Ptme::addVcInterface(VcId_t vcId, VirtualChannelIF* vc) {
}
}
bool Ptme::isBusy(uint8_t vcId) const {
const auto& vcInterfaceMapIter = vcInterfaceMap.find(vcId);
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual "
"channel with id "
<< static_cast<unsigned int>(vcId) << std::endl;
return UNKNOWN_VC_ID;
VirtualChannelIF* Ptme::getVirtChannel(uint8_t vcId) {
auto channelIter = vcInterfaceMap.find(vcId);
if (channelIter == vcInterfaceMap.end()) {
return nullptr;
}
return vcInterfaceMapIter->second->isBusy();
}
void Ptme::cancelTransfer(uint8_t vcId) {
VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId);
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
return;
}
return vcInterfaceMapIter->second->cancelTransfer();
return channelIter->second;
}

View File

@ -34,9 +34,8 @@ class Ptme : public PtmeIF, public SystemObject {
virtual ~Ptme();
ReturnValue_t initialize() override;
ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) override;
bool isBusy(uint8_t vcId) const override;
void cancelTransfer(uint8_t vcId) override;
bool containsVc(uint8_t vcId) const override;
VirtualChannelIF* getVirtChannel(uint8_t vcId) override;
/**
* @brief This function adds the reference to a virtual channel interface to the vcInterface

View File

@ -1,6 +1,8 @@
#ifndef LINUX_OBC_PTMEIF_H_
#define LINUX_OBC_PTMEIF_H_
#include <linux/ipcore/VirtualChannelIF.h>
#include "fsfw/returnvalues/returnvalue.h"
/**
@ -14,16 +16,8 @@ class PtmeIF {
public:
virtual ~PtmeIF(){};
/**
* @brief Implements to function to write to a specific virtual channel.
*
* @param vcId Virtual channel to write to
* @param data Pointer to buffer holding the data to write
* @param size Number of bytes to write
*/
virtual ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) = 0;
virtual bool isBusy(uint8_t vcId) const = 0;
virtual void cancelTransfer(uint8_t vcId) = 0;
virtual bool containsVc(uint8_t vcId) const = 0;
virtual VirtualChannelIF* getVirtChannel(uint8_t vcId) = 0;
};
#endif /* LINUX_OBC_PTMEIF_H_ */

View File

@ -138,8 +138,17 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
return result;
}
dumpedLen = tmReader.getFullPacketLen();
result = channel.write(tmReader.getFullData(), dumpedLen);
if (result == DirectTmSinkIF::IS_BUSY) {
size_t partiallyWrittenSize = 0;
result = channel.write(tmReader.getFullData(), dumpedLen, partiallyWrittenSize);
if (result == VirtualChannelIF::PARTIALLY_WRITTEN) {
result = channel.handleLastWriteSynchronously(tmReader.getFullData(), partiallyWrittenSize,
dumpedLen - partiallyWrittenSize, 20);
if (result != returnvalue::OK) {
Review

vom

vom
// TODO: Event? Might lead to dangerous spam though..
sif::warning << "PersistentTmStore: Synchronous write of last segment failed with code 0x"
<< std::setw(4) << std::hex << result << std::endl;
}
} else if (result == DirectTmSinkIF::IS_BUSY) {
sif::warning << "PersistentTmStore: Unexpected VC channel busy" << std::endl;
} else if (result != returnvalue::OK) {
sif::warning << "PersistentTmStore: Unexpected VC channel write failure" << std::endl;

View File

@ -1,25 +1,64 @@
#include "VirtualChannel.h"
#include <fsfw/tasks/TaskFactory.h>
VirtualChannel::VirtualChannel(object_id_t objectId, uint8_t vcId, const char* vcName, PtmeIF& ptme,
const std::atomic_bool& txOn)
: SystemObject(objectId), ptme(ptme), vcId(vcId), vcName(vcName), txOn(txOn) {}
ReturnValue_t VirtualChannel::initialize() { return returnvalue::OK; }
ReturnValue_t VirtualChannel::sendNextTm(const uint8_t* data, size_t size) {
return write(data, size);
ReturnValue_t VirtualChannel::sendNextTm(const uint8_t* data, size_t size, size_t& writtenSize) {
return write(data, size, writtenSize);
}
ReturnValue_t VirtualChannel::write(const uint8_t* data, size_t size) {
return ptme.writeToVc(vcId, data, size);
ReturnValue_t VirtualChannel::write(const uint8_t* data, size_t size, size_t& writtenSize) {
if (!ptme.containsVc(vcId)) {
return CHANNEL_DOES_NOT_EXIST;
}
return ptme.getVirtChannel(vcId)->write(data, size, writtenSize);
}
uint8_t VirtualChannel::getVcid() const { return vcId; }
ReturnValue_t VirtualChannel::finishWrite(const uint8_t* data, size_t remainingSize) {
if (!ptme.containsVc(vcId)) {
return CHANNEL_DOES_NOT_EXIST;
}
return ptme.getVirtChannel(vcId)->finishWrite(data, remainingSize);
}
const char* VirtualChannel::getName() const { return vcName.c_str(); }
bool VirtualChannel::isBusy() const { return ptme.isBusy(vcId); }
bool VirtualChannel::isBusy() const {
if (!ptme.containsVc(vcId)) {
return CHANNEL_DOES_NOT_EXIST;
}
return ptme.getVirtChannel(vcId)->isBusy();
}
void VirtualChannel::cancelTransfer() { ptme.cancelTransfer(vcId); }
void VirtualChannel::cancelTransfer() {
if (!ptme.containsVc(vcId)) {
return;
}
ptme.getVirtChannel(vcId)->cancelTransfer();
}
bool VirtualChannel::isTxOn() const { return txOn; }
ReturnValue_t VirtualChannel::handleLastWriteSynchronously(const uint8_t* data, size_t start,
size_t remLen, unsigned maxDelayMs) {
unsigned delayMs = 0;
while (true) {
if (isBusy()) {
if (delayMs >= maxDelayMs) {
break;
}
TaskFactory::delayTask(10);
delayMs += 10;
continue;
}
return finishWrite(data, start);
}
return returnvalue::FAILED;
}

View File

@ -15,6 +15,10 @@
*/
class VirtualChannel : public SystemObject, public VirtualChannelIF {
public:
static constexpr uint8_t CLASS_ID = CLASS_ID::VIRTUAL_CHANNEL;
static constexpr ReturnValue_t CHANNEL_DOES_NOT_EXIST = returnvalue::makeCode(CLASS_ID, 0);
/**
* @brief Constructor
*
@ -25,9 +29,12 @@ class VirtualChannel : public SystemObject, public VirtualChannelIF {
const std::atomic_bool& linkStateProvider);
ReturnValue_t initialize() override;
ReturnValue_t sendNextTm(const uint8_t* data, size_t size);
ReturnValue_t sendNextTm(const uint8_t* data, size_t size, size_t& writtenSize);
bool isBusy() const override;
ReturnValue_t write(const uint8_t* data, size_t size) override;
ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) override;
ReturnValue_t finishWrite(const uint8_t* data, size_t remainingSize) override;
ReturnValue_t handleLastWriteSynchronously(const uint8_t* data, size_t start, size_t remLen,
unsigned maxDelayMs);
void cancelTransfer() override;
uint8_t getVcid() const;
bool isTxOn() const;

View File

@ -36,8 +36,19 @@ ReturnValue_t VirtualChannelWithQueue::handleNextTm(bool performWriteOp) {
return result;
}
// TODO: Hnadle partial write handling
size_t partiallyWrittenSize = 0;
if (performWriteOp) {
result = write(data, size);
result = write(data, size, partiallyWrittenSize);
if (result == PARTIALLY_WRITTEN) {
result = handleLastWriteSynchronously(data, size, partiallyWrittenSize, 20);
if (result != returnvalue::OK) {
// TODO: Event? Might lead to dangerous spam though..
Review

nikolaus

nikolaus
sif::warning
<< "VirtualChannelWithQueue: Synchronous write of last segment failed with code 0x"
<< std::setw(4) << std::hex << result << std::endl;
}
}
}
// Try delete in any case, ignore failures (which should not happen), it is more important to
// propagate write errors.

View File

@ -13,6 +13,7 @@ class DirectTmSinkIF {
static constexpr uint8_t CLASS_ID = CLASS_ID::TM_SINK;
static constexpr ReturnValue_t IS_BUSY = returnvalue::makeCode(CLASS_ID, 0);
static constexpr ReturnValue_t PARTIALLY_WRITTEN = returnvalue::makeCode(CLASS_ID, 1);
/**
* @brief Implements the functionality to write to a TM sink directly
@ -20,9 +21,12 @@ class DirectTmSinkIF {
* @param data Pointer to buffer holding the data to write
* @param size Number of bytes to write
* @return returnvalue::OK on success, returnvalue::FAILED on failure, IS_BUSY
* if the TM sink is busy.
* if the TM sink is busy, PARTIALLY_WRITTEN if only a portion of the bytes could be
* written.
*/
virtual ReturnValue_t write(const uint8_t* data, size_t size) = 0;
virtual ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) = 0;
virtual ReturnValue_t finishWrite(const uint8_t* data, size_t remainingSize) = 0;
virtual bool isBusy() const = 0;
};

2
tmtc

@ -1 +1 @@
Subproject commit e249f147bc1738003d31290df8f2b525d91c3482
Subproject commit 84df438e9d74898cbb3c6319ba55193c0c8d0b0c