From 17a1ae9d0e11e749cbe31012fe133c95ef9c7ae2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 28 Jan 2021 11:28:28 +0100 Subject: [PATCH 1/3] rtems bugfixes and updates only --- osal/rtems/CMakeLists.txt | 6 +- osal/rtems/Clock.cpp | 6 +- osal/rtems/CpuUsage.cpp | 2 +- osal/rtems/FixedTimeslotTask.cpp | 140 ++++++++++++++++++ osal/rtems/FixedTimeslotTask.h | 81 ++++++++++ osal/rtems/MultiObjectTask.cpp | 92 ------------ osal/rtems/Mutex.cpp | 12 +- osal/rtems/Mutex.h | 2 +- osal/rtems/MutexFactory.cpp | 5 +- osal/rtems/PeriodicTask.cpp | 83 +++++++++++ .../{MultiObjectTask.h => PeriodicTask.h} | 18 +-- osal/rtems/PollingTask.cpp | 131 ---------------- osal/rtems/PollingTask.h | 85 ----------- osal/rtems/RTEMSTaskBase.cpp | 84 +++++++++++ osal/rtems/RTEMSTaskBase.h | 47 ++++++ osal/rtems/RtemsBasic.cpp | 1 + osal/rtems/RtemsBasic.h | 3 +- osal/rtems/TaskFactory.cpp | 21 ++- 18 files changed, 481 insertions(+), 338 deletions(-) create mode 100644 osal/rtems/FixedTimeslotTask.cpp create mode 100644 osal/rtems/FixedTimeslotTask.h delete mode 100644 osal/rtems/MultiObjectTask.cpp create mode 100644 osal/rtems/PeriodicTask.cpp rename osal/rtems/{MultiObjectTask.h => PeriodicTask.h} (90%) delete mode 100644 osal/rtems/PollingTask.cpp delete mode 100644 osal/rtems/PollingTask.h create mode 100644 osal/rtems/RTEMSTaskBase.cpp create mode 100644 osal/rtems/RTEMSTaskBase.h diff --git a/osal/rtems/CMakeLists.txt b/osal/rtems/CMakeLists.txt index bff03184..cd266125 100644 --- a/osal/rtems/CMakeLists.txt +++ b/osal/rtems/CMakeLists.txt @@ -5,13 +5,13 @@ target_sources(${LIB_FSFW_NAME} InitTask.cpp InternalErrorCodes.cpp MessageQueue.cpp - MultiObjectTask.cpp + PeriodicTask.cpp Mutex.cpp MutexFactory.cpp - PollingTask.cpp + FixedTimeslotTask.cpp QueueFactory.cpp RtemsBasic.cpp - TaskBase.cpp + RTEMSTaskBase.cpp TaskFactory.cpp ) diff --git a/osal/rtems/Clock.cpp b/osal/rtems/Clock.cpp index 8bd7ac37..9f4634cc 100644 --- a/osal/rtems/Clock.cpp +++ b/osal/rtems/Clock.cpp @@ -104,9 +104,13 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) { } ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { - // TIsn't this a bug? Are RTEMS ticks always microseconds? + /* For all but the last field, the struct will be filled with the correct values */ rtems_time_of_day* timeRtems = reinterpret_cast(time); rtems_status_code status = rtems_clock_get_tod(timeRtems); + /* The last field now contains the RTEMS ticks of the seconds from 0 + to rtems_clock_get_ticks_per_second() minus one. We calculate the microseconds accordingly */ + timeRtems->ticks = static_cast(timeRtems->ticks) / + rtems_clock_get_ticks_per_second() * 1e6; switch (status) { case RTEMS_SUCCESSFUL: return HasReturnvaluesIF::RETURN_OK; diff --git a/osal/rtems/CpuUsage.cpp b/osal/rtems/CpuUsage.cpp index 6655c69b..89c01336 100644 --- a/osal/rtems/CpuUsage.cpp +++ b/osal/rtems/CpuUsage.cpp @@ -164,7 +164,7 @@ ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer, if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - if ((*size = *size - MAX_LENGTH_OF_THREAD_NAME) < 0) { + if (*size < MAX_LENGTH_OF_THREAD_NAME) { return STREAM_TOO_SHORT; } memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME); diff --git a/osal/rtems/FixedTimeslotTask.cpp b/osal/rtems/FixedTimeslotTask.cpp new file mode 100644 index 00000000..3a3be6b3 --- /dev/null +++ b/osal/rtems/FixedTimeslotTask.cpp @@ -0,0 +1,140 @@ +#include "FixedTimeslotTask.h" +#include "RtemsBasic.h" + +#include "../../tasks/FixedSequenceSlot.h" +#include "../../objectmanager/SystemObjectIF.h" +#include "../../objectmanager/ObjectManagerIF.h" +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../serviceinterface/ServiceInterface.h" + +#include +#include +#include +#include +#include +#include +#include + +#if FSFW_CPP_OSTREAM_ENABLED == 1 +#include +#endif + +#include +#include + +uint32_t FixedTimeslotTask::deadlineMissedCount = 0; + +FixedTimeslotTask::FixedTimeslotTask(const char *name, rtems_task_priority setPriority, + size_t setStack, uint32_t setOverallPeriod, void (*setDeadlineMissedFunc)(void)): + RTEMSTaskBase(setPriority, setStack, name), periodId(0), pst(setOverallPeriod) { + // All additional attributes are applied to the object. + this->deadlineMissedFunc = setDeadlineMissedFunc; +} + +FixedTimeslotTask::~FixedTimeslotTask() { +} + +rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) { + /* The argument is re-interpreted as a FixedTimeslotTask */ + FixedTimeslotTask *originalTask(reinterpret_cast(argument)); + /* The task's functionality is called. */ + return originalTask->taskFunctionality(); + /* Should never be reached */ +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "Polling task " << originalTask->getId() << " returned from taskFunctionality." << + std::endl; +#endif +} + +void FixedTimeslotTask::missedDeadlineCounter() { + FixedTimeslotTask::deadlineMissedCount++; + if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount + << " deadlines." << std::endl; +#endif + } +} + +ReturnValue_t FixedTimeslotTask::startTask() { + rtems_status_code status = rtems_task_start(id, FixedTimeslotTask::taskEntryPoint, + rtems_task_argument((void *) this)); + if (status != RTEMS_SUCCESSFUL) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "PollingTask::startTask for " << std::hex << this->getId() + << std::dec << " failed." << std::endl; +#endif + } + switch(status){ + case RTEMS_SUCCESSFUL: + //ask started successfully + return HasReturnvaluesIF::RETURN_OK; + default: + /* + RTEMS_INVALID_ADDRESS - invalid task entry point + RTEMS_INVALID_ID - invalid task id + RTEMS_INCORRECT_STATE - task not in the dormant state + RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */ + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep) { + ExecutableObjectIF* object = objectManager->get(componentId); + if (object != nullptr) { + pst.addSlot(componentId, slotTimeMs, executionStep, object, 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::endl; +#endif + return HasReturnvaluesIF::RETURN_FAILED; +} + +uint32_t FixedTimeslotTask::getPeriodMs() const { + return pst.getLengthMs(); +} + +ReturnValue_t FixedTimeslotTask::checkSequence() const { + return pst.checkSequence(); +} + +void FixedTimeslotTask::taskFunctionality() { + /* A local iterator for the Polling Sequence Table is created to find the start time for + the first entry. */ + FixedSlotSequence::SlotListIter it = pst.current; + + /* Initialize the PST with the correct calling task */ + pst.intializeSequenceAfterTaskCreation(); + + /* The start time for the first entry is read. */ + rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs); + RTEMSTaskBase::setAndStartPeriod(interval,&periodId); + //The task's "infinite" inner loop is entered. + while (1) { + if (pst.slotFollowsImmediately()) { + /* Do nothing */ + } + else { + /* The interval for the next polling slot is selected. */ + interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs()); + /* The period is checked and restarted with the new interval. + If the deadline was missed, the deadlineMissedFunc is called. */ + rtems_status_code status = RTEMSTaskBase::restartPeriod(interval,periodId); + if (status == RTEMS_TIMEOUT) { + if (this->deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } + } + } + /* The device handler for this slot is executed and the next one is chosen. */ + this->pst.executeAndAdvance(); + } +} + +ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms){ + return RTEMSTaskBase::sleepFor(ms); +}; diff --git a/osal/rtems/FixedTimeslotTask.h b/osal/rtems/FixedTimeslotTask.h new file mode 100644 index 00000000..0d78c474 --- /dev/null +++ b/osal/rtems/FixedTimeslotTask.h @@ -0,0 +1,81 @@ +#ifndef FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ +#define FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ + +#include "RTEMSTaskBase.h" +#include "../../tasks/FixedSlotSequence.h" +#include "../../tasks/FixedTimeslotTaskIF.h" + +class FixedTimeslotTask: public RTEMSTaskBase, public FixedTimeslotTaskIF { +public: + /** + * @brief The standard constructor of the class. + * @details + * This is the general constructor of the class. In addition to the TaskBase parameters, + * the following variables are passed: + * @param setDeadlineMissedFunc The function pointer to the deadline missed function + * that shall be assigned. + * @param getPst The object id of the completely initialized polling sequence. + */ + FixedTimeslotTask( const char *name, rtems_task_priority setPriority, size_t setStackSize, + uint32_t overallPeriod, void (*setDeadlineMissedFunc)()); + + /** + * @brief The destructor of the class. + * @details + * The destructor frees all heap memory that was allocated on thread initialization + * for the PST andthe device handlers. This is done by calling the PST's destructor. + */ + virtual ~FixedTimeslotTask( void ); + + ReturnValue_t startTask( void ); + /** + * This static function can be used as #deadlineMissedFunc. + * It counts missedDeadlines and prints the number of missed deadlines every 10th time. + */ + static void missedDeadlineCounter(); + /** + * A helper variable to count missed deadlines. + */ + static uint32_t deadlineMissedCount; + + ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep); + + uint32_t getPeriodMs() const; + + ReturnValue_t checkSequence() const; + + ReturnValue_t sleepFor(uint32_t ms); +protected: + /** + * @brief id of the associated OS period + */ + rtems_id periodId; + + FixedSlotSequence pst; + + /** + * @brief This attribute holds a function pointer that is executed when a deadline was missed. + * + * @details + * Another function may be announced to determine the actions to perform when a deadline + * was missed. Currently, only one function for missing any deadline is allowed. + * If not used, it shall be declared NULL. + */ + void ( *deadlineMissedFunc )( void ) = nullptr; + /** + * @brief This is the entry point in a new polling thread. + * @details This method is the entry point in the new thread + */ + static rtems_task taskEntryPoint( rtems_task_argument argument ); + + /** + * @brief This function holds the main functionality of the thread. + * @details + * Holding the main functionality of the task, this method is most important. + * It links the functionalities provided by FixedSlotSequence with the OS's system calls to + * keep the timing of the periods. + */ + void taskFunctionality( void ); +}; + +#endif /* FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ */ diff --git a/osal/rtems/MultiObjectTask.cpp b/osal/rtems/MultiObjectTask.cpp deleted file mode 100644 index b111f724..00000000 --- a/osal/rtems/MultiObjectTask.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @file MultiObjectTask.cpp - * @brief This file defines the MultiObjectTask class. - * @date 30.01.2014 - * @author baetz - */ - -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include "../../tasks/ExecutableObjectIF.h" -#include "MultiObjectTask.h" - -MultiObjectTask::MultiObjectTask(const char *name, rtems_task_priority setPriority, - size_t setStack, rtems_interval setPeriod, void (*setDeadlineMissedFunc)()) : - TaskBase(setPriority, setStack, name), periodTicks( - RtemsBasic::convertMsToTicks(setPeriod)), periodId(0), deadlineMissedFunc( - setDeadlineMissedFunc) { -} - -MultiObjectTask::~MultiObjectTask(void) { - //Do not delete objects, we were responsible for ptrs only. - rtems_rate_monotonic_delete(periodId); -} -rtems_task MultiObjectTask::taskEntryPoint(rtems_task_argument argument) { - //The argument is re-interpreted as MultiObjectTask. The Task object is global, so it is found from any place. - MultiObjectTask *originalTask(reinterpret_cast(argument)); - originalTask->taskFunctionality(); -} - -ReturnValue_t MultiObjectTask::startTask() { - rtems_status_code status = rtems_task_start(id, MultiObjectTask::taskEntryPoint, - rtems_task_argument((void *) this)); - if (status != RTEMS_SUCCESSFUL) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "ObjectTask::startTask for " << std::hex << this->getId() - << std::dec << " failed." << std::endl; -#endif - } - switch(status){ - case RTEMS_SUCCESSFUL: - //ask started successfully - return HasReturnvaluesIF::RETURN_OK; - default: -/* RTEMS_INVALID_ADDRESS - invalid task entry point - RTEMS_INVALID_ID - invalid task id - RTEMS_INCORRECT_STATE - task not in the dormant state - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */ - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -ReturnValue_t MultiObjectTask::sleepFor(uint32_t ms) { - return TaskBase::sleepFor(ms); -} - -void MultiObjectTask::taskFunctionality() { - TaskBase::setAndStartPeriod(periodTicks,&periodId); - //The task's "infinite" inner loop is entered. - while (1) { - for (ObjectList::iterator it = objectList.begin(); - it != objectList.end(); ++it) { - (*it)->performOperation(); - } - rtems_status_code status = TaskBase::restartPeriod(periodTicks,periodId); - if (status == RTEMS_TIMEOUT) { - char nameSpace[8] = { 0 }; - char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace), - nameSpace); -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "ObjectTask: " << ptr << " Deadline missed." << std::endl; -#endif - if (this->deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } - } - } -} - -ReturnValue_t MultiObjectTask::addComponent(object_id_t object) { - ExecutableObjectIF* newObject = objectManager->get( - object); - if (newObject == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - objectList.push_back(newObject); - newObject->setTaskIF(this); - - return HasReturnvaluesIF::RETURN_OK; -} - -uint32_t MultiObjectTask::getPeriodMs() const { - return RtemsBasic::convertTicksToMs(periodTicks); -} diff --git a/osal/rtems/Mutex.cpp b/osal/rtems/Mutex.cpp index 7dd512fa..f65c1f55 100644 --- a/osal/rtems/Mutex.cpp +++ b/osal/rtems/Mutex.cpp @@ -1,18 +1,20 @@ #include "Mutex.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../serviceinterface/ServiceInterface.h" uint8_t Mutex::count = 0; -Mutex::Mutex() : - mutexId(0) { +Mutex::Mutex() { rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++; rtems_status_code status = rtems_semaphore_create(mutexName, 1, RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0, &mutexId); if (status != RTEMS_SUCCESSFUL) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "Mutex: creation with name, id " << mutexName << ", " << mutexId - << " failed with " << status << std::endl; + sif::error << "Mutex::Mutex: Creation with name, id " << mutexName << ", " << mutexId << + " failed with " << status << std::endl; +#else + sif::printError("Mutex::Mutex: Creation with name, id %s, %d failed with %d\n", mutexName, + static_cast(mutexId), static_cast(status)); #endif } } diff --git a/osal/rtems/Mutex.h b/osal/rtems/Mutex.h index 4c861318..c4917e08 100644 --- a/osal/rtems/Mutex.h +++ b/osal/rtems/Mutex.h @@ -11,7 +11,7 @@ public: ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0); ReturnValue_t unlockMutex(); private: - rtems_id mutexId; + rtems_id mutexId = 0; static uint8_t count; }; diff --git a/osal/rtems/MutexFactory.cpp b/osal/rtems/MutexFactory.cpp index 24af5fa9..adc599e9 100644 --- a/osal/rtems/MutexFactory.cpp +++ b/osal/rtems/MutexFactory.cpp @@ -1,6 +1,7 @@ -#include "../../ipc/MutexFactory.h" #include "Mutex.h" -#include "RtemsBasic.h" + +#include "../../ipc/MutexFactory.h" + MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); diff --git a/osal/rtems/PeriodicTask.cpp b/osal/rtems/PeriodicTask.cpp new file mode 100644 index 00000000..067983cb --- /dev/null +++ b/osal/rtems/PeriodicTask.cpp @@ -0,0 +1,83 @@ +#include "PeriodicTask.h" + +#include "../../serviceinterface/ServiceInterface.h" +#include "../../tasks/ExecutableObjectIF.h" + +PeriodicTask::PeriodicTask(const char *name, rtems_task_priority setPriority, + size_t setStack, rtems_interval setPeriod, void (*setDeadlineMissedFunc)()) : + RTEMSTaskBase(setPriority, setStack, name), + periodTicks(RtemsBasic::convertMsToTicks(setPeriod)), + deadlineMissedFunc(setDeadlineMissedFunc) { +} + +PeriodicTask::~PeriodicTask(void) { + /* Do not delete objects, we were responsible for pointers only. */ + rtems_rate_monotonic_delete(periodId); +} + +rtems_task PeriodicTask::taskEntryPoint(rtems_task_argument argument) { + /* The argument is re-interpreted as MultiObjectTask. The Task object is global, + so it is found from any place. */ + PeriodicTask *originalTask(reinterpret_cast(argument)); + return originalTask->taskFunctionality();; +} + +ReturnValue_t PeriodicTask::startTask() { + rtems_status_code status = rtems_task_start(id, PeriodicTask::taskEntryPoint, + rtems_task_argument((void *) this)); + if (status != RTEMS_SUCCESSFUL) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "ObjectTask::startTask for " << std::hex << this->getId() + << std::dec << " failed." << std::endl; +#endif + } + switch(status){ + case RTEMS_SUCCESSFUL: + /* Task started successfully */ + return HasReturnvaluesIF::RETURN_OK; + default: + /* RTEMS_INVALID_ADDRESS - invalid task entry point + RTEMS_INVALID_ID - invalid task id + RTEMS_INCORRECT_STATE - task not in the dormant state + RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */ + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { + return RTEMSTaskBase::sleepFor(ms); +} + +void PeriodicTask::taskFunctionality() { + RTEMSTaskBase::setAndStartPeriod(periodTicks,&periodId); + for (const auto& object: objectList) { + object->initializeAfterTaskCreation(); + } + /* The task's "infinite" inner loop is entered. */ + while (1) { + for (const auto& object: objectList) { + object->performOperation(); + } + rtems_status_code status = RTEMSTaskBase::restartPeriod(periodTicks,periodId); + if (status == RTEMS_TIMEOUT) { + if (this->deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } + } + } +} + +ReturnValue_t PeriodicTask::addComponent(object_id_t object) { + ExecutableObjectIF* newObject = objectManager->get(object); + if (newObject == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + objectList.push_back(newObject); + newObject->setTaskIF(this); + + return HasReturnvaluesIF::RETURN_OK; +} + +uint32_t PeriodicTask::getPeriodMs() const { + return RtemsBasic::convertTicksToMs(periodTicks); +} diff --git a/osal/rtems/MultiObjectTask.h b/osal/rtems/PeriodicTask.h similarity index 90% rename from osal/rtems/MultiObjectTask.h rename to osal/rtems/PeriodicTask.h index 04d122a3..2ecce457 100644 --- a/osal/rtems/MultiObjectTask.h +++ b/osal/rtems/PeriodicTask.h @@ -1,10 +1,10 @@ -#ifndef FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ -#define FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ +#ifndef FSFW_OSAL_RTEMS_PERIODICTASK_H_ +#define FSFW_OSAL_RTEMS_PERIODICTASK_H_ +#include "RTEMSTaskBase.h" #include "../../objectmanager/ObjectManagerIF.h" #include "../../tasks/PeriodicTaskIF.h" -#include "TaskBase.h" #include class ExecutableObjectIF; @@ -18,7 +18,7 @@ class ExecutableObjectIF; * @author baetz * @ingroup task_handling */ -class MultiObjectTask: public TaskBase, public PeriodicTaskIF { +class PeriodicTask: public RTEMSTaskBase, public PeriodicTaskIF { public: /** * @brief Standard constructor of the class. @@ -35,13 +35,13 @@ public: * @param setDeadlineMissedFunc The function pointer to the deadline missed function * that shall be assigned. */ - MultiObjectTask(const char *name, rtems_task_priority setPriority, size_t setStack, rtems_interval setPeriod, - void (*setDeadlineMissedFunc)()); + PeriodicTask(const char *name, rtems_task_priority setPriority, size_t setStack, + rtems_interval setPeriod, void (*setDeadlineMissedFunc)()); /** * @brief Currently, the executed object's lifetime is not coupled with the task object's * lifetime, so the destructor is empty. */ - virtual ~MultiObjectTask(void); + virtual ~PeriodicTask(void); /** * @brief The method to start the task. @@ -76,7 +76,7 @@ protected: /** * @brief id of the associated OS period */ - rtems_id periodId; + rtems_id periodId = 0; /** * @brief The pointer to the deadline-missed function. * @details This pointer stores the function that is executed if the task's deadline is missed. @@ -104,4 +104,4 @@ protected: void taskFunctionality(void); }; -#endif /* FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ */ +#endif /* FSFW_OSAL_RTEMS_PERIODICTASK_H_ */ diff --git a/osal/rtems/PollingTask.cpp b/osal/rtems/PollingTask.cpp deleted file mode 100644 index 0ebf63e2..00000000 --- a/osal/rtems/PollingTask.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include "../../tasks/FixedSequenceSlot.h" -#include "../../objectmanager/SystemObjectIF.h" -#include "../../objectmanager/ObjectManagerIF.h" -#include "PollingTask.h" -#include "RtemsBasic.h" -#include "../../returnvalues/HasReturnvaluesIF.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -uint32_t PollingTask::deadlineMissedCount = 0; - -PollingTask::PollingTask(const char *name, rtems_task_priority setPriority, - size_t setStack, uint32_t setOverallPeriod, - void (*setDeadlineMissedFunc)()) : - TaskBase(setPriority, setStack, name), periodId(0), pst( - setOverallPeriod) { - // All additional attributes are applied to the object. - this->deadlineMissedFunc = setDeadlineMissedFunc; -} - -PollingTask::~PollingTask() { -} - -rtems_task PollingTask::taskEntryPoint(rtems_task_argument argument) { - - //The argument is re-interpreted as PollingTask. - PollingTask *originalTask(reinterpret_cast(argument)); - //The task's functionality is called. - originalTask->taskFunctionality(); -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "Polling task " << originalTask->getId() - << " returned from taskFunctionality." << std::endl; -#endif -} - -void PollingTask::missedDeadlineCounter() { - PollingTask::deadlineMissedCount++; - if (PollingTask::deadlineMissedCount % 10 == 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PST missed " << PollingTask::deadlineMissedCount - << " deadlines." << std::endl; -#endif - } -} - -ReturnValue_t PollingTask::startTask() { - rtems_status_code status = rtems_task_start(id, PollingTask::taskEntryPoint, - rtems_task_argument((void *) this)); - if (status != RTEMS_SUCCESSFUL) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PollingTask::startTask for " << std::hex << this->getId() - << std::dec << " failed." << std::endl; -#endif - } - switch(status){ - case RTEMS_SUCCESSFUL: - //ask started successfully - return HasReturnvaluesIF::RETURN_OK; - default: -/* RTEMS_INVALID_ADDRESS - invalid task entry point - RTEMS_INVALID_ID - invalid task id - RTEMS_INCORRECT_STATE - task not in the dormant state - RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */ - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -ReturnValue_t PollingTask::addSlot(object_id_t componentId, - uint32_t slotTimeMs, int8_t executionStep) { - ExecutableObjectIF* object = objectManager->get(componentId); - if (object != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, object, 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::endl; -#endif - return HasReturnvaluesIF::RETURN_FAILED; -} - -uint32_t PollingTask::getPeriodMs() const { - return pst.getLengthMs(); -} - -ReturnValue_t PollingTask::checkSequence() const { - return pst.checkSequence(); -} - -#include - -void PollingTask::taskFunctionality() { - // A local iterator for the Polling Sequence Table is created to find the start time for the first entry. - FixedSlotSequence::SlotListIter it = pst.current; - - //The start time for the first entry is read. - rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs); - TaskBase::setAndStartPeriod(interval,&periodId); - //The task's "infinite" inner loop is entered. - while (1) { - if (pst.slotFollowsImmediately()) { - //Do nothing - } else { - //The interval for the next polling slot is selected. - interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs()); - //The period is checked and restarted with the new interval. - //If the deadline was missed, the deadlineMissedFunc is called. - rtems_status_code status = TaskBase::restartPeriod(interval,periodId); - if (status == RTEMS_TIMEOUT) { - if (this->deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } - } - } - //The device handler for this slot is executed and the next one is chosen. - this->pst.executeAndAdvance(); - } -} - -ReturnValue_t PollingTask::sleepFor(uint32_t ms){ - return TaskBase::sleepFor(ms); -}; diff --git a/osal/rtems/PollingTask.h b/osal/rtems/PollingTask.h deleted file mode 100644 index 42deaf09..00000000 --- a/osal/rtems/PollingTask.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef FSFW_OSAL_RTEMS_POLLINGTASK_H_ -#define FSFW_OSAL_RTEMS_POLLINGTASK_H_ - -#include "../../tasks/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" -#include "TaskBase.h" - -class PollingTask: public TaskBase, public FixedTimeslotTaskIF { - public: - /** - * @brief The standard constructor of the class. - * - * @details This is the general constructor of the class. In addition to the TaskBase parameters, - * the following variables are passed: - * - * @param (*setDeadlineMissedFunc)() The function pointer to the deadline missed function that shall be assigned. - * - * @param getPst The object id of the completely initialized polling sequence. - */ - PollingTask( const char *name, rtems_task_priority setPriority, size_t setStackSize, uint32_t overallPeriod, void (*setDeadlineMissedFunc)()); - - /** - * @brief The destructor of the class. - * - * @details The destructor frees all heap memory that was allocated on thread initialization for the PST and - * the device handlers. This is done by calling the PST's destructor. - */ - virtual ~PollingTask( void ); - - ReturnValue_t startTask( void ); - /** - * This static function can be used as #deadlineMissedFunc. - * It counts missedDeadlines and prints the number of missed deadlines every 10th time. - */ - static void missedDeadlineCounter(); - /** - * A helper variable to count missed deadlines. - */ - static uint32_t deadlineMissedCount; - - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep); - - uint32_t getPeriodMs() const; - - ReturnValue_t checkSequence() const; - - ReturnValue_t sleepFor(uint32_t ms); -protected: - /** - * @brief id of the associated OS period - */ - rtems_id periodId; - - FixedSlotSequence pst; - - /** - * @brief This attribute holds a function pointer that is executed when a deadline was missed. - * - * @details Another function may be announced to determine the actions to perform when a deadline was missed. - * Currently, only one function for missing any deadline is allowed. - * If not used, it shall be declared NULL. - */ - void ( *deadlineMissedFunc )( void ); - /** - * @brief This is the entry point in a new polling thread. - * - * @details This method, that is the generalOSAL::checkAndRestartPeriod( this->periodId, interval ); entry point in the new thread, is here set to generate - * and link the Polling Sequence Table to the thread object and start taskFunctionality() - * on success. If operation of the task is ended for some reason, - * the destructor is called to free allocated memory. - */ - static rtems_task taskEntryPoint( rtems_task_argument argument ); - - /** - * @brief This function holds the main functionality of the thread. - * - * - * @details Holding the main functionality of the task, this method is most important. - * It links the functionalities provided by FixedSlotSequence with the OS's System Calls - * to keep the timing of the periods. - */ - void taskFunctionality( void ); -}; - -#endif /* FSFW_OSAL_RTEMS_POLLINGTASK_H_ */ diff --git a/osal/rtems/RTEMSTaskBase.cpp b/osal/rtems/RTEMSTaskBase.cpp new file mode 100644 index 00000000..d0cdc876 --- /dev/null +++ b/osal/rtems/RTEMSTaskBase.cpp @@ -0,0 +1,84 @@ +#include "RTEMSTaskBase.h" +#include "../../serviceinterface/ServiceInterface.h" + +const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = RTEMS_MINIMUM_STACK_SIZE; + +RTEMSTaskBase::RTEMSTaskBase(rtems_task_priority set_priority, size_t stack_size, + const char *name) { + rtems_name osalName = 0; + for (uint8_t i = 0; i < 4; i++) { + if (name[i] == 0) { + break; + } + osalName += name[i] << (8 * (3 - i)); + } + //The task is created with the operating system's system call. + rtems_status_code status = RTEMS_UNSATISFIED; + if (set_priority <= 99) { + status = rtems_task_create(osalName, + (0xFF - 2 * set_priority), stack_size, + RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR, + RTEMS_FLOATING_POINT, &id); + } + ReturnValue_t result = convertReturnCode(status); + if (result != HasReturnvaluesIF::RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "TaskBase::TaskBase: createTask with name " << std::hex + << osalName << std::dec << " failed with return code " + << (uint32_t) status << std::endl; +#endif + this->id = 0; + } +} + +RTEMSTaskBase::~RTEMSTaskBase() { + rtems_task_delete(id); +} + +rtems_id RTEMSTaskBase::getId() { + return this->id; +} + +ReturnValue_t RTEMSTaskBase::sleepFor(uint32_t ms) { + rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms)); + return convertReturnCode(status); +} + + +ReturnValue_t RTEMSTaskBase::convertReturnCode(rtems_status_code inValue) { + switch (inValue) { + case RTEMS_SUCCESSFUL: + return HasReturnvaluesIF::RETURN_OK; + case RTEMS_MP_NOT_CONFIGURED: + return HasReturnvaluesIF::RETURN_FAILED; + case RTEMS_INVALID_NAME: + return HasReturnvaluesIF::RETURN_FAILED; + case RTEMS_TOO_MANY: + return HasReturnvaluesIF::RETURN_FAILED; + case RTEMS_INVALID_ADDRESS: + return HasReturnvaluesIF::RETURN_FAILED; + case RTEMS_UNSATISFIED: + return HasReturnvaluesIF::RETURN_FAILED; + case RTEMS_INVALID_PRIORITY: + return HasReturnvaluesIF::RETURN_FAILED; + default: + return HasReturnvaluesIF::RETURN_FAILED; + } + +} + + +ReturnValue_t RTEMSTaskBase::setAndStartPeriod(rtems_interval period, rtems_id *periodId) { + rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd'); + rtems_status_code status = rtems_rate_monotonic_create(periodName, periodId); + if (status == RTEMS_SUCCESSFUL) { + status = restartPeriod(period,*periodId); + } + return convertReturnCode(status); +} + +rtems_status_code RTEMSTaskBase::restartPeriod(rtems_interval period, rtems_id periodId){ + //This is necessary to avoid a call with period = 0, which does not start the period. + rtems_status_code status = rtems_rate_monotonic_period(periodId, period + 1); + return status; +} diff --git a/osal/rtems/RTEMSTaskBase.h b/osal/rtems/RTEMSTaskBase.h new file mode 100644 index 00000000..0b8be3e9 --- /dev/null +++ b/osal/rtems/RTEMSTaskBase.h @@ -0,0 +1,47 @@ +#ifndef FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_ +#define FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_ + +#include "RtemsBasic.h" +#include "../../tasks/PeriodicTaskIF.h" + +/** + * @brief This is the basic task handling class for rtems. + * + * @details Task creation base class for rtems. + */ +class RTEMSTaskBase { +protected: + /** + * @brief The class stores the task id it got assigned from the operating system in this attribute. + * If initialization fails, the id is set to zero. + */ + rtems_id id; +public: + /** + * @brief The constructor creates and initializes a task. + * @details This is accomplished by using the operating system call to create a task. The name is + * created automatically with the help od taskCounter. Priority and stack size are + * adjustable, all other attributes are set with default values. + * @param priority Sets the priority of a task. Values range from a low 0 to a high 99. + * @param stack_size The stack size reserved by the operating system for the task. + * @param nam The name of the Task, as a null-terminated String. Currently max 4 chars supported (excluding Null-terminator), rest will be truncated + */ + RTEMSTaskBase( rtems_task_priority priority, size_t stack_size, const char *name); + /** + * @brief In the destructor, the created task is deleted. + */ + virtual ~RTEMSTaskBase(); + /** + * @brief This method returns the task id of this class. + */ + rtems_id getId(); + + ReturnValue_t sleepFor(uint32_t ms); + static ReturnValue_t setAndStartPeriod(rtems_interval period, rtems_id *periodId); + static rtems_status_code restartPeriod(rtems_interval period, rtems_id periodId); +private: + static ReturnValue_t convertReturnCode(rtems_status_code inValue); +}; + + +#endif /* FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_ */ diff --git a/osal/rtems/RtemsBasic.cpp b/osal/rtems/RtemsBasic.cpp index 17cb3458..8ab0ddcd 100644 --- a/osal/rtems/RtemsBasic.cpp +++ b/osal/rtems/RtemsBasic.cpp @@ -1,5 +1,6 @@ #include "RtemsBasic.h" +// TODO: Can this be removed? //ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) { // if (inValue == RTEMS_SUCCESSFUL) { diff --git a/osal/rtems/RtemsBasic.h b/osal/rtems/RtemsBasic.h index d0ca5aba..73f23186 100644 --- a/osal/rtems/RtemsBasic.h +++ b/osal/rtems/RtemsBasic.h @@ -2,12 +2,13 @@ #define FSFW_OSAL_RTEMS_RTEMSBASIC_H_ #include "../../returnvalues/HasReturnvaluesIF.h" + #include #include #include #include -#include +#include class RtemsBasic { public: diff --git a/osal/rtems/TaskFactory.cpp b/osal/rtems/TaskFactory.cpp index bab48a44..5dad69fe 100644 --- a/osal/rtems/TaskFactory.cpp +++ b/osal/rtems/TaskFactory.cpp @@ -1,8 +1,9 @@ -#include "../../tasks/TaskFactory.h" -#include "MultiObjectTask.h" -#include "PollingTask.h" +#include "FixedTimeslotTask.h" +#include "PeriodicTask.h" #include "InitTask.h" #include "RtemsBasic.h" + +#include "../../tasks/TaskFactory.h" #include "../../returnvalues/HasReturnvaluesIF.h" //TODO: Different variant than the lazy loading in QueueFactory. What's better and why? @@ -15,15 +16,21 @@ TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; } -PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) { +PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_, + TaskStackSize stackSize_,TaskPeriod periodInSeconds_, + TaskDeadlineMissedFunction deadLineMissedFunction_) { rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond(); - return static_cast(new MultiObjectTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_)); + return static_cast(new PeriodicTask(name_, taskPriority_, stackSize_, + taskPeriod,deadLineMissedFunction_)); } -FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) { +FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_, + TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_, + TaskDeadlineMissedFunction deadLineMissedFunction_) { rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond(); - return static_cast(new PollingTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_)); + return static_cast(new FixedTimeslotTask(name_, taskPriority_, + stackSize_, taskPeriod, deadLineMissedFunction_)); } ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { From 9b2772c12660f95a1977cb098a0f7b29ddf3c7d1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 8 Feb 2021 13:42:44 +0100 Subject: [PATCH 2/3] better diagnostic printout if case there are issues --- tmtcservices/CommandingServiceBase.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 259f2ccb..8b6f7a09 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -7,6 +7,7 @@ #include "../ipc/QueueFactory.h" #include "../tmtcpacket/pus/TcPacketStored.h" #include "../tmtcpacket/pus/TmPacketStored.h" +#include "../serviceinterface/ServiceInterface.h" object_id_t CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT; object_id_t CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT; @@ -104,9 +105,27 @@ ReturnValue_t CommandingServiceBase::initialize() { void CommandingServiceBase::handleCommandQueue() { CommandMessage reply; ReturnValue_t result = RETURN_FAILED; - for (result = commandQueue->receiveMessage(&reply); result == RETURN_OK; - result = commandQueue->receiveMessage(&reply)) { - handleCommandMessage(&reply); + while(true) { + result = commandQueue->receiveMessage(&reply); + if (result == HasReturnvaluesIF::RETURN_OK) { + handleCommandMessage(&reply); + continue; + } + else if(result == MessageQueueIF::EMPTY) { + break; + } + else { +#if FSFW_VERBOSE_LEVEL >= 1 +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "CommandingServiceBase::handleCommandQueue: Receiving message failed" + "with code" << result << std::endl; +#else + sif::printWarning("CommandingServiceBase::handleCommandQueue: Receiving message " + "failed with code %d\n", result); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ +#endif /* FSFW_VERBOSE_LEVEL >= 1 */ + break; + } } } From 16763202c1e6ba0cf83f1dea6bece23b894e0723 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 8 Feb 2021 14:22:34 +0100 Subject: [PATCH 3/3] taken over action folder --- action/ActionHelper.cpp | 214 +++++++++++++++++---------------- action/ActionHelper.h | 177 +++++++++++++-------------- action/ActionMessage.cpp | 86 ++++++------- action/ActionMessage.h | 44 +++---- action/CommandActionHelper.cpp | 188 ++++++++++++++--------------- action/CommandActionHelper.h | 36 +++--- action/CommandsActionsIF.h | 28 ++--- action/HasActionsIF.h | 44 +++---- action/SimpleActionHelper.cpp | 102 ++++++++-------- action/SimpleActionHelper.h | 30 ++--- 10 files changed, 480 insertions(+), 469 deletions(-) diff --git a/action/ActionHelper.cpp b/action/ActionHelper.cpp index 28557916..e32be68b 100644 --- a/action/ActionHelper.cpp +++ b/action/ActionHelper.cpp @@ -3,151 +3,119 @@ #include "../ipc/MessageQueueSenderIF.h" #include "../objectmanager/ObjectManagerIF.h" +#include "../serviceinterface/ServiceInterface.h" ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : - owner(setOwner), queueToUse(useThisQueue) { + owner(setOwner), queueToUse(useThisQueue) { } ActionHelper::~ActionHelper() { } ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) { - if (command->getCommand() == ActionMessage::EXECUTE_ACTION) { - ActionId_t currentAction = ActionMessage::getActionId(command); - prepareExecution(command->getSender(), currentAction, - ActionMessage::getStoreId(command)); - return HasReturnvaluesIF::RETURN_OK; - } else { - return CommandMessage::UNKNOWN_COMMAND; - } + if (command->getCommand() == ActionMessage::EXECUTE_ACTION) { + ActionId_t currentAction = ActionMessage::getActionId(command); + prepareExecution(command->getSender(), currentAction, + ActionMessage::getStoreId(command)); + return HasReturnvaluesIF::RETURN_OK; + } else { + return CommandMessage::UNKNOWN_COMMAND; + } } ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) { - ipcStore = objectManager->get(objects::IPC_STORE); - if (ipcStore == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - if(queueToUse_ != nullptr) { - setQueueToUse(queueToUse_); - } + ipcStore = objectManager->get(objects::IPC_STORE); + if (ipcStore == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + if(queueToUse_ != nullptr) { + setQueueToUse(queueToUse_); + } - return HasReturnvaluesIF::RETURN_OK; + return HasReturnvaluesIF::RETURN_OK; } void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) { - CommandMessage reply; - ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result); - queueToUse->sendMessage(reportTo, &reply); + CommandMessage reply; + ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result); + queueToUse->sendMessage(reportTo, &reply); } void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) { - CommandMessage reply; - ActionMessage::setCompletionReply(&reply, commandId, result); - queueToUse->sendMessage(reportTo, &reply); + CommandMessage reply; + ActionMessage::setCompletionReply(&reply, commandId, result); + queueToUse->sendMessage(reportTo, &reply); } void ActionHelper::setQueueToUse(MessageQueueIF* queue) { - queueToUse = queue; + queueToUse = queue; } void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress) { - const uint8_t* dataPtr = NULL; - size_t size = 0; - ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { - CommandMessage reply; - ActionMessage::setStepReply(&reply, actionId, 0, result); - queueToUse->sendMessage(commandedBy, &reply); - return; - } - result = owner->executeAction(actionId, commandedBy, dataPtr, size); - ipcStore->deleteData(dataAddress); - if(result == HasActionsIF::EXECUTION_FINISHED) { - CommandMessage reply; - ActionMessage::setCompletionReply(&reply, actionId, result); - queueToUse->sendMessage(commandedBy, &reply); - } - if (result != HasReturnvaluesIF::RETURN_OK) { - CommandMessage reply; - ActionMessage::setStepReply(&reply, actionId, 0, result); - queueToUse->sendMessage(commandedBy, &reply); - return; - } + const uint8_t* dataPtr = NULL; + size_t size = 0; + ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); + if (result != HasReturnvaluesIF::RETURN_OK) { + CommandMessage reply; + ActionMessage::setStepReply(&reply, actionId, 0, result); + queueToUse->sendMessage(commandedBy, &reply); + return; + } + result = owner->executeAction(actionId, commandedBy, dataPtr, size); + ipcStore->deleteData(dataAddress); + if(result == HasActionsIF::EXECUTION_FINISHED) { + CommandMessage reply; + ActionMessage::setCompletionReply(&reply, actionId, result); + queueToUse->sendMessage(commandedBy, &reply); + } + if (result != HasReturnvaluesIF::RETURN_OK) { + CommandMessage reply; + ActionMessage::setStepReply(&reply, actionId, 0, result); + queueToUse->sendMessage(commandedBy, &reply); + return; + } } ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, - ActionId_t replyId, SerializeIF* data, bool hideSender) { - CommandMessage reply; - store_address_t storeAddress; - uint8_t *dataPtr; - size_t maxSize = data->getSerializedSize(); - if (maxSize == 0) { - //No error, there's simply nothing to report. - return HasReturnvaluesIF::RETURN_OK; - } - size_t size = 0; - ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize, - &dataPtr); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - result = data->serialize(&dataPtr, &size, maxSize, - SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { - ipcStore->deleteData(storeAddress); - return result; - } - // We don't need to report the objectId, as we receive REQUESTED data - // before the completion success message. - // True aperiodic replies need to be reported with - // another dedicated message. - ActionMessage::setDataReply(&reply, replyId, storeAddress); - - // If the sender needs to be hidden, for example to handle packet - // as unrequested reply, this will be done here. - if (hideSender) { - result = MessageQueueSenderIF::sendMessage(reportTo, &reply); - } - else { - result = queueToUse->sendMessage(reportTo, &reply); - } - - if (result != HasReturnvaluesIF::RETURN_OK){ - ipcStore->deleteData(storeAddress); - } - return result; -} - -void ActionHelper::resetHelper() { -} - -ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, - ActionId_t replyId, const uint8_t *data, size_t dataSize, - bool hideSender) { + ActionId_t replyId, SerializeIF* data, bool hideSender) { CommandMessage reply; store_address_t storeAddress; - ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize); + uint8_t *dataPtr; + size_t maxSize = data->getSerializedSize(); + if (maxSize == 0) { + /* No error, there's simply nothing to report. */ + return HasReturnvaluesIF::RETURN_OK; + } + size_t size = 0; + ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize, + &dataPtr); if (result != HasReturnvaluesIF::RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "ActionHelper::reportData: Getting free element from IPC store failed!" << + std::endl; +#else + sif::printWarning("ActionHelper::reportData: Getting free element from IPC " + "store failed!\n"); +#endif return result; } - + result = data->serialize(&dataPtr, &size, maxSize, + SerializeIF::Endianness::BIG); if (result != HasReturnvaluesIF::RETURN_OK) { ipcStore->deleteData(storeAddress); return result; } - // We don't need to report the objectId, as we receive REQUESTED data - // before the completion success message. - // True aperiodic replies need to be reported with - // another dedicated message. + /* We don't need to report the objectId, as we receive REQUESTED data before the completion + success message. True aperiodic replies need to be reported with another dedicated message. */ ActionMessage::setDataReply(&reply, replyId, storeAddress); - // If the sender needs to be hidden, for example to handle packet - // as unrequested reply, this will be done here. + /* If the sender needs to be hidden, for example to handle packet + as unrequested reply, this will be done here. */ if (hideSender) { result = MessageQueueSenderIF::sendMessage(reportTo, &reply); } @@ -160,3 +128,45 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, } return result; } + +void ActionHelper::resetHelper() { +} + +ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, + ActionId_t replyId, const uint8_t *data, size_t dataSize, + bool hideSender) { + CommandMessage reply; + store_address_t storeAddress; + ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize); + if (result != HasReturnvaluesIF::RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "ActionHelper::reportData: Adding data to IPC store failed!" << std::endl; +#else + sif::printWarning("ActionHelper::reportData: Adding data to IPC store failed!\n"); +#endif + return result; + } + + if (result != HasReturnvaluesIF::RETURN_OK) { + ipcStore->deleteData(storeAddress); + return result; + } + + /* We don't need to report the objectId, as we receive REQUESTED data before the completion + success message. True aperiodic replies need to be reported with another dedicated message. */ + ActionMessage::setDataReply(&reply, replyId, storeAddress); + + /* If the sender needs to be hidden, for example to handle packet + as unrequested reply, this will be done here. */ + if (hideSender) { + result = MessageQueueSenderIF::sendMessage(reportTo, &reply); + } + else { + result = queueToUse->sendMessage(reportTo, &reply); + } + + if (result != HasReturnvaluesIF::RETURN_OK) { + ipcStore->deleteData(storeAddress); + } + return result; +} diff --git a/action/ActionHelper.h b/action/ActionHelper.h index a91722f3..35ac41d1 100644 --- a/action/ActionHelper.h +++ b/action/ActionHelper.h @@ -18,68 +18,68 @@ class HasActionsIF; class ActionHelper { public: - /** - * Constructor of the action helper - * @param setOwner Pointer to the owner of the interface - * @param useThisQueue messageQueue to be used, can be set during - * initialize function as well. - */ - ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); + /** + * Constructor of the action helper + * @param setOwner Pointer to the owner of the interface + * @param useThisQueue messageQueue to be used, can be set during + * initialize function as well. + */ + ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); - virtual ~ActionHelper(); - /** - * Function to be called from the owner with a new command message - * - * If the message is a valid action message the helper will use the - * executeAction function from HasActionsIF. - * If the message is invalid or the callback fails a message reply will be - * send to the sender of the message automatically. - * - * @param command Pointer to a command message received by the owner - * @return HasReturnvaluesIF::RETURN_OK if the message is a action message, - * CommandMessage::UNKNOW_COMMAND if this message ID is unkown - */ - ReturnValue_t handleActionMessage(CommandMessage* command); - /** - * Helper initialize function. Must be called before use of any other - * helper function - * @param queueToUse_ Pointer to the messageQueue to be used, optional - * if queue was set in constructor - * @return Returns RETURN_OK if successful - */ - ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr); - /** - * Function to be called from the owner to send a step message. - * Success or failure will be determined by the result value. - * - * @param step Number of steps already done - * @param reportTo The messageQueueId to report the step message to - * @param commandId ID of the executed command - * @param result Result of the execution - */ - void step(uint8_t step, MessageQueueId_t reportTo, - ActionId_t commandId, - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); - /** - * Function to be called by the owner to send a action completion message - * - * @param reportTo MessageQueueId_t to report the action completion message to - * @param commandId ID of the executed command - * @param result Result of the execution - */ - void finish(MessageQueueId_t reportTo, ActionId_t commandId, - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); - /** - * Function to be called by the owner if an action does report data. - * Takes a SerializeIF* pointer and serializes it into the IPC store. - * @param reportTo MessageQueueId_t to report the action completion - * message to - * @param replyId ID of the executed command - * @param data Pointer to the data - * @return Returns RETURN_OK if successful, otherwise failure code - */ - ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, - SerializeIF* data, bool hideSender = false); + virtual ~ActionHelper(); + /** + * Function to be called from the owner with a new command message + * + * If the message is a valid action message the helper will use the + * executeAction function from HasActionsIF. + * If the message is invalid or the callback fails a message reply will be + * send to the sender of the message automatically. + * + * @param command Pointer to a command message received by the owner + * @return HasReturnvaluesIF::RETURN_OK if the message is a action message, + * CommandMessage::UNKNOW_COMMAND if this message ID is unkown + */ + ReturnValue_t handleActionMessage(CommandMessage* command); + /** + * Helper initialize function. Must be called before use of any other + * helper function + * @param queueToUse_ Pointer to the messageQueue to be used, optional + * if queue was set in constructor + * @return Returns RETURN_OK if successful + */ + ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr); + /** + * Function to be called from the owner to send a step message. + * Success or failure will be determined by the result value. + * + * @param step Number of steps already done + * @param reportTo The messageQueueId to report the step message to + * @param commandId ID of the executed command + * @param result Result of the execution + */ + void step(uint8_t step, MessageQueueId_t reportTo, + ActionId_t commandId, + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + /** + * Function to be called by the owner to send a action completion message + * + * @param reportTo MessageQueueId_t to report the action completion message to + * @param commandId ID of the executed command + * @param result Result of the execution + */ + void finish(MessageQueueId_t reportTo, ActionId_t commandId, + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + /** + * Function to be called by the owner if an action does report data. + * Takes a SerializeIF* pointer and serializes it into the IPC store. + * @param reportTo MessageQueueId_t to report the action completion + * message to + * @param replyId ID of the executed command + * @param data Pointer to the data + * @return Returns RETURN_OK if successful, otherwise failure code + */ + ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, + SerializeIF* data, bool hideSender = false); /** * Function to be called by the owner if an action does report data. * Takes the raw data and writes it into the IPC store. @@ -91,35 +91,36 @@ public: */ ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, const uint8_t* data, size_t dataSize, bool hideSender = false); - /** - * Function to setup the MessageQueueIF* of the helper. Can be used to - * set the MessageQueueIF* if message queue is unavailable at construction - * and initialize but must be setup before first call of other functions. - * @param queue Queue to be used by the helper - */ - void setQueueToUse(MessageQueueIF *queue); + /** + * Function to setup the MessageQueueIF* of the helper. Can be used to + * set the MessageQueueIF* if message queue is unavailable at construction + * and initialize but must be setup before first call of other functions. + * @param queue Queue to be used by the helper + */ + void setQueueToUse(MessageQueueIF *queue); protected: - //!< Increase of value of this per step - static const uint8_t STEP_OFFSET = 1; - HasActionsIF* owner;//!< Pointer to the owner - //! Queue to be used as response sender, has to be set in ctor or with - //! setQueueToUse - MessageQueueIF* queueToUse; - //! Pointer to an IPC Store, initialized during construction or - StorageManagerIF* ipcStore = nullptr; + //! Increase of value of this per step + static const uint8_t STEP_OFFSET = 1; + //! Pointer to the owner + HasActionsIF* owner; + //! Queue to be used as response sender, has to be set in ctor or with + //! setQueueToUse + MessageQueueIF* queueToUse; + //! Pointer to an IPC Store, initialized during construction or + StorageManagerIF* ipcStore = nullptr; - /** - * Internal function called by handleActionMessage - * @param commandedBy MessageQueueID of Commander - * @param actionId ID of action to be done - * @param dataAddress Address of additional data in IPC Store - */ - virtual void prepareExecution(MessageQueueId_t commandedBy, - ActionId_t actionId, store_address_t dataAddress); - /** - * @brief Default implementation is empty. - */ - virtual void resetHelper(); + /** + * Internal function called by handleActionMessage + * @param commandedBy MessageQueueID of Commander + * @param actionId ID of action to be done + * @param dataAddress Address of additional data in IPC Store + */ + virtual void prepareExecution(MessageQueueId_t commandedBy, + ActionId_t actionId, store_address_t dataAddress); + /** + * @brief Default implementation is empty. + */ + virtual void resetHelper(); }; #endif /* FSFW_ACTION_ACTIONHELPER_H_ */ diff --git a/action/ActionMessage.cpp b/action/ActionMessage.cpp index 1c00dee0..c3eb4710 100644 --- a/action/ActionMessage.cpp +++ b/action/ActionMessage.cpp @@ -11,71 +11,71 @@ ActionMessage::~ActionMessage() { } void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid, - store_address_t parameters) { - message->setCommand(EXECUTE_ACTION); - message->setParameter(fid); - message->setParameter2(parameters.raw); + store_address_t parameters) { + message->setCommand(EXECUTE_ACTION); + message->setParameter(fid); + message->setParameter2(parameters.raw); } ActionId_t ActionMessage::getActionId(const CommandMessage* message) { - return ActionId_t(message->getParameter()); + return ActionId_t(message->getParameter()); } store_address_t ActionMessage::getStoreId(const CommandMessage* message) { - store_address_t temp; - temp.raw = message->getParameter2(); - return temp; + store_address_t temp; + temp.raw = message->getParameter2(); + return temp; } void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step, - ReturnValue_t result) { - if (result == HasReturnvaluesIF::RETURN_OK) { - message->setCommand(STEP_SUCCESS); - } else { - message->setCommand(STEP_FAILED); - } - message->setParameter(fid); - message->setParameter2((step << 16) + result); + ReturnValue_t result) { + if (result == HasReturnvaluesIF::RETURN_OK) { + message->setCommand(STEP_SUCCESS); + } else { + message->setCommand(STEP_FAILED); + } + message->setParameter(fid); + message->setParameter2((step << 16) + result); } uint8_t ActionMessage::getStep(const CommandMessage* message) { - return uint8_t((message->getParameter2() >> 16) & 0xFF); + return uint8_t((message->getParameter2() >> 16) & 0xFF); } ReturnValue_t ActionMessage::getReturnCode(const CommandMessage* message) { - return message->getParameter2() & 0xFFFF; + return message->getParameter2() & 0xFFFF; } void ActionMessage::setDataReply(CommandMessage* message, ActionId_t actionId, - store_address_t data) { - message->setCommand(DATA_REPLY); - message->setParameter(actionId); - message->setParameter2(data.raw); + store_address_t data) { + message->setCommand(DATA_REPLY); + message->setParameter(actionId); + message->setParameter2(data.raw); } void ActionMessage::setCompletionReply(CommandMessage* message, - ActionId_t fid, ReturnValue_t result) { - if (result == HasReturnvaluesIF::RETURN_OK or result == HasActionsIF::EXECUTION_FINISHED) { - message->setCommand(COMPLETION_SUCCESS); - } else { - message->setCommand(COMPLETION_FAILED); - } - message->setParameter(fid); - message->setParameter2(result); + ActionId_t fid, ReturnValue_t result) { + if (result == HasReturnvaluesIF::RETURN_OK or result == HasActionsIF::EXECUTION_FINISHED) { + message->setCommand(COMPLETION_SUCCESS); + } else { + message->setCommand(COMPLETION_FAILED); + } + message->setParameter(fid); + message->setParameter2(result); } void ActionMessage::clear(CommandMessage* message) { - switch(message->getCommand()) { - case EXECUTE_ACTION: - case DATA_REPLY: { - StorageManagerIF *ipcStore = objectManager->get( - objects::IPC_STORE); - if (ipcStore != NULL) { - ipcStore->deleteData(getStoreId(message)); - } - break; - } - default: - break; - } + switch(message->getCommand()) { + case EXECUTE_ACTION: + case DATA_REPLY: { + StorageManagerIF *ipcStore = objectManager->get( + objects::IPC_STORE); + if (ipcStore != NULL) { + ipcStore->deleteData(getStoreId(message)); + } + break; + } + default: + break; + } } diff --git a/action/ActionMessage.h b/action/ActionMessage.h index deb11095..246ac601 100644 --- a/action/ActionMessage.h +++ b/action/ActionMessage.h @@ -15,29 +15,29 @@ using ActionId_t = uint32_t; */ class ActionMessage { private: - ActionMessage(); + ActionMessage(); public: - static const uint8_t MESSAGE_ID = messagetypes::ACTION; - static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1); - static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2); - static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3); - static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4); - static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5); - static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6); - virtual ~ActionMessage(); - static void setCommand(CommandMessage* message, ActionId_t fid, - store_address_t parameters); - static ActionId_t getActionId(const CommandMessage* message ); - static store_address_t getStoreId(const CommandMessage* message ); - static void setStepReply(CommandMessage* message, ActionId_t fid, - uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); - static uint8_t getStep(const CommandMessage* message ); - static ReturnValue_t getReturnCode(const CommandMessage* message ); - static void setDataReply(CommandMessage* message, ActionId_t actionId, - store_address_t data); - static void setCompletionReply(CommandMessage* message, ActionId_t fid, - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); - static void clear(CommandMessage* message); + static const uint8_t MESSAGE_ID = messagetypes::ACTION; + static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1); + static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2); + static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3); + static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4); + static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5); + static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6); + virtual ~ActionMessage(); + static void setCommand(CommandMessage* message, ActionId_t fid, + store_address_t parameters); + static ActionId_t getActionId(const CommandMessage* message ); + static store_address_t getStoreId(const CommandMessage* message ); + static void setStepReply(CommandMessage* message, ActionId_t fid, + uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + static uint8_t getStep(const CommandMessage* message ); + static ReturnValue_t getReturnCode(const CommandMessage* message ); + static void setDataReply(CommandMessage* message, ActionId_t actionId, + store_address_t data); + static void setCompletionReply(CommandMessage* message, ActionId_t fid, + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + static void clear(CommandMessage* message); }; #endif /* FSFW_ACTION_ACTIONMESSAGE_H_ */ diff --git a/action/CommandActionHelper.cpp b/action/CommandActionHelper.cpp index 4e88f3c3..148b3657 100644 --- a/action/CommandActionHelper.cpp +++ b/action/CommandActionHelper.cpp @@ -5,123 +5,123 @@ #include "../objectmanager/ObjectManagerIF.h" CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) : - owner(setOwner), queueToUse(NULL), ipcStore( - NULL), commandCount(0), lastTarget(0) { + owner(setOwner), queueToUse(NULL), ipcStore( + NULL), commandCount(0), lastTarget(0) { } CommandActionHelper::~CommandActionHelper() { } ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, - ActionId_t actionId, SerializeIF *data) { - HasActionsIF *receiver = objectManager->get(commandTo); - if (receiver == NULL) { - return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS; - } - store_address_t storeId; - uint8_t *storePointer; - size_t maxSize = data->getSerializedSize(); - ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, - &storePointer); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - size_t size = 0; - result = data->serialize(&storePointer, &size, maxSize, - SerializeIF::Endianness::BIG); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - return sendCommand(receiver->getCommandQueue(), actionId, storeId); + ActionId_t actionId, SerializeIF *data) { + HasActionsIF *receiver = objectManager->get(commandTo); + if (receiver == NULL) { + return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS; + } + store_address_t storeId; + uint8_t *storePointer; + size_t maxSize = data->getSerializedSize(); + ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, + &storePointer); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + size_t size = 0; + result = data->serialize(&storePointer, &size, maxSize, + SerializeIF::Endianness::BIG); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return sendCommand(receiver->getCommandQueue(), actionId, storeId); } ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, - ActionId_t actionId, const uint8_t *data, uint32_t size) { -// if (commandCount != 0) { -// return CommandsFunctionsIF::ALREADY_COMMANDING; -// } - HasActionsIF *receiver = objectManager->get(commandTo); - if (receiver == NULL) { - return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS; - } - store_address_t storeId; - ReturnValue_t result = ipcStore->addData(&storeId, data, size); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - return sendCommand(receiver->getCommandQueue(), actionId, storeId); + ActionId_t actionId, const uint8_t *data, uint32_t size) { +// if (commandCount != 0) { +// return CommandsFunctionsIF::ALREADY_COMMANDING; +// } + HasActionsIF *receiver = objectManager->get(commandTo); + if (receiver == NULL) { + return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS; + } + store_address_t storeId; + ReturnValue_t result = ipcStore->addData(&storeId, data, size); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return sendCommand(receiver->getCommandQueue(), actionId, storeId); } ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId, - ActionId_t actionId, store_address_t storeId) { - CommandMessage command; - ActionMessage::setCommand(&command, actionId, storeId); - ReturnValue_t result = queueToUse->sendMessage(queueId, &command); - if (result != HasReturnvaluesIF::RETURN_OK) { - ipcStore->deleteData(storeId); - } - lastTarget = queueId; - commandCount++; - return result; + ActionId_t actionId, store_address_t storeId) { + CommandMessage command; + ActionMessage::setCommand(&command, actionId, storeId); + ReturnValue_t result = queueToUse->sendMessage(queueId, &command); + if (result != HasReturnvaluesIF::RETURN_OK) { + ipcStore->deleteData(storeId); + } + lastTarget = queueId; + commandCount++; + return result; } ReturnValue_t CommandActionHelper::initialize() { - ipcStore = objectManager->get(objects::IPC_STORE); - if (ipcStore == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; - } + ipcStore = objectManager->get(objects::IPC_STORE); + if (ipcStore == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } - queueToUse = owner->getCommandQueuePtr(); - if (queueToUse == NULL) { - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; + queueToUse = owner->getCommandQueuePtr(); + if (queueToUse == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) { - if (reply->getSender() != lastTarget) { - return HasReturnvaluesIF::RETURN_FAILED; - } - switch (reply->getCommand()) { - case ActionMessage::COMPLETION_SUCCESS: - commandCount--; - owner->completionSuccessfulReceived(ActionMessage::getActionId(reply)); - return HasReturnvaluesIF::RETURN_OK; - case ActionMessage::COMPLETION_FAILED: - commandCount--; - owner->completionFailedReceived(ActionMessage::getActionId(reply), - ActionMessage::getReturnCode(reply)); - return HasReturnvaluesIF::RETURN_OK; - case ActionMessage::STEP_SUCCESS: - owner->stepSuccessfulReceived(ActionMessage::getActionId(reply), - ActionMessage::getStep(reply)); - return HasReturnvaluesIF::RETURN_OK; - case ActionMessage::STEP_FAILED: - commandCount--; - owner->stepFailedReceived(ActionMessage::getActionId(reply), - ActionMessage::getStep(reply), - ActionMessage::getReturnCode(reply)); - return HasReturnvaluesIF::RETURN_OK; - case ActionMessage::DATA_REPLY: - extractDataForOwner(ActionMessage::getActionId(reply), - ActionMessage::getStoreId(reply)); - return HasReturnvaluesIF::RETURN_OK; - default: - return HasReturnvaluesIF::RETURN_FAILED; - } + if (reply->getSender() != lastTarget) { + return HasReturnvaluesIF::RETURN_FAILED; + } + switch (reply->getCommand()) { + case ActionMessage::COMPLETION_SUCCESS: + commandCount--; + owner->completionSuccessfulReceived(ActionMessage::getActionId(reply)); + return HasReturnvaluesIF::RETURN_OK; + case ActionMessage::COMPLETION_FAILED: + commandCount--; + owner->completionFailedReceived(ActionMessage::getActionId(reply), + ActionMessage::getReturnCode(reply)); + return HasReturnvaluesIF::RETURN_OK; + case ActionMessage::STEP_SUCCESS: + owner->stepSuccessfulReceived(ActionMessage::getActionId(reply), + ActionMessage::getStep(reply)); + return HasReturnvaluesIF::RETURN_OK; + case ActionMessage::STEP_FAILED: + commandCount--; + owner->stepFailedReceived(ActionMessage::getActionId(reply), + ActionMessage::getStep(reply), + ActionMessage::getReturnCode(reply)); + return HasReturnvaluesIF::RETURN_OK; + case ActionMessage::DATA_REPLY: + extractDataForOwner(ActionMessage::getActionId(reply), + ActionMessage::getStoreId(reply)); + return HasReturnvaluesIF::RETURN_OK; + default: + return HasReturnvaluesIF::RETURN_FAILED; + } } uint8_t CommandActionHelper::getCommandCount() const { - return commandCount; + return commandCount; } void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) { - const uint8_t * data = NULL; - size_t size = 0; - ReturnValue_t result = ipcStore->getData(storeId, &data, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { - return; - } - owner->dataReceived(actionId, data, size); - ipcStore->deleteData(storeId); + const uint8_t * data = NULL; + size_t size = 0; + ReturnValue_t result = ipcStore->getData(storeId, &data, &size); + if (result != HasReturnvaluesIF::RETURN_OK) { + return; + } + owner->dataReceived(actionId, data, size); + ipcStore->deleteData(storeId); } diff --git a/action/CommandActionHelper.h b/action/CommandActionHelper.h index cfed8c94..96ef1763 100644 --- a/action/CommandActionHelper.h +++ b/action/CommandActionHelper.h @@ -11,26 +11,26 @@ class CommandsActionsIF; class CommandActionHelper { - friend class CommandsActionsIF; + friend class CommandsActionsIF; public: - CommandActionHelper(CommandsActionsIF* owner); - virtual ~CommandActionHelper(); - ReturnValue_t commandAction(object_id_t commandTo, - ActionId_t actionId, const uint8_t* data, uint32_t size); - ReturnValue_t commandAction(object_id_t commandTo, - ActionId_t actionId, SerializeIF* data); - ReturnValue_t initialize(); - ReturnValue_t handleReply(CommandMessage* reply); - uint8_t getCommandCount() const; + CommandActionHelper(CommandsActionsIF* owner); + virtual ~CommandActionHelper(); + ReturnValue_t commandAction(object_id_t commandTo, + ActionId_t actionId, const uint8_t* data, uint32_t size); + ReturnValue_t commandAction(object_id_t commandTo, + ActionId_t actionId, SerializeIF* data); + ReturnValue_t initialize(); + ReturnValue_t handleReply(CommandMessage* reply); + uint8_t getCommandCount() const; private: - CommandsActionsIF* owner; - MessageQueueIF* queueToUse; - StorageManagerIF* ipcStore; - uint8_t commandCount; - MessageQueueId_t lastTarget; - void extractDataForOwner(ActionId_t actionId, store_address_t storeId); - ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId, - store_address_t storeId); + CommandsActionsIF* owner; + MessageQueueIF* queueToUse; + StorageManagerIF* ipcStore; + uint8_t commandCount; + MessageQueueId_t lastTarget; + void extractDataForOwner(ActionId_t actionId, store_address_t storeId); + ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId, + store_address_t storeId); }; #endif /* COMMANDACTIONHELPER_H_ */ diff --git a/action/CommandsActionsIF.h b/action/CommandsActionsIF.h index 491bfc70..fe7e856c 100644 --- a/action/CommandsActionsIF.h +++ b/action/CommandsActionsIF.h @@ -15,22 +15,22 @@ * - replyReceived(id, step, cause) (if cause == OK, it's a success). */ class CommandsActionsIF { - friend class CommandActionHelper; + friend class CommandActionHelper; public: - static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF; - static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1); - static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2); - virtual ~CommandsActionsIF() {} - virtual MessageQueueIF* getCommandQueuePtr() = 0; + static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF; + static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1); + static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2); + virtual ~CommandsActionsIF() {} + virtual MessageQueueIF* getCommandQueuePtr() = 0; protected: - virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0; - virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, - ReturnValue_t returnCode) = 0; - virtual void dataReceived(ActionId_t actionId, const uint8_t* data, - uint32_t size) = 0; - virtual void completionSuccessfulReceived(ActionId_t actionId) = 0; - virtual void completionFailedReceived(ActionId_t actionId, - ReturnValue_t returnCode) = 0; + virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0; + virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, + ReturnValue_t returnCode) = 0; + virtual void dataReceived(ActionId_t actionId, const uint8_t* data, + uint32_t size) = 0; + virtual void completionSuccessfulReceived(ActionId_t actionId) = 0; + virtual void completionFailedReceived(ActionId_t actionId, + ReturnValue_t returnCode) = 0; }; diff --git a/action/HasActionsIF.h b/action/HasActionsIF.h index 690f0369..056e674c 100644 --- a/action/HasActionsIF.h +++ b/action/HasActionsIF.h @@ -35,28 +35,28 @@ */ class HasActionsIF { public: - static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF; - static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1); - static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2); - static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3); - static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4); - virtual ~HasActionsIF() { } - /** - * Function to get the MessageQueueId_t of the implementing object - * @return MessageQueueId_t of the object - */ - virtual MessageQueueId_t getCommandQueue() const = 0; - /** - * Execute or initialize the execution of a certain function. - * The ActionHelpers will execute this function and behave differently - * depending on the returnvalue. - * - * @return - * -@c EXECUTION_FINISHED Finish reply will be generated - * -@c Not RETURN_OK Step failure reply will be generated - */ - virtual ReturnValue_t executeAction(ActionId_t actionId, - MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0; + static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF; + static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1); + static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2); + static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3); + static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4); + virtual ~HasActionsIF() { } + /** + * Function to get the MessageQueueId_t of the implementing object + * @return MessageQueueId_t of the object + */ + virtual MessageQueueId_t getCommandQueue() const = 0; + /** + * Execute or initialize the execution of a certain function. + * The ActionHelpers will execute this function and behave differently + * depending on the returnvalue. + * + * @return + * -@c EXECUTION_FINISHED Finish reply will be generated + * -@c Not RETURN_OK Step failure reply will be generated + */ + virtual ReturnValue_t executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0; }; diff --git a/action/SimpleActionHelper.cpp b/action/SimpleActionHelper.cpp index af57736c..f77d0147 100644 --- a/action/SimpleActionHelper.cpp +++ b/action/SimpleActionHelper.cpp @@ -2,74 +2,74 @@ #include "SimpleActionHelper.h" SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner, - MessageQueueIF* useThisQueue) : - ActionHelper(setOwner, useThisQueue), isExecuting(false) { + MessageQueueIF* useThisQueue) : + ActionHelper(setOwner, useThisQueue), isExecuting(false) { } SimpleActionHelper::~SimpleActionHelper() { } void SimpleActionHelper::step(ReturnValue_t result) { - // STEP_OFFESET is subtracted to compensate for adding offset in base - // method, which is not necessary here. - ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction, - result); - if (result != HasReturnvaluesIF::RETURN_OK) { - resetHelper(); - } + // STEP_OFFESET is subtracted to compensate for adding offset in base + // method, which is not necessary here. + ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction, + result); + if (result != HasReturnvaluesIF::RETURN_OK) { + resetHelper(); + } } void SimpleActionHelper::finish(ReturnValue_t result) { - ActionHelper::finish(lastCommander, lastAction, result); - resetHelper(); + ActionHelper::finish(lastCommander, lastAction, result); + resetHelper(); } ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) { - return ActionHelper::reportData(lastCommander, lastAction, data); + return ActionHelper::reportData(lastCommander, lastAction, data); } void SimpleActionHelper::resetHelper() { - stepCount = 0; - isExecuting = false; - lastAction = 0; - lastCommander = 0; + stepCount = 0; + isExecuting = false; + lastAction = 0; + lastCommander = 0; } void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, - ActionId_t actionId, store_address_t dataAddress) { - CommandMessage reply; - if (isExecuting) { - ipcStore->deleteData(dataAddress); - ActionMessage::setStepReply(&reply, actionId, 0, - HasActionsIF::IS_BUSY); - queueToUse->sendMessage(commandedBy, &reply); - } - const uint8_t* dataPtr = NULL; - size_t size = 0; - ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { - ActionMessage::setStepReply(&reply, actionId, 0, result); - queueToUse->sendMessage(commandedBy, &reply); - return; - } - lastCommander = commandedBy; - lastAction = actionId; - result = owner->executeAction(actionId, commandedBy, dataPtr, size); - ipcStore->deleteData(dataAddress); - switch (result) { - case HasReturnvaluesIF::RETURN_OK: - isExecuting = true; - stepCount++; - break; - case HasActionsIF::EXECUTION_FINISHED: - ActionMessage::setCompletionReply(&reply, actionId, - HasReturnvaluesIF::RETURN_OK); - queueToUse->sendMessage(commandedBy, &reply); - break; - default: - ActionMessage::setStepReply(&reply, actionId, 0, result); - queueToUse->sendMessage(commandedBy, &reply); - break; - } + ActionId_t actionId, store_address_t dataAddress) { + CommandMessage reply; + if (isExecuting) { + ipcStore->deleteData(dataAddress); + ActionMessage::setStepReply(&reply, actionId, 0, + HasActionsIF::IS_BUSY); + queueToUse->sendMessage(commandedBy, &reply); + } + const uint8_t* dataPtr = NULL; + size_t size = 0; + ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); + if (result != HasReturnvaluesIF::RETURN_OK) { + ActionMessage::setStepReply(&reply, actionId, 0, result); + queueToUse->sendMessage(commandedBy, &reply); + return; + } + lastCommander = commandedBy; + lastAction = actionId; + result = owner->executeAction(actionId, commandedBy, dataPtr, size); + ipcStore->deleteData(dataAddress); + switch (result) { + case HasReturnvaluesIF::RETURN_OK: + isExecuting = true; + stepCount++; + break; + case HasActionsIF::EXECUTION_FINISHED: + ActionMessage::setCompletionReply(&reply, actionId, + HasReturnvaluesIF::RETURN_OK); + queueToUse->sendMessage(commandedBy, &reply); + break; + default: + ActionMessage::setStepReply(&reply, actionId, 0, result); + queueToUse->sendMessage(commandedBy, &reply); + break; + } } diff --git a/action/SimpleActionHelper.h b/action/SimpleActionHelper.h index 1f35d9fd..7c6c4e00 100644 --- a/action/SimpleActionHelper.h +++ b/action/SimpleActionHelper.h @@ -4,27 +4,27 @@ #include "ActionHelper.h" /** - * @brief This is an action helper which is only able to service one action - * at a time but remembers last commander and last action which - * simplifies usage + * @brief This is an action helper which is only able to service one action + * at a time but remembers last commander and last action which + * simplifies usage */ class SimpleActionHelper: public ActionHelper { public: - SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); - virtual ~SimpleActionHelper(); - void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); - void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); - ReturnValue_t reportData(SerializeIF* data); + SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); + virtual ~SimpleActionHelper(); + void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + ReturnValue_t reportData(SerializeIF* data); protected: - void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, - store_address_t dataAddress); - virtual void resetHelper(); + void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, + store_address_t dataAddress); + virtual void resetHelper(); private: - bool isExecuting; - MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE; - ActionId_t lastAction = 0; - uint8_t stepCount = 0; + bool isExecuting; + MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE; + ActionId_t lastAction = 0; + uint8_t stepCount = 0; }; #endif /* SIMPLEACTIONHELPER_H_ */