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/CC2640R2F: how to prevent the compile optimize a block of code?

Part Number: CC2640R2F

Tool/software: TI C/C++ Compiler: TI v18.12.3.LTS of CCS 9.2.0.00013

the code block not to be optimized:

    GPIO_setOutputEnableDio(IOID_8, GPIO_OUTPUT_ENABLE); //HWREGBITW( GPIO_BASE + GPIO_O_DOE31_0, IOID_8 ) = GPIO_OUTPUT_ENABLE; //
    GPIO_setOutputEnableDio(IOID_8, GPIO_OUTPUT_DISABLE);//HWREGBITW( GPIO_BASE + GPIO_O_DOE31_0, IOID_8 ) = GPIO_OUTPUT_DISABLE; //
    IOCIOInputSet(IOID_8, IOC_INPUT_ENABLE); //gpioEnableInputBuf(Board_DIO8);
    scifTaskData.task0.output.buzz = GPIO_readDio(IOID_8); //gpioGetInputValue(Board_DIO8; output.buzz);
    //GPIO_clearDio(IOID_8); //gpioClearOutput(Board_DIO8);
    IOCIOInputSet(IOID_8, IOC_INPUT_DISABLE); //gpioDisableInputBuf(Board_DIO8);

if the project optimization is set to none, the code work as expected. with any optimization , the code does not work as expected. it seems the 1st line of the first 2 lines was optimized off, but this 2 lines are critical for the code to work,as the 1st line is to charge a capacitor and the 2nd line is to discharge the capacitor, so that a great change of a serial resistor could be detected.

and optimization for code size is prefered, so only need to prevent the compiler from optimizing several lines of code.

the related functions defined in the sdk:

__STATIC_INLINE void
GPIO_setOutputEnableDio( uint32_t dioNumber, uint32_t outputEnableValue )
{
    // Check the arguments.
    ASSERT( dioNumberLegal( dioNumber ));
    ASSERT(( outputEnableValue == GPIO_OUTPUT_DISABLE ) ||
           ( outputEnableValue == GPIO_OUTPUT_ENABLE  )    );

    // Update the output enable bit for the specified DIO.
    HWREGBITW( GPIO_BASE + GPIO_O_DOE31_0, dioNumber ) = outputEnableValue;
}


__STATIC_INLINE void
GPIO_setOutputEnableDio( uint32_t dioNumber, uint32_t outputEnableValue )
{
    // Check the arguments.
    ASSERT( dioNumberLegal( dioNumber ));
    ASSERT(( outputEnableValue == GPIO_OUTPUT_DISABLE ) ||
           ( outputEnableValue == GPIO_OUTPUT_ENABLE  )    );

    // Update the output enable bit for the specified DIO.
    HWREGBITW( GPIO_BASE + GPIO_O_DOE31_0, dioNumber ) = outputEnableValue;
}

  • put ”#pragma FUNCTION_OPTIONS(sensorTrig, "-Ooff")“ before the function definition does compile but still not work. the 2 lines get  optimized off again in the asm code.

  • For the source file which contains ...

    ke fan said:
    the code block not to be optimized:

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

    Thanks and regards,

    -George

  • the test case pp source code

    problem_file.c.txt

  • there's volatile key word for HWREG, the volatile should prevent optimization of the data.

    //*****************************************************************************
    //
    // Macros for direct hardware access.
    //
    // If using these macros the programmer should be aware of any limitations to
    // the address accessed i.e. if it supports word and/or byte access.
    //
    //*****************************************************************************
    // Word (32 bit) access to address x
    // Read example  : my32BitVar = HWREG(base_addr + offset) ;
    // Write example : HWREG(base_addr + offset) = my32BitVar ;
    #define HWREG(x)                                                              \
            (*((volatile unsigned long *)(x)))
    
    
    //*****************************************************************************
    //
    // Macros for hardware access to bit-band supported addresses via the bit-band region.
    //
    // Macros calculate the corresponding address to access in the bit-band region
    // based on the actual address of the memory/register and the bit number.
    //
    // Do NOT use these macros to access the bit-band region directly!
    //
    //*****************************************************************************
    // Bit-band access to address x bit number b using word access (32 bit)
    #define HWREGBITW(x, b)                                                       \
            HWREG(((unsigned long)(x) & 0xF0000000) | 0x02000000 |                \
                  (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))
    

  • Thank you for the preprocessed source code.  Next time, instead of copying 50,000 lines into a single post, please attach a file.  Use the paper clip icon.  That is much easier to handle.  I changed your post so the source code is now in an attached file.

    Unfortunately, I am unable to reproduce the problem.  No matter what I try, when I inspect the resulting assembly code, I see something similar to the following ...

            MOVS      A1, #8                ; [DPU_V7M3_PIPE] |49874| 
            MOVS      A2, #1                ; [DPU_V7M3_PIPE] |49874| 
            BL        GPIO_setOutputEnableDio ; [DPU_V7M3_PIPE] |49874| 
            ; CALL OCCURS {GPIO_setOutputEnableDio }  ; [] |49874| 
            MOVS      A1, #8                ; [DPU_V7M3_PIPE] |49876| 
            MOVS      A2, #0                ; [DPU_V7M3_PIPE] |49876| 
            BL        GPIO_setOutputEnableDio ; [DPU_V7M3_PIPE] |49876| 
    

    This code does not inline the calls to the function GPIO_setOutputEnableDio.  Instead, an out-of-line function is generated, and this code calls that function two times.  

    However, I had to guess at the build options.  Please show exactly how the compiler is invoked.

    Thanks and regards,

    -George

  • thank you and sorry for the trouble. had first tried several times attachment, but always failed, maybe there's bug in browser or web.

    this is message in console after building the file:

    "D:\\ti\\ccs920\\ccs\\utils\\bin\\gmake" -k -j 8 Application/beacon_nortos.obj -O 
     
    Building file: "../Application/beacon_nortos.c"
    Invoking: ARM Compiler
    "D:/ti/ccs920/ccs/tools/compiler/ti-cgt-arm_18.12.3.LTS/bin/armcl" -mv7M3 --code_state=16 --float_support=none -me -O4 --opt_for_speed=0 --include_path="D:/ti/workspace_v9_2/lkirws_nortos_ccs" --include_path="D:/ti/simplelink_cc2640r2_sdk_3_30_00_20/source/ti/devices/cc26x0r2" --include_path="D:/ti/simplelink_cc2640r2_sdk_3_30_00_20/source" --include_path="D:/ti/simplelink_cc2640r2_sdk_3_30_00_20/kernel/nortos" --include_path="D:/ti/simplelink_cc2640r2_sdk_3_30_00_20/kernel/nortos/posix" --include_path="D:/ti/ccs920/xdctools_3_60_01_27_core/packages" --include_path="D:/ti/workspace_v9_2" --include_path="D:/ti/workspace_v9_2/rfs/CC2640R2_RSM/smartrf_settings" --include_path="D:/ti/ccs920/ccs/tools/compiler/ti-cgt-arm_18.12.3.LTS/include" --advice:power="1,2,3,4,5,7,9,10,12" --define=NORTOS --define=DISABLE_DCDC --define=sensor=11 --define=xRSM_USE_SC --define=xRSM_USE_TRIG --define=road=2 --define=uartlog_FILE="\"beacon_nortos.c\"" --define=xUARTLOG_ENABLE --define=Display_DISABLE_ALL --define=DeviceFamily_CC26X0R2 --define=CC26XX --define=CC26XX_R2 --define=POWER_SAVING --define=RF_SINGLEMODE --define=USE_DEFAULT_USER_CFG --define=xdc_runtime_Assert_DISABLE_ALL --define=xdc_runtime_Log_DISABLE_ALL --define=RSM_USE_BUZZ --preproc_with_comment --preproc_with_compile --obj_directory="Application"  "../Application/beacon_nortos.c"

    the objdump -D -S beacon_nortos.obj shows what the same as your posted:

    00000102 <sensorTrig>:
     102:   b580            push    {r7, lr}
     104:   4869            ldr     r0, [pc, #420]  ; (2ac <mainThread+0x76>)
     106:   4968            ldr     r1, [pc, #416]  ; (2a8 <mainThread+0x72>)
     108:   8800            ldrh    r0, [r0, #0]
     10a:   8008            strh    r0, [r1, #0]
     10c:   2008            movs    r0, #8
     10e:   2101            movs    r1, #1
     110:   f7ff fffe       bl      0 <GPIO_setOutputEnableDio>
     114:   2008            movs    r0, #8
     116:   2100            movs    r1, #0
     118:   f7ff fffe       bl      0 <GPIO_setOutputEnableDio>
     11c:   2008            movs    r0, #8
     11e:   f04f 5100       mov.w   r1, #536870912  ; 0x20000000
     122:   f7ff fffe       bl      0 <NOROM_IOCIOInputSet>
    

    but the objdump for the project out file shows:

        scifTaskData.task0.state.buzz = scifTaskData.task0.output.buzz;
         810:       8930            ldrh    r0, [r6, #8]
         812:       81b0            strh    r0, [r6, #12]
        IOCIOInputSet(IOID_8, IOC_INPUT_ENABLE); //gpioEnableInputBuf(Board_DIO8);
         814:       f04f 5100       mov.w   r1, #536870912  ; 0x20000000
        ASSERT( dioNumberLegal( dioNumber ));
        ASSERT(( outputEnableValue == GPIO_OUTPUT_DISABLE ) ||
               ( outputEnableValue == GPIO_OUTPUT_ENABLE  )    );
    
        // Update the output enable bit for the specified DIO.
        HWREGBITW( GPIO_BASE + GPIO_O_DOE31_0, dioNumber ) = outputEnableValue;
         818:       603d            str     r5, [r7, #0]
         81a:       2008            movs    r0, #8
         81c:       603c            str     r4, [r7, #0]
         81e:       f003 fef5       bl      460c <NOROM_IOCIOInputSet>
        return (( HWREG( GPIO_BASE + GPIO_O_DIN31_0 ) >> dioNumber ) & 1 );
         822:       f8d8 0000       ldr.w   r0, [r8]
        IOCIOInputSet(IOID_8, IOC_INPUT_DISABLE); //gpioDisableInputBuf(Board_DIO8);
         826:       4621            mov     r1, r4
         828:       f3c0 2000       ubfx    r0, r0, #8, #1
        scifTaskData.task0.output.buzz = GPIO_readDio(IOID_8); //gpioGetInputValue(Board_DIO8; output.buzz);
         82c:       8130            strh    r0, [r6, #8]
        IOCIOInputSet(IOID_8, IOC_INPUT_DISABLE); //gpioDisableInputBuf(Board_DIO8);
         82e:       2008            movs    r0, #8
         830:       f003 feec       bl      460c <NOROM_IOCIOInputSet>
        scifTaskData.task0.output.buzz ^= 1;
    

    and debugging could not set breakpoint at the 2 lines of GPIO_setOutputEnableDio, the breakpoint is automatically disabled and seems being optimized away. set breakpiont 1 line over the 2 lines and when breaked, the disassembly window showed:

    238           scifTaskData.task0.state.buzz = scifTaskData.task0.output.buzz;
              $C$L8:
    00000810:   8930                ldrh       r0, [r6, #8]
    00000812:   81B0                strh       r0, [r6, #0xc]
    244           IOCIOInputSet(IOID_8, IOC_INPUT_ENABLE); //gpioEnableInputBuf(Board_DIO8);
    00000814:   F04F5100            mov.w      r1, #0x20000000
    487           HWREGBITW( GPIO_BASE + GPIO_O_DOE31_0, dioNumber ) = outputEnableValue;
    00000818:   603D                str        r5, [r7]
    244           IOCIOInputSet(IOID_8, IOC_INPUT_ENABLE); //gpioEnableInputBuf(Board_DIO8);
    0000081a:   2008                movs       r0, #8
    487           HWREGBITW( GPIO_BASE + GPIO_O_DOE31_0, dioNumber ) = outputEnableValue;
    0000081c:   603C                str        r4, [r7]
    244           IOCIOInputSet(IOID_8, IOC_INPUT_ENABLE); //gpioEnableInputBuf(Board_DIO8);
    0000081e:   F003FEF5            bl         #0x460c
    177           return (( HWREG( GPIO_BASE + GPIO_O_DIN31_0 ) >> dioNumber ) & 1 );
    00000822:   F8D80000            ldr.w      r0, [r8]
    247           IOCIOInputSet(IOID_8, IOC_INPUT_DISABLE); //gpioDisableInputBuf(Board_DIO8);
    00000826:   4621                mov        r1, r4
    177           return (( HWREG( GPIO_BASE + GPIO_O_DIN31_0 ) >> dioNumber ) & 1 );
    00000828:   F3C02000            ubfx       r0, r0, #8, #1
    245           scifTaskData.task0.output.buzz = GPIO_readDio(IOID_8); //gpioGetInputValue(Board_DIO8; output.buzz);
    0000082c:   8130                strh       r0, [r6, #8]
    247           IOCIOInputSet(IOID_8, IOC_INPUT_DISABLE); //gpioDisableInputBuf(Board_DIO8);
    0000082e:   2008                movs       r0, #8
    00000830:   F003FEEC            bl         #0x460c
    249           scifTaskData.task0.output.buzz ^= 1;

    but

  • I'm not sure what is happening.  Here is my guess.

    You build with -O4.  This means there is optimization which occurs during the link.  That is, optimization happens after the initial compile of the file beacon_nortos.c.  It is possible the function GPIO_setOutputEnableDio is inlined.  Instead of calls to that function, the code inside the function appears instead, with the arguments replaced where necessary.  That is probably why ...

    ke fan said:
    debugging could not set breakpoint at the 2 lines of GPIO_setOutputEnableDio

    I'm not clear on where you set your breakpoint, but it appears to be a completely different location.  Try setting a breakpoint at the start of the function sensorTrig, and see if my guess about inlining GPIO_setOutputEnableDio is right.

    Thanks and regards,

    -George

  • the compiler does not optimized the block of code,how to prevent linker from optimizing the block of code?

  • I'm still confused.  I wonder if this isn't just a problem related to setting a breakpoint in optimized code.  Try setting a breakpoint only at the very first instruction of sensorTrig.  Then repeatedly run from one breakpoint to another.  Does the code behave correctly?  Or, set no breakpoints at all.  Does the code behave correctly?

    Thanks and regards,

    -George

  • it seem with -O4 the linker optimized the compiled file further for the project out file,the linker seems optimized off the bl instructions in the compiled object file. no breakpoint at all, the code does not behave as with optimization off. the breakpoint was set at the very first instruction of sensorTrig: "scifTaskData.task0.state.buzz = scifTaskData.task0.output.buzz;", the breakpoint was set for step into the assembly code to check the optimized assembly code. the attached is the objdump output of the project out file with -O4: o4.c

  • I searched the objdump output for the symbol name sensorTrig.  It isn't there.  I don't understand.  Shouldn't I see that name?

    Thanks and regards,

    -George

  • it seems that both the sensorTrig function and its calling function named sensorTask were inlined by the linker into the function named mainThread, since the first statement of sensorTrig function is "scifTaskData.task0.state.buzz = scifTaskData.task0.output.buzz;", and it is in the function named mainThread. and the operations of the GPIO IOID8 follows that statment, but the operations is out of sequence which is critical: IOCIOInputSet(IOID_8, IOC_INPUT_ENABLE) is called first, but it is "HWREGBITW( GPIO_BASE + GPIO_O_DOE31_0, dioNumber ) = outputEnableValue;" should be the first operation, and there should be 2 times operation ""HWREGBITW( GPIO_BASE + GPIO_O_DOE31_0, dioNumber ) = outputEnableValue;" with different outputEnableValues, but there's only 1 such operation left by the linker. it seems the linker deem the first of 2 consecutive such GPIO operations is useless and get rid of the first such operation. but both 2 such operations do have external effects for the sensor to work and should not be omitted. 

        913     scifTaskData.task0.state.buzz = scifTaskData.task0.output.buzz;
        914      810:       8930            ldrh    r0, [r6, #8]
        915      812:       81b0            strh    r0, [r6, #12]
        916     IOCIOInputSet(IOID_8, IOC_INPUT_ENABLE); //gpioEnableInputBuf(Board_DIO8);
        917      814:       f04f 5100       mov.w   r1, #536870912  ; 0x20000000
        918     ASSERT( dioNumberLegal( dioNumber ));
        919     ASSERT(( outputEnableValue == GPIO_OUTPUT_DISABLE ) ||
        920            ( outputEnableValue == GPIO_OUTPUT_ENABLE  )    );
        921
        922     // Update the output enable bit for the specified DIO.
        923     HWREGBITW( GPIO_BASE + GPIO_O_DOE31_0, dioNumber ) = outputEnableValue;
        924      818:       603d            str     r5, [r7, #0]
        925      81a:       2008            movs    r0, #8
        926      81c:       603c            str     r4, [r7, #0]
        927      81e:       f003 fef5       bl      460c <NOROM_IOCIOInputSet>
        928     return (( HWREG( GPIO_BASE + GPIO_O_DIN31_0 ) >> dioNumber ) & 1 );
        929      822:       f8d8 0000       ldr.w   r0, [r8]
        930     IOCIOInputSet(IOID_8, IOC_INPUT_DISABLE); //gpioDisableInputBuf(Board_DIO8);
        931      826:       4621            mov     r1, r4
        932      828:       f3c0 2000       ubfx    r0, r0, #8, #1
        933     scifTaskData.task0.output.buzz = GPIO_readDio(IOID_8); //gpioGetInputValue(Board_DIO8; output.buzz);
        934      82c:       8130            strh    r0, [r6, #8]
        935     IOCIOInputSet(IOID_8, IOC_INPUT_DISABLE); //gpioDisableInputBuf(Board_DIO8);
        936      82e:       2008            movs    r0, #8
        937      830:       f003 feec       bl      460c <NOROM_IOCIOInputSet>
        938     scifTaskData.task0.output.buzz ^= 1;
    

    compaired with what the "objdump -D -S beacon_nortos.obj" showed:

    00000102 <sensorTrig>:
     102:   b580            push    {r7, lr}
     104:   4869            ldr     r0, [pc, #420]  ; (2ac <mainThread+0x76>)
     106:   4968            ldr     r1, [pc, #416]  ; (2a8 <mainThread+0x72>)
     108:   8800            ldrh    r0, [r0, #0]
     10a:   8008            strh    r0, [r1, #0]
     10c:   2008            movs    r0, #8
     10e:   2101            movs    r1, #1
     110:   f7ff fffe       bl      0 <GPIO_setOutputEnableDio>
     114:   2008            movs    r0, #8
     116:   2100            movs    r1, #0
     118:   f7ff fffe       bl      0 <GPIO_setOutputEnableDio>
     11c:   2008            movs    r0, #8
     11e:   f04f 5100       mov.w   r1, #536870912  ; 0x20000000
     122:   f7ff fffe       bl      0 <NOROM_IOCIOInputSet>

  • I will contact you by private message.

    Thanks and regards,

    -George

  • Activity on this thread continues in private messages.  When it is resolved, I will post a summary here.

    Thanks and regards,

    -George

  • At higher levels of optimization, accesses to a memory mapped peripheral occurred only two CPU instructions apart.  This was too fast for the peripheral.  I recommended adding calls to the compiler intrinsic __delay_cycles.  I am confident that solves the problem, though I have not received confirmation of that.

    Thanks and regards,

    -George

  • thank you very much! he function with __delay_cycles used with rearrangement of instructions works fine as expected。