From 1ea7355d85e316aadfd90468b3e808bb3dc95ee9 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 16 Aug 2009 13:07:24 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1073 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/various/ch.hpp | 618 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 618 insertions(+) create mode 100644 os/various/ch.hpp (limited to 'os/various/ch.hpp') diff --git a/os/various/ch.hpp b/os/various/ch.hpp new file mode 100644 index 000000000..b13e8db6d --- /dev/null +++ b/os/various/ch.hpp @@ -0,0 +1,618 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ch.hpp + * @brief C++ wrapper classes and definitions. + * @addtogroup CPlusPlusLibrary + * @{ + */ + +#include + +#ifndef _CH_HPP_ +#define _CH_HPP_ + +namespace chibios_rt { + + /** + * @brief Class encapsulating the base system functionalities. + */ + class System { + public: + /** + * @brief ChibiOS/RT initialization. + * @details The system is initialized, the idle thread is spawned and the + * current instruction flow becomes the main thread with priority + * @p NORMALPRIO. + */ + static void Init(void); + + /** + * @brief Kernel lock. + * + * @note On some ports it is faster to invoke chSysLock() directly because + * inlining. + */ + static void Lock(void); + + /** + * @brief Kernel unlock. + * + * @note On some ports it is faster to invoke chSysUnlock() directly + * because inlining. + */ + static void Unlock(void); + + /** + * @brief Returns the system time as system ticks. + * + * @note the system tick time interval is implementation dependent. + */ + static systime_t GetTime(void); + }; + + /** + * @brief Timer class. + */ + class Timer { + public: + /** + * @brief Embedded @p VirtualTimer structure. + */ + struct ::VirtualTimer timer; + + /** + * @brief Starts the timer. + * + * @param time the time in system ticks + * @param vtfunc the timer callback function + * @param par the parameter for the callback function + * @note It must be called with the interrupts disabled. + * @note The associated function is invoked by an interrupt handler. + */ + void Set(systime_t time, vtfunc_t vtfunc, void *par); + + /** + * @brief Resets the timer. + * + * @note It must be called with the interrupts disabled. + * @note The timer MUST be active when this function is invoked. + */ + void Reset(); + + /** + * @brief Returns the timer status. + * + * @retval TRUE The timer is armed. + * @retval FALSE The timer already fired its callback. + */ + bool IsArmed(void); + }; + + /** + * @brief Base class for a ChibiOS/RT thread. + * @details The thread body is the virtual function @p Main(). + */ + class BaseThread { + public: + /** + * @brief Pointer to the system thread. + */ + ::Thread *thread_ref; + + /** + * @brief Thread constructor. + * @details The thread object is initialized and a system thread is + * started. + * + * @param workspace pointer to the workspace area + * @param wsize size of the workspace area + * @param prio thread priority + */ + BaseThread(void *workspace, size_t wsize, tprio_t prio); + + /** + * @brief Thread exit. + * + * @param msg the exit message + */ + static void Exit(msg_t msg); + +#if CH_USE_WAITEXIT + /** + * @brief Synchronization on Thread exit. + * + * @return the exit message from the thread + */ + msg_t Wait(void); +#endif /* CH_USE_WAITEXIT */ + + /** + * @brief Resumes the thread. + * @details The thread encapsulated into the object is resumed. + */ + void Resume(void); + + /** + * @brief Changes the thread priority. + * + * @param newprio the new priority level + */ + static void SetPriority(tprio_t newprio); + + /** + * @brief Requests thread termination. + * @details A termination flag is pended on the thread, it is thread + * responsibility to detect it and exit. + */ + void Terminate(void); + + /** + * @brief Suspends the thread execution for the specified number of + * system ticks. + * + * @param n the number of system ticks + */ + static void Sleep(systime_t n); + + /** + * @brief Suspends the thread execution until the specified time arrives. + * + * @param time the system time + */ + static void SleepUntil(systime_t time); + +#if CH_USE_MESSAGES + /** + * @brief Sends a message to the thread and returns the answer. + * + * @param tp the target thread + * @param msg the sent message + * @return The returned message. + */ + static msg_t SendMessage(::Thread *tp, msg_t msg); + + /** + * @brief Sends a message to the thread and returns the answer. + * + * @param msg the sent message + * @return The returned message. + */ + msg_t SendMessage(msg_t msg); + + /** + * @brief Waits for a message and returns it. + * + * @return The incoming message. + */ + static msg_t WaitMessage(void); + + /** + * @brief Returns an enqueued message or @p NULL. + * + * @return The incoming message. + * @retval NULL No incoming message. + */ + static msg_t GetMessage(void); + + /** + * @brief Releases the next message in queue with a reply. + * + * @param msg the answer message + */ + static void ReleaseMessage(msg_t msg); + + /** + * @brief Returns true if there is at least one message in queue. + * + * @retval TRUE A message is waiting in queue. + * @retval FALSE A message is not waiting in queue. + */ + static bool IsPendingMessage(void); +#endif /* CH_USE_MESSAGES */ + + /** + * @brief Thread body function. + * + * @return The exit message. + */ + virtual msg_t Main(void); + }; + + /** + * @brief Enhanced threads template class. + * @details This class introduces thread names and static working area + * allocation. + * + * @param N the working area size for the thread class + */ + template + class EnhancedThread : public BaseThread { + protected: + WORKING_AREA(wa, N); // Thread working area. + + public: + /** + * @brief The thread name. + */ + const char *name; + + /** + * @brief Full constructor. + * @details This constructor allows to set a priority level for the new + * thread. + * @param tname the name to be assigned to the thread + * @param prio the priority to be assigned to the thread + */ + EnhancedThread(const char *tname, tprio_t prio) : + BaseThread(wa, sizeof wa, prio) { + + name = tname; + } + + /** + * @brief Simplified constructor. + * @details This constructor allows to create a thread by simply + * specifying a name. In is assumed @p NORMALPRIO as initial priority. + * + * @param tname the name to be assigned to the thread + */ + EnhancedThread(const char *tname) : + BaseThread(wa, sizeof wa, NORMALPRIO) { + + name = tname; + } + }; + +#if CH_USE_SEMAPHORES + /** + * @brief Class encapsulating a semaphore. + */ + class Semaphore { + public: + /** + * @brief Embedded @p ::Semaphore structure. + */ + struct ::Semaphore sem; + + /** + * @brief Semaphore constructor. + * @details The embedded @p ::Semaphore structure is initialized. + * + * @param n the semaphore counter value, must be greater or equal to zero + */ + Semaphore(cnt_t n); + + /** + * @brief Resets a semaphore. + * + * @param n the new semaphore counter value, must be greater or equal to zero + */ + void Reset(cnt_t n); + + /** + * @brief Wait operation on the semaphore. + * + * @retval RDY_OK if the semaphore was signaled or not taken. + * @retval RDY_RESET if the semaphore was reset. + */ + msg_t Wait(void); + + /** + * @brief Wait operation on the semaphore with timeout. + * + * @param time the number of ticks before the operation fails + * @retval RDY_OK if the semaphore was signaled or not taken. + * @retval RDY_RESET if the semaphore was reset. + * @retval RDY_TIMEOUT if the semaphore was not signaled or reset within the + * specified timeout. + */ + msg_t WaitTimeout(systime_t time); + + /** + * @brief Signal operation on the semaphore. + * @details The semaphore is signaled, the next thread in queue, if any, + * is awakened. + */ + void Signal(void); + +#if CH_USE_SEMSW + /** + * @brief Atomic signal and wait operations. + * + * @param ssem pointer to a @p Semaphore to be signaled + * @param wsem pointer to a @p Semaphore to be wait on + * @retval RDY_OK if the semaphore was signaled or not taken. + * @retval RDY_RESET if the semaphore was reset. + */ + static msg_t SignalWait(Semaphore *ssem, Semaphore *wsem); +#endif /* CH_USE_SEMSW */ + }; +#endif /* CH_USE_SEMAPHORES */ + +#if CH_USE_MUTEXES + /** + * @brief Class encapsulating a mutex. + */ + class Mutex { + public: + /** + * @brief Embedded @p ::Mutex structure. + */ + struct ::Mutex mutex; + + /** + * @brief Mutex constructor. + * @details The embedded @p ::Mutex structure is initialized. + */ + Mutex(void); + + /** + * @brief Tries a lock operation on the mutex. + * @retval TRUE if the mutex was successfully acquired + * @retval FALSE if the lock attempt failed. + */ + bool TryLock(void); + + /** + * @brief Locks the mutex. + * @details Performs a lock operation on the mutex, if the mutex is + * already locked then the thread enters the mutex priority queue and + * waits. + */ + void Lock(void); + + /** + * @brief Unlocks the mutex. + * @details Performs an unlock operation on the mutex, the next waiting + * thread, if any, is resumed and locks the mutex. + */ + static void Unlock(void); + + /** + * @brief Unlocks all the mutexes owned by the invoking thread. + * @details This operation is MUCH MORE efficient than releasing + * the mutexes one by one and not just because the call overhead, this + * function does not have any overhead related to the priority inheritance + * mechanism. + */ + static void UnlockAll(void); + }; + +#if CH_USE_CONDVARS + /** + * @brief Class encapsulating a conditional variable. + */ + class CondVar { + public: + /** + * @brief Embedded @p ::CondVar structure. + */ + struct ::CondVar condvar; + + /** + * @brief CondVar constructor. + * @details The embedded @p ::CondVar structure is initialized. + */ + CondVar(void); + + /** + * @brief Signals the CondVar. + * @details The next thread waiting on the @p CondVar, if any, is awakened. + */ + void Signal(void); + + /** + * @brief Broadcasts the CondVar. + * @details All the threads waiting on the @p CondVar, if any, are awakened. + */ + void Broadcast(void); + + /** + * @brief Waits on the CondVar while releasing the controlling mutex. + * + * @return The wakep mode. + * @retval RDY_OK if the condvar was signaled using chCondSignal(). + * @retval RDY_RESET if the condvar was signaled using chCondBroadcast(). + */ + msg_t Wait(void); + +#if CH_USE_CONDVARS_TIMEOUT + /** + * @brief Waits on the CondVar while releasing the controlling mutex. + * + * @param time the number of ticks before the operation fails + * @return The wakep mode. + * @retval RDY_OK if the condvar was signaled using chCondSignal(). + * @retval RDY_RESET if the condvar was signaled using chCondBroadcast(). + * @retval RDY_TIMEOUT if the condvar was not signaled within the specified + * timeout. + */ + msg_t WaitTimeout(systime_t time); +#endif /* CH_USE_CONDVARS_TIMEOUT */ + }; +#endif /* CH_USE_CONDVARS */ +#endif /* CH_USE_MUTEXES */ + +#if CH_USE_EVENTS + /** + * @brief Class encapsulating an event source. + */ + class Event { + public: + /** + * @brief Embedded @p ::EventSource structure. + */ + struct ::EventSource event; + + /** + * @brief Event constructor. + * @details The embedded @p ::EventSource structure is initialized. + */ + Event(void); + + /** + * @brief Registers a listener on the event source. + * + * @param elp pointer to the @p EventListener structure + * @param eid numeric identifier assigned to the Event Listener + */ + void Register(EventListener *elp, eventid_t eid); + + /** + * @brief Registers an Event Listener on an Event Source. + * + * @param elp pointer to the @p EventListener structure + * @param emask the mask of event flags to be pended to the thread when the + * event source is broadcasted + * @note Multiple Event Listeners can specify the same bits to be pended. + */ + void RegisterMask(EventListener *elp, eventmask_t emask); + + /** + * @brief Unregisters a listener. + * @details The specified listeners is no more signaled by the event + * source. + * + * @param elp the listener to be unregistered + */ + void Unregister(EventListener *elp); + + /** + * @brief Broadcasts an event. + * @details All the listeners registered on the event source are signaled. + */ + void Broadcast(void); + + /** + * @brief Clears specified events from the pending events mask. + * + * @param mask the events to be cleared + * @return The pending events that were cleared. + */ + static eventmask_t Clear(eventmask_t mask); + + /** + * @brief Makes an events mask pending in the current thread. + * @details This functon is @b much faster than using @p Broadcast(). + * + * @param mask the events to be pended + * @return The current pending events mask. + */ + static eventmask_t Pend(eventmask_t mask); + + /** + * @brief Invokes the event handlers associated with a mask. + * + * @param mask mask of the events to be dispatched + * @param handlers an array of @p evhandler_t. The array must be + * have indexes from zero up the higher registered event + * identifier. + */ + static void Dispatch(const evhandler_t handlers[], eventmask_t mask); + + /** + * @brief Waits for a single event. + * @details A pending event among those specified in @p ewmask is selected, + * cleared and its mask returned. + * + * @param ewmask mask of the events that the function should wait for, + * @p ALL_EVENTS enables all the events + * @return The mask of the lowest id served and cleared event. + * @note One and only one event is served in the function, the one with the + * lowest event id. The function is meant to be invoked into a loop in + * order to serve all the pending events.
+ * This means that Event Listeners with a lower event identifier have + * an higher priority. + */ + static eventmask_t WaitOne(eventmask_t ewmask); + + /** + * @brief Waits for any of the specified events. + * @details The function waits for any event among those specified in + * @p ewmask to become pending then the events are cleared and returned. + * + * @param ewmask mask of the events that the function should wait for, + * @p ALL_EVENTS enables all the events + * @return The mask of the served and cleared events. + */ + static eventmask_t WaitAny(eventmask_t ewmask); + + /** + * @brief Waits for all the specified event flags then clears them. + * @details The function waits for all the events specified in @p ewmask + * to become pending then the events are cleared and returned. + * + * @param ewmask mask of the event ids that the function should wait for + * @return The mask of the served and cleared events. + */ + static eventmask_t WaitAll(eventmask_t ewmask); + +#if CH_USE_EVENTS_TIMEOUT + /** + * @brief Waits for a single event. + * @details A pending event among those specified in @p ewmask is selected, + * cleared and its mask returned. + * @param ewmask mask of the events that the function should wait for, + * @p ALL_EVENTS enables all the events + * @param time the number of ticks before the operation timouts + * @return The mask of the lowest id served and cleared event. + * @retval 0 if the specified timeout expired. + * @note One and only one event is served in the function, the one with the + * lowest event id. The function is meant to be invoked into a loop in + * order to serve all the pending events.
+ * This means that Event Listeners with a lower event identifier have + * an higher priority. + */ + static eventmask_t WaitOneTimeout(eventmask_t ewmask, systime_t time); + + /** + * @brief Waits for any of the specified events. + * @details The function waits for any event among those specified in + * @p ewmask to become pending then the events are cleared and returned. + * + * @param ewmask mask of the events that the function should wait for, + * @p ALL_EVENTS enables all the events + * @param time the number of ticks before the operation timouts + * @return The mask of the served and cleared events. + * @retval 0 if the specified timeout expired. + */ + static eventmask_t WaitAnyTimeout(eventmask_t ewmask, systime_t time); + + /** + * @brief Waits for all the specified event flags then clears them. + * @details The function waits for all the events specified in @p ewmask + * to become pending then the events are cleared and returned. + * + * @param ewmask mask of the event ids that the function should wait for + * @param time the number of ticks before the operation timouts + * @return The mask of the served and cleared events. + * @retval 0 if the specified timeout expired. + */ + static eventmask_t WaitAllTimeout(eventmask_t ewmask, systime_t time); + +#endif /* CH_USE_EVENTS_TIMEOUT */ + }; +#endif /* CH_USE_EVENTS */ +} + +#endif /* _CH_HPP_ */ + +/** @} */ -- cgit v1.2.3