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/TM4C1290NCPDT: Out of order execution in debug mode

Part Number: TM4C1290NCPDT


Tool/software: Code Composer Studio

Hi,

I am using CCS version 10.1.0.00010 with TivaC EK-TM4C1294XL LaunchPad under Windows 10 x64 professional.

I have noticed that when I step through my code in debug mode, the code execution path is not in the order written in source code. I guess there is some sort of optimization going on. However, it's pretty misleading, for example I noticed the code seems to execute  GPIOPinRead before a previous GPIOPinTypeGPIOInput. This makes debugging pretty confusing. I would appreciate any clarification.

Thanks,

Sam

  • Hi Sam,

    Sam Frank said:
    I guess there is some sort of optimization going on.

    This is highly likely. 

    https://dev.ti.com/tirex/explore/node?node=AA6fEd9YTSwdDSyHdoLE9Q__FUz-xrs__LATEST

    What is the optimization level being used?

    Thanks

    ki

  • Hi Ki,

    The optimization level is 2 in debug build.

    Sam

  • Yes, -o2 is fairly aggressive and it is at this stage where source line debug starts getting pretty difficult.

  • I turned optimization off and stepping through the code follows the source code. However, it's pretty strange to see that GPIOPinRead is executed before GPIOPinTypeGPIOInput with -o2 optimization! Does code composer studio follow accurately the code execution in the processor when optimization is enabled?

    Thanks,

    Sam

  • I am not an optimizer expert but it is not unusual to see code seemingly executed out of order (for optimized code). In the link I sent:

    • Does single stepping proceed through the code exactly as written? Or, does it skip around in seemingly random order?

    You can't rely on source line debugging for heavily optimized code.

  • ok, Thanks!

    Sam

  • Sam Frank said:
    However, it's pretty strange to see that GPIOPinRead is executed before GPIOPinTypeGPIOInput with -o2 optimization!

    The optimizer is allowed to re-order instructions which don't change the observed behaviour. For a source statement which has a function call there may be several instructions generated. The optimizer may re-order instructions which perform "setup" operations for the function call, e.g. loading registers, while still correctly performing the actual function calls in the source order.

    E.g. took the following example source:

    void main(void)
    {
        SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOJ);
        while (!SysCtlPeripheralReady (SYSCTL_PERIPH_GPIOJ))
        {
        }
        GPIOPinTypeGPIOInput (GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        GPIOPadConfigSet (GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
        switch_inputs = GPIOPinRead (GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    }

    When compiler using TI ARM compiler v20.2.2 using -O2, then when source stepping in CCS 10.1 the apparent order of source statements were executed in was:

    • SysCtlPeripheralReady
    • SysCtlPeripheralEnable
    • SysCtlPeripheralReady
    • GPIOPinRead
    • GPIOPinTypeGPIOInput
    • GPIOPadConfigSet
    • GPIOPinRead

    I.e. source stepping showed a confusing order.

    The Disassembly view in the CCS debugger showed the following for source statements interleaved with the generated instructions:

              main():
    000003b8:   B510                push       {r4, r14}
    14            while (!SysCtlPeripheralReady (SYSCTL_PERIPH_GPIOJ))
    000003ba:   4C0D                ldr        r4, [pc, #0x34]
    13            SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOJ);
    000003bc:   4620                mov        r0, r4
    000003be:   F000F839            bl         SysCtlPeripheralEnable
    14            while (!SysCtlPeripheralReady (SYSCTL_PERIPH_GPIOJ))
              $C$L1:
    000003c2:   4620                mov        r0, r4
    000003c4:   F000F81A            bl         SysCtlPeripheralReady
    000003c8:   2800                cmp        r0, #0
    000003ca:   D0FA                beq        $C$L1
    19            switch_inputs = GPIOPinRead (GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    000003cc:   4C09                ldr        r4, [pc, #0x24]
    17            GPIOPinTypeGPIOInput (GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    000003ce:   2103                movs       r1, #3
    000003d0:   4620                mov        r0, r4
    000003d2:   F000F887            bl         GPIOPinTypeGPIOInput
    18            GPIOPadConfigSet (GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    000003d6:   2103                movs       r1, #3
    000003d8:   2201                movs       r2, #1
    000003da:   230A                movs       r3, #0xa
    000003dc:   4620                mov        r0, r4
    000003de:   F7FFFF13            bl         GPIOPadConfigSet
    19            switch_inputs = GPIOPinRead (GPIO_PORTJ_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    000003e2:   2103                movs       r1, #3
    000003e4:   4620                mov        r0, r4
    000003e6:   F000F88E            bl         GPIOPinRead
    000003ea:   4903                ldr        r1, [pc, #0xc]
    000003ec:   6008                str        r0, [r1]
    000003ee:   BD10                pop        {r4, pc}

    The order of the actual function calls, i.e. the bl instructions, matches the order in the source statements. The confusing source stepping order shown in the CCS debugger is a side-effect of the multiple instructions for the source statements being re-order by the optimiser. In this example the re-ordering is valid.