DDC-I Logo

Sitemap  

DDC-I Ada Compiler System  
JTAG Debugging with Caches Enabled

Product Family: SCORE
Target CPU: PowerPC
Language: Ada, C 
Host: PC/Windows, Sparc/Solaris

When debugging, many debuggers disable data and/or instruction caches on the target. The reason for this is that the caches cause the hardware to not truly reflect what the debug information provides. For example, a program may change a variable by updating a memory location. If this location is in the data cache and has not yet been written out to actual memory, the debugger will get the wrong data when it reads the actual memory location for the variable. Similarly, the way that is most frequently used to set a software breakpoint is to modify the memory at the code location where the breakpoint is to be set. If the instruction is already in the instruction cache and is not read from actual memory, the breakpoint will not | fire | even though the instruction is executed. There are a variety of similar problems that can occur when data and/or instruction caches are enabled on the target.

When debugging with a debug monitor on the target hardware, the debug monitor may solve the cache problems by containing code that will force a consistency between the caches and the actual memory by flushing the caches (copying the contents of the caches out to actual memory), and by invalidating the instruction cache (emptying the instruction cache of valid instructions so that it will be refilled from actual memory). The code that forces consistency between the caches and actual memory is executed whenever the target stops at a breakpoint or because of step completion.

When JTAG debugging, there is no debug monitor code running on the target hardware. So it is the responsibility of the host-side debugger to ensure the consistency between the caches and actual memory. Unfortunately, the code that needs to be executed to do this will vary somewhat from target board to target board, so it is not practical to try to explicitly build this into the host side of the debugger.

In SCORE for the PowerPC, there is the concept of a board-dependent set of routines called the | User Configurable Code | (UCC for short) that is written to initialize the board and provide interfaces to board hardware such as UARTs. Typically the UCC also contains board dependent code to initialize and manipulate the caches for the processor/board combination. It is here that code can also be added for the JTAG debugger to use.

Specifically, in SCORE for the PowerPC, JTAG debugging will run with the data and instruction caches enabled if a routine that the debugger (and only the debugger) can use to provide cache consistency is provided. Such a routine should flush the data cache and invalidate the data and instruction caches. The JTAG debugger will look for code that begins with the label "ddci_jtag_debug_fixup_cache" and ends with "ddci_jtag_debug_fixup_cache_end". The UCC contains a file ucc_asm_macros.h that provides a macro for placing a global label, such as the ones above, in assembly files. To allow PowerPC JTAG debugging with the caches enabled, provide the required routine surrounded by the specified labels, and make sure that it is included in the link.

Here is an example of an assembly file for the Sandpoint 755 that provides the code needed by the debugger.

#include "ucc_asm_macros.h"

/* Define the following to be 
appropriate for your machine */

#define HID0_SPR_NUMBER  1008	
#define DCACHE_BLOCKSIZE   32
#define PHYMEMHI 0x400    /* high order part 
                             of limit of memory     */
#define	DCFI  0x400	  /* bit 21, Data Cache 
                             Flash Invalidate.      */
#define ICFI  0x00000800  /* bit 20, Instruction
                                                          Caceh Flash Invalidate */


/* BEGIN FUNCTION  */	
/* void ddci_init_debug_support(void); 
 * Input:	none
 * Output:	none
 * Side effects:
 *   None
 */
global_routine(ddci_init_debug_support)
	blr
/* The following is used only by the 
   debugger when JTAG debugging.        */
/* It allows the data and instruction 
   caches to be enabled by the code.    */
/* It is executed whenever a breakpoint 
   is hit or a machine step is          */
/* completed.                           */
global_label(ddci_jtag_debug_fixup_cache)
/* save registers to be used */
        stw   r3, -4(r1)
        stw	  r4, -8(r1)
        stw	  r5, -12(r1)
        mfcr  r5
        stw	  r5, -16(r1)
/* Flush the data cache */
        li	  r3, 0
        lis   r4, PHYMEMHI
        add   r4, r3, r4
L.ddci_fix_loop:
        dcbf  0, r3
        addi  r3, r3, DCACHE_BLOCKSIZE
        cmplw cr0, r3, r4
        blt   L.ddci_fix_loop
        isync
        sync
/* Invalidate the data cache */
        mfspr r3, HID0_SPR_NUMBER
        ori	  r4, r3, DCFI	/* Set DCFI bit 
                                   in "HID0" (GPR4). */
        xori  r5, r4, DCFI	/* Clear DCFI bit 
                                   in "HID0" (GPR5). */
        mtspr HID0_SPR_NUMBER, r4
        mtspr HID0_SPR_NUMBER, r5
        isync
        sync
/* Invalidate the instruction cache */
        mfspr	r3, HID0_SPR_NUMBER
        ori	  r4, r3, ICFI	/* Set bit 20 in 
                                   "HID0" (GPR4).    */
        xori  r5, r4, ICFI	/* Clear bit 20 
                                   in "HID0" (GPR5). */
        mtspr HID0_SPR_NUMBER, r4
        mtspr HID0_SPR_NUMBER, r5
        isync
        sync
/* Restore registers used */
        lwz   r5, -16(r1)
        mtcr  r5
        lwz   r5, -12(r1)
        lwz   r4, -8(r1)
        lwz   r3, -4(r1)
global_label(ddci_jtag_debug_fixup_cache_end)
        blr	
.end

Notice that the code actually begins with the global_routine "ddci_init_debug_support" that merely does a return. This is so that we can ensure that the needed coded is linked in by calling ddci_init_debug_support somewhere in the program code. Typically such a call would be added into the UCC code in the file initialize.c. So that the call can be made, the entry also needs to be defined in a header that is included.

In SCORE 2.4 and later, the UCC code for the Sandpoint 750/755 and the UCC code for the Excimer boards contain complete examples of the code needed to allow the debugger to properly handle code that runs with the caches enabled.

 

Contact
602-275-7172
sales@ddci.com

IDIQ Contract Vehicles:
--------------
AMCOM Express
DESP II
F2AST
R23G

Links

Support

Members Area
    -Member Login/Return
    -Login Help

Atlas Support Packages
    -Atlas Premium
    -Atlas Advantage
    -Atlas Choice

Complimentary Support

Submit a Software Trouble Report

Customer Quote:
"DDC-I has a good solution for us and your willingness to get down to the issues and help us get what we need has made it a clear choice."