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.

Compiler optimizations

Other Parts Discussed in Thread: TMS320F28069

Hi,

I am working on a motion control project for TMS320F28069 using CCS6.1.2 compiler 6.4.9. Without optimizations everything works fine.

Now I am trying to optimize my code for speed. Using highest levels --opt_level4 and -- opt_for_speed5, produces some unwanted behavior. Specifically, in a part of C code, which prepares a buffer for SCI transmission and finally enables a transmit interrupt, in the final code generated by the compiler, enabling the interrupt occurs a few lines before finalizing the buffer pointer causing occasionally transmitting bytes outside of the buffer. The C code looks like this:

Return_Status = Defined_Status;

// send the checksum and start Tx

// buffer is almost ready, just need to set the pointer and start transmission

TXbytes++;

*TXpointer = checksum;

TXpointer = TXbuffer;

TXENA;       // #define TXENA SciaRegs.SCIFFTX.bit.TXFFIENA = 1

TXpointer and TXbuffer are volatile as well as SciaRegs.

This is the code from disassembly window during debug:

        C$L493:
00d799:   9208        MOV          AL, @0x8
2642      Return_Status = Defined_Status;
00d79a:   930A        MOV          AH, @0xa
2644      TXbytes++;
00d79b:   0A02        INC          @0x2
00d79c:   761F01C1    MOVW         DP, #0x1c1
2645      *TXpointer = checksum;
00d79e:   96C4        MOV          *+XAR4[0], AL
2647      LDCN_TXENA;
00d79f:   1A1A0020    OR           @0x1a, #0x0020
00d7a1:   761F04CE    MOVW         DP, #0x4ce
2646      TXpointer = TXbuffer;
00d7a3:   B20C        MOVL         @0xc, XAR1
2642      Return_Status = Defined_Status;
00d7a4:   9705        MOV          @0x5, AH

Looks like the generated code is randomly reordered (or at least I cannot find any reasonable explanation).

Now, I have so many questions about this and don't know where to start. Here are a few:

1. Is this a bug or am I missing something?

2. Is there a way to disable reordering at this particular place of my code or in the whole project?

3. What optimization settings allow this kind of reordering? I tried a few different optimization levels but run into random illegal interrupts and cannot figure out what part of the code is causing these.

4. What would you guys recommend to solve this problem?

Thank you in advance!

Vesko

  • The code is barely reordered at all. "Return_Status = Defined_Status" appears twice because the compiler had to issue two instructions for it and they drifted apart; I can't say why without a complete test case that reproduces the code. I don't see anything wrong with the code. I suspect that the bug is in the interrupt routine. Make sure it properly saves and restores every register it could possibly change, in particular DP.
  • Dear Archaeologist,
    Thank you for your answer!
    I understand that the two instructions (MOV AH, @0x0A and MOV @0x05, AH) do "Return_Status = Defined_Status" got separated so the second can use the data page from MOVW DP, #0x4ce. That is OK and makes sense.

    What is wrong (or what I do not like at all) is the fact that enabling the transmit interrupt (OR @0x1a, #0x0020) happens BEFORE setting up the pointer to the transmit buffer (TXpointer = TXbuffer -> MOVL @0xc, XAR1), which gives a chance for an interrupt before the pointer is set. I am sure the interrupt itself is correct - it works when the above code is in the intended order:
    ...
    TXpointer = TXbuffer;
    TXENA; // #define TXENA SciaRegs.SCIFFTX.bit.TXFFIENA = 1
    ...
    I can also confirm that the bytes are receive at the other end match the sequence in the Expressions window od the debugger starting at TXbuffer[ 10] (10 is where TXpointer points to prior to setting it to the start of TXbuffer.

    I just tried inserting DINT before and EINT after
    TXpointer = TXbuffer;
    TXENA; // #define TXENA SciaRegs.SCIFFTX.bit.TXFFIENA = 1

    It did not change the incorrect order of the two instruction but at least it works now.


    Still, I would like to get some more input from guys like you with more experience using compiler optimizations.

    Thanks again!
    Vesko
  • My guess is you are using volatile incorrectly.  To understand whether that guess is correct, we need to see a test case.  Please preprocess the C file which contains the problem function and attach that to your next post.  Also show the build options exactly as the compiler sees them.

    Thanks and regards,

    -George

  • You indicate that the pointer value TXpointer must be set properly before the interrupt, so TXpointer itself must be volatile. Make sure it is a volatile pointer to volatile memory. Make sure that TXbuffer is a volatile buffer.
  • As I stated in the original post, these two are volatile:
    volatile Uint16 TXbuffer [32];
    Uint16 *RXpointer;
    volatile Uint16 *TXpointer;
    Is this what you mean?

    A more general question - Is there a pragma or something else that I can use to tell the compiler to not reorder a part of the source code?
    Thank you,
    Vesko
  • Hi George,
    Sorry for the stupid questions.

    1. How do I attach a file?

    2. I generated the ".pp" file (File settings -> Parser Preprocessing Options - M0de: manual, Preprocess only) but it only contains a list of include files like bellow. Is this what you need?
    ...
    ldcn_comm.obj: ../ldcn_comm.c
    ldcn_comm.obj: D:/4Work/Software/DSP/LS231G_062.612/PM_Sensorless/Includes/F2806x_Cla_defines.h
    ldcn_comm.obj: ../target_CLA.h
    ldcn_comm.obj: ../target.h
    ldcn_comm.obj: D:/4Work/Software/DSP/LS231G_062.612/PM_Sensorless/Includes/F2806x_Device.h

    3. Can you please explain to me what you mean by "using volatile incorrectly"? I have a pointer and a buffer:
    volatile Uint16 TXbuffer [32];
    volatile Uint16 *TXpointer;
    and using:
    volatile struct SCI_REGS SciaRegs;
    from F2806x_GlobalValiableDefs.c.
    What could be wrong and how a wrong or correct use would change the reordering behavior of the compiler?

    4. Is there a pragma or something that can change the optimization settings for a part of a source file?

    5. What optimization levels enable this reordering?

    Thank you in advance!

    Regards,
    Vesko
  • Vesko Vitchev said:
    1. How do I attach a file?

    The interface for composing a forum post has icon that looks like a paper clip.  Use that.  Most file extensions, including .pp, are rejected.  Add ".txt" to the end of the file name.

    Vesko Vitchev said:
    2. I generated the ".pp" file (File settings -> Parser Preprocessing Options - M0de: manual, Preprocess only) but it only contains a list of include files like bellow. Is this what you need?

    No.  That file appears in the Debug directory (or whatever the current build configuration is named).  You want the .pp file that is in the same directory as the original C source file.

    Vesko Vitchev said:
    3. Can you please explain to me what you mean by "using volatile incorrectly"? I have a pointer and a buffer:
    volatile Uint16 TXbuffer [32];

    I suspect you need to change ...

    Vesko Vitchev said:
    volatile Uint16 *TXpointer;

    to ...

    volatile Uint16 * volatile TXpointer;

    But I need a test case I can build to be sure.

    Vesko Vitchev said:
    4. Is there a pragma or something that can change the optimization settings for a part of a source file?

    There is a #pragma FUNCTION_OPTIONS which can do that.  But I don't think you should worry that yet.

    Vesko Vitchev said:
    5. What optimization levels enable this reordering?

    Any of them.  But the higher the optimization level, the more likely it is you will see code reordering.

    Thanks and regards,

    -George

  • test_tx.pp.txtHi George,

    Thank you for the information!

    The default interface of reply to post does not have the rich formatting (and attaching files). That is what got me confused.

    Anyway, I am attaching the .pp file.

    Here is again the code I see in the disassembly window during debug:

    37        *TXpointer++ = Temp;
    01043d:   90FF        ANDB         AL, #0xff
    01043e:   93A9        MOV          AH, @AL
    01043f:   92A6        MOV          AL, @AR6
    38       checksum += Temp;
    010440:   94A8        ADD          AL, @AH
    37        *TXpointer++ = Temp;
    010441:   97E5        MOV          *+XAR5[4], AH
    41       TXbytes++;
    010442:   0A10        INC          @0x10
    010443:   761F01C1    MOVW         DP, #0x1c1
    42       *TXpointer = checksum;
    010445:   96ED        MOV          *+XAR5[5], AL
    44       SciaRegs.SCIFFTX.bit.TXFFIENA = 1;                       <-
    010446:   1A1A0020    OR           @0x1a, #0x0020               <- this instruction ...
    010448:   761F04C1    MOVW         DP, #0x4c1
    43       TXpointer = TXbuffer;
    01044a:   A012        MOVL         @0x12, XAR5

                                                                                                    <- ... should be here
    01044b:   0006        LRETR       

    Regards,

    Vesko

  • I cannot reproduce this result ...

    Vesko Vitchev said:

    010446:   1A1A0020    OR           @0x1a, #0x0020               <- this instruction ...
    010448:   761F04C1    MOVW         DP, #0x4c1
    43       TXpointer = TXbuffer;
    01044a:   A012        MOVL         @0x12, XAR5

                                                                                                    <- ... should be here
    01044b:   0006        LRETR       

    But I had to guess at your build options.  Please show the build options exactly as the compiler sees them.

    Thanks and regards,

    -George

  • Hi George,

    Here is the output from compiling the file and linking the project:

    "D:\\CCSv62\\ccsv6\\utils\\bin\\gmake" -k all
    'Building file: ../test_tx.c'
    'Invoking: C2000 Compiler'
    "D:/CCSv62/ccsv6/tools/compiler/ti-cgt-c2000_6.4.9/bin/cl2000" -v28 -ml --vcu_support=vcu0 --cla_support=cla0 --float_support=fpu32 -O4 --opt_for_speed=5 --include_path="D:/CCSv62/ccsv6/tools/compiler/ti-cgt-c2000_6.4.9/include" --include_path="D:/4Work/Software/DSP/LS231G_062.612t/Test/Includes" --advice:performance=all -g --gen_acp_raw --define="FLASH" --define=CNC_SAFETY=1 --define=CSM_LOCKED=0 --define="_DEBUG" --define="LARGE_MODEL" --define="FLOATING_MATH" --define=AMPLIFIER=1 --quiet --diag_warning=225 --gen_opt_info=2 --asm_listing --asm_define=FLASH_RUN=1  "../test_tx.c"
    'Finished building: ../test_tx.c'
    ' '
    'Building target: Test_F2806x.out'
    'Invoking: C2000 Linker'
    "D:/CCSv62/ccsv6/tools/compiler/ti-cgt-c2000_6.4.9/bin/cl2000" -v28 -ml --vcu_support=vcu0 --cla_support=cla0 --float_support=fpu32 -O4 --opt_for_speed=5 --advice:performance=all -g --gen_acp_raw --define="FLASH" --define=CNC_SAFETY=1 --define=CSM_LOCKED=0 --define="_DEBUG" --define="LARGE_MODEL" --define="FLOATING_MATH" --define=AMPLIFIER=1 --quiet --diag_warning=225 --gen_opt_info=2 --asm_listing --asm_define=FLASH_RUN=1 -z -m"Test_F2806x.map" --stack_size=0x380 --warn_sections -i"D:/CCSv62/ccsv6/tools/compiler/ti-cgt-c2000_6.4.9/lib" -i"D:/4Work/Software/DSP/LS231G_062.612t/Test" -i"D:/CCSv62/ccsv6/tools/compiler/ti-cgt-c2000_6.4.9/include" --reread_libs --xml_link_info="Test_F2806x_linkInfo.xml" --rom_model -o "Test_F2806x.out" "D:/4Work/Software/DSP/LS_Include/Kits/libs/math/FPUfastRTS/V100/lib/rts2800_fpu32_fast_supplement.lib" -l"rts2800_fpu32.lib" "D:/4Work/Software/DSP/LS_Include/Kits/libs/math/IQmath/v15c/lib/IQmath_fpu32.lib" "./CCD_camera.obj" "./CLA_shared.obj" "./CodeStartBranch.obj" "./DSP28xxx_SectionCopy_nonBIOS.obj" "./EEprom.obj" "./F2806x_GlobalVariableDefs.obj" "./F2806x_usDelay.obj" "./Flash2806x_API.obj" "./Flash2806x_CsmKeys.obj" "./IO.obj" "./IOcla.obj" "./LDCN.obj" "./PIDFilter.obj" "./PM_Sensorless-DevInit_F2806x.obj" "./Test.obj" "./Passwords.obj" "./Planner.obj" "./QEP.obj" "./Serial_Encoder.obj" "./Trajectory.obj" "./f2806xpwm_PM.obj" "./f2806xpwmdac_PM.obj" "./ldcn_comm.obj" "./ldcn_comm_io.obj" "./rampgen.obj" "./test_tx.obj" "../2806x_BootROM_API_TABLE_Symbols_fpu32.lib" "D:/4Work/Software/DSP/LS_Include/Kits/libs/math/CLAmath/v400/lib/CLAmath_fpu32.lib" "../F28069_nonBIOS_flash.cmd" "../F2806x_Headers_nonBIOS.cmd" 
    'Finished building target: Test_F2806x.out'
    ' '

    Regards,

    Vesko

  • Thank you for showing the build options.  I can reproduce the same assembly output.  I filed SDSCM00052800 in the SDOWP system to have this investigated.  You are welcome to follow it with the SDOWP link below in my signature.

    Thanks and regards,

    -George

  • You must declare TXpointer as volatile:

    volatile Uint16 * volatile TXpointer;

    Without the second volatile, it only points to volatile memory, and is not itself volatile.