Data Watch-point and Trace unit(DWT) interface.
Revision 0:37014c6bb5cd, committed 2017-10-08
- Comitter:
- YasuhiroKawai
- Date:
- Sun Oct 08 05:51:12 2017 +0000
- Commit message:
- Initial revision
Changed in this revision
Dwt.cpp | Show annotated file Show diff for this revision Revisions of this file |
Dwt.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Dwt.cpp Sun Oct 08 05:51:12 2017 +0000 @@ -0,0 +1,97 @@ + +#include <mbed.h> +#include "Dwt.h" + +const uint32_t Dwt::DWT_REGS_ADDR = 0xe0001000; +const uint32_t Dwt::SCB_DEMCR_ADDR = 0xe000edfc; + +const uint32_t Dwt::NUMCOMP_POS = 28; +const uint32_t Dwt::NUMCOMP_MASK = (0xfU << Dwt::NUMCOMP_POS); +const uint32_t Dwt::NOTRCPKT = (1 << 27); +const uint32_t Dwt::NOEXTTRIG = (1 << 26); +const uint32_t Dwt::NOCYCCNT = (1 << 25); +const uint32_t Dwt::NOPRFCNT = (1 << 24); + +const uint32_t Dwt::CYCEVTENA = (1 << 22); +const uint32_t Dwt::FOLDEVTENA = (1 << 21); +const uint32_t Dwt::LSUEVTENA = (1 << 20); +const uint32_t Dwt::SLEEPEVTENA = (1 << 19); +const uint32_t Dwt::EXCEVTENA = (1 << 18); +const uint32_t Dwt::CPIEVTENA = (1 << 17); +const uint32_t Dwt::EXCTRCENA = (1 << 16); +const uint32_t Dwt::PCSAMPLENA = (1 << 12); +const uint32_t Dwt::CYCCNTENA = (1 << 0); + +const uint32_t Dwt::TRCENA = (1 << 24); + +const uint32_t Dwt::EVENA_MASK = Dwt::CYCEVTENA | Dwt::FOLDEVTENA | Dwt::LSUEVTENA | Dwt::SLEEPEVTENA | + Dwt::EXCEVTENA | Dwt::CPIEVTENA | Dwt::EXCTRCENA | Dwt::PCSAMPLENA | + Dwt::CYCCNTENA; + + + +Dwt::Dwt() +{ + _regs = (volatile dwt_regs_t *)DWT_REGS_ADDR; + _scb_demcr_regs = (volatile uint32_t *)SCB_DEMCR_ADDR; +} + +bool +Dwt::isTRCPKT_Available() +{ + return((_regs->DWT_CTRL & NOTRCPKT) == 0); +} + + +bool +Dwt::isEXTTRIG_Available() +{ + return((_regs->DWT_CTRL & NOEXTTRIG) == 0); +} + +bool +Dwt::isCYCCNT_Available() +{ + return((_regs->DWT_CTRL & NOCYCCNT) == 0); +} + +bool +Dwt::isPRFCNT_Available() +{ + return((_regs->DWT_CTRL & NOPRFCNT) == 0); +} + +void +Dwt::enableCYCCNT() +{ + *_scb_demcr_regs |= TRCENA; +} + +void +Dwt::disableCYCCNT() +{ + *_scb_demcr_regs &= ~TRCENA; +} + +void +Dwt::setEvent(uint32_t ev) +{ + uint32_t tmp; + tmp = _regs->DWT_CTRL; + tmp &= ~EVENA_MASK; + tmp |= ev & EVENA_MASK; + _regs->DWT_CTRL = tmp; +} + +/// ICNT = CNT_CYCLES + CNT_FOLD - (CNT_LSU + CNT_EXC + CNT_SLEEP + CNT_CPI) +uint32_t +Dwt::getInstructionCount() +{ + uint32_t cnt_cycles = getCYCCNT(); + uint32_t cnt_fold = getFOLDCNT(); + uint32_t cnt_lsu = getLSUCNT(); + uint32_t cnt_exc = getEXCCNT(); + uint32_t cnt_sleep = getSLEEPCNT(); + uint32_t cnt_cpi = getCPICNT(); + return(cnt_cycles + cnt_fold - (cnt_lsu + cnt_exc + cnt_sleep + cnt_cpi)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Dwt.h Sun Oct 08 05:51:12 2017 +0000 @@ -0,0 +1,177 @@ +/** + * DWT class + */ +#ifndef DWT_H +#define DWT_H + +/** + * The Data Watchpoint and Trace unit intarface + * + * @code + * #include "mbed.h" + * #include "Dwt.h" + * + * Serial pc(SERIAL_TX, SERIAL_RX); + * Dwt dwt; + * + * int main() { + * uint32_t t; + * uint32_t n; + * + * dwt.enableCYCCNT(); + * dwt.resetCYCCNT(); + * dwt.startCount(); + * <Write some codes to measure the execution cycle here.> + * dwt.stopCount(); + * t = dwt.getCYCCNT(); + * n = dwt.getInstructionCount(); + * pc.printf("%d cycles, %d instructions.\n", t, n); + * } + * @endcode + */ +#define DWT_MAJOR_VERSION (0) +#define DWT_MINOR_VERSION (1) + +class Dwt +{ + /** + * The Data Watchpoint and Trace unit intarface + */ +public: + + /** + * Create a DWT interface + */ + Dwt(); + + /// Returns whether the implementation supports trace sampling and exception tracing. + /// true : Trace sampling and exception tracing supported. + /// false : Trace sampling and exception tracing not supported. + bool isTRCPKT_Available(); + /// Returns whether the implementation includes external match signals, CMPMATCH[N]. + bool isEXTTRIG_Available(); + /// Returns whether the implementation supports a cycle counter. + bool isCYCCNT_Available(); + /// Returns whether the implementation supports the profiling counters. + bool isPRFCNT_Available(); + + void enableCYCCNT(); + void disableCYCCNT(); + inline void startCYCCNT() { + _regs->DWT_CTRL |= CYCCNTENA; + } + inline void stopCYCCNT() { + _regs->DWT_CTRL &= ~CYCCNTENA; + } + inline void resetCYCCNT() { + _regs->DWT_CYCCNT = 0; + } + inline uint32_t getCYCCNT() { + return(_regs->DWT_CYCCNT); + } + inline uint32_t readDwtCtrl() { + return(_regs->DWT_CTRL); + } + inline uint32_t getNumComp() { + return((_regs->DWT_CTRL & NUMCOMP_MASK) >> NUMCOMP_POS); + } + void setEvent(uint32_t ev); + inline uint32_t getEvent() { + return(_regs->DWT_CTRL & EVENA_MASK); + } + /// Returns additional cycles required to execute multicycle instructions and + /// instruction fetch stalls. + inline uint32_t getCPICNT() { + return(_regs->DWT_CPICNT); + } + /// Returns the total cycles spent in exception processing. + inline uint32_t getEXCCNT() { + return(_regs->DWT_EXCCNT); + } + /// Returns the total number of cycles that the processor is sleeping. + inline uint32_t getSLEEPCNT() { + return(_regs->DWT_SLEEPCNT); + } + /// Returns the additional cycles required to execute all load or + /// store instructions. + inline uint32_t getLSUCNT() { + return(_regs->DWT_LSUCNT); + } + /// Returns the number of instructions that takes 0 cycles. + inline uint32_t getFOLDCNT() { + return(_regs->DWT_FOLDCNT); + } + /// start all counters + inline void startCount() { + _regs->DWT_CTRL |= (Dwt::CPIEVTENA | Dwt::EXCEVTENA | Dwt::SLEEPEVTENA | + Dwt::LSUEVTENA | Dwt::FOLDEVTENA | Dwt::CYCCNTENA); + } + /// stop all counters + inline void stopCount() { + _regs->DWT_CTRL &= ~(Dwt::CPIEVTENA | Dwt::EXCEVTENA | Dwt::SLEEPEVTENA | + Dwt::LSUEVTENA | Dwt::FOLDEVTENA | Dwt::CYCCNTENA); + } + /// Returns number of executed instructions. + uint32_t getInstructionCount(); +private: + typedef struct { + uint32_t DWT_COMP; ///< Provides a reference value for use by + ///< comparator n. + uint32_t DWT_MASK; ///< Provides the size of the ignore mask applied + ///< to the access address for address range + ///< matching by comparator n. + uint32_t DWT_FUNCTION; ///< Controls the operation of comparator n. + uint32_t reserved; + } dwt_cmp_regs_t; + + typedef struct { + uint32_t DWT_CTRL; ///< Control register + uint32_t DWT_CYCCNT; ///< Shows or sets the value of the processor + ///< cycle counter, CYCCNT. + uint32_t DWT_CPICNT; ///< Counts additional cycles required to execute + ///< multicycle instructions and instruction + ///< fetch stalls. + uint32_t DWT_EXCCNT; ///< Counts the total cycles spent in exception + ///< processing. + uint32_t DWT_SLEEPCNT; ///< Counts the total number of cycles that the + ///< processor is sleeping. + uint32_t DWT_LSUCNT; ///< Increments on the additional cycles required + ///< to execute all load or store instructions. + uint32_t DWT_FOLDCNT; ///< Increments on each instruction that takes 0 + ///< cycles. + uint32_t DWT_PCSR; ///< Samples the current value of the program + ///< counter. + dwt_cmp_regs_t regs[16]; + } dwt_regs_t; + + static const uint32_t DWT_REGS_ADDR; + static const uint32_t SCB_DEMCR_ADDR; + + static const uint32_t NUMCOMP_POS; + static const uint32_t NUMCOMP_MASK; + static const uint32_t NOTRCPKT; + static const uint32_t NOEXTTRIG; + static const uint32_t NOCYCCNT; + static const uint32_t NOPRFCNT; +public: + static const uint32_t CYCEVTENA; /// Enables POSTCNT underflow Event counter packets generation. + static const uint32_t FOLDEVTENA; /// Enables generation of the Folded-instruction counter overflow event. + static const uint32_t LSUEVTENA; /// Enables generation of the LSU counter overflow event. + static const uint32_t SLEEPEVTENA; /// Enables generation of the Sleep counter overflow event. + static const uint32_t EXCEVTENA; /// Enables generation of the Exception overhead counter overflow event: + static const uint32_t CPIEVTENA; /// Enables generation of the CPI counter overflow event. + static const uint32_t EXCTRCENA; /// Enables generation of the CPI counter overflow event. + static const uint32_t PCSAMPLENA; /// Enables use of POSTCNT counter as a timer for Periodic PC sample packet generation. + static const uint32_t CYCCNTENA; /// Enables CYCCNT. + +private: + static const uint32_t TRCENA; + static const uint32_t EVENA_MASK; + +private: + volatile dwt_regs_t *_regs; + volatile uint32_t *_scb_demcr_regs; +}; + + +#endif /* DWT_H */