source: rtems/c/src/lib/libbsp/arm/tms570/misc/cpucounterread.c @ d13ce75

4.115
Last change on this file since d13ce75 was d13ce75, checked in by Pavel Pisa <pisa@…>, on 08/22/14 at 15:20:46

bsp/tms570: implemented and tested initialization of Cortex-R performance counters.

The code is written as BSP specific now but it should work for all
Cortex-A and R based CPUs and can be moved to ARM generic place in future.

StackOverflow? suggested sequences of writes to the registers required
to start counters is used.

http://stackoverflow.com/questions/3247373/how-to-measure-program-execution-time-in-arm-cortex-a8-processor

  • Property mode set to 100644
File size: 2.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup tms570_clocks
5 *
6 * @brief Cortex-R performace counters
7 *
8 * The counters setup functions are these which has been suggested
9 * on StackOverflow
10 *
11 * Code is probably for use on Cortex-A without modifications as well.
12 *
13 * http://stackoverflow.com/questions/3247373/how-to-measure-program-execution-time-in-arm-cortex-a8-processor
14 */
15
16/*
17 * Copyright (c) 2014 Pavel Pisa <pisa@cmp.felk.cvut.cz>
18 *
19 * Czech Technical University in Prague
20 * Zikova 1903/4
21 * 166 36 Praha 6
22 * Czech Republic
23 *
24 * The license and distribution terms for this file may be
25 * found in the file LICENSE in this distribution or at
26 * http://www.rtems.org/license/LICENSE.
27 */
28
29#include <stdlib.h>
30
31#include <rtems.h>
32#include <bsp.h>
33
34static int cpu_counter_initialized;
35
36
37/**
38 * @brief set mode of Cortex-R performance counters
39 *
40 * Based on example found on http://stackoverflow.com
41 *
42 * @param[in] do_reset if set, values of the counters are reset
43 * @param[in] enable_divider if set, CCNT counts clocks divided by 64
44 * @retval Void
45 */
46static inline void _CPU_Counter_init_perfcounters(
47    int32_t do_reset,
48    int32_t enable_divider
49)
50{
51  /* in general enable all counters (including cycle counter) */
52  int32_t value = 1;
53
54  /* peform reset */
55  if (do_reset)
56  {
57    value |= 2;     /* reset all counters to zero */
58    value |= 4;     /* reset cycle counter to zero */
59  }
60
61  if (enable_divider)
62    value |= 8;     /* enable "by 64" divider for CCNT */
63
64  value |= 16;
65
66  /* program the performance-counter control-register */
67  asm volatile ("mcr p15, 0, %0, c9, c12, 0\t\n" :: "r"(value));
68
69  /* enable all counters */
70  asm volatile ("mcr p15, 0, %0, c9, c12, 1\t\n" :: "r"(0x8000000f));
71
72  /* clear overflows */
73  asm volatile ("mcr p15, 0, %0, c9, c12, 3\t\n" :: "r"(0x8000000f));
74}
75
76/**
77 * @brief initialize Cortex-R performance counters subsystem
78 *
79 * Based on example found on http://stackoverflow.com
80 *
81 * @retval Void
82 *
83 */
84static void _CPU_Counter_initialize(void)
85{
86  rtems_interrupt_level level;
87
88  rtems_interrupt_disable(level);
89
90  if ( cpu_counter_initialized ) {
91    rtems_interrupt_enable(level);
92    return;
93  }
94
95  /* enable user-mode access to the performance counter */
96  asm volatile ("mcr p15, 0, %0, c9, c14, 0\n\t" :: "r"(1));
97
98  /* disable counter overflow interrupts (just in case) */
99  asm volatile ("mcr p15, 0, %0, c9, c14, 2\n\t" :: "r"(0x8000000f));
100
101  _CPU_Counter_init_perfcounters(false, false);
102
103  cpu_counter_initialized = 1;
104
105  rtems_interrupt_enable(level);
106}
107
108/**
109 * @brief returns the actual value of Cortex-R cycle counter register
110 *
111 * The register is incremented at each core clock period
112 *
113 * @retval x actual core clock counter value
114 *
115 */
116CPU_Counter_ticks _CPU_Counter_read(void)
117{
118  uint32_t ticks;
119  if ( !cpu_counter_initialized ) {
120    _CPU_Counter_initialize();
121  }
122  asm volatile ("mrc p15, 0, %0, c9, c13, 0\n": "=r" (ticks));
123  return ticks;
124}
Note: See TracBrowser for help on using the repository browser.