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.

Writing same value to PWM registers is slow

Expert 2730 points


I'm writing the same value to 4 PWM registers. The code which the compailer makes is not very sensful to me.

        MOVW      DP,#_Period
        MOVL      ACC,@_Period          ; |191|
        MOVW      DP,#_EPwm3Regs+42
        MOVL      @_EPwm3Regs+42,ACC    ; |191|
    .dwpsn    file "../source/Interrupt.c",line 192,column 2,is_stmt
        MOVW      DP,#_Period
        MOVL      ACC,@_Period          ; |192|
        MOVW      DP,#_EPwm4Regs+42
        MOVL      @_EPwm4Regs+42,ACC    ; |192|
    .dwpsn    file "../source/Interrupt.c",line 193,column 2,is_stmt
        MOVW      DP,#_Period
        MOVL      ACC,@_Period          ; |193|
        MOVW      DP,#_EPwm5Regs+42
        MOVL      @_EPwm5Regs+42,ACC    ; |193|
    .dwpsn    file "../source/Interrupt.c",line 194,column 2,is_stmt
        MOVW      DP,#_Period
        MOVL      ACC,@_Period          ; |194|
        MOVW      DP,#_EPwm6Regs+42
        MOVL      @_EPwm6Regs+42,ACC    ; |194|

Why it is always loading the same value to ACC? If the value in ACC is already correct why to load it again? I also tried to put this Period to temporay value.

        MOVW      DP,#_Period
        MOVL      ACC,@_Period          ; |189|
        MOVL      *-SP[2],ACC           ; |189|
       .dwpsn    file "../source/Interrupt.c",line 191,column 2,is_stmt
        MOVL      ACC,*-SP[2]           ; |191|
        MOVL      @_EPwm3Regs+42,ACC    ; |191|
    .dwpsn    file "../source/Interrupt.c",line 192,column 2,is_stmt
        MOVW      DP,#_EPwm4Regs+42
        MOVL      ACC,*-SP[2]           ; |192|
        MOVL      @_EPwm4Regs+42,ACC    ; |192|
    .dwpsn    file "../source/Interrupt.c",line 193,column 2,is_stmt
        MOVW      DP,#_EPwm5Regs+42
        MOVL      ACC,*-SP[2]           ; |193|
        MOVL      @_EPwm5Regs+42,ACC    ; |193|
    .dwpsn    file "../source/Interrupt.c",line 194,column 2,is_stmt
        MOVW      DP,#_EPwm6Regs+42
        MOVL      ACC,*-SP[2]           ; |194|
        MOVL      @_EPwm6Regs+42,ACC    ; |194|

Then I can reduce one cycle from every writing because now it is using -SP[2]. Period is defined as global but not volatile. I don't have any optimitzation. Should I have to make this more quickly? How to optimization goes with the CCS4? The options seems to be different from 3.3. I'm asking this because I have to write to 14 registers at this interrupt and this alone will take ~1us. It's quite a lot if running on 270kHz.

  • JHi,

    In the first code sample, since Period is volatile the compiler is forced to read its value every time it is referenced. This is how volatile works - because it tells the compiler the value can change outside of the current context and no access will be optimized out.

    For the 2nd code sample - If the temp value is not volatile then I see no reason why the compiler should keep reading it.  I am going to move this thread to the compiler forum so the experts there can take a look.

    -Lori

  • JHi said:

    [..] I don't have any optimitzation. Should I have to make this more quickly? [..]

    Yes.  If speed is a concern, you should always use optimization, at least -O0.   It looks like your temporary variable is being stored in *-SP[2].  If you use optimization at any level, this variable will most likely live in a register and you won't have these redundant loads.

     

  • Lori Heustess said:

    JHi,

    In the first code sample, since Period is volatile the compiler is forced to read its value every time it is referenced. This is how volatile works - because it tells the compiler the value can change outside of the current context and no access will be optimized out.

    For the 2nd code sample - If the temp value is not volatile then I see no reason why the compiler should keep reading it.  I am going to move this thread to the compiler forum so the experts there can take a look.

    -Lori

    As I wrote in my post: The Period is defined as global and NOT volatile.

    And then maybe a stupid question: how dow I use optimization in CCS4? Optimization for speed doesn't remove this problem and I can't find this -o option from CCS4. Or do I just have to add this -o to compiler options by my self and there is no more a choice for it?

    Edit: I found the optimization and if I use Period as it is, nothing changes, but If I introduce this temporary value then it will work as it should. I wonder why it can't optimize it in first place? Here is the optimized code where I have introduced temporary value.

            MOVW      DP,#_Period
            MOVL      ACC,@_Period          ; |189|
         .dwpsn    file "../source/Interrupt.c",line 191,column 2,is_stmt
            MOVL      @_EPwm3Regs+42,ACC    ; |191|
        .dwpsn    file "../source/Interrupt.c",line 192,column 2,is_stmt
            MOVW      DP,#_EPwm4Regs+42
            MOVL      @_EPwm4Regs+42,ACC    ; |192|
        .dwpsn    file "../source/Interrupt.c",line 193,column 2,is_stmt
            MOVW      DP,#_EPwm5Regs+42
            MOVL      @_EPwm5Regs+42,ACC    ; |193|
        .dwpsn    file "../source/Interrupt.c",line 194,column 2,is_stmt
            MOVW      DP,#_EPwm6Regs+42
            MOVL      @_EPwm6Regs+42,ACC    ; |194|

  • The -O option I refer to is also called --opt_level.  You should see this option on the basic options tab in CCS.  You must use --opt_level with at least 0 to turn on most optimization.  There is another option, -mf (also known as --opt_for_speed) which does not turn on those optimizations but instead specifies a size/speed tradeoff goal.