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.

Errors in setting the Performance Counter Selection Register in HALCoGen 04.03.00?

Other Parts Discussed in Thread: HALCOGEN

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.

    8726.sys_pmu.asm

    Thanks and regards,

    Zhaohong

  • Hi Chester,

    It is fixed in 4.04.00 release which is due 7th April. .

  • Prathap said:
    It is fixed in 4.04.00 release which is due 7th April. .

    I have installed HALCoGen 04.04.00 and confirm that the _pmuInit_ and _pmuSetCountEvent_ functions have been fixed.

    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