我目前正在尝试使用 ARM Cortex-a9(在 Xilinx zynq EPP 上)上的事件计数器来计算周期。为此,我从 ARM 改编了一些 ARM 示例代码。我正在使用 GNU ARM EABI 编译器对这个裸机进行编程。
我理解使用 PMU 的方式是您首先必须启用 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"
);
}
然后您将性能计数器配置为计算某种类型的事件(0x11
在这种情况下为周期)
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
}
然后你启用事件计数器
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
}
在此之后,您立即重置事件计数器
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
}
你让你的应用程序运行并读取事件计数器
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;
}
然后你禁用事件计数器
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
}
和 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"
);
}
但是,当我尝试读取存储在事件计数器中的值时,我得到 0。我知道我的 PMU 配置正确,因为我能够PMCCNTR
毫无问题地读取循环计数器 ( )。我配置计数器的方式或读取它的方式可能存在问题。这种内联汇编的东西对我来说很新,所以如果有人能指出我正确的方向,我将永远感激不尽。