From 7df1922633061419f0a66c03e34ad16d4db7457d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 14 May 2022 09:38:59 +0200 Subject: [PATCH 1/9] refactor task IF --- hal/src/fsfw_hal/linux/CommandExecutor.cpp | 2 + hal/src/fsfw_hal/linux/spi/SpiComIF.cpp | 27 ++++++++++-- hal/src/fsfw_hal/linux/spi/SpiComIF.h | 30 +++++++++++--- src/fsfw/osal/linux/FixedTimeslotTask.cpp | 4 +- src/fsfw/osal/linux/FixedTimeslotTask.h | 13 +++--- src/fsfw/osal/linux/PeriodicPosixTask.cpp | 41 +++++++++++++++---- src/fsfw/osal/linux/PeriodicPosixTask.h | 14 +++++-- src/fsfw/tasks/FixedSlotSequence.cpp | 2 + src/fsfw/tasks/FixedSlotSequence.h | 2 + src/fsfw/tasks/FixedTimeslotTaskIF.h | 2 +- src/fsfw/tasks/PeriodicTaskIF.h | 6 ++- .../unit/power/testPowerSwitcher.cpp | 4 +- 12 files changed, 114 insertions(+), 33 deletions(-) diff --git a/hal/src/fsfw_hal/linux/CommandExecutor.cpp b/hal/src/fsfw_hal/linux/CommandExecutor.cpp index 49c44ebf..dcdd10ee 100644 --- a/hal/src/fsfw_hal/linux/CommandExecutor.cpp +++ b/hal/src/fsfw_hal/linux/CommandExecutor.cpp @@ -205,3 +205,5 @@ ReturnValue_t CommandExecutor::executeBlocking() { } return HasReturnvaluesIF::RETURN_OK; } + +const std::vector& CommandExecutor::getReadVector() const { return readVec; } diff --git a/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp b/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp index dcf92b5d..3c257f1f 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp +++ b/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp @@ -401,12 +401,33 @@ void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed) if (retval != 0) { utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed"); } - // This updates the SPI clock default polarity. Only setting the mode does not update - // the line state, which can be an issue on mode switches because the clock line will - // switch the state after the chip select is pulled low +} + +void SpiComIF::getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const { + uint8_t tmpMode = 0; + int retval = ioctl(spiFd, SPI_IOC_RD_MODE, &tmpMode); + if (retval != 0) { + utility::handleIoctlError("SpiComIF::getSpiSpeedAndMode: Reading SPI mode failed"); + } + mode = static_cast(tmpMode); + + retval = ioctl(spiFd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); + if (retval != 0) { + utility::handleIoctlError("SpiComIF::getSpiSpeedAndMode: Getting SPI speed failed"); + } +} + +const std::string& SpiComIF::getSpiDev() const { return dev; } + +void SpiComIF::updateLinePolarity(int spiFd) { clockUpdateTransfer.len = 0; retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer); if (retval != 0) { utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed"); } } + +void SpiComIF::setMutexParams(MutexIF::TimeoutType timeoutType_, uint32_t timeoutMs_) { + timeoutType = timeoutType_; + timeoutMs = timeoutMs_; +} diff --git a/hal/src/fsfw_hal/linux/spi/SpiComIF.h b/hal/src/fsfw_hal/linux/spi/SpiComIF.h index 357afa2f..1400dcfc 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiComIF.h +++ b/hal/src/fsfw_hal/linux/spi/SpiComIF.h @@ -22,15 +22,17 @@ class SpiCookie; */ class SpiComIF : public DeviceCommunicationIF, public SystemObject { public: - static constexpr uint8_t spiRetvalId = CLASS_ID::HAL_SPI; + static constexpr dur_millis_t DEFAULT_MUTEX_TIMEOUT = 20; + + static constexpr uint8_t CLASS_ID = CLASS_ID::HAL_SPI; static constexpr ReturnValue_t OPENING_FILE_FAILED = - HasReturnvaluesIF::makeReturnCode(spiRetvalId, 0); + HasReturnvaluesIF::makeReturnCode(CLASS_ID, 0); /* Full duplex (ioctl) transfer failure */ static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED = - HasReturnvaluesIF::makeReturnCode(spiRetvalId, 1); + HasReturnvaluesIF::makeReturnCode(CLASS_ID, 1); /* Half duplex (read/write) transfer failure */ static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED = - HasReturnvaluesIF::makeReturnCode(spiRetvalId, 2); + HasReturnvaluesIF::makeReturnCode(CLASS_ID, 2); SpiComIF(object_id_t objectId, GpioIF* gpioComIF); @@ -45,6 +47,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject { * the chip select must be driven from outside of the com if. */ MutexIF* getMutex(MutexIF::TimeoutType* timeoutType = nullptr, uint32_t* timeoutMs = nullptr); + void setMutexParams(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs); /** * Perform a regular send operation using Linux iotcl. This is public so it can be used @@ -59,6 +62,23 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject { GpioIF* getGpioInterface(); void setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed); +<<<<<<< Updated upstream +======= + void getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const; + + /** + * This updates the SPI clock default polarity. Only setting the mode does not update + * the line state, which can be an issue on mode switches because the clock line will + * switch the state after the chip select is pulled low. + * + * It is recommended to call this function after #setSpiSpeedAndMode and after locking the + * CS mutex if the SPI bus has multiple SPI devices with different speed and SPI modes attached. + * @param spiFd + */ + void updateLinePolarity(int spiFd); + + const std::string& getSpiDev() const; +>>>>>>> Stashed changes void performSpiWiretapping(SpiCookie* spiCookie); ReturnValue_t getReadBuffer(address_t spiAddress, uint8_t** buffer); @@ -73,7 +93,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject { MutexIF* spiMutex = nullptr; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; - uint32_t timeoutMs = 20; + uint32_t timeoutMs = DEFAULT_MUTEX_TIMEOUT; spi_ioc_transfer clockUpdateTransfer = {}; using SpiDeviceMap = std::unordered_map; diff --git a/src/fsfw/osal/linux/FixedTimeslotTask.cpp b/src/fsfw/osal/linux/FixedTimeslotTask.cpp index 1f4d6e23..d1fccdf9 100644 --- a/src/fsfw/osal/linux/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/linux/FixedTimeslotTask.cpp @@ -14,6 +14,8 @@ FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, size_t st FixedTimeslotTask::~FixedTimeslotTask() {} +bool FixedTimeslotTask::isEmpty() const { return pst.isEmpty(); } + void* FixedTimeslotTask::taskEntryPoint(void* arg) { // The argument is re-interpreted as PollingTask. FixedTimeslotTask* originalTask(reinterpret_cast(arg)); @@ -50,7 +52,7 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotT return HasReturnvaluesIF::RETURN_FAILED; } -ReturnValue_t FixedTimeslotTask::checkSequence() const { return pst.checkSequence(); } +ReturnValue_t FixedTimeslotTask::checkSequence() { return pst.checkSequence(); } void FixedTimeslotTask::taskFunctionality() { // Like FreeRTOS pthreads are running as soon as they are created diff --git a/src/fsfw/osal/linux/FixedTimeslotTask.h b/src/fsfw/osal/linux/FixedTimeslotTask.h index 76b92db3..a5dc9032 100644 --- a/src/fsfw/osal/linux/FixedTimeslotTask.h +++ b/src/fsfw/osal/linux/FixedTimeslotTask.h @@ -24,15 +24,18 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread { FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, uint32_t periodMs_); virtual ~FixedTimeslotTask(); - virtual ReturnValue_t startTask(); + ReturnValue_t startTask() override; - virtual ReturnValue_t sleepFor(uint32_t ms); + ReturnValue_t sleepFor(uint32_t ms) override; - virtual uint32_t getPeriodMs() const; + uint32_t getPeriodMs() const override; - virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep); + ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep) override; - virtual ReturnValue_t checkSequence() const; + ReturnValue_t checkSequence() override; + + bool isEmpty() const override; /** * This static function can be used as #deadlineMissedFunc. diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.cpp b/src/fsfw/osal/linux/PeriodicPosixTask.cpp index e1937df4..26b6f53e 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.cpp +++ b/src/fsfw/osal/linux/PeriodicPosixTask.cpp @@ -26,12 +26,12 @@ void* PeriodicPosixTask::taskEntryPoint(void* arg) { return NULL; } -ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) { +ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object, uint8_t opCode) { ExecutableObjectIF* newObject = ObjectManager::instance()->get(object); - return addComponent(newObject); + return addComponent(newObject, opCode); } -ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object) { +ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object, uint8_t opCode) { if (object == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" @@ -43,7 +43,7 @@ ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object) { #endif return HasReturnvaluesIF::RETURN_FAILED; } - objectList.push_back(object); + objectList.emplace(object, opCode); object->setTaskIF(this); return HasReturnvaluesIF::RETURN_OK; @@ -54,6 +54,9 @@ ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) { } ReturnValue_t PeriodicPosixTask::startTask(void) { + if (isEmpty()) { + return HasReturnvaluesIF::RETURN_FAILED; + } started = true; PosixThread::createTask(&taskEntryPoint, this); return HasReturnvaluesIF::RETURN_OK; @@ -64,15 +67,13 @@ void PeriodicPosixTask::taskFunctionality(void) { suspend(); } - for (auto const& object : objectList) { - object->initializeAfterTaskCreation(); - } + initObjsAfterTaskCreation(); uint64_t lastWakeTime = getCurrentMonotonicTimeMs(); // The task's "infinite" inner loop is entered. while (1) { - for (auto const& object : objectList) { - object->performOperation(); + for (auto const& objOpCodePair : objectList) { + objOpCodePair.first->performOperation(objOpCodePair.second); } if (not PosixThread::delayUntil(&lastWakeTime, periodMs)) { @@ -84,3 +85,25 @@ void PeriodicPosixTask::taskFunctionality(void) { } uint32_t PeriodicPosixTask::getPeriodMs() const { return periodMs; } + +bool PeriodicPosixTask::isEmpty() const { return objectList.empty(); } + +ReturnValue_t PeriodicPosixTask::initObjsAfterTaskCreation() { + std::multiset uniqueObjects; + ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; + uint32_t count = 0; + for (const auto& obj : objectList) { + // Ensure that each unique object is initialized once. + if (uniqueObjects.find(obj.first) == uniqueObjects.end()) { + ReturnValue_t result = obj.first->initializeAfterTaskCreation(); + if (result != HasReturnvaluesIF::RETURN_OK) { + count++; + status = result; + } + uniqueObjects.emplace(obj.first); + } + } + if (count > 0) { + } + return status; +} diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.h b/src/fsfw/osal/linux/PeriodicPosixTask.h index 3cd9847a..1142c854 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.h +++ b/src/fsfw/osal/linux/PeriodicPosixTask.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ #define FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ -#include +#include #include "../../objectmanager/ObjectManagerIF.h" #include "../../tasks/ExecutableObjectIF.h" @@ -40,7 +40,7 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { * @param object Id of the object to add. * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. */ - ReturnValue_t addComponent(object_id_t object) override; + ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override; /** * Adds an object to the list of objects to be executed. @@ -48,14 +48,20 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { * @param object pointer to the object to add. * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. */ - ReturnValue_t addComponent(ExecutableObjectIF* object) override; + ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override; uint32_t getPeriodMs() const override; ReturnValue_t sleepFor(uint32_t ms) override; + ReturnValue_t initObjsAfterTaskCreation(); + + bool isEmpty() const override; + private: - typedef std::vector ObjectList; //!< Typedef for the List of objects. + //! Typedef for the List of objects. Will contain the objects to execute and their respective + //! op codes + using ObjectList = std::multiset>; /** * @brief This attribute holds a list of objects to be executed. */ diff --git a/src/fsfw/tasks/FixedSlotSequence.cpp b/src/fsfw/tasks/FixedSlotSequence.cpp index d4c67b4d..62c0e99c 100644 --- a/src/fsfw/tasks/FixedSlotSequence.cpp +++ b/src/fsfw/tasks/FixedSlotSequence.cpp @@ -164,3 +164,5 @@ ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { void FixedSlotSequence::addCustomCheck(ReturnValue_t (*customCheckFunction)(const SlotList&)) { this->customCheckFunction = customCheckFunction; } + +bool FixedSlotSequence::isEmpty() const { return slotList.empty(); } diff --git a/src/fsfw/tasks/FixedSlotSequence.h b/src/fsfw/tasks/FixedSlotSequence.h index a287c5b2..5ece7126 100644 --- a/src/fsfw/tasks/FixedSlotSequence.h +++ b/src/fsfw/tasks/FixedSlotSequence.h @@ -159,6 +159,8 @@ class FixedSlotSequence { */ ReturnValue_t intializeSequenceAfterTaskCreation() const; + bool isEmpty() const; + protected: /** * @brief This list contains all PollingSlot objects, defining order and diff --git a/src/fsfw/tasks/FixedTimeslotTaskIF.h b/src/fsfw/tasks/FixedTimeslotTaskIF.h index 497db245..9d85ac4a 100644 --- a/src/fsfw/tasks/FixedTimeslotTaskIF.h +++ b/src/fsfw/tasks/FixedTimeslotTaskIF.h @@ -30,7 +30,7 @@ class FixedTimeslotTaskIF : public PeriodicTaskIF { * Check whether the sequence is valid and perform all other required * initialization steps which are needed after task creation */ - virtual ReturnValue_t checkSequence() const = 0; + virtual ReturnValue_t checkSequence() = 0; }; #endif /* FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ */ diff --git a/src/fsfw/tasks/PeriodicTaskIF.h b/src/fsfw/tasks/PeriodicTaskIF.h index c78a32de..2ae268fc 100644 --- a/src/fsfw/tasks/PeriodicTaskIF.h +++ b/src/fsfw/tasks/PeriodicTaskIF.h @@ -31,7 +31,7 @@ class PeriodicTaskIF { * Add an object to the task. The object needs to implement ExecutableObjectIF * @return */ - virtual ReturnValue_t addComponent(object_id_t object) { + virtual ReturnValue_t addComponent(object_id_t object, uint8_t opCode = 0) { return HasReturnvaluesIF::RETURN_FAILED; }; @@ -41,13 +41,15 @@ class PeriodicTaskIF { * Add an object to the task. * @return */ - virtual ReturnValue_t addComponent(ExecutableObjectIF* object) { + virtual ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode = 0) { return HasReturnvaluesIF::RETURN_FAILED; }; virtual ReturnValue_t sleepFor(uint32_t ms) = 0; virtual uint32_t getPeriodMs() const = 0; + + virtual bool isEmpty() const = 0; }; #endif /* PERIODICTASKIF_H_ */ diff --git a/tests/src/fsfw_tests/unit/power/testPowerSwitcher.cpp b/tests/src/fsfw_tests/unit/power/testPowerSwitcher.cpp index d8523558..941055ac 100644 --- a/tests/src/fsfw_tests/unit/power/testPowerSwitcher.cpp +++ b/tests/src/fsfw_tests/unit/power/testPowerSwitcher.cpp @@ -67,7 +67,5 @@ TEST_CASE("Power Switcher", "[power-switcher]") { REQUIRE(not switcherUsingDummy.active()); } - SECTION("More Dummy Tests") { - - } + SECTION("More Dummy Tests") {} } From 18b342e94b59123b986fca3242ba375be3c6aefd Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 17 May 2022 18:12:05 +0200 Subject: [PATCH 2/9] vector as core container is ok --- src/fsfw/osal/linux/PeriodicPosixTask.cpp | 7 ++++--- src/fsfw/osal/linux/PeriodicPosixTask.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.cpp b/src/fsfw/osal/linux/PeriodicPosixTask.cpp index 26b6f53e..44d669df 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.cpp +++ b/src/fsfw/osal/linux/PeriodicPosixTask.cpp @@ -1,6 +1,7 @@ #include "fsfw/osal/linux/PeriodicPosixTask.h" -#include +#include +#include #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/serviceinterface/ServiceInterface.h" @@ -23,7 +24,7 @@ void* PeriodicPosixTask::taskEntryPoint(void* arg) { PeriodicPosixTask* originalTask(reinterpret_cast(arg)); // The task's functionality is called. originalTask->taskFunctionality(); - return NULL; + return nullptr; } ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object, uint8_t opCode) { @@ -43,7 +44,7 @@ ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object, uint8_ #endif return HasReturnvaluesIF::RETURN_FAILED; } - objectList.emplace(object, opCode); + objectList.push_back({object, opCode}); object->setTaskIF(this); return HasReturnvaluesIF::RETURN_OK; diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.h b/src/fsfw/osal/linux/PeriodicPosixTask.h index 1142c854..a3c6b187 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.h +++ b/src/fsfw/osal/linux/PeriodicPosixTask.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ #define FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ -#include +#include #include "../../objectmanager/ObjectManagerIF.h" #include "../../tasks/ExecutableObjectIF.h" @@ -61,7 +61,7 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { private: //! Typedef for the List of objects. Will contain the objects to execute and their respective //! op codes - using ObjectList = std::multiset>; + using ObjectList = std::vector>; /** * @brief This attribute holds a list of objects to be executed. */ From 7b3de873644150fe82cb54399b35c59c7134cd3c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 18 May 2022 13:19:43 +0200 Subject: [PATCH 3/9] removed some changes which belong in separate PR --- hal/src/fsfw_hal/linux/CommandExecutor.cpp | 2 -- hal/src/fsfw_hal/linux/spi/SpiComIF.cpp | 27 +++---------------- hal/src/fsfw_hal/linux/spi/SpiComIF.h | 30 ++++------------------ 3 files changed, 8 insertions(+), 51 deletions(-) diff --git a/hal/src/fsfw_hal/linux/CommandExecutor.cpp b/hal/src/fsfw_hal/linux/CommandExecutor.cpp index dcdd10ee..49c44ebf 100644 --- a/hal/src/fsfw_hal/linux/CommandExecutor.cpp +++ b/hal/src/fsfw_hal/linux/CommandExecutor.cpp @@ -205,5 +205,3 @@ ReturnValue_t CommandExecutor::executeBlocking() { } return HasReturnvaluesIF::RETURN_OK; } - -const std::vector& CommandExecutor::getReadVector() const { return readVec; } diff --git a/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp b/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp index 3c257f1f..dcf92b5d 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp +++ b/hal/src/fsfw_hal/linux/spi/SpiComIF.cpp @@ -401,33 +401,12 @@ void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed) if (retval != 0) { utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed"); } -} - -void SpiComIF::getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const { - uint8_t tmpMode = 0; - int retval = ioctl(spiFd, SPI_IOC_RD_MODE, &tmpMode); - if (retval != 0) { - utility::handleIoctlError("SpiComIF::getSpiSpeedAndMode: Reading SPI mode failed"); - } - mode = static_cast(tmpMode); - - retval = ioctl(spiFd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); - if (retval != 0) { - utility::handleIoctlError("SpiComIF::getSpiSpeedAndMode: Getting SPI speed failed"); - } -} - -const std::string& SpiComIF::getSpiDev() const { return dev; } - -void SpiComIF::updateLinePolarity(int spiFd) { + // This updates the SPI clock default polarity. Only setting the mode does not update + // the line state, which can be an issue on mode switches because the clock line will + // switch the state after the chip select is pulled low clockUpdateTransfer.len = 0; retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer); if (retval != 0) { utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed"); } } - -void SpiComIF::setMutexParams(MutexIF::TimeoutType timeoutType_, uint32_t timeoutMs_) { - timeoutType = timeoutType_; - timeoutMs = timeoutMs_; -} diff --git a/hal/src/fsfw_hal/linux/spi/SpiComIF.h b/hal/src/fsfw_hal/linux/spi/SpiComIF.h index 1400dcfc..357afa2f 100644 --- a/hal/src/fsfw_hal/linux/spi/SpiComIF.h +++ b/hal/src/fsfw_hal/linux/spi/SpiComIF.h @@ -22,17 +22,15 @@ class SpiCookie; */ class SpiComIF : public DeviceCommunicationIF, public SystemObject { public: - static constexpr dur_millis_t DEFAULT_MUTEX_TIMEOUT = 20; - - static constexpr uint8_t CLASS_ID = CLASS_ID::HAL_SPI; + static constexpr uint8_t spiRetvalId = CLASS_ID::HAL_SPI; static constexpr ReturnValue_t OPENING_FILE_FAILED = - HasReturnvaluesIF::makeReturnCode(CLASS_ID, 0); + HasReturnvaluesIF::makeReturnCode(spiRetvalId, 0); /* Full duplex (ioctl) transfer failure */ static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED = - HasReturnvaluesIF::makeReturnCode(CLASS_ID, 1); + HasReturnvaluesIF::makeReturnCode(spiRetvalId, 1); /* Half duplex (read/write) transfer failure */ static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED = - HasReturnvaluesIF::makeReturnCode(CLASS_ID, 2); + HasReturnvaluesIF::makeReturnCode(spiRetvalId, 2); SpiComIF(object_id_t objectId, GpioIF* gpioComIF); @@ -47,7 +45,6 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject { * the chip select must be driven from outside of the com if. */ MutexIF* getMutex(MutexIF::TimeoutType* timeoutType = nullptr, uint32_t* timeoutMs = nullptr); - void setMutexParams(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs); /** * Perform a regular send operation using Linux iotcl. This is public so it can be used @@ -62,23 +59,6 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject { GpioIF* getGpioInterface(); void setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed); -<<<<<<< Updated upstream -======= - void getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const; - - /** - * This updates the SPI clock default polarity. Only setting the mode does not update - * the line state, which can be an issue on mode switches because the clock line will - * switch the state after the chip select is pulled low. - * - * It is recommended to call this function after #setSpiSpeedAndMode and after locking the - * CS mutex if the SPI bus has multiple SPI devices with different speed and SPI modes attached. - * @param spiFd - */ - void updateLinePolarity(int spiFd); - - const std::string& getSpiDev() const; ->>>>>>> Stashed changes void performSpiWiretapping(SpiCookie* spiCookie); ReturnValue_t getReadBuffer(address_t spiAddress, uint8_t** buffer); @@ -93,7 +73,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject { MutexIF* spiMutex = nullptr; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; - uint32_t timeoutMs = DEFAULT_MUTEX_TIMEOUT; + uint32_t timeoutMs = 20; spi_ioc_transfer clockUpdateTransfer = {}; using SpiDeviceMap = std::unordered_map; From e87b5a0207070ebe3125cd675a108cae29d5c2f0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 18 May 2022 14:32:35 +0200 Subject: [PATCH 4/9] new base class for periodic tasks --- src/fsfw/osal/linux/PeriodicPosixTask.cpp | 57 ++--------------------- src/fsfw/osal/linux/PeriodicPosixTask.h | 55 ++++------------------ src/fsfw/tasks/PeriodicTaskBase.cpp | 57 +++++++++++++++++++++++ src/fsfw/tasks/PeriodicTaskBase.h | 52 +++++++++++++++++++++ src/fsfw/tasks/PeriodicTaskIF.h | 24 +++++----- src/fsfw/tasks/TaskFactory.h | 2 +- src/fsfw/tasks/Typedef.h | 13 ------ src/fsfw/tasks/definitions.h | 13 ++++++ 8 files changed, 148 insertions(+), 125 deletions(-) create mode 100644 src/fsfw/tasks/PeriodicTaskBase.cpp create mode 100644 src/fsfw/tasks/PeriodicTaskBase.h delete mode 100644 src/fsfw/tasks/Typedef.h create mode 100644 src/fsfw/tasks/definitions.h diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.cpp b/src/fsfw/osal/linux/PeriodicPosixTask.cpp index 44d669df..510ec59c 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.cpp +++ b/src/fsfw/osal/linux/PeriodicPosixTask.cpp @@ -8,12 +8,10 @@ #include "fsfw/tasks/ExecutableObjectIF.h" PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, - uint32_t period_, void(deadlineMissedFunc_)()) + uint32_t period_, TaskDeadlineMissedFunction dlMissedFunc_) : PosixThread(name_, priority_, stackSize_), - objectList(), - started(false), - periodMs(period_), - deadlineMissedFunc(deadlineMissedFunc_) {} + PeriodicTaskBase(period_, dlMissedFunc_), + started(false) {} PeriodicPosixTask::~PeriodicPosixTask() { // Not Implemented @@ -27,31 +25,8 @@ void* PeriodicPosixTask::taskEntryPoint(void* arg) { return nullptr; } -ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object, uint8_t opCode) { - ExecutableObjectIF* newObject = ObjectManager::instance()->get(object); - return addComponent(newObject, opCode); -} - -ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object, uint8_t opCode) { - if (object == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" - << " it implements ExecutableObjectIF!" << std::endl; -#else - sif::printError( - "PeriodicTask::addComponent: Invalid object. Make sure it " - "implements ExecutableObjectIF!\n"); -#endif - return HasReturnvaluesIF::RETURN_FAILED; - } - objectList.push_back({object, opCode}); - object->setTaskIF(this); - - return HasReturnvaluesIF::RETURN_OK; -} - ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) { - return PosixThread::sleep((uint64_t)ms * 1000000); + return PosixThread::sleep(static_cast(ms * 1000000)); } ReturnValue_t PeriodicPosixTask::startTask(void) { @@ -84,27 +59,3 @@ void PeriodicPosixTask::taskFunctionality(void) { } } } - -uint32_t PeriodicPosixTask::getPeriodMs() const { return periodMs; } - -bool PeriodicPosixTask::isEmpty() const { return objectList.empty(); } - -ReturnValue_t PeriodicPosixTask::initObjsAfterTaskCreation() { - std::multiset uniqueObjects; - ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; - uint32_t count = 0; - for (const auto& obj : objectList) { - // Ensure that each unique object is initialized once. - if (uniqueObjects.find(obj.first) == uniqueObjects.end()) { - ReturnValue_t result = obj.first->initializeAfterTaskCreation(); - if (result != HasReturnvaluesIF::RETURN_OK) { - count++; - status = result; - } - uniqueObjects.emplace(obj.first); - } - } - if (count > 0) { - } - return status; -} diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.h b/src/fsfw/osal/linux/PeriodicPosixTask.h index a3c6b187..3dcc6bcc 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.h +++ b/src/fsfw/osal/linux/PeriodicPosixTask.h @@ -1,14 +1,17 @@ #ifndef FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ #define FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ -#include - -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/ExecutableObjectIF.h" -#include "../../tasks/PeriodicTaskIF.h" #include "PosixThread.h" -class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { +#include + +#include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/tasks/ExecutableObjectIF.h" +#include "fsfw/tasks/PeriodicTaskIF.h" +#include "fsfw/tasks/PeriodicTaskBase.h" + + +class PeriodicPosixTask : public PosixThread, public PeriodicTaskBase { public: /** * Create a generic periodic task. @@ -34,48 +37,16 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { * to the system call. */ ReturnValue_t startTask() override; - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override; - - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object pointer to the object to add. - * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override; - - uint32_t getPeriodMs() const override; ReturnValue_t sleepFor(uint32_t ms) override; - ReturnValue_t initObjsAfterTaskCreation(); - - bool isEmpty() const override; - private: - //! Typedef for the List of objects. Will contain the objects to execute and their respective - //! op codes - using ObjectList = std::vector>; - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; /** * @brief Flag to indicate that the task was started and is allowed to run */ bool started; - /** - * @brief Period of the task in milliseconds - */ - uint32_t periodMs; /** * @brief The function containing the actual functionality of the task. * @details The method sets and starts @@ -92,14 +63,6 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF { * of the child class. Needs a valid pointer to the derived class. */ static void* taskEntryPoint(void* arg); - /** - * @brief The pointer to the deadline-missed function. - * @details This pointer stores the function that is executed if the task's deadline is missed. - * So, each may react individually on a timing failure. The pointer may be - * NULL, then nothing happens on missing the deadline. The deadline is equal to the next execution - * of the periodic task. - */ - void (*deadlineMissedFunc)(); }; #endif /* FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ */ diff --git a/src/fsfw/tasks/PeriodicTaskBase.cpp b/src/fsfw/tasks/PeriodicTaskBase.cpp new file mode 100644 index 00000000..606fee1e --- /dev/null +++ b/src/fsfw/tasks/PeriodicTaskBase.cpp @@ -0,0 +1,57 @@ +#include +#include "PeriodicTaskBase.h" + +#include + +PeriodicTaskBase::PeriodicTaskBase(uint32_t periodMs_, + TaskDeadlineMissedFunction deadlineMissedFunc_) + : periodMs(periodMs_), deadlineMissedFunc(deadlineMissedFunc_) {} + +uint32_t PeriodicTaskBase::getPeriodMs() const { return periodMs; } + +bool PeriodicTaskBase::isEmpty() const override { + return objectList.empty(); +} + +ReturnValue_t PeriodicTaskBase::initObjsAfterTaskCreation() { + std::multiset uniqueObjects; + ReturnValue_t status = HasReturnvaluesIF::RETURN_OK; + uint32_t count = 0; + for (const auto& obj : objectList) { + // Ensure that each unique object is initialized once. + if (uniqueObjects.find(obj.first) == uniqueObjects.end()) { + ReturnValue_t result = obj.first->initializeAfterTaskCreation(); + if (result != HasReturnvaluesIF::RETURN_OK) { + count++; + status = result; + } + uniqueObjects.emplace(obj.first); + } + } + if (count > 0) { + } + return status; +} + +ReturnValue_t PeriodicTaskBase::addComponent(object_id_t object, uint8_t opCode) { + ExecutableObjectIF* newObject = ObjectManager::instance()->get(object); + return addComponent(newObject, opCode); +} + +ReturnValue_t PeriodicTaskBase::addComponent(ExecutableObjectIF* object, uint8_t opCode) { + if (object == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PeriodicTask::addComponent: Invalid object. Make sure" + << " it implements ExecutableObjectIF!" << std::endl; +#else + sif::printError( + "PeriodicTask::addComponent: Invalid object. Make sure it " + "implements ExecutableObjectIF!\n"); +#endif + return HasReturnvaluesIF::RETURN_FAILED; + } + objectList.push_back({object, opCode}); + object->setTaskIF(this); + + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/src/fsfw/tasks/PeriodicTaskBase.h b/src/fsfw/tasks/PeriodicTaskBase.h new file mode 100644 index 00000000..4b330426 --- /dev/null +++ b/src/fsfw/tasks/PeriodicTaskBase.h @@ -0,0 +1,52 @@ +#ifndef FSFW_SRC_FSFW_TASKS_PERIODICTASKBASE_H_ +#define FSFW_SRC_FSFW_TASKS_PERIODICTASKBASE_H_ + +#include "fsfw/tasks/PeriodicTaskIF.h" +#include "fsfw/tasks/definitions.h" +#include +#include + +class ExecutableObjectIF; + +class PeriodicTaskBase: public PeriodicTaskIF { +public: + PeriodicTaskBase(uint32_t periodMs, TaskDeadlineMissedFunction deadlineMissedFunc = nullptr); + + ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override; + ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override; + + + uint32_t getPeriodMs() const override; + + bool isEmpty() const override; + + ReturnValue_t initObjsAfterTaskCreation(); + +protected: + + //! Typedef for the List of objects. Will contain the objects to execute and their respective + //! operation codes + using ObjectList = std::vector>; + /** + * @brief This attribute holds a list of objects to be executed. + */ + ObjectList objectList; + + /** + * @brief Period of the task in milliseconds + */ + uint32_t periodMs; + + /** + * @brief The pointer to the deadline-missed function. + * @details This pointer stores the function that is executed if the task's deadline is missed. + * So, each may react individually on a timing failure. The pointer may be + * NULL, then nothing happens on missing the deadline. The deadline is equal to the next execution + * of the periodic task. + */ + TaskDeadlineMissedFunction deadlineMissedFunc = nullptr; +}; + + + +#endif /* FSFW_SRC_FSFW_TASKS_PERIODICTASKBASE_H_ */ diff --git a/src/fsfw/tasks/PeriodicTaskIF.h b/src/fsfw/tasks/PeriodicTaskIF.h index 2ae268fc..076ef56e 100644 --- a/src/fsfw/tasks/PeriodicTaskIF.h +++ b/src/fsfw/tasks/PeriodicTaskIF.h @@ -1,11 +1,10 @@ #ifndef FRAMEWORK_TASK_PERIODICTASKIF_H_ #define FRAMEWORK_TASK_PERIODICTASKIF_H_ -#include +#include "fsfw/objectmanager/SystemObjectIF.h" +#include "fsfw/tasks/ExecutableObjectIF.h" -#include "../objectmanager/SystemObjectIF.h" -#include "../timemanager/Clock.h" -class ExecutableObjectIF; +#include /** * New version of TaskIF @@ -26,20 +25,21 @@ class PeriodicTaskIF { virtual ReturnValue_t startTask() = 0; /** - * Add a component (object) to a periodic task. - * @param object - * Add an object to the task. The object needs to implement ExecutableObjectIF - * @return + * Adds an object to the list of objects to be executed. + * The objects are executed in the order added. The object needs to implement + * ExecutableObjectIF + * @param object Id of the object to add. + * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. */ virtual ReturnValue_t addComponent(object_id_t object, uint8_t opCode = 0) { return HasReturnvaluesIF::RETURN_FAILED; }; /** - * Add an object to a periodic task. - * @param object - * Add an object to the task. - * @return + * Adds an object to the list of objects to be executed. + * The objects are executed in the order added. + * @param object pointer to the object to add. + * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. */ virtual ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode = 0) { return HasReturnvaluesIF::RETURN_FAILED; diff --git a/src/fsfw/tasks/TaskFactory.h b/src/fsfw/tasks/TaskFactory.h index fcd62678..828c533e 100644 --- a/src/fsfw/tasks/TaskFactory.h +++ b/src/fsfw/tasks/TaskFactory.h @@ -4,7 +4,7 @@ #include #include "FixedTimeslotTaskIF.h" -#include "Typedef.h" +#include "definitions.h" /** * Singleton Class that produces Tasks. diff --git a/src/fsfw/tasks/Typedef.h b/src/fsfw/tasks/Typedef.h deleted file mode 100644 index 1bb75131..00000000 --- a/src/fsfw/tasks/Typedef.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef FSFW_TASKS_TYPEDEF_H_ -#define FSFW_TASKS_TYPEDEF_H_ - -#include -#include - -typedef const char* TaskName; -typedef uint32_t TaskPriority; -typedef size_t TaskStackSize; -typedef double TaskPeriod; -typedef void (*TaskDeadlineMissedFunction)(); - -#endif /* FSFW_TASKS_TYPEDEF_H_ */ diff --git a/src/fsfw/tasks/definitions.h b/src/fsfw/tasks/definitions.h new file mode 100644 index 00000000..bca9b768 --- /dev/null +++ b/src/fsfw/tasks/definitions.h @@ -0,0 +1,13 @@ +#ifndef FSFW_TASKS_TYPEDEF_H_ +#define FSFW_TASKS_TYPEDEF_H_ + +#include +#include + +using TaskName = const char*; +using TaskPriority = uint32_t; +using TaskStackSize = size_t; +using TaskPeriod = double; +using TaskDeadlineMissedFunction = void (*)(); + +#endif /* FSFW_TASKS_TYPEDEF_H_ */ From b47eb0a7ff7445f078413c63588c7145ef2891fb Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 18 May 2022 14:39:37 +0200 Subject: [PATCH 5/9] minor bugfix --- src/fsfw/tasks/CMakeLists.txt | 3 ++- src/fsfw/tasks/PeriodicTaskBase.cpp | 2 +- src/fsfw/tasks/PeriodicTaskBase.h | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fsfw/tasks/CMakeLists.txt b/src/fsfw/tasks/CMakeLists.txt index df69520a..537320b7 100644 --- a/src/fsfw/tasks/CMakeLists.txt +++ b/src/fsfw/tasks/CMakeLists.txt @@ -1,2 +1,3 @@ target_sources(${LIB_FSFW_NAME} PRIVATE FixedSequenceSlot.cpp - FixedSlotSequence.cpp) + FixedSlotSequence.cpp + PeriodicTaskBase.cpp) diff --git a/src/fsfw/tasks/PeriodicTaskBase.cpp b/src/fsfw/tasks/PeriodicTaskBase.cpp index 606fee1e..87745b14 100644 --- a/src/fsfw/tasks/PeriodicTaskBase.cpp +++ b/src/fsfw/tasks/PeriodicTaskBase.cpp @@ -9,7 +9,7 @@ PeriodicTaskBase::PeriodicTaskBase(uint32_t periodMs_, uint32_t PeriodicTaskBase::getPeriodMs() const { return periodMs; } -bool PeriodicTaskBase::isEmpty() const override { +bool PeriodicTaskBase::isEmpty() const { return objectList.empty(); } diff --git a/src/fsfw/tasks/PeriodicTaskBase.h b/src/fsfw/tasks/PeriodicTaskBase.h index 4b330426..cc4eae4b 100644 --- a/src/fsfw/tasks/PeriodicTaskBase.h +++ b/src/fsfw/tasks/PeriodicTaskBase.h @@ -15,7 +15,6 @@ public: ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override; ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override; - uint32_t getPeriodMs() const override; bool isEmpty() const override; From 1886da0d3f8360693d8bc60eebc39f3169805dbb Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 18 May 2022 15:42:18 +0200 Subject: [PATCH 6/9] refactoring host osal --- src/fsfw/osal/host/PeriodicTask.cpp | 32 +++---------- src/fsfw/osal/host/PeriodicTask.h | 55 +++-------------------- src/fsfw/osal/linux/FixedTimeslotTask.cpp | 12 ++--- src/fsfw/osal/linux/FixedTimeslotTask.h | 11 +++-- src/fsfw/osal/linux/PeriodicPosixTask.cpp | 15 ++++--- src/fsfw/osal/linux/PeriodicPosixTask.h | 11 +++-- src/fsfw/osal/linux/PosixThread.h | 30 ++++++------- src/fsfw/osal/linux/TaskFactory.cpp | 4 +- src/fsfw/tasks/CMakeLists.txt | 6 +-- src/fsfw/tasks/PeriodicTaskBase.cpp | 14 +++--- src/fsfw/tasks/PeriodicTaskBase.h | 31 +++++++------ src/fsfw/tasks/PeriodicTaskIF.h | 4 +- 12 files changed, 83 insertions(+), 142 deletions(-) diff --git a/src/fsfw/osal/host/PeriodicTask.cpp b/src/fsfw/osal/host/PeriodicTask.cpp index cdcfafa6..ed4ef3f1 100644 --- a/src/fsfw/osal/host/PeriodicTask.cpp +++ b/src/fsfw/osal/host/PeriodicTask.cpp @@ -20,8 +20,8 @@ #endif PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack, - TaskPeriod setPeriod, void (*setDeadlineMissedFunc)()) - : started(false), taskName(name), period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) { + TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_) + : PeriodicTaskBase(setPeriod, dlmFunc_), started(false), taskName(name) { // It is probably possible to set task priorities by using the native // task handles for Windows / Linux mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this); @@ -75,9 +75,7 @@ ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { } void PeriodicTask::taskFunctionality() { - for (const auto& object : objectList) { - object->initializeAfterTaskCreation(); - } + initObjsAfterTaskCreation(); std::chrono::milliseconds periodChrono(static_cast(period * 1000)); auto currentStartTime{std::chrono::duration_cast( @@ -89,33 +87,17 @@ void PeriodicTask::taskFunctionality() { if (terminateThread.load()) { break; } - for (const auto& object : objectList) { - object->performOperation(); + for (const auto& objectPair : objectList) { + objectPair.first->performOperation(objectPair.second); } if (not delayForInterval(¤tStartTime, periodChrono)) { - if (deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); + if (dlmFunc != nullptr) { + this->dlmFunc(); } } } } -ReturnValue_t PeriodicTask::addComponent(object_id_t object) { - ExecutableObjectIF* newObject = ObjectManager::instance()->get(object); - return addComponent(newObject); -} - -ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) { - if (object == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - object->setTaskIF(this); - objectList.push_back(object); - return HasReturnvaluesIF::RETURN_OK; -} - -uint32_t PeriodicTask::getPeriodMs() const { return period * 1000; } - bool PeriodicTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) { bool shouldDelay = false; // Get current wakeup time diff --git a/src/fsfw/osal/host/PeriodicTask.h b/src/fsfw/osal/host/PeriodicTask.h index 6c4d5e8b..a565c584 100644 --- a/src/fsfw/osal/host/PeriodicTask.h +++ b/src/fsfw/osal/host/PeriodicTask.h @@ -6,9 +6,9 @@ #include #include -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/PeriodicTaskIF.h" -#include "../../tasks/Typedef.h" +#include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/tasks/PeriodicTaskBase.h" +#include "fsfw/tasks/definitions.h" class ExecutableObjectIF; @@ -19,7 +19,7 @@ class ExecutableObjectIF; * * @ingroup task_handling */ -class PeriodicTask : public PeriodicTaskIF { +class PeriodicTask : public PeriodicTaskBase { public: /** * @brief Standard constructor of the class. @@ -34,7 +34,7 @@ class PeriodicTask : public PeriodicTaskIF { * assigned. */ PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack, - TaskPeriod setPeriod, void (*setDeadlineMissedFunc)()); + TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc); /** * @brief Currently, the executed object's lifetime is not coupled with * the task object's lifetime, so the destructor is empty. @@ -49,62 +49,19 @@ class PeriodicTask : public PeriodicTaskIF { * to the system call. */ ReturnValue_t startTask(void); - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object Id of the object to add. - * @return - * -@c RETURN_OK on success - * -@c RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(object_id_t object); - - /** - * Adds an object to the list of objects to be executed. - * The objects are executed in the order added. - * @param object pointer to the object to add. - * @return - * -@c RETURN_OK on success - * -@c RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addComponent(ExecutableObjectIF* object); - - uint32_t getPeriodMs() const; ReturnValue_t sleepFor(uint32_t ms); protected: using chron_ms = std::chrono::milliseconds; bool started; - //!< Typedef for the List of objects. - typedef std::vector ObjectList; std::thread mainThread; std::atomic terminateThread{false}; - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; - std::condition_variable initCondition; std::mutex initMutex; std::string taskName; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed. So, each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); + /** * @brief This is the function executed in the new task's context. * @details diff --git a/src/fsfw/osal/linux/FixedTimeslotTask.cpp b/src/fsfw/osal/linux/FixedTimeslotTask.cpp index d1fccdf9..4d912a40 100644 --- a/src/fsfw/osal/linux/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/linux/FixedTimeslotTask.cpp @@ -9,8 +9,10 @@ uint32_t FixedTimeslotTask::deadlineMissedCount = 0; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN; FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, - uint32_t periodMs_) - : PosixThread(name_, priority_, stackSize_), pst(periodMs_), started(false) {} + TaskPeriod periodSeconds_) + : posixThread(name_, priority_, stackSize_), + pst(static_cast(periodSeconds_ * 1000)), + started(false) {} FixedTimeslotTask::~FixedTimeslotTask() {} @@ -26,7 +28,7 @@ void* FixedTimeslotTask::taskEntryPoint(void* arg) { ReturnValue_t FixedTimeslotTask::startTask() { started = true; - createTask(&taskEntryPoint, this); + posixThread.createTask(&taskEntryPoint, this); return HasReturnvaluesIF::RETURN_OK; } @@ -57,13 +59,13 @@ ReturnValue_t FixedTimeslotTask::checkSequence() { return pst.checkSequence(); } void FixedTimeslotTask::taskFunctionality() { // Like FreeRTOS pthreads are running as soon as they are created if (!started) { - suspend(); + posixThread.suspend(); } pst.intializeSequenceAfterTaskCreation(); // The start time for the first entry is read. - uint64_t lastWakeTime = getCurrentMonotonicTimeMs(); + uint64_t lastWakeTime = posixThread.getCurrentMonotonicTimeMs(); uint64_t interval = pst.getIntervalToNextSlotMs(); // The task's "infinite" inner loop is entered. diff --git a/src/fsfw/osal/linux/FixedTimeslotTask.h b/src/fsfw/osal/linux/FixedTimeslotTask.h index a5dc9032..ecce7321 100644 --- a/src/fsfw/osal/linux/FixedTimeslotTask.h +++ b/src/fsfw/osal/linux/FixedTimeslotTask.h @@ -3,11 +3,12 @@ #include -#include "../../tasks/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" #include "PosixThread.h" +#include "fsfw/tasks/FixedSlotSequence.h" +#include "fsfw/tasks/FixedTimeslotTaskIF.h" +#include "fsfw/tasks/definitions.h" -class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread { +class FixedTimeslotTask : public FixedTimeslotTaskIF { public: /** * Create a generic periodic task. @@ -21,7 +22,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread { * @param period_ * @param deadlineMissedFunc_ */ - FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, uint32_t periodMs_); + FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod periodSeconds_); virtual ~FixedTimeslotTask(); ReturnValue_t startTask() override; @@ -59,6 +60,8 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread { virtual void taskFunctionality(); private: + PosixThread posixThread; + /** * @brief This is the entry point in a new thread. * diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.cpp b/src/fsfw/osal/linux/PeriodicPosixTask.cpp index 510ec59c..f52067f1 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.cpp +++ b/src/fsfw/osal/linux/PeriodicPosixTask.cpp @@ -1,16 +1,16 @@ #include "fsfw/osal/linux/PeriodicPosixTask.h" -#include #include +#include #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/tasks/ExecutableObjectIF.h" PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, - uint32_t period_, TaskDeadlineMissedFunction dlMissedFunc_) - : PosixThread(name_, priority_, stackSize_), - PeriodicTaskBase(period_, dlMissedFunc_), + TaskPeriod period_, TaskDeadlineMissedFunction dlMissedFunc_) + : PeriodicTaskBase(period_, dlMissedFunc_), + posixThread(name_, priority_, stackSize_), started(false) {} PeriodicPosixTask::~PeriodicPosixTask() { @@ -34,18 +34,19 @@ ReturnValue_t PeriodicPosixTask::startTask(void) { return HasReturnvaluesIF::RETURN_FAILED; } started = true; - PosixThread::createTask(&taskEntryPoint, this); + posixThread.createTask(&taskEntryPoint, this); return HasReturnvaluesIF::RETURN_OK; } void PeriodicPosixTask::taskFunctionality(void) { if (not started) { - suspend(); + posixThread.suspend(); } initObjsAfterTaskCreation(); - uint64_t lastWakeTime = getCurrentMonotonicTimeMs(); + uint64_t lastWakeTime = posixThread.getCurrentMonotonicTimeMs(); + uint64_t periodMs = getPeriodMs(); // The task's "infinite" inner loop is entered. while (1) { for (auto const& objOpCodePair : objectList) { diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.h b/src/fsfw/osal/linux/PeriodicPosixTask.h index 3dcc6bcc..3ab79ed0 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.h +++ b/src/fsfw/osal/linux/PeriodicPosixTask.h @@ -1,17 +1,15 @@ #ifndef FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ #define FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ -#include "PosixThread.h" - #include +#include "PosixThread.h" #include "fsfw/objectmanager/ObjectManagerIF.h" #include "fsfw/tasks/ExecutableObjectIF.h" -#include "fsfw/tasks/PeriodicTaskIF.h" #include "fsfw/tasks/PeriodicTaskBase.h" +#include "fsfw/tasks/PeriodicTaskIF.h" - -class PeriodicPosixTask : public PosixThread, public PeriodicTaskBase { +class PeriodicPosixTask : public PeriodicTaskBase { public: /** * Create a generic periodic task. @@ -25,7 +23,7 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskBase { * @param period_ * @param deadlineMissedFunc_ */ - PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, uint32_t period_, + PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_, void (*deadlineMissedFunc_)()); virtual ~PeriodicPosixTask(); @@ -41,6 +39,7 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskBase { ReturnValue_t sleepFor(uint32_t ms) override; private: + PosixThread posixThread; /** * @brief Flag to indicate that the task was started and is allowed to run diff --git a/src/fsfw/osal/linux/PosixThread.h b/src/fsfw/osal/linux/PosixThread.h index 69c6c5b7..78fdfa2b 100644 --- a/src/fsfw/osal/linux/PosixThread.h +++ b/src/fsfw/osal/linux/PosixThread.h @@ -35,6 +35,21 @@ class PosixThread { */ void resume(); + /** + * @brief Function that has to be called by derived class because the + * derived class pointer has to be valid as argument. + * @details + * This function creates a pthread with the given parameters. As the + * function requires a pointer to the derived object it has to be called + * after the this pointer of the derived object is valid. + * Sets the taskEntryPoint as function to be called by new a thread. + * @param fnc_ Function which will be executed by the thread. + * @param arg_ + * argument of the taskEntryPoint function, needs to be this pointer + * of derived class + */ + void createTask(void* (*fnc_)(void*), void* arg_); + /** * Delay function similar to FreeRtos delayUntil function * @@ -55,21 +70,6 @@ class PosixThread { protected: pthread_t thread; - /** - * @brief Function that has to be called by derived class because the - * derived class pointer has to be valid as argument. - * @details - * This function creates a pthread with the given parameters. As the - * function requires a pointer to the derived object it has to be called - * after the this pointer of the derived object is valid. - * Sets the taskEntryPoint as function to be called by new a thread. - * @param fnc_ Function which will be executed by the thread. - * @param arg_ - * argument of the taskEntryPoint function, needs to be this pointer - * of derived class - */ - void createTask(void* (*fnc_)(void*), void* arg_); - private: char name[PTHREAD_MAX_NAMELEN]; int priority; diff --git a/src/fsfw/osal/linux/TaskFactory.cpp b/src/fsfw/osal/linux/TaskFactory.cpp index 8503039f..b9e7eb28 100644 --- a/src/fsfw/osal/linux/TaskFactory.cpp +++ b/src/fsfw/osal/linux/TaskFactory.cpp @@ -15,14 +15,14 @@ TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; } PeriodicTaskIF* TaskFactory::createPeriodicTask( TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { - return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_ * 1000, + return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_, deadLineMissedFunction_); } FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask( TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { - return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_ * 1000); + return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_); } ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { diff --git a/src/fsfw/tasks/CMakeLists.txt b/src/fsfw/tasks/CMakeLists.txt index 537320b7..6128c272 100644 --- a/src/fsfw/tasks/CMakeLists.txt +++ b/src/fsfw/tasks/CMakeLists.txt @@ -1,3 +1,3 @@ -target_sources(${LIB_FSFW_NAME} PRIVATE FixedSequenceSlot.cpp - FixedSlotSequence.cpp - PeriodicTaskBase.cpp) +target_sources( + ${LIB_FSFW_NAME} PRIVATE FixedSequenceSlot.cpp FixedSlotSequence.cpp + PeriodicTaskBase.cpp) diff --git a/src/fsfw/tasks/PeriodicTaskBase.cpp b/src/fsfw/tasks/PeriodicTaskBase.cpp index 87745b14..021ba7b5 100644 --- a/src/fsfw/tasks/PeriodicTaskBase.cpp +++ b/src/fsfw/tasks/PeriodicTaskBase.cpp @@ -1,17 +1,15 @@ -#include #include "PeriodicTaskBase.h" +#include + #include -PeriodicTaskBase::PeriodicTaskBase(uint32_t periodMs_, - TaskDeadlineMissedFunction deadlineMissedFunc_) - : periodMs(periodMs_), deadlineMissedFunc(deadlineMissedFunc_) {} +PeriodicTaskBase::PeriodicTaskBase(TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_) + : period(period), dlmFunc(dlmFunc_) {} -uint32_t PeriodicTaskBase::getPeriodMs() const { return periodMs; } +uint32_t PeriodicTaskBase::getPeriodMs() const { return static_cast(period * 1000); } -bool PeriodicTaskBase::isEmpty() const { - return objectList.empty(); -} +bool PeriodicTaskBase::isEmpty() const { return objectList.empty(); } ReturnValue_t PeriodicTaskBase::initObjsAfterTaskCreation() { std::multiset uniqueObjects; diff --git a/src/fsfw/tasks/PeriodicTaskBase.h b/src/fsfw/tasks/PeriodicTaskBase.h index cc4eae4b..a262a2d4 100644 --- a/src/fsfw/tasks/PeriodicTaskBase.h +++ b/src/fsfw/tasks/PeriodicTaskBase.h @@ -1,16 +1,17 @@ #ifndef FSFW_SRC_FSFW_TASKS_PERIODICTASKBASE_H_ #define FSFW_SRC_FSFW_TASKS_PERIODICTASKBASE_H_ +#include +#include + #include "fsfw/tasks/PeriodicTaskIF.h" #include "fsfw/tasks/definitions.h" -#include -#include class ExecutableObjectIF; -class PeriodicTaskBase: public PeriodicTaskIF { -public: - PeriodicTaskBase(uint32_t periodMs, TaskDeadlineMissedFunction deadlineMissedFunc = nullptr); +class PeriodicTaskBase : public PeriodicTaskIF { + public: + PeriodicTaskBase(TaskPeriod period, TaskDeadlineMissedFunction deadlineMissedFunc = nullptr); ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override; ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override; @@ -21,8 +22,7 @@ public: ReturnValue_t initObjsAfterTaskCreation(); -protected: - + protected: //! Typedef for the List of objects. Will contain the objects to execute and their respective //! operation codes using ObjectList = std::vector>; @@ -32,20 +32,19 @@ protected: ObjectList objectList; /** - * @brief Period of the task in milliseconds + * @brief Period of task in floating point seconds */ - uint32_t periodMs; + TaskPeriod period; /** * @brief The pointer to the deadline-missed function. - * @details This pointer stores the function that is executed if the task's deadline is missed. - * So, each may react individually on a timing failure. The pointer may be - * NULL, then nothing happens on missing the deadline. The deadline is equal to the next execution - * of the periodic task. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed. So, each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. */ - TaskDeadlineMissedFunction deadlineMissedFunc = nullptr; + TaskDeadlineMissedFunction dlmFunc = nullptr; }; - - #endif /* FSFW_SRC_FSFW_TASKS_PERIODICTASKBASE_H_ */ diff --git a/src/fsfw/tasks/PeriodicTaskIF.h b/src/fsfw/tasks/PeriodicTaskIF.h index 076ef56e..ec25faa8 100644 --- a/src/fsfw/tasks/PeriodicTaskIF.h +++ b/src/fsfw/tasks/PeriodicTaskIF.h @@ -1,11 +1,11 @@ #ifndef FRAMEWORK_TASK_PERIODICTASKIF_H_ #define FRAMEWORK_TASK_PERIODICTASKIF_H_ +#include + #include "fsfw/objectmanager/SystemObjectIF.h" #include "fsfw/tasks/ExecutableObjectIF.h" -#include - /** * New version of TaskIF * Follows RAII principles, i.e. there's no create or delete method. From 64e7d4bb5e61c5ce2ece0bedddaffde086d7fe99 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 18 May 2022 18:15:31 +0200 Subject: [PATCH 7/9] continued refactoring --- src/fsfw/osal/host/FixedTimeslotTask.cpp | 19 ++++++------ src/fsfw/osal/host/FixedTimeslotTask.h | 38 ++++++++++-------------- 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/src/fsfw/osal/host/FixedTimeslotTask.cpp b/src/fsfw/osal/host/FixedTimeslotTask.cpp index 07853938..0c4acf8e 100644 --- a/src/fsfw/osal/host/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/host/FixedTimeslotTask.cpp @@ -22,12 +22,12 @@ FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod setPeriod, - void (*setDeadlineMissedFunc)()) + TaskDeadlineMissedFunction dlmFunc_) : started(false), - pollingSeqTable(setPeriod * 1000), + pollingSeqTable(static_cast(setPeriod * 1000)), taskName(name), period(setPeriod), - deadlineMissedFunc(setDeadlineMissedFunc) { + dlmFunc(dlmFunc_) { // It is propably possible to set task priorities by using the native // task handles for Windows / Linux mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this); @@ -39,7 +39,7 @@ FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority, tasks::insertTaskName(mainThread.get_id(), taskName); } -FixedTimeslotTask::~FixedTimeslotTask(void) { +FixedTimeslotTask::~FixedTimeslotTask() { // Do not delete objects, we were responsible for ptrs only. terminateThread = true; if (mainThread.joinable()) { @@ -48,7 +48,7 @@ FixedTimeslotTask::~FixedTimeslotTask(void) { } void FixedTimeslotTask::taskEntryPoint(void* argument) { - FixedTimeslotTask* originalTask(reinterpret_cast(argument)); + auto* originalTask(reinterpret_cast(argument)); if (not originalTask->started) { // we have to suspend/block here until the task is started. @@ -114,8 +114,7 @@ void FixedTimeslotTask::taskFunctionality() { ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) { - ExecutableObjectIF* executableObject = - ObjectManager::instance()->get(componentId); + auto* executableObject = ObjectManager::instance()->get(componentId); if (executableObject != nullptr) { pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, executableObject, this); return HasReturnvaluesIF::RETURN_OK; @@ -133,9 +132,9 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotT return HasReturnvaluesIF::RETURN_FAILED; } -ReturnValue_t FixedTimeslotTask::checkSequence() const { return pollingSeqTable.checkSequence(); } +ReturnValue_t FixedTimeslotTask::checkSequence() { return pollingSeqTable.checkSequence(); } -uint32_t FixedTimeslotTask::getPeriodMs() const { return period * 1000; } +uint32_t FixedTimeslotTask::getPeriodMs() const { return static_cast(period * 1000); } bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) { bool shouldDelay = false; @@ -176,3 +175,5 @@ bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chr (*previousWakeTimeMs) = currentStartTime; return false; } + +bool FixedTimeslotTask::isEmpty() const { return pollingSeqTable.isEmpty() }; diff --git a/src/fsfw/osal/host/FixedTimeslotTask.h b/src/fsfw/osal/host/FixedTimeslotTask.h index cdbc6f23..69c84c75 100644 --- a/src/fsfw/osal/host/FixedTimeslotTask.h +++ b/src/fsfw/osal/host/FixedTimeslotTask.h @@ -6,10 +6,10 @@ #include #include -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../tasks/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" -#include "../../tasks/Typedef.h" +#include "fsfw/objectmanager/ObjectManagerIF.h" +#include "fsfw/tasks/FixedSlotSequence.h" +#include "fsfw/tasks/FixedTimeslotTaskIF.h" +#include "fsfw/tasks/definitions.h" class ExecutableObjectIF; @@ -39,7 +39,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * @brief Currently, the executed object's lifetime is not coupled with * the task object's lifetime, so the destructor is empty. */ - virtual ~FixedTimeslotTask(void); + ~FixedTimeslotTask() override; /** * @brief The method to start the task. @@ -48,7 +48,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * The address of the task object is passed as an argument * to the system call. */ - ReturnValue_t startTask(void); + ReturnValue_t startTask() override; /** * Add timeslot to the polling sequence table. @@ -57,22 +57,23 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * @param executionStep * @return */ - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep); + ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) override; - ReturnValue_t checkSequence() const override; + ReturnValue_t checkSequence() override; - uint32_t getPeriodMs() const; + ReturnValue_t sleepFor(uint32_t ms) override; + uint32_t getPeriodMs() const override; - ReturnValue_t sleepFor(uint32_t ms); + bool isEmpty() const override; protected: using chron_ms = std::chrono::milliseconds; bool started; - //!< Typedef for the List of objects. - typedef std::vector ObjectList; + std::thread mainThread; std::atomic terminateThread{false}; + TaskDeadlineMissedFunction dlmFunc = nullptr; //! Polling sequence table which contains the object to execute //! and information like the timeslots and the passed execution step. @@ -89,15 +90,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { */ TaskPeriod period; - /** - * @brief The pointer to the deadline-missed function. - * @details - * This pointer stores the function that is executed if the task's deadline - * is missed. So, each may react individually on a timing failure. - * The pointer may be NULL, then nothing happens on missing the deadline. - * The deadline is equal to the next execution of the periodic task. - */ - void (*deadlineMissedFunc)(void); /** * @brief This is the function executed in the new task's context. * @details @@ -117,9 +109,9 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * the checkAndRestartPeriod system call blocks the task until the next * period. On missing the deadline, the deadlineMissedFunction is executed. */ - void taskFunctionality(void); + void taskFunctionality(); - bool delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval); + bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval); }; #endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */ From 08f1ebf9fc1fac2bdada7005b8dad54f55bf2429 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 18 May 2022 23:45:38 +0200 Subject: [PATCH 8/9] continued refactoring --- src/fsfw/osal/host/FixedTimeslotTask.cpp | 2 +- src/fsfw/osal/host/FixedTimeslotTask.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/fsfw/osal/host/FixedTimeslotTask.cpp b/src/fsfw/osal/host/FixedTimeslotTask.cpp index 0c4acf8e..02570f68 100644 --- a/src/fsfw/osal/host/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/host/FixedTimeslotTask.cpp @@ -176,4 +176,4 @@ bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chr return false; } -bool FixedTimeslotTask::isEmpty() const { return pollingSeqTable.isEmpty() }; +bool FixedTimeslotTask::isEmpty() const { return pollingSeqTable.isEmpty(); } diff --git a/src/fsfw/osal/host/FixedTimeslotTask.h b/src/fsfw/osal/host/FixedTimeslotTask.h index 69c84c75..fa7c688d 100644 --- a/src/fsfw/osal/host/FixedTimeslotTask.h +++ b/src/fsfw/osal/host/FixedTimeslotTask.h @@ -73,7 +73,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { std::thread mainThread; std::atomic terminateThread{false}; - TaskDeadlineMissedFunction dlmFunc = nullptr; //! Polling sequence table which contains the object to execute //! and information like the timeslots and the passed execution step. @@ -89,7 +88,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * It is expressed in clock ticks. */ TaskPeriod period; - + TaskDeadlineMissedFunction dlmFunc = nullptr; /** * @brief This is the function executed in the new task's context. * @details @@ -111,7 +110,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { */ void taskFunctionality(); - bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval); + static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval); }; #endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */ From 3a162907076f6b0ce592f0282cb786e71ba3eae4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 19 May 2022 00:44:34 +0200 Subject: [PATCH 9/9] refactored and tested hosted and linux task IF --- src/fsfw/osal/host/FixedTimeslotTask.cpp | 23 +++------- src/fsfw/osal/host/FixedTimeslotTask.h | 27 +++--------- src/fsfw/osal/host/PeriodicTask.cpp | 9 +--- src/fsfw/osal/host/PeriodicTask.h | 12 ++--- src/fsfw/osal/host/TaskFactory.cpp | 4 +- src/fsfw/osal/host/taskHelpers.cpp | 2 +- src/fsfw/osal/host/taskHelpers.h | 2 +- src/fsfw/osal/linux/FixedTimeslotTask.cpp | 53 ++++++----------------- src/fsfw/osal/linux/FixedTimeslotTask.h | 24 +++------- src/fsfw/osal/linux/PeriodicPosixTask.cpp | 32 +++++--------- src/fsfw/osal/linux/PeriodicPosixTask.h | 6 +-- src/fsfw/osal/linux/TaskFactory.cpp | 5 ++- src/fsfw/tasks/CMakeLists.txt | 2 +- src/fsfw/tasks/FixedSlotSequence.h | 2 +- src/fsfw/tasks/FixedTimeslotTaskBase.cpp | 29 +++++++++++++ src/fsfw/tasks/FixedTimeslotTaskBase.h | 44 +++++++++++++++++++ src/fsfw/tasks/FixedTimeslotTaskIF.h | 2 +- src/fsfw/tasks/PeriodicTaskBase.cpp | 18 ++++++-- src/fsfw/tasks/PeriodicTaskBase.h | 7 +-- src/fsfw/tasks/PeriodicTaskIF.h | 2 +- src/fsfw/tasks/definitions.h | 2 +- 21 files changed, 160 insertions(+), 147 deletions(-) create mode 100644 src/fsfw/tasks/FixedTimeslotTaskBase.cpp create mode 100644 src/fsfw/tasks/FixedTimeslotTaskBase.h diff --git a/src/fsfw/osal/host/FixedTimeslotTask.cpp b/src/fsfw/osal/host/FixedTimeslotTask.cpp index 02570f68..931e6a22 100644 --- a/src/fsfw/osal/host/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/host/FixedTimeslotTask.cpp @@ -3,9 +3,7 @@ #include #include -#include "fsfw/ipc/MutexFactory.h" #include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/osal/host/FixedTimeslotTask.h" #include "fsfw/osal/host/Mutex.h" #include "fsfw/osal/host/taskHelpers.h" #include "fsfw/platform.h" @@ -23,11 +21,7 @@ FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority, TaskStackSize setStack, TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_) - : started(false), - pollingSeqTable(static_cast(setPeriod * 1000)), - taskName(name), - period(setPeriod), - dlmFunc(dlmFunc_) { + : FixedTimeslotTaskBase(setPeriod, dlmFunc_), started(false), taskName(name) { // It is propably possible to set task priorities by using the native // task handles for Windows / Linux mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this); @@ -80,7 +74,7 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { return HasReturnvaluesIF::RETURN_OK; } -void FixedTimeslotTask::taskFunctionality() { +[[noreturn]] void FixedTimeslotTask::taskFunctionality() { pollingSeqTable.intializeSequenceAfterTaskCreation(); // A local iterator for the Polling Sequence Table is created to @@ -106,8 +100,11 @@ void FixedTimeslotTask::taskFunctionality() { // we need to wait before executing the current slot // this gives us the time to wait: interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs()); - delayForInterval(¤tStartTime, interval); - // TODO deadline missed check + if (not delayForInterval(¤tStartTime, interval)) { + if (dlmFunc != nullptr) { + dlmFunc(); + } + } } } } @@ -132,10 +129,6 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotT return HasReturnvaluesIF::RETURN_FAILED; } -ReturnValue_t FixedTimeslotTask::checkSequence() { return pollingSeqTable.checkSequence(); } - -uint32_t FixedTimeslotTask::getPeriodMs() const { return static_cast(period * 1000); } - bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) { bool shouldDelay = false; // Get current wakeup time @@ -175,5 +168,3 @@ bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chr (*previousWakeTimeMs) = currentStartTime; return false; } - -bool FixedTimeslotTask::isEmpty() const { return pollingSeqTable.isEmpty(); } diff --git a/src/fsfw/osal/host/FixedTimeslotTask.h b/src/fsfw/osal/host/FixedTimeslotTask.h index fa7c688d..d85ad34c 100644 --- a/src/fsfw/osal/host/FixedTimeslotTask.h +++ b/src/fsfw/osal/host/FixedTimeslotTask.h @@ -8,7 +8,7 @@ #include "fsfw/objectmanager/ObjectManagerIF.h" #include "fsfw/tasks/FixedSlotSequence.h" -#include "fsfw/tasks/FixedTimeslotTaskIF.h" +#include "fsfw/tasks/FixedTimeslotTaskBase.h" #include "fsfw/tasks/definitions.h" class ExecutableObjectIF; @@ -19,7 +19,7 @@ class ExecutableObjectIF; * @details * @ingroup task_handling */ -class FixedTimeslotTask : public FixedTimeslotTaskIF { +class FixedTimeslotTask : public FixedTimeslotTaskBase { public: /** * @brief Standard constructor of the class. @@ -57,14 +57,10 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * @param executionStep * @return */ - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) override; - - ReturnValue_t checkSequence() override; + ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep) override; ReturnValue_t sleepFor(uint32_t ms) override; - uint32_t getPeriodMs() const override; - - bool isEmpty() const override; protected: using chron_ms = std::chrono::milliseconds; @@ -74,21 +70,10 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { std::thread mainThread; std::atomic terminateThread{false}; - //! Polling sequence table which contains the object to execute - //! and information like the timeslots and the passed execution step. - FixedSlotSequence pollingSeqTable; - std::condition_variable initCondition; std::mutex initMutex; std::string taskName; - /** - * @brief The period of the task. - * @details - * The period determines the frequency of the task's execution. - * It is expressed in clock ticks. - */ - TaskPeriod period; - TaskDeadlineMissedFunction dlmFunc = nullptr; + /** * @brief This is the function executed in the new task's context. * @details @@ -108,7 +93,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * the checkAndRestartPeriod system call blocks the task until the next * period. On missing the deadline, the deadlineMissedFunction is executed. */ - void taskFunctionality(); + [[noreturn]] void taskFunctionality(); static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval); }; diff --git a/src/fsfw/osal/host/PeriodicTask.cpp b/src/fsfw/osal/host/PeriodicTask.cpp index ed4ef3f1..1f18d335 100644 --- a/src/fsfw/osal/host/PeriodicTask.cpp +++ b/src/fsfw/osal/host/PeriodicTask.cpp @@ -3,13 +3,10 @@ #include #include -#include "fsfw/ipc/MutexFactory.h" -#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/osal/host/Mutex.h" #include "fsfw/osal/host/taskHelpers.h" #include "fsfw/platform.h" #include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw/tasks/ExecutableObjectIF.h" #if defined(PLATFORM_WIN) #include @@ -33,7 +30,7 @@ PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStack tasks::insertTaskName(mainThread.get_id(), taskName); } -PeriodicTask::~PeriodicTask(void) { +PeriodicTask::~PeriodicTask() { // Do not delete objects, we were responsible for ptrs only. terminateThread = true; if (mainThread.joinable()) { @@ -42,7 +39,7 @@ PeriodicTask::~PeriodicTask(void) { } void PeriodicTask::taskEntryPoint(void* argument) { - PeriodicTask* originalTask(reinterpret_cast(argument)); + auto* originalTask(reinterpret_cast(argument)); if (not originalTask->started) { // we have to suspend/block here until the task is started. @@ -80,8 +77,6 @@ void PeriodicTask::taskFunctionality() { std::chrono::milliseconds periodChrono(static_cast(period * 1000)); auto currentStartTime{std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch())}; - auto nextStartTime{currentStartTime}; - /* Enter the loop that defines the task behavior. */ for (;;) { if (terminateThread.load()) { diff --git a/src/fsfw/osal/host/PeriodicTask.h b/src/fsfw/osal/host/PeriodicTask.h index a565c584..6fdaae4e 100644 --- a/src/fsfw/osal/host/PeriodicTask.h +++ b/src/fsfw/osal/host/PeriodicTask.h @@ -39,7 +39,7 @@ class PeriodicTask : public PeriodicTaskBase { * @brief Currently, the executed object's lifetime is not coupled with * the task object's lifetime, so the destructor is empty. */ - virtual ~PeriodicTask(void); + ~PeriodicTask() override; /** * @brief The method to start the task. @@ -48,9 +48,9 @@ class PeriodicTask : public PeriodicTaskBase { * The address of the task object is passed as an argument * to the system call. */ - ReturnValue_t startTask(void); + ReturnValue_t startTask() override; - ReturnValue_t sleepFor(uint32_t ms); + ReturnValue_t sleepFor(uint32_t ms) override; protected: using chron_ms = std::chrono::milliseconds; @@ -81,9 +81,9 @@ class PeriodicTask : public PeriodicTaskBase { * the checkAndRestartPeriod system call blocks the task until the next * period. On missing the deadline, the deadlineMissedFunction is executed. */ - void taskFunctionality(void); + void taskFunctionality(); - bool delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval); + static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval); }; -#endif /* PERIODICTASK_H_ */ +#endif /* FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ */ diff --git a/src/fsfw/osal/host/TaskFactory.cpp b/src/fsfw/osal/host/TaskFactory.cpp index 6e74fd57..ec4c1554 100644 --- a/src/fsfw/osal/host/TaskFactory.cpp +++ b/src/fsfw/osal/host/TaskFactory.cpp @@ -14,9 +14,9 @@ TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); // Not used for the host implementation for now because C++ thread abstraction is used const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0; -TaskFactory::TaskFactory() {} +TaskFactory::TaskFactory() = default; -TaskFactory::~TaskFactory() {} +TaskFactory::~TaskFactory() = default; TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; } diff --git a/src/fsfw/osal/host/taskHelpers.cpp b/src/fsfw/osal/host/taskHelpers.cpp index aba2948a..432cf30c 100644 --- a/src/fsfw/osal/host/taskHelpers.cpp +++ b/src/fsfw/osal/host/taskHelpers.cpp @@ -6,7 +6,7 @@ std::mutex nameMapLock; std::map taskNameMap; -ReturnValue_t tasks::insertTaskName(std::thread::id threadId, std::string taskName) { +ReturnValue_t tasks::insertTaskName(std::thread::id threadId, const std::string& taskName) { std::lock_guard lg(nameMapLock); auto returnPair = taskNameMap.emplace(threadId, taskName); if (not returnPair.second) { diff --git a/src/fsfw/osal/host/taskHelpers.h b/src/fsfw/osal/host/taskHelpers.h index cf553011..13a71d16 100644 --- a/src/fsfw/osal/host/taskHelpers.h +++ b/src/fsfw/osal/host/taskHelpers.h @@ -7,7 +7,7 @@ namespace tasks { -ReturnValue_t insertTaskName(std::thread::id threadId, std::string taskName); +ReturnValue_t insertTaskName(std::thread::id threadId, const std::string& taskName); std::string getTaskName(std::thread::id threadId); } // namespace tasks diff --git a/src/fsfw/osal/linux/FixedTimeslotTask.cpp b/src/fsfw/osal/linux/FixedTimeslotTask.cpp index 4d912a40..c2823b00 100644 --- a/src/fsfw/osal/linux/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/linux/FixedTimeslotTask.cpp @@ -1,26 +1,21 @@ #include "fsfw/osal/linux/FixedTimeslotTask.h" -#include +#include -#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/serviceinterface/ServiceInterface.h" uint32_t FixedTimeslotTask::deadlineMissedCount = 0; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN; -FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, - TaskPeriod periodSeconds_) - : posixThread(name_, priority_, stackSize_), - pst(static_cast(periodSeconds_ * 1000)), +FixedTimeslotTask::FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_, + TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_) + : FixedTimeslotTaskBase(periodSeconds_, dlmFunc_), + posixThread(name_, priority_, stackSize_), started(false) {} -FixedTimeslotTask::~FixedTimeslotTask() {} - -bool FixedTimeslotTask::isEmpty() const { return pst.isEmpty(); } - void* FixedTimeslotTask::taskEntryPoint(void* arg) { // The argument is re-interpreted as PollingTask. - FixedTimeslotTask* originalTask(reinterpret_cast(arg)); + auto* originalTask(reinterpret_cast(arg)); // The task's functionality is called. originalTask->taskFunctionality(); return nullptr; @@ -36,45 +31,25 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { return PosixThread::sleep((uint64_t)ms * 1000000); } -uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); } - -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) { - ExecutableObjectIF* executableObject = - ObjectManager::instance()->get(componentId); - if (executableObject != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, executableObject, this); - return HasReturnvaluesIF::RETURN_OK; - } - -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst" - << std::dec << std::endl; -#endif - return HasReturnvaluesIF::RETURN_FAILED; -} - -ReturnValue_t FixedTimeslotTask::checkSequence() { return pst.checkSequence(); } - -void FixedTimeslotTask::taskFunctionality() { +[[noreturn]] void FixedTimeslotTask::taskFunctionality() { // Like FreeRTOS pthreads are running as soon as they are created if (!started) { posixThread.suspend(); } - pst.intializeSequenceAfterTaskCreation(); + pollingSeqTable.intializeSequenceAfterTaskCreation(); // The start time for the first entry is read. - uint64_t lastWakeTime = posixThread.getCurrentMonotonicTimeMs(); - uint64_t interval = pst.getIntervalToNextSlotMs(); + uint64_t lastWakeTime = PosixThread::getCurrentMonotonicTimeMs(); + uint32_t interval = 0; // The task's "infinite" inner loop is entered. - while (1) { - if (pst.slotFollowsImmediately()) { + while (true) { + if (pollingSeqTable.slotFollowsImmediately()) { // Do nothing } else { // The interval for the next polling slot is selected. - interval = this->pst.getIntervalToPreviousSlotMs(); + interval = pollingSeqTable.getIntervalToPreviousSlotMs(); // The period is checked and restarted with the new interval. // If the deadline was missed, the deadlineMissedFunc is called. if (!PosixThread::delayUntil(&lastWakeTime, interval)) { @@ -83,7 +58,7 @@ void FixedTimeslotTask::taskFunctionality() { } } // The device handler for this slot is executed and the next one is chosen. - this->pst.executeAndAdvance(); + pollingSeqTable.executeAndAdvance(); } } diff --git a/src/fsfw/osal/linux/FixedTimeslotTask.h b/src/fsfw/osal/linux/FixedTimeslotTask.h index ecce7321..d6c7c0fb 100644 --- a/src/fsfw/osal/linux/FixedTimeslotTask.h +++ b/src/fsfw/osal/linux/FixedTimeslotTask.h @@ -5,10 +5,10 @@ #include "PosixThread.h" #include "fsfw/tasks/FixedSlotSequence.h" -#include "fsfw/tasks/FixedTimeslotTaskIF.h" +#include "fsfw/tasks/FixedTimeslotTaskBase.h" #include "fsfw/tasks/definitions.h" -class FixedTimeslotTask : public FixedTimeslotTaskIF { +class FixedTimeslotTask : public FixedTimeslotTaskBase { public: /** * Create a generic periodic task. @@ -22,22 +22,14 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * @param period_ * @param deadlineMissedFunc_ */ - FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod periodSeconds_); - virtual ~FixedTimeslotTask(); + FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_, + TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_); + ~FixedTimeslotTask() override = default; ReturnValue_t startTask() override; ReturnValue_t sleepFor(uint32_t ms) override; - uint32_t getPeriodMs() const override; - - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) override; - - ReturnValue_t checkSequence() override; - - bool isEmpty() const override; - /** * This static function can be used as #deadlineMissedFunc. * It counts missedDeadlines and prints the number of missed deadlines every 10th time. @@ -57,10 +49,11 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * It links the functionalities provided by FixedSlotSequence with the * OS's System Calls to keep the timing of the periods. */ - virtual void taskFunctionality(); + [[noreturn]] virtual void taskFunctionality(); private: PosixThread posixThread; + bool started; /** * @brief This is the entry point in a new thread. @@ -74,9 +67,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF { * arbitrary data. */ static void* taskEntryPoint(void* arg); - FixedSlotSequence pst; - - bool started; }; #endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */ diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.cpp b/src/fsfw/osal/linux/PeriodicPosixTask.cpp index f52067f1..09b106ed 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.cpp +++ b/src/fsfw/osal/linux/PeriodicPosixTask.cpp @@ -1,35 +1,27 @@ -#include "fsfw/osal/linux/PeriodicPosixTask.h" +#include "PeriodicPosixTask.h" -#include -#include - -#include "fsfw/objectmanager/ObjectManager.h" -#include "fsfw/serviceinterface/ServiceInterface.h" +#include "fsfw/serviceinterface.h" #include "fsfw/tasks/ExecutableObjectIF.h" PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, - TaskPeriod period_, TaskDeadlineMissedFunction dlMissedFunc_) - : PeriodicTaskBase(period_, dlMissedFunc_), + TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_) + : PeriodicTaskBase(period_, dlmFunc_), posixThread(name_, priority_, stackSize_), started(false) {} -PeriodicPosixTask::~PeriodicPosixTask() { - // Not Implemented -} - void* PeriodicPosixTask::taskEntryPoint(void* arg) { // The argument is re-interpreted as PollingTask. - PeriodicPosixTask* originalTask(reinterpret_cast(arg)); + auto* originalTask(reinterpret_cast(arg)); // The task's functionality is called. originalTask->taskFunctionality(); return nullptr; } ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) { - return PosixThread::sleep(static_cast(ms * 1000000)); + return PosixThread::sleep(static_cast(ms) * 1000000); } -ReturnValue_t PeriodicPosixTask::startTask(void) { +ReturnValue_t PeriodicPosixTask::startTask() { if (isEmpty()) { return HasReturnvaluesIF::RETURN_FAILED; } @@ -38,24 +30,24 @@ ReturnValue_t PeriodicPosixTask::startTask(void) { return HasReturnvaluesIF::RETURN_OK; } -void PeriodicPosixTask::taskFunctionality(void) { +[[noreturn]] void PeriodicPosixTask::taskFunctionality() { if (not started) { posixThread.suspend(); } initObjsAfterTaskCreation(); - uint64_t lastWakeTime = posixThread.getCurrentMonotonicTimeMs(); + uint64_t lastWakeTime = PosixThread::getCurrentMonotonicTimeMs(); uint64_t periodMs = getPeriodMs(); // The task's "infinite" inner loop is entered. - while (1) { + while (true) { for (auto const& objOpCodePair : objectList) { objOpCodePair.first->performOperation(objOpCodePair.second); } if (not PosixThread::delayUntil(&lastWakeTime, periodMs)) { - if (this->deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); + if (dlmFunc != nullptr) { + dlmFunc(); } } } diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.h b/src/fsfw/osal/linux/PeriodicPosixTask.h index 3ab79ed0..085c10b9 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.h +++ b/src/fsfw/osal/linux/PeriodicPosixTask.h @@ -24,8 +24,8 @@ class PeriodicPosixTask : public PeriodicTaskBase { * @param deadlineMissedFunc_ */ PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_, - void (*deadlineMissedFunc_)()); - virtual ~PeriodicPosixTask(); + TaskDeadlineMissedFunction dlmFunc_); + ~PeriodicPosixTask() override = default; /** * @brief The method to start the task. @@ -54,7 +54,7 @@ class PeriodicPosixTask : public PeriodicTaskBase { * will be blocked until the next period. On missing the deadline, the deadlineMissedFunction is * executed. */ - virtual void taskFunctionality(void); + [[noreturn]] virtual void taskFunctionality(); /** * @brief This is the entry point in a new thread. * diff --git a/src/fsfw/osal/linux/TaskFactory.cpp b/src/fsfw/osal/linux/TaskFactory.cpp index b9e7eb28..a28e685d 100644 --- a/src/fsfw/osal/linux/TaskFactory.cpp +++ b/src/fsfw/osal/linux/TaskFactory.cpp @@ -8,7 +8,7 @@ // TODO: Different variant than the lazy loading in QueueFactory. What's better and why? TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); -TaskFactory::~TaskFactory() {} +TaskFactory::~TaskFactory() = default; TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; } @@ -22,7 +22,8 @@ PeriodicTaskIF* TaskFactory::createPeriodicTask( FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask( TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { - return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_); + return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_, + deadLineMissedFunction_); } ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { diff --git a/src/fsfw/tasks/CMakeLists.txt b/src/fsfw/tasks/CMakeLists.txt index 6128c272..1d4ab4e1 100644 --- a/src/fsfw/tasks/CMakeLists.txt +++ b/src/fsfw/tasks/CMakeLists.txt @@ -1,3 +1,3 @@ target_sources( ${LIB_FSFW_NAME} PRIVATE FixedSequenceSlot.cpp FixedSlotSequence.cpp - PeriodicTaskBase.cpp) + PeriodicTaskBase.cpp FixedTimeslotTaskBase.cpp) diff --git a/src/fsfw/tasks/FixedSlotSequence.h b/src/fsfw/tasks/FixedSlotSequence.h index 5ece7126..838963c1 100644 --- a/src/fsfw/tasks/FixedSlotSequence.h +++ b/src/fsfw/tasks/FixedSlotSequence.h @@ -35,7 +35,7 @@ class FixedSlotSequence { * @brief The constructor of the FixedSlotSequence object. * @param setLength The period length, expressed in ms. */ - FixedSlotSequence(uint32_t setLengthMs); + explicit FixedSlotSequence(uint32_t setLengthMs); /** * @brief The destructor of the FixedSlotSequence object. diff --git a/src/fsfw/tasks/FixedTimeslotTaskBase.cpp b/src/fsfw/tasks/FixedTimeslotTaskBase.cpp new file mode 100644 index 00000000..26726582 --- /dev/null +++ b/src/fsfw/tasks/FixedTimeslotTaskBase.cpp @@ -0,0 +1,29 @@ +#include "FixedTimeslotTaskBase.h" + +#include "fsfw/objectmanager/ObjectManager.h" + +FixedTimeslotTaskBase::FixedTimeslotTaskBase(TaskPeriod period_, + TaskDeadlineMissedFunction dlmFunc_) + : pollingSeqTable(getPeriodMs()), period(period_), dlmFunc(dlmFunc_) {} +uint32_t FixedTimeslotTaskBase::getPeriodMs() const { return static_cast(period * 1000); } + +bool FixedTimeslotTaskBase::isEmpty() const { return pollingSeqTable.isEmpty(); } + +ReturnValue_t FixedTimeslotTaskBase::checkSequence() { return pollingSeqTable.checkSequence(); } + +ReturnValue_t FixedTimeslotTaskBase::addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep) { + auto* executableObject = ObjectManager::instance()->get(componentId); + if (executableObject != nullptr) { + pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, executableObject, this); + return HasReturnvaluesIF::RETURN_OK; + } + +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << componentId + << std::setfill(' ') << " not found, not adding it to PST" << std::dec << std::endl; +#else + sif::printError("Component 0x%08x not found, not adding it to PST\n"); +#endif + return HasReturnvaluesIF::RETURN_FAILED; +} diff --git a/src/fsfw/tasks/FixedTimeslotTaskBase.h b/src/fsfw/tasks/FixedTimeslotTaskBase.h new file mode 100644 index 00000000..91a4f649 --- /dev/null +++ b/src/fsfw/tasks/FixedTimeslotTaskBase.h @@ -0,0 +1,44 @@ +#ifndef FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H +#define FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H + +#include "FixedSlotSequence.h" +#include "FixedTimeslotTaskIF.h" +#include "definitions.h" + +class FixedTimeslotTaskBase : public FixedTimeslotTaskIF { + public: + explicit FixedTimeslotTaskBase(TaskPeriod period, TaskDeadlineMissedFunction dlmFunc = nullptr); + ~FixedTimeslotTaskBase() override = default; + ; + + protected: + //! Polling sequence table which contains the object to execute + //! and information like the timeslots and the passed execution step. + FixedSlotSequence pollingSeqTable; + + /** + * @brief Period of task in floating point seconds + */ + TaskPeriod period; + + /** + * @brief The pointer to the deadline-missed function. + * @details + * This pointer stores the function that is executed if the task's deadline + * is missed. So, each may react individually on a timing failure. + * The pointer may be NULL, then nothing happens on missing the deadline. + * The deadline is equal to the next execution of the periodic task. + */ + TaskDeadlineMissedFunction dlmFunc = nullptr; + + ReturnValue_t checkSequence() override; + + [[nodiscard]] uint32_t getPeriodMs() const override; + + [[nodiscard]] bool isEmpty() const override; + + ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep) override; +}; + +#endif // FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H diff --git a/src/fsfw/tasks/FixedTimeslotTaskIF.h b/src/fsfw/tasks/FixedTimeslotTaskIF.h index 9d85ac4a..dec382c3 100644 --- a/src/fsfw/tasks/FixedTimeslotTaskIF.h +++ b/src/fsfw/tasks/FixedTimeslotTaskIF.h @@ -11,7 +11,7 @@ */ class FixedTimeslotTaskIF : public PeriodicTaskIF { public: - virtual ~FixedTimeslotTaskIF() {} + ~FixedTimeslotTaskIF() override = default; static constexpr ReturnValue_t SLOT_LIST_EMPTY = HasReturnvaluesIF::makeReturnCode(CLASS_ID::FIXED_SLOT_TASK_IF, 0); diff --git a/src/fsfw/tasks/PeriodicTaskBase.cpp b/src/fsfw/tasks/PeriodicTaskBase.cpp index 021ba7b5..cc8784d9 100644 --- a/src/fsfw/tasks/PeriodicTaskBase.cpp +++ b/src/fsfw/tasks/PeriodicTaskBase.cpp @@ -1,11 +1,21 @@ #include "PeriodicTaskBase.h" -#include - #include +#include "fsfw/objectmanager/ObjectManager.h" +#include "fsfw/serviceinterface.h" + PeriodicTaskBase::PeriodicTaskBase(TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_) - : period(period), dlmFunc(dlmFunc_) {} + : period(period_), dlmFunc(dlmFunc_) { + // Hints at configuration error + if (PeriodicTaskBase::getPeriodMs() <= 1) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "Passed task period 0 or smaller than 1 ms" << std::endl; +#else + sif::printWarning("Passed task period 0 or smaller than 1ms\n"); +#endif + } +} uint32_t PeriodicTaskBase::getPeriodMs() const { return static_cast(period * 1000); } @@ -32,7 +42,7 @@ ReturnValue_t PeriodicTaskBase::initObjsAfterTaskCreation() { } ReturnValue_t PeriodicTaskBase::addComponent(object_id_t object, uint8_t opCode) { - ExecutableObjectIF* newObject = ObjectManager::instance()->get(object); + auto* newObject = ObjectManager::instance()->get(object); return addComponent(newObject, opCode); } diff --git a/src/fsfw/tasks/PeriodicTaskBase.h b/src/fsfw/tasks/PeriodicTaskBase.h index a262a2d4..68791fb8 100644 --- a/src/fsfw/tasks/PeriodicTaskBase.h +++ b/src/fsfw/tasks/PeriodicTaskBase.h @@ -11,14 +11,15 @@ class ExecutableObjectIF; class PeriodicTaskBase : public PeriodicTaskIF { public: - PeriodicTaskBase(TaskPeriod period, TaskDeadlineMissedFunction deadlineMissedFunc = nullptr); + explicit PeriodicTaskBase(TaskPeriod period, + TaskDeadlineMissedFunction deadlineMissedFunc = nullptr); ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override; ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override; - uint32_t getPeriodMs() const override; + [[nodiscard]] uint32_t getPeriodMs() const override; - bool isEmpty() const override; + [[nodiscard]] bool isEmpty() const override; ReturnValue_t initObjsAfterTaskCreation(); diff --git a/src/fsfw/tasks/PeriodicTaskIF.h b/src/fsfw/tasks/PeriodicTaskIF.h index ec25faa8..a6d6a6d6 100644 --- a/src/fsfw/tasks/PeriodicTaskIF.h +++ b/src/fsfw/tasks/PeriodicTaskIF.h @@ -17,7 +17,7 @@ class PeriodicTaskIF { /** * @brief A virtual destructor as it is mandatory for interfaces. */ - virtual ~PeriodicTaskIF() {} + virtual ~PeriodicTaskIF() = default; /** * @brief With the startTask method, a created task can be started * for the first time. diff --git a/src/fsfw/tasks/definitions.h b/src/fsfw/tasks/definitions.h index bca9b768..586884b6 100644 --- a/src/fsfw/tasks/definitions.h +++ b/src/fsfw/tasks/definitions.h @@ -5,7 +5,7 @@ #include using TaskName = const char*; -using TaskPriority = uint32_t; +using TaskPriority = int; using TaskStackSize = size_t; using TaskPeriod = double; using TaskDeadlineMissedFunction = void (*)();