qs.h

Go to the documentation of this file.
00001 
00002 // Product: QS/C++ platform-independent public interface.
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 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
00028 #ifndef qs_h
00029 #define qs_h
00030 
00036 
00037 #ifndef Q_SPY
00038     #error "Q_SPY must be defined to include qs.h"
00039 #endif
00040 
00042 
00049 enum QSpyRecords {
00050     // QEP records
00051     QS_QEP_STATE_EMPTY,
00052     QS_QEP_STATE_ENTRY,                               
00053     QS_QEP_STATE_EXIT,                                 
00054     QS_QEP_STATE_INIT,          
00055     QS_QEP_INIT_TRAN,           
00056     QS_QEP_INTERN_TRAN,                  
00057     QS_QEP_TRAN,                           
00058     QS_QEP_IGNORED,             
00059     QS_QEP_RESERVED1,
00060     QS_QEP_RESERVED0,
00061 
00062     // QF records
00063     QS_QF_ACTIVE_ADD,                
00064     QS_QF_ACTIVE_REMOVE,         
00065     QS_QF_ACTIVE_SUBSCRIBE,                  
00066     QS_QF_ACTIVE_UNSUBSCRIBE,              
00067     QS_QF_ACTIVE_POST_FIFO,  
00068     QS_QF_ACTIVE_POST_LIFO,  
00069     QS_QF_ACTIVE_GET, 
00070     QS_QF_ACTIVE_GET_LAST,      
00071     QS_QF_EQUEUE_INIT,                     
00072     QS_QF_EQUEUE_POST_FIFO,     
00073     QS_QF_EQUEUE_POST_LIFO,     
00074     QS_QF_EQUEUE_GET,              
00075     QS_QF_EQUEUE_GET_LAST,              
00076     QS_QF_MPOOL_INIT,                       
00077     QS_QF_MPOOL_GET,        
00078     QS_QF_MPOOL_PUT,         
00079     QS_QF_PUBLISH,       
00080     QS_QF_RESERVED8,
00081     QS_QF_NEW,                                         
00082     QS_QF_GC_ATTEMPT,                          
00083     QS_QF_GC,                                          
00084     QS_QF_TICK,                                     
00085     QS_QF_TIMEEVT_ARM,                             
00086     QS_QF_TIMEEVT_AUTO_DISARM,      
00087     QS_QF_TIMEEVT_DISARM_ATTEMPT,
00088     QS_QF_TIMEEVT_DISARM,           
00089     QS_QF_TIMEEVT_REARM,                         
00090     QS_QF_TIMEEVT_POST,      
00091     QS_QF_RESERVED7,
00092     QS_QF_INT_LOCK,                                
00093     QS_QF_INT_UNLOCK,                            
00094     QS_QF_ISR_ENTRY,                                   
00095     QS_QF_ISR_EXIT,                                     
00096     QS_QF_RESERVED6,
00097     QS_QF_RESERVED5,
00098     QS_QF_RESERVED4,
00099     QS_QF_RESERVED3,
00100     QS_QF_RESERVED2,
00101     QS_QF_RESERVED1,
00102     QS_QF_RESERVED0,
00103 
00104     // QK records
00105     QS_QK_MUTEX_LOCK,                             
00106     QS_QK_MUTEX_UNLOCK,                         
00107     QS_QK_SCHEDULE,      
00108     QS_QK_RESERVED6,
00109     QS_QK_RESERVED5,
00110     QS_QK_RESERVED4,
00111     QS_QK_RESERVED3,
00112     QS_QK_RESERVED2,
00113     QS_QK_RESERVED1,
00114     QS_QK_RESERVED0,
00115 
00116     // Miscellaneous QS records
00117     QS_SIG_DICTIONARY,                            
00118     QS_OBJ_DICTIONARY,                            
00119     QS_FUN_DICTIONARY,                          
00120     QS_ASSERT,                                
00121     QS_RESERVED5,
00122     QS_RESERVED4,
00123     QS_RESERVED3,
00124     QS_RESERVED2,
00125     QS_RESERVED1,
00126     QS_RESERVED0,
00127 
00128     // User records
00129     QS_USER                
00130 };
00131 
00134 #define QS_ALL_RECORDS          ((uint8_t)0xFF)
00135 
00138 #define QS_EOD                  ((uint16_t)0xFFFF)
00139 
00140 
00141 #ifndef QS_TIME_SIZE
00142 
00149     #define QS_TIME_SIZE 4
00150 #endif
00151 #if (QS_TIME_SIZE == 1)
00152     typedef uint8_t QSTimeCtr;
00153     #define QS_TIME_()   QS::u8_(QS::onGetTime())
00154 #elif (QS_TIME_SIZE == 2)
00155     typedef uint16_t QSTimeCtr;
00156     #define QS_TIME_()   QS::u16_(QS::onGetTime())
00157 #elif (QS_TIME_SIZE == 4)
00158 
00162     typedef uint32_t QSTimeCtr;
00163 
00165     #define QS_TIME_()   QS::u32_(QS::onGetTime())
00166 #else
00167     #error "QS_TIME_SIZE defined incorrectly, expected 1, 2, or 4"
00168 #endif
00169 
00170 #ifndef Q_ROM                      // provide the default if Q_ROM NOT defined
00171     #define Q_ROM
00172 #endif
00173 #ifndef Q_ROM_VAR              // provide the default if Q_ROM_VAR NOT defined
00174     #define Q_ROM_VAR
00175 #endif
00176 #ifndef Q_ROM_BYTE            // provide the default if Q_ROM_BYTE NOT defined
00177     #define Q_ROM_BYTE(rom_var_)   (rom_var_)
00178 #endif
00179 
00180 
00185 class QS {
00186 public:
00187 
00193     static char const Q_ROM * Q_ROM_VAR getVersion(void);
00194 
00213     static void initBuf(uint8_t sto[], uint32_t stoSize);
00214 
00228     static void filterOn(uint8_t rec);
00229 
00242     static void filterOff(uint8_t rec);
00243 
00250     static void begin(uint8_t rec);
00251 
00258     static void end(void);
00259 
00260     // unformatted data elements output ......................................
00261 
00265     static void u8_(uint8_t d);
00266 
00270     static void u16_(uint16_t d);
00271 
00275     static void u32_(uint32_t d);
00276 
00281     static void str_(char const *s);
00282 
00287     static void str_ROM_(char const Q_ROM * Q_ROM_VAR s);
00288 
00289     // formatted data elements output ........................................
00290 
00294     static void u8(uint8_t format, uint8_t d);
00295 
00299     static void u16(uint8_t format, uint16_t d);
00300 
00304     static void u32(uint8_t format, uint32_t d);
00305 
00310     static void f32(uint8_t format, float d);
00311 
00316     static void f64(uint8_t format, double d);
00317 
00322     static void str(char const *s);
00323 
00328     static void str_ROM(char const Q_ROM * Q_ROM_VAR s);
00329 
00333     static void mem(uint8_t const *blk, uint8_t size);
00334 
00335     // QS buffer access ......................................................
00336 
00345     static uint16_t getByte(void);
00346 
00367     static uint8_t const *getBlock(uint16_t *pNbytes);
00368 
00369 // platform-dependent callback functions, need to be implemented by clients
00370 public:
00371 
00372     // platform-specific callback functions, need to be implemented by clients
00388     static uint8_t onStartup(void const *arg);
00389 
00396     static void onCleanup(void);
00397 
00404     static void onFlush(void);
00405 
00419     static QSTimeCtr onGetTime(void);
00420 
00421 // Global and Local QS filters ...............................................
00422 public:
00423     static uint8_t glbFilter_[32];                
00424     static void const *smObj_;         
00425     static void const *aoObj_;       
00426     static void const *mpObj_;            
00427     static void const *eqObj_;             
00428     static void const *teObj_;            
00429     static void const *apObj_;
00430 
00431 // Miscallaneous .............................................................
00432 public:
00434     static QSTimeCtr volatile tickCtr_;
00435 };
00436 
00437 
00439 // Macros for adding QS instrumentation to the client code
00440 
00446 #define QS_INIT(arg_)           QS::onStartup(arg_)
00447 
00453 #define QS_EXIT()               QS::onCleanup()
00454 
00462 #define QS_FILTER_ON(rec_)      QS::filterOn(rec_)
00463 
00470 #define QS_FILTER_OFF(rec_)     QS::filterOff(rec_)
00471 
00495 #define QS_FILTER_SM_OBJ(obj_)  (QS::smObj_ = (obj_))
00496 
00514 #define QS_FILTER_AO_OBJ(obj_)  (QS::aoObj_ = (obj_))
00515 
00532 #define QS_FILTER_MP_OBJ(obj_)  (QS::mpObj_ = (obj_))
00533 
00550 #define QS_FILTER_EQ_OBJ(obj_)  (QS::eqObj_ = (obj_))
00551 
00569 #define QS_FILTER_TE_OBJ(obj_)  (QS::teObj_ = (obj_))
00570 
00584 #define QS_FILTER_AP_OBJ(obj_)  (QS_apObj_ = (obj_))
00585 
00586 
00588 // Macros to generate user QS records
00589 
00591 #define QS_BEGIN_NOLOCK(rec_, obj_) \
00592     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00593           & (1U << ((uint8_t)(rec_) & 7U))) != 0) \
00594         && ((QS::apObj_ == (void *)0) || (QS::apObj_ == (obj_)))) \
00595     { \
00596         QS::begin((uint8_t)(rec_)); \
00597         QS_TIME_();
00598 
00600 #define QS_END_NOLOCK() \
00601     QS_END_NOLOCK_()
00602 
00603                                     // QS-specific interrupt locking/unlocking
00604 #ifndef QF_INT_KEY_TYPE
00612     #define QS_INT_LOCK_KEY_
00613 
00622     #define QS_INT_LOCK_()      QF_INT_LOCK(ignore_)
00623 
00632     #define QS_INT_UNLOCK_()    QF_INT_UNLOCK(ignore_)
00633 #else
00634     #define QS_INT_LOCK_KEY_    QF_INT_KEY_TYPE intLockKey_;
00635     #define QS_INT_LOCK_()      QF_INT_LOCK(intLockKey_)
00636     #define QS_INT_UNLOCK_()    QF_INT_UNLOCK(intLockKey_)
00637 #endif
00638 
00646 #define QS_BEGIN(rec_, obj_) \
00647     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00648           & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
00649         && ((QS::apObj_ == (void *)0) || (QS::apObj_ == (obj_)))) \
00650     { \
00651         QS_INT_LOCK_KEY_ \
00652         QS_INT_LOCK_(); \
00653         QS::begin((uint8_t)(rec_)); \
00654         QS_TIME_();
00655 
00659 #define QS_END() \
00660     QS_END_()
00661 
00662 
00664 // Macros for use inside other macros or internally in the QP code
00665 
00669 #define QS_BEGIN_(rec_, objFilter_, obj_) \
00670     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00671           & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
00672         && (((objFilter_) == (void *)0) || ((objFilter_) == (obj_)))) \
00673     { \
00674         QS_INT_LOCK_(); \
00675         QS::begin((uint8_t)(rec_));
00676 
00680 #define QS_END_() \
00681         QS::end(); \
00682         QS_INT_UNLOCK_(); \
00683     }
00684 
00689 #define QS_BEGIN_NOLOCK_(rec_, objFilter_, obj_) \
00690     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00691           & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
00692         && (((objFilter_) == (void *)0) || ((objFilter_) == (obj_)))) \
00693     { \
00694         QS::begin((uint8_t)(rec_));
00695 
00700 #define QS_END_NOLOCK_() \
00701         QS::end(); \
00702     }
00703 
00705 #define QS_U8_(data_)           QS::u8_(data_)
00706 
00708 #define QS_U16_(data_)          QS::u16_(data_)
00709 
00711 #define QS_U32_(data_)          QS::u32_(data_)
00712 
00713 
00714 #if (QS_OBJ_PTR_SIZE == 1)
00715     #define QS_OBJ_(obj_)       QS::u8_((uint8_t)(obj_))
00716 #elif (QS_OBJ_PTR_SIZE == 2)
00717     #define QS_OBJ_(obj_)       QS::u16_((uint16_t)(obj_))
00718 #elif (QS_OBJ_PTR_SIZE == 4)
00719     #define QS_OBJ_(obj_)       QS::u32_((uint32_t)(obj_))
00720 #else
00721 
00726     #define QS_OBJ_(obj_)       QS::u32_((uint32_t)(obj_))
00727 #endif
00728 
00729 
00730 #if (QS_FUN_PTR_SIZE == 1)
00731     #define QS_FUN_(fun_)       QS::u8_((uint8_t)(fun_))
00732 #elif (QS_FUN_PTR_SIZE == 2)
00733     #define QS_FUN_(fun_)       QS::u16_((uint16_t)(fun_))
00734 #elif (QS_FUN_PTR_SIZE == 4)
00735     #define QS_FUN_(fun_)       QS::u32_((uint32_t)(fun_))
00736 #else
00737 
00742     #define QS_FUN_(fun_)       QS::u32_((uint32_t)(fun_))
00743 #endif
00744 
00747 #define QS_STR_(msg_)           QS::str_(msg_)
00748 
00751 #define QS_STR_ROM_(msg_)       QS::str_ROM_(msg_)
00752 
00754 // Macros for use in the client code
00755 
00760 enum QSType {
00761     QS_I8_T,                                  
00762     QS_U8_T,                                
00763     QS_I16_T,                                
00764     QS_U16_T,                              
00765     QS_I32_T,                                
00766     QS_U32_T,                              
00767     QS_F32_T,                                
00768     QS_F64_T,                                
00769     QS_STR_T,                         
00770     QS_MEM_T,                         
00771     QS_SIG_T,                                         
00772     QS_OBJ_T,                                       
00773     QS_FUN_T                                      
00774 };
00775 
00777 #define QS_I8(width_, data_) \
00778     QS::u8((uint8_t)(((width_) << 4)) | QS_I8_T, (data_))
00779 
00781 #define QS_U8(width_, data_) \
00782     QS::u8((uint8_t)(((width_) << 4)) | QS_U8_T, (data_))
00783 
00785 #define QS_I16(width_, data_) \
00786     QS::u16((uint8_t)(((width_) << 4)) | QS_I16_T, (data_))
00787 
00789 #define QS_U16(width_, data_) \
00790     QS::u16((uint8_t)(((width_) << 4)) | QS_U16_T, (data_))
00791 
00793 #define QS_I32(width_, data_) \
00794     QS::u32((uint8_t)(((width_) << 4)) | QS_I32_T, (data_))
00795 
00797 #define QS_U32(width_, data_) \
00798     QS::u32((uint8_t)(((width_) << 4)) | QS_U32_T, (data_))
00799 
00801 #define QS_F32(width_, data_) \
00802     QS::f32((uint8_t)(((width_) << 4)) | QS_F32_T, (data_))
00803 
00805 #define QS_F64(width_, data_) \
00806     QS::f64((uint8_t)(((width_) << 4)) | QS_F64_T, (data_))
00807 
00809 #define QS_STR(str_)            QS::str(str_)
00810 
00813 #define QS_STR_ROM(str_)        QS::str_ROM(str_)
00814 
00817 #define QS_MEM(mem_, size_)     QS::mem((mem_), (size_))
00818 
00819 
00820 #if (QS_OBJ_PTR_SIZE == 1)
00821     #define QS_OBJ(obj_)        QS::u8(QS_OBJ_T, (uint8_t)(obj_))
00822 #elif (QS_OBJ_PTR_SIZE == 2)
00823     #define QS_OBJ(obj_)        QS::u16(QS_OBJ_T, (uint16_t)(obj_))
00824 #elif (QS_OBJ_PTR_SIZE == 4)
00825     #define QS_OBJ(obj_)        QS::u32(QS_OBJ_T, (uint32_t)(obj_))
00826 #else
00828     #define QS_OBJ(obj_)        QS::u32(QS_OBJ_T, (uint32_t)(obj_))
00829 #endif
00830 
00831 
00832 #if (QS_FUN_PTR_SIZE == 1)
00833     #define QS_FUN(fun_)        QS::u8(QS_FUN_T, (uint8_t)(fun_))
00834 #elif (QS_FUN_PTR_SIZE == 2)
00835     #define QS_FUN(fun_)        QS::u16(QS_FUN_T, (uint16_t)(fun_))
00836 #elif (QS_FUN_PTR_SIZE == 4)
00837     #define QS_FUN(fun_)        QS::u32(QS_FUN_T, (uint32_t)(fun_))
00838 #else
00840     #define QS_FUN(fun_)        QS::u32(QS_FUN_T, (uint32_t)(fun_))
00841 #endif
00842 
00843 
00883 #define QS_SIG_DICTIONARY(sig_, obj_) \
00884     if (((QS::glbFilter_[(uint8_t)QS_SIG_DICTIONARY >> 3U] \
00885           & (1U << ((uint8_t)QS_SIG_DICTIONARY & 7U))) != 0U)) \
00886     { \
00887         static char const Q_ROM Q_ROM_VAR sig_name__[] = #sig_; \
00888         QS_INT_LOCK_KEY_ \
00889         QS_INT_LOCK_(); \
00890         QS::begin((uint8_t)QS_SIG_DICTIONARY); \
00891         QS_SIG_(sig_); \
00892         QS_OBJ_(obj_); \
00893         QS_STR_ROM_(sig_name__); \
00894         QS::end(); \
00895         QS_INT_UNLOCK_(); \
00896         QS::onFlush(); \
00897     } else ((void)0)
00898 
00911 #define QS_OBJ_DICTIONARY(obj_) \
00912     if (((QS::glbFilter_[(uint8_t)QS_OBJ_DICTIONARY >> 3U] \
00913           & (1U << ((uint8_t)QS_OBJ_DICTIONARY & 7U))) != 0U)) \
00914     { \
00915         static char const Q_ROM Q_ROM_VAR obj_name__[] = #obj_; \
00916         QS_INT_LOCK_KEY_ \
00917         QS_INT_LOCK_(); \
00918         QS::begin((uint8_t)QS_OBJ_DICTIONARY); \
00919         QS_OBJ_(obj_); \
00920         QS_STR_ROM_(obj_name__); \
00921         QS::end(); \
00922         QS_INT_UNLOCK_(); \
00923         QS::onFlush(); \
00924     } else ((void)0)
00925 
00937 #define QS_FUN_DICTIONARY(fun_) \
00938     if (((QS::glbFilter_[(uint8_t)QS_FUN_DICTIONARY >> 3U] \
00939           & (1U << ((uint8_t)QS_FUN_DICTIONARY & 7U))) != 0U)) \
00940     { \
00941         static char const Q_ROM Q_ROM_VAR fun_name__[] = #fun_; \
00942         QS_INT_LOCK_KEY_ \
00943         QS_INT_LOCK_(); \
00944         QS::begin((uint8_t)QS_FUN_DICTIONARY); \
00945         QS_FUN_(fun_); \
00946         QS_STR_ROM_(fun_name__); \
00947         QS::end(); \
00948         QS_INT_UNLOCK_(); \
00949         QS::onFlush(); \
00950     } else ((void)0)
00951 
00958 #define QS_FLUSH()   QS::onFlush()
00959 
00960 
00962 #define QF_QS_INT_LOCK() \
00963     QS_BEGIN_NOLOCK_(QS_QF_INT_LOCK, (void *)0, (void *)0); \
00964         QS_TIME_(); \
00965         QS_U8_((uint8_t)(++QF_intLockNest_)); \
00966     QS_END_NOLOCK_()
00967 
00969 #define QF_QS_INT_UNLOCK() \
00970     QS_BEGIN_NOLOCK_(QS_QF_INT_UNLOCK, (void *)0, (void *)0); \
00971         QS_TIME_(); \
00972         QS_U8_((uint8_t)(QF_intLockNest_--)); \
00973     QS_END_NOLOCK_()
00974 
00976 #define QF_QS_ISR_ENTRY(isrnest_, prio_) \
00977     QS_BEGIN_NOLOCK_(QS_QF_ISR_ENTRY, (void *)0, (void *)0); \
00978         QS_TIME_(); \
00979         QS_U8_(isrnest_); \
00980         QS_U8_(prio_); \
00981     QS_END_NOLOCK_()
00982 
00984 #define QF_QS_ISR_EXIT(isrnest_, prio_) \
00985     QS_BEGIN_NOLOCK_(QS_QF_ISR_EXIT, (void *)0, (void *)0); \
00986         QS_TIME_(); \
00987         QS_U8_(isrnest_); \
00988         QS_U8_(prio_); \
00989     QS_END_NOLOCK_()
00990 
00992 #define QF_QS_ACTION(act_)      (act_)
00993 
00997 extern uint8_t QF_intLockNest_;
00998 
00999 #endif                                                                 // qs_h

Generated on Sat Nov 15 13:53:47 2008 for QP/C++ by  doxygen 1.5.4