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.

TMS320F28379D: Apparent bug in firmware if/else execution using asm breakpoint labels from a DSS script

Part Number: TMS320F28379D
Other Parts Discussed in Thread: LAUNCHXL-F28379D

Over the past several weeks I have been corresponding with TI guru Ki re: an apparent problem correctly executing C/C++ if / else statements when a DSS script uses the asm("<label>:") construct to mark locations in code where the DSS script defines breakpoints. At first I thought the problem lay in faulty builds of TI demo boards. My most recent tests used 5 different TI demo boards, one controlCARD and 4 different LaunchXL-F28379D boards. All behaved the same way. Here is a description of my tests.

The test program reads from two GPIO pins (52 and 67). The test software succeeds if one input is high and the other low. VALID_CASE_0 occurs if GPIO67 is low and  GPIO52 is high. VALID_CASE_1 occurs if GPIO67 is high and BPIO52 is low. INVALID_GPIO_INPUTS is returned If the two pins match, either both high or both low. This approach makes it easy to test different paths through the if / else logic with no changes to the firmware.

I have tested behavior with CCS version 10.4 using compiler version 20.5 and with CCS version 12 and compiler version 22.6. Results are the same. NOTE: Results DO change with project compiler optimization level. The results listed here are with optimization level 1: Local Optimizations.

Output from the 3 test cases were as shown below for all the demo boards:

GPIO52=1, GPIO67=0: Correct if execution, results are: VALID_CASE_0, TEST_IS_DONE

GPIO52=0, GPIO67=1 Faulty if execution, results are: VALID_CASE1, VALID_CASE_0, TEST_IS_DONE

GPIO52=1, GPIO67=1 Faulty if execution, results are: INVALID_GPIO_INPUTS, VALID_CASE_0, TEST_IS_DONE

In all 3 cases, the first if case reported IS the correct one, but when there is apparent faulty if execution, the breakpoint for a 2nd if /else case is also hit before the program exits the if / else cases entirely.

I tested a hypothesis that the if / else failure occurs under a DSS debug session when the asm("<label>:") statement is the last statement in an if / else case. In the test program, I moved the asm(*) statements above the last executable line in each if / else case. Now DSS executes the debug session correctly for all 3 test cases. So it does appear that a C2000 compiler bug may be placing the breakpoint label in the wrong location if the if / else logic if the label is the last statement in an if or else case. The work-around once the problem is understood is to move the breakpoint label so it is not the last statement in an if or else case.

Here is a ZIP file containing the CCS project. The DSS script is in folder JVScript.

1323.DssBkptTest.zip

  • NOTE: Results DO change with project compiler optimization level. The results listed here are with optimization level 1: Local Optimizations.

    Note that I can reproduce the faulty behavior when optimization level 1 (-o1) is enabled. If I disable optimization completely, I always get the correct behavior.

    I know that when adding explicit asm statements in C code, there are additional considerations to be taken into account. I will leave this explanation to my colleagues more familiar with the compiler

    ki

  • The compiler has done nothing wrong.  The problem is in your presumption that there is exactly one way to reach an asm created label that appears at the end of a block controlled by an if/else condition.  As you will see, that presumption is incorrect.

    Thank you for submitting a CCS project.  I built it with C2000 compiler version 20.2.5.LTS.  In particular, I made sure to use compiler option --opt_level=1. I also added the option --src_interlist.  This causes the compiler to not delete the auto-generated assembly file, and to add comments to it which make it easier to understand.  The assembly file has the same name as the source file, with the file extension changed to .asm.  Consider the file GpioInputCheck.asm.  To make it easy to focus on the lines that matter, I changed the file in these ways:

    • Only the function CheckIdInputs remains
    • All the directives, like .text and .dwattr, are removed
    • All blank lines are removed

    Here it is:

    _CheckIdInputs:
    ;* AR4   assigned to $O$C1
    ;* AL    assigned to _bGpioInputsAreValid
    ;*** 81	-----------------------    if ( !*(C$1 = &GpioValues[0]) ) goto g4;
            MOVL      XAR4,#_GpioValues     ; [CPU_ARAU] |81| 
            MOV       AL,*+XAR4[0]          ; [CPU_ALU] |81| 
            B         $C$L3,EQ              ; [CPU_ALU] |81| 
            ; branchcc occurs ; [] |81| 
    ;*** 81	-----------------------    if ( !C$1[1] ) goto g7;
            MOV       AL,*+XAR4[1]          ; [CPU_ALU] |81| 
            B         $C$L5,EQ              ; [CPU_ALU] |81| 
            ; branchcc occurs ; [] |81| 
    ;*** 86	-----------------------    if ( GpioValues[0] ) goto g6;
            MOVW      DP,#_GpioValues       ; [CPU_ARAU] 
            MOV       AL,@$BLOCKED(_GpioValues) ; [CPU_ALU] |86| 
            B         $C$L4,NEQ             ; [CPU_ALU] |86| 
            ; branchcc occurs ; [] |86| 
    $C$L3:    
    ;***	-----------------------g4:
    ;*** 86	-----------------------    if ( !GpioValues[1] ) goto g6;
            MOVW      DP,#_GpioValues+1     ; [CPU_ARAU] 
            MOV       AL,@$BLOCKED(_GpioValues)+1 ; [CPU_ALU] |86| 
            B         $C$L4,EQ              ; [CPU_ALU] |86| 
            ; branchcc occurs ; [] |86| 
    ;*** 88	-----------------------    _bGpioInputsAreValid = 1u;
    ;*** 89	-----------------------    asm("VALID_CASE_1:");
    ;***  	-----------------------    goto g8;
            MOVB      AL,#1                 ; [CPU_ALU] |88| 
    VALID_CASE_1:
            B         $C$L6,UNC             ; [CPU_ALU] 
            ; branch occurs ; [] 
    $C$L4:    
    ;***	-----------------------g6:
    ;*** 93	-----------------------    _bGpioInputsAreValid = 0u;
    ;*** 94	-----------------------    asm("INVALID_GPIO_INPUTS:");
    ;*** 94	-----------------------    goto g8;
            MOVB      AL,#0                 ; [CPU_ALU] |93| 
    INVALID_GPIO_INPUTS:
            B         $C$L6,UNC             ; [CPU_ALU] |94| 
            ; branch occurs ; [] |94| 
    $C$L5:    
    ;***	-----------------------g7:
    ;*** 83	-----------------------    _bGpioInputsAreValid = 1u;
    ;*** 84	-----------------------    asm("VALID_CASE_0:");
    ;***	-----------------------g8:
    ;*** 97	-----------------------    return _bGpioInputsAreValid;
            MOVB      AL,#1                 ; [CPU_ALU] |83| 
    VALID_CASE_0:
    $C$L6:    
            SPM       #0                    ; [CPU_ALU] 
            LRETR     ; [CPU_ALU] 

    This code is correct, in the sense that it returns the correct result for all input.  But notice lines 48 and 49.  They each define a label, for the same address.  Line 48 defines the label VALID_CASE_0 and line 49 defines the label $C$L6.  Any label that begins $C$ is a label generated by the compiler.  Note that there are two branches to $C$L6.  One on line 30, and another on line 39.  Suppose execution reaches line 30.  That means the breakpoint for VALID_CASE_1 is seen.  What happens next?  An unconditional branch to $C$L6.  That means the breakpoint for VALID_CASE_0 is seen, even though the instruction just before it does not execute.  It is a similar situation when execution reaches line 39. 

    I'm unsure of the best solution.  One quick workaround is to add a nop to each asm statement.

        asm("VALID_CASE_0: nop");
     

    Thanks and regards,

    -George

  • George - Thanks for taking the time to analyze this issue thoroughly. I wonder how many other users of DSS scripts have encountered this behavior. Do you know if TI has plans to modify the compiler to prevent this behavior in future releases?

    I've added a nop to all my DSS asm labels to innoculate against encountering this problem again.

  • TI has plans to modify the compiler to prevent this behavior in future releases?

    There are no such plans.

    Thanks and regards,

    -George