Linux Face / QPFramework
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers qk.h Source File

qk.h

Go to the documentation of this file.
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