QP/C++
qs.h
Go to the documentation of this file.
00001 
00002 // Product: QS/C++ platform-independent public interface.
00003 // Last Updated for Version: 4.3.00
00004 // Date of the Last Update:  Nov 01, 2011
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2011 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 #ifdef Q_USE_NAMESPACE
00038 namespace QP {
00039 #endif
00040 
00041 #ifndef Q_SPY
00042     #error "Q_SPY must be defined to include qs.h"
00043 #endif
00044 
00046 
00053 enum QSpyRecords {
00054     // QEP records
00055     QS_QEP_STATE_EMPTY,
00056     QS_QEP_STATE_ENTRY,                               
00057     QS_QEP_STATE_EXIT,                                 
00058     QS_QEP_STATE_INIT,          
00059     QS_QEP_INIT_TRAN,           
00060     QS_QEP_INTERN_TRAN,                  
00061     QS_QEP_TRAN,                           
00062     QS_QEP_IGNORED,             
00063     QS_QEP_DISPATCH,          
00064     QS_QEP_RESERVED0,
00065 
00066     // QF records
00067     QS_QF_ACTIVE_ADD,                
00068     QS_QF_ACTIVE_REMOVE,         
00069     QS_QF_ACTIVE_SUBSCRIBE,                  
00070     QS_QF_ACTIVE_UNSUBSCRIBE,              
00071     QS_QF_ACTIVE_POST_FIFO,  
00072     QS_QF_ACTIVE_POST_LIFO,  
00073     QS_QF_ACTIVE_GET, 
00074     QS_QF_ACTIVE_GET_LAST,      
00075     QS_QF_EQUEUE_INIT,                     
00076     QS_QF_EQUEUE_POST_FIFO,     
00077     QS_QF_EQUEUE_POST_LIFO,     
00078     QS_QF_EQUEUE_GET,              
00079     QS_QF_EQUEUE_GET_LAST,              
00080     QS_QF_MPOOL_INIT,                       
00081     QS_QF_MPOOL_GET,        
00082     QS_QF_MPOOL_PUT,         
00083     QS_QF_PUBLISH,       
00084     QS_QF_RESERVED8,
00085     QS_QF_NEW,                                         
00086     QS_QF_GC_ATTEMPT,                          
00087     QS_QF_GC,                                          
00088     QS_QF_TICK,                                     
00089     QS_QF_TIMEEVT_ARM,                             
00090     QS_QF_TIMEEVT_AUTO_DISARM,      
00091     QS_QF_TIMEEVT_DISARM_ATTEMPT,
00092     QS_QF_TIMEEVT_DISARM,           
00093     QS_QF_TIMEEVT_REARM,                         
00094     QS_QF_TIMEEVT_POST,      
00095     QS_QF_TIMEEVT_CTR,                 
00096     QS_QF_CRIT_ENTRY,                        
00097     QS_QF_CRIT_EXIT,                          
00098     QS_QF_ISR_ENTRY,                                   
00099     QS_QF_ISR_EXIT,                                     
00100     QS_QF_INT_DISABLE,                           
00101     QS_QF_INT_ENABLE,                             
00102     QS_QF_RESERVED4,
00103     QS_QF_RESERVED3,
00104     QS_QF_RESERVED2,
00105     QS_QF_RESERVED1,
00106     QS_QF_RESERVED0,
00107 
00108     // QK records
00109     QS_QK_MUTEX_LOCK,                             
00110     QS_QK_MUTEX_UNLOCK,                         
00111     QS_QK_SCHEDULE,      
00112     QS_QK_RESERVED6,
00113     QS_QK_RESERVED5,
00114     QS_QK_RESERVED4,
00115     QS_QK_RESERVED3,
00116     QS_QK_RESERVED2,
00117     QS_QK_RESERVED1,
00118     QS_QK_RESERVED0,
00119 
00120     // Miscellaneous QS records
00121     QS_SIG_DICTIONARY,                            
00122     QS_OBJ_DICTIONARY,                            
00123     QS_FUN_DICTIONARY,                          
00124     QS_ASSERT,                                
00125     QS_RESERVED5,
00126     QS_RESERVED4,
00127     QS_RESERVED3,
00128     QS_RESERVED2,
00129     QS_RESERVED1,
00130     QS_RESERVED0,
00131 
00132     // User records
00133     QS_USER                
00134 };
00135 
00138 #define QS_ALL_RECORDS          ((uint8_t)0xFF)
00139 
00142 #define QS_EOD                  ((uint16_t)0xFFFF)
00143 
00144 
00145 #ifndef QS_TIME_SIZE
00146 
00153     #define QS_TIME_SIZE 4
00154 #endif
00155 #if (QS_TIME_SIZE == 1)
00156     typedef uint8_t QSTimeCtr;
00157     #define QS_TIME_()   QS::u8_(QS::onGetTime())
00158 #elif (QS_TIME_SIZE == 2)
00159     typedef uint16_t QSTimeCtr;
00160     #define QS_TIME_()   QS::u16_(QS::onGetTime())
00161 #elif (QS_TIME_SIZE == 4)
00162 
00166     typedef uint32_t QSTimeCtr;
00167 
00169     #define QS_TIME_()   QS::u32_(QS::onGetTime())
00170 #else
00171     #error "QS_TIME_SIZE defined incorrectly, expected 1, 2, or 4"
00172 #endif
00173 
00174 #ifndef Q_ROM                      // provide the default if Q_ROM NOT defined
00175     #define Q_ROM
00176 #endif
00177 #ifndef Q_ROM_VAR              // provide the default if Q_ROM_VAR NOT defined
00178     #define Q_ROM_VAR
00179 #endif
00180 #ifndef Q_ROM_BYTE            // provide the default if Q_ROM_BYTE NOT defined
00181     #define Q_ROM_BYTE(rom_var_)   (rom_var_)
00182 #endif
00183 
00184 
00189 class QS {
00190 public:
00191 
00197     static char const Q_ROM * Q_ROM_VAR getVersion(void);
00198 
00217     static void initBuf(uint8_t sto[], uint32_t stoSize);
00218 
00232     static void filterOn(uint8_t rec);
00233 
00246     static void filterOff(uint8_t rec);
00247 
00254     static void begin(uint8_t rec);
00255 
00262     static void end(void);
00263 
00264     // unformatted data elements output ......................................
00265 
00269     static void u8_(uint8_t d);
00270 
00274     static void u16_(uint16_t d);
00275 
00279     static void u32_(uint32_t d);
00280 
00285     static void str_(char const *s);
00286 
00291     static void str_ROM_(char const Q_ROM * Q_ROM_VAR s);
00292 
00293     // formatted data elements output ........................................
00294 
00298     static void u8(uint8_t format, uint8_t d);
00299 
00303     static void u16(uint8_t format, uint16_t d);
00304 
00308     static void u32(uint8_t format, uint32_t d);
00309 
00314     static void f32(uint8_t format, float d);
00315 
00320     static void f64(uint8_t format, double d);
00321 
00326     static void str(char const *s);
00327 
00332     static void str_ROM(char const Q_ROM * Q_ROM_VAR s);
00333 
00337     static void mem(uint8_t const *blk, uint8_t size);
00338 
00339 #if (QS_OBJ_PTR_SIZE == 8) || (QS_FUN_PTR_SIZE == 8)
00340 
00341 
00342 
00343     static void u64_(uint64_t d);
00344 
00348     static void u64(uint8_t format, uint64_t d);
00349 #endif
00350 
00351     // QS buffer access ......................................................
00352 
00361     static uint16_t getByte(void);
00362 
00383     static uint8_t const *getBlock(uint16_t *pNbytes);
00384 
00385 // platform-dependent callback functions, need to be implemented by clients
00386 public:
00387 
00388     // platform-specific callback functions, need to be implemented by clients
00404     static uint8_t onStartup(void const *arg);
00405 
00412     static void onCleanup(void);
00413 
00420     static void onFlush(void);
00421 
00435     static QSTimeCtr onGetTime(void);
00436 
00437 // Global and Local QS filters ...............................................
00438 public:
00439     static uint8_t glbFilter_[32];                
00440     static void const *smObj_;         
00441     static void const *aoObj_;       
00442     static void const *mpObj_;            
00443     static void const *eqObj_;             
00444     static void const *teObj_;            
00445     static void const *apObj_;
00446 
00447 // Miscallaneous .............................................................
00448 public:
00450     static QSTimeCtr volatile tickCtr_;
00451 };
00452 
00453 
00455 // Macros for adding QS instrumentation to the client code
00456 
00462 #define QS_INIT(arg_)           QS::onStartup(arg_)
00463 
00469 #define QS_EXIT()               QS::onCleanup()
00470 
00478 #define QS_FILTER_ON(rec_)      QS::filterOn(rec_)
00479 
00486 #define QS_FILTER_OFF(rec_)     QS::filterOff(rec_)
00487 
00511 #define QS_FILTER_SM_OBJ(obj_)  (QS::smObj_ = (obj_))
00512 
00530 #define QS_FILTER_AO_OBJ(obj_)  (QS::aoObj_ = (obj_))
00531 
00548 #define QS_FILTER_MP_OBJ(obj_)  (QS::mpObj_ = (obj_))
00549 
00566 #define QS_FILTER_EQ_OBJ(obj_)  (QS::eqObj_ = (obj_))
00567 
00585 #define QS_FILTER_TE_OBJ(obj_)  (QS::teObj_ = (obj_))
00586 
00600 #define QS_FILTER_AP_OBJ(obj_)  (QS::apObj_ = (obj_))
00601 
00602 
00604 // Macros to generate user QS records
00605 
00607 #define QS_BEGIN_NOCRIT(rec_, obj_) \
00608     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00609           & (1U << ((uint8_t)(rec_) & 7U))) != 0) \
00610         && ((QS::apObj_ == (void *)0) || (QS::apObj_ == (obj_)))) \
00611     { \
00612         QS::begin((uint8_t)(rec_)); \
00613         QS_TIME_();
00614 
00616 #define QS_END_NOCRIT() \
00617     QS_END_NOCRIT_()
00618 
00619                                                // QS-specific critical section
00620 #ifndef QF_CRIT_STAT_TYPE
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631     #define QS_CRIT_STAT_
00632 
00642     #define QS_CRIT_ENTRY_()    QF_CRIT_ENTRY(dummy)
00643 
00653     #define QS_CRIT_EXIT_()     QF_CRIT_EXIT(dummy)
00654 
00655 #else
00656     #define QS_CRIT_STAT_       QF_CRIT_STAT_TYPE critStat_;
00657     #define QS_CRIT_ENTRY_()    QF_CRIT_ENTRY(critStat_)
00658     #define QS_CRIT_EXIT_()     QF_CRIT_EXIT(critStat_)
00659 #endif
00660 
00668 #define QS_BEGIN(rec_, obj_) \
00669     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00670           & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
00671         && ((QS::apObj_ == (void *)0) || (QS::apObj_ == (obj_)))) \
00672     { \
00673         QS_CRIT_STAT_ \
00674         QS_CRIT_ENTRY_(); \
00675         QS::begin((uint8_t)(rec_)); \
00676         QS_TIME_();
00677 
00681 #define QS_END() \
00682     QS_END_()
00683 
00684 
00686 // Macros for use inside other macros or internally in the QP code
00687 
00691 #define QS_BEGIN_(rec_, objFilter_, obj_) \
00692     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00693           & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
00694         && (((objFilter_) == (void *)0) || ((objFilter_) == (obj_)))) \
00695     { \
00696         QS_CRIT_ENTRY_(); \
00697         QS::begin((uint8_t)(rec_));
00698 
00702 #define QS_END_() \
00703         QS::end(); \
00704         QS_CRIT_EXIT_(); \
00705     }
00706 
00711 #define QS_BEGIN_NOCRIT_(rec_, objFilter_, obj_) \
00712     if (((QS::glbFilter_[(uint8_t)(rec_) >> 3U] \
00713           & (1U << ((uint8_t)(rec_) & 7U))) != 0U) \
00714         && (((objFilter_) == (void *)0) || ((objFilter_) == (obj_)))) \
00715     { \
00716         QS::begin((uint8_t)(rec_));
00717 
00722 #define QS_END_NOCRIT_() \
00723         QS::end(); \
00724     }
00725 
00727 #define QS_U8_(data_)           QS::u8_(data_)
00728 
00730 #define QS_U16_(data_)          QS::u16_(data_)
00731 
00733 #define QS_U32_(data_)          QS::u32_(data_)
00734 
00735 
00736 #if (QS_OBJ_PTR_SIZE == 1)
00737     #define QS_OBJ_(obj_)       QS::u8_((uint8_t)(obj_))
00738 #elif (QS_OBJ_PTR_SIZE == 2)
00739     #define QS_OBJ_(obj_)       QS::u16_((uint16_t)(obj_))
00740 #elif (QS_OBJ_PTR_SIZE == 4)
00741     #define QS_OBJ_(obj_)       QS::u32_((uint32_t)(obj_))
00742 #elif (QS_OBJ_PTR_SIZE == 8)
00743     #define QS_OBJ_(obj_)       QS::u64_((uint64_t)(obj_))
00744 #else
00745 
00750     #define QS_OBJ_(obj_)       QS::u32_((uint32_t)(obj_))
00751 #endif
00752 
00753 
00754 #if (QS_FUN_PTR_SIZE == 1)
00755     #define QS_FUN_(fun_)       QS::u8_((uint8_t)(fun_))
00756 #elif (QS_FUN_PTR_SIZE == 2)
00757     #define QS_FUN_(fun_)       QS::u16_((uint16_t)(fun_))
00758 #elif (QS_FUN_PTR_SIZE == 4)
00759     #define QS_FUN_(fun_)       QS::u32_((uint32_t)(fun_))
00760 #elif (QS_FUN_PTR_SIZE == 8)
00761     #define QS_FUN_(fun_)       QS::u64_((uint64_t)(fun_))
00762 #else
00763 
00768     #define QS_FUN_(fun_)       QS::u32_((uint32_t)(fun_))
00769 #endif
00770 
00773 #define QS_STR_(msg_)           QS::str_(msg_)
00774 
00777 #define QS_STR_ROM_(msg_)       QS::str_ROM_(msg_)
00778 
00780 // Macros for use in the client code
00781 
00786 enum QSType {
00787     QS_I8_T,                                  
00788     QS_U8_T,                                
00789     QS_I16_T,                                
00790     QS_U16_T,                              
00791     QS_I32_T,                                
00792     QS_U32_T,                              
00793     QS_F32_T,                                
00794     QS_F64_T,                                
00795     QS_STR_T,                         
00796     QS_MEM_T,                         
00797     QS_SIG_T,                                         
00798     QS_OBJ_T,                                       
00799     QS_FUN_T,                                     
00800     QS_I64_T,                                
00801     QS_U64_T,                              
00802     QS_U32_HEX_T                    
00803 };
00804 
00806 #define QS_I8(width_, data_) \
00807     QS::u8((uint8_t)(((width_) << 4)) | QS_I8_T, (data_))
00808 
00810 #define QS_U8(width_, data_) \
00811     QS::u8((uint8_t)(((width_) << 4)) | QS_U8_T, (data_))
00812 
00814 #define QS_I16(width_, data_) \
00815     QS::u16((uint8_t)(((width_) << 4)) | QS_I16_T, (data_))
00816 
00818 #define QS_U16(width_, data_) \
00819     QS::u16((uint8_t)(((width_) << 4)) | QS_U16_T, (data_))
00820 
00822 #define QS_I32(width_, data_) \
00823     QS::u32((uint8_t)(((width_) << 4)) | QS_I32_T, (data_))
00824 
00826 #define QS_U32(width_, data_) \
00827     QS::u32((uint8_t)(((width_) << 4)) | QS_U32_T, (data_))
00828 
00830 #define QS_F32(width_, data_) \
00831     QS::f32((uint8_t)(((width_) << 4)) | QS_F32_T, (data_))
00832 
00834 #define QS_F64(width_, data_) \
00835     QS::f64((uint8_t)(((width_) << 4)) | QS_F64_T, (data_))
00836 
00838 #define QS_I64(width_, data_) \
00839     QS::u64((uint8_t)(((width_) << 4)) | QS_I64_T, (data_))
00840 
00842 #define QS_U64(width_, data_) \
00843     QS::u64((uint8_t)(((width_) << 4)) | QS_U64_T, (data_))
00844 
00846 #define QS_U32_HEX(width_, data_) \
00847     QS::u32((uint8_t)(((width_) << 4)) | QS_U32_HEX_T, (data_))
00848 
00850 #define QS_STR(str_)            QS::str(str_)
00851 
00854 #define QS_STR_ROM(str_)        QS::str_ROM(str_)
00855 
00858 #define QS_MEM(mem_, size_)     QS::mem((mem_), (size_))
00859 
00860 
00861 #if (QS_OBJ_PTR_SIZE == 1)
00862     #define QS_OBJ(obj_)        QS::u8(QS_OBJ_T, (uint8_t)(obj_))
00863 #elif (QS_OBJ_PTR_SIZE == 2)
00864     #define QS_OBJ(obj_)        QS::u16(QS_OBJ_T, (uint16_t)(obj_))
00865 #elif (QS_OBJ_PTR_SIZE == 4)
00866     #define QS_OBJ(obj_)        QS::u32(QS_OBJ_T, (uint32_t)(obj_))
00867 #elif (QS_OBJ_PTR_SIZE == 8)
00868     #define QS_OBJ(obj_)        QS::u64(QS_OBJ_T, (uint64_t)(obj_))
00869 #else
00870 
00871     #define QS_OBJ(obj_)        QS::u32(QS_OBJ_T, (uint32_t)(obj_))
00872 #endif
00873 
00874 
00875 #if (QS_FUN_PTR_SIZE == 1)
00876     #define QS_FUN(fun_)        QS::u8(QS_FUN_T, (uint8_t)(fun_))
00877 #elif (QS_FUN_PTR_SIZE == 2)
00878     #define QS_FUN(fun_)        QS::u16(QS_FUN_T, (uint16_t)(fun_))
00879 #elif (QS_FUN_PTR_SIZE == 4)
00880     #define QS_FUN(fun_)        QS::u32(QS_FUN_T, (uint32_t)(fun_))
00881 #elif (QS_FUN_PTR_SIZE == 8)
00882     #define QS_FUN(fun_)        QS::u64(QS_FUN_T, (uint64_t)(fun_))
00883 #else
00884 
00885     #define QS_FUN(fun_)        QS::u32(QS_FUN_T, (uint32_t)(fun_))
00886 #endif
00887 
00888 
00928 #define QS_SIG_DICTIONARY(sig_, obj_) \
00929     if (((QS::glbFilter_[(uint8_t)QS_SIG_DICTIONARY >> 3U] \
00930           & (1U << ((uint8_t)QS_SIG_DICTIONARY & 7U))) != 0U)) \
00931     { \
00932         static char const Q_ROM Q_ROM_VAR sig_name__[] = #sig_; \
00933         QS_CRIT_STAT_ \
00934         QS_CRIT_ENTRY_(); \
00935         QS::begin((uint8_t)QS_SIG_DICTIONARY); \
00936         QS_SIG_(sig_); \
00937         QS_OBJ_(obj_); \
00938         QS_STR_ROM_(sig_name__); \
00939         QS::end(); \
00940         QS_CRIT_EXIT_(); \
00941         QS::onFlush(); \
00942     } else ((void)0)
00943 
00956 #define QS_OBJ_DICTIONARY(obj_) \
00957     if (((QS::glbFilter_[(uint8_t)QS_OBJ_DICTIONARY >> 3U] \
00958           & (1U << ((uint8_t)QS_OBJ_DICTIONARY & 7U))) != 0U)) \
00959     { \
00960         static char const Q_ROM Q_ROM_VAR obj_name__[] = #obj_; \
00961         QS_CRIT_STAT_ \
00962         QS_CRIT_ENTRY_(); \
00963         QS::begin((uint8_t)QS_OBJ_DICTIONARY); \
00964         QS_OBJ_(obj_); \
00965         QS_STR_ROM_(obj_name__); \
00966         QS::end(); \
00967         QS_CRIT_EXIT_(); \
00968         QS::onFlush(); \
00969     } else ((void)0)
00970 
00982 #define QS_FUN_DICTIONARY(fun_) \
00983     if (((QS::glbFilter_[(uint8_t)QS_FUN_DICTIONARY >> 3U] \
00984           & (1U << ((uint8_t)QS_FUN_DICTIONARY & 7U))) != 0U)) \
00985     { \
00986         static char const Q_ROM Q_ROM_VAR fun_name__[] = #fun_; \
00987         QS_CRIT_STAT_ \
00988         QS_CRIT_ENTRY_(); \
00989         QS::begin((uint8_t)QS_FUN_DICTIONARY); \
00990         QS_FUN_(fun_); \
00991         QS_STR_ROM_(fun_name__); \
00992         QS::end(); \
00993         QS_CRIT_EXIT_(); \
00994         QS::onFlush(); \
00995     } else ((void)0)
00996 
01003 #define QS_FLUSH()   QS::onFlush()
01004 
01005 
01007 #define QF_QS_CRIT_ENTRY() \
01008     QS_BEGIN_NOCRIT_(QS_QF_CRIT_ENTRY, (void *)0, (void *)0); \
01009         QS_TIME_(); \
01010         QS_U8_((uint8_t)(++QF_critNest_)); \
01011     QS_END_NOCRIT_()
01012 
01014 #define QF_QS_CRIT_EXIT() \
01015     QS_BEGIN_NOCRIT_(QS_QF_CRIT_EXIT, (void *)0, (void *)0); \
01016         QS_TIME_(); \
01017         QS_U8_((uint8_t)(QF_critNest_--)); \
01018     QS_END_NOCRIT_()
01019 
01021 #define QF_QS_ISR_ENTRY(isrnest_, prio_) \
01022     QS_BEGIN_NOCRIT_(QS_QF_ISR_ENTRY, (void *)0, (void *)0); \
01023         QS_TIME_(); \
01024         QS_U8_(isrnest_); \
01025         QS_U8_(prio_); \
01026     QS_END_NOCRIT_()
01027 
01029 #define QF_QS_ISR_EXIT(isrnest_, prio_) \
01030     QS_BEGIN_NOCRIT_(QS_QF_ISR_EXIT, (void *)0, (void *)0); \
01031         QS_TIME_(); \
01032         QS_U8_(isrnest_); \
01033         QS_U8_(prio_); \
01034     QS_END_NOCRIT_()
01035 
01037 #define QF_QS_ACTION(act_)      (act_)
01038 
01042 extern uint8_t QF_critNest_;
01043 
01044 #ifdef Q_USE_NAMESPACE
01045 }                                                              // namespace QP
01046 #endif
01047 
01048 #endif                                                                 // qs_h