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 v6 Breakpoints not reloading after each "Debug( F11)"

I have been seeing flaky behavior from the software breakpoints for a while, but have still had good luck with HW breakpoints, except there aren't enough of those.  I guessed that it had something to do with the debugger loosing track of where lines were, when I added a line , or commented a block out, until today....

Today, I noticed that the software BP would stop working every time I reloaded to change only the argument of one assignment line, it was only a one bit change, so it should not affect the instruction ordering.  Here is a screen shot, with an 1 error shown when it works only on the HW break point, but not the 3 obviously marked, and enabled, SW breakpoints...it just runs until it gets back to line 205, where the HW breakpoint is.  This is how it looks and works just after a Debug/Reload(F11)

Now if I double click each of the SW breakpoint "blue dots" on lines 210,222,234, then everything works , and it stops properly on each breakpoint, but now I get four red errors listed in the console, perhaps one for each break-point? Screenshot below:

And that works until, I Debug/Reload via F11 again, and then it goes back to the behavior in the first screen shot.

Supporting Details:

  • CCS v6 Version: 6.0.0.00190
  • TMS28069
  • Code is in flash but moved to 28069 RAM on boot, thus all breakpoints are in RAM
  • Spectrum Digital XDS560V2 Traveler Emulator
  • Another problem that I've had since going version 6 is the the Auto Complete, via Ctrl-Space, doesn't seem to work all the time, especially for enumerated types, and register structs.  I had to manually look up the exact spelling of SpiaRegs.SPIFFRX.bit.RXFIFORESET yesterday, which was excessively tedious.  This may not be related.

  • Don,

    I am able to duplicate the behavior. The breakpoints seem to get set correctly in the RAM address but do not halt at it when the code is run the first time after a load/reload. If the breakpoint is simply disabled/re-enabled by unchecking and re-checking the check box in the Breakpoints view (which does trigger the error messages in the console), then it halts correctly at those breakpoints (until another reload of the program).

    So I am able to duplicate the same behavior but only for code regions that are designated as load to Flash and run from RAM. Everything works fine if code stays entirely in RAM or in Flash.

    I will file a bug report for this and post an update here with the bug number.

  • I have submitted bug # SDSCM00050566 to track this issue. Please feel free to track its status using the SDOWP link in my signature.

  • Thanks for the update, Aarti.

    -Don

  • Don,

    A software breakpoint is actually a replacement of the opcode at the breakpoint with a trap, break or some other similar instruction that will halt the target when under debug.  The debugger somewhat hides this from you so that you can still see the original disassembly and/or modify it.

    As such, if your application writes a new instruction where a software breakpoint has been set, the special halting opcode will be replaced with this new instruction.  This effectively removes the breakpoint without informing the debugger that this was done.  This is why the breakpoints fail to halt, and also why an error is printed when you remove it (as a remove writes the original opcode back, but it checks that the breakpoint opcode is still there first).

    This is a limitation of software breakpoints.  Your application doesn't tell the debugger when it's about to do this, so there isn't much the debugger can do other than detect it well after the fact.

    You can work around this in one of two ways.  The easiest way is to use hardware breakpoints instead.  This isn't intrusive on the target, and it's easy, but you do have only a limited number of hw breakpoints.

    The other thing you can do is to set a breakpoint that will effectively tell the debugger what the application is about to do so that the debugger can do something about this.  To do this, set a breakpoint right before the code that does the copy from flash to RAM.  Right click on this breakpoint and select properties.  Under "Debugger Response->Action", change the value from "Remain Halted" to "Execute Expression (GEL)".  A new sub-property should appear named "Expression".  Change it's value to "DisableBreakpointsDuringRAMCopy()".  Then click ok.

    Next, open the startup GEL file by selecting "Tools->GEL Files" and double clicking on the gel file in there (or you can add a new empty GEL file if you don't have one".  In the editor, add the following text:

    DisableBreakpointsDuringRAMCopy()
    {
        GEL_RemoveDebugState();
        GEL_Go( LabelWhereCopyIsDone );
        GEL_RestoreDebugState();
        GEL_Run();
    }

    You'll have to change "LabelWhereCopyIsDone" to some symbol that's meaningful in your application.  When the breakpoint you set earlier is hit, it will execute this function, which will remove all breakpoints, run to the end of the copy, restore all breakpoints, and then run again.  It will even preserve which breakpoints you had disabled (it won't enable those ones).  The only downside is that you won't halt at any breakpoints during the execution of that function, and the target will have to briefly halt twice.  If you need to debug that specific function, you'll have to disable this workaround and use hw breakpoints.

    It's a bit of a complex setup, but you only have to do it once.  Please let me know if you run into any problems.

    Darian

  • Sorry for long delay in responding, been busy with other issues...

    So my code to copy is in assembly,  that I copied from the TI guide on how to run from RAM...

    I've tried adding a breakpoint, as described above, but I'm not sure this code ever returns from the GEL GO expression, and thus never re-enables breakpoints.

    Thanks in advance,

    Don

    ***********************************************************************
    
    WD_DISABLE	.set	1		;set to 1 to disable WD, else set to 0
    
        .ref copy_sections
        .global code_start
    
    ***********************************************************************
    * Function: codestart section
    *
    * Description: Branch to code starting point
    ***********************************************************************
    
        .sect "codestart"
    
    code_start:
        .if WD_DISABLE == 1
            LB wd_disable       ;Branch to watchdog disable code
        .else
            LB copy_sections    ;Branch to copy_sections 
        .endif
    
    ;end codestart section
    
    ***********************************************************************
    * Function: wd_disable
    *
    * Description: Disables the watchdog timer
    ***********************************************************************
        .if WD_DISABLE == 1
    
        .sect "wddisable"
    wd_disable:
        SETC OBJMODE        ;Set OBJMODE for 28x object code
        EALLOW              ;Enable EALLOW protected register access
        MOVZ DP, #7029h>>6  ;Set data page for WDCR register
        MOV @7029h, #0068h  ;Set WDDIS bit in WDCR to disable WD
        EDIS                ;Disable EALLOW protected register access
        LB copy_sections    ;Branch to copy_sections 
    
        .endif
    
    ;end wd_disable
    
    	.end
    	

  • Don,

    There could be two problems:

    1) copy_sections doesn't return (it copies, and then branches to the start of what it copied), so a breakpoint set immediately after will never be hit.

    2) The location you are GEL_Go'ing to is in RAM and is copied over.  GEL_Go also uses a breakpoint to operate, and that breakpoint could be copied over.

    In the first case, you have the code and can tell what's happening.  You'll have to figure out where to tell GEL_Go to run to - worst case just set it to the entry point of the RAM code.  In the second case, you can get CCS to use a hardware breakpoint at the location GEL_Go will try to run to instead of a software.  This can be done by modifying the memory map (either in the GEL callback, or permanently), or by using GEL_HWBreakPtAdd() followed by GEL_Run() instead of a GEL_Go().  The catch with the second method is that you'll have to add an OnHalt() callback to remove the hw breakpoint and re-run as GEL_Run is not synchronous (ie it returns immediately, whereas GEL_Go returns only after the halt).

    Darian

  • I'm experiencing the same problem in CCSv5 so decided to see if its fixed in CCsv6. Unfortunately the SDSCM00050566 bug report status at SDOWP and it says "Declined". Why won't they fix this?

    Cheers2u
    Eddie
  • Eddie,

    This specific issue turned out to be because the application was writing over the software breakpoints set by the debugger.  That's a fundamental limitation of software breakpoints, and hardware/embedded breakpoints would need to be used instead.  Please see my earlier post for more details.

    If your application isn't self-modifying, then you are experiencing a different issue.

    Darian