cortex_m3.c 57.5 KB
Newer Older
1
2
3
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
oharboe's avatar
oharboe committed
4
 *                                                                         *
5
6
7
 *   Copyright (C) 2006 by Magnus Lundin                                   *
 *   lundin@mlu.mine.nu                                                    *
 *                                                                         *
8
9
10
 *   Copyright (C) 2008 by Spencer Oliver                                  *
 *   spen@spen-soft.co.uk                                                  *
 *                                                                         *
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
25
26
 *                                                                         *
 *                                                                         *
27
 *   Cortex-M3(tm) TRM, ARM DDI 0337E (r1p1) and 0337G (r2p0)              *
28
 *                                                                         *
29
30
31
32
33
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

34
#include "breakpoints.h"
35
#include "cortex_m3.h"
36
#include "target_request.h"
37
#include "target_type.h"
zwelch's avatar
zwelch committed
38
#include "arm_disassembler.h"
39
#include "register.h"
40
#include "arm_opcodes.h"
41
#include "arm_semihosting.h"
42

43
44
/* NOTE:  most of this should work fine for the Cortex-M1 and
 * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M.
45
46
47
 * Some differences:  M0/M1 doesn't have FBP remapping or the
 * DWT tracing/profiling support.  (So the cycle counter will
 * not be usable; the other stuff isn't currently used here.)
David Brownell's avatar
David Brownell committed
48
49
50
51
 *
 * Although there are some workarounds for errata seen only in r0p0
 * silicon, such old parts are hard to find and thus not much tested
 * any longer.
52
53
 */

54

55
/* forward declarations */
Zachary T Welch's avatar
Zachary T Welch committed
56
57
58
59
static int cortex_m3_set_breakpoint(struct target *target, struct breakpoint *breakpoint);
static int cortex_m3_unset_breakpoint(struct target *target, struct breakpoint *breakpoint);
static void cortex_m3_enable_watchpoints(struct target *target);
static int cortex_m3_store_core_reg_u32(struct target *target,
60
		enum armv7m_regtype type, uint32_t num, uint32_t value);
61

62
static int cortexm3_dap_read_coreregister_u32(struct swjdp_common *swjdp,
63
		uint32_t *value, int regnum)
64
65
{
	int retval;
66
	uint32_t dcrdr;
67
68

	/* because the DCB_DCRDR is used for the emulated dcc channel
69
	 * we have to save/restore the DCB_DCRDR when used */
70
71
72
73
74

	mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr);

	/* mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); */
	dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
75
76
77
	retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum);
	if (retval != ERROR_OK)
		return retval;
78
79
80

	/* mem_ap_read_u32(swjdp, DCB_DCRDR, value); */
	dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
81
82
83
	retval = dap_queue_ap_read(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
	if (retval != ERROR_OK)
		return retval;
84

85
	retval = dap_run(swjdp);
86
87
	if (retval != ERROR_OK)
		return retval;
88
89
90
91
92
93

	/* restore DCB_DCRDR - this needs to be in a seperate
	 * transaction otherwise the emulated DCC channel breaks */
	if (retval == ERROR_OK)
		retval = mem_ap_write_atomic_u32(swjdp, DCB_DCRDR, dcrdr);

94
95
96
	return retval;
}

97
static int cortexm3_dap_write_coreregister_u32(struct swjdp_common *swjdp,
98
		uint32_t value, int regnum)
99
100
{
	int retval;
101
	uint32_t dcrdr;
102
103

	/* because the DCB_DCRDR is used for the emulated dcc channel
104
	 * we have to save/restore the DCB_DCRDR when used */
105
106
107
108
109

	mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr);

	/* mem_ap_write_u32(swjdp, DCB_DCRDR, core_regs[i]); */
	dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
110
111
	retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
	// XXX check retval
112

113
	/* mem_ap_write_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR); */
114
	dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
115
116
	retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR);
	// XXX check retval
117

118
	retval = dap_run(swjdp);
119
120
121
122
123
124

	/* restore DCB_DCRDR - this needs to be in a seperate
	 * transaction otherwise the emulated DCC channel breaks */
	if (retval == ERROR_OK)
		retval = mem_ap_write_atomic_u32(swjdp, DCB_DCRDR, dcrdr);

125
126
127
	return retval;
}

Zachary T Welch's avatar
Zachary T Welch committed
128
static int cortex_m3_write_debug_halt_mask(struct target *target,
129
		uint32_t mask_on, uint32_t mask_off)
130
{
131
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
132
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
zwelch's avatar
zwelch committed
133

134
135
136
137
	/* mask off status bits */
	cortex_m3->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off);
	/* create new register mask */
	cortex_m3->dcb_dhcsr |= DBGKEY | C_DEBUGEN | mask_on;
zwelch's avatar
zwelch committed
138

139
	return mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, cortex_m3->dcb_dhcsr);
140
141
}

Zachary T Welch's avatar
Zachary T Welch committed
142
static int cortex_m3_clear_halt(struct target *target)
143
{
144
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
145
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
zwelch's avatar
zwelch committed
146

147
148
	/* clear step if any */
	cortex_m3_write_debug_halt_mask(target, C_HALT, C_STEP);
zwelch's avatar
zwelch committed
149

150
	/* Read Debug Fault Status Register */
151
	mem_ap_read_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
David Brownell's avatar
David Brownell committed
152

153
	/* Clear Debug Fault Status */
154
	mem_ap_write_atomic_u32(swjdp, NVIC_DFSR, cortex_m3->nvic_dfsr);
duane's avatar
duane committed
155
	LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32 "", cortex_m3->nvic_dfsr);
156
157

	return ERROR_OK;
158
159
}

Zachary T Welch's avatar
Zachary T Welch committed
160
static int cortex_m3_single_step_core(struct target *target)
161
{
162
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
163
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
164
	uint32_t dhcsr_save;
zwelch's avatar
zwelch committed
165

166
167
	/* backup dhcsr reg */
	dhcsr_save = cortex_m3->dcb_dhcsr;
zwelch's avatar
zwelch committed
168

David Brownell's avatar
David Brownell committed
169
170
171
172
	/* Mask interrupts before clearing halt, if done already.  This avoids
	 * Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing
	 * HALT can put the core into an unknown state.
	 */
ntfreak's avatar
ntfreak committed
173
	if (!(cortex_m3->dcb_dhcsr & C_MASKINTS))
David Brownell's avatar
David Brownell committed
174
175
176
177
		mem_ap_write_atomic_u32(swjdp, DCB_DHCSR,
				DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN);
	mem_ap_write_atomic_u32(swjdp, DCB_DHCSR,
				DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN);
178
	LOG_DEBUG(" ");
zwelch's avatar
zwelch committed
179

180
	/* restore dhcsr reg */
zwelch's avatar
zwelch committed
181
	cortex_m3->dcb_dhcsr = dhcsr_save;
182
	cortex_m3_clear_halt(target);
zwelch's avatar
zwelch committed
183

184
185
186
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
187
static int cortex_m3_endreset_event(struct target *target)
188
189
{
	int i;
190
	int retval;
191
	uint32_t dcb_demcr;
192
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
193
	struct armv7m_common *armv7m = &cortex_m3->armv7m;
194
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
195
	struct cortex_m3_fp_comparator *fp_list = cortex_m3->fp_comparator_list;
196
	struct cortex_m3_dwt_comparator *dwt_list = cortex_m3->dwt_comparator_list;
197

198
	/* REVISIT The four debug monitor bits are currently ignored... */
199
	mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr);
duane's avatar
duane committed
200
	LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32 "",dcb_demcr);
zwelch's avatar
zwelch committed
201

David Brownell's avatar
David Brownell committed
202
	/* this register is used for emulated dcc channel */
203
	mem_ap_write_u32(swjdp, DCB_DCRDR, 0);
zwelch's avatar
zwelch committed
204

205
	/* Enable debug requests */
206
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
207
	if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
208
		mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
zwelch's avatar
zwelch committed
209

210
211
	/* clear any interrupt masking */
	cortex_m3_write_debug_halt_mask(target, 0, C_MASKINTS);
zwelch's avatar
zwelch committed
212

213
214
	/* Enable features controlled by ITM and DWT blocks, and catch only
	 * the vectors we were told to pay attention to.
David Brownell's avatar
David Brownell committed
215
	 *
216
217
218
	 * Target firmware is responsible for all fault handling policy
	 * choices *EXCEPT* explicitly scripted overrides like "vector_catch"
	 * or manual updates to the NVIC SHCSR and CCR registers.
David Brownell's avatar
David Brownell committed
219
	 */
220
	mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | armv7m->demcr);
221

David Brownell's avatar
David Brownell committed
222
223
224
225
	/* Paranoia: evidently some (early?) chips don't preserve all the
	 * debug state (including FBP, DWT, etc) across reset...
	 */

226
227
	/* Enable FPB */
	target_write_u32(target, FP_CTRL, 3);
228
	cortex_m3->fpb_enabled = 1;
229
230

	/* Restore FPB registers */
231
	for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++)
232
233
234
	{
		target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
	}
zwelch's avatar
zwelch committed
235

236
	/* Restore DWT registers */
237
	for (i = 0; i < cortex_m3->dwt_num_comp; i++)
238
	{
David Brownell's avatar
David Brownell committed
239
240
241
242
243
244
		target_write_u32(target, dwt_list[i].dwt_comparator_address + 0,
				dwt_list[i].comp);
		target_write_u32(target, dwt_list[i].dwt_comparator_address + 4,
				dwt_list[i].mask);
		target_write_u32(target, dwt_list[i].dwt_comparator_address + 8,
				dwt_list[i].function);
245
	}
246
247
248
	retval = dap_run(swjdp);
	if (retval != ERROR_OK)
		return retval;
zwelch's avatar
zwelch committed
249

250
	register_cache_invalidate(cortex_m3->armv7m.core_cache);
zwelch's avatar
zwelch committed
251

252
	/* make sure we have latest dhcsr flags */
253
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
zwelch's avatar
zwelch committed
254

255
	return retval;
256
257
}

Zachary T Welch's avatar
Zachary T Welch committed
258
static int cortex_m3_examine_debug_reason(struct target *target)
259
{
260
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
261

262
	/* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason */
263
	/* only check the debug reason if we don't know it already */
zwelch's avatar
zwelch committed
264

265
	if ((target->debug_reason != DBG_REASON_DBGRQ)
ntfreak's avatar
ntfreak committed
266
		&& (target->debug_reason != DBG_REASON_SINGLESTEP))
267
	{
268
		if (cortex_m3->nvic_dfsr & DFSR_BKPT)
269
270
		{
			target->debug_reason = DBG_REASON_BREAKPOINT;
271
			if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
272
273
				target->debug_reason = DBG_REASON_WPTANDBKPT;
		}
274
		else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
275
			target->debug_reason = DBG_REASON_WATCHPOINT;
276
277
		else if (cortex_m3->nvic_dfsr & DFSR_VCATCH)
			target->debug_reason = DBG_REASON_BREAKPOINT;
David Brownell's avatar
David Brownell committed
278
		else /* EXTERNAL, HALTED */
279
			target->debug_reason = DBG_REASON_UNDEFINED;
280
281
282
283
284
	}

	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
285
static int cortex_m3_examine_exception_reason(struct target *target)
286
{
287
	uint32_t shcsr, except_sr, cfsr = -1, except_ar = -1;
288
	struct armv7m_common *armv7m = target_to_armv7m(target);
289
	struct swjdp_common *swjdp = &armv7m->swjdp_info;
290
	int retval;
291

292
	mem_ap_read_u32(swjdp, NVIC_SHCSR, &shcsr);
293
294
295
296
297
	switch (armv7m->exception_number)
	{
		case 2:	/* NMI */
			break;
		case 3:	/* Hard Fault */
298
			mem_ap_read_atomic_u32(swjdp, NVIC_HFSR, &except_sr);
ntfreak's avatar
ntfreak committed
299
			if (except_sr & 0x40000000)
300
			{
301
				mem_ap_read_u32(swjdp, NVIC_CFSR, &cfsr);
302
303
304
			}
			break;
		case 4:	/* Memory Management */
305
			mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
zwelch's avatar
zwelch committed
306
			mem_ap_read_u32(swjdp, NVIC_MMFAR, &except_ar);
307
308
			break;
		case 5:	/* Bus Fault */
309
			mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
zwelch's avatar
zwelch committed
310
			mem_ap_read_u32(swjdp, NVIC_BFAR, &except_ar);
311
312
			break;
		case 6:	/* Usage Fault */
313
			mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
314
315
316
317
			break;
		case 11:	/* SVCall */
			break;
		case 12:	/* Debug Monitor */
318
			mem_ap_read_u32(swjdp, NVIC_DFSR, &except_sr);
319
320
321
322
323
324
325
326
327
			break;
		case 14:	/* PendSV */
			break;
		case 15:	/* SysTick */
			break;
		default:
			except_sr = 0;
			break;
	}
328
329
330
331
332
333
334
	retval = dap_run(swjdp);
	if (retval == ERROR_OK)
		LOG_DEBUG("%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32
			", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32,
			armv7m_exception_string(armv7m->exception_number),
			shcsr, except_sr, cfsr, except_ar);
	return retval;
335
336
}

337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
/* PSP is used in some thread modes */
static const int armv7m_psp_reg_map[17] = {
	ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
	ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
	ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
	ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC,
	ARMV7M_xPSR,
};

/* MSP is used in handler and some thread modes */
static const int armv7m_msp_reg_map[17] = {
	ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
	ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
	ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
	ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC,
	ARMV7M_xPSR,
};

Zachary T Welch's avatar
Zachary T Welch committed
355
static int cortex_m3_debug_entry(struct target *target)
356
{
357
	int i;
358
	uint32_t xPSR;
359
	int retval;
360
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
361
	struct armv7m_common *armv7m = &cortex_m3->armv7m;
362
	struct arm *arm = &armv7m->arm;
363
	struct swjdp_common *swjdp = &armv7m->swjdp_info;
David Brownell's avatar
David Brownell committed
364
	struct reg *r;
365

366
	LOG_DEBUG(" ");
367
368

	cortex_m3_clear_halt(target);
369
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
370
371
372
373
374

	if ((retval = armv7m->examine_debug_reason(target)) != ERROR_OK)
		return retval;

	/* Examine target state and mode */
375
	/* First load register acessible through core debug port*/
376
377
378
	int num_regs = armv7m->core_cache->num_regs;

	for (i = 0; i < num_regs; i++)
379
380
	{
		if (!armv7m->core_cache->reg_list[i].valid)
381
			armv7m->read_core_reg(target, i);
382
383
	}

David Brownell's avatar
David Brownell committed
384
385
	r = armv7m->core_cache->reg_list + ARMV7M_xPSR;
	xPSR = buf_get_u32(r->value, 0, 32);
386
387

#ifdef ARMV7_GDB_HACKS
388
389
390
	/* FIXME this breaks on scan chains with more than one Cortex-M3.
	 * Instead, each CM3 should have its own dummy value...
	 */
391
392
393
	/* copy real xpsr reg for gdb, setting thumb bit */
	buf_set_u32(armv7m_gdb_dummy_cpsr_value, 0, 32, xPSR);
	buf_set_u32(armv7m_gdb_dummy_cpsr_value, 5, 1, 1);
David Brownell's avatar
David Brownell committed
394
395
	armv7m_gdb_dummy_cpsr_reg.valid = r->valid;
	armv7m_gdb_dummy_cpsr_reg.dirty = r->dirty;
396
397
#endif

398
	/* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
ntfreak's avatar
ntfreak committed
399
	if (xPSR & 0xf00)
400
	{
David Brownell's avatar
David Brownell committed
401
		r->dirty = r->valid;
ntfreak's avatar
ntfreak committed
402
		cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
403
404
405
	}

	/* Are we in an exception handler */
406
407
408
409
	if (xPSR & 0x1FF)
	{
		armv7m->core_mode = ARMV7M_MODE_HANDLER;
		armv7m->exception_number = (xPSR & 0x1FF);
410
411
412

		arm->core_mode = ARM_MODE_HANDLER;
		arm->map = armv7m_msp_reg_map;
413
	}
414
	else
415
	{
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
		unsigned control = buf_get_u32(armv7m->core_cache
				->reg_list[ARMV7M_CONTROL].value, 0, 2);

		/* is this thread privileged? */
		armv7m->core_mode = control & 1;
		arm->core_mode = armv7m->core_mode
				? ARM_MODE_USER_THREAD
				: ARM_MODE_THREAD;

		/* which stack is it using? */
		if (control & 2)
			arm->map = armv7m_psp_reg_map;
		else
			arm->map = armv7m_msp_reg_map;

431
432
		armv7m->exception_number = 0;
	}
zwelch's avatar
zwelch committed
433

434
435
436
437
438
	if (armv7m->exception_number)
	{
		cortex_m3_examine_exception_reason(target);
	}

duane's avatar
duane committed
439
	LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
440
		armv7m_mode_strings[armv7m->core_mode],
David Brownell's avatar
David Brownell committed
441
		*(uint32_t*)(arm->pc->value),
442
		target_state_name(target));
443
444
445
446
447
448
449

	if (armv7m->post_debug_entry)
		armv7m->post_debug_entry(target);

	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
450
static int cortex_m3_poll(struct target *target)
451
452
{
	int retval;
453
	enum target_state prev_target_state = target->state;
454
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
455
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
456
457

	/* Read from Debug Halting Control and Status Register */
458
	retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
459
460
461
	if (retval != ERROR_OK)
	{
		target->state = TARGET_UNKNOWN;
462
		return retval;
463
	}
zwelch's avatar
zwelch committed
464

465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
	/* Recover from lockup.  See ARMv7-M architecture spec,
	 * section B1.5.15 "Unrecoverable exception cases".
	 *
	 * REVISIT Is there a better way to report and handle this?
	 */
	if (cortex_m3->dcb_dhcsr & S_LOCKUP) {
		LOG_WARNING("%s -- clearing lockup after double fault",
				target_name(target));
		cortex_m3_write_debug_halt_mask(target, C_HALT, 0);
		target->debug_reason = DBG_REASON_DBGRQ;

		/* refresh status bits */
		mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
	}

480
	if (cortex_m3->dcb_dhcsr & S_RESET_ST)
481
	{
482
		/* check if still in reset */
483
		mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
zwelch's avatar
zwelch committed
484

485
486
487
		if (cortex_m3->dcb_dhcsr & S_RESET_ST)
		{
			target->state = TARGET_RESET;
488
			return ERROR_OK;
489
		}
490
	}
zwelch's avatar
zwelch committed
491

492
	if (target->state == TARGET_RESET)
493
	{
David Brownell's avatar
David Brownell committed
494
495
496
497
498
		/* Cannot switch context while running so endreset is
		 * called with target->state == TARGET_RESET
		 */
		LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32,
				cortex_m3->dcb_dhcsr);
499
500
501
502
		cortex_m3_endreset_event(target);
		target->state = TARGET_RUNNING;
		prev_target_state = TARGET_RUNNING;
	}
zwelch's avatar
zwelch committed
503

504
	if (cortex_m3->dcb_dhcsr & S_HALT)
505
506
507
508
509
510
	{
		target->state = TARGET_HALTED;

		if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET))
		{
			if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
511
				return retval;
zwelch's avatar
zwelch committed
512

513
514
515
			if (arm_semihosting(target, &retval) != 0)
				return retval;

516
517
518
519
			target_call_event_callbacks(target, TARGET_EVENT_HALTED);
		}
		if (prev_target_state == TARGET_DEBUG_RUNNING)
		{
520
			LOG_DEBUG(" ");
521
			if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
522
				return retval;
523
524
525
526

			target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
		}
	}
zwelch's avatar
zwelch committed
527

528
529
530
	/* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
	 * How best to model low power modes?
	 */
531

532
533
534
535
536
537
538
539
540
	if (target->state == TARGET_UNKNOWN)
	{
		/* check if processor is retiring instructions */
		if (cortex_m3->dcb_dhcsr & S_RETIRE_ST)
		{
			target->state = TARGET_RUNNING;
			return ERROR_OK;
		}
	}
zwelch's avatar
zwelch committed
541

542
	return ERROR_OK;
543
544
}

Zachary T Welch's avatar
Zachary T Welch committed
545
static int cortex_m3_halt(struct target *target)
546
{
zwelch's avatar
zwelch committed
547
	LOG_DEBUG("target->state: %s",
548
		target_state_name(target));
zwelch's avatar
zwelch committed
549

550
551
	if (target->state == TARGET_HALTED)
	{
552
		LOG_DEBUG("target was already halted");
oharboe's avatar
   
oharboe committed
553
		return ERROR_OK;
554
	}
zwelch's avatar
zwelch committed
555

556
557
	if (target->state == TARGET_UNKNOWN)
	{
558
		LOG_WARNING("target was in unknown state when halt was requested");
559
	}
zwelch's avatar
zwelch committed
560
561

	if (target->state == TARGET_RESET)
562
	{
563
		if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst())
564
		{
565
			LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
566
567
568
569
570
571
572
573
			return ERROR_TARGET_FAILURE;
		}
		else
		{
			/* we came here in a reset_halt or reset_init sequence
			 * debug entry was already prepared in cortex_m3_prepare_reset_halt()
			 */
			target->debug_reason = DBG_REASON_DBGRQ;
zwelch's avatar
zwelch committed
574
575

			return ERROR_OK;
576
577
578
		}
	}

579
	/* Write to Debug Halting Control and Status Register */
580
	cortex_m3_write_debug_halt_mask(target, C_HALT, 0);
581
582

	target->debug_reason = DBG_REASON_DBGRQ;
zwelch's avatar
zwelch committed
583

584
585
586
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
587
static int cortex_m3_soft_reset_halt(struct target *target)
588
{
589
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
590
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
591
	uint32_t dcb_dhcsr = 0;
ntfreak's avatar
ntfreak committed
592
	int retval, timeout = 0;
593

594
	/* Enter debug state on reset; restore DEMCR in endreset_event() */
David Brownell's avatar
David Brownell committed
595
596
	mem_ap_write_u32(swjdp, DCB_DEMCR,
			TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
zwelch's avatar
zwelch committed
597

David Brownell's avatar
David Brownell committed
598
599
600
	/* Request a core-only reset */
	mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR,
			AIRCR_VECTKEY | AIRCR_VECTRESET);
601
602
603
	target->state = TARGET_RESET;

	/* registers are now invalid */
604
	register_cache_invalidate(cortex_m3->armv7m.core_cache);
605

606
	while (timeout < 100)
607
	{
608
		retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
609
610
		if (retval == ERROR_OK)
		{
David Brownell's avatar
David Brownell committed
611
612
613
614
			mem_ap_read_atomic_u32(swjdp, NVIC_DFSR,
					&cortex_m3->nvic_dfsr);
			if ((dcb_dhcsr & S_HALT)
					&& (cortex_m3->nvic_dfsr & DFSR_VCATCH))
615
			{
David Brownell's avatar
David Brownell committed
616
617
618
619
				LOG_DEBUG("system reset-halted, DHCSR 0x%08x, "
					"DFSR 0x%08x",
					(unsigned) dcb_dhcsr,
					(unsigned) cortex_m3->nvic_dfsr);
620
				cortex_m3_poll(target);
David Brownell's avatar
David Brownell committed
621
				/* FIXME restore user's vector catch config */
622
623
624
				return ERROR_OK;
			}
			else
David Brownell's avatar
David Brownell committed
625
626
627
				LOG_DEBUG("waiting for system reset-halt, "
					"DHCSR 0x%08x, %d ms",
					(unsigned) dcb_dhcsr, timeout);
628
629
		}
		timeout++;
630
		alive_sleep(1);
631
	}
zwelch's avatar
zwelch committed
632

633
634
635
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
636
static void cortex_m3_enable_breakpoints(struct target *target)
637
{
638
	struct breakpoint *breakpoint = target->breakpoints;
639
640
641
642

	/* set any pending breakpoints */
	while (breakpoint)
	{
643
		if (!breakpoint->set)
644
645
646
647
648
			cortex_m3_set_breakpoint(target, breakpoint);
		breakpoint = breakpoint->next;
	}
}

Zachary T Welch's avatar
Zachary T Welch committed
649
static int cortex_m3_resume(struct target *target, int current,
650
		uint32_t address, int handle_breakpoints, int debug_execution)
651
{
652
	struct armv7m_common *armv7m = target_to_armv7m(target);
653
	struct breakpoint *breakpoint = NULL;
654
	uint32_t resume_pc;
David Brownell's avatar
David Brownell committed
655
	struct reg *r;
zwelch's avatar
zwelch committed
656

657
658
	if (target->state != TARGET_HALTED)
	{
659
		LOG_WARNING("target not halted");
660
661
		return ERROR_TARGET_NOT_HALTED;
	}
zwelch's avatar
zwelch committed
662

663
664
665
666
667
668
	if (!debug_execution)
	{
		target_free_all_working_areas(target);
		cortex_m3_enable_breakpoints(target);
		cortex_m3_enable_watchpoints(target);
	}
zwelch's avatar
zwelch committed
669

670
671
	if (debug_execution)
	{
David Brownell's avatar
David Brownell committed
672
673
		r = armv7m->core_cache->reg_list + ARMV7M_PRIMASK;

674
		/* Disable interrupts */
David Brownell's avatar
David Brownell committed
675
676
677
678
679
680
681
682
683
684
685
686
687
		/* We disable interrupts in the PRIMASK register instead of
		 * masking with C_MASKINTS.  This is probably the same issue
		 * as Cortex-M3 Erratum 377493 (fixed in r1p0):  C_MASKINTS
		 * in parallel with disabled interrupts can cause local faults
		 * to not be taken.
		 *
		 * REVISIT this clearly breaks non-debug execution, since the
		 * PRIMASK register state isn't saved/restored...  workaround
		 * by never resuming app code after debug execution.
		 */
		buf_set_u32(r->value, 0, 1, 1);
		r->dirty = true;
		r->valid = true;
688

689
		/* Make sure we are in Thumb mode */
David Brownell's avatar
David Brownell committed
690
691
692
693
		r = armv7m->core_cache->reg_list + ARMV7M_xPSR;
		buf_set_u32(r->value, 24, 1, 1);
		r->dirty = true;
		r->valid = true;
694
695
696
	}

	/* current = 1: continue on current pc, otherwise continue at <address> */
David Brownell's avatar
David Brownell committed
697
	r = armv7m->arm.pc;
zwelch's avatar
zwelch committed
698
	if (!current)
699
	{
David Brownell's avatar
David Brownell committed
700
701
702
		buf_set_u32(r->value, 0, 32, address);
		r->dirty = true;
		r->valid = true;
703
	}
zwelch's avatar
zwelch committed
704

705
706
707
708
709
710
711
712
713
714
	/* if we halted last time due to a bkpt instruction
	 * then we have to manually step over it, otherwise
	 * the core will break again */

	if (!breakpoint_find(target, buf_get_u32(r->value, 0, 32))
			&& !debug_execution)
	{
		armv7m_maybe_skip_bkpt_inst(target, NULL);
	}

David Brownell's avatar
David Brownell committed
715
	resume_pc = buf_get_u32(r->value, 0, 32);
716

717
	armv7m_restore_context(target);
zwelch's avatar
zwelch committed
718

719
720
721
722
723
724
	/* the front-end may request us not to handle breakpoints */
	if (handle_breakpoints)
	{
		/* Single step past breakpoint at current address */
		if ((breakpoint = breakpoint_find(target, resume_pc)))
		{
725
			LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %d)",
726
					  breakpoint->address,
David Brownell's avatar
David Brownell committed
727
					  breakpoint->unique_id);
728
729
730
			cortex_m3_unset_breakpoint(target, breakpoint);
			cortex_m3_single_step_core(target);
			cortex_m3_set_breakpoint(target, breakpoint);
731
732
		}
	}
zwelch's avatar
zwelch committed
733

734
	/* Restart core */
735
	cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
zwelch's avatar
zwelch committed
736

737
738
739
	target->debug_reason = DBG_REASON_NOTHALTED;

	/* registers are now invalid */
740
741
	register_cache_invalidate(armv7m->core_cache);

742
743
744
745
	if (!debug_execution)
	{
		target->state = TARGET_RUNNING;
		target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
duane's avatar
duane committed
746
		LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
747
748
749
750
751
	}
	else
	{
		target->state = TARGET_DEBUG_RUNNING;
		target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
duane's avatar
duane committed
752
		LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
753
	}
zwelch's avatar
zwelch committed
754

755
756
757
	return ERROR_OK;
}

zwelch's avatar
zwelch committed
758
/* int irqstepcount = 0; */
Zachary T Welch's avatar
Zachary T Welch committed
759
static int cortex_m3_step(struct target *target, int current,
760
		uint32_t address, int handle_breakpoints)
761
{
762
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
763
	struct armv7m_common *armv7m = &cortex_m3->armv7m;
764
	struct swjdp_common *swjdp = &armv7m->swjdp_info;
765
	struct breakpoint *breakpoint = NULL;
David Brownell's avatar
David Brownell committed
766
	struct reg *pc = armv7m->arm.pc;
767
	bool bkpt_inst_found = false;
768
769
770

	if (target->state != TARGET_HALTED)
	{
771
		LOG_WARNING("target not halted");
772
773
774
775
776
		return ERROR_TARGET_NOT_HALTED;
	}

	/* current = 1: continue on current pc, otherwise continue at <address> */
	if (!current)
David Brownell's avatar
David Brownell committed
777
		buf_set_u32(pc->value, 0, 32, address);
zwelch's avatar
zwelch committed
778

779
	/* the front-end may request us not to handle breakpoints */
780
	if (handle_breakpoints) {
David Brownell's avatar
David Brownell committed
781
782
		breakpoint = breakpoint_find(target,
				buf_get_u32(pc->value, 0, 32));
783
		if (breakpoint)
784
			cortex_m3_unset_breakpoint(target, breakpoint);
785
	}
zwelch's avatar
zwelch committed
786

787
788
	armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);

789
	target->debug_reason = DBG_REASON_SINGLESTEP;
zwelch's avatar
zwelch committed
790

791
	armv7m_restore_context(target);
zwelch's avatar
zwelch committed
792

793
	target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
zwelch's avatar
zwelch committed
794

795
796
797
798
799
800
801
802
803
	/* if no bkpt instruction is found at pc then we can perform
	 * a normal step, otherwise we have to manually step over the bkpt
	 * instruction - as such simulate a step */
	if (bkpt_inst_found == false)
	{
		/* set step and clear halt */
		cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT);
	}

804
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
805

806
	/* registers are now invalid */
807
	register_cache_invalidate(cortex_m3->armv7m.core_cache);
zwelch's avatar
zwelch committed
808

809
810
811
	if (breakpoint)
		cortex_m3_set_breakpoint(target, breakpoint);

David Brownell's avatar
David Brownell committed
812
813
814
	LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
			" nvic_icsr = 0x%" PRIx32,
			cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
815
816
817
818

	cortex_m3_debug_entry(target);
	target_call_event_callbacks(target, TARGET_EVENT_HALTED);

David Brownell's avatar
David Brownell committed
819
820
821
	LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
			" nvic_icsr = 0x%" PRIx32,
			cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
822

823
824
825
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
826
static int cortex_m3_assert_reset(struct target *target)
827
{
828
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
829
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
oharboe's avatar
oharboe committed
830
	int assert_srst = 1;
zwelch's avatar
zwelch committed
831
832

	LOG_DEBUG("target->state: %s",
833
		target_state_name(target));
zwelch's avatar
zwelch committed
834

835
	enum reset_types jtag_reset_config = jtag_get_reset_config();
836
837
838
839
840
841

	/*
	 * We can reset Cortex-M3 targets using just the NVIC without
	 * requiring SRST, getting a SoC reset (or a core-only reset)
	 * instead of a system reset.
	 */
842
	if (!(jtag_reset_config & RESET_HAS_SRST))
843
		assert_srst = 0;
zwelch's avatar
zwelch committed
844

845
	/* Enable debug requests */
846
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
847
	if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
848
		mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
zwelch's avatar
zwelch committed
849

850
	mem_ap_write_u32(swjdp, DCB_DCRDR, 0);
zwelch's avatar
zwelch committed
851

oharboe's avatar
   
oharboe committed
852
	if (!target->reset_halt)
853
854
855
	{
		/* Set/Clear C_MASKINTS in a separate operation */
		if (cortex_m3->dcb_dhcsr & C_MASKINTS)
David Brownell's avatar
David Brownell committed
856
857
			mem_ap_write_atomic_u32(swjdp, DCB_DHCSR,
					DBGKEY | C_DEBUGEN | C_HALT);
858
859

		/* clear any debug flags before resuming */
860
		cortex_m3_clear_halt(target);
zwelch's avatar
zwelch committed
861

862
863
		/* clear C_HALT in dhcsr reg */
		cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
864
	}
865
866
	else
	{
David Brownell's avatar