more bugfixes
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
EIVE/eive-obsw/pipeline/head This commit looks good

This commit is contained in:
Robin Müller 2023-10-13 09:39:50 +02:00
parent 7c42e05c23
commit 8dbc5cad48
Signed by: muellerr
GPG Key ID: A649FB78196E3849
6 changed files with 37 additions and 14 deletions

View File

@ -16,6 +16,14 @@ will consitute of a breaking change warranting a new major release:
# [unreleased] # [unreleased]
## Fixed
- If the PTME is driven in a way where it fills faster than it can be emptied, the interface
can become full during the process of a regular packet write. The interface of the PAPB VC
component was adapted to account for this partial success state. The caller must now check
for the `PARTIALLY_WRITTEN` state and must take care of finishing a write in some shape or
form before starting the next packet transfer.
# [v7.1.0] 2023-10-11 # [v7.1.0] 2023-10-11
- Bumped `eive-tmtc` to v5.8.0. - Bumped `eive-tmtc` to v5.8.0.

View File

@ -28,6 +28,10 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size, size_t& w
if (size < 4) { if (size < 4) {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
// The user must call finishWrite before starting a new packet transfer.
if (partialWriteActive) {
return INCOMPLETE_PARTIAL_WRITE;
}
if (pollReadyForPacket()) { if (pollReadyForPacket()) {
startPacketTransfer(ByteWidthCfg::ONE); startPacketTransfer(ByteWidthCfg::ONE);
} else { } else {
@ -37,7 +41,7 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size, size_t& w
abortPacketTransfer(); abortPacketTransfer();
return returnvalue::FAILED; return returnvalue::FAILED;
} }
return finishWriteInternal(data, size, writtenSize); return finishWriteInternal(data, 0, size, writtenSize, false);
} }
void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) { void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) {
@ -53,26 +57,34 @@ bool PapbVcInterface::pollReadyForPacket() const {
return (reg >> 6) & 0b1; return (reg >> 6) & 0b1;
} }
ReturnValue_t PapbVcInterface::finishWrite(const uint8_t* data, size_t remainingSize) { ReturnValue_t PapbVcInterface::finishWrite(const uint8_t* data, size_t start,
size_t remainingSize) {
if (not pollReadyForPacket()) { if (not pollReadyForPacket()) {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
size_t dummy = 0; size_t dummy = 0;
return finishWriteInternal(data, remainingSize, dummy); return finishWriteInternal(data, start, remainingSize, dummy, true);
} }
ReturnValue_t PapbVcInterface::finishWriteInternal(const uint8_t* data, size_t remainingSize, ReturnValue_t PapbVcInterface::finishWriteInternal(const uint8_t* data, size_t start,
size_t& writtenSize) { size_t remainingSize, size_t& writtenSize,
bool abortOnPartialWrite) {
for (size_t idx = 0; idx < remainingSize; idx++) { for (size_t idx = 0; idx < remainingSize; idx++) {
if (not pollReadyForOctet(MAX_BUSY_POLLS)) { if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
if (not pollReadyForPacket()) { if (not pollReadyForPacket()) {
writtenSize = idx; writtenSize = start + idx;
partialWriteActive = true;
if (abortOnPartialWrite) {
abortPacketTransfer();
partialWriteActive = false;
return returnvalue::FAILED;
}
return PARTIALLY_WRITTEN; return PARTIALLY_WRITTEN;
} }
abortPacketTransfer(); abortPacketTransfer();
return returnvalue::FAILED; return returnvalue::FAILED;
} }
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]); *(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[start + idx]);
} }
if (not pollReadyForOctet(MAX_BUSY_POLLS)) { if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer(); abortPacketTransfer();

View File

@ -42,8 +42,9 @@ class PapbVcInterface : public VirtualChannelIF {
*/ */
ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) 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 finishWrite(const uint8_t* data, size_t start, size_t remainingSize) override;
ReturnValue_t finishWriteInternal(const uint8_t* data, size_t remainingSize, size_t& writtenSize); ReturnValue_t finishWriteInternal(const uint8_t* data, size_t start, size_t remainingSize,
size_t& writtenSize, bool abortOnPartialWrite);
void cancelTransfer() override; void cancelTransfer() override;
@ -91,6 +92,7 @@ class PapbVcInterface : public VirtualChannelIF {
std::string uioFile; std::string uioFile;
int mapNum = 0; int mapNum = 0;
bool partialWriteActive = false;
mutable struct timespec nextDelay = {.tv_sec = 0, .tv_nsec = 0}; mutable struct timespec nextDelay = {.tv_sec = 0, .tv_nsec = 0};
const struct timespec BETWEEN_POLL_DELAY = {.tv_sec = 0, .tv_nsec = 10}; const struct timespec BETWEEN_POLL_DELAY = {.tv_sec = 0, .tv_nsec = 10};
mutable struct timespec remDelay; mutable struct timespec remDelay;

View File

@ -21,11 +21,11 @@ ReturnValue_t VirtualChannel::write(const uint8_t* data, size_t size, size_t& wr
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) { ReturnValue_t VirtualChannel::finishWrite(const uint8_t* data, size_t start, size_t remainingSize) {
if (!ptme.containsVc(vcId)) { if (!ptme.containsVc(vcId)) {
return CHANNEL_DOES_NOT_EXIST; return CHANNEL_DOES_NOT_EXIST;
} }
return ptme.getVirtChannel(vcId)->finishWrite(data, remainingSize); return ptme.getVirtChannel(vcId)->finishWrite(data, start, remainingSize);
} }
const char* VirtualChannel::getName() const { return vcName.c_str(); } const char* VirtualChannel::getName() const { return vcName.c_str(); }
@ -58,7 +58,7 @@ ReturnValue_t VirtualChannel::handleLastWriteSynchronously(const uint8_t* data,
delayMs += 10; delayMs += 10;
continue; continue;
} }
return finishWrite(data, start); return finishWrite(data, start, remLen);
} }
return returnvalue::FAILED; return returnvalue::FAILED;
} }

View File

@ -32,7 +32,7 @@ class VirtualChannel : public SystemObject, public VirtualChannelIF {
ReturnValue_t sendNextTm(const uint8_t* data, size_t size, size_t& writtenSize); 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, size_t& writtenSize) 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 finishWrite(const uint8_t* data, size_t start, size_t remainingSize) override;
ReturnValue_t handleLastWriteSynchronously(const uint8_t* data, size_t start, size_t remLen, ReturnValue_t handleLastWriteSynchronously(const uint8_t* data, size_t start, size_t remLen,
unsigned maxDelayMs); unsigned maxDelayMs);
void cancelTransfer() override; void cancelTransfer() override;

View File

@ -14,6 +14,7 @@ class DirectTmSinkIF {
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); static constexpr ReturnValue_t PARTIALLY_WRITTEN = returnvalue::makeCode(CLASS_ID, 1);
static constexpr ReturnValue_t INCOMPLETE_PARTIAL_WRITE = returnvalue::makeCode(CLASS_ID, 2);
/** /**
* @brief Implements the functionality to write to a TM sink directly * @brief Implements the functionality to write to a TM sink directly
@ -26,7 +27,7 @@ class DirectTmSinkIF {
*/ */
virtual ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) = 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 ReturnValue_t finishWrite(const uint8_t* data, size_t start, size_t remainingSize) = 0;
virtual bool isBusy() const = 0; virtual bool isBusy() const = 0;
}; };