This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
The _pmuInit_ assembly function in the sys_pmu.asm file generated by HALCoGen 04.03.00 for a RM46L852PGE is the following:
_pmuInit_ stmfd sp!, {r0} ; set control register mrc p15, #0, r0, c9, c12, #0 orr r0, r0, #(1 << 4) + 6 + 1 mcr p15, #0, r0, c9, c12, #0 ; clear flags mov r0, #0 sub r0, r0, #1 mcr p15, #0, r0, c9, c12, #3 ; select counter 0 event mcr p15, #0, r0, c9, c12, #5 ; select counter mov r0, #0x11 mcr p15, #0, r0, c9, c13, #1 ; select event ; select counter 1 event mov r0, #1 mcr p15, #0, r0, c9, c12, #5 ; select counter mov r0, #0x11 mcr p15, #0, r0, c9, c13, #1 ; select event ; select counter 2 event mov r0, #2 mcr p15, #0, r0, c9, c12, #5 ; select counter mov r0, #0x11 mcr p15, #0, r0, c9, c13, #1 ; select event ldmfd sp!, {r0} bx lr .endasmfunc
Looking at the code, I think the section to "select counter 0 event" is not setting the r0 register to the correct value for counter zero before writing to the Performance Counter Selection Register. From single stepping the assembler the code which is supposed to be selecting the counter 0 event ends up writing b00011 to the Performance Counter Selection Register which is not a valid value for the Cortex R4F (valid values are b00000 to b00010 for counters 0 to 2):
The code should be corrected to set r0 to zero to select counter zero:
_pmuInit_ stmfd sp!, {r0} ; set control register mrc p15, #0, r0, c9, c12, #0 orr r0, r0, #(1 << 4) + 6 + 1 mcr p15, #0, r0, c9, c12, #0 ; clear flags mov r0, #0 sub r0, r0, #1 mcr p15, #0, r0, c9, c12, #3 ; select counter 0 event mov r0, #0 mcr p15, #0, r0, c9, c12, #5 ; select counter mov r0, #0x11 mcr p15, #0, r0, c9, c13, #1 ; select event ; select counter 1 event mov r0, #1 mcr p15, #0, r0, c9, c12, #5 ; select counter mov r0, #0x11 mcr p15, #0, r0, c9, c13, #1 ; select event ; select counter 2 event mov r0, #2 mcr p15, #0, r0, c9, c12, #5 ; select counter mov r0, #0x11 mcr p15, #0, r0, c9, c13, #1 ; select event ldmfd sp!, {r0} bx lr
There also appears to be errors in how the Performance Counter Selection Register is written by the _pmuSetCountEvent_ and _pmuGetEventCount_ functions. These functions are documented in the generated sys_pmu.h as taking a counter parameter with the range 0..2:
/** @fn void _pmuSetCountEvent_(uint32 counter, uint32 event) * @brief Set event counter count event * @param[in] counter - Counter select 0..2 * @param[in] event - Count event */ void _pmuSetCountEvent_(uint32 counter, uint32 event); /** @fn uint32 _pmuGetEventCount_(uint32 counter) * @brief Returns current event counter value * @param[in] counter - Counter select 0..2 * * @return event counter count. */ uint32 _pmuGetEventCount_(uint32 counter);
However, looking at the assembler in the generated sys_pmu.asm shows an initial lsr instruction which left-shifts the counter parameter by one bit before writing to the Performance Counter Selection Register:
.def _pmuSetCountEvent_ .asmfunc _pmuSetCountEvent_ lsr r0, r0, #1 mcr p15, #0, r0, c9, c12, #5 ; select counter mcr p15, #0, r1, c9, c13, #1 ; select event bx lr .endasmfunc
.def _pmuGetEventCount_ .asmfunc _pmuGetEventCount_ lsr r0, r0, #1 mcr p15, #0, r0, c9, c12, #5 ; select counter mrc p15, #0, r0, c9, c13, #2 ; read event counter bx lr .endasmfunc
To correct the error, the lsr instruction should be removed from the generated functions, I.e. the code should be:
.def _pmuSetCountEvent_ .asmfunc _pmuSetCountEvent_ mcr p15, #0, r0, c9, c12, #5 ; select counter mcr p15, #0, r1, c9, c13, #1 ; select event bx lr .endasmfunc .def _pmuGetCycleCount_ .asmfunc _pmuGetCycleCount_ mrc p15, #0, r0, c9, c13, #0 bx lr .endasmfunc
Chester,
Thanks you very much for the post. I have passed your post to the Halcogen team and they will get back to you shortly. By the way, I have used the attached code for setting up and using PMUin performance evaluation. They seem to work fine.
Thanks and regards,
Zhaohong
I have installed HALCoGen 04.04.00 and confirm that the _pmuInit_ and _pmuSetCountEvent_ functions have been fixed.Prathap said:It is fixed in 4.04.00 release which is due 7th April. .
However, the _pmuGetEventCount_ function still has the incorrect lsr r0, r0, #1 instruction:
.def _pmuGetEventCount_ .asmfunc _pmuGetEventCount_ lsr r0, r0, #1 mcr p15, #0, r0, c9, c12, #5 ; select counter mrc p15, #0, r0, c9, c13, #2 ; read event counter bx lr .endasmfunc
I now realize there was an error in my previous post, in that I didn't list the corrected _pmuGetEventCount_ function, which is:
.def _pmuGetEventCount_ .asmfunc _pmuGetEventCount_ mcr p15, #0, r0, c9, c12, #5 ; select counter mrc p15, #0, r0, c9, c13, #2 ; read event counter bx lr .endasmfunc