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][
w \x00]Hardware watchpoint 1: g_testloc
(gdb) cont
Continuing.
w \x00]Sending packet: $Z2,8360,4#e9...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][
[\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][
[$][#][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
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?
False alarm: DBGAUTHSTATUS = 0xff.
DBGEN is high and invasive and non-invasibe secure and non-secure debug is enabled.
So what the heck is wrong?
The problem is solved. It was the OS lock.
Both double lock and dbg lock were clear.