I'm currently trying to use event counters on ARM Cortex-a9 (on Xilinx zynq EPP) to count the loops. For this purpose I adapted some ARM example code from ARM. I program this bare metal using the GNU ARM EABI compiler.
As I understand it, the use of PMU is that you must first enable the PMU.
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" ); }
then you set up a performance counter to count a specific type of event ( 0x11 for loops in this case)
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 }
Then you turn on the event counter
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");
after that you immediately reset the event counter
void reset_pmn(void){ asm volatile( "MRC p15, 0, r0, c9, c12, 0\n\t");
you start your application and read the event counter
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; }
and then you turn off the event counter
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");
and pmu.
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" ); }
However, when I try to read the value stored in the event counter, I get 0. I know that my PMU is configured correctly, because I can read the loop counter ( PMCCNTR ) without any problems. There is probably a problem with how I set up the counter or how I read it. This built-in compilation is quite new for me, so if someone can point me in the right direction, I will be forever grateful.