1
0
forked from fsfw/fsfw

Today's the day. Renamed platform to framework.

This commit is contained in:
Bastian Baetz
2016-06-15 23:48:41 +02:00
committed by Ulrich Mohr
parent 40987d0b27
commit 1d22a6c97e
356 changed files with 33946 additions and 3 deletions

183
osal/CpuUsage.cpp Normal file
View File

@ -0,0 +1,183 @@
#include <framework/osal/CpuUsage.h>
#include <framework/serialize/SerialArrayListAdapter.h>
#include <framework/serialize/SerializeAdapter.h>
#include <string.h>
extern "C" {
#include <rtems/cpuuse.h>
}
int handlePrint(void * token, const char *format, ...) {
CpuUsage *cpuUsage = (CpuUsage *) token;
if (cpuUsage->counter == 0) {
//header
cpuUsage->counter++;
return 0;
}
if (cpuUsage->counter % 2 == 1) {
{
//we can not tell when the last call is so we assume it be every uneven time
va_list vl;
va_start(vl, format);
float timeSinceLastReset = va_arg(vl,uint32_t);
uint32_t timeSinceLastResetDecimals = va_arg(vl,uint32_t);
timeSinceLastReset = timeSinceLastReset
+ (timeSinceLastResetDecimals / 1000.);
cpuUsage->timeSinceLastReset = timeSinceLastReset;
va_end(vl);
}
//task name and id
va_list vl;
va_start(vl, format);
cpuUsage->cachedValue.id = va_arg(vl,uint32_t);
const char *name = va_arg(vl,const char *);
memcpy(cpuUsage->cachedValue.name, name,
CpuUsage::ThreadData::MAX_LENGTH_OF_THREAD_NAME);
va_end(vl);
} else {
//statistics
va_list vl;
va_start(vl, format);
float run = va_arg(vl,uint32_t);
uint32_t runDecimals = va_arg(vl,uint32_t);
float percent = va_arg(vl,uint32_t);
uint32_t percent_decimals = va_arg(vl,uint32_t);
run = run + (runDecimals / 1000.);
percent = percent + (percent_decimals / 1000.);
cpuUsage->cachedValue.percentUsage = percent;
cpuUsage->cachedValue.timeRunning = run;
cpuUsage->threadData.insert(cpuUsage->cachedValue);
va_end(vl);
}
cpuUsage->counter++;
return 0;
}
CpuUsage::CpuUsage() :
counter(0), timeSinceLastReset(0) {
}
CpuUsage::~CpuUsage() {
}
void CpuUsage::resetCpuUsage() {
rtems_cpu_usage_reset();
}
void CpuUsage::read() {
rtems_cpu_usage_report_with_plugin(this, &handlePrint);
}
void CpuUsage::clear() {
counter = 0;
timeSinceLastReset = 0;
threadData.clear();
}
ReturnValue_t CpuUsage::serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const {
ReturnValue_t result = SerializeAdapter<float>::serialize(
&timeSinceLastReset, buffer, size, max_size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return SerialArrayListAdapter<ThreadData>::serialize(&threadData, buffer,
size, max_size, bigEndian);
}
uint32_t CpuUsage::getSerializedSize() const {
uint32_t size = 0;
size += sizeof(timeSinceLastReset);
size += SerialArrayListAdapter<ThreadData>::getSerializedSize(&threadData);
return size;
}
ReturnValue_t CpuUsage::deSerialize(const uint8_t** buffer, int32_t* size,
bool bigEndian) {
ReturnValue_t result = SerializeAdapter<float>::deSerialize(
&timeSinceLastReset, buffer, size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return SerialArrayListAdapter<ThreadData>::deSerialize(&threadData, buffer,
size, bigEndian);
}
ReturnValue_t CpuUsage::ThreadData::serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const {
ReturnValue_t result = SerializeAdapter<uint32_t>::serialize(&id, buffer,
size, max_size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (*size + MAX_LENGTH_OF_THREAD_NAME > max_size) {
return BUFFER_TOO_SHORT;
}
memcpy(*buffer, name, MAX_LENGTH_OF_THREAD_NAME);
*size += MAX_LENGTH_OF_THREAD_NAME;
*buffer += MAX_LENGTH_OF_THREAD_NAME;
result = SerializeAdapter<float>::serialize(&timeRunning,
buffer, size, max_size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter<float>::serialize(&percentUsage,
buffer, size, max_size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t CpuUsage::ThreadData::getSerializedSize() const {
uint32_t size = 0;
size += sizeof(id);
size += MAX_LENGTH_OF_THREAD_NAME;
size += sizeof(timeRunning);
size += sizeof(percentUsage);
return size;
}
ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer,
int32_t* size, bool bigEndian) {
ReturnValue_t result = SerializeAdapter<uint32_t>::deSerialize(&id, buffer,
size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if ((*size = *size - MAX_LENGTH_OF_THREAD_NAME) < 0) {
return STREAM_TOO_SHORT;
}
memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME);
*buffer -= MAX_LENGTH_OF_THREAD_NAME;
result = SerializeAdapter<float>::deSerialize(&timeRunning,
buffer, size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter<float>::deSerialize(&percentUsage,
buffer, size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
}

53
osal/CpuUsage.h Normal file
View File

@ -0,0 +1,53 @@
#ifndef CPUUSAGE_H_
#define CPUUSAGE_H_
#include <framework/container/FixedArrayList.h>
#include <framework/serialize/SerializeIF.h>
#include <stdarg.h>
class CpuUsage : public SerializeIF {
public:
static const uint8_t MAXIMUM_NUMBER_OF_THREADS = 30;
class ThreadData: public SerializeIF {
public:
static const uint8_t MAX_LENGTH_OF_THREAD_NAME = 4;
uint32_t id;
char name[MAX_LENGTH_OF_THREAD_NAME];
float timeRunning;
float percentUsage;
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const;
virtual uint32_t getSerializedSize() const;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size,
bool bigEndian);
};
CpuUsage();
virtual ~CpuUsage();
uint8_t counter;
float timeSinceLastReset;
FixedArrayList<ThreadData, MAXIMUM_NUMBER_OF_THREADS> threadData;
ThreadData cachedValue;
static void resetCpuUsage();
void read();
void clear();
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const;
virtual uint32_t getSerializedSize() const;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size,
bool bigEndian);
};
#endif /* CPUUSAGE_H_ */

View File

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

39
osal/InternalErrorCodes.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef INTERNALERRORCODES_H_
#define INTERNALERRORCODES_H_
#include <framework/returnvalues/HasReturnvaluesIF.h>
class InternalErrorCodes {
public:
static const uint8_t INTERFACE_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 );
static const ReturnValue_t INVALID_WORKSPACE_ADDRESS = MAKE_RETURN_CODE(0x03 );
static const ReturnValue_t TOO_LITTLE_WORKSPACE = MAKE_RETURN_CODE(0x04 );
static const ReturnValue_t WORKSPACE_ALLOCATION = MAKE_RETURN_CODE(0x05 );
static const ReturnValue_t INTERRUPT_STACK_TOO_SMALL = MAKE_RETURN_CODE(0x06 );
static const ReturnValue_t THREAD_EXITTED = MAKE_RETURN_CODE(0x07 );
static const ReturnValue_t INCONSISTENT_MP_INFORMATION = MAKE_RETURN_CODE(0x08 );
static const ReturnValue_t INVALID_NODE = MAKE_RETURN_CODE(0x09 );
static const ReturnValue_t NO_MPCI = MAKE_RETURN_CODE(0x0a );
static const ReturnValue_t BAD_PACKET = MAKE_RETURN_CODE(0x0b );
static const ReturnValue_t OUT_OF_PACKETS = MAKE_RETURN_CODE(0x0c );
static const ReturnValue_t OUT_OF_GLOBAL_OBJECTS = MAKE_RETURN_CODE(0x0d );
static const ReturnValue_t OUT_OF_PROXIES = MAKE_RETURN_CODE(0x0e );
static const ReturnValue_t INVALID_GLOBAL_ID = MAKE_RETURN_CODE(0x0f );
static const ReturnValue_t BAD_STACK_HOOK = MAKE_RETURN_CODE(0x10 );
static const ReturnValue_t BAD_ATTRIBUTES = MAKE_RETURN_CODE(0x11 );
static const ReturnValue_t IMPLEMENTATION_KEY_CREATE_INCONSISTENCY = MAKE_RETURN_CODE(0x12 );
static const ReturnValue_t IMPLEMENTATION_BLOCKING_OPERATION_CANCEL = MAKE_RETURN_CODE(0x13 );
static const ReturnValue_t MUTEX_OBTAIN_FROM_BAD_STATE = MAKE_RETURN_CODE(0x14 );
static const ReturnValue_t UNLIMITED_AND_MAXIMUM_IS_0 = MAKE_RETURN_CODE(0x15 );
virtual ~InternalErrorCodes();
static ReturnValue_t translate(uint8_t code);
private:
InternalErrorCodes();
};
#endif /* INTERNALERRORCODES_H_ */

282
osal/OSAL.cpp Normal file
View File

@ -0,0 +1,282 @@
/**
* @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 Normal file
View File

@ -0,0 +1,430 @@
/**
* @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_ */