CFDP source handler #776
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 313 translations.
|
* @brief Auto-generated event translation file. Contains 313 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-10-11 10:54:39
|
* Generated on: 2023-10-13 09:17:41
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 174 translations.
|
* Contains 174 translations.
|
||||||
* Generated on: 2023-10-11 10:54:39
|
* Generated on: 2023-10-13 09:17:41
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ enum commonClassIds : uint8_t {
|
|||||||
LOCAL_PARAM_HANDLER, // LPH
|
LOCAL_PARAM_HANDLER, // LPH
|
||||||
PERSISTENT_TM_STORE, // PTM
|
PERSISTENT_TM_STORE, // PTM
|
||||||
TM_SINK, // TMS
|
TM_SINK, // TMS
|
||||||
|
VIRTUAL_CHANNEL, // VCS
|
||||||
COMMON_CLASS_ID_END // [EXPORT] : [END]
|
COMMON_CLASS_ID_END // [EXPORT] : [END]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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
|
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
|
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
|
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
|
||||||
|
|
@ -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
|
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
|
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
|
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,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 313 translations.
|
* @brief Auto-generated event translation file. Contains 313 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-10-11 10:54:39
|
* Generated on: 2023-10-13 09:17:41
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 178 translations.
|
* Contains 178 translations.
|
||||||
* Generated on: 2023-10-11 10:54:39
|
* Generated on: 2023-10-13 09:17:41
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 313 translations.
|
* @brief Auto-generated event translation file. Contains 313 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-10-11 10:54:39
|
* Generated on: 2023-10-13 09:17:41
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 178 translations.
|
* Contains 178 translations.
|
||||||
* Generated on: 2023-10-11 10:54:39
|
* Generated on: 2023-10-13 09:17:41
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ ReturnValue_t PapbVcInterface::initialize() {
|
|||||||
return returnvalue::OK;
|
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.
|
// There are no packets smaller than 4, this is considered a configuration error.
|
||||||
if (size < 4) {
|
if (size < 4) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
@ -37,19 +37,7 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
|
|||||||
abortPacketTransfer();
|
abortPacketTransfer();
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
for (size_t idx = 0; idx < size; idx++) {
|
return finishWritePartialOpt(data, size, true);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) {
|
void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) {
|
||||||
@ -65,6 +53,26 @@ bool PapbVcInterface::pollReadyForPacket() const {
|
|||||||
return (reg >> 6) & 0b1;
|
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() {
|
bool PapbVcInterface::isVcInterfaceBufferEmpty() {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
gpio::Levels papbEmptyState = gpio::Levels::HIGH;
|
gpio::Levels papbEmptyState = gpio::Levels::HIGH;
|
||||||
@ -101,21 +109,8 @@ inline bool PapbVcInterface::pollReadyForOctet(uint32_t maxCycles) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PapbVcInterface::sendTestFrame() {
|
ReturnValue_t PapbVcInterface::finishWrite(const uint8_t* data, size_t remainingSize) {
|
||||||
/** Size of one complete transfer frame data field amounts to 1105 bytes */
|
return finishWritePartialOpt(data, remainingSize, false);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PapbVcInterface::abortPacketTransfer() { *vcBaseReg = CONFIG_ABORT; }
|
void PapbVcInterface::abortPacketTransfer() { *vcBaseReg = CONFIG_ABORT; }
|
||||||
|
@ -40,7 +40,11 @@ class PapbVcInterface : public VirtualChannelIF {
|
|||||||
* @param size
|
* @param size
|
||||||
* @return returnvalue::OK on successfull write, PAPB_BUSY if PAPB is busy.
|
* @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;
|
void cancelTransfer() override;
|
||||||
|
|
||||||
@ -126,12 +130,6 @@ class PapbVcInterface : public VirtualChannelIF {
|
|||||||
* the packet buffer of the virtual channel or not.
|
* the packet buffer of the virtual channel or not.
|
||||||
*/
|
*/
|
||||||
bool isVcInterfaceBufferEmpty();
|
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_ */
|
#endif /* LINUX_OBC_PAPBVCINTERFACE_H_ */
|
||||||
|
@ -19,15 +19,12 @@ ReturnValue_t Ptme::initialize() {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) {
|
bool Ptme::containsVc(uint8_t vcId) const {
|
||||||
VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId);
|
auto channelIter = vcInterfaceMap.find(vcId);
|
||||||
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
|
if (channelIter == vcInterfaceMap.end()) {
|
||||||
sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual "
|
return false;
|
||||||
"channel with id "
|
|
||||||
<< static_cast<unsigned int>(vcId) << std::endl;
|
|
||||||
return UNKNOWN_VC_ID;
|
|
||||||
}
|
}
|
||||||
return vcInterfaceMapIter->second->write(data, size);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ptme::addVcInterface(VcId_t vcId, VirtualChannelIF* vc) {
|
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 {
|
VirtualChannelIF* Ptme::getVirtChannel(uint8_t vcId) {
|
||||||
const auto& vcInterfaceMapIter = vcInterfaceMap.find(vcId);
|
auto channelIter = vcInterfaceMap.find(vcId);
|
||||||
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
|
if (channelIter == vcInterfaceMap.end()) {
|
||||||
sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual "
|
return nullptr;
|
||||||
"channel with id "
|
|
||||||
<< static_cast<unsigned int>(vcId) << std::endl;
|
|
||||||
return UNKNOWN_VC_ID;
|
|
||||||
}
|
}
|
||||||
return vcInterfaceMapIter->second->isBusy();
|
return channelIter->second;
|
||||||
}
|
|
||||||
|
|
||||||
void Ptme::cancelTransfer(uint8_t vcId) {
|
|
||||||
VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId);
|
|
||||||
if (vcInterfaceMapIter == vcInterfaceMap.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return vcInterfaceMapIter->second->cancelTransfer();
|
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,8 @@ class Ptme : public PtmeIF, public SystemObject {
|
|||||||
virtual ~Ptme();
|
virtual ~Ptme();
|
||||||
|
|
||||||
ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) override;
|
bool containsVc(uint8_t vcId) const override;
|
||||||
bool isBusy(uint8_t vcId) const override;
|
VirtualChannelIF* getVirtChannel(uint8_t vcId) override;
|
||||||
void cancelTransfer(uint8_t vcId) override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function adds the reference to a virtual channel interface to the vcInterface
|
* @brief This function adds the reference to a virtual channel interface to the vcInterface
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef LINUX_OBC_PTMEIF_H_
|
#ifndef LINUX_OBC_PTMEIF_H_
|
||||||
#define LINUX_OBC_PTMEIF_H_
|
#define LINUX_OBC_PTMEIF_H_
|
||||||
|
|
||||||
|
#include <linux/ipcore/VirtualChannelIF.h>
|
||||||
|
|
||||||
#include "fsfw/returnvalues/returnvalue.h"
|
#include "fsfw/returnvalues/returnvalue.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,16 +16,8 @@ class PtmeIF {
|
|||||||
public:
|
public:
|
||||||
virtual ~PtmeIF(){};
|
virtual ~PtmeIF(){};
|
||||||
|
|
||||||
/**
|
virtual bool containsVc(uint8_t vcId) const = 0;
|
||||||
* @brief Implements to function to write to a specific virtual channel.
|
virtual VirtualChannelIF* getVirtChannel(uint8_t vcId) = 0;
|
||||||
*
|
|
||||||
* @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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* LINUX_OBC_PTMEIF_H_ */
|
#endif /* LINUX_OBC_PTMEIF_H_ */
|
||||||
|
@ -138,8 +138,17 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
dumpedLen = tmReader.getFullPacketLen();
|
dumpedLen = tmReader.getFullPacketLen();
|
||||||
result = channel.write(tmReader.getFullData(), dumpedLen);
|
size_t partiallyWrittenSize = 0;
|
||||||
if (result == DirectTmSinkIF::IS_BUSY) {
|
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) {
|
||||||
|
|||||||
|
// 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;
|
sif::warning << "PersistentTmStore: Unexpected VC channel busy" << std::endl;
|
||||||
} else if (result != returnvalue::OK) {
|
} else if (result != returnvalue::OK) {
|
||||||
sif::warning << "PersistentTmStore: Unexpected VC channel write failure" << std::endl;
|
sif::warning << "PersistentTmStore: Unexpected VC channel write failure" << std::endl;
|
||||||
|
@ -1,25 +1,64 @@
|
|||||||
#include "VirtualChannel.h"
|
#include "VirtualChannel.h"
|
||||||
|
|
||||||
|
#include <fsfw/tasks/TaskFactory.h>
|
||||||
|
|
||||||
VirtualChannel::VirtualChannel(object_id_t objectId, uint8_t vcId, const char* vcName, PtmeIF& ptme,
|
VirtualChannel::VirtualChannel(object_id_t objectId, uint8_t vcId, const char* vcName, PtmeIF& ptme,
|
||||||
const std::atomic_bool& txOn)
|
const std::atomic_bool& txOn)
|
||||||
: SystemObject(objectId), ptme(ptme), vcId(vcId), vcName(vcName), txOn(txOn) {}
|
: SystemObject(objectId), ptme(ptme), vcId(vcId), vcName(vcName), txOn(txOn) {}
|
||||||
|
|
||||||
ReturnValue_t VirtualChannel::initialize() { return returnvalue::OK; }
|
ReturnValue_t VirtualChannel::initialize() { return returnvalue::OK; }
|
||||||
|
|
||||||
ReturnValue_t VirtualChannel::sendNextTm(const uint8_t* data, size_t size) {
|
ReturnValue_t VirtualChannel::sendNextTm(const uint8_t* data, size_t size, size_t& writtenSize) {
|
||||||
return write(data, size);
|
return write(data, size, writtenSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t VirtualChannel::write(const uint8_t* data, size_t size) {
|
ReturnValue_t VirtualChannel::write(const uint8_t* data, size_t size, size_t& writtenSize) {
|
||||||
return ptme.writeToVc(vcId, data, size);
|
if (!ptme.containsVc(vcId)) {
|
||||||
|
return CHANNEL_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
|
return ptme.getVirtChannel(vcId)->write(data, size, writtenSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t VirtualChannel::getVcid() const { return vcId; }
|
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(); }
|
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; }
|
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;
|
||||||
|
}
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
class VirtualChannel : public SystemObject, public VirtualChannelIF {
|
class VirtualChannel : public SystemObject, public VirtualChannelIF {
|
||||||
public:
|
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
|
* @brief Constructor
|
||||||
*
|
*
|
||||||
@ -25,9 +29,12 @@ class VirtualChannel : public SystemObject, public VirtualChannelIF {
|
|||||||
const std::atomic_bool& linkStateProvider);
|
const std::atomic_bool& linkStateProvider);
|
||||||
|
|
||||||
ReturnValue_t initialize() override;
|
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;
|
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;
|
void cancelTransfer() override;
|
||||||
uint8_t getVcid() const;
|
uint8_t getVcid() const;
|
||||||
bool isTxOn() const;
|
bool isTxOn() const;
|
||||||
|
@ -36,8 +36,19 @@ ReturnValue_t VirtualChannelWithQueue::handleNextTm(bool performWriteOp) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Hnadle partial write handling
|
||||||
|
size_t partiallyWrittenSize = 0;
|
||||||
if (performWriteOp) {
|
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..
|
||||||
meggert
commented
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
|
// Try delete in any case, ignore failures (which should not happen), it is more important to
|
||||||
// propagate write errors.
|
// propagate write errors.
|
||||||
|
@ -13,6 +13,7 @@ class DirectTmSinkIF {
|
|||||||
static constexpr uint8_t CLASS_ID = CLASS_ID::TM_SINK;
|
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 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
|
* @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 data Pointer to buffer holding the data to write
|
||||||
* @param size Number of bytes to write
|
* @param size Number of bytes to write
|
||||||
* @return returnvalue::OK on success, returnvalue::FAILED on failure, IS_BUSY
|
* @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;
|
virtual bool isBusy() const = 0;
|
||||||
};
|
};
|
||||||
|
2
tmtc
2
tmtc
@ -1 +1 @@
|
|||||||
Subproject commit e249f147bc1738003d31290df8f2b525d91c3482
|
Subproject commit 84df438e9d74898cbb3c6319ba55193c0c8d0b0c
|
Loading…
Reference in New Issue
Block a user
vom