title: ARM Cortex-a9 event counters return 0
body: <p>I'm currently trying to use the event counters on an ARM Cortex-a9 (on a Xilinx zynq EPP) to count cycles. I've adapted some ARM example code from ARM for this purpose. I'm programming this bare-metal with the GNU ARM EABI compiler.</p>
  
  <p>The way I understand the use of the PMU is that you first have to enable the PMU.</p>
  
  <pre><code>void enable_pmu (void){
      asm volatile(   "MRC     p15, 0, r0, c9, c12, 0\n\t"
                      "ORR     r0, r0, #0x01\n\t"
                      "MCR     p15, 0, r0, c9, c12, 0\n\t"
      );
  }
  </code></pre>
  
  <p>then you configure the performance counter to count a certain type of event (<code>0x11</code>  for cycles in this case)</p>
  
  <pre><code>void config_pmn(unsigned counter,int event){
      asm volatile(   "AND     %[counter], %[counter], #0x1F\n\t" :: [counter] "r" (counter));    //Mask to leave only bits 4:0
      asm volatile(   "MCR     p15, 0, %[counter], c9, c12, 5\n\t" :: [counter] "r" (counter));   //Write PMSELR Register
      asm volatile(   "ISB\n\t");                                                                 //Synchronize context
      asm volatile(   "MCR     p15, 0, %[event], c9, c13, 1\n\t" :: [event] "r" (counter));       //Write PMXEVTYPER Register
  }
  </code></pre>
  
  <p>Then you enable the event counter</p>
  
  <pre><code>void enable_pmn(int counter){
      asm volatile(   "MOV     r1, #0x1\n\t");
      asm volatile(   "MOV     r1, r1, LSL %[counter]\n\t" :: [counter] "r" (counter));
      asm volatile(   "MCR     p15, 0, r1, c9, c12, 1\n\t");      //Write PMCNTENSET Register
  }
  </code></pre>
  
  <p>after this you immediately reset the event counter</p>
  
  <pre><code>void reset_pmn(void){
      asm volatile(   "MRC     p15, 0, r0, c9, c12, 0\n\t");  //Read PMCR
      asm volatile(   "ORR     r0, r0, #0x2\n\t");            //Set P bit (Event counter reset)
      asm volatile(   "MCR     p15, 0, r0, c9, c12, 0\n\t");  //Write PMCR
  }
  </code></pre>
  
  <p>you let your application run and read the event counter</p>
  
  <pre><code>int read_pmn(int counter){
      int value;
      asm volatile(   "AND     %0,%0, #0x1F\n\t" :: "r" (counter));          //Mask to leave only bits 4:0
      asm volatile(   "MCR     p15, 0, %[counter], c9, c12, 5\n\t" ::[counter] "r" (counter));        //Write PMSELR Register
      asm volatile(   "ISB\n\t");                                                                     //Synchronize context
      asm volatile(   "MRC     p15, 0,%[value] , c9, c13, 2\n\t" : [value] "=r" (value));                 //Read current PMNx Register
      return value;
  }
  </code></pre>
  
  <p>and then you disable the event counter</p>
  
  <pre><code>void disable_pmn(int counter){
       asm volatile(  "MOV     r1, #0x1\n\t");
       asm volatile(  "MOV     r1, r1, LSL %[counter] \n\t":: [counter] "r" (counter));
       asm volatile(  "MCR     p15, 0, r1, c9, c12, 2\n\t");  //Write PMCNTENCLR Register
  }
  </code></pre>
  
  <p>and the pmu.</p>
  
  <pre><code>void disable_pmu (void){
      asm volatile(   "MRC     p15, 0, r0, c9, c12, 0\n\t"
                      "BIC     r0, r0, #0x01\n\t"
                      "MCR     p15, 0, r0, c9, c12, 0\n\t"
      );
  }
  </code></pre>
  
  <p>However when I try to read the value stored in the event counter I get 0. I know my PMU is configured correctly because I'm able to read the cycle counter (<code>PMCCNTR</code>) without a problem. Probably there is a problem with the way I configure the counter or the way I read it. This inline assembly stuff is pretty new to me so if somebody can point me in the right direction I would be forever grateful.</p>