arm7_9_common.c 93.6 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007,2008 yvind Harboe                                 *
6
7
 *   oyvind.harboe@zylin.com                                               *
 *                                                                         *
8
9
10
 *   Copyright (C) 2008 by Spencer Oliver                                  *
 *   spen@spen-soft.co.uk                                                  *
 *                                                                         *
11
12
13
 *   Copyright (C) 2008 by Hongtao Zheng                                   *
 *   hontor@126.com                                                        *
 *                                                                         *
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 *   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.             *
 ***************************************************************************/
29
#ifdef HAVE_CONFIG_H
30
#include "config.h"
31
32
#endif

33
#include "embeddedice.h"
34
#include "target_request.h"
35
#include "arm7_9_common.h"
oharboe's avatar
oharboe committed
36
#include "time_support.h"
37
#include "arm_simulator.h"
38
39
40
41
42
43
44
45
46
47
48


int arm7_9_debug_entry(target_t *target);
int arm7_9_enable_sw_bkpts(struct target_s *target);

/* command handler forward declarations */
int handle_arm7_9_write_xpsr_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_write_xpsr_im8_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_read_core_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_write_core_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_dbgrq_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
49
int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
50
int handle_arm7_9_dcc_downloads_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
51
int handle_arm7_9_etm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
52

53
54
55
56
57
58
/**
 * Clear watchpoints for an ARM7/9 target.
 *
 * @param arm7_9 Pointer to the common struct for an ARM7/9 target
 * @return JTAG error status after executing queue
 */
59
60
61
62
63
static int arm7_9_clear_watchpoints(arm7_9_common_t *arm7_9)
{
	embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
	embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
	arm7_9->sw_breakpoints_added = 0;
64
	arm7_9->wp0_used = 0;
65
66
	arm7_9->wp1_used = arm7_9->wp1_used_default;
	arm7_9->wp_available = arm7_9->wp_available_max;
67

68
69
70
	return jtag_execute_queue();
}

71
72
73
74
75
76
77
/**
 * Assign a watchpoint to one of the two available hardware comparators in an
 * ARM7 or ARM9 target.
 *
 * @param arm7_9 Pointer to the common struct for an ARM7/9 target
 * @param breakpoint Pointer to the breakpoint to be used as a watchpoint
 */
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
static void arm7_9_assign_wp(arm7_9_common_t *arm7_9, breakpoint_t *breakpoint)
{
	if (!arm7_9->wp0_used)
	{
		arm7_9->wp0_used = 1;
		breakpoint->set = 1;
		arm7_9->wp_available--;
	}
	else if (!arm7_9->wp1_used)
	{
		arm7_9->wp1_used = 1;
		breakpoint->set = 2;
		arm7_9->wp_available--;
	}
	else
	{
		LOG_ERROR("BUG: no hardware comparator available");
	}
}

98
99
100
101
102
103
104
/**
 * Setup an ARM7/9 target's embedded ICE registers for software breakpoints.
 *
 * @param arm7_9 Pointer to common struct for ARM7/9 targets
 * @return Error codes if there is a problem finding a watchpoint or the result
 *         of executing the JTAG queue
 */
105
106
107
static int arm7_9_set_software_breakpoints(arm7_9_common_t *arm7_9)
{
	if (arm7_9->sw_breakpoints_added)
108
	{
109
110
111
112
113
114
115
116
		return ERROR_OK;
	}
	if (arm7_9->wp_available < 1)
	{
		LOG_WARNING("can't enable sw breakpoints with no watchpoint unit available");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
	arm7_9->wp_available--;
oharboe's avatar
oharboe committed
117

118
119
120
121
122
123
124
125
126
127
128
129
130
131
	/* pick a breakpoint unit */
	if (!arm7_9->wp0_used)
	{
		arm7_9->sw_breakpoints_added=1;
		arm7_9->wp0_used = 3;
	} else if (!arm7_9->wp1_used)
	{
		arm7_9->sw_breakpoints_added=2;
		arm7_9->wp1_used = 3;
	}
	else
	{
		LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1");
		return ERROR_FAIL;
132
	}
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
	if (arm7_9->sw_breakpoints_added==1)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE], arm7_9->arm_bkpt);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0x0);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffffu);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
	}
	else if (arm7_9->sw_breakpoints_added==2)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE], arm7_9->arm_bkpt);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0x0);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], 0xffffffffu);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
	}
	else
151
	{
152
153
		LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1");
		return ERROR_FAIL;
154
	}
155

156
	return jtag_execute_queue();
157
158
}

159
160
161
162
163
164
/**
 * Setup the common pieces for an ARM7/9 target after reset or on startup.
 *
 * @param target Pointer to an ARM7/9 target to setup
 * @return Result of clearing the watchpoints on the target
 */
165
int arm7_9_setup(target_t *target)
166
{
167
168
169
170
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;

	return arm7_9_clear_watchpoints(arm7_9);
171
172
}

173
174
175
176
177
178
179
180
181
182
183
184
/**
 * Retrieves the architecture information pointers for ARMv4/5 and ARM7/9
 * targets.  A return of ERROR_OK signifies that the target is a valid target
 * and that the pointers have been set properly.
 *
 * @param target Pointer to the target device to get the pointers from
 * @param armv4_5_p Pointer to be filled in with the common struct for ARMV4/5
 *                  targets
 * @param arm7_9_p Pointer to be filled in with the common struct for ARM7/9
 *                 targets
 * @return ERROR_OK if successful
 */
185
186
187
188
int arm7_9_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
189

190
191
192
193
	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
	{
		return -1;
	}
194

195
196
197
198
	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
	{
		return -1;
	}
199

200
201
	*armv4_5_p = armv4_5;
	*arm7_9_p = arm7_9;
202

203
204
205
	return ERROR_OK;
}

206
207
208
209
210
211
212
213
214
215
/**
 * Set either a hardware or software breakpoint on an ARM7/9 target.  The
 * breakpoint is set up even if it is already set.  Some actions, e.g. reset,
 * might have erased the values in Embedded ICE.
 *
 * @param target Pointer to the target device to set the breakpoints on
 * @param breakpoint Pointer to the breakpoint to be set
 * @return For hardware breakpoints, this is the result of executing the JTAG
 *         queue.  For software breakpoints, this will be the status of the
 *         required memory reads and writes
216
 */
217
218
219
220
int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
221
	int retval=ERROR_OK;
222

223
224
	if (target->state != TARGET_HALTED)
	{
225
		LOG_WARNING("target not halted");
226
227
		return ERROR_TARGET_NOT_HALTED;
	}
228

229
230
231
	if (breakpoint->type == BKPT_HARD)
	{
		/* either an ARM (4 byte) or Thumb (2 byte) breakpoint */
232
		uint32_t mask = (breakpoint->length == 4) ? 0x3u : 0x1u;
233
234
235
236
237
238
239

		/* reassign a hw breakpoint */
		if (breakpoint->set==0)
		{
			arm7_9_assign_wp(arm7_9, breakpoint);
		}

240
		if (breakpoint->set==1)
241
242
243
244
245
246
247
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], breakpoint->address);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffffu);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
		}
248
		else if (breakpoint->set==2)
249
250
251
252
253
254
255
256
257
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], breakpoint->address);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffffu);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
		}
		else
		{
258
			LOG_ERROR("BUG: no hardware comparator available");
259
260
			return ERROR_OK;
		}
261
262

		retval=jtag_execute_queue();
263
264
265
	}
	else if (breakpoint->type == BKPT_SOFT)
	{
zwelch's avatar
zwelch committed
266
		if ((retval=arm7_9_set_software_breakpoints(arm7_9)) != ERROR_OK)
267
			return retval;
oharboe's avatar
oharboe committed
268

269
270
271
		/* did we already set this breakpoint? */
		if (breakpoint->set)
			return ERROR_OK;
oharboe's avatar
oharboe committed
272

273
274
		if (breakpoint->length == 4)
		{
275
			uint32_t verify = 0xffffffff;
276
			/* keep the original instruction in target endianness */
zwelch's avatar
zwelch committed
277
			if ((retval = target_read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
278
279
280
			{
				return retval;
			}
drath's avatar
drath committed
281
			/* write the breakpoint instruction in target endianness (arm7_9->arm_bkpt is host endian) */
282
283
284
285
			if ((retval = target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt)) != ERROR_OK)
			{
				return retval;
			}
286

287
			if ((retval = target_read_u32(target, breakpoint->address, &verify)) != ERROR_OK)
288
289
290
			{
				return retval;
			}
ntfreak's avatar
ntfreak committed
291
292
			if (verify != arm7_9->arm_bkpt)
			{
duane's avatar
duane committed
293
				LOG_ERROR("Unable to set 32 bit software breakpoint at address %08" PRIx32 " - check that memory is read/writable", breakpoint->address);
ntfreak's avatar
ntfreak committed
294
295
				return ERROR_OK;
			}
296
297
298
		}
		else
		{
zwelch's avatar
zwelch committed
299
			uint16_t verify = 0xffff;
300
			/* keep the original instruction in target endianness */
zwelch's avatar
zwelch committed
301
			if ((retval = target_read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
302
303
304
			{
				return retval;
			}
drath's avatar
drath committed
305
			/* write the breakpoint instruction in target endianness (arm7_9->thumb_bkpt is host endian) */
306
307
308
309
			if ((retval = target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt)) != ERROR_OK)
			{
				return retval;
			}
310

311
			if ((retval = target_read_u16(target, breakpoint->address, &verify)) != ERROR_OK)
312
313
314
			{
				return retval;
			}
ntfreak's avatar
ntfreak committed
315
316
			if (verify != arm7_9->thumb_bkpt)
			{
duane's avatar
duane committed
317
				LOG_ERROR("Unable to set thumb software breakpoint at address %08" PRIx32 " - check that memory is read/writable", breakpoint->address);
ntfreak's avatar
ntfreak committed
318
319
				return ERROR_OK;
			}
320
321
322
323
		}
		breakpoint->set = 1;
	}

324
	return retval;
325
326
}

327
328
329
330
331
332
333
334
335
336
337
338
/**
 * Unsets an existing breakpoint on an ARM7/9 target.  If it is a hardware
 * breakpoint, the watchpoint used will be freed and the Embedded ICE registers
 * will be updated.  Otherwise, the software breakpoint will be restored to its
 * original instruction if it hasn't already been modified.
 *
 * @param target Pointer to ARM7/9 target to unset the breakpoint from
 * @param breakpoint Pointer to breakpoint to be unset
 * @return For hardware breakpoints, this is the result of executing the JTAG
 *         queue.  For software breakpoints, this will be the status of the
 *         required memory reads and writes
 */
339
340
int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
341
342
	int retval = ERROR_OK;

343
344
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
345

346
347
	if (!breakpoint->set)
	{
348
		LOG_WARNING("breakpoint not set");
349
350
		return ERROR_OK;
	}
351

352
353
354
355
356
357
	if (breakpoint->type == BKPT_HARD)
	{
		if (breakpoint->set == 1)
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
			arm7_9->wp0_used = 0;
358
			arm7_9->wp_available++;
359
360
361
362
363
		}
		else if (breakpoint->set == 2)
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
			arm7_9->wp1_used = 0;
364
			arm7_9->wp_available++;
365
		}
366
		retval = jtag_execute_queue();
367
368
369
370
		breakpoint->set = 0;
	}
	else
	{
371
		/* restore original instruction (kept in target endianness) */
372
373
		if (breakpoint->length == 4)
		{
374
			uint32_t current_instr;
375
			/* check that user program as not modified breakpoint instruction */
376
			if ((retval = target_read_memory(target, breakpoint->address, 4, 1, (uint8_t*)&current_instr)) != ERROR_OK)
377
378
379
			{
				return retval;
			}
380
			if (current_instr==arm7_9->arm_bkpt)
zwelch's avatar
zwelch committed
381
				if ((retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
382
383
384
				{
					return retval;
				}
385
386
387
		}
		else
		{
zwelch's avatar
zwelch committed
388
			uint16_t current_instr;
389
			/* check that user program as not modified breakpoint instruction */
390
			if ((retval = target_read_memory(target, breakpoint->address, 2, 1, (uint8_t*)&current_instr)) != ERROR_OK)
391
392
393
			{
				return retval;
			}
394
			if (current_instr==arm7_9->thumb_bkpt)
zwelch's avatar
zwelch committed
395
				if ((retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
396
397
398
				{
					return retval;
				}
399
400
401
402
		}
		breakpoint->set = 0;
	}

403
	return retval;
404
405
}

406
407
408
409
410
411
412
413
414
/**
 * Add a breakpoint to an ARM7/9 target.  This makes sure that there are no
 * dangling breakpoints and that the desired breakpoint can be added.
 *
 * @param target Pointer to the target ARM7/9 device to add a breakpoint to
 * @param breakpoint Pointer to the breakpoint to be added
 * @return An error status if there is a problem adding the breakpoint or the
 *         result of setting the breakpoint
 */
415
int arm7_9_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
416
417
418
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
419

420
421
	if (target->state != TARGET_HALTED)
	{
422
		LOG_WARNING("target not halted");
423
424
		return ERROR_TARGET_NOT_HALTED;
	}
oharboe's avatar
oharboe committed
425

426
	if (arm7_9->breakpoint_count==0)
427
	{
oharboe's avatar
oharboe committed
428
429
		/* make sure we don't have any dangling breakpoints. This is vital upon
		 * GDB connect/disconnect
430
		 */
oharboe's avatar
oharboe committed
431
		arm7_9_clear_watchpoints(arm7_9);
432
	}
433

434
	if ((breakpoint->type == BKPT_HARD) && (arm7_9->wp_available < 1))
435
	{
436
		LOG_INFO("no watchpoint unit available for hardware breakpoint");
437
438
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
439

440
	if ((breakpoint->length != 2) && (breakpoint->length != 4))
441
	{
442
		LOG_INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
443
444
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
445

446
	if (breakpoint->type == BKPT_HARD)
447
	{
448
		arm7_9_assign_wp(arm7_9, breakpoint);
449
	}
oharboe's avatar
oharboe committed
450

451
	arm7_9->breakpoint_count++;
oharboe's avatar
oharboe committed
452

453
	return arm7_9_set_breakpoint(target, breakpoint);
454
455
}

456
457
458
459
460
461
462
463
464
465
/**
 * Removes a breakpoint from an ARM7/9 target.  This will make sure there are no
 * dangling breakpoints and updates available watchpoints if it is a hardware
 * breakpoint.
 *
 * @param target Pointer to the target to have a breakpoint removed
 * @param breakpoint Pointer to the breakpoint to be removed
 * @return Error status if there was a problem unsetting the breakpoint or the
 *         watchpoints could not be cleared
 */
466
467
int arm7_9_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
468
	int retval = ERROR_OK;
469
470
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
471

zwelch's avatar
zwelch committed
472
	if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK)
473
474
475
	{
		return retval;
	}
476

477
478
	if (breakpoint->type == BKPT_HARD)
		arm7_9->wp_available++;
oharboe's avatar
oharboe committed
479

480
481
482
483
	arm7_9->breakpoint_count--;
	if (arm7_9->breakpoint_count==0)
	{
		/* make sure we don't have any dangling breakpoints */
zwelch's avatar
zwelch committed
484
		if ((retval = arm7_9_clear_watchpoints(arm7_9)) != ERROR_OK)
485
486
487
		{
			return retval;
		}
488
	}
489

490
491
492
	return ERROR_OK;
}

493
494
495
496
497
498
499
500
501
502
/**
 * Sets a watchpoint for an ARM7/9 target in one of the watchpoint units.  It is
 * considered a bug to call this function when there are no available watchpoint
 * units.
 *
 * @param target Pointer to an ARM7/9 target to set a watchpoint on
 * @param watchpoint Pointer to the watchpoint to be set
 * @return Error status if watchpoint set fails or the result of executing the
 *         JTAG queue
 */
503
504
int arm7_9_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
505
	int retval = ERROR_OK;
506
507
508
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	int rw_mask = 1;
509
	uint32_t mask;
510

511
	mask = watchpoint->length - 1;
512

513
514
	if (target->state != TARGET_HALTED)
	{
515
		LOG_WARNING("target not halted");
516
517
		return ERROR_TARGET_NOT_HALTED;
	}
518

519
520
521
522
	if (watchpoint->rw == WPT_ACCESS)
		rw_mask = 0;
	else
		rw_mask = 1;
523

524
525
526
527
528
	if (!arm7_9->wp0_used)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], watchpoint->address);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], watchpoint->mask);
zwelch's avatar
zwelch committed
529
		if ( watchpoint->mask != 0xffffffffu )
530
531
532
533
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE], watchpoint->value);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1));

zwelch's avatar
zwelch committed
534
		if ((retval = jtag_execute_queue()) != ERROR_OK)
535
536
537
		{
			return retval;
		}
538
539
540
541
542
543
544
545
		watchpoint->set = 1;
		arm7_9->wp0_used = 2;
	}
	else if (!arm7_9->wp1_used)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], watchpoint->address);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], watchpoint->mask);
zwelch's avatar
zwelch committed
546
		if ( watchpoint->mask != 0xffffffffu )
547
548
549
550
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE], watchpoint->value);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1));

zwelch's avatar
zwelch committed
551
		if ((retval = jtag_execute_queue()) != ERROR_OK)
552
553
554
		{
			return retval;
		}
555
556
		watchpoint->set = 2;
		arm7_9->wp1_used = 2;
557
	}
558
559
	else
	{
560
		LOG_ERROR("BUG: no hardware comparator available");
561
562
		return ERROR_OK;
	}
563

564
565
566
	return ERROR_OK;
}

567
568
569
570
571
572
573
574
/**
 * Unset an existing watchpoint and clear the used watchpoint unit.
 *
 * @param target Pointer to the target to have the watchpoint removed
 * @param watchpoint Pointer to the watchpoint to be removed
 * @return Error status while trying to unset the watchpoint or the result of
 *         executing the JTAG queue
 */
575
576
int arm7_9_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
577
	int retval = ERROR_OK;
578
579
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
580

581
582
	if (target->state != TARGET_HALTED)
	{
583
		LOG_WARNING("target not halted");
584
585
		return ERROR_TARGET_NOT_HALTED;
	}
586

587
588
	if (!watchpoint->set)
	{
589
		LOG_WARNING("breakpoint not set");
590
591
		return ERROR_OK;
	}
592

593
594
595
	if (watchpoint->set == 1)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
zwelch's avatar
zwelch committed
596
		if ((retval = jtag_execute_queue()) != ERROR_OK)
597
598
599
		{
			return retval;
		}
600
601
602
603
604
		arm7_9->wp0_used = 0;
	}
	else if (watchpoint->set == 2)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
zwelch's avatar
zwelch committed
605
		if ((retval = jtag_execute_queue()) != ERROR_OK)
606
607
608
		{
			return retval;
		}
609
610
611
612
613
614
615
		arm7_9->wp1_used = 0;
	}
	watchpoint->set = 0;

	return ERROR_OK;
}

616
617
618
619
620
621
622
623
/**
 * Add a watchpoint to an ARM7/9 target.  If there are no watchpoint units
 * available, an error response is returned.
 *
 * @param target Pointer to the ARM7/9 target to add a watchpoint to
 * @param watchpoint Pointer to the watchpoint to be added
 * @return Error status while trying to add the watchpoint
 */
624
int arm7_9_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
625
626
627
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
628

629
630
	if (target->state != TARGET_HALTED)
	{
631
		LOG_WARNING("target not halted");
632
633
		return ERROR_TARGET_NOT_HALTED;
	}
634

635
636
637
638
	if (arm7_9->wp_available < 1)
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
639

640
	if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
641
642
643
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
644

645
	arm7_9->wp_available--;
646

647
648
649
	return ERROR_OK;
}

650
651
652
653
654
655
656
657
/**
 * Remove a watchpoint from an ARM7/9 target.  The watchpoint will be unset and
 * the used watchpoint unit will be reopened.
 *
 * @param target Pointer to the target to remove a watchpoint from
 * @param watchpoint Pointer to the watchpoint to be removed
 * @return Result of trying to unset the watchpoint
 */
658
659
int arm7_9_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
660
	int retval = ERROR_OK;
661
662
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
663

664
665
	if (watchpoint->set)
	{
zwelch's avatar
zwelch committed
666
		if ((retval = arm7_9_unset_watchpoint(target, watchpoint)) != ERROR_OK)
667
668
669
		{
			return retval;
		}
670
	}
671

672
	arm7_9->wp_available++;
673

674
675
676
	return ERROR_OK;
}

677
678
679
680
681
682
683
684
685
/**
 * Restarts the target by sending a RESTART instruction and moving the JTAG
 * state to IDLE.  This includes a timeout waiting for DBGACK and SYSCOMP to be
 * asserted by the processor.
 *
 * @param target Pointer to target to issue commands to
 * @return Error status if there is a timeout or a problem while executing the
 *         JTAG queue
 */
686
687
688
int arm7_9_execute_sys_speed(struct target_s *target)
{
	int retval;
689

690
691
692
693
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
694

695
	/* set RESTART instruction */
696
	jtag_set_end_state(TAP_IDLE);
oharboe's avatar
oharboe committed
697
698
699
700
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
701
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
702

oharboe's avatar
oharboe committed
703
704
705
	long long then=timeval_ms();
	int timeout;
	while (!(timeout=((timeval_ms()-then)>1000)))
706
707
708
709
710
711
712
713
	{
		/* read debug status register */
		embeddedice_read_reg(dbg_stat);
		if ((retval = jtag_execute_queue()) != ERROR_OK)
			return retval;
		if ((buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
				   && (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_SYSCOMP, 1)))
			break;
oharboe's avatar
oharboe committed
714
715
716
717
718
719
720
		if (debug_level>=3)
		{
			alive_sleep(100);
		} else
		{
			keep_alive();
		}
721
	}
oharboe's avatar
oharboe committed
722
	if (timeout)
723
	{
duane's avatar
duane committed
724
		LOG_ERROR("timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: %" PRIx32 "", buf_get_u32(dbg_stat->value, 0, dbg_stat->size));
725
726
		return ERROR_TARGET_TIMEOUT;
	}
727

728
729
730
	return ERROR_OK;
}

731
732
733
734
735
736
737
738
/**
 * Restarts the target by sending a RESTART instruction and moving the JTAG
 * state to IDLE.  This validates that DBGACK and SYSCOMP are set without
 * waiting until they are.
 *
 * @param target Pointer to the target to issue commands to
 * @return Always ERROR_OK
 */
739
740
int arm7_9_execute_fast_sys_speed(struct target_s *target)
{
mifi's avatar
mifi committed
741
	static int set=0;
742
	static uint8_t check_value[4], check_mask[4];
743

744
745
746
747
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
748

749
	/* set RESTART instruction */
750
	jtag_set_end_state(TAP_IDLE);
oharboe's avatar
oharboe committed
751
752
753
754
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
755
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
756

mifi's avatar
mifi committed
757
758
759
	if (!set)
	{
		/* check for DBGACK and SYSCOMP set (others don't care) */
760

mifi's avatar
mifi committed
761
		/* NB! These are constants that must be available until after next jtag_execute() and
762
763
764
		 * we evaluate the values upon first execution in lieu of setting up these constants
		 * during early setup.
		 * */
mifi's avatar
mifi committed
765
766
767
768
		buf_set_u32(check_value, 0, 32, 0x9);
		buf_set_u32(check_mask, 0, 32, 0x9);
		set=1;
	}
769

770
	/* read debug status register */
771
	embeddedice_read_reg_w_check(dbg_stat, check_value, check_mask);
772
773
774
775

	return ERROR_OK;
}

776
777
778
779
780
781
782
783
/**
 * Get some data from the ARM7/9 target.
 *
 * @param target Pointer to the ARM7/9 target to read data from
 * @param size The number of 32bit words to be read
 * @param buffer Pointer to the buffer that will hold the data
 * @return The result of receiving data from the Embedded ICE unit
 */
784
int arm7_9_target_request_data(target_t *target, uint32_t size, uint8_t *buffer)
785
786
787
788
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
789
	uint32_t *data;
790
	int retval = ERROR_OK;
791
	uint32_t i;
792

793
	data = malloc(size * (sizeof(uint32_t)));
794

795
	retval = embeddedice_receive(jtag_info, data, size);
796

797
	/* return the 32-bit ints in the 8-bit array */
798
799
800
801
	for (i = 0; i < size; i++)
	{
		h_u32_to_le(buffer + (i * 4), data[i]);
	}
802

803
	free(data);
804

805
	return retval;
806
807
}

808
809
810
811
812
813
814
815
816
/**
 * Handles requests to an ARM7/9 target.  If debug messaging is enabled, the
 * target is running and the DCC control register has the W bit high, this will
 * execute the request on the target.
 *
 * @param priv Void pointer expected to be a target_t pointer
 * @return ERROR_OK unless there are issues with the JTAG queue or when reading
 *                  from the Embedded ICE unit
 */
817
818
int arm7_9_handle_target_request(void *priv)
{
819
	int retval = ERROR_OK;
820
	target_t *target = priv;
821
	if (!target_was_examined(target))
822
		return ERROR_OK;
823
824
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
825
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
826
	reg_t *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL];
827

828
829
	if (!target->dbg_msg_enabled)
		return ERROR_OK;
830

831
832
833
834
	if (target->state == TARGET_RUNNING)
	{
		/* read DCC control register */
		embeddedice_read_reg(dcc_control);
835
836
837
838
		if ((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
839

840
841
842
		/* check W bit */
		if (buf_get_u32(dcc_control->value, 1, 1) == 1)
		{
843
			uint32_t request;
844

845
846
847
848
849
850
851
852
			if ((retval = embeddedice_receive(jtag_info, &request, 1)) != ERROR_OK)
			{
				return retval;
			}
			if ((retval = target_request(target, request)) != ERROR_OK)
			{
				return retval;
			}
853
854
		}
	}
855

856
857
858
	return ERROR_OK;
}

859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
/**
 * Polls an ARM7/9 target for its current status.  If DBGACK is set, the target
 * is manipulated to the right halted state based on its current state.  This is
 * what happens:
 *
 * <table>
 * 		<tr><th>State</th><th>Action</th></tr>
 * 		<tr><td>TARGET_RUNNING | TARGET_RESET</td><td>Enters debug mode.  If TARGET_RESET, pc may be checked</td></tr>
 * 		<tr><td>TARGET_UNKNOWN</td><td>Warning is logged</td></tr>
 * 		<tr><td>TARGET_DEBUG_RUNNING</td><td>Enters debug mode</td></tr>
 * 		<tr><td>TARGET_HALTED</td><td>Nothing</td></tr>
 * </table>
 *
 * If the target does not end up in the halted state, a warning is produced.  If
 * DBGACK is cleared, then the target is expected to either be running or
 * running in debug.
 *
 * @param target Pointer to the ARM7/9 target to poll
 * @return ERROR_OK or an error status if a command fails
 */
879
int arm7_9_poll(target_t *target)
880
881
882
883
884
885
886
887
888
889
{
	int retval;
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];

	/* read debug status register */
	embeddedice_read_reg(dbg_stat);
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
890
		return retval;
891
	}
892

893
894
	if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
	{
895
/*		LOG_DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));*/
896
		if (target->state == TARGET_UNKNOWN)
897
		{
898
			target->state = TARGET_RUNNING;
899
			LOG_WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
900
901
902
		}
		if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
		{
903
904
905
			int check_pc=0;
			if (target->state == TARGET_RESET)
			{
oharboe's avatar
   
oharboe committed
906
				if (target->reset_halt)
907
				{
908
					enum reset_types jtag_reset_config = jtag_get_reset_config();
909
910
911
912
913
914
					if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0)
					{
						check_pc = 1;
					}
				}
			}
915

916
			target->state = TARGET_HALTED;
917

918
919
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
920

921
922
923
			if (check_pc)
			{
				reg_t *reg = register_get_by_name(target->reg_cache, "pc", 1);
924
				uint32_t t=*((uint32_t *)reg->value);
zwelch's avatar
zwelch committed
925
				if (t != 0)
926
				{
927
					LOG_ERROR("PC was not 0. Does this target need srst_pulls_trst?");
928
929
				}
			}
930

931
932
933
934
			if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
			{
				return retval;
			}
935
936
937
938
939
940
		}
		if (target->state == TARGET_DEBUG_RUNNING)
		{
			target->state = TARGET_HALTED;
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
941

942
943
944
945
			if ((retval = target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED)) != ERROR_OK)
			{
				return retval;
			}
946
		}
947
948
		if (target->state != TARGET_HALTED)
		{
949
			LOG_WARNING("DBGACK set, but the target did not end up in the halted state %d", target->state);
950
		}
951
	}
952
953
954
955
956
	else
	{
		if (target->state != TARGET_DEBUG_RUNNING)
			target->state = TARGET_RUNNING;
	}
957

958
	return ERROR_OK;
959
960
}

961
962
963
964
965
966
967
968
969
970
971
/**
 * Asserts the reset (SRST) on an ARM7/9 target.  Some -S targets (ARM966E-S in
 * the STR912 isn't affected, ARM926EJ-S in the LPC3180 and AT91SAM9260 is
 * affected) completely stop the JTAG clock while the core is held in reset
 * (SRST).  It isn't possible to program the halt condition once reset is
 * asserted, hence a hook that allows the target to set up its reset-halt
 * condition is setup prior to asserting reset.
 *
 * @param target Pointer to an ARM7/9 target to assert reset on
 * @return ERROR_FAIL if the JTAG device does not have SRST, otherwise ERROR_OK
 */
972
973
int arm7_9_assert_reset(target_t *target)
{
974
975
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
oharboe's avatar
oharboe committed
976
	LOG_DEBUG("target->state: %s",
977
		  Jim_Nvp_value2name_simple( nvp_target_state,target->state)->name);
978

979
	enum reset_types jtag_reset_config = jtag_get_reset_config();
980
981
982
983
984
	if (!(jtag_reset_config & RESET_HAS_SRST))
	{
		LOG_ERROR("Can't assert SRST");
		return ERROR_FAIL;
	}
oharboe's avatar
   
oharboe committed
985

oharboe's avatar
   
oharboe committed
986
	if (target->reset_halt)
987
	{
oharboe's avatar
   
oharboe committed
988
989
990
		/*
		 * Some targets do not support communication while SRST is asserted. We need to
		 * set up the reset vector catch here.
991
		 *
oharboe's avatar
   
oharboe committed
992
		 * If TRST is asserted, then these settings will be reset anyway, so setting them
993
		 * here is harmless.
oharboe's avatar
   
oharboe committed
994
995
996
997
998
999
1000
		 */
		if (arm7_9->has_vector_catch)
		{
			/* program vector catch register to catch reset vector */
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1);
		}
		else
For faster browsing, not all history is shown. View entire blame