refactor freeRTOS task components

This commit is contained in:
Robin Müller 2022-05-27 00:31:20 +02:00 committed by Gitea
parent 347714d53a
commit 7292b02907
5 changed files with 47 additions and 136 deletions

View File

@ -1,27 +1,25 @@
#include "fsfw/osal/freertos/FixedTimeslotTask.h" #include "fsfw/osal/freertos/FixedTimeslotTask.h"
#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/serviceinterface.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
uint32_t FixedTimeslotTask::MISSED_DEADLINE_COUNT = 0;
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority,
TaskStackSize setStack, TaskPeriod overallPeriod, TaskStackSize setStack, TaskPeriod period,
void (*setDeadlineMissedFunc)()) TaskDeadlineMissedFunction dlmFunc_)
: started(false), handle(nullptr), pst(overallPeriod * 1000) { : FixedTimeslotTaskBase(period, dlmFunc_), started(false), handle(nullptr) {
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
// All additional attributes are applied to the object.
this->deadlineMissedFunc = setDeadlineMissedFunc;
} }
FixedTimeslotTask::~FixedTimeslotTask() {} FixedTimeslotTask::~FixedTimeslotTask() = default;
void FixedTimeslotTask::taskEntryPoint(void* argument) { void FixedTimeslotTask::taskEntryPoint(void* argument) {
// The argument is re-interpreted as FixedTimeslotTask. The Task object is // The argument is re-interpreted as FixedTimeslotTask. The Task object is
// global, so it is found from any place. // global, so it is found from any place.
FixedTimeslotTask* originalTask(reinterpret_cast<FixedTimeslotTask*>(argument)); auto* originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
/* Task should not start until explicitly requested, /* Task should not start until explicitly requested,
* but in FreeRTOS, tasks start as soon as they are created if the scheduler * but in FreeRTOS, tasks start as soon as they are created if the scheduler
* is running but not if the scheduler is not running. * is running but not if the scheduler is not running.
@ -32,21 +30,23 @@ void FixedTimeslotTask::taskEntryPoint(void* argument) {
* can continue */ * can continue */
if (not originalTask->started) { if (not originalTask->started) {
vTaskSuspend(NULL); vTaskSuspend(nullptr);
} }
originalTask->taskFunctionality(); originalTask->taskFunctionality();
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Polling task " << originalTask->handle << " returned from taskFunctionality." sif::debug << "Polling task " << originalTask->handle << " returned from taskFunctionality."
<< std::endl; << std::endl;
#else
sif::printDebug("Polling task returned from taskFunctionality\n");
#endif #endif
} }
void FixedTimeslotTask::missedDeadlineCounter() { void FixedTimeslotTask::missedDeadlineCounter() {
FixedTimeslotTask::deadlineMissedCount++; FixedTimeslotTask::MISSED_DEADLINE_COUNT++;
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { if (FixedTimeslotTask::MISSED_DEADLINE_COUNT % 10 == 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines." sif::error << "PST missed " << FixedTimeslotTask::MISSED_DEADLINE_COUNT << " deadlines"
<< std::endl; << std::endl;
#endif #endif
} }
@ -63,31 +63,12 @@ ReturnValue_t FixedTimeslotTask::startTask() {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, [[noreturn]] void FixedTimeslotTask::taskFunctionality() {
int8_t executionStep) {
ExecutableObjectIF* handler = ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
if (handler != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep, handler, 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 // A local iterator for the Polling Sequence Table is created to find the
// start time for the first entry. // start time for the first entry.
auto slotListIter = pst.current; auto slotListIter = pollingSeqTable.current;
pst.intializeSequenceAfterTaskCreation(); pollingSeqTable.intializeSequenceAfterTaskCreation();
// The start time for the first entry is read. // The start time for the first entry is read.
uint32_t intervalMs = slotListIter->pollingTimeMs; uint32_t intervalMs = slotListIter->pollingTimeMs;
@ -108,10 +89,10 @@ void FixedTimeslotTask::taskFunctionality() {
/* Enter the loop that defines the task behavior. */ /* Enter the loop that defines the task behavior. */
for (;;) { for (;;) {
// The component for this slot is executed and the next one is chosen. // The component for this slot is executed and the next one is chosen.
this->pst.executeAndAdvance(); this->pollingSeqTable.executeAndAdvance();
if (not pst.slotFollowsImmediately()) { if (not pollingSeqTable.slotFollowsImmediately()) {
// Get the interval till execution of the next slot. // Get the interval till execution of the next slot.
intervalMs = this->pst.getIntervalToPreviousSlotMs(); intervalMs = this->pollingSeqTable.getIntervalToPreviousSlotMs();
interval = pdMS_TO_TICKS(intervalMs); interval = pdMS_TO_TICKS(intervalMs);
#if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10 #if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10
@ -132,8 +113,8 @@ void FixedTimeslotTask::taskFunctionality() {
} }
void FixedTimeslotTask::handleMissedDeadline() { void FixedTimeslotTask::handleMissedDeadline() {
if (deadlineMissedFunc != nullptr) { if (dlmFunc != nullptr) {
this->deadlineMissedFunc(); dlmFunc();
} }
} }

View File

@ -4,11 +4,11 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "FreeRTOSTaskIF.h" #include "FreeRTOSTaskIF.h"
#include "fsfw/tasks/FixedSlotSequence.h" #include "fsfw/tasks/FixedSlotSequence.h"
#include "fsfw/tasks/FixedTimeslotTaskIF.h" #include "fsfw/tasks/FixedTimeslotTaskBase.h"
#include "fsfw/tasks/Typedef.h" #include "fsfw/tasks/definitions.h"
#include "task.h" #include "task.h"
class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF { class FixedTimeslotTask : public FixedTimeslotTaskBase, public FreeRTOSTaskIF {
public: public:
/** /**
* Keep in mind that you need to call before vTaskStartScheduler()! * Keep in mind that you need to call before vTaskStartScheduler()!
@ -23,7 +23,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
* @return Pointer to the newly created task. * @return Pointer to the newly created task.
*/ */
FixedTimeslotTask(TaskName name, TaskPriority setPriority, TaskStackSize setStack, FixedTimeslotTask(TaskName name, TaskPriority setPriority, TaskStackSize setStack,
TaskPeriod overallPeriod, void (*setDeadlineMissedFunc)()); TaskPeriod overallPeriod, TaskDeadlineMissedFunction dlmFunc);
/** /**
* @brief The destructor of the class. * @brief The destructor of the class.
@ -32,9 +32,9 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
* initialization for the PST and the device handlers. This is done by * initialization for the PST and the device handlers. This is done by
* calling the PST's destructor. * calling the PST's destructor.
*/ */
virtual ~FixedTimeslotTask(void); ~FixedTimeslotTask() override;
ReturnValue_t startTask(void); ReturnValue_t startTask() 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 * It counts missedDeadlines and prints the number of missed deadlines
@ -44,14 +44,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
/** /**
* A helper variable to count missed deadlines. * A helper variable to count missed deadlines.
*/ */
static uint32_t deadlineMissedCount; static uint32_t MISSED_DEADLINE_COUNT;
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep) override;
uint32_t getPeriodMs() const override;
ReturnValue_t checkSequence() const override;
ReturnValue_t sleepFor(uint32_t ms) override; ReturnValue_t sleepFor(uint32_t ms) override;
@ -61,17 +54,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
bool started; bool started;
TaskHandle_t handle; TaskHandle_t handle;
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 for a new task. * @brief This is the entry point for a new task.
* @details * @details
@ -88,7 +70,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
* 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.
*/ */
void taskFunctionality(void); [[noreturn]] void taskFunctionality();
void handleMissedDeadline(); void handleMissedDeadline();
}; };

View File

@ -6,11 +6,11 @@
class FreeRTOSTaskIF { class FreeRTOSTaskIF {
public: public:
virtual ~FreeRTOSTaskIF() {} virtual ~FreeRTOSTaskIF() = default;
virtual TaskHandle_t getTaskHandle() = 0; virtual TaskHandle_t getTaskHandle() = 0;
protected: protected:
bool checkMissedDeadline(const TickType_t xLastWakeTime, const TickType_t interval) { static bool checkMissedDeadline(const TickType_t xLastWakeTime, const TickType_t interval) {
/* Check whether deadline was missed while also taking overflows /* Check whether deadline was missed while also taking overflows
* into account. Drawing this on paper with a timeline helps to understand * into account. Drawing this on paper with a timeline helps to understand
* it. */ * it. */

View File

@ -5,8 +5,8 @@
#include "fsfw/tasks/ExecutableObjectIF.h" #include "fsfw/tasks/ExecutableObjectIF.h"
PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack, PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
TaskPeriod setPeriod, TaskDeadlineMissedFunction deadlineMissedFunc) TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_)
: started(false), handle(NULL), period(setPeriod), deadlineMissedFunc(deadlineMissedFunc) { : PeriodicTaskBase(setStack, dlmFunc_), started(false), handle(nullptr), period(setPeriod) {
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
BaseType_t status = xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); BaseType_t status = xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
if (status != pdPASS) { if (status != pdPASS) {
@ -18,14 +18,13 @@ PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStack
} }
} }
PeriodicTask::~PeriodicTask(void) { // Do not delete objects, we were responsible for ptrs only.
// Do not delete objects, we were responsible for ptrs only. PeriodicTask::~PeriodicTask() = default;
}
void PeriodicTask::taskEntryPoint(void* argument) { void PeriodicTask::taskEntryPoint(void* argument) {
// The argument is re-interpreted as PeriodicTask. The Task object is // The argument is re-interpreted as PeriodicTask. The Task object is
// global, so it is found from any place. // global, so it is found from any place.
PeriodicTask* originalTask(reinterpret_cast<PeriodicTask*>(argument)); auto* originalTask(reinterpret_cast<PeriodicTask*>(argument));
/* Task should not start until explicitly requested, /* Task should not start until explicitly requested,
* but in FreeRTOS, tasks start as soon as they are created if the scheduler * but in FreeRTOS, tasks start as soon as they are created if the scheduler
* is running but not if the scheduler is not running. * is running but not if the scheduler is not running.
@ -36,7 +35,7 @@ void PeriodicTask::taskEntryPoint(void* argument) {
* can continue */ * can continue */
if (not originalTask->started) { if (not originalTask->started) {
vTaskSuspend(NULL); vTaskSuspend(nullptr);
} }
originalTask->taskFunctionality(); originalTask->taskFunctionality();
@ -62,7 +61,7 @@ ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void PeriodicTask::taskFunctionality() { [[noreturn]] void PeriodicTask::taskFunctionality() {
TickType_t xLastWakeTime; TickType_t xLastWakeTime;
const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.); const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.);
@ -95,32 +94,10 @@ void PeriodicTask::taskFunctionality() {
} }
} }
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
return addComponent(newObject);
}
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
if (object == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
"it implement ExecutableObjectIF"
<< std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
objectList.push_back(object);
object->setTaskIF(this);
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t PeriodicTask::getPeriodMs() const { return period * 1000; }
TaskHandle_t PeriodicTask::getTaskHandle() { return handle; } TaskHandle_t PeriodicTask::getTaskHandle() { return handle; }
void PeriodicTask::handleMissedDeadline() { void PeriodicTask::handleMissedDeadline() {
if (deadlineMissedFunc != nullptr) { if (dlmFunc != nullptr) {
this->deadlineMissedFunc(); dlmFunc();
} }
} }

View File

@ -6,8 +6,8 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "FreeRTOSTaskIF.h" #include "FreeRTOSTaskIF.h"
#include "fsfw/objectmanager/ObjectManagerIF.h" #include "fsfw/objectmanager/ObjectManagerIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h" #include "fsfw/tasks/PeriodicTaskBase.h"
#include "fsfw/tasks/Typedef.h" #include "fsfw/tasks/definitions.h"
#include "task.h" #include "task.h"
class ExecutableObjectIF; class ExecutableObjectIF;
@ -17,7 +17,7 @@ class ExecutableObjectIF;
* periodic activities of multiple objects. * periodic activities of multiple objects.
* @ingroup task_handling * @ingroup task_handling
*/ */
class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF { class PeriodicTask : public PeriodicTaskBase, public FreeRTOSTaskIF {
public: public:
/** /**
* Keep in Mind that you need to call before this vTaskStartScheduler()! * Keep in Mind that you need to call before this vTaskStartScheduler()!
@ -43,7 +43,7 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
* @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.
@ -53,27 +53,6 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
* to the system call. * to the system call.
*/ */
ReturnValue_t startTask() override; ReturnValue_t startTask() override;
/**
* Adds an object to the list of objects to be executed.
* The objects are executed in the order added.
* @param object Id of the object to add.
* @return
* -@c RETURN_OK on success
* -@c RETURN_FAILED if the object could not be added.
*/
ReturnValue_t addComponent(object_id_t object) override;
/**
* Adds an object to the list of objects to be executed.
* The objects are executed in the order added.
* @param object Id of the object to add.
* @return
* -@c RETURN_OK on success
* -@c RETURN_FAILED if the object could not be added.
*/
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
uint32_t getPeriodMs() const override;
ReturnValue_t sleepFor(uint32_t ms) override; ReturnValue_t sleepFor(uint32_t ms) override;
@ -96,15 +75,7 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
* It is expressed in clock ticks. * It is expressed in clock ticks.
*/ */
TaskPeriod period; TaskPeriod period;
/**
* @brief The pointer to the deadline-missed function.
* @details
* This pointer stores the function that is executed if the task's deadline
* is missed so each may react individually on a timing failure.
* The pointer may be NULL, then nothing happens on missing the deadline.
* The deadline is equal to the next execution of the periodic task.
*/
void (*deadlineMissedFunc)(void);
/** /**
* @brief This is the function executed in the new task's context. * @brief This is the function executed in the new task's context.
* @details * @details
@ -125,7 +96,7 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
* the next period. * the next period.
* On missing the deadline, the deadlineMissedFunction is executed. * On missing the deadline, the deadlineMissedFunction is executed.
*/ */
void taskFunctionality(void); [[noreturn]] void taskFunctionality();
void handleMissedDeadline(); void handleMissedDeadline();
}; };