updating code from Flying Laptop

This is the framework of Flying Laptop OBSW version A.13.0.
This commit is contained in:
2018-07-12 16:29:32 +02:00
parent 1d22a6c97e
commit 575f70ba03
395 changed files with 12807 additions and 8404 deletions

145
osal/rtems/Clock.cpp Normal file
View File

@ -0,0 +1,145 @@
#include <framework/timemanager/Clock.h>
#include "RtemsBasic.h"
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
uint32_t Clock::getTicksPerSecond(void){
rtems_interval ticks_per_second;
(void) rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
return ticks_per_second;
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
//We need to cast to rtems internal time of day type here. Both structs have the same structure
//rtems provides no const guarantee, so we need to cast the const away
//TODO Check if this can be done safely
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(const_cast<TimeOfDay_t*>(time));
rtems_status_code status = rtems_clock_set(timeRtems);
return RtemsBasic::convertReturnCode(status);
}
ReturnValue_t Clock::setClock(const timeval* time) {
timespec newTime;
newTime.tv_sec = time->tv_sec;
newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND;
//SHOULDDO: Not sure if we need to protect this call somehow (by thread lock or something).
//Uli: rtems docu says you can call this from an ISR, not sure if this means no protetion needed
_TOD_Set(&newTime);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) {
rtems_status_code status = rtems_clock_get_tod_timeval(time);
return RtemsBasic::convertReturnCode(status);
}
ReturnValue_t Clock::getUptime(timeval* uptime) {
timespec time;
rtems_status_code status = rtems_clock_get_uptime(&time);
uptime->tv_sec = time.tv_sec;
time.tv_nsec = time.tv_nsec / 1000;
uptime->tv_usec = time.tv_nsec;
return RtemsBasic::convertReturnCode(status);
}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
*uptimeMs = rtems_clock_get_ticks_since_boot();
return RtemsBasic::convertReturnCode(RTEMS_SUCCESSFUL);
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval temp_time;
rtems_status_code returnValue = rtems_clock_get_tod_timeval(&temp_time);
*time = ((uint64_t) temp_time.tv_sec * 1000000) + temp_time.tv_usec;
return RtemsBasic::convertReturnCode(returnValue);
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time);
rtems_status_code status = rtems_clock_get_tod(timeRtems);
return RtemsBasic::convertReturnCode(status);
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
timeval* to) {
//Fails in 2038..
const rtems_time_of_day* timeRtems = reinterpret_cast<const rtems_time_of_day*>(from);
to->tv_sec = _TOD_To_seconds(timeRtems);
to->tv_usec = timeRtems->ticks * 1000;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24.
/ 3600.;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
//SHOULDDO: works not for dates in the past (might have less leap seconds)
if (timeMutex == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
uint16_t leapSeconds;
ReturnValue_t result = getLeapSeconds(&leapSeconds);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
timeval leapSeconds_timeval = { 0, 0 };
leapSeconds_timeval.tv_sec = leapSeconds;
//initial offset between UTC and TAI
timeval UTCtoTAI1972 = { 10, 0 };
timeval TAItoTT = { 32, 184000 };
*tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
leapSeconds = leapSeconds_;
result = timeMutex->unlockMutex();
return result;
}
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
if(timeMutex==NULL){
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
*leapSeconds_ = leapSeconds;
result = timeMutex->unlockMutex();
return result;
}
ReturnValue_t Clock::checkOrCreateClockMutex(){
if(timeMutex==NULL){
MutexFactory* mutexFactory = MutexFactory::instance();
if (mutexFactory == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
timeMutex = mutexFactory->createMutex();
if (timeMutex == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}

27
osal/rtems/InitTask.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "InitTask.h"
#include "RtemsBasic.h"
InitTask::InitTask() {
}
InitTask::~InitTask() {
}
void InitTask::deleteTask(){
rtems_task_delete(RTEMS_SELF);
}
ReturnValue_t InitTask::startTask() {
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t InitTask::sleepFor(uint32_t ms) {
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
return RtemsBasic::convertReturnCode(status);
}
uint32_t InitTask::getPeriodMs() const {
return 0;
}

28
osal/rtems/InitTask.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef OS_RTEMS_INITTASK_H_
#define OS_RTEMS_INITTASK_H_
#include <framework/tasks/PeriodicTaskIF.h>
//TODO move into static function in TaskIF
/**
* The init task is created automatically by RTEMS.
* As one may need to control it (e.g. suspending it for a while),
* this dummy class provides an implementation of TaskIF to do so.
* Warning: The init task is deleted with this stub, i.e. the destructor
* calls rtems_task_delete(RTEMS_SELF)
*/
class InitTask: public PeriodicTaskIF {
public:
InitTask();
virtual ~InitTask();
ReturnValue_t startTask();
ReturnValue_t sleepFor(uint32_t ms);
uint32_t getPeriodMs() const;
void deleteTask();
};
#endif /* OS_RTEMS_INITTASK_H_ */

View File

@ -0,0 +1,59 @@
#include <framework/osal/InternalErrorCodes.h>
#include <rtems/score/interr.h>
ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
switch (code) {
case INTERNAL_ERROR_NO_CONFIGURATION_TABLE:
return NO_CONFIGURATION_TABLE;
case INTERNAL_ERROR_NO_CPU_TABLE:
return NO_CPU_TABLE;
case INTERNAL_ERROR_INVALID_WORKSPACE_ADDRESS:
return INVALID_WORKSPACE_ADDRESS;
case INTERNAL_ERROR_TOO_LITTLE_WORKSPACE:
return TOO_LITTLE_WORKSPACE;
case INTERNAL_ERROR_WORKSPACE_ALLOCATION:
return WORKSPACE_ALLOCATION;
case INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL:
return INTERRUPT_STACK_TOO_SMALL;
case INTERNAL_ERROR_THREAD_EXITTED:
return THREAD_EXITTED;
case INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION:
return INCONSISTENT_MP_INFORMATION;
case INTERNAL_ERROR_INVALID_NODE:
return INVALID_NODE;
case INTERNAL_ERROR_NO_MPCI:
return NO_MPCI;
case INTERNAL_ERROR_BAD_PACKET:
return BAD_PACKET;
case INTERNAL_ERROR_OUT_OF_PACKETS:
return OUT_OF_PACKETS;
case INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS:
return OUT_OF_GLOBAL_OBJECTS;
case INTERNAL_ERROR_OUT_OF_PROXIES:
return OUT_OF_PROXIES;
case INTERNAL_ERROR_INVALID_GLOBAL_ID:
return INVALID_GLOBAL_ID;
case INTERNAL_ERROR_BAD_STACK_HOOK:
return BAD_STACK_HOOK;
case INTERNAL_ERROR_BAD_ATTRIBUTES:
return BAD_ATTRIBUTES;
case INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY:
return IMPLEMENTATION_KEY_CREATE_INCONSISTENCY;
case INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL:
return IMPLEMENTATION_BLOCKING_OPERATION_CANCEL;
case INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE:
return MUTEX_OBTAIN_FROM_BAD_STATE;
case INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0:
return UNLIMITED_AND_MAXIMUM_IS_0;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
InternalErrorCodes::InternalErrorCodes() {
}
InternalErrorCodes::~InternalErrorCodes() {
}

70
osal/rtems/Interrupt.cpp Normal file
View File

@ -0,0 +1,70 @@
#include "Interrupt.h"
#include <bsp_flp/bsp_flp.h>
#include "RtemsBasic.h"
ReturnValue_t Interrupt::enableInterrupt(InterruptNumber_t interruptNumber) {
volatile uint32_t* irqMask = hw_irq_mask;
uint32_t expectedValue = *irqMask | (1 << interruptNumber);
*irqMask = expectedValue;
uint32_t tempValue = *irqMask;
if (tempValue == expectedValue) {
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t Interrupt::setInterruptServiceRoutine(IsrHandler_t handler,
InterruptNumber_t interrupt, IsrHandler_t* oldHandler) {
IsrHandler_t oldHandler_local;
if (oldHandler == NULL) {
oldHandler = &oldHandler_local;
}
//+ 0x10 comes because of trap type assignment to IRQs in UT699 processor
rtems_status_code status = rtems_interrupt_catch(handler, interrupt + 0x10,
oldHandler);
return RtemsBasic::convertReturnCode(status);
}
ReturnValue_t Interrupt::disableInterrupt(InterruptNumber_t interruptNumber) {
//TODO Not implemented
return HasReturnvaluesIF::RETURN_FAILED;
}
//SHOULDDO: Make default values (edge, polarity) settable?
ReturnValue_t Interrupt::enableGpioInterrupt(InterruptNumber_t interrupt) {
volatile uint32_t* irqMask = hw_irq_mask;
uint32_t expectedValue = *irqMask | (1 << interrupt);
*irqMask = expectedValue;
uint32_t tempValue = *irqMask;
if (tempValue == expectedValue) {
volatile hw_gpio_port_t* ioPorts = hw_gpio_port;
ioPorts->direction &= ~(1 << interrupt); //Direction In
ioPorts->interrupt_edge |= 1 << interrupt; //Edge triggered
ioPorts->interrupt_polarity |= 1 << interrupt; //Trigger on rising edge
ioPorts->interrupt_mask |= 1 << interrupt; //Enable
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t Interrupt::disableGpioInterrupt(InterruptNumber_t interrupt) {
volatile uint32_t* irqMask = hw_irq_mask;
uint32_t expectedValue = *irqMask & ~(1 << interrupt);
*irqMask = expectedValue;
uint32_t tempValue = *irqMask;
if (tempValue == expectedValue) {
//Disable gpio IRQ
volatile hw_gpio_port_t* ioPorts = hw_gpio_port;
ioPorts->interrupt_mask &= ~(1 << interrupt);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
bool Interrupt::isInterruptInProgress() {
return rtems_interrupt_is_in_progress();
}

50
osal/rtems/Interrupt.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef OS_RTEMS_INTERRUPT_H_
#define OS_RTEMS_INTERRUPT_H_
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <cstring>
#include <rtems.h>
typedef rtems_isr_entry IsrHandler_t;
typedef rtems_isr IsrReturn_t;
typedef rtems_vector_number InterruptNumber_t;
class Interrupt {
public:
virtual ~Interrupt(){};
/**
* Establishes a new interrupt service routine.
* @param handler The service routine to establish
* @param interrupt The interrupt (NOT trap type) the routine shall react to.
* @return RETURN_OK on success. Otherwise, the OS failure code is returned.
*/
static ReturnValue_t setInterruptServiceRoutine(IsrHandler_t handler,
InterruptNumber_t interrupt, IsrHandler_t *oldHandler = NULL);
static ReturnValue_t enableInterrupt(InterruptNumber_t interruptNumber);
static ReturnValue_t disableInterrupt(InterruptNumber_t interruptNumber);
/**
* Enables the interrupt given.
* The function tests, if the InterruptMask register was written successfully.
* @param interrupt The interrupt to enable.
* @return RETURN_OK if the interrupt was set successfully. RETURN_FAILED else.
*/
static ReturnValue_t enableGpioInterrupt(InterruptNumber_t interrupt);
/**
* Disables the interrupt given.
* @param interrupt The interrupt to disable.
* @return RETURN_OK if the interrupt was set successfully. RETURN_FAILED else.
*/
static ReturnValue_t disableGpioInterrupt(InterruptNumber_t interrupt);
/**
* Checks if the current executing context is an ISR.
* @return true if handling an interrupt, false else.
*/
static bool isInterruptInProgress();
};
#endif /* OS_RTEMS_INTERRUPT_H_ */

116
osal/rtems/MessageQueue.cpp Normal file
View File

@ -0,0 +1,116 @@
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include "MessageQueue.h"
#include "RtemsBasic.h"
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) :
id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(NULL) {
rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
rtems_status_code status = rtems_message_queue_create(name, message_depth,
max_message_size, 0, &(this->id));
if (status != RTEMS_SUCCESSFUL) {
error << "MessageQueue::MessageQueue: Creating Queue " << std::hex
<< name << std::dec << " failed with status:"
<< (uint32_t) status << std::endl;
this->id = 0;
}
}
MessageQueue::~MessageQueue() {
rtems_message_queue_delete(id);
}
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, bool ignoreFault) {
return sendMessage(sendTo, message, this->getId(), ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) {
return sendToDefault(message, this->getId());
}
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
if (this->lastPartner != 0) {
return sendMessage(this->lastPartner, message, this->getId());
} else {
//TODO: Good returnCode
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->lastPartner;
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
rtems_status_code status = rtems_message_queue_receive(id,
message->getBuffer(), &(message->messageSize),
RTEMS_NO_WAIT, 1);
if (status == RTEMS_SUCCESSFUL) {
this->lastPartner = message->getSender();
//Check size of incoming message.
if (message->messageSize < message->getMinimumMessageSize()) {
return HasReturnvaluesIF::RETURN_FAILED;
}
} else {
//No message was received. Keep lastPartner anyway, I might send something later.
//But still, delete packet content.
memset(message->getData(), 0, message->MAX_DATA_SIZE);
}
return RtemsBasic::convertReturnCode(status);
}
MessageQueueId_t MessageQueue::getLastPartner() const {
return this->lastPartner;
}
ReturnValue_t MessageQueue::flush(uint32_t* count) {
rtems_status_code status = rtems_message_queue_flush(id, count);
return RtemsBasic::convertReturnCode(status);
}
MessageQueueId_t MessageQueue::getId() const {
return this->id;
}
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDestination = defaultDestination;
}
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
message->setSender(sentFrom);
rtems_status_code result = rtems_message_queue_send(sendTo,
message->getBuffer(), message->messageSize);
//TODO: Check if we're in ISR.
if (result != RTEMS_SUCCESSFUL && !ignoreFault) {
if (internalErrorReporter == NULL) {
internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
}
if (internalErrorReporter != NULL) {
internalErrorReporter->queueMessageNotSent();
}
}
return result;
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessage(defaultDestination, message, sentFrom, ignoreFault);
}
MessageQueueId_t MessageQueue::getDefaultDestination() const {
return this->defaultDestination;
}
bool MessageQueue::isDefaultDestinationSet() const {
return (defaultDestination != NO_QUEUE);
}
uint16_t MessageQueue::queueCounter = 0;

174
osal/rtems/MessageQueue.h Normal file
View File

@ -0,0 +1,174 @@
/**
* @file MessageQueue.h
*
* @date 10/02/2012
* @author Bastian Baetz
*
* @brief This file contains the definition of the MessageQueue class.
*/
#ifndef MESSAGEQUEUE_H_
#define MESSAGEQUEUE_H_
#include <framework/internalError/InternalErrorReporterIF.h>
#include <framework/ipc/MessageQueueIF.h>
#include <framework/ipc/MessageQueueMessage.h>
/**
* @brief This class manages sending and receiving of message queue messages.
*
* @details Message queues are used to pass asynchronous messages between processes.
* They work like post boxes, where all incoming messages are stored in FIFO
* order. This class creates a new receiving queue and provides methods to fetch
* received messages. Being a child of MessageQueueSender, this class also provides
* methods to send a message to a user-defined or a default destination. In addition
* it also provides a reply method to answer to the queue it received its last message
* from.
* The MessageQueue should be used as "post box" for a single owning object. So all
* message queue communication is "n-to-one".
* For creating the queue, as well as sending and receiving messages, the class makes
* use of the operating system calls provided.
* \ingroup message_queue
*/
class MessageQueue : public MessageQueueIF {
public:
/**
* @brief The constructor initializes and configures the message queue.
* @details By making use of the according operating system call, a message queue is created
* and initialized. The message depth - the maximum number of messages to be
* buffered - may be set with the help of a parameter, whereas the message size is
* automatically set to the maximum message queue message size. The operating system
* sets the message queue id, or i case of failure, it is set to zero.
* @param message_depth The number of messages to be buffered before passing an error to the
* sender. Default is three.
* @param max_message_size With this parameter, the maximum message size can be adjusted.
* This should be left default.
*/
MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE );
/**
* @brief The destructor deletes the formerly created message queue.
* @details This is accomplished by using the delete call provided by the operating system.
*/
virtual ~MessageQueue();
/**
* @brief This operation sends a message to the given destination.
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its
* queue id as "sentFrom" parameter.
* @param sendTo This parameter specifies the message queue id of the destination message queue.
* @param message A pointer to a previously created message, which is sent.
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
*/
ReturnValue_t sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, bool ignoreFault = false );
/**
* @brief This operation sends a message to the default destination.
* @details As in the sendMessage method, this function uses the sendToDefault call of the
* MessageQueueSender parent class and adds its queue id as "sentFrom" information.
* @param message A pointer to a previously created message, which is sent.
*/
ReturnValue_t sendToDefault( MessageQueueMessage* message );
/**
* @brief This operation sends a message to the last communication partner.
* @details This operation simplifies answering an incoming message by using the stored
* lastParnter information as destination. If there was no message received yet
* (i.e. lastPartner is zero), an error code is returned.
* @param message A pointer to a previously created message, which is sent.
*/
ReturnValue_t reply( MessageQueueMessage* message );
/**
* @brief This function reads available messages from the message queue and returns the sender.
* @details It works identically to the other receiveMessage call, but in addition returns the
* sender's queue id.
* @param message A pointer to a message in which the received data is stored.
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
*/
ReturnValue_t receiveMessage(MessageQueueMessage* message,
MessageQueueId_t *receivedFrom);
/**
* @brief This function reads available messages from the message queue.
* @details If data is available it is stored in the passed message pointer. The message's
* original content is overwritten and the sendFrom information is stored in the
* lastPartner attribute. Else, the lastPartner information remains untouched, the
* message's content is cleared and the function returns immediately.
* @param message A pointer to a message in which the received data is stored.
*/
ReturnValue_t receiveMessage(MessageQueueMessage* message);
/**
* Deletes all pending messages in the queue.
* @param count The number of flushed messages.
* @return RETURN_OK on success.
*/
ReturnValue_t flush(uint32_t* count);
/**
* @brief This method returns the message queue id of the last communication partner.
*/
MessageQueueId_t getLastPartner() const;
/**
* @brief This method returns the message queue id of this class's message queue.
*/
MessageQueueId_t getId() const;
/**
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
* \details This method takes the message provided, adds the sentFrom information and passes
* it on to the destination provided with an operating system call. The OS's return
* value is returned.
* \param sendTo This parameter specifies the message queue id to send the message to.
* \param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
* This variable is set to zero by default.
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
*/
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
/**
* \brief The sendToDefault method sends a queue message to the default destination.
* \details In all other aspects, it works identical to the sendMessage method.
* \param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
* This variable is set to zero by default.
*/
virtual ReturnValue_t sendToDefault( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
/**
* \brief This method is a simple setter for the default destination.
*/
void setDefaultDestination(MessageQueueId_t defaultDestination);
/**
* \brief This method is a simple getter for the default destination.
*/
MessageQueueId_t getDefaultDestination() const;
bool isDefaultDestinationSet() const;
private:
/**
* @brief The class stores the queue id it got assigned from the operating system in this attribute.
* If initialization fails, the queue id is set to zero.
*/
MessageQueueId_t id;
/**
* @brief In this attribute, the queue id of the last communication partner is stored
* to allow for replying.
*/
MessageQueueId_t lastPartner;
/**
* @brief The message queue's name -a user specific information for the operating system- is
* generated automatically with the help of this static counter.
*/
/**
* \brief This attribute stores a default destination to send messages to.
* \details It is stored to simplify sending to always-the-same receiver. The attribute may
* be set in the constructor or by a setter call to setDefaultDestination.
*/
MessageQueueId_t defaultDestination;
/**
* \brief This attribute stores a reference to the internal error reporter for reporting full queues.
* \details In the event of a full destination queue, the reporter will be notified. The reference is set
* by lazy loading
*/
InternalErrorReporterIF *internalErrorReporter;
static uint16_t queueCounter;
};
#endif /* MESSAGEQUEUE_H_ */

View File

@ -0,0 +1,90 @@
/**
* @file MultiObjectTask.cpp
* @brief This file defines the MultiObjectTask class.
* @date 30.01.2014
* @author baetz
*/
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/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) {
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
rtems_status_code status = rtems_rate_monotonic_create(periodName,
&periodId);
if (status != RTEMS_SUCCESSFUL) {
error << "ObjectTask::period create failed with status " << status
<< std::endl;
}
}
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) {
error << "ObjectTask::startTask for " << std::hex << this->getId()
<< std::dec << " failed." << std::endl;
}
return RtemsBasic::convertReturnCode(status);
}
ReturnValue_t MultiObjectTask::sleepFor(uint32_t ms) {
return TaskBase::sleepFor(ms);
}
void MultiObjectTask::taskFunctionality() {
//The +1 is necessary to avoid a call with period = 0, which does not start the period.
rtems_status_code status = rtems_rate_monotonic_period(periodId,
periodTicks + 1);
if (status != RTEMS_SUCCESSFUL) {
error << "ObjectTask::period start failed with status " << status
<< std::endl;
return;
}
//The task's "infinite" inner loop is entered.
while (1) {
for (ObjectList::iterator it = objectList.begin();
it != objectList.end(); ++it) {
(*it)->performOperation();
}
status = rtems_rate_monotonic_period(periodId, periodTicks + 1);
if (status == RTEMS_TIMEOUT) {
char nameSpace[8] = { 0 };
char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace),
nameSpace);
error << "ObjectTask: " << ptr << " Deadline missed." << std::endl;
if (this->deadlineMissedFunc != NULL) {
this->deadlineMissedFunc();
}
}
}
}
ReturnValue_t MultiObjectTask::addComponent(object_id_t object) {
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(
object);
if (newObject == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
objectList.push_back(newObject);
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t MultiObjectTask::getPeriodMs() const {
return RtemsBasic::convertTicksToMs(periodTicks);
}

View File

@ -0,0 +1,113 @@
/**
* @file MultiObjectTask.h
* @brief This file defines the MultiObjectTask class.
* @date 30.01.2014
* @author baetz
*/
#ifndef MULTIOBJECTTASK_H_
#define MULTIOBJECTTASK_H_
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/tasks/PeriodicTaskIF.h>
#include "TaskBase.h"
#include <vector>
class ExecutableObjectIF;
/**
* @brief This class represents a specialized task for periodic activities of multiple objects.
*
* @details MultiObjectTask is an extension to ObjectTask in the way that it is able to execute
* multiple objects that implement the ExecutableObjectIF interface. The objects must be
* added prior to starting the task.
*
* @ingroup task_handling
*/
class MultiObjectTask: public TaskBase, public PeriodicTaskIF {
public:
/**
* @brief Standard constructor of the class.
* @details The class is initialized without allocated objects. These need to be added
* with #addObject.
* In the underlying TaskBase class, a new operating system task is created.
* In addition to the TaskBase parameters, the period, the pointer to the
* aforementioned initialization function and an optional "deadline-missed"
* function pointer is passed.
* @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 setPeriod The length of the period with which the task's functionality will be
* executed. It is expressed in clock ticks.
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
* that shall be assigned.
*/
MultiObjectTask(const char *name, rtems_task_priority setPriority, size_t setStack, rtems_interval setPeriod,
void (*setDeadlineMissedFunc)());
/**
* @brief Currently, the executed object's lifetime is not coupled with the task object's
* lifetime, so the destructor is empty.
*/
virtual ~MultiObjectTask(void);
/**
* @brief The method to start the task.
* @details The method starts the task with the respective system call.
* Entry point is the taskEntryPoint method described below.
* The address of the task object is passed as an argument
* to the system call.
*/
ReturnValue_t startTask(void);
/**
* Adds an object to the list of objects to be executed.
* The objects are executed in the order added.
* @param object Id of the object to add.
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
*/
ReturnValue_t addComponent(object_id_t object);
uint32_t getPeriodMs() const;
ReturnValue_t sleepFor(uint32_t ms);
protected:
typedef std::vector<ExecutableObjectIF*> ObjectList; //!< Typedef for the List of objects.
/**
* @brief This attribute holds a list of objects to be executed.
*/
ObjectList objectList;
/**
* @brief The period of the task.
* @details The period determines the frequency of the task's execution. It is expressed in clock ticks.
*/
rtems_interval periodTicks;
/**
* @brief id of the associated OS period
*/
rtems_id periodId;
/**
* @brief The pointer to the deadline-missed function.
* @details This pointer stores the function that is executed if the task's deadline is missed.
* So, each may react individually on a timing failure. The pointer may be NULL,
* then nothing happens on missing the deadline. The deadline is equal to the next execution
* of the periodic task.
*/
void (*deadlineMissedFunc)(void);
/**
* @brief This is the function executed in the new task's context.
* @details It converts the argument back to the thread object type and copies the class instance
* to the task context. The taskFunctionality method is called afterwards.
* @param A pointer to the task object itself is passed as argument.
*/
static rtems_task taskEntryPoint(rtems_task_argument argument);
/**
* @brief The function containing the actual functionality of the task.
* @details The method sets and starts
* the task's period, then enters a loop that is repeated as long as the isRunning
* attribute is true. Within the loop, all performOperation methods of the added
* objects are called. Afterwards the checkAndRestartPeriod system call blocks the task
* until the next period.
* On missing the deadline, the deadlineMissedFunction is executed.
*/
void taskFunctionality(void);
};
#endif /* MULTIOBJECTTASK_H_ */

35
osal/rtems/Mutex.cpp Normal file
View File

@ -0,0 +1,35 @@
#include "Mutex.h"
#include <framework/serviceinterface/ServiceInterfaceStream.h>
const uint32_t MutexIF::NO_TIMEOUT = RTEMS_NO_TIMEOUT;
uint8_t Mutex::count = 0;
Mutex::Mutex() :
mutexId(0) {
rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++;
rtems_status_code status = rtems_semaphore_create(mutexName, 1,
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
&mutexId);
if (status != RTEMS_SUCCESSFUL) {
error << "Mutex: creation with name, id " << mutexName << ", " << mutexId
<< " failed with " << status << std::endl;
}
}
Mutex::~Mutex() {
rtems_status_code status = rtems_semaphore_delete(mutexId);
if (status != RTEMS_SUCCESSFUL) {
error << "Mutex: deletion for id " << mutexId
<< " failed with " << status << std::endl;
}
}
ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) {
rtems_status_code status = rtems_semaphore_obtain(mutexId, RTEMS_WAIT, timeoutMs);
return RtemsBasic::convertReturnCode(status);
}
ReturnValue_t Mutex::unlockMutex() {
rtems_status_code status = rtems_semaphore_release(mutexId);
return RtemsBasic::convertReturnCode(status);
}

18
osal/rtems/Mutex.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef OS_RTEMS_MUTEX_H_
#define OS_RTEMS_MUTEX_H_
#include <framework/ipc/MutexIF.h>
#include "RtemsBasic.h"
class Mutex : public MutexIF {
public:
Mutex();
~Mutex();
ReturnValue_t lockMutex(uint32_t timeoutMs);
ReturnValue_t unlockMutex();
private:
rtems_id mutexId;
static uint8_t count;
};
#endif /* OS_RTEMS_MUTEX_H_ */

View File

@ -0,0 +1,24 @@
#include <framework/ipc/MutexFactory.h>
#include "Mutex.h"
#include "RtemsBasic.h"
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
MutexFactory::MutexFactory() {
}
MutexFactory::~MutexFactory() {
}
MutexFactory* MutexFactory::instance() {
return MutexFactory::factoryInstance;
}
MutexIF* MutexFactory::createMutex() {
return new Mutex();
}
void MutexFactory::deleteMutex(MutexIF* mutex) {
delete mutex;
}

106
osal/rtems/PollingTask.cpp Normal file
View File

@ -0,0 +1,106 @@
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include "PollingTask.h"
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;
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
rtems_status_code status = rtems_rate_monotonic_create(periodName,
&periodId);
if (status != RTEMS_SUCCESSFUL) {
error << "PollingTask::period create failed with status " << status
<< std::endl;
}
}
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();
debug << "Polling task " << originalTask->getId()
<< " returned from taskFunctionality." << std::endl;
}
void PollingTask::missedDeadlineCounter() {
PollingTask::deadlineMissedCount++;
if (PollingTask::deadlineMissedCount % 10 == 0) {
error << "PST missed " << PollingTask::deadlineMissedCount
<< " deadlines." << std::endl;
}
}
ReturnValue_t PollingTask::startTask() {
rtems_status_code status = rtems_task_start(id, PollingTask::taskEntryPoint,
rtems_task_argument((void *) this));
if (status != RTEMS_SUCCESSFUL) {
error << "PollingTask::startTask for " << std::hex << this->getId()
<< std::dec << " failed." << std::endl;
}
return RtemsBasic::convertReturnCode(status);
}
ReturnValue_t PollingTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep) {
pst.addSlot(componentId, slotTimeMs, executionStep, this);
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t PollingTask::getPeriodMs() const {
return pst.getLengthMs();
}
ReturnValue_t PollingTask::checkSequence() const {
return pst.checkSequence();
}
void PollingTask::taskFunctionality() {
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
std::list<FixedSequenceSlot*>::iterator it = pst.current;
//The start time for the first entry is read.
rtems_interval interval = RtemsBasic::convertMsToTicks(
(*it)->pollingTimeMs);
//The period is set up and started with the system call.
//The +1 is necessary to avoid a call with period = 0, which does not start the period.
rtems_status_code status = rtems_rate_monotonic_period(periodId,
interval + 1);
if (status != RTEMS_SUCCESSFUL) {
error << "PollingTask::period start failed with status " << status
<< std::endl;
return;
}
//The task's "infinite" inner loop is entered.
while (1) {
if (pst.slotFollowsImmediately()) {
//Do nothing
} else {
//The interval for the next polling slot is selected.
interval = this->pst.getIntervalMs();
//The period is checked and restarted with the new interval.
//If the deadline was missed, the deadlineMissedFunc is called.
status = rtems_rate_monotonic_period(periodId, interval);
if (status == RTEMS_TIMEOUT) {
if (this->deadlineMissedFunc != NULL) {
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);
};

85
osal/rtems/PollingTask.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef POLLINGTASK_H_
#define POLLINGTASK_H_
#include <framework/devicehandlers/FixedSlotSequence.h>
#include <framework/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 /* POLLINGTASK_H_ */

View File

@ -0,0 +1,36 @@
#include <framework/ipc/QueueFactory.h>
#include "MessageQueue.h"
#include "RtemsBasic.h"
QueueFactory* QueueFactory::factoryInstance = NULL;
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom) {
message->setSender(sentFrom);
rtems_status_code result = rtems_message_queue_send(sendTo, message->getBuffer(),
message->messageSize);
return RtemsBasic::convertReturnCode(result);
}
QueueFactory* QueueFactory::instance() {
if (factoryInstance == NULL) {
factoryInstance = new QueueFactory;
}
return factoryInstance;
}
QueueFactory::QueueFactory() {
}
QueueFactory::~QueueFactory() {
}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t message_depth,
uint32_t max_message_size) {
return new MessageQueue(message_depth, max_message_size);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) {
delete queue;
}

70
osal/rtems/RtemsBasic.cpp Normal file
View File

@ -0,0 +1,70 @@
#include "RtemsBasic.h"
ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
if (inValue == RTEMS_SUCCESSFUL) {
return HasReturnvaluesIF::RETURN_OK;
} else {
switch(inValue){
case RTEMS_SUCCESSFUL:
return OperatingSystemIF::SUCCESSFUL;
case RTEMS_TASK_EXITTED:
return OperatingSystemIF::TASK_EXITTED;
case RTEMS_MP_NOT_CONFIGURED:
return OperatingSystemIF::MP_NOT_CONFIGURED;
case RTEMS_INVALID_NAME:
return OperatingSystemIF::INVALID_NAME;
case RTEMS_INVALID_ID:
return OperatingSystemIF::INVALID_ID;
case RTEMS_TOO_MANY:
return OperatingSystemIF::TOO_MANY;
case RTEMS_TIMEOUT:
return OperatingSystemIF::TIMEOUT;
case RTEMS_OBJECT_WAS_DELETED:
return OperatingSystemIF::OBJECT_WAS_DELETED;
case RTEMS_INVALID_SIZE:
return OperatingSystemIF::INVALID_SIZE;
case RTEMS_INVALID_ADDRESS:
return OperatingSystemIF::INVALID_ADDRESS;
case RTEMS_INVALID_NUMBER:
return OperatingSystemIF::INVALID_NUMBER;
case RTEMS_NOT_DEFINED:
return OperatingSystemIF::NOT_DEFINED;
case RTEMS_RESOURCE_IN_USE:
return OperatingSystemIF::RESOURCE_IN_USE;
//TODO RTEMS_UNSATISFIED is double mapped for FLP so it will only return Queue_empty and not unsatisfied
case RTEMS_UNSATISFIED:
return OperatingSystemIF::QUEUE_EMPTY;
case RTEMS_INCORRECT_STATE:
return OperatingSystemIF::INCORRECT_STATE;
case RTEMS_ALREADY_SUSPENDED:
return OperatingSystemIF::ALREADY_SUSPENDED;
case RTEMS_ILLEGAL_ON_SELF:
return OperatingSystemIF::ILLEGAL_ON_SELF;
case RTEMS_ILLEGAL_ON_REMOTE_OBJECT:
return OperatingSystemIF::ILLEGAL_ON_REMOTE_OBJECT;
case RTEMS_CALLED_FROM_ISR:
return OperatingSystemIF::CALLED_FROM_ISR;
case RTEMS_INVALID_PRIORITY:
return OperatingSystemIF::INVALID_PRIORITY;
case RTEMS_INVALID_CLOCK:
return OperatingSystemIF::INVALID_CLOCK;
case RTEMS_INVALID_NODE:
return OperatingSystemIF::INVALID_NODE;
case RTEMS_NOT_CONFIGURED:
return OperatingSystemIF::NOT_CONFIGURED;
case RTEMS_NOT_OWNER_OF_RESOURCE:
return OperatingSystemIF::NOT_OWNER_OF_RESOURCE;
case RTEMS_NOT_IMPLEMENTED:
return OperatingSystemIF::NOT_IMPLEMENTED;
case RTEMS_INTERNAL_ERROR:
return OperatingSystemIF::INTERNAL_ERROR;
case RTEMS_NO_MEMORY:
return OperatingSystemIF::NO_MEMORY;
case RTEMS_IO_ERROR:
return OperatingSystemIF::IO_ERROR;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
}

39
osal/rtems/RtemsBasic.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef OS_RTEMS_RTEMSBASIC_H_
#define OS_RTEMS_RTEMSBASIC_H_
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/osal/OperatingSystemIF.h>
extern "C" {
#include <bsp_flp/rtems_config.h>
}
#include <rtems/endian.h>
#include <rtems.h>
#include <rtems/libio.h>
#include <rtems/error.h>
#include <rtems/stackchk.h>
#include <stddef.h>
class RtemsBasic: public OperatingSystemIF {
public:
/**
* A method to convert an OS-specific return code to the frameworks return value concept.
* @param inValue The return code coming from the OS.
* @return The converted return value.
*/
static ReturnValue_t convertReturnCode(rtems_status_code inValue);
static rtems_interval convertMsToTicks(uint32_t msIn) {
rtems_interval ticks_per_second;
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
return (ticks_per_second * msIn) / 1000;
}
static rtems_interval convertTicksToMs(rtems_interval ticksIn) {
rtems_interval ticks_per_second;
rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
return (ticksIn * 1000) / ticks_per_second;
}
};
#endif /* OS_RTEMS_RTEMSBASIC_H_ */

43
osal/rtems/TaskBase.cpp Normal file
View File

@ -0,0 +1,43 @@
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include "TaskBase.h"
const uint64_t PeriodicTaskIF::MINIMUM_STACK_SIZE=RTEMS_MINIMUM_STACK_SIZE;
TaskBase::TaskBase(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 >= 0 && 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 = RtemsBasic::convertReturnCode(status);
if (result != HasReturnvaluesIF::RETURN_OK) {
error << "TaskBase::TaskBase: createTask with name " << std::hex
<< osalName << std::dec << " failed with return code "
<< (uint32_t) status << std::endl;
this->id = 0;
}
}
TaskBase::~TaskBase() {
rtems_task_delete(id);
}
rtems_id TaskBase::getId() {
return this->id;
}
ReturnValue_t TaskBase::sleepFor(uint32_t ms) {
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
return RtemsBasic::convertReturnCode(status);
}

43
osal/rtems/TaskBase.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef TASKBASE_H_
#define TASKBASE_H_
#include "RtemsBasic.h"
#include <framework/tasks/PeriodicTaskIF.h>
/**
* @brief This is the basic task handling class for rtems.
*
* @details Task creation base class for rtems.
*/
class TaskBase {
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
*/
TaskBase( rtems_task_priority priority, size_t stack_size, const char *name);
/**
* @brief In the destructor, the created task is deleted.
*/
virtual ~TaskBase();
/**
* @brief This method returns the task id of this class.
*/
rtems_id getId();
ReturnValue_t sleepFor(uint32_t ms);
};
#endif /* TASKBASE_H_ */

View File

@ -0,0 +1,34 @@
#include <framework/tasks/TaskFactory.h>
#include "MultiObjectTask.h"
#include "PollingTask.h"
#include "InitTask.h"
#include <framework/returnvalues/HasReturnvaluesIF.h>
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
TaskFactory::~TaskFactory() {
}
TaskFactory* TaskFactory::instance() {
return TaskFactory::factoryInstance;
}
PeriodicTaskIF* TaskFactory::createPeriodicTask(OSAL::TaskName name_,OSAL::TaskPriority taskPriority_,OSAL::TaskStackSize stackSize_,OSAL::TaskPeriod periodInSeconds_,OSAL::TaskDeadlineMissedFunction deadLineMissedFunction_) {
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
return static_cast<PeriodicTaskIF*>(new MultiObjectTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_));
}
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(OSAL::TaskName name_,OSAL::TaskPriority taskPriority_,OSAL::TaskStackSize stackSize_,OSAL::TaskPeriod periodInSeconds_,OSAL::TaskDeadlineMissedFunction deadLineMissedFunction_) {
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
return static_cast<FixedTimeslotTaskIF*>(new PollingTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_));
}
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
//TODO not implemented
return HasReturnvaluesIF::RETURN_FAILED;
}
TaskFactory::TaskFactory() {
}