cortex_m3.c 57.3 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
	dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum);
76
77
78

	/* mem_ap_read_u32(swjdp, DCB_DCRDR, value); */
	dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
79
	dap_ap_read_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
80

81
	retval = dap_run(swjdp);
82
83
84
85
86
87

	/* 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);

88
89
90
	return retval;
}

91
static int cortexm3_dap_write_coreregister_u32(struct swjdp_common *swjdp,
92
		uint32_t value, int regnum)
93
94
{
	int retval;
95
	uint32_t dcrdr;
96
97

	/* because the DCB_DCRDR is used for the emulated dcc channel
98
	 * we have to save/restore the DCB_DCRDR when used */
99
100
101
102
103

	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);
104
	dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
105

106
	/* mem_ap_write_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR); */
107
	dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
108
	dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR);
109

110
	retval = dap_run(swjdp);
111
112
113
114
115
116

	/* 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);

117
118
119
	return retval;
}

Zachary T Welch's avatar
Zachary T Welch committed
120
static int cortex_m3_write_debug_halt_mask(struct target *target,
121
		uint32_t mask_on, uint32_t mask_off)
122
{
123
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
124
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
zwelch's avatar
zwelch committed
125

126
127
128
129
	/* 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
130

131
	return mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, cortex_m3->dcb_dhcsr);
132
133
}

Zachary T Welch's avatar
Zachary T Welch committed
134
static int cortex_m3_clear_halt(struct target *target)
135
{
136
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
137
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
zwelch's avatar
zwelch committed
138

139
140
	/* clear step if any */
	cortex_m3_write_debug_halt_mask(target, C_HALT, C_STEP);
zwelch's avatar
zwelch committed
141

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

145
	/* Clear Debug Fault Status */
146
	mem_ap_write_atomic_u32(swjdp, NVIC_DFSR, cortex_m3->nvic_dfsr);
duane's avatar
duane committed
147
	LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32 "", cortex_m3->nvic_dfsr);
148
149

	return ERROR_OK;
150
151
}

Zachary T Welch's avatar
Zachary T Welch committed
152
static int cortex_m3_single_step_core(struct target *target)
153
{
154
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
155
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
156
	uint32_t dhcsr_save;
zwelch's avatar
zwelch committed
157

158
159
	/* backup dhcsr reg */
	dhcsr_save = cortex_m3->dcb_dhcsr;
zwelch's avatar
zwelch committed
160

David Brownell's avatar
David Brownell committed
161
162
163
164
	/* 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
165
	if (!(cortex_m3->dcb_dhcsr & C_MASKINTS))
David Brownell's avatar
David Brownell committed
166
167
168
169
		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);
170
	LOG_DEBUG(" ");
zwelch's avatar
zwelch committed
171

172
	/* restore dhcsr reg */
zwelch's avatar
zwelch committed
173
	cortex_m3->dcb_dhcsr = dhcsr_save;
174
	cortex_m3_clear_halt(target);
zwelch's avatar
zwelch committed
175

176
177
178
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
179
static int cortex_m3_endreset_event(struct target *target)
180
181
{
	int i;
182
	int retval;
183
	uint32_t dcb_demcr;
184
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
185
	struct armv7m_common *armv7m = &cortex_m3->armv7m;
186
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
187
	struct cortex_m3_fp_comparator *fp_list = cortex_m3->fp_comparator_list;
188
	struct cortex_m3_dwt_comparator *dwt_list = cortex_m3->dwt_comparator_list;
189

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

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

197
	/* Enable debug requests */
198
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
199
	if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
200
		mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
zwelch's avatar
zwelch committed
201

202
203
	/* clear any interrupt masking */
	cortex_m3_write_debug_halt_mask(target, 0, C_MASKINTS);
zwelch's avatar
zwelch committed
204

205
206
	/* 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
207
	 *
208
209
210
	 * 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
211
	 */
212
	mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | armv7m->demcr);
213

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

218
219
	/* Enable FPB */
	target_write_u32(target, FP_CTRL, 3);
220
	cortex_m3->fpb_enabled = 1;
221
222

	/* Restore FPB registers */
223
	for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++)
224
225
226
	{
		target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
	}
zwelch's avatar
zwelch committed
227

228
	/* Restore DWT registers */
229
	for (i = 0; i < cortex_m3->dwt_num_comp; i++)
230
	{
David Brownell's avatar
David Brownell committed
231
232
233
234
235
236
		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);
237
	}
238
239
240
	retval = dap_run(swjdp);
	if (retval != ERROR_OK)
		return retval;
zwelch's avatar
zwelch committed
241

242
	register_cache_invalidate(cortex_m3->armv7m.core_cache);
zwelch's avatar
zwelch committed
243

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

247
	return retval;
248
249
}

Zachary T Welch's avatar
Zachary T Welch committed
250
static int cortex_m3_examine_debug_reason(struct target *target)
251
{
252
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
253

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

257
	if ((target->debug_reason != DBG_REASON_DBGRQ)
ntfreak's avatar
ntfreak committed
258
		&& (target->debug_reason != DBG_REASON_SINGLESTEP))
259
	{
260
		if (cortex_m3->nvic_dfsr & DFSR_BKPT)
261
262
		{
			target->debug_reason = DBG_REASON_BREAKPOINT;
263
			if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
264
265
				target->debug_reason = DBG_REASON_WPTANDBKPT;
		}
266
		else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
267
			target->debug_reason = DBG_REASON_WATCHPOINT;
268
269
		else if (cortex_m3->nvic_dfsr & DFSR_VCATCH)
			target->debug_reason = DBG_REASON_BREAKPOINT;
David Brownell's avatar
David Brownell committed
270
		else /* EXTERNAL, HALTED */
271
			target->debug_reason = DBG_REASON_UNDEFINED;
272
273
274
275
276
	}

	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
277
static int cortex_m3_examine_exception_reason(struct target *target)
278
{
279
	uint32_t shcsr, except_sr, cfsr = -1, except_ar = -1;
280
	struct armv7m_common *armv7m = target_to_armv7m(target);
281
	struct swjdp_common *swjdp = &armv7m->swjdp_info;
282
	int retval;
283

284
	mem_ap_read_u32(swjdp, NVIC_SHCSR, &shcsr);
285
286
287
288
289
	switch (armv7m->exception_number)
	{
		case 2:	/* NMI */
			break;
		case 3:	/* Hard Fault */
290
			mem_ap_read_atomic_u32(swjdp, NVIC_HFSR, &except_sr);
ntfreak's avatar
ntfreak committed
291
			if (except_sr & 0x40000000)
292
			{
293
				mem_ap_read_u32(swjdp, NVIC_CFSR, &cfsr);
294
295
296
			}
			break;
		case 4:	/* Memory Management */
297
			mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
zwelch's avatar
zwelch committed
298
			mem_ap_read_u32(swjdp, NVIC_MMFAR, &except_ar);
299
300
			break;
		case 5:	/* Bus Fault */
301
			mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
zwelch's avatar
zwelch committed
302
			mem_ap_read_u32(swjdp, NVIC_BFAR, &except_ar);
303
304
			break;
		case 6:	/* Usage Fault */
305
			mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
306
307
308
309
			break;
		case 11:	/* SVCall */
			break;
		case 12:	/* Debug Monitor */
310
			mem_ap_read_u32(swjdp, NVIC_DFSR, &except_sr);
311
312
313
314
315
316
317
318
319
			break;
		case 14:	/* PendSV */
			break;
		case 15:	/* SysTick */
			break;
		default:
			except_sr = 0;
			break;
	}
320
321
322
323
324
325
326
	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;
327
328
}

329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/* 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
347
static int cortex_m3_debug_entry(struct target *target)
348
{
349
	int i;
350
	uint32_t xPSR;
351
	int retval;
352
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
353
	struct armv7m_common *armv7m = &cortex_m3->armv7m;
354
	struct arm *arm = &armv7m->arm;
355
	struct swjdp_common *swjdp = &armv7m->swjdp_info;
David Brownell's avatar
David Brownell committed
356
	struct reg *r;
357

358
	LOG_DEBUG(" ");
359
360

	cortex_m3_clear_halt(target);
361
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
362
363
364
365
366

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

	/* Examine target state and mode */
367
	/* First load register acessible through core debug port*/
368
369
370
	int num_regs = armv7m->core_cache->num_regs;

	for (i = 0; i < num_regs; i++)
371
372
	{
		if (!armv7m->core_cache->reg_list[i].valid)
373
			armv7m->read_core_reg(target, i);
374
375
	}

David Brownell's avatar
David Brownell committed
376
377
	r = armv7m->core_cache->reg_list + ARMV7M_xPSR;
	xPSR = buf_get_u32(r->value, 0, 32);
378
379

#ifdef ARMV7_GDB_HACKS
380
381
382
	/* FIXME this breaks on scan chains with more than one Cortex-M3.
	 * Instead, each CM3 should have its own dummy value...
	 */
383
384
385
	/* 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
386
387
	armv7m_gdb_dummy_cpsr_reg.valid = r->valid;
	armv7m_gdb_dummy_cpsr_reg.dirty = r->dirty;
388
389
#endif

390
	/* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
ntfreak's avatar
ntfreak committed
391
	if (xPSR & 0xf00)
392
	{
David Brownell's avatar
David Brownell committed
393
		r->dirty = r->valid;
ntfreak's avatar
ntfreak committed
394
		cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
395
396
397
	}

	/* Are we in an exception handler */
398
399
400
401
	if (xPSR & 0x1FF)
	{
		armv7m->core_mode = ARMV7M_MODE_HANDLER;
		armv7m->exception_number = (xPSR & 0x1FF);
402
403
404

		arm->core_mode = ARM_MODE_HANDLER;
		arm->map = armv7m_msp_reg_map;
405
	}
406
	else
407
	{
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
		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;

423
424
		armv7m->exception_number = 0;
	}
zwelch's avatar
zwelch committed
425

426
427
428
429
430
	if (armv7m->exception_number)
	{
		cortex_m3_examine_exception_reason(target);
	}

duane's avatar
duane committed
431
	LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
432
		armv7m_mode_strings[armv7m->core_mode],
David Brownell's avatar
David Brownell committed
433
		*(uint32_t*)(arm->pc->value),
434
		target_state_name(target));
435
436
437
438
439
440
441

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

	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
442
static int cortex_m3_poll(struct target *target)
443
444
{
	int retval;
445
	enum target_state prev_target_state = target->state;
446
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
447
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
448
449

	/* Read from Debug Halting Control and Status Register */
450
	retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
451
452
453
	if (retval != ERROR_OK)
	{
		target->state = TARGET_UNKNOWN;
454
		return retval;
455
	}
zwelch's avatar
zwelch committed
456

457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
	/* 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);
	}

472
	if (cortex_m3->dcb_dhcsr & S_RESET_ST)
473
	{
474
		/* check if still in reset */
475
		mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
zwelch's avatar
zwelch committed
476

477
478
479
		if (cortex_m3->dcb_dhcsr & S_RESET_ST)
		{
			target->state = TARGET_RESET;
480
			return ERROR_OK;
481
		}
482
	}
zwelch's avatar
zwelch committed
483

484
	if (target->state == TARGET_RESET)
485
	{
David Brownell's avatar
David Brownell committed
486
487
488
489
490
		/* 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);
491
492
493
494
		cortex_m3_endreset_event(target);
		target->state = TARGET_RUNNING;
		prev_target_state = TARGET_RUNNING;
	}
zwelch's avatar
zwelch committed
495

496
	if (cortex_m3->dcb_dhcsr & S_HALT)
497
498
499
500
501
502
	{
		target->state = TARGET_HALTED;

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

505
506
507
			if (arm_semihosting(target, &retval) != 0)
				return retval;

508
509
510
511
			target_call_event_callbacks(target, TARGET_EVENT_HALTED);
		}
		if (prev_target_state == TARGET_DEBUG_RUNNING)
		{
512
			LOG_DEBUG(" ");
513
			if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
514
				return retval;
515
516
517
518

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

520
521
522
	/* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
	 * How best to model low power modes?
	 */
523

524
525
526
527
528
529
530
531
532
	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
533

534
	return ERROR_OK;
535
536
}

Zachary T Welch's avatar
Zachary T Welch committed
537
static int cortex_m3_halt(struct target *target)
538
{
zwelch's avatar
zwelch committed
539
	LOG_DEBUG("target->state: %s",
540
		target_state_name(target));
zwelch's avatar
zwelch committed
541

542
543
	if (target->state == TARGET_HALTED)
	{
544
		LOG_DEBUG("target was already halted");
oharboe's avatar
   
oharboe committed
545
		return ERROR_OK;
546
	}
zwelch's avatar
zwelch committed
547

548
549
	if (target->state == TARGET_UNKNOWN)
	{
550
		LOG_WARNING("target was in unknown state when halt was requested");
551
	}
zwelch's avatar
zwelch committed
552
553

	if (target->state == TARGET_RESET)
554
	{
555
		if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst())
556
		{
557
			LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
558
559
560
561
562
563
564
565
			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
566
567

			return ERROR_OK;
568
569
570
		}
	}

571
	/* Write to Debug Halting Control and Status Register */
572
	cortex_m3_write_debug_halt_mask(target, C_HALT, 0);
573
574

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

576
577
578
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
579
static int cortex_m3_soft_reset_halt(struct target *target)
580
{
581
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
582
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
583
	uint32_t dcb_dhcsr = 0;
ntfreak's avatar
ntfreak committed
584
	int retval, timeout = 0;
585

586
	/* Enter debug state on reset; restore DEMCR in endreset_event() */
David Brownell's avatar
David Brownell committed
587
588
	mem_ap_write_u32(swjdp, DCB_DEMCR,
			TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
zwelch's avatar
zwelch committed
589

David Brownell's avatar
David Brownell committed
590
591
592
	/* Request a core-only reset */
	mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR,
			AIRCR_VECTKEY | AIRCR_VECTRESET);
593
594
595
	target->state = TARGET_RESET;

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

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

625
626
627
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
628
static void cortex_m3_enable_breakpoints(struct target *target)
629
{
630
	struct breakpoint *breakpoint = target->breakpoints;
631
632
633
634

	/* set any pending breakpoints */
	while (breakpoint)
	{
635
		if (!breakpoint->set)
636
637
638
639
640
			cortex_m3_set_breakpoint(target, breakpoint);
		breakpoint = breakpoint->next;
	}
}

Zachary T Welch's avatar
Zachary T Welch committed
641
static int cortex_m3_resume(struct target *target, int current,
642
		uint32_t address, int handle_breakpoints, int debug_execution)
643
{
644
	struct armv7m_common *armv7m = target_to_armv7m(target);
645
	struct breakpoint *breakpoint = NULL;
646
	uint32_t resume_pc;
David Brownell's avatar
David Brownell committed
647
	struct reg *r;
zwelch's avatar
zwelch committed
648

649
650
	if (target->state != TARGET_HALTED)
	{
651
		LOG_WARNING("target not halted");
652
653
		return ERROR_TARGET_NOT_HALTED;
	}
zwelch's avatar
zwelch committed
654

655
656
657
658
659
660
	if (!debug_execution)
	{
		target_free_all_working_areas(target);
		cortex_m3_enable_breakpoints(target);
		cortex_m3_enable_watchpoints(target);
	}
zwelch's avatar
zwelch committed
661

662
663
	if (debug_execution)
	{
David Brownell's avatar
David Brownell committed
664
665
		r = armv7m->core_cache->reg_list + ARMV7M_PRIMASK;

666
		/* Disable interrupts */
David Brownell's avatar
David Brownell committed
667
668
669
670
671
672
673
674
675
676
677
678
679
		/* 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;
680

681
		/* Make sure we are in Thumb mode */
David Brownell's avatar
David Brownell committed
682
683
684
685
		r = armv7m->core_cache->reg_list + ARMV7M_xPSR;
		buf_set_u32(r->value, 24, 1, 1);
		r->dirty = true;
		r->valid = true;
686
687
688
	}

	/* current = 1: continue on current pc, otherwise continue at <address> */
David Brownell's avatar
David Brownell committed
689
	r = armv7m->arm.pc;
zwelch's avatar
zwelch committed
690
	if (!current)
691
	{
David Brownell's avatar
David Brownell committed
692
693
694
		buf_set_u32(r->value, 0, 32, address);
		r->dirty = true;
		r->valid = true;
695
	}
zwelch's avatar
zwelch committed
696

697
698
699
700
701
702
703
704
705
706
	/* 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
707
	resume_pc = buf_get_u32(r->value, 0, 32);
708

709
	armv7m_restore_context(target);
zwelch's avatar
zwelch committed
710

711
712
713
714
715
716
	/* 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)))
		{
717
			LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %d)",
718
					  breakpoint->address,
David Brownell's avatar
David Brownell committed
719
					  breakpoint->unique_id);
720
721
722
			cortex_m3_unset_breakpoint(target, breakpoint);
			cortex_m3_single_step_core(target);
			cortex_m3_set_breakpoint(target, breakpoint);
723
724
		}
	}
zwelch's avatar
zwelch committed
725

726
	/* Restart core */
727
	cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
zwelch's avatar
zwelch committed
728

729
730
731
	target->debug_reason = DBG_REASON_NOTHALTED;

	/* registers are now invalid */
732
733
	register_cache_invalidate(armv7m->core_cache);

734
735
736
737
	if (!debug_execution)
	{
		target->state = TARGET_RUNNING;
		target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
duane's avatar
duane committed
738
		LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
739
740
741
742
743
	}
	else
	{
		target->state = TARGET_DEBUG_RUNNING;
		target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
duane's avatar
duane committed
744
		LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
745
	}
zwelch's avatar
zwelch committed
746

747
748
749
	return ERROR_OK;
}

zwelch's avatar
zwelch committed
750
/* int irqstepcount = 0; */
Zachary T Welch's avatar
Zachary T Welch committed
751
static int cortex_m3_step(struct target *target, int current,
752
		uint32_t address, int handle_breakpoints)
753
{
754
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
755
	struct armv7m_common *armv7m = &cortex_m3->armv7m;
756
	struct swjdp_common *swjdp = &armv7m->swjdp_info;
757
	struct breakpoint *breakpoint = NULL;
David Brownell's avatar
David Brownell committed
758
	struct reg *pc = armv7m->arm.pc;
759
	bool bkpt_inst_found = false;
760
761
762

	if (target->state != TARGET_HALTED)
	{
763
		LOG_WARNING("target not halted");
764
765
766
767
768
		return ERROR_TARGET_NOT_HALTED;
	}

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

771
	/* the front-end may request us not to handle breakpoints */
772
	if (handle_breakpoints) {
David Brownell's avatar
David Brownell committed
773
774
		breakpoint = breakpoint_find(target,
				buf_get_u32(pc->value, 0, 32));
775
		if (breakpoint)
776
			cortex_m3_unset_breakpoint(target, breakpoint);
777
	}
zwelch's avatar
zwelch committed
778

779
780
	armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);

781
	target->debug_reason = DBG_REASON_SINGLESTEP;
zwelch's avatar
zwelch committed
782

783
	armv7m_restore_context(target);
zwelch's avatar
zwelch committed
784

785
	target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
zwelch's avatar
zwelch committed
786

787
788
789
790
791
792
793
794
795
	/* 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);
	}

796
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
797

798
	/* registers are now invalid */
799
	register_cache_invalidate(cortex_m3->armv7m.core_cache);
zwelch's avatar
zwelch committed
800

801
802
803
	if (breakpoint)
		cortex_m3_set_breakpoint(target, breakpoint);

David Brownell's avatar
David Brownell committed
804
805
806
	LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
			" nvic_icsr = 0x%" PRIx32,
			cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
807
808
809
810

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

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

815
816
817
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
818
static int cortex_m3_assert_reset(struct target *target)
819
{
820
	struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
821
	struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
oharboe's avatar
oharboe committed
822
	int assert_srst = 1;
zwelch's avatar
zwelch committed
823
824

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

827
	enum reset_types jtag_reset_config = jtag_get_reset_config();
828
829
830
831
832
833

	/*
	 * 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.
	 */
834
	if (!(jtag_reset_config & RESET_HAS_SRST))
835
		assert_srst = 0;
zwelch's avatar
zwelch committed
836

837
	/* Enable debug requests */
838
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
839
	if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
840
		mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
zwelch's avatar
zwelch committed
841

842
	mem_ap_write_u32(swjdp, DCB_DCRDR, 0);
zwelch's avatar
zwelch committed
843

oharboe's avatar
   
oharboe committed
844
	if (!target->reset_halt)
845
846
847
	{
		/* Set/Clear C_MASKINTS in a separate operation */
		if (cortex_m3->dcb_dhcsr & C_MASKINTS)
David Brownell's avatar
David Brownell committed
848
849
			mem_ap_write_atomic_u32(swjdp, DCB_DHCSR,
					DBGKEY | C_DEBUGEN | C_HALT);
850
851

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

854
855
		/* clear C_HALT in dhcsr reg */
		cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
856
	}
857
858
	else
	{
859
860
861
862
863
864
		/* Halt in debug on reset; endreset_event() restores DEMCR.
		 *
		 * REVISIT catching BUSERR presumably helps to defend against
		 * bad vector table entries.  Should this include MMERR or
		 * other flags too?
		 */
David Brownell's avatar
David Brownell committed