refactored and tested hosted and linux task IF
This commit is contained in:
@ -1,26 +1,21 @@
|
||||
#include "fsfw/osal/linux/FixedTimeslotTask.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <climits>
|
||||
|
||||
#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<uint32_t>(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<FixedTimeslotTask*>(arg));
|
||||
auto* originalTask(reinterpret_cast<FixedTimeslotTask*>(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<ExecutableObjectIF>(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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -1,35 +1,27 @@
|
||||
#include "fsfw/osal/linux/PeriodicPosixTask.h"
|
||||
#include "PeriodicPosixTask.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <set>
|
||||
|
||||
#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<PeriodicPosixTask*>(arg));
|
||||
auto* originalTask(reinterpret_cast<PeriodicPosixTask*>(arg));
|
||||
// The task's functionality is called.
|
||||
originalTask->taskFunctionality();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) {
|
||||
return PosixThread::sleep(static_cast<uint64_t>(ms * 1000000));
|
||||
return PosixThread::sleep(static_cast<uint64_t>(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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) {
|
||||
|
Reference in New Issue
Block a user