target.c 118 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007-2009 Øyvind Harboe                                 *
6
7
 *   oyvind.harboe@zylin.com                                               *
 *                                                                         *
8
9
10
 *   Copyright (C) 2008, Duane Ellis                                       *
 *   openocd@duaneeellis.com                                               *
 *                                                                         *
11
12
13
 *   Copyright (C) 2008 by Spencer Oliver                                  *
 *   spen@spen-soft.co.uk                                                  *
 *                                                                         *
14
15
16
 *   Copyright (C) 2008 by Rick Altherr                                    *
 *   kc8apf@kc8apf.net>                                                    *
 *                                                                         *
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 *   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 "target.h"
37
#include "target_type.h"
38
#include "target_request.h"
39
40
41
42
#include "time_support.h"
#include "register.h"
#include "trace.h"
#include "image.h"
43
44
45
#include "jtag.h"


46
static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
47

Zachary T Welch's avatar
Zachary T Welch committed
48
49
static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv);
static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv);
50

51
/* targets */
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
extern struct target_type arm7tdmi_target;
extern struct target_type arm720t_target;
extern struct target_type arm9tdmi_target;
extern struct target_type arm920t_target;
extern struct target_type arm966e_target;
extern struct target_type arm926ejs_target;
extern struct target_type fa526_target;
extern struct target_type feroceon_target;
extern struct target_type dragonite_target;
extern struct target_type xscale_target;
extern struct target_type cortexm3_target;
extern struct target_type cortexa8_target;
extern struct target_type arm11_target;
extern struct target_type mips_m4k_target;
extern struct target_type avr_target;

struct target_type *target_types[] =
69
70
71
72
73
74
75
{
	&arm7tdmi_target,
	&arm9tdmi_target,
	&arm920t_target,
	&arm720t_target,
	&arm966e_target,
	&arm926ejs_target,
76
	&fa526_target,
77
	&feroceon_target,
78
	&dragonite_target,
79
80
	&xscale_target,
	&cortexm3_target,
81
	&cortexa8_target,
oharboe's avatar
oharboe committed
82
	&arm11_target,
ntfreak's avatar
ntfreak committed
83
	&mips_m4k_target,
84
	&avr_target,
85
86
87
	NULL,
};

Zachary T Welch's avatar
Zachary T Welch committed
88
struct target *all_targets = NULL;
89
struct target_event_callback *target_event_callbacks = NULL;
90
struct target_timer_callback *target_timer_callbacks = NULL;
91

92
93
94
95
96
97
98
99
const Jim_Nvp nvp_assert[] = {
	{ .name = "assert", NVP_ASSERT },
	{ .name = "deassert", NVP_DEASSERT },
	{ .name = "T", NVP_ASSERT },
	{ .name = "F", NVP_DEASSERT },
	{ .name = "t", NVP_ASSERT },
	{ .name = "f", NVP_DEASSERT },
	{ .name = NULL, .value = -1 }
100
101
};

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
const Jim_Nvp nvp_error_target[] = {
	{ .value = ERROR_TARGET_INVALID, .name = "err-invalid" },
	{ .value = ERROR_TARGET_INIT_FAILED, .name = "err-init-failed" },
	{ .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" },
	{ .value = ERROR_TARGET_NOT_HALTED, .name = "err-not-halted" },
	{ .value = ERROR_TARGET_FAILURE, .name = "err-failure" },
	{ .value = ERROR_TARGET_UNALIGNED_ACCESS   , .name = "err-unaligned-access" },
	{ .value = ERROR_TARGET_DATA_ABORT , .name = "err-data-abort" },
	{ .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE , .name = "err-resource-not-available" },
	{ .value = ERROR_TARGET_TRANSLATION_FAULT  , .name = "err-translation-fault" },
	{ .value = ERROR_TARGET_NOT_RUNNING, .name = "err-not-running" },
	{ .value = ERROR_TARGET_NOT_EXAMINED, .name = "err-not-examined" },
	{ .value = -1, .name = NULL }
};

117
const char *target_strerror_safe(int err)
118
119
120
{
	const Jim_Nvp *n;

121
	n = Jim_Nvp_value2name_simple(nvp_error_target, err);
zwelch's avatar
zwelch committed
122
	if (n->name == NULL) {
123
124
125
126
127
128
		return "unknown";
	} else {
		return n->name;
	}
}

129
static const Jim_Nvp nvp_target_event[] = {
130
131
	{ .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" },
	{ .value = TARGET_EVENT_OLD_pre_resume         , .name = "old-pre_resume" },
132

133
	{ .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" },
134
135
136
137
138
	{ .value = TARGET_EVENT_HALTED, .name = "halted" },
	{ .value = TARGET_EVENT_RESUMED, .name = "resumed" },
	{ .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
	{ .value = TARGET_EVENT_RESUME_END, .name = "resume-end" },

139
140
141
	{ .name = "gdb-start", .value = TARGET_EVENT_GDB_START },
	{ .name = "gdb-end", .value = TARGET_EVENT_GDB_END },

142
	/* historical name */
143

144
	{ .value = TARGET_EVENT_RESET_START, .name = "reset-start" },
145
146
147
148
149
150
151
152
153

	{ .value = TARGET_EVENT_RESET_ASSERT_PRE,    .name = "reset-assert-pre" },
	{ .value = TARGET_EVENT_RESET_ASSERT_POST,   .name = "reset-assert-post" },
	{ .value = TARGET_EVENT_RESET_DEASSERT_PRE,  .name = "reset-deassert-pre" },
	{ .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" },
	{ .value = TARGET_EVENT_RESET_HALT_PRE,      .name = "reset-halt-pre" },
	{ .value = TARGET_EVENT_RESET_HALT_POST,     .name = "reset-halt-post" },
	{ .value = TARGET_EVENT_RESET_WAIT_PRE,      .name = "reset-wait-pre" },
	{ .value = TARGET_EVENT_RESET_WAIT_POST,     .name = "reset-wait-post" },
154
155
156
	{ .value = TARGET_EVENT_RESET_INIT , .name = "reset-init" },
	{ .value = TARGET_EVENT_RESET_END, .name = "reset-end" },

157
	{ .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" },
158
	{ .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" },
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
	{ .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" },
	{ .value = TARGET_EVENT_DEBUG_RESUMED, .name = "debug-resumed" },

	{ .value = TARGET_EVENT_GDB_ATTACH, .name = "gdb-attach" },
	{ .value = TARGET_EVENT_GDB_DETACH, .name = "gdb-detach" },

	{ .value = TARGET_EVENT_GDB_FLASH_WRITE_START, .name = "gdb-flash-write-start" },
	{ .value = TARGET_EVENT_GDB_FLASH_WRITE_END  , .name = "gdb-flash-write-end"   },

	{ .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" },
	{ .value = TARGET_EVENT_GDB_FLASH_ERASE_END  , .name = "gdb-flash-erase-end" },

	{ .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
	{ .value = TARGET_EVENT_RESUMED     , .name = "resume-ok" },
	{ .value = TARGET_EVENT_RESUME_END  , .name = "resume-end" },

	{ .name = NULL, .value = -1 }
177
178
};

179
180
181
182
183
184
185
const Jim_Nvp nvp_target_state[] = {
	{ .name = "unknown", .value = TARGET_UNKNOWN },
	{ .name = "running", .value = TARGET_RUNNING },
	{ .name = "halted",  .value = TARGET_HALTED },
	{ .name = "reset",   .value = TARGET_RESET },
	{ .name = "debug-running", .value = TARGET_DEBUG_RUNNING },
	{ .name = NULL, .value = -1 },
186
187
};

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
const Jim_Nvp nvp_target_debug_reason [] = {
	{ .name = "debug-request"            , .value = DBG_REASON_DBGRQ },
	{ .name = "breakpoint"               , .value = DBG_REASON_BREAKPOINT },
	{ .name = "watchpoint"               , .value = DBG_REASON_WATCHPOINT },
	{ .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT },
	{ .name = "single-step"              , .value = DBG_REASON_SINGLESTEP },
	{ .name = "target-not-halted"        , .value = DBG_REASON_NOTHALTED  },
	{ .name = "undefined"                , .value = DBG_REASON_UNDEFINED },
	{ .name = NULL, .value = -1 },
};

const Jim_Nvp nvp_target_endian[] = {
	{ .name = "big",    .value = TARGET_BIG_ENDIAN },
	{ .name = "little", .value = TARGET_LITTLE_ENDIAN },
	{ .name = "be",     .value = TARGET_BIG_ENDIAN },
203
	{ .name = "le",     .value = TARGET_LITTLE_ENDIAN },
204
205
206
	{ .name = NULL,     .value = -1 },
};

207
208
209
210
211
212
213
214
const Jim_Nvp nvp_reset_modes[] = {
	{ .name = "unknown", .value = RESET_UNKNOWN },
	{ .name = "run"    , .value = RESET_RUN },
	{ .name = "halt"   , .value = RESET_HALT },
	{ .name = "init"   , .value = RESET_INIT },
	{ .name = NULL     , .value = -1 },
};

215
const char *
Zachary T Welch's avatar
Zachary T Welch committed
216
target_state_name( struct target *t )
217
218
219
220
221
222
223
224
225
226
{
	const char *cp;
	cp = Jim_Nvp_value2name_simple(nvp_target_state, t->state)->name;
	if( !cp ){
		LOG_ERROR("Invalid target state: %d", (int)(t->state));
		cp = "(*BUG*unknown*BUG*)";
	}
	return cp;
}

227
/* determine the number of the new target */
228
static int new_target_number(void)
229
{
Zachary T Welch's avatar
Zachary T Welch committed
230
	struct target *t;
231
232
233
234
235
	int x;

	/* number is 0 based */
	x = -1;
	t = all_targets;
zwelch's avatar
zwelch committed
236
237
	while (t) {
		if (x < t->target_number) {
238
239
240
241
			x = t->target_number;
		}
		t = t->next;
	}
zwelch's avatar
zwelch committed
242
	return x + 1;
243
244
}

245
/* read a uint32_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
246
uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
247
248
249
250
251
252
253
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		return le_to_h_u32(buffer);
	else
		return be_to_h_u32(buffer);
}

zwelch's avatar
zwelch committed
254
/* read a uint16_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
255
uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer)
256
257
258
259
260
261
262
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		return le_to_h_u16(buffer);
	else
		return be_to_h_u16(buffer);
}

263
/* read a uint8_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
264
uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer)
265
266
267
268
{
	return *buffer & 0x0ff;
}

269
/* write a uint32_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
270
void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value)
271
272
273
274
275
276
277
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		h_u32_to_le(buffer, value);
	else
		h_u32_to_be(buffer, value);
}

zwelch's avatar
zwelch committed
278
/* write a uint16_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
279
void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value)
280
281
282
283
284
285
286
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		h_u16_to_le(buffer, value);
	else
		h_u16_to_be(buffer, value);
}

287
/* write a uint8_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
288
void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value)
289
290
291
292
{
	*buffer = value;
}

293
/* return a pointer to a configured target; id is name or number */
Zachary T Welch's avatar
Zachary T Welch committed
294
struct target *get_target(const char *id)
295
{
Zachary T Welch's avatar
Zachary T Welch committed
296
	struct target *target;
297
298
299
300
301
302
303
304
305

	/* try as tcltarget name */
	for (target = all_targets; target; target = target->next) {
		if (target->cmd_name == NULL)
			continue;
		if (strcmp(id, target->cmd_name) == 0)
			return target;
	}

306
307
	/* It's OK to remove this fallback sometime after August 2010 or so */

308
	/* no match, try as number */
309
310
	unsigned num;
	if (parse_uint(id, &num) != ERROR_OK)
311
312
313
		return NULL;

	for (target = all_targets; target; target = target->next) {
314
315
316
		if (target->target_number == (int)num) {
			LOG_WARNING("use '%s' as target identifier, not '%u'",
					target->cmd_name, num);
317
			return target;
318
		}
319
320
321
322
323
	}

	return NULL;
}

324
/* returns a pointer to the n-th configured target */
Zachary T Welch's avatar
Zachary T Welch committed
325
static struct target *get_target_by_num(int num)
326
{
Zachary T Welch's avatar
Zachary T Welch committed
327
	struct target *target = all_targets;
328

zwelch's avatar
zwelch committed
329
330
	while (target) {
		if (target->target_number == num) {
331
			return target;
332
		}
333
334
335
336
337
338
		target = target->next;
	}

	return NULL;
}

Zachary T Welch's avatar
Zachary T Welch committed
339
struct target* get_current_target(command_context_t *cmd_ctx)
340
{
Zachary T Welch's avatar
Zachary T Welch committed
341
	struct target *target = get_target_by_num(cmd_ctx->current_target);
oharboe's avatar
oharboe committed
342

343
344
	if (target == NULL)
	{
345
		LOG_ERROR("BUG: current_target out of bounds");
346
347
348
		exit(-1);
	}

oharboe's avatar
oharboe committed
349
	return target;
350
351
}

Zachary T Welch's avatar
Zachary T Welch committed
352
int target_poll(struct target *target)
353
{
354
355
	int retval;

356
	/* We can't poll until after examine */
357
	if (!target_was_examined(target))
358
359
360
361
	{
		/* Fail silently lest we pollute the log */
		return ERROR_FAIL;
	}
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

	retval = target->type->poll(target);
	if (retval != ERROR_OK)
		return retval;

	if (target->halt_issued)
	{
		if (target->state == TARGET_HALTED)
		{
			target->halt_issued = false;
		} else
		{
			long long t = timeval_ms() - target->halt_issued_time;
			if (t>1000)
			{
				target->halt_issued = false;
				LOG_INFO("Halt timed out, wake up GDB.");
				target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
			}
		}
	}

	return ERROR_OK;
385
386
}

Zachary T Welch's avatar
Zachary T Welch committed
387
int target_halt(struct target *target)
388
{
389
	int retval;
390
	/* We can't poll until after examine */
391
	if (!target_was_examined(target))
392
393
394
395
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
396
397
398
399
400
401
402
403
404

	retval = target->type->halt(target);
	if (retval != ERROR_OK)
		return retval;

	target->halt_issued = true;
	target->halt_issued_time = timeval_ms();

	return ERROR_OK;
405
406
}

Zachary T Welch's avatar
Zachary T Welch committed
407
int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
408
{
409
	int retval;
oharboe's avatar
oharboe committed
410

411
	/* We can't poll until after examine */
412
	if (!target_was_examined(target))
413
414
415
416
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
oharboe's avatar
oharboe committed
417

oharboe's avatar
oharboe committed
418
419
420
421
	/* note that resume *must* be asynchronous. The CPU can halt before we poll. The CPU can
	 * even halt at the current PC as a result of a software breakpoint being inserted by (a bug?)
	 * the application.
	 */
422
423
	if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK)
		return retval;
oharboe's avatar
oharboe committed
424

425
	return retval;
426
427
}

oharboe's avatar
oharboe committed
428
int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode)
429
430
{
	char buf[100];
431
	int retval;
432
	Jim_Nvp *n;
433
	n = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode);
zwelch's avatar
zwelch committed
434
	if (n->name == NULL) {
435
436
437
438
		LOG_ERROR("invalid reset mode");
		return ERROR_FAIL;
	}

439
440
441
442
	/* disable polling during reset to make reset event scripts
	 * more predictable, i.e. dr/irscan & pathmove in events will
	 * not have JTAG operations injected into the middle of a sequence.
	 */
443
444
445
	bool save_poll = jtag_poll_get_enabled();

	jtag_poll_set_enabled(false);
446

447
448
	sprintf(buf, "ocd_process_reset %s", n->name);
	retval = Jim_Eval(interp, buf);
449

450
	jtag_poll_set_enabled(save_poll);
451

zwelch's avatar
zwelch committed
452
	if (retval != JIM_OK) {
453
		Jim_PrintErrorMessage(interp);
454
455
		return ERROR_FAIL;
	}
456
457

	/* We want any events to be processed before the prompt */
458
	retval = target_call_timer_callbacks_now();
459

460
	return retval;
461
462
}

Zachary T Welch's avatar
Zachary T Welch committed
463
static int identity_virt2phys(struct target *target,
David Brownell's avatar
David Brownell committed
464
		uint32_t virtual, uint32_t *physical)
465
466
467
468
469
{
	*physical = virtual;
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
470
static int no_mmu(struct target *target, int *enabled)
471
{
472
	*enabled = 0;
473
474
475
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
476
static int default_examine(struct target *target)
477
{
478
	target_set_examined(target);
479
480
481
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
482
int target_examine_one(struct target *target)
zwelch's avatar
zwelch committed
483
484
485
486
{
	return target->type->examine(target);
}

zwelch's avatar
zwelch committed
487
488
static int jtag_enable_callback(enum jtag_event event, void *priv)
{
Zachary T Welch's avatar
Zachary T Welch committed
489
	struct target *target = priv;
zwelch's avatar
zwelch committed
490
491
492
493
494
495
496
497
498

	if (event != JTAG_TAP_EVENT_ENABLE || !target->tap->enabled)
		return ERROR_OK;

	jtag_unregister_event_callback(jtag_enable_callback, target);
	return target_examine_one(target);
}


zwelch's avatar
zwelch committed
499
/* Targets that correctly implement init + examine, i.e.
500
 * no communication with target during init:
oharboe's avatar
oharboe committed
501
502
 *
 * XScale
503
 */
ntfreak's avatar
ntfreak committed
504
int target_examine(void)
505
506
{
	int retval = ERROR_OK;
Zachary T Welch's avatar
Zachary T Welch committed
507
	struct target *target;
zwelch's avatar
zwelch committed
508
509

	for (target = all_targets; target; target = target->next)
510
	{
zwelch's avatar
zwelch committed
511
512
513
514
		/* defer examination, but don't skip it */
		if (!target->tap->enabled) {
			jtag_register_event_callback(jtag_enable_callback,
					target);
zwelch's avatar
zwelch committed
515
			continue;
zwelch's avatar
zwelch committed
516
		}
zwelch's avatar
zwelch committed
517
		if ((retval = target_examine_one(target)) != ERROR_OK)
518
519
520
521
			return retval;
	}
	return retval;
}
Zachary T Welch's avatar
Zachary T Welch committed
522
const char *target_get_name(struct target *target)
zwelch's avatar
zwelch committed
523
524
525
{
	return target->type->name;
}
526

Zachary T Welch's avatar
Zachary T Welch committed
527
static int target_write_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
528
{
529
	if (!target_was_examined(target))
530
531
532
533
534
535
536
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
	return target->type->write_memory_imp(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
537
static int target_read_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
538
{
539
	if (!target_was_examined(target))
540
541
542
543
544
545
546
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
	return target->type->read_memory_imp(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
547
static int target_soft_reset_halt_imp(struct target *target)
548
{
549
	if (!target_was_examined(target))
550
551
552
553
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
554
555
556
557
558
	if (!target->type->soft_reset_halt_imp) {
		LOG_ERROR("Target %s does not support soft_reset_halt",
				target->cmd_name);
		return ERROR_FAIL;
	}
559
560
561
	return target->type->soft_reset_halt_imp(target);
}

Zachary T Welch's avatar
Zachary T Welch committed
562
static int target_run_algorithm_imp(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info)
563
{
564
	if (!target_was_examined(target))
565
566
567
568
569
570
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
	return target->type->run_algorithm_imp(target, num_mem_params, mem_params, num_reg_params, reg_param, entry_point, exit_point, timeout_ms, arch_info);
}
571

Zachary T Welch's avatar
Zachary T Welch committed
572
int target_read_memory(struct target *target,
573
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
574
575
576
577
{
	return target->type->read_memory(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
578
int target_read_phys_memory(struct target *target,
579
580
581
582
583
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
{
	return target->type->read_phys_memory(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
584
int target_write_memory(struct target *target,
585
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
586
587
588
{
	return target->type->write_memory(target, address, size, count, buffer);
}
589

Zachary T Welch's avatar
Zachary T Welch committed
590
int target_write_phys_memory(struct target *target,
591
592
593
594
595
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
{
	return target->type->write_phys_memory(target, address, size, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
596
int target_bulk_write_memory(struct target *target,
597
		uint32_t address, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
598
599
600
601
{
	return target->type->bulk_write_memory(target, address, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
602
int target_add_breakpoint(struct target *target,
603
		struct breakpoint *breakpoint)
604
605
606
{
	return target->type->add_breakpoint(target, breakpoint);
}
Zachary T Welch's avatar
Zachary T Welch committed
607
int target_remove_breakpoint(struct target *target,
608
		struct breakpoint *breakpoint)
609
610
611
612
{
	return target->type->remove_breakpoint(target, breakpoint);
}

Zachary T Welch's avatar
Zachary T Welch committed
613
int target_add_watchpoint(struct target *target,
614
		struct watchpoint *watchpoint)
615
616
617
{
	return target->type->add_watchpoint(target, watchpoint);
}
Zachary T Welch's avatar
Zachary T Welch committed
618
int target_remove_watchpoint(struct target *target,
619
		struct watchpoint *watchpoint)
620
621
622
{
	return target->type->remove_watchpoint(target, watchpoint);
}
zwelch's avatar
zwelch committed
623

Zachary T Welch's avatar
Zachary T Welch committed
624
int target_get_gdb_reg_list(struct target *target,
Zachary T Welch's avatar
Zachary T Welch committed
625
		struct reg **reg_list[], int *reg_list_size)
zwelch's avatar
zwelch committed
626
627
628
{
	return target->type->get_gdb_reg_list(target, reg_list, reg_list_size);
}
Zachary T Welch's avatar
Zachary T Welch committed
629
int target_step(struct target *target,
630
		int current, uint32_t address, int handle_breakpoints)
zwelch's avatar
zwelch committed
631
632
633
634
{
	return target->type->step(target, current, address, handle_breakpoints);
}

zwelch's avatar
zwelch committed
635

Zachary T Welch's avatar
Zachary T Welch committed
636
int target_run_algorithm(struct target *target,
637
		int num_mem_params, struct mem_param *mem_params,
638
		int num_reg_params, struct reg_param *reg_param,
639
		uint32_t entry_point, uint32_t exit_point,
zwelch's avatar
zwelch committed
640
641
642
643
644
645
646
		int timeout_ms, void *arch_info)
{
	return target->type->run_algorithm(target,
			num_mem_params, mem_params, num_reg_params, reg_param,
			entry_point, exit_point, timeout_ms, arch_info);
}

647
/// @returns @c true if the target has been examined.
Zachary T Welch's avatar
Zachary T Welch committed
648
bool target_was_examined(struct target *target)
649
650
651
652
{
	return target->type->examined;
}
/// Sets the @c examined flag for the given target.
Zachary T Welch's avatar
Zachary T Welch committed
653
void target_set_examined(struct target *target)
654
655
656
657
{
	target->type->examined = true;
}
// Reset the @c examined flag for the given target.
Zachary T Welch's avatar
Zachary T Welch committed
658
void target_reset_examined(struct target *target)
659
660
661
662
{
	target->type->examined = false;
}

zwelch's avatar
zwelch committed
663

664

Zachary T Welch's avatar
Zachary T Welch committed
665
static int default_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
666
{
667
	LOG_ERROR("Not implemented: %s", __func__);
668
669
670
	return ERROR_FAIL;
}

Zachary T Welch's avatar
Zachary T Welch committed
671
static int default_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
672
{
673
	LOG_ERROR("Not implemented: %s", __func__);
674
675
676
	return ERROR_FAIL;
}

Zachary T Welch's avatar
Zachary T Welch committed
677
static int arm_cp_check(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm)
678
679
680
681
682
683
684
685
686
687
688
689
690
691
{
	/* basic check */
	if (!target_was_examined(target))
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}

	if ((cpnum <0) || (cpnum > 15))
	{
		LOG_ERROR("Illegal co-processor %d", cpnum);
		return ERROR_FAIL;
	}

692
	if (op1 > 7)
693
694
695
696
697
	{
		LOG_ERROR("Illegal op1");
		return ERROR_FAIL;
	}

698
	if (op2 > 7)
699
700
701
702
703
	{
		LOG_ERROR("Illegal op2");
		return ERROR_FAIL;
	}

704
	if (CRn > 15)
705
706
707
708
709
	{
		LOG_ERROR("Illegal CRn");
		return ERROR_FAIL;
	}

710
	if (CRm > 15)
711
712
713
714
715
	{
		LOG_ERROR("Illegal CRm");
		return ERROR_FAIL;
	}

716
717
718
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
719
int target_mrc(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
720
721
722
723
724
725
726
727
728
729
{
	int retval;

	retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm);
	if (retval != ERROR_OK)
		return retval;

	return target->type->mrc(target, cpnum, op1, op2, CRn, CRm, value);
}

Zachary T Welch's avatar
Zachary T Welch committed
730
int target_mcr(struct target *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
731
732
733
734
735
736
737
738
739
740
{
	int retval;

	retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm);
	if (retval != ERROR_OK)
		return retval;

	return target->type->mcr(target, cpnum, op1, op2, CRn, CRm, value);
}

741
static int
Zachary T Welch's avatar
Zachary T Welch committed
742
err_read_phys_memory(struct target *target, uint32_t address,
743
		uint32_t size, uint32_t count, uint8_t *buffer)
744
{
745
	LOG_ERROR("Not implemented: %s", __func__);
746
	return ERROR_FAIL;
747
748
}

749
static int
Zachary T Welch's avatar
Zachary T Welch committed
750
err_write_phys_memory(struct target *target, uint32_t address,
751
		uint32_t size, uint32_t count, uint8_t *buffer)
752
{
753
	LOG_ERROR("Not implemented: %s", __func__);
754
	return ERROR_FAIL;
755
756
}

757
758
int target_init(struct command_context_s *cmd_ctx)
{
Zachary T Welch's avatar
Zachary T Welch committed
759
	struct target *target;
760
	int retval;
oharboe's avatar
oharboe committed
761

762
	for (target = all_targets; target; target = target->next) {
763
		struct target_type *type = target->type;
764

765
		target_reset_examined(target);
766
767
768
769
		if (target->type->examine == NULL)
		{
			target->type->examine = default_examine;
		}
oharboe's avatar
oharboe committed
770

771
		if ((retval = target->type->init_target(cmd_ctx, target)) != ERROR_OK)
772
		{
zwelch's avatar
zwelch committed
773
			LOG_ERROR("target '%s' init failed", target_get_name(target));
774
			return retval;
775
		}
oharboe's avatar
oharboe committed
776

David Brownell's avatar
David Brownell committed
777
778
779
780
		/**
		 * @todo MCR/MRC are ARM-specific; don't require them in
		 * all targets, or for ARMs without coprocessors.
		 */
781
782
783
		if (target->type->mcr == NULL)
		{
			target->type->mcr = default_mcr;
784
785
786
787
788
789
790
791
		} else
		{
			/* FIX! multiple targets will generally register global commands
			 * multiple times. Only register this one if *one* of the
			 * targets need the command. Hmm... make it a command on the
			 * Jim Tcl target object?
			 */
			register_jim(cmd_ctx, "mcr", jim_mcrmrc, "write coprocessor <cpnum> <op1> <op2> <CRn> <CRm> <value>");
792
793
794
795
796
		}

		if (target->type->mrc == NULL)
		{
			target->type->mrc = default_mrc;
797
798
799
		} else
		{
			register_jim(cmd_ctx, "mrc", jim_mcrmrc, "read coprocessor <cpnum> <op1> <op2> <CRn> <CRm>");
800
801
802
		}


David Brownell's avatar
David Brownell committed
803
804
805
806
807
808
		/**
		 * @todo get rid of those *memory_imp() methods, now that all
		 * callers are using target_*_memory() accessors ... and make
		 * sure the "physical" paths handle the same issues.
		 */

809
810
811
812
813
814
815
816
817
818
819
820
		/* a non-invasive way(in terms of patches) to add some code that
		 * runs before the type->write/read_memory implementation
		 */
		target->type->write_memory_imp = target->type->write_memory;
		target->type->write_memory = target_write_memory_imp;
		target->type->read_memory_imp = target->type->read_memory;
		target->type->read_memory = target_read_memory_imp;
		target->type->soft_reset_halt_imp = target->type->soft_reset_halt;
		target->type->soft_reset_halt = target_soft_reset_halt_imp;
		target->type->run_algorithm_imp = target->type->run_algorithm;
		target->type->run_algorithm = target_run_algorithm_imp;

821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
		/* Sanity-check MMU support ... stub in what we must, to help
		 * implement it in stages, but warn if we need to do so.
		 */
		if (type->mmu) {
			if (type->write_phys_memory == NULL) {
				LOG_ERROR("type '%s' is missing %s",
						type->name,
						"write_phys_memory");
				type->write_phys_memory = err_write_phys_memory;
			}
			if (type->read_phys_memory == NULL) {
				LOG_ERROR("type '%s' is missing %s",
						type->name,
						"read_phys_memory");
				type->read_phys_memory = err_read_phys_memory;
			}
			if (type->virt2phys == NULL) {
				LOG_ERROR("type '%s' is missing %s",
						type->name,
						"virt2phys");
				type->virt2phys = identity_virt2phys;
			}

		/* Make sure no-MMU targets all behave the same:  make no
		 * distinction between physical and virtual addresses, and
		 * ensure that virt2phys() is always an identity mapping.
		 */
		} else {
			if (type->write_phys_memory
					|| type->read_phys_memory
					|| type->virt2phys)
				LOG_WARNING("type '%s' has broken MMU hooks",
						type->name);

			type->mmu = no_mmu;
			type->write_phys_memory = type->write_memory;
			type->read_phys_memory = type->read_memory;
			type->virt2phys = identity_virt2phys;
859
860
		}
	}
oharboe's avatar
oharboe committed
861

862
	if (all_targets)
863
	{
zwelch's avatar
zwelch committed
864
		if ((retval = target_register_user_commands(cmd_ctx)) != ERROR_OK)
865
			return retval;
zwelch's avatar
zwelch committed
866
		if ((retval = target_register_timer_callback(handle_target, 100, 1, NULL)) != ERROR_OK)
867
			return retval;
868
	}
oharboe's avatar
oharboe committed
869

870
871
872
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
873
int target_register_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv)
874
{
875
	struct target_event_callback **callbacks_p = &target_event_callbacks;
oharboe's avatar
oharboe committed
876

877
878
879
880
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
881

882
883
884
885
886
887
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
888

889
	(*callbacks_p) = malloc(sizeof(struct target_event_callback));
890
891
892
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
893

894
895
896
897
898
	return ERROR_OK;
}

int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
{
899
	struct target_timer_callback **callbacks_p = &target_timer_callbacks;
900
	struct timeval now;
oharboe's avatar
oharboe committed
901

902
903
904
905
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
906

907
908
909
910
911
912
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
913

914
	(*callbacks_p) = malloc(sizeof(struct target_timer_callback));
915
916
917
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->periodic = periodic;
	(*callbacks_p)->time_ms = time_ms;
oharboe's avatar
oharboe committed
918

919
920
921
922
923
924
925
926
927
	gettimeofday(&now, NULL);
	(*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
	time_ms -= (time_ms % 1000);
	(*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000);
	if ((*callbacks_p)->when.tv_usec > 1000000)
	{
		(*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;
		(*callbacks_p)->when.tv_sec += 1;
	}
oharboe's avatar
oharboe committed
928

929
930
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
931

932
933
934
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
935
int target_unregister_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv)
936
{
937
938
	struct target_event_callback **p = &target_event_callbacks;
	struct target_event_callback *c = target_event_callbacks;
oharboe's avatar
oharboe committed
939

940
941
942
943
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
944

945
946
	while (c)
	{
947
		struct target_event_callback *next = c->next;
948
949
950
951
952
953
954
955
956
957
		if ((c->callback == callback) && (c->priv == priv))
		{
			*p = next;
			free(c);
			return ERROR_OK;
		}
		else
			p = &(c->next);
		c = next;
	}
oharboe's avatar
oharboe committed
958

959
960
961
962
963
	return ERROR_OK;
}

int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
{
964
965
	struct target_timer_callback **p = &target_timer_callbacks;
	struct target_timer_callback *c = target_timer_callbacks;
oharboe's avatar
oharboe committed
966

967
968
969
970
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
971

972
973
	while (c)
	{
974
		struct target_timer_callback *next = c->next;
975
976
977
978
979
980
981
982
983
984
		if ((c->callback == callback) && (c->priv == priv))
		{
			*p = next;
			free(c);
			return ERROR_OK;
		}
		else
			p = &(c->next);
		c = next;
	}
oharboe's avatar
oharboe committed
985

986
987
988
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
989
int target_call_event_callbacks(struct target *target, enum target_event event)
990
{
991
992
	struct target_event_callback *callback = target_event_callbacks;
	struct target_event_callback *next_callback;
oharboe's avatar
oharboe committed
993

994
995
996
	if (event == TARGET_EVENT_HALTED)
	{
		/* execute early halted first */
997
		target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
998
999
	}

1000
	LOG_DEBUG("target event %i (%s)",
For faster browsing, not all history is shown. View entire blame