From 180107e971e1cc83570c38fe73d7077bd570ab21 Mon Sep 17 00:00:00 2001 From: Christian Mauderer Date: Mon, 30 Jan 2017 11:33:31 +0100 Subject: 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 16a6b83262..afef7daa09 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 16e971f85a..7d2581879f 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 0a69363c7f..a6cc8a34ac 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 ); -- cgit v1.2.3