timeslot update for FreeRTOS
This commit is contained in:
parent
9465c8f2b2
commit
66cf2d3559
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* @file PollingSlot.cpp
|
||||
* @brief This file defines the PollingSlot class.
|
||||
* @date 19.12.2012
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include "FixedSequenceSlot.h"
|
||||
#include "../objectmanager/SystemObjectIF.h"
|
||||
#include <cstddef>
|
||||
|
||||
FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime,
|
||||
int8_t setSequenceId, PeriodicTaskIF* executingTask) :
|
||||
handler(NULL), pollingTimeMs(setTime), opcode(setSequenceId) {
|
||||
handler = objectManager->get<ExecutableObjectIF>(handlerId);
|
||||
handler->setTaskIF(executingTask);
|
||||
}
|
||||
|
||||
FixedSequenceSlot::~FixedSequenceSlot() {}
|
||||
|
@ -1,162 +1,166 @@
|
||||
#include "FixedTimeslotTask.h"
|
||||
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
|
||||
|
||||
FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority,
|
||||
TaskStackSize setStack, TaskPeriod overallPeriod,
|
||||
void (*setDeadlineMissedFunc)()) :
|
||||
started(false), handle(NULL), pst(overallPeriod * 1000) {
|
||||
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
|
||||
xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
|
||||
// All additional attributes are applied to the object.
|
||||
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
||||
}
|
||||
|
||||
FixedTimeslotTask::~FixedTimeslotTask() {
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
||||
|
||||
// The argument is re-interpreted as FixedTimeslotTask. The Task object is
|
||||
// global, so it is found from any place.
|
||||
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
||||
/* Task should not start until explicitly requested,
|
||||
* but in FreeRTOS, tasks start as soon as they are created if the scheduler
|
||||
* is running but not if the scheduler is not running.
|
||||
* To be able to accommodate both cases we check a member which is set in
|
||||
* #startTask(). If it is not set and we get here, the scheduler was started
|
||||
* before #startTask() was called and we need to suspend if it is set,
|
||||
* the scheduler was not running before #startTask() was called and we
|
||||
* can continue */
|
||||
|
||||
if (not originalTask->started) {
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
originalTask->taskFunctionality();
|
||||
sif::debug << "Polling task " << originalTask->handle
|
||||
<< " returned from taskFunctionality." << std::endl;
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::missedDeadlineCounter() {
|
||||
FixedTimeslotTask::deadlineMissedCount++;
|
||||
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
||||
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount
|
||||
<< " deadlines." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||
started = true;
|
||||
|
||||
// We must not call resume if scheduler is not started yet
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
vTaskResume(handle);
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
|
||||
uint32_t slotTimeMs, int8_t executionStep) {
|
||||
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) {
|
||||
pst.addSlot(componentId, slotTimeMs, executionStep, this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
sif::error << "Component " << std::hex << componentId <<
|
||||
" not found, not adding it to pst" << std::endl;
|
||||
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.
|
||||
auto slotListIter = pst.current;
|
||||
|
||||
//The start time for the first entry is read.
|
||||
uint32_t intervalMs = slotListIter->pollingTimeMs;
|
||||
TickType_t interval = pdMS_TO_TICKS(intervalMs);
|
||||
|
||||
TickType_t xLastWakeTime;
|
||||
/* The xLastWakeTime variable needs to be initialized with the current tick
|
||||
count. Note that this is the only time the variable is written to
|
||||
explicitly. After this assignment, xLastWakeTime is updated automatically
|
||||
internally within vTaskDelayUntil(). */
|
||||
xLastWakeTime = xTaskGetTickCount();
|
||||
|
||||
// wait for first entry's start time
|
||||
if(interval > 0) {
|
||||
vTaskDelayUntil(&xLastWakeTime, interval);
|
||||
}
|
||||
|
||||
/* Enter the loop that defines the task behavior. */
|
||||
for (;;) {
|
||||
//The component for this slot is executed and the next one is chosen.
|
||||
this->pst.executeAndAdvance();
|
||||
if (not pst.slotFollowsImmediately()) {
|
||||
// Get the interval till execution of the next slot.
|
||||
intervalMs = this->pst.getIntervalToPreviousSlotMs();
|
||||
interval = pdMS_TO_TICKS(intervalMs);
|
||||
|
||||
checkMissedDeadline(xLastWakeTime, interval);
|
||||
|
||||
// Wait for the interval. This exits immediately if a deadline was
|
||||
// missed while also updating the last wake time.
|
||||
vTaskDelayUntil(&xLastWakeTime, interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime,
|
||||
const TickType_t interval) {
|
||||
/* Check whether deadline was missed while also taking overflows
|
||||
* into account. Drawing this on paper with a timeline helps to understand
|
||||
* it. */
|
||||
TickType_t currentTickCount = xTaskGetTickCount();
|
||||
TickType_t timeToWake = xLastWakeTime + interval;
|
||||
// Time to wake has not overflown.
|
||||
if(timeToWake > xLastWakeTime) {
|
||||
/* If the current time has overflown exclusively or the current
|
||||
* tick count is simply larger than the time to wake, a deadline was
|
||||
* missed */
|
||||
if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) {
|
||||
handleMissedDeadline();
|
||||
}
|
||||
}
|
||||
/* Time to wake has overflown. A deadline was missed if the current time
|
||||
* is larger than the time to wake */
|
||||
else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) {
|
||||
handleMissedDeadline();
|
||||
}
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::handleMissedDeadline() {
|
||||
#ifdef DEBUG
|
||||
sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) <<
|
||||
" missed deadline!\n" << std::flush;
|
||||
#endif
|
||||
if(deadlineMissedFunc != nullptr) {
|
||||
this->deadlineMissedFunc();
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
||||
vTaskDelay(pdMS_TO_TICKS(ms));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
TaskHandle_t FixedTimeslotTask::getTaskHandle() {
|
||||
return handle;
|
||||
}
|
||||
#include "FixedTimeslotTask.h"
|
||||
|
||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
|
||||
|
||||
FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority,
|
||||
TaskStackSize setStack, TaskPeriod overallPeriod,
|
||||
void (*setDeadlineMissedFunc)()) :
|
||||
started(false), handle(nullptr), pst(overallPeriod * 1000) {
|
||||
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
|
||||
xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
|
||||
// All additional attributes are applied to the object.
|
||||
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
||||
}
|
||||
|
||||
FixedTimeslotTask::~FixedTimeslotTask() {
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
||||
|
||||
// The argument is re-interpreted as FixedTimeslotTask. The Task object is
|
||||
// global, so it is found from any place.
|
||||
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
||||
/* Task should not start until explicitly requested,
|
||||
* but in FreeRTOS, tasks start as soon as they are created if the scheduler
|
||||
* is running but not if the scheduler is not running.
|
||||
* To be able to accommodate both cases we check a member which is set in
|
||||
* #startTask(). If it is not set and we get here, the scheduler was started
|
||||
* before #startTask() was called and we need to suspend if it is set,
|
||||
* the scheduler was not running before #startTask() was called and we
|
||||
* can continue */
|
||||
|
||||
if (not originalTask->started) {
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
originalTask->taskFunctionality();
|
||||
sif::debug << "Polling task " << originalTask->handle
|
||||
<< " returned from taskFunctionality." << std::endl;
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::missedDeadlineCounter() {
|
||||
FixedTimeslotTask::deadlineMissedCount++;
|
||||
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
||||
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount
|
||||
<< " deadlines." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||
started = true;
|
||||
|
||||
// We must not call resume if scheduler is not started yet
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
vTaskResume(handle);
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
|
||||
uint32_t slotTimeMs, int8_t executionStep) {
|
||||
ExecutableObjectIF* handler =
|
||||
objectManager->get<ExecutableObjectIF>(componentId);
|
||||
if (handler != nullptr) {
|
||||
pst.addSlot(componentId, slotTimeMs, executionStep, handler, this);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
sif::error << "Component " << std::hex << componentId <<
|
||||
" not found, not adding it to pst" << std::endl;
|
||||
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.
|
||||
auto slotListIter = pst.current;
|
||||
|
||||
pst.intializeSequenceAfterTaskCreation();
|
||||
|
||||
//The start time for the first entry is read.
|
||||
uint32_t intervalMs = slotListIter->pollingTimeMs;
|
||||
TickType_t interval = pdMS_TO_TICKS(intervalMs);
|
||||
|
||||
TickType_t xLastWakeTime;
|
||||
/* The xLastWakeTime variable needs to be initialized with the current tick
|
||||
count. Note that this is the only time the variable is written to
|
||||
explicitly. After this assignment, xLastWakeTime is updated automatically
|
||||
internally within vTaskDelayUntil(). */
|
||||
xLastWakeTime = xTaskGetTickCount();
|
||||
|
||||
// wait for first entry's start time
|
||||
if(interval > 0) {
|
||||
vTaskDelayUntil(&xLastWakeTime, interval);
|
||||
}
|
||||
|
||||
/* Enter the loop that defines the task behavior. */
|
||||
for (;;) {
|
||||
//The component for this slot is executed and the next one is chosen.
|
||||
this->pst.executeAndAdvance();
|
||||
if (not pst.slotFollowsImmediately()) {
|
||||
// Get the interval till execution of the next slot.
|
||||
intervalMs = this->pst.getIntervalToPreviousSlotMs();
|
||||
interval = pdMS_TO_TICKS(intervalMs);
|
||||
|
||||
checkMissedDeadline(xLastWakeTime, interval);
|
||||
|
||||
// Wait for the interval. This exits immediately if a deadline was
|
||||
// missed while also updating the last wake time.
|
||||
vTaskDelayUntil(&xLastWakeTime, interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime,
|
||||
const TickType_t interval) {
|
||||
/* Check whether deadline was missed while also taking overflows
|
||||
* into account. Drawing this on paper with a timeline helps to understand
|
||||
* it. */
|
||||
TickType_t currentTickCount = xTaskGetTickCount();
|
||||
TickType_t timeToWake = xLastWakeTime + interval;
|
||||
// Time to wake has not overflown.
|
||||
if(timeToWake > xLastWakeTime) {
|
||||
/* If the current time has overflown exclusively or the current
|
||||
* tick count is simply larger than the time to wake, a deadline was
|
||||
* missed */
|
||||
if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) {
|
||||
handleMissedDeadline();
|
||||
}
|
||||
}
|
||||
/* Time to wake has overflown. A deadline was missed if the current time
|
||||
* is larger than the time to wake */
|
||||
else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) {
|
||||
handleMissedDeadline();
|
||||
}
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::handleMissedDeadline() {
|
||||
#ifdef DEBUG
|
||||
sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) <<
|
||||
" missed deadline!\n" << std::flush;
|
||||
#endif
|
||||
if(deadlineMissedFunc != nullptr) {
|
||||
this->deadlineMissedFunc();
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
||||
vTaskDelay(pdMS_TO_TICKS(ms));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
TaskHandle_t FixedTimeslotTask::getTaskHandle() {
|
||||
return handle;
|
||||
}
|
||||
|
@ -1,102 +1,101 @@
|
||||
#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
|
||||
#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
|
||||
|
||||
#include "FreeRTOSTaskIF.h"
|
||||
#include "../../devicehandlers/FixedSlotSequence.h"
|
||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
||||
#include "../../tasks/Typedef.h"
|
||||
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Keep in mind that you need to call before vTaskStartScheduler()!
|
||||
* A lot of task parameters are set in "FreeRTOSConfig.h".
|
||||
* @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN
|
||||
* @param setPriority Number of priorities specified by
|
||||
* configMAX_PRIORITIES. High taskPriority_ number means high priority.
|
||||
* @param setStack Stack size in words (not bytes!).
|
||||
* Lower limit specified by configMINIMAL_STACK_SIZE
|
||||
* @param overallPeriod Period in seconds.
|
||||
* @param setDeadlineMissedFunc Callback if a deadline was missed.
|
||||
* @return Pointer to the newly created task.
|
||||
*/
|
||||
FixedTimeslotTask(TaskName name, TaskPriority setPriority,
|
||||
TaskStackSize setStack, TaskPeriod 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 ~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) override;
|
||||
|
||||
uint32_t getPeriodMs() const override;
|
||||
|
||||
ReturnValue_t checkSequence() const override;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
TaskHandle_t getTaskHandle() override;
|
||||
|
||||
protected:
|
||||
bool started;
|
||||
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.
|
||||
* @details
|
||||
* This method starts the task by calling taskFunctionality(), as soon as
|
||||
* all requirements (task scheduler has started and startTask()
|
||||
* has been called) are met.
|
||||
*/
|
||||
static void taskEntryPoint(void* argument);
|
||||
|
||||
/**
|
||||
* @brief This function holds the main functionality of the thread.
|
||||
* @details
|
||||
* Core function holding the main functionality of the task
|
||||
* It links the functionalities provided by FixedSlotSequence with the
|
||||
* OS's System Calls to keep the timing of the periods.
|
||||
*/
|
||||
void taskFunctionality(void);
|
||||
|
||||
void checkMissedDeadline(const TickType_t xLastWakeTime,
|
||||
const TickType_t interval);
|
||||
void handleMissedDeadline();
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ */
|
||||
#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
|
||||
#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
|
||||
|
||||
#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h"
|
||||
#include "../../tasks/FixedSlotSequence.h"
|
||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
||||
#include "../../tasks/Typedef.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Keep in mind that you need to call before vTaskStartScheduler()!
|
||||
* A lot of task parameters are set in "FreeRTOSConfig.h".
|
||||
* @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN
|
||||
* @param setPriority Number of priorities specified by
|
||||
* configMAX_PRIORITIES. High taskPriority_ number means high priority.
|
||||
* @param setStack Stack size in words (not bytes!).
|
||||
* Lower limit specified by configMINIMAL_STACK_SIZE
|
||||
* @param overallPeriod Period in seconds.
|
||||
* @param setDeadlineMissedFunc Callback if a deadline was missed.
|
||||
* @return Pointer to the newly created task.
|
||||
*/
|
||||
FixedTimeslotTask(TaskName name, TaskPriority setPriority,
|
||||
TaskStackSize setStack, TaskPeriod 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 ~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) override;
|
||||
|
||||
uint32_t getPeriodMs() const override;
|
||||
|
||||
ReturnValue_t checkSequence() const override;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
TaskHandle_t getTaskHandle() override;
|
||||
|
||||
protected:
|
||||
bool started;
|
||||
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.
|
||||
* @details
|
||||
* This method starts the task by calling taskFunctionality(), as soon as
|
||||
* all requirements (task scheduler has started and startTask()
|
||||
* has been called) are met.
|
||||
*/
|
||||
static void taskEntryPoint(void* argument);
|
||||
|
||||
/**
|
||||
* @brief This function holds the main functionality of the thread.
|
||||
* @details
|
||||
* Core function holding the main functionality of the task
|
||||
* It links the functionalities provided by FixedSlotSequence with the
|
||||
* OS's System Calls to keep the timing of the periods.
|
||||
*/
|
||||
void taskFunctionality(void);
|
||||
|
||||
void checkMissedDeadline(const TickType_t xLastWakeTime,
|
||||
const TickType_t interval);
|
||||
void handleMissedDeadline();
|
||||
};
|
||||
|
||||
#endif /* POLLINGTASK_H_ */
|
||||
|
17
tasks/FixedSequenceSlot.cpp
Normal file
17
tasks/FixedSequenceSlot.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "FixedSequenceSlot.h"
|
||||
#include "../objectmanager/SystemObjectIF.h"
|
||||
#include <cstddef>
|
||||
|
||||
FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime,
|
||||
int8_t setSequenceId, ExecutableObjectIF* executableObject,
|
||||
PeriodicTaskIF* executingTask) :
|
||||
pollingTimeMs(setTime), opcode(setSequenceId) {
|
||||
if(executableObject == nullptr) {
|
||||
return;
|
||||
}
|
||||
this->executableObject = executableObject;
|
||||
this->executableObject->setTaskIF(executingTask);
|
||||
}
|
||||
|
||||
FixedSequenceSlot::~FixedSequenceSlot() {}
|
||||
|
@ -1,60 +1,57 @@
|
||||
/**
|
||||
* @file FixedSequenceSlot.h
|
||||
* @brief This file defines the PollingSlot class.
|
||||
* @date 19.12.2012
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef FIXEDSEQUENCESLOT_H_
|
||||
#define FIXEDSEQUENCESLOT_H_
|
||||
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../tasks/ExecutableObjectIF.h"
|
||||
class PeriodicTaskIF;
|
||||
|
||||
/**
|
||||
* @brief This class is the representation of a single polling sequence table entry.
|
||||
*
|
||||
* @details The PollingSlot class is the representation of a single polling
|
||||
* sequence table entry.
|
||||
*/
|
||||
class FixedSequenceSlot {
|
||||
public:
|
||||
FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs,
|
||||
int8_t setSequenceId, PeriodicTaskIF* executingTask );
|
||||
virtual ~FixedSequenceSlot();
|
||||
|
||||
/**
|
||||
* @brief Handler identifies which device handler object is executed in this slot.
|
||||
*/
|
||||
ExecutableObjectIF* handler;
|
||||
|
||||
/**
|
||||
* @brief This attribute defines when a device handler object is executed.
|
||||
*
|
||||
* @details The pollingTime attribute identifies the time the handler is executed in ms.
|
||||
* It must be smaller than the period length of the polling sequence.
|
||||
*/
|
||||
uint32_t pollingTimeMs;
|
||||
|
||||
/**
|
||||
* @brief This value defines the type of device communication.
|
||||
*
|
||||
* @details The state of this value decides what communication routine is
|
||||
* called in the PST executable or the device handler object.
|
||||
*/
|
||||
uint8_t opcode;
|
||||
|
||||
/**
|
||||
* @brief Operator overload for the comparison operator to
|
||||
* allow sorting by polling time.
|
||||
* @param fixedSequenceSlot
|
||||
* @return
|
||||
*/
|
||||
bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const {
|
||||
return pollingTimeMs < fixedSequenceSlot.pollingTimeMs;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* FIXEDSEQUENCESLOT_H_ */
|
||||
#ifndef FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_
|
||||
#define FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_
|
||||
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../tasks/ExecutableObjectIF.h"
|
||||
class PeriodicTaskIF;
|
||||
|
||||
/**
|
||||
* @brief This class is the representation of a single polling sequence
|
||||
* table entry.
|
||||
* @details
|
||||
* The PollingSlot class is the representation of a single polling
|
||||
* sequence table entry.
|
||||
* @author baetz
|
||||
*/
|
||||
class FixedSequenceSlot {
|
||||
public:
|
||||
FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs,
|
||||
int8_t setSequenceId, ExecutableObjectIF* executableObject,
|
||||
PeriodicTaskIF* executingTask);
|
||||
virtual ~FixedSequenceSlot();
|
||||
|
||||
/**
|
||||
* @brief Handler identifies which object is executed in this slot.
|
||||
*/
|
||||
ExecutableObjectIF* executableObject = nullptr;
|
||||
|
||||
/**
|
||||
* @brief This attribute defines when a device handler object is executed.
|
||||
* @details
|
||||
* The pollingTime attribute identifies the time the handler is
|
||||
* executed in ms. It must be smaller than the period length of the
|
||||
* polling sequence.
|
||||
*/
|
||||
uint32_t pollingTimeMs;
|
||||
|
||||
/**
|
||||
* @brief This value defines the type of device communication.
|
||||
*
|
||||
* @details The state of this value decides what communication routine is
|
||||
* called in the PST executable or the device handler object.
|
||||
*/
|
||||
uint8_t opcode;
|
||||
|
||||
/**
|
||||
* @brief Operator overload for the comparison operator to
|
||||
* allow sorting by polling time.
|
||||
* @param fixedSequenceSlot
|
||||
* @return
|
||||
*/
|
||||
bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const {
|
||||
return pollingTimeMs < fixedSequenceSlot.pollingTimeMs;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* FIXEDSEQUENCESLOT_H_ */
|
@ -1,123 +1,147 @@
|
||||
#include "FixedSlotSequence.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) :
|
||||
lengthMs(setLengthMs) {
|
||||
current = slotList.begin();
|
||||
}
|
||||
|
||||
FixedSlotSequence::~FixedSlotSequence() {
|
||||
// Call the destructor on each list entry.
|
||||
slotList.clear();
|
||||
}
|
||||
|
||||
void FixedSlotSequence::executeAndAdvance() {
|
||||
current->handler->performOperation(current->opcode);
|
||||
// if (returnValue != RETURN_OK) {
|
||||
// this->sendErrorMessage( returnValue );
|
||||
// }
|
||||
//Increment the polling Sequence iterator
|
||||
this->current++;
|
||||
//Set it to the beginning, if the list's end is reached.
|
||||
if (this->current == this->slotList.end()) {
|
||||
this->current = this->slotList.begin();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t FixedSlotSequence::getIntervalToNextSlotMs() {
|
||||
uint32_t oldTime;
|
||||
SlotListIter slotListIter = current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
oldTime = slotListIter->pollingTimeMs;
|
||||
// Advance to the next object.
|
||||
slotListIter++;
|
||||
// Find the next interval which is not 0.
|
||||
while (slotListIter != slotList.end()) {
|
||||
if (oldTime != slotListIter->pollingTimeMs) {
|
||||
return slotListIter->pollingTimeMs - oldTime;
|
||||
} else {
|
||||
slotListIter++;
|
||||
}
|
||||
}
|
||||
// If the list end is reached (this is definitely an interval != 0),
|
||||
// the interval is calculated by subtracting the remaining time of the PST
|
||||
// and adding the start time of the first handler in the list.
|
||||
slotListIter = slotList.begin();
|
||||
return lengthMs - oldTime + slotListIter->pollingTimeMs;
|
||||
}
|
||||
|
||||
uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() {
|
||||
uint32_t currentTime;
|
||||
SlotListIter slotListIter = current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
currentTime = slotListIter->pollingTimeMs;
|
||||
|
||||
//if it is the first slot, calculate difference to last slot
|
||||
if (slotListIter == slotList.begin()){
|
||||
return lengthMs - (--slotList.end())->pollingTimeMs + currentTime;
|
||||
}
|
||||
// get previous slot
|
||||
slotListIter--;
|
||||
|
||||
return currentTime - slotListIter->pollingTimeMs;
|
||||
}
|
||||
|
||||
bool FixedSlotSequence::slotFollowsImmediately() {
|
||||
uint32_t currentTime = current->pollingTimeMs;
|
||||
SlotListIter fixedSequenceIter = this->current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
if (fixedSequenceIter == slotList.begin())
|
||||
return false;
|
||||
fixedSequenceIter--;
|
||||
if (fixedSequenceIter->pollingTimeMs == currentTime) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t FixedSlotSequence::getLengthMs() const {
|
||||
return this->lengthMs;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedSlotSequence::checkSequence() const {
|
||||
if(slotList.empty()) {
|
||||
sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
auto slotIt = slotList.begin();
|
||||
uint32_t count = 0;
|
||||
uint32_t time = 0;
|
||||
while (slotIt != slotList.end()) {
|
||||
if (slotIt->handler == nullptr) {
|
||||
sif::error << "FixedSlotSequene::initialize: ObjectId does not exist!"
|
||||
<< std::endl;
|
||||
count++;
|
||||
} else if (slotIt->pollingTimeMs < time) {
|
||||
sif::error << "FixedSlotSequence::initialize: Time: "
|
||||
<< slotIt->pollingTimeMs
|
||||
<< " is smaller than previous with " << time << std::endl;
|
||||
count++;
|
||||
} else {
|
||||
// All ok, print slot.
|
||||
//info << "Current slot polling time: " << std::endl;
|
||||
//info << std::dec << slotIt->pollingTimeMs << std::endl;
|
||||
}
|
||||
time = slotIt->pollingTimeMs;
|
||||
slotIt++;
|
||||
}
|
||||
//info << "Number of elements in slot list: "
|
||||
// << slotList.size() << std::endl;
|
||||
if (count > 0) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
int8_t executionStep, PeriodicTaskIF* executingTask) {
|
||||
this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, executionStep,
|
||||
executingTask));
|
||||
this->current = slotList.begin();
|
||||
}
|
||||
#include "FixedSlotSequence.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include <cstdlib>
|
||||
|
||||
FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) :
|
||||
lengthMs(setLengthMs) {
|
||||
current = slotList.begin();
|
||||
}
|
||||
|
||||
FixedSlotSequence::~FixedSlotSequence() {
|
||||
// Call the destructor on each list entry.
|
||||
slotList.clear();
|
||||
}
|
||||
|
||||
void FixedSlotSequence::executeAndAdvance() {
|
||||
current->executableObject->performOperation(current->opcode);
|
||||
// if (returnValue != RETURN_OK) {
|
||||
// this->sendErrorMessage( returnValue );
|
||||
// }
|
||||
//Increment the polling Sequence iterator
|
||||
this->current++;
|
||||
//Set it to the beginning, if the list's end is reached.
|
||||
if (this->current == this->slotList.end()) {
|
||||
this->current = this->slotList.begin();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t FixedSlotSequence::getIntervalToNextSlotMs() {
|
||||
uint32_t oldTime;
|
||||
SlotListIter slotListIter = current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
oldTime = slotListIter->pollingTimeMs;
|
||||
// Advance to the next object.
|
||||
slotListIter++;
|
||||
// Find the next interval which is not 0.
|
||||
while (slotListIter != slotList.end()) {
|
||||
if (oldTime != slotListIter->pollingTimeMs) {
|
||||
return slotListIter->pollingTimeMs - oldTime;
|
||||
} else {
|
||||
slotListIter++;
|
||||
}
|
||||
}
|
||||
// If the list end is reached (this is definitely an interval != 0),
|
||||
// the interval is calculated by subtracting the remaining time of the PST
|
||||
// and adding the start time of the first handler in the list.
|
||||
slotListIter = slotList.begin();
|
||||
return lengthMs - oldTime + slotListIter->pollingTimeMs;
|
||||
}
|
||||
|
||||
uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() {
|
||||
uint32_t currentTime;
|
||||
SlotListIter slotListIter = current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
currentTime = slotListIter->pollingTimeMs;
|
||||
|
||||
//if it is the first slot, calculate difference to last slot
|
||||
if (slotListIter == slotList.begin()){
|
||||
return lengthMs - (--slotList.end())->pollingTimeMs + currentTime;
|
||||
}
|
||||
// get previous slot
|
||||
slotListIter--;
|
||||
|
||||
return currentTime - slotListIter->pollingTimeMs;
|
||||
}
|
||||
|
||||
bool FixedSlotSequence::slotFollowsImmediately() {
|
||||
uint32_t currentTime = current->pollingTimeMs;
|
||||
SlotListIter fixedSequenceIter = this->current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
if (fixedSequenceIter == slotList.begin())
|
||||
return false;
|
||||
fixedSequenceIter--;
|
||||
if (fixedSequenceIter->pollingTimeMs == currentTime) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t FixedSlotSequence::getLengthMs() const {
|
||||
return this->lengthMs;
|
||||
}
|
||||
|
||||
void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
int8_t executionStep, ExecutableObjectIF* executableObject,
|
||||
PeriodicTaskIF* executingTask) {
|
||||
this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs,
|
||||
executionStep, executableObject, executingTask));
|
||||
this->current = slotList.begin();
|
||||
}
|
||||
|
||||
ReturnValue_t FixedSlotSequence::checkSequence() const {
|
||||
if(slotList.empty()) {
|
||||
sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
uint32_t count = 0;
|
||||
uint32_t time = 0;
|
||||
for(const auto& slot: slotList) {
|
||||
if (slot.executableObject == nullptr) {
|
||||
count++;
|
||||
}
|
||||
else if (slot.pollingTimeMs < time) {
|
||||
sif::error << "FixedSlotSequence::initialize: Time: "
|
||||
<< slot.pollingTimeMs << " is smaller than previous with "
|
||||
<< time << std::endl;
|
||||
count++;
|
||||
}
|
||||
else {
|
||||
// All ok, print slot.
|
||||
//sif::info << "Current slot polling time: " << std::endl;
|
||||
//sif::info << std::dec << slotIt->pollingTimeMs << std::endl;
|
||||
}
|
||||
time = slot.pollingTimeMs;
|
||||
|
||||
}
|
||||
//sif::info << "Number of elements in slot list: "
|
||||
// << slotList.size() << std::endl;
|
||||
if (count > 0) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const {
|
||||
std::set<ExecutableObjectIF*> uniqueObjects;
|
||||
uint32_t count = 0;
|
||||
for(const auto& slot: slotList) {
|
||||
// Ensure that each unique object is initialized once.
|
||||
if(uniqueObjects.find(slot.executableObject) == uniqueObjects.end()) {
|
||||
ReturnValue_t result =
|
||||
slot.executableObject->initializeAfterTaskCreation();
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
count++;
|
||||
}
|
||||
uniqueObjects.emplace(slot.executableObject);
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
sif::error << "FixedSlotSequence::intializeSequenceAfterTaskCreation:"
|
||||
"Counted " << count << " failed initializations!" << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
@ -1,152 +1,159 @@
|
||||
#ifndef FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_
|
||||
#define FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_
|
||||
|
||||
#include "FixedSequenceSlot.h"
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include <set>
|
||||
|
||||
/**
|
||||
* @brief This class is the representation of a Polling Sequence Table in software.
|
||||
*
|
||||
* @details
|
||||
* The FixedSlotSequence object maintains the dynamic execution of
|
||||
* device handler objects.
|
||||
*
|
||||
* The main idea is to create a list of device handlers, to announce all
|
||||
* handlers to thepolling sequence and to maintain a list of
|
||||
* polling slot objects. This slot list represents the Polling Sequence Table
|
||||
* in software.
|
||||
*
|
||||
* Each polling slot contains information to indicate when and
|
||||
* which device handler shall be executed within a given polling period.
|
||||
* The sequence is then executed by iterating through this slot list.
|
||||
* Handlers are invoking by calling a certain function stored in the handler list.
|
||||
*/
|
||||
class FixedSlotSequence {
|
||||
public:
|
||||
using SlotList = std::multiset<FixedSequenceSlot>;
|
||||
using SlotListIter = std::multiset<FixedSequenceSlot>::iterator;
|
||||
|
||||
/**
|
||||
* @brief The constructor of the FixedSlotSequence object.
|
||||
*
|
||||
* @details The constructor takes two arguments, the period length and the init function.
|
||||
*
|
||||
* @param setLength The period length, expressed in ms.
|
||||
*/
|
||||
FixedSlotSequence(uint32_t setLengthMs);
|
||||
|
||||
/**
|
||||
* @brief The destructor of the FixedSlotSequence object.
|
||||
*
|
||||
* @details The destructor frees all allocated memory by iterating through the slotList
|
||||
* and deleting all allocated resources.
|
||||
*/
|
||||
virtual ~FixedSlotSequence();
|
||||
|
||||
/**
|
||||
* @brief This is a method to add an PollingSlot object to slotList.
|
||||
*
|
||||
* @details Here, a polling slot object is added to the slot list. It is appended
|
||||
* to the end of the list. The list is currently NOT reordered.
|
||||
* Afterwards, the iterator current is set to the beginning of the list.
|
||||
* @param Object ID of the object to add
|
||||
* @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask
|
||||
* will be called inside the slot period.
|
||||
* @param setSequenceId ID which can be used to distinguish
|
||||
* different task operations
|
||||
* @param
|
||||
* @param
|
||||
*/
|
||||
void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId,
|
||||
PeriodicTaskIF* executingTask);
|
||||
|
||||
/**
|
||||
* Checks if the current slot shall be executed immediately after the one before.
|
||||
* This allows to distinguish between grouped and not grouped handlers.
|
||||
* @return - @c true if the slot has the same polling time as the previous
|
||||
* - @c false else
|
||||
*/
|
||||
bool slotFollowsImmediately();
|
||||
|
||||
/**
|
||||
* @brief This method returns the time until the next software
|
||||
* component is invoked.
|
||||
*
|
||||
* @details
|
||||
* This method is vitally important for the operation of the PST.
|
||||
* By fetching the polling time of the current slot and that of the
|
||||
* next one (or the first one, if the list end is reached)
|
||||
* it calculates and returns the interval in milliseconds within
|
||||
* which the handler execution shall take place.
|
||||
* If the next slot has the same time as the current one, it is ignored
|
||||
* until a slot with different time or the end of the PST is found.
|
||||
*/
|
||||
uint32_t getIntervalToNextSlotMs();
|
||||
|
||||
/**
|
||||
* @brief This method returns the time difference between the current
|
||||
* slot and the previous slot
|
||||
*
|
||||
* @details
|
||||
* This method is vitally important for the operation of the PST.
|
||||
* By fetching the polling time of the current slot and that of the previous
|
||||
* one (or the last one, if the slot is the first one) it calculates and
|
||||
* returns the interval in milliseconds that the handler execution shall
|
||||
* be delayed.
|
||||
*/
|
||||
uint32_t getIntervalToPreviousSlotMs();
|
||||
|
||||
/**
|
||||
* @brief This method returns the length of this FixedSlotSequence instance.
|
||||
*/
|
||||
uint32_t getLengthMs() const;
|
||||
|
||||
/**
|
||||
* @brief The method to execute the device handler entered in the current
|
||||
* PollingSlot object.
|
||||
*
|
||||
* @details
|
||||
* Within this method the device handler object to be executed is chosen by
|
||||
* looking up the handler address of the current slot in the handlerMap.
|
||||
* Either the device handler's talkToInterface or its listenToInterface
|
||||
* method is invoked, depending on the isTalking flag of the polling slot.
|
||||
* After execution the iterator current is increased or, by reaching the
|
||||
* end of slotList, reset to the beginning.
|
||||
*/
|
||||
void executeAndAdvance();
|
||||
|
||||
/**
|
||||
* @brief An iterator that indicates the current polling slot to execute.
|
||||
*
|
||||
* @details This is an iterator for slotList and always points to the
|
||||
* polling slot which is executed next.
|
||||
*/
|
||||
SlotListIter current;
|
||||
|
||||
/**
|
||||
* Iterate through slotList and check successful creation.
|
||||
* Checks if timing is ok (must be ascending) and if all handlers were found.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t checkSequence() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief This list contains all PollingSlot objects, defining order and
|
||||
* execution time of the device handler objects.
|
||||
*
|
||||
* @details
|
||||
* The slot list is a std:list object that contains all created
|
||||
* PollingSlot instances. They are NOT ordered automatically, so by
|
||||
* adding entries, the correct order needs to be ensured. By iterating
|
||||
* through this list the polling sequence is executed. Two entries with
|
||||
* identical polling times are executed immediately one after another.
|
||||
*/
|
||||
SlotList slotList;
|
||||
|
||||
uint32_t lengthMs;
|
||||
};
|
||||
|
||||
#endif /* FIXEDSLOTSEQUENCE_H_ */
|
||||
#ifndef FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_
|
||||
#define FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_
|
||||
|
||||
#include "FixedSequenceSlot.h"
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
/**
|
||||
* @brief This class is the representation of a Polling Sequence Table in software.
|
||||
* @details
|
||||
* The FixedSlotSequence object maintains the dynamic execution of
|
||||
* device handler objects.
|
||||
*
|
||||
* The main idea is to create a list of device handlers, to announce all
|
||||
* handlers to thepolling sequence and to maintain a list of
|
||||
* polling slot objects. This slot list represents the Polling Sequence Table
|
||||
* in software.
|
||||
*
|
||||
* Each polling slot contains information to indicate when and
|
||||
* which device handler shall be executed within a given polling period.
|
||||
* The sequence is then executed by iterating through this slot list.
|
||||
* Handlers are invoking by calling a certain function stored in the handler list.
|
||||
*/
|
||||
class FixedSlotSequence {
|
||||
public:
|
||||
using SlotList = std::multiset<FixedSequenceSlot>;
|
||||
using SlotListIter = std::multiset<FixedSequenceSlot>::iterator;
|
||||
|
||||
/**
|
||||
* @brief The constructor of the FixedSlotSequence object.
|
||||
*
|
||||
* @details The constructor takes two arguments, the period length and the init function.
|
||||
*
|
||||
* @param setLength The period length, expressed in ms.
|
||||
*/
|
||||
FixedSlotSequence(uint32_t setLengthMs);
|
||||
|
||||
/**
|
||||
* @brief The destructor of the FixedSlotSequence object.
|
||||
*
|
||||
* @details The destructor frees all allocated memory by iterating through the slotList
|
||||
* and deleting all allocated resources.
|
||||
*/
|
||||
virtual ~FixedSlotSequence();
|
||||
|
||||
/**
|
||||
* @brief This is a method to add an PollingSlot object to slotList.
|
||||
*
|
||||
* @details Here, a polling slot object is added to the slot list. It is appended
|
||||
* to the end of the list. The list is currently NOT reordered.
|
||||
* Afterwards, the iterator current is set to the beginning of the list.
|
||||
* @param Object ID of the object to add
|
||||
* @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask
|
||||
* will be called inside the slot period.
|
||||
* @param setSequenceId ID which can be used to distinguish
|
||||
* different task operations
|
||||
* @param
|
||||
* @param
|
||||
*/
|
||||
void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId,
|
||||
ExecutableObjectIF* executableObject, PeriodicTaskIF* executingTask);
|
||||
|
||||
/**
|
||||
* Checks if the current slot shall be executed immediately after the one before.
|
||||
* This allows to distinguish between grouped and not grouped handlers.
|
||||
* @return - @c true if the slot has the same polling time as the previous
|
||||
* - @c false else
|
||||
*/
|
||||
bool slotFollowsImmediately();
|
||||
|
||||
/**
|
||||
* @brief This method returns the time until the next software
|
||||
* component is invoked.
|
||||
*
|
||||
* @details
|
||||
* This method is vitally important for the operation of the PST.
|
||||
* By fetching the polling time of the current slot and that of the
|
||||
* next one (or the first one, if the list end is reached)
|
||||
* it calculates and returns the interval in milliseconds within
|
||||
* which the handler execution shall take place.
|
||||
* If the next slot has the same time as the current one, it is ignored
|
||||
* until a slot with different time or the end of the PST is found.
|
||||
*/
|
||||
uint32_t getIntervalToNextSlotMs();
|
||||
|
||||
/**
|
||||
* @brief This method returns the time difference between the current
|
||||
* slot and the previous slot
|
||||
*
|
||||
* @details
|
||||
* This method is vitally important for the operation of the PST.
|
||||
* By fetching the polling time of the current slot and that of the previous
|
||||
* one (or the last one, if the slot is the first one) it calculates and
|
||||
* returns the interval in milliseconds that the handler execution shall
|
||||
* be delayed.
|
||||
*/
|
||||
uint32_t getIntervalToPreviousSlotMs();
|
||||
|
||||
/**
|
||||
* @brief This method returns the length of this FixedSlotSequence instance.
|
||||
*/
|
||||
uint32_t getLengthMs() const;
|
||||
|
||||
/**
|
||||
* @brief The method to execute the device handler entered in the current
|
||||
* PollingSlot object.
|
||||
*
|
||||
* @details
|
||||
* Within this method the device handler object to be executed is chosen by
|
||||
* looking up the handler address of the current slot in the handlerMap.
|
||||
* Either the device handler's talkToInterface or its listenToInterface
|
||||
* method is invoked, depending on the isTalking flag of the polling slot.
|
||||
* After execution the iterator current is increased or, by reaching the
|
||||
* end of slotList, reset to the beginning.
|
||||
*/
|
||||
void executeAndAdvance();
|
||||
|
||||
/**
|
||||
* @brief An iterator that indicates the current polling slot to execute.
|
||||
*
|
||||
* @details This is an iterator for slotList and always points to the
|
||||
* polling slot which is executed next.
|
||||
*/
|
||||
SlotListIter current;
|
||||
|
||||
/**
|
||||
* @brief Check and initialize slot list.
|
||||
* @details
|
||||
* Checks if timing is ok (must be ascending) and if all handlers were found.
|
||||
* Also calls any initialization steps which are required after task
|
||||
* creation.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t checkSequence() const;
|
||||
|
||||
ReturnValue_t intializeSequenceAfterTaskCreation() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief This list contains all PollingSlot objects, defining order and
|
||||
* execution time of the device handler objects.
|
||||
*
|
||||
* @details
|
||||
* The slot list is a std:list object that contains all created
|
||||
* PollingSlot instances. They are NOT ordered automatically, so by
|
||||
* adding entries, the correct order needs to be ensured. By iterating
|
||||
* through this list the polling sequence is executed. Two entries with
|
||||
* identical polling times are executed immediately one after another.
|
||||
*/
|
||||
SlotList slotList;
|
||||
|
||||
uint32_t lengthMs;
|
||||
|
||||
bool isEmpty = false;
|
||||
};
|
||||
|
||||
#endif /* FIXEDSLOTSEQUENCE_H_ */
|
Loading…
Reference in New Issue
Block a user