|
QP/C++
|
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
1.7.5.1