cortex_m3.c 55.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
34
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "cortex_m3.h"
35
#include "target_request.h"
36
#include "target_type.h"
zwelch's avatar
zwelch committed
37
#include "arm_disassembler.h"
38
39


40
41
42
43
/* NOTE:  most of this should work fine for the Cortex-M1 and
 * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M.
 */

44
45
46
#define ARRAY_SIZE(x)	((int)(sizeof(x)/sizeof((x)[0])))


47
/* forward declarations */
48
49
50
51
52
static int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
static int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
static void cortex_m3_enable_watchpoints(struct target_s *target);
static int cortex_m3_store_core_reg_u32(target_t *target,
		enum armv7m_regtype type, uint32_t num, uint32_t value);
53

54
#ifdef ARMV7_GDB_HACKS
55
extern uint8_t armv7m_gdb_dummy_cpsr_value[];
56
57
58
extern reg_t armv7m_gdb_dummy_cpsr_reg;
#endif

59
60
static int cortexm3_dap_read_coreregister_u32(swjdp_common_t *swjdp,
		uint32_t *value, int regnum)
61
62
{
	int retval;
63
	uint32_t dcrdr;
64
65

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

	mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr);

	swjdp->trans_mode = TRANS_MODE_COMPOSITE;

	/* mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); */
	dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
74
	dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum);
75
76
77

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

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

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

87
88
89
	return retval;
}

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

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

	mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr);

	swjdp->trans_mode = TRANS_MODE_COMPOSITE;

	/* mem_ap_write_u32(swjdp, DCB_DCRDR, core_regs[i]); */
	dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
105
	dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
106

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

	retval = swjdp_transaction_endcheck(swjdp);
112
113
114
115
116
117

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

118
119
120
	return retval;
}

121
122
static int cortex_m3_write_debug_halt_mask(target_t *target,
		uint32_t mask_on, uint32_t mask_off)
123
{
124
125
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
	struct swjdp_common_s *swjdp = &cortex_m3->armv7m.swjdp_info;
zwelch's avatar
zwelch committed
126

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

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

135
static int cortex_m3_clear_halt(target_t *target)
136
{
137
138
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
	struct swjdp_common_s *swjdp = &cortex_m3->armv7m.swjdp_info;
zwelch's avatar
zwelch committed
139

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

143
	/* Read Debug Fault Status Register */
144
	mem_ap_read_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
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
}

152
static int cortex_m3_single_step_core(target_t *target)
153
{
154
155
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
	struct swjdp_common_s *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

161
	/* mask interrupts if not done already */
ntfreak's avatar
ntfreak committed
162
	if (!(cortex_m3->dcb_dhcsr & C_MASKINTS))
163
164
		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);
165
	LOG_DEBUG(" ");
zwelch's avatar
zwelch committed
166

167
	/* restore dhcsr reg */
zwelch's avatar
zwelch committed
168
	cortex_m3->dcb_dhcsr = dhcsr_save;
169
	cortex_m3_clear_halt(target);
zwelch's avatar
zwelch committed
170

171
172
173
	return ERROR_OK;
}

174
static int cortex_m3_endreset_event(target_t *target)
175
176
{
	int i;
177
	uint32_t dcb_demcr;
178
179
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
	struct swjdp_common_s *swjdp = &cortex_m3->armv7m.swjdp_info;
zwelch's avatar
zwelch committed
180
	cortex_m3_fp_comparator_t *fp_list = cortex_m3->fp_comparator_list;
ntfreak's avatar
ntfreak committed
181
	cortex_m3_dwt_comparator_t *dwt_list = cortex_m3->dwt_comparator_list;
182

183
	mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr);
duane's avatar
duane committed
184
	LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32 "",dcb_demcr);
zwelch's avatar
zwelch committed
185

186
	/* this regsiter is used for emulated dcc channel */
187
	mem_ap_write_u32(swjdp, DCB_DCRDR, 0);
zwelch's avatar
zwelch committed
188

189
	/* Enable debug requests */
190
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
191
	if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
192
		mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
zwelch's avatar
zwelch committed
193

194
195
	/* clear any interrupt masking */
	cortex_m3_write_debug_halt_mask(target, 0, C_MASKINTS);
zwelch's avatar
zwelch committed
196

197
	/* Enable trace and dwt */
198
	mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR);
199
	/* Monitor bus faults */
200
	mem_ap_write_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA);
201
202
203

	/* Enable FPB */
	target_write_u32(target, FP_CTRL, 3);
204
	cortex_m3->fpb_enabled = 1;
205
206

	/* Restore FPB registers */
207
	for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++)
208
209
210
	{
		target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
	}
zwelch's avatar
zwelch committed
211

212
	/* Restore DWT registers */
213
	for (i = 0; i < cortex_m3->dwt_num_comp; i++)
214
	{
David Brownell's avatar
David Brownell committed
215
216
217
218
219
220
		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);
221
	}
222
	swjdp_transaction_endcheck(swjdp);
zwelch's avatar
zwelch committed
223

224
	armv7m_invalidate_core_regs(target);
zwelch's avatar
zwelch committed
225

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

229
230
231
	return ERROR_OK;
}

232
static int cortex_m3_examine_debug_reason(target_t *target)
233
{
234
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
235

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

239
	if ((target->debug_reason != DBG_REASON_DBGRQ)
ntfreak's avatar
ntfreak committed
240
		&& (target->debug_reason != DBG_REASON_SINGLESTEP))
241
	{
242
		if (cortex_m3->nvic_dfsr & DFSR_BKPT)
243
244
		{
			target->debug_reason = DBG_REASON_BREAKPOINT;
245
			if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
246
247
				target->debug_reason = DBG_REASON_WPTANDBKPT;
		}
248
		else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
249
			target->debug_reason = DBG_REASON_WATCHPOINT;
250
251
		else if (cortex_m3->nvic_dfsr & DFSR_VCATCH)
			target->debug_reason = DBG_REASON_BREAKPOINT;
David Brownell's avatar
David Brownell committed
252
		else /* EXTERNAL, HALTED */
253
			target->debug_reason = DBG_REASON_UNDEFINED;
254
255
256
257
258
	}

	return ERROR_OK;
}

259
static int cortex_m3_examine_exception_reason(target_t *target)
260
{
261
	uint32_t shcsr, except_sr, cfsr = -1, except_ar = -1;
262
	struct armv7m_common_s *armv7m = target_to_armv7m(target);
263
	swjdp_common_t *swjdp = &armv7m->swjdp_info;
264

265
	mem_ap_read_u32(swjdp, NVIC_SHCSR, &shcsr);
266
267
268
269
270
	switch (armv7m->exception_number)
	{
		case 2:	/* NMI */
			break;
		case 3:	/* Hard Fault */
271
			mem_ap_read_atomic_u32(swjdp, NVIC_HFSR, &except_sr);
ntfreak's avatar
ntfreak committed
272
			if (except_sr & 0x40000000)
273
			{
274
				mem_ap_read_u32(swjdp, NVIC_CFSR, &cfsr);
275
276
277
			}
			break;
		case 4:	/* Memory Management */
278
			mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
zwelch's avatar
zwelch committed
279
			mem_ap_read_u32(swjdp, NVIC_MMFAR, &except_ar);
280
281
			break;
		case 5:	/* Bus Fault */
282
			mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
zwelch's avatar
zwelch committed
283
			mem_ap_read_u32(swjdp, NVIC_BFAR, &except_ar);
284
285
			break;
		case 6:	/* Usage Fault */
286
			mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
287
288
289
290
			break;
		case 11:	/* SVCall */
			break;
		case 12:	/* Debug Monitor */
291
			mem_ap_read_u32(swjdp, NVIC_DFSR, &except_sr);
292
293
294
295
296
297
298
299
300
301
			break;
		case 14:	/* PendSV */
			break;
		case 15:	/* SysTick */
			break;
		default:
			except_sr = 0;
			break;
	}
	swjdp_transaction_endcheck(swjdp);
duane's avatar
duane committed
302
	LOG_DEBUG("%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32 ", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32 "", armv7m_exception_string(armv7m->exception_number), \
303
		shcsr, except_sr, cfsr, except_ar);
304
305
306
	return ERROR_OK;
}

307
static int cortex_m3_debug_entry(target_t *target)
308
{
309
	int i;
310
	uint32_t xPSR;
311
	int retval;
312
313
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
	struct armv7m_common_s *armv7m = &cortex_m3->armv7m;
314
	swjdp_common_t *swjdp = &armv7m->swjdp_info;
315

316
	LOG_DEBUG(" ");
317
318

	cortex_m3_clear_halt(target);
319
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
320
321
322
323
324

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

	/* Examine target state and mode */
325
	/* First load register acessible through core debug port*/
326
327
328
	int num_regs = armv7m->core_cache->num_regs;

	for (i = 0; i < num_regs; i++)
329
330
	{
		if (!armv7m->core_cache->reg_list[i].valid)
331
			armv7m->read_core_reg(target, i);
332
333
334
	}

	xPSR = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32);
335
336
337
338
339
340
341
342
343

#ifdef ARMV7_GDB_HACKS
	/* 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);
	armv7m_gdb_dummy_cpsr_reg.valid = armv7m->core_cache->reg_list[ARMV7M_xPSR].valid;
	armv7m_gdb_dummy_cpsr_reg.dirty = armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty;
#endif

344
	/* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
ntfreak's avatar
ntfreak committed
345
	if (xPSR & 0xf00)
346
	{
347
		armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = armv7m->core_cache->reg_list[ARMV7M_xPSR].valid;
ntfreak's avatar
ntfreak committed
348
		cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
349
350
351
	}

	/* Are we in an exception handler */
352
353
354
355
356
	if (xPSR & 0x1FF)
	{
		armv7m->core_mode = ARMV7M_MODE_HANDLER;
		armv7m->exception_number = (xPSR & 0x1FF);
	}
357
	else
358
	{
359
		armv7m->core_mode = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1);
360
361
		armv7m->exception_number = 0;
	}
zwelch's avatar
zwelch committed
362

363
364
365
366
367
	if (armv7m->exception_number)
	{
		cortex_m3_examine_exception_reason(target);
	}

duane's avatar
duane committed
368
	LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
369
		armv7m_mode_strings[armv7m->core_mode],
370
		*(uint32_t*)(armv7m->core_cache->reg_list[15].value),
371
		target_state_name(target));
372
373
374
375
376
377
378

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

	return ERROR_OK;
}

379
static int cortex_m3_poll(target_t *target)
380
381
{
	int retval;
382
	enum target_state prev_target_state = target->state;
383
384
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
	struct swjdp_common_s *swjdp = &cortex_m3->armv7m.swjdp_info;
385
386

	/* Read from Debug Halting Control and Status Register */
387
	retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
388
389
390
	if (retval != ERROR_OK)
	{
		target->state = TARGET_UNKNOWN;
391
		return retval;
392
	}
zwelch's avatar
zwelch committed
393

394
	if (cortex_m3->dcb_dhcsr & S_RESET_ST)
395
	{
396
		/* check if still in reset */
397
		mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
zwelch's avatar
zwelch committed
398

399
400
401
		if (cortex_m3->dcb_dhcsr & S_RESET_ST)
		{
			target->state = TARGET_RESET;
402
			return ERROR_OK;
403
		}
404
	}
zwelch's avatar
zwelch committed
405

406
	if (target->state == TARGET_RESET)
407
408
	{
		/* Cannot switch context while running so endreset is called with target->state == TARGET_RESET */
duane's avatar
duane committed
409
		LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32 "", cortex_m3->dcb_dhcsr);
410
411
412
413
		cortex_m3_endreset_event(target);
		target->state = TARGET_RUNNING;
		prev_target_state = TARGET_RUNNING;
	}
zwelch's avatar
zwelch committed
414

415
	if (cortex_m3->dcb_dhcsr & S_HALT)
416
417
418
419
420
421
	{
		target->state = TARGET_HALTED;

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

424
425
426
427
			target_call_event_callbacks(target, TARGET_EVENT_HALTED);
		}
		if (prev_target_state == TARGET_DEBUG_RUNNING)
		{
428
			LOG_DEBUG(" ");
429
			if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
430
				return retval;
431
432
433
434

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

436
437
438
	/* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
	 * How best to model low power modes?
	 */
439

440
441
442
443
444
445
446
447
448
	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
449

450
	return ERROR_OK;
451
452
}

453
static int cortex_m3_halt(target_t *target)
454
{
zwelch's avatar
zwelch committed
455
	LOG_DEBUG("target->state: %s",
456
		target_state_name(target));
zwelch's avatar
zwelch committed
457

458
459
	if (target->state == TARGET_HALTED)
	{
460
		LOG_DEBUG("target was already halted");
oharboe's avatar
   
oharboe committed
461
		return ERROR_OK;
462
	}
zwelch's avatar
zwelch committed
463

464
465
	if (target->state == TARGET_UNKNOWN)
	{
466
		LOG_WARNING("target was in unknown state when halt was requested");
467
	}
zwelch's avatar
zwelch committed
468
469

	if (target->state == TARGET_RESET)
470
	{
471
		if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst())
472
		{
473
			LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
474
475
476
477
478
479
480
481
			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
482
483

			return ERROR_OK;
484
485
486
		}
	}

487
	/* Write to Debug Halting Control and Status Register */
488
	cortex_m3_write_debug_halt_mask(target, C_HALT, 0);
489
490

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

492
493
494
	return ERROR_OK;
}

495
static int cortex_m3_soft_reset_halt(struct target_s *target)
496
{
497
498
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
	struct swjdp_common_s *swjdp = &cortex_m3->armv7m.swjdp_info;
499
	uint32_t dcb_dhcsr = 0;
ntfreak's avatar
ntfreak committed
500
	int retval, timeout = 0;
501
502

	/* Enter debug state on reset, cf. end_reset_event() */
503
	mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
zwelch's avatar
zwelch committed
504
505

	/* Request a reset */
506
	mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_VECTRESET);
507
508
509
510
511
	target->state = TARGET_RESET;

	/* registers are now invalid */
	armv7m_invalidate_core_regs(target);

512
	while (timeout < 100)
513
	{
514
		retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
515
516
		if (retval == ERROR_OK)
		{
517
			mem_ap_read_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
518
			if ((dcb_dhcsr & S_HALT) && (cortex_m3->nvic_dfsr & DFSR_VCATCH))
519
			{
duane's avatar
duane committed
520
				LOG_DEBUG("system reset-halted, dcb_dhcsr 0x%" PRIx32 ", nvic_dfsr 0x%" PRIx32 "", dcb_dhcsr, cortex_m3->nvic_dfsr);
521
522
523
524
				cortex_m3_poll(target);
				return ERROR_OK;
			}
			else
duane's avatar
duane committed
525
				LOG_DEBUG("waiting for system reset-halt, dcb_dhcsr 0x%" PRIx32 ", %i ms", dcb_dhcsr, timeout);
526
527
		}
		timeout++;
528
		alive_sleep(1);
529
	}
zwelch's avatar
zwelch committed
530

531
532
533
	return ERROR_OK;
}

534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
static void cortex_m3_enable_breakpoints(struct target_s *target)
{
	breakpoint_t *breakpoint = target->breakpoints;

	/* set any pending breakpoints */
	while (breakpoint)
	{
		if (breakpoint->set == 0)
			cortex_m3_set_breakpoint(target, breakpoint);
		breakpoint = breakpoint->next;
	}
}

static int cortex_m3_resume(struct target_s *target, int current,
		uint32_t address, int handle_breakpoints, int debug_execution)
549
{
550
	struct armv7m_common_s *armv7m = target_to_armv7m(target);
551
	breakpoint_t *breakpoint = NULL;
552
	uint32_t resume_pc;
zwelch's avatar
zwelch committed
553

554
555
	if (target->state != TARGET_HALTED)
	{
556
		LOG_WARNING("target not halted");
557
558
		return ERROR_TARGET_NOT_HALTED;
	}
zwelch's avatar
zwelch committed
559

560
561
562
563
564
565
	if (!debug_execution)
	{
		target_free_all_working_areas(target);
		cortex_m3_enable_breakpoints(target);
		cortex_m3_enable_watchpoints(target);
	}
zwelch's avatar
zwelch committed
566

567
568
569
	if (debug_execution)
	{
		/* Disable interrupts */
570
		/* We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS,
zwelch's avatar
zwelch committed
571
		 * This is probably the same issue as Cortex-M3 Errata	377493:
572
573
574
575
		 * C_MASKINTS in parallel with disabled interrupts can cause local faults to not be taken. */
		buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
		armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
		armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;
576

577
		/* Make sure we are in Thumb mode */
zwelch's avatar
zwelch committed
578
		buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32,
579
			buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1 << 24));
580
581
		armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
		armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
582
583
584
	}

	/* current = 1: continue on current pc, otherwise continue at <address> */
zwelch's avatar
zwelch committed
585
	if (!current)
586
587
588
589
590
	{
		buf_set_u32(armv7m->core_cache->reg_list[15].value, 0, 32, address);
		armv7m->core_cache->reg_list[15].dirty = 1;
		armv7m->core_cache->reg_list[15].valid = 1;
	}
zwelch's avatar
zwelch committed
591

592
593
	resume_pc = buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32);

594
	armv7m_restore_context(target);
zwelch's avatar
zwelch committed
595

596
597
598
599
600
601
	/* 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)))
		{
602
			LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %d)",
603
					  breakpoint->address,
David Brownell's avatar
David Brownell committed
604
					  breakpoint->unique_id);
605
606
607
			cortex_m3_unset_breakpoint(target, breakpoint);
			cortex_m3_single_step_core(target);
			cortex_m3_set_breakpoint(target, breakpoint);
608
609
		}
	}
zwelch's avatar
zwelch committed
610

611
	/* Restart core */
612
	cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
zwelch's avatar
zwelch committed
613

614
615
616
617
618
619
620
621
	target->debug_reason = DBG_REASON_NOTHALTED;

	/* registers are now invalid */
	armv7m_invalidate_core_regs(target);
	if (!debug_execution)
	{
		target->state = TARGET_RUNNING;
		target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
duane's avatar
duane committed
622
		LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
623
624
625
626
627
	}
	else
	{
		target->state = TARGET_DEBUG_RUNNING;
		target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
duane's avatar
duane committed
628
		LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
629
	}
zwelch's avatar
zwelch committed
630

631
632
633
	return ERROR_OK;
}

zwelch's avatar
zwelch committed
634
/* int irqstepcount = 0; */
635
636
static int cortex_m3_step(struct target_s *target, int current,
		uint32_t address, int handle_breakpoints)
637
{
638
639
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
	struct armv7m_common_s *armv7m = &cortex_m3->armv7m;
640
	swjdp_common_t *swjdp = &armv7m->swjdp_info;
641
642
643
644
	breakpoint_t *breakpoint = NULL;

	if (target->state != TARGET_HALTED)
	{
645
		LOG_WARNING("target not halted");
646
647
648
649
650
		return ERROR_TARGET_NOT_HALTED;
	}

	/* current = 1: continue on current pc, otherwise continue at <address> */
	if (!current)
651
652
		buf_set_u32(cortex_m3->armv7m.core_cache->reg_list[15].value,
				0, 32, address);
zwelch's avatar
zwelch committed
653

654
	/* the front-end may request us not to handle breakpoints */
655
656
657
658
	if (handle_breakpoints) {
		breakpoint = breakpoint_find(target, buf_get_u32(armv7m
				->core_cache->reg_list[15].value, 0, 32));
		if (breakpoint)
659
			cortex_m3_unset_breakpoint(target, breakpoint);
660
	}
zwelch's avatar
zwelch committed
661

662
	target->debug_reason = DBG_REASON_SINGLESTEP;
zwelch's avatar
zwelch committed
663

664
	armv7m_restore_context(target);
zwelch's avatar
zwelch committed
665

666
	target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
zwelch's avatar
zwelch committed
667

668
669
	/* set step and clear halt */
	cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT);
670
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
671

672
673
	/* registers are now invalid */
	armv7m_invalidate_core_regs(target);
zwelch's avatar
zwelch committed
674

675
676
677
	if (breakpoint)
		cortex_m3_set_breakpoint(target, breakpoint);

duane's avatar
duane committed
678
	LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32 " nvic_icsr = 0x%" PRIx32 "", cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
679
680
681
682

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

duane's avatar
duane committed
683
	LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32 " nvic_icsr = 0x%" PRIx32 "", cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
684
685
686
	return ERROR_OK;
}

687
static int cortex_m3_assert_reset(target_t *target)
688
{
689
690
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
	struct swjdp_common_s *swjdp = &cortex_m3->armv7m.swjdp_info;
oharboe's avatar
oharboe committed
691
	int assert_srst = 1;
zwelch's avatar
zwelch committed
692
693

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

696
	enum reset_types jtag_reset_config = jtag_get_reset_config();
697
698
699
700
701
702

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

706
	/* Enable debug requests */
707
	mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
708
	if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
709
		mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
zwelch's avatar
zwelch committed
710

711
	mem_ap_write_u32(swjdp, DCB_DCRDR, 0);
zwelch's avatar
zwelch committed
712

oharboe's avatar
   
oharboe committed
713
	if (!target->reset_halt)
714
715
716
	{
		/* Set/Clear C_MASKINTS in a separate operation */
		if (cortex_m3->dcb_dhcsr & C_MASKINTS)
717
			mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT);
718
719

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

722
723
		/* clear C_HALT in dhcsr reg */
		cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
zwelch's avatar
zwelch committed
724
725

		/* Enter debug state on reset, cf. end_reset_event() */
726
		mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR);
727
	}
728
729
730
	else
	{
		/* Enter debug state on reset, cf. end_reset_event() */
731
		mem_ap_write_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
732
	}
zwelch's avatar
zwelch committed
733

734
735
736
737
738
739
740
741
742
743
744
745
	/*
	 * When nRST is asserted on most Stellaris devices, it clears some of
	 * the debug state.  The ARMv7M and Cortex-M3 TRMs say that's wrong;
	 * and OpenOCD depends on those TRMs.  So we won't use SRST on those
	 * chips.  (Only power-on reset should affect debug state, beyond a
	 * few specified bits; not the chip's nRST input, wired to SRST.)
	 *
	 * REVISIT current errata specs don't seem to cover this issue.
	 * Do we have more details than this email?
	 *   https://lists.berlios.de/pipermail
	 *	/openocd-development/2008-August/003065.html
	 */
746
	if (strcmp(target->variant, "lm3s") == 0)
747
	{
748
		/* Check for silicon revisions with the issue. */
749
		uint32_t did0;
zwelch's avatar
zwelch committed
750

751
752
753
754
755
756
		if (target_read_u32(target, 0x400fe000, &did0) == ERROR_OK)
		{
			switch ((did0 >> 16) & 0xff)
			{
				case 0:
					/* all Sandstorm suffer issue */
oharboe's avatar
oharboe committed
757
					assert_srst = 0;
758
					break;
zwelch's avatar
zwelch committed
759

760
761
				case 1:
				case 3:
762
763
764
765
					/* Fury and DustDevil rev A have
					 * this nRST problem.  It should
					 * be fixed in rev B silicon.
					 */
766
					if (((did0 >> 8) & 0xff) == 0)
oharboe's avatar
oharboe committed
767
						assert_srst = 0;
768
					break;
769
770
771
				case 4:
					/* Tempest should be fine. */
					break;
772
773
			}
		}
774
	}
zwelch's avatar
zwelch committed
775

oharboe's avatar
oharboe committed
776
	if (assert_srst)
777
	{
778
		/* default to asserting srst */
779
780
781
782
783
784
785
786
		if (jtag_reset_config & RESET_SRST_PULLS_TRST)
		{
			jtag_add_reset(1, 1);
		}
		else
		{
			jtag_add_reset(0, 1);
		}
787
	}
788
789
	else
	{
790
791
792
793
794
795
796
797
		/* Use a standard Cortex-M3 software reset mechanism.
		 * SYSRESETREQ will reset SoC peripherals outside the
		 * core, like watchdog timers, if the SoC wires it up
		 * correctly.  Else VECRESET can reset just the core.
		 */
		mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR,
				AIRCR_VECTKEY | AIRCR_SYSRESETREQ);
		LOG_DEBUG("Using Cortex-M3 SYSRESETREQ");
798
799

		{
800
801
802
803
			/* I do not know why this is necessary, but it
			 * fixes strange effects (step/resume cause NMI
			 * after reset) on LM3S6918 -- Michael Schwingen
			 */
804
			uint32_t tmp;
805
			mem_ap_read_atomic_u32(swjdp, NVIC_AIRCR, &tmp);
806
		}
807
	}
zwelch's avatar
zwelch committed
808

809
810
	target->state = TARGET_RESET;
	jtag_add_sleep(50000);
zwelch's avatar
zwelch committed
811

812
813
	armv7m_invalidate_core_regs(target);

814
815
816
	if (target->reset_halt)
	{
		int retval;
zwelch's avatar
zwelch committed
817
		if ((retval = target_halt(target)) != ERROR_OK)
818
			return retval;
819
	}
zwelch's avatar
zwelch committed
820

821
822
823
	return ERROR_OK;
}

824
static int cortex_m3_deassert_reset(target_t *target)
zwelch's avatar
zwelch committed
825
826
{
	LOG_DEBUG("target->state: %s",
827
		target_state_name(target));
zwelch's avatar
zwelch committed
828

829
830
	/* deassert reset lines */
	jtag_add_reset(0, 0);
zwelch's avatar
zwelch committed
831

832
833
834
	return ERROR_OK;
}

835
836
static int
cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
837
{
838
	int retval;
zwelch's avatar
zwelch committed
839
	int fp_num = 0;
840
	uint32_t hilo;
841
842
	struct cortex_m3_common_s *cortex_m3 = target_to_cm3(target);
	cortex_m3_fp_comparator_t *comparator_list = cortex_m3->fp_comparator_list;
843
844
845

	if (breakpoint->set)
	{
846
		LOG_WARNING("breakpoint (BPID: %d) already set", breakpoint->unique_id);
847
848
		return ERROR_OK;
	}
zwelch's avatar
zwelch committed
849

850
851
	if (cortex_m3->auto_bp_type)
	{
ntfreak's avatar
ntfreak committed
852
		breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
853
854
855
856
	}

	if (breakpoint->type == BKPT_HARD)
	{
zwelch's avatar
zwelch committed
857
		while (comparator_list[fp_num].used && (fp_num < <