/* 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 . */ /** * @addtogroup CPlusPlusLibrary * @{ */ #include #ifndef _CH_HPP_ #define _CH_HPP_ namespace chibios_rt { /** * Class encapsulating the base system functionalities. */ class System { public: /** * ChibiOS/RT initialization. * 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); /** * Disables interrupts. * @note On some ports it is faster to invoke chSysLock() directly because * inlining. */ static void Lock(void); /** * Enables interrupts. * @note On some ports it is faster to invoke chSysUnlock() directly * because inlining. */ static void Unlock(void); /** * Returns the system time as system ticks. * @note the system tick time interval is implementation dependent. */ static systime_t GetTime(void); }; /** * Timer class. */ class Timer { public: /** * Embedded @p VirtualTimer structure. */ struct ::VirtualTimer timer; /** * 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); /** * 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(); /** * Returns the timer status. * @retval TRUE The timer is armed. * @retval FALSE The timer already fired its callback. */ bool IsArmed(void); }; /** * Base class for a ChibiOS/RT thread, the thread body is the virtual * function @p Main(). */ class BaseThread { public: /** * Pointer to the system thread. */ ::Thread *thread_ref; /** * Thread constructor. * 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); /** * Thread exit. * @param msg the exit message */ static void Exit(msg_t msg); #ifdef CH_USE_WAITEXIT /** * Synchronization on Thread exit. * @return the exit message from the thread */ msg_t Wait(void); #endif /* CH_USE_WAITEXIT */ /** * Resumes the thread. * The thread encapsulated into the object is resumed. */ void Resume(void); /** * Change thread priority. * @param newprio the new priority level */ static void SetPriority(tprio_t newprio); /** * Requests thread termination. * A termination flag is pended on the thread, it is thread responsibility * to detect it and exit. */ void Terminate(void); /** * Suspends the thread execution for the specified number of system ticks. * @param n the number of system ticks */ static void Sleep(systime_t n); /** * Suspends the thread execution until the specified time arrives. * @param time the system time */ static void SleepUntil(systime_t time); #ifdef CH_USE_MESSAGES /** * 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); /** * 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); /** * Waits for a message and returns it. * @return The incoming message. */ static msg_t WaitMessage(void); /** * Returns an enqueued message or @p NULL. * @return The incoming message. * @retval NULL No incoming message. */ static msg_t GetMessage(void); /** * Releases the next message in queue with a reply. * @param msg the answer message */ static void ReleaseMessage(msg_t msg); /** * 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 */ /** * Thread body function. * @return The exit message. */ virtual msg_t Main(void); }; /** * Enhanced threads template class. 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: /** * The thread name. */ const char *name; /** * Full constructor. It allows to set a priority level for the new thread * and specify the special option flags. * @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; } /** * Simplified constructor, it allows to create a thread by simply * specifying a name. In is assumed @p NORMALPRIO as initial priority * and no special option flags. * @param tname the name to be assigned to the thread */ EnhancedThread(const char *tname) : BaseThread(wa, sizeof wa, NORMALPRIO) { name = tname; } }; #ifdef CH_USE_SEMAPHORES /** * Class encapsulating a @p Semaphore. */ class Semaphore { public: /** * Embedded @p Semaphore structure. */ struct ::Semaphore sem; /** * Semaphore constructor. * The embedded @p ::Semaphore structure is initialized. * @param n the semaphore counter value, must be greater or equal to zero */ Semaphore(cnt_t n); /** * Resets a semaphore. * @param n the new semaphore counter value, must be greater or equal to zero */ void Reset(cnt_t n); /** * 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); #ifdef CH_USE_SEMAPHORES_TIMEOUT /** * 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); #endif /* CH_USE_SEMAPHORES_TIMEOUT */ /** * Signal operation on the semaphore. * The semaphore is signaled, the next thread in queue, if any, is awakened. */ void Signal(void); #ifdef CH_USE_SEMSW /** * 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 */ #ifdef CH_USE_MUTEXES /** * Class encapsulating a @p Mutex. */ class Mutex { public: /** * Embedded @p Mutex structure. */ struct ::Mutex mutex; /** * Mutex constructor. * The embedded @p ::Mutex structure is initialized. */ Mutex(void); /** * 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); /** * Locks the mutex. * 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); /** * Unlocks the mutex. * Performs an unlock operation on the mutex, the next waiting thread, if * any, is resumed and locks the mutex. */ static void Unlock(void); /** * Unlocks all the mutexes owned by the invoking thread. * 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); }; #ifdef CH_USE_CONDVARS /** * Class encapsulating a @p CondVar. */ class CondVar { public: /** * Embedded @p CondVar structure. */ struct ::CondVar condvar; /** * CondVar constructor. * The embedded @p ::CondVar structure is initialized. */ CondVar(void); /** * Signals the CondVar. * The next thread waiting on the @p CondVar, if any, is awakened. */ void Signal(void); /** * Broadcasts the CondVar. * All the threads waiting on the @p CondVar, if any, are awakened. */ void Broadcast(void); /** * 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); #ifdef CH_USE_CONDVARS_TIMEOUT /** * 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 */ #ifdef CH_USE_EVENTS /** * Class encapsulating an @p EventSource. */ class Event { public: /** * Embedded @p EventSource structure. */ struct ::EventSource event; /** * Event constructor. * The embedded @p ::EventSource structure is initialized. */ Event(void); /** * 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); /** * 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); /** * Unregisters a listener. * The specified listeners is no more signaled by the event source. * @param elp the listener to be unregistered */ void Unregister(EventListener *elp); /** * Broadcasts an event. * All the listeners registered on the event source are signaled. */ void Broadcast(void); /** * 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); /** * Makes an events mask pending in the current thread, this 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); /** * 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); /** * 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); /** * Waits for any of the specified events. * 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); /** * Waits for all the specified event flags then clears them. * 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); #ifdef CH_USE_EVENTS_TIMEOUT /** * Waits for a single event. * 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); /** * Waits for any of the specified events. * 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); /** * Waits for all the specified event flags then clears them. * 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_ */ /** @} */