Merge pull request 'RTEMS Updates and Bugfixes' (#363) from mueller/rtems-only into development
Reviewed-on: fsfw/fsfw#363
This commit is contained in:
commit
48375a5221
@ -5,13 +5,13 @@ target_sources(${LIB_FSFW_NAME}
|
|||||||
InitTask.cpp
|
InitTask.cpp
|
||||||
InternalErrorCodes.cpp
|
InternalErrorCodes.cpp
|
||||||
MessageQueue.cpp
|
MessageQueue.cpp
|
||||||
MultiObjectTask.cpp
|
PeriodicTask.cpp
|
||||||
Mutex.cpp
|
Mutex.cpp
|
||||||
MutexFactory.cpp
|
MutexFactory.cpp
|
||||||
PollingTask.cpp
|
FixedTimeslotTask.cpp
|
||||||
QueueFactory.cpp
|
QueueFactory.cpp
|
||||||
RtemsBasic.cpp
|
RtemsBasic.cpp
|
||||||
TaskBase.cpp
|
RTEMSTaskBase.cpp
|
||||||
TaskFactory.cpp
|
TaskFactory.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -104,9 +104,13 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||||
// TIsn't this a bug? Are RTEMS ticks always microseconds?
|
/* For all but the last field, the struct will be filled with the correct values */
|
||||||
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time);
|
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time);
|
||||||
rtems_status_code status = rtems_clock_get_tod(timeRtems);
|
rtems_status_code status = rtems_clock_get_tod(timeRtems);
|
||||||
|
/* The last field now contains the RTEMS ticks of the seconds from 0
|
||||||
|
to rtems_clock_get_ticks_per_second() minus one. We calculate the microseconds accordingly */
|
||||||
|
timeRtems->ticks = static_cast<float>(timeRtems->ticks) /
|
||||||
|
rtems_clock_get_ticks_per_second() * 1e6;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case RTEMS_SUCCESSFUL:
|
case RTEMS_SUCCESSFUL:
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
@ -164,7 +164,7 @@ ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer,
|
|||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if ((*size = *size - MAX_LENGTH_OF_THREAD_NAME) < 0) {
|
if (*size < MAX_LENGTH_OF_THREAD_NAME) {
|
||||||
return STREAM_TOO_SHORT;
|
return STREAM_TOO_SHORT;
|
||||||
}
|
}
|
||||||
memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME);
|
memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME);
|
||||||
|
140
osal/rtems/FixedTimeslotTask.cpp
Normal file
140
osal/rtems/FixedTimeslotTask.cpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#include "FixedTimeslotTask.h"
|
||||||
|
#include "RtemsBasic.h"
|
||||||
|
|
||||||
|
#include "../../tasks/FixedSequenceSlot.h"
|
||||||
|
#include "../../objectmanager/SystemObjectIF.h"
|
||||||
|
#include "../../objectmanager/ObjectManagerIF.h"
|
||||||
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
#include "../../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
|
#include <rtems/bspIo.h>
|
||||||
|
#include <rtems/io.h>
|
||||||
|
#include <rtems/rtems/ratemon.h>
|
||||||
|
#include <rtems/rtems/status.h>
|
||||||
|
#include <rtems/rtems/tasks.h>
|
||||||
|
#include <rtems/rtems/types.h>
|
||||||
|
#include <sys/_stdint.h>
|
||||||
|
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
||||||
|
|
||||||
|
FixedTimeslotTask::FixedTimeslotTask(const char *name, rtems_task_priority setPriority,
|
||||||
|
size_t setStack, uint32_t setOverallPeriod, void (*setDeadlineMissedFunc)(void)):
|
||||||
|
RTEMSTaskBase(setPriority, setStack, name), periodId(0), pst(setOverallPeriod) {
|
||||||
|
// All additional attributes are applied to the object.
|
||||||
|
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedTimeslotTask::~FixedTimeslotTask() {
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) {
|
||||||
|
/* The argument is re-interpreted as a FixedTimeslotTask */
|
||||||
|
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
||||||
|
/* The task's functionality is called. */
|
||||||
|
return originalTask->taskFunctionality();
|
||||||
|
/* Should never be reached */
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "Polling task " << originalTask->getId() << " returned from taskFunctionality." <<
|
||||||
|
std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedTimeslotTask::missedDeadlineCounter() {
|
||||||
|
FixedTimeslotTask::deadlineMissedCount++;
|
||||||
|
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount
|
||||||
|
<< " deadlines." << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||||
|
rtems_status_code status = rtems_task_start(id, FixedTimeslotTask::taskEntryPoint,
|
||||||
|
rtems_task_argument((void *) this));
|
||||||
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PollingTask::startTask for " << std::hex << this->getId()
|
||||||
|
<< std::dec << " failed." << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
switch(status){
|
||||||
|
case RTEMS_SUCCESSFUL:
|
||||||
|
//ask started successfully
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
RTEMS_INVALID_ADDRESS - invalid task entry point
|
||||||
|
RTEMS_INVALID_ID - invalid task id
|
||||||
|
RTEMS_INCORRECT_STATE - task not in the dormant state
|
||||||
|
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
|
||||||
|
uint32_t slotTimeMs, int8_t executionStep) {
|
||||||
|
ExecutableObjectIF* object = objectManager->get<ExecutableObjectIF>(componentId);
|
||||||
|
if (object != nullptr) {
|
||||||
|
pst.addSlot(componentId, slotTimeMs, executionStep, object, 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 start time for
|
||||||
|
the first entry. */
|
||||||
|
FixedSlotSequence::SlotListIter it = pst.current;
|
||||||
|
|
||||||
|
/* Initialize the PST with the correct calling task */
|
||||||
|
pst.intializeSequenceAfterTaskCreation();
|
||||||
|
|
||||||
|
/* The start time for the first entry is read. */
|
||||||
|
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
|
||||||
|
RTEMSTaskBase::setAndStartPeriod(interval,&periodId);
|
||||||
|
//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 = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs());
|
||||||
|
/* The period is checked and restarted with the new interval.
|
||||||
|
If the deadline was missed, the deadlineMissedFunc is called. */
|
||||||
|
rtems_status_code status = RTEMSTaskBase::restartPeriod(interval,periodId);
|
||||||
|
if (status == RTEMS_TIMEOUT) {
|
||||||
|
if (this->deadlineMissedFunc != nullptr) {
|
||||||
|
this->deadlineMissedFunc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* The device handler for this slot is executed and the next one is chosen. */
|
||||||
|
this->pst.executeAndAdvance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms){
|
||||||
|
return RTEMSTaskBase::sleepFor(ms);
|
||||||
|
};
|
81
osal/rtems/FixedTimeslotTask.h
Normal file
81
osal/rtems/FixedTimeslotTask.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#ifndef FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
|
||||||
|
#define FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
|
||||||
|
|
||||||
|
#include "RTEMSTaskBase.h"
|
||||||
|
#include "../../tasks/FixedSlotSequence.h"
|
||||||
|
#include "../../tasks/FixedTimeslotTaskIF.h"
|
||||||
|
|
||||||
|
class FixedTimeslotTask: public RTEMSTaskBase, public FixedTimeslotTaskIF {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief The standard constructor of the class.
|
||||||
|
* @details
|
||||||
|
* This is the general constructor of the class. In addition to the TaskBase parameters,
|
||||||
|
* the following variables are passed:
|
||||||
|
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
|
||||||
|
* that shall be assigned.
|
||||||
|
* @param getPst The object id of the completely initialized polling sequence.
|
||||||
|
*/
|
||||||
|
FixedTimeslotTask( const char *name, rtems_task_priority setPriority, size_t setStackSize,
|
||||||
|
uint32_t 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 andthe 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);
|
||||||
|
|
||||||
|
uint32_t getPeriodMs() const;
|
||||||
|
|
||||||
|
ReturnValue_t checkSequence() const;
|
||||||
|
|
||||||
|
ReturnValue_t sleepFor(uint32_t ms);
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief id of the associated OS period
|
||||||
|
*/
|
||||||
|
rtems_id periodId;
|
||||||
|
|
||||||
|
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 ) = nullptr;
|
||||||
|
/**
|
||||||
|
* @brief This is the entry point in a new polling thread.
|
||||||
|
* @details This method is the entry point in the new thread
|
||||||
|
*/
|
||||||
|
static rtems_task taskEntryPoint( rtems_task_argument argument );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function holds the main functionality of the thread.
|
||||||
|
* @details
|
||||||
|
* Holding the main functionality of the task, this method is most important.
|
||||||
|
* It links the functionalities provided by FixedSlotSequence with the OS's system calls to
|
||||||
|
* keep the timing of the periods.
|
||||||
|
*/
|
||||||
|
void taskFunctionality( void );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ */
|
@ -1,92 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file MultiObjectTask.cpp
|
|
||||||
* @brief This file defines the MultiObjectTask class.
|
|
||||||
* @date 30.01.2014
|
|
||||||
* @author baetz
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include "../../tasks/ExecutableObjectIF.h"
|
|
||||||
#include "MultiObjectTask.h"
|
|
||||||
|
|
||||||
MultiObjectTask::MultiObjectTask(const char *name, rtems_task_priority setPriority,
|
|
||||||
size_t setStack, rtems_interval setPeriod, void (*setDeadlineMissedFunc)()) :
|
|
||||||
TaskBase(setPriority, setStack, name), periodTicks(
|
|
||||||
RtemsBasic::convertMsToTicks(setPeriod)), periodId(0), deadlineMissedFunc(
|
|
||||||
setDeadlineMissedFunc) {
|
|
||||||
}
|
|
||||||
|
|
||||||
MultiObjectTask::~MultiObjectTask(void) {
|
|
||||||
//Do not delete objects, we were responsible for ptrs only.
|
|
||||||
rtems_rate_monotonic_delete(periodId);
|
|
||||||
}
|
|
||||||
rtems_task MultiObjectTask::taskEntryPoint(rtems_task_argument argument) {
|
|
||||||
//The argument is re-interpreted as MultiObjectTask. The Task object is global, so it is found from any place.
|
|
||||||
MultiObjectTask *originalTask(reinterpret_cast<MultiObjectTask*>(argument));
|
|
||||||
originalTask->taskFunctionality();
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MultiObjectTask::startTask() {
|
|
||||||
rtems_status_code status = rtems_task_start(id, MultiObjectTask::taskEntryPoint,
|
|
||||||
rtems_task_argument((void *) this));
|
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "ObjectTask::startTask for " << std::hex << this->getId()
|
|
||||||
<< std::dec << " failed." << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
switch(status){
|
|
||||||
case RTEMS_SUCCESSFUL:
|
|
||||||
//ask started successfully
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
default:
|
|
||||||
/* RTEMS_INVALID_ADDRESS - invalid task entry point
|
|
||||||
RTEMS_INVALID_ID - invalid task id
|
|
||||||
RTEMS_INCORRECT_STATE - task not in the dormant state
|
|
||||||
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MultiObjectTask::sleepFor(uint32_t ms) {
|
|
||||||
return TaskBase::sleepFor(ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MultiObjectTask::taskFunctionality() {
|
|
||||||
TaskBase::setAndStartPeriod(periodTicks,&periodId);
|
|
||||||
//The task's "infinite" inner loop is entered.
|
|
||||||
while (1) {
|
|
||||||
for (ObjectList::iterator it = objectList.begin();
|
|
||||||
it != objectList.end(); ++it) {
|
|
||||||
(*it)->performOperation();
|
|
||||||
}
|
|
||||||
rtems_status_code status = TaskBase::restartPeriod(periodTicks,periodId);
|
|
||||||
if (status == RTEMS_TIMEOUT) {
|
|
||||||
char nameSpace[8] = { 0 };
|
|
||||||
char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace),
|
|
||||||
nameSpace);
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "ObjectTask: " << ptr << " Deadline missed." << std::endl;
|
|
||||||
#endif
|
|
||||||
if (this->deadlineMissedFunc != nullptr) {
|
|
||||||
this->deadlineMissedFunc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MultiObjectTask::addComponent(object_id_t object) {
|
|
||||||
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(
|
|
||||||
object);
|
|
||||||
if (newObject == nullptr) {
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
objectList.push_back(newObject);
|
|
||||||
newObject->setTaskIF(this);
|
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MultiObjectTask::getPeriodMs() const {
|
|
||||||
return RtemsBasic::convertTicksToMs(periodTicks);
|
|
||||||
}
|
|
@ -1,18 +1,20 @@
|
|||||||
#include "Mutex.h"
|
#include "Mutex.h"
|
||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
#include "../../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
uint8_t Mutex::count = 0;
|
uint8_t Mutex::count = 0;
|
||||||
|
|
||||||
Mutex::Mutex() :
|
Mutex::Mutex() {
|
||||||
mutexId(0) {
|
|
||||||
rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++;
|
rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++;
|
||||||
rtems_status_code status = rtems_semaphore_create(mutexName, 1,
|
rtems_status_code status = rtems_semaphore_create(mutexName, 1,
|
||||||
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
|
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
|
||||||
&mutexId);
|
&mutexId);
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "Mutex: creation with name, id " << mutexName << ", " << mutexId
|
sif::error << "Mutex::Mutex: Creation with name, id " << mutexName << ", " << mutexId <<
|
||||||
<< " failed with " << status << std::endl;
|
" failed with " << status << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("Mutex::Mutex: Creation with name, id %s, %d failed with %d\n", mutexName,
|
||||||
|
static_cast<int>(mutexId), static_cast<int>(status));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ public:
|
|||||||
ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0);
|
ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0);
|
||||||
ReturnValue_t unlockMutex();
|
ReturnValue_t unlockMutex();
|
||||||
private:
|
private:
|
||||||
rtems_id mutexId;
|
rtems_id mutexId = 0;
|
||||||
static uint8_t count;
|
static uint8_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "../../ipc/MutexFactory.h"
|
|
||||||
#include "Mutex.h"
|
#include "Mutex.h"
|
||||||
#include "RtemsBasic.h"
|
|
||||||
|
#include "../../ipc/MutexFactory.h"
|
||||||
|
|
||||||
|
|
||||||
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
||||||
|
|
||||||
|
83
osal/rtems/PeriodicTask.cpp
Normal file
83
osal/rtems/PeriodicTask.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include "PeriodicTask.h"
|
||||||
|
|
||||||
|
#include "../../serviceinterface/ServiceInterface.h"
|
||||||
|
#include "../../tasks/ExecutableObjectIF.h"
|
||||||
|
|
||||||
|
PeriodicTask::PeriodicTask(const char *name, rtems_task_priority setPriority,
|
||||||
|
size_t setStack, rtems_interval setPeriod, void (*setDeadlineMissedFunc)()) :
|
||||||
|
RTEMSTaskBase(setPriority, setStack, name),
|
||||||
|
periodTicks(RtemsBasic::convertMsToTicks(setPeriod)),
|
||||||
|
deadlineMissedFunc(setDeadlineMissedFunc) {
|
||||||
|
}
|
||||||
|
|
||||||
|
PeriodicTask::~PeriodicTask(void) {
|
||||||
|
/* Do not delete objects, we were responsible for pointers only. */
|
||||||
|
rtems_rate_monotonic_delete(periodId);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_task PeriodicTask::taskEntryPoint(rtems_task_argument argument) {
|
||||||
|
/* The argument is re-interpreted as MultiObjectTask. The Task object is global,
|
||||||
|
so it is found from any place. */
|
||||||
|
PeriodicTask *originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||||
|
return originalTask->taskFunctionality();;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PeriodicTask::startTask() {
|
||||||
|
rtems_status_code status = rtems_task_start(id, PeriodicTask::taskEntryPoint,
|
||||||
|
rtems_task_argument((void *) this));
|
||||||
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "ObjectTask::startTask for " << std::hex << this->getId()
|
||||||
|
<< std::dec << " failed." << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
switch(status){
|
||||||
|
case RTEMS_SUCCESSFUL:
|
||||||
|
/* Task started successfully */
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
default:
|
||||||
|
/* RTEMS_INVALID_ADDRESS - invalid task entry point
|
||||||
|
RTEMS_INVALID_ID - invalid task id
|
||||||
|
RTEMS_INCORRECT_STATE - task not in the dormant state
|
||||||
|
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) {
|
||||||
|
return RTEMSTaskBase::sleepFor(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeriodicTask::taskFunctionality() {
|
||||||
|
RTEMSTaskBase::setAndStartPeriod(periodTicks,&periodId);
|
||||||
|
for (const auto& object: objectList) {
|
||||||
|
object->initializeAfterTaskCreation();
|
||||||
|
}
|
||||||
|
/* The task's "infinite" inner loop is entered. */
|
||||||
|
while (1) {
|
||||||
|
for (const auto& object: objectList) {
|
||||||
|
object->performOperation();
|
||||||
|
}
|
||||||
|
rtems_status_code status = RTEMSTaskBase::restartPeriod(periodTicks,periodId);
|
||||||
|
if (status == RTEMS_TIMEOUT) {
|
||||||
|
if (this->deadlineMissedFunc != nullptr) {
|
||||||
|
this->deadlineMissedFunc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
||||||
|
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(object);
|
||||||
|
if (newObject == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
objectList.push_back(newObject);
|
||||||
|
newObject->setTaskIF(this);
|
||||||
|
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PeriodicTask::getPeriodMs() const {
|
||||||
|
return RtemsBasic::convertTicksToMs(periodTicks);
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
#ifndef FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_
|
#ifndef FSFW_OSAL_RTEMS_PERIODICTASK_H_
|
||||||
#define FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_
|
#define FSFW_OSAL_RTEMS_PERIODICTASK_H_
|
||||||
|
|
||||||
|
#include "RTEMSTaskBase.h"
|
||||||
#include "../../objectmanager/ObjectManagerIF.h"
|
#include "../../objectmanager/ObjectManagerIF.h"
|
||||||
#include "../../tasks/PeriodicTaskIF.h"
|
#include "../../tasks/PeriodicTaskIF.h"
|
||||||
|
|
||||||
#include "TaskBase.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class ExecutableObjectIF;
|
class ExecutableObjectIF;
|
||||||
@ -18,7 +18,7 @@ class ExecutableObjectIF;
|
|||||||
* @author baetz
|
* @author baetz
|
||||||
* @ingroup task_handling
|
* @ingroup task_handling
|
||||||
*/
|
*/
|
||||||
class MultiObjectTask: public TaskBase, public PeriodicTaskIF {
|
class PeriodicTask: public RTEMSTaskBase, public PeriodicTaskIF {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Standard constructor of the class.
|
* @brief Standard constructor of the class.
|
||||||
@ -35,13 +35,13 @@ public:
|
|||||||
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
|
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
|
||||||
* that shall be assigned.
|
* that shall be assigned.
|
||||||
*/
|
*/
|
||||||
MultiObjectTask(const char *name, rtems_task_priority setPriority, size_t setStack, rtems_interval setPeriod,
|
PeriodicTask(const char *name, rtems_task_priority setPriority, size_t setStack,
|
||||||
void (*setDeadlineMissedFunc)());
|
rtems_interval setPeriod, void (*setDeadlineMissedFunc)());
|
||||||
/**
|
/**
|
||||||
* @brief Currently, the executed object's lifetime is not coupled with the task object's
|
* @brief Currently, the executed object's lifetime is not coupled with the task object's
|
||||||
* lifetime, so the destructor is empty.
|
* lifetime, so the destructor is empty.
|
||||||
*/
|
*/
|
||||||
virtual ~MultiObjectTask(void);
|
virtual ~PeriodicTask(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The method to start the task.
|
* @brief The method to start the task.
|
||||||
@ -76,7 +76,7 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* @brief id of the associated OS period
|
* @brief id of the associated OS period
|
||||||
*/
|
*/
|
||||||
rtems_id periodId;
|
rtems_id periodId = 0;
|
||||||
/**
|
/**
|
||||||
* @brief The pointer to the deadline-missed function.
|
* @brief The pointer to the deadline-missed function.
|
||||||
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
||||||
@ -104,4 +104,4 @@ protected:
|
|||||||
void taskFunctionality(void);
|
void taskFunctionality(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ */
|
#endif /* FSFW_OSAL_RTEMS_PERIODICTASK_H_ */
|
@ -1,131 +0,0 @@
|
|||||||
#include "../../tasks/FixedSequenceSlot.h"
|
|
||||||
#include "../../objectmanager/SystemObjectIF.h"
|
|
||||||
#include "../../objectmanager/ObjectManagerIF.h"
|
|
||||||
#include "PollingTask.h"
|
|
||||||
#include "RtemsBasic.h"
|
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
|
||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include <rtems/bspIo.h>
|
|
||||||
#include <rtems/rtems/ratemon.h>
|
|
||||||
#include <rtems/rtems/status.h>
|
|
||||||
#include <rtems/rtems/tasks.h>
|
|
||||||
#include <rtems/rtems/types.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <sys/_stdint.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
uint32_t PollingTask::deadlineMissedCount = 0;
|
|
||||||
|
|
||||||
PollingTask::PollingTask(const char *name, rtems_task_priority setPriority,
|
|
||||||
size_t setStack, uint32_t setOverallPeriod,
|
|
||||||
void (*setDeadlineMissedFunc)()) :
|
|
||||||
TaskBase(setPriority, setStack, name), periodId(0), pst(
|
|
||||||
setOverallPeriod) {
|
|
||||||
// All additional attributes are applied to the object.
|
|
||||||
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
PollingTask::~PollingTask() {
|
|
||||||
}
|
|
||||||
|
|
||||||
rtems_task PollingTask::taskEntryPoint(rtems_task_argument argument) {
|
|
||||||
|
|
||||||
//The argument is re-interpreted as PollingTask.
|
|
||||||
PollingTask *originalTask(reinterpret_cast<PollingTask*>(argument));
|
|
||||||
//The task's functionality is called.
|
|
||||||
originalTask->taskFunctionality();
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::debug << "Polling task " << originalTask->getId()
|
|
||||||
<< " returned from taskFunctionality." << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PollingTask::missedDeadlineCounter() {
|
|
||||||
PollingTask::deadlineMissedCount++;
|
|
||||||
if (PollingTask::deadlineMissedCount % 10 == 0) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PST missed " << PollingTask::deadlineMissedCount
|
|
||||||
<< " deadlines." << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PollingTask::startTask() {
|
|
||||||
rtems_status_code status = rtems_task_start(id, PollingTask::taskEntryPoint,
|
|
||||||
rtems_task_argument((void *) this));
|
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PollingTask::startTask for " << std::hex << this->getId()
|
|
||||||
<< std::dec << " failed." << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
switch(status){
|
|
||||||
case RTEMS_SUCCESSFUL:
|
|
||||||
//ask started successfully
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
default:
|
|
||||||
/* RTEMS_INVALID_ADDRESS - invalid task entry point
|
|
||||||
RTEMS_INVALID_ID - invalid task id
|
|
||||||
RTEMS_INCORRECT_STATE - task not in the dormant state
|
|
||||||
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PollingTask::addSlot(object_id_t componentId,
|
|
||||||
uint32_t slotTimeMs, int8_t executionStep) {
|
|
||||||
ExecutableObjectIF* object = objectManager->get<ExecutableObjectIF>(componentId);
|
|
||||||
if (object != nullptr) {
|
|
||||||
pst.addSlot(componentId, slotTimeMs, executionStep, object, 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 PollingTask::getPeriodMs() const {
|
|
||||||
return pst.getLengthMs();
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PollingTask::checkSequence() const {
|
|
||||||
return pst.checkSequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <rtems/io.h>
|
|
||||||
|
|
||||||
void PollingTask::taskFunctionality() {
|
|
||||||
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
|
|
||||||
FixedSlotSequence::SlotListIter it = pst.current;
|
|
||||||
|
|
||||||
//The start time for the first entry is read.
|
|
||||||
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
|
|
||||||
TaskBase::setAndStartPeriod(interval,&periodId);
|
|
||||||
//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 = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs());
|
|
||||||
//The period is checked and restarted with the new interval.
|
|
||||||
//If the deadline was missed, the deadlineMissedFunc is called.
|
|
||||||
rtems_status_code status = TaskBase::restartPeriod(interval,periodId);
|
|
||||||
if (status == RTEMS_TIMEOUT) {
|
|
||||||
if (this->deadlineMissedFunc != nullptr) {
|
|
||||||
this->deadlineMissedFunc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//The device handler for this slot is executed and the next one is chosen.
|
|
||||||
this->pst.executeAndAdvance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PollingTask::sleepFor(uint32_t ms){
|
|
||||||
return TaskBase::sleepFor(ms);
|
|
||||||
};
|
|
@ -1,85 +0,0 @@
|
|||||||
#ifndef FSFW_OSAL_RTEMS_POLLINGTASK_H_
|
|
||||||
#define FSFW_OSAL_RTEMS_POLLINGTASK_H_
|
|
||||||
|
|
||||||
#include "../../tasks/FixedSlotSequence.h"
|
|
||||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
|
||||||
#include "TaskBase.h"
|
|
||||||
|
|
||||||
class PollingTask: public TaskBase, public FixedTimeslotTaskIF {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief The standard constructor of the class.
|
|
||||||
*
|
|
||||||
* @details This is the general constructor of the class. In addition to the TaskBase parameters,
|
|
||||||
* the following variables are passed:
|
|
||||||
*
|
|
||||||
* @param (*setDeadlineMissedFunc)() The function pointer to the deadline missed function that shall be assigned.
|
|
||||||
*
|
|
||||||
* @param getPst The object id of the completely initialized polling sequence.
|
|
||||||
*/
|
|
||||||
PollingTask( const char *name, rtems_task_priority setPriority, size_t setStackSize, uint32_t 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 ~PollingTask( 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);
|
|
||||||
|
|
||||||
uint32_t getPeriodMs() const;
|
|
||||||
|
|
||||||
ReturnValue_t checkSequence() const;
|
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms);
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief id of the associated OS period
|
|
||||||
*/
|
|
||||||
rtems_id periodId;
|
|
||||||
|
|
||||||
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 in a new polling thread.
|
|
||||||
*
|
|
||||||
* @details This method, that is the generalOSAL::checkAndRestartPeriod( this->periodId, interval ); entry point in the new thread, is here set to generate
|
|
||||||
* and link the Polling Sequence Table to the thread object and start taskFunctionality()
|
|
||||||
* on success. If operation of the task is ended for some reason,
|
|
||||||
* the destructor is called to free allocated memory.
|
|
||||||
*/
|
|
||||||
static rtems_task taskEntryPoint( rtems_task_argument argument );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This function holds the main functionality of the thread.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @details Holding the main functionality of the task, this method is most important.
|
|
||||||
* It links the functionalities provided by FixedSlotSequence with the OS's System Calls
|
|
||||||
* to keep the timing of the periods.
|
|
||||||
*/
|
|
||||||
void taskFunctionality( void );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_RTEMS_POLLINGTASK_H_ */
|
|
84
osal/rtems/RTEMSTaskBase.cpp
Normal file
84
osal/rtems/RTEMSTaskBase.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "RTEMSTaskBase.h"
|
||||||
|
#include "../../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = RTEMS_MINIMUM_STACK_SIZE;
|
||||||
|
|
||||||
|
RTEMSTaskBase::RTEMSTaskBase(rtems_task_priority set_priority, size_t stack_size,
|
||||||
|
const char *name) {
|
||||||
|
rtems_name osalName = 0;
|
||||||
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
|
if (name[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
osalName += name[i] << (8 * (3 - i));
|
||||||
|
}
|
||||||
|
//The task is created with the operating system's system call.
|
||||||
|
rtems_status_code status = RTEMS_UNSATISFIED;
|
||||||
|
if (set_priority <= 99) {
|
||||||
|
status = rtems_task_create(osalName,
|
||||||
|
(0xFF - 2 * set_priority), stack_size,
|
||||||
|
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
|
||||||
|
RTEMS_FLOATING_POINT, &id);
|
||||||
|
}
|
||||||
|
ReturnValue_t result = convertReturnCode(status);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "TaskBase::TaskBase: createTask with name " << std::hex
|
||||||
|
<< osalName << std::dec << " failed with return code "
|
||||||
|
<< (uint32_t) status << std::endl;
|
||||||
|
#endif
|
||||||
|
this->id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RTEMSTaskBase::~RTEMSTaskBase() {
|
||||||
|
rtems_task_delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_id RTEMSTaskBase::getId() {
|
||||||
|
return this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t RTEMSTaskBase::sleepFor(uint32_t ms) {
|
||||||
|
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
|
||||||
|
return convertReturnCode(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t RTEMSTaskBase::convertReturnCode(rtems_status_code inValue) {
|
||||||
|
switch (inValue) {
|
||||||
|
case RTEMS_SUCCESSFUL:
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
case RTEMS_MP_NOT_CONFIGURED:
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
case RTEMS_INVALID_NAME:
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
case RTEMS_TOO_MANY:
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
case RTEMS_INVALID_ADDRESS:
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
case RTEMS_UNSATISFIED:
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
case RTEMS_INVALID_PRIORITY:
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
default:
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t RTEMSTaskBase::setAndStartPeriod(rtems_interval period, rtems_id *periodId) {
|
||||||
|
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
|
||||||
|
rtems_status_code status = rtems_rate_monotonic_create(periodName, periodId);
|
||||||
|
if (status == RTEMS_SUCCESSFUL) {
|
||||||
|
status = restartPeriod(period,*periodId);
|
||||||
|
}
|
||||||
|
return convertReturnCode(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_status_code RTEMSTaskBase::restartPeriod(rtems_interval period, rtems_id periodId){
|
||||||
|
//This is necessary to avoid a call with period = 0, which does not start the period.
|
||||||
|
rtems_status_code status = rtems_rate_monotonic_period(periodId, period + 1);
|
||||||
|
return status;
|
||||||
|
}
|
47
osal/rtems/RTEMSTaskBase.h
Normal file
47
osal/rtems/RTEMSTaskBase.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_
|
||||||
|
#define FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_
|
||||||
|
|
||||||
|
#include "RtemsBasic.h"
|
||||||
|
#include "../../tasks/PeriodicTaskIF.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This is the basic task handling class for rtems.
|
||||||
|
*
|
||||||
|
* @details Task creation base class for rtems.
|
||||||
|
*/
|
||||||
|
class RTEMSTaskBase {
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief The class stores the task id it got assigned from the operating system in this attribute.
|
||||||
|
* If initialization fails, the id is set to zero.
|
||||||
|
*/
|
||||||
|
rtems_id id;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief The constructor creates and initializes a task.
|
||||||
|
* @details This is accomplished by using the operating system call to create a task. The name is
|
||||||
|
* created automatically with the help od taskCounter. Priority and stack size are
|
||||||
|
* adjustable, all other attributes are set with default values.
|
||||||
|
* @param priority Sets the priority of a task. Values range from a low 0 to a high 99.
|
||||||
|
* @param stack_size The stack size reserved by the operating system for the task.
|
||||||
|
* @param nam The name of the Task, as a null-terminated String. Currently max 4 chars supported (excluding Null-terminator), rest will be truncated
|
||||||
|
*/
|
||||||
|
RTEMSTaskBase( rtems_task_priority priority, size_t stack_size, const char *name);
|
||||||
|
/**
|
||||||
|
* @brief In the destructor, the created task is deleted.
|
||||||
|
*/
|
||||||
|
virtual ~RTEMSTaskBase();
|
||||||
|
/**
|
||||||
|
* @brief This method returns the task id of this class.
|
||||||
|
*/
|
||||||
|
rtems_id getId();
|
||||||
|
|
||||||
|
ReturnValue_t sleepFor(uint32_t ms);
|
||||||
|
static ReturnValue_t setAndStartPeriod(rtems_interval period, rtems_id *periodId);
|
||||||
|
static rtems_status_code restartPeriod(rtems_interval period, rtems_id periodId);
|
||||||
|
private:
|
||||||
|
static ReturnValue_t convertReturnCode(rtems_status_code inValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_ */
|
@ -1,5 +1,6 @@
|
|||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
|
|
||||||
|
// TODO: Can this be removed?
|
||||||
|
|
||||||
//ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
|
//ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
|
||||||
// if (inValue == RTEMS_SUCCESSFUL) {
|
// if (inValue == RTEMS_SUCCESSFUL) {
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_
|
#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_
|
||||||
|
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
#include <rtems/libio.h>
|
#include <rtems/libio.h>
|
||||||
#include <rtems/error.h>
|
#include <rtems/error.h>
|
||||||
#include <rtems/stackchk.h>
|
#include <rtems/stackchk.h>
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
class RtemsBasic {
|
class RtemsBasic {
|
||||||
public:
|
public:
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "../../tasks/TaskFactory.h"
|
#include "FixedTimeslotTask.h"
|
||||||
#include "MultiObjectTask.h"
|
#include "PeriodicTask.h"
|
||||||
#include "PollingTask.h"
|
|
||||||
#include "InitTask.h"
|
#include "InitTask.h"
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
|
|
||||||
|
#include "../../tasks/TaskFactory.h"
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
//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?
|
||||||
@ -15,15 +16,21 @@ TaskFactory* TaskFactory::instance() {
|
|||||||
return TaskFactory::factoryInstance;
|
return TaskFactory::factoryInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
|
||||||
|
TaskStackSize stackSize_,TaskPeriod periodInSeconds_,
|
||||||
|
TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||||
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
||||||
|
|
||||||
return static_cast<PeriodicTaskIF*>(new MultiObjectTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_));
|
return static_cast<PeriodicTaskIF*>(new PeriodicTask(name_, taskPriority_, stackSize_,
|
||||||
|
taskPeriod,deadLineMissedFunction_));
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,
|
||||||
|
TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,
|
||||||
|
TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||||
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
||||||
return static_cast<FixedTimeslotTaskIF*>(new PollingTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_));
|
return static_cast<FixedTimeslotTaskIF*>(new FixedTimeslotTask(name_, taskPriority_,
|
||||||
|
stackSize_, taskPeriod, deadLineMissedFunction_));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
||||||
|
Loading…
Reference in New Issue
Block a user