C2000 Breakpoints in code loaded to Flash and run from RAM

From Texas Instruments Wiki
Jump to: navigation, search

Introduction

In C2000 applications, software breakpoints set in code regions that are loaded to Flash but run from RAM and enabled prior to loading code, may not work as expected. The breakpoints will appear be set correctly in the RAM address but program will not halt 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 then it will halt correctly at those breakpoints (until another reload of the program). Also "Trouble removing Breakpoint" messages will appear in the console when the breakpoint is disabled.

Explanation

When a software breakpoint is set, the emulation driver reads the instruction at that location and replaces it with a software breakpoint op-code that will then halt the target when in debug mode. The debugger somewhat hides this from you so you can still see the original disassembly and/or modify it.

If the application writes a new instruction to the address where a software breakpoint has been set (as in the case of code that is copied from Flash to RAM at boot time), the special halting opcode will be replaced with this new instruction. This effectively removes the breakpoint without the debugger's knowledge. 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. Since the debugger is not aware of when an application might do this, there isn't much the debugger can do other than detect it well after the fact. If the breakpoint is enabled after the code has been copied from Flash to RAM, then they will work.

Workarounds

The easiest work around is to use hardware breakpoints instead. This is also not intrusive on the target, but C2000 has only two hardware breakpoints available.

The other option 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, follow the steps below:

  • 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.
  • 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();
}
Change "LabelWhereCopyIsDone" to the symbol that's meaningful to your application.
  • When the breakpoint 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 the disabled breakpoints (but won't enable those). The only downside is that it 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 hardware breakpoints instead.

For additional information please refer to this thread: https://e2e.ti.com/support/development_tools/code_composer_studio/f/81/p/354642/1246978#1246978