EIVE upstream #29
@ -3,9 +3,7 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "fsfw/ipc/MutexFactory.h"
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/osal/host/FixedTimeslotTask.h"
|
|
||||||
#include "fsfw/osal/host/Mutex.h"
|
#include "fsfw/osal/host/Mutex.h"
|
||||||
#include "fsfw/osal/host/taskHelpers.h"
|
#include "fsfw/osal/host/taskHelpers.h"
|
||||||
#include "fsfw/platform.h"
|
#include "fsfw/platform.h"
|
||||||
@ -23,11 +21,7 @@
|
|||||||
FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority,
|
FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority,
|
||||||
TaskStackSize setStack, TaskPeriod setPeriod,
|
TaskStackSize setStack, TaskPeriod setPeriod,
|
||||||
TaskDeadlineMissedFunction dlmFunc_)
|
TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: started(false),
|
: FixedTimeslotTaskBase(setPeriod, dlmFunc_), started(false), taskName(name) {
|
||||||
pollingSeqTable(static_cast<uint32_t>(setPeriod * 1000)),
|
|
||||||
taskName(name),
|
|
||||||
period(setPeriod),
|
|
||||||
dlmFunc(dlmFunc_) {
|
|
||||||
// It is propably possible to set task priorities by using the native
|
// It is propably possible to set task priorities by using the native
|
||||||
// task handles for Windows / Linux
|
// task handles for Windows / Linux
|
||||||
mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this);
|
mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this);
|
||||||
@ -80,7 +74,7 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedTimeslotTask::taskFunctionality() {
|
[[noreturn]] void FixedTimeslotTask::taskFunctionality() {
|
||||||
pollingSeqTable.intializeSequenceAfterTaskCreation();
|
pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||||
|
|
||||||
// A local iterator for the Polling Sequence Table is created to
|
// A local iterator for the Polling Sequence Table is created to
|
||||||
@ -106,8 +100,11 @@ void FixedTimeslotTask::taskFunctionality() {
|
|||||||
// we need to wait before executing the current slot
|
// we need to wait before executing the current slot
|
||||||
// this gives us the time to wait:
|
// this gives us the time to wait:
|
||||||
interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs());
|
interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs());
|
||||||
delayForInterval(¤tStartTime, interval);
|
if (not delayForInterval(¤tStartTime, interval)) {
|
||||||
// TODO deadline missed check
|
if (dlmFunc != nullptr) {
|
||||||
|
dlmFunc();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,10 +129,6 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotT
|
|||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::checkSequence() { return pollingSeqTable.checkSequence(); }
|
|
||||||
|
|
||||||
uint32_t FixedTimeslotTask::getPeriodMs() const { return static_cast<uint32_t>(period * 1000); }
|
|
||||||
|
|
||||||
bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) {
|
bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) {
|
||||||
bool shouldDelay = false;
|
bool shouldDelay = false;
|
||||||
// Get current wakeup time
|
// Get current wakeup time
|
||||||
@ -175,5 +168,3 @@ bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chr
|
|||||||
(*previousWakeTimeMs) = currentStartTime;
|
(*previousWakeTimeMs) = currentStartTime;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FixedTimeslotTask::isEmpty() const { return pollingSeqTable.isEmpty(); }
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||||
#include "fsfw/tasks/FixedSlotSequence.h"
|
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||||
#include "fsfw/tasks/FixedTimeslotTaskIF.h"
|
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||||
#include "fsfw/tasks/definitions.h"
|
#include "fsfw/tasks/definitions.h"
|
||||||
|
|
||||||
class ExecutableObjectIF;
|
class ExecutableObjectIF;
|
||||||
@ -19,7 +19,7 @@ class ExecutableObjectIF;
|
|||||||
* @details
|
* @details
|
||||||
* @ingroup task_handling
|
* @ingroup task_handling
|
||||||
*/
|
*/
|
||||||
class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
class FixedTimeslotTask : public FixedTimeslotTaskBase {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Standard constructor of the class.
|
* @brief Standard constructor of the class.
|
||||||
@ -57,14 +57,10 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
|||||||
* @param executionStep
|
* @param executionStep
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) override;
|
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||||
|
int8_t executionStep) override;
|
||||||
ReturnValue_t checkSequence() override;
|
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
uint32_t getPeriodMs() const override;
|
|
||||||
|
|
||||||
bool isEmpty() const override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using chron_ms = std::chrono::milliseconds;
|
using chron_ms = std::chrono::milliseconds;
|
||||||
@ -74,21 +70,10 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
|||||||
std::thread mainThread;
|
std::thread mainThread;
|
||||||
std::atomic<bool> terminateThread{false};
|
std::atomic<bool> terminateThread{false};
|
||||||
|
|
||||||
//! Polling sequence table which contains the object to execute
|
|
||||||
//! and information like the timeslots and the passed execution step.
|
|
||||||
FixedSlotSequence pollingSeqTable;
|
|
||||||
|
|
||||||
std::condition_variable initCondition;
|
std::condition_variable initCondition;
|
||||||
std::mutex initMutex;
|
std::mutex initMutex;
|
||||||
std::string taskName;
|
std::string taskName;
|
||||||
/**
|
|
||||||
* @brief The period of the task.
|
|
||||||
* @details
|
|
||||||
* The period determines the frequency of the task's execution.
|
|
||||||
* It is expressed in clock ticks.
|
|
||||||
*/
|
|
||||||
TaskPeriod period;
|
|
||||||
TaskDeadlineMissedFunction dlmFunc = nullptr;
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the function executed in the new task's context.
|
* @brief This is the function executed in the new task's context.
|
||||||
* @details
|
* @details
|
||||||
@ -108,7 +93,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
|||||||
* the checkAndRestartPeriod system call blocks the task until the next
|
* the checkAndRestartPeriod system call blocks the task until the next
|
||||||
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
||||||
*/
|
*/
|
||||||
void taskFunctionality();
|
[[noreturn]] void taskFunctionality();
|
||||||
|
|
||||||
static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval);
|
static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval);
|
||||||
};
|
};
|
||||||
|
@ -3,13 +3,10 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "fsfw/ipc/MutexFactory.h"
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
|
||||||
#include "fsfw/osal/host/Mutex.h"
|
#include "fsfw/osal/host/Mutex.h"
|
||||||
#include "fsfw/osal/host/taskHelpers.h"
|
#include "fsfw/osal/host/taskHelpers.h"
|
||||||
#include "fsfw/platform.h"
|
#include "fsfw/platform.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
|
||||||
|
|
||||||
#if defined(PLATFORM_WIN)
|
#if defined(PLATFORM_WIN)
|
||||||
#include <processthreadsapi.h>
|
#include <processthreadsapi.h>
|
||||||
@ -33,7 +30,7 @@ PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStack
|
|||||||
tasks::insertTaskName(mainThread.get_id(), taskName);
|
tasks::insertTaskName(mainThread.get_id(), taskName);
|
||||||
}
|
}
|
||||||
|
|
||||||
PeriodicTask::~PeriodicTask(void) {
|
PeriodicTask::~PeriodicTask() {
|
||||||
// Do not delete objects, we were responsible for ptrs only.
|
// Do not delete objects, we were responsible for ptrs only.
|
||||||
terminateThread = true;
|
terminateThread = true;
|
||||||
if (mainThread.joinable()) {
|
if (mainThread.joinable()) {
|
||||||
@ -42,7 +39,7 @@ PeriodicTask::~PeriodicTask(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PeriodicTask::taskEntryPoint(void* argument) {
|
void PeriodicTask::taskEntryPoint(void* argument) {
|
||||||
PeriodicTask* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
auto* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||||
|
|
||||||
if (not originalTask->started) {
|
if (not originalTask->started) {
|
||||||
// we have to suspend/block here until the task is started.
|
// we have to suspend/block here until the task is started.
|
||||||
@ -80,8 +77,6 @@ void PeriodicTask::taskFunctionality() {
|
|||||||
std::chrono::milliseconds periodChrono(static_cast<uint32_t>(period * 1000));
|
std::chrono::milliseconds periodChrono(static_cast<uint32_t>(period * 1000));
|
||||||
auto currentStartTime{std::chrono::duration_cast<std::chrono::milliseconds>(
|
auto currentStartTime{std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
std::chrono::system_clock::now().time_since_epoch())};
|
std::chrono::system_clock::now().time_since_epoch())};
|
||||||
auto nextStartTime{currentStartTime};
|
|
||||||
|
|
||||||
/* Enter the loop that defines the task behavior. */
|
/* Enter the loop that defines the task behavior. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (terminateThread.load()) {
|
if (terminateThread.load()) {
|
||||||
|
@ -39,7 +39,7 @@ class PeriodicTask : public PeriodicTaskBase {
|
|||||||
* @brief Currently, the executed object's lifetime is not coupled with
|
* @brief Currently, the executed object's lifetime is not coupled with
|
||||||
* the task object's lifetime, so the destructor is empty.
|
* the task object's lifetime, so the destructor is empty.
|
||||||
*/
|
*/
|
||||||
virtual ~PeriodicTask(void);
|
~PeriodicTask() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The method to start the task.
|
* @brief The method to start the task.
|
||||||
@ -48,9 +48,9 @@ class PeriodicTask : public PeriodicTaskBase {
|
|||||||
* The address of the task object is passed as an argument
|
* The address of the task object is passed as an argument
|
||||||
* to the system call.
|
* to the system call.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t startTask(void);
|
ReturnValue_t startTask() override;
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms);
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using chron_ms = std::chrono::milliseconds;
|
using chron_ms = std::chrono::milliseconds;
|
||||||
@ -81,9 +81,9 @@ class PeriodicTask : public PeriodicTaskBase {
|
|||||||
* the checkAndRestartPeriod system call blocks the task until the next
|
* the checkAndRestartPeriod system call blocks the task until the next
|
||||||
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
||||||
*/
|
*/
|
||||||
void taskFunctionality(void);
|
void taskFunctionality();
|
||||||
|
|
||||||
bool delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval);
|
static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PERIODICTASK_H_ */
|
#endif /* FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ */
|
||||||
|
@ -14,9 +14,9 @@ TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
|||||||
// Not used for the host implementation for now because C++ thread abstraction is used
|
// Not used for the host implementation for now because C++ thread abstraction is used
|
||||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0;
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0;
|
||||||
|
|
||||||
TaskFactory::TaskFactory() {}
|
TaskFactory::TaskFactory() = default;
|
||||||
|
|
||||||
TaskFactory::~TaskFactory() {}
|
TaskFactory::~TaskFactory() = default;
|
||||||
|
|
||||||
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
std::mutex nameMapLock;
|
std::mutex nameMapLock;
|
||||||
std::map<std::thread::id, std::string> taskNameMap;
|
std::map<std::thread::id, std::string> taskNameMap;
|
||||||
|
|
||||||
ReturnValue_t tasks::insertTaskName(std::thread::id threadId, std::string taskName) {
|
ReturnValue_t tasks::insertTaskName(std::thread::id threadId, const std::string& taskName) {
|
||||||
std::lock_guard<std::mutex> lg(nameMapLock);
|
std::lock_guard<std::mutex> lg(nameMapLock);
|
||||||
auto returnPair = taskNameMap.emplace(threadId, taskName);
|
auto returnPair = taskNameMap.emplace(threadId, taskName);
|
||||||
if (not returnPair.second) {
|
if (not returnPair.second) {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace tasks {
|
namespace tasks {
|
||||||
|
|
||||||
ReturnValue_t insertTaskName(std::thread::id threadId, std::string taskName);
|
ReturnValue_t insertTaskName(std::thread::id threadId, const std::string& taskName);
|
||||||
std::string getTaskName(std::thread::id threadId);
|
std::string getTaskName(std::thread::id threadId);
|
||||||
|
|
||||||
} // namespace tasks
|
} // namespace tasks
|
||||||
|
@ -1,26 +1,21 @@
|
|||||||
#include "fsfw/osal/linux/FixedTimeslotTask.h"
|
#include "fsfw/osal/linux/FixedTimeslotTask.h"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <climits>
|
||||||
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
||||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
|
||||||
|
|
||||||
FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_,
|
FixedTimeslotTask::FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
|
||||||
TaskPeriod periodSeconds_)
|
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: posixThread(name_, priority_, stackSize_),
|
: FixedTimeslotTaskBase(periodSeconds_, dlmFunc_),
|
||||||
pst(static_cast<uint32_t>(periodSeconds_ * 1000)),
|
posixThread(name_, priority_, stackSize_),
|
||||||
started(false) {}
|
started(false) {}
|
||||||
|
|
||||||
FixedTimeslotTask::~FixedTimeslotTask() {}
|
|
||||||
|
|
||||||
bool FixedTimeslotTask::isEmpty() const { return pst.isEmpty(); }
|
|
||||||
|
|
||||||
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
||||||
// The argument is re-interpreted as PollingTask.
|
// 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.
|
// The task's functionality is called.
|
||||||
originalTask->taskFunctionality();
|
originalTask->taskFunctionality();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -36,45 +31,25 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
|||||||
return PosixThread::sleep((uint64_t)ms * 1000000);
|
return PosixThread::sleep((uint64_t)ms * 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); }
|
[[noreturn]] void FixedTimeslotTask::taskFunctionality() {
|
||||||
|
|
||||||
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() {
|
|
||||||
// Like FreeRTOS pthreads are running as soon as they are created
|
// Like FreeRTOS pthreads are running as soon as they are created
|
||||||
if (!started) {
|
if (!started) {
|
||||||
posixThread.suspend();
|
posixThread.suspend();
|
||||||
}
|
}
|
||||||
|
|
||||||
pst.intializeSequenceAfterTaskCreation();
|
pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||||
|
|
||||||
// The start time for the first entry is read.
|
// The start time for the first entry is read.
|
||||||
uint64_t lastWakeTime = posixThread.getCurrentMonotonicTimeMs();
|
uint64_t lastWakeTime = PosixThread::getCurrentMonotonicTimeMs();
|
||||||
uint64_t interval = pst.getIntervalToNextSlotMs();
|
uint32_t interval = 0;
|
||||||
|
|
||||||
// The task's "infinite" inner loop is entered.
|
// The task's "infinite" inner loop is entered.
|
||||||
while (1) {
|
while (true) {
|
||||||
if (pst.slotFollowsImmediately()) {
|
if (pollingSeqTable.slotFollowsImmediately()) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
} else {
|
} else {
|
||||||
// The interval for the next polling slot is selected.
|
// 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.
|
// The period is checked and restarted with the new interval.
|
||||||
// If the deadline was missed, the deadlineMissedFunc is called.
|
// If the deadline was missed, the deadlineMissedFunc is called.
|
||||||
if (!PosixThread::delayUntil(&lastWakeTime, interval)) {
|
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.
|
// 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 "PosixThread.h"
|
||||||
#include "fsfw/tasks/FixedSlotSequence.h"
|
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||||
#include "fsfw/tasks/FixedTimeslotTaskIF.h"
|
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||||
#include "fsfw/tasks/definitions.h"
|
#include "fsfw/tasks/definitions.h"
|
||||||
|
|
||||||
class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
class FixedTimeslotTask : public FixedTimeslotTaskBase {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Create a generic periodic task.
|
* Create a generic periodic task.
|
||||||
@ -22,22 +22,14 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
|||||||
* @param period_
|
* @param period_
|
||||||
* @param deadlineMissedFunc_
|
* @param deadlineMissedFunc_
|
||||||
*/
|
*/
|
||||||
FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod periodSeconds_);
|
FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
|
||||||
virtual ~FixedTimeslotTask();
|
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_);
|
||||||
|
~FixedTimeslotTask() override = default;
|
||||||
|
|
||||||
ReturnValue_t startTask() override;
|
ReturnValue_t startTask() override;
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms) 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.
|
* This static function can be used as #deadlineMissedFunc.
|
||||||
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
|
* 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
|
* It links the functionalities provided by FixedSlotSequence with the
|
||||||
* OS's System Calls to keep the timing of the periods.
|
* OS's System Calls to keep the timing of the periods.
|
||||||
*/
|
*/
|
||||||
virtual void taskFunctionality();
|
[[noreturn]] virtual void taskFunctionality();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PosixThread posixThread;
|
PosixThread posixThread;
|
||||||
|
bool started;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the entry point in a new thread.
|
* @brief This is the entry point in a new thread.
|
||||||
@ -74,9 +67,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
|||||||
* arbitrary data.
|
* arbitrary data.
|
||||||
*/
|
*/
|
||||||
static void* taskEntryPoint(void* arg);
|
static void* taskEntryPoint(void* arg);
|
||||||
FixedSlotSequence pst;
|
|
||||||
|
|
||||||
bool started;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */
|
#endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */
|
||||||
|
@ -1,35 +1,27 @@
|
|||||||
#include "fsfw/osal/linux/PeriodicPosixTask.h"
|
#include "PeriodicPosixTask.h"
|
||||||
|
|
||||||
#include <cerrno>
|
#include "fsfw/serviceinterface.h"
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
|
||||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||||
|
|
||||||
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_,
|
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_,
|
||||||
TaskPeriod period_, TaskDeadlineMissedFunction dlMissedFunc_)
|
TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: PeriodicTaskBase(period_, dlMissedFunc_),
|
: PeriodicTaskBase(period_, dlmFunc_),
|
||||||
posixThread(name_, priority_, stackSize_),
|
posixThread(name_, priority_, stackSize_),
|
||||||
started(false) {}
|
started(false) {}
|
||||||
|
|
||||||
PeriodicPosixTask::~PeriodicPosixTask() {
|
|
||||||
// Not Implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
||||||
// The argument is re-interpreted as PollingTask.
|
// 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.
|
// The task's functionality is called.
|
||||||
originalTask->taskFunctionality();
|
originalTask->taskFunctionality();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) {
|
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()) {
|
if (isEmpty()) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
@ -38,24 +30,24 @@ ReturnValue_t PeriodicPosixTask::startTask(void) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeriodicPosixTask::taskFunctionality(void) {
|
[[noreturn]] void PeriodicPosixTask::taskFunctionality() {
|
||||||
if (not started) {
|
if (not started) {
|
||||||
posixThread.suspend();
|
posixThread.suspend();
|
||||||
}
|
}
|
||||||
|
|
||||||
initObjsAfterTaskCreation();
|
initObjsAfterTaskCreation();
|
||||||
|
|
||||||
uint64_t lastWakeTime = posixThread.getCurrentMonotonicTimeMs();
|
uint64_t lastWakeTime = PosixThread::getCurrentMonotonicTimeMs();
|
||||||
uint64_t periodMs = getPeriodMs();
|
uint64_t periodMs = getPeriodMs();
|
||||||
// The task's "infinite" inner loop is entered.
|
// The task's "infinite" inner loop is entered.
|
||||||
while (1) {
|
while (true) {
|
||||||
for (auto const& objOpCodePair : objectList) {
|
for (auto const& objOpCodePair : objectList) {
|
||||||
objOpCodePair.first->performOperation(objOpCodePair.second);
|
objOpCodePair.first->performOperation(objOpCodePair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not PosixThread::delayUntil(&lastWakeTime, periodMs)) {
|
if (not PosixThread::delayUntil(&lastWakeTime, periodMs)) {
|
||||||
if (this->deadlineMissedFunc != nullptr) {
|
if (dlmFunc != nullptr) {
|
||||||
this->deadlineMissedFunc();
|
dlmFunc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@ class PeriodicPosixTask : public PeriodicTaskBase {
|
|||||||
* @param deadlineMissedFunc_
|
* @param deadlineMissedFunc_
|
||||||
*/
|
*/
|
||||||
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_,
|
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_,
|
||||||
void (*deadlineMissedFunc_)());
|
TaskDeadlineMissedFunction dlmFunc_);
|
||||||
virtual ~PeriodicPosixTask();
|
~PeriodicPosixTask() override = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The method to start the task.
|
* @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
|
* will be blocked until the next period. On missing the deadline, the deadlineMissedFunction is
|
||||||
* executed.
|
* executed.
|
||||||
*/
|
*/
|
||||||
virtual void taskFunctionality(void);
|
[[noreturn]] virtual void taskFunctionality();
|
||||||
/**
|
/**
|
||||||
* @brief This is the entry point in a new thread.
|
* @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?
|
// TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
||||||
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
||||||
|
|
||||||
TaskFactory::~TaskFactory() {}
|
TaskFactory::~TaskFactory() = default;
|
||||||
|
|
||||||
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
||||||
|
|
||||||
@ -22,7 +22,8 @@ PeriodicTaskIF* TaskFactory::createPeriodicTask(
|
|||||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
|
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
|
||||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
||||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
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) {
|
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
target_sources(
|
target_sources(
|
||||||
${LIB_FSFW_NAME} PRIVATE FixedSequenceSlot.cpp FixedSlotSequence.cpp
|
${LIB_FSFW_NAME} PRIVATE FixedSequenceSlot.cpp FixedSlotSequence.cpp
|
||||||
PeriodicTaskBase.cpp)
|
PeriodicTaskBase.cpp FixedTimeslotTaskBase.cpp)
|
||||||
|
@ -35,7 +35,7 @@ class FixedSlotSequence {
|
|||||||
* @brief The constructor of the FixedSlotSequence object.
|
* @brief The constructor of the FixedSlotSequence object.
|
||||||
* @param setLength The period length, expressed in ms.
|
* @param setLength The period length, expressed in ms.
|
||||||
*/
|
*/
|
||||||
FixedSlotSequence(uint32_t setLengthMs);
|
explicit FixedSlotSequence(uint32_t setLengthMs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The destructor of the FixedSlotSequence object.
|
* @brief The destructor of the FixedSlotSequence object.
|
||||||
|
29
src/fsfw/tasks/FixedTimeslotTaskBase.cpp
Normal file
29
src/fsfw/tasks/FixedTimeslotTaskBase.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "FixedTimeslotTaskBase.h"
|
||||||
|
|
||||||
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
|
|
||||||
|
FixedTimeslotTaskBase::FixedTimeslotTaskBase(TaskPeriod period_,
|
||||||
|
TaskDeadlineMissedFunction dlmFunc_)
|
||||||
|
: pollingSeqTable(getPeriodMs()), period(period_), dlmFunc(dlmFunc_) {}
|
||||||
|
uint32_t FixedTimeslotTaskBase::getPeriodMs() const { return static_cast<uint32_t>(period * 1000); }
|
||||||
|
|
||||||
|
bool FixedTimeslotTaskBase::isEmpty() const { return pollingSeqTable.isEmpty(); }
|
||||||
|
|
||||||
|
ReturnValue_t FixedTimeslotTaskBase::checkSequence() { return pollingSeqTable.checkSequence(); }
|
||||||
|
|
||||||
|
ReturnValue_t FixedTimeslotTaskBase::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||||
|
int8_t executionStep) {
|
||||||
|
auto* executableObject = ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
|
||||||
|
if (executableObject != nullptr) {
|
||||||
|
pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, executableObject, this);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << componentId
|
||||||
|
<< std::setfill(' ') << " not found, not adding it to PST" << std::dec << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("Component 0x%08x not found, not adding it to PST\n");
|
||||||
|
#endif
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
44
src/fsfw/tasks/FixedTimeslotTaskBase.h
Normal file
44
src/fsfw/tasks/FixedTimeslotTaskBase.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H
|
||||||
|
#define FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H
|
||||||
|
|
||||||
|
#include "FixedSlotSequence.h"
|
||||||
|
#include "FixedTimeslotTaskIF.h"
|
||||||
|
#include "definitions.h"
|
||||||
|
|
||||||
|
class FixedTimeslotTaskBase : public FixedTimeslotTaskIF {
|
||||||
|
public:
|
||||||
|
explicit FixedTimeslotTaskBase(TaskPeriod period, TaskDeadlineMissedFunction dlmFunc = nullptr);
|
||||||
|
~FixedTimeslotTaskBase() override = default;
|
||||||
|
;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//! Polling sequence table which contains the object to execute
|
||||||
|
//! and information like the timeslots and the passed execution step.
|
||||||
|
FixedSlotSequence pollingSeqTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Period of task in floating point seconds
|
||||||
|
*/
|
||||||
|
TaskPeriod period;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The pointer to the deadline-missed function.
|
||||||
|
* @details
|
||||||
|
* This pointer stores the function that is executed if the task's deadline
|
||||||
|
* is missed. So, each may react individually on a timing failure.
|
||||||
|
* The pointer may be NULL, then nothing happens on missing the deadline.
|
||||||
|
* The deadline is equal to the next execution of the periodic task.
|
||||||
|
*/
|
||||||
|
TaskDeadlineMissedFunction dlmFunc = nullptr;
|
||||||
|
|
||||||
|
ReturnValue_t checkSequence() override;
|
||||||
|
|
||||||
|
[[nodiscard]] uint32_t getPeriodMs() const override;
|
||||||
|
|
||||||
|
[[nodiscard]] bool isEmpty() const override;
|
||||||
|
|
||||||
|
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||||
|
int8_t executionStep) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FSFW_EXAMPLE_HOSTED_FIXEDTIMESLOTTASKBASE_H
|
@ -11,7 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
class FixedTimeslotTaskIF : public PeriodicTaskIF {
|
class FixedTimeslotTaskIF : public PeriodicTaskIF {
|
||||||
public:
|
public:
|
||||||
virtual ~FixedTimeslotTaskIF() {}
|
~FixedTimeslotTaskIF() override = default;
|
||||||
|
|
||||||
static constexpr ReturnValue_t SLOT_LIST_EMPTY =
|
static constexpr ReturnValue_t SLOT_LIST_EMPTY =
|
||||||
HasReturnvaluesIF::makeReturnCode(CLASS_ID::FIXED_SLOT_TASK_IF, 0);
|
HasReturnvaluesIF::makeReturnCode(CLASS_ID::FIXED_SLOT_TASK_IF, 0);
|
||||||
|
@ -1,11 +1,21 @@
|
|||||||
#include "PeriodicTaskBase.h"
|
#include "PeriodicTaskBase.h"
|
||||||
|
|
||||||
#include <fsfw/objectmanager/ObjectManager.h>
|
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
PeriodicTaskBase::PeriodicTaskBase(TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_)
|
PeriodicTaskBase::PeriodicTaskBase(TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: period(period), dlmFunc(dlmFunc_) {}
|
: period(period_), dlmFunc(dlmFunc_) {
|
||||||
|
// Hints at configuration error
|
||||||
|
if (PeriodicTaskBase::getPeriodMs() <= 1) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "Passed task period 0 or smaller than 1 ms" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Passed task period 0 or smaller than 1ms\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t PeriodicTaskBase::getPeriodMs() const { return static_cast<uint32_t>(period * 1000); }
|
uint32_t PeriodicTaskBase::getPeriodMs() const { return static_cast<uint32_t>(period * 1000); }
|
||||||
|
|
||||||
@ -32,7 +42,7 @@ ReturnValue_t PeriodicTaskBase::initObjsAfterTaskCreation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PeriodicTaskBase::addComponent(object_id_t object, uint8_t opCode) {
|
ReturnValue_t PeriodicTaskBase::addComponent(object_id_t object, uint8_t opCode) {
|
||||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
auto* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
||||||
return addComponent(newObject, opCode);
|
return addComponent(newObject, opCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,14 +11,15 @@ class ExecutableObjectIF;
|
|||||||
|
|
||||||
class PeriodicTaskBase : public PeriodicTaskIF {
|
class PeriodicTaskBase : public PeriodicTaskIF {
|
||||||
public:
|
public:
|
||||||
PeriodicTaskBase(TaskPeriod period, TaskDeadlineMissedFunction deadlineMissedFunc = nullptr);
|
explicit PeriodicTaskBase(TaskPeriod period,
|
||||||
|
TaskDeadlineMissedFunction deadlineMissedFunc = nullptr);
|
||||||
|
|
||||||
ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override;
|
ReturnValue_t addComponent(object_id_t object, uint8_t opCode) override;
|
||||||
ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override;
|
ReturnValue_t addComponent(ExecutableObjectIF* object, uint8_t opCode) override;
|
||||||
|
|
||||||
uint32_t getPeriodMs() const override;
|
[[nodiscard]] uint32_t getPeriodMs() const override;
|
||||||
|
|
||||||
bool isEmpty() const override;
|
[[nodiscard]] bool isEmpty() const override;
|
||||||
|
|
||||||
ReturnValue_t initObjsAfterTaskCreation();
|
ReturnValue_t initObjsAfterTaskCreation();
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class PeriodicTaskIF {
|
|||||||
/**
|
/**
|
||||||
* @brief A virtual destructor as it is mandatory for interfaces.
|
* @brief A virtual destructor as it is mandatory for interfaces.
|
||||||
*/
|
*/
|
||||||
virtual ~PeriodicTaskIF() {}
|
virtual ~PeriodicTaskIF() = default;
|
||||||
/**
|
/**
|
||||||
* @brief With the startTask method, a created task can be started
|
* @brief With the startTask method, a created task can be started
|
||||||
* for the first time.
|
* for the first time.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
using TaskName = const char*;
|
using TaskName = const char*;
|
||||||
using TaskPriority = uint32_t;
|
using TaskPriority = int;
|
||||||
using TaskStackSize = size_t;
|
using TaskStackSize = size_t;
|
||||||
using TaskPeriod = double;
|
using TaskPeriod = double;
|
||||||
using TaskDeadlineMissedFunction = void (*)();
|
using TaskDeadlineMissedFunction = void (*)();
|
||||||
|
Loading…
Reference in New Issue
Block a user