Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
qk.h
00001 ////////////////////////////////////////////////////////////////////////////// 00002 // Product: QK/C++ platform-independent public interface 00003 // Last Updated for Version: 4.0.03 00004 // Date of the Last Update: Dec 26, 2008 00005 // 00006 // Q u a n t u m L e a P s 00007 // --------------------------- 00008 // innovating embedded systems 00009 // 00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved. 00011 // 00012 // This software may be distributed and modified under the terms of the GNU 00013 // General Public License version 2 (GPL) as published by the Free Software 00014 // Foundation and appearing in the file GPL.TXT included in the packaging of 00015 // this file. Please note that GPL Section 2[b] requires that all works based 00016 // on this software must also be made publicly available under the terms of 00017 // the GPL ("Copyleft"). 00018 // 00019 // Alternatively, this software may be distributed and modified under the 00020 // terms of Quantum Leaps commercial licenses, which expressly supersede 00021 // the GPL and are specifically designed for licensees interested in 00022 // retaining the proprietary status of their code. 00023 // 00024 // Contact information: 00025 // Quantum Leaps Web site: http://www.quantum-leaps.com 00026 // e-mail: info@quantum-leaps.com 00027 ////////////////////////////////////////////////////////////////////////////// 00028 #ifndef qk_h 00029 #define qk_h 00030 00031 /// \file 00032 /// \ingroup qep qf qk qs 00033 /// \brief QK/C++ platform-independent public interface. 00034 /// 00035 /// This header file must be included directly or indirectly 00036 /// in all modules (*.cpp files) that use QK/C++. 00037 00038 #include "qequeue.h" // The QK kernel uses the native QF event queue 00039 #include "qmpool.h" // The QK kernel uses the native QF memory pool 00040 #include "qpset.h" // The QK kernel uses the native QF priority set 00041 00042 00043 ////////////////////////////////////////////////////////////////////////////// 00044 // QF configuration for QK 00045 00046 /// \brief This macro defines the type of the event queue used for the 00047 /// active objects. 00048 /// 00049 /// \note This is just an example of the macro definition. Typically, you need 00050 /// to define it in the specific QF port file (qf_port.h). In case of QK, 00051 /// which always depends on the native QF queue, this macro is defined at the 00052 /// level of the platform-independent interface qk.h. 00053 #define QF_EQUEUE_TYPE QEQueue 00054 00055 #if defined(QK_TLS) || defined(QK_EXT_SAVE) 00056 /// \brief This macro defines the type of the OS-Object used for blocking 00057 /// the native QF event queue when the queue is empty 00058 /// 00059 /// In QK, the OS object is used to hold the per-thread flags, which might 00060 /// be used, for example, to rembember the thread attributes (e.g., 00061 /// if the thread uses a floating point co-processor). The OS object value 00062 /// is set on per-thread basis in QActive::start(). Later, the extended 00063 /// context switch macros (QK_EXT_SAVE() and QK_EXT_RESTORE()) might use 00064 /// the per-thread flags to determine what kind of extended context switch 00065 /// this particular thread needs (e.g., the thread might not be using the 00066 /// coprocessor or might be using a different one). 00067 #define QF_OS_OBJECT_TYPE uint8_t 00068 00069 /// \brief This macro defines the type of the thread handle used for the 00070 /// active objects. 00071 /// 00072 /// The thread type in QK is the pointer to the thread-local storage (TLS) 00073 /// This thread-local storage can be set on per-thread basis in 00074 /// QActive::start(). Later, the QK scheduler, passes the pointer to the 00075 /// thread-local storage to the macro #QK_TLS. 00076 #define QF_THREAD_TYPE void * 00077 #endif /* QK_TLS || QK_EXT_SAVE */ 00078 00079 #if (QF_MAX_ACTIVE <= 8) 00080 extern QPSet8 volatile QK_readySet_; ///< ready set of QK 00081 #else 00082 extern QPSet64 volatile QK_readySet_; ///< ready set of QK 00083 #endif 00084 00085 extern uint8_t volatile QK_currPrio_; ///< current task/interrupt priority 00086 extern uint8_t volatile QK_intNest_; ///< interrupt nesting level 00087 00088 // QK active object queue implementation ..................................... 00089 00090 /// \brief Platform-dependent macro defining how QF should block the calling 00091 /// task when the QF native queue is empty 00092 /// 00093 /// \note This is just an example of #QACTIVE_EQUEUE_WAIT_ for the QK-port 00094 /// of QF. QK never activates a task that has no events to process, so in this 00095 /// case the macro asserts that the queue is not empty. In other QF ports you 00096 // need to define the macro appropriately for the underlying kernel/OS you're 00097 /// using. 00098 #define QACTIVE_EQUEUE_WAIT_(me_) \ 00099 Q_ASSERT((me_)->m_eQueue.m_frontEvt != (QEvent *)0) 00100 00101 /// \brief Platform-dependent macro defining how QF should signal the 00102 /// active object task that an event has just arrived. 00103 /// 00104 /// The macro is necessary only when the native QF event queue is used. 00105 /// The signaling of task involves unblocking the task if it is blocked. 00106 /// 00107 /// \note #QACTIVE_EQUEUE_SIGNAL_ is called from a critical section. 00108 /// It might leave the critical section internally, but must restore 00109 /// the critical section before exiting to the caller. 00110 /// 00111 /// \note This is just an example of #QACTIVE_EQUEUE_SIGNAL_ for the QK-port 00112 /// of QF. In other QF ports you need to define the macro appropriately for 00113 /// the underlying kernel/OS you're using. 00114 #define QACTIVE_EQUEUE_SIGNAL_(me_) \ 00115 QK_readySet_.insert((me_)->m_prio); \ 00116 if (QK_intNest_ == (uint8_t)0) { \ 00117 QK_SCHEDULE_(); \ 00118 } else ((void)0) 00119 00120 /// \brief Platform-dependent macro defining the action QF should take 00121 /// when the native QF event queue becomes empty. 00122 /// 00123 /// \note #QACTIVE_EQUEUE_ONEMPTY_ is called from a critical section. 00124 /// It should not leave the critical section. 00125 /// 00126 /// \note This is just an example of #QACTIVE_EQUEUE_ONEMPTY_ for the QK-port 00127 /// of QF. In other QF ports you need to define the macro appropriately for 00128 /// the underlying kernel/OS you're using. 00129 #define QACTIVE_EQUEUE_ONEMPTY_(me_) \ 00130 QK_readySet_.remove((me_)->m_prio) 00131 00132 // QK event pool operations .................................................. 00133 00134 /// \brief This macro defines the type of the event pool used in this QF port. 00135 /// 00136 /// \note This is just an example of the macro definition. Typically, you need 00137 /// to define it in the specific QF port file (qf_port.h). In case of QK, 00138 /// which always depends on the native QF memory pool, this macro is defined 00139 /// at the level of the platform-independent interface qk.h. 00140 #define QF_EPOOL_TYPE_ QMPool 00141 00142 /// \brief Platform-dependent macro defining the event pool initialization 00143 /// 00144 /// \note This is just an example of #QF_EPOOL_INIT_ for the QK-port of QF. 00145 /// In other QF ports you need to define the macro appropriately for the 00146 /// underlying kernel/OS you're using. 00147 #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ 00148 (p_).init(poolSto_, poolSize_, evtSize_) 00149 00150 /// \brief Platform-dependent macro defining how QF should obtain the 00151 /// event pool block-size 00152 /// 00153 /// \note This is just an example of #QF_EPOOL_EVENT_SIZE_ for the QK-port 00154 /// of QF. In other QF ports you need to define the macro appropriately for 00155 /// the underlying kernel/OS you're using. 00156 #define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize()) 00157 00158 /// \brief Platform-dependent macro defining how QF should obtain an event 00159 /// \a e_ from the event pool \a p_ 00160 /// 00161 /// \note This is just an example of #QF_EPOOL_GET_ for the QK-port of QF. 00162 /// In other QF ports you need to define the macro appropriately for the 00163 /// underlying kernel/OS you're using. 00164 #define QF_EPOOL_GET_(p_, e_) ((e_) = (QEvent *)(p_).get()) 00165 00166 /// \brief Platform-dependent macro defining how QF should return an event 00167 /// \a e_ to the event pool \a p_ 00168 /// 00169 /// \note This is just an example of #QF_EPOOL_PUT_ for the QK-port of QF. 00170 /// In other QF ports you need to define the macro appropriately for the 00171 /// underlying kernel/OS you're using. 00172 #define QF_EPOOL_PUT_(p_, e_) ((p_).put(e_)) 00173 00174 #ifndef QK_NO_MUTEX 00175 ////////////////////////////////////////////////////////////////////////// 00176 /// \brief QK Mutex type. 00177 /// 00178 /// QMutex represents the priority-ceiling mutex available in QK. 00179 /// \sa QK::mutexLock() 00180 /// \sa QK::mutexUnlock() 00181 typedef uint8_t QMutex; 00182 #endif // QK_NO_MUTEX 00183 00184 ////////////////////////////////////////////////////////////////////////////// 00185 /// \brief QK services. 00186 /// 00187 /// This class groups together QK services. It has only static members and 00188 /// should not be instantiated. 00189 /// 00190 // \note The QK scheduler, QK priority, QK ready set, etc. belong conceptually 00191 /// to the QK class (as static class members). However, to avoid C++ potential 00192 /// name-mangling problems in assembly language, these elements are defined 00193 /// outside of the QK class and use the extern "C" linkage specification. 00194 /// 00195 class QK { 00196 public: 00197 00198 /// \brief get the current QK version number string 00199 /// 00200 /// \return version of the QK as a constant 6-character string of the 00201 /// form x.y.zz, where x is a 1-digit major version number, y is a 00202 /// 1-digit minor version number, and zz is a 2-digit release number. 00203 /// 00204 /// \sa QK::getPortVersion() 00205 static char const Q_ROM * Q_ROM_VAR getVersion(void); 00206 00207 /// \brief Returns the QK-port version. 00208 /// 00209 /// This function returns constant version string in the format x.y.zz, 00210 /// where x (one digit) is the major version, y (one digit) is the minor 00211 /// version, and zz (two digits) is the maintenance release version. 00212 /// An example of the QK-port version string is "1.1.03". 00213 /// 00214 /// \sa QK::getVersion() 00215 static char const Q_ROM * Q_ROM_VAR getPortVersion(void); 00216 00217 /// \brief QK idle callback (customized in BSPs for QK) 00218 /// 00219 /// QK::onIdle() is called continously by the QK idle loop. This callback 00220 /// gives the application an opportunity to enter a power-saving CPU mode, 00221 /// or perform some other idle processing. 00222 /// 00223 /// \note QK::onIdle() is invoked with interrupts unlocked and must also 00224 /// return with interrupts unlocked. 00225 /// 00226 /// \sa QF::onIdle() 00227 static void onIdle(void); 00228 00229 #ifndef QK_NO_MUTEX 00230 00231 /// \brief QK priority-ceiling mutex lock 00232 /// 00233 /// Lock the QK scheduler up to the priority level \a prioCeiling. 00234 /// 00235 // \note This function should be always paired with QK::mutexUnlock(). 00236 /// The code between QK::mutexLock() and QK::mutexUnlock() should be 00237 /// kept to the minimum. 00238 /// 00239 /// \include qk_mux.cpp 00240 static QMutex mutexLock(uint8_t prioCeiling); 00241 00242 /// \brief QK priority-ceiling mutex unlock 00243 /// 00244 /// \note This function should be always paired with QK::mutexLock(). 00245 /// The code between QK::mutexLock() and QK::mutexUnlock() should be 00246 /// kept to the minimum. 00247 /// 00248 /// \include qk_mux.cpp 00249 static void mutexUnlock(QMutex mutex); 00250 00251 #endif // QK_NO_MUTEX 00252 00253 }; 00254 00255 extern "C" { 00256 00257 /// \brief QK initialization 00258 /// 00259 /// QK_init() is called from QF_init() in qk.cpp. This function is 00260 /// defined in the QK ports. 00261 void QK_init(void); 00262 00263 // QK scheduler and extended scheduler 00264 #ifndef QF_INT_KEY_TYPE 00265 void QK_schedule_(void); // QK scheduler 00266 void QK_scheduleExt_(void); // QK extended scheduler 00267 00268 #define QK_SCHEDULE_() QK_schedule_() 00269 #else 00270 00271 /// \brief The QK scheduler 00272 /// 00273 /// \note The QK scheduler must be always called with the interrupts 00274 /// locked and unlocks interrupts internally. 00275 /// 00276 /// The signature of QK_schedule_() depends on the policy of locking and 00277 /// unlocking interrupts. When the interrupt lock key is not used 00278 /// (#QF_INT_KEY_TYPE undefined), the signature is as follows: \n 00279 /// void QK_schedule_(void); \n 00280 /// 00281 /// However, when the interrupt key lock is used (#QF_INT_KEY_TYPE 00282 /// defined), the signature is different: \n 00283 /// void QK_schedule_(QF_INT_KEY_TYPE intLockKey); \n 00284 /// 00285 /// For the internal use, these differences are hidden by the macro 00286 /// #QK_SCHEDULE_. 00287 void QK_schedule_(QF_INT_KEY_TYPE intLockKey); 00288 00289 /// \brief The QK extended scheduler for interrupt context 00290 /// 00291 /// \note The QK extended exscheduler must be always called with the 00292 /// interrupts locked and unlocks interrupts internally. 00293 /// 00294 /// The signature of QK_scheduleExt_() depends on the policy of locking 00295 /// and unlocking interrupts. When the interrupt lock key is not used 00296 /// (#QF_INT_KEY_TYPE undefined), the signature is as follows: \n 00297 /// void QK_scheduleExt_(void); \n 00298 /// 00299 /// However, when the interrupt key lock is used (#QF_INT_KEY_TYPE 00300 /// defined), the signature is different: \n 00301 /// void QK_scheduleExt_(QF_INT_KEY_TYPE intLockKey); \n 00302 void QK_scheduleExt_(QF_INT_KEY_TYPE intLockKey); // QK extended scheduler 00303 00304 /// #QF_INT_KEY_TYPE is defined, this internal macro invokes 00305 /// QK_schedule_() passing the key variable as the parameter. Otherwise 00306 /// QK_schedule_() is invoked without parameters. 00307 /// \sa #QK_INT_LOCK, #QK_INT_UNLOCK 00308 #define QK_SCHEDULE_() QK_schedule_(intLockKey_) 00309 00310 #endif 00311 } // extern "C" 00312 00313 ////////////////////////////////////////////////////////////////////////////// 00314 // QS software tracing integration, only if enabled 00315 #ifdef Q_SPY // QS software tracing enabled? 00316 #ifndef qs_h 00317 #include "qs_port.h" // include QS port 00318 #endif 00319 #else 00320 #ifndef qs_dummy_h 00321 #include "qs_dummy.h" // disable the QS software tracing 00322 #endif 00323 #endif // Q_SPY 00324 00325 #endif // qk_h
Generated on Tue Jul 12 2022 20:22:36 by
1.7.2