Software Breakpoints in the IDE

From Texas Instruments Wiki
Jump to: navigation, search

How convenient would it be to do something like this:

 if (some_assertion_failure) {
 halt_the_target_in_a_spin_loop_so_i_can_see_the_processor_state()
 }

Typically we think of breakpoints as IDE-only i.e. we manually have to set BPs at certain locations. However it would be neat to programmatically trigger a breakpoint. Naturally we can do this with AET but not every chip has AET capabilities.

The good news is we can do this with the software breakpoint opcode - each TI Instruction Set Architecture has one. Here is some code we use to apply programmatic software breakpoints

/*
 * ======== UTL_assert ========
 * Assert macro for exceptions
 *
 * If an assertion fails, we interrupt the execution flow and preserve
 * the state of the system.
 * If the application is being debugged with Code Composer Studio, we place
 * a word in program memory that has the effect of a breakpoint -- it halts
 * the execution and CCS shows the line of code where the failed assertion
 * occurred. The special word that causes the breakpoint effect is different
 * for every DSP family.
 * Otherwise, if CCS is not used, we disable interrupts and run into an
 * infinite loop, waiting for the user to halt the target manually.
 * To do so, define UTL_ASSERTCCS macro flag externally to be 0.
 */
#if UTL_ASSERT == 1 /* first check if UTL_ASSERT() is enabled at all */
 
 /*
 * First we define the special word for each platform:
 * On 55x we add a NOP to guard against small possibility that
 * long instruction pipeline causes debugger to stop at next C src line
 * instead of currently executing C src statement. We also ensure this
 * works on both 55x mnemonic (default) and algebraic 55x assembler.
 * Note that asm statement is a single execution context to maintain
 * pre-processor consistency.
 */
 #if defined( _54_ )
 #define UTL_STOPWORD asm( " ESTOP" )
 #elif defined( _55_ )
 #define UTL_STOPWORD asm(" ;\n .if (.MNEMONIC)\n ESTOP_1\n .else\n ESTOP_1()\n .endif\n NOP")
 #elif defined(_64P_) /* Joule */
 #define UTL_STOPWORD asm( " SWBP 0")
 #elif defined( _6x_ )
 #define UTL_STOPWORD asm( " NOP\n .word 0x10000000" )
 #else
 #define UTL_ASSERTCCS 0 /* unknown platform => no CCS breakpoint */
 #endif
 
 #if !defined( UTL_ASSERTCCS )
 #define UTL_ASSERTCCS 1
 #endif
 
 /* check if it's OK with the user to use CCS breakpoints for asserts() */
 #if UTL_ASSERTCCS == 1
 /* it is; define the UTL_assert macro */
 #define UTL_assert( expr ) \
 for (; !( expr ); ) \
 UTL_STOPWORD
 
 #else /* UTL_ASSERTCCS == 0 */ /* no Code Composer Studio here */
 #define UTL_assert( expr ) do { \
 if ( !(expr) ) { /* use UTL_error() to halt, prototyped below */ \
 UTL_error( "Assertion Violation: " __FILE__ ", line " \
 UTL_stringify(__LINE__) " (" UTL_stringify(expr) ")", 0 ); \
 } \
 } while (0)
 #endif /* UTL_ASSERTCCS */
 
 /*
 * UTL_assertFunc() is meant for testing expressions with side effects,
 * i.e. mostly for checking function calls. If enabled, behaves exactly
 * the same as UTL_assert. If disabled, it is not expanded to nothing
 * but to actual expression. E.g.,
 * UTL_assertFunc( someFunc() == TRUE );
 * If asserts are disabled, expands to
 * (someFunc() == TRUE);
 */
 #define UTL_assertFunc UTL_assert
 
#else /* UTL_ASSERT */
 #define UTL_assert( expr )
 #define UTL_assertFunc( expr ) (expr)
#endif /* UTL_ASSERT */

This code shows the mnemonic / opcode for the different ISAs. You can use the UTL_assert() macro or just the UTL_STOPWORD definition.

Typical usage might be:
 mbxProcess = MBX_create(sizeof(CtrlMsg), THRPROCESS_MBXLENGTH, NULL);
 UTL_assert( mbxProcess != NULL ); // halt the target and debug if we fail

For the C28x devices, the software breakpoint instruction is: asm( "ESTOP0")


This capability is also being considered for the simulator - the enhancement number is SDSCM00025430.

Another topic to look at is Simulator Data Breakpoints and Watchpoints. However this feature is not available on all ISAs.