updating code from Flying Laptop
This is the framework of Flying Laptop OBSW version A.13.0.
This commit is contained in:
13
osal/Endiness.h
Normal file
13
osal/Endiness.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef FRAMEWORK_OSAL_ENDINESS_H_
|
||||
#define FRAMEWORK_OSAL_ENDINESS_H_
|
||||
|
||||
//We have to define BYTE_ORDER for that specific OS/Hardware so this must be done somewhere
|
||||
#ifndef API
|
||||
#error Please specify Operating System API. Supported: API=RTEMS_API
|
||||
#elif API == RTEMS_API
|
||||
#include "rtems/RtemsBasic.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_ENDINESS_H_ */
|
@ -5,7 +5,7 @@
|
||||
|
||||
class InternalErrorCodes {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = INTERNAL_ERROR_CODES;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::INTERNAL_ERROR_CODES;
|
||||
|
||||
static const ReturnValue_t NO_CONFIGURATION_TABLE = MAKE_RETURN_CODE(0x01 );
|
||||
static const ReturnValue_t NO_CPU_TABLE = MAKE_RETURN_CODE(0x02 );
|
||||
|
176
osal/Linux/Clock.cpp
Normal file
176
osal/Linux/Clock.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <framework/timemanager/Clock.h>
|
||||
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
#include <linux/sysinfo.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//#include <fstream>
|
||||
|
||||
|
||||
uint32_t Clock::getTicksPerSecond(void){
|
||||
//TODO This function returns the ticks per second for thread ticks not clock ticks
|
||||
// timespec ticks;
|
||||
// int status = clock_getres(CLOCK_REALTIME,&ticks);
|
||||
//
|
||||
// if(status!=0){
|
||||
// //TODO errno
|
||||
// return 0xFFFFFFFF;
|
||||
// }
|
||||
// uint32_t resolution = 1e9 / ticks.tv_nsec;
|
||||
uint32_t resolution = sysconf(_SC_CLK_TCK);
|
||||
return resolution;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
//TODO timeOfDay conversion
|
||||
timespec timeUnix;
|
||||
int status = clock_settime(CLOCK_REALTIME,&timeUnix);
|
||||
if(status!=0){
|
||||
//TODO errno
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||
timespec timeUnix;
|
||||
timeUnix.tv_sec = time->tv_sec;
|
||||
timeUnix.tv_nsec = (__syscall_slong_t) time->tv_usec * 1000;
|
||||
int status = clock_settime(CLOCK_REALTIME,&timeUnix);
|
||||
if(status!=0){
|
||||
//TODO errno
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
timespec timeUnix;
|
||||
int status = clock_gettime(CLOCK_REALTIME,&timeUnix);
|
||||
if(status!=0){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
time->tv_sec = timeUnix.tv_sec;
|
||||
time->tv_usec = timeUnix.tv_nsec / 1000.0;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||
timeval timeVal;
|
||||
ReturnValue_t result = getClock_timeval(&timeVal);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
*time = (uint64_t)timeVal.tv_sec*1e6 + timeVal.tv_usec;
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(timeval* uptime) {
|
||||
//TODO This is not posix compatible and delivers only seconds precision
|
||||
struct sysinfo sysInfo;
|
||||
int result = sysinfo(&sysInfo);
|
||||
if(result != 0){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
uptime->tv_sec = sysInfo.uptime;
|
||||
uptime->tv_usec = 0;
|
||||
|
||||
|
||||
//Linux specific file read but more precise
|
||||
// double uptimeSeconds;
|
||||
// if(std::ifstream("/proc/uptime",std::ios::in) >> uptimeSeconds){
|
||||
// uptime->tv_sec = uptimeSeconds;
|
||||
// uptime->tv_usec = uptimeSeconds *(double) 1e6 - (uptime->tv_sec *1e6);
|
||||
// }
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
|
||||
timeval uptime;
|
||||
ReturnValue_t result = getUptime(&uptime);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
*uptimeMs = uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||
timespec timeUnix;
|
||||
int status = clock_gettime(CLOCK_REALTIME,&timeUnix);
|
||||
if(status != 0){
|
||||
//TODO errno
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
timespec ticks;
|
||||
status = clock_getres(CLOCK_REALTIME,&ticks);
|
||||
if(status!=0){
|
||||
//TODO errno
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
uint32_t resolution = 1e9 / ticks.tv_nsec;
|
||||
|
||||
|
||||
struct tm* timeInfo;
|
||||
timeInfo = gmtime(&timeUnix.tv_sec);
|
||||
time->year = timeInfo->tm_year + 1900;
|
||||
time->month = timeInfo->tm_mon+1;
|
||||
time->day = timeInfo->tm_mday;
|
||||
time->hour = timeInfo->tm_hour;
|
||||
time->minute = timeInfo->tm_min;
|
||||
time->second = timeInfo->tm_sec;
|
||||
time->ticks = (timeUnix.tv_nsec / (double) 1e9) * resolution;
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
|
||||
timeval* to) {
|
||||
|
||||
tm fromTm;
|
||||
//Note: Fails for years before AD
|
||||
fromTm.tm_year = from->year - 1900;
|
||||
fromTm.tm_mon = from->month - 1;
|
||||
fromTm.tm_mday = from->day;
|
||||
fromTm.tm_hour = from->hour;
|
||||
fromTm.tm_min = from->minute;
|
||||
fromTm.tm_sec = from->second;
|
||||
|
||||
timespec ticks;
|
||||
uint32_t status = clock_getres(CLOCK_REALTIME,&ticks);
|
||||
if(status!=0){
|
||||
//TODO errno
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
uint32_t resolution = 1e9 / ticks.tv_nsec;
|
||||
|
||||
to->tv_sec = mktime(&fromTm);
|
||||
to->tv_usec = (from->ticks /(double) resolution) * 1e6;
|
||||
|
||||
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
282
osal/OSAL.cpp
282
osal/OSAL.cpp
@ -1,282 +0,0 @@
|
||||
/**
|
||||
* @file OSAL.cpp
|
||||
* @brief This file defines the OSAL class.
|
||||
* @date 19.12.2012
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include <framework/osal/OSAL.h>
|
||||
|
||||
#ifndef API
|
||||
#error Please specify Operating System API. Supported: API=RTEMS_API
|
||||
#elif API == RTEMS_API
|
||||
|
||||
#include <bsp_flp/bsp_flp.h>
|
||||
//#include <bsp_flp/rmap/RMAPCookie.h>
|
||||
|
||||
ReturnValue_t OSAL::convertReturnCode(uint8_t inValue) {
|
||||
if (inValue == RTEMS_SUCCESSFUL) {
|
||||
return OSAL::RETURN_OK;
|
||||
} else {
|
||||
return MAKE_RETURN_CODE(inValue);
|
||||
}
|
||||
}
|
||||
|
||||
Name_t OSAL::buildName(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4) {
|
||||
return rtems_build_name(c1, c2, c3, c4);
|
||||
}
|
||||
|
||||
Interval_t OSAL::getTicksPerSecond() {
|
||||
Interval_t ticks_per_second;
|
||||
(void) rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
|
||||
return ticks_per_second;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::setClock(TimeOfDay_t* time) {
|
||||
ReturnValue_t status = rtems_clock_set(time);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::setClock(timeval* time) {
|
||||
timespec newTime;
|
||||
newTime.tv_sec = time->tv_sec;
|
||||
newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND;
|
||||
//TODO: Not sure if we need to protect this call somehow (by thread lock or something).
|
||||
_TOD_Set(&newTime);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::getClock_timeval(timeval* time) {
|
||||
ReturnValue_t status = rtems_clock_get_tod_timeval(time);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::getClock_usecs(uint64_t* time) {
|
||||
timeval temp_time;
|
||||
uint8_t returnValue = rtems_clock_get_tod_timeval(&temp_time);
|
||||
*time = ((uint64_t) temp_time.tv_sec * 1000000) + temp_time.tv_usec;
|
||||
return OSAL::convertReturnCode(returnValue);
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::getDateAndTime(TimeOfDay_t* time) {
|
||||
ReturnValue_t status = rtems_clock_get_tod(time);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::sleepFor(Interval_t ticks) {
|
||||
ReturnValue_t status = rtems_task_wake_after(ticks);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
ReturnValue_t OSAL::createTask(Name_t name, TaskPriority_t initial_priority,
|
||||
size_t stack_size, OpusMode_t initial_modes, Attribute_t attribute_set,
|
||||
TaskId_t* id) {
|
||||
if (initial_priority >= 0 && initial_priority <= 99) {
|
||||
ReturnValue_t status = rtems_task_create(name,
|
||||
(0xFF - 2 * initial_priority), stack_size, initial_modes,
|
||||
attribute_set, id);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
} else {
|
||||
return OSAL::UNSATISFIED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::findTask(Name_t name, TaskId_t* id) {
|
||||
ReturnValue_t status = rtems_task_ident(name, RTEMS_SEARCH_ALL_NODES, id);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::startTask(TaskId_t* id, TaskEntry_t entry_point,
|
||||
TaskArgument_t argument) {
|
||||
return rtems_task_start(*id, entry_point, argument);
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::deleteTask(TaskId_t* id) {
|
||||
if (id == RTEMS_SELF) {
|
||||
return rtems_task_delete(RTEMS_SELF);
|
||||
} else {
|
||||
return rtems_task_delete(*id);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::setAndStartPeriod(Interval_t period, PeriodId_t *periodId,
|
||||
Name_t name) {
|
||||
uint8_t status;
|
||||
status = rtems_rate_monotonic_create(name, periodId);
|
||||
if (status == RTEMS_SUCCESSFUL) {
|
||||
//This is necessary to avoid a call with period = 0, which does not start the period.
|
||||
status = rtems_rate_monotonic_period(*periodId, period + 1);
|
||||
}
|
||||
return OSAL::convertReturnCode(status);
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::checkAndRestartPeriod(PeriodId_t periodId,
|
||||
Interval_t period) {
|
||||
ReturnValue_t status = rtems_rate_monotonic_period(periodId, period);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::deletePeriod(TaskId_t* id) {
|
||||
rtems_name period_name;
|
||||
rtems_id period_id;
|
||||
rtems_object_get_classic_name(*id, &period_name);
|
||||
period_name = (period_name & 0xFFFFFF00) + 0x50;
|
||||
rtems_rate_monotonic_ident(period_name, &period_id);
|
||||
ReturnValue_t status = rtems_rate_monotonic_delete(period_id);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::reportPeriodStatistics() {
|
||||
rtems_rate_monotonic_report_statistics();
|
||||
return OSAL::SUCCESSFUL;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::createMessageQueue(Name_t name, uint32_t count,
|
||||
size_t max_message_size, Attribute_t attribute_set,
|
||||
MessageQueueId_t* id) {
|
||||
ReturnValue_t status = rtems_message_queue_create(name, count,
|
||||
max_message_size, attribute_set, id);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::findMessageQueue(Name_t name, MessageQueueId_t* id) {
|
||||
ReturnValue_t status = rtems_message_queue_ident(name,
|
||||
RTEMS_SEARCH_ALL_NODES, id);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::sendMessage(MessageQueueId_t id, const void* buffer,
|
||||
size_t size) {
|
||||
ReturnValue_t status = rtems_message_queue_send(id, buffer, size);
|
||||
return OSAL::convertReturnCode(status);
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::receiveMessage(MessageQueueId_t id, void* buffer,
|
||||
size_t bufSize, size_t* recSize, Option_t option_set,
|
||||
Interval_t timeout) {
|
||||
ReturnValue_t status = rtems_message_queue_receive(id, buffer, recSize,
|
||||
option_set, timeout);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::flushMessageQueue(MessageQueueId_t id, uint32_t* count) {
|
||||
ReturnValue_t status = rtems_message_queue_flush(id, count);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::deleteMessageQueue(MessageQueueId_t* id) {
|
||||
ReturnValue_t status = rtems_message_queue_delete(*id);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::createMutex(Name_t name, MutexId_t* id) {
|
||||
ReturnValue_t status = rtems_semaphore_create(name, 1,
|
||||
RTEMS_SIMPLE_BINARY_SEMAPHORE, 0, id);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::deleteMutex(MutexId_t* id) {
|
||||
ReturnValue_t status = rtems_semaphore_delete(*id);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::lockMutex(MutexId_t* id, Interval_t timeout) {
|
||||
ReturnValue_t status = rtems_semaphore_obtain(*id, WAIT, timeout);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::getUptime(timeval* uptime) {
|
||||
timespec time;
|
||||
ReturnValue_t 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;
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::getUptime(uint32_t* uptimeMs) {
|
||||
*uptimeMs = rtems_clock_get_ticks_since_boot();
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::unlockMutex(MutexId_t* id) {
|
||||
ReturnValue_t status = rtems_semaphore_release(*id);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::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
|
||||
ReturnValue_t status = rtems_interrupt_catch(handler, interrupt + 0x10,
|
||||
oldHandler);
|
||||
status = convertReturnCode(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//TODO: Make default values (edge, polarity) settable?
|
||||
ReturnValue_t OSAL::enableInterrupt(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 RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::disableInterrupt(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 RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
bool OSAL::isInterruptInProgress() {
|
||||
return rtems_interrupt_is_in_progress();
|
||||
}
|
||||
|
||||
ReturnValue_t OSAL::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
|
||||
timeval* to) {
|
||||
//Fails in 2038..
|
||||
to->tv_sec = _TOD_To_seconds(from);
|
||||
to->tv_usec = 0;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
#endif /* API */
|
430
osal/OSAL.h
430
osal/OSAL.h
@ -1,430 +0,0 @@
|
||||
/**
|
||||
* @file OSAL.h
|
||||
* @brief This file defines the OSAL class.
|
||||
* @date 19.12.2012
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef OSAL_H_
|
||||
#define OSAL_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#define RTEMS_API 1
|
||||
|
||||
#ifndef API
|
||||
#error Please specify Operating System API. Supported: API=RTEMS_API
|
||||
#elif API == RTEMS_API
|
||||
#include <rtems/endian.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/error.h>
|
||||
#include <rtems/stackchk.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//include RMAP
|
||||
|
||||
#define opus_main Init2
|
||||
#define opus_main_arguments rtems_task_argument
|
||||
|
||||
//Typedefs for RTEMS: //TODO: these are global, shouldn't they have some prefix?
|
||||
/**
|
||||
* A typedef to pass options to RTEMS elements.
|
||||
*/
|
||||
typedef rtems_option Option_t;
|
||||
/**
|
||||
* A typedef to pass attributes to RTEMS elements.
|
||||
*/
|
||||
typedef rtems_attribute Attribute_t;
|
||||
/**
|
||||
* A typedef for RTEMS task modes.
|
||||
*/
|
||||
typedef rtems_mode OpusMode_t;
|
||||
/**
|
||||
* A typedef for time intervals. In clock ticks.
|
||||
*/
|
||||
typedef rtems_interval Interval_t;
|
||||
typedef rtems_time_of_day TimeOfDay_t;
|
||||
typedef rtems_id TaskId_t;
|
||||
typedef rtems_id PeriodId_t;
|
||||
typedef rtems_id MutexId_t;
|
||||
typedef rtems_id MessageQueueId_t;
|
||||
typedef rtems_name Name_t;
|
||||
|
||||
typedef rtems_task_argument TaskArgument_t;
|
||||
typedef rtems_task_entry TaskEntry_t;
|
||||
typedef rtems_task TaskReturn_t;
|
||||
typedef rtems_task_priority TaskPriority_t;
|
||||
typedef rtems_isr_entry IsrHandler_t;
|
||||
typedef rtems_isr IsrReturn_t;
|
||||
typedef rtems_vector_number InterruptNumber_t;
|
||||
|
||||
/**
|
||||
* This class contains encapsulates all System Calls to the Operating System.
|
||||
* It is currently tailored to the RTEMS Operating system, but should in general
|
||||
* support different OS.
|
||||
* For more detailed information on the Operating System calls, please refer to the
|
||||
* RTEMS documentation at www.rtems.org .
|
||||
*/
|
||||
class OSAL: public HasReturnvaluesIF {
|
||||
private:
|
||||
/**
|
||||
* 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(uint8_t inValue);
|
||||
public:
|
||||
|
||||
static const uint8_t INTERFACE_ID = OPERATING_SYSTEM_ABSTRACTION;
|
||||
//Interrupts:
|
||||
static const uint32_t INTERRUPT_MASK_REGISTER_ADDRESS = 0x80000240;
|
||||
//API Status codes:
|
||||
static const ReturnValue_t SUCCESSFUL = RTEMS_SUCCESSFUL;
|
||||
static const ReturnValue_t TASK_EXITTED =
|
||||
MAKE_RETURN_CODE( RTEMS_TASK_EXITTED );
|
||||
static const ReturnValue_t MP_NOT_CONFIGURED =
|
||||
MAKE_RETURN_CODE( RTEMS_MP_NOT_CONFIGURED );
|
||||
static const ReturnValue_t INVALID_NAME =
|
||||
MAKE_RETURN_CODE( RTEMS_INVALID_NAME );
|
||||
static const ReturnValue_t INVALID_ID = MAKE_RETURN_CODE( RTEMS_INVALID_ID );
|
||||
static const ReturnValue_t TOO_MANY = MAKE_RETURN_CODE( RTEMS_TOO_MANY );
|
||||
static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE( RTEMS_TIMEOUT );
|
||||
static const ReturnValue_t OBJECT_WAS_DELETED =
|
||||
MAKE_RETURN_CODE( RTEMS_OBJECT_WAS_DELETED );
|
||||
static const ReturnValue_t INVALID_SIZE =
|
||||
MAKE_RETURN_CODE( RTEMS_INVALID_SIZE );
|
||||
static const ReturnValue_t INVALID_ADDRESS =
|
||||
MAKE_RETURN_CODE( RTEMS_INVALID_ADDRESS );
|
||||
static const ReturnValue_t INVALID_NUMBER =
|
||||
MAKE_RETURN_CODE( RTEMS_INVALID_NUMBER );
|
||||
static const ReturnValue_t NOT_DEFINED =
|
||||
MAKE_RETURN_CODE( RTEMS_NOT_DEFINED );
|
||||
static const ReturnValue_t RESOURCE_IN_USE =
|
||||
MAKE_RETURN_CODE( RTEMS_RESOURCE_IN_USE );
|
||||
static const ReturnValue_t UNSATISFIED =
|
||||
MAKE_RETURN_CODE( RTEMS_UNSATISFIED );
|
||||
static const ReturnValue_t QUEUE_EMPTY =
|
||||
MAKE_RETURN_CODE( RTEMS_UNSATISFIED );
|
||||
static const ReturnValue_t INCORRECT_STATE =
|
||||
MAKE_RETURN_CODE( RTEMS_INCORRECT_STATE );
|
||||
static const ReturnValue_t ALREADY_SUSPENDED =
|
||||
MAKE_RETURN_CODE( RTEMS_ALREADY_SUSPENDED );
|
||||
static const ReturnValue_t ILLEGAL_ON_SELF =
|
||||
MAKE_RETURN_CODE( RTEMS_ILLEGAL_ON_SELF );
|
||||
static const ReturnValue_t ILLEGAL_ON_REMOTE_OBJECT =
|
||||
MAKE_RETURN_CODE( RTEMS_ILLEGAL_ON_REMOTE_OBJECT );
|
||||
static const ReturnValue_t CALLED_FROM_ISR =
|
||||
MAKE_RETURN_CODE( RTEMS_CALLED_FROM_ISR );
|
||||
static const ReturnValue_t INVALID_PRIORITY =
|
||||
MAKE_RETURN_CODE( RTEMS_INVALID_PRIORITY );
|
||||
static const ReturnValue_t INVALID_CLOCK =
|
||||
MAKE_RETURN_CODE( RTEMS_INVALID_CLOCK );
|
||||
static const ReturnValue_t INVALID_NODE =
|
||||
MAKE_RETURN_CODE( RTEMS_INVALID_NODE );
|
||||
static const ReturnValue_t NOT_CONFIGURED =
|
||||
MAKE_RETURN_CODE( RTEMS_NOT_CONFIGURED );
|
||||
static const ReturnValue_t NOT_OWNER_OF_RESOURCE =
|
||||
MAKE_RETURN_CODE( RTEMS_NOT_OWNER_OF_RESOURCE );
|
||||
static const ReturnValue_t NOT_IMPLEMENTED =
|
||||
MAKE_RETURN_CODE( RTEMS_NOT_IMPLEMENTED );
|
||||
static const ReturnValue_t INTERNAL_ERROR =
|
||||
MAKE_RETURN_CODE( RTEMS_INTERNAL_ERROR );
|
||||
static const ReturnValue_t NO_MEMORY = MAKE_RETURN_CODE( RTEMS_NO_MEMORY );
|
||||
static const ReturnValue_t IO_ERROR = MAKE_RETURN_CODE( RTEMS_IO_ERROR );
|
||||
//API options:
|
||||
static const Option_t DEFAULT_OPTIONS = RTEMS_DEFAULT_OPTIONS;
|
||||
static const Option_t WAIT = RTEMS_WAIT;
|
||||
static const Option_t NO_WAIT = RTEMS_NO_WAIT;
|
||||
static const Option_t EVENT_ALL = RTEMS_EVENT_ALL;
|
||||
static const Option_t EVENT_ANY = RTEMS_EVENT_ANY;
|
||||
//API Attributes:
|
||||
static const Attribute_t DEFAULT_ATTRIBUTES = RTEMS_DEFAULT_ATTRIBUTES;
|
||||
static const Attribute_t LOCAL = RTEMS_LOCAL;
|
||||
static const Attribute_t GLOBAL = RTEMS_GLOBAL;
|
||||
static const Attribute_t FIFO = RTEMS_FIFO;
|
||||
static const Attribute_t PRIORITY = RTEMS_PRIORITY;
|
||||
static const Attribute_t NO_FLOATING_POINT = RTEMS_NO_FLOATING_POINT;
|
||||
static const Attribute_t FLOATING_POINT = RTEMS_FLOATING_POINT;
|
||||
//API Modes:
|
||||
static const OpusMode_t ALL_MODE_MASKS = RTEMS_ALL_MODE_MASKS;
|
||||
static const OpusMode_t DEFAULT_MODES = RTEMS_DEFAULT_MODES;
|
||||
static const OpusMode_t CURRENT_MODE = RTEMS_CURRENT_MODE;
|
||||
static const OpusMode_t PREEMPT = RTEMS_PREEMPT;
|
||||
static const OpusMode_t NO_PREEMPT = RTEMS_NO_PREEMPT;
|
||||
static const OpusMode_t NO_TIMESLICE = RTEMS_NO_TIMESLICE;
|
||||
static const OpusMode_t TIMESLICE = RTEMS_TIMESLICE;
|
||||
static const OpusMode_t ASR = RTEMS_ASR;
|
||||
static const OpusMode_t NO_ASR = RTEMS_NO_ASR;
|
||||
//API Time and Timing
|
||||
static const Interval_t MILISECOND_WAIT = 1;
|
||||
static const Interval_t NO_TIMEOUT = RTEMS_NO_TIMEOUT;
|
||||
static const TaskId_t TASK_MYSELF = RTEMS_SELF;
|
||||
static const size_t MINIMUM_STACK_SIZE = RTEMS_MINIMUM_STACK_SIZE;
|
||||
/**
|
||||
* This is a helper method to build a qualified name out of single characters
|
||||
* @param c1 The first character
|
||||
* @param c2 The second character
|
||||
* @param c3 The third character
|
||||
* @param c4 The fourth character
|
||||
* @return A name suitable for use for the Operating System
|
||||
*/
|
||||
static Name_t buildName(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4);
|
||||
/**
|
||||
* This method returns the number of clock ticks per second.
|
||||
* In RTEMS, this is typically 1000.
|
||||
* @return The number of ticks.
|
||||
*/
|
||||
static Interval_t getTicksPerSecond(void);
|
||||
/**
|
||||
* This system call sets the system time.
|
||||
* To set the time, it uses a TimeOfDay_t struct.
|
||||
* @param time The struct with the time settings to set.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t setClock(TimeOfDay_t* time);
|
||||
/**
|
||||
* This system call sets the system time.
|
||||
* To set the time, it uses a timeval struct.
|
||||
* @param time The struct with the time settings to set.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t setClock(timeval* time);
|
||||
/**
|
||||
* This system call returns the current system clock in timeval format.
|
||||
* The timval format has the fields \c tv_sec with seconds and \c tv_usec with
|
||||
* microseconds since an OS-defined epoch.
|
||||
* @param time A pointer to a timeval struct where the current time is stored.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getClock_timeval(timeval* time);
|
||||
|
||||
/**
|
||||
* Get the time since boot in a timeval struct
|
||||
*
|
||||
* @param[out] time A pointer to a timeval struct where the uptime is stored.
|
||||
* @return\c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getUptime(timeval* uptime);
|
||||
|
||||
/**
|
||||
* Get the time since boot in milliseconds
|
||||
*
|
||||
* This value can overflow! Still, it can be used to calculate time intervalls
|
||||
* between two calls up to 49 days by always using uint32_t in the calculation
|
||||
*
|
||||
* @param ms uptime in ms
|
||||
* @return RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getUptime(uint32_t* uptimeMs);
|
||||
|
||||
/**
|
||||
* Returns the time in microseconds since an OS-defined epoch.
|
||||
* The time is returned in a 64 bit unsigned integer.
|
||||
* @param time A pointer to a 64 bit unisigned integer where the data is stored.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getClock_usecs(uint64_t* time);
|
||||
/**
|
||||
* Returns the time in a TimeOfDay_t struct.
|
||||
* @param time A pointer to a TimeOfDay_t struct.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getDateAndTime(TimeOfDay_t* time);
|
||||
/**
|
||||
* Converts a time of day struct to POSIX seconds.
|
||||
* @param time The time of day as input
|
||||
* @param timeval The corresponding seconds since the epoch.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to);
|
||||
/**
|
||||
* Commands the calling task to sleep for a certain number of clock ticks.
|
||||
* Typically other tasks are executed then.
|
||||
* @param ticks The number of clock ticks to sleep.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t sleepFor(Interval_t ticks);
|
||||
|
||||
/**
|
||||
* With this call, a new task is created.
|
||||
* The task is created (its resources are acquired), but it is not started.
|
||||
* @param name A name as specified in the OS.
|
||||
* @param initial_priority The task's priority. Ranging from 0 (lowest) to 99 (highest).
|
||||
* @param stack_size The stack size reserved for this task.
|
||||
* @param initial_modes Options for the task's mode (preemptible, time slicing, etc..)
|
||||
* @param attribute_set Options for the task's attributes (floating point, local/global)
|
||||
* @param id The OS returns the task id, that uniquely identifies the task.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t createTask(Name_t name,
|
||||
TaskPriority_t initial_priority, size_t stack_size,
|
||||
OpusMode_t initial_modes, Attribute_t attribute_set, TaskId_t *id);
|
||||
/**
|
||||
* Finds a task with the help of its name.
|
||||
* @param name Name of the task to find
|
||||
* @param id The OS returns the task id, that uniquely identifies the task.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t findTask(Name_t name, TaskId_t *id);
|
||||
/**
|
||||
* Starts a task.
|
||||
* The task immediately starts running.
|
||||
* @param id The task id.
|
||||
* @param entry_point A pointer to the (static) method that is executed by the task.
|
||||
* @param argument One argument (a void* pointer) may be passed to the task.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t startTask(TaskId_t *id, TaskEntry_t entry_point,
|
||||
TaskArgument_t argument);
|
||||
/**
|
||||
* With this call, tasks are deleted from the system
|
||||
* @param id The task id.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t deleteTask(TaskId_t *id);
|
||||
/**
|
||||
* Checks if the current executing context is an ISR.
|
||||
* @return true if handling an interrupt, false else.
|
||||
*/
|
||||
static bool isInterruptInProgress();
|
||||
/**
|
||||
* An task is not executed periodically by default.
|
||||
* This is activated with this call. This is managed internally.
|
||||
* @param period The task's period in clock ticks.
|
||||
* @param[out] periodId The newly created period's id
|
||||
* @param name optional name for the period
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t setAndStartPeriod(Interval_t period, PeriodId_t *periodId, Name_t name = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd'));
|
||||
/**
|
||||
* This call must be made in a periodic task, when activities of one cycle are finished.
|
||||
* This is managed internally.
|
||||
* @param periodId Id of the period as returned by setAndStartPeriod()
|
||||
* @param period The period duration for the next cycle.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t checkAndRestartPeriod(PeriodId_t periodId, Interval_t period);
|
||||
/**
|
||||
* This call deletes the period.
|
||||
* This is managed internally.
|
||||
* @param id Pointer to the task identifier the period belongs to.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t deletePeriod(TaskId_t *id);
|
||||
/**
|
||||
* With this call the period statistics (and therefore the periodic task
|
||||
* statistics) are printed to the screen.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t reportPeriodStatistics();
|
||||
|
||||
/**
|
||||
* With this call, a new message queue is created.
|
||||
* @param name A qualified name for the message queue.
|
||||
* @param count Number of messages the queue can store before it rejects new messages.
|
||||
* @param max_message_size Maximum size of a single message.
|
||||
* @param attribute_set Attributes for the message queue (fifo/priority, local/global)
|
||||
* @param id A unique message queue identifier returned by the OS.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t createMessageQueue(Name_t name, uint32_t count,
|
||||
size_t max_message_size, Attribute_t attribute_set,
|
||||
MessageQueueId_t *id);
|
||||
/**
|
||||
* Returns a message queue id by its name.
|
||||
* @param name The queue's name.
|
||||
* @param id A pointer to the queue id to return to.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t findMessageQueue(Name_t name, MessageQueueId_t *id);
|
||||
/**
|
||||
* Sends a message to the queue given by id.
|
||||
* @param id Id of the queue to send to
|
||||
* @param buffer A pointer to any kind of data to send over the queue.
|
||||
* @param size Size of the data to send.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t sendMessage(MessageQueueId_t id, const void *buffer,
|
||||
size_t size);
|
||||
/**
|
||||
* Checks, if a message was received by a queue with identifier id.
|
||||
* @param id The id of the checked task.
|
||||
* @param buffer Pointer to the buffer to store to.
|
||||
* @param bufSize Maximum size of the buffer.
|
||||
* @param recSize The actual message size is returned here.
|
||||
* @param option_set Specifies, if the task waits for a message (WAIT/ NO_WAIT).
|
||||
* @param timeout If the task waits, this interval specifies how long (in clock ticks).
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t receiveMessage(MessageQueueId_t id, void *buffer,
|
||||
size_t bufSize, size_t *recSize, Option_t option_set,
|
||||
Interval_t timeout);
|
||||
/**
|
||||
* Deletes all pending messages in a certain queue.
|
||||
* @param id Id of the queue to flush
|
||||
* @param count Number of flushed messages.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t flushMessageQueue( MessageQueueId_t id, uint32_t* count );
|
||||
/**
|
||||
* Deletes a message queue from the system.
|
||||
* @param id Id of the queue to delete.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t deleteMessageQueue(MessageQueueId_t *id);
|
||||
|
||||
/**
|
||||
* Creates a new mutual exclusive lock (or semaphore).
|
||||
* With these locks, concurrent access to system resources (data pool, ...) can be
|
||||
* controlled.
|
||||
* @param name A qualified name for the mutex.
|
||||
* @param id The mutex's id as returned by the OS.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t createMutex(Name_t name, MutexId_t *id);
|
||||
/**
|
||||
* Deletes the mutex identified by id.
|
||||
* @param id Id of the mutex to delete.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t deleteMutex(MutexId_t *id);
|
||||
/**
|
||||
* With this call, a task tries to acquire the mutex.
|
||||
* Must be used in conjunction with unlockMutex.
|
||||
* @param id Id of the mutex to acquire.
|
||||
* @param timeout Specifies how long a task waits for the mutex. Default is NO_TIMEOUT.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t lockMutex(MutexId_t *id, Interval_t timeout);
|
||||
/**
|
||||
* Releases a mutex.
|
||||
* Must be used in conjunction with lockMutex.
|
||||
* @param id Id of the mutex to release.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t unlockMutex(MutexId_t *id);
|
||||
/**
|
||||
* 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 );
|
||||
/**
|
||||
* 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 enableInterrupt( 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 disableInterrupt( InterruptNumber_t interrupt );
|
||||
};
|
||||
|
||||
#endif /* API */
|
||||
#endif /* OSAL_H_ */
|
144
osal/OperatingSystemIF.h
Normal file
144
osal/OperatingSystemIF.h
Normal file
@ -0,0 +1,144 @@
|
||||
#ifndef FRAMEWORK_OSAL_OPERATINGSYSTEMIF_H_
|
||||
#define FRAMEWORK_OSAL_OPERATINGSYSTEMIF_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
class OperatingSystemIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::OPERATING_SYSTEM_ABSTRACTION;
|
||||
|
||||
//API Status codes, must be implemented by the Operating System (TODO comments based on rtems status.h):
|
||||
|
||||
/**
|
||||
* This is the status to indicate successful completion.
|
||||
*/
|
||||
static const ReturnValue_t SUCCESSFUL = MAKE_RETURN_CODE(0);
|
||||
/**
|
||||
* This is the status to indicate that a thread exited.
|
||||
*/
|
||||
static const ReturnValue_t TASK_EXITTED = MAKE_RETURN_CODE(1);
|
||||
/**
|
||||
* This is the status to indicate multiprocessing is not configured.
|
||||
*/
|
||||
static const ReturnValue_t MP_NOT_CONFIGURED = MAKE_RETURN_CODE(2);
|
||||
/**
|
||||
* This is the status to indicate that the object name was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_NAME = MAKE_RETURN_CODE(3);
|
||||
/**
|
||||
* This is the status to indicate that the object Id was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_ID = MAKE_RETURN_CODE(4);
|
||||
/**
|
||||
* This is the status to indicate you have attempted to create too many
|
||||
* instances of a particular object class.
|
||||
*
|
||||
* Used for full messages Queues as well
|
||||
*/
|
||||
static const ReturnValue_t TOO_MANY = MAKE_RETURN_CODE(5);
|
||||
/**
|
||||
* This is the status to indicate that a blocking directive timed out.
|
||||
*/
|
||||
static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(6);
|
||||
/**
|
||||
* This is the status to indicate the the object was deleted
|
||||
* while the task was blocked waiting.
|
||||
*/
|
||||
static const ReturnValue_t OBJECT_WAS_DELETED = MAKE_RETURN_CODE(7);
|
||||
/**
|
||||
* This is the status to indicate that the specified size was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_SIZE = MAKE_RETURN_CODE(8);
|
||||
/**
|
||||
* This is the status to indicate that the specified address is invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(9);
|
||||
/**
|
||||
* This is the status to indicate that the specified number was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_NUMBER = MAKE_RETURN_CODE(10);
|
||||
/**
|
||||
* This is the status to indicate that the item has not been initialized.
|
||||
*/
|
||||
static const ReturnValue_t NOT_DEFINED =MAKE_RETURN_CODE(11);
|
||||
/**
|
||||
* This is the status to indicate that the object still has
|
||||
* resources in use.
|
||||
*/
|
||||
static const ReturnValue_t RESOURCE_IN_USE =MAKE_RETURN_CODE(12);
|
||||
/**
|
||||
* This is the status to indicate that the request was not satisfied.
|
||||
*/
|
||||
static const ReturnValue_t UNSATISFIED =MAKE_RETURN_CODE(13);
|
||||
/**
|
||||
* Indicates that a Message Queue is empty (unable to allocate it)
|
||||
*/
|
||||
static const ReturnValue_t QUEUE_EMPTY =MAKE_RETURN_CODE(14);
|
||||
/**
|
||||
* This is the status to indicate that a thread is in wrong state
|
||||
* was in the wrong execution state for the requested operation.
|
||||
*/
|
||||
static const ReturnValue_t INCORRECT_STATE =MAKE_RETURN_CODE(15);
|
||||
/**
|
||||
* This is the status to indicate thread was already suspended.
|
||||
*/
|
||||
static const ReturnValue_t ALREADY_SUSPENDED = MAKE_RETURN_CODE(16);
|
||||
/**
|
||||
* This is the status to indicate that the operation is illegal
|
||||
* on calling thread.
|
||||
*/
|
||||
static const ReturnValue_t ILLEGAL_ON_SELF =MAKE_RETURN_CODE(17);
|
||||
/**
|
||||
* This is the status to indicate illegal for remote object.
|
||||
*/
|
||||
static const ReturnValue_t ILLEGAL_ON_REMOTE_OBJECT=MAKE_RETURN_CODE(18);
|
||||
/**
|
||||
* This is the status to indicate that the operation should not be
|
||||
* called from from this excecution environment.
|
||||
*/
|
||||
static const ReturnValue_t CALLED_FROM_ISR=MAKE_RETURN_CODE(19);
|
||||
/**
|
||||
* This is the status to indicate that an invalid thread priority
|
||||
* was provided.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_PRIORITY=MAKE_RETURN_CODE(20);
|
||||
/**
|
||||
* This is the status to indicate that the specified date/time was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_CLOCK=MAKE_RETURN_CODE(21);
|
||||
/**
|
||||
* This is the status to indicate that the specified node Id was invalid.
|
||||
*/
|
||||
static const ReturnValue_t INVALID_NODE=MAKE_RETURN_CODE(22);
|
||||
/**
|
||||
* This is the status to indicate that the directive was not configured.
|
||||
*/
|
||||
static const ReturnValue_t NOT_CONFIGURED=MAKE_RETURN_CODE(23);
|
||||
/**
|
||||
* This is the status to indicate that the caller is not the
|
||||
* owner of the resource.
|
||||
*/
|
||||
static const ReturnValue_t NOT_OWNER_OF_RESOURCE=MAKE_RETURN_CODE(24);
|
||||
/**
|
||||
* This is the status to indicate the the directive or requested
|
||||
* portion of the directive is not implemented.
|
||||
*/
|
||||
static const ReturnValue_t NOT_IMPLEMENTED=MAKE_RETURN_CODE(25);
|
||||
/**
|
||||
* This is the status to indicate that an internal RTEMS inconsistency
|
||||
* was detected.
|
||||
*/
|
||||
static const ReturnValue_t INTERNAL_ERROR=MAKE_RETURN_CODE(26);
|
||||
/**
|
||||
* This is the status to indicate that the directive attempted to allocate
|
||||
* memory but was unable to do so.
|
||||
*/
|
||||
static const ReturnValue_t NO_MEMORY=MAKE_RETURN_CODE(27);
|
||||
/**
|
||||
* This is the status to indicate an driver IO error.
|
||||
*/
|
||||
static const ReturnValue_t IO_ERROR=MAKE_RETURN_CODE(28);
|
||||
|
||||
virtual ~OperatingSystemIF() {};
|
||||
};
|
||||
#endif /* FRAMEWORK_OSAL_OPERATINGSYSTEMIF_H_ */
|
145
osal/rtems/Clock.cpp
Normal file
145
osal/rtems/Clock.cpp
Normal 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
27
osal/rtems/InitTask.cpp
Normal 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
28
osal/rtems/InitTask.h
Normal 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_ */
|
70
osal/rtems/Interrupt.cpp
Normal file
70
osal/rtems/Interrupt.cpp
Normal 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
50
osal/rtems/Interrupt.h
Normal 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
116
osal/rtems/MessageQueue.cpp
Normal 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
174
osal/rtems/MessageQueue.h
Normal 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_ */
|
90
osal/rtems/MultiObjectTask.cpp
Normal file
90
osal/rtems/MultiObjectTask.cpp
Normal 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);
|
||||
}
|
113
osal/rtems/MultiObjectTask.h
Normal file
113
osal/rtems/MultiObjectTask.h
Normal 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
35
osal/rtems/Mutex.cpp
Normal 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
18
osal/rtems/Mutex.h
Normal 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_ */
|
24
osal/rtems/MutexFactory.cpp
Normal file
24
osal/rtems/MutexFactory.cpp
Normal 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
106
osal/rtems/PollingTask.cpp
Normal 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
85
osal/rtems/PollingTask.h
Normal 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_ */
|
36
osal/rtems/QueueFactory.cpp
Normal file
36
osal/rtems/QueueFactory.cpp
Normal 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
70
osal/rtems/RtemsBasic.cpp
Normal 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
39
osal/rtems/RtemsBasic.h
Normal 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
43
osal/rtems/TaskBase.cpp
Normal 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
43
osal/rtems/TaskBase.h
Normal 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_ */
|
34
osal/rtems/TaskFactory.cpp
Normal file
34
osal/rtems/TaskFactory.cpp
Normal 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() {
|
||||
}
|
Reference in New Issue
Block a user