fsfw/osal/OSAL.cpp
2016-06-15 23:48:49 +02:00

283 lines
8.2 KiB
C++

/**
* @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 */