cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F427 - Cant get watchpoints to work

turboscrew
Senior III

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;
	}
}

4 REPLIES 4
turboscrew
Senior III

An update:

I checked that in our system thread mode is privileged (by reading the CONTROL register). So accessing the debug registers should be allowed.

Then I read the DHCSR and it was zero. DEMCR was also zero even after I tried to set the TRCENA-bit.

Any idea what keeps the TRCENA-bit low? The running debugger (SWD)?

To my understanding STM32F427 should have watchpoints implemented.

turboscrew
Senior III

Somewhere I found something about lock register (LAR). If there is one in STM32F427, where can I find more? ARM documents seem to leave authentication IMPLEMENTATION DEFINED, and I haven't found any STM manuals that discuss those things. HAL and CMSIS don't seem to know anything about those things.

turboscrew
Senior III

Hmm, CMSIS seems to know ITM LAR...

turboscrew
Senior III

​Tried with LAR address 0xE0001FB0 and 0xE0000FB0. No help.

BTW, reading DWT_CTRL gives 0x40000000. Does this mean that the DWT is not locked?

Still, the result of this is zero:

	tmp = DWT_DEMCR;
	if ((tmp & (1<<24)) == 0) // if TRACENA
	{
		DWT_DEMCR |= (1<<24); // DWT disabled, enable it
	}
	tmp = DWT_DEMCR;