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.

CCS/MSP432P4111: Two variables mapped on same register with compiler optimization

Part Number: MSP432P4111

Tool/software: Code Composer Studio

Hello,

I'm writing code on msp432 with CCS 8.3.1.00004 and TI compiler v19.6.0 STS.

My application needs to fit in 4000hex size in flash so I have no other choice but using compiler optimization in order to reduce final size code.

Today I am encountering a weird issue. I need to make a LED blink, I quickly write a very simple code to do the job where I need it.

My issue : I does work when optimization is set to "off" at approximately 10Hz, with 10% duty cycle. But when I set for example, lv 0 register optimization, the frequency goes up to 50kHz, 50% duty cycle.

I tried to debug step by step and the software jump over the loop, I had some watches and I see something weird, two variables are mapped on the same register ! I put an instruction into the loop to be sure the optimization doesn't skip something, And the variable on the same register decrease together... I don't understand the situation, and my friend google too.

I succed to override the optimization for that specific function with #pragma and adding volatile to all variables. I don't like my workaround and it seems that my coworker have the same issue with a bigger software on the same MSP/compiler.

I make a big screenshot to show you what I said :

- the code vdBlinkRedLed() on the top right corner ;

- watches on top left ;

- the disassembly view with optimization on the left ;

- the disassembly view with my workaround on the right ;

Does anybody know what happened here ? thanks

  • I'm not sure, but I suspect one or more variables must be marked volatile.  Please put the source file updater.c in the state before these kinds of changes were made ...

    Clement COLLE said:
    I succed to override the optimization for that specific function with #pragma and adding volatile to all variables.

    Then follow the directions in the article How to Submit a Compiler Test Case.

    Thanks and regards,

    -George

  • File uploaded, let me know if you need somehing else !

    thank you

    updater.pp.txt

  • A delay loop like ...

    for (u32IteratorTick=u32LedTicks2 ; u32IteratorTick>0 ; u32IteratorTick--);

    ... gets optimized away.  Replace it with a call to the __delay_cycles intrinsic.  For example ...

     __delay_cycles(15000);
    

    Please search for __delay_cycles in the ARM compiler manual.

    Thanks and regards,

    -George

  • Thank you, I didn't know __delay_cycles. It will be useful.

    However I might be wrong, but I think the main issue remain.

    When I first tried to solvethe situation by myself , I put instructions in the loop in order to avoid the simple delay loop.

    I just repeat the same test to be sure and share with you (screenshot and preproc file attached).

    Yes, the code is meaningless, it is just to force the compiler to do something correct with my loop.

    As you can see, although my loop is not a delay loop anymore, two variables are in the same register and in step by step we can see them decreasing together.

    0172.updaterV2.pp.txt

  • Please show the compiler build options.  Rebuild your project, then copy-n-paste the complete invocation of the compiler on the source file updater.c.

    Thanks and regards,

    -George

  • Clement COLLE said:
    As you can see, although my loop is not a delay loop anymore, two variables are in the same register and in step by step we can see them decreasing together.

    In the vdBlinkRedLed function the variables u32IteratorTick and u32LedTicks1 have both been assigned to register R3 by the optimiser.

    The only reference to the u32LedTicks1 variable in the function is the following which sets the initial value of u32IteratorTick for the loop:

           for (u32IteratorTick=u32LedTicks1 ; u32IteratorTick>0 ; u32IteratorTick--)

    Therefore, by the optimiser assigning both variables to the same register I can't see that the generated code is incorrect. However, this is one example where debugging optimised code can be confusing since local variables which don't have overlapping lifetimes can validly share the same register.

  • The explanation from Chester Gillon is probably correct.  Nonetheless, I'd appreciate if you would send the information I requested in my previous post.  That will allow me to check and be sure.

    Thanks and regards,

    -George

  • Hello George,

    I'm sorry for the delay, I was very busy with an other urgent work.

    Building file: "../updater/updater.c"
    Invoking: ARM Compiler
    "C:/ti/ccsv8/tools/compiler/ti-cgt-arm_19.6.0.STS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O0 --opt_for_speed=0 --include_path="C:/Users/CLC/Documents/Workspace/UNI V2/Logiciel/448_boot_univ2" --include_path="C:/ti/ccsv8/ccs_base/arm/include/CMSIS" --include_path="C:/ti/ccsv8/ccs_base/arm/include" --include_path="C:/Users/CLC/Documents/Workspace/UNI V2/Logiciel/448_boot_univ2/DriverLib" --include_path="C:/ti/ccsv8/tools/compiler/ti-cgt-arm_19.6.0.STS/include" --advice:power=all --define=ccs --define=__MSP432P4111__ -g --gcc --preproc_with_comment --preproc_with_compile --diag_warning=225 --diag_wrap=off --display_error_number --abi=eabi --obj_directory="updater"  "../updater/updater.c"
    "../updater/updater.c", line 19: remark #2623-D: (ULP 5.4) Detected an assignment to a type with size less than int. To avoid unnecessary sign extension, use int-sized types for local varaibles and convert to smaller types for static storage.
    "../updater/updater.c", line 88: remark #1543-D: (ULP 12.2) Detected for loop with repetitive data transfer. Recommend using DMA
    "../updater/updater.c", line 94: remark #1543-D: (ULP 12.2) Detected for loop with repetitive data transfer. Recommend using DMA
    Finished building: "../updater/updater.c"

    I used a scope in the morning and I made some timing tests:

    u32LedTicks1 = 150000;
    u32LedTicks2 = 150000;
    → On time on the LED pin : 18.2µs

    u32LedTicks1 = 150000;
    u32LedTicks2 = 15000;
    → On time on the LED pin : 18.2µs

    u32LedTicks1 = 15000;
    u32LedTicks2 = 150000;
    → On time on the LED pin : 18.2µs

    u32LedTicks1 = 15000;
    u32LedTicks2 = 15000;
    → On time on the LED pin : 17.4µs

    It is possible that I miss something, but I think something is wrong with the generated code.

    Thank you for your help !

  • Thank you for the build options and compiler version.  I can confirm that the explanation by Chester Gillon is correct.  There is no evidence the compiler has made any errors.

    Clement COLLE said:
    I used a scope in the morning and I made some timing tests:

    I'm sorry, but I don't know how to interpret that.  Please describe the behavior in terms of what the code does.  For instance, does each loop iterate the correct number of times?

    More important than anything else ... Why haven't you changed to the code to use the __delay_cycles intrinsic instead of the for loops?  That will probably fix your problem.

    Thanks and regards,

    -George