2021-07-13 20:58:45 +02:00
|
|
|
#include "fsfw/osal/linux/FixedTimeslotTask.h"
|
2021-06-05 19:52:38 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
#include <limits.h>
|
|
|
|
|
2021-07-13 20:58:45 +02:00
|
|
|
#include "fsfw/objectmanager/ObjectManager.h"
|
|
|
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
2018-07-13 18:28:26 +02:00
|
|
|
|
|
|
|
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
|
|
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_,
|
2022-05-18 15:42:18 +02:00
|
|
|
TaskPeriod periodSeconds_)
|
|
|
|
: posixThread(name_, priority_, stackSize_),
|
|
|
|
pst(static_cast<uint32_t>(periodSeconds_ * 1000)),
|
|
|
|
started(false) {}
|
2018-07-13 18:28:26 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
FixedTimeslotTask::~FixedTimeslotTask() {}
|
2018-07-13 18:28:26 +02:00
|
|
|
|
2022-05-14 09:38:59 +02:00
|
|
|
bool FixedTimeslotTask::isEmpty() const { return pst.isEmpty(); }
|
|
|
|
|
2018-07-13 18:28:26 +02:00
|
|
|
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
2022-02-02 10:29:30 +01:00
|
|
|
// The argument is re-interpreted as PollingTask.
|
|
|
|
FixedTimeslotTask* originalTask(reinterpret_cast<FixedTimeslotTask*>(arg));
|
|
|
|
// The task's functionality is called.
|
|
|
|
originalTask->taskFunctionality();
|
|
|
|
return nullptr;
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t FixedTimeslotTask::startTask() {
|
2022-02-02 10:29:30 +01:00
|
|
|
started = true;
|
2022-05-18 15:42:18 +02:00
|
|
|
posixThread.createTask(&taskEntryPoint, this);
|
2022-02-02 10:29:30 +01:00
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return PosixThread::sleep((uint64_t)ms * 1000000);
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); }
|
2018-07-13 18:28:26 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
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;
|
|
|
|
}
|
2020-04-30 22:03:16 +02:00
|
|
|
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst"
|
|
|
|
<< std::dec << std::endl;
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2022-02-02 10:29:30 +01:00
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
2022-05-14 09:38:59 +02:00
|
|
|
ReturnValue_t FixedTimeslotTask::checkSequence() { return pst.checkSequence(); }
|
2018-07-13 18:28:26 +02:00
|
|
|
|
|
|
|
void FixedTimeslotTask::taskFunctionality() {
|
2022-02-02 10:29:30 +01:00
|
|
|
// Like FreeRTOS pthreads are running as soon as they are created
|
|
|
|
if (!started) {
|
2022-05-18 15:42:18 +02:00
|
|
|
posixThread.suspend();
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pst.intializeSequenceAfterTaskCreation();
|
|
|
|
|
|
|
|
// The start time for the first entry is read.
|
2022-05-18 15:42:18 +02:00
|
|
|
uint64_t lastWakeTime = posixThread.getCurrentMonotonicTimeMs();
|
2022-02-02 10:29:30 +01:00
|
|
|
uint64_t interval = pst.getIntervalToNextSlotMs();
|
|
|
|
|
|
|
|
// 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 = this->pst.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)) {
|
|
|
|
// No time left on timer -> we missed the deadline
|
|
|
|
missedDeadlineCounter();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// The device handler for this slot is executed and the next one is chosen.
|
|
|
|
this->pst.executeAndAdvance();
|
|
|
|
}
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FixedTimeslotTask::missedDeadlineCounter() {
|
2022-02-02 10:29:30 +01:00
|
|
|
FixedTimeslotTask::deadlineMissedCount++;
|
|
|
|
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2022-02-02 10:29:30 +01:00
|
|
|
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines."
|
|
|
|
<< std::endl;
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
2018-07-13 18:28:26 +02:00
|
|
|
}
|