cortex_m3.c 46.1 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
25
26
27
28
29
30
31
32
 *   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.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "replacements.h"

#include "cortex_m3.h"
ntfreak's avatar
ntfreak committed
33
#include "armv7m.h"
34
35
36

#include "register.h"
#include "target.h"
37
#include "target_request.h"
38
39
40
41
42
43
44
45
46
#include "log.h"
#include "jtag.h"
#include "arm_jtag.h"

#include <stdlib.h>
#include <string.h>

/* cli handling */
int cortex_m3_register_commands(struct command_context_s *cmd_ctx);
ntfreak's avatar
ntfreak committed
47
int handle_cortex_m3_mask_interrupts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
48
49
50
51

/* forward declarations */
void cortex_m3_enable_breakpoints(struct target_s *target);
void cortex_m3_enable_watchpoints(struct target_s *target);
52
int cortex_m3_target_create(struct target_s *target, Jim_Interp *interp);
53
int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
oharboe's avatar
oharboe committed
54
int cortex_m3_quit(void);
55
56
int cortex_m3_load_core_reg_u32(target_t *target, enum armv7m_regtype type, u32 num, u32 *value);
int cortex_m3_store_core_reg_u32(target_t *target, enum armv7m_regtype type, u32 num, u32 value);
57
int cortex_m3_target_request_data(target_t *target, u32 size, u8 *buffer);
58
int cortex_m3_examine(struct target_s *target);
59

60
61
62
63
64
#ifdef ARMV7_GDB_HACKS
extern u8 armv7m_gdb_dummy_cpsr_value[];
extern reg_t armv7m_gdb_dummy_cpsr_reg;
#endif

65
66
67
68
69
70
71
target_type_t cortexm3_target =
{
	.name = "cortex_m3",

	.poll = cortex_m3_poll,
	.arch_state = armv7m_arch_state,

72
73
	.target_request_data = cortex_m3_target_request_data,
	
74
75
76
77
78
79
80
	.halt = cortex_m3_halt,
	.resume = cortex_m3_resume,
	.step = cortex_m3_step,

	.assert_reset = cortex_m3_assert_reset,
	.deassert_reset = cortex_m3_deassert_reset,
	.soft_reset_halt = cortex_m3_soft_reset_halt,
81
	
82
83
84
85
86
	.get_gdb_reg_list = armv7m_get_gdb_reg_list,

	.read_memory = cortex_m3_read_memory,
	.write_memory = cortex_m3_write_memory,
	.bulk_write_memory = cortex_m3_bulk_write_memory,
ntfreak's avatar
ntfreak committed
87
	.checksum_memory = armv7m_checksum_memory,
88
	.blank_check_memory = armv7m_blank_check_memory,
ntfreak's avatar
ntfreak committed
89
	
90
91
92
93
94
95
96
97
	.run_algorithm = armv7m_run_algorithm,
	
	.add_breakpoint = cortex_m3_add_breakpoint,
	.remove_breakpoint = cortex_m3_remove_breakpoint,
	.add_watchpoint = cortex_m3_add_watchpoint,
	.remove_watchpoint = cortex_m3_remove_watchpoint,

	.register_commands = cortex_m3_register_commands,
98
	.target_create = cortex_m3_target_create,
99
	.init_target = cortex_m3_init_target,
100
	.examine = cortex_m3_examine,
101
102
103
	.quit = cortex_m3_quit
};

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
int cortex_m3_write_debug_halt_mask(target_t *target, u32 mask_on, u32 mask_off)
{
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
	
	/* 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;
	
	return ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, cortex_m3->dcb_dhcsr);
}

119
120
121
122
123
124
int cortex_m3_clear_halt(target_t *target)
{
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
125
	
126
127
128
	/* clear step if any */
	cortex_m3_write_debug_halt_mask(target, C_HALT, C_STEP);
	
129
130
131
132
133
134
135
	/* Read Debug Fault Status Register */
	ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
	/* Write Debug Fault Status Register to enable processing to resume ?? Try with and without this !! */
	ahbap_write_system_atomic_u32(swjdp, NVIC_DFSR, cortex_m3->nvic_dfsr);
	LOG_DEBUG(" NVIC_DFSR 0x%x", cortex_m3->nvic_dfsr);

	return ERROR_OK;
136
137
138
139
140
141
142
143
}

int cortex_m3_single_step_core(target_t *target)
{
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
144
145
146
147
148
149
	u32 dhcsr_save;
	
	/* backup dhcsr reg */
	dhcsr_save = cortex_m3->dcb_dhcsr;
	
	/* mask interrupts if not done already */
ntfreak's avatar
ntfreak committed
150
	if (!(cortex_m3->dcb_dhcsr & C_MASKINTS))
151
152
		ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN);
	ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN);
153
	LOG_DEBUG(" ");
154
155
156
	
	/* restore dhcsr reg */
	cortex_m3->dcb_dhcsr = dhcsr_save;	
157
158
159
160
161
162
163
164
165
166
167
168
169
	cortex_m3_clear_halt(target);
	
	return ERROR_OK;
}

int cortex_m3_exec_opcode(target_t *target,u32 opcode, int len /* MODE, r0_invalue, &r0_outvalue */ )
{
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
	u32 savedram;
	int retvalue;
170
171
172
173
174
	
	ahbap_read_system_u32(swjdp, 0x20000000, &savedram);
	ahbap_write_system_u32(swjdp, 0x20000000, opcode);
	ahbap_write_coreregister_u32(swjdp, 0x20000000, 15);
	cortex_m3_single_step_core(target);
175
	armv7m->core_cache->reg_list[15].dirty = armv7m->core_cache->reg_list[15].valid;
176
	retvalue = ahbap_write_system_atomic_u32(swjdp, 0x20000000, savedram);
177
178
179
180
	
	return retvalue;
}

181
#if 0
182
183
184
185
186
187
188
189
190
191
192
/* Enable interrupts */
int cortex_m3_cpsie(target_t *target, u32 IF)
{
	return cortex_m3_exec_opcode(target, ARMV7M_T_CPSIE(IF), 2);
}

/* Disable interrupts */
int cortex_m3_cpsid(target_t *target, u32 IF)
{
	return cortex_m3_exec_opcode(target, ARMV7M_T_CPSID(IF), 2);
}
193
#endif
194
195
196
197

int cortex_m3_endreset_event(target_t *target)
{
	int i;
198
	u32 dcb_demcr;
199
200
201
202
203
204
	
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
	cortex_m3_fp_comparator_t *fp_list = cortex_m3->fp_comparator_list; 
ntfreak's avatar
ntfreak committed
205
	cortex_m3_dwt_comparator_t *dwt_list = cortex_m3->dwt_comparator_list;
206

207
	ahbap_read_system_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr);
208
	LOG_DEBUG("DCB_DEMCR = 0x%8.8x",dcb_demcr);
209
	
210
211
	/* this regsiter is used for emulated dcc channel */
	ahbap_write_system_u32(swjdp, DCB_DCRDR, 0);
212
	
213
214
	/* Enable debug requests */
	ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
215
	if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
216
217
218
219
220
		ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
	
	/* clear any interrupt masking */
	cortex_m3_write_debug_halt_mask(target, 0, C_MASKINTS);
	
221
	/* Enable trace and dwt */
222
	ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR);
223
	/* Monitor bus faults */
224
	ahbap_write_system_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA);
225
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
235
236
	{
		target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
	}
	
	/* Restore DWT registers */
237
	for (i = 0; i < cortex_m3->dwt_num_comp; i++)
238
239
	{
		target_write_u32(target, dwt_list[i].dwt_comparator_address, dwt_list[i].comp);
ntfreak's avatar
ntfreak committed
240
241
		target_write_u32(target, dwt_list[i].dwt_comparator_address | 0x4, dwt_list[i].mask);
		target_write_u32(target, dwt_list[i].dwt_comparator_address | 0x8, dwt_list[i].function);
242
	}
243
	swjdp_transaction_endcheck(swjdp);
244
245
	
	armv7m_invalidate_core_regs(target);
246
247
248
249
	
	/* make sure we have latest dhcsr flags */
	ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
	
250
251
252
253
254
255
256
257
258
	return ERROR_OK;
}

int cortex_m3_examine_debug_reason(target_t *target)
{
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;

259
	/* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason */
260
261
262
	/* only check the debug reason if we don't know it already */
	
	if ((target->debug_reason != DBG_REASON_DBGRQ)
ntfreak's avatar
ntfreak committed
263
		&& (target->debug_reason != DBG_REASON_SINGLESTEP))
264
	{
265
		/*  INCOMPLETE */
266

267
		if (cortex_m3->nvic_dfsr & DFSR_BKPT)
268
269
		{
			target->debug_reason = DBG_REASON_BREAKPOINT;
270
			if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
271
272
				target->debug_reason = DBG_REASON_WPTANDBKPT;
		}
273
		else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
274
275
276
277
278
279
280
281
			target->debug_reason = DBG_REASON_WATCHPOINT;
	}

	return ERROR_OK;
}

int cortex_m3_examine_exception_reason(target_t *target)
{
ntfreak's avatar
ntfreak committed
282
	u32 shcsr, except_sr, cfsr = -1, except_ar = -1;
283
284
285
286
287
288
289
290
291
292
293
294
295

	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;

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

int cortex_m3_debug_entry(target_t *target)
{
333
	int i;
334
335
336
337
338
339
340
341
	u32 xPSR;
	int retval;

	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;

342
	LOG_DEBUG(" ");
343
344
345
346
347
348
349
350
351
352
	if (armv7m->pre_debug_entry)
		armv7m->pre_debug_entry(target);

	cortex_m3_clear_halt(target);
	ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);

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

	/* Examine target state and mode */
353
	/* First load register acessible through core debug port*/
354
355
356
	for (i = 0; i < ARMV7M_PRIMASK; i++)
	{
		if (!armv7m->core_cache->reg_list[i].valid)
357
			armv7m->read_core_reg(target, i);
358
359
360
	}

	xPSR = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32);
361
362
363
364
365
366
367
368
369

#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

370
	/* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
ntfreak's avatar
ntfreak committed
371
	if (xPSR & 0xf00)
372
	{
373
		armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = armv7m->core_cache->reg_list[ARMV7M_xPSR].valid;
ntfreak's avatar
ntfreak committed
374
		cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
375
376
	}

377
	/* Now we can load SP core registers */
378
379
380
	for (i = ARMV7M_PRIMASK; i < ARMV7NUMCOREREGS; i++)
	{
		if (!armv7m->core_cache->reg_list[i].valid)
381
			armv7m->read_core_reg(target, i);
382
383
384
	}

	/* Are we in an exception handler */
385
386
387
388
389
390
391
392
393
394
395
	if (xPSR & 0x1FF)
	{
		armv7m->core_mode = ARMV7M_MODE_HANDLER;
		armv7m->exception_number = (xPSR & 0x1FF);
	}
	else
	{
		armv7m->core_mode = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1);
		armv7m->exception_number = 0;
	}
	
396
397
398
399
400
	if (armv7m->exception_number)
	{
		cortex_m3_examine_exception_reason(target);
	}

401
	LOG_DEBUG("entered debug state in core mode: %s at PC 0x%x, target->state: %s", 
402
403
404
		armv7m_mode_strings[armv7m->core_mode],
		*(u32*)(armv7m->core_cache->reg_list[15].value), 
		Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
405
406
407
408
409
410
411

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

	return ERROR_OK;
}

412
int cortex_m3_poll(target_t *target)
413
414
{
	int retval;
415
	enum target_state prev_target_state = target->state;
416
417
418
419
420
421
422
423
424
425
426
	
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;

	/* Read from Debug Halting Control and Status Register */
	retval = ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
	if (retval != ERROR_OK)
	{
		target->state = TARGET_UNKNOWN;
427
		return retval;
428
429
	}
	
430
	if (cortex_m3->dcb_dhcsr & S_RESET_ST)
431
	{
432
433
434
435
436
437
		/* check if still in reset */
		ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
		
		if (cortex_m3->dcb_dhcsr & S_RESET_ST)
		{
			target->state = TARGET_RESET;
438
			return ERROR_OK;
439
		}
440
	}
441
442
	
	if (target->state == TARGET_RESET)
443
444
	{
		/* Cannot switch context while running so endreset is called with target->state == TARGET_RESET */
445
		LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%x", cortex_m3->dcb_dhcsr);
446
447
448
449
450
		cortex_m3_endreset_event(target);
		target->state = TARGET_RUNNING;
		prev_target_state = TARGET_RUNNING;
	}
	
451
	if (cortex_m3->dcb_dhcsr & S_HALT)
452
453
454
455
456
457
	{
		target->state = TARGET_HALTED;

		if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET))
		{
			if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
458
				return retval;
459
460
461
462
463
			
			target_call_event_callbacks(target, TARGET_EVENT_HALTED);
		}
		if (prev_target_state == TARGET_DEBUG_RUNNING)
		{
464
			LOG_DEBUG(" ");
465
			if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
466
				return retval;
467
468
469
470
471
472

			target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
		}
	}
		
	/*
473
	if (cortex_m3->dcb_dhcsr & S_SLEEP)
474
475
476
		target->state = TARGET_SLEEP;
	*/

477
#if 0
478
	/* Read Debug Fault Status Register, added to figure out the lockup when running flashtest.script  */
479
	ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
480
	LOG_DEBUG("dcb_dhcsr 0x%x, nvic_dfsr 0x%x, target->state: %s", cortex_m3->dcb_dhcsr, cortex_m3->nvic_dfsr, Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name );
481
482
#endif
	
483
	return ERROR_OK;
484
485
486
487
}

int cortex_m3_halt(target_t *target)
{
488
	LOG_DEBUG("target->state: %s", 
489
		Jim_Nvp_value2name_simple(nvp_target_state, target->state )->name);
490
	
491
492
	if (target->state == TARGET_HALTED)
	{
493
		LOG_DEBUG("target was already halted");
oharboe's avatar
   
oharboe committed
494
		return ERROR_OK;
495
496
497
498
	}
	
	if (target->state == TARGET_UNKNOWN)
	{
499
		LOG_WARNING("target was in unknown state when halt was requested");
500
501
502
503
504
505
	}
	
	if (target->state == TARGET_RESET) 
	{
		if ((jtag_reset_config & RESET_SRST_PULLS_TRST) && jtag_srst)
		{
506
			LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
507
508
509
510
511
512
513
514
515
516
517
518
519
			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;
			
			return ERROR_OK; 
		}
	}

520
	/* Write to Debug Halting Control and Status Register */
521
	cortex_m3_write_debug_halt_mask(target, C_HALT, 0);
522
523
524
525
526
527
528
529
530
531
532
533

	target->debug_reason = DBG_REASON_DBGRQ;
	
	return ERROR_OK;
}

int cortex_m3_soft_reset_halt(struct target_s *target)
{
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
ntfreak's avatar
ntfreak committed
534
535
	u32 dcb_dhcsr = 0;
	int retval, timeout = 0;
536
537

	/* Enter debug state on reset, cf. end_reset_event() */
538
	ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
539
540
	
	/* Request a reset */ 
541
	ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_VECTRESET);
542
543
544
545
546
	target->state = TARGET_RESET;

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

547
	while (timeout < 100)
548
549
550
551
	{
		retval = ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
		if (retval == ERROR_OK)
		{
552
			ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
553
			if ((dcb_dhcsr & S_HALT) && (cortex_m3->nvic_dfsr & DFSR_VCATCH))
554
			{
555
				LOG_DEBUG("system reset-halted, dcb_dhcsr 0x%x, nvic_dfsr 0x%x", dcb_dhcsr, cortex_m3->nvic_dfsr);
556
557
558
559
				cortex_m3_poll(target);
				return ERROR_OK;
			}
			else
560
				LOG_DEBUG("waiting for system reset-halt, dcb_dhcsr 0x%x, %i ms", dcb_dhcsr, timeout);
561
562
		}
		timeout++;
563
		alive_sleep(1);
564
565
566
567
568
569
570
571
572
573
	}
		
	return ERROR_OK;
}

int cortex_m3_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
{
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	breakpoint_t *breakpoint = NULL;
574
	u32 resume_pc;
575
576
577
	
	if (target->state != TARGET_HALTED)
	{
578
		LOG_WARNING("target not halted");
579
580
581
582
583
584
585
586
587
588
589
590
591
		return ERROR_TARGET_NOT_HALTED;
	}
	
	if (!debug_execution)
	{
		target_free_all_working_areas(target);
		cortex_m3_enable_breakpoints(target);
		cortex_m3_enable_watchpoints(target);
	}
	
	if (debug_execution)
	{
		/* Disable interrupts */
592
		/* We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS,
593
		 * This is probably the same issue as Cortex-M3 Errata	377493: 
594
		 * C_MASKINTS in parallel with disabled interrupts can cause local faults to not be taken. */
595
		buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
596
597
598
		armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
		armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;

599
600
		/* Make sure we are in Thumb mode */
		buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32, 
ntfreak's avatar
ntfreak committed
601
			buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1<<24));
602
603
		armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
		armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
604
605
606
607
608
609
610
611
612
613
614
615
	}

	/* current = 1: continue on current pc, otherwise continue at <address> */
	if (!current) 
	{
		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;
	}
	
	resume_pc = buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32);

616
	armv7m_restore_context(target);
617
618
619
620
621
622
623
	
	/* 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)))
		{
624
625
626
627
			LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
			cortex_m3_unset_breakpoint(target, breakpoint);
			cortex_m3_single_step_core(target);
			cortex_m3_set_breakpoint(target, breakpoint);
628
629
		}
	}
630
	
631
	/* Restart core */
632
633
	cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
	
634
635
636
637
638
639
640
641
	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);
642
		LOG_DEBUG("target resumed at 0x%x", resume_pc);
643
644
645
646
647
	}
	else
	{
		target->state = TARGET_DEBUG_RUNNING;
		target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
648
		LOG_DEBUG("target debug resumed at 0x%x", resume_pc);
649
650
651
652
653
	}
	
	return ERROR_OK;
}

654
/* int irqstepcount=0; */
655
656
657
658
659
660
661
662
663
664
int cortex_m3_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
{
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
	breakpoint_t *breakpoint = NULL;

	if (target->state != TARGET_HALTED)
	{
665
		LOG_WARNING("target not halted");
666
667
668
669
670
671
672
673
674
675
676
677
678
679
		return ERROR_TARGET_NOT_HALTED;
	}

	/* current = 1: continue on current pc, otherwise continue at <address> */
	if (!current)
		buf_set_u32(armv7m->core_cache->reg_list[15].value, 0, 32, address);
	
	/* the front-end may request us not to handle breakpoints */
	if (handle_breakpoints)
		if ((breakpoint = breakpoint_find(target, buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32))))
			cortex_m3_unset_breakpoint(target, breakpoint);
	
	target->debug_reason = DBG_REASON_SINGLESTEP;
	
680
	armv7m_restore_context(target);
681
682
	
	target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
683
	
684
685
	/* set step and clear halt */
	cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT);
686
687
	ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);

688
689
	/* registers are now invalid */
	armv7m_invalidate_core_regs(target);
690
691
692
693
	
	if (breakpoint)
		cortex_m3_set_breakpoint(target, breakpoint);

694
	LOG_DEBUG("target stepped dcb_dhcsr = 0x%x nvic_icsr = 0x%x", cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
695
696
697
698

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

699
	LOG_DEBUG("target stepped dcb_dhcsr = 0x%x nvic_icsr = 0x%x", cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
700
701
702
703
704
	return ERROR_OK;
}

int cortex_m3_assert_reset(target_t *target)
{
705
706
707
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
oharboe's avatar
oharboe committed
708
	int assert_srst = 1;
709
	
710
	LOG_DEBUG("target->state: %s", 
711
		Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name );
712
	
713
714
715
716
717
	if (!(jtag_reset_config & RESET_HAS_SRST))
	{
		LOG_ERROR("Can't assert SRST");
		return ERROR_FAIL;
	}
oharboe's avatar
   
oharboe committed
718
	
719
720
721
	/* Enable debug requests */
	ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
	if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
722
		ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
723
		
724
725
	ahbap_write_system_u32(swjdp, DCB_DCRDR, 0 );
	
oharboe's avatar
   
oharboe committed
726
	if (!target->reset_halt)
727
728
729
	{
		/* Set/Clear C_MASKINTS in a separate operation */
		if (cortex_m3->dcb_dhcsr & C_MASKINTS)
730
			ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT);
731
732

		/* clear any debug flags before resuming */
733
		cortex_m3_clear_halt(target);
734
735
736
		
		/* clear C_HALT in dhcsr reg */
		cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
737
738
739
740
							
		/* Enter debug state on reset, cf. end_reset_event() */	
		ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR);
	}
741
742
743
	else
	{
		/* Enter debug state on reset, cf. end_reset_event() */
744
		ahbap_write_system_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
745
	}
746
	
747
748
749
750
	/* following hack is to handle luminary reset
	 * when srst is asserted the luminary device seesm to also clear the debug registers
	 * which does not match the armv7 debug TRM */
		
751
	if (strcmp(target->variant, "lm3s") == 0)
752
	{
753
754
755
756
757
758
759
760
761
762
763
		/* get revision of lm3s target, only early silicon has this issue
		 * Fury Rev B, DustDevil Rev B, Tempest all ok */
		
		u32 did0;
		
		if (target_read_u32(target, 0x400fe000, &did0) == ERROR_OK)
		{
			switch ((did0 >> 16) & 0xff)
			{
				case 0:
					/* all Sandstorm suffer issue */
oharboe's avatar
oharboe committed
764
					assert_srst = 0;
765
766
767
768
769
770
					break;
				
				case 1:
				case 3:
					/* only Fury/DustDevil rev A suffer reset problems */
					if (((did0 >> 8) & 0xff) == 0)
oharboe's avatar
oharboe committed
771
						assert_srst = 0;
772
773
774
					break;
			}
		}
775
	}
776
	
oharboe's avatar
oharboe committed
777
	if (assert_srst)
778
	{
779
		/* default to asserting srst */
780
781
782
783
784
785
786
787
		if (jtag_reset_config & RESET_SRST_PULLS_TRST)
		{
			jtag_add_reset(1, 1);
		}
		else
		{
			jtag_add_reset(0, 1);
		}
788
	}
789
790
791
	else
	{
		/* this causes the luminary device to reset using the watchdog */
792
		ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ);
793
		LOG_DEBUG("Using Luminary Reset: SYSRESETREQ");
794
795
796

		{
			/* I do not know why this is necessary, but it fixes strange effects
797
			 * (step/resume cause a NMI after reset) on LM3S6918 -- Michael Schwingen */
798
			u32 tmp;
799
			ahbap_read_system_atomic_u32(swjdp, NVIC_AIRCR, &tmp);
800
		}
801
	}
802
803
804
805
806
807
	
	target->state = TARGET_RESET;
	jtag_add_sleep(50000);
	
	armv7m_invalidate_core_regs(target);

808
809
810
	if (target->reset_halt)
	{
		int retval;
811
812
		if ((retval = target_halt(target))!=ERROR_OK)
			return retval;
813
	}
814
	
815
816
817
818
	return ERROR_OK;
}

int cortex_m3_deassert_reset(target_t *target)
819
{		
820
	LOG_DEBUG("target->state: %s", 
821
		Jim_Nvp_value2name_simple(nvp_target_state, target->state )->name);
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
	
	/* deassert reset lines */
	jtag_add_reset(0, 0);
		
	return ERROR_OK;
}

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

int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
844
	int retval;
845
846
847
848
849
850
851
852
853
854
855
	int fp_num=0;
	u32 hilo;
	
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	
	cortex_m3_fp_comparator_t * comparator_list = cortex_m3->fp_comparator_list;

	if (breakpoint->set)
	{
856
		LOG_WARNING("breakpoint already set");
857
858
		return ERROR_OK;
	}
859
	
860
861
	if (cortex_m3->auto_bp_type)
	{
ntfreak's avatar
ntfreak committed
862
		breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
863
864
865
866
	}

	if (breakpoint->type == BKPT_HARD)
	{
ntfreak's avatar
ntfreak committed
867
		while(comparator_list[fp_num].used && (fp_num < cortex_m3->fp_num_code))
868
			fp_num++;
ntfreak's avatar
ntfreak committed
869
		if (fp_num >= cortex_m3->fp_num_code)
870
		{
871
872
			LOG_DEBUG("ERROR Can not find free FP Comparator");
			LOG_WARNING("ERROR Can not find free FP Comparator");
873
874
			exit(-1);
		}
ntfreak's avatar
ntfreak committed
875
876
		breakpoint->set = fp_num + 1;
		hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW;
877
		comparator_list[fp_num].used = 1;
ntfreak's avatar
ntfreak committed
878
		comparator_list[fp_num].fpcr_value = (breakpoint->address & 0x1FFFFFFC) | hilo | 1;
879
		target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value);
880
		LOG_DEBUG("fpc_num %i fpcr_value 0x%x", fp_num, comparator_list[fp_num].fpcr_value);
881
882
883
884
885
		if (!cortex_m3->fpb_enabled)
		{
			LOG_DEBUG("FPB wasn't enabled, do it now");
			target_write_u32(target, FP_CTRL, 3);
		}
886
887
888
889
890
	}
	else if (breakpoint->type == BKPT_SOFT)
	{
		u8 code[4];
		buf_set_u32(code, 0, 32, ARMV7M_T_BKPT(0x11));
891
892
893
894
895
896
897
898
		if((retval = target->type->read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr)) != ERROR_OK)
		{
			return retval;
		}
		if((retval = target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, code)) != ERROR_OK)
		{
			return retval;
		}
899
900
901
902
903
904
905
906
		breakpoint->set = 0x11; /* Any nice value but 0 */
	}

	return ERROR_OK;
}

int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
907
	int retval;
908
909
910
911
912
913
914
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	cortex_m3_fp_comparator_t * comparator_list = cortex_m3->fp_comparator_list;

	if (!breakpoint->set)
	{
915
		LOG_WARNING("breakpoint not set");
916
917
918
919
920
		return ERROR_OK;
	}
	
	if (breakpoint->type == BKPT_HARD)
	{
ntfreak's avatar
ntfreak committed
921
922
		int fp_num = breakpoint->set - 1;
		if ((fp_num < 0) || (fp_num >= cortex_m3->fp_num_code))
923
		{
924
			LOG_DEBUG("Invalid FP Comparator number in breakpoint");
925
926
927
928
929
930
931
932
933
934
935
			return ERROR_OK;
		}
		comparator_list[fp_num].used = 0;
		comparator_list[fp_num].fpcr_value = 0;
		target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value);
	}
	else
	{
		/* restore original instruction (kept in target endianness) */
		if (breakpoint->length == 4)
		{
936
937
938
939
			if((retval = target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
			{
				return retval;
			}
940
941
942
		}
		else
		{
943
944
945
946
			if((retval = target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
			{
				return retval;
			}
947
948
949
950
951
952
953
954
955
956
957
958
		}
	}
	breakpoint->set = 0;

	return ERROR_OK;
}

int cortex_m3_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
959

960
961
	if (cortex_m3->auto_bp_type)
	{
ntfreak's avatar
ntfreak committed
962
		breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
963
964
965
966
967
968
969
970
#ifdef ARMV7_GDB_HACKS
		if (breakpoint->length != 2) {
			/* XXX Hack: Replace all breakpoints with length != 2 with
			 * a hardware breakpoint. */ 
			breakpoint->type = BKPT_HARD;
			breakpoint->length = 2;
		}
#endif
971
972
	}

ntfreak's avatar
ntfreak committed
973
	if ((breakpoint->type == BKPT_HARD) && (breakpoint->address >= 0x20000000))
974
	{
975
		LOG_INFO("flash patch comparator requested outside code memory region");
976
977
978
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}

ntfreak's avatar
ntfreak committed
979
	if ((breakpoint->type == BKPT_SOFT) && (breakpoint->address < 0x20000000))
980
	{
981
		LOG_INFO("soft breakpoint requested in code (flash) memory region");
982
983
984
985
986
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}

	if ((breakpoint->type == BKPT_HARD) && (cortex_m3->fp_code_available < 1))
	{
987
		LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
988
989
990
991
992
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}

	if ((breakpoint->length != 2))
	{
993
		LOG_INFO("only breakpoints of two bytes length supported");
994
995
996
997
998
999
1000
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
	
	if (breakpoint->type == BKPT_HARD)
		cortex_m3->fp_code_available--;
	cortex_m3_set_breakpoint(target, breakpoint);