Skip to main content
turboscrew
Senior III
Mar 30, 2019 10:56 AM UTC
Question

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

This topic has been closed for replies.

4 replies

turboscrew
Senior III
Apr 1, 2019 5:20 PM UTC

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
Apr 1, 2019 6:14 PM UTC

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
Apr 1, 2019 6:50 PM UTC

Hmm, CMSIS seems to know ITM LAR...

turboscrew
Senior III
Apr 2, 2019 10:31 AM UTC

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