arm7_9_common.c 94.3 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
static int arm7_9_clear_watchpoints(arm7_9_common_t *arm7_9)
{
61
	LOG_DEBUG("-");
62
63
64
	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;
65
	arm7_9->wp0_used = 0;
66
67
	arm7_9->wp1_used = arm7_9->wp1_used_default;
	arm7_9->wp_available = arm7_9->wp_available_max;
68

69
70
71
	return jtag_execute_queue();
}

72
73
74
75
76
77
78
/**
 * 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
 */
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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");
	}
97
98
99
100
	LOG_DEBUG("BPID: %d (0x%08" PRIx32 ") using hw wp: %d", 
			  breakpoint->unique_id,
			  breakpoint->address,
			  breakpoint->set );
101
102
}

103
104
105
106
107
108
109
/**
 * 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
 */
110
111
112
static int arm7_9_set_software_breakpoints(arm7_9_common_t *arm7_9)
{
	if (arm7_9->sw_breakpoints_added)
113
	{
114
115
116
117
118
119
120
121
		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
122

123
124
125
	/* pick a breakpoint unit */
	if (!arm7_9->wp0_used)
	{
zwelch's avatar
zwelch committed
126
		arm7_9->sw_breakpoints_added = 1;
127
128
129
		arm7_9->wp0_used = 3;
	} else if (!arm7_9->wp1_used)
	{
zwelch's avatar
zwelch committed
130
		arm7_9->sw_breakpoints_added = 2;
131
132
133
134
135
136
		arm7_9->wp1_used = 3;
	}
	else
	{
		LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1");
		return ERROR_FAIL;
137
	}
138

zwelch's avatar
zwelch committed
139
	if (arm7_9->sw_breakpoints_added == 1)
140
141
142
143
144
145
146
	{
		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);
	}
zwelch's avatar
zwelch committed
147
	else if (arm7_9->sw_breakpoints_added == 2)
148
149
150
151
152
153
154
155
	{
		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
156
	{
157
158
		LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1");
		return ERROR_FAIL;
159
	}
160
161
	LOG_DEBUG("SW BP using hw wp: %d", 
			  arm7_9->sw_breakpoints_added );
162

163
	return jtag_execute_queue();
164
165
}

166
167
168
169
170
171
/**
 * 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
 */
172
int arm7_9_setup(target_t *target)
173
{
174
175
176
177
	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);
178
179
}

180
181
182
183
184
185
186
187
188
189
190
191
/**
 * 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
 */
192
193
194
195
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;
196

197
198
199
200
	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
	{
		return -1;
	}
201

202
203
204
205
	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
	{
		return -1;
	}
206

207
208
	*armv4_5_p = armv4_5;
	*arm7_9_p = arm7_9;
209

210
211
212
	return ERROR_OK;
}

213
214
215
216
217
218
219
220
221
222
/**
 * 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
223
 */
224
225
226
227
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;
zwelch's avatar
zwelch committed
228
	int retval = ERROR_OK;
229

230
231
232
233
	LOG_DEBUG("BPID: %d, Address: 0x%08" PRIx32,
			  breakpoint->unique_id,
			  breakpoint->address );

234
235
	if (target->state != TARGET_HALTED)
	{
236
		LOG_WARNING("target not halted");
237
238
		return ERROR_TARGET_NOT_HALTED;
	}
239

240
241
242
	if (breakpoint->type == BKPT_HARD)
	{
		/* either an ARM (4 byte) or Thumb (2 byte) breakpoint */
243
		uint32_t mask = (breakpoint->length == 4) ? 0x3u : 0x1u;
244
245

		/* reassign a hw breakpoint */
zwelch's avatar
zwelch committed
246
		if (breakpoint->set == 0)
247
248
249
250
		{
			arm7_9_assign_wp(arm7_9, breakpoint);
		}

zwelch's avatar
zwelch committed
251
		if (breakpoint->set == 1)
252
253
254
255
256
257
258
		{
			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);
		}
zwelch's avatar
zwelch committed
259
		else if (breakpoint->set == 2)
260
261
262
263
264
265
266
267
268
		{
			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
		{
269
			LOG_ERROR("BUG: no hardware comparator available");
270
271
			return ERROR_OK;
		}
272

zwelch's avatar
zwelch committed
273
		retval = jtag_execute_queue();
274
275
276
	}
	else if (breakpoint->type == BKPT_SOFT)
	{
zwelch's avatar
zwelch committed
277
		if ((retval = arm7_9_set_software_breakpoints(arm7_9)) != ERROR_OK)
278
			return retval;
oharboe's avatar
oharboe committed
279

280
281
282
		/* did we already set this breakpoint? */
		if (breakpoint->set)
			return ERROR_OK;
oharboe's avatar
oharboe committed
283

284
285
		if (breakpoint->length == 4)
		{
286
			uint32_t verify = 0xffffffff;
287
			/* keep the original instruction in target endianness */
zwelch's avatar
zwelch committed
288
			if ((retval = target_read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
289
290
291
			{
				return retval;
			}
drath's avatar
drath committed
292
			/* write the breakpoint instruction in target endianness (arm7_9->arm_bkpt is host endian) */
293
294
295
296
			if ((retval = target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt)) != ERROR_OK)
			{
				return retval;
			}
297

298
			if ((retval = target_read_u32(target, breakpoint->address, &verify)) != ERROR_OK)
299
300
301
			{
				return retval;
			}
ntfreak's avatar
ntfreak committed
302
303
			if (verify != arm7_9->arm_bkpt)
			{
duane's avatar
duane committed
304
				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
305
306
				return ERROR_OK;
			}
307
308
309
		}
		else
		{
zwelch's avatar
zwelch committed
310
			uint16_t verify = 0xffff;
311
			/* keep the original instruction in target endianness */
zwelch's avatar
zwelch committed
312
			if ((retval = target_read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
313
314
315
			{
				return retval;
			}
drath's avatar
drath committed
316
			/* write the breakpoint instruction in target endianness (arm7_9->thumb_bkpt is host endian) */
317
318
319
320
			if ((retval = target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt)) != ERROR_OK)
			{
				return retval;
			}
321

322
			if ((retval = target_read_u16(target, breakpoint->address, &verify)) != ERROR_OK)
323
324
325
			{
				return retval;
			}
ntfreak's avatar
ntfreak committed
326
327
			if (verify != arm7_9->thumb_bkpt)
			{
duane's avatar
duane committed
328
				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
329
330
				return ERROR_OK;
			}
331
332
333
334
		}
		breakpoint->set = 1;
	}

335
	return retval;
336
337
}

338
339
340
341
342
343
344
345
346
347
348
349
/**
 * 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
 */
350
351
int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
352
353
	int retval = ERROR_OK;

354
355
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
356

357
358
359
360
	LOG_DEBUG("BPID: %d, Address: 0x%08" PRIx32,
			  breakpoint->unique_id,
			  breakpoint->address );

361
362
	if (!breakpoint->set)
	{
363
		LOG_WARNING("breakpoint not set");
364
365
		return ERROR_OK;
	}
366

367
368
	if (breakpoint->type == BKPT_HARD)
	{
369
370
371
		LOG_DEBUG("BPID: %d Releasing hw wp: %d", 
				  breakpoint->unique_id,
				  breakpoint->set );
372
373
374
375
		if (breakpoint->set == 1)
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
			arm7_9->wp0_used = 0;
376
			arm7_9->wp_available++;
377
378
379
380
381
		}
		else if (breakpoint->set == 2)
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
			arm7_9->wp1_used = 0;
382
			arm7_9->wp_available++;
383
		}
384
		retval = jtag_execute_queue();
385
386
387
388
		breakpoint->set = 0;
	}
	else
	{
389
		/* restore original instruction (kept in target endianness) */
390
391
		if (breakpoint->length == 4)
		{
392
			uint32_t current_instr;
393
			/* check that user program as not modified breakpoint instruction */
394
			if ((retval = target_read_memory(target, breakpoint->address, 4, 1, (uint8_t*)&current_instr)) != ERROR_OK)
395
396
397
			{
				return retval;
			}
zwelch's avatar
zwelch committed
398
			if (current_instr == arm7_9->arm_bkpt)
zwelch's avatar
zwelch committed
399
				if ((retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
400
401
402
				{
					return retval;
				}
403
404
405
		}
		else
		{
zwelch's avatar
zwelch committed
406
			uint16_t current_instr;
407
			/* check that user program as not modified breakpoint instruction */
408
			if ((retval = target_read_memory(target, breakpoint->address, 2, 1, (uint8_t*)&current_instr)) != ERROR_OK)
409
410
411
			{
				return retval;
			}
zwelch's avatar
zwelch committed
412
			if (current_instr == arm7_9->thumb_bkpt)
zwelch's avatar
zwelch committed
413
				if ((retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
414
415
416
				{
					return retval;
				}
417
418
419
420
		}
		breakpoint->set = 0;
	}

421
	return retval;
422
423
}

424
425
426
427
428
429
430
431
432
/**
 * 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
 */
433
int arm7_9_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
434
435
436
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
437

438
439
	if (target->state != TARGET_HALTED)
	{
440
		LOG_WARNING("target not halted");
441
442
		return ERROR_TARGET_NOT_HALTED;
	}
oharboe's avatar
oharboe committed
443

zwelch's avatar
zwelch committed
444
	if (arm7_9->breakpoint_count == 0)
445
	{
oharboe's avatar
oharboe committed
446
447
		/* make sure we don't have any dangling breakpoints. This is vital upon
		 * GDB connect/disconnect
448
		 */
oharboe's avatar
oharboe committed
449
		arm7_9_clear_watchpoints(arm7_9);
450
	}
451

452
	if ((breakpoint->type == BKPT_HARD) && (arm7_9->wp_available < 1))
453
	{
454
		LOG_INFO("no watchpoint unit available for hardware breakpoint");
455
456
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
457

458
	if ((breakpoint->length != 2) && (breakpoint->length != 4))
459
	{
460
		LOG_INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
461
462
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
463

464
	if (breakpoint->type == BKPT_HARD)
465
	{
466
		arm7_9_assign_wp(arm7_9, breakpoint);
467
	}
oharboe's avatar
oharboe committed
468

469
	arm7_9->breakpoint_count++;
oharboe's avatar
oharboe committed
470

471
	return arm7_9_set_breakpoint(target, breakpoint);
472
473
}

474
475
476
477
478
479
480
481
482
483
/**
 * 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
 */
484
485
int arm7_9_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
486
	int retval = ERROR_OK;
487
488
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
489

zwelch's avatar
zwelch committed
490
	if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK)
491
492
493
	{
		return retval;
	}
494

495
496
	if (breakpoint->type == BKPT_HARD)
		arm7_9->wp_available++;
oharboe's avatar
oharboe committed
497

498
	arm7_9->breakpoint_count--;
zwelch's avatar
zwelch committed
499
	if (arm7_9->breakpoint_count == 0)
500
501
	{
		/* make sure we don't have any dangling breakpoints */
zwelch's avatar
zwelch committed
502
		if ((retval = arm7_9_clear_watchpoints(arm7_9)) != ERROR_OK)
503
504
505
		{
			return retval;
		}
506
	}
507

508
509
510
	return ERROR_OK;
}

511
512
513
514
515
516
517
518
519
520
/**
 * 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
 */
521
522
int arm7_9_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
523
	int retval = ERROR_OK;
524
525
526
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	int rw_mask = 1;
527
	uint32_t mask;
528

529
	mask = watchpoint->length - 1;
530

531
532
	if (target->state != TARGET_HALTED)
	{
533
		LOG_WARNING("target not halted");
534
535
		return ERROR_TARGET_NOT_HALTED;
	}
536

537
538
539
540
	if (watchpoint->rw == WPT_ACCESS)
		rw_mask = 0;
	else
		rw_mask = 1;
541

542
543
544
545
546
	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);
547
		if (watchpoint->mask != 0xffffffffu)
548
549
550
551
			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
552
		if ((retval = jtag_execute_queue()) != ERROR_OK)
553
554
555
		{
			return retval;
		}
556
557
558
559
560
561
562
563
		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);
564
		if (watchpoint->mask != 0xffffffffu)
565
566
567
568
			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
569
		if ((retval = jtag_execute_queue()) != ERROR_OK)
570
571
572
		{
			return retval;
		}
573
574
		watchpoint->set = 2;
		arm7_9->wp1_used = 2;
575
	}
576
577
	else
	{
578
		LOG_ERROR("BUG: no hardware comparator available");
579
580
		return ERROR_OK;
	}
581

582
583
584
	return ERROR_OK;
}

585
586
587
588
589
590
591
592
/**
 * 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
 */
593
594
int arm7_9_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
595
	int retval = ERROR_OK;
596
597
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
598

599
600
	if (target->state != TARGET_HALTED)
	{
601
		LOG_WARNING("target not halted");
602
603
		return ERROR_TARGET_NOT_HALTED;
	}
604

605
606
	if (!watchpoint->set)
	{
607
		LOG_WARNING("breakpoint not set");
608
609
		return ERROR_OK;
	}
610

611
612
613
	if (watchpoint->set == 1)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
zwelch's avatar
zwelch committed
614
		if ((retval = jtag_execute_queue()) != ERROR_OK)
615
616
617
		{
			return retval;
		}
618
619
620
621
622
		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
623
		if ((retval = jtag_execute_queue()) != ERROR_OK)
624
625
626
		{
			return retval;
		}
627
628
629
630
631
632
633
		arm7_9->wp1_used = 0;
	}
	watchpoint->set = 0;

	return ERROR_OK;
}

634
635
636
637
638
639
640
641
/**
 * 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
 */
642
int arm7_9_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
643
644
645
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
646

647
648
	if (target->state != TARGET_HALTED)
	{
649
		LOG_WARNING("target not halted");
650
651
		return ERROR_TARGET_NOT_HALTED;
	}
652

653
654
655
656
	if (arm7_9->wp_available < 1)
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
657

658
	if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
659
660
661
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
662

663
	arm7_9->wp_available--;
664

665
666
667
	return ERROR_OK;
}

668
669
670
671
672
673
674
675
/**
 * 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
 */
676
677
int arm7_9_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
678
	int retval = ERROR_OK;
679
680
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
681

682
683
	if (watchpoint->set)
	{
zwelch's avatar
zwelch committed
684
		if ((retval = arm7_9_unset_watchpoint(target, watchpoint)) != ERROR_OK)
685
686
687
		{
			return retval;
		}
688
	}
689

690
	arm7_9->wp_available++;
691

692
693
694
	return ERROR_OK;
}

695
696
697
698
699
700
701
702
703
/**
 * 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
 */
704
705
706
int arm7_9_execute_sys_speed(struct target_s *target)
{
	int retval;
707

708
709
710
711
	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];
712

713
	/* set RESTART instruction */
714
	jtag_set_end_state(TAP_IDLE);
oharboe's avatar
oharboe committed
715
716
717
718
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
719
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
720

zwelch's avatar
zwelch committed
721
	long long then = timeval_ms();
oharboe's avatar
oharboe committed
722
	int timeout;
zwelch's avatar
zwelch committed
723
	while (!(timeout = ((timeval_ms()-then) > 1000)))
724
725
726
727
728
729
730
731
	{
		/* 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;
zwelch's avatar
zwelch committed
732
		if (debug_level >= 3)
oharboe's avatar
oharboe committed
733
734
735
736
737
738
		{
			alive_sleep(100);
		} else
		{
			keep_alive();
		}
739
	}
oharboe's avatar
oharboe committed
740
	if (timeout)
741
	{
duane's avatar
duane committed
742
		LOG_ERROR("timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: %" PRIx32 "", buf_get_u32(dbg_stat->value, 0, dbg_stat->size));
743
744
		return ERROR_TARGET_TIMEOUT;
	}
745

746
747
748
	return ERROR_OK;
}

749
750
751
752
753
754
755
756
/**
 * 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
 */
757
758
int arm7_9_execute_fast_sys_speed(struct target_s *target)
{
zwelch's avatar
zwelch committed
759
	static int set = 0;
760
	static uint8_t check_value[4], check_mask[4];
761

762
763
764
765
	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];
766

767
	/* set RESTART instruction */
768
	jtag_set_end_state(TAP_IDLE);
oharboe's avatar
oharboe committed
769
770
771
772
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
773
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
774

mifi's avatar
mifi committed
775
776
777
	if (!set)
	{
		/* check for DBGACK and SYSCOMP set (others don't care) */
778

mifi's avatar
mifi committed
779
		/* NB! These are constants that must be available until after next jtag_execute() and
780
781
782
		 * we evaluate the values upon first execution in lieu of setting up these constants
		 * during early setup.
		 * */
mifi's avatar
mifi committed
783
784
		buf_set_u32(check_value, 0, 32, 0x9);
		buf_set_u32(check_mask, 0, 32, 0x9);
zwelch's avatar
zwelch committed
785
		set = 1;
mifi's avatar
mifi committed
786
	}
787

788
	/* read debug status register */
789
	embeddedice_read_reg_w_check(dbg_stat, check_value, check_mask);
790
791
792
793

	return ERROR_OK;
}

794
795
796
797
798
799
800
801
/**
 * 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
 */
802
int arm7_9_target_request_data(target_t *target, uint32_t size, uint8_t *buffer)
803
804
805
806
{
	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;
807
	uint32_t *data;
808
	int retval = ERROR_OK;
809
	uint32_t i;
810

811
	data = malloc(size * (sizeof(uint32_t)));
812

813
	retval = embeddedice_receive(jtag_info, data, size);
814

815
	/* return the 32-bit ints in the 8-bit array */
816
817
818
819
	for (i = 0; i < size; i++)
	{
		h_u32_to_le(buffer + (i * 4), data[i]);
	}
820

821
	free(data);
822

823
	return retval;
824
825
}

826
827
828
829
830
831
832
833
834
/**
 * 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
 */
835
836
int arm7_9_handle_target_request(void *priv)
{
837
	int retval = ERROR_OK;
838
	target_t *target = priv;
839
	if (!target_was_examined(target))
840
		return ERROR_OK;
841
842
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
843
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
844
	reg_t *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL];
845

846
847
	if (!target->dbg_msg_enabled)
		return ERROR_OK;
848

849
850
851
852
	if (target->state == TARGET_RUNNING)
	{
		/* read DCC control register */
		embeddedice_read_reg(dcc_control);
853
854
855
856
		if ((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
857

858
859
860
		/* check W bit */
		if (buf_get_u32(dcc_control->value, 1, 1) == 1)
		{
861
			uint32_t request;
862

863
864
865
866
867
868
869
870
			if ((retval = embeddedice_receive(jtag_info, &request, 1)) != ERROR_OK)
			{
				return retval;
			}
			if ((retval = target_request(target, request)) != ERROR_OK)
			{
				return retval;
			}
871
872
		}
	}
873

874
875
876
	return ERROR_OK;
}

877
878
879
880
881
882
/**
 * 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>
zwelch's avatar
zwelch committed
883
884
885
886
887
 * 		<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>
888
889
890
891
892
893
894
895
896
 * </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
 */
897
int arm7_9_poll(target_t *target)
898
899
900
901
902
903
904
905
906
907
{
	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)
	{
908
		return retval;
909
	}
910

911
912
	if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
	{
913
/*		LOG_DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));*/
914
		if (target->state == TARGET_UNKNOWN)
915
		{
916
			target->state = TARGET_RUNNING;
917
			LOG_WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
918
919
920
		}
		if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
		{
zwelch's avatar
zwelch committed
921
			int check_pc = 0;
922
923
			if (target->state == TARGET_RESET)
			{
oharboe's avatar
   
oharboe committed
924
				if (target->reset_halt)
925
				{
926
					enum reset_types jtag_reset_config = jtag_get_reset_config();
zwelch's avatar
zwelch committed
927
					if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
928
929
930
931
932
					{
						check_pc = 1;
					}
				}
			}
933

934
			target->state = TARGET_HALTED;
935

936
937
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
938

939
940
941
			if (check_pc)
			{
				reg_t *reg = register_get_by_name(target->reg_cache, "pc", 1);
942
				uint32_t t=*((uint32_t *)reg->value);
zwelch's avatar
zwelch committed
943
				if (t != 0)
944
				{
945
					LOG_ERROR("PC was not 0. Does this target need srst_pulls_trst?");
946
947
				}
			}
948

949
950
951
952
			if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
			{
				return retval;
			}
953
954
955
956
957
958
		}
		if (target->state == TARGET_DEBUG_RUNNING)
		{
			target->state = TARGET_HALTED;
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
959

960
961
962
963
			if ((retval = target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED)) != ERROR_OK)
			{
				return retval;
			}
964
		}
965
966
		if (target->state != TARGET_HALTED)
		{
967
			LOG_WARNING("DBGACK set, but the target did not end up in the halted state %d", target->state);
968
		}
969
	}
970
971
972
973
974
	else
	{
		if (target->state != TARGET_DEBUG_RUNNING)
			target->state = TARGET_RUNNING;
	}
975

976
	return ERROR_OK;
977
978
}

979
980
981
982
983
984
985
986
987
988
989
/**
 * 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
 */
990
991
int arm7_9_assert_reset(target_t *target)
{
992
993
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
oharboe's avatar
oharboe committed
994
	LOG_DEBUG("target->state: %s",
995
		  Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name);
996

997
	enum reset_types jtag_reset_config = jtag_get_reset_config();
998
999
1000
	if (!(jtag_reset_config & RESET_HAS_SRST))
	{
		LOG_ERROR("Can't assert SRST");
For faster browsing, not all history is shown. View entire blame