What's wrong when watchpoint doesn't watch?

I've been trying to get a watchpoint to trigger, but no luck.

There should be 4 watchpoints accordíng to DBGDIDR, DBGDSCR=0x0204000e, so there shouldn't be any problems there?

I use (just in case) the cp14 interface - write DBGWVR0 and DBGWCR0 and read them back to see that the values went there.

Then I access the memory location, but nothing happens. Oh, and there are no masks in the CPSR set.

The program runs in non-secure SVC-mode.

Here's the watchpoint setting code:

void rpi2_set_watchpoint(unsigned int num, unsigned int addr, unsigned int control)
{
    char scratchpad[9];
    SYNC;

    volatile uint32_t *pval;
    pval = (volatile uint32_t *)(dbg_reg_base + 0x088);

#if 0
    // if memory-mapped interface works
    //  96-111 0x180-0x1BC DBGWVRm 4 watchpoint values
    // 112-127 0x1C0-0x1FC DBGWCRm 4 watchpoint controls
    uint32_t *pval, *pctrl;
    pval = (volatile uint32_t *)(dbg_reg_base + 0x180);
    pctrl = (volatile uint32_t *)(dbg_reg_base + 0x1c0);
    pval[num] = (uint32_t)addr;
    pctrl[num] = control;
#else
    // have to use cp14
    switch (num)
    {
    case 0:
        serial_raw_puts("\r\nwatch0!\r\n");
        // write to DBGWVR0
        asm volatile ("mcr p14, 0, %[val], c0, c0, 6\n\t" ::[val] "r" (addr) :);
        // write to DBGWCR0
        asm volatile ("mcr p14, 0, %[ctl], c0, c0, 7\n\t" ::[ctl] "r" (control) :);
        // debug
        asm volatile ("mrc p14, 0, %[val], c0, c0, 6\n\t" :[val] "=r" (addr) ::);
        asm volatile ("mrc p14, 0, %[ctl], c0, c0, 7\n\t" :[ctl] "=r" (control) ::);
        serial_raw_puts("DBGWVR0: ");
        util_word_to_hex(scratchpad, addr);
        serial_raw_puts(scratchpad);
        serial_raw_puts(" DBGWCR0: ");
        util_word_to_hex(scratchpad, control);
        serial_raw_puts(scratchpad);
        serial_raw_puts(" DBGDSCR: ");
        util_word_to_hex(scratchpad, *pval);
        serial_raw_puts(scratchpad);
        serial_raw_puts("\r\n");
        break;
    case 1:
        serial_raw_puts("\r\nwatch1!\r\n");
        // write to DBGWVR1
        asm volatile ("mcr p14, 0, %[val], c0, c1, 6\n\t" ::[val] "r" (addr) :);
        // write to DBGWCR1
        asm volatile ("mcr p14, 0, %[ctl], c0, c1, 7\n\t" ::[ctl] "r" (control) :);
        break;
    case 2:
        serial_raw_puts("\r\nwatch2!\r\n");
        // write to DBGWVR2
        asm volatile ("mcr p14, 0, %[val], c0, c2, 6\n\t" ::[val] "r" (addr) :);
        // write to DBGWCR2
        asm volatile ("mcr p14, 0, %[ctl], c0, c2, 7\n\t" ::[ctl] "r" (control) :);
        break;
    case 3:
        serial_raw_puts("\r\nwatch3!\r\n");
        // write to DBGWVR3
        asm volatile ("mcr p14, 0, %[val], c0, c3, 6\n\t" ::[val] "r" (addr) :);
        // write to DBGWCR3
        asm volatile ("mcr p14, 0, %[ctl], c0, c3, 7\n\t" ::[ctl] "r" (control) :);
        break;
    default:
        serial_raw_puts("\r\nwatch?!\r\n");
        // do nothing;
        break;
    }
#endif
    SYNC;
}

The machine is Raspberry Pi 2B if that helps.

The output from the function (through dgb):

w \x00](gdb) watch g_testloc

Sending packet: $m8360,4#9e...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][

r +]Ack

[$][7][0][8][3][0][0][0][0][#][9][2]Packet received: 70830000

[

w \x00]Sending packet: $m8360,4#9e...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][

r +]Ack

[$][7][0][8][3][0][0][0][0][#][9][2]Packet received: 70830000

[

w \x00]Hardware watchpoint 1: g_testloc

(gdb) cont

Continuing.

Sending packet: $m8360,4#9e...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][

r +]Ack

[$][7][0][8][3][0][0][0][0][#][9][2]Packet received: 70830000

[

w \x00]Sending packet: $Z2,8360,4#e9...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][

r +]Ack

[\r][\n][w][a][t][c][h][ ][n][u][m][=][ ][0][0][0][0][0][0][0][0][ ][v][a][l][=][0][0][0][0][8][3][6][0][ ][c][t][r][l][0][0][0][0][2][1][f][7][\r][\n][\r][\n][w][a][t][c][h][0][!][\r][\n][D][B][G][W][V][R][0][:][ ][0][0][0][0][8][3][6][0][ ][D][B][G][W][C][R][0][:][ ][0][0][0][0][2][1][f][7][ ][D][B][G][D][S][C][R][:][ ][0][2][0][4][0][0][0][e][\r][\n][$][O][K][#][9][a]Packet received: OK

[

w \x00]Packet Z2 (write-watchpoint) is supported

Sending packet: $vCont?#49...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][

r +]Ack

[$][#][0][0]Packet received:

The address of g_testloc is indeed 0x8360

Disassembly of section .bss:

00008360 <g_testloc>:

    8360:    00000000     andeq    r0, r0, r0

Parents
  • Did some more searching and reading...

    DBGEN The Debug Enable signal enables invasive debug

    Is it so that HW breakpoints and watchpoints can only be used with an external debug POD?

    And only bkpt instruction works without it?

    There seems to be a possibility that the DBGEN can be changed by program if such register is implemented. I was wondering if there is a way to alter it via DCC registers?

Reply
  • Did some more searching and reading...

    DBGEN The Debug Enable signal enables invasive debug

    Is it so that HW breakpoints and watchpoints can only be used with an external debug POD?

    And only bkpt instruction works without it?

    There seems to be a possibility that the DBGEN can be changed by program if such register is implemented. I was wondering if there is a way to alter it via DCC registers?

Children