From caa7c20adf03443e5aaded9b15091ff93d54392c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 31 Mar 2023 15:12:05 +0200 Subject: [PATCH] tweaks --- linux/ipcore/PapbVcInterface.cpp | 30 ++++++++++++--------- linux/ipcore/PapbVcInterface.h | 4 +-- mission/com/PersistentSingleTmStoreTask.cpp | 3 +++ mission/com/TmStoreTaskBase.cpp | 3 ++- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp index 446e3afd..c0deb5fc 100644 --- a/linux/ipcore/PapbVcInterface.cpp +++ b/linux/ipcore/PapbVcInterface.cpp @@ -27,27 +27,27 @@ ReturnValue_t PapbVcInterface::initialize() { } ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) { - if (pollPapbBusySignal(0) == returnvalue::OK) { + if (pollInterfaceReadiness(0, true) == returnvalue::OK) { startPacketTransfer(); } else { return DirectTmSinkIF::IS_BUSY; } for (size_t idx = 0; idx < size; idx++) { // This delay is super-important, DO NOT REMOVE! - // Polling the GPIO too often can mess up the scheduler. + // Polling the GPIO or the config register too often messes up the scheduler. // TODO: Maybe this should not be done like this. It would be better if there was a custom // FPGA module which can accept packets and then takes care of dumping that packet into // the PTME. DMA would be an ideal solution for this. - // nanosleep(&BETWEEN_POLL_DELAY, &remDelay); - if (pollPapbBusySignal(2) == returnvalue::OK) { + nanosleep(&BETWEEN_POLL_DELAY, &remDelay); + if (pollInterfaceReadiness(2, false) == returnvalue::OK) { *(vcBaseReg + DATA_REG_OFFSET) = static_cast(data[idx]); } else { abortPacketTransfer(); return returnvalue::FAILED; } } - // nanosleep(&BETWEEN_POLL_DELAY, &remDelay); - if (pollPapbBusySignal(2) == returnvalue::OK) { + nanosleep(&BETWEEN_POLL_DELAY, &remDelay); + if (pollInterfaceReadiness(2, false) == returnvalue::OK) { completePacketTransfer(); } else { abortPacketTransfer(); @@ -60,17 +60,23 @@ void PapbVcInterface::startPacketTransfer() { *vcBaseReg = CONFIG_START; } void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; } -ReturnValue_t PapbVcInterface::pollPapbBusySignal(uint32_t maxPollRetries) const { +ReturnValue_t PapbVcInterface::pollInterfaceReadiness(uint32_t maxPollRetries, + bool checkReadyState) const { uint32_t busyIdx = 0; - nextDelay.tv_nsec = 0; + nextDelay.tv_nsec = FIRST_NON_NULL_DELAY_NS; while (true) { // Check if PAPB interface is ready to receive data. Use the configuration register for this. // Bit 5, see PTME ptme_001_01-0-7-r2 Table 31. - bool busy = ((*vcBaseReg) >> 5) & 0b1; + uint32_t reg = *vcBaseReg; + bool busy = (reg >> 5) & 0b1; + bool ready = (reg >> 6) & 0b1; if (not busy) { return returnvalue::OK; } + if(checkReadyState and not ready) { + return PAPB_BUSY; + } busyIdx++; if (busyIdx >= maxPollRetries) { @@ -80,9 +86,7 @@ ReturnValue_t PapbVcInterface::pollPapbBusySignal(uint32_t maxPollRetries) const // Ignore signal handling here for now. nanosleep(&nextDelay, &remDelay); // Adaptive delay. - if (nextDelay.tv_nsec == 0) { - nextDelay.tv_nsec = FIRST_NON_NULL_DELAY_NS; - } else if (nextDelay.tv_nsec * 2 <= MAX_DELAY_PAPB_POLLING_NS) { + if (nextDelay.tv_nsec * 2 <= MAX_DELAY_PAPB_POLLING_NS) { nextDelay.tv_nsec *= 2; } } @@ -109,7 +113,7 @@ void PapbVcInterface::isVcInterfaceBufferEmpty() { return; } -bool PapbVcInterface::isBusy() const { return pollPapbBusySignal(0) == PAPB_BUSY; } +bool PapbVcInterface::isBusy() const { return pollInterfaceReadiness(0, true) == PAPB_BUSY; } void PapbVcInterface::cancelTransfer() { abortPacketTransfer(); } diff --git a/linux/ipcore/PapbVcInterface.h b/linux/ipcore/PapbVcInterface.h index 22b8ee5f..42cfbc19 100644 --- a/linux/ipcore/PapbVcInterface.h +++ b/linux/ipcore/PapbVcInterface.h @@ -91,7 +91,7 @@ class PapbVcInterface : public VirtualChannelIF { std::string uioFile; int mapNum = 0; mutable struct timespec nextDelay = {.tv_sec = 0, .tv_nsec = 0}; - const struct timespec BETWEEN_POLL_DELAY = {.tv_sec = 0, .tv_nsec = 5}; + const struct timespec BETWEEN_POLL_DELAY = {.tv_sec = 0, .tv_nsec = 10}; mutable struct timespec remDelay; volatile uint32_t* vcBaseReg = nullptr; @@ -119,7 +119,7 @@ class PapbVcInterface : public VirtualChannelIF { * * @return returnvalue::OK when ready to receive data else PAPB_BUSY. */ - inline ReturnValue_t pollPapbBusySignal(uint32_t maxPollRetries) const; + inline ReturnValue_t pollInterfaceReadiness(uint32_t maxPollRetries, bool checkReadyState) const; /** * @brief This function can be used for debugging to check whether there are packets in diff --git a/mission/com/PersistentSingleTmStoreTask.cpp b/mission/com/PersistentSingleTmStoreTask.cpp index 2d05b25f..421f2a74 100644 --- a/mission/com/PersistentSingleTmStoreTask.cpp +++ b/mission/com/PersistentSingleTmStoreTask.cpp @@ -25,6 +25,9 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) { } else if (dumpContext.vcBusyDuringDump) { // TODO: Might not be necessary TaskFactory::delayTask(10); + } else { + // TODO: Would be best to remove this, but not delaying here can lead to evil issues. + TaskFactory::delayTask(2); } } } diff --git a/mission/com/TmStoreTaskBase.cpp b/mission/com/TmStoreTaskBase.cpp index 91555f04..d6db4095 100644 --- a/mission/com/TmStoreTaskBase.cpp +++ b/mission/com/TmStoreTaskBase.cpp @@ -142,11 +142,12 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store, dumpDoneHandler(); return returnvalue::OK; } + dumpedLen = tmReader.getFullPacketLen(); // Only write to VC if mode is on, but always confirm the dump. // If the mode is OFF, it is assumed the PTME is not usable and is not allowed to be written // (e.g. to confirm a reset or the transmitter is off anyway). if (mode == MODE_ON) { - result = channel.write(tmReader.getFullData(), tmReader.getFullPacketLen()); + result = channel.write(tmReader.getFullData(), dumpedLen); if (result == DirectTmSinkIF::IS_BUSY) { sif::warning << "PersistentTmStore: Unexpected VC channel busy" << std::endl; } else if (result != returnvalue::OK) {