STM32F427 - Cant get watchpoints to work
I've been trying to use watchpoints to catch a possible bad write.
I tried with Atollic TrueSTUDIO, but it doesn't seen to catch anything.
Then I tried code, but haven't got it to catch anything either. I'd prefer the code, because GDB doesn't support memory regions, but the HW should.
Am I missing something? I would think that because breakpoints work, the debug events are handled right, or do I need the DebugMon_Handler and and (maybe) change the halting to debug monitor exception? (And loose the IDE breakpoints.)
#define DWT_ADDRESS 0xE0001000
#define DHCSR_ADDR 0xE000DEF0
#define DFSR_ADDR 0xE000ED30
#define DWT_CTRL (*((uint32_t *)DWT_ADDRESS))
#define DWT_COMP_0 (*((uint32_t *)DWT_ADDRESS + 0x20))
#define DWT_MASK_0 (*((uint32_t *)DWT_ADDRESS + 0x24))
#define DWT_FUNCTION_0 (*((uint32_t *)DWT_ADDRESS + 0x28))
#define DWT_COMP_1 (*((uint32_t *)DWT_ADDRESS + 0x20 + 1*16))
#define DWT_MASK_1 (*((uint32_t *)DWT_ADDRESS + 0x24 + 1*16))
#define DWT_FUNCTION_1 (*((uint32_t *)DWT_ADDRESS + 0x28 + 1*16))
#define DWT_DHCSR (*((uint32_t *)DHCSR_ADDR))
#define DWT_DEMCR (*((uint32_t *)DHCSR_ADDR + 12))
/*
* address: within region
* region_sz: region size as power of 2
* datasize: 0=none, 1 = byte, 2=half word, 3 = word
* accessmode: 0 = none1 = RO, 2=WO, 3=RW
*
* if datasize = 0, then check for address only
* if accessmode = 0, then remove watchpoint
*/
void set_watchpoint(uint32_t address, uint32_t region_sz, uint32_t data, uint8_t datasize, uint8_t accessmode)
{
uint32_t mask = 0;
uint32_t tmp;
tmp = DWT_DHCSR; // for checking the C_DEBUGEN under breakpoint
tmp = DWT_DEMCR;
if ((tmp & (1<<24)) == 0) // if TRACENA
{
DWT_DEMCR |= (1<<24); // DWT disabled, enable it
}
while(region_sz) {
region_sz >>= 1;
mask++;
}
/* address region to watch */
DWT_COMP_0 = address;
DWT_MASK_0 = mask;
if (datasize !=0) {
/* address and data match used */
datasize -=1;
DWT_FUNCTION_0 = 0; // DWT_COMP_0 is linked address comparator
tmp = 0x0100; // data match + linked comparator 1
tmp |= (datasize << 10);
DWT_COMP_1 = data; // DWT_COMP_1 is the data value comparator
DWT_MASK_1 = 0;
if (accessmode == 0) DWT_FUNCTION_1 = 0;
else DWT_FUNCTION_1 = tmp | (4 + accessmode);
} else {
/* only address match used */
if (accessmode == 0) DWT_FUNCTION_0 = 0;
else DWT_FUNCTION_0 = 4 + accessmode;
}
}