From 0074691a67f857c9b3f880fb581e0af1d5673337 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 31 Jul 1997 22:13:29 +0000 Subject: Merged very large and much appreciated patch from Chris Johns . This patch includes the ods68302 bsp, the RTEMS++ class library, and the rtems++ test. --- c/src/lib/librtems++/Makefile.in | 49 +++++ c/src/lib/librtems++/README | 266 +++++++++++++++++++++++++++ c/src/lib/librtems++/rtemsEvent.cc | 75 ++++++++ c/src/lib/librtems++/rtemsInterrupt.cc | 110 ++++++++++++ c/src/lib/librtems++/rtemsMessageQueue.cc | 164 +++++++++++++++++ c/src/lib/librtems++/rtemsSemaphore.cc | 174 ++++++++++++++++++ c/src/lib/librtems++/rtemsStatusCode.cc | 77 ++++++++ c/src/lib/librtems++/rtemsTask.cc | 287 ++++++++++++++++++++++++++++++ c/src/lib/librtems++/rtemsTimer.cc | 100 +++++++++++ 9 files changed, 1302 insertions(+) create mode 100644 c/src/lib/librtems++/Makefile.in create mode 100644 c/src/lib/librtems++/README create mode 100644 c/src/lib/librtems++/rtemsEvent.cc create mode 100644 c/src/lib/librtems++/rtemsInterrupt.cc create mode 100644 c/src/lib/librtems++/rtemsMessageQueue.cc create mode 100644 c/src/lib/librtems++/rtemsSemaphore.cc create mode 100644 c/src/lib/librtems++/rtemsStatusCode.cc create mode 100644 c/src/lib/librtems++/rtemsTask.cc create mode 100644 c/src/lib/librtems++/rtemsTimer.cc (limited to 'c/src/lib/librtems++') diff --git a/c/src/lib/librtems++/Makefile.in b/c/src/lib/librtems++/Makefile.in new file mode 100644 index 0000000000..5e67e02110 --- /dev/null +++ b/c/src/lib/librtems++/Makefile.in @@ -0,0 +1,49 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH=@srcdir@ + +LIBNAME=librtems++.a +LIB=${ARCH}/${LIBNAME} + +# C and C++ source names, if any, go here -- minus the .c or .cc +CC_PIECES=rtemsEvent rtemsInterrupt rtemsMessageQueue rtemsSemaphore \ + rtemsStatusCode rtemsTask rtemsTimer +CC_FILES=$(CC_PIECES:%=%.cc) +CC_O_FILES=$(CC_PIECES:%=${ARCH}/%.o) + +SRCS=$(CC_FILES) +OBJS=$(CC_O_FILES) + +include $(RTEMS_CUSTOM) +include $(PROJECT_ROOT)/make/lib.cfg + +# +# Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += $(LIBC_DEFINES) + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += $(LIB) +CLOBBER_ADDITIONS += + +all: ${ARCH} $(LIB) + $(INSTALL_VARIANT) -m 644 ${LIB} ${PROJECT_RELEASE}/lib + +$(LIB): $(SRCS) ${OBJS} + $(make-library) + + diff --git a/c/src/lib/librtems++/README b/c/src/lib/librtems++/README new file mode 100644 index 0000000000..65b0eb980e --- /dev/null +++ b/c/src/lib/librtems++/README @@ -0,0 +1,266 @@ +# +# $Id$ +# + +RTEMS C++ Library +================= + +The RTEMS C++ Library or librtems++ is a wrapper for the RTEMS API. +The classes provide as close a match to the RTEMS C API, for +performance, to share the existing C documentation as much as +possible, and to allow easy tracking of any changes to the RTEMS C +API. + +The C++ interface only uses RTEMS API calls. No external references +or internal interfaces are used. This allows the classes to be used +in separately compiled modules or applications which link to the RTEMS +trap interface. + +(This is the goal, which has not quite been reached. The TOD macro for +micro-seconds to ticks is used, and this uses an internal global RTEMS +variable) + +The C++ interface does not deal with RTEMS initialisation or the +device driver interface. The current view is these parts of a system +are best handled in the current manner. This means BSP for +initialisation and the C API for drivers. + +RTEMS C++ Classes +================= + +The classes map to the managers of RTEMS. + +The methods have default values selected which try to fit most cases +or follow the documented RTEMS default values. Moving from left to +right the parameters become less used, allowing the defaults to be +selected. An example is the scope parameter for most classes. This +can be local or global. I assume that most RTEMS objects are local, +therefore it has been made the last parameter. + +Inline methods have been used for methods which are commonly used in +applications. This tries to add the minimum of overhead. For +example, the methods to send or receive events are inline, while all +methods for control of a task are not. + +The RTEMS types, enumerations, and defines are used. If a new type, +enumeration or define is made it will map directly to the RTEMS +equivalent. For example the enumeration Scope is defined for various +classes which can be local or global. The elements of the enumeration +are forced to the same value as the RTEMS values. An enumeration is +used in this case to allow the compiler to type check a little +better. It saves having to check only RTEMS_LOCAL or RTEMS_GLOBAL is +passed as a parameter (I am not convinced this is really needed as the +goal was to not define anything and to only use what RTEMS provided). + +Where possible the various parts of an option bit set, or mode can be +controlled separately or controlled as a group. An example is the +task mode. The RTEMS C API allows a set of modes to be modified at +once. The TaskMode class allows this to occur, while also providing +methods to control a single mode item. + +The name of an object is always passed as a string. The classes turn +the string into a rtems_name variable. The string does not have to be +nul character terminated. + +The RTEMS C API uses 'delete' to remove or kill an RTEMS object. This +is a reserved word in C++, so the word 'destroy' is used instead. + +Calling the classes from interrupts follows the rules of RTEMS. An +exception introduced by the class library is the last status code. +There is only one last status code for each instance of the library's +classes and it is not protected. This needs to be watched for. Maybe +a better solution needs to be found, such as interrupt calls do not set +the last status code. + +RTEMS objects created by the C++ library can be operated on by C code +just as any other RTEMS object. If limitations exist they should be +documented in under the class. + +RTEMS Object Ownership +====================== + +The concept of ownership of an object is not defined as part of the +RTEMS C API. A piece of code executing as part a task can create a +message queue. Another piece of code running as part of a different +task can destroy the message queue. Correct behavior between the code +that creates the message queue and the code which destroy's the +message queue must be provided by the programmer. + +The librtems++ supports the concept of ownership of an RTEMS object. +Only the C++ object that creates the RTEMS object can destroy it. A +C++ object can connect to an existing RTEMS object and control it, +how-ever it can not destroy it. + +Copy constructors and assignment operators are provided to in-force +this rule. + +Ownership only applies to classes that create RTEMS objects. These +classes contain a flag which signals ownership of the id. + +Timeouts +======== + +The timeout value is specified in micro-seconds. The classes turn the +micro-second timeout value into ticks required by the RTEMS C API. + +This causes a problem for timeout values which are less than one tick. +This case is tested for and the timeout value is set to one tick. All +other cases round down to the nearest tick. + +Status Codes +============ + +All classes which form the C++ API are derived from the StatusCode +class. This class provides a common method for handling the status +code returned by RTEMS. + +The last returned status code is held in the StatusCode object. It +can be queried directly, or as a boolean. You can also obtain an +error string for the status code. + +The setting of a status code is restricted to derived classes. + +The last status code attribute of the class is only ever set to an +RTEMS defined status code. + +Event Class +=========== + +The event class allows users to send and receive events to and from +tasks. + +Events objects are by default connected the RTEMS_SELF task. A send +or receive will operate on the task currently executing. + +An Event object can be connected to a task using the connect method. +The name is the name of the task. Connection can also be achieved by +using the copy constructor or assignment operator. + +Events can be sent to a task by specifying an RTEMS task id, or by +passing a reference to a Task object. + +Interrupt Class +=============== + +The interrupt class allows a protected virtual method of a derived +class to be an interrupt handler. + +You derive from this class and provide the handler method. The next +interrupt after the vector is caught will cause the handler method to +be entered. + +You can chain the interrupt by calling the chain method. If the old +handler is not an instance of this class the chain is passed as "void +(*)(void)". If it is an instance of this class, the handler method is +directly called. (Chaining has not been tested) + +This class implements a table of pointers to the last instance to +catch the interrupt. A static method of the class catches the +interrupt and re-directs the interrupt to the instance in the table. +The re-direct adds a additional virtual function call and return to +the overhead of the interrupt. For a i386 type processor this is +about 12 instructions including the function call entry. + +Message Queue Class +=================== + +The MessageQueue class allows message queue's to be created, or +connected too. Only the creator can destroy a message queue. + +The class implements, sending, urgent sending, broadcast, flushing, +and receiving. + +Semaphore Class +=============== + +The Semaphore class allows semaphores to be created, or connected +too. Only the creator can destroy a semaphore. + +All types of semaphores can be created. + +(Not tested in the test code) + +Task Class +========== + +The Task class allows tasks to be created, or connected too. Only the +creator can destroy a task. + +If creating a task, derive from the Task class and provide the body +method. The body method is the entry point for a task. When +connecting to an existing task, no body method is required to be +provided. It is how-ever required if you create a task. This is not +enforced by the compiler, how-ever the default body will be entered, +and it contains no code. The RTEMS default behaviour for a task that +returns occurs. + +The mode of a task is controlled using the TaskMode class. + +The Task class allows you to start, restart, suspend, and resume a +task. You can control the priority, and access the note-pad +registers. The task can also be slept using the wake_after and +wake_when methods. + +Currently the task argument is used to pass the 'this' pointer to the +libraries default task body. The actual argument is held in the class +instance and passed to the virtual body method. This means of passing +the 'this' pointer through RTEMS to the default task body requires the +actual task object to perform a restart call. This is not really the +best solution to the problem. Another solution is to remove a notpad +register, say 31 from the task and use it. This would mean any Task +object could stop and restart a task how-ever a notpad register is +lost. Any other ideas are welcome. + +Task Mode Class +=============== + +The TaskMode class allows you to query or change the mode of a task. +The object only operates on the currently executing task. + +The standard flags defined in RTEMS are used. + +Methods are provided to operate on a group of modes which are required +to be changed in a single operation. The mode and mask is specified +by ORing the required flags as documented in the RTEMS manual. + +Methods are provided for accessing and controlling a specific mode. +The returned value will only contain the requested mode's flags, and +only the that mode will be changed when setting a mode. + +Timer Class +=========== + +The Timer class allows timers to be created. You cannot connect to an +existing timer. + +You derive from the Timer class and provide the trigger method. This +method is called when the timer triggers or times out. + +You can request a single shot timer using the fire_after or fire_when +methods, or a periodic timer by calling the repeat_file_at method. + +You cannot copy timer objects. + +Contact +======= +Send any question to me Chris Johns at cjohns@plessey.com.au, or the RTEMS +mailing list. + +To Do +===== + +1) Develop a complete test suite (under way, cjohns@plessey.com.au). + +2) Complete wrapping the remaining RTEMS C API. + +3) Provide light weight cout/cerr/clog classes based on printf for +embedded systems. + +4) Provide a memory serial class which maps the <> operators onto +raw memory in network byte order independent of CPU byte order. + +5) Fix the Task class so any Task object can restart a task. + +6) Provide some frame work classes which allow actor type objects that +start in an ordered manner. + diff --git a/c/src/lib/librtems++/rtemsEvent.cc b/c/src/lib/librtems++/rtemsEvent.cc new file mode 100644 index 0000000000..a917f32836 --- /dev/null +++ b/c/src/lib/librtems++/rtemsEvent.cc @@ -0,0 +1,75 @@ +/* + ------------------------------------------------------------------------ + $Id$ + ------------------------------------------------------------------------ + + COPYRIGHT (c) 1997 + Objective Design Systems Ltd Pty (ODS) + All rights reserved (R) Objective Design Systems Ltd Pty + + The license and distribution terms for this file may be found in the + file LICENSE in this distribution or at + http://www.OARcorp.com/rtems/license.html. + + ------------------------------------------------------------------------ + + See header file. + + ------------------------------------------------------------------------ +*/ + +#include + +/* ---- + rtemsEvent +*/ + +rtemsEvent::rtemsEvent(const char *name_str, rtems_unsigned32 node) + : name(rtems_build_name('S', 'E', 'L', 'F')), + id(RTEMS_SELF) +{ + connect(name_str, node); +} + +rtemsEvent::rtemsEvent(const rtemsEvent& event) +{ + name = event.name; + id = event.id; +} + +rtemsEvent::rtemsEvent() + : name(rtems_build_name('S', 'E', 'L', 'F')), + id(RTEMS_SELF) +{ +} + +rtemsEvent::~rtemsEvent() +{ +} + +const rtemsEvent& rtemsEvent::operator=(const rtemsEvent& event) +{ + name = event.name; + id = event.id; + + return *this; +} + +const rtems_status_code rtemsEvent::connect(const char *name_str, + const rtems_unsigned32 node) +{ + name = rtems_build_name(name_str[0], + name_str[1], + name_str[2], + name_str[3]); + + set_status_code(rtems_task_ident(name, node, &id)); + + if (unsuccessful()) + { + name = rtems_build_name('S', 'E', 'L', 'F'); + id = RTEMS_SELF; + } + + return last_status_code(); +} diff --git a/c/src/lib/librtems++/rtemsInterrupt.cc b/c/src/lib/librtems++/rtemsInterrupt.cc new file mode 100644 index 0000000000..c445807c35 --- /dev/null +++ b/c/src/lib/librtems++/rtemsInterrupt.cc @@ -0,0 +1,110 @@ +/* + ------------------------------------------------------------------------ + $Id$ + ------------------------------------------------------------------------ + + COPYRIGHT (c) 1997 + Objective Design Systems Ltd Pty (ODS) + All rights reserved (R) Objective Design Systems Ltd Pty + + The license and distribution terms for this file may be found in the + file LICENSE in this distribution or at + http://www.OARcorp.com/rtems/license.html. + + ------------------------------------------------------------------------ + + See header file. + + ------------------------------------------------------------------------ +*/ + +#include + +/* ---- + Interrupt Table + + This table is used to re-direct the call from RTEMS to a user + object +*/ + +static rtemsInterrupt *interrupt_table[CPU_INTERRUPT_NUMBER_OF_VECTORS]; + +// has the table been initialised +static bool initialised = false; + +/* ---- + rtemsInterrupt +*/ + +rtemsInterrupt::rtemsInterrupt() + : vector(0), + caught(false), + old_handler(0), + old_interrupt(0) +{ + if (!initialised) + { + for (rtems_vector_number vec = 0; + vec < CPU_INTERRUPT_NUMBER_OF_VECTORS; + vec++) + { + interrupt_table[vector] = 0; + } + initialised = true; + } +} + +const rtems_status_code rtemsInterrupt::isr_catch(const rtems_vector_number vec) +{ + if (vec >= CPU_INTERRUPT_NUMBER_OF_VECTORS) + return set_status_code(RTEMS_INVALID_NUMBER); + + if (caught) + return set_status_code(RTEMS_RESOURCE_IN_USE); + + old_interrupt = interrupt_table[vector]; + interrupt_table[vector] = this; + vector = vec; + + set_status_code(rtems_interrupt_catch(redirector, + vector, + &old_handler)); + + if (successful()) + caught = true; + else + { + interrupt_table[vector] = old_interrupt; + old_interrupt = 0; + old_handler = 0; + vector = 0; + } + + return last_status_code(); +} + +const rtems_status_code rtemsInterrupt::release(void) +{ + if (caught) + { + set_status_code(rtems_interrupt_catch(old_handler, + vector, + &old_handler)); + + interrupt_table[vector] = old_interrupt; + old_interrupt = 0; + old_handler = 0; + vector = 0; + caught = false; + } + else + set_status_code(RTEMS_SUCCESSFUL); + + return last_status_code(); +} + +void rtemsInterrupt::redirector(rtems_vector_number vector) +{ + if (interrupt_table[vector]) + interrupt_table[vector]->handler(); +} diff --git a/c/src/lib/librtems++/rtemsMessageQueue.cc b/c/src/lib/librtems++/rtemsMessageQueue.cc new file mode 100644 index 0000000000..1978e1c6ec --- /dev/null +++ b/c/src/lib/librtems++/rtemsMessageQueue.cc @@ -0,0 +1,164 @@ +/* + ------------------------------------------------------------------------ + $Id$ + ------------------------------------------------------------------------ + + COPYRIGHT (c) 1997 + Objective Design Systems Ltd Pty (ODS) + All rights reserved (R) Objective Design Systems Ltd Pty + + The license and distribution terms for this file may be found in the + file LICENSE in this distribution or at + http://www.OARcorp.com/rtems/license.html. + + ------------------------------------------------------------------------ + + See header file. + + ------------------------------------------------------------------------ +*/ + +#include + +/* ---- + rtemsMessageQueue +*/ + +rtemsMessageQueue::rtemsMessageQueue(const char* mqname, + const rtems_unsigned32 count, + const rtems_unsigned32 max_message_size, + const WaitMode wait_mode, + const Scope scope) + : name(0), + owner(true), + id(0) +{ + strcpy(name_str, "NOID"); + create(mqname, count, max_message_size, wait_mode, scope); +} + +rtemsMessageQueue::rtemsMessageQueue(const char *mqname, + const rtems_unsigned32 node) + : name(0), + owner(false), + id(0) +{ + strcpy(name_str, "NOID"); + connect(mqname, node); +} + +rtemsMessageQueue::rtemsMessageQueue(const rtemsMessageQueue& message_queue) + : name(0), + owner(false), + id(0) +{ + name = message_queue.name; + strcpy(name_str, message_queue.name_str); + id = message_queue.id; +} + +rtemsMessageQueue::rtemsMessageQueue() + : name(0), + owner(false), + id(0) +{ + strcpy(name_str, "NOID"); +} + +rtemsMessageQueue::~rtemsMessageQueue() +{ + destroy(); +} + +void rtemsMessageQueue::make_invalid() +{ + strcpy(name_str, "NOID"); + name = 0; + id = 0; + owner = false; +} + +const rtems_status_code rtemsMessageQueue::create(const char* mqname, + const rtems_unsigned32 count, + const rtems_unsigned32 max_message_size, + const WaitMode wait_mode, + const Scope scope) +{ + if (id) + return set_status_code(RTEMS_ILLEGAL_ON_SELF); + + owner = true; + + strcpy(name_str, " "); + for (int c = 0; (c < 4) && (mqname[c] != '\0'); c++) + name_str[c] = mqname[c]; + name = rtems_build_name(name_str[0], + name_str[1], + name_str[2], + name_str[3]); + + set_status_code(rtems_message_queue_create(name, + count, + max_message_size, + scope | wait_mode, + &id)); + + if (unsuccessful()) + { + make_invalid(); + } + + return last_status_code(); +} + +const rtems_status_code rtemsMessageQueue::destroy() +{ + if (id && owner) + { + set_status_code(rtems_message_queue_delete(id)); + make_invalid(); + } + else + set_status_code(RTEMS_NOT_OWNER_OF_RESOURCE); + + return last_status_code(); +} + +const rtemsMessageQueue& rtemsMessageQueue::operator=(const rtemsMessageQueue& message_queue) +{ + if (!owner) + { + name = message_queue.name; + strcpy(name_str, message_queue.name_str); + id = message_queue.id; + } + + return *this; +} + +const rtems_status_code rtemsMessageQueue::connect(const char *mqname, + const rtems_unsigned32 node) +{ + if (id && owner) + return set_status_code(RTEMS_UNSATISFIED); + + // change state to not owner + owner = false; + + strcpy(name_str, " "); + for (int c = 0; (c < 4) && (mqname[c] != '\0'); c++) + name_str[c] = mqname[c]; + name = rtems_build_name(name_str[0], + name_str[1], + name_str[2], + name_str[3]); + + set_status_code(rtems_message_queue_ident(name, node, &id)); + + if (unsuccessful()) + { + make_invalid(); + } + + return last_status_code(); +} diff --git a/c/src/lib/librtems++/rtemsSemaphore.cc b/c/src/lib/librtems++/rtemsSemaphore.cc new file mode 100644 index 0000000000..1e0d3de472 --- /dev/null +++ b/c/src/lib/librtems++/rtemsSemaphore.cc @@ -0,0 +1,174 @@ +/* + ------------------------------------------------------------------------ + $Id$ + ------------------------------------------------------------------------ + + COPYRIGHT (c) 1997 + Objective Design Systems Ltd Pty (ODS) + All rights reserved (R) Objective Design Systems Ltd Pty + + The license and distribution terms for this file may be found in the + file LICENSE in this distribution or at + http://www.OARcorp.com/rtems/license.html. + + ------------------------------------------------------------------------ + + See header file. + + ------------------------------------------------------------------------ +*/ + +#include + +/* ---- + rtemsSemaphore +*/ + +rtemsSemaphore::rtemsSemaphore(const char* sname, + const Scope scope, + const rtems_unsigned32 counter, + const WaitMode wait_mode, + const Type type, + const Priority priority, + const Ceiling ceiling, + const rtems_task_priority priority_ceiling) + : name(0), + owner(true), + id(0) +{ + strcpy(name_str, "NOID"); + create(sname, + scope, + counter, + wait_mode, + type, + priority, + ceiling, + priority_ceiling); +} + +rtemsSemaphore::rtemsSemaphore(const char *sname, const rtems_unsigned32 node) + : name(0), + owner(false), + id(0) +{ + strcpy(name_str, "NOID"); + connect(sname, node); +} + +rtemsSemaphore::rtemsSemaphore(const rtemsSemaphore& semaphore) + : name(0), + owner(false), + id(0) +{ + name = semaphore.name; + strcpy(name_str, semaphore.name_str); + id = semaphore.id; +} + +rtemsSemaphore::rtemsSemaphore() + : name(0), + owner(false), + id(0) +{ + strcpy(name_str, "NOID"); +} + +rtemsSemaphore::~rtemsSemaphore() +{ + destroy(); +} + +void rtemsSemaphore::make_invalid() +{ + strcpy(name_str, "NOID"); + name = 0; + id = 0; + owner = false; +} + +const rtems_status_code rtemsSemaphore::create(const char* sname, + const Scope scope, + const rtems_unsigned32 counter, + const WaitMode wait_mode, + const Type type, + const Priority priority, + const Ceiling ceiling, + const rtems_task_priority priority_ceiling) +{ + if (id) + return set_status_code(RTEMS_ILLEGAL_ON_SELF); + + owner = true; + + strcpy(name_str, " "); + for (int c = 0; (c < 4) && (sname[c] != '\0'); c++) + name_str[c] = sname[c]; + name = rtems_build_name(name_str[0], + name_str[1], + name_str[2], + name_str[3]); + + set_status_code(rtems_semaphore_create(name, + counter, + scope | wait_mode | type | priority | ceiling, + priority_ceiling, + &id)); + + if (unsuccessful()) + { + make_invalid(); + } + + return last_status_code(); +} + +const rtems_status_code rtemsSemaphore::destroy() +{ + if (id && owner) + { + set_status_code(rtems_semaphore_delete(id)); + make_invalid(); + } + else + set_status_code(RTEMS_NOT_OWNER_OF_RESOURCE); + + return last_status_code(); +} + +const rtemsSemaphore& rtemsSemaphore::operator=(const rtemsSemaphore& semaphore) +{ + if (!owner) + { + name = semaphore.name; + id = semaphore.id; + } + return *this; +} + +const rtems_status_code rtemsSemaphore::connect(const char *sname, + const rtems_unsigned32 node) +{ + if (id && owner) + return set_status_code(RTEMS_UNSATISFIED); + + // change state to not owner + owner = false; + + strcpy(name_str, " "); + for (int c = 0; (c < 4) && (sname[c] != '\0'); c++) + name_str[c] = sname[c]; + name = rtems_build_name(name_str[0], + name_str[1], + name_str[2], + name_str[3]); + + set_status_code(rtems_semaphore_ident(name, node, &id)); + + if (unsuccessful()) + { + make_invalid(); + } + + return last_status_code(); +} diff --git a/c/src/lib/librtems++/rtemsStatusCode.cc b/c/src/lib/librtems++/rtemsStatusCode.cc new file mode 100644 index 0000000000..e8e3f965ba --- /dev/null +++ b/c/src/lib/librtems++/rtemsStatusCode.cc @@ -0,0 +1,77 @@ +/* + ------------------------------------------------------------------------ + $Id$ + ------------------------------------------------------------------------ + + COPYRIGHT (c) 1997 + Objective Design Systems Ltd Pty (ODS) + All rights reserved (R) Objective Design Systems Ltd Pty + + The license and distribution terms for this file may be found in the + file LICENSE in this distribution or at + http://www.OARcorp.com/rtems/license.html. + + ------------------------------------------------------------------------ + + See header file. + + ------------------------------------------------------------------------ +*/ + +#include + +/* ---- + Status Code string table +*/ + +static char *status_strings[RTEMS_STATUS_CODES_LAST + 1] = +{ + "RTEMS[00] successful completion", + "RTEMS[01] task exitted, returned from a thread", + "RTEMS[02] multiprocessing not configured", + "RTEMS[03] invalid object name", + "RTEMS[04] invalid object id", + "RTEMS[05] too many", + "RTEMS[06] timed out waiting", + "RTEMS[07] object deleted while waiting", + "RTEMS[08] specified size was invalid", + "RTEMS[09] address specified is invalid", + "RTEMS[10] number was invalid", + "RTEMS[11] item has not been initialized", + "RTEMS[12] resources still outstanding", + "RTEMS[13] request not satisfied", + "RTEMS[14] thread is in wrong state", + "RTEMS[15] thread already in state", + "RTEMS[16] illegal on calling thread", + "RTEMS[17] illegal for remote object", + "RTEMS[18] called from wrong environment", + "RTEMS[19] invalid thread priority", + "RTEMS[20] invalid date/time", + "RTEMS[21] invalid node id", + "RTEMS[22] directive not configured", + "RTEMS[23] not owner of resource", + "RTEMS[24] directive not implemented", + "RTEMS[25] RTEMS inconsistency detected", + "RTEMS[26] could not get enough memory" +}; + +/* ---- + StatusCode +*/ + +const char *rtemsStatusCode::last_status_string() +{ + return status_string(last_status); +} + +const char *rtemsStatusCode::status_string(rtems_status_code status_code) +{ + // mapped from "rtems/rtems/status.h" + if (status_code <= RTEMS_STATUS_CODES_LAST) + { + return status_strings[status_code]; + } + + return "unknown status code"; +} + diff --git a/c/src/lib/librtems++/rtemsTask.cc b/c/src/lib/librtems++/rtemsTask.cc new file mode 100644 index 0000000000..d90c8f669f --- /dev/null +++ b/c/src/lib/librtems++/rtemsTask.cc @@ -0,0 +1,287 @@ +/* + ------------------------------------------------------------------------ + $Id$ + ------------------------------------------------------------------------ + + COPYRIGHT (c) 1997 + Objective Design Systems Ltd Pty (ODS) + All rights reserved (R) Objective Design Systems Ltd Pty + + The license and distribution terms for this file may be found in the + file LICENSE in this distribution or at + http://www.OARcorp.com/rtems/license.html. + + ------------------------------------------------------------------------ + + See header file. + + ------------------------------------------------------------------------ +*/ + +#include +// include to allow it to be compiled +#include + +/* ---- + rtemsTask +*/ + +rtemsTask::rtemsTask(const char* tname, + const rtems_task_priority initial_priority, + const rtems_unsigned32 stack_size, + const rtems_mode preemption, + const rtems_mode timeslice, + const rtems_mode asr, + const rtems_interrupt_level interrupt_level, + const FloatingPoint floating_point, + const Scope scope) + : name(rtems_build_name('S', 'E', 'L', 'F')), + owner(true), + id(RTEMS_SELF), + argument(0) +{ + strcpy(name_str, "SELF"); + create(tname, + initial_priority, + stack_size, + preemption, + timeslice, + asr, + interrupt_level, + floating_point, + scope); +} + +rtemsTask::rtemsTask(const char *tname, rtems_unsigned32 node) + : name(rtems_build_name('S', 'E', 'L', 'F')), + owner(false), + id(RTEMS_SELF), + argument(0) +{ + strcpy(name_str, "SELF"); + connect(tname, node); +} + +rtemsTask::rtemsTask(const rtemsTask& task) + : name(rtems_build_name('S', 'E', 'L', 'F')), + owner(false), + id(RTEMS_SELF), + argument(0) +{ + name = task.name; + strcpy(name_str, task.name_str); + argument = task.argument; + id = task.id; +} + +rtemsTask::rtemsTask() + : name(rtems_build_name('S', 'E', 'L', 'F')), + owner(false), + id(RTEMS_SELF), + argument(0) +{ + strcpy(name_str, "SELF"); +} + +rtemsTask::~rtemsTask() +{ + destroy(); +} + +void rtemsTask::make_self() +{ + strcpy(name_str, "SELF"); + name = rtems_build_name('S', 'E', 'L', 'F'); + id = RTEMS_SELF; + owner = false; +} + +const rtems_status_code rtemsTask::create(const char* tname, + const rtems_task_priority initial_priority, + const rtems_unsigned32 stack_size, + const rtems_mode preemption, + const rtems_mode timeslice, + const rtems_mode asr, + const rtems_interrupt_level interrupt_level, + const FloatingPoint floating_point, + const Scope scope) +{ + if (id) + return set_status_code(RTEMS_ILLEGAL_ON_SELF); + + owner = true; + + strcpy(name_str, " "); + for (int c = 0; (c < 4) && (tname[c] != '\0'); c++) + name_str[c] = tname[c]; + name = rtems_build_name(name_str[0], + name_str[1], + name_str[2], + name_str[3]); + + // protect the values that be set as the parameters are not enums + set_status_code(rtems_task_create(name, + initial_priority, + stack_size, + (preemption & RTEMS_PREEMPT_MASK) | + (timeslice & RTEMS_TIMESLICE_MASK) | + (asr & RTEMS_ASR_MASK) | + (interrupt_level & RTEMS_INTERRUPT_MASK), + floating_point | scope, + &id)); + + if (unsuccessful()) + { + make_self(); + } + + return last_status_code(); +} + +const rtems_status_code rtemsTask::destroy() +{ + if (id && owner) + { + set_status_code(rtems_task_delete(id)); + make_self(); + } + else + set_status_code(RTEMS_NOT_OWNER_OF_RESOURCE); + + return last_status_code(); +} + +const rtemsTask& rtemsTask::operator=(const rtemsTask& task) +{ + if (!owner) + { + name = task.name; + strcpy(name_str, task.name_str); + argument = task.argument; + id = task.id; + } + return *this; +} + +const rtems_status_code rtemsTask::connect(const char *sname, + const rtems_unsigned32 node) +{ + if (id && owner) + return set_status_code(RTEMS_UNSATISFIED); + + // change state to not owner + owner = false; + + strcpy(name_str, " "); + for (int c = 0; (c < 4) && (sname[c] != '\0'); c++) + name_str[c] = sname[c]; + name = rtems_build_name(name_str[0], + name_str[1], + name_str[2], + name_str[3]); + + set_status_code(rtems_task_ident(name, node, &id)); + + if (unsuccessful()) + { + make_self(); + } + + return last_status_code(); +} + +const rtems_status_code rtemsTask::start(const rtems_task_argument arg) +{ + if (owner) + { + argument = arg; + // pass the this pointer as the argument + set_status_code(rtems_task_start(id, + origin, + (rtems_task_argument) this)); + } + else + set_status_code(RTEMS_NOT_OWNER_OF_RESOURCE); + return last_status_code(); +} + +const rtems_status_code rtemsTask::restart(const rtems_task_argument arg) +{ + if (owner) + { + argument = arg; + set_status_code(rtems_task_restart(id, (rtems_task_argument) this)); + } + else + set_status_code(RTEMS_NOT_OWNER_OF_RESOURCE); + + return last_status_code(); +} + +const rtems_status_code rtemsTask::suspend() +{ + return set_status_code(rtems_task_suspend(id)); +} + +const rtems_status_code rtemsTask::resume() +{ + return set_status_code(rtems_task_resume(id)); +} + +const rtems_status_code rtemsTask::wake_after(const rtems_interval micro_secs) +{ + rtems_interval usecs = + micro_secs && (micro_secs < _TOD_Microseconds_per_tick) ? + _TOD_Microseconds_per_tick : micro_secs; + return set_status_code(rtems_task_wake_after(TOD_MICROSECONDS_TO_TICKS(usecs))); +} + +const rtems_status_code rtemsTask::wake_when(const rtems_time_of_day& tod) +{ + return set_status_code(rtems_task_wake_when((rtems_time_of_day*) &tod)); +} + +const rtems_status_code rtemsTask::get_priority(rtems_task_priority& priority) +{ + return set_status_code(rtems_task_set_priority(id, + RTEMS_CURRENT_PRIORITY, + &priority)); +} + +const rtems_status_code rtemsTask::set_priority(const rtems_task_priority priority) +{ + rtems_task_priority old_priority; + return set_status_code(rtems_task_set_priority(id, + priority, + &old_priority)); +} + +const rtems_status_code rtemsTask::set_priority(const rtems_task_priority priority, + rtems_task_priority& old_priority) +{ + return set_status_code(rtems_task_set_priority(id, + priority, + &old_priority)); +} + +const rtems_status_code rtemsTask::get_note(const rtems_unsigned32 notepad, + rtems_unsigned32& note) +{ + return set_status_code(rtems_task_get_note(id, notepad, ¬e)); +} + +const rtems_status_code rtemsTask::set_note(const rtems_unsigned32 notepad, + const rtems_unsigned32 note) +{ + return set_status_code(rtems_task_set_note(id, notepad, note)); +} + +void rtemsTask::body(rtems_task_argument ) +{ +} + +rtems_task rtemsTask::origin(rtems_task_argument argument) +{ + rtemsTask *task = (rtemsTask*) argument; + task->body(task->argument); +} diff --git a/c/src/lib/librtems++/rtemsTimer.cc b/c/src/lib/librtems++/rtemsTimer.cc new file mode 100644 index 0000000000..b87ffd5e80 --- /dev/null +++ b/c/src/lib/librtems++/rtemsTimer.cc @@ -0,0 +1,100 @@ +/* + ------------------------------------------------------------------------ + $Id$ + ------------------------------------------------------------------------ + + COPYRIGHT (c) 1997 + Objective Design Systems Ltd Pty (ODS) + All rights reserved (R) Objective Design Systems Ltd Pty + + The license and distribution terms for this file may be found in the + file LICENSE in this distribution or at + http://www.OARcorp.com/rtems/license.html. + + ------------------------------------------------------------------------ + + See header file. + + ------------------------------------------------------------------------ +*/ + +#include + +/* ---- + rtemsTimer +*/ + +rtemsTimer::rtemsTimer(const char* tname) + : name(0), + repeat(false), + id(0) +{ + strcpy(name_str, " "); + create(tname); +} + +rtemsTimer::rtemsTimer() + : name(0), + repeat(false), + id(0) +{ + strcpy(name_str, " "); +} + +rtemsTimer::~rtemsTimer() +{ + destroy(); +} + +void rtemsTimer::make_invalid() +{ + strcpy(name_str, " "); + name = 0; + id = 0; + repeat = false; +} +const rtems_status_code rtemsTimer::create(const char* tname) +{ + if (id) + return set_status_code(RTEMS_ILLEGAL_ON_SELF); + + strcpy(name_str, " "); + for (int c = 0; (c < 4) && (tname[c] != '\0'); c++) + name_str[c] = tname[c]; + name = rtems_build_name(name_str[0], + name_str[1], + name_str[2], + name_str[3]); + + set_status_code(rtems_timer_create(name, &id)); + + if (unsuccessful()) + { + make_invalid(); + } + + return last_status_code(); +} + +const rtems_status_code rtemsTimer::destroy() +{ + if (id) + { + set_status_code(rtems_timer_delete(id)); + make_invalid(); + } + else + set_status_code(RTEMS_NOT_OWNER_OF_RESOURCE); + + return last_status_code(); +} + +void rtemsTimer::common_handler(rtems_id , void *user_data) +{ + rtemsTimer *timer = (rtemsTimer*) user_data; + + if (timer->repeat) + timer->reset(); + + timer->triggered(); +} -- cgit v1.2.3