cortex_m3.c 44.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *   Copyright (C) 2006 by Magnus Lundin                                   *
 *   lundin@mlu.mine.nu                                                    *
 *                                                                         *
 *   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
29
#include "armv7m.h"
30
31
32

#include "register.h"
#include "target.h"
33
#include "target_request.h"
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#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);

/* forward declarations */
void cortex_m3_unset_all_breakpoints_and_watchpoints(struct target_s *target);
void cortex_m3_enable_breakpoints(struct target_s *target);
void cortex_m3_enable_watchpoints(struct target_s *target);
void cortex_m3_disable_bkpts_and_wpts(struct target_s *target);
int cortex_m3_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
int cortex_m3_quit();
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);
54
55
int cortex_m3_target_request_data(target_t *target, u32 size, u8 *buffer);

56
57
58
59
60
61
62
target_type_t cortexm3_target =
{
	.name = "cortex_m3",

	.poll = cortex_m3_poll,
	.arch_state = armv7m_arch_state,

63
64
	.target_request_data = cortex_m3_target_request_data,
	
65
66
67
68
69
70
71
	.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,
72
73
	.prepare_reset_halt = cortex_m3_prepare_reset_halt,
	
74
75
76
77
78
	.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
79
80
	.checksum_memory = armv7m_checksum_memory,
	
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
	.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,
	.target_command = cortex_m3_target_command,
	.init_target = cortex_m3_init_target,
	.quit = cortex_m3_quit
};

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;
    
    /* 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);
105
    DEBUG(" NVIC_DFSR 0x%x", cortex_m3->nvic_dfsr);
106
107
108
109
110
111
112
113
114
115
116

    return ERROR_OK;
}

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;

ntfreak's avatar
ntfreak committed
117
	if (!(cortex_m3->dcb_dhcsr & C_MASKINTS))
118
119
120
		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 );
	cortex_m3->dcb_dhcsr |= C_MASKINTS;
ntfreak's avatar
ntfreak committed
121
	DEBUG(" ");
122
123
124
125
126
127
128
129
130
131
132
133
134
	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;
135
136
137
138
139
	
	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);
140
	armv7m->core_cache->reg_list[15].dirty = armv7m->core_cache->reg_list[15].valid;
141
	retvalue = ahbap_write_system_atomic_u32(swjdp, 0x20000000, savedram);		
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
	
	return retvalue;
}

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

int cortex_m3_endreset_event(target_t *target)
{
	int i;
161
	u32 dcb_demcr;
162
163
164
165
166
167
	
	/* 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
168
	cortex_m3_dwt_comparator_t *dwt_list = cortex_m3->dwt_comparator_list;
169

170
171
172
	ahbap_read_system_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr);
	DEBUG("DCB_DEMCR = 0x%8.8x",dcb_demcr);
	
173
174
	ahbap_write_system_u32(swjdp, DCB_DCRDR, 0 );
	
175
176
	/* Enable debug requests */
	ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
177
	if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
178
179
		ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN );
	/* Enable trace and dwt */
180
	ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR );
181
182
183
184
185
186
187
	/* Monitor bus faults */
	ahbap_write_system_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA );

	/* Enable FPB */
	target_write_u32(target, FP_CTRL, 3);

	/* Restore FPB registers */
ntfreak's avatar
ntfreak committed
188
	for ( i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++)
189
190
191
192
193
	{
		target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
	}
	
	/* Restore DWT registers */
ntfreak's avatar
ntfreak committed
194
	for ( i = 0; i < cortex_m3->dwt_num_comp; i++)
195
196
	{
		target_write_u32(target, dwt_list[i].dwt_comparator_address, dwt_list[i].comp);
ntfreak's avatar
ntfreak committed
197
198
		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);
199
	}
200
	swjdp_transaction_endcheck(swjdp);
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
	
	/* Make sure working_areas are all free */
	target_free_all_working_areas(target);
	
	/* We are in process context */
	armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
	armv7m_invalidate_core_regs(target);
	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;

217
	/* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason */
218
219
220
	/* only check the debug reason if we don't know it already */
	
	if ((target->debug_reason != DBG_REASON_DBGRQ)
ntfreak's avatar
ntfreak committed
221
		&& (target->debug_reason != DBG_REASON_SINGLESTEP))
222
	{
223
		/*  INCOMPLETE */
224

225
		if (cortex_m3->nvic_dfsr & DFSR_BKPT)
226
227
		{
			target->debug_reason = DBG_REASON_BREAKPOINT;
228
			if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
229
230
				target->debug_reason = DBG_REASON_WPTANDBKPT;
		}
231
		else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
232
233
234
235
236
237
238
239
			target->debug_reason = DBG_REASON_WATCHPOINT;
	}

	return ERROR_OK;
}

int cortex_m3_examine_exception_reason(target_t *target)
{
ntfreak's avatar
ntfreak committed
240
	u32 shcsr, except_sr, cfsr = -1, except_ar = -1;
241
242
243
244
245
246
247
248
249
250
251
252
253

	/* 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
254
			if (except_sr & 0x40000000)
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
			{
				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);
ntfreak's avatar
ntfreak committed
284
285
    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);
286
287
288
289
290
	return ERROR_OK;
}

int cortex_m3_debug_entry(target_t *target)
{
291
	int i;
292
293
294
295
296
297
298
299
	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;

ntfreak's avatar
ntfreak committed
300
	DEBUG(" ");
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
	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 */
	/* First load register acessible through core debug port*/	
	for (i = 0; i < ARMV7M_PRIMASK; i++)
	{
		if (!armv7m->core_cache->reg_list[i].valid)
			armv7m->read_core_reg(target, i);		
	}

	xPSR = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32);
	
	/* For IT instructions xPSR must be reloaded on resume and clear on debug exec*/
ntfreak's avatar
ntfreak committed
321
	if (xPSR & 0xf00)
322
	{
323
		armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = armv7m->core_cache->reg_list[ARMV7M_xPSR].valid;
ntfreak's avatar
ntfreak committed
324
		cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
325
326
327
328
329
330
331
332
333
334
335
	}


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

	/* Are we in an exception handler */
ntfreak's avatar
ntfreak committed
336
337
    armv7m->core_mode = (xPSR & 0x1FF) ? ARMV7M_MODE_HANDLER : ARMV7M_MODE_THREAD;
    armv7m->exception_number = xPSR & 0x1FF;
338
339
340
341
342
	if (armv7m->exception_number)
	{
		cortex_m3_examine_exception_reason(target);
	}

ntfreak's avatar
ntfreak committed
343
	DEBUG("entered debug state at PC 0x%x, target->state: %s ", *(u32*)(armv7m->core_cache->reg_list[15].value), target_state_strings[target->state]);
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

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

	return ERROR_OK;
}

enum target_state cortex_m3_poll(target_t *target)
{
	int retval;
	u32 prev_target_state = target->state;
	
	/* 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;
		return TARGET_UNKNOWN;
	}
	
369
	if (cortex_m3->dcb_dhcsr & S_RESET_ST)
370
	{
371
372
373
374
375
376
377
378
		/* 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;
			return target->state;
		}
379
	}
380
381
	
	if (target->state == TARGET_RESET)
382
383
	{
		/* Cannot switch context while running so endreset is called with target->state == TARGET_RESET */
384
		DEBUG("Exit from reset with dcb_dhcsr 0x%x", cortex_m3->dcb_dhcsr);
385
386
387
388
389
		cortex_m3_endreset_event(target);
		target->state = TARGET_RUNNING;
		prev_target_state = TARGET_RUNNING;
	}
	
390
	if (cortex_m3->dcb_dhcsr & S_HALT)
391
392
393
394
395
396
	{
		target->state = TARGET_HALTED;

		if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET))
		{
			if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
397
				return TARGET_UNKNOWN;
398
399
400
401
402
			
			target_call_event_callbacks(target, TARGET_EVENT_HALTED);
		}
		if (prev_target_state == TARGET_DEBUG_RUNNING)
		{
ntfreak's avatar
ntfreak committed
403
			DEBUG(" ");
404
			if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
405
				return TARGET_UNKNOWN;
406
407
408
409
410
411

			target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
		}
	}
		
	/*
412
	if (cortex_m3->dcb_dhcsr & S_SLEEP)
413
414
415
416
417
		target->state = TARGET_SLEEP;
	*/

    /* Read Debug Fault Status Register, added to figure out the lockup when running flashtest.script  */
    ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
418
	DEBUG("dcb_dhcsr 0x%x, nvic_dfsr 0x%x, target->state: %s", cortex_m3->dcb_dhcsr, cortex_m3->nvic_dfsr, target_state_strings[target->state]);	
419
420
421
422
423
424
425
426
427
428
429
430
	return target->state;
}

int cortex_m3_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;
	
	DEBUG("target->state: %s", target_state_strings[target->state]);
	
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
	if (target->state == TARGET_HALTED)
	{
		WARNING("target was already halted");
		return ERROR_TARGET_ALREADY_HALTED;
	}
	
	if (target->state == TARGET_UNKNOWN)
	{
		WARNING("target was in unknown state when halt was requested");
	}
	
	if (target->state == TARGET_RESET) 
	{
		if ((jtag_reset_config & RESET_SRST_PULLS_TRST) && jtag_srst)
		{
			ERROR("can't request a halt while in reset if nSRST pulls nTRST");
			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; 
		}
	}

460
461
462
463
464
465
466
467
468
469
470
471
472
473
	/* Write to Debug Halting Control and Status Register */
	ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT );

	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
474
475
	u32 dcb_dhcsr = 0;
	int retval, timeout = 0;
476
477
478
479
480
481
482
483
484
	
	/* Check that we are using process_context, or change and print warning */
	if (armv7m_get_context(target) != ARMV7M_PROCESS_CONTEXT)
	{
		DEBUG("Changing to process contex registers");
		armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
	}

	/* Enter debug state on reset, cf. end_reset_event() */
ntfreak's avatar
ntfreak committed
485
	ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET );
486
487
488
489
490
491
492
493
	
	/* Request a reset */ 
	ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_VECTRESET );
	target->state = TARGET_RESET;

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

494
	while (timeout < 100)
495
496
497
498
499
	{
		retval = ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
		if (retval == ERROR_OK)
		{
		    ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
500
			if ((dcb_dhcsr & S_HALT) && (cortex_m3->nvic_dfsr & DFSR_VCATCH))
501
			{
ntfreak's avatar
ntfreak committed
502
				DEBUG("system reset-halted, dcb_dhcsr 0x%x, nvic_dfsr 0x%x", dcb_dhcsr, cortex_m3->nvic_dfsr);
503
504
505
506
				cortex_m3_poll(target);
				return ERROR_OK;
			}
			else
ntfreak's avatar
ntfreak committed
507
				DEBUG("waiting for system reset-halt, dcb_dhcsr 0x%x, %i ms", dcb_dhcsr, timeout);
508
509
510
511
512
513
514
515
		}
		timeout++;
		usleep(1000);
	}
		
	return ERROR_OK;
}

516
517
518
519
520
int cortex_m3_prepare_reset_halt(struct target_s *target)
{
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
521
522
	u32 dcb_demcr, dcb_dhcsr;
	
523
524
525
526
527
528
	/* Enable debug requests */
	ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
	if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
		ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN );
	
	/* Enter debug state on reset, cf. end_reset_event() */
529
530
531
532
533
	ahbap_write_system_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET );
	
	ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
	ahbap_read_system_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr);
	DEBUG("dcb_dhcsr 0x%x, dcb_demcr 0x%x, ", dcb_dhcsr, dcb_demcr);
534
535
536
537
	
	return ERROR_OK;
}

538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
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;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
	breakpoint_t *breakpoint = NULL;
	u32 dcb_dhcsr, resume_pc;
	
	if (target->state != TARGET_HALTED)
	{
		WARNING("target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}
	
	if (!debug_execution)
	{
		/* Check that we are using process_context, or change and print warning */
		if (armv7m_get_context(target) != ARMV7M_PROCESS_CONTEXT)
		{
			WARNING("Incorrect context in resume");
			armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
		}
ntfreak's avatar
ntfreak committed
561
		
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
		target_free_all_working_areas(target);
		cortex_m3_enable_breakpoints(target);
		cortex_m3_enable_watchpoints(target);

		/* TODOLATER Interrupt handling/disable for debug execution, cache ... ... */ 
	}
	
	dcb_dhcsr = DBGKEY | C_DEBUGEN;
	if (debug_execution)
	{
		/* Check that we are using debug_context, or change and print warning */
		if (armv7m_get_context(target) != ARMV7M_DEBUG_CONTEXT)
		{
			WARNING("Incorrect context in debug_exec resume");
			armv7m_use_context(target, ARMV7M_DEBUG_CONTEXT);
		}
		/* Disable interrupts */
		/* 
		   We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS,
		   This is probably the same inssue as Cortex-M3 Errata	377493: 
		   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);
		/* 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
587
			buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1<<24));
588
589
590
591
592
593
594
595
596
597
598
599
	}

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

600
	armv7m_restore_context(target);
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
	
	/* 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)))
		{
				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);
		}
	}

	/* Set/Clear C_MASKINTS in a separate operation */
ntfreak's avatar
ntfreak committed
616
	if ((cortex_m3->dcb_dhcsr & C_MASKINTS) != (dcb_dhcsr & C_MASKINTS))
617
		ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, dcb_dhcsr | C_HALT );
618
	
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
	/* Restart core */
	ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, dcb_dhcsr );
	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);
		DEBUG("target resumed at 0x%x",resume_pc);
	}
	else
	{
		target->state = TARGET_DEBUG_RUNNING;
		target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
		DEBUG("target debug resumed at 0x%x",resume_pc);
	}
	
	return ERROR_OK;
}

ntfreak's avatar
ntfreak committed
641
//int irqstepcount=0;
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
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)
	{
		WARNING("target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}
	
	/* Check that we are using process_context, or change and print warning */
	if (armv7m_get_context(target) != ARMV7M_PROCESS_CONTEXT)
	{
		WARNING("Incorrect context in step, must be process");
		armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
	}

	/* 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;
	
674
	armv7m_restore_context(target);
675
676
677
	
	target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
    
ntfreak's avatar
ntfreak committed
678
	if (cortex_m3->dcb_dhcsr & C_MASKINTS)
679
680
681
682
683
684
685
686
687
688
689
		ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN );
	ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY| C_STEP | C_DEBUGEN);
	ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);

	/* If we run in process context then registers are now invalid */
	if (armv7m_get_context(target) == ARMV7M_PROCESS_CONTEXT)
		armv7m_invalidate_core_regs(target);
	
	if (breakpoint)
		cortex_m3_set_breakpoint(target, breakpoint);

ntfreak's avatar
ntfreak committed
690
	DEBUG("target stepped dcb_dhcsr = 0x%x nvic_icsr = 0x%x", cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
691
692
693
694

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

ntfreak's avatar
ntfreak committed
695
	DEBUG("target stepped dcb_dhcsr = 0x%x nvic_icsr = 0x%x", cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
696
697
698
699
700
701
	return ERROR_OK;
}

int cortex_m3_assert_reset(target_t *target)
{
	int retval;
702
703
704
705
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
	
706
707
	DEBUG("target->state: %s", target_state_strings[target->state]);
	
708
709
	ahbap_write_system_u32(swjdp, DCB_DCRDR, 0 );
	
710
711
712
713
714
715
716
717
718
719
720
721
722
	if (target->reset_mode == RESET_RUN)
	{
		/* Set/Clear C_MASKINTS in a separate operation */
		if (cortex_m3->dcb_dhcsr & C_MASKINTS)
			ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT );
		
		cortex_m3_clear_halt(target);
							
		/* Enter debug state on reset, cf. end_reset_event() */	
		ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN );
		ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR);
	}
	
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
	if (target->state == TARGET_HALTED || target->state == TARGET_UNKNOWN)
	{
		/* assert SRST and TRST */
		/* system would get ouf sync if we didn't reset test-logic, too */
		if ((retval = jtag_add_reset(1, 1)) != ERROR_OK)
		{
			if (retval == ERROR_JTAG_RESET_CANT_SRST)
			{
				WARNING("can't assert srst");
				return retval;
			}
			else
			{
				ERROR("unknown error");
				exit(-1);
			}
		}
		jtag_add_sleep(5000);
		if ((retval = jtag_add_reset(0, 1)) != ERROR_OK)
		{
			if (retval == ERROR_JTAG_RESET_WOULD_ASSERT_TRST)
			{
				WARNING("srst resets test logic, too");
				retval = jtag_add_reset(1, 1);
			}
		}
	}
	else
	{
		if ((retval = jtag_add_reset(0, 1)) != ERROR_OK)
		{
			if (retval == ERROR_JTAG_RESET_WOULD_ASSERT_TRST)
			{
				WARNING("srst resets test logic, too");
				retval = jtag_add_reset(1, 1);
			}
			
			if (retval == ERROR_JTAG_RESET_CANT_SRST)
			{
				WARNING("can't assert srsrt");
				return retval;
			}
			else if (retval != ERROR_OK)
			{
				ERROR("unknown error");
				exit(-1);
			}
		}
	}
	
	target->state = TARGET_RESET;
	jtag_add_sleep(50000);
	
	armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
	armv7m_invalidate_core_regs(target);

	return ERROR_OK;
}

int cortex_m3_deassert_reset(target_t *target)
783
{		
784
785
786
787
788
789
790
791
792
793
794
795
	DEBUG("target->state: %s", target_state_strings[target->state]);
	
	/* deassert reset lines */
	jtag_add_reset(0, 0);
		
	return ERROR_OK;
}

void cortex_m3_unset_all_breakpoints_and_watchpoints(struct target_s *target)
{

}
ntfreak's avatar
ntfreak committed
796

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
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)
{
	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)
	{
		WARNING("breakpoint already set");
		return ERROR_OK;
	}

	if (cortex_m3->auto_bp_type)
	{
ntfreak's avatar
ntfreak committed
829
		breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
830
831
832
833
	}

	if (breakpoint->type == BKPT_HARD)
	{
ntfreak's avatar
ntfreak committed
834
		while(comparator_list[fp_num].used && (fp_num < cortex_m3->fp_num_code))
835
			fp_num++;
ntfreak's avatar
ntfreak committed
836
		if (fp_num >= cortex_m3->fp_num_code)
837
838
839
840
841
		{
			DEBUG("ERROR Can not find free FP Comparator");
			WARNING("ERROR Can not find free FP Comparator");
			exit(-1);
		}
ntfreak's avatar
ntfreak committed
842
843
		breakpoint->set = fp_num + 1;
		hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW;
844
		comparator_list[fp_num].used = 1;
ntfreak's avatar
ntfreak committed
845
		comparator_list[fp_num].fpcr_value = (breakpoint->address & 0x1FFFFFFC) | hilo | 1;
846
		target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value);
ntfreak's avatar
ntfreak committed
847
		DEBUG("fpc_num %i fpcr_value 0x%x", fp_num, comparator_list[fp_num].fpcr_value);
848
849
850
851
852
	}
	else if (breakpoint->type == BKPT_SOFT)
	{
		u8 code[4];
		buf_set_u32(code, 0, 32, ARMV7M_T_BKPT(0x11));
ntfreak's avatar
ntfreak committed
853
854
		target->type->read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr);
		target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, code);
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
		breakpoint->set = 0x11; /* Any nice value but 0 */
	}

	return ERROR_OK;
}

int cortex_m3_unset_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;
	cortex_m3_fp_comparator_t * comparator_list = cortex_m3->fp_comparator_list;

	if (!breakpoint->set)
	{
		WARNING("breakpoint not set");
		return ERROR_OK;
	}
	
	if (breakpoint->type == BKPT_HARD)
	{
ntfreak's avatar
ntfreak committed
876
877
		int fp_num = breakpoint->set - 1;
		if ((fp_num < 0) || (fp_num >= cortex_m3->fp_num_code))
878
879
880
881
882
883
884
885
886
887
888
889
890
		{
			DEBUG("Invalid FP Comparator number in breakpoint");
			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)
		{
ntfreak's avatar
ntfreak committed
891
			target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr);
892
893
894
		}
		else
		{
ntfreak's avatar
ntfreak committed
895
			target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr);
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
		}
	}
	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;
	
	if (cortex_m3->auto_bp_type)
	{
ntfreak's avatar
ntfreak committed
911
		breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
912
913
	}

ntfreak's avatar
ntfreak committed
914
	if ((breakpoint->type == BKPT_HARD) && (breakpoint->address >= 0x20000000))
915
916
917
918
919
	{
		INFO("flash patch comparator requested outside code memory region");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}

ntfreak's avatar
ntfreak committed
920
	if ((breakpoint->type == BKPT_SOFT) && (breakpoint->address < 0x20000000))
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
	{
		INFO("soft breakpoint requested in code (flash) memory region");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}

	if ((breakpoint->type == BKPT_HARD) && (cortex_m3->fp_code_available < 1))
	{
		INFO("no flash patch comparator unit available for hardware breakpoint");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}

	if ((breakpoint->length != 2))
	{
		INFO("only breakpoints of two bytes length supported");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
	
	if (breakpoint->type == BKPT_HARD)
		cortex_m3->fp_code_available--;
	cortex_m3_set_breakpoint(target, breakpoint);
	
	return ERROR_OK;
}

int cortex_m3_remove_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;
	
	if (target->state != TARGET_HALTED)
	{
		WARNING("target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}
	
	if (cortex_m3->auto_bp_type)
	{
ntfreak's avatar
ntfreak committed
959
		breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
	}

	if (breakpoint->set)
	{
		cortex_m3_unset_breakpoint(target, breakpoint);
	}
	
	if (breakpoint->type == BKPT_HARD)
		cortex_m3->fp_code_available++;
	
	return ERROR_OK;
}

int cortex_m3_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
	int dwt_num=0;
	u32 mask, temp;
	
	/* get pointers to arch-specific information */
	armv7m_common_t *armv7m = target->arch_info;
	cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
	cortex_m3_dwt_comparator_t * comparator_list = cortex_m3->dwt_comparator_list;

	if (watchpoint->set)
	{
		WARNING("watchpoint already set");
		return ERROR_OK;
	}

	if (watchpoint->mask == 0xffffffffu)
	{
ntfreak's avatar
ntfreak committed
991
		while(comparator_list[dwt_num].used && (dwt_num < cortex_m3->dwt_num_comp))
992
			dwt_num++;
ntfreak's avatar
ntfreak committed
993
		if (dwt_num >= cortex_m3->dwt_num_comp)
994
995
996
997
998
		{
			DEBUG("ERROR Can not find free DWT Comparator");
			WARNING("ERROR Can not find free DWT Comparator");
			return -1;
		}
ntfreak's avatar
ntfreak committed
999
		watchpoint->set = dwt_num + 1;
1000
		mask = 0;
For faster browsing, not all history is shown. View entire blame