ChibiOS/RT Architecture - Reference Manual - Guides |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. 00003 00004 This file is part of ChibiOS/RT. 00005 00006 ChibiOS/RT is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 ChibiOS/RT is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 --- 00020 00021 A special exception to the GPL can be applied should you wish to distribute 00022 a combined work that includes ChibiOS/RT, without being obliged to provide 00023 the source code for any proprietary components. See the file exception.txt 00024 for full details of how and when the exception can be applied. 00025 */ 00026 00027 /** 00028 * @file ch.hpp 00029 * @brief C++ wrapper classes and definitions. 00030 * @addtogroup cpp_library 00031 * @{ 00032 */ 00033 00034 #include <ch.h> 00035 00036 #ifndef _CH_HPP_ 00037 #define _CH_HPP_ 00038 00039 namespace chibios_rt { 00040 00041 /** 00042 * @brief Class encapsulating the base system functionalities. 00043 */ 00044 class System { 00045 public: 00046 /** 00047 * @brief ChibiOS/RT initialization. 00048 * @details The system is initialized, the idle thread is spawned and the 00049 * current instruction flow becomes the main thread with priority 00050 * @p NORMALPRIO. 00051 */ 00052 static void Init(void); 00053 00054 /** 00055 * @brief Kernel lock. 00056 * 00057 * @note On some ports it is faster to invoke chSysLock() directly because 00058 * inlining. 00059 */ 00060 static void Lock(void); 00061 00062 /** 00063 * @brief Kernel unlock. 00064 * 00065 * @note On some ports it is faster to invoke chSysUnlock() directly 00066 * because inlining. 00067 */ 00068 static void Unlock(void); 00069 00070 /** 00071 * @brief Returns the system time as system ticks. 00072 * 00073 * @note the system tick time interval is implementation dependent. 00074 */ 00075 static systime_t GetTime(void); 00076 }; 00077 00078 /** 00079 * @brief Timer class. 00080 */ 00081 class Timer { 00082 public: 00083 /** 00084 * @brief Embedded @p VirtualTimer structure. 00085 */ 00086 struct ::VirtualTimer timer; 00087 00088 /** 00089 * @brief Starts the timer. 00090 * 00091 * @param time the time in system ticks 00092 * @param vtfunc the timer callback function 00093 * @param par the parameter for the callback function 00094 * @note It must be called with the interrupts disabled. 00095 * @note The associated function is invoked by an interrupt handler. 00096 */ 00097 void Set(systime_t time, vtfunc_t vtfunc, void *par); 00098 00099 /** 00100 * @brief Resets the timer. 00101 * 00102 * @note It must be called with the interrupts disabled. 00103 * @note The timer MUST be active when this function is invoked. 00104 */ 00105 void Reset(); 00106 00107 /** 00108 * @brief Returns the timer status. 00109 * 00110 * @retval TRUE The timer is armed. 00111 * @retval FALSE The timer already fired its callback. 00112 */ 00113 bool IsArmed(void); 00114 }; 00115 00116 /** 00117 * @brief Base class for a ChibiOS/RT thread. 00118 * @details The thread body is the virtual function @p Main(). 00119 */ 00120 class BaseThread { 00121 public: 00122 /** 00123 * @brief Pointer to the system thread. 00124 */ 00125 ::Thread *thread_ref; 00126 00127 /** 00128 * @brief Thread constructor. 00129 * @details The thread object is initialized and a system thread is 00130 * started. 00131 * 00132 * @param workspace pointer to the workspace area 00133 * @param wsize size of the workspace area 00134 * @param prio thread priority 00135 */ 00136 BaseThread(void *workspace, size_t wsize, tprio_t prio); 00137 00138 /** 00139 * @brief Thread exit. 00140 * 00141 * @param msg the exit message 00142 */ 00143 static void Exit(msg_t msg); 00144 00145 #if CH_USE_WAITEXIT 00146 /** 00147 * @brief Synchronization on Thread exit. 00148 * 00149 * @return the exit message from the thread 00150 */ 00151 msg_t Wait(void); 00152 #endif /* CH_USE_WAITEXIT */ 00153 00154 /** 00155 * @brief Resumes the thread. 00156 * @details The thread encapsulated into the object is resumed. 00157 */ 00158 void Resume(void); 00159 00160 /** 00161 * @brief Changes the thread priority. 00162 * 00163 * @param newprio the new priority level 00164 */ 00165 static void SetPriority(tprio_t newprio); 00166 00167 /** 00168 * @brief Requests thread termination. 00169 * @details A termination flag is pended on the thread, it is thread 00170 * responsibility to detect it and exit. 00171 */ 00172 void Terminate(void); 00173 00174 /** 00175 * @brief Suspends the thread execution for the specified number of 00176 * system ticks. 00177 * 00178 * @param n the number of system ticks 00179 */ 00180 static void Sleep(systime_t n); 00181 00182 /** 00183 * @brief Suspends the thread execution until the specified time arrives. 00184 * 00185 * @param time the system time 00186 */ 00187 static void SleepUntil(systime_t time); 00188 00189 #if CH_USE_MESSAGES 00190 /** 00191 * @brief Sends a message to the thread and returns the answer. 00192 * 00193 * @param tp the target thread 00194 * @param msg the sent message 00195 * @return The returned message. 00196 */ 00197 static msg_t SendMessage(::Thread *tp, msg_t msg); 00198 00199 /** 00200 * @brief Sends a message to the thread and returns the answer. 00201 * 00202 * @param msg the sent message 00203 * @return The returned message. 00204 */ 00205 msg_t SendMessage(msg_t msg); 00206 00207 /** 00208 * @brief Waits for a message and returns it. 00209 * 00210 * @return The incoming message. 00211 */ 00212 static msg_t WaitMessage(void); 00213 00214 /** 00215 * @brief Returns an enqueued message or @p NULL. 00216 * 00217 * @return The incoming message. 00218 * @retval NULL No incoming message. 00219 */ 00220 static msg_t GetMessage(void); 00221 00222 /** 00223 * @brief Releases the next message in queue with a reply. 00224 * 00225 * @param msg the answer message 00226 */ 00227 static void ReleaseMessage(msg_t msg); 00228 00229 /** 00230 * @brief Returns true if there is at least one message in queue. 00231 * 00232 * @retval TRUE A message is waiting in queue. 00233 * @retval FALSE A message is not waiting in queue. 00234 */ 00235 static bool IsPendingMessage(void); 00236 #endif /* CH_USE_MESSAGES */ 00237 00238 /** 00239 * @brief Thread body function. 00240 * 00241 * @return The exit message. 00242 */ 00243 virtual msg_t Main(void); 00244 }; 00245 00246 /** 00247 * @brief Enhanced threads template class. 00248 * @details This class introduces thread names and static working area 00249 * allocation. 00250 * 00251 * @param N the working area size for the thread class 00252 */ 00253 template <int N> 00254 class EnhancedThread : public BaseThread { 00255 protected: 00256 WORKING_AREA(wa, N); // Thread working area. 00257 00258 public: 00259 /** 00260 * @brief The thread name. 00261 */ 00262 const char *name; 00263 00264 /** 00265 * @brief Full constructor. 00266 * @details This constructor allows to set a priority level for the new 00267 * thread. 00268 * @param tname the name to be assigned to the thread 00269 * @param prio the priority to be assigned to the thread 00270 */ 00271 EnhancedThread(const char *tname, tprio_t prio) : 00272 BaseThread(wa, sizeof wa, prio) { 00273 00274 name = tname; 00275 } 00276 00277 /** 00278 * @brief Simplified constructor. 00279 * @details This constructor allows to create a thread by simply 00280 * specifying a name. In is assumed @p NORMALPRIO as initial priority. 00281 * 00282 * @param tname the name to be assigned to the thread 00283 */ 00284 EnhancedThread(const char *tname) : 00285 BaseThread(wa, sizeof wa, NORMALPRIO) { 00286 00287 name = tname; 00288 } 00289 }; 00290 00291 #if CH_USE_SEMAPHORES 00292 /** 00293 * @brief Class encapsulating a semaphore. 00294 */ 00295 class Semaphore { 00296 public: 00297 /** 00298 * @brief Embedded @p ::Semaphore structure. 00299 */ 00300 struct ::Semaphore sem; 00301 00302 /** 00303 * @brief Semaphore constructor. 00304 * @details The embedded @p ::Semaphore structure is initialized. 00305 * 00306 * @param n the semaphore counter value, must be greater or equal to zero 00307 */ 00308 Semaphore(cnt_t n); 00309 00310 /** 00311 * @brief Resets a semaphore. 00312 * 00313 * @param n the new semaphore counter value, must be greater or equal to zero 00314 */ 00315 void Reset(cnt_t n); 00316 00317 /** 00318 * @brief Wait operation on the semaphore. 00319 * 00320 * @retval RDY_OK if the semaphore was signaled or not taken. 00321 * @retval RDY_RESET if the semaphore was reset. 00322 */ 00323 msg_t Wait(void); 00324 00325 /** 00326 * @brief Wait operation on the semaphore with timeout. 00327 * 00328 * @param time the number of ticks before the operation fails 00329 * @retval RDY_OK if the semaphore was signaled or not taken. 00330 * @retval RDY_RESET if the semaphore was reset. 00331 * @retval RDY_TIMEOUT if the semaphore was not signaled or reset within the 00332 * specified timeout. 00333 */ 00334 msg_t WaitTimeout(systime_t time); 00335 00336 /** 00337 * @brief Signal operation on the semaphore. 00338 * @details The semaphore is signaled, the next thread in queue, if any, 00339 * is awakened. 00340 */ 00341 void Signal(void); 00342 00343 #if CH_USE_SEMSW 00344 /** 00345 * @brief Atomic signal and wait operations. 00346 * 00347 * @param ssem pointer to a @p Semaphore to be signaled 00348 * @param wsem pointer to a @p Semaphore to be wait on 00349 * @retval RDY_OK if the semaphore was signaled or not taken. 00350 * @retval RDY_RESET if the semaphore was reset. 00351 */ 00352 static msg_t SignalWait(Semaphore *ssem, Semaphore *wsem); 00353 #endif /* CH_USE_SEMSW */ 00354 }; 00355 #endif /* CH_USE_SEMAPHORES */ 00356 00357 #if CH_USE_MUTEXES 00358 /** 00359 * @brief Class encapsulating a mutex. 00360 */ 00361 class Mutex { 00362 public: 00363 /** 00364 * @brief Embedded @p ::Mutex structure. 00365 */ 00366 struct ::Mutex mutex; 00367 00368 /** 00369 * @brief Mutex constructor. 00370 * @details The embedded @p ::Mutex structure is initialized. 00371 */ 00372 Mutex(void); 00373 00374 /** 00375 * @brief Tries a lock operation on the mutex. 00376 * @retval TRUE if the mutex was successfully acquired 00377 * @retval FALSE if the lock attempt failed. 00378 */ 00379 bool TryLock(void); 00380 00381 /** 00382 * @brief Locks the mutex. 00383 * @details Performs a lock operation on the mutex, if the mutex is 00384 * already locked then the thread enters the mutex priority queue and 00385 * waits. 00386 */ 00387 void Lock(void); 00388 00389 /** 00390 * @brief Unlocks the mutex. 00391 * @details Performs an unlock operation on the mutex, the next waiting 00392 * thread, if any, is resumed and locks the mutex. 00393 */ 00394 static void Unlock(void); 00395 00396 /** 00397 * @brief Unlocks all the mutexes owned by the invoking thread. 00398 * @details This operation is <b>MUCH MORE</b> efficient than releasing 00399 * the mutexes one by one and not just because the call overhead, this 00400 * function does not have any overhead related to the priority inheritance 00401 * mechanism. 00402 */ 00403 static void UnlockAll(void); 00404 }; 00405 00406 #if CH_USE_CONDVARS 00407 /** 00408 * @brief Class encapsulating a conditional variable. 00409 */ 00410 class CondVar { 00411 public: 00412 /** 00413 * @brief Embedded @p ::CondVar structure. 00414 */ 00415 struct ::CondVar condvar; 00416 00417 /** 00418 * @brief CondVar constructor. 00419 * @details The embedded @p ::CondVar structure is initialized. 00420 */ 00421 CondVar(void); 00422 00423 /** 00424 * @brief Signals the CondVar. 00425 * @details The next thread waiting on the @p CondVar, if any, is awakened. 00426 */ 00427 void Signal(void); 00428 00429 /** 00430 * @brief Broadcasts the CondVar. 00431 * @details All the threads waiting on the @p CondVar, if any, are awakened. 00432 */ 00433 void Broadcast(void); 00434 00435 /** 00436 * @brief Waits on the CondVar while releasing the controlling mutex. 00437 * 00438 * @return The wakep mode. 00439 * @retval RDY_OK if the condvar was signaled using chCondSignal(). 00440 * @retval RDY_RESET if the condvar was signaled using chCondBroadcast(). 00441 */ 00442 msg_t Wait(void); 00443 00444 #if CH_USE_CONDVARS_TIMEOUT 00445 /** 00446 * @brief Waits on the CondVar while releasing the controlling mutex. 00447 * 00448 * @param time the number of ticks before the operation fails 00449 * @return The wakep mode. 00450 * @retval RDY_OK if the condvar was signaled using chCondSignal(). 00451 * @retval RDY_RESET if the condvar was signaled using chCondBroadcast(). 00452 * @retval RDY_TIMEOUT if the condvar was not signaled within the specified 00453 * timeout. 00454 */ 00455 msg_t WaitTimeout(systime_t time); 00456 #endif /* CH_USE_CONDVARS_TIMEOUT */ 00457 }; 00458 #endif /* CH_USE_CONDVARS */ 00459 #endif /* CH_USE_MUTEXES */ 00460 00461 #if CH_USE_EVENTS 00462 /** 00463 * @brief Class encapsulating an event source. 00464 */ 00465 class Event { 00466 public: 00467 /** 00468 * @brief Embedded @p ::EventSource structure. 00469 */ 00470 struct ::EventSource event; 00471 00472 /** 00473 * @brief Event constructor. 00474 * @details The embedded @p ::EventSource structure is initialized. 00475 */ 00476 Event(void); 00477 00478 /** 00479 * @brief Registers a listener on the event source. 00480 * 00481 * @param elp pointer to the @p EventListener structure 00482 * @param eid numeric identifier assigned to the Event Listener 00483 */ 00484 void Register(EventListener *elp, eventid_t eid); 00485 00486 /** 00487 * @brief Registers an Event Listener on an Event Source. 00488 * 00489 * @param elp pointer to the @p EventListener structure 00490 * @param emask the mask of event flags to be pended to the thread when the 00491 * event source is broadcasted 00492 * @note Multiple Event Listeners can specify the same bits to be pended. 00493 */ 00494 void RegisterMask(EventListener *elp, eventmask_t emask); 00495 00496 /** 00497 * @brief Unregisters a listener. 00498 * @details The specified listeners is no more signaled by the event 00499 * source. 00500 * 00501 * @param elp the listener to be unregistered 00502 */ 00503 void Unregister(EventListener *elp); 00504 00505 /** 00506 * @brief Broadcasts an event. 00507 * @details All the listeners registered on the event source are signaled. 00508 */ 00509 void Broadcast(void); 00510 00511 /** 00512 * @brief Clears specified events from the pending events mask. 00513 * 00514 * @param mask the events to be cleared 00515 * @return The pending events that were cleared. 00516 */ 00517 static eventmask_t Clear(eventmask_t mask); 00518 00519 /** 00520 * @brief Makes an events mask pending in the current thread. 00521 * @details This functon is @b much faster than using @p Broadcast(). 00522 * 00523 * @param mask the events to be pended 00524 * @return The current pending events mask. 00525 */ 00526 static eventmask_t Pend(eventmask_t mask); 00527 00528 /** 00529 * @brief Invokes the event handlers associated with a mask. 00530 * 00531 * @param mask mask of the events to be dispatched 00532 * @param handlers an array of @p evhandler_t. The array must be 00533 * have indexes from zero up the higher registered event 00534 * identifier. 00535 */ 00536 static void Dispatch(const evhandler_t handlers[], eventmask_t mask); 00537 00538 /** 00539 * @brief Waits for a single event. 00540 * @details A pending event among those specified in @p ewmask is selected, 00541 * cleared and its mask returned. 00542 * 00543 * @param ewmask mask of the events that the function should wait for, 00544 * @p ALL_EVENTS enables all the events 00545 * @return The mask of the lowest id served and cleared event. 00546 * @note One and only one event is served in the function, the one with the 00547 * lowest event id. The function is meant to be invoked into a loop in 00548 * order to serve all the pending events.<br> 00549 * This means that Event Listeners with a lower event identifier have 00550 * an higher priority. 00551 */ 00552 static eventmask_t WaitOne(eventmask_t ewmask); 00553 00554 /** 00555 * @brief Waits for any of the specified events. 00556 * @details The function waits for any event among those specified in 00557 * @p ewmask to become pending then the events are cleared and returned. 00558 * 00559 * @param ewmask mask of the events that the function should wait for, 00560 * @p ALL_EVENTS enables all the events 00561 * @return The mask of the served and cleared events. 00562 */ 00563 static eventmask_t WaitAny(eventmask_t ewmask); 00564 00565 /** 00566 * @brief Waits for all the specified event flags then clears them. 00567 * @details The function waits for all the events specified in @p ewmask 00568 * to become pending then the events are cleared and returned. 00569 * 00570 * @param ewmask mask of the event ids that the function should wait for 00571 * @return The mask of the served and cleared events. 00572 */ 00573 static eventmask_t WaitAll(eventmask_t ewmask); 00574 00575 #if CH_USE_EVENTS_TIMEOUT 00576 /** 00577 * @brief Waits for a single event. 00578 * @details A pending event among those specified in @p ewmask is selected, 00579 * cleared and its mask returned. 00580 * @param ewmask mask of the events that the function should wait for, 00581 * @p ALL_EVENTS enables all the events 00582 * @param time the number of ticks before the operation timouts 00583 * @return The mask of the lowest id served and cleared event. 00584 * @retval 0 if the specified timeout expired. 00585 * @note One and only one event is served in the function, the one with the 00586 * lowest event id. The function is meant to be invoked into a loop in 00587 * order to serve all the pending events.<br> 00588 * This means that Event Listeners with a lower event identifier have 00589 * an higher priority. 00590 */ 00591 static eventmask_t WaitOneTimeout(eventmask_t ewmask, systime_t time); 00592 00593 /** 00594 * @brief Waits for any of the specified events. 00595 * @details The function waits for any event among those specified in 00596 * @p ewmask to become pending then the events are cleared and returned. 00597 * 00598 * @param ewmask mask of the events that the function should wait for, 00599 * @p ALL_EVENTS enables all the events 00600 * @param time the number of ticks before the operation timouts 00601 * @return The mask of the served and cleared events. 00602 * @retval 0 if the specified timeout expired. 00603 */ 00604 static eventmask_t WaitAnyTimeout(eventmask_t ewmask, systime_t time); 00605 00606 /** 00607 * @brief Waits for all the specified event flags then clears them. 00608 * @details The function waits for all the events specified in @p ewmask 00609 * to become pending then the events are cleared and returned. 00610 * 00611 * @param ewmask mask of the event ids that the function should wait for 00612 * @param time the number of ticks before the operation timouts 00613 * @return The mask of the served and cleared events. 00614 * @retval 0 if the specified timeout expired. 00615 */ 00616 static eventmask_t WaitAllTimeout(eventmask_t ewmask, systime_t time); 00617 00618 #endif /* CH_USE_EVENTS_TIMEOUT */ 00619 }; 00620 #endif /* CH_USE_EVENTS */ 00621 } 00622 00623 #endif /* _CH_HPP_ */ 00624 00625 /** @} */