| |||
| Home > Debug > Using the debug functionality > Programming breakpoints and watchpoints | |||
This section describes the following operations:
When programming a simple breakpoint, you must set the byte address select bits in the control register appropriately. For a breakpoint in ARM state, this is simple. For Thumb state, you must calculate the value based on the address.
For a simple breakpoint, you can program the settings for the other control bits as Table 12.42 shows:
Table 12.42. Values to write to DBGBCR for a simple breakpoint
| Bits | Value to write | Description |
|---|---|---|
| [31:29] | 0b000 | Reserved |
| [28:24] | 0b00000 | Breakpoint address mask |
| [23] | 0b0 | Reserved |
| [22:20] | 0b000 | Meaning of DBGBVR |
| [19:16] | 0b0000 | Linked BRP number |
| [15:9] | 0b00 | Reserved |
| [8:5] | Derived from address | Byte address select |
| [4:3] | 0b00 | Reserved |
| [2:1] | 0b11 | Supervisor access control |
| [0] | 0b1 | Breakpoint enable |
Example 12.7 shows the sequence of instructions for setting a simple breakpoint.
Example 12.7. Setting a simple breakpoint
SetSimpleBreakpoint(int break_num, uint32 address, iset_t isa)
{
// Step 1. Disable the breakpoint being set.
WriteDebugRegister(80 + break_num, 0x0);
// Step 2. Write address to the DBGBVR, leaving the bottom 2 bits zero.
WriteDebugRegister(64 + break_num, address & 0xFFFFFFC);
// Step 3. Determine the byte address select value to use.
case (isa) of
{
// Note: The processor does not support Jazelle or ThumbEE states
when THUMB:
byte_address_select := (3 << (address & 2));
when ARM:
byte_address_select := 15;
}
// Step 4. Write the mask and control register to enable the breakpoint.
WriteDebugRegister(80 + break_num, 7 | (byte_address_select << 5));
}
The simplest and most common type of watchpoint watches for a write to a given address in memory. In practice, a data object spans a range of addresses but is aligned to a boundary corresponding to its size, so you must set the byte address select bits in the same way as for a breakpoint.
For a simple watchpoint, you can program the settings for the other control bits as Table 12.43 shows:
Table 12.43. Values to write to DBGWCR for a simple watchpoint
| Bits | Value to write | Description |
|---|---|---|
| [31:29] | 0b000 | Reserved |
| [28:24] | 0b00000 | Watchpoint address mask |
| [23:21] | 0b000 | Reserved |
| [20] | 0b0 | Enable linking |
| [19:16] | 0b0000 | Linked BRP number |
| [15:13] | 0b00 | Reserved |
| [12:5] | Derived from address | Byte address select |
| [4:3] | 0b10 | Load/Store access control |
| [2:1] | 0b11 | Privileged access control |
| [0] | 0b1 | Watchpoint enable |
Example 12.8 shows the code for setting a simple aligned watchpoint.
Example 12.8. Setting a simple aligned watchpoint
SetSimpleAlignedWatchpoint(int watch_num, uint32 address, int size)
{
// Step 1. Disable the watchpoint being set.
WriteDebugRegister(112 + watch_num, 0);
// (Step 2. Write address to the DBGWVR, leaving the bottom 3 bits zero.
WriteDebugRegister(96 + watch_num, address & 0xFFFFFF8);
// Step 3. Determine the byte address select value to use.
case (size) of
{
when 1:
byte_address_select := (1 << (address & 7));
when 2:
byte_address_select := (3 << (address & 6));
when 4:
byte_address_select := (15 << (address & 4));
when 8:
byte_address_select := 255;
}
// Step 4. Write the mask and control register to enable the watchpoint.
WriteDebugRegister(112 + watch_num, 23 | (byte_address_select << 5));
}
Using the byte address select bits, certain unaligned objects up to a doubleword (64 bits) can be watched in a single watchpoint. However, this cannot cover all cases, and in many cases a second watchpoint might be required.
Table 12.44 shows some examples.
Table 12.44. Example byte address masks for watchpointed objects
| Address of object | Object size in bytes | First address value | First byte address mask | Second address value | Second byte address mask |
|---|---|---|---|---|---|
0x00008000 | 1 | 0x00008000 | 0b00000001 | Not required | - |
0x00008007 | 1 | 0x00008000 | 0b10000000 | Not required | - |
0x00009000 | 2 | 0x00009000 | 0b00000011 | Not required | - |
0x0000900c | 2 | 0x00009000 | 0b11000000 | Not required | - |
0x0000900d | 2 | 0x00009000 | 0b10000000 | 0x00009008 | 0b00000001 |
0x0000A000 | 4 | 0x0000A000 | 0b00001111 | Not required | - |
0x0000A003 | 4 | 0x0000A000 | 0b01111000 | Not required | - |
0x0000A005 | 4 | 0x0000A000 | 0b11100000 | 0x0000A008 | 0b00000001 |
0x0000B000 | 8 | 0x0000B000 | 0b11111111 | Not required | - |
0x0000B001 | 8 | 0x0000B000 | 0b11111110 | 0x0000B008 | 0b00000001 |
Example 12.9 shows the code for setting a simple unaligned watchpoint.
Example 12.9. Setting a simple unaligned watchpoint
bool SetSimpleWatchpoint(int watch_num, uint32 address, int size)
{
// Step 1. Disable the watchpoint being set.
WriteDebugRegister(112 + watch_num, 0x0);
// Step 2. Write addresses to the DBGWVRs, leaving the bottom 3 bits zero.
WriteDebugRegister(96 + watch_num, (address & 0xFFFFFF8));
// Step 3. Determine the byte address select value to use.
byte_address_select := (1 << size) - 1;
byte_address_select := (byte_address_select) << (address & 7);
// Step 4. Write the mask and control register to enable the breakpoint.
WriteDebugRegister (112 + watch_num, 5'b23 | ((byte_address_select & 0xFF) << 5));
// Step 5. Set second watchpoint if required. This is the case if the byte
// address mask is more than 8 bits.
if (byte_address_select >= 256)
{
WriteDebugRegister(112 + watch_num + 1, 0);
WriteDebugRegister(96 + watch_num + 1, (address & 0xFFFFFF8) + 8);
WriteDebugRegister(112 + watch_num + 1 23| ((byte_address_select & 0xFF00) >> 3));
}
// Step 6. Return flag to caller indicating if second watchpoint was used.
return (byte_address_select >= 256)
}