target.c 127 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
Øyvind Harboe's avatar
Øyvind Harboe committed
5
 *   Copyright (C) 2007-2010 Ø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
 *   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

36
37
#include <helper/time_support.h>
#include <jtag/jtag.h>
38
#include <flash/nor/core.h>
39

40
#include "target.h"
41
#include "target_type.h"
42
#include "target_request.h"
43
#include "breakpoints.h"
44
45
46
#include "register.h"
#include "trace.h"
#include "image.h"
47
48


49
50
51
52
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);
53
static int target_register_user_commands(struct command_context *cmd_ctx);
54

55
/* targets */
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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;
71
extern struct target_type dsp563xx_target;
Zachary T Welch's avatar
Zachary T Welch committed
72
extern struct target_type testee_target;
73

74
static struct target_type *target_types[] =
75
76
77
78
79
80
81
{
	&arm7tdmi_target,
	&arm9tdmi_target,
	&arm920t_target,
	&arm720t_target,
	&arm966e_target,
	&arm926ejs_target,
82
	&fa526_target,
83
	&feroceon_target,
84
	&dragonite_target,
85
86
	&xscale_target,
	&cortexm3_target,
87
	&cortexa8_target,
oharboe's avatar
oharboe committed
88
	&arm11_target,
ntfreak's avatar
ntfreak committed
89
	&mips_m4k_target,
90
	&avr_target,
91
	&dsp563xx_target,
Zachary T Welch's avatar
Zachary T Welch committed
92
	&testee_target,
93
94
95
	NULL,
};

Zachary T Welch's avatar
Zachary T Welch committed
96
struct target *all_targets = NULL;
97
98
static struct target_event_callback *target_event_callbacks = NULL;
static struct target_timer_callback *target_timer_callbacks = NULL;
99

100
static const Jim_Nvp nvp_assert[] = {
101
102
103
104
105
106
107
	{ .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 }
108
109
};

110
static const Jim_Nvp nvp_error_target[] = {
111
112
113
114
115
116
117
118
119
120
121
122
123
124
	{ .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 }
};

125
static const char *target_strerror_safe(int err)
126
127
128
{
	const Jim_Nvp *n;

129
	n = Jim_Nvp_value2name_simple(nvp_error_target, err);
zwelch's avatar
zwelch committed
130
	if (n->name == NULL) {
131
132
133
134
135
136
		return "unknown";
	} else {
		return n->name;
	}
}

137
static const Jim_Nvp nvp_target_event[] = {
138
139
	{ .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" },
	{ .value = TARGET_EVENT_OLD_pre_resume         , .name = "old-pre_resume" },
140

141
	{ .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" },
142
143
144
145
146
	{ .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" },

147
148
149
	{ .name = "gdb-start", .value = TARGET_EVENT_GDB_START },
	{ .name = "gdb-end", .value = TARGET_EVENT_GDB_END },

150
	/* historical name */
151

152
	{ .value = TARGET_EVENT_RESET_START, .name = "reset-start" },
153
154

	{ .value = TARGET_EVENT_RESET_ASSERT_PRE,    .name = "reset-assert-pre" },
155
	{ .value = TARGET_EVENT_RESET_ASSERT,        .name = "reset-assert" },
156
157
158
159
160
161
162
	{ .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" },
163
164
	{ .value = TARGET_EVENT_RESET_INIT,          .name = "reset-init" },
	{ .value = TARGET_EVENT_RESET_END,           .name = "reset-end" },
165

166
	{ .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" },
167
	{ .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" },
168

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
	{ .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 }
186
187
};

188
static const Jim_Nvp nvp_target_state[] = {
189
190
191
192
193
194
	{ .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 },
195
196
};

197
static const Jim_Nvp nvp_target_debug_reason [] = {
198
199
200
201
202
203
204
205
206
207
	{ .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 },
};

208
static const Jim_Nvp nvp_target_endian[] = {
209
210
211
	{ .name = "big",    .value = TARGET_BIG_ENDIAN },
	{ .name = "little", .value = TARGET_LITTLE_ENDIAN },
	{ .name = "be",     .value = TARGET_BIG_ENDIAN },
212
	{ .name = "le",     .value = TARGET_LITTLE_ENDIAN },
213
214
215
	{ .name = NULL,     .value = -1 },
};

216
static const Jim_Nvp nvp_reset_modes[] = {
217
218
219
220
221
222
223
	{ .name = "unknown", .value = RESET_UNKNOWN },
	{ .name = "run"    , .value = RESET_RUN },
	{ .name = "halt"   , .value = RESET_HALT },
	{ .name = "init"   , .value = RESET_INIT },
	{ .name = NULL     , .value = -1 },
};

224
225
226
227
228
229
230
231
232
233
234
235
236
const char *debug_reason_name(struct target *t)
{
	const char *cp;

	cp = Jim_Nvp_value2name_simple(nvp_target_debug_reason,
			t->debug_reason)->name;
	if (!cp) {
		LOG_ERROR("Invalid debug reason: %d", (int)(t->debug_reason));
		cp = "(*BUG*unknown*BUG*)";
	}
	return cp;
}

237
const char *
Zachary T Welch's avatar
Zachary T Welch committed
238
target_state_name( struct target *t )
239
240
241
242
243
244
245
246
247
248
{
	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;
}

249
/* determine the number of the new target */
250
static int new_target_number(void)
251
{
Zachary T Welch's avatar
Zachary T Welch committed
252
	struct target *t;
253
254
255
256
257
	int x;

	/* number is 0 based */
	x = -1;
	t = all_targets;
zwelch's avatar
zwelch committed
258
259
	while (t) {
		if (x < t->target_number) {
260
261
262
263
			x = t->target_number;
		}
		t = t->next;
	}
zwelch's avatar
zwelch committed
264
	return x + 1;
265
266
}

267
/* read a uint32_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
268
uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
269
270
271
272
273
274
275
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		return le_to_h_u32(buffer);
	else
		return be_to_h_u32(buffer);
}

zwelch's avatar
zwelch committed
276
/* read a uint16_t from a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
277
uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer)
278
279
280
281
282
283
284
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		return le_to_h_u16(buffer);
	else
		return be_to_h_u16(buffer);
}

285
/* read a uint8_t from a buffer in target memory endianness */
286
static uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer)
287
288
289
290
{
	return *buffer & 0x0ff;
}

291
/* write a uint32_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
292
void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value)
293
294
295
296
297
298
299
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		h_u32_to_le(buffer, value);
	else
		h_u32_to_be(buffer, value);
}

zwelch's avatar
zwelch committed
300
/* write a uint16_t to a buffer in target memory endianness */
Zachary T Welch's avatar
Zachary T Welch committed
301
void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value)
302
303
304
305
306
307
308
{
	if (target->endianness == TARGET_LITTLE_ENDIAN)
		h_u16_to_le(buffer, value);
	else
		h_u16_to_be(buffer, value);
}

309
/* write a uint8_t to a buffer in target memory endianness */
310
static void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value)
311
312
313
314
{
	*buffer = value;
}

315
/* return a pointer to a configured target; id is name or number */
Zachary T Welch's avatar
Zachary T Welch committed
316
struct target *get_target(const char *id)
317
{
Zachary T Welch's avatar
Zachary T Welch committed
318
	struct target *target;
319
320
321
322
323
324
325
326
327

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

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

330
	/* no match, try as number */
331
332
	unsigned num;
	if (parse_uint(id, &num) != ERROR_OK)
333
334
335
		return NULL;

	for (target = all_targets; target; target = target->next) {
336
337
338
		if (target->target_number == (int)num) {
			LOG_WARNING("use '%s' as target identifier, not '%u'",
					target->cmd_name, num);
339
			return target;
340
		}
341
342
343
344
345
	}

	return NULL;
}

346
/* returns a pointer to the n-th configured target */
Zachary T Welch's avatar
Zachary T Welch committed
347
static struct target *get_target_by_num(int num)
348
{
Zachary T Welch's avatar
Zachary T Welch committed
349
	struct target *target = all_targets;
350

zwelch's avatar
zwelch committed
351
352
	while (target) {
		if (target->target_number == num) {
353
			return target;
354
		}
355
356
357
358
359
360
		target = target->next;
	}

	return NULL;
}

361
struct target* get_current_target(struct command_context *cmd_ctx)
362
{
Zachary T Welch's avatar
Zachary T Welch committed
363
	struct target *target = get_target_by_num(cmd_ctx->current_target);
oharboe's avatar
oharboe committed
364

365
366
	if (target == NULL)
	{
367
		LOG_ERROR("BUG: current_target out of bounds");
368
369
370
		exit(-1);
	}

oharboe's avatar
oharboe committed
371
	return target;
372
373
}

Zachary T Welch's avatar
Zachary T Welch committed
374
int target_poll(struct target *target)
375
{
376
377
	int retval;

378
	/* We can't poll until after examine */
379
	if (!target_was_examined(target))
380
381
382
383
	{
		/* Fail silently lest we pollute the log */
		return ERROR_FAIL;
	}
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406

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

Zachary T Welch's avatar
Zachary T Welch committed
409
int target_halt(struct target *target)
410
{
411
	int retval;
412
	/* We can't poll until after examine */
413
	if (!target_was_examined(target))
414
415
416
417
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
418
419
420
421
422
423
424
425
426

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

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

	return ERROR_OK;
427
428
}

David Brownell's avatar
David Brownell committed
429
430
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
/**
 * Make the target (re)start executing using its saved execution
 * context (possibly with some modifications).
 *
 * @param target Which target should start executing.
 * @param current True to use the target's saved program counter instead
 *	of the address parameter
 * @param address Optionally used as the program counter.
 * @param handle_breakpoints True iff breakpoints at the resumption PC
 *	should be skipped.  (For example, maybe execution was stopped by
 *	such a breakpoint, in which case it would be counterprodutive to
 *	let it re-trigger.
 * @param debug_execution False if all working areas allocated by OpenOCD
 *	should be released and/or restored to their original contents.
 *	(This would for example be true to run some downloaded "helper"
 *	algorithm code, which resides in one such working buffer and uses
 *	another for data storage.)
 *
 * @todo Resolve the ambiguity about what the "debug_execution" flag
 * signifies.  For example, Target implementations don't agree on how
 * it relates to invalidation of the register cache, or to whether
 * breakpoints and watchpoints should be enabled.  (It would seem wrong
 * to enable breakpoints when running downloaded "helper" algorithms
 * (debug_execution true), since the breakpoints would be set to match
 * target firmware being debugged, not the helper algorithm.... and
 * enabling them could cause such helpers to malfunction (for example,
 * by overwriting data with a breakpoint instruction.  On the other
 * hand the infrastructure for running such helpers might use this
 * procedure but rely on hardware breakpoint to detect termination.)
 */
Zachary T Welch's avatar
Zachary T Welch committed
459
int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
460
{
461
	int retval;
oharboe's avatar
oharboe committed
462

463
	/* We can't poll until after examine */
464
	if (!target_was_examined(target))
465
466
467
468
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
oharboe's avatar
oharboe committed
469

David Brownell's avatar
David Brownell committed
470
471
472
	/* 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.
oharboe's avatar
oharboe committed
473
	 */
474
475
	if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK)
		return retval;
oharboe's avatar
oharboe committed
476

477
	return retval;
478
479
}

480
static int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode)
481
482
{
	char buf[100];
483
	int retval;
484
	Jim_Nvp *n;
485
	n = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode);
zwelch's avatar
zwelch committed
486
	if (n->name == NULL) {
487
488
489
490
		LOG_ERROR("invalid reset mode");
		return ERROR_FAIL;
	}

491
492
493
494
	/* 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.
	 */
495
496
497
	bool save_poll = jtag_poll_get_enabled();

	jtag_poll_set_enabled(false);
498

499
	sprintf(buf, "ocd_process_reset %s", n->name);
500
	retval = Jim_Eval(cmd_ctx->interp, buf);
501

502
	jtag_poll_set_enabled(save_poll);
503

zwelch's avatar
zwelch committed
504
	if (retval != JIM_OK) {
505
		Jim_PrintErrorMessage(cmd_ctx->interp);
506
507
		return ERROR_FAIL;
	}
508
509

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

Øyvind Harboe's avatar
Øyvind Harboe committed
512
513
514
515
516
	struct target *target;
	for (target = all_targets; target; target = target->next) {
		target->type->check_reset(target);
	}

517
	return retval;
518
519
}

Zachary T Welch's avatar
Zachary T Welch committed
520
static int identity_virt2phys(struct target *target,
David Brownell's avatar
David Brownell committed
521
		uint32_t virtual, uint32_t *physical)
522
523
524
525
526
{
	*physical = virtual;
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
527
static int no_mmu(struct target *target, int *enabled)
528
{
529
	*enabled = 0;
530
531
532
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
533
static int default_examine(struct target *target)
534
{
535
	target_set_examined(target);
536
537
538
	return ERROR_OK;
}

Øyvind Harboe's avatar
Øyvind Harboe committed
539
540
541
542
543
544
/* no check by default */
static int default_check_reset(struct target *target)
{
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
545
int target_examine_one(struct target *target)
zwelch's avatar
zwelch committed
546
547
548
549
{
	return target->type->examine(target);
}

zwelch's avatar
zwelch committed
550
551
static int jtag_enable_callback(enum jtag_event event, void *priv)
{
Zachary T Welch's avatar
Zachary T Welch committed
552
	struct target *target = priv;
zwelch's avatar
zwelch committed
553
554
555
556
557
558
559
560
561

	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
562
/* Targets that correctly implement init + examine, i.e.
563
 * no communication with target during init:
oharboe's avatar
oharboe committed
564
565
 *
 * XScale
566
 */
ntfreak's avatar
ntfreak committed
567
int target_examine(void)
568
569
{
	int retval = ERROR_OK;
Zachary T Welch's avatar
Zachary T Welch committed
570
	struct target *target;
zwelch's avatar
zwelch committed
571
572

	for (target = all_targets; target; target = target->next)
573
	{
zwelch's avatar
zwelch committed
574
575
576
577
		/* defer examination, but don't skip it */
		if (!target->tap->enabled) {
			jtag_register_event_callback(jtag_enable_callback,
					target);
zwelch's avatar
zwelch committed
578
			continue;
zwelch's avatar
zwelch committed
579
		}
zwelch's avatar
zwelch committed
580
		if ((retval = target_examine_one(target)) != ERROR_OK)
581
582
583
584
			return retval;
	}
	return retval;
}
585
const char *target_type_name(struct target *target)
zwelch's avatar
zwelch committed
586
587
588
{
	return target->type->name;
}
589

Zachary T Welch's avatar
Zachary T Welch committed
590
static int target_write_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
591
{
592
	if (!target_was_examined(target))
593
594
595
596
597
598
599
	{
		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
600
static int target_read_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
601
{
602
	if (!target_was_examined(target))
603
604
605
606
607
608
609
	{
		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
610
static int target_soft_reset_halt_imp(struct target *target)
611
{
612
	if (!target_was_examined(target))
613
614
615
616
	{
		LOG_ERROR("Target not examined yet");
		return ERROR_FAIL;
	}
617
618
	if (!target->type->soft_reset_halt_imp) {
		LOG_ERROR("Target %s does not support soft_reset_halt",
619
				target_name(target));
620
621
		return ERROR_FAIL;
	}
622
623
624
	return target->type->soft_reset_halt_imp(target);
}

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
/**
 * Downloads a target-specific native code algorithm to the target,
 * and executes it.  * Note that some targets may need to set up, enable,
 * and tear down a breakpoint (hard or * soft) to detect algorithm
 * termination, while others may support  lower overhead schemes where
 * soft breakpoints embedded in the algorithm automatically terminate the
 * algorithm.
 *
 * @param target used to run the algorithm
 * @param arch_info target-specific description of the algorithm.
 */
int target_run_algorithm(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)
641
{
642
643
	int retval = ERROR_FAIL;

644
	if (!target_was_examined(target))
645
646
	{
		LOG_ERROR("Target not examined yet");
647
		goto done;
648
	}
David Brownell's avatar
David Brownell committed
649
	if (!target->type->run_algorithm) {
650
651
652
653
654
		LOG_ERROR("Target type '%s' does not support %s",
				target_type_name(target), __func__);
		goto done;
	}

655
	target->running_alg = true;
656
657
658
659
	retval = target->type->run_algorithm(target,
			num_mem_params, mem_params,
			num_reg_params, reg_param,
			entry_point, exit_point, timeout_ms, arch_info);
660
	target->running_alg = false;
661
662
663

done:
	return retval;
664
}
665

666

Zachary T Welch's avatar
Zachary T Welch committed
667
int target_read_memory(struct target *target,
668
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
669
670
671
672
{
	return target->type->read_memory(target, address, size, count, buffer);
}

673
static int target_read_phys_memory(struct target *target,
674
675
676
677
678
		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
679
int target_write_memory(struct target *target,
680
		uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
681
682
683
{
	return target->type->write_memory(target, address, size, count, buffer);
}
684

685
static int target_write_phys_memory(struct target *target,
686
687
688
689
690
		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
691
int target_bulk_write_memory(struct target *target,
692
		uint32_t address, uint32_t count, uint8_t *buffer)
zwelch's avatar
zwelch committed
693
694
695
696
{
	return target->type->bulk_write_memory(target, address, count, buffer);
}

Zachary T Welch's avatar
Zachary T Welch committed
697
int target_add_breakpoint(struct target *target,
698
		struct breakpoint *breakpoint)
699
{
700
701
702
703
	if (target->state != TARGET_HALTED) {
		LOG_WARNING("target %s is not halted", target->cmd_name);
		return ERROR_TARGET_NOT_HALTED;
	}
704
705
	return target->type->add_breakpoint(target, breakpoint);
}
Zachary T Welch's avatar
Zachary T Welch committed
706
int target_remove_breakpoint(struct target *target,
707
		struct breakpoint *breakpoint)
708
709
710
711
{
	return target->type->remove_breakpoint(target, breakpoint);
}

Zachary T Welch's avatar
Zachary T Welch committed
712
int target_add_watchpoint(struct target *target,
713
		struct watchpoint *watchpoint)
714
{
715
716
717
718
	if (target->state != TARGET_HALTED) {
		LOG_WARNING("target %s is not halted", target->cmd_name);
		return ERROR_TARGET_NOT_HALTED;
	}
719
720
	return target->type->add_watchpoint(target, watchpoint);
}
Zachary T Welch's avatar
Zachary T Welch committed
721
int target_remove_watchpoint(struct target *target,
722
		struct watchpoint *watchpoint)
723
724
725
{
	return target->type->remove_watchpoint(target, watchpoint);
}
zwelch's avatar
zwelch committed
726

Zachary T Welch's avatar
Zachary T Welch committed
727
int target_get_gdb_reg_list(struct target *target,
Zachary T Welch's avatar
Zachary T Welch committed
728
		struct reg **reg_list[], int *reg_list_size)
zwelch's avatar
zwelch committed
729
730
731
{
	return target->type->get_gdb_reg_list(target, reg_list, reg_list_size);
}
Zachary T Welch's avatar
Zachary T Welch committed
732
int target_step(struct target *target,
733
		int current, uint32_t address, int handle_breakpoints)
zwelch's avatar
zwelch committed
734
735
736
737
{
	return target->type->step(target, current, address, handle_breakpoints);
}

zwelch's avatar
zwelch committed
738

739
740
741
742
743
/**
 * Reset the @c examined flag for the given target.
 * Pure paranoia -- targets are zeroed on allocation.
 */
static void target_reset_examined(struct target *target)
744
{
745
	target->examined = false;
746
747
}

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

756
static int
Zachary T Welch's avatar
Zachary T Welch committed
757
err_write_phys_memory(struct target *target, uint32_t address,
758
		uint32_t size, uint32_t count, uint8_t *buffer)
759
{
760
	LOG_ERROR("Not implemented: %s", __func__);
761
	return ERROR_FAIL;
762
763
}

764
765
static int handle_target(void *priv);

766
767
static int target_init_one(struct command_context *cmd_ctx,
		struct target *target)
768
{
769
	target_reset_examined(target);
oharboe's avatar
oharboe committed
770

771
772
773
	struct target_type *type = target->type;
	if (type->examine == NULL)
		type->examine = default_examine;
774

Øyvind Harboe's avatar
Øyvind Harboe committed
775
776
777
	if (type->check_reset== NULL)
		type->check_reset = default_check_reset;

778
779
780
781
782
783
	int retval = type->init_target(cmd_ctx, target);
	if (ERROR_OK != retval)
	{
		LOG_ERROR("target '%s' init failed", target_name(target));
		return retval;
	}
oharboe's avatar
oharboe committed
784

785
786
787
788
789
790
791
792
793
794
	/**
	 * @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.
	 */
	/* a non-invasive way(in terms of patches) to add some code that
	 * runs before the type->write/read_memory implementation
	 */
	type->write_memory_imp = target->type->write_memory;
	type->write_memory = target_write_memory_imp;
oharboe's avatar
oharboe committed
795

796
797
	type->read_memory_imp = target->type->read_memory;
	type->read_memory = target_read_memory_imp;
798

799
800
	type->soft_reset_halt_imp = target->type->soft_reset_halt;
	type->soft_reset_halt = target_soft_reset_halt_imp;
David Brownell's avatar
David Brownell committed
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
	/* 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 write_phys_memory",
					type->name);
			type->write_phys_memory = err_write_phys_memory;
		}
		if (type->read_phys_memory == NULL)
		{
			LOG_ERROR("type '%s' is missing read_phys_memory",
					type->name);
			type->read_phys_memory = err_read_phys_memory;
		}
		if (type->virt2phys == NULL)
		{
			LOG_ERROR("type '%s' is missing virt2phys", type->name);
			type->virt2phys = identity_virt2phys;
		}
	}
	else
	{
827
828
829
830
		/* 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.
		 */
831
832
833
834
		if (type->write_phys_memory || type->read_phys_memory
				|| type->virt2phys)
		{
			LOG_WARNING("type '%s' has bad MMU hooks", type->name);
835
		}
836
837
838
839
840

		type->mmu = no_mmu;
		type->write_phys_memory = type->write_memory;
		type->read_phys_memory = type->read_memory;
		type->virt2phys = identity_virt2phys;
841
	}
842
843
	return ERROR_OK;
}
oharboe's avatar
oharboe committed
844

845
static int target_init(struct command_context *cmd_ctx)
846
847
848
849
850
{
	struct target *target;
	int retval;

	for (target = all_targets; target; target = target->next)
851
	{
852
853
		retval = target_init_one(cmd_ctx, target);
		if (ERROR_OK != retval)
854
			return retval;
855
	}
oharboe's avatar
oharboe committed
856

857
858
859
860
861
862
863
864
865
866
867
868
	if (!all_targets)
		return ERROR_OK;

	retval = target_register_user_commands(cmd_ctx);
	if (ERROR_OK != retval)
		return retval;

	retval = target_register_timer_callback(&handle_target,
			100, 1, cmd_ctx->interp);
	if (ERROR_OK != retval)
		return retval;

869
870
871
	return ERROR_OK;
}

872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
COMMAND_HANDLER(handle_target_init_command)
{
	if (CMD_ARGC != 0)
		return ERROR_COMMAND_SYNTAX_ERROR;

	static bool target_initialized = false;
	if (target_initialized)
	{
		LOG_INFO("'target init' has already been called");
		return ERROR_OK;
	}
	target_initialized = true;

	LOG_DEBUG("Initializing targets...");
	return target_init(CMD_CTX);
}

Zachary T Welch's avatar
Zachary T Welch committed
889
int target_register_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv)
890
{
891
	struct target_event_callback **callbacks_p = &target_event_callbacks;
oharboe's avatar
oharboe committed
892

893
894
895
896
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
897

898
899
900
901
902
903
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
904

905
	(*callbacks_p) = malloc(sizeof(struct target_event_callback));
906
907
908
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
909

910
911
912
913
914
	return ERROR_OK;
}

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

918
919
920
921
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
922

923
924
925
926
927
928
	if (*callbacks_p)
	{
		while ((*callbacks_p)->next)
			callbacks_p = &((*callbacks_p)->next);
		callbacks_p = &((*callbacks_p)->next);
	}
oharboe's avatar
oharboe committed
929

930
	(*callbacks_p) = malloc(sizeof(struct target_timer_callback));
931
932
933
	(*callbacks_p)->callback = callback;
	(*callbacks_p)->periodic = periodic;
	(*callbacks_p)->time_ms = time_ms;
oharboe's avatar
oharboe committed
934

935
936
937
938
939
940
941
942
943
	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
944

945
946
	(*callbacks_p)->priv = priv;
	(*callbacks_p)->next = NULL;
oharboe's avatar
oharboe committed
947

948
949
950
	return ERROR_OK;
}

Zachary T Welch's avatar
Zachary T Welch committed
951
int target_unregister_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv)
952
{
953
954
	struct target_event_callback **p = &target_event_callbacks;
	struct target_event_callback *c = target_event_callbacks;
oharboe's avatar
oharboe committed
955

956
957
958
959
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
960

961
962
	while (c)
	{
963
		struct target_event_callback *next = c->next;
964
965
966
967
968
969
970
971
972
973
		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
974

975
976
977
	return ERROR_OK;
}

978
static int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
979
{
980
981
	struct target_timer_callback **p = &target_timer_callbacks;
	struct target_timer_callback *c = target_timer_callbacks;
oharboe's avatar
oharboe committed
982

983
984
985
986
	if (callback == NULL)
	{
		return ERROR_INVALID_ARGUMENTS;
	}
oharboe's avatar
oharboe committed
987

988
989
	while (c)
	{
990
		struct target_timer_callback *next = c->next;
991
992
993
994
995
996
997
998
999
1000
		if ((c->callback == callback) && (c->priv == priv))
		{
			*p = next;
			free(c);
			return ERROR_OK;
		}
		else
			p = &(c->next);
		c = next;
	}
For faster browsing, not all history is shown. View entire blame