Hello ,all。I am now learning the use of PMU. But when I do this, PMXEVCNTR_EL0 is always 0. PMCCNTR_EL0 is normal
Device: cortex-a72(ARMV8.2-A)
System: Rtos(ThreadX)
step
1. Configure PMCNTENSET_EL0 to enable Cycle counter
2. Configure pmuserenr_el0(en).
3. Configure PMSELR_EL0 to select count.
4. Configure PMXEVTYPER_EL0 and set events.
5. Configure PMCNTENSET_EL0 to enable Cycle counter and event counter
6. Configure PMCR_EL0 and enable PMU, reset Cycle counter, and event counter
7. Run the test code
8 Stop the PMUs
9. Configure PMSELR_EL0 to select count,
10 Read PMXEVCNTR_EL0 and PMCCNTR_EL0.
result
PMXEVCNTR_EL0 is 0, and PMCCNTR_EL0 is normal
I have checked the value of the relevant register, and the value of the register is indeed changed. I have checked the Arm® Cortex®-A76 Core Technical Reference Manual, and all the events set are also supported.
Note: The code is running in firmware.code:void ARM_PMU_Start(void) { // PMU->CTRL |= PMU_CTRL_ENABLE_Msk;
int val=0;
__asm__ volatile("msr pmuserenr_el0, %0" :: "r" ((1 << 0) | (1 << 2)));
__asm__ volatile("msr PMSELR_EL0, %0" : : "r" (0)); __asm__ volatile("isb" : :); __asm__ volatile("msr PMXEVTYPER_EL0, %0" : : "r" (0x2)); __asm__ volatile("isb" : :);
__asm__ volatile("msr PMSELR_EL0, %0" : : "r" (1)); __asm__ volatile("isb" : :); __asm__ volatile("msr PMXEVTYPER_EL0, %0" : : "r" (0x4)); __asm__ volatile("isb" : :);
__asm__ volatile("msr PMSELR_EL0, %0" : : "r" (2)); __asm__ volatile("isb" : :); __asm__ volatile("msr PMXEVTYPER_EL0, %0" : : "r" (0x6)); __asm__ volatile("isb" : :); __asm__ volatile("msr PMCNTENSET_EL0, %0" : : "r" ((7|(1<<31)))); __asm__ volatile("isb" : :);
__asm__ volatile("mrs %0, PMCR_EL0" : "=r" (val)); val|=1 << 0; val|=1 << 1; val|=1 << 2; __asm__ volatile("msr PMCR_EL0, %0" : : "r" (val)); __asm__ volatile("isb" : :);
}void ARM_PMU_Stop(){ int val=0; __asm__ volatile("mrs %0, pmcr_el0" : "=r" (val)); __asm__ volatile("msr pmcr_el0, %0" : : "r" (val&(~PMU_CTRL_ENABLE_Msk))); __asm__ volatile("mrs %0, pmccntr_el0" : "=r" (val)); printf("Perf:pmccntr_el0 %d \n",val);
__asm__ volatile("msr PMSELR_EL0, %0" : : "r" (0)); __asm__ volatile("isb" : :); __asm__ volatile("mrs %0, PMXEVCNTR_EL0" : "=r" (val)); printf("Perf:PMXEVCNTR_EL0 %d \n",val);
__asm__ volatile("msr PMSELR_EL0, %0" : : "r" (1)); __asm__ volatile("isb" : :); __asm__ volatile("mrs %0, PMXEVCNTR_EL0" : "=r" (val)); printf("Perf:PMXEVCNTR_EL0 %d \n",val);
__asm__ volatile("msr PMSELR_EL0, %0" : : "r" (2)); __asm__ volatile("isb" : :); __asm__ volatile("mrs %0, PMXEVCNTR_EL0" : "=r" (val)); printf("Perf:PMXEVCNTR_EL0 %d \n",val);}void Test_PMU(){ ARM_PMU_Start(); test_code();//the test code ARM_PMU_Stop(); }
Here you should also enable both event counts & cycle counter read feature.From the code "__asm__ volatile("msr pmuserenr_el0, %0" :: "r" ((1 << 0) | (1 << 2)))", we saw that you have enabled CR & EN feature. I think you should also set the ER(bit 3) to make event counters read enabled.
I try to enable read feature, but it still return 0 for event counter, any other suggestion?
I did that, but the register is still 0