[rtems commit] bsps/arm: Fix Cortex-M DWT CPU counter.

Sebastian Huber sebh at rtems.org
Mon Jan 30 10:36:04 UTC 2017


Module:    rtems
Branch:    master
Commit:    180107e971e1cc83570c38fe73d7077bd570ab21
Changeset: http://git.rtems.org/rtems/commit/?id=180107e971e1cc83570c38fe73d7077bd570ab21

Author:    Christian Mauderer <Christian.Mauderer at embedded-brains.de>
Date:      Mon Jan 30 11:33:31 2017 +0100

bsps/arm: Fix Cortex-M DWT CPU counter.

It is necessary to enable the DWT using a special initialization
sequence before the CYCCNT can be enabled. See for example the
RESET_CYCLE_COUNTER in libbsp/arm/atsam/utils/utility.h.

Note that this problem only occurs if no debugger is connected. A
debugger most likely already enables the necessary module.

---

 .../arm/shared/armv7m/clock/armv7m-clock-config.c  |  8 ++--
 .../arm/shared/armv7m/startup/armv7m-cpucounter.c  |  8 ++--
 cpukit/score/cpu/arm/rtems/score/armv7m.h          | 46 +++++++++++++++++++++-
 3 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c b/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c
index 16a6b83..afef7da 100644
--- a/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c
+++ b/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c
@@ -123,7 +123,6 @@ static void _ARMV7M_Systick_handler_install(void)
 
 static void _ARMV7M_Systick_initialize(void)
 {
-  volatile ARMV7M_DWT *dwt = _ARMV7M_DWT;
   volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
   #ifdef BSP_ARMV7M_SYSTICK_FREQUENCY
     uint64_t freq = BSP_ARMV7M_SYSTICK_FREQUENCY;
@@ -132,7 +131,7 @@ static void _ARMV7M_Systick_initialize(void)
   #endif
   uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
   uint64_t interval = (freq * us_per_tick) / 1000000ULL;
-  uint32_t dwt_ctrl;
+  bool cyccnt_enabled;
 
   systick->rvr = (uint32_t) interval;
   systick->cvr = 0;
@@ -140,9 +139,8 @@ static void _ARMV7M_Systick_initialize(void)
     | ARMV7M_SYSTICK_CSR_TICKINT
     | ARMV7M_SYSTICK_CSR_CLKSOURCE;
 
-  dwt_ctrl = dwt->ctrl;
-  if ((dwt_ctrl & ARMV7M_DWT_CTRL_NOCYCCNT) == 0) {
-    dwt->ctrl = dwt_ctrl | ARMV7M_DWT_CTRL_CYCCNTENA;
+  cyccnt_enabled = _ARMV7M_DWT_Enable_CYCCNT();
+  if (cyccnt_enabled) {
     _ARMV7M_TC.base.tc.tc_get_timecount = _ARMV7M_TC_dwt_get_timecount;
     _ARMV7M_TC.base.tc.tc_counter_mask = 0xffffffff;
     _ARMV7M_TC.base.tc.tc_frequency = freq;
diff --git a/c/src/lib/libbsp/arm/shared/armv7m/startup/armv7m-cpucounter.c b/c/src/lib/libbsp/arm/shared/armv7m/startup/armv7m-cpucounter.c
index 16e971f..7d25818 100644
--- a/c/src/lib/libbsp/arm/shared/armv7m/startup/armv7m-cpucounter.c
+++ b/c/src/lib/libbsp/arm/shared/armv7m/startup/armv7m-cpucounter.c
@@ -28,12 +28,11 @@ CPU_Counter_ticks _CPU_Counter_read(void)
 
 static void armv7m_cpu_counter_initialize(void)
 {
-  volatile ARMV7M_DWT *dwt = _ARMV7M_DWT;
-  uint32_t dwt_ctrl;
+  bool cyccnt_enabled;
 
-  dwt_ctrl = dwt->ctrl;
+  cyccnt_enabled = _ARMV7M_DWT_Enable_CYCCNT();
 
-  if ((dwt_ctrl & ARMV7M_DWT_CTRL_NOCYCCNT) == 0) {
+  if (cyccnt_enabled) {
     #ifdef BSP_ARMV7M_SYSTICK_FREQUENCY
       uint64_t freq = BSP_ARMV7M_SYSTICK_FREQUENCY;
     #else
@@ -41,7 +40,6 @@ static void armv7m_cpu_counter_initialize(void)
       uint64_t freq = ARMV7M_SYSTICK_CALIB_TENMS_GET(systick->calib) * 100ULL;
     #endif
 
-    dwt->ctrl = dwt_ctrl | ARMV7M_DWT_CTRL_CYCCNTENA;
     rtems_counter_initialize_converter(freq);
   } else {
     bsp_fatal(BSP_ARM_ARMV7M_CPU_COUNTER_INIT);
diff --git a/cpukit/score/cpu/arm/rtems/score/armv7m.h b/cpukit/score/cpu/arm/rtems/score/armv7m.h
index 0a69363..a6cc8a3 100644
--- a/cpukit/score/cpu/arm/rtems/score/armv7m.h
+++ b/cpukit/score/cpu/arm/rtems/score/armv7m.h
@@ -93,7 +93,7 @@ typedef struct {
   uint32_t foldcnt;
   uint32_t pcsr;
   ARMV7M_DWT_comparator comparator[249];
-  uint32_t reserved_e0001fb0[1];
+#define ARMV7M_DWT_LAR_UNLOCK_MAGIC 0xc5acce55U
   uint32_t lar;
   uint32_t lsr;
 } ARMV7M_DWT;
@@ -347,6 +347,26 @@ typedef struct {
     0 \
   }
 
+typedef struct {
+  uint32_t dhcsr;
+  uint32_t dcrsr;
+  uint32_t dcrdr;
+#define ARMV7M_DEBUG_DEMCR_VC_CORERESET (1U << 0)
+#define ARMV7M_DEBUG_DEMCR_VC_MMERR (1U << 4)
+#define ARMV7M_DEBUG_DEMCR_VC_NOCPERR (1U << 5)
+#define ARMV7M_DEBUG_DEMCR_VC_CHKERR (1U << 6)
+#define ARMV7M_DEBUG_DEMCR_VC_STATERR (1U << 7)
+#define ARMV7M_DEBUG_DEMCR_VC_BUSERR (1U << 8)
+#define ARMV7M_DEBUG_DEMCR_VC_INTERR (1U << 9)
+#define ARMV7M_DEBUG_DEMCR_VC_HARDERR (1U << 10)
+#define ARMV7M_DEBUG_DEMCR_MON_EN (1U << 16)
+#define ARMV7M_DEBUG_DEMCR_MON_PEND (1U << 17)
+#define ARMV7M_DEBUG_DEMCR_MON_STEP (1U << 18)
+#define ARMV7M_DEBUG_DEMCR_MON_REQ (1U << 19)
+#define ARMV7M_DEBUG_DEMCR_TRCENA (1U << 24)
+  uint32_t demcr;
+} ARMV7M_DEBUG;
+
 #define ARMV7M_DWT_BASE 0xe0001000
 #define ARMV7M_SCS_BASE 0xe000e000
 #define ARMV7M_ICTAC_BASE (ARMV7M_SCS_BASE + 0x0)
@@ -354,6 +374,7 @@ typedef struct {
 #define ARMV7M_NVIC_BASE (ARMV7M_SCS_BASE + 0x100)
 #define ARMV7M_SCB_BASE (ARMV7M_SCS_BASE + 0xd00)
 #define ARMV7M_MPU_BASE (ARMV7M_SCS_BASE + 0xd90)
+#define ARMV7M_DEBUG_BASE (ARMV7M_SCS_BASE + 0xdf0)
 
 #define _ARMV7M_DWT \
   ((volatile ARMV7M_DWT *) ARMV7M_DWT_BASE)
@@ -367,6 +388,8 @@ typedef struct {
   ((volatile ARMV7M_NVIC *) ARMV7M_NVIC_BASE)
 #define _ARMV7M_MPU \
   ((volatile ARMV7M_MPU *) ARMV7M_MPU_BASE)
+#define _ARMV7M_DEBUG \
+  ((volatile ARMV7M_DEBUG *) ARMV7M_DEBUG_BASE)
 
 #define ARMV7M_VECTOR_MSP 0
 #define ARMV7M_VECTOR_RESET 1
@@ -535,6 +558,27 @@ static inline int _ARMV7M_NVIC_Get_priority( int irq )
   return _ARMV7M_NVIC->ipr [irq];
 }
 
+static inline bool _ARMV7M_DWT_Enable_CYCCNT( void )
+{
+  uint32_t demcr;
+  uint32_t dwt_ctrl;
+
+  demcr = _ARMV7M_DEBUG->demcr;
+  _ARMV7M_DEBUG->demcr = demcr | ARMV7M_DEBUG_DEMCR_TRCENA;
+  _ARM_Data_synchronization_barrier();
+
+  dwt_ctrl = _ARMV7M_DWT->ctrl;
+  if ((dwt_ctrl & ARMV7M_DWT_CTRL_NOCYCCNT) == 0) {
+    _ARMV7M_DWT->lar = ARMV7M_DWT_LAR_UNLOCK_MAGIC;
+    _ARM_Data_synchronization_barrier();
+    _ARMV7M_DWT->ctrl = dwt_ctrl | ARMV7M_DWT_CTRL_CYCCNTENA;
+    return true;
+  } else {
+    _ARMV7M_DEBUG->demcr = demcr;
+    return false;
+  }
+}
+
 int _ARMV7M_Get_exception_priority( int vector );
 
 void _ARMV7M_Set_exception_priority( int vector, int priority );



More information about the vc mailing list