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/librtems++/README | 266 +++++++++++++++++++ c/src/librtems++/include/rtems++/rtemsEvent.h | 127 +++++++++ c/src/librtems++/include/rtems++/rtemsInterrupt.h | 105 ++++++++ .../librtems++/include/rtems++/rtemsMessageQueue.h | 176 +++++++++++++ c/src/librtems++/include/rtems++/rtemsSemaphore.h | 145 +++++++++++ c/src/librtems++/include/rtems++/rtemsStatusCode.h | 57 ++++ c/src/librtems++/include/rtems++/rtemsTask.h | 171 ++++++++++++ c/src/librtems++/include/rtems++/rtemsTaskMode.h | 210 +++++++++++++++ c/src/librtems++/include/rtems++/rtemsTimer.h | 145 +++++++++++ c/src/librtems++/src/Makefile.in | 49 ++++ c/src/librtems++/src/rtemsEvent.cc | 75 ++++++ c/src/librtems++/src/rtemsInterrupt.cc | 110 ++++++++ c/src/librtems++/src/rtemsMessageQueue.cc | 164 ++++++++++++ c/src/librtems++/src/rtemsSemaphore.cc | 174 +++++++++++++ c/src/librtems++/src/rtemsStatusCode.cc | 77 ++++++ c/src/librtems++/src/rtemsTask.cc | 287 +++++++++++++++++++++ c/src/librtems++/src/rtemsTimer.cc | 100 +++++++ 17 files changed, 2438 insertions(+) create mode 100644 c/src/librtems++/README create mode 100644 c/src/librtems++/include/rtems++/rtemsEvent.h create mode 100644 c/src/librtems++/include/rtems++/rtemsInterrupt.h create mode 100644 c/src/librtems++/include/rtems++/rtemsMessageQueue.h create mode 100644 c/src/librtems++/include/rtems++/rtemsSemaphore.h create mode 100644 c/src/librtems++/include/rtems++/rtemsStatusCode.h create mode 100644 c/src/librtems++/include/rtems++/rtemsTask.h create mode 100644 c/src/librtems++/include/rtems++/rtemsTaskMode.h create mode 100644 c/src/librtems++/include/rtems++/rtemsTimer.h create mode 100644 c/src/librtems++/src/Makefile.in create mode 100644 c/src/librtems++/src/rtemsEvent.cc create mode 100644 c/src/librtems++/src/rtemsInterrupt.cc create mode 100644 c/src/librtems++/src/rtemsMessageQueue.cc create mode 100644 c/src/librtems++/src/rtemsSemaphore.cc create mode 100644 c/src/librtems++/src/rtemsStatusCode.cc create mode 100644 c/src/librtems++/src/rtemsTask.cc create mode 100644 c/src/librtems++/src/rtemsTimer.cc (limited to 'c/src/librtems++') diff --git a/c/src/librtems++/README b/c/src/librtems++/README new file mode 100644 index 0000000000..65b0eb980e --- /dev/null +++ b/c/src/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/librtems++/include/rtems++/rtemsEvent.h b/c/src/librtems++/include/rtems++/rtemsEvent.h new file mode 100644 index 0000000000..3cc19eeb32 --- /dev/null +++ b/c/src/librtems++/include/rtems++/rtemsEvent.h @@ -0,0 +1,127 @@ +/* + ------------------------------------------------------------------------ + $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. + + ------------------------------------------------------------------------ + + rtemsEvent class. + + This class allows the user to send and receive RTEMS events to a task. + + ------------------------------------------------------------------------ */ + +#if !defined(_rtemsEvent_h_) +#define _rtemsEvent_h_ + +#include +#include + +/* ---- + rtemsEvent +*/ + +class rtemsEvent + : public rtemsStatusCode +{ +public: + // attribute a task can have + + enum WaitMode { wait = RTEMS_WAIT, + no_wait = RTEMS_NO_WAIT}; + enum Condition { any = RTEMS_EVENT_ANY, + all = RTEMS_EVENT_ALL}; + + // only the first 4 characters of the name are taken + + // connect to a task + rtemsEvent(const char* name, rtems_unsigned32 node = RTEMS_SEARCH_ALL_NODES); + + // copy and default constructors + rtemsEvent(const rtemsEvent& event); + rtemsEvent(); + + virtual ~rtemsEvent(); + + // connect to an existing task object, will not be the owner + const rtemsEvent& operator=(const rtemsEvent& event); + virtual const rtems_status_code connect(const char *name, + const rtems_unsigned32 node = RTEMS_SEARCH_ALL_NODES); + + // send an event + inline const rtems_status_code send(const rtems_id task, + const rtems_event_set events); + inline const rtems_status_code send(const rtemsTask& task, + const rtems_event_set events) ; + inline const rtems_status_code send(const rtems_event_set events); + + // receive an event, can block a task if no events waiting + inline const rtems_status_code receive(const rtems_event_set event_in, + rtems_event_set& event_out, + const rtems_interval micro_secs = 0, + const WaitMode wait = wait, + const Condition condition = any); + + // object id, and name + const rtems_id task_id_is() const { return id; } + const rtems_name task_name_is() const { return name; } + +private: + // task name + rtems_name name; + + // the rtems task id, object handle + rtems_id id; + +}; + +const rtems_status_code rtemsEvent::send(const rtems_id task, + const rtems_event_set events) +{ + set_status_code(rtems_event_send(task, events)); + return last_status_code(); +} + +const rtems_status_code rtemsEvent::send(const rtemsTask& task, + const rtems_event_set events) +{ + set_status_code(rtems_event_send(task.id_is(), events)); + return last_status_code(); +} + +const rtems_status_code rtemsEvent::send(const rtems_event_set events) +{ + set_status_code(rtems_event_send(id, events)); + return last_status_code(); +} + +const rtems_status_code rtemsEvent::receive(const rtems_event_set event_in, + rtems_event_set& event_out, + const rtems_interval micro_secs, + const WaitMode wait, + const Condition condition) +{ + rtems_interval usecs = + micro_secs && (micro_secs < _TOD_Microseconds_per_tick) ? + _TOD_Microseconds_per_tick : micro_secs; + set_status_code(rtems_event_receive(event_in, + wait | condition, + TOD_MICROSECONDS_TO_TICKS(usecs), + &event_out)); + return last_status_code(); +} + +#endif // _rtemsEvent_h_ + + + + + diff --git a/c/src/librtems++/include/rtems++/rtemsInterrupt.h b/c/src/librtems++/include/rtems++/rtemsInterrupt.h new file mode 100644 index 0000000000..0dc6a20d5e --- /dev/null +++ b/c/src/librtems++/include/rtems++/rtemsInterrupt.h @@ -0,0 +1,105 @@ +/* + ------------------------------------------------------------------------ + $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. + + ------------------------------------------------------------------------ + + rtemsInterrupt class. + + This class catches an interrupt and passes control to the user's + derived class throught the handler method. + + The interrupt is released back to the previous handler when this + object destructs. + + The old handler can be chained to after the interrupt is + caught. Watch the stack usage! + + More than one instance of this class can catch the same vector. The + application will have to chain to the other objects if required. 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. + + The isr catch extends the documented return codes with : + + RTEMS_RESOURCE_IN_USE = interrupt already caught + + ------------------------------------------------------------------------ */ + +#if !defined(_rtemsInterrupt_h_) +#define _rtemsInterrupt_h_ + +#include + +/* ---- + rtemsInterrupt +*/ + +class rtemsInterrupt + : public rtemsStatusCode +{ +public: + rtemsInterrupt(); + virtual ~rtemsInterrupt(); + + // catch the interrupt + virtual const rtems_status_code isr_catch(const rtems_vector_number vector); + + // release the interrupt back to the previous handle + virtual const rtems_status_code release(); + + // the old handler + const rtems_isr_entry old_isr_handler() const { return old_handler; } + +protected: + + // called after the interrupt is caught and it goes off + virtual void handler() = 0; + + // chain to the previous handler, + inline void chain() const; + +private: + const rtemsInterrupt& operator=(const rtemsInterrupt& ); + Interrupt(const rtemsInterrupt& ); + + // the vector caught + rtems_vector_number vector; + + // true when the interrupt is caught + bool caught; + + // returned when catching the interrupt + rtems_isr_entry old_handler; + + // old interrupt table entry + rtemsInterrupt *old_interrupt; + + // common handler to redirect the interrupts + static void redirector(rtems_vector_number vector); +}; + +void rtemsInterrupt::chain() const +{ + if (old_interrupt) + old_interrupt->handler(); + else if (old_handler) + ((void(*)()) old_handler)(); +} + +#endif // _rtemsInterrupt_h_ + + + + + diff --git a/c/src/librtems++/include/rtems++/rtemsMessageQueue.h b/c/src/librtems++/include/rtems++/rtemsMessageQueue.h new file mode 100644 index 0000000000..910c7279f7 --- /dev/null +++ b/c/src/librtems++/include/rtems++/rtemsMessageQueue.h @@ -0,0 +1,176 @@ +/* + ------------------------------------------------------------------------ + $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. + + ------------------------------------------------------------------------ + + rtemsMessageQueue class. + + This class allows the user to create a RTEMS message queue, or to + access and manage an already existing message queue. + + The first constructor with the message queue parameters creates a + RTEMS message queue object. The destructor of this object also + deletes the message queue object. The last status code should be + checked after construction to see if the create completed + successfully. + + The second constructor connects to an existing message queue + object. The last status code should be checked after construction to + see if the message queue existed. + + The third constructor is a copy constructor. Connects to an existing + object which is in scope. + + The fourth constructor allows for the message queue to be created + after construction, or to connect to a message queue later. + + ------------------------------------------------------------------------ */ + +#if !defined(_rtemsMessageQueue_h_) +#define _rtemsMessageQueue_h_ + +#include + +/* ---- + rtemsMessageQueue +*/ + +class rtemsMessageQueue + : public rtemsStatusCode +{ +public: + // attribute a message queue can have + enum WaitMode { wait_by_fifo = RTEMS_FIFO, + wait_by_priority = RTEMS_PRIORITY }; + enum Scope { local = RTEMS_LOCAL, + global = RTEMS_GLOBAL }; + + // only the first 4 characters of the name are taken + + // creates a message queue + rtemsMessageQueue(const char* name, + const rtems_unsigned32 count, + const rtems_unsigned32 max_message_size, + const WaitMode wait_mode = wait_by_fifo, + const Scope scope = local); + + // connects to a message queue + rtemsMessageQueue(const char *name, const rtems_unsigned32 node = RTEMS_SEARCH_ALL_NODES); + + // copy and default constructors + rtemsMessageQueue(const rtemsMessageQueue& message_queue); + rtemsMessageQueue(); + + // only the creator's destructor will delete the actual object + virtual ~rtemsMessageQueue(); + + // create or destroy (delete) the message queue + virtual const rtems_status_code create(const char* name, + const rtems_unsigned32 count, + const rtems_unsigned32 max_message_size, + const WaitMode wait_mode = wait_by_fifo, + const Scope scope = local); + virtual const rtems_status_code destroy(); + + // connect to an existing message queue object, will not be the owner + const rtemsMessageQueue& operator=(const rtemsMessageQueue& message_queue); + virtual const rtems_status_code connect(const char *name, + const rtems_unsigned32 node = RTEMS_SEARCH_ALL_NODES); + + // send a message of size from the buffer + inline const rtems_status_code send(const void *buffer, + const rtems_unsigned32 size); + inline const rtems_status_code urgent(const void *buffer, + const rtems_unsigned32 size); + inline const rtems_status_code broadcast(const void *buffer, + const rtems_unsigned32 size, + rtems_unsigned32& count); + + // receive a message of size, the timeout is in micro-secs + inline const rtems_status_code receive(const void *buffer, + rtems_unsigned32& size, + rtems_interval micro_secs = RTEMS_NO_TIMEOUT, + bool wait = true); + + // flush a message queue, returning the number of messages dropped + inline const rtems_status_code flush(rtems_unsigned32& size); + + // object id, and name + const rtems_id id_is() const { return id; } + const rtems_name name_is() const { return name; } + const char *name_string() const { return name_str; } + +private: + + // make this object reference an invalid RTEMS object + void make_invalid(); + + // message queue name + rtems_name name; + char name_str[5]; + + // owner, true if this object owns the message queue + // will delete the message queue when it destructs + bool owner; + + // the rtems id, object handle + rtems_id id; +}; + +const rtems_status_code rtemsMessageQueue::send(const void *buffer, + const rtems_unsigned32 size) +{ + return set_status_code(rtems_message_queue_send(id, (void*) buffer, size)); +} + +const rtems_status_code rtemsMessageQueue::urgent(const void *buffer, + const rtems_unsigned32 size) +{ + return set_status_code(rtems_message_queue_urgent(id, (void*) buffer, size)); +} + +const rtems_status_code rtemsMessageQueue::broadcast(const void *buffer, + const rtems_unsigned32 size, + rtems_unsigned32& count) +{ + return set_status_code(rtems_message_queue_broadcast(id, + (void*) buffer, + size, + &count)); +} + +const rtems_status_code rtemsMessageQueue::receive(const void *buffer, + rtems_unsigned32& size, + rtems_interval micro_secs, + bool wait) +{ + rtems_interval usecs = + micro_secs && (micro_secs < _TOD_Microseconds_per_tick) ? + _TOD_Microseconds_per_tick : micro_secs; + return set_status_code(rtems_message_queue_receive(id, + (void*) buffer, + &size, + wait ? RTEMS_WAIT : RTEMS_NO_WAIT, + TOD_MICROSECONDS_TO_TICKS(usecs))); +} + +const rtems_status_code rtemsMessageQueue::flush(rtems_unsigned32& count) +{ + return set_status_code(rtems_message_queue_flush(id, &count)); +} + +#endif // _rtemsMessageQueue_h_ + + + + diff --git a/c/src/librtems++/include/rtems++/rtemsSemaphore.h b/c/src/librtems++/include/rtems++/rtemsSemaphore.h new file mode 100644 index 0000000000..9d4fdbeb58 --- /dev/null +++ b/c/src/librtems++/include/rtems++/rtemsSemaphore.h @@ -0,0 +1,145 @@ +/* + ------------------------------------------------------------------------ + $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. + + ------------------------------------------------------------------------ + + rtemsSemaphore class. + + This class allows the user to create a RTEMS semaphore, or to use an + already existing semaphore. The type of semaphore is decitated by + the constructor used. + + The first constructor with the semaphore parameters creates a RTEMS + semaphore object. The destructor of this object also deletes the + semaphore object. The last status code should be checked after + construction to see if the semaphore create was successfull. + + The second constructor connects to an existing. The last status code + should be checked after construction to see if the semaphore + existed. + + The third constructor is a copy constructor. Connects to an existing + object which is in scope. + + ------------------------------------------------------------------------ */ + +#if !defined(_rtemsSemaphore_h_) +#define _rtemsSemaphore_h_ + +#include + +/* ---- + rtemsSemaphore +*/ + +class rtemsSemaphore + : public rtemsStatusCode +{ +public: + // attribute a semaphore can have + enum WaitMode { wait_by_fifo = RTEMS_FIFO, + wait_by_priority = RTEMS_PRIORITY }; + enum Type { binary = RTEMS_BINARY_SEMAPHORE, + counting = RTEMS_COUNTING_SEMAPHORE }; + enum Priority { no_priority_inherit = RTEMS_NO_INHERIT_PRIORITY, + inherit_priority = RTEMS_INHERIT_PRIORITY }; + enum Ceiling { no_priority_ceiling = RTEMS_NO_PRIORITY_CEILING, + priority_ceiling = RTEMS_PRIORITY_CEILING }; + enum Scope { local = RTEMS_LOCAL, + global = RTEMS_GLOBAL }; + + // only the first 4 characters of the name are taken, + // the counter must be set to 1 for binary semaphores + + // create a semaphore object + rtemsSemaphore(const char* name, + const Scope scope = local, + const rtems_unsigned32 counter = 1, + const WaitMode wait_mode = wait_by_fifo, + const Type type = binary, + const Priority priority = no_priority_inherit, + const Ceiling ceiling = no_priority_ceiling, + const rtems_task_priority priority_ceiling = 0); + + // connect to an existing semaphore object by name + rtemsSemaphore(const char *name, const rtems_unsigned32 node); + + // attach this object to an other objects semaphore + rtemsSemaphore(const rtemsSemaphore& semaphore); + rtemsSemaphore(); + + // only the creator's destructor will delete the actual object + virtual ~rtemsSemaphore(); + + // create or destroy (delete) a semaphore + virtual const rtems_status_code create(const char* name, + const Scope scope = local, + const rtems_unsigned32 counter = 1, + const WaitMode wait_mode = wait_by_fifo, + const Type type = binary, + const Priority priority = no_priority_inherit, + const Ceiling ceiling = no_priority_ceiling, + const rtems_task_priority priority_ceiling = 0); + virtual const rtems_status_code destroy(); + + // connect to an existing semaphore object, will not be the owner + const rtemsSemaphore& operator=(const rtemsSemaphore& semaphore); + virtual const rtems_status_code connect(const char *name, rtems_unsigned32 node); + + // obtain the semaphore, timeout is in micro-seconds + inline const rtems_status_code obtain(bool wait = true, + const rtems_unsigned32 micro_secs = RTEMS_NO_TIMEOUT); + + // release the semaphore, blocks threads eligble + inline const rtems_status_code release(); + + // object id, and name + const rtems_id id_is() const { return id; } + const rtems_name name_is() const { return name; } + const char *name_string() const { return name_str; } + +private: + + // make the object reference no valid RTEMS object + void make_invalid(); + + // semaphore name + rtems_name name; + char name_str[5]; + + // owner, true if this object owns the semaphore + // will delete the semaphore when it destructs + bool owner; + + // the rtems id, object handle + rtems_id id; +}; + +const rtems_status_code rtemsSemaphore::obtain(const bool wait, + const rtems_unsigned32 micro_secs) +{ + rtems_interval usecs = + micro_secs && (micro_secs < _TOD_Microseconds_per_tick) ? + _TOD_Microseconds_per_tick : micro_secs; + return + set_status_code(rtems_semaphore_obtain(id, + wait ? RTEMS_WAIT : RTEMS_NO_WAIT, + TOD_MICROSECONDS_TO_TICKS(usecs))); +} + +const rtems_status_code rtemsSemaphore::release(void) +{ + return set_status_code(rtems_semaphore_release(id)); +} + +#endif // _rtemsSemaphore_h_ diff --git a/c/src/librtems++/include/rtems++/rtemsStatusCode.h b/c/src/librtems++/include/rtems++/rtemsStatusCode.h new file mode 100644 index 0000000000..fee230868b --- /dev/null +++ b/c/src/librtems++/include/rtems++/rtemsStatusCode.h @@ -0,0 +1,57 @@ +/* + ------------------------------------------------------------------------ + $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. + + ------------------------------------------------------------------------ + + rtemsStatusCode controls and manages status codes from the RTEMS kernel. + + ------------------------------------------------------------------------ +*/ + +#if !defined(_rtemsStatusCode_h_) +#define _rtemsStatusCode_h_ + +#include + +/* ---- + rtemsStatusCode +*/ + +class rtemsStatusCode +{ +public: + + rtemsStatusCode() { last_status = RTEMS_NOT_CONFIGURED; } + + const bool successful() { return last_status == RTEMS_SUCCESSFUL; } + const bool unsuccessful() { return last_status != RTEMS_SUCCESSFUL; } + + // return the last status code + const rtems_status_code last_status_code() { return last_status; } + + // return the last status as a string + const char *last_status_string(); + + const char *status_string(rtems_status_code status_code); + +protected: + const rtems_status_code set_status_code(const rtems_status_code status) + { return (last_status = status); } + +private: + + // public at the moment, this might change + rtems_status_code last_status; +}; + +#endif // _rtemsStatusCode_h_ diff --git a/c/src/librtems++/include/rtems++/rtemsTask.h b/c/src/librtems++/include/rtems++/rtemsTask.h new file mode 100644 index 0000000000..08156428fb --- /dev/null +++ b/c/src/librtems++/include/rtems++/rtemsTask.h @@ -0,0 +1,171 @@ +/* + ------------------------------------------------------------------------ + $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. + + ------------------------------------------------------------------------ + + rtemsTask class. + + This class allows the user to create a RTEMS task, or to access and + manage an already existing task. + + The first constructor with the task parameters creates a RTEMS task + object. The destructor of this object also deletes the task + object. The last status code should be checked after construction to + see if the create completed successfully. + + The second constructor connects to an existing task object. The last + status code should be checked after construction to see if the + task existed. + + The third constructor is a copy constructor. Connects to an existing + object which is in scope. + + The RTEMS id is set to self in the default construction. + + The creation of the task object can be defered until after + construction. This allows for static task objects to be created. + + RTEMS should be initialised before static constructors run, how-ever + threads will will not. You need to watch the start-order. + + A task object can change state from an owner of a task to being + connected to a task. + + Task objects connected to another task do not receive notification + when the task connected to changes state. + + The sleep methods operate on the current thread not the task + reference by this object. + + Mode control is through the rtemsTaskMode class. + + The rtemsTask class reserved notepad register 31. + + ------------------------------------------------------------------------ */ + +#if !defined(_rtemsTask_h_) +#define _rtemsTask_h_ + +#include + +/* ---- + rtemsTask +*/ + +class rtemsTask + : public rtemsStatusCode +{ +public: + enum FloatingPoint { fpoff = RTEMS_NO_FLOATING_POINT, + fpon = RTEMS_FLOATING_POINT }; + enum Scope { local = RTEMS_LOCAL, + global = RTEMS_GLOBAL }; + + // only the first 4 characters of the name are taken + + // creates a task + rtemsTask(const char* name, + const rtems_task_priority initial_priority, + const rtems_unsigned32 stack_size, + const rtems_mode preemption = RTEMS_NO_PREEMPT, + const rtems_mode timeslice = RTEMS_NO_TIMESLICE, + const rtems_mode asr = RTEMS_NO_ASR, + const rtems_interrupt_level interrupt_level = 0, + const FloatingPoint floating_point = fpoff, + const Scope scope = local); + + // connects to a task + rtemsTask(const char *name, const rtems_unsigned32 node = RTEMS_SEARCH_ALL_NODES); + + // copy and default constructors + rtemsTask(const rtemsTask& task); + rtemsTask(); + + // only the creator's destructor will delete the actual object + virtual ~rtemsTask(); + + // create or destroy (delete) the task + virtual const rtems_status_code create(const char* name, + const rtems_task_priority initial_priority, + const rtems_unsigned32 stack_size, + const rtems_mode preemption = RTEMS_NO_PREEMPT, + const rtems_mode timeslice = RTEMS_NO_TIMESLICE, + const rtems_mode asr = RTEMS_NO_ASR, + const rtems_interrupt_level interrupt_level = 0, + const FloatingPoint floating_point = fpoff, + const Scope scope = local); + virtual const rtems_status_code destroy(); + + // connect to an existing task object, will not be the owner + const rtemsTask& operator=(const rtemsTask& task); + virtual const rtems_status_code connect(const char *name, + const rtems_unsigned32 node = RTEMS_SEARCH_ALL_NODES); + + // run control + virtual const rtems_status_code start(const rtems_task_argument argument); + virtual const rtems_status_code restart(const rtems_task_argument argument); + virtual const rtems_status_code suspend(); + virtual const rtems_status_code resume(); + + // sleep control, the timeout is in micro-seconds + virtual const rtems_status_code wake_after(const rtems_interval micro_secs); + virtual const rtems_status_code wake_when(const rtems_time_of_day& tod); + + // priority control + const rtems_status_code get_priority(rtems_task_priority& priority); + const rtems_status_code set_priority(const rtems_task_priority priority); + const rtems_status_code set_priority(const rtems_task_priority priority, + rtems_task_priority& old_priority); + + // notepad control + const rtems_status_code get_note(const rtems_unsigned32 notepad, + rtems_unsigned32& note); + const rtems_status_code set_note(const rtems_unsigned32 notepad, + const rtems_unsigned32 note); + + // object id, and name + const rtems_id id_is() const { return id; } + const rtems_name name_is() const { return name; } + const char *name_string() const { return name_str; } + +protected: + + // task entry point + virtual void body(rtems_task_argument argument); + +private: + + // make the object to point to RTEMS_SELF + void make_self(); + + // task name + rtems_name name; + char name_str[5]; + + // owner, true if this object owns the task + // will delete the task when it destructs + bool owner; + + // the rtems id, object handle + rtems_id id; + + // the argument for the task, this class uses the actual argument + // passed to RTEMS + rtems_task_argument argument; + + // common entry point to the task + static rtems_task origin(rtems_task_argument argument); +}; + +#endif // _rtemsTask_h_ + diff --git a/c/src/librtems++/include/rtems++/rtemsTaskMode.h b/c/src/librtems++/include/rtems++/rtemsTaskMode.h new file mode 100644 index 0000000000..6d32897cc0 --- /dev/null +++ b/c/src/librtems++/include/rtems++/rtemsTaskMode.h @@ -0,0 +1,210 @@ +/* + ------------------------------------------------------------------------ + $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. + + ------------------------------------------------------------------------ + + rtemsTaskMode class. + + This class allows the user to query or change the mode of an RTEMS + task. + + This 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. + + 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. + + ------------------------------------------------------------------------ */ + +#if !defined(_rtemsTaskMode_h_) +#define _rtemsTaskMode_h_ + +#include + +/* ---- + rtemsTaskMode +*/ + +class rtemsTaskMode + : public rtemsStatusCode +{ +public: + + rtemsTaskMode() {}; + + // group mode control, OR the values together + inline const rtems_status_code get_mode(rtems_mode& mode); + inline const rtems_status_code set_mode(const rtems_mode mode, + const rtems_mode mask); + inline const rtems_status_code set_mode(const rtems_mode mode, + const rtems_mode mask, + rtems_mode& old_mode); + + // preemption control + inline const rtems_status_code get_preemption_state(rtems_mode& preemption); + inline const rtems_status_code set_preemption_state(const rtems_mode preemption); + inline const rtems_status_code set_preemption_state(const rtems_mode preemption, + rtems_mode& old_preemption); + inline const boolean preemption_set(const rtems_mode preemption); + + // timeslice control + inline const rtems_status_code get_timeslice_state(rtems_mode& timeslice); + inline const rtems_status_code set_timeslice_state(const rtems_mode timeslice); + inline const rtems_status_code set_timeslice_state(const rtems_mode timeslice, + rtems_mode& old_timeslice); + inline const boolean timeslice_set(const rtems_mode preemption); + + // async-sub-routine control + inline const rtems_status_code get_asr_state(rtems_mode& asr); + inline const rtems_status_code set_asr_state(const rtems_mode asr); + inline const rtems_status_code set_asr_state(const rtems_mode asr, + rtems_mode& old_asr); + inline const boolean asr_set(const rtems_mode preemption); + + // interrupt mask control + inline const rtems_status_code get_interrupt_level(rtems_interrupt_level& level); + inline const rtems_status_code set_interrupt_level(const rtems_interrupt_level level); + inline const rtems_status_code set_interrupt_level(const rtems_interrupt_level level, + rtems_interrupt_level& old_level); +}; + +const rtems_status_code rtemsTaskMode::get_mode(rtems_mode& mode) +{ + return set_status_code(rtems_task_mode(0, RTEMS_CURRENT_MODE, &mode)); +} + +const rtems_status_code rtemsTaskMode::set_mode(const rtems_mode mode, + const rtems_mode mask) +{ + rtems_mode old_mode; + return set_status_code(rtems_task_mode(mode, mask, &old_mode)); +} + +const rtems_status_code rtemsTaskMode::set_mode(const rtems_mode mode, + const rtems_mode mask, + rtems_mode& old_mode) +{ + return set_status_code(rtems_task_mode(mode, mask, &old_mode)); +} + +const rtems_status_code rtemsTaskMode::get_preemption_state(rtems_mode& preemption) +{ + set_status_code(rtems_task_mode(0, RTEMS_CURRENT_MODE, &preemption)); + preemption &= RTEMS_PREEMPT_MASK; + return last_status_code(); +} + +const rtems_status_code rtemsTaskMode::set_preemption_state(const rtems_mode preemption) +{ + rtems_mode old_mode; + return set_status_code(rtems_task_mode(preemption, RTEMS_PREEMPT_MASK, &old_mode)); +} + +const rtems_status_code rtemsTaskMode::set_preemption_state(const rtems_mode preemption, + rtems_mode& old_preemption) +{ + set_status_code(rtems_task_mode(preemption, RTEMS_PREEMPT_MASK, &old_preemption)); + old_preemption &= RTEMS_PREEMPT_MASK; + return last_status_code(); +} + +const boolean rtemsTaskMode::preemption_set(const rtems_mode preemption) +{ + return (preemption & RTEMS_PREEMPT_MASK) ? false : true; +} + +const rtems_status_code rtemsTaskMode::get_timeslice_state(rtems_mode& timeslice) +{ + set_status_code(rtems_task_mode(0, RTEMS_CURRENT_MODE, ×lice)); + timeslice &= RTEMS_TIMESLICE_MASK; + return last_status_code(); +} + +const rtems_status_code rtemsTaskMode::set_timeslice_state(const rtems_mode timeslice) +{ + rtems_mode old_mode; + return set_status_code(rtems_task_mode(timeslice, RTEMS_TIMESLICE_MASK, &old_mode)); +} + +const rtems_status_code rtemsTaskMode::set_timeslice_state(const rtems_mode timeslice, + rtems_mode& old_timeslice) +{ + set_status_code(rtems_task_mode(timeslice, RTEMS_TIMESLICE_MASK, &old_timeslice)); + old_timeslice &= RTEMS_TIMESLICE_MASK; + return last_status_code(); +} + +const boolean rtemsTaskMode::timeslice_set(const rtems_mode timeslice) +{ + return (timeslice & RTEMS_TIMESLICE_MASK) ? true : false; +} + +const rtems_status_code rtemsTaskMode::get_asr_state(rtems_mode& asr) +{ + set_status_code(rtems_task_mode(0, RTEMS_CURRENT_MODE, &asr)); + asr &= RTEMS_ASR_MASK; + return last_status_code(); +} + +const rtems_status_code rtemsTaskMode::set_asr_state(const rtems_mode asr) +{ + rtems_mode old_mode; + return set_status_code(rtems_task_mode(asr, RTEMS_ASR_MASK, &old_mode)); +} + +const rtems_status_code rtemsTaskMode::set_asr_state(const rtems_mode asr, + rtems_mode& old_asr) +{ + set_status_code(rtems_task_mode(asr, RTEMS_ASR_MASK, &old_asr)); + old_asr &= RTEMS_ASR_MASK; + return last_status_code(); +} + +const boolean rtemsTaskMode::asr_set(const rtems_mode asr) +{ + return (asr & RTEMS_ASR_MASK) ? true : false; +} + +const rtems_status_code rtemsTaskMode::get_interrupt_level(rtems_interrupt_level& level) +{ + rtems_mode mode; + set_status_code(rtems_task_mode(0, RTEMS_CURRENT_MODE, &mode)); + level = mode & RTEMS_INTERRUPT_MASK; + return last_status_code(); +} + +const rtems_status_code rtemsTaskMode::set_interrupt_level(const rtems_interrupt_level level) +{ + rtems_mode old_mode; + return set_status_code(rtems_task_mode(level, RTEMS_INTERRUPT_MASK, &old_mode)); +} + +const rtems_status_code rtemsTaskMode::set_interrupt_level(rtems_interrupt_level level, + rtems_interrupt_level& old_level) +{ + set_status_code(rtems_task_mode(level, RTEMS_INTERRUPT_MASK, &old_level)); + old_level = old_level & RTEMS_INTERRUPT_MASK; + return last_status_code(); +} + +#endif // _rtemsTaskMode_h_ + + + + diff --git a/c/src/librtems++/include/rtems++/rtemsTimer.h b/c/src/librtems++/include/rtems++/rtemsTimer.h new file mode 100644 index 0000000000..43401bab73 --- /dev/null +++ b/c/src/librtems++/include/rtems++/rtemsTimer.h @@ -0,0 +1,145 @@ +/* + ------------------------------------------------------------------------ + $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. + + ------------------------------------------------------------------------ + + rtemsTimer class. + + This class allows the user to create a RTEMS timer. + + The trigger method is called when the timer expires. The method is + called using the thread which calls the RTEMS 'rtems_clock_tick' + method. + + Timers are always local to a node. + + ------------------------------------------------------------------------ */ + +#if !defined(_rtemsTimer_h_) +#define _rtemsTimer_h_ + +#include + +/* ---- + rtemsTimer +*/ + +class rtemsTimer + : public rtemsStatusCode +{ +public: + // only the first 4 characters of the name are taken, + + // create a timer object + rtemsTimer(const char* name); + rtemsTimer(); + + // destroies the actual object + virtual ~rtemsTimer(); + + // create or destroy (delete) the timer + virtual const rtems_status_code create(const char* name); + virtual const rtems_status_code destroy(); + + // timer control + inline const rtems_status_code fire_after(const rtems_interval micro_secs); + inline const rtems_status_code repeat_fire_at(const rtems_interval micro_secs); + inline const rtems_status_code fire_when(const rtems_time_of_day& when); + + inline const rtems_status_code cancel(); + inline const rtems_status_code reset(); + + // object id, and name + const rtems_id id_is() const { return id; } + const rtems_name name_is() const { return name; } + const char *name_string() const { return name_str; } + +protected: + + // triggered method is called when the timer fires + virtual void triggered() = 0; + +private: + // not permitted + rtemsTimer(const rtemsTimer& timer); + rtemsTimer& operator=(const rtemsTimer& timer); + + // make this object reference an invalid RTEMS object + void make_invalid(); + + // semaphore name + rtems_name name; + char name_str[5]; + + // repeat true restart the timer when it fires + bool repeat; + + // the rtems id, object handle + rtems_id id; + + // common timer handler + static void common_handler(rtems_id id, void *user_data); +}; + +const rtems_status_code rtemsTimer::fire_after(const rtems_interval micro_secs) +{ + repeat = false; + rtems_interval usecs = + micro_secs && (micro_secs < _TOD_Microseconds_per_tick) ? + _TOD_Microseconds_per_tick : micro_secs; + return set_status_code(rtems_timer_fire_after(id, + TOD_MICROSECONDS_TO_TICKS(usecs), + common_handler, + this)); +} + +const rtems_status_code rtemsTimer::repeat_fire_at(const rtems_interval micro_secs) +{ + repeat = true; + rtems_interval usecs = + micro_secs && (micro_secs < _TOD_Microseconds_per_tick) ? + _TOD_Microseconds_per_tick : micro_secs; + return set_status_code(rtems_timer_fire_after(id, + TOD_MICROSECONDS_TO_TICKS(usecs), + common_handler, + this)); +} + +const rtems_status_code rtemsTimer::fire_when(const rtems_time_of_day& when) +{ + return set_status_code(rtems_timer_fire_when(id, + (rtems_time_of_day*) &when, + common_handler, + this)); +} + +const rtems_status_code rtemsTimer::cancel() +{ + repeat = false; + return set_status_code(rtems_timer_cancel(id)); +} + +const rtems_status_code rtemsTimer::reset() +{ + return set_status_code(rtems_timer_reset(id)); +} + +#endif // _rtemsTimer_h_ + + + + + + + + diff --git a/c/src/librtems++/src/Makefile.in b/c/src/librtems++/src/Makefile.in new file mode 100644 index 0000000000..5e67e02110 --- /dev/null +++ b/c/src/librtems++/src/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/librtems++/src/rtemsEvent.cc b/c/src/librtems++/src/rtemsEvent.cc new file mode 100644 index 0000000000..a917f32836 --- /dev/null +++ b/c/src/librtems++/src/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/librtems++/src/rtemsInterrupt.cc b/c/src/librtems++/src/rtemsInterrupt.cc new file mode 100644 index 0000000000..c445807c35 --- /dev/null +++ b/c/src/librtems++/src/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/librtems++/src/rtemsMessageQueue.cc b/c/src/librtems++/src/rtemsMessageQueue.cc new file mode 100644 index 0000000000..1978e1c6ec --- /dev/null +++ b/c/src/librtems++/src/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/librtems++/src/rtemsSemaphore.cc b/c/src/librtems++/src/rtemsSemaphore.cc new file mode 100644 index 0000000000..1e0d3de472 --- /dev/null +++ b/c/src/librtems++/src/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/librtems++/src/rtemsStatusCode.cc b/c/src/librtems++/src/rtemsStatusCode.cc new file mode 100644 index 0000000000..e8e3f965ba --- /dev/null +++ b/c/src/librtems++/src/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/librtems++/src/rtemsTask.cc b/c/src/librtems++/src/rtemsTask.cc new file mode 100644 index 0000000000..d90c8f669f --- /dev/null +++ b/c/src/librtems++/src/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/librtems++/src/rtemsTimer.cc b/c/src/librtems++/src/rtemsTimer.cc new file mode 100644 index 0000000000..b87ffd5e80 --- /dev/null +++ b/c/src/librtems++/src/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